mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-06-15 18:31:05 +00:00
removes use of sc_client::Client from sc-rpc (#5063)
* removes use of sc_client::Client from sc-rpc * remove Client impl from sc-finality-benches * remove client impl from sc-finality-grandpa * read_proof accepts iterator * remove generic Executor param from ExecutorProvider * fix long ass line * code style changes * merge with master Co-authored-by: Arkadiy Paronyan <arkady.paronyan@gmail.com>
This commit is contained in:
committed by
GitHub
parent
dc85ccb7df
commit
99ae5342eb
Generated
+2
@@ -3569,6 +3569,7 @@ dependencies = [
|
|||||||
"sc-basic-authorship",
|
"sc-basic-authorship",
|
||||||
"sc-cli",
|
"sc-cli",
|
||||||
"sc-client",
|
"sc-client",
|
||||||
|
"sc-client-api",
|
||||||
"sc-consensus-aura",
|
"sc-consensus-aura",
|
||||||
"sc-executor",
|
"sc-executor",
|
||||||
"sc-finality-grandpa",
|
"sc-finality-grandpa",
|
||||||
@@ -5777,6 +5778,7 @@ dependencies = [
|
|||||||
"sp-runtime",
|
"sp-runtime",
|
||||||
"sp-state-machine",
|
"sp-state-machine",
|
||||||
"sp-std",
|
"sp-std",
|
||||||
|
"sp-storage",
|
||||||
"sp-test-primitives",
|
"sp-test-primitives",
|
||||||
"sp-transaction-pool",
|
"sp-transaction-pool",
|
||||||
"sp-trie",
|
"sp-trie",
|
||||||
|
|||||||
@@ -30,6 +30,7 @@ sp-consensus = { version = "0.8.0-alpha.2", path = "../../../primitives/consensu
|
|||||||
grandpa = { version = "0.8.0-alpha.2", package = "sc-finality-grandpa", path = "../../../client/finality-grandpa" }
|
grandpa = { version = "0.8.0-alpha.2", package = "sc-finality-grandpa", path = "../../../client/finality-grandpa" }
|
||||||
grandpa-primitives = { version = "2.0.0-alpha.2", package = "sp-finality-grandpa", path = "../../../primitives/finality-grandpa" }
|
grandpa-primitives = { version = "2.0.0-alpha.2", package = "sp-finality-grandpa", path = "../../../primitives/finality-grandpa" }
|
||||||
sc-client = { version = "0.8.0-alpha.2", path = "../../../client/" }
|
sc-client = { version = "0.8.0-alpha.2", path = "../../../client/" }
|
||||||
|
sc-client-api = { version = "2.0.0-alpha.2", path = "../../../client/api" }
|
||||||
sp-runtime = { version = "2.0.0-alpha.2", path = "../../../primitives/runtime" }
|
sp-runtime = { version = "2.0.0-alpha.2", path = "../../../primitives/runtime" }
|
||||||
sc-basic-authorship = { path = "../../../client/basic-authorship" , version = "0.8.0-alpha.2"}
|
sc-basic-authorship = { path = "../../../client/basic-authorship" , version = "0.8.0-alpha.2"}
|
||||||
|
|
||||||
|
|||||||
@@ -3,13 +3,14 @@
|
|||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
use sc_client::LongestChain;
|
use sc_client::LongestChain;
|
||||||
|
use sc_client_api::ExecutorProvider;
|
||||||
use node_template_runtime::{self, GenesisConfig, opaque::Block, RuntimeApi};
|
use node_template_runtime::{self, GenesisConfig, opaque::Block, RuntimeApi};
|
||||||
use sc_service::{error::{Error as ServiceError}, AbstractService, Configuration, ServiceBuilder};
|
use sc_service::{error::{Error as ServiceError}, AbstractService, Configuration, ServiceBuilder};
|
||||||
use sp_inherents::InherentDataProviders;
|
use sp_inherents::InherentDataProviders;
|
||||||
use sc_executor::native_executor_instance;
|
use sc_executor::native_executor_instance;
|
||||||
pub use sc_executor::NativeExecutor;
|
pub use sc_executor::NativeExecutor;
|
||||||
use sp_consensus_aura::sr25519::{AuthorityPair as AuraPair};
|
use sp_consensus_aura::sr25519::{AuthorityPair as AuraPair};
|
||||||
use grandpa::{self, FinalityProofProvider as GrandpaFinalityProofProvider};
|
use grandpa::{self, FinalityProofProvider as GrandpaFinalityProofProvider, StorageAndProofProvider};
|
||||||
|
|
||||||
// Our native executor instance.
|
// Our native executor instance.
|
||||||
native_executor_instance!(
|
native_executor_instance!(
|
||||||
@@ -24,6 +25,7 @@ native_executor_instance!(
|
|||||||
/// be able to perform chain operations.
|
/// be able to perform chain operations.
|
||||||
macro_rules! new_full_start {
|
macro_rules! new_full_start {
|
||||||
($config:expr) => {{
|
($config:expr) => {{
|
||||||
|
use std::sync::Arc;
|
||||||
let mut import_setup = None;
|
let mut import_setup = None;
|
||||||
let inherent_data_providers = sp_inherents::InherentDataProviders::new();
|
let inherent_data_providers = sp_inherents::InherentDataProviders::new();
|
||||||
|
|
||||||
@@ -42,7 +44,7 @@ macro_rules! new_full_start {
|
|||||||
.ok_or_else(|| sc_service::Error::SelectChainRequired)?;
|
.ok_or_else(|| sc_service::Error::SelectChainRequired)?;
|
||||||
|
|
||||||
let (grandpa_block_import, grandpa_link) =
|
let (grandpa_block_import, grandpa_link) =
|
||||||
grandpa::block_import(client.clone(), &*client, select_chain)?;
|
grandpa::block_import(client.clone(), &(client.clone() as Arc<_>), select_chain)?;
|
||||||
|
|
||||||
let aura_block_import = sc_consensus_aura::AuraBlockImport::<_, _, _, AuraPair>::new(
|
let aura_block_import = sc_consensus_aura::AuraBlockImport::<_, _, _, AuraPair>::new(
|
||||||
grandpa_block_import.clone(), client.clone(),
|
grandpa_block_import.clone(), client.clone(),
|
||||||
@@ -87,9 +89,11 @@ pub fn new_full(config: Configuration<GenesisConfig>)
|
|||||||
.expect("Link Half and Block Import are present for Full Services or setup failed before. qed");
|
.expect("Link Half and Block Import are present for Full Services or setup failed before. qed");
|
||||||
|
|
||||||
let service = builder
|
let service = builder
|
||||||
.with_finality_proof_provider(|client, backend|
|
.with_finality_proof_provider(|client, backend| {
|
||||||
Ok(Arc::new(GrandpaFinalityProofProvider::new(backend, client)) as _)
|
// GenesisAuthoritySetProvider is implemented for StorageAndProofProvider
|
||||||
)?
|
let provider = client as Arc<dyn StorageAndProofProvider<_, _>>;
|
||||||
|
Ok(Arc::new(GrandpaFinalityProofProvider::new(backend, provider)) as _)
|
||||||
|
})?
|
||||||
.build()?;
|
.build()?;
|
||||||
|
|
||||||
if participates_in_consensus {
|
if participates_in_consensus {
|
||||||
@@ -201,7 +205,10 @@ pub fn new_light(config: Configuration<GenesisConfig>)
|
|||||||
.map(|fetcher| fetcher.checker().clone())
|
.map(|fetcher| fetcher.checker().clone())
|
||||||
.ok_or_else(|| "Trying to start light import queue without active fetch checker")?;
|
.ok_or_else(|| "Trying to start light import queue without active fetch checker")?;
|
||||||
let grandpa_block_import = grandpa::light_block_import(
|
let grandpa_block_import = grandpa::light_block_import(
|
||||||
client.clone(), backend, &*client.clone(), Arc::new(fetch_checker),
|
client.clone(),
|
||||||
|
backend,
|
||||||
|
&(client.clone() as Arc<_>),
|
||||||
|
Arc::new(fetch_checker),
|
||||||
)?;
|
)?;
|
||||||
let finality_proof_import = grandpa_block_import.clone();
|
let finality_proof_import = grandpa_block_import.clone();
|
||||||
let finality_proof_request_builder =
|
let finality_proof_request_builder =
|
||||||
@@ -218,8 +225,10 @@ pub fn new_light(config: Configuration<GenesisConfig>)
|
|||||||
|
|
||||||
Ok((import_queue, finality_proof_request_builder))
|
Ok((import_queue, finality_proof_request_builder))
|
||||||
})?
|
})?
|
||||||
.with_finality_proof_provider(|client, backend|
|
.with_finality_proof_provider(|client, backend| {
|
||||||
Ok(Arc::new(GrandpaFinalityProofProvider::new(backend, client)) as _)
|
// GenesisAuthoritySetProvider is implemented for StorageAndProofProvider
|
||||||
)?
|
let provider = client as Arc<dyn StorageAndProofProvider<_, _>>;
|
||||||
|
Ok(Arc::new(GrandpaFinalityProofProvider::new(backend, provider)) as _)
|
||||||
|
})?
|
||||||
.build()
|
.build()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ use std::sync::Arc;
|
|||||||
|
|
||||||
use sc_consensus_babe;
|
use sc_consensus_babe;
|
||||||
use sc_client::{self, LongestChain};
|
use sc_client::{self, LongestChain};
|
||||||
use grandpa::{self, FinalityProofProvider as GrandpaFinalityProofProvider};
|
use grandpa::{self, FinalityProofProvider as GrandpaFinalityProofProvider, StorageAndProofProvider};
|
||||||
use node_executor;
|
use node_executor;
|
||||||
use node_primitives::Block;
|
use node_primitives::Block;
|
||||||
use node_runtime::{GenesisConfig, RuntimeApi};
|
use node_runtime::{GenesisConfig, RuntimeApi};
|
||||||
@@ -45,6 +45,7 @@ use sc_offchain::OffchainWorkers;
|
|||||||
/// be able to perform chain operations.
|
/// be able to perform chain operations.
|
||||||
macro_rules! new_full_start {
|
macro_rules! new_full_start {
|
||||||
($config:expr) => {{
|
($config:expr) => {{
|
||||||
|
use std::sync::Arc;
|
||||||
type RpcExtension = jsonrpc_core::IoHandler<sc_rpc::Metadata>;
|
type RpcExtension = jsonrpc_core::IoHandler<sc_rpc::Metadata>;
|
||||||
let mut import_setup = None;
|
let mut import_setup = None;
|
||||||
let inherent_data_providers = sp_inherents::InherentDataProviders::new();
|
let inherent_data_providers = sp_inherents::InherentDataProviders::new();
|
||||||
@@ -64,7 +65,7 @@ macro_rules! new_full_start {
|
|||||||
.ok_or_else(|| sc_service::Error::SelectChainRequired)?;
|
.ok_or_else(|| sc_service::Error::SelectChainRequired)?;
|
||||||
let (grandpa_block_import, grandpa_link) = grandpa::block_import(
|
let (grandpa_block_import, grandpa_link) = grandpa::block_import(
|
||||||
client.clone(),
|
client.clone(),
|
||||||
&*client,
|
&(client.clone() as Arc<_>),
|
||||||
select_chain,
|
select_chain,
|
||||||
)?;
|
)?;
|
||||||
let justification_import = grandpa_block_import.clone();
|
let justification_import = grandpa_block_import.clone();
|
||||||
@@ -116,6 +117,7 @@ macro_rules! new_full {
|
|||||||
($config:expr, $with_startup_data: expr) => {{
|
($config:expr, $with_startup_data: expr) => {{
|
||||||
use futures::prelude::*;
|
use futures::prelude::*;
|
||||||
use sc_network::Event;
|
use sc_network::Event;
|
||||||
|
use sc_client_api::ExecutorProvider;
|
||||||
|
|
||||||
let (
|
let (
|
||||||
is_authority,
|
is_authority,
|
||||||
@@ -139,9 +141,11 @@ macro_rules! new_full {
|
|||||||
let (builder, mut import_setup, inherent_data_providers) = new_full_start!($config);
|
let (builder, mut import_setup, inherent_data_providers) = new_full_start!($config);
|
||||||
|
|
||||||
let service = builder
|
let service = builder
|
||||||
.with_finality_proof_provider(|client, backend|
|
.with_finality_proof_provider(|client, backend| {
|
||||||
Ok(Arc::new(grandpa::FinalityProofProvider::new(backend, client)) as _)
|
// GenesisAuthoritySetProvider is implemented for StorageAndProofProvider
|
||||||
)?
|
let provider = client as Arc<dyn grandpa::StorageAndProofProvider<_, _>>;
|
||||||
|
Ok(Arc::new(grandpa::FinalityProofProvider::new(backend, provider)) as _)
|
||||||
|
})?
|
||||||
.build()?;
|
.build()?;
|
||||||
|
|
||||||
let (block_import, grandpa_link, babe_link) = import_setup.take()
|
let (block_import, grandpa_link, babe_link) = import_setup.take()
|
||||||
@@ -255,8 +259,7 @@ type ConcreteBlock = node_primitives::Block;
|
|||||||
type ConcreteClient =
|
type ConcreteClient =
|
||||||
Client<
|
Client<
|
||||||
Backend<ConcreteBlock>,
|
Backend<ConcreteBlock>,
|
||||||
LocalCallExecutor<Backend<ConcreteBlock>,
|
LocalCallExecutor<Backend<ConcreteBlock>, NativeExecutor<node_executor::Executor>>,
|
||||||
NativeExecutor<node_executor::Executor>>,
|
|
||||||
ConcreteBlock,
|
ConcreteBlock,
|
||||||
node_runtime::RuntimeApi
|
node_runtime::RuntimeApi
|
||||||
>;
|
>;
|
||||||
@@ -317,7 +320,7 @@ pub fn new_light(config: NodeConfiguration)
|
|||||||
let grandpa_block_import = grandpa::light_block_import(
|
let grandpa_block_import = grandpa::light_block_import(
|
||||||
client.clone(),
|
client.clone(),
|
||||||
backend,
|
backend,
|
||||||
&*client,
|
&(client.clone() as Arc<_>),
|
||||||
Arc::new(fetch_checker),
|
Arc::new(fetch_checker),
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
@@ -342,9 +345,11 @@ pub fn new_light(config: NodeConfiguration)
|
|||||||
|
|
||||||
Ok((import_queue, finality_proof_request_builder))
|
Ok((import_queue, finality_proof_request_builder))
|
||||||
})?
|
})?
|
||||||
.with_finality_proof_provider(|client, backend|
|
.with_finality_proof_provider(|client, backend| {
|
||||||
Ok(Arc::new(GrandpaFinalityProofProvider::new(backend, client)) as _)
|
// GenesisAuthoritySetProvider is implemented for StorageAndProofProvider
|
||||||
)?
|
let provider = client as Arc<dyn StorageAndProofProvider<_, _>>;
|
||||||
|
Ok(Arc::new(GrandpaFinalityProofProvider::new(backend, provider)) as _)
|
||||||
|
})?
|
||||||
.with_rpc_extensions(|builder,| ->
|
.with_rpc_extensions(|builder,| ->
|
||||||
Result<RpcExtension, _>
|
Result<RpcExtension, _>
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -34,6 +34,7 @@ sp-runtime = { version = "2.0.0-alpha.2", default-features = false, path = "../.
|
|||||||
sp-state-machine = { version = "0.8.0-alpha.2", path = "../../primitives/state-machine" }
|
sp-state-machine = { version = "0.8.0-alpha.2", path = "../../primitives/state-machine" }
|
||||||
sc-telemetry = { version = "2.0.0-alpha.2", path = "../telemetry" }
|
sc-telemetry = { version = "2.0.0-alpha.2", path = "../telemetry" }
|
||||||
sp-trie = { version = "2.0.0-alpha.2", path = "../../primitives/trie" }
|
sp-trie = { version = "2.0.0-alpha.2", path = "../../primitives/trie" }
|
||||||
|
sp-storage = { version = "2.0.0-alpha.2", path = "../../primitives/storage" }
|
||||||
sp-transaction-pool = { version = "2.0.0-alpha.2", path = "../../primitives/transaction-pool" }
|
sp-transaction-pool = { version = "2.0.0-alpha.2", path = "../../primitives/transaction-pool" }
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ use sp_state_machine::{
|
|||||||
ChangesTrieState, ChangesTrieStorage as StateChangesTrieStorage, ChangesTrieTransaction,
|
ChangesTrieState, ChangesTrieStorage as StateChangesTrieStorage, ChangesTrieTransaction,
|
||||||
StorageCollection, ChildStorageCollection,
|
StorageCollection, ChildStorageCollection,
|
||||||
};
|
};
|
||||||
|
use sp_storage::{StorageData, StorageKey, ChildInfo};
|
||||||
use crate::{
|
use crate::{
|
||||||
blockchain::{
|
blockchain::{
|
||||||
Backend as BlockchainBackend, well_known_cache_keys
|
Backend as BlockchainBackend, well_known_cache_keys
|
||||||
@@ -38,6 +39,7 @@ use sp_consensus::BlockOrigin;
|
|||||||
use parking_lot::RwLock;
|
use parking_lot::RwLock;
|
||||||
|
|
||||||
pub use sp_state_machine::Backend as StateBackend;
|
pub use sp_state_machine::Backend as StateBackend;
|
||||||
|
use std::marker::PhantomData;
|
||||||
|
|
||||||
/// Extracts the state backend type for the given backend.
|
/// Extracts the state backend type for the given backend.
|
||||||
pub type StateBackendFor<B, Block> = <B as Backend<Block>>::State;
|
pub type StateBackendFor<B, Block> = <B as Backend<Block>>::State;
|
||||||
@@ -237,6 +239,123 @@ pub trait AuxStore {
|
|||||||
fn get_aux(&self, key: &[u8]) -> sp_blockchain::Result<Option<Vec<u8>>>;
|
fn get_aux(&self, key: &[u8]) -> sp_blockchain::Result<Option<Vec<u8>>>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// An `Iterator` that iterates keys in a given block under a prefix.
|
||||||
|
pub struct KeyIterator<'a, State, Block> {
|
||||||
|
state: State,
|
||||||
|
prefix: Option<&'a StorageKey>,
|
||||||
|
current_key: Vec<u8>,
|
||||||
|
_phantom: PhantomData<Block>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl <'a, State, Block> KeyIterator<'a, State, Block> {
|
||||||
|
/// create a KeyIterator instance
|
||||||
|
pub fn new(state: State, prefix: Option<&'a StorageKey>, current_key: Vec<u8>) -> Self {
|
||||||
|
Self {
|
||||||
|
state,
|
||||||
|
prefix,
|
||||||
|
current_key,
|
||||||
|
_phantom: PhantomData,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, State, Block> Iterator for KeyIterator<'a, State, Block> where
|
||||||
|
Block: BlockT,
|
||||||
|
State: StateBackend<HashFor<Block>>,
|
||||||
|
{
|
||||||
|
type Item = StorageKey;
|
||||||
|
|
||||||
|
fn next(&mut self) -> Option<Self::Item> {
|
||||||
|
let next_key = self.state
|
||||||
|
.next_storage_key(&self.current_key)
|
||||||
|
.ok()
|
||||||
|
.flatten()?;
|
||||||
|
// this terminates the iterator the first time it fails.
|
||||||
|
if let Some(prefix) = self.prefix {
|
||||||
|
if !next_key.starts_with(&prefix.0[..]) {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
self.current_key = next_key.clone();
|
||||||
|
Some(StorageKey(next_key))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/// Provides acess to storage primitives
|
||||||
|
pub trait StorageProvider<Block: BlockT, B: Backend<Block>> {
|
||||||
|
/// Given a `BlockId` and a key, return the value under the key in that block.
|
||||||
|
fn storage(&self, id: &BlockId<Block>, key: &StorageKey) -> sp_blockchain::Result<Option<StorageData>>;
|
||||||
|
|
||||||
|
/// Given a `BlockId` and a key prefix, return the matching storage keys in that block.
|
||||||
|
fn storage_keys(&self, id: &BlockId<Block>, key_prefix: &StorageKey) -> sp_blockchain::Result<Vec<StorageKey>>;
|
||||||
|
|
||||||
|
/// Given a `BlockId` and a key, return the value under the hash in that block.
|
||||||
|
fn storage_hash(&self, id: &BlockId<Block>, key: &StorageKey) -> sp_blockchain::Result<Option<Block::Hash>>;
|
||||||
|
|
||||||
|
/// Given a `BlockId` and a key prefix, return the matching child storage keys and values in that block.
|
||||||
|
fn storage_pairs(
|
||||||
|
&self,
|
||||||
|
id: &BlockId<Block>,
|
||||||
|
key_prefix: &StorageKey
|
||||||
|
) -> sp_blockchain::Result<Vec<(StorageKey, StorageData)>>;
|
||||||
|
|
||||||
|
/// Given a `BlockId` and a key prefix, return a `KeyIterator` iterates matching storage keys in that block.
|
||||||
|
fn storage_keys_iter<'a>(
|
||||||
|
&self,
|
||||||
|
id: &BlockId<Block>,
|
||||||
|
prefix: Option<&'a StorageKey>,
|
||||||
|
start_key: Option<&StorageKey>
|
||||||
|
) -> sp_blockchain::Result<KeyIterator<'a, B::State, Block>>;
|
||||||
|
|
||||||
|
/// Given a `BlockId`, a key and a child storage key, return the value under the key in that block.
|
||||||
|
fn child_storage(
|
||||||
|
&self,
|
||||||
|
id: &BlockId<Block>,
|
||||||
|
storage_key: &StorageKey,
|
||||||
|
child_info: ChildInfo,
|
||||||
|
key: &StorageKey
|
||||||
|
) -> sp_blockchain::Result<Option<StorageData>>;
|
||||||
|
|
||||||
|
/// Given a `BlockId`, a key prefix, and a child storage key, return the matching child storage keys.
|
||||||
|
fn child_storage_keys(
|
||||||
|
&self,
|
||||||
|
id: &BlockId<Block>,
|
||||||
|
child_storage_key: &StorageKey,
|
||||||
|
child_info: ChildInfo,
|
||||||
|
key_prefix: &StorageKey
|
||||||
|
) -> sp_blockchain::Result<Vec<StorageKey>>;
|
||||||
|
|
||||||
|
/// Given a `BlockId`, a key and a child storage key, return the hash under the key in that block.
|
||||||
|
fn child_storage_hash(
|
||||||
|
&self,
|
||||||
|
id: &BlockId<Block>,
|
||||||
|
storage_key: &StorageKey,
|
||||||
|
child_info: ChildInfo,
|
||||||
|
key: &StorageKey
|
||||||
|
) -> sp_blockchain::Result<Option<Block::Hash>>;
|
||||||
|
|
||||||
|
/// Get longest range within [first; last] that is possible to use in `key_changes`
|
||||||
|
/// and `key_changes_proof` calls.
|
||||||
|
/// Range could be shortened from the beginning if some changes tries have been pruned.
|
||||||
|
/// Returns Ok(None) if changes tries are not supported.
|
||||||
|
fn max_key_changes_range(
|
||||||
|
&self,
|
||||||
|
first: NumberFor<Block>,
|
||||||
|
last: BlockId<Block>,
|
||||||
|
) -> sp_blockchain::Result<Option<(NumberFor<Block>, BlockId<Block>)>>;
|
||||||
|
|
||||||
|
/// Get pairs of (block, extrinsic) where key has been changed at given blocks range.
|
||||||
|
/// Works only for runtimes that are supporting changes tries.
|
||||||
|
///
|
||||||
|
/// Changes are returned in descending order (i.e. last block comes first).
|
||||||
|
fn key_changes(
|
||||||
|
&self,
|
||||||
|
first: NumberFor<Block>,
|
||||||
|
last: BlockId<Block>,
|
||||||
|
storage_key: Option<&StorageKey>,
|
||||||
|
key: &StorageKey
|
||||||
|
) -> sp_blockchain::Result<Vec<(NumberFor<Block>, u32)>>;
|
||||||
|
}
|
||||||
|
|
||||||
/// Client backend.
|
/// Client backend.
|
||||||
///
|
///
|
||||||
/// Manages the data layer.
|
/// Manages the data layer.
|
||||||
|
|||||||
@@ -29,6 +29,18 @@ use sp_externalities::Extensions;
|
|||||||
use sp_core::NativeOrEncoded;
|
use sp_core::NativeOrEncoded;
|
||||||
|
|
||||||
use sp_api::{ProofRecorder, InitializeBlock, StorageTransactionCache};
|
use sp_api::{ProofRecorder, InitializeBlock, StorageTransactionCache};
|
||||||
|
use crate::execution_extensions::ExecutionExtensions;
|
||||||
|
|
||||||
|
/// Executor Provider
|
||||||
|
pub trait ExecutorProvider<Block: BlockT> {
|
||||||
|
/// executor instance
|
||||||
|
type Executor: CallExecutor<Block>;
|
||||||
|
/// Get call executor reference.
|
||||||
|
fn executor(&self) -> &Self::Executor;
|
||||||
|
|
||||||
|
/// Get a reference to the execution extensions.
|
||||||
|
fn execution_extensions(&self) -> &ExecutionExtensions<Block>;
|
||||||
|
}
|
||||||
|
|
||||||
/// Method call executor.
|
/// Method call executor.
|
||||||
pub trait CallExecutor<B: BlockT> {
|
pub trait CallExecutor<B: BlockT> {
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ use futures::channel::mpsc;
|
|||||||
use sp_core::storage::StorageKey;
|
use sp_core::storage::StorageKey;
|
||||||
use sp_runtime::{
|
use sp_runtime::{
|
||||||
traits::{Block as BlockT, NumberFor},
|
traits::{Block as BlockT, NumberFor},
|
||||||
generic::BlockId
|
generic::{BlockId, SignedBlock}
|
||||||
};
|
};
|
||||||
use sp_consensus::BlockOrigin;
|
use sp_consensus::BlockOrigin;
|
||||||
|
|
||||||
@@ -76,9 +76,13 @@ pub trait BlockchainEvents<Block: BlockT> {
|
|||||||
/// Fetch block body by ID.
|
/// Fetch block body by ID.
|
||||||
pub trait BlockBody<Block: BlockT> {
|
pub trait BlockBody<Block: BlockT> {
|
||||||
/// Get block body by ID. Returns `None` if the body is not stored.
|
/// Get block body by ID. Returns `None` if the body is not stored.
|
||||||
fn block_body(&self,
|
fn block_body(
|
||||||
|
&self,
|
||||||
id: &BlockId<Block>
|
id: &BlockId<Block>
|
||||||
) -> sp_blockchain::Result<Option<Vec<<Block as BlockT>::Extrinsic>>>;
|
) -> sp_blockchain::Result<Option<Vec<<Block as BlockT>::Extrinsic>>>;
|
||||||
|
|
||||||
|
/// Get full block by id.
|
||||||
|
fn block(&self, id: &BlockId<Block>) -> sp_blockchain::Result<Option<SignedBlock<Block>>>;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Provide a list of potential uncle headers for a given block.
|
/// Provide a list of potential uncle headers for a given block.
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ pub mod client;
|
|||||||
pub mod execution_extensions;
|
pub mod execution_extensions;
|
||||||
pub mod light;
|
pub mod light;
|
||||||
pub mod notifications;
|
pub mod notifications;
|
||||||
|
pub mod proof_provider;
|
||||||
|
|
||||||
pub use sp_blockchain as blockchain;
|
pub use sp_blockchain as blockchain;
|
||||||
pub use backend::*;
|
pub use backend::*;
|
||||||
@@ -31,6 +32,7 @@ pub use call_executor::*;
|
|||||||
pub use client::*;
|
pub use client::*;
|
||||||
pub use light::*;
|
pub use light::*;
|
||||||
pub use notifications::*;
|
pub use notifications::*;
|
||||||
|
pub use proof_provider::*;
|
||||||
|
|
||||||
pub use sp_state_machine::{StorageProof, ExecutionStrategy};
|
pub use sp_state_machine::{StorageProof, ExecutionStrategy};
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,71 @@
|
|||||||
|
// Copyright 2017-2020 Parity Technologies (UK) Ltd.
|
||||||
|
// This file is part of Substrate.
|
||||||
|
|
||||||
|
// Substrate is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
|
||||||
|
// Substrate is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with Substrate. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
//! Proof utilities
|
||||||
|
use sp_runtime::{
|
||||||
|
generic::BlockId,
|
||||||
|
traits::{Block as BlockT},
|
||||||
|
};
|
||||||
|
use crate::{StorageProof, ChangesProof};
|
||||||
|
use sp_storage::{ChildInfo, StorageKey};
|
||||||
|
|
||||||
|
/// Interface for providing block proving utilities.
|
||||||
|
pub trait ProofProvider<Block: BlockT> {
|
||||||
|
/// Reads storage value at a given block + key, returning read proof.
|
||||||
|
fn read_proof(
|
||||||
|
&self,
|
||||||
|
id: &BlockId<Block>,
|
||||||
|
keys: &mut dyn Iterator<Item=&[u8]>,
|
||||||
|
) -> sp_blockchain::Result<StorageProof>;
|
||||||
|
|
||||||
|
/// Reads child storage value at a given block + storage_key + key, returning
|
||||||
|
/// read proof.
|
||||||
|
fn read_child_proof(
|
||||||
|
&self,
|
||||||
|
id: &BlockId<Block>,
|
||||||
|
storage_key: &[u8],
|
||||||
|
child_info: ChildInfo,
|
||||||
|
keys: &mut dyn Iterator<Item=&[u8]>,
|
||||||
|
) -> sp_blockchain::Result<StorageProof>;
|
||||||
|
|
||||||
|
/// Execute a call to a contract on top of state in a block of given hash
|
||||||
|
/// AND returning execution proof.
|
||||||
|
///
|
||||||
|
/// No changes are made.
|
||||||
|
fn execution_proof(
|
||||||
|
&self,
|
||||||
|
id: &BlockId<Block>,
|
||||||
|
method: &str,
|
||||||
|
call_data: &[u8],
|
||||||
|
) -> sp_blockchain::Result<(Vec<u8>, StorageProof)>;
|
||||||
|
/// Reads given header and generates CHT-based header proof.
|
||||||
|
fn header_proof(&self, id: &BlockId<Block>) -> sp_blockchain::Result<(Block::Header, StorageProof)>;
|
||||||
|
|
||||||
|
/// Get proof for computation of (block, extrinsic) pairs where key has been changed at given blocks range.
|
||||||
|
/// `min` is the hash of the first block, which changes trie root is known to the requester - when we're using
|
||||||
|
/// changes tries from ascendants of this block, we should provide proofs for changes tries roots
|
||||||
|
/// `max` is the hash of the last block known to the requester - we can't use changes tries from descendants
|
||||||
|
/// of this block.
|
||||||
|
/// Works only for runtimes that are supporting changes tries.
|
||||||
|
fn key_changes_proof(
|
||||||
|
&self,
|
||||||
|
first: Block::Hash,
|
||||||
|
last: Block::Hash,
|
||||||
|
min: Block::Hash,
|
||||||
|
max: Block::Hash,
|
||||||
|
storage_key: Option<&StorageKey>,
|
||||||
|
key: &StorageKey,
|
||||||
|
) -> sp_blockchain::Result<ChangesProof<Block::Header>>;
|
||||||
|
}
|
||||||
@@ -28,10 +28,7 @@ use parking_lot::RwLock;
|
|||||||
use sp_blockchain::{HeaderBackend, Error as ClientError, HeaderMetadata};
|
use sp_blockchain::{HeaderBackend, Error as ClientError, HeaderMetadata};
|
||||||
use std::marker::PhantomData;
|
use std::marker::PhantomData;
|
||||||
|
|
||||||
use sc_client_api::{
|
use sc_client_api::{backend::Backend, utils::is_descendent_of};
|
||||||
backend::Backend,
|
|
||||||
utils::is_descendent_of,
|
|
||||||
};
|
|
||||||
use sc_client::apply_aux;
|
use sc_client::apply_aux;
|
||||||
use finality_grandpa::{
|
use finality_grandpa::{
|
||||||
BlockNumberOps, Equivocation, Error as GrandpaError, round::State as RoundState,
|
BlockNumberOps, Equivocation, Error as GrandpaError, round::State as RoundState,
|
||||||
|
|||||||
@@ -34,16 +34,15 @@
|
|||||||
//! finality proof (that finalizes some block C that is ancestor of the B and descendant
|
//! finality proof (that finalizes some block C that is ancestor of the B and descendant
|
||||||
//! of the U) could be returned.
|
//! of the U) could be returned.
|
||||||
|
|
||||||
use std::iter;
|
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use log::{trace, warn};
|
use log::{trace, warn};
|
||||||
|
|
||||||
use sp_blockchain::{Backend as BlockchainBackend, Error as ClientError, Result as ClientResult};
|
use sp_blockchain::{Backend as BlockchainBackend, Error as ClientError, Result as ClientResult};
|
||||||
use sc_client_api::{
|
use sc_client_api::{
|
||||||
backend::Backend, CallExecutor, StorageProof,
|
backend::Backend, StorageProof,
|
||||||
light::{FetchChecker, RemoteReadRequest},
|
light::{FetchChecker, RemoteReadRequest},
|
||||||
|
StorageProvider, ProofProvider,
|
||||||
};
|
};
|
||||||
use sc_client::Client;
|
|
||||||
use parity_scale_codec::{Encode, Decode};
|
use parity_scale_codec::{Encode, Decode};
|
||||||
use finality_grandpa::BlockNumberOps;
|
use finality_grandpa::BlockNumberOps;
|
||||||
use sp_runtime::{
|
use sp_runtime::{
|
||||||
@@ -67,12 +66,25 @@ pub trait AuthoritySetForFinalityProver<Block: BlockT>: Send + Sync {
|
|||||||
fn prove_authorities(&self, block: &BlockId<Block>) -> ClientResult<StorageProof>;
|
fn prove_authorities(&self, block: &BlockId<Block>) -> ClientResult<StorageProof>;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Client-based implementation of AuthoritySetForFinalityProver.
|
/// Trait that combines `StorageProvider` and `ProofProvider`
|
||||||
impl<B, E, Block: BlockT, RA> AuthoritySetForFinalityProver<Block> for Client<B, E, Block, RA>
|
pub trait StorageAndProofProvider<Block, BE>: StorageProvider<Block, BE> + ProofProvider<Block> + Send + Sync
|
||||||
where
|
where
|
||||||
B: Backend<Block> + Send + Sync + 'static,
|
Block: BlockT,
|
||||||
E: CallExecutor<Block> + 'static + Clone + Send + Sync,
|
BE: Backend<Block> + Send + Sync,
|
||||||
RA: Send + Sync,
|
{}
|
||||||
|
|
||||||
|
/// Blanket implementation.
|
||||||
|
impl<Block, BE, P> StorageAndProofProvider<Block, BE> for P
|
||||||
|
where
|
||||||
|
Block: BlockT,
|
||||||
|
BE: Backend<Block> + Send + Sync,
|
||||||
|
P: StorageProvider<Block, BE> + ProofProvider<Block> + Send + Sync,
|
||||||
|
{}
|
||||||
|
|
||||||
|
/// Implementation of AuthoritySetForFinalityProver.
|
||||||
|
impl<BE, Block: BlockT> AuthoritySetForFinalityProver<Block> for Arc<dyn StorageAndProofProvider<Block, BE>>
|
||||||
|
where
|
||||||
|
BE: Backend<Block> + Send + Sync + 'static,
|
||||||
{
|
{
|
||||||
fn authorities(&self, block: &BlockId<Block>) -> ClientResult<AuthorityList> {
|
fn authorities(&self, block: &BlockId<Block>) -> ClientResult<AuthorityList> {
|
||||||
let storage_key = StorageKey(GRANDPA_AUTHORITIES_KEY.to_vec());
|
let storage_key = StorageKey(GRANDPA_AUTHORITIES_KEY.to_vec());
|
||||||
@@ -83,7 +95,7 @@ impl<B, E, Block: BlockT, RA> AuthoritySetForFinalityProver<Block> for Client<B,
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn prove_authorities(&self, block: &BlockId<Block>) -> ClientResult<StorageProof> {
|
fn prove_authorities(&self, block: &BlockId<Block>) -> ClientResult<StorageProof> {
|
||||||
self.read_proof(block, iter::once(GRANDPA_AUTHORITIES_KEY))
|
self.read_proof(block, &mut std::iter::once(GRANDPA_AUTHORITIES_KEY))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -146,11 +158,13 @@ impl<B, Block: BlockT> FinalityProofProvider<B, Block>
|
|||||||
///
|
///
|
||||||
/// - backend for accessing blockchain data;
|
/// - backend for accessing blockchain data;
|
||||||
/// - authority_provider for calling and proving runtime methods.
|
/// - authority_provider for calling and proving runtime methods.
|
||||||
pub fn new(
|
pub fn new<P>(
|
||||||
backend: Arc<B>,
|
backend: Arc<B>,
|
||||||
authority_provider: Arc<dyn AuthoritySetForFinalityProver<Block>>,
|
authority_provider: P,
|
||||||
) -> Self {
|
) -> Self
|
||||||
FinalityProofProvider { backend, authority_provider }
|
where P: AuthoritySetForFinalityProver<Block> + 'static,
|
||||||
|
{
|
||||||
|
FinalityProofProvider { backend, authority_provider: Arc::new(authority_provider) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -541,8 +541,7 @@ impl<Backend, Block: BlockT, Client, SC> GrandpaBlockImport<Backend, Block, Clie
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<BE, Block: BlockT, Client, SC>
|
impl<BE, Block: BlockT, Client, SC> GrandpaBlockImport<BE, Block, Client, SC>
|
||||||
GrandpaBlockImport<BE, Block, Client, SC>
|
|
||||||
where
|
where
|
||||||
BE: Backend<Block>,
|
BE: Backend<Block>,
|
||||||
Client: crate::ClientForGrandpa<Block, BE>,
|
Client: crate::ClientForGrandpa<Block, BE>,
|
||||||
|
|||||||
@@ -57,11 +57,11 @@ use futures::StreamExt;
|
|||||||
use log::{debug, info};
|
use log::{debug, info};
|
||||||
use futures::channel::mpsc;
|
use futures::channel::mpsc;
|
||||||
use sc_client_api::{
|
use sc_client_api::{
|
||||||
|
backend::{AuxStore, Backend},
|
||||||
LockImportRun, BlockchainEvents, CallExecutor,
|
LockImportRun, BlockchainEvents, CallExecutor,
|
||||||
backend::{AuxStore, Backend}, ExecutionStrategy, Finalizer, TransactionFor,
|
ExecutionStrategy, Finalizer, TransactionFor, ExecutorProvider,
|
||||||
};
|
};
|
||||||
use sp_blockchain::{HeaderBackend, Error as ClientError, HeaderMetadata};
|
use sp_blockchain::{HeaderBackend, Error as ClientError, HeaderMetadata};
|
||||||
use sc_client::Client;
|
|
||||||
use parity_scale_codec::{Decode, Encode};
|
use parity_scale_codec::{Decode, Encode};
|
||||||
use sp_runtime::generic::BlockId;
|
use sp_runtime::generic::BlockId;
|
||||||
use sp_runtime::traits::{NumberFor, Block as BlockT, DigestFor, Zero};
|
use sp_runtime::traits::{NumberFor, Block as BlockT, DigestFor, Zero};
|
||||||
@@ -96,7 +96,7 @@ mod observer;
|
|||||||
mod until_imported;
|
mod until_imported;
|
||||||
mod voting_rule;
|
mod voting_rule;
|
||||||
|
|
||||||
pub use finality_proof::FinalityProofProvider;
|
pub use finality_proof::{FinalityProofProvider, StorageAndProofProvider};
|
||||||
pub use justification::GrandpaJustification;
|
pub use justification::GrandpaJustification;
|
||||||
pub use light_import::light_block_import;
|
pub use light_import::light_block_import;
|
||||||
pub use voting_rule::{
|
pub use voting_rule::{
|
||||||
@@ -266,7 +266,7 @@ impl<Block: BlockT, Client> BlockStatus<Block> for Arc<Client> where
|
|||||||
pub trait ClientForGrandpa<Block, BE>:
|
pub trait ClientForGrandpa<Block, BE>:
|
||||||
LockImportRun<Block, BE> + Finalizer<Block, BE> + AuxStore
|
LockImportRun<Block, BE> + Finalizer<Block, BE> + AuxStore
|
||||||
+ HeaderMetadata<Block, Error = sp_blockchain::Error> + HeaderBackend<Block>
|
+ HeaderMetadata<Block, Error = sp_blockchain::Error> + HeaderBackend<Block>
|
||||||
+ BlockchainEvents<Block> + ProvideRuntimeApi<Block>
|
+ BlockchainEvents<Block> + ProvideRuntimeApi<Block> + ExecutorProvider<Block>
|
||||||
+ BlockImport<Block, Transaction = TransactionFor<BE, Block>, Error = sp_consensus::Error>
|
+ BlockImport<Block, Transaction = TransactionFor<BE, Block>, Error = sp_consensus::Error>
|
||||||
where
|
where
|
||||||
BE: Backend<Block>,
|
BE: Backend<Block>,
|
||||||
@@ -279,7 +279,7 @@ impl<Block, BE, T> ClientForGrandpa<Block, BE> for T
|
|||||||
Block: BlockT,
|
Block: BlockT,
|
||||||
T: LockImportRun<Block, BE> + Finalizer<Block, BE> + AuxStore
|
T: LockImportRun<Block, BE> + Finalizer<Block, BE> + AuxStore
|
||||||
+ HeaderMetadata<Block, Error = sp_blockchain::Error> + HeaderBackend<Block>
|
+ HeaderMetadata<Block, Error = sp_blockchain::Error> + HeaderBackend<Block>
|
||||||
+ BlockchainEvents<Block> + ProvideRuntimeApi<Block>
|
+ BlockchainEvents<Block> + ProvideRuntimeApi<Block> + ExecutorProvider<Block>
|
||||||
+ BlockImport<Block, Transaction = TransactionFor<BE, Block>, Error = sp_consensus::Error>,
|
+ BlockImport<Block, Transaction = TransactionFor<BE, Block>, Error = sp_consensus::Error>,
|
||||||
{}
|
{}
|
||||||
|
|
||||||
@@ -387,11 +387,8 @@ pub trait GenesisAuthoritySetProvider<Block: BlockT> {
|
|||||||
fn get(&self) -> Result<AuthorityList, ClientError>;
|
fn get(&self) -> Result<AuthorityList, ClientError>;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<B, E, Block: BlockT, RA> GenesisAuthoritySetProvider<Block> for Client<B, E, Block, RA>
|
impl<Block: BlockT, E> GenesisAuthoritySetProvider<Block> for Arc<dyn ExecutorProvider<Block, Executor = E>>
|
||||||
where
|
where E: CallExecutor<Block>,
|
||||||
B: Backend<Block> + Send + Sync + 'static,
|
|
||||||
E: CallExecutor<Block> + Send + Sync,
|
|
||||||
RA: Send + Sync,
|
|
||||||
{
|
{
|
||||||
fn get(&self) -> Result<AuthorityList, ClientError> {
|
fn get(&self) -> Result<AuthorityList, ClientError> {
|
||||||
// This implementation uses the Grandpa runtime API instead of reading directly from the
|
// This implementation uses the Grandpa runtime API instead of reading directly from the
|
||||||
|
|||||||
@@ -18,7 +18,9 @@ use std::collections::HashMap;
|
|||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use log::{info, trace, warn};
|
use log::{info, trace, warn};
|
||||||
use parking_lot::RwLock;
|
use parking_lot::RwLock;
|
||||||
use sc_client_api::backend::{AuxStore, Backend, Finalizer, TransactionFor};
|
use sc_client_api::{
|
||||||
|
backend::{AuxStore, Backend, Finalizer, TransactionFor},
|
||||||
|
};
|
||||||
use sp_blockchain::{HeaderBackend, Error as ClientError, well_known_cache_keys};
|
use sp_blockchain::{HeaderBackend, Error as ClientError, well_known_cache_keys};
|
||||||
use parity_scale_codec::{Encode, Decode};
|
use parity_scale_codec::{Encode, Decode};
|
||||||
use sp_consensus::{
|
use sp_consensus::{
|
||||||
|
|||||||
@@ -328,7 +328,7 @@ impl<B, BE, C, N> Future for ObserverWork<B, BE, C, N>
|
|||||||
where
|
where
|
||||||
B: BlockT,
|
B: BlockT,
|
||||||
BE: Backend<B> + Unpin + 'static,
|
BE: Backend<B> + Unpin + 'static,
|
||||||
C: crate::ClientForGrandpa<B, BE>+ 'static,
|
C: crate::ClientForGrandpa<B, BE> + 'static,
|
||||||
N: NetworkT<B>,
|
N: NetworkT<B>,
|
||||||
NumberFor<B>: BlockNumberOps,
|
NumberFor<B>: BlockNumberOps,
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ use sp_consensus::{
|
|||||||
use std::{
|
use std::{
|
||||||
collections::{HashMap, HashSet},
|
collections::{HashMap, HashSet},
|
||||||
result,
|
result,
|
||||||
pin::Pin, task,
|
pin::Pin,
|
||||||
};
|
};
|
||||||
use parity_scale_codec::Decode;
|
use parity_scale_codec::Decode;
|
||||||
use sp_runtime::traits::{Block as BlockT, Header as HeaderT, HashFor};
|
use sp_runtime::traits::{Block as BlockT, Header as HeaderT, HashFor};
|
||||||
@@ -170,8 +170,7 @@ impl TestNetFactory for GrandpaTestNet {
|
|||||||
) -> Option<Arc<dyn sc_network::config::FinalityProofProvider<Block>>> {
|
) -> Option<Arc<dyn sc_network::config::FinalityProofProvider<Block>>> {
|
||||||
match client {
|
match client {
|
||||||
PeersClient::Full(_, ref backend) => {
|
PeersClient::Full(_, ref backend) => {
|
||||||
let authorities_provider = Arc::new(self.test_config.clone());
|
Some(Arc::new(FinalityProofProvider::new(backend.clone(), self.test_config.clone())))
|
||||||
Some(Arc::new(FinalityProofProvider::new(backend.clone(), authorities_provider)))
|
|
||||||
},
|
},
|
||||||
PeersClient::Light(_, _) => None,
|
PeersClient::Light(_, _) => None,
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,7 +18,7 @@
|
|||||||
|
|
||||||
use sc_client::Client as SubstrateClient;
|
use sc_client::Client as SubstrateClient;
|
||||||
use sp_blockchain::{Error, Info as BlockchainInfo};
|
use sp_blockchain::{Error, Info as BlockchainInfo};
|
||||||
use sc_client_api::{ChangesProof, StorageProof, CallExecutor};
|
use sc_client_api::{ChangesProof, StorageProof, CallExecutor, ProofProvider};
|
||||||
use sp_consensus::{BlockImport, BlockStatus, Error as ConsensusError};
|
use sp_consensus::{BlockImport, BlockStatus, Error as ConsensusError};
|
||||||
use sp_runtime::traits::{Block as BlockT, Header as HeaderT, NumberFor};
|
use sp_runtime::traits::{Block as BlockT, Header as HeaderT, NumberFor};
|
||||||
use sp_runtime::generic::{BlockId};
|
use sp_runtime::generic::{BlockId};
|
||||||
@@ -50,7 +50,11 @@ pub trait Client<Block: BlockT>: Send + Sync {
|
|||||||
-> Result<(Block::Header, StorageProof), Error>;
|
-> Result<(Block::Header, StorageProof), Error>;
|
||||||
|
|
||||||
/// Get storage read execution proof.
|
/// Get storage read execution proof.
|
||||||
fn read_proof(&self, block: &Block::Hash, keys: &[Vec<u8>]) -> Result<StorageProof, Error>;
|
fn read_proof(
|
||||||
|
&self,
|
||||||
|
block: &Block::Hash,
|
||||||
|
keys: &mut dyn Iterator<Item=&[u8]>,
|
||||||
|
) -> Result<StorageProof, Error>;
|
||||||
|
|
||||||
/// Get child storage read execution proof.
|
/// Get child storage read execution proof.
|
||||||
fn read_child_proof(
|
fn read_child_proof(
|
||||||
@@ -58,7 +62,7 @@ pub trait Client<Block: BlockT>: Send + Sync {
|
|||||||
block: &Block::Hash,
|
block: &Block::Hash,
|
||||||
storage_key: &[u8],
|
storage_key: &[u8],
|
||||||
child_info: ChildInfo,
|
child_info: ChildInfo,
|
||||||
keys: &[Vec<u8>],
|
keys: &mut dyn Iterator<Item=&[u8]>,
|
||||||
) -> Result<StorageProof, Error>;
|
) -> Result<StorageProof, Error>;
|
||||||
|
|
||||||
/// Get method execution proof.
|
/// Get method execution proof.
|
||||||
@@ -125,14 +129,19 @@ impl<B, E, Block, RA> Client<Block> for SubstrateClient<B, E, Block, RA> where
|
|||||||
(self as &SubstrateClient<B, E, Block, RA>).justification(id)
|
(self as &SubstrateClient<B, E, Block, RA>).justification(id)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn header_proof(&self, block_number: <Block::Header as HeaderT>::Number)
|
fn header_proof(
|
||||||
-> Result<(Block::Header, StorageProof), Error>
|
&self,
|
||||||
{
|
block_number: <Block::Header as HeaderT>::Number,
|
||||||
(self as &SubstrateClient<B, E, Block, RA>).header_proof(&BlockId::Number(block_number))
|
)-> Result<(Block::Header, StorageProof), Error> {
|
||||||
|
ProofProvider::<Block>::header_proof(self, &BlockId::Number(block_number))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn read_proof(&self, block: &Block::Hash, keys: &[Vec<u8>]) -> Result<StorageProof, Error> {
|
fn read_proof(
|
||||||
(self as &SubstrateClient<B, E, Block, RA>).read_proof(&BlockId::Hash(block.clone()), keys)
|
&self,
|
||||||
|
block: &Block::Hash,
|
||||||
|
keys: &mut dyn Iterator<Item=&[u8]>,
|
||||||
|
) -> Result<StorageProof, Error> {
|
||||||
|
ProofProvider::<Block>::read_proof(self, &BlockId::Hash(block.clone()), keys)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn read_child_proof(
|
fn read_child_proof(
|
||||||
@@ -140,10 +149,9 @@ impl<B, E, Block, RA> Client<Block> for SubstrateClient<B, E, Block, RA> where
|
|||||||
block: &Block::Hash,
|
block: &Block::Hash,
|
||||||
storage_key: &[u8],
|
storage_key: &[u8],
|
||||||
child_info: ChildInfo,
|
child_info: ChildInfo,
|
||||||
keys: &[Vec<u8>],
|
keys: &mut dyn Iterator<Item=&[u8]>,
|
||||||
) -> Result<StorageProof, Error> {
|
) -> Result<StorageProof, Error> {
|
||||||
(self as &SubstrateClient<B, E, Block, RA>)
|
ProofProvider::<Block>::read_child_proof(self, &BlockId::Hash(block.clone()), storage_key, child_info, keys)
|
||||||
.read_child_proof(&BlockId::Hash(block.clone()), storage_key, child_info, keys)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn execution_proof(
|
fn execution_proof(
|
||||||
@@ -152,7 +160,8 @@ impl<B, E, Block, RA> Client<Block> for SubstrateClient<B, E, Block, RA> where
|
|||||||
method: &str,
|
method: &str,
|
||||||
data: &[u8],
|
data: &[u8],
|
||||||
) -> Result<(Vec<u8>, StorageProof), Error> {
|
) -> Result<(Vec<u8>, StorageProof), Error> {
|
||||||
(self as &SubstrateClient<B, E, Block, RA>).execution_proof(
|
ProofProvider::<Block>::execution_proof(
|
||||||
|
self,
|
||||||
&BlockId::Hash(block.clone()),
|
&BlockId::Hash(block.clone()),
|
||||||
method,
|
method,
|
||||||
data,
|
data,
|
||||||
@@ -168,7 +177,7 @@ impl<B, E, Block, RA> Client<Block> for SubstrateClient<B, E, Block, RA> where
|
|||||||
storage_key: Option<&StorageKey>,
|
storage_key: Option<&StorageKey>,
|
||||||
key: &StorageKey,
|
key: &StorageKey,
|
||||||
) -> Result<ChangesProof<Block::Header>, Error> {
|
) -> Result<ChangesProof<Block::Header>, Error> {
|
||||||
(self as &SubstrateClient<B, E, Block, RA>).key_changes_proof(first, last, min, max, storage_key, key)
|
ProofProvider::<Block>::key_changes_proof(self, first, last, min, max, storage_key, key)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_descendent_of(&self, base: &Block::Hash, block: &Block::Hash) -> Result<bool, Error> {
|
fn is_descendent_of(&self, base: &Block::Hash, block: &Block::Hash) -> Result<bool, Error> {
|
||||||
|
|||||||
@@ -1473,7 +1473,10 @@ impl<B: BlockT, H: ExHashT> Protocol<B, H> {
|
|||||||
|
|
||||||
trace!(target: "sync", "Remote read request {} from {} ({} at {})",
|
trace!(target: "sync", "Remote read request {} from {} ({} at {})",
|
||||||
request.id, who, keys_str(), request.block);
|
request.id, who, keys_str(), request.block);
|
||||||
let proof = match self.context_data.chain.read_proof(&request.block, &request.keys) {
|
let proof = match self.context_data.chain.read_proof(
|
||||||
|
&request.block,
|
||||||
|
&mut request.keys.iter().map(AsRef::as_ref)
|
||||||
|
) {
|
||||||
Ok(proof) => proof,
|
Ok(proof) => proof,
|
||||||
Err(error) => {
|
Err(error) => {
|
||||||
trace!(target: "sync", "Remote read request {} from {} ({} at {}) failed with: {}",
|
trace!(target: "sync", "Remote read request {} from {} ({} at {}) failed with: {}",
|
||||||
@@ -1523,7 +1526,7 @@ impl<B: BlockT, H: ExHashT> Protocol<B, H> {
|
|||||||
&request.block,
|
&request.block,
|
||||||
&request.storage_key,
|
&request.storage_key,
|
||||||
child_info,
|
child_info,
|
||||||
&request.keys,
|
&mut request.keys.iter().map(AsRef::as_ref),
|
||||||
) {
|
) {
|
||||||
Ok(proof) => proof,
|
Ok(proof) => proof,
|
||||||
Err(error) => {
|
Err(error) => {
|
||||||
|
|||||||
@@ -467,7 +467,7 @@ where
|
|||||||
|
|
||||||
let block = Decode::decode(&mut request.block.as_ref())?;
|
let block = Decode::decode(&mut request.block.as_ref())?;
|
||||||
|
|
||||||
let proof = match self.chain.read_proof(&block, &request.keys) {
|
let proof = match self.chain.read_proof(&block, &mut request.keys.iter().map(AsRef::as_ref)) {
|
||||||
Ok(proof) => proof,
|
Ok(proof) => proof,
|
||||||
Err(error) => {
|
Err(error) => {
|
||||||
log::trace!("remote read request from {} ({} at {:?}) failed with: {}",
|
log::trace!("remote read request from {} ({} at {:?}) failed with: {}",
|
||||||
@@ -508,7 +508,12 @@ where
|
|||||||
|
|
||||||
let proof =
|
let proof =
|
||||||
if let Some(info) = ChildInfo::resolve_child_info(request.child_type, &request.child_info[..]) {
|
if let Some(info) = ChildInfo::resolve_child_info(request.child_type, &request.child_info[..]) {
|
||||||
match self.chain.read_child_proof(&block, &request.storage_key, info, &request.keys) {
|
match self.chain.read_child_proof(
|
||||||
|
&block,
|
||||||
|
&request.storage_key,
|
||||||
|
info,
|
||||||
|
&mut request.keys.iter().map(AsRef::as_ref)
|
||||||
|
) {
|
||||||
Ok(proof) => proof,
|
Ok(proof) => proof,
|
||||||
Err(error) => {
|
Err(error) => {
|
||||||
log::trace!("remote read child request from {} ({} {} at {:?}) failed with: {}",
|
log::trace!("remote read child request from {} ({} {} at {:?}) failed with: {}",
|
||||||
|
|||||||
@@ -169,6 +169,7 @@ mod tests {
|
|||||||
use substrate_test_runtime_client::runtime::Block;
|
use substrate_test_runtime_client::runtime::Block;
|
||||||
use sc_transaction_pool::{BasicPool, FullChainApi};
|
use sc_transaction_pool::{BasicPool, FullChainApi};
|
||||||
use sp_transaction_pool::{TransactionPool, InPoolTransaction};
|
use sp_transaction_pool::{TransactionPool, InPoolTransaction};
|
||||||
|
use sc_client_api::ExecutorProvider;
|
||||||
|
|
||||||
struct MockNetworkStateInfo();
|
struct MockNetworkStateInfo();
|
||||||
|
|
||||||
|
|||||||
@@ -22,8 +22,7 @@ mod tests;
|
|||||||
use std::{sync::Arc, convert::TryInto};
|
use std::{sync::Arc, convert::TryInto};
|
||||||
use log::warn;
|
use log::warn;
|
||||||
|
|
||||||
use sc_client::Client;
|
use sp_blockchain::{Error as ClientError, HeaderBackend};
|
||||||
use sp_blockchain::Error as ClientError;
|
|
||||||
|
|
||||||
use rpc::futures::{
|
use rpc::futures::{
|
||||||
Sink, Future,
|
Sink, Future,
|
||||||
@@ -36,7 +35,7 @@ use jsonrpc_pubsub::{typed::Subscriber, SubscriptionId};
|
|||||||
use codec::{Encode, Decode};
|
use codec::{Encode, Decode};
|
||||||
use sp_core::{Bytes, traits::BareCryptoStorePtr};
|
use sp_core::{Bytes, traits::BareCryptoStorePtr};
|
||||||
use sp_api::ProvideRuntimeApi;
|
use sp_api::ProvideRuntimeApi;
|
||||||
use sp_runtime::{generic, traits};
|
use sp_runtime::generic;
|
||||||
use sp_transaction_pool::{
|
use sp_transaction_pool::{
|
||||||
TransactionPool, InPoolTransaction, TransactionStatus,
|
TransactionPool, InPoolTransaction, TransactionStatus,
|
||||||
BlockHash, TxHash, TransactionFor, error::IntoPoolError,
|
BlockHash, TxHash, TransactionFor, error::IntoPoolError,
|
||||||
@@ -48,9 +47,9 @@ pub use sc_rpc_api::author::*;
|
|||||||
use self::error::{Error, FutureResult, Result};
|
use self::error::{Error, FutureResult, Result};
|
||||||
|
|
||||||
/// Authoring API
|
/// Authoring API
|
||||||
pub struct Author<B, E, P, Block: traits::Block, RA> {
|
pub struct Author<P, Client> {
|
||||||
/// Substrate client
|
/// Substrate client
|
||||||
client: Arc<Client<B, E, Block, RA>>,
|
client: Arc<Client>,
|
||||||
/// Transactions pool
|
/// Transactions pool
|
||||||
pool: Arc<P>,
|
pool: Arc<P>,
|
||||||
/// Subscriptions manager
|
/// Subscriptions manager
|
||||||
@@ -59,10 +58,10 @@ pub struct Author<B, E, P, Block: traits::Block, RA> {
|
|||||||
keystore: BareCryptoStorePtr,
|
keystore: BareCryptoStorePtr,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<B, E, P, Block: traits::Block, RA> Author<B, E, P, Block, RA> {
|
impl<P, Client> Author<P, Client> {
|
||||||
/// Create new instance of Authoring API.
|
/// Create new instance of Authoring API.
|
||||||
pub fn new(
|
pub fn new(
|
||||||
client: Arc<Client<B, E, Block, RA>>,
|
client: Arc<Client>,
|
||||||
pool: Arc<P>,
|
pool: Arc<P>,
|
||||||
subscriptions: Subscriptions,
|
subscriptions: Subscriptions,
|
||||||
keystore: BareCryptoStorePtr,
|
keystore: BareCryptoStorePtr,
|
||||||
@@ -76,18 +75,11 @@ impl<B, E, P, Block: traits::Block, RA> Author<B, E, P, Block, RA> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<B, E, P, RA> AuthorApi<TxHash<P>, BlockHash<P>>
|
impl<P, Client> AuthorApi<TxHash<P>, BlockHash<P>> for Author<P, Client>
|
||||||
for Author<B, E, P, <P as TransactionPool>::Block, RA>
|
where
|
||||||
where
|
P: TransactionPool + Sync + Send + 'static,
|
||||||
B: sc_client_api::backend::Backend<<P as TransactionPool>::Block> + Send + Sync + 'static,
|
Client: HeaderBackend<P::Block> + ProvideRuntimeApi<P::Block> + Send + Sync + 'static,
|
||||||
E: sc_client::CallExecutor<<P as TransactionPool>::Block> + Send + Sync + 'static,
|
Client::Api: SessionKeys<P::Block, Error = ClientError>,
|
||||||
P: TransactionPool + Sync + Send + 'static,
|
|
||||||
P::Block: traits::Block,
|
|
||||||
P::Error: 'static,
|
|
||||||
RA: Send + Sync + 'static,
|
|
||||||
Client<B, E, P::Block, RA>: ProvideRuntimeApi<P::Block>,
|
|
||||||
<Client<B, E, P::Block, RA> as ProvideRuntimeApi<P::Block>>::Api:
|
|
||||||
SessionKeys<P::Block, Error = ClientError>,
|
|
||||||
{
|
{
|
||||||
type Metadata = crate::metadata::Metadata;
|
type Metadata = crate::metadata::Metadata;
|
||||||
|
|
||||||
@@ -105,7 +97,7 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn rotate_keys(&self) -> Result<Bytes> {
|
fn rotate_keys(&self) -> Result<Bytes> {
|
||||||
let best_block_hash = self.client.chain_info().best_hash;
|
let best_block_hash = self.client.info().best_hash;
|
||||||
self.client.runtime_api().generate_session_keys(
|
self.client.runtime_api().generate_session_keys(
|
||||||
&generic::BlockId::Hash(best_block_hash),
|
&generic::BlockId::Hash(best_block_hash),
|
||||||
None,
|
None,
|
||||||
@@ -113,7 +105,7 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn has_session_keys(&self, session_keys: Bytes) -> Result<bool> {
|
fn has_session_keys(&self, session_keys: Bytes) -> Result<bool> {
|
||||||
let best_block_hash = self.client.chain_info().best_hash;
|
let best_block_hash = self.client.info().best_hash;
|
||||||
let keys = self.client.runtime_api().decode_session_keys(
|
let keys = self.client.runtime_api().decode_session_keys(
|
||||||
&generic::BlockId::Hash(best_block_hash),
|
&generic::BlockId::Hash(best_block_hash),
|
||||||
session_keys.to_vec(),
|
session_keys.to_vec(),
|
||||||
@@ -133,7 +125,7 @@ where
|
|||||||
Ok(xt) => xt,
|
Ok(xt) => xt,
|
||||||
Err(err) => return Box::new(result(Err(err.into()))),
|
Err(err) => return Box::new(result(Err(err.into()))),
|
||||||
};
|
};
|
||||||
let best_block_hash = self.client.chain_info().best_hash;
|
let best_block_hash = self.client.info().best_hash;
|
||||||
Box::new(self.pool
|
Box::new(self.pool
|
||||||
.submit_one(&generic::BlockId::hash(best_block_hash), xt)
|
.submit_one(&generic::BlockId::hash(best_block_hash), xt)
|
||||||
.compat()
|
.compat()
|
||||||
@@ -176,7 +168,7 @@ where
|
|||||||
xt: Bytes,
|
xt: Bytes,
|
||||||
) {
|
) {
|
||||||
let submit = || -> Result<_> {
|
let submit = || -> Result<_> {
|
||||||
let best_block_hash = self.client.chain_info().best_hash;
|
let best_block_hash = self.client.info().best_hash;
|
||||||
let dxt = TransactionFor::<P>::decode(&mut &xt[..])
|
let dxt = TransactionFor::<P>::decode(&mut &xt[..])
|
||||||
.map_err(error::Error::from)?;
|
.map_err(error::Error::from)?;
|
||||||
Ok(
|
Ok(
|
||||||
|
|||||||
@@ -25,8 +25,8 @@ use sp_core::{
|
|||||||
};
|
};
|
||||||
use rpc::futures::Stream as _;
|
use rpc::futures::Stream as _;
|
||||||
use substrate_test_runtime_client::{
|
use substrate_test_runtime_client::{
|
||||||
self, AccountKeyring, runtime::{Extrinsic, Transfer, SessionKeys, RuntimeApi, Block},
|
self, AccountKeyring, runtime::{Extrinsic, Transfer, SessionKeys, Block},
|
||||||
DefaultTestClientBuilderExt, TestClientBuilderExt, Backend, Client, Executor,
|
DefaultTestClientBuilderExt, TestClientBuilderExt, Backend, Client,
|
||||||
};
|
};
|
||||||
use sc_transaction_pool::{BasicPool, FullChainApi};
|
use sc_transaction_pool::{BasicPool, FullChainApi};
|
||||||
use tokio::runtime;
|
use tokio::runtime;
|
||||||
@@ -75,7 +75,7 @@ impl Default for TestSetup {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl TestSetup {
|
impl TestSetup {
|
||||||
fn author(&self) -> Author<Backend, Executor, FullTransactionPool, Block, RuntimeApi> {
|
fn author(&self) -> Author<FullTransactionPool, Client<Backend>> {
|
||||||
Author {
|
Author {
|
||||||
client: self.client.clone(),
|
client: self.client.clone(),
|
||||||
pool: self.pool.clone(),
|
pool: self.pool.clone(),
|
||||||
|
|||||||
@@ -20,37 +20,39 @@ use std::sync::Arc;
|
|||||||
use rpc::futures::future::result;
|
use rpc::futures::future::result;
|
||||||
|
|
||||||
use sc_rpc_api::Subscriptions;
|
use sc_rpc_api::Subscriptions;
|
||||||
use sc_client_api::{CallExecutor, backend::Backend};
|
use sc_client_api::{BlockchainEvents, BlockBody};
|
||||||
use sc_client::Client;
|
|
||||||
use sp_runtime::{generic::{BlockId, SignedBlock}, traits::{Block as BlockT}};
|
use sp_runtime::{generic::{BlockId, SignedBlock}, traits::{Block as BlockT}};
|
||||||
|
|
||||||
use super::{ChainBackend, client_err, error::FutureResult};
|
use super::{ChainBackend, client_err, error::FutureResult};
|
||||||
|
use std::marker::PhantomData;
|
||||||
|
use sp_blockchain::HeaderBackend;
|
||||||
|
|
||||||
/// Blockchain API backend for full nodes. Reads all the data from local database.
|
/// Blockchain API backend for full nodes. Reads all the data from local database.
|
||||||
pub struct FullChain<B, E, Block: BlockT, RA> {
|
pub struct FullChain<Block: BlockT, Client> {
|
||||||
/// Substrate client.
|
/// Substrate client.
|
||||||
client: Arc<Client<B, E, Block, RA>>,
|
client: Arc<Client>,
|
||||||
/// Current subscriptions.
|
/// Current subscriptions.
|
||||||
subscriptions: Subscriptions,
|
subscriptions: Subscriptions,
|
||||||
|
/// phantom member to pin the block type
|
||||||
|
_phantom: PhantomData<Block>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<B, E, Block: BlockT, RA> FullChain<B, E, Block, RA> {
|
impl<Block: BlockT, Client> FullChain<Block, Client> {
|
||||||
/// Create new Chain API RPC handler.
|
/// Create new Chain API RPC handler.
|
||||||
pub fn new(client: Arc<Client<B, E, Block, RA>>, subscriptions: Subscriptions) -> Self {
|
pub fn new(client: Arc<Client>, subscriptions: Subscriptions) -> Self {
|
||||||
Self {
|
Self {
|
||||||
client,
|
client,
|
||||||
subscriptions,
|
subscriptions,
|
||||||
|
_phantom: PhantomData,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<B, E, Block, RA> ChainBackend<B, E, Block, RA> for FullChain<B, E, Block, RA> where
|
impl<Block, Client> ChainBackend<Client, Block> for FullChain<Block, Client> where
|
||||||
Block: BlockT + 'static,
|
Block: BlockT + 'static,
|
||||||
B: Backend<Block> + Send + Sync + 'static,
|
Client: BlockBody<Block> + HeaderBackend<Block> + BlockchainEvents<Block> + 'static,
|
||||||
E: CallExecutor<Block> + Send + Sync + 'static,
|
|
||||||
RA: Send + Sync + 'static,
|
|
||||||
{
|
{
|
||||||
fn client(&self) -> &Arc<Client<B, E, Block, RA>> {
|
fn client(&self) -> &Arc<Client> {
|
||||||
&self.client
|
&self.client
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -60,7 +62,7 @@ impl<B, E, Block, RA> ChainBackend<B, E, Block, RA> for FullChain<B, E, Block, R
|
|||||||
|
|
||||||
fn header(&self, hash: Option<Block::Hash>) -> FutureResult<Option<Block::Header>> {
|
fn header(&self, hash: Option<Block::Hash>) -> FutureResult<Option<Block::Header>> {
|
||||||
Box::new(result(self.client
|
Box::new(result(self.client
|
||||||
.header(&BlockId::Hash(self.unwrap_or_best(hash)))
|
.header(BlockId::Hash(self.unwrap_or_best(hash)))
|
||||||
.map_err(client_err)
|
.map_err(client_err)
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ use rpc::futures::future::{result, Future, Either};
|
|||||||
|
|
||||||
use sc_rpc_api::Subscriptions;
|
use sc_rpc_api::Subscriptions;
|
||||||
use sc_client::{
|
use sc_client::{
|
||||||
Client, light::{fetcher::{Fetcher, RemoteBodyRequest}, blockchain::RemoteBlockchain},
|
light::{fetcher::{Fetcher, RemoteBodyRequest}, blockchain::RemoteBlockchain},
|
||||||
};
|
};
|
||||||
use sp_runtime::{
|
use sp_runtime::{
|
||||||
generic::{BlockId, SignedBlock},
|
generic::{BlockId, SignedBlock},
|
||||||
@@ -30,12 +30,14 @@ use sp_runtime::{
|
|||||||
};
|
};
|
||||||
|
|
||||||
use super::{ChainBackend, client_err, error::FutureResult};
|
use super::{ChainBackend, client_err, error::FutureResult};
|
||||||
|
use sp_blockchain::HeaderBackend;
|
||||||
|
use sc_client_api::BlockchainEvents;
|
||||||
|
|
||||||
/// Blockchain API backend for light nodes. Reads all the data from local
|
/// Blockchain API backend for light nodes. Reads all the data from local
|
||||||
/// database, if available, or fetches it from remote node otherwise.
|
/// database, if available, or fetches it from remote node otherwise.
|
||||||
pub struct LightChain<B, E, Block: BlockT, RA, F> {
|
pub struct LightChain<Block: BlockT, Client, F> {
|
||||||
/// Substrate client.
|
/// Substrate client.
|
||||||
client: Arc<Client<B, E, Block, RA>>,
|
client: Arc<Client>,
|
||||||
/// Current subscriptions.
|
/// Current subscriptions.
|
||||||
subscriptions: Subscriptions,
|
subscriptions: Subscriptions,
|
||||||
/// Remote blockchain reference
|
/// Remote blockchain reference
|
||||||
@@ -44,10 +46,10 @@ pub struct LightChain<B, E, Block: BlockT, RA, F> {
|
|||||||
fetcher: Arc<F>,
|
fetcher: Arc<F>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<B, E, Block: BlockT, RA, F: Fetcher<Block>> LightChain<B, E, Block, RA, F> {
|
impl<Block: BlockT, Client, F: Fetcher<Block>> LightChain<Block, Client, F> {
|
||||||
/// Create new Chain API RPC handler.
|
/// Create new Chain API RPC handler.
|
||||||
pub fn new(
|
pub fn new(
|
||||||
client: Arc<Client<B, E, Block, RA>>,
|
client: Arc<Client>,
|
||||||
subscriptions: Subscriptions,
|
subscriptions: Subscriptions,
|
||||||
remote_blockchain: Arc<dyn RemoteBlockchain<Block>>,
|
remote_blockchain: Arc<dyn RemoteBlockchain<Block>>,
|
||||||
fetcher: Arc<F>,
|
fetcher: Arc<F>,
|
||||||
@@ -61,14 +63,12 @@ impl<B, E, Block: BlockT, RA, F: Fetcher<Block>> LightChain<B, E, Block, RA, F>
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<B, E, Block, RA, F> ChainBackend<B, E, Block, RA> for LightChain<B, E, Block, RA, F> where
|
impl<Block, Client, F> ChainBackend<Client, Block> for LightChain<Block, Client, F> where
|
||||||
Block: BlockT + 'static,
|
Block: BlockT + 'static,
|
||||||
B: sc_client_api::backend::Backend<Block> + Send + Sync + 'static,
|
Client: BlockchainEvents<Block> + HeaderBackend<Block> + Send + Sync + 'static,
|
||||||
E: sc_client::CallExecutor<Block> + Send + Sync + 'static,
|
|
||||||
RA: Send + Sync + 'static,
|
|
||||||
F: Fetcher<Block> + Send + Sync + 'static,
|
F: Fetcher<Block> + Send + Sync + 'static,
|
||||||
{
|
{
|
||||||
fn client(&self) -> &Arc<Client<B, E, Block, RA>> {
|
fn client(&self) -> &Arc<Client> {
|
||||||
&self.client
|
&self.client
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ use rpc::{
|
|||||||
|
|
||||||
use sc_rpc_api::Subscriptions;
|
use sc_rpc_api::Subscriptions;
|
||||||
use sc_client::{
|
use sc_client::{
|
||||||
self, Client, BlockchainEvents,
|
self, BlockchainEvents,
|
||||||
light::{fetcher::Fetcher, blockchain::RemoteBlockchain},
|
light::{fetcher::Fetcher, blockchain::RemoteBlockchain},
|
||||||
};
|
};
|
||||||
use jsonrpc_pubsub::{typed::Subscriber, SubscriptionId};
|
use jsonrpc_pubsub::{typed::Subscriber, SubscriptionId};
|
||||||
@@ -45,16 +45,17 @@ use sp_runtime::{
|
|||||||
use self::error::{Result, Error, FutureResult};
|
use self::error::{Result, Error, FutureResult};
|
||||||
|
|
||||||
pub use sc_rpc_api::chain::*;
|
pub use sc_rpc_api::chain::*;
|
||||||
|
use sp_blockchain::HeaderBackend;
|
||||||
|
use sc_client_api::BlockBody;
|
||||||
|
|
||||||
/// Blockchain backend API
|
/// Blockchain backend API
|
||||||
trait ChainBackend<B, E, Block: BlockT, RA>: Send + Sync + 'static
|
trait ChainBackend<Client, Block: BlockT>: Send + Sync + 'static
|
||||||
where
|
where
|
||||||
Block: BlockT + 'static,
|
Block: BlockT + 'static,
|
||||||
B: sc_client_api::backend::Backend<Block> + Send + Sync + 'static,
|
Client: HeaderBackend<Block> + BlockchainEvents<Block> + 'static,
|
||||||
E: sc_client::CallExecutor<Block> + Send + Sync + 'static,
|
|
||||||
{
|
{
|
||||||
/// Get client reference.
|
/// Get client reference.
|
||||||
fn client(&self) -> &Arc<Client<B, E, Block, RA>>;
|
fn client(&self) -> &Arc<Client>;
|
||||||
|
|
||||||
/// Get subscriptions reference.
|
/// Get subscriptions reference.
|
||||||
fn subscriptions(&self) -> &Subscriptions;
|
fn subscriptions(&self) -> &Subscriptions;
|
||||||
@@ -62,7 +63,7 @@ trait ChainBackend<B, E, Block: BlockT, RA>: Send + Sync + 'static
|
|||||||
/// Tries to unwrap passed block hash, or uses best block hash otherwise.
|
/// Tries to unwrap passed block hash, or uses best block hash otherwise.
|
||||||
fn unwrap_or_best(&self, hash: Option<Block::Hash>) -> Block::Hash {
|
fn unwrap_or_best(&self, hash: Option<Block::Hash>) -> Block::Hash {
|
||||||
match hash.into() {
|
match hash.into() {
|
||||||
None => self.client().chain_info().best_hash,
|
None => self.client().info().best_hash,
|
||||||
Some(hash) => hash,
|
Some(hash) => hash,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -81,9 +82,9 @@ trait ChainBackend<B, E, Block: BlockT, RA>: Send + Sync + 'static
|
|||||||
number: Option<NumberOrHex<NumberFor<Block>>>,
|
number: Option<NumberOrHex<NumberFor<Block>>>,
|
||||||
) -> Result<Option<Block::Hash>> {
|
) -> Result<Option<Block::Hash>> {
|
||||||
Ok(match number {
|
Ok(match number {
|
||||||
None => Some(self.client().chain_info().best_hash),
|
None => Some(self.client().info().best_hash),
|
||||||
Some(num_or_hex) => self.client()
|
Some(num_or_hex) => self.client()
|
||||||
.header(&BlockId::number(num_or_hex.to_number()?))
|
.header(BlockId::number(num_or_hex.to_number()?))
|
||||||
.map_err(client_err)?
|
.map_err(client_err)?
|
||||||
.map(|h| h.hash()),
|
.map(|h| h.hash()),
|
||||||
})
|
})
|
||||||
@@ -91,7 +92,7 @@ trait ChainBackend<B, E, Block: BlockT, RA>: Send + Sync + 'static
|
|||||||
|
|
||||||
/// Get hash of the last finalized block in the canon chain.
|
/// Get hash of the last finalized block in the canon chain.
|
||||||
fn finalized_head(&self) -> Result<Block::Hash> {
|
fn finalized_head(&self) -> Result<Block::Hash> {
|
||||||
Ok(self.client().chain_info().finalized_hash)
|
Ok(self.client().info().finalized_hash)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// All new head subscription
|
/// All new head subscription
|
||||||
@@ -104,7 +105,7 @@ trait ChainBackend<B, E, Block: BlockT, RA>: Send + Sync + 'static
|
|||||||
self.client(),
|
self.client(),
|
||||||
self.subscriptions(),
|
self.subscriptions(),
|
||||||
subscriber,
|
subscriber,
|
||||||
|| self.client().chain_info().best_hash,
|
|| self.client().info().best_hash,
|
||||||
|| self.client().import_notification_stream()
|
|| self.client().import_notification_stream()
|
||||||
.map(|notification| Ok::<_, ()>(notification.header))
|
.map(|notification| Ok::<_, ()>(notification.header))
|
||||||
.compat(),
|
.compat(),
|
||||||
@@ -130,7 +131,7 @@ trait ChainBackend<B, E, Block: BlockT, RA>: Send + Sync + 'static
|
|||||||
self.client(),
|
self.client(),
|
||||||
self.subscriptions(),
|
self.subscriptions(),
|
||||||
subscriber,
|
subscriber,
|
||||||
|| self.client().chain_info().best_hash,
|
|| self.client().info().best_hash,
|
||||||
|| self.client().import_notification_stream()
|
|| self.client().import_notification_stream()
|
||||||
.filter(|notification| future::ready(notification.is_new_best))
|
.filter(|notification| future::ready(notification.is_new_best))
|
||||||
.map(|notification| Ok::<_, ()>(notification.header))
|
.map(|notification| Ok::<_, ()>(notification.header))
|
||||||
@@ -157,7 +158,7 @@ trait ChainBackend<B, E, Block: BlockT, RA>: Send + Sync + 'static
|
|||||||
self.client(),
|
self.client(),
|
||||||
self.subscriptions(),
|
self.subscriptions(),
|
||||||
subscriber,
|
subscriber,
|
||||||
|| self.client().chain_info().finalized_hash,
|
|| self.client().info().finalized_hash,
|
||||||
|| self.client().finality_notification_stream()
|
|| self.client().finality_notification_stream()
|
||||||
.map(|notification| Ok::<_, ()>(notification.header))
|
.map(|notification| Ok::<_, ()>(notification.header))
|
||||||
.compat(),
|
.compat(),
|
||||||
@@ -175,15 +176,13 @@ trait ChainBackend<B, E, Block: BlockT, RA>: Send + Sync + 'static
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Create new state API that works on full node.
|
/// Create new state API that works on full node.
|
||||||
pub fn new_full<B, E, Block: BlockT, RA>(
|
pub fn new_full<Block: BlockT, Client>(
|
||||||
client: Arc<Client<B, E, Block, RA>>,
|
client: Arc<Client>,
|
||||||
subscriptions: Subscriptions,
|
subscriptions: Subscriptions,
|
||||||
) -> Chain<B, E, Block, RA>
|
) -> Chain<Block, Client>
|
||||||
where
|
where
|
||||||
Block: BlockT + 'static,
|
Block: BlockT + 'static,
|
||||||
B: sc_client_api::backend::Backend<Block> + Send + Sync + 'static,
|
Client: BlockBody<Block> + HeaderBackend<Block> + BlockchainEvents<Block> + 'static,
|
||||||
E: sc_client::CallExecutor<Block> + Send + Sync + 'static + Clone,
|
|
||||||
RA: Send + Sync + 'static,
|
|
||||||
{
|
{
|
||||||
Chain {
|
Chain {
|
||||||
backend: Box::new(self::chain_full::FullChain::new(client, subscriptions)),
|
backend: Box::new(self::chain_full::FullChain::new(client, subscriptions)),
|
||||||
@@ -191,17 +190,15 @@ pub fn new_full<B, E, Block: BlockT, RA>(
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Create new state API that works on light node.
|
/// Create new state API that works on light node.
|
||||||
pub fn new_light<B, E, Block: BlockT, RA, F: Fetcher<Block>>(
|
pub fn new_light<Block: BlockT, Client, F: Fetcher<Block>>(
|
||||||
client: Arc<Client<B, E, Block, RA>>,
|
client: Arc<Client>,
|
||||||
subscriptions: Subscriptions,
|
subscriptions: Subscriptions,
|
||||||
remote_blockchain: Arc<dyn RemoteBlockchain<Block>>,
|
remote_blockchain: Arc<dyn RemoteBlockchain<Block>>,
|
||||||
fetcher: Arc<F>,
|
fetcher: Arc<F>,
|
||||||
) -> Chain<B, E, Block, RA>
|
) -> Chain<Block, Client>
|
||||||
where
|
where
|
||||||
Block: BlockT + 'static,
|
Block: BlockT + 'static,
|
||||||
B: sc_client_api::backend::Backend<Block> + Send + Sync + 'static,
|
Client: BlockBody<Block> + HeaderBackend<Block> + BlockchainEvents<Block> + 'static,
|
||||||
E: sc_client::CallExecutor<Block> + Send + Sync + 'static + Clone,
|
|
||||||
RA: Send + Sync + 'static,
|
|
||||||
F: Send + Sync + 'static,
|
F: Send + Sync + 'static,
|
||||||
{
|
{
|
||||||
Chain {
|
Chain {
|
||||||
@@ -215,15 +212,15 @@ pub fn new_light<B, E, Block: BlockT, RA, F: Fetcher<Block>>(
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Chain API with subscriptions support.
|
/// Chain API with subscriptions support.
|
||||||
pub struct Chain<B, E, Block: BlockT, RA> {
|
pub struct Chain<Block: BlockT, Client> {
|
||||||
backend: Box<dyn ChainBackend<B, E, Block, RA>>,
|
backend: Box<dyn ChainBackend<Client, Block>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<B, E, Block, RA> ChainApi<NumberFor<Block>, Block::Hash, Block::Header, SignedBlock<Block>> for Chain<B, E, Block, RA> where
|
impl<Block, Client> ChainApi<NumberFor<Block>, Block::Hash, Block::Header, SignedBlock<Block>> for
|
||||||
Block: BlockT + 'static,
|
Chain<Block, Client>
|
||||||
B: sc_client_api::backend::Backend<Block> + Send + Sync + 'static,
|
where
|
||||||
E: sc_client::CallExecutor<Block> + Send + Sync + 'static,
|
Block: BlockT + 'static,
|
||||||
RA: Send + Sync + 'static
|
Client: HeaderBackend<Block> + BlockchainEvents<Block> + 'static,
|
||||||
{
|
{
|
||||||
type Metadata = crate::metadata::Metadata;
|
type Metadata = crate::metadata::Metadata;
|
||||||
|
|
||||||
@@ -281,16 +278,15 @@ impl<B, E, Block, RA> ChainApi<NumberFor<Block>, Block::Hash, Block::Header, Sig
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Subscribe to new headers.
|
/// Subscribe to new headers.
|
||||||
fn subscribe_headers<B, E, Block, RA, F, G, S, ERR>(
|
fn subscribe_headers<Block, Client, F, G, S, ERR>(
|
||||||
client: &Arc<Client<B, E, Block, RA>>,
|
client: &Arc<Client>,
|
||||||
subscriptions: &Subscriptions,
|
subscriptions: &Subscriptions,
|
||||||
subscriber: Subscriber<Block::Header>,
|
subscriber: Subscriber<Block::Header>,
|
||||||
best_block_hash: G,
|
best_block_hash: G,
|
||||||
stream: F,
|
stream: F,
|
||||||
) where
|
) where
|
||||||
Block: BlockT + 'static,
|
Block: BlockT + 'static,
|
||||||
B: sc_client_api::backend::Backend<Block> + Send + Sync + 'static,
|
Client: HeaderBackend<Block> + 'static,
|
||||||
E: sc_client::CallExecutor<Block> + Send + Sync + 'static,
|
|
||||||
F: FnOnce() -> S,
|
F: FnOnce() -> S,
|
||||||
G: FnOnce() -> Block::Hash,
|
G: FnOnce() -> Block::Hash,
|
||||||
ERR: ::std::fmt::Debug,
|
ERR: ::std::fmt::Debug,
|
||||||
@@ -298,7 +294,7 @@ fn subscribe_headers<B, E, Block, RA, F, G, S, ERR>(
|
|||||||
{
|
{
|
||||||
subscriptions.add(subscriber, |sink| {
|
subscriptions.add(subscriber, |sink| {
|
||||||
// send current head right at the start.
|
// send current head right at the start.
|
||||||
let header = client.header(&BlockId::Hash(best_block_hash()))
|
let header = client.header(BlockId::Hash(best_block_hash()))
|
||||||
.map_err(client_err)
|
.map_err(client_err)
|
||||||
.and_then(|header| {
|
.and_then(|header| {
|
||||||
header.ok_or_else(|| "Best header missing.".to_owned().into())
|
header.ok_or_else(|| "Best header missing.".to_owned().into())
|
||||||
|
|||||||
@@ -27,26 +27,26 @@ use jsonrpc_pubsub::{typed::Subscriber, SubscriptionId};
|
|||||||
use rpc::{Result as RpcResult, futures::{Future, future::result}};
|
use rpc::{Result as RpcResult, futures::{Future, future::result}};
|
||||||
|
|
||||||
use sc_rpc_api::Subscriptions;
|
use sc_rpc_api::Subscriptions;
|
||||||
use sc_client::{Client, CallExecutor, light::{blockchain::RemoteBlockchain, fetcher::Fetcher}};
|
use sc_client::{light::{blockchain::RemoteBlockchain, fetcher::Fetcher}};
|
||||||
use sp_core::{Bytes, storage::{StorageKey, StorageData, StorageChangeSet}};
|
use sp_core::{Bytes, storage::{StorageKey, StorageData, StorageChangeSet}};
|
||||||
use sp_version::RuntimeVersion;
|
use sp_version::RuntimeVersion;
|
||||||
use sp_runtime::traits::Block as BlockT;
|
use sp_runtime::traits::Block as BlockT;
|
||||||
|
|
||||||
use sp_api::{Metadata, ProvideRuntimeApi};
|
use sp_api::{Metadata, ProvideRuntimeApi, CallApiAt};
|
||||||
|
|
||||||
use self::error::{Error, FutureResult};
|
use self::error::{Error, FutureResult};
|
||||||
|
|
||||||
pub use sc_rpc_api::state::*;
|
pub use sc_rpc_api::state::*;
|
||||||
|
use sc_client_api::{ExecutorProvider, StorageProvider, BlockchainEvents, Backend};
|
||||||
|
use sp_blockchain::{HeaderMetadata, HeaderBackend};
|
||||||
|
|
||||||
const STORAGE_KEYS_PAGED_MAX_COUNT: u32 = 1000;
|
const STORAGE_KEYS_PAGED_MAX_COUNT: u32 = 1000;
|
||||||
|
|
||||||
/// State backend API.
|
/// State backend API.
|
||||||
pub trait StateBackend<B, E, Block: BlockT, RA>: Send + Sync + 'static
|
pub trait StateBackend<Block: BlockT, Client>: Send + Sync + 'static
|
||||||
where
|
where
|
||||||
Block: BlockT + 'static,
|
Block: BlockT + 'static,
|
||||||
B: sc_client_api::backend::Backend<Block> + Send + Sync + 'static,
|
Client: Send + Sync + 'static,
|
||||||
E: sc_client::CallExecutor<Block> + Send + Sync + 'static,
|
|
||||||
RA: Send + Sync + 'static,
|
|
||||||
{
|
{
|
||||||
/// Call runtime method at given block.
|
/// Call runtime method at given block.
|
||||||
fn call(
|
fn call(
|
||||||
@@ -194,18 +194,18 @@ pub trait StateBackend<B, E, Block: BlockT, RA>: Send + Sync + 'static
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Create new state API that works on full node.
|
/// Create new state API that works on full node.
|
||||||
pub fn new_full<B, E, Block: BlockT, RA>(
|
pub fn new_full<BE, Block: BlockT, Client>(
|
||||||
client: Arc<Client<B, E, Block, RA>>,
|
client: Arc<Client>,
|
||||||
subscriptions: Subscriptions,
|
subscriptions: Subscriptions,
|
||||||
) -> State<B, E, Block, RA>
|
) -> State<Block, Client>
|
||||||
where
|
where
|
||||||
Block: BlockT + 'static,
|
Block: BlockT + 'static,
|
||||||
B: sc_client_api::backend::Backend<Block> + Send + Sync + 'static,
|
BE: Backend<Block> + 'static,
|
||||||
E: CallExecutor<Block> + Send + Sync + 'static + Clone,
|
Client: ExecutorProvider<Block> + StorageProvider<Block, BE> + HeaderBackend<Block>
|
||||||
RA: Send + Sync + 'static,
|
+ HeaderMetadata<Block, Error = sp_blockchain::Error> + BlockchainEvents<Block>
|
||||||
Client<B, E, Block, RA>: ProvideRuntimeApi<Block>,
|
+ CallApiAt<Block, Error = sp_blockchain::Error>
|
||||||
<Client<B, E, Block, RA> as ProvideRuntimeApi<Block>>::Api:
|
+ ProvideRuntimeApi<Block> + Send + Sync + 'static,
|
||||||
Metadata<Block, Error = sp_blockchain::Error>,
|
Client::Api: Metadata<Block, Error = sp_blockchain::Error>,
|
||||||
{
|
{
|
||||||
State {
|
State {
|
||||||
backend: Box::new(self::state_full::FullState::new(client, subscriptions)),
|
backend: Box::new(self::state_full::FullState::new(client, subscriptions)),
|
||||||
@@ -213,17 +213,19 @@ pub fn new_full<B, E, Block: BlockT, RA>(
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Create new state API that works on light node.
|
/// Create new state API that works on light node.
|
||||||
pub fn new_light<B, E, Block: BlockT, RA, F: Fetcher<Block>>(
|
pub fn new_light<BE, Block: BlockT, Client, F: Fetcher<Block>>(
|
||||||
client: Arc<Client<B, E, Block, RA>>,
|
client: Arc<Client>,
|
||||||
subscriptions: Subscriptions,
|
subscriptions: Subscriptions,
|
||||||
remote_blockchain: Arc<dyn RemoteBlockchain<Block>>,
|
remote_blockchain: Arc<dyn RemoteBlockchain<Block>>,
|
||||||
fetcher: Arc<F>,
|
fetcher: Arc<F>,
|
||||||
) -> State<B, E, Block, RA>
|
) -> State<Block, Client>
|
||||||
where
|
where
|
||||||
Block: BlockT + 'static,
|
Block: BlockT + 'static,
|
||||||
B: sc_client_api::backend::Backend<Block> + Send + Sync + 'static,
|
BE: Backend<Block> + 'static,
|
||||||
E: CallExecutor<Block> + Send + Sync + 'static + Clone,
|
Client: ExecutorProvider<Block> + StorageProvider<Block, BE>
|
||||||
RA: Send + Sync + 'static,
|
+ HeaderMetadata<Block, Error = sp_blockchain::Error>
|
||||||
|
+ ProvideRuntimeApi<Block> + HeaderBackend<Block> + BlockchainEvents<Block>
|
||||||
|
+ Send + Sync + 'static,
|
||||||
F: Send + Sync + 'static,
|
F: Send + Sync + 'static,
|
||||||
{
|
{
|
||||||
State {
|
State {
|
||||||
@@ -237,16 +239,14 @@ pub fn new_light<B, E, Block: BlockT, RA, F: Fetcher<Block>>(
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// State API with subscriptions support.
|
/// State API with subscriptions support.
|
||||||
pub struct State<B, E, Block, RA> {
|
pub struct State<Block, Client> {
|
||||||
backend: Box<dyn StateBackend<B, E, Block, RA>>,
|
backend: Box<dyn StateBackend<Block, Client>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<B, E, Block, RA> StateApi<Block::Hash> for State<B, E, Block, RA>
|
impl<Block, Client> StateApi<Block::Hash> for State<Block, Client>
|
||||||
where
|
where
|
||||||
Block: BlockT + 'static,
|
Block: BlockT + 'static,
|
||||||
B: sc_client_api::backend::Backend<Block> + Send + Sync + 'static,
|
Client: Send + Sync + 'static,
|
||||||
E: CallExecutor<Block> + Send + Sync + 'static + Clone,
|
|
||||||
RA: Send + Sync + 'static,
|
|
||||||
{
|
{
|
||||||
type Metadata = crate::metadata::Metadata;
|
type Metadata = crate::metadata::Metadata;
|
||||||
|
|
||||||
|
|||||||
@@ -26,12 +26,8 @@ use rpc::{Result as RpcResult, futures::{stream, Future, Sink, Stream, future::r
|
|||||||
|
|
||||||
use sc_rpc_api::Subscriptions;
|
use sc_rpc_api::Subscriptions;
|
||||||
use sc_client_api::backend::Backend;
|
use sc_client_api::backend::Backend;
|
||||||
use sp_blockchain::{
|
use sp_blockchain::{Result as ClientResult, Error as ClientError, HeaderMetadata, CachedHeaderMetadata, HeaderBackend};
|
||||||
Result as ClientResult, Error as ClientError, HeaderMetadata, CachedHeaderMetadata
|
use sc_client::BlockchainEvents;
|
||||||
};
|
|
||||||
use sc_client::{
|
|
||||||
Client, CallExecutor, BlockchainEvents
|
|
||||||
};
|
|
||||||
use sp_core::{
|
use sp_core::{
|
||||||
Bytes, storage::{well_known_keys, StorageKey, StorageData, StorageChangeSet, ChildInfo},
|
Bytes, storage::{well_known_keys, StorageKey, StorageData, StorageChangeSet, ChildInfo},
|
||||||
};
|
};
|
||||||
@@ -40,9 +36,11 @@ use sp_runtime::{
|
|||||||
generic::BlockId, traits::{Block as BlockT, NumberFor, SaturatedConversion},
|
generic::BlockId, traits::{Block as BlockT, NumberFor, SaturatedConversion},
|
||||||
};
|
};
|
||||||
|
|
||||||
use sp_api::{Metadata, ProvideRuntimeApi};
|
use sp_api::{Metadata, ProvideRuntimeApi, CallApiAt};
|
||||||
|
|
||||||
use super::{StateBackend, error::{FutureResult, Error, Result}, client_err, child_resolution_error};
|
use super::{StateBackend, error::{FutureResult, Error, Result}, client_err, child_resolution_error};
|
||||||
|
use std::marker::PhantomData;
|
||||||
|
use sc_client_api::{CallExecutor, StorageProvider, ExecutorProvider};
|
||||||
|
|
||||||
/// Ranges to query in state_queryStorage.
|
/// Ranges to query in state_queryStorage.
|
||||||
struct QueryStorageRange<Block: BlockT> {
|
struct QueryStorageRange<Block: BlockT> {
|
||||||
@@ -59,25 +57,27 @@ struct QueryStorageRange<Block: BlockT> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// State API backend for full nodes.
|
/// State API backend for full nodes.
|
||||||
pub struct FullState<B, E, Block: BlockT, RA> {
|
pub struct FullState<BE, Block: BlockT, Client> {
|
||||||
client: Arc<Client<B, E, Block, RA>>,
|
client: Arc<Client>,
|
||||||
subscriptions: Subscriptions,
|
subscriptions: Subscriptions,
|
||||||
|
_phantom: PhantomData<(BE, Block)>
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<B, E, Block: BlockT, RA> FullState<B, E, Block, RA>
|
impl<BE, Block: BlockT, Client> FullState<BE, Block, Client>
|
||||||
where
|
where
|
||||||
|
BE: Backend<Block>,
|
||||||
|
Client: StorageProvider<Block, BE> + HeaderBackend<Block>
|
||||||
|
+ HeaderMetadata<Block, Error = sp_blockchain::Error>,
|
||||||
Block: BlockT + 'static,
|
Block: BlockT + 'static,
|
||||||
B: Backend<Block> + Send + Sync + 'static,
|
|
||||||
E: CallExecutor<Block> + Send + Sync + 'static + Clone,
|
|
||||||
{
|
{
|
||||||
/// Create new state API backend for full nodes.
|
/// Create new state API backend for full nodes.
|
||||||
pub fn new(client: Arc<Client<B, E, Block, RA>>, subscriptions: Subscriptions) -> Self {
|
pub fn new(client: Arc<Client>, subscriptions: Subscriptions) -> Self {
|
||||||
Self { client, subscriptions }
|
Self { client, subscriptions, _phantom: PhantomData }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns given block hash or best block hash if None is passed.
|
/// Returns given block hash or best block hash if None is passed.
|
||||||
fn block_or_best(&self, hash: Option<Block::Hash>) -> ClientResult<Block::Hash> {
|
fn block_or_best(&self, hash: Option<Block::Hash>) -> ClientResult<Block::Hash> {
|
||||||
Ok(hash.unwrap_or_else(|| self.client.chain_info().best_hash))
|
Ok(hash.unwrap_or_else(|| self.client.info().best_hash))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Splits the `query_storage` block range into 'filtered' and 'unfiltered' subranges.
|
/// Splits the `query_storage` block range into 'filtered' and 'unfiltered' subranges.
|
||||||
@@ -212,14 +212,14 @@ impl<B, E, Block: BlockT, RA> FullState<B, E, Block, RA>
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<B, E, Block, RA> StateBackend<B, E, Block, RA> for FullState<B, E, Block, RA> where
|
impl<BE, Block, Client> StateBackend<Block, Client> for FullState<BE, Block, Client> where
|
||||||
Block: BlockT + 'static,
|
Block: BlockT + 'static,
|
||||||
B: Backend<Block> + Send + Sync + 'static,
|
BE: Backend<Block> + 'static,
|
||||||
E: CallExecutor<Block> + Send + Sync + 'static + Clone,
|
Client: ExecutorProvider<Block> + StorageProvider<Block, BE> + HeaderBackend<Block>
|
||||||
RA: Send + Sync + 'static,
|
+ HeaderMetadata<Block, Error = sp_blockchain::Error> + BlockchainEvents<Block>
|
||||||
Client<B, E, Block, RA>: ProvideRuntimeApi<Block>,
|
+ CallApiAt<Block, Error = sp_blockchain::Error> + ProvideRuntimeApi<Block>
|
||||||
<Client<B, E, Block, RA> as ProvideRuntimeApi<Block>>::Api:
|
+ Send + Sync + 'static,
|
||||||
Metadata<Block, Error = sp_blockchain::Error>,
|
Client::Api: Metadata<Block, Error = sp_blockchain::Error>,
|
||||||
{
|
{
|
||||||
fn call(
|
fn call(
|
||||||
&self,
|
&self,
|
||||||
@@ -424,7 +424,7 @@ impl<B, E, Block, RA> StateBackend<B, E, Block, RA> for FullState<B, E, Block, R
|
|||||||
|
|
||||||
let stream = stream
|
let stream = stream
|
||||||
.filter_map(move |_| {
|
.filter_map(move |_| {
|
||||||
let info = client.chain_info();
|
let info = client.info();
|
||||||
let version = client
|
let version = client
|
||||||
.runtime_version_at(&BlockId::hash(info.best_hash))
|
.runtime_version_at(&BlockId::hash(info.best_hash))
|
||||||
.map_err(client_err)
|
.map_err(client_err)
|
||||||
@@ -478,7 +478,7 @@ impl<B, E, Block, RA> StateBackend<B, E, Block, RA> for FullState<B, E, Block, R
|
|||||||
// initial values
|
// initial values
|
||||||
let initial = stream::iter_result(keys
|
let initial = stream::iter_result(keys
|
||||||
.map(|keys| {
|
.map(|keys| {
|
||||||
let block = self.client.chain_info().best_hash;
|
let block = self.client.info().best_hash;
|
||||||
let changes = keys
|
let changes = keys
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|key| self.storage(Some(block.clone()).into(), key.clone())
|
.map(|key| self.storage(Some(block.clone()).into(), key.clone())
|
||||||
|
|||||||
@@ -39,10 +39,9 @@ use rpc::{
|
|||||||
};
|
};
|
||||||
|
|
||||||
use sc_rpc_api::Subscriptions;
|
use sc_rpc_api::Subscriptions;
|
||||||
use sc_client_api::backend::Backend;
|
use sp_blockchain::{Error as ClientError, HeaderBackend};
|
||||||
use sp_blockchain::Error as ClientError;
|
|
||||||
use sc_client::{
|
use sc_client::{
|
||||||
BlockchainEvents, Client, CallExecutor,
|
BlockchainEvents,
|
||||||
light::{
|
light::{
|
||||||
blockchain::{future_header, RemoteBlockchain},
|
blockchain::{future_header, RemoteBlockchain},
|
||||||
fetcher::{Fetcher, RemoteCallRequest, RemoteReadRequest, RemoteReadChildRequest},
|
fetcher::{Fetcher, RemoteCallRequest, RemoteReadRequest, RemoteReadChildRequest},
|
||||||
@@ -60,8 +59,8 @@ use super::{StateBackend, error::{FutureResult, Error}, client_err};
|
|||||||
type StorageMap = HashMap<StorageKey, Option<StorageData>>;
|
type StorageMap = HashMap<StorageKey, Option<StorageData>>;
|
||||||
|
|
||||||
/// State API backend for light nodes.
|
/// State API backend for light nodes.
|
||||||
pub struct LightState<Block: BlockT, F: Fetcher<Block>, B, E, RA> {
|
pub struct LightState<Block: BlockT, F: Fetcher<Block>, Client> {
|
||||||
client: Arc<Client<B, E, Block, RA>>,
|
client: Arc<Client>,
|
||||||
subscriptions: Subscriptions,
|
subscriptions: Subscriptions,
|
||||||
version_subscriptions: SimpleSubscriptions<Block::Hash, RuntimeVersion>,
|
version_subscriptions: SimpleSubscriptions<Block::Hash, RuntimeVersion>,
|
||||||
storage_subscriptions: Arc<Mutex<StorageSubscriptions<Block>>>,
|
storage_subscriptions: Arc<Mutex<StorageSubscriptions<Block>>>,
|
||||||
@@ -134,16 +133,14 @@ impl<Hash, V> SharedRequests<Hash, V> for SimpleSubscriptions<Hash, V> where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<Block: BlockT, F: Fetcher<Block> + 'static, B, E, RA> LightState<Block, F, B, E, RA>
|
impl<Block: BlockT, F: Fetcher<Block> + 'static, Client> LightState<Block, F, Client>
|
||||||
where
|
where
|
||||||
Block: BlockT,
|
Block: BlockT,
|
||||||
B: Backend<Block> + Send + Sync + 'static,
|
Client: HeaderBackend<Block> + Send + Sync + 'static,
|
||||||
E: CallExecutor<Block> + Send + Sync + 'static + Clone,
|
|
||||||
RA: Send + Sync + 'static,
|
|
||||||
{
|
{
|
||||||
/// Create new state API backend for light nodes.
|
/// Create new state API backend for light nodes.
|
||||||
pub fn new(
|
pub fn new(
|
||||||
client: Arc<Client<B, E, Block, RA>>,
|
client: Arc<Client>,
|
||||||
subscriptions: Subscriptions,
|
subscriptions: Subscriptions,
|
||||||
remote_blockchain: Arc<dyn RemoteBlockchain<Block>>,
|
remote_blockchain: Arc<dyn RemoteBlockchain<Block>>,
|
||||||
fetcher: Arc<F>,
|
fetcher: Arc<F>,
|
||||||
@@ -164,16 +161,14 @@ impl<Block: BlockT, F: Fetcher<Block> + 'static, B, E, RA> LightState<Block, F,
|
|||||||
|
|
||||||
/// Returns given block hash or best block hash if None is passed.
|
/// Returns given block hash or best block hash if None is passed.
|
||||||
fn block_or_best(&self, hash: Option<Block::Hash>) -> Block::Hash {
|
fn block_or_best(&self, hash: Option<Block::Hash>) -> Block::Hash {
|
||||||
hash.unwrap_or_else(|| self.client.chain_info().best_hash)
|
hash.unwrap_or_else(|| self.client.info().best_hash)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<Block, F, B, E, RA> StateBackend<B, E, Block, RA> for LightState<Block, F, B, E, RA>
|
impl<Block, F, Client> StateBackend<Block, Client> for LightState<Block, F, Client>
|
||||||
where
|
where
|
||||||
Block: BlockT,
|
Block: BlockT,
|
||||||
B: Backend<Block> + Send + Sync + 'static,
|
Client: BlockchainEvents<Block> + HeaderBackend<Block> + Send + Sync + 'static,
|
||||||
E: CallExecutor<Block> + Send + Sync + 'static + Clone,
|
|
||||||
RA: Send + Sync + 'static,
|
|
||||||
F: Fetcher<Block> + 'static
|
F: Fetcher<Block> + 'static
|
||||||
{
|
{
|
||||||
fn call(
|
fn call(
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ use sc_client_api::{
|
|||||||
BlockchainEvents,
|
BlockchainEvents,
|
||||||
backend::RemoteBackend, light::RemoteBlockchain,
|
backend::RemoteBackend, light::RemoteBlockchain,
|
||||||
execution_extensions::ExtensionsFactory,
|
execution_extensions::ExtensionsFactory,
|
||||||
|
ExecutorProvider, CallExecutor
|
||||||
};
|
};
|
||||||
use sc_client::Client;
|
use sc_client::Client;
|
||||||
use sc_chain_spec::{RuntimeGenesis, Extension};
|
use sc_chain_spec::{RuntimeGenesis, Extension};
|
||||||
@@ -799,7 +800,9 @@ ServiceBuilder<
|
|||||||
TBackend::OffchainStorage,
|
TBackend::OffchainStorage,
|
||||||
TBl
|
TBl
|
||||||
>,
|
>,
|
||||||
>, Error> {
|
>, Error>
|
||||||
|
where TExec: CallExecutor<TBl, Backend = TBackend>,
|
||||||
|
{
|
||||||
let ServiceBuilder {
|
let ServiceBuilder {
|
||||||
marker: _,
|
marker: _,
|
||||||
mut config,
|
mut config,
|
||||||
|
|||||||
@@ -35,6 +35,7 @@ use sp_consensus::{
|
|||||||
use sc_executor::{NativeExecutor, NativeExecutionDispatch};
|
use sc_executor::{NativeExecutor, NativeExecutionDispatch};
|
||||||
|
|
||||||
use std::{io::{Read, Write, Seek}, pin::Pin};
|
use std::{io::{Read, Write, Seek}, pin::Pin};
|
||||||
|
use sc_client_api::BlockBody;
|
||||||
|
|
||||||
/// Build a chain spec json
|
/// Build a chain spec json
|
||||||
pub fn build_spec<G, E>(spec: ChainSpec<G, E>, raw: bool) -> error::Result<String> where
|
pub fn build_spec<G, E>(spec: ChainSpec<G, E>, raw: bool) -> error::Result<String> where
|
||||||
|
|||||||
+268
-316
@@ -66,7 +66,8 @@ pub use sc_client_api::{
|
|||||||
backend::{
|
backend::{
|
||||||
self, BlockImportOperation, PrunableStateChangesTrieStorage,
|
self, BlockImportOperation, PrunableStateChangesTrieStorage,
|
||||||
ClientImportOperation, Finalizer, ImportSummary, NewBlockState,
|
ClientImportOperation, Finalizer, ImportSummary, NewBlockState,
|
||||||
LockImportRun, changes_tries_state_at_block,
|
changes_tries_state_at_block, StorageProvider,
|
||||||
|
LockImportRun,
|
||||||
},
|
},
|
||||||
client::{
|
client::{
|
||||||
ImportNotifications, FinalityNotification, FinalityNotifications, BlockImportNotification,
|
ImportNotifications, FinalityNotification, FinalityNotifications, BlockImportNotification,
|
||||||
@@ -75,7 +76,7 @@ pub use sc_client_api::{
|
|||||||
},
|
},
|
||||||
execution_extensions::{ExecutionExtensions, ExecutionStrategies},
|
execution_extensions::{ExecutionExtensions, ExecutionStrategies},
|
||||||
notifications::{StorageNotifications, StorageEventStream},
|
notifications::{StorageNotifications, StorageEventStream},
|
||||||
CallExecutor,
|
CallExecutor, ExecutorProvider, ProofProvider,
|
||||||
};
|
};
|
||||||
use sp_blockchain::Error;
|
use sp_blockchain::Error;
|
||||||
use prometheus_endpoint::Registry;
|
use prometheus_endpoint::Registry;
|
||||||
@@ -85,6 +86,7 @@ use crate::{
|
|||||||
light::{call_executor::prove_execution, fetcher::ChangesProof},
|
light::{call_executor::prove_execution, fetcher::ChangesProof},
|
||||||
in_mem, genesis, cht, block_rules::{BlockRules, LookupResult as BlockLookupResult},
|
in_mem, genesis, cht, block_rules::{BlockRules, LookupResult as BlockLookupResult},
|
||||||
};
|
};
|
||||||
|
use crate::client::backend::KeyIterator;
|
||||||
|
|
||||||
/// Substrate Client
|
/// Substrate Client
|
||||||
pub struct Client<B, E, Block, RA> where Block: BlockT {
|
pub struct Client<B, E, Block, RA> where Block: BlockT {
|
||||||
@@ -100,46 +102,6 @@ pub struct Client<B, E, Block, RA> where Block: BlockT {
|
|||||||
_phantom: PhantomData<RA>,
|
_phantom: PhantomData<RA>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// An `Iterator` that iterates keys in a given block under a prefix.
|
|
||||||
pub struct KeyIterator<'a, State, Block> {
|
|
||||||
state: State,
|
|
||||||
prefix: Option<&'a StorageKey>,
|
|
||||||
current_key: Vec<u8>,
|
|
||||||
_phantom: PhantomData<Block>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl <'a, State, Block> KeyIterator<'a, State, Block> {
|
|
||||||
fn new(state: State, prefix: Option<&'a StorageKey>, current_key: Vec<u8>) -> Self {
|
|
||||||
Self {
|
|
||||||
state,
|
|
||||||
prefix,
|
|
||||||
current_key,
|
|
||||||
_phantom: PhantomData,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a, State, Block> Iterator for KeyIterator<'a, State, Block> where
|
|
||||||
Block: BlockT,
|
|
||||||
State: StateBackend<HashFor<Block>>,
|
|
||||||
{
|
|
||||||
type Item = StorageKey;
|
|
||||||
|
|
||||||
fn next(&mut self) -> Option<Self::Item> {
|
|
||||||
let next_key = self.state
|
|
||||||
.next_storage_key(&self.current_key)
|
|
||||||
.ok()
|
|
||||||
.flatten()?;
|
|
||||||
if let Some(prefix) = self.prefix {
|
|
||||||
if !next_key.starts_with(&prefix.0[..]) {
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
self.current_key = next_key.clone();
|
|
||||||
Some(StorageKey(next_key))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// used in importing a block, where additional changes are made after the runtime
|
// used in importing a block, where additional changes are made after the runtime
|
||||||
// executed.
|
// executed.
|
||||||
enum PrePostHeader<H> {
|
enum PrePostHeader<H> {
|
||||||
@@ -324,119 +286,14 @@ impl<B, E, Block, RA> Client<B, E, Block, RA> where
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get a reference to the execution extensions.
|
|
||||||
pub fn execution_extensions(&self) -> &ExecutionExtensions<Block> {
|
|
||||||
&self.execution_extensions
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Get a reference to the state at a given block.
|
/// Get a reference to the state at a given block.
|
||||||
pub fn state_at(&self, block: &BlockId<Block>) -> sp_blockchain::Result<B::State> {
|
pub fn state_at(&self, block: &BlockId<Block>) -> sp_blockchain::Result<B::State> {
|
||||||
self.backend.state_at(*block)
|
self.backend.state_at(*block)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Given a `BlockId` and a key prefix, return the matching storage keys in that block.
|
|
||||||
pub fn storage_keys(&self, id: &BlockId<Block>, key_prefix: &StorageKey) -> sp_blockchain::Result<Vec<StorageKey>> {
|
|
||||||
let keys = self.state_at(id)?.keys(&key_prefix.0).into_iter().map(StorageKey).collect();
|
|
||||||
Ok(keys)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Given a `BlockId` and a key prefix, return the matching child storage keys and values in that block.
|
|
||||||
pub fn storage_pairs(&self, id: &BlockId<Block>, key_prefix: &StorageKey)
|
|
||||||
-> sp_blockchain::Result<Vec<(StorageKey, StorageData)>>
|
|
||||||
{
|
|
||||||
let state = self.state_at(id)?;
|
|
||||||
let keys = state
|
|
||||||
.keys(&key_prefix.0)
|
|
||||||
.into_iter()
|
|
||||||
.map(|k| {
|
|
||||||
let d = state.storage(&k).ok().flatten().unwrap_or_default();
|
|
||||||
(StorageKey(k), StorageData(d))
|
|
||||||
})
|
|
||||||
.collect();
|
|
||||||
Ok(keys)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Given a `BlockId` and a key prefix, return a `KeyIterator` iterates matching storage keys in that block.
|
|
||||||
pub fn storage_keys_iter<'a>(
|
|
||||||
&self,
|
|
||||||
id: &BlockId<Block>,
|
|
||||||
prefix: Option<&'a StorageKey>,
|
|
||||||
start_key: Option<&StorageKey>
|
|
||||||
) -> sp_blockchain::Result<KeyIterator<'a, B::State, Block>> {
|
|
||||||
let state = self.state_at(id)?;
|
|
||||||
let start_key = start_key
|
|
||||||
.or(prefix)
|
|
||||||
.map(|key| key.0.clone())
|
|
||||||
.unwrap_or_else(Vec::new);
|
|
||||||
Ok(KeyIterator::new(state, prefix, start_key))
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Given a `BlockId` and a key, return the value under the key in that block.
|
|
||||||
pub fn storage(&self, id: &BlockId<Block>, key: &StorageKey)
|
|
||||||
-> sp_blockchain::Result<Option<StorageData>>
|
|
||||||
{
|
|
||||||
Ok(self.state_at(id)?
|
|
||||||
.storage(&key.0).map_err(|e| sp_blockchain::Error::from_state(Box::new(e)))?
|
|
||||||
.map(StorageData)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Given a `BlockId` and a key, return the value under the hash in that block.
|
|
||||||
pub fn storage_hash(&self, id: &BlockId<Block>, key: &StorageKey)
|
|
||||||
-> sp_blockchain::Result<Option<Block::Hash>>
|
|
||||||
{
|
|
||||||
Ok(self.state_at(id)?
|
|
||||||
.storage_hash(&key.0).map_err(|e| sp_blockchain::Error::from_state(Box::new(e)))?
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Given a `BlockId`, a key prefix, and a child storage key, return the matching child storage keys.
|
|
||||||
pub fn child_storage_keys(
|
|
||||||
&self,
|
|
||||||
id: &BlockId<Block>,
|
|
||||||
child_storage_key: &StorageKey,
|
|
||||||
child_info: ChildInfo,
|
|
||||||
key_prefix: &StorageKey
|
|
||||||
) -> sp_blockchain::Result<Vec<StorageKey>> {
|
|
||||||
let keys = self.state_at(id)?
|
|
||||||
.child_keys(&child_storage_key.0, child_info, &key_prefix.0)
|
|
||||||
.into_iter()
|
|
||||||
.map(StorageKey)
|
|
||||||
.collect();
|
|
||||||
Ok(keys)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Given a `BlockId`, a key and a child storage key, return the value under the key in that block.
|
|
||||||
pub fn child_storage(
|
|
||||||
&self,
|
|
||||||
id: &BlockId<Block>,
|
|
||||||
storage_key: &StorageKey,
|
|
||||||
child_info: ChildInfo,
|
|
||||||
key: &StorageKey
|
|
||||||
) -> sp_blockchain::Result<Option<StorageData>> {
|
|
||||||
Ok(self.state_at(id)?
|
|
||||||
.child_storage(&storage_key.0, child_info, &key.0)
|
|
||||||
.map_err(|e| sp_blockchain::Error::from_state(Box::new(e)))?
|
|
||||||
.map(StorageData))
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Given a `BlockId`, a key and a child storage key, return the hash under the key in that block.
|
|
||||||
pub fn child_storage_hash(
|
|
||||||
&self,
|
|
||||||
id: &BlockId<Block>,
|
|
||||||
storage_key: &StorageKey,
|
|
||||||
child_info: ChildInfo,
|
|
||||||
key: &StorageKey
|
|
||||||
) -> sp_blockchain::Result<Option<Block::Hash>> {
|
|
||||||
Ok(self.state_at(id)?
|
|
||||||
.child_storage_hash(&storage_key.0, child_info, &key.0)
|
|
||||||
.map_err(|e| sp_blockchain::Error::from_state(Box::new(e)))?
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Get the code at a given block.
|
/// Get the code at a given block.
|
||||||
pub fn code_at(&self, id: &BlockId<Block>) -> sp_blockchain::Result<Vec<u8>> {
|
pub fn code_at(&self, id: &BlockId<Block>) -> sp_blockchain::Result<Vec<u8>> {
|
||||||
Ok(self.storage(id, &StorageKey(well_known_keys::CODE.to_vec()))?
|
Ok(StorageProvider::storage(self, id, &StorageKey(well_known_keys::CODE.to_vec()))?
|
||||||
.expect("None is returned if there's no value stored for the given key;\
|
.expect("None is returned if there's no value stored for the given key;\
|
||||||
':code' key is always defined; qed").0)
|
':code' key is always defined; qed").0)
|
||||||
}
|
}
|
||||||
@@ -446,57 +303,6 @@ impl<B, E, Block, RA> Client<B, E, Block, RA> where
|
|||||||
self.executor.runtime_version(id)
|
self.executor.runtime_version(id)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get call executor reference.
|
|
||||||
pub fn executor(&self) -> &E {
|
|
||||||
&self.executor
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Reads storage value at a given block + key, returning read proof.
|
|
||||||
pub fn read_proof<I>(&self, id: &BlockId<Block>, keys: I) -> sp_blockchain::Result<StorageProof> where
|
|
||||||
I: IntoIterator,
|
|
||||||
I::Item: AsRef<[u8]>,
|
|
||||||
{
|
|
||||||
self.state_at(id)
|
|
||||||
.and_then(|state| prove_read(state, keys)
|
|
||||||
.map_err(Into::into))
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Reads child storage value at a given block + storage_key + key, returning
|
|
||||||
/// read proof.
|
|
||||||
pub fn read_child_proof<I>(
|
|
||||||
&self,
|
|
||||||
id: &BlockId<Block>,
|
|
||||||
storage_key: &[u8],
|
|
||||||
child_info: ChildInfo,
|
|
||||||
keys: I,
|
|
||||||
) -> sp_blockchain::Result<StorageProof> where
|
|
||||||
I: IntoIterator,
|
|
||||||
I::Item: AsRef<[u8]>,
|
|
||||||
{
|
|
||||||
self.state_at(id)
|
|
||||||
.and_then(|state| prove_child_read(state, storage_key, child_info, keys)
|
|
||||||
.map_err(Into::into))
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Execute a call to a contract on top of state in a block of given hash
|
|
||||||
/// AND returning execution proof.
|
|
||||||
///
|
|
||||||
/// No changes are made.
|
|
||||||
pub fn execution_proof(&self,
|
|
||||||
id: &BlockId<Block>,
|
|
||||||
method: &str,
|
|
||||||
call_data: &[u8]
|
|
||||||
) -> sp_blockchain::Result<(Vec<u8>, StorageProof)> {
|
|
||||||
let state = self.state_at(id)?;
|
|
||||||
let header = self.prepare_environment_block(id)?;
|
|
||||||
prove_execution(state, header, &self.executor, method, call_data)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Reads given header and generates CHT-based header proof.
|
|
||||||
pub fn header_proof(&self, id: &BlockId<Block>) -> sp_blockchain::Result<(Block::Header, StorageProof)> {
|
|
||||||
self.header_proof_with_cht_size(id, cht::size())
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Get block hash by number.
|
/// Get block hash by number.
|
||||||
pub fn block_hash(&self,
|
pub fn block_hash(&self,
|
||||||
block_number: <<Block as BlockT>::Header as HeaderT>::Number
|
block_number: <<Block as BlockT>::Header as HeaderT>::Number
|
||||||
@@ -531,112 +337,6 @@ impl<B, E, Block, RA> Client<B, E, Block, RA> where
|
|||||||
Ok((header, proof))
|
Ok((header, proof))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get longest range within [first; last] that is possible to use in `key_changes`
|
|
||||||
/// and `key_changes_proof` calls.
|
|
||||||
/// Range could be shortened from the beginning if some changes tries have been pruned.
|
|
||||||
/// Returns Ok(None) if changes tries are not supported.
|
|
||||||
pub fn max_key_changes_range(
|
|
||||||
&self,
|
|
||||||
first: NumberFor<Block>,
|
|
||||||
last: BlockId<Block>,
|
|
||||||
) -> sp_blockchain::Result<Option<(NumberFor<Block>, BlockId<Block>)>> {
|
|
||||||
let last_number = self.backend.blockchain().expect_block_number_from_id(&last)?;
|
|
||||||
let last_hash = self.backend.blockchain().expect_block_hash_from_id(&last)?;
|
|
||||||
if first > last_number {
|
|
||||||
return Err(sp_blockchain::Error::ChangesTrieAccessFailed("Invalid changes trie range".into()));
|
|
||||||
}
|
|
||||||
|
|
||||||
let (storage, configs) = match self.require_changes_trie(first, last_hash, false).ok() {
|
|
||||||
Some((storage, configs)) => (storage, configs),
|
|
||||||
None => return Ok(None),
|
|
||||||
};
|
|
||||||
|
|
||||||
let first_available_changes_trie = configs.last().map(|config| config.0);
|
|
||||||
match first_available_changes_trie {
|
|
||||||
Some(first_available_changes_trie) => {
|
|
||||||
let oldest_unpruned = storage.oldest_pruned_digest_range_end();
|
|
||||||
let first = std::cmp::max(first_available_changes_trie, oldest_unpruned);
|
|
||||||
Ok(Some((first, last)))
|
|
||||||
},
|
|
||||||
None => Ok(None)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Get pairs of (block, extrinsic) where key has been changed at given blocks range.
|
|
||||||
/// Works only for runtimes that are supporting changes tries.
|
|
||||||
///
|
|
||||||
/// Changes are returned in descending order (i.e. last block comes first).
|
|
||||||
pub fn key_changes(
|
|
||||||
&self,
|
|
||||||
first: NumberFor<Block>,
|
|
||||||
last: BlockId<Block>,
|
|
||||||
storage_key: Option<&StorageKey>,
|
|
||||||
key: &StorageKey
|
|
||||||
) -> sp_blockchain::Result<Vec<(NumberFor<Block>, u32)>> {
|
|
||||||
let last_number = self.backend.blockchain().expect_block_number_from_id(&last)?;
|
|
||||||
let last_hash = self.backend.blockchain().expect_block_hash_from_id(&last)?;
|
|
||||||
let (storage, configs) = self.require_changes_trie(first, last_hash, true)?;
|
|
||||||
|
|
||||||
let mut result = Vec::new();
|
|
||||||
let best_number = self.backend.blockchain().info().best_number;
|
|
||||||
for (config_zero, config_end, config) in configs {
|
|
||||||
let range_first = ::std::cmp::max(first, config_zero + One::one());
|
|
||||||
let range_anchor = match config_end {
|
|
||||||
Some((config_end_number, config_end_hash)) => if last_number > config_end_number {
|
|
||||||
ChangesTrieAnchorBlockId { hash: config_end_hash, number: config_end_number }
|
|
||||||
} else {
|
|
||||||
ChangesTrieAnchorBlockId { hash: convert_hash(&last_hash), number: last_number }
|
|
||||||
},
|
|
||||||
None => ChangesTrieAnchorBlockId { hash: convert_hash(&last_hash), number: last_number },
|
|
||||||
};
|
|
||||||
|
|
||||||
let config_range = ChangesTrieConfigurationRange {
|
|
||||||
config: &config,
|
|
||||||
zero: config_zero.clone(),
|
|
||||||
end: config_end.map(|(config_end_number, _)| config_end_number),
|
|
||||||
};
|
|
||||||
let result_range: Vec<(NumberFor<Block>, u32)> = key_changes::<HashFor<Block>, _>(
|
|
||||||
config_range,
|
|
||||||
storage.storage(),
|
|
||||||
range_first,
|
|
||||||
&range_anchor,
|
|
||||||
best_number,
|
|
||||||
storage_key.as_ref().map(|x| &x.0[..]),
|
|
||||||
&key.0)
|
|
||||||
.and_then(|r| r.map(|r| r.map(|(block, tx)| (block, tx))).collect::<Result<_, _>>())
|
|
||||||
.map_err(|err| sp_blockchain::Error::ChangesTrieAccessFailed(err))?;
|
|
||||||
result.extend(result_range);
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(result)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Get proof for computation of (block, extrinsic) pairs where key has been changed at given blocks range.
|
|
||||||
/// `min` is the hash of the first block, which changes trie root is known to the requester - when we're using
|
|
||||||
/// changes tries from ascendants of this block, we should provide proofs for changes tries roots
|
|
||||||
/// `max` is the hash of the last block known to the requester - we can't use changes tries from descendants
|
|
||||||
/// of this block.
|
|
||||||
/// Works only for runtimes that are supporting changes tries.
|
|
||||||
pub fn key_changes_proof(
|
|
||||||
&self,
|
|
||||||
first: Block::Hash,
|
|
||||||
last: Block::Hash,
|
|
||||||
min: Block::Hash,
|
|
||||||
max: Block::Hash,
|
|
||||||
storage_key: Option<&StorageKey>,
|
|
||||||
key: &StorageKey,
|
|
||||||
) -> sp_blockchain::Result<ChangesProof<Block::Header>> {
|
|
||||||
self.key_changes_proof_with_cht_size(
|
|
||||||
first,
|
|
||||||
last,
|
|
||||||
min,
|
|
||||||
max,
|
|
||||||
storage_key,
|
|
||||||
key,
|
|
||||||
cht::size(),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Does the same work as `key_changes_proof`, but assumes that CHTs are of passed size.
|
/// Does the same work as `key_changes_proof`, but assumes that CHTs are of passed size.
|
||||||
pub fn key_changes_proof_with_cht_size(
|
pub fn key_changes_proof_with_cht_size(
|
||||||
&self,
|
&self,
|
||||||
@@ -1344,17 +1044,6 @@ impl<B, E, Block, RA> Client<B, E, Block, RA> where
|
|||||||
self.backend.blockchain().justification(*id)
|
self.backend.blockchain().justification(*id)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get full block by id.
|
|
||||||
pub fn block(&self, id: &BlockId<Block>)
|
|
||||||
-> sp_blockchain::Result<Option<SignedBlock<Block>>>
|
|
||||||
{
|
|
||||||
Ok(match (self.header(id)?, self.body(id)?, self.justification(id)?) {
|
|
||||||
(Some(header), Some(extrinsics), justification) =>
|
|
||||||
Some(SignedBlock { block: Block::new(header, extrinsics), justification }),
|
|
||||||
_ => None,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Gets the uncles of the block with `target_hash` going back `max_generation` ancestors.
|
/// Gets the uncles of the block with `target_hash` going back `max_generation` ancestors.
|
||||||
pub fn uncles(&self, target_hash: Block::Hash, max_generation: NumberFor<Block>) -> sp_blockchain::Result<Vec<Block::Hash>> {
|
pub fn uncles(&self, target_hash: Block::Hash, max_generation: NumberFor<Block>) -> sp_blockchain::Result<Vec<Block::Hash>> {
|
||||||
let load_header = |id: Block::Hash| -> sp_blockchain::Result<Block::Header> {
|
let load_header = |id: Block::Hash| -> sp_blockchain::Result<Block::Header> {
|
||||||
@@ -1399,6 +1088,70 @@ impl<B, E, Block, RA> Client<B, E, Block, RA> where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<B, E, Block, RA> ProofProvider<Block> for Client<B, E, Block, RA> where
|
||||||
|
B: backend::Backend<Block>,
|
||||||
|
E: CallExecutor<Block>,
|
||||||
|
Block: BlockT,
|
||||||
|
{
|
||||||
|
fn read_proof(
|
||||||
|
&self,
|
||||||
|
id: &BlockId<Block>,
|
||||||
|
keys: &mut dyn Iterator<Item=&[u8]>,
|
||||||
|
) -> sp_blockchain::Result<StorageProof> {
|
||||||
|
self.state_at(id)
|
||||||
|
.and_then(|state| prove_read(state, keys)
|
||||||
|
.map_err(Into::into))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn read_child_proof(
|
||||||
|
&self,
|
||||||
|
id: &BlockId<Block>,
|
||||||
|
storage_key: &[u8],
|
||||||
|
child_info: ChildInfo,
|
||||||
|
keys: &mut dyn Iterator<Item=&[u8]>,
|
||||||
|
) -> sp_blockchain::Result<StorageProof> {
|
||||||
|
self.state_at(id)
|
||||||
|
.and_then(|state| prove_child_read(state, storage_key, child_info, keys)
|
||||||
|
.map_err(Into::into))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn execution_proof(
|
||||||
|
&self,
|
||||||
|
id: &BlockId<Block>,
|
||||||
|
method: &str,
|
||||||
|
call_data: &[u8]
|
||||||
|
) -> sp_blockchain::Result<(Vec<u8>, StorageProof)> {
|
||||||
|
let state = self.state_at(id)?;
|
||||||
|
let header = self.prepare_environment_block(id)?;
|
||||||
|
prove_execution(state, header, &self.executor, method, call_data)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn header_proof(&self, id: &BlockId<Block>) -> sp_blockchain::Result<(Block::Header, StorageProof)> {
|
||||||
|
self.header_proof_with_cht_size(id, cht::size())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn key_changes_proof(
|
||||||
|
&self,
|
||||||
|
first: Block::Hash,
|
||||||
|
last: Block::Hash,
|
||||||
|
min: Block::Hash,
|
||||||
|
max: Block::Hash,
|
||||||
|
storage_key: Option<&StorageKey>,
|
||||||
|
key: &StorageKey,
|
||||||
|
) -> sp_blockchain::Result<ChangesProof<Block::Header>> {
|
||||||
|
self.key_changes_proof_with_cht_size(
|
||||||
|
first,
|
||||||
|
last,
|
||||||
|
min,
|
||||||
|
max,
|
||||||
|
storage_key,
|
||||||
|
key,
|
||||||
|
cht::size(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
impl<B, E, Block, RA> BlockBuilderProvider<B, Block, Self> for Client<B, E, Block, RA>
|
impl<B, E, Block, RA> BlockBuilderProvider<B, Block, Self> for Client<B, E, Block, RA>
|
||||||
where
|
where
|
||||||
B: backend::Backend<Block> + Send + Sync + 'static,
|
B: backend::Backend<Block> + Send + Sync + 'static,
|
||||||
@@ -1425,6 +1178,196 @@ impl<B, E, Block, RA> BlockBuilderProvider<B, Block, Self> for Client<B, E, Bloc
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<B, E, Block, RA> ExecutorProvider<Block> for Client<B, E, Block, RA> where
|
||||||
|
B: backend::Backend<Block>,
|
||||||
|
E: CallExecutor<Block>,
|
||||||
|
Block: BlockT,
|
||||||
|
{
|
||||||
|
type Executor = E;
|
||||||
|
|
||||||
|
fn executor(&self) -> &Self::Executor {
|
||||||
|
&self.executor
|
||||||
|
}
|
||||||
|
|
||||||
|
fn execution_extensions(&self) -> &ExecutionExtensions<Block> {
|
||||||
|
&self.execution_extensions
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<B, E, Block, RA> StorageProvider<Block, B> for Client<B, E, Block, RA> where
|
||||||
|
B: backend::Backend<Block>,
|
||||||
|
E: CallExecutor<Block>,
|
||||||
|
Block: BlockT,
|
||||||
|
{
|
||||||
|
fn storage_keys(&self, id: &BlockId<Block>, key_prefix: &StorageKey) -> sp_blockchain::Result<Vec<StorageKey>> {
|
||||||
|
let keys = self.state_at(id)?.keys(&key_prefix.0).into_iter().map(StorageKey).collect();
|
||||||
|
Ok(keys)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn storage_pairs(&self, id: &BlockId<Block>, key_prefix: &StorageKey)
|
||||||
|
-> sp_blockchain::Result<Vec<(StorageKey, StorageData)>>
|
||||||
|
{
|
||||||
|
let state = self.state_at(id)?;
|
||||||
|
let keys = state
|
||||||
|
.keys(&key_prefix.0)
|
||||||
|
.into_iter()
|
||||||
|
.map(|k| {
|
||||||
|
let d = state.storage(&k).ok().flatten().unwrap_or_default();
|
||||||
|
(StorageKey(k), StorageData(d))
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
Ok(keys)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fn storage_keys_iter<'a>(
|
||||||
|
&self,
|
||||||
|
id: &BlockId<Block>,
|
||||||
|
prefix: Option<&'a StorageKey>,
|
||||||
|
start_key: Option<&StorageKey>
|
||||||
|
) -> sp_blockchain::Result<KeyIterator<'a, B::State, Block>> {
|
||||||
|
let state = self.state_at(id)?;
|
||||||
|
let start_key = start_key
|
||||||
|
.or(prefix)
|
||||||
|
.map(|key| key.0.clone())
|
||||||
|
.unwrap_or_else(Vec::new);
|
||||||
|
Ok(KeyIterator::new(state, prefix, start_key))
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fn storage(&self, id: &BlockId<Block>, key: &StorageKey) -> sp_blockchain::Result<Option<StorageData>>
|
||||||
|
{
|
||||||
|
Ok(self.state_at(id)?
|
||||||
|
.storage(&key.0).map_err(|e| sp_blockchain::Error::from_state(Box::new(e)))?
|
||||||
|
.map(StorageData)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fn storage_hash(&self, id: &BlockId<Block>, key: &StorageKey) -> sp_blockchain::Result<Option<Block::Hash>>
|
||||||
|
{
|
||||||
|
Ok(self.state_at(id)?
|
||||||
|
.storage_hash(&key.0).map_err(|e| sp_blockchain::Error::from_state(Box::new(e)))?
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fn child_storage_keys(
|
||||||
|
&self,
|
||||||
|
id: &BlockId<Block>,
|
||||||
|
child_storage_key: &StorageKey,
|
||||||
|
child_info: ChildInfo,
|
||||||
|
key_prefix: &StorageKey
|
||||||
|
) -> sp_blockchain::Result<Vec<StorageKey>> {
|
||||||
|
let keys = self.state_at(id)?
|
||||||
|
.child_keys(&child_storage_key.0, child_info, &key_prefix.0)
|
||||||
|
.into_iter()
|
||||||
|
.map(StorageKey)
|
||||||
|
.collect();
|
||||||
|
Ok(keys)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fn child_storage(
|
||||||
|
&self,
|
||||||
|
id: &BlockId<Block>,
|
||||||
|
storage_key: &StorageKey,
|
||||||
|
child_info: ChildInfo,
|
||||||
|
key: &StorageKey
|
||||||
|
) -> sp_blockchain::Result<Option<StorageData>> {
|
||||||
|
Ok(self.state_at(id)?
|
||||||
|
.child_storage(&storage_key.0, child_info, &key.0)
|
||||||
|
.map_err(|e| sp_blockchain::Error::from_state(Box::new(e)))?
|
||||||
|
.map(StorageData))
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fn child_storage_hash(
|
||||||
|
&self,
|
||||||
|
id: &BlockId<Block>,
|
||||||
|
storage_key: &StorageKey,
|
||||||
|
child_info: ChildInfo,
|
||||||
|
key: &StorageKey
|
||||||
|
) -> sp_blockchain::Result<Option<Block::Hash>> {
|
||||||
|
Ok(self.state_at(id)?
|
||||||
|
.child_storage_hash(&storage_key.0, child_info, &key.0)
|
||||||
|
.map_err(|e| sp_blockchain::Error::from_state(Box::new(e)))?
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn max_key_changes_range(
|
||||||
|
&self,
|
||||||
|
first: NumberFor<Block>,
|
||||||
|
last: BlockId<Block>,
|
||||||
|
) -> sp_blockchain::Result<Option<(NumberFor<Block>, BlockId<Block>)>> {
|
||||||
|
let last_number = self.backend.blockchain().expect_block_number_from_id(&last)?;
|
||||||
|
let last_hash = self.backend.blockchain().expect_block_hash_from_id(&last)?;
|
||||||
|
if first > last_number {
|
||||||
|
return Err(sp_blockchain::Error::ChangesTrieAccessFailed("Invalid changes trie range".into()));
|
||||||
|
}
|
||||||
|
|
||||||
|
let (storage, configs) = match self.require_changes_trie(first, last_hash, false).ok() {
|
||||||
|
Some((storage, configs)) => (storage, configs),
|
||||||
|
None => return Ok(None),
|
||||||
|
};
|
||||||
|
|
||||||
|
let first_available_changes_trie = configs.last().map(|config| config.0);
|
||||||
|
match first_available_changes_trie {
|
||||||
|
Some(first_available_changes_trie) => {
|
||||||
|
let oldest_unpruned = storage.oldest_pruned_digest_range_end();
|
||||||
|
let first = std::cmp::max(first_available_changes_trie, oldest_unpruned);
|
||||||
|
Ok(Some((first, last)))
|
||||||
|
},
|
||||||
|
None => Ok(None)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn key_changes(
|
||||||
|
&self,
|
||||||
|
first: NumberFor<Block>,
|
||||||
|
last: BlockId<Block>,
|
||||||
|
storage_key: Option<&StorageKey>,
|
||||||
|
key: &StorageKey
|
||||||
|
) -> sp_blockchain::Result<Vec<(NumberFor<Block>, u32)>> {
|
||||||
|
let last_number = self.backend.blockchain().expect_block_number_from_id(&last)?;
|
||||||
|
let last_hash = self.backend.blockchain().expect_block_hash_from_id(&last)?;
|
||||||
|
let (storage, configs) = self.require_changes_trie(first, last_hash, true)?;
|
||||||
|
|
||||||
|
let mut result = Vec::new();
|
||||||
|
let best_number = self.backend.blockchain().info().best_number;
|
||||||
|
for (config_zero, config_end, config) in configs {
|
||||||
|
let range_first = ::std::cmp::max(first, config_zero + One::one());
|
||||||
|
let range_anchor = match config_end {
|
||||||
|
Some((config_end_number, config_end_hash)) => if last_number > config_end_number {
|
||||||
|
ChangesTrieAnchorBlockId { hash: config_end_hash, number: config_end_number }
|
||||||
|
} else {
|
||||||
|
ChangesTrieAnchorBlockId { hash: convert_hash(&last_hash), number: last_number }
|
||||||
|
},
|
||||||
|
None => ChangesTrieAnchorBlockId { hash: convert_hash(&last_hash), number: last_number },
|
||||||
|
};
|
||||||
|
|
||||||
|
let config_range = ChangesTrieConfigurationRange {
|
||||||
|
config: &config,
|
||||||
|
zero: config_zero.clone(),
|
||||||
|
end: config_end.map(|(config_end_number, _)| config_end_number),
|
||||||
|
};
|
||||||
|
let result_range: Vec<(NumberFor<Block>, u32)> = key_changes::<HashFor<Block>, _>(
|
||||||
|
config_range,
|
||||||
|
storage.storage(),
|
||||||
|
range_first,
|
||||||
|
&range_anchor,
|
||||||
|
best_number,
|
||||||
|
storage_key.as_ref().map(|x| &x.0[..]),
|
||||||
|
&key.0)
|
||||||
|
.and_then(|r| r.map(|r| r.map(|(block, tx)| (block, tx))).collect::<Result<_, _>>())
|
||||||
|
.map_err(|err| sp_blockchain::Error::ChangesTrieAccessFailed(err))?;
|
||||||
|
result.extend(result_range);
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(result)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<B, E, Block, RA> HeaderMetadata<Block> for Client<B, E, Block, RA> where
|
impl<B, E, Block, RA> HeaderMetadata<Block> for Client<B, E, Block, RA> where
|
||||||
B: backend::Backend<Block>,
|
B: backend::Backend<Block>,
|
||||||
E: CallExecutor<Block>,
|
E: CallExecutor<Block>,
|
||||||
@@ -1902,6 +1845,15 @@ impl<B, E, Block, RA> BlockBody<Block> for Client<B, E, Block, RA>
|
|||||||
) -> sp_blockchain::Result<Option<Vec<<Block as BlockT>::Extrinsic>>> {
|
) -> sp_blockchain::Result<Option<Vec<<Block as BlockT>::Extrinsic>>> {
|
||||||
self.body(id)
|
self.body(id)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn block(&self, id: &BlockId<Block>) -> sp_blockchain::Result<Option<SignedBlock<Block>>>
|
||||||
|
{
|
||||||
|
Ok(match (self.header(id)?, self.body(id)?, self.justification(id)?) {
|
||||||
|
(Some(header), Some(extrinsics), justification) =>
|
||||||
|
Some(SignedBlock { block: Block::new(header, extrinsics), justification }),
|
||||||
|
_ => None,
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<B, E, Block, RA> backend::AuxStore for Client<B, E, Block, RA>
|
impl<B, E, Block, RA> backend::AuxStore for Client<B, E, Block, RA>
|
||||||
|
|||||||
@@ -40,7 +40,7 @@ use sp_blockchain::{Error as ClientError, Result as ClientResult};
|
|||||||
use sc_client_api::{
|
use sc_client_api::{
|
||||||
backend::RemoteBackend,
|
backend::RemoteBackend,
|
||||||
light::RemoteCallRequest,
|
light::RemoteCallRequest,
|
||||||
call_executor::CallExecutor
|
call_executor::CallExecutor,
|
||||||
};
|
};
|
||||||
use sc_executor::{RuntimeVersion, NativeVersion};
|
use sc_executor::{RuntimeVersion, NativeVersion};
|
||||||
|
|
||||||
@@ -288,6 +288,7 @@ mod tests {
|
|||||||
use sp_core::H256;
|
use sp_core::H256;
|
||||||
use sc_client_api::backend::{Backend, NewBlockState};
|
use sc_client_api::backend::{Backend, NewBlockState};
|
||||||
use crate::in_mem::Backend as InMemBackend;
|
use crate::in_mem::Backend as InMemBackend;
|
||||||
|
use sc_client_api::ProofProvider;
|
||||||
use sp_runtime::traits::BlakeTwo256;
|
use sp_runtime::traits::BlakeTwo256;
|
||||||
|
|
||||||
struct DummyCallExecutor;
|
struct DummyCallExecutor;
|
||||||
|
|||||||
@@ -349,6 +349,7 @@ pub mod tests {
|
|||||||
use sp_runtime::{generic::BlockId, traits::BlakeTwo256};
|
use sp_runtime::{generic::BlockId, traits::BlakeTwo256};
|
||||||
use sp_state_machine::Backend;
|
use sp_state_machine::Backend;
|
||||||
use super::*;
|
use super::*;
|
||||||
|
use sc_client_api::{StorageProvider, ProofProvider};
|
||||||
|
|
||||||
const CHILD_INFO_1: ChildInfo<'static> = ChildInfo::new_default(b"unique_id_1");
|
const CHILD_INFO_1: ChildInfo<'static> = ChildInfo::new_default(b"unique_id_1");
|
||||||
|
|
||||||
@@ -378,7 +379,7 @@ pub mod tests {
|
|||||||
.and_then(|v| Decode::decode(&mut &v.0[..]).ok()).unwrap();
|
.and_then(|v| Decode::decode(&mut &v.0[..]).ok()).unwrap();
|
||||||
let remote_read_proof = remote_client.read_proof(
|
let remote_read_proof = remote_client.read_proof(
|
||||||
&remote_block_id,
|
&remote_block_id,
|
||||||
&[well_known_keys::HEAP_PAGES],
|
&mut std::iter::once(well_known_keys::HEAP_PAGES),
|
||||||
).unwrap();
|
).unwrap();
|
||||||
|
|
||||||
// check remote read proof locally
|
// check remote read proof locally
|
||||||
@@ -426,7 +427,7 @@ pub mod tests {
|
|||||||
&remote_block_id,
|
&remote_block_id,
|
||||||
b":child_storage:default:child1",
|
b":child_storage:default:child1",
|
||||||
CHILD_INFO_1,
|
CHILD_INFO_1,
|
||||||
&[b"key1"],
|
&mut std::iter::once("key1".as_bytes()),
|
||||||
).unwrap();
|
).unwrap();
|
||||||
|
|
||||||
// check locally
|
// check locally
|
||||||
|
|||||||
Reference in New Issue
Block a user