Skip to content
This repository was archived by the owner on Nov 15, 2023. It is now read-only.
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
88 changes: 85 additions & 3 deletions client/db/src/storage_cache.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,9 @@
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.

//! Global cache state.
//! Global state cache. Maintains recently queried/committed state values
//! Tracks changes over the span of a few recent blocks and handles forks
//! by tracking/removing cache entries for conflicting changes.

use std::collections::{VecDeque, HashSet, HashMap};
use std::sync::Arc;
Expand Down Expand Up @@ -343,12 +345,27 @@ impl<B: BlockT> CacheChanges<B> {
);
let cache = &mut *cache;
// Filter out committing block if any.
let enacted: Vec<_> = enacted
let mut enacted: Vec<_> = enacted
.iter()
.filter(|h| commit_hash.as_ref().map_or(true, |p| *h != p))
.cloned()
.collect();
cache.sync(&enacted, retracted);

let mut retracted = std::borrow::Cow::Borrowed(retracted);
if let Some(commit_hash) = &commit_hash {
if let Some(m) = cache.modifications.iter_mut().find(|m| &m.hash == commit_hash) {
if m.is_canon != is_best {
// Same block comitted twice with different state changes.
// Treat it as reenacted/retracted.
if is_best {
enacted.push(commit_hash.clone());
} else {
retracted.to_mut().push(commit_hash.clone());
}
}
}
}
cache.sync(&enacted, &retracted);
// Propagate cache only if committing on top of the latest canonical state
// blocks are ordered by number and only one block with a given number is marked as canonical
// (contributed to canonical state cache)
Expand Down Expand Up @@ -1316,6 +1333,71 @@ mod tests {
);
assert_eq!(s.storage(&key).unwrap(), None);
}

#[test]
fn same_block_no_changes() {
sp_tracing::try_init_simple();

let root_parent = H256::random();
let key = H256::random()[..].to_vec();
let h1 = H256::random();
let h2 = H256::random();

let shared = new_shared_cache::<Block>(256*1024, (0,1));

let mut s = CachingState::new(
InMemoryBackend::<BlakeTwo256>::default(),
shared.clone(),
Some(root_parent),
);
s.cache.sync_cache(
&[],
&[],
vec![(key.clone(), Some(vec![1]))],
vec![],
Some(h1),
Some(1),
true,
);
assert_eq!(shared.lock().lru_storage.get(&key).unwrap(), &Some(vec![1]));

let mut s = CachingState::new(
InMemoryBackend::<BlakeTwo256>::default(),
shared.clone(),
Some(h1),
);

// commit as non-best
s.cache.sync_cache(
&[],
&[],
vec![(key.clone(), Some(vec![2]))],
vec![],
Some(h2),
Some(2),
false,
);

assert_eq!(shared.lock().lru_storage.get(&key).unwrap(), &Some(vec![1]));

let mut s = CachingState::new(
InMemoryBackend::<BlakeTwo256>::default(),
shared.clone(),
Some(h1),
);

// commit again as best with no changes
s.cache.sync_cache(
&[],
&[],
vec![],
vec![],
Some(h2),
Some(2),
true,
);
assert_eq!(s.storage(&key).unwrap(), None);
}
}

#[cfg(test)]
Expand Down