Run cargo fmt on the whole code base (#9394)

* Run cargo fmt on the whole code base

* Second run

* Add CI check

* Fix compilation

* More unnecessary braces

* Handle weights

* Use --all

* Use correct attributes...

* Fix UI tests

* AHHHHHHHHH

* 🤦

* Docs

* Fix compilation

* 🤷

* Please stop

* 🤦 x 2

* More

* make rustfmt.toml consistent with polkadot

Co-authored-by: André Silva <andrerfosilva@gmail.com>
This commit is contained in:
Bastian Köcher
2021-07-21 16:32:32 +02:00
committed by GitHub
parent d451c38c1c
commit 7b56ab15b4
1010 changed files with 53339 additions and 51208 deletions
+103 -90
View File
@@ -19,38 +19,44 @@
//! Light client backend. Only stores headers and justifications of blocks.
//! Everything else is requested from full nodes on demand.
use std::collections::{HashMap, HashSet};
use std::sync::Arc;
use parking_lot::RwLock;
use std::{
collections::{HashMap, HashSet},
sync::Arc,
};
use codec::{Decode, Encode};
use sp_core::ChangesTrieConfiguration;
use sp_core::storage::{well_known_keys, ChildInfo};
use sp_core::offchain::storage::InMemOffchainStorage;
use sp_state_machine::{
Backend as StateBackend, TrieBackend, InMemoryBackend, ChangesTrieTransaction,
StorageCollection, ChildStorageCollection, IndexOperation,
};
use sp_runtime::{generic::BlockId, Justification, Justifications, Storage};
use sp_runtime::traits::{Block as BlockT, NumberFor, Zero, Header, HashFor};
use sp_blockchain::{Error as ClientError, Result as ClientResult};
use sc_client_api::{
backend::{
AuxStore, Backend as ClientBackend, BlockImportOperation, RemoteBackend, NewBlockState,
PrunableStateChangesTrieStorage,
},
blockchain::{
HeaderBackend as BlockchainHeaderBackend, well_known_cache_keys,
},
light::Storage as BlockchainStorage,
in_mem::check_genesis_storage,
UsageInfo,
};
use super::blockchain::Blockchain;
use hash_db::Hasher;
use sc_client_api::{
backend::{
AuxStore, Backend as ClientBackend, BlockImportOperation, NewBlockState,
PrunableStateChangesTrieStorage, RemoteBackend,
},
blockchain::{well_known_cache_keys, HeaderBackend as BlockchainHeaderBackend},
in_mem::check_genesis_storage,
light::Storage as BlockchainStorage,
UsageInfo,
};
use sp_blockchain::{Error as ClientError, Result as ClientResult};
use sp_core::{
offchain::storage::InMemOffchainStorage,
storage::{well_known_keys, ChildInfo},
ChangesTrieConfiguration,
};
use sp_runtime::{
generic::BlockId,
traits::{Block as BlockT, HashFor, Header, NumberFor, Zero},
Justification, Justifications, Storage,
};
use sp_state_machine::{
Backend as StateBackend, ChangesTrieTransaction, ChildStorageCollection, InMemoryBackend,
IndexOperation, StorageCollection, TrieBackend,
};
const IN_MEMORY_EXPECT_PROOF: &str = "InMemory state backend has Void error type and always succeeds; qed";
const IN_MEMORY_EXPECT_PROOF: &str =
"InMemory state backend has Void error type and always succeeds; qed";
/// Light client backend.
pub struct Backend<S, H: Hasher> {
@@ -84,11 +90,7 @@ pub enum GenesisOrUnavailableState<H: Hasher> {
impl<S, H: Hasher> Backend<S, H> {
/// Create new light backend.
pub fn new(blockchain: Arc<Blockchain<S>>) -> Self {
Self {
blockchain,
genesis_state: RwLock::new(None),
import_lock: Default::default(),
}
Self { blockchain, genesis_state: RwLock::new(None), import_lock: Default::default() }
}
/// Get shared blockchain reference.
@@ -102,9 +104,13 @@ impl<S: AuxStore, H: Hasher> AuxStore for Backend<S, H> {
'a,
'b: 'a,
'c: 'a,
I: IntoIterator<Item=&'a(&'c [u8], &'c [u8])>,
D: IntoIterator<Item=&'a &'b [u8]>,
>(&self, insert: I, delete: D) -> ClientResult<()> {
I: IntoIterator<Item = &'a (&'c [u8], &'c [u8])>,
D: IntoIterator<Item = &'a &'b [u8]>,
>(
&self,
insert: I,
delete: D,
) -> ClientResult<()> {
self.blockchain.storage().insert_aux(insert, delete)
}
@@ -114,10 +120,10 @@ impl<S: AuxStore, H: Hasher> AuxStore for Backend<S, H> {
}
impl<S, Block> ClientBackend<Block> for Backend<S, HashFor<Block>>
where
Block: BlockT,
S: BlockchainStorage<Block>,
Block::Hash: Ord,
where
Block: BlockT,
S: BlockchainStorage<Block>,
Block::Hash: Ord,
{
type BlockImportOperation = ImportOperation<Block, S>;
type Blockchain = Blockchain<S>;
@@ -141,15 +147,12 @@ impl<S, Block> ClientBackend<Block> for Backend<S, HashFor<Block>>
fn begin_state_operation(
&self,
_operation: &mut Self::BlockImportOperation,
_block: BlockId<Block>
_block: BlockId<Block>,
) -> ClientResult<()> {
Ok(())
}
fn commit_operation(
&self,
mut operation: Self::BlockImportOperation,
) -> ClientResult<()> {
fn commit_operation(&self, mut operation: Self::BlockImportOperation) -> ClientResult<()> {
if !operation.finalized_blocks.is_empty() {
for block in operation.finalized_blocks {
self.blockchain.storage().finalize_header(block)?;
@@ -159,7 +162,9 @@ impl<S, Block> ClientBackend<Block> for Backend<S, HashFor<Block>>
if let Some(header) = operation.header {
let is_genesis_import = header.number().is_zero();
if let Some(new_config) = operation.changes_trie_config_update {
operation.cache.insert(well_known_cache_keys::CHANGES_TRIE_CONFIG, new_config.encode());
operation
.cache
.insert(well_known_cache_keys::CHANGES_TRIE_CONFIG, new_config.encode());
}
self.blockchain.storage().import_header(
header,
@@ -175,11 +180,12 @@ impl<S, Block> ClientBackend<Block> for Backend<S, HashFor<Block>>
} else {
for (key, maybe_val) in operation.aux_ops {
match maybe_val {
Some(val) => self.blockchain.storage().insert_aux(
&[(&key[..], &val[..])],
std::iter::empty(),
)?,
None => self.blockchain.storage().insert_aux(std::iter::empty(), &[&key[..]])?,
Some(val) => self
.blockchain
.storage()
.insert_aux(&[(&key[..], &val[..])], std::iter::empty())?,
None =>
self.blockchain.storage().insert_aux(std::iter::empty(), &[&key[..]])?,
}
}
}
@@ -229,7 +235,7 @@ impl<S, Block> ClientBackend<Block> for Backend<S, HashFor<Block>>
// special case for genesis block
if block_number.is_zero() {
if let Some(genesis_state) = self.genesis_state.read().clone() {
return Ok(GenesisOrUnavailableState::Genesis(genesis_state));
return Ok(GenesisOrUnavailableState::Genesis(genesis_state))
}
}
@@ -246,10 +252,7 @@ impl<S, Block> ClientBackend<Block> for Backend<S, HashFor<Block>>
Err(ClientError::NotAvailableOnLightClient)
}
fn remove_leaf_block(
&self,
_hash: &Block::Hash,
) -> ClientResult<()> {
fn remove_leaf_block(&self, _hash: &Block::Hash) -> ClientResult<()> {
Err(ClientError::NotAvailableOnLightClient)
}
@@ -265,8 +268,9 @@ where
Block::Hash: Ord,
{
fn is_local_state_available(&self, block: &BlockId<Block>) -> bool {
self.genesis_state.read().is_some()
&& self.blockchain.expect_block_number_from_id(block)
self.genesis_state.read().is_some() &&
self.blockchain
.expect_block_number_from_id(block)
.map(|num| num.is_zero())
.unwrap_or(false)
}
@@ -277,10 +281,10 @@ where
}
impl<S, Block> BlockImportOperation<Block> for ImportOperation<Block, S>
where
Block: BlockT,
S: BlockchainStorage<Block>,
Block::Hash: Ord,
where
Block: BlockT,
S: BlockchainStorage<Block>,
Block::Hash: Ord,
{
type State = GenesisOrUnavailableState<HashFor<Block>>;
@@ -326,10 +330,14 @@ impl<S, Block> BlockImportOperation<Block> for ImportOperation<Block, S>
check_genesis_storage(&input)?;
// changes trie configuration
let changes_trie_config = input.top.iter()
let changes_trie_config = input
.top
.iter()
.find(|(k, _)| &k[..] == well_known_keys::CHANGES_TRIE_CONFIG)
.map(|(_, v)| Decode::decode(&mut &v[..])
.expect("changes trie configuration is encoded properly at genesis"));
.map(|(_, v)| {
Decode::decode(&mut &v[..])
.expect("changes trie configuration is encoded properly at genesis")
});
self.changes_trie_config_update = Some(changes_trie_config);
// this is only called when genesis block is imported => shouldn't be performance bottleneck
@@ -337,7 +345,8 @@ impl<S, Block> BlockImportOperation<Block> for ImportOperation<Block, S>
storage.insert(None, input.top);
// create a list of children keys to re-compute roots for
let child_delta = input.children_default
let child_delta = input
.children_default
.iter()
.map(|(_storage_key, storage_child)| (&storage_child.child_info, std::iter::empty()));
@@ -360,7 +369,8 @@ impl<S, Block> BlockImportOperation<Block> for ImportOperation<Block, S>
}
fn insert_aux<I>(&mut self, ops: I) -> ClientResult<()>
where I: IntoIterator<Item=(Vec<u8>, Option<Vec<u8>>)>
where
I: IntoIterator<Item = (Vec<u8>, Option<Vec<u8>>)>,
{
self.aux_ops.append(&mut ops.into_iter().collect());
Ok(())
@@ -389,7 +399,10 @@ impl<S, Block> BlockImportOperation<Block> for ImportOperation<Block, S>
Ok(())
}
fn update_transaction_index(&mut self, _index: Vec<IndexOperation>) -> sp_blockchain::Result<()> {
fn update_transaction_index(
&mut self,
_index: Vec<IndexOperation>,
) -> sp_blockchain::Result<()> {
// noop for the light client
Ok(())
}
@@ -405,8 +418,8 @@ impl<H: Hasher> std::fmt::Debug for GenesisOrUnavailableState<H> {
}
impl<H: Hasher> StateBackend<H> for GenesisOrUnavailableState<H>
where
H::Out: Ord + codec::Codec,
where
H::Out: Ord + codec::Codec,
{
type Error = ClientError;
type Transaction = <InMemoryBackend<H> as StateBackend<H>>::Transaction;
@@ -420,11 +433,7 @@ impl<H: Hasher> StateBackend<H> for GenesisOrUnavailableState<H>
}
}
fn child_storage(
&self,
child_info: &ChildInfo,
key: &[u8],
) -> ClientResult<Option<Vec<u8>>> {
fn child_storage(&self, child_info: &ChildInfo, key: &[u8]) -> ClientResult<Option<Vec<u8>>> {
match *self {
GenesisOrUnavailableState::Genesis(ref state) =>
Ok(state.child_storage(child_info, key).expect(IN_MEMORY_EXPECT_PROOF)),
@@ -446,24 +455,24 @@ impl<H: Hasher> StateBackend<H> for GenesisOrUnavailableState<H>
key: &[u8],
) -> Result<Option<Vec<u8>>, Self::Error> {
match *self {
GenesisOrUnavailableState::Genesis(ref state) => Ok(
state.next_child_storage_key(child_info, key)
.expect(IN_MEMORY_EXPECT_PROOF)
),
GenesisOrUnavailableState::Genesis(ref state) =>
Ok(state.next_child_storage_key(child_info, key).expect(IN_MEMORY_EXPECT_PROOF)),
GenesisOrUnavailableState::Unavailable => Err(ClientError::NotAvailableOnLightClient),
}
}
fn for_keys_with_prefix<A: FnMut(&[u8])>(&self, prefix: &[u8], action: A) {
match *self {
GenesisOrUnavailableState::Genesis(ref state) => state.for_keys_with_prefix(prefix, action),
GenesisOrUnavailableState::Genesis(ref state) =>
state.for_keys_with_prefix(prefix, action),
GenesisOrUnavailableState::Unavailable => (),
}
}
fn for_key_values_with_prefix<A: FnMut(&[u8], &[u8])>(&self, prefix: &[u8], action: A) {
match *self {
GenesisOrUnavailableState::Genesis(ref state) => state.for_key_values_with_prefix(prefix, action),
GenesisOrUnavailableState::Genesis(ref state) =>
state.for_key_values_with_prefix(prefix, action),
GenesisOrUnavailableState::Unavailable => (),
}
}
@@ -477,9 +486,9 @@ impl<H: Hasher> StateBackend<H> for GenesisOrUnavailableState<H>
allow_missing: bool,
) -> ClientResult<bool> {
match *self {
GenesisOrUnavailableState::Genesis(ref state) =>
Ok(state.apply_to_key_values_while(child_info, prefix, start_at, action, allow_missing)
.expect(IN_MEMORY_EXPECT_PROOF)),
GenesisOrUnavailableState::Genesis(ref state) => Ok(state
.apply_to_key_values_while(child_info, prefix, start_at, action, allow_missing)
.expect(IN_MEMORY_EXPECT_PROOF)),
GenesisOrUnavailableState::Unavailable => Err(ClientError::NotAvailableOnLightClient),
}
}
@@ -512,11 +521,13 @@ impl<H: Hasher> StateBackend<H> for GenesisOrUnavailableState<H>
fn storage_root<'a>(
&self,
delta: impl Iterator<Item=(&'a [u8], Option<&'a [u8]>)>,
) -> (H::Out, Self::Transaction) where H::Out: Ord {
delta: impl Iterator<Item = (&'a [u8], Option<&'a [u8]>)>,
) -> (H::Out, Self::Transaction)
where
H::Out: Ord,
{
match *self {
GenesisOrUnavailableState::Genesis(ref state) =>
state.storage_root(delta),
GenesisOrUnavailableState::Genesis(ref state) => state.storage_root(delta),
GenesisOrUnavailableState::Unavailable => Default::default(),
}
}
@@ -524,15 +535,17 @@ impl<H: Hasher> StateBackend<H> for GenesisOrUnavailableState<H>
fn child_storage_root<'a>(
&self,
child_info: &ChildInfo,
delta: impl Iterator<Item=(&'a [u8], Option<&'a [u8]>)>,
) -> (H::Out, bool, Self::Transaction) where H::Out: Ord {
delta: impl Iterator<Item = (&'a [u8], Option<&'a [u8]>)>,
) -> (H::Out, bool, Self::Transaction)
where
H::Out: Ord,
{
match *self {
GenesisOrUnavailableState::Genesis(ref state) => {
let (root, is_equal, _) = state.child_storage_root(child_info, delta);
(root, is_equal, Default::default())
},
GenesisOrUnavailableState::Unavailable =>
(H::Out::default(), true, Default::default()),
GenesisOrUnavailableState::Unavailable => (H::Out::default(), true, Default::default()),
}
}
@@ -550,7 +563,7 @@ impl<H: Hasher> StateBackend<H> for GenesisOrUnavailableState<H>
}
}
fn register_overlay_stats(&self, _stats: &sp_state_machine::StateMachineStats) { }
fn register_overlay_stats(&self, _stats: &sp_state_machine::StateMachineStats) {}
fn usage_info(&self) -> sp_state_machine::UsageInfo {
sp_state_machine::UsageInfo::empty()
+48 -36
View File
@@ -21,27 +21,25 @@
use std::sync::Arc;
use sp_runtime::{Justifications, generic::BlockId};
use sp_runtime::traits::{Block as BlockT, Header as HeaderT, NumberFor, Zero};
use sp_blockchain::{
HeaderMetadata, CachedHeaderMetadata, Error as ClientError, Result as ClientResult,
use sp_runtime::{
generic::BlockId,
traits::{Block as BlockT, Header as HeaderT, NumberFor, Zero},
Justifications,
};
use crate::fetcher::RemoteHeaderRequest;
pub use sc_client_api::{
backend::{
AuxStore, NewBlockState, ProvideChtRoots,
},
backend::{AuxStore, NewBlockState, ProvideChtRoots},
blockchain::{
Backend as BlockchainBackend, BlockStatus, Cache as BlockchainCache,
well_known_cache_keys, Backend as BlockchainBackend, BlockStatus, Cache as BlockchainCache,
HeaderBackend as BlockchainHeaderBackend, Info as BlockchainInfo, ProvideCache,
well_known_cache_keys,
},
light::{
RemoteBlockchain, LocalOrRemote, Storage
},
cht,
light::{LocalOrRemote, RemoteBlockchain, Storage},
};
use sp_blockchain::{
CachedHeaderMetadata, Error as ClientError, HeaderMetadata, Result as ClientResult,
};
use crate::fetcher::RemoteHeaderRequest;
/// Light client blockchain.
pub struct Blockchain<S> {
@@ -51,9 +49,7 @@ pub struct Blockchain<S> {
impl<S> Blockchain<S> {
/// Create new light blockchain backed with given storage.
pub fn new(storage: S) -> Self {
Self {
storage,
}
Self { storage }
}
/// Get storage reference.
@@ -62,7 +58,11 @@ impl<S> Blockchain<S> {
}
}
impl<S, Block> BlockchainHeaderBackend<Block> for Blockchain<S> where Block: BlockT, S: Storage<Block> {
impl<S, Block> BlockchainHeaderBackend<Block> for Blockchain<S>
where
Block: BlockT,
S: Storage<Block>,
{
fn header(&self, id: BlockId<Block>) -> ClientResult<Option<Block::Header>> {
match RemoteBlockchain::header(self, id)? {
LocalOrRemote::Local(header) => Ok(Some(header)),
@@ -83,15 +83,25 @@ impl<S, Block> BlockchainHeaderBackend<Block> for Blockchain<S> where Block: Blo
self.storage.number(hash)
}
fn hash(&self, number: <<Block as BlockT>::Header as HeaderT>::Number) -> ClientResult<Option<Block::Hash>> {
fn hash(
&self,
number: <<Block as BlockT>::Header as HeaderT>::Number,
) -> ClientResult<Option<Block::Hash>> {
self.storage.hash(number)
}
}
impl<S, Block> HeaderMetadata<Block> for Blockchain<S> where Block: BlockT, S: Storage<Block> {
impl<S, Block> HeaderMetadata<Block> for Blockchain<S>
where
Block: BlockT,
S: Storage<Block>,
{
type Error = ClientError;
fn header_metadata(&self, hash: Block::Hash) -> Result<CachedHeaderMetadata<Block>, Self::Error> {
fn header_metadata(
&self,
hash: Block::Hash,
) -> Result<CachedHeaderMetadata<Block>, Self::Error> {
self.storage.header_metadata(hash)
}
@@ -104,7 +114,11 @@ impl<S, Block> HeaderMetadata<Block> for Blockchain<S> where Block: BlockT, S: S
}
}
impl<S, Block> BlockchainBackend<Block> for Blockchain<S> where Block: BlockT, S: Storage<Block> {
impl<S, Block> BlockchainBackend<Block> for Blockchain<S>
where
Block: BlockT,
S: Storage<Block>,
{
fn body(&self, _id: BlockId<Block>) -> ClientResult<Option<Vec<Block::Extrinsic>>> {
Err(ClientError::NotAvailableOnLightClient)
}
@@ -129,16 +143,13 @@ impl<S, Block> BlockchainBackend<Block> for Blockchain<S> where Block: BlockT, S
Err(ClientError::NotAvailableOnLightClient)
}
fn indexed_transaction(
&self,
_hash: &Block::Hash,
) -> ClientResult<Option<Vec<u8>>> {
fn indexed_transaction(&self, _hash: &Block::Hash) -> ClientResult<Option<Vec<u8>>> {
Err(ClientError::NotAvailableOnLightClient)
}
fn block_indexed_body(
&self,
_id: BlockId<Block>
_id: BlockId<Block>,
) -> sp_blockchain::Result<Option<Vec<Vec<u8>>>> {
Err(ClientError::NotAvailableOnLightClient)
}
@@ -151,16 +162,16 @@ impl<S: Storage<Block>, Block: BlockT> ProvideCache<Block> for Blockchain<S> {
}
impl<S, Block: BlockT> RemoteBlockchain<Block> for Blockchain<S>
where
S: Storage<Block>,
where
S: Storage<Block>,
{
fn header(&self, id: BlockId<Block>) -> ClientResult<LocalOrRemote<
Block::Header,
RemoteHeaderRequest<Block::Header>,
>> {
fn header(
&self,
id: BlockId<Block>,
) -> ClientResult<LocalOrRemote<Block::Header, RemoteHeaderRequest<Block::Header>>> {
// first, try to read header from local storage
if let Some(local_header) = self.storage.header(id)? {
return Ok(LocalOrRemote::Local(local_header));
return Ok(LocalOrRemote::Local(local_header))
}
// we need to know block number to check if it's a part of CHT
@@ -173,8 +184,9 @@ impl<S, Block: BlockT> RemoteBlockchain<Block> for Blockchain<S>
};
// if the header is genesis (never pruned), non-canonical, or from future => return
if number.is_zero() || self.storage.status(BlockId::Number(number))? == BlockStatus::Unknown {
return Ok(LocalOrRemote::Unknown);
if number.is_zero() || self.storage.status(BlockId::Number(number))? == BlockStatus::Unknown
{
return Ok(LocalOrRemote::Unknown)
}
Ok(LocalOrRemote::Remote(RemoteHeaderRequest {
+46 -51
View File
@@ -18,34 +18,33 @@
//! Methods that light client could use to execute runtime calls.
use std::{
sync::Arc, panic::UnwindSafe, result, cell::RefCell,
};
use std::{cell::RefCell, panic::UnwindSafe, result, sync::Arc};
use codec::{Encode, Decode};
use codec::{Decode, Encode};
use hash_db::Hasher;
use sp_core::{
convert_hash, NativeOrEncoded, traits::{CodeExecutor, SpawnNamed},
};
use sp_runtime::{
generic::BlockId, traits::{Block as BlockT, Header as HeaderT, HashFor},
convert_hash,
traits::{CodeExecutor, SpawnNamed},
NativeOrEncoded,
};
use sp_externalities::Extensions;
use sp_state_machine::{
self, Backend as StateBackend, OverlayedChanges, ExecutionStrategy, create_proof_check_backend,
execution_proof_check_on_trie_backend, ExecutionManager, StorageProof,
use sp_runtime::{
generic::BlockId,
traits::{Block as BlockT, HashFor, Header as HeaderT},
};
use sp_state_machine::{
self, create_proof_check_backend, execution_proof_check_on_trie_backend,
Backend as StateBackend, ExecutionManager, ExecutionStrategy, OverlayedChanges, StorageProof,
};
use hash_db::Hasher;
use sp_api::{ProofRecorder, StorageTransactionCache};
use sp_blockchain::{Error as ClientError, Result as ClientResult};
use sc_client_api::{
backend::RemoteBackend,
light::RemoteCallRequest,
call_executor::CallExecutor,
backend::RemoteBackend, call_executor::CallExecutor, light::RemoteCallRequest,
};
use sc_executor::{RuntimeVersion, NativeVersion};
use sc_executor::{NativeVersion, RuntimeVersion};
/// Call executor that is able to execute calls only on genesis state.
///
@@ -64,19 +63,15 @@ impl<B, L> GenesisCallExecutor<B, L> {
impl<B, L: Clone> Clone for GenesisCallExecutor<B, L> {
fn clone(&self) -> Self {
GenesisCallExecutor {
backend: self.backend.clone(),
local: self.local.clone(),
}
GenesisCallExecutor { backend: self.backend.clone(), local: self.local.clone() }
}
}
impl<Block, B, Local> CallExecutor<Block> for
GenesisCallExecutor<B, Local>
where
Block: BlockT,
B: RemoteBackend<Block>,
Local: CallExecutor<Block>,
impl<Block, B, Local> CallExecutor<Block> for GenesisCallExecutor<B, Local>
where
Block: BlockT,
B: RemoteBackend<Block>,
Local: CallExecutor<Block>,
{
type Error = ClientError;
@@ -99,7 +94,7 @@ impl<Block, B, Local> CallExecutor<Block> for
fn contextual_call<
EM: Fn(
Result<NativeOrEncoded<R>, Self::Error>,
Result<NativeOrEncoded<R>, Self::Error>
Result<NativeOrEncoded<R>, Self::Error>,
) -> Result<NativeOrEncoded<R>, Self::Error>,
R: Encode + Decode + PartialEq,
NC: FnOnce() -> result::Result<R, sp_api::ApiError> + UnwindSafe,
@@ -114,7 +109,10 @@ impl<Block, B, Local> CallExecutor<Block> for
native_call: Option<NC>,
recorder: &Option<ProofRecorder<Block>>,
extensions: Option<Extensions>,
) -> ClientResult<NativeOrEncoded<R>> where ExecutionManager<EM>: Clone {
) -> ClientResult<NativeOrEncoded<R>>
where
ExecutionManager<EM>: Clone,
{
// there's no actual way/need to specify native/wasm execution strategy on light node
// => we can safely ignore passed values
@@ -125,7 +123,7 @@ impl<Block, B, Local> CallExecutor<Block> for
Result<NativeOrEncoded<R>, Local::Error>,
) -> Result<NativeOrEncoded<R>, Local::Error>,
_,
NC
NC,
>(
&self.local,
at,
@@ -137,7 +135,8 @@ impl<Block, B, Local> CallExecutor<Block> for
native_call,
recorder,
extensions,
).map_err(|e| ClientError::Execution(Box::new(e.to_string()))),
)
.map_err(|e| ClientError::Execution(Box::new(e.to_string()))),
false => Err(ClientError::NotAvailableOnLightClient),
}
}
@@ -174,24 +173,19 @@ pub fn prove_execution<Block, S, E>(
method: &str,
call_data: &[u8],
) -> ClientResult<(Vec<u8>, StorageProof)>
where
Block: BlockT,
S: StateBackend<HashFor<Block>>,
E: CallExecutor<Block>,
where
Block: BlockT,
S: StateBackend<HashFor<Block>>,
E: CallExecutor<Block>,
{
let trie_state = state.as_trie_backend()
.ok_or_else(||
Box::new(sp_state_machine::ExecutionError::UnableToGenerateProof) as
Box<dyn sp_state_machine::Error>
)?;
let trie_state = state.as_trie_backend().ok_or_else(|| {
Box::new(sp_state_machine::ExecutionError::UnableToGenerateProof)
as Box<dyn sp_state_machine::Error>
})?;
// execute method + record execution proof
let (result, exec_proof) = executor.prove_at_trie_state(
&trie_state,
&mut Default::default(),
method,
call_data,
)?;
let (result, exec_proof) =
executor.prove_at_trie_state(&trie_state, &mut Default::default(), method, call_data)?;
Ok((result, exec_proof))
}
@@ -205,11 +199,11 @@ pub fn check_execution_proof<Header, E, H>(
request: &RemoteCallRequest<Header>,
remote_proof: StorageProof,
) -> ClientResult<Vec<u8>>
where
Header: HeaderT,
E: CodeExecutor + Clone + 'static,
H: Hasher,
H::Out: Ord + codec::Codec + 'static,
where
Header: HeaderT,
E: CodeExecutor + Clone + 'static,
H: Hasher,
H::Out: Ord + codec::Codec + 'static,
{
let local_state_root = request.header.state_root();
let root: H::Out = convert_hash(&local_state_root);
@@ -220,7 +214,8 @@ pub fn check_execution_proof<Header, E, H>(
// TODO: Remove when solved: https://github.com/paritytech/substrate/issues/5047
let backend_runtime_code = sp_state_machine::backend::BackendRuntimeCode::new(&trie_backend);
let runtime_code = backend_runtime_code.runtime_code()
let runtime_code = backend_runtime_code
.runtime_code()
.map_err(|_e| ClientError::RuntimeCodeMissing)?;
// execute method
+133 -97
View File
@@ -18,34 +18,39 @@
//! Light client data fetcher. Fetches requested data from remote full nodes.
use std::sync::Arc;
use std::collections::{BTreeMap, HashMap};
use std::marker::PhantomData;
use hash_db::{HashDB, Hasher, EMPTY_PREFIX};
use codec::{Decode, Encode};
use sp_core::{convert_hash, traits::{CodeExecutor, SpawnNamed}, storage::{ChildInfo, ChildType}};
use sp_runtime::traits::{
Block as BlockT, Header as HeaderT, Hash, HashFor, NumberFor,
AtLeast32Bit, CheckedConversion,
use std::{
collections::{BTreeMap, HashMap},
marker::PhantomData,
sync::Arc,
};
use sp_state_machine::{
ChangesTrieRootsStorage, ChangesTrieAnchorBlockId, ChangesTrieConfigurationRange,
InMemoryChangesTrieStorage, TrieBackend, read_proof_check, key_changes_proof_check_with_db,
read_child_proof_check,
use codec::{Decode, Encode};
use hash_db::{HashDB, Hasher, EMPTY_PREFIX};
use sp_blockchain::{Error as ClientError, Result as ClientResult};
use sp_core::{
convert_hash,
storage::{ChildInfo, ChildType},
traits::{CodeExecutor, SpawnNamed},
};
use sp_runtime::traits::{
AtLeast32Bit, Block as BlockT, CheckedConversion, Hash, HashFor, Header as HeaderT, NumberFor,
};
pub use sp_state_machine::StorageProof;
use sp_blockchain::{Error as ClientError, Result as ClientResult};
use sp_state_machine::{
key_changes_proof_check_with_db, read_child_proof_check, read_proof_check,
ChangesTrieAnchorBlockId, ChangesTrieConfigurationRange, ChangesTrieRootsStorage,
InMemoryChangesTrieStorage, TrieBackend,
};
use crate::{blockchain::Blockchain, call_executor::check_execution_proof};
pub use sc_client_api::{
cht,
light::{
RemoteCallRequest, RemoteHeaderRequest, RemoteReadRequest, RemoteReadChildRequest,
RemoteChangesRequest, ChangesProof, RemoteBodyRequest, Fetcher, FetchChecker,
ChangesProof, FetchChecker, Fetcher, RemoteBodyRequest, RemoteCallRequest,
RemoteChangesRequest, RemoteHeaderRequest, RemoteReadChildRequest, RemoteReadRequest,
Storage as BlockchainStorage,
},
cht,
};
use crate::{blockchain::Blockchain, call_executor::check_execution_proof};
/// Remote data checker.
pub struct LightDataChecker<E, H, B: BlockT, S: BlockchainStorage<B>> {
@@ -62,9 +67,7 @@ impl<E, H, B: BlockT, S: BlockchainStorage<B>> LightDataChecker<E, H, B, S> {
executor: E,
spawn_handle: Box<dyn SpawnNamed>,
) -> Self {
Self {
blockchain, executor, spawn_handle, _hasher: PhantomData
}
Self { blockchain, executor, spawn_handle, _hasher: PhantomData }
}
/// Check remote changes query proof assuming that CHT-s are of given size.
@@ -74,26 +77,39 @@ impl<E, H, B: BlockT, S: BlockchainStorage<B>> LightDataChecker<E, H, B, S> {
remote_proof: ChangesProof<B::Header>,
cht_size: NumberFor<B>,
) -> ClientResult<Vec<(NumberFor<B>, u32)>>
where
H: Hasher,
H::Out: Ord + codec::Codec,
where
H: Hasher,
H::Out: Ord + codec::Codec,
{
// since we need roots of all changes tries for the range begin..max
// => remote node can't use max block greater that one that we have passed
if remote_proof.max_block > request.max_block.0 || remote_proof.max_block < request.last_block.0 {
if remote_proof.max_block > request.max_block.0 ||
remote_proof.max_block < request.last_block.0
{
return Err(ClientError::ChangesTrieAccessFailed(format!(
"Invalid max_block used by the remote node: {}. Local: {}..{}..{}",
remote_proof.max_block, request.first_block.0, request.last_block.0, request.max_block.0,
)).into());
remote_proof.max_block,
request.first_block.0,
request.last_block.0,
request.max_block.0,
))
.into())
}
// check if remote node has responded with extra changes trie roots proofs
// all changes tries roots must be in range [request.first_block.0; request.tries_roots.0)
let is_extra_first_root = remote_proof.roots.keys().next()
.map(|first_root| *first_root < request.first_block.0
|| *first_root >= request.tries_roots.0)
let is_extra_first_root = remote_proof
.roots
.keys()
.next()
.map(|first_root| {
*first_root < request.first_block.0 || *first_root >= request.tries_roots.0
})
.unwrap_or(false);
let is_extra_last_root = remote_proof.roots.keys().next_back()
let is_extra_last_root = remote_proof
.roots
.keys()
.next_back()
.map(|last_root| *last_root >= request.tries_roots.0)
.unwrap_or(false);
if is_extra_first_root || is_extra_last_root {
@@ -112,11 +128,7 @@ impl<E, H, B: BlockT, S: BlockchainStorage<B>> LightDataChecker<E, H, B, S> {
let remote_roots_proof = remote_proof.roots_proof;
let remote_proof = remote_proof.proof;
if !remote_roots.is_empty() {
self.check_changes_tries_proof(
cht_size,
&remote_roots,
remote_roots_proof,
)?;
self.check_changes_tries_proof(cht_size, &remote_roots, remote_roots_proof)?;
}
// and now check the key changes proof + get the changes
@@ -125,7 +137,10 @@ impl<E, H, B: BlockT, S: BlockchainStorage<B>> LightDataChecker<E, H, B, S> {
for config_range in &request.changes_trie_configs {
let result_range = key_changes_proof_check_with_db::<H, _>(
ChangesTrieConfigurationRange {
config: config_range.config.as_ref().ok_or(ClientError::ChangesTriesNotSupported)?,
config: config_range
.config
.as_ref()
.ok_or(ClientError::ChangesTriesNotSupported)?,
zero: config_range.zero.0,
end: config_range.end.map(|(n, _)| n),
},
@@ -141,7 +156,8 @@ impl<E, H, B: BlockT, S: BlockchainStorage<B>> LightDataChecker<E, H, B, S> {
},
remote_max_block,
request.storage_key.as_ref(),
&request.key)
&request.key,
)
.map_err(|err| ClientError::ChangesTrieAccessFailed(err))?;
result.extend(result_range);
}
@@ -156,9 +172,9 @@ impl<E, H, B: BlockT, S: BlockchainStorage<B>> LightDataChecker<E, H, B, S> {
remote_roots: &BTreeMap<NumberFor<B>, B::Hash>,
remote_roots_proof: StorageProof,
) -> ClientResult<()>
where
H: Hasher,
H::Out: Ord + codec::Codec,
where
H: Hasher,
H::Out: Ord + codec::Codec,
{
// all the checks are sharing the same storage
let storage = remote_roots_proof.into_memory_db();
@@ -166,52 +182,62 @@ impl<E, H, B: BlockT, S: BlockchainStorage<B>> LightDataChecker<E, H, B, S> {
// remote_roots.keys() are sorted => we can use this to group changes tries roots
// that are belongs to the same CHT
let blocks = remote_roots.keys().cloned();
cht::for_each_cht_group::<B::Header, _, _, _>(cht_size, blocks, |mut storage, _, cht_blocks| {
// get local changes trie CHT root for given CHT
// it should be there, because it is never pruned AND request has been composed
// when required header has been pruned (=> replaced with CHT)
let first_block = cht_blocks.first().cloned()
.expect("for_each_cht_group never calls callback with empty groups");
let local_cht_root = self.blockchain.storage().changes_trie_cht_root(cht_size, first_block)?
.ok_or(ClientError::InvalidCHTProof)?;
cht::for_each_cht_group::<B::Header, _, _, _>(
cht_size,
blocks,
|mut storage, _, cht_blocks| {
// get local changes trie CHT root for given CHT
// it should be there, because it is never pruned AND request has been composed
// when required header has been pruned (=> replaced with CHT)
let first_block = cht_blocks
.first()
.cloned()
.expect("for_each_cht_group never calls callback with empty groups");
let local_cht_root = self
.blockchain
.storage()
.changes_trie_cht_root(cht_size, first_block)?
.ok_or(ClientError::InvalidCHTProof)?;
// check changes trie root for every block within CHT range
for block in cht_blocks {
// check if the proofs storage contains the root
// normally this happens in when the proving backend is created, but since
// we share the storage for multiple checks, do it here
let mut cht_root = H::Out::default();
cht_root.as_mut().copy_from_slice(local_cht_root.as_ref());
if !storage.contains(&cht_root, EMPTY_PREFIX) {
return Err(ClientError::InvalidCHTProof.into());
// check changes trie root for every block within CHT range
for block in cht_blocks {
// check if the proofs storage contains the root
// normally this happens in when the proving backend is created, but since
// we share the storage for multiple checks, do it here
let mut cht_root = H::Out::default();
cht_root.as_mut().copy_from_slice(local_cht_root.as_ref());
if !storage.contains(&cht_root, EMPTY_PREFIX) {
return Err(ClientError::InvalidCHTProof.into())
}
// check proof for single changes trie root
let proving_backend = TrieBackend::new(storage, cht_root);
let remote_changes_trie_root = remote_roots[&block];
cht::check_proof_on_proving_backend::<B::Header, H>(
local_cht_root,
block,
remote_changes_trie_root,
&proving_backend,
)?;
// and return the storage to use in following checks
storage = proving_backend.into_storage();
}
// check proof for single changes trie root
let proving_backend = TrieBackend::new(storage, cht_root);
let remote_changes_trie_root = remote_roots[&block];
cht::check_proof_on_proving_backend::<B::Header, H>(
local_cht_root,
block,
remote_changes_trie_root,
&proving_backend,
)?;
// and return the storage to use in following checks
storage = proving_backend.into_storage();
}
Ok(storage)
}, storage)
Ok(storage)
},
storage,
)
}
}
impl<E, Block, H, S> FetchChecker<Block> for LightDataChecker<E, H, Block, S>
where
Block: BlockT,
E: CodeExecutor + Clone + 'static,
H: Hasher,
H::Out: Ord + codec::Codec + 'static,
S: BlockchainStorage<Block>,
where
Block: BlockT,
E: CodeExecutor + Clone + 'static,
H: Hasher,
H::Out: Ord + codec::Codec + 'static,
S: BlockchainStorage<Block>,
{
fn check_header_proof(
&self,
@@ -219,15 +245,16 @@ impl<E, Block, H, S> FetchChecker<Block> for LightDataChecker<E, H, Block, S>
remote_header: Option<Block::Header>,
remote_proof: StorageProof,
) -> ClientResult<Block::Header> {
let remote_header = remote_header.ok_or_else(||
ClientError::from(ClientError::InvalidCHTProof))?;
let remote_header =
remote_header.ok_or_else(|| ClientError::from(ClientError::InvalidCHTProof))?;
let remote_header_hash = remote_header.hash();
cht::check_proof::<Block::Header, H>(
request.cht_root,
request.block,
remote_header_hash,
remote_proof,
).map(|_| remote_header)
)
.map(|_| remote_header)
}
fn check_read_proof(
@@ -239,7 +266,8 @@ impl<E, Block, H, S> FetchChecker<Block> for LightDataChecker<E, H, Block, S>
convert_hash(request.header.state_root()),
remote_proof,
request.keys.iter(),
).map_err(|e| ClientError::from(e))
)
.map_err(|e| ClientError::from(e))
}
fn check_read_child_proof(
@@ -256,7 +284,8 @@ impl<E, Block, H, S> FetchChecker<Block> for LightDataChecker<E, H, Block, S>
remote_proof,
&child_info,
request.keys.iter(),
).map_err(|e| ClientError::from(e))
)
.map_err(|e| ClientError::from(e))
}
fn check_execution_proof(
@@ -275,7 +304,7 @@ impl<E, Block, H, S> FetchChecker<Block> for LightDataChecker<E, H, Block, S>
fn check_changes_proof(
&self,
request: &RemoteChangesRequest<Block::Header>,
remote_proof: ChangesProof<Block::Header>
remote_proof: ChangesProof<Block::Header>,
) -> ClientResult<Vec<(NumberFor<Block>, u32)>> {
self.check_changes_proof_with_cht_size(request, remote_proof, cht::size())
}
@@ -283,12 +312,11 @@ impl<E, Block, H, S> FetchChecker<Block> for LightDataChecker<E, H, Block, S>
fn check_body_proof(
&self,
request: &RemoteBodyRequest<Block::Header>,
body: Vec<Block::Extrinsic>
body: Vec<Block::Extrinsic>,
) -> ClientResult<Vec<Block::Extrinsic>> {
// TODO: #2621
let extrinsics_root = HashFor::<Block>::ordered_trie_root(
body.iter().map(Encode::encode).collect(),
);
let extrinsics_root =
HashFor::<Block>::ordered_trie_root(body.iter().map(Encode::encode).collect());
if *request.header.extrinsics_root() == extrinsics_root {
Ok(body)
} else {
@@ -297,7 +325,6 @@ impl<E, Block, H, S> FetchChecker<Block> for LightDataChecker<E, H, Block, S>
expected: extrinsics_root.to_string(),
})
}
}
}
@@ -308,10 +335,18 @@ struct RootsStorage<'a, Number: AtLeast32Bit, Hash: 'a> {
}
impl<'a, H, Number, Hash> ChangesTrieRootsStorage<H, Number> for RootsStorage<'a, Number, Hash>
where
H: Hasher,
Number: std::fmt::Display + std::hash::Hash + Clone + AtLeast32Bit + Encode + Decode + Send + Sync + 'static,
Hash: 'a + Send + Sync + Clone + AsRef<[u8]>,
where
H: Hasher,
Number: std::fmt::Display
+ std::hash::Hash
+ Clone
+ AtLeast32Bit
+ Encode
+ Decode
+ Send
+ Sync
+ 'static,
Hash: 'a + Send + Sync + Clone + AsRef<[u8]>,
{
fn build_anchor(
&self,
@@ -329,7 +364,8 @@ impl<'a, H, Number, Hash> ChangesTrieRootsStorage<H, Number> for RootsStorage<'a
let root = if block < self.roots.0 {
self.prev_roots.get(&Number::unique_saturated_from(block)).cloned()
} else {
let index: Option<usize> = block.checked_sub(&self.roots.0).and_then(|index| index.checked_into());
let index: Option<usize> =
block.checked_sub(&self.roots.0).and_then(|index| index.checked_into());
index.and_then(|index| self.roots.1.get(index as usize).cloned())
};
+10 -7
View File
@@ -18,16 +18,19 @@
//! Light client components.
use sp_core::traits::{CodeExecutor, SpawnNamed};
use sp_runtime::traits::{Block as BlockT, HashFor};
use std::sync::Arc;
use sp_core::traits::{CodeExecutor, SpawnNamed};
pub mod backend;
pub mod blockchain;
pub mod call_executor;
pub mod fetcher;
pub use {backend::*, blockchain::*, call_executor::*, fetcher::*};
pub use backend::*;
pub use blockchain::*;
pub use call_executor::*;
pub use fetcher::*;
/// Create an instance of fetch data checker.
pub fn new_fetch_checker<E, B: BlockT, S: BlockchainStorage<B>>(
@@ -35,8 +38,8 @@ pub fn new_fetch_checker<E, B: BlockT, S: BlockchainStorage<B>>(
executor: E,
spawn_handle: Box<dyn SpawnNamed>,
) -> LightDataChecker<E, HashFor<B>, B, S>
where
E: CodeExecutor,
where
E: CodeExecutor,
{
LightDataChecker::new(blockchain, executor, spawn_handle)
}
@@ -48,9 +51,9 @@ pub fn new_light_blockchain<B: BlockT, S: BlockchainStorage<B>>(storage: S) -> A
/// Create an instance of light client backend.
pub fn new_light_backend<B, S>(blockchain: Arc<Blockchain<S>>) -> Arc<Backend<S, HashFor<B>>>
where
B: BlockT,
S: BlockchainStorage<B>,
where
B: BlockT,
S: BlockchainStorage<B>,
{
Arc::new(Backend::new(blockchain))
}