Skip to content
This repository was archived by the owner on Nov 15, 2023. It is now read-only.

Commit 0e736a2

Browse files
pepyakingavofyork
authored andcommitted
Iterate over overlay to decide which keys to purge (#436)
1 parent 91c3ea9 commit 0e736a2

File tree

2 files changed

+68
-0
lines changed

2 files changed

+68
-0
lines changed

substrate/state-machine/src/ext.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,7 @@ impl<'a, B: 'a> Externalities for Ext<'a, B>
121121

122122
fn clear_prefix(&mut self, prefix: &[u8]) {
123123
self.mark_dirty();
124+
self.overlay.clear_prefix(prefix);
124125
self.backend.for_keys_with_prefix(prefix, |key| {
125126
self.overlay.set_storage(key.to_vec(), None);
126127
});

substrate/state-machine/src/lib.rs

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,10 +68,37 @@ impl OverlayedChanges {
6868
.map(|x| x.as_ref().map(AsRef::as_ref))
6969
}
7070

71+
/// Inserts the given key-value pair into the prospective change set.
72+
///
73+
/// `None` can be used to delete a value specified by the given key.
7174
fn set_storage(&mut self, key: Vec<u8>, val: Option<Vec<u8>>) {
7275
self.prospective.insert(key, val);
7376
}
7477

78+
/// Removes all key-value pairs which keys share the given prefix.
79+
///
80+
/// NOTE that this doesn't take place immediately but written into the prospective
81+
/// change set, and still can be reverted by [`discard_prospective`].
82+
///
83+
/// [`discard_prospective`]: #method.discard_prospective
84+
fn clear_prefix(&mut self, prefix: &[u8]) {
85+
// Iterate over all prospective and mark all keys that share
86+
// the given prefix as removed (None).
87+
for (key, value) in self.prospective.iter_mut() {
88+
if key.starts_with(prefix) {
89+
*value = None;
90+
}
91+
}
92+
93+
// Then do the same with keys from commited changes.
94+
// NOTE that we are making changes in the prospective change set.
95+
for key in self.committed.keys() {
96+
if key.starts_with(prefix) {
97+
self.prospective.insert(key.to_owned(), None);
98+
}
99+
}
100+
}
101+
75102
/// Discard prospective changes to state.
76103
pub fn discard_prospective(&mut self) {
77104
self.prospective.clear();
@@ -540,4 +567,44 @@ mod tests {
540567
assert_eq!(remote_result, vec![66]);
541568
assert_eq!(remote_result, local_result);
542569
}
570+
571+
#[test]
572+
fn clear_prefix_in_ext_works() {
573+
let initial: HashMap<_, _> = map![
574+
b"aaa".to_vec() => b"0".to_vec(),
575+
b"abb".to_vec() => b"1".to_vec(),
576+
b"abc".to_vec() => b"2".to_vec(),
577+
b"bbb".to_vec() => b"3".to_vec()
578+
];
579+
let backend = InMemory::from(initial).try_into_trie_backend().unwrap();
580+
let mut overlay = OverlayedChanges {
581+
committed: map![
582+
b"aba".to_vec() => Some(b"1312".to_vec()),
583+
b"bab".to_vec() => Some(b"228".to_vec())
584+
],
585+
prospective: map![
586+
b"abd".to_vec() => Some(b"69".to_vec()),
587+
b"bbd".to_vec() => Some(b"42".to_vec())
588+
],
589+
};
590+
591+
{
592+
let mut ext = Ext::new(&mut overlay, &backend);
593+
ext.clear_prefix(b"ab");
594+
}
595+
overlay.commit_prospective();
596+
597+
assert_eq!(
598+
overlay.committed,
599+
map![
600+
b"abb".to_vec() => None,
601+
b"abc".to_vec() => None,
602+
b"aba".to_vec() => None,
603+
b"abd".to_vec() => None,
604+
605+
b"bab".to_vec() => Some(b"228".to_vec()),
606+
b"bbd".to_vec() => Some(b"42".to_vec())
607+
],
608+
);
609+
}
543610
}

0 commit comments

Comments
 (0)