mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-06-13 01:11:10 +00:00
Inner hashing of value in state trie (runtime versioning). (#9732)
* starting * Updated from other branch. * setting flag * flag in storage struct * fix flagging to access and insert. * added todo to fix * also missing serialize meta to storage proof * extract meta. * Isolate old trie layout. * failing test that requires storing in meta when old hash scheme is used. * old hash compatibility * Db migrate. * runing tests with both states when interesting. * fix chain spec test with serde default. * export state (missing trie function). * Pending using new branch, lacking genericity on layout resolution. * extract and set global meta * Update to branch 4 * fix iterator with root flag (no longer insert node). * fix trie root hashing of root * complete basic backend. * Remove old_hash meta from proof that do not use inner_hashing. * fix trie test for empty (force layout on empty deltas). * Root update fix. * debug on meta * Use trie key iteration that do not include value in proofs. * switch default test ext to use inner hash. * small integration test, and fix tx cache mgmt in ext. test failing * Proof scenario at state-machine level. * trace for db upgrade * try different param * act more like iter_from. * Bigger batches. * Update trie dependency. * drafting codec changes and refact * before removing unused branch no value alt hashing. more work todo rename all flag var to alt_hash, and remove extrinsic replace by storage query at every storage_root call. * alt hashing only for branch with value. * fix trie tests * Hash of value include the encoded size. * removing fields(broken) * fix trie_stream to also include value length in inner hash. * triedbmut only using alt type if inner hashing. * trie_stream to also only use alt hashing type when actually alt hashing. * Refactor meta state, logic should work with change of trie treshold. * Remove NoMeta variant. * Remove state_hashed trigger specific functions. * pending switching to using threshold, new storage root api does not make much sense. * refactoring to use state from backend (not possible payload changes). * Applying from previous state * Remove default from storage, genesis need a special build. * rem empty space * Catch problem: when using triedb with default: we should not revert nodes: otherwhise thing as trie codec cannot decode-encode without changing state. * fix compilation * Right logic to avoid switch on reencode when default layout. * Clean up some todos * remove trie meta from root upstream * update upstream and fix benches. * split some long lines. * UPdate trie crate to work with new design. * Finish update to refactored upstream. * update to latest triedb changes. * Clean up. * fix executor test. * rust fmt from master. * rust format. * rustfmt * fix * start host function driven versioning * update state-machine part * still need access to state version from runtime * state hash in mem: wrong * direction likely correct, but passing call to code exec for genesis init seem awkward. * state version serialize in runtime, wrong approach, just initialize it with no threshold for core api < 4 seems more proper. * stateversion from runtime version (core api >= 4). * update trie, fix tests * unused import * clean some TODOs * Require RuntimeVersionOf for executor * use RuntimeVersionOf to resolve genesis state version. * update runtime version test * fix state-machine tests * TODO * Use runtime version from storage wasm with fast sync. * rustfmt * fmt * fix test * revert useless changes. * clean some unused changes * fmt * removing useless trait function. * remove remaining reference to state_hash * fix some imports * Follow chain state version management. * trie update, fix and constant threshold for trie layouts. * update deps * Update to latest trie pr changes. * fix benches * Verify proof requires right layout. * update trie_root * Update trie deps to latest * Update to latest trie versioning * Removing patch * update lock * extrinsic for sc-service-test using layout v0. * Adding RuntimeVersionOf to CallExecutor works. * fmt * error when resolving version and no wasm in storage. * use existing utils to instantiate runtime code. * Patch to delay runtime switch. * Revert "Patch to delay runtime switch." This reverts commit 67e55fee468f1a0cda853f5362b22e0d775786da. * useless closure * remove remaining state_hash variables. * Remove outdated comment * useless inner hash * fmt * fmt and opt-in feature to apply state change. * feature gate core version, use new test feature for node and test node * Use a 'State' api version instead of Core one. * fix merge of test function * use blake macro. * Fix state api (require declaring the api in runtime). * Opt out feature, fix macro for io to select a given version instead of latest. * run test nodes on new state. * fix * Apply review change (docs and error). * fmt * use explicit runtime_interface in doc test * fix ui test * fix doc test * fmt * use default for path and specname when resolving version. * small review related changes. * doc value size requirement. * rename old_state feature * Remove macro changes * feature rename * state version as host function parameter * remove flag for client api * fix tests * switch storage chain proof to V1 * host functions, pass by state version enum * use WrappedRuntimeCode * start * state_version in runtime version * rust fmt * Update storage proof of max size. * fix runtime version rpc test * right intent of convert from compat * fix doc test * fix doc test * split proof * decode without replay, and remove some reexports. * Decode with compatibility by default. * switch state_version to u8. And remove RuntimeVersionBasis. * test * use api when reading embedded version * fix decode with apis * extract core version instead * test fix * unused import * review changes. Co-authored-by: kianenigma <kian@parity.io>
This commit is contained in:
@@ -34,7 +34,7 @@ use sp_core::{
|
||||
};
|
||||
use sp_runtime::{
|
||||
traits::{Block as BlockT, HashFor},
|
||||
Storage,
|
||||
StateVersion, Storage,
|
||||
};
|
||||
use sp_state_machine::{
|
||||
backend::Backend as StateBackend, ChildStorageCollection, DBValue, ProofRecorder,
|
||||
@@ -73,6 +73,7 @@ impl<Block: BlockT> sp_state_machine::Storage<HashFor<Block>> for StorageDb<Bloc
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// State that manages the backend database reference. Allows runtime to control the database.
|
||||
pub struct BenchmarkingState<B: BlockT> {
|
||||
root: Cell<B::Hash>,
|
||||
@@ -105,9 +106,10 @@ impl<B: BlockT> BenchmarkingState<B> {
|
||||
record_proof: bool,
|
||||
enable_tracking: bool,
|
||||
) -> Result<Self, String> {
|
||||
let state_version = sp_runtime::StateVersion::default();
|
||||
let mut root = B::Hash::default();
|
||||
let mut mdb = MemoryDB::<HashFor<B>>::default();
|
||||
sp_state_machine::TrieDBMut::<HashFor<B>>::new(&mut mdb, &mut root);
|
||||
sp_state_machine::TrieDBMutV1::<HashFor<B>>::new(&mut mdb, &mut root);
|
||||
|
||||
let mut state = BenchmarkingState {
|
||||
state: RefCell::new(None),
|
||||
@@ -138,6 +140,7 @@ impl<B: BlockT> BenchmarkingState<B> {
|
||||
state.state.borrow_mut().as_mut().unwrap().full_storage_root(
|
||||
genesis.top.iter().map(|(k, v)| (k.as_ref(), Some(v.as_ref()))),
|
||||
child_delta,
|
||||
state_version,
|
||||
);
|
||||
state.genesis = transaction.clone().drain();
|
||||
state.genesis_root = root.clone();
|
||||
@@ -415,6 +418,7 @@ impl<B: BlockT> StateBackend<HashFor<B>> for BenchmarkingState<B> {
|
||||
fn storage_root<'a>(
|
||||
&self,
|
||||
delta: impl Iterator<Item = (&'a [u8], Option<&'a [u8]>)>,
|
||||
state_version: StateVersion,
|
||||
) -> (B::Hash, Self::Transaction)
|
||||
where
|
||||
B::Hash: Ord,
|
||||
@@ -422,13 +426,14 @@ impl<B: BlockT> StateBackend<HashFor<B>> for BenchmarkingState<B> {
|
||||
self.state
|
||||
.borrow()
|
||||
.as_ref()
|
||||
.map_or(Default::default(), |s| s.storage_root(delta))
|
||||
.map_or(Default::default(), |s| s.storage_root(delta, state_version))
|
||||
}
|
||||
|
||||
fn child_storage_root<'a>(
|
||||
&self,
|
||||
child_info: &ChildInfo,
|
||||
delta: impl Iterator<Item = (&'a [u8], Option<&'a [u8]>)>,
|
||||
state_version: StateVersion,
|
||||
) -> (B::Hash, bool, Self::Transaction)
|
||||
where
|
||||
B::Hash: Ord,
|
||||
@@ -436,7 +441,7 @@ impl<B: BlockT> StateBackend<HashFor<B>> for BenchmarkingState<B> {
|
||||
self.state
|
||||
.borrow()
|
||||
.as_ref()
|
||||
.map_or(Default::default(), |s| s.child_storage_root(child_info, delta))
|
||||
.map_or(Default::default(), |s| s.child_storage_root(child_info, delta, state_version))
|
||||
}
|
||||
|
||||
fn pairs(&self) -> Vec<(Vec<u8>, Vec<u8>)> {
|
||||
|
||||
@@ -82,7 +82,7 @@ use sp_runtime::{
|
||||
Block as BlockT, Hash, HashFor, Header as HeaderT, NumberFor, One, SaturatedConversion,
|
||||
Zero,
|
||||
},
|
||||
Justification, Justifications, Storage,
|
||||
Justification, Justifications, StateVersion, Storage,
|
||||
};
|
||||
use sp_state_machine::{
|
||||
backend::Backend as StateBackend, ChildStorageCollection, DBValue, IndexOperation,
|
||||
@@ -235,22 +235,24 @@ impl<B: BlockT> StateBackend<HashFor<B>> for RefTrackingState<B> {
|
||||
fn storage_root<'a>(
|
||||
&self,
|
||||
delta: impl Iterator<Item = (&'a [u8], Option<&'a [u8]>)>,
|
||||
state_version: StateVersion,
|
||||
) -> (B::Hash, Self::Transaction)
|
||||
where
|
||||
B::Hash: Ord,
|
||||
{
|
||||
self.state.storage_root(delta)
|
||||
self.state.storage_root(delta, state_version)
|
||||
}
|
||||
|
||||
fn child_storage_root<'a>(
|
||||
&self,
|
||||
child_info: &ChildInfo,
|
||||
delta: impl Iterator<Item = (&'a [u8], Option<&'a [u8]>)>,
|
||||
state_version: StateVersion,
|
||||
) -> (B::Hash, bool, Self::Transaction)
|
||||
where
|
||||
B::Hash: Ord,
|
||||
{
|
||||
self.state.child_storage_root(child_info, delta)
|
||||
self.state.child_storage_root(child_info, delta, state_version)
|
||||
}
|
||||
|
||||
fn pairs(&self) -> Vec<(Vec<u8>, Vec<u8>)> {
|
||||
@@ -760,7 +762,11 @@ impl<Block: BlockT> BlockImportOperation<Block> {
|
||||
}
|
||||
}
|
||||
|
||||
fn apply_new_state(&mut self, storage: Storage) -> ClientResult<Block::Hash> {
|
||||
fn apply_new_state(
|
||||
&mut self,
|
||||
storage: Storage,
|
||||
state_version: StateVersion,
|
||||
) -> ClientResult<Block::Hash> {
|
||||
if storage.top.keys().any(|k| well_known_keys::is_child_storage_key(&k)) {
|
||||
return Err(sp_blockchain::Error::InvalidState.into())
|
||||
}
|
||||
@@ -775,6 +781,7 @@ impl<Block: BlockT> BlockImportOperation<Block> {
|
||||
let (root, transaction) = self.old_state.full_storage_root(
|
||||
storage.top.iter().map(|(k, v)| (&k[..], Some(&v[..]))),
|
||||
child_delta,
|
||||
state_version,
|
||||
);
|
||||
|
||||
self.db_updates = transaction;
|
||||
@@ -814,14 +821,23 @@ impl<Block: BlockT> sc_client_api::backend::BlockImportOperation<Block>
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn reset_storage(&mut self, storage: Storage) -> ClientResult<Block::Hash> {
|
||||
let root = self.apply_new_state(storage)?;
|
||||
fn reset_storage(
|
||||
&mut self,
|
||||
storage: Storage,
|
||||
state_version: StateVersion,
|
||||
) -> ClientResult<Block::Hash> {
|
||||
let root = self.apply_new_state(storage, state_version)?;
|
||||
self.commit_state = true;
|
||||
Ok(root)
|
||||
}
|
||||
|
||||
fn set_genesis_state(&mut self, storage: Storage, commit: bool) -> ClientResult<Block::Hash> {
|
||||
let root = self.apply_new_state(storage)?;
|
||||
fn set_genesis_state(
|
||||
&mut self,
|
||||
storage: Storage,
|
||||
commit: bool,
|
||||
state_version: StateVersion,
|
||||
) -> ClientResult<Block::Hash> {
|
||||
let root = self.apply_new_state(storage, state_version)?;
|
||||
self.commit_state = commit;
|
||||
Ok(root)
|
||||
}
|
||||
@@ -924,7 +940,8 @@ impl<Block: BlockT> EmptyStorage<Block> {
|
||||
pub fn new() -> Self {
|
||||
let mut root = Block::Hash::default();
|
||||
let mut mdb = MemoryDB::<HashFor<Block>>::default();
|
||||
sp_state_machine::TrieDBMut::<HashFor<Block>>::new(&mut mdb, &mut root);
|
||||
// both triedbmut are the same on empty storage.
|
||||
sp_state_machine::TrieDBMutV1::<HashFor<Block>>::new(&mut mdb, &mut root);
|
||||
EmptyStorage(root)
|
||||
}
|
||||
}
|
||||
@@ -2262,7 +2279,7 @@ pub(crate) mod tests {
|
||||
use sp_runtime::{
|
||||
testing::{Block as RawBlock, ExtrinsicWrapper, Header},
|
||||
traits::{BlakeTwo256, Hash},
|
||||
ConsensusEngineId,
|
||||
ConsensusEngineId, StateVersion,
|
||||
};
|
||||
|
||||
const CONS0_ENGINE_ID: ConsensusEngineId = *b"CON0";
|
||||
@@ -2295,7 +2312,7 @@ pub(crate) mod tests {
|
||||
let header = Header {
|
||||
number,
|
||||
parent_hash,
|
||||
state_root: BlakeTwo256::trie_root(Vec::new()),
|
||||
state_root: BlakeTwo256::trie_root(Vec::new(), StateVersion::V1),
|
||||
digest,
|
||||
extrinsics_root,
|
||||
};
|
||||
@@ -2375,6 +2392,10 @@ pub(crate) mod tests {
|
||||
|
||||
#[test]
|
||||
fn set_state_data() {
|
||||
set_state_data_inner(StateVersion::V0);
|
||||
set_state_data_inner(StateVersion::V1);
|
||||
}
|
||||
fn set_state_data_inner(state_version: StateVersion) {
|
||||
let db = Backend::<Block>::new_test(2, 0);
|
||||
let hash = {
|
||||
let mut op = db.begin_operation().unwrap();
|
||||
@@ -2390,15 +2411,18 @@ pub(crate) mod tests {
|
||||
|
||||
header.state_root = op
|
||||
.old_state
|
||||
.storage_root(storage.iter().map(|(x, y)| (&x[..], Some(&y[..]))))
|
||||
.storage_root(storage.iter().map(|(x, y)| (&x[..], Some(&y[..]))), state_version)
|
||||
.0
|
||||
.into();
|
||||
let hash = header.hash();
|
||||
|
||||
op.reset_storage(Storage {
|
||||
top: storage.into_iter().collect(),
|
||||
children_default: Default::default(),
|
||||
})
|
||||
op.reset_storage(
|
||||
Storage {
|
||||
top: storage.into_iter().collect(),
|
||||
children_default: Default::default(),
|
||||
},
|
||||
state_version,
|
||||
)
|
||||
.unwrap();
|
||||
op.set_block_data(header.clone(), Some(vec![]), None, None, NewBlockState::Best)
|
||||
.unwrap();
|
||||
@@ -2427,9 +2451,10 @@ pub(crate) mod tests {
|
||||
|
||||
let storage = vec![(vec![1, 3, 5], None), (vec![5, 5, 5], Some(vec![4, 5, 6]))];
|
||||
|
||||
let (root, overlay) = op
|
||||
.old_state
|
||||
.storage_root(storage.iter().map(|(k, v)| (&k[..], v.as_ref().map(|v| &v[..]))));
|
||||
let (root, overlay) = op.old_state.storage_root(
|
||||
storage.iter().map(|(k, v)| (&k[..], v.as_ref().map(|v| &v[..]))),
|
||||
state_version,
|
||||
);
|
||||
op.update_db_storage(overlay).unwrap();
|
||||
header.state_root = root.into();
|
||||
|
||||
@@ -2450,6 +2475,7 @@ pub(crate) mod tests {
|
||||
#[test]
|
||||
fn delete_only_when_negative_rc() {
|
||||
sp_tracing::try_init_simple();
|
||||
let state_version = StateVersion::default();
|
||||
let key;
|
||||
let backend = Backend::<Block>::new_test(1, 0);
|
||||
|
||||
@@ -2466,13 +2492,14 @@ pub(crate) mod tests {
|
||||
extrinsics_root: Default::default(),
|
||||
};
|
||||
|
||||
header.state_root = op.old_state.storage_root(std::iter::empty()).0.into();
|
||||
header.state_root =
|
||||
op.old_state.storage_root(std::iter::empty(), state_version).0.into();
|
||||
let hash = header.hash();
|
||||
|
||||
op.reset_storage(Storage {
|
||||
top: Default::default(),
|
||||
children_default: Default::default(),
|
||||
})
|
||||
op.reset_storage(
|
||||
Storage { top: Default::default(), children_default: Default::default() },
|
||||
state_version,
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
key = op.db_updates.insert(EMPTY_PREFIX, b"hello");
|
||||
@@ -2506,7 +2533,7 @@ pub(crate) mod tests {
|
||||
|
||||
header.state_root = op
|
||||
.old_state
|
||||
.storage_root(storage.iter().cloned().map(|(x, y)| (x, Some(y))))
|
||||
.storage_root(storage.iter().cloned().map(|(x, y)| (x, Some(y))), state_version)
|
||||
.0
|
||||
.into();
|
||||
let hash = header.hash();
|
||||
@@ -2543,7 +2570,7 @@ pub(crate) mod tests {
|
||||
|
||||
header.state_root = op
|
||||
.old_state
|
||||
.storage_root(storage.iter().cloned().map(|(x, y)| (x, Some(y))))
|
||||
.storage_root(storage.iter().cloned().map(|(x, y)| (x, Some(y))), state_version)
|
||||
.0
|
||||
.into();
|
||||
let hash = header.hash();
|
||||
@@ -2577,7 +2604,7 @@ pub(crate) mod tests {
|
||||
|
||||
header.state_root = op
|
||||
.old_state
|
||||
.storage_root(storage.iter().cloned().map(|(x, y)| (x, Some(y))))
|
||||
.storage_root(storage.iter().cloned().map(|(x, y)| (x, Some(y))), state_version)
|
||||
.0
|
||||
.into();
|
||||
|
||||
@@ -2912,6 +2939,7 @@ pub(crate) mod tests {
|
||||
|
||||
#[test]
|
||||
fn storage_hash_is_cached_correctly() {
|
||||
let state_version = StateVersion::default();
|
||||
let backend = Backend::<Block>::new_test(10, 10);
|
||||
|
||||
let hash0 = {
|
||||
@@ -2931,15 +2959,18 @@ pub(crate) mod tests {
|
||||
|
||||
header.state_root = op
|
||||
.old_state
|
||||
.storage_root(storage.iter().map(|(x, y)| (&x[..], Some(&y[..]))))
|
||||
.storage_root(storage.iter().map(|(x, y)| (&x[..], Some(&y[..]))), state_version)
|
||||
.0
|
||||
.into();
|
||||
let hash = header.hash();
|
||||
|
||||
op.reset_storage(Storage {
|
||||
top: storage.into_iter().collect(),
|
||||
children_default: Default::default(),
|
||||
})
|
||||
op.reset_storage(
|
||||
Storage {
|
||||
top: storage.into_iter().collect(),
|
||||
children_default: Default::default(),
|
||||
},
|
||||
state_version,
|
||||
)
|
||||
.unwrap();
|
||||
op.set_block_data(header.clone(), Some(vec![]), None, None, NewBlockState::Best)
|
||||
.unwrap();
|
||||
@@ -2968,9 +2999,10 @@ pub(crate) mod tests {
|
||||
|
||||
let storage = vec![(b"test".to_vec(), Some(b"test2".to_vec()))];
|
||||
|
||||
let (root, overlay) = op
|
||||
.old_state
|
||||
.storage_root(storage.iter().map(|(k, v)| (&k[..], v.as_ref().map(|v| &v[..]))));
|
||||
let (root, overlay) = op.old_state.storage_root(
|
||||
storage.iter().map(|(k, v)| (&k[..], v.as_ref().map(|v| &v[..]))),
|
||||
state_version,
|
||||
);
|
||||
op.update_db_storage(overlay).unwrap();
|
||||
header.state_root = root.into();
|
||||
let hash = header.hash();
|
||||
@@ -3212,7 +3244,7 @@ pub(crate) mod tests {
|
||||
let header = Header {
|
||||
number: 1,
|
||||
parent_hash: block0,
|
||||
state_root: BlakeTwo256::trie_root(Vec::new()),
|
||||
state_root: BlakeTwo256::trie_root(Vec::new(), StateVersion::V1),
|
||||
digest: Default::default(),
|
||||
extrinsics_root: Default::default(),
|
||||
};
|
||||
@@ -3224,7 +3256,7 @@ pub(crate) mod tests {
|
||||
let header = Header {
|
||||
number: 2,
|
||||
parent_hash: block1,
|
||||
state_root: BlakeTwo256::trie_root(Vec::new()),
|
||||
state_root: BlakeTwo256::trie_root(Vec::new(), StateVersion::V1),
|
||||
digest: Default::default(),
|
||||
extrinsics_root: Default::default(),
|
||||
};
|
||||
@@ -3247,7 +3279,7 @@ pub(crate) mod tests {
|
||||
let header = Header {
|
||||
number: 1,
|
||||
parent_hash: block0,
|
||||
state_root: BlakeTwo256::trie_root(Vec::new()),
|
||||
state_root: BlakeTwo256::trie_root(Vec::new(), StateVersion::V1),
|
||||
digest: Default::default(),
|
||||
extrinsics_root: Default::default(),
|
||||
};
|
||||
|
||||
@@ -26,7 +26,10 @@ use linked_hash_map::{Entry, LinkedHashMap};
|
||||
use log::trace;
|
||||
use parking_lot::{RwLock, RwLockUpgradableReadGuard};
|
||||
use sp_core::{hexdisplay::HexDisplay, storage::ChildInfo};
|
||||
use sp_runtime::traits::{Block as BlockT, HashFor, Header, NumberFor};
|
||||
use sp_runtime::{
|
||||
traits::{Block as BlockT, HashFor, Header, NumberFor},
|
||||
StateVersion,
|
||||
};
|
||||
use sp_state_machine::{
|
||||
backend::Backend as StateBackend, ChildStorageCollection, StorageCollection, StorageKey,
|
||||
StorageValue, TrieBackend,
|
||||
@@ -673,22 +676,24 @@ impl<S: StateBackend<HashFor<B>>, B: BlockT> StateBackend<HashFor<B>> for Cachin
|
||||
fn storage_root<'a>(
|
||||
&self,
|
||||
delta: impl Iterator<Item = (&'a [u8], Option<&'a [u8]>)>,
|
||||
state_version: StateVersion,
|
||||
) -> (B::Hash, Self::Transaction)
|
||||
where
|
||||
B::Hash: Ord,
|
||||
{
|
||||
self.state.storage_root(delta)
|
||||
self.state.storage_root(delta, state_version)
|
||||
}
|
||||
|
||||
fn child_storage_root<'a>(
|
||||
&self,
|
||||
child_info: &ChildInfo,
|
||||
delta: impl Iterator<Item = (&'a [u8], Option<&'a [u8]>)>,
|
||||
state_version: StateVersion,
|
||||
) -> (B::Hash, bool, Self::Transaction)
|
||||
where
|
||||
B::Hash: Ord,
|
||||
{
|
||||
self.state.child_storage_root(child_info, delta)
|
||||
self.state.child_storage_root(child_info, delta, state_version)
|
||||
}
|
||||
|
||||
fn pairs(&self) -> Vec<(Vec<u8>, Vec<u8>)> {
|
||||
@@ -871,22 +876,24 @@ impl<S: StateBackend<HashFor<B>>, B: BlockT> StateBackend<HashFor<B>>
|
||||
fn storage_root<'a>(
|
||||
&self,
|
||||
delta: impl Iterator<Item = (&'a [u8], Option<&'a [u8]>)>,
|
||||
state_version: StateVersion,
|
||||
) -> (B::Hash, Self::Transaction)
|
||||
where
|
||||
B::Hash: Ord,
|
||||
{
|
||||
self.caching_state().storage_root(delta)
|
||||
self.caching_state().storage_root(delta, state_version)
|
||||
}
|
||||
|
||||
fn child_storage_root<'a>(
|
||||
&self,
|
||||
child_info: &ChildInfo,
|
||||
delta: impl Iterator<Item = (&'a [u8], Option<&'a [u8]>)>,
|
||||
state_version: StateVersion,
|
||||
) -> (B::Hash, bool, Self::Transaction)
|
||||
where
|
||||
B::Hash: Ord,
|
||||
{
|
||||
self.caching_state().child_storage_root(child_info, delta)
|
||||
self.caching_state().child_storage_root(child_info, delta, state_version)
|
||||
}
|
||||
|
||||
fn pairs(&self) -> Vec<(Vec<u8>, Vec<u8>)> {
|
||||
@@ -1182,7 +1189,10 @@ mod tests {
|
||||
|
||||
let shared = new_shared_cache::<Block>(256 * 1024, (0, 1));
|
||||
let mut backend = InMemoryBackend::<BlakeTwo256>::default();
|
||||
backend.insert(std::iter::once((None, vec![(key.clone(), Some(vec![1]))])));
|
||||
backend.insert(
|
||||
std::iter::once((None, vec![(key.clone(), Some(vec![1]))])),
|
||||
Default::default(),
|
||||
);
|
||||
|
||||
let mut s = CachingState::new(backend.clone(), shared.clone(), Some(root_parent));
|
||||
s.cache.sync_cache(
|
||||
|
||||
Reference in New Issue
Block a user