Skip to content
This repository was archived by the owner on Nov 15, 2023. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from 8 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
4 changes: 4 additions & 0 deletions core/client/db/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,10 @@ impl<B: BlockT> StateBackend<Blake2Hasher> for RefTrackingState<B> {
self.state.for_keys_with_prefix(prefix, f)
}

fn for_key_values_with_prefix<F: FnMut(&[u8], &[u8])>(&self, prefix: &[u8], f: F) {
self.state.for_key_values_with_prefix(prefix, f)
}

fn for_keys_in_child_storage<F: FnMut(&[u8])>(&self, storage_key: &[u8], f: F) {
self.state.for_keys_in_child_storage(storage_key, f)
}
Expand Down
4 changes: 4 additions & 0 deletions core/client/db/src/storage_cache.rs
Original file line number Diff line number Diff line change
Expand Up @@ -523,6 +523,10 @@ impl<H: Hasher, S: StateBackend<H>, B:Block> StateBackend<H> for CachingState<H,
self.state.for_keys_with_prefix(prefix, f)
}

fn for_key_values_with_prefix<F: FnMut(&[u8], &[u8])>(&self, prefix: &[u8], f: F) {
self.state.for_key_values_with_prefix(prefix, f)
}

fn for_keys_in_child_storage<F: FnMut(&[u8])>(&self, storage_key: &[u8], f: F) {
self.state.for_keys_in_child_storage(storage_key, f)
}
Expand Down
17 changes: 14 additions & 3 deletions core/client/src/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -531,6 +531,7 @@ impl<B, E, Block, RA> Client<B, E, Block, RA> where
&self,
first: NumberFor<Block>,
last: BlockId<Block>,
storage_key: Option<&StorageKey>,
key: &StorageKey
) -> error::Result<Vec<(NumberFor<Block>, u32)>> {
let (config, storage) = self.require_changes_trie()?;
Expand All @@ -546,6 +547,7 @@ impl<B, E, Block, RA> Client<B, E, Block, RA> where
number: last_number,
},
self.backend.blockchain().info().best_number,
storage_key.as_ref().map(|sk| sk.0.as_slice()),
&key.0)
.and_then(|r| r.map(|r| r.map(|(block, tx)| (block, tx))).collect::<Result<_, _>>())
.map_err(|err| error::Error::ChangesTrieAccessFailed(err))
Expand All @@ -563,13 +565,15 @@ impl<B, E, Block, RA> Client<B, E, Block, RA> where
last: Block::Hash,
min: Block::Hash,
max: Block::Hash,
key: &StorageKey
storage_key: Option<&StorageKey>,
key: &StorageKey,
) -> error::Result<ChangesProof<Block::Header>> {
self.key_changes_proof_with_cht_size(
first,
last,
min,
max,
storage_key,
key,
cht::size(),
)
Expand All @@ -582,6 +586,7 @@ impl<B, E, Block, RA> Client<B, E, Block, RA> where
last: Block::Hash,
min: Block::Hash,
max: Block::Hash,
storage_key: Option<&StorageKey>,
key: &StorageKey,
cht_size: NumberFor<Block>,
) -> error::Result<ChangesProof<Block::Header>> {
Expand Down Expand Up @@ -648,7 +653,8 @@ impl<B, E, Block, RA> Client<B, E, Block, RA> where
number: last_number,
},
max_number,
&key.0
storage_key.as_ref().map(|sk| sk.0.as_slice()),
&key.0,
)
.map_err(|err| error::Error::from(error::Error::ChangesTrieAccessFailed(err)))?;

Expand Down Expand Up @@ -2457,7 +2463,12 @@ pub(crate) mod tests {

for (index, (begin, end, key, expected_result)) in test_cases.into_iter().enumerate() {
let end = client.block_hash(end).unwrap().unwrap();
let actual_result = client.key_changes(begin, BlockId::Hash(end), &StorageKey(key)).unwrap();
let actual_result = client.key_changes(
begin,
BlockId::Hash(end),
None,
&StorageKey(key),
).unwrap();
match actual_result == expected_result {
true => (),
false => panic!(format!("Failed test {}: actual = {:?}, expected = {:?}",
Expand Down
13 changes: 13 additions & 0 deletions core/client/src/light/backend.rs
Original file line number Diff line number Diff line change
Expand Up @@ -377,6 +377,10 @@ where
// whole state is not available on light node
}

fn for_key_values_with_prefix<A: FnMut(&[u8], &[u8])>(&self, _prefix: &[u8], _action: A) {
// whole state is not available on light node
}

fn for_keys_in_child_storage<A: FnMut(&[u8])>(&self, _storage_key: &[u8], _action: A) {
// whole state is not available on light node
}
Expand Down Expand Up @@ -448,6 +452,15 @@ where
}
}

fn for_key_values_with_prefix<A: FnMut(&[u8], &[u8])>(&self, prefix: &[u8], action: A) {
match *self {
OnDemandOrGenesisState::OnDemand(ref state) =>
StateBackend::<H>::for_key_values_with_prefix(state, prefix, action),
OnDemandOrGenesisState::Genesis(ref state) => state.for_key_values_with_prefix(prefix, action),
}
}


fn for_keys_in_child_storage<A: FnMut(&[u8])>(&self, storage_key: &[u8], action: A) {
match *self {
OnDemandOrGenesisState::OnDemand(ref state) =>
Expand Down
14 changes: 10 additions & 4 deletions core/client/src/light/fetcher.rs
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,8 @@ pub struct RemoteChangesRequest<Header: HeaderT> {
/// Known changes trie roots for the range of blocks [tries_roots.0..max_block].
/// Proofs for roots of ascendants of tries_roots.0 are provided by the remote node.
pub tries_roots: (Header::Number, Header::Hash, Vec<Header::Hash>),
/// Optional Child Storage key to read.
pub storage_key: Option<Vec<u8>>,
/// Storage key to read.
pub key: Vec<u8>,
/// Number of times to retry request. None means that default RETRY_COUNT is used.
Expand Down Expand Up @@ -297,6 +299,7 @@ impl<E, H, B: BlockT, S: BlockchainStorage<B>, F> LightDataChecker<E, H, B, S, F
number: request.last_block.0,
},
remote_max_block,
request.storage_key.as_ref().map(Vec::as_slice),
&request.key)
.map_err(|err| ClientError::ChangesTrieAccessFailed(err))
}
Expand Down Expand Up @@ -678,7 +681,7 @@ pub mod tests {
// 'fetch' changes proof from remote node
let key = StorageKey(key);
let remote_proof = remote_client.key_changes_proof(
begin_hash, end_hash, begin_hash, max_hash, &key
begin_hash, end_hash, begin_hash, max_hash, None, &key
).unwrap();

// check proof on local client
Expand All @@ -690,6 +693,7 @@ pub mod tests {
max_block: (max, max_hash),
tries_roots: (begin, begin_hash, local_roots_range),
key: key.0,
storage_key: None,
retry_count: None,
};
let local_result = local_checker.check_changes_proof(&request, ChangesProof {
Expand Down Expand Up @@ -724,7 +728,7 @@ pub mod tests {
let b3 = remote_client.block_hash_from_id(&BlockId::Number(3)).unwrap().unwrap();
let b4 = remote_client.block_hash_from_id(&BlockId::Number(4)).unwrap().unwrap();
let remote_proof = remote_client.key_changes_proof_with_cht_size(
b1, b4, b3, b4, &dave, 4
b1, b4, b3, b4, None, &dave, 4
).unwrap();

// prepare local checker, having a root of changes trie CHT#0
Expand All @@ -743,6 +747,7 @@ pub mod tests {
last_block: (4, b4),
max_block: (4, b4),
tries_roots: (3, b3, vec![remote_roots[2].clone(), remote_roots[3].clone()]),
storage_key: None,
key: dave.0,
retry_count: None,
};
Expand Down Expand Up @@ -774,7 +779,7 @@ pub mod tests {
// 'fetch' changes proof from remote node
let key = StorageKey(key);
let remote_proof = remote_client.key_changes_proof(
begin_hash, end_hash, begin_hash, max_hash, &key).unwrap();
begin_hash, end_hash, begin_hash, max_hash, None, &key).unwrap();

let local_roots_range = local_roots.clone()[(begin - 1) as usize..].to_vec();
let request = RemoteChangesRequest::<Header> {
Expand All @@ -783,6 +788,7 @@ pub mod tests {
last_block: (end, end_hash),
max_block: (max, max_hash),
tries_roots: (begin, begin_hash, local_roots_range.clone()),
storage_key: None,
key: key.0,
retry_count: None,
};
Expand Down Expand Up @@ -836,7 +842,7 @@ pub mod tests {
let b3 = remote_client.block_hash_from_id(&BlockId::Number(3)).unwrap().unwrap();
let b4 = remote_client.block_hash_from_id(&BlockId::Number(4)).unwrap().unwrap();
let remote_proof = remote_client.key_changes_proof_with_cht_size(
b1, b4, b3, b4, &dave, 4
b1, b4, b3, b4, None, &dave, 4
).unwrap();

// fails when changes trie CHT is missing from the local db
Expand Down
6 changes: 4 additions & 2 deletions core/network/src/chain.rs
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ pub trait Client<Block: BlockT>: Send + Sync {
last: Block::Hash,
min: Block::Hash,
max: Block::Hash,
storage_key: Option<&StorageKey>,
key: &StorageKey
) -> Result<ChangesProof<Block::Header>, Error>;

Expand Down Expand Up @@ -123,9 +124,10 @@ impl<B, E, Block, RA> Client<Block> for SubstrateClient<B, E, Block, RA> where
last: Block::Hash,
min: Block::Hash,
max: Block::Hash,
key: &StorageKey
storage_key: Option<&StorageKey>,
key: &StorageKey,
) -> Result<ChangesProof<Block::Header>, Error> {
(self as &SubstrateClient<B, E, Block, RA>).key_changes_proof(first, last, min, max, key)
(self as &SubstrateClient<B, E, Block, RA>).key_changes_proof(first, last, min, max, storage_key, key)
}

fn is_descendent_of(&self, base: &Block::Hash, block: &Block::Hash) -> Result<bool, Error> {
Expand Down
20 changes: 16 additions & 4 deletions core/network/src/protocol.rs
Original file line number Diff line number Diff line change
Expand Up @@ -225,14 +225,16 @@ impl<'a, B: BlockT> OnDemandNetwork<B> for OnDemandIn<'a, B> {
last: <B as BlockT>::Hash,
min: <B as BlockT>::Hash,
max: <B as BlockT>::Hash,
key: Vec<u8>
storage_key: Option<Vec<u8>>,
key: Vec<u8>,
) {
let message = message::generic::Message::RemoteChangesRequest(message::RemoteChangesRequest {
id,
first,
last,
min,
max,
storage_key,
key,
});

Expand Down Expand Up @@ -1348,24 +1350,34 @@ impl<B: BlockT, S: NetworkSpecialization<B>, H: ExHashT> Protocol<B, S, H> {
trace!(target: "sync", "Remote changes proof request {} from {} for key {} ({}..{})",
request.id,
who,
request.key.to_hex::<String>(),
if let Some(sk) = request.storage_key.as_ref() {
format!("{} : {}", sk.to_hex::<String>(), request.key.to_hex::<String>())
} else {
request.key.to_hex::<String>()
},
request.first,
request.last
);
let storage_key = request.storage_key.map(|sk| StorageKey(sk));
let key = StorageKey(request.key);
let proof = match self.context_data.chain.key_changes_proof(
request.first,
request.last,
request.min,
request.max,
&key
storage_key.as_ref(),
&key,
) {
Ok(proof) => proof,
Err(error) => {
trace!(target: "sync", "Remote changes proof request {} from {} for key {} ({}..{}) failed with: {}",
request.id,
who,
key.0.to_hex::<String>(),
if let Some(sk) = storage_key {
format!("{} : {}", sk.0.to_hex::<String>(), key.0.to_hex::<String>())
} else {
key.0.to_hex::<String>()
},
request.first,
request.last,
error
Expand Down
2 changes: 2 additions & 0 deletions core/network/src/protocol/message.rs
Original file line number Diff line number Diff line change
Expand Up @@ -345,6 +345,8 @@ pub mod generic {
pub min: H,
/// Hash of the last block that we can use when querying changes.
pub max: H,
/// Storage child node key which changes are requested.
pub storage_key: Option<Vec<u8>>,
/// Storage key which changes are requested.
pub key: Vec<u8>,
}
Expand Down
7 changes: 5 additions & 2 deletions core/network/src/protocol/on_demand.rs
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,8 @@ pub trait OnDemandNetwork<B: BlockT> {
last: <B as BlockT>::Hash,
min: <B as BlockT>::Hash,
max: <B as BlockT>::Hash,
key: Vec<u8>
storage_key: Option<Vec<u8>>,
key: Vec<u8>,
);

/// Send to `who` a body request.
Expand Down Expand Up @@ -601,6 +602,7 @@ impl<Block: BlockT> Request<Block> {
data.last_block.1.clone(),
data.tries_roots.1.clone(),
data.max_block.1.clone(),
data.storage_key.clone(),
data.key.clone(),
),
RequestData::RemoteBody(ref data, _) =>
Expand Down Expand Up @@ -757,7 +759,7 @@ pub mod tests {
_: Vec<u8>) {}
fn send_call_request(&mut self, _: &PeerId, _: RequestId, _: <B as BlockT>::Hash, _: String, _: Vec<u8>) {}
fn send_changes_request(&mut self, _: &PeerId, _: RequestId, _: <B as BlockT>::Hash, _: <B as BlockT>::Hash,
_: <B as BlockT>::Hash, _: <B as BlockT>::Hash, _: Vec<u8>) {}
_: <B as BlockT>::Hash, _: <B as BlockT>::Hash, _: Option<Vec<u8>>, _: Vec<u8>) {}
fn send_body_request(&mut self, _: &PeerId, _: RequestId, _: BlockAttributes, _: FromBlock<<B as BlockT>::Hash,
<<B as BlockT>::Header as HeaderT>::Number>, _: Option<B::Hash>, _: Direction, _: Option<u32>) {}
}
Expand Down Expand Up @@ -1069,6 +1071,7 @@ pub mod tests {
max_block: (100, Default::default()),
tries_roots: (1, Default::default(), vec![]),
key: vec![],
storage_key: None,
retry_count: None,
}, tx));
let thread = ::std::thread::spawn(move || {
Expand Down
2 changes: 1 addition & 1 deletion core/rpc/src/state/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -305,7 +305,7 @@ impl<B, E, Block: BlockT, RA> State<B, E, Block, RA> where
for key in keys {
let mut last_block = None;
let mut last_value = last_values.get(key).cloned().unwrap_or_default();
for (block, _) in self.client.key_changes(begin, end, key)?.into_iter().rev() {
for (block, _) in self.client.key_changes(begin, end, None, key)?.into_iter().rev() {
if last_block == Some(block) {
continue;
}
Expand Down
14 changes: 13 additions & 1 deletion core/state-machine/src/backend.rs
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,14 @@ pub trait Backend<H: Hasher> {

/// Retrieve all entries keys of which start with the given prefix and
/// call `f` for each of those keys.
fn for_keys_with_prefix<F: FnMut(&[u8])>(&self, prefix: &[u8], f: F);
fn for_keys_with_prefix<F: FnMut(&[u8])>(&self, prefix: &[u8], mut f: F) {
self.for_key_values_with_prefix(prefix, |k, _v| f(k))
}

/// Retrieve all entries keys and values of which start with the given prefix and
/// call `f` for each of those keys.
fn for_key_values_with_prefix<F: FnMut(&[u8], &[u8])>(&self, prefix: &[u8], f: F);


/// Calculate the storage root, with given delta over what is already stored in
/// the backend, and produce a "transaction" that can be used to commit.
Expand Down Expand Up @@ -301,6 +308,11 @@ impl<H: Hasher> Backend<H> for InMemory<H> {
self.inner.get(&None).map(|map| map.keys().filter(|key| key.starts_with(prefix)).map(|k| &**k).for_each(f));
}

fn for_key_values_with_prefix<F: FnMut(&[u8], &[u8])>(&self, prefix: &[u8], mut f: F) {
self.inner.get(&None).map(|map| map.iter().filter(|(key, _val)| key.starts_with(prefix))
.for_each(|(k, v)| f(k, v)));
}

fn for_keys_in_child_storage<F: FnMut(&[u8])>(&self, storage_key: &[u8], mut f: F) {
self.inner.get(&Some(storage_key.to_vec())).map(|map| map.keys().for_each(|k| f(&k)));
}
Expand Down
Loading