Remove requirement on Hash = H256, make Proposer return StorageChanges and Proof (#3860)

* Extend `Proposer` to optionally generate a proof of the proposal

* Something

* Refactor sr-api to not depend on client anymore

* Fix benches

* Apply suggestions from code review

Co-Authored-By: Tomasz Drwięga <tomusdrw@users.noreply.github.com>

* Apply suggestions from code review

* Introduce new `into_storage_changes` function

* Switch to runtime api for `execute_block` and don't require `H256`
anywhere in the code

* Put the `StorageChanges` into the `Proposal`

* Move the runtime api error to its own trait

* Adds `StorageTransactionCache` to the runtime api

This requires that we add `type NodeBlock = ` to the
`impl_runtime_apis!` macro to work around some bugs in rustc :(

* Remove `type NodeBlock` and switch to a "better" hack

* Start using the transaction cache from the runtime api

* Make it compile

* Move `InMemory` to its own file

* Make all tests work again

* Return block, storage_changes and proof from Blockbuilder::bake()

* Make sure that we use/set `storage_changes` when possible

* Add test

* Fix deadlock

* Remove accidentally added folders

* Introduce `RecordProof` as argument type to be more explicit

* Update client/src/client.rs

Co-Authored-By: Tomasz Drwięga <tomusdrw@users.noreply.github.com>

* Update primitives/state-machine/src/ext.rs

Co-Authored-By: Tomasz Drwięga <tomusdrw@users.noreply.github.com>

* Integrates review feedback

* Remove `unsafe` usage

* Update client/block-builder/src/lib.rs

Co-Authored-By: Benjamin Kampmann <ben@gnunicorn.org>

* Update client/src/call_executor.rs

* Bump versions

Co-authored-by: Tomasz Drwięga <tomusdrw@users.noreply.github.com>
Co-authored-by: Benjamin Kampmann <ben.kampmann@googlemail.com>
This commit is contained in:
Bastian Köcher
2020-01-10 10:48:32 +01:00
committed by GitHub
parent 74d6e660c6
commit fd6b29dd2c
140 changed files with 4860 additions and 3339 deletions
+15 -1
View File
@@ -3135,6 +3135,7 @@ dependencies = [
"pallet-contracts-rpc 2.0.0",
"pallet-transaction-payment-rpc 2.0.0",
"sc-client 2.0.0",
"sp-api 2.0.0",
"sp-runtime 2.0.0",
"sp-transaction-pool 2.0.0",
"substrate-frame-rpc-system 2.0.0",
@@ -3632,6 +3633,7 @@ dependencies = [
"parity-scale-codec 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_json 1.0.44 (registry+https://github.com/rust-lang/crates.io-index)",
"sp-api 2.0.0",
"sp-blockchain 2.0.0",
"sp-core 2.0.0",
"sp-rpc 2.0.0",
@@ -4019,6 +4021,7 @@ dependencies = [
"pallet-transaction-payment-rpc-runtime-api 2.0.0",
"parity-scale-codec 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)",
"sp-api 2.0.0",
"sp-blockchain 2.0.0",
"sp-core 2.0.0",
"sp-rpc 2.0.0",
@@ -4998,7 +5001,7 @@ dependencies = [
"sp-blockchain 2.0.0",
"sp-core 2.0.0",
"sp-runtime 2.0.0",
"sp-test-primitives 2.0.0",
"substrate-test-runtime-client 2.0.0",
]
[[package]]
@@ -5014,6 +5017,7 @@ dependencies = [
"sc-client-api 2.0.0",
"sc-telemetry 2.0.0",
"sc-transaction-pool 2.0.0",
"sp-api 2.0.0",
"sp-blockchain 2.0.0",
"sp-consensus 0.8.0",
"sp-core 2.0.0",
@@ -5029,9 +5033,11 @@ name = "sc-block-builder"
version = "2.0.0"
dependencies = [
"parity-scale-codec 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"sc-client-api 2.0.0",
"sp-api 2.0.0",
"sp-block-builder 2.0.0",
"sp-blockchain 2.0.0",
"sp-consensus 0.8.0",
"sp-core 2.0.0",
"sp-runtime 2.0.0",
"sp-state-machine 2.0.0",
@@ -5290,6 +5296,7 @@ dependencies = [
"log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
"parity-scale-codec 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"sc-client-api 2.0.0",
"sp-api 2.0.0",
"sp-block-builder 2.0.0",
"sp-blockchain 2.0.0",
"sp-consensus 0.8.0",
@@ -5311,11 +5318,13 @@ dependencies = [
"parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
"sc-client-api 2.0.0",
"sc-telemetry 2.0.0",
"sp-api 2.0.0",
"sp-blockchain 2.0.0",
"sp-consensus 0.8.0",
"sp-core 2.0.0",
"sp-inherents 2.0.0",
"sp-runtime 2.0.0",
"sp-state-machine 2.0.0",
"substrate-test-runtime-client 2.0.0",
]
@@ -6137,6 +6146,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
name = "sp-api"
version = "2.0.0"
dependencies = [
"hash-db 0.15.2 (registry+https://github.com/rust-lang/crates.io-index)",
"parity-scale-codec 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"sp-api-proc-macro 2.0.0",
"sp-core 2.0.0",
@@ -6190,6 +6200,7 @@ dependencies = [
name = "sp-application-crypto-test"
version = "2.0.0"
dependencies = [
"sp-api 2.0.0",
"sp-application-crypto 2.0.0",
"sp-core 2.0.0",
"sp-runtime 2.0.0",
@@ -6272,6 +6283,7 @@ dependencies = [
"sp-core 2.0.0",
"sp-inherents 2.0.0",
"sp-runtime 2.0.0",
"sp-state-machine 2.0.0",
"sp-std 2.0.0",
"sp-test-primitives 2.0.0",
"sp-version 2.0.0",
@@ -6847,6 +6859,7 @@ dependencies = [
"sc-client 2.0.0",
"sc-transaction-pool 2.0.0",
"serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)",
"sp-api 2.0.0",
"sp-blockchain 2.0.0",
"sp-core 2.0.0",
"sp-runtime 2.0.0",
@@ -6922,6 +6935,7 @@ dependencies = [
"sc-block-builder 2.0.0",
"sc-client 2.0.0",
"sc-client-api 2.0.0",
"sp-api 2.0.0",
"sp-blockchain 2.0.0",
"sp-core 2.0.0",
"sp-runtime 2.0.0",
+1 -1
View File
@@ -118,7 +118,7 @@ pub fn new_full<C: Send + Default + 'static>(config: Configuration<C, GenesisCon
let can_author_with =
sp_consensus::CanAuthorWithNativeVersion::new(client.executor().clone());
let aura = sc_consensus_aura::start_aura::<_, _, _, _, _, AuraPair, _, _, _, _>(
let aura = sc_consensus_aura::start_aura::<_, _, _, _, _, AuraPair, _, _, _>(
sc_consensus_aura::SlotDuration::get_or_compute(&*client)?,
client,
select_chain,
+6 -5
View File
@@ -39,7 +39,6 @@ use sp_runtime::traits::Block as BlockT;
use node_executor::NativeExecutor;
use sc_network::NetworkService;
use sc_offchain::OffchainWorkers;
use sp_core::Blake2Hasher;
construct_simple_protocol! {
/// Demo protocol attachment for substrate.
@@ -113,9 +112,7 @@ macro_rules! new_full_start {
/// concrete types instead.
macro_rules! new_full {
($config:expr, $with_startup_data: expr) => {{
use futures01::Stream;
use futures::{
compat::Stream01CompatExt,
stream::StreamExt,
future::{FutureExt, TryFutureExt},
};
@@ -300,7 +297,7 @@ pub fn new_full<C: Send + Default + 'static>(config: NodeConfiguration<C>)
ConcreteTransactionPool,
OffchainWorkers<
ConcreteClient,
<ConcreteBackend as sc_client_api::backend::Backend<Block, Blake2Hasher>>::OffchainStorage,
<ConcreteBackend as sc_client_api::backend::Backend<Block>>::OffchainStorage,
ConcreteBlock,
>
>,
@@ -387,6 +384,7 @@ mod tests {
use sc_consensus_babe::CompatibleDigestItem;
use sp_consensus::{
Environment, Proposer, BlockImportParams, BlockOrigin, ForkChoiceStrategy, BlockImport,
RecordProof,
};
use node_primitives::{Block, DigestItem, Signature};
use node_runtime::{BalancesCall, Call, UncheckedExtrinsic, Address};
@@ -439,6 +437,7 @@ mod tests {
internal_justification: Vec::new(),
finalized: false,
body: Some(block.extrinsics),
storage_changes: None,
header: block.header,
auxiliary: Vec::new(),
}
@@ -540,7 +539,8 @@ mod tests {
inherent_data,
digest,
std::time::Duration::from_secs(1),
)).expect("Error making test block");
RecordProof::Yes,
)).expect("Error making test block").block;
let (new_header, new_body) = new_block.deconstruct();
let pre_hash = new_header.hash();
@@ -559,6 +559,7 @@ mod tests {
justification: None,
post_digests: vec![item],
body: Some(new_body),
storage_changes: None,
finalized: false,
auxiliary: Vec::new(),
fork_choice: ForkChoiceStrategy::LongestChain,
+1 -1
View File
@@ -37,7 +37,7 @@ wabt = "0.9.2"
[features]
wasmtime = [
"sc-executor/wasmtime",
"sc-executor/wasmtime",
]
wasmi-errno = [
"sc-executor/wasmi-errno",
-1
View File
@@ -27,4 +27,3 @@ native_executor_instance!(
node_runtime::api::dispatch,
node_runtime::native_version
);
+3 -3
View File
@@ -43,7 +43,7 @@ use node_primitives::{Balance, Hash};
use wabt;
use node_testing::keyring::*;
mod common;
pub mod common;
use self::common::{*, sign};
/// The wasm runtime binary which hasn't undergone the compacting process.
@@ -821,11 +821,11 @@ fn full_wasm_block_import_works_with_changes_trie() {
#[test]
fn should_import_block_with_test_client() {
use node_testing::client::{
ClientExt, TestClientBuilderExt, TestClientBuilder,
ClientBlockImportExt, TestClientBuilderExt, TestClientBuilder,
sp_consensus::BlockOrigin,
};
let client = TestClientBuilder::new().build();
let mut client = TestClientBuilder::new().build();
let block1 = changes_trie_block();
let block_data = block1.0;
let block = node_primitives::Block::decode(&mut &block_data[..]).unwrap();
+2 -4
View File
@@ -15,15 +15,13 @@
// along with Substrate. If not, see <http://www.gnu.org/licenses/>.
use codec::{Encode, Decode};
use frame_support::{
Hashable,
};
use frame_support::Hashable;
use sp_state_machine::TestExternalities as CoreTestExternalities;
use sp_core::{
Blake2Hasher, NeverNativeValue, NativeOrEncoded,
traits::CodeExecutor,
};
use sp_runtime::traits::{Header as HeaderT};
use sp_runtime::traits::Header as HeaderT;
use sc_executor::{NativeExecutor, WasmExecutionMethod};
use sc_executor::error::Result;
+1 -1
View File
@@ -37,7 +37,7 @@ use node_runtime::impls::LinearWeightToFee;
use node_primitives::Balance;
use node_testing::keyring::*;
mod common;
pub mod common;
use self::common::{*, sign};
#[test]
@@ -28,7 +28,7 @@ use frame_system::offchain::{SubmitSignedTransaction, SubmitUnsignedTransaction}
use pallet_im_online::sr25519::AuthorityPair as Key;
use codec::Decode;
mod common;
pub mod common;
use self::common::*;
#[test]
+1
View File
@@ -10,6 +10,7 @@ jsonrpc-core = "14.0.3"
node-primitives = { version = "2.0.0", path = "../primitives" }
node-runtime = { version = "2.0.0", path = "../runtime" }
sp-runtime = { version = "2.0.0", path = "../../../primitives/runtime" }
sp-api = { version = "2.0.0", path = "../../../primitives/api" }
pallet-contracts-rpc = { version = "2.0.0", path = "../../../frame/contracts/rpc/" }
pallet-transaction-payment-rpc = { version = "2.0.0", path = "../../../frame/transaction-payment/rpc/" }
substrate-frame-rpc-system = { version = "2.0.0", path = "../../../utils/frame/rpc/system" }
+2 -2
View File
@@ -33,7 +33,7 @@ use std::sync::Arc;
use node_primitives::{Block, AccountId, Index, Balance};
use node_runtime::UncheckedExtrinsic;
use sp_runtime::traits::ProvideRuntimeApi;
use sp_api::ProvideRuntimeApi;
use sp_transaction_pool::TransactionPool;
/// Light client extra dependencies.
@@ -62,7 +62,7 @@ pub fn create<C, P, M, F>(
pool: Arc<P>,
light_deps: Option<LightDeps<F>>,
) -> jsonrpc_core::IoHandler<M> where
C: ProvideRuntimeApi,
C: ProvideRuntimeApi<Block>,
C: sc_client::blockchain::HeaderBackend<Block>,
C: Send + Sync + 'static,
C::Api: substrate_frame_rpc_system::AccountNonceApi<Block, AccountId, Index>,
+2 -2
View File
@@ -80,8 +80,8 @@ pub const VERSION: RuntimeVersion = RuntimeVersion {
// and set impl_version to equal spec_version. If only runtime
// implementation changes and behavior does not, then leave spec_version as
// is and increment impl_version.
spec_version: 200,
impl_version: 200,
spec_version: 201,
impl_version: 201,
apis: RUNTIME_API_VERSIONS,
};
@@ -43,10 +43,9 @@ use std::sync::Arc;
use log::info;
use sc_client::Client;
use sp_block_builder::BlockBuilder;
use sp_api::ConstructRuntimeApi;
use sp_core::{Blake2Hasher, Hasher};
use sp_api::{ConstructRuntimeApi, ProvideRuntimeApi};
use sp_runtime::generic::BlockId;
use sp_runtime::traits::{Block as BlockT, ProvideRuntimeApi, One, Zero};
use sp_runtime::traits::{Block as BlockT, One, Zero};
use crate::{RuntimeAdapter, create_block};
@@ -59,12 +58,13 @@ pub fn next<RA, Backend, Exec, Block, RtApi>(
prior_block_id: BlockId<Block>,
) -> Option<Block>
where
Block: BlockT<Hash = <Blake2Hasher as Hasher>::Out>,
Exec: sc_client::CallExecutor<Block, Blake2Hasher> + Send + Sync + Clone,
Backend: sc_client_api::backend::Backend<Block, Blake2Hasher> + Send,
Client<Backend, Exec, Block, RtApi>: ProvideRuntimeApi,
<Client<Backend, Exec, Block, RtApi> as ProvideRuntimeApi>::Api:
BlockBuilder<Block, Error = sp_blockchain::Error>,
Block: BlockT,
Exec: sc_client::CallExecutor<Block, Backend = Backend> + Send + Sync + Clone,
Backend: sc_client_api::backend::Backend<Block> + Send,
Client<Backend, Exec, Block, RtApi>: ProvideRuntimeApi<Block>,
<Client<Backend, Exec, Block, RtApi> as ProvideRuntimeApi<Block>>::Api:
BlockBuilder<Block, Error = sp_blockchain::Error> +
sp_api::ApiExt<Block, StateBackend = Backend::State>,
RtApi: ConstructRuntimeApi<Block, Client<Backend, Exec, Block, RtApi>> + Send + Sync,
RA: RuntimeAdapter,
{
@@ -28,18 +28,16 @@ use log::info;
use sc_client::Client;
use sp_block_builder::BlockBuilder;
use sp_api::ConstructRuntimeApi;
use sp_api::{ConstructRuntimeApi, ProvideRuntimeApi, ApiExt};
use sp_consensus::{
BlockOrigin, BlockImportParams, InherentData, ForkChoiceStrategy,
SelectChain
};
use sp_consensus::block_import::BlockImport;
use codec::{Decode, Encode};
use sp_core::{Blake2Hasher, Hasher};
use sp_runtime::generic::BlockId;
use sp_runtime::traits::{
Block as BlockT, Header as HeaderT, ProvideRuntimeApi, SimpleArithmetic,
One, Zero,
Block as BlockT, Header as HeaderT, SimpleArithmetic, One, Zero,
};
pub use crate::modes::Mode;
@@ -100,16 +98,17 @@ pub fn factory<RA, Backend, Exec, Block, RtApi, Sc>(
select_chain: &Sc,
) -> sc_cli::error::Result<()>
where
Block: BlockT<Hash = <Blake2Hasher as Hasher>::Out>,
Exec: sc_client::CallExecutor<Block, Blake2Hasher> + Send + Sync + Clone,
Backend: sc_client_api::backend::Backend<Block, Blake2Hasher> + Send,
Client<Backend, Exec, Block, RtApi>: ProvideRuntimeApi,
<Client<Backend, Exec, Block, RtApi> as ProvideRuntimeApi>::Api:
BlockBuilder<Block, Error = sp_blockchain::Error>,
Block: BlockT,
Exec: sc_client::CallExecutor<Block, Backend = Backend> + Send + Sync + Clone,
Backend: sc_client_api::backend::Backend<Block> + Send,
Client<Backend, Exec, Block, RtApi>: ProvideRuntimeApi<Block>,
<Client<Backend, Exec, Block, RtApi> as ProvideRuntimeApi<Block>>::Api:
BlockBuilder<Block, Error = sp_blockchain::Error> +
ApiExt<Block, StateBackend = Backend::State>,
RtApi: ConstructRuntimeApi<Block, Client<Backend, Exec, Block, RtApi>> + Send + Sync,
Sc: SelectChain<Block>,
RA: RuntimeAdapter,
<<RA as RuntimeAdapter>::Block as BlockT>::Hash: From<sp_core::H256>,
RA: RuntimeAdapter<Block = Block>,
Block::Hash: From<sp_core::H256>,
{
if *factory_state.mode() != Mode::MasterToNToM && factory_state.rounds() > RA::Number::one() {
let msg = "The factory can only be used with rounds set to 1 in this mode.".into();
@@ -144,7 +143,7 @@ where
} {
best_hash = block.header().hash();
best_block_id = BlockId::<Block>::hash(best_hash);
import_block(&client, block);
import_block(client.clone(), block);
info!("Imported block at {}", factory_state.block_no());
}
@@ -159,13 +158,14 @@ pub fn create_block<RA, Backend, Exec, Block, RtApi>(
inherent_extrinsics: Vec<<Block as BlockT>::Extrinsic>,
) -> Block
where
Block: BlockT<Hash = <Blake2Hasher as Hasher>::Out>,
Exec: sc_client::CallExecutor<Block, Blake2Hasher> + Send + Sync + Clone,
Backend: sc_client_api::backend::Backend<Block, Blake2Hasher> + Send,
Client<Backend, Exec, Block, RtApi>: ProvideRuntimeApi,
Block: BlockT,
Exec: sc_client::CallExecutor<Block, Backend = Backend> + Send + Sync + Clone,
Backend: sc_client_api::backend::Backend<Block> + Send,
Client<Backend, Exec, Block, RtApi>: ProvideRuntimeApi<Block>,
RtApi: ConstructRuntimeApi<Block, Client<Backend, Exec, Block, RtApi>> + Send + Sync,
<Client<Backend, Exec, Block, RtApi> as ProvideRuntimeApi>::Api:
BlockBuilder<Block, Error = sp_blockchain::Error>,
<Client<Backend, Exec, Block, RtApi> as ProvideRuntimeApi<Block>>::Api:
BlockBuilder<Block, Error = sp_blockchain::Error> +
ApiExt<Block, StateBackend = Backend::State>,
RA: RuntimeAdapter,
{
let mut block = client.new_block(Default::default()).expect("Failed to create new block");
@@ -178,22 +178,27 @@ where
block.push(inherent).expect("Failed ...");
}
block.bake().expect("Failed to bake block")
block.build().expect("Failed to bake block").block
}
fn import_block<Backend, Exec, Block, RtApi>(
client: &Arc<Client<Backend, Exec, Block, RtApi>>,
mut client: Arc<Client<Backend, Exec, Block, RtApi>>,
block: Block
) -> () where
Block: BlockT<Hash = <Blake2Hasher as Hasher>::Out>,
Exec: sc_client::CallExecutor<Block, Blake2Hasher> + Send + Sync + Clone,
Backend: sc_client_api::backend::Backend<Block, Blake2Hasher> + Send,
Block: BlockT,
Exec: sc_client::CallExecutor<Block> + Send + Sync + Clone,
Backend: sc_client_api::backend::Backend<Block> + Send,
Client<Backend, Exec, Block, RtApi>: ProvideRuntimeApi<Block>,
<Client<Backend, Exec, Block, RtApi> as ProvideRuntimeApi<Block>>::Api:
sp_api::Core<Block, Error = sp_blockchain::Error> +
ApiExt<Block, StateBackend = Backend::State>,
{
let import = BlockImportParams {
origin: BlockOrigin::File,
header: block.header().clone(),
post_digests: Vec::new(),
body: Some(block.extrinsics().to_vec()),
storage_changes: None,
finalized: false,
justification: None,
auxiliary: Vec::new(),
@@ -201,5 +206,5 @@ fn import_block<Backend, Exec, Block, RtApi>(
allow_missing_state: false,
import_existing: false,
};
(&**client).import_block(import, HashMap::new()).expect("Failed to import block");
client.import_block(import, HashMap::new()).expect("Failed to import block");
}
@@ -38,9 +38,8 @@ use std::sync::Arc;
use log::info;
use sc_client::Client;
use sp_block_builder::BlockBuilder;
use sp_api::ConstructRuntimeApi;
use sp_core::{Blake2Hasher, Hasher};
use sp_runtime::traits::{Block as BlockT, ProvideRuntimeApi, One};
use sp_api::{ConstructRuntimeApi, ProvideRuntimeApi};
use sp_runtime::traits::{Block as BlockT, One};
use sp_runtime::generic::BlockId;
use crate::{Mode, RuntimeAdapter, create_block};
@@ -54,12 +53,13 @@ pub fn next<RA, Backend, Exec, Block, RtApi>(
prior_block_id: BlockId<Block>,
) -> Option<Block>
where
Block: BlockT<Hash = <Blake2Hasher as Hasher>::Out>,
Exec: sc_client::CallExecutor<Block, Blake2Hasher> + Send + Sync + Clone,
Backend: sc_client_api::backend::Backend<Block, Blake2Hasher> + Send,
Client<Backend, Exec, Block, RtApi>: ProvideRuntimeApi,
<Client<Backend, Exec, Block, RtApi> as ProvideRuntimeApi>::Api:
BlockBuilder<Block, Error = sp_blockchain::Error>,
Block: BlockT,
Exec: sc_client::CallExecutor<Block, Backend = Backend> + Send + Sync + Clone,
Backend: sc_client_api::backend::Backend<Block> + Send,
Client<Backend, Exec, Block, RtApi>: ProvideRuntimeApi<Block>,
<Client<Backend, Exec, Block, RtApi> as ProvideRuntimeApi<Block>>::Api:
BlockBuilder<Block, Error = sp_blockchain::Error> +
sp_api::ApiExt<Block, StateBackend = Backend::State>,
RtApi: ConstructRuntimeApi<Block, Client<Backend, Exec, Block, RtApi>> + Send + Sync,
RA: RuntimeAdapter,
{
+53 -43
View File
@@ -21,8 +21,7 @@ use std::collections::HashMap;
use sp_core::ChangesTrieConfiguration;
use sp_core::offchain::OffchainStorage;
use sp_runtime::{generic::BlockId, Justification, Storage};
use sp_runtime::traits::{Block as BlockT, NumberFor};
use sp_state_machine::backend::Backend as StateBackend;
use sp_runtime::traits::{Block as BlockT, NumberFor, HasherFor};
use sp_state_machine::{ChangesTrieStorage as StateChangesTrieStorage, ChangesTrieTransaction};
use crate::{
blockchain::{
@@ -33,9 +32,19 @@ use crate::{
};
use sp_blockchain;
use sp_consensus::BlockOrigin;
use hash_db::Hasher;
use parking_lot::RwLock;
pub use sp_state_machine::Backend as StateBackend;
/// Extracts the state backend type for the given backend.
pub type StateBackendFor<B, Block> = <B as Backend<Block>>::State;
/// Extracts the transaction for the given state backend.
pub type TransactionForSB<B, Block> = <B as StateBackend<HasherFor<Block>>>::Transaction;
/// Extracts the transaction for the given backend.
pub type TransactionFor<B, Block> = TransactionForSB<StateBackendFor<B, Block>, Block>;
/// In memory array of storage values.
pub type StorageCollection = Vec<(Vec<u8>, Option<Vec<u8>>)>;
@@ -62,11 +71,7 @@ pub struct ImportSummary<Block: BlockT> {
}
/// Import operation wrapper
pub struct ClientImportOperation<
Block: BlockT,
H: Hasher<Out=Block::Hash>,
B: Backend<Block, H>,
> {
pub struct ClientImportOperation<Block: BlockT, B: Backend<Block>> {
/// DB Operation.
pub op: B::BlockImportOperation,
/// Summary of imported block.
@@ -107,12 +112,9 @@ impl NewBlockState {
/// Block insertion operation.
///
/// Keeps hold if the inserted block state and data.
pub trait BlockImportOperation<Block, H> where
Block: BlockT,
H: Hasher<Out=Block::Hash>,
{
pub trait BlockImportOperation<Block: BlockT> {
/// Associated state backend type.
type State: StateBackend<H>;
type State: StateBackend<HasherFor<Block>>;
/// Returns pending state.
///
@@ -132,10 +134,13 @@ pub trait BlockImportOperation<Block, H> where
fn update_cache(&mut self, cache: HashMap<well_known_cache_keys::Id, Vec<u8>>);
/// Inject storage data into the database.
fn update_db_storage(&mut self, update: <Self::State as StateBackend<H>>::Transaction) -> sp_blockchain::Result<()>;
fn update_db_storage(
&mut self,
update: TransactionForSB<Self::State, Block>,
) -> sp_blockchain::Result<()>;
/// Inject storage data into the database replacing any existing data.
fn reset_storage(&mut self, storage: Storage) -> sp_blockchain::Result<H::Out>;
fn reset_storage(&mut self, storage: Storage) -> sp_blockchain::Result<Block::Hash>;
/// Set storage changes.
fn update_storage(
@@ -145,7 +150,10 @@ pub trait BlockImportOperation<Block, H> where
) -> sp_blockchain::Result<()>;
/// Inject changes trie data into the database.
fn update_changes_trie(&mut self, update: ChangesTrieTransaction<H, NumberFor<Block>>) -> sp_blockchain::Result<()>;
fn update_changes_trie(
&mut self,
update: ChangesTrieTransaction<HasherFor<Block>, NumberFor<Block>>,
) -> sp_blockchain::Result<()>;
/// Insert auxiliary keys.
///
@@ -154,13 +162,18 @@ pub trait BlockImportOperation<Block, H> where
where I: IntoIterator<Item=(Vec<u8>, Option<Vec<u8>>)>;
/// Mark a block as finalized.
fn mark_finalized(&mut self, id: BlockId<Block>, justification: Option<Justification>) -> sp_blockchain::Result<()>;
/// Mark a block as new head. If both block import and set head are specified, set head overrides block import's best block rule.
fn mark_finalized(
&mut self,
id: BlockId<Block>,
justification: Option<Justification>,
) -> sp_blockchain::Result<()>;
/// Mark a block as new head. If both block import and set head are specified, set head
/// overrides block import's best block rule.
fn mark_head(&mut self, id: BlockId<Block>) -> sp_blockchain::Result<()>;
}
/// Finalize Facilities
pub trait Finalizer<Block: BlockT, H: Hasher<Out=Block::Hash>, B: Backend<Block, H>> {
pub trait Finalizer<Block: BlockT, B: Backend<Block>> {
/// Mark all blocks up to given as finalized in operation.
///
/// If `justification` is provided it is stored with the given finalized
@@ -172,7 +185,7 @@ pub trait Finalizer<Block: BlockT, H: Hasher<Out=Block::Hash>, B: Backend<Block,
/// best block should use `SelectChain` instead of the client.
fn apply_finality(
&self,
operation: &mut ClientImportOperation<Block, H, B>,
operation: &mut ClientImportOperation<Block, B>,
id: BlockId<Block>,
justification: Option<Justification>,
notify: bool,
@@ -226,20 +239,17 @@ pub trait AuxStore {
/// should not be pruned. The backend should internally reference-count
/// its state objects.
///
/// The same applies for live `BlockImportOperation`s: while an import operation building on a parent `P`
/// is alive, the state for `P` should not be pruned.
pub trait Backend<Block, H>: AuxStore + Send + Sync where
Block: BlockT,
H: Hasher<Out=Block::Hash>,
{
/// The same applies for live `BlockImportOperation`s: while an import operation building on a
/// parent `P` is alive, the state for `P` should not be pruned.
pub trait Backend<Block: BlockT>: AuxStore + Send + Sync {
/// Associated block insertion operation type.
type BlockImportOperation: BlockImportOperation<Block, H, State=Self::State>;
type BlockImportOperation: BlockImportOperation<Block, State = Self::State>;
/// Associated blockchain backend type.
type Blockchain: BlockchainBackend<Block>;
/// Associated state backend type.
type State: StateBackend<H>;
type State: StateBackend<HasherFor<Block>> + Send;
/// Changes trie storage.
type ChangesTrieStorage: PrunableStateChangesTrieStorage<Block, H>;
type ChangesTrieStorage: PrunableStateChangesTrieStorage<Block>;
/// Offchain workers local storage.
type OffchainStorage: OffchainStorage;
@@ -249,7 +259,11 @@ pub trait Backend<Block, H>: AuxStore + Send + Sync where
fn begin_operation(&self) -> sp_blockchain::Result<Self::BlockImportOperation>;
/// Note an operation to contain state transition.
fn begin_state_operation(&self, operation: &mut Self::BlockImportOperation, block: BlockId<Block>) -> sp_blockchain::Result<()>;
fn begin_state_operation(
&self,
operation: &mut Self::BlockImportOperation,
block: BlockId<Block>,
) -> sp_blockchain::Result<()>;
/// Commit block insertion.
fn commit_operation(&self, transaction: Self::BlockImportOperation) -> sp_blockchain::Result<()>;
@@ -257,7 +271,11 @@ pub trait Backend<Block, H>: AuxStore + Send + Sync where
/// Finalize block with given Id.
///
/// This should only be called if the parent of the given block has been finalized.
fn finalize_block(&self, block: BlockId<Block>, justification: Option<Justification>) -> sp_blockchain::Result<()>;
fn finalize_block(
&self,
block: BlockId<Block>,
justification: Option<Justification>,
) -> sp_blockchain::Result<()>;
/// Returns reference to blockchain backend.
fn blockchain(&self) -> &Self::Blockchain;
@@ -321,8 +339,8 @@ pub trait Backend<Block, H>: AuxStore + Send + Sync where
}
/// Changes trie storage that supports pruning.
pub trait PrunableStateChangesTrieStorage<Block: BlockT, H: Hasher>:
StateChangesTrieStorage<H, NumberFor<Block>>
pub trait PrunableStateChangesTrieStorage<Block: BlockT>:
StateChangesTrieStorage<HasherFor<Block>, NumberFor<Block>>
{
/// Get number block of oldest, non-pruned changes trie.
fn oldest_changes_trie_block(
@@ -333,18 +351,10 @@ pub trait PrunableStateChangesTrieStorage<Block: BlockT, H: Hasher>:
}
/// Mark for all Backend implementations, that are making use of state data, stored locally.
pub trait LocalBackend<Block, H>: Backend<Block, H>
where
Block: BlockT,
H: Hasher<Out=Block::Hash>,
{}
pub trait LocalBackend<Block: BlockT>: Backend<Block> {}
/// Mark for all Backend implementations, that are fetching required state data from remote nodes.
pub trait RemoteBackend<Block, H>: Backend<Block, H>
where
Block: BlockT,
H: Hasher<Out=Block::Hash>,
{
pub trait RemoteBackend<Block: BlockT>: Backend<Block> {
/// Returns true if the state for given block is available locally.
fn is_local_state_available(&self, block: &BlockId<Block>) -> bool;
+15 -45
View File
@@ -16,33 +16,28 @@
//! A method call executor interface.
use std::{cmp::Ord, panic::UnwindSafe, result, cell::RefCell};
use std::{panic::UnwindSafe, result, cell::RefCell};
use codec::{Encode, Decode};
use sp_runtime::{
generic::BlockId, traits::Block as BlockT, traits::NumberFor,
generic::BlockId, traits::{Block as BlockT, HasherFor},
};
use sp_state_machine::{
self, OverlayedChanges, ExecutionManager, ExecutionStrategy,
ChangesTrieTransaction, StorageProof,
OverlayedChanges, ExecutionManager, ExecutionStrategy, StorageProof,
};
use sc_executor::{RuntimeVersion, NativeVersion};
use sp_externalities::Extensions;
use hash_db::Hasher;
use sp_core::{Blake2Hasher, NativeOrEncoded};
use sp_core::NativeOrEncoded;
use sp_api::{ProofRecorder, InitializeBlock};
use sp_blockchain;
use sp_api::{ProofRecorder, InitializeBlock, StorageTransactionCache};
/// Method call executor.
pub trait CallExecutor<B, H>
where
B: BlockT,
H: Hasher<Out=B::Hash>,
H::Out: Ord,
{
pub trait CallExecutor<B: BlockT> {
/// Externalities error type.
type Error: sp_state_machine::Error;
/// The backend used by the node.
type Backend: crate::backend::Backend<B>;
/// Execute a call to a contract on top of state in a block of given hash.
///
/// No changes are made.
@@ -76,6 +71,9 @@ where
method: &str,
call_data: &[u8],
changes: &RefCell<OverlayedChanges>,
storage_transaction_cache: Option<&RefCell<
StorageTransactionCache<B, <Self::Backend as crate::backend::Backend<B>>::State>,
>>,
initialize_block: InitializeBlock<'a, B>,
execution_manager: ExecutionManager<EM>,
native_call: Option<NC>,
@@ -88,38 +86,10 @@ where
/// No changes are made.
fn runtime_version(&self, id: &BlockId<B>) -> Result<RuntimeVersion, sp_blockchain::Error>;
/// Execute a call to a contract on top of given state.
///
/// No changes are made.
fn call_at_state<
S: sp_state_machine::Backend<H>,
F: FnOnce(
Result<NativeOrEncoded<R>, Self::Error>,
Result<NativeOrEncoded<R>, Self::Error>,
) -> Result<NativeOrEncoded<R>, Self::Error>,
R: Encode + Decode + PartialEq,
NC: FnOnce() -> result::Result<R, String> + UnwindSafe,
>(&self,
state: &S,
overlay: &mut OverlayedChanges,
method: &str,
call_data: &[u8],
manager: ExecutionManager<F>,
native_call: Option<NC>,
extensions: Option<Extensions>,
) -> Result<
(
NativeOrEncoded<R>,
(S::Transaction, H::Out),
Option<ChangesTrieTransaction<Blake2Hasher, NumberFor<B>>>
),
sp_blockchain::Error,
>;
/// Execute a call to a contract on top of given state, gathering execution proof.
///
/// No changes are made.
fn prove_at_state<S: sp_state_machine::Backend<H>>(
fn prove_at_state<S: sp_state_machine::Backend<HasherFor<B>>>(
&self,
mut state: S,
overlay: &mut OverlayedChanges,
@@ -137,9 +107,9 @@ where
/// Execute a call to a contract on top of given trie state, gathering execution proof.
///
/// No changes are made.
fn prove_at_trie_state<S: sp_state_machine::TrieBackendStorage<H>>(
fn prove_at_trie_state<S: sp_state_machine::TrieBackendStorage<HasherFor<B>>>(
&self,
trie_state: &sp_state_machine::TrieBackend<S, H>,
trie_state: &sp_state_machine::TrieBackend<S, HasherFor<B>>,
overlay: &mut OverlayedChanges,
method: &str,
call_data: &[u8]
+6 -8
View File
@@ -34,12 +34,10 @@ pub use notifications::*;
pub use sp_state_machine::{StorageProof, ExecutionStrategy};
/// Utility methods for the client.
pub mod utils {
use sp_blockchain::{HeaderBackend, HeaderMetadata, Error};
use sp_core::H256;
use sp_runtime::traits::{Block as BlockT};
use sp_blockchain::{HeaderBackend, HeaderMetadata, Error};
use sp_runtime::traits::Block as BlockT;
use std::borrow::Borrow;
/// Returns a function for checking block ancestry, the returned function will
@@ -48,11 +46,11 @@ pub mod utils {
/// represent the current block `hash` and its `parent hash`, if given the
/// function that's returned will assume that `hash` isn't part of the local DB
/// yet, and all searches in the DB will instead reference the parent.
pub fn is_descendent_of<'a, Block: BlockT<Hash=H256>, T, H: Borrow<H256> + 'a>(
pub fn is_descendent_of<'a, Block: BlockT, T>(
client: &'a T,
current: Option<(H, H)>,
) -> impl Fn(&H256, &H256) -> Result<bool, Error> + 'a
where T: HeaderBackend<Block> + HeaderMetadata<Block, Error=Error>,
current: Option<(Block::Hash, Block::Hash)>,
) -> impl Fn(&Block::Hash, &Block::Hash) -> Result<bool, Error> + 'a
where T: HeaderBackend<Block> + HeaderMetadata<Block, Error = Error>,
{
move |base, hash| {
if base == hash { return Ok(false); }
@@ -26,10 +26,10 @@ sp-authority-discovery = { version = "2.0.0", path = "../../primitives/authority
sp-blockchain = { version = "2.0.0", path = "../../primitives/blockchain" }
sp-core = { version = "2.0.0", path = "../../primitives/core" }
sp-runtime = { version = "2.0.0", path = "../../primitives/runtime" }
sp-api = { version = "2.0.0", path = "../../primitives/api" }
[dev-dependencies]
env_logger = "0.7.0"
quickcheck = "0.9.0"
sc-peerset = { version = "2.0.0", path = "../peerset" }
sp-api = { version = "2.0.0", path = "../../primitives/api" }
sp-test-primitives = { version = "2.0.0", path = "../../primitives/test-primitives" }
substrate-test-runtime-client = { version = "2.0.0", path = "../../test-utils/runtime/client"}
@@ -65,8 +65,8 @@ use sc_network::{DhtEvent, ExHashT, NetworkStateInfo};
use sp_authority_discovery::{AuthorityDiscoveryApi, AuthorityId, AuthoritySignature, AuthorityPair};
use sp_core::crypto::{key_types, Pair};
use sp_core::traits::BareCryptoStorePtr;
use sp_runtime::generic::BlockId;
use sp_runtime::traits::{Block as BlockT, ProvideRuntimeApi};
use sp_runtime::{traits::Block as BlockT, generic::BlockId};
use sp_api::ProvideRuntimeApi;
use addr_cache::AddrCache;
#[cfg(test)]
@@ -93,8 +93,8 @@ pub struct AuthorityDiscovery<Client, Network, Block>
where
Block: BlockT + 'static,
Network: NetworkProvider,
Client: ProvideRuntimeApi + Send + Sync + 'static + HeaderBackend<Block>,
<Client as ProvideRuntimeApi>::Api: AuthorityDiscoveryApi<Block>,
Client: ProvideRuntimeApi<Block> + Send + Sync + 'static + HeaderBackend<Block>,
<Client as ProvideRuntimeApi<Block>>::Api: AuthorityDiscoveryApi<Block>,
{
client: Arc<Client>,
@@ -126,8 +126,9 @@ impl<Client, Network, Block> AuthorityDiscovery<Client, Network, Block>
where
Block: BlockT + Unpin + 'static,
Network: NetworkProvider,
Client: ProvideRuntimeApi + Send + Sync + 'static + HeaderBackend<Block>,
<Client as ProvideRuntimeApi>::Api: AuthorityDiscoveryApi<Block, Error = sp_blockchain::Error>,
Client: ProvideRuntimeApi<Block> + Send + Sync + 'static + HeaderBackend<Block>,
<Client as ProvideRuntimeApi<Block>>::Api:
AuthorityDiscoveryApi<Block, Error = sp_blockchain::Error>,
Self: Future<Output = ()>,
{
/// Return a new authority discovery.
@@ -413,8 +414,9 @@ impl<Client, Network, Block> Future for AuthorityDiscovery<Client, Network, Bloc
where
Block: BlockT + Unpin + 'static,
Network: NetworkProvider,
Client: ProvideRuntimeApi + Send + Sync + 'static + HeaderBackend<Block>,
<Client as ProvideRuntimeApi>::Api: AuthorityDiscoveryApi<Block, Error = sp_blockchain::Error>,
Client: ProvideRuntimeApi<Block> + Send + Sync + 'static + HeaderBackend<Block>,
<Client as ProvideRuntimeApi<Block>>::Api:
AuthorityDiscoveryApi<Block, Error = sp_blockchain::Error>,
{
type Output = ();
@@ -21,11 +21,10 @@ use futures::executor::block_on;
use futures::future::poll_fn;
use libp2p::{kad, PeerId};
use sp_api::{ApiExt, Core, RuntimeVersion, StorageProof};
use sp_api::{ApiExt, ApiErrorExt, Core, RuntimeVersion, StorageProof, ProvideRuntimeApi, ApiRef};
use sp_core::{testing::KeyStore, ExecutionContext, NativeOrEncoded};
use sp_runtime::traits::Zero;
use sp_runtime::traits::{ApiRef, Block as BlockT, NumberFor, ProvideRuntimeApi};
use sp_test_primitives::Block;
use sp_runtime::traits::{Zero, Block as BlockT, NumberFor};
use substrate_test_runtime_client::runtime::Block;
use super::*;
@@ -94,7 +93,7 @@ struct TestApi {
authorities: Vec<AuthorityId>,
}
impl ProvideRuntimeApi for TestApi {
impl ProvideRuntimeApi<Block> for TestApi {
type Api = RuntimeApi;
fn runtime_api<'a>(&'a self) -> ApiRef<'a, Self::Api> {
@@ -182,12 +181,18 @@ impl Core<Block> for RuntimeApi {
}
}
impl ApiExt<Block> for RuntimeApi {
impl ApiErrorExt for RuntimeApi {
type Error = sp_blockchain::Error;
}
impl ApiExt<Block> for RuntimeApi {
type StateBackend = <
substrate_test_runtime_client::Backend as sc_client_api::backend::Backend<Block>
>::State;
fn map_api_result<F: FnOnce(&Self) -> std::result::Result<R, E>, R, E>(
&self,
_: F,
_: F
) -> std::result::Result<R, E> {
unimplemented!("Not required for testing!")
}
@@ -195,7 +200,7 @@ impl ApiExt<Block> for RuntimeApi {
fn runtime_version_at(
&self,
_: &BlockId<Block>,
) -> std::result::Result<RuntimeVersion, sp_blockchain::Error> {
) -> std::result::Result<RuntimeVersion, Self::Error> {
unimplemented!("Not required for testing!")
}
@@ -206,6 +211,19 @@ impl ApiExt<Block> for RuntimeApi {
fn extract_proof(&mut self) -> Option<StorageProof> {
unimplemented!("Not required for testing!")
}
fn into_storage_changes<
T: sp_api::ChangesTrieStorage<sp_api::HasherFor<Block>, sp_api::NumberFor<Block>>
>(
&self,
_: &Self::StateBackend,
_: Option<&T>,
_: <Block as sp_api::BlockT>::Hash,
) -> std::result::Result<sp_api::StorageChanges<Self::StateBackend, Block>, String>
where Self: Sized
{
unimplemented!("Not required for testing!")
}
}
impl AuthorityDiscoveryApi<Block> for RuntimeApi {
@@ -8,6 +8,7 @@ edition = "2018"
log = "0.4.8"
futures = "0.3.1"
codec = { package = "parity-scale-codec", version = "1.0.0" }
sp-api = { version = "2.0.0", path = "../../primitives/api" }
sp-runtime = { version = "2.0.0", path = "../../primitives/runtime" }
sp-core = { version = "2.0.0", path = "../../primitives/core" }
sp-blockchain = { version = "2.0.0", path = "../../primitives/blockchain" }
@@ -19,23 +19,21 @@
// FIXME #1021 move this into sp-consensus
use std::{time, sync::Arc};
use sc_client_api::CallExecutor;
use sp_blockchain;
use sc_client_api::{CallExecutor, backend};
use sc_client::Client as SubstrateClient;
use codec::Decode;
use sp_consensus::{evaluation};
use sp_consensus::{evaluation, Proposal, RecordProof};
use sp_inherents::InherentData;
use log::{error, info, debug, trace};
use sp_core::{H256, Blake2Hasher, ExecutionContext};
use sp_core::ExecutionContext;
use sp_runtime::{
traits::{
Block as BlockT, Hash as HashT, Header as HeaderT, ProvideRuntimeApi, DigestFor, BlakeTwo256
},
traits::{Block as BlockT, Hash as HashT, Header as HeaderT, DigestFor, BlakeTwo256},
generic::BlockId,
};
use sp_transaction_pool::{TransactionPool, InPoolTransaction};
use sc_telemetry::{telemetry, CONSENSUS_INFO};
use sc_block_builder::BlockBuilderApi;
use sp_api::{ProvideRuntimeApi, ApiExt};
/// Proposer factory.
pub struct ProposerFactory<C, A> where A: TransactionPool {
@@ -46,15 +44,16 @@ pub struct ProposerFactory<C, A> where A: TransactionPool {
}
impl<B, E, Block, RA, A> ProposerFactory<SubstrateClient<B, E, Block, RA>, A>
where
A: TransactionPool<Block=Block> + 'static,
B: sc_client_api::backend::Backend<Block, Blake2Hasher> + Send + Sync + 'static,
E: CallExecutor<Block, Blake2Hasher> + Send + Sync + Clone + 'static,
Block: BlockT<Hash=H256>,
RA: Send + Sync + 'static,
SubstrateClient<B, E, Block, RA>: ProvideRuntimeApi,
<SubstrateClient<B, E, Block, RA> as ProvideRuntimeApi>::Api:
BlockBuilderApi<Block, Error = sp_blockchain::Error>,
where
A: TransactionPool<Block = Block> + 'static,
B: backend::Backend<Block> + Send + Sync + 'static,
E: CallExecutor<Block> + Send + Sync + Clone + 'static,
Block: BlockT,
RA: Send + Sync + 'static,
SubstrateClient<B, E, Block, RA>: ProvideRuntimeApi<Block>,
<SubstrateClient<B, E, Block, RA> as ProvideRuntimeApi<Block>>::Api:
BlockBuilderApi<Block, Error = sp_blockchain::Error> +
ApiExt<Block, StateBackend = backend::StateBackendFor<B, Block>>,
{
pub fn init_with_now(
&mut self,
@@ -83,16 +82,17 @@ where
}
impl<B, E, Block, RA, A> sp_consensus::Environment<Block> for
ProposerFactory<SubstrateClient<B, E, Block, RA>, A>
where
A: TransactionPool<Block=Block> + 'static,
B: sc_client_api::backend::Backend<Block, Blake2Hasher> + Send + Sync + 'static,
E: CallExecutor<Block, Blake2Hasher> + Send + Sync + Clone + 'static,
Block: BlockT<Hash=H256>,
RA: Send + Sync + 'static,
SubstrateClient<B, E, Block, RA>: ProvideRuntimeApi,
<SubstrateClient<B, E, Block, RA> as ProvideRuntimeApi>::Api:
BlockBuilderApi<Block, Error = sp_blockchain::Error>,
ProposerFactory<SubstrateClient<B, E, Block, RA>, A>
where
A: TransactionPool<Block = Block> + 'static,
B: backend::Backend<Block> + Send + Sync + 'static,
E: CallExecutor<Block> + Send + Sync + Clone + 'static,
Block: BlockT,
RA: Send + Sync + 'static,
SubstrateClient<B, E, Block, RA>: ProvideRuntimeApi<Block>,
<SubstrateClient<B, E, Block, RA> as ProvideRuntimeApi<Block>>::Api:
BlockBuilderApi<Block, Error = sp_blockchain::Error> +
ApiExt<Block, StateBackend = backend::StateBackendFor<B, Block>>,
{
type Proposer = Proposer<Block, SubstrateClient<B, E, Block, RA>, A>;
type Error = sp_blockchain::Error;
@@ -121,18 +121,22 @@ struct ProposerInner<Block: BlockT, C, A: TransactionPool> {
}
impl<B, E, Block, RA, A> sp_consensus::Proposer<Block> for
Proposer<Block, SubstrateClient<B, E, Block, RA>, A>
where
A: TransactionPool<Block=Block> + 'static,
B: sc_client_api::backend::Backend<Block, Blake2Hasher> + Send + Sync + 'static,
E: CallExecutor<Block, Blake2Hasher> + Send + Sync + Clone + 'static,
Block: BlockT<Hash=H256>,
RA: Send + Sync + 'static,
SubstrateClient<B, E, Block, RA>: ProvideRuntimeApi,
<SubstrateClient<B, E, Block, RA> as ProvideRuntimeApi>::Api:
BlockBuilderApi<Block, Error = sp_blockchain::Error>,
Proposer<Block, SubstrateClient<B, E, Block, RA>, A>
where
A: TransactionPool<Block = Block> + 'static,
B: backend::Backend<Block> + Send + Sync + 'static,
E: CallExecutor<Block> + Send + Sync + Clone + 'static,
Block: BlockT,
RA: Send + Sync + 'static,
SubstrateClient<B, E, Block, RA>: ProvideRuntimeApi<Block>,
<SubstrateClient<B, E, Block, RA> as ProvideRuntimeApi<Block>>::Api:
BlockBuilderApi<Block, Error = sp_blockchain::Error> +
ApiExt<Block, StateBackend = backend::StateBackendFor<B, Block>>,
{
type Create = tokio_executor::blocking::Blocking<Result<Block, sp_blockchain::Error>>;
type Transaction = backend::TransactionFor<B, Block>;
type Proposal = tokio_executor::blocking::Blocking<
Result<Proposal<Block, Self::Transaction>, Self::Error>
>;
type Error = sp_blockchain::Error;
fn propose(
@@ -140,38 +144,45 @@ where
inherent_data: InherentData,
inherent_digests: DigestFor<Block>,
max_duration: time::Duration,
) -> Self::Create {
record_proof: RecordProof,
) -> Self::Proposal {
let inner = self.inner.clone();
tokio_executor::blocking::run(move || {
// leave some time for evaluation and block finalization (33%)
let deadline = (inner.now)() + max_duration - max_duration / 3;
inner.propose_with(inherent_data, inherent_digests, deadline)
inner.propose_with(inherent_data, inherent_digests, deadline, record_proof)
})
}
}
impl<Block, B, E, RA, A> ProposerInner<Block, SubstrateClient<B, E, Block, RA>, A> where
A: TransactionPool<Block=Block> + 'static,
B: sc_client_api::backend::Backend<Block, Blake2Hasher> + Send + Sync + 'static,
E: CallExecutor<Block, Blake2Hasher> + Send + Sync + Clone + 'static,
Block: BlockT<Hash=H256>,
impl<Block, B, E, RA, A> ProposerInner<Block, SubstrateClient<B, E, Block, RA>, A> where
A: TransactionPool<Block = Block>,
B: sc_client_api::backend::Backend<Block> + Send + Sync + 'static,
E: CallExecutor<Block> + Send + Sync + Clone + 'static,
Block: BlockT,
RA: Send + Sync + 'static,
SubstrateClient<B, E, Block, RA>: ProvideRuntimeApi,
<SubstrateClient<B, E, Block, RA> as ProvideRuntimeApi>::Api:
BlockBuilderApi<Block, Error = sp_blockchain::Error>,
SubstrateClient<B, E, Block, RA>: ProvideRuntimeApi<Block>,
<SubstrateClient<B, E, Block, RA> as ProvideRuntimeApi<Block>>::Api:
BlockBuilderApi<Block, Error = sp_blockchain::Error> +
ApiExt<Block, StateBackend = backend::StateBackendFor<B, Block>>,
{
fn propose_with(
&self,
inherent_data: InherentData,
inherent_digests: DigestFor<Block>,
deadline: time::Instant,
) -> Result<Block, sp_blockchain::Error> {
record_proof: RecordProof,
) -> Result<Proposal<Block, backend::TransactionFor<B, Block>>, sp_blockchain::Error> {
/// If the block is full we will attempt to push at most
/// this number of transactions before quitting for real.
/// It allows us to increase block utilization.
const MAX_SKIPPED_TRANSACTIONS: usize = 8;
let mut block_builder = self.client.new_block_at(&self.parent_id, inherent_digests)?;
let mut block_builder = self.client.new_block_at(
&self.parent_id,
inherent_digests,
record_proof,
)?;
// We don't check the API versions any further here since the dispatch compatibility
// check should be enough.
@@ -194,7 +205,10 @@ impl<Block, B, E, RA, A> ProposerInner<Block, SubstrateClient<B, E, Block, RA>,
debug!("Attempting to push transactions from the pool.");
for pending_tx in pending_iterator {
if (self.now)() > deadline {
debug!("Consensus deadline reached when pushing block transactions, proceeding with proposing.");
debug!(
"Consensus deadline reached when pushing block transactions, \
proceeding with proposing."
);
break;
}
@@ -232,7 +246,7 @@ impl<Block, B, E, RA, A> ProposerInner<Block, SubstrateClient<B, E, Block, RA>,
self.transaction_pool.remove_invalid(&unqueue_invalid);
let block = block_builder.bake()?;
let (block, storage_changes, proof) = block_builder.build()?.into_inner();
info!("Prepared block for proposing at {} [hash: {:?}; parent_hash: {}; extrinsics: [{}]]",
block.header().number(),
@@ -257,7 +271,7 @@ impl<Block, B, E, RA, A> ProposerInner<Block, SubstrateClient<B, E, Block, RA>,
error!("Failed to evaluate authored block: {:?}", err);
}
Ok(block)
Ok(Proposal { block, proof, storage_changes })
}
}
@@ -267,8 +281,14 @@ mod tests {
use parking_lot::Mutex;
use sp_consensus::Proposer;
use substrate_test_runtime_client::{self, runtime::{Extrinsic, Transfer}, AccountKeyring};
use substrate_test_runtime_client::{
runtime::{Extrinsic, Transfer}, AccountKeyring, DefaultTestClientBuilderExt,
TestClientBuilderExt,
};
use sc_transaction_pool::{BasicPool, FullChainApi};
use sp_api::Core;
use backend::Backend;
use sp_blockchain::HeaderBackend;
fn extrinsic(nonce: u64) -> Extrinsic {
Transfer {
@@ -308,12 +328,58 @@ mod tests {
// when
let deadline = time::Duration::from_secs(3);
let block = futures::executor::block_on(proposer.propose(Default::default(), Default::default(), deadline))
.unwrap();
let block = futures::executor::block_on(
proposer.propose(Default::default(), Default::default(), deadline, RecordProof::No)
).map(|r| r.block).unwrap();
// then
// block should have some extrinsics although we have some more in the pool.
assert_eq!(block.extrinsics().len(), 1);
assert_eq!(txpool.ready().count(), 2);
}
#[test]
fn proposed_storage_changes_should_match_execute_block_storage_changes() {
let (client, backend) = substrate_test_runtime_client::TestClientBuilder::new()
.build_with_backend();
let client = Arc::new(client);
let txpool = Arc::new(BasicPool::new(Default::default(), FullChainApi::new(client.clone())));
let genesis_hash = client.info().best_hash;
let block_id = BlockId::Hash(genesis_hash);
futures::executor::block_on(
txpool.submit_at(&BlockId::number(0), vec![extrinsic(0)]),
).unwrap();
let mut proposer_factory = ProposerFactory {
client: client.clone(),
transaction_pool: txpool.clone(),
};
let mut proposer = proposer_factory.init_with_now(
&client.header(&block_id).unwrap().unwrap(),
Box::new(move || time::Instant::now()),
).unwrap();
let deadline = time::Duration::from_secs(9);
let proposal = futures::executor::block_on(
proposer.propose(Default::default(), Default::default(), deadline, RecordProof::No),
).unwrap();
assert_eq!(proposal.block.extrinsics().len(), 1);
let api = client.runtime_api();
api.execute_block(&block_id, proposal.block).unwrap();
let state = backend.state_at(block_id).unwrap();
let changes_trie_storage = backend.changes_trie_storage();
let storage_changes = api.into_storage_changes(&state, changes_trie_storage, genesis_hash)
.unwrap();
assert_eq!(
proposal.storage_changes.transaction_storage_root,
storage_changes.transaction_storage_root,
);
}
}
+4 -3
View File
@@ -20,7 +20,7 @@
//!
//! ```
//! # use sc_basic_authority::ProposerFactory;
//! # use sp_consensus::{Environment, Proposer};
//! # use sp_consensus::{Environment, Proposer, RecordProof};
//! # use sp_runtime::generic::BlockId;
//! # use std::{sync::Arc, time::Duration};
//! # use substrate_test_runtime_client::{self, runtime::{Extrinsic, Transfer}, AccountKeyring};
@@ -43,12 +43,13 @@
//! let future = proposer.propose(
//! Default::default(),
//! Default::default(),
//! Duration::from_secs(2)
//! Duration::from_secs(2),
//! RecordProof::Yes,
//! );
//!
//! // We wait until the proposition is performed.
//! let block = futures::executor::block_on(future).unwrap();
//! println!("Generated block: {:?}", block);
//! println!("Generated block: {:?}", block.block);
//! ```
//!
+4 -2
View File
@@ -7,8 +7,10 @@ edition = "2018"
[dependencies]
sp-state-machine = { version = "2.0.0", path = "../../primitives/state-machine" }
sp-runtime = { version = "2.0.0", path = "../../primitives/runtime" }
sp-api = { version = "2.0.0", path = "../../primitives/api" }
sp-consensus = { version = "0.8.0", path = "../../primitives/consensus/common" }
sp-blockchain = { version = "2.0.0", path = "../../primitives/blockchain" }
sp-core = { version = "2.0.0", path = "../../primitives/core" }
codec = { package = "parity-scale-codec", version = "1.0.6", features = ["derive"] }
sp-block-builder = { version = "2.0.0", path = "../../primitives/block-builder" }
sp-api = { version = "2.0.0", path = "../../primitives/api" }
sc-client-api = { version = "2.0.0", path = "../api" }
codec = { package = "parity-scale-codec", version = "1.0.6", features = ["derive"] }
+77 -39
View File
@@ -29,32 +29,56 @@ use codec::Encode;
use sp_runtime::{
generic::BlockId,
traits::{
Header as HeaderT, Hash, Block as BlockT, HashFor, ProvideRuntimeApi, ApiRef, DigestFor,
NumberFor, One,
}
Header as HeaderT, Hash, Block as BlockT, HashFor, DigestFor, NumberFor, One, HasherFor,
},
};
use sp_blockchain::{ApplyExtrinsicFailed, Error};
use sp_core::ExecutionContext;
use sp_state_machine::StorageProof;
use sp_api::{Core, ApiExt, ApiErrorFor};
use sp_api::{Core, ApiExt, ApiErrorFor, ApiRef, ProvideRuntimeApi, StorageChanges, StorageProof};
use sp_consensus::RecordProof;
pub use sp_block_builder::BlockBuilder as BlockBuilderApi;
use sc_client_api::backend;
/// A block that was build by [`BlockBuilder`] plus some additional data.
///
/// This additional data includes the `storage_changes`, these changes can be applied to the
/// backend to get the state of the block. Furthermore an optional `proof` is included which
/// can be used to proof that the build block contains the expected data. The `proof` will
/// only be set when proof recording was activated.
pub struct BuiltBlock<Block: BlockT, StateBackend: backend::StateBackend<HasherFor<Block>>> {
/// The actual block that was build.
pub block: Block,
/// The changes that need to be applied to the backend to get the state of the build block.
pub storage_changes: StorageChanges<StateBackend, Block>,
/// An optional proof that was recorded while building the block.
pub proof: Option<StorageProof>,
}
impl<Block: BlockT, StateBackend: backend::StateBackend<HasherFor<Block>>> BuiltBlock<Block, StateBackend> {
/// Convert into the inner values.
pub fn into_inner(self) -> (Block, StorageChanges<StateBackend, Block>, Option<StorageProof>) {
(self.block, self.storage_changes, self.proof)
}
}
/// Utility for building new (valid) blocks from a stream of extrinsics.
pub struct BlockBuilder<'a, Block: BlockT, A: ProvideRuntimeApi> {
header: Block::Header,
pub struct BlockBuilder<'a, Block: BlockT, A: ProvideRuntimeApi<Block>, B> {
extrinsics: Vec<Block::Extrinsic>,
api: ApiRef<'a, A::Api>,
block_id: BlockId<Block>,
parent_hash: Block::Hash,
backend: &'a B,
}
impl<'a, Block, A> BlockBuilder<'a, Block, A>
impl<'a, Block, A, B> BlockBuilder<'a, Block, A, B>
where
Block: BlockT,
A: ProvideRuntimeApi + 'a,
A::Api: BlockBuilderApi<Block>,
ApiErrorFor<A, Block>: From<Error>,
A: ProvideRuntimeApi<Block> + 'a,
A::Api: BlockBuilderApi<Block, Error = Error> +
ApiExt<Block, StateBackend = backend::StateBackendFor<B, Block>>,
B: backend::Backend<Block>,
{
/// Create a new instance of builder based on the given `parent_hash` and `parent_number`.
///
@@ -65,8 +89,9 @@ where
api: &'a A,
parent_hash: Block::Hash,
parent_number: NumberFor<Block>,
proof_recording: bool,
record_proof: RecordProof,
inherent_digests: DigestFor<Block>,
backend: &'a B,
) -> Result<Self, ApiErrorFor<A, Block>> {
let header = <<Block as BlockT>::Header as HeaderT>::new(
parent_number + One::one(),
@@ -78,7 +103,7 @@ where
let mut api = api.runtime_api();
if proof_recording {
if record_proof.yes() {
api.record_proof();
}
@@ -89,10 +114,11 @@ where
)?;
Ok(Self {
header,
parent_hash,
extrinsics: Vec::new(),
api,
block_id,
backend,
})
}
@@ -122,7 +148,7 @@ where
extrinsics.push(xt);
Ok(())
}
Err(e) => Err(ApplyExtrinsicFailed::from(e).into())?,
Err(e) => Err(ApplyExtrinsicFailed::from(e).into()),
}
})
} else {
@@ -136,44 +162,56 @@ where
extrinsics.push(xt);
Ok(())
}
Err(tx_validity) => Err(ApplyExtrinsicFailed::Validity(tx_validity).into())?,
Err(tx_validity) => Err(ApplyExtrinsicFailed::Validity(tx_validity).into()),
}
})
}
}
/// Consume the builder to return a valid `Block` containing all pushed extrinsics.
pub fn bake(mut self) -> Result<Block, ApiErrorFor<A, Block>> {
self.bake_impl()?;
Ok(<Block as BlockT>::new(self.header, self.extrinsics))
}
fn bake_impl(&mut self) -> Result<(), ApiErrorFor<A, Block>> {
self.header = self.api.finalize_block_with_context(
/// Consume the builder to build a valid `Block` containing all pushed extrinsics.
///
/// Returns the build `Block`, the changes to the storage and an optional `StorageProof`
/// supplied by `self.api`, combined as [`BuiltBlock`].
/// The storage proof will be `Some(_)` when proof recording was enabled.
pub fn build(mut self) -> Result<
BuiltBlock<Block, backend::StateBackendFor<B, Block>>,
ApiErrorFor<A, Block>
> {
let header = self.api.finalize_block_with_context(
&self.block_id, ExecutionContext::BlockConstruction
)?;
debug_assert_eq!(
self.header.extrinsics_root().clone(),
header.extrinsics_root().clone(),
HashFor::<Block>::ordered_trie_root(
self.extrinsics.iter().map(Encode::encode).collect(),
),
);
Ok(())
}
/// Consume the builder to return a valid `Block` containing all pushed extrinsics
/// and the generated proof.
///
/// The proof will be `Some(_)`, if proof recording was enabled while creating
/// the block builder.
pub fn bake_and_extract_proof(mut self)
-> Result<(Block, Option<StorageProof>), ApiErrorFor<A, Block>>
{
self.bake_impl()?;
let proof = self.api.extract_proof();
Ok((<Block as BlockT>::new(self.header, self.extrinsics), proof))
let state = self.backend.state_at(self.block_id)?;
let changes_trie_storage = self.backend.changes_trie_storage();
let parent_hash = self.parent_hash;
// The unsafe is required because the consume requires that we drop/consume the inner api
// (what we do here).
let storage_changes = self.api.into_storage_changes(
&state,
changes_trie_storage,
parent_hash,
);
// We need to destroy the state, before we check if `storage_changes` is `Ok(_)`
{
let _lock = self.backend.get_import_lock().read();
self.backend.destroy_state(state)?;
}
Ok(BuiltBlock {
block: <Block as BlockT>::new(header, self.extrinsics),
storage_changes: storage_changes?,
proof,
})
}
}
+80 -55
View File
@@ -54,15 +54,20 @@ use sp_blockchain::{
};
use sp_block_builder::BlockBuilder as BlockBuilderApi;
use sp_runtime::{generic::{BlockId, OpaqueDigestItemId}, Justification};
use sp_runtime::traits::{Block as BlockT, Header, DigestItemFor, ProvideRuntimeApi, Zero, Member};
use sp_runtime::traits::{Block as BlockT, Header, DigestItemFor, Zero, Member};
use sp_api::ProvideRuntimeApi;
use sp_core::crypto::Pair;
use sp_inherents::{InherentDataProviders, InherentData};
use sp_timestamp::{
TimestampInherentData, InherentType as TimestampInherent, InherentError as TIError
};
use sc_telemetry::{telemetry, CONSENSUS_TRACE, CONSENSUS_DEBUG, CONSENSUS_INFO};
use sc_consensus_slots::{CheckedHeader, SlotWorker, SlotInfo, SlotCompatible};
use sc_consensus_slots::check_equivocation;
use sc_consensus_slots::{
CheckedHeader, SlotWorker, SlotInfo, SlotCompatible, StorageChanges, check_equivocation,
};
use sc_keystore::KeyStorePtr;
use sp_api::ApiExt;
@@ -91,7 +96,7 @@ impl SlotDuration {
where
A: Codec,
B: BlockT,
C: AuxStore + ProvideRuntimeApi,
C: AuxStore + ProvideRuntimeApi<B>,
C::Api: AuraApi<B, A, Error = sp_blockchain::Error>,
{
sc_consensus_slots::SlotDuration::get_or_compute(client, |a, b| a.slot_duration(b)).map(Self)
@@ -137,7 +142,7 @@ impl SlotCompatible for AuraSlotCompatible {
}
/// Start the aura worker. The returned future should be run in a futures executor.
pub fn start_aura<B, C, SC, E, I, P, SO, CAW, Error, H>(
pub fn start_aura<B, C, SC, E, I, P, SO, CAW, Error>(
slot_duration: SlotDuration,
client: Arc<C>,
select_chain: SC,
@@ -149,19 +154,17 @@ pub fn start_aura<B, C, SC, E, I, P, SO, CAW, Error, H>(
keystore: KeyStorePtr,
can_author_with: CAW,
) -> Result<impl futures01::Future<Item = (), Error = ()>, sp_consensus::Error> where
B: BlockT<Header=H>,
C: ProvideRuntimeApi + BlockOf + ProvideCache<B> + AuxStore + Send + Sync,
B: BlockT,
C: ProvideRuntimeApi<B> + BlockOf + ProvideCache<B> + AuxStore + Send + Sync,
C::Api: AuraApi<B, AuthorityId<P>>,
SC: SelectChain<B>,
E: Environment<B, Error=Error> + Send + Sync + 'static,
E::Proposer: Proposer<B, Error=Error>,
<E::Proposer as Proposer<B>>::Create: Unpin + Send,
E: Environment<B, Error = Error> + Send + Sync + 'static,
E::Proposer: Proposer<B, Error = Error, Transaction = sp_api::TransactionFor<C, B>>,
P: Pair + Send + Sync,
P::Public: Hash + Member + Encode + Decode,
P::Signature: Hash + Member + Encode + Decode,
H: Header<Hash=B::Hash>,
I: BlockImport<B> + Send + Sync + 'static,
Error: ::std::error::Error + Send + From<::sp_consensus::Error> + From<I::Error> + 'static,
I: BlockImport<B, Transaction = sp_api::TransactionFor<C, B>> + Send + Sync + 'static,
Error: std::error::Error + Send + From<sp_consensus::Error> + 'static,
SO: SyncOracle + Send + Sync + Clone,
CAW: CanAuthorWith<B> + Send,
{
@@ -199,20 +202,18 @@ struct AuraWorker<C, E, I, P, SO> {
_key_type: PhantomData<P>,
}
impl<H, B, C, E, I, P, Error, SO> sc_consensus_slots::SimpleSlotWorker<B> for AuraWorker<C, E, I, P, SO> where
B: BlockT<Header=H>,
C: ProvideRuntimeApi + BlockOf + ProvideCache<B> + Sync,
impl<B, C, E, I, P, Error, SO> sc_consensus_slots::SimpleSlotWorker<B> for AuraWorker<C, E, I, P, SO> where
B: BlockT,
C: ProvideRuntimeApi<B> + BlockOf + ProvideCache<B> + Sync,
C::Api: AuraApi<B, AuthorityId<P>>,
E: Environment<B, Error=Error>,
E::Proposer: Proposer<B, Error=Error>,
<E::Proposer as Proposer<B>>::Create: Unpin + Send,
H: Header<Hash=B::Hash>,
I: BlockImport<B> + Send + Sync + 'static,
E: Environment<B, Error = Error>,
E::Proposer: Proposer<B, Error = Error, Transaction = sp_api::TransactionFor<C, B>>,
I: BlockImport<B, Transaction = sp_api::TransactionFor<C, B>> + Send + Sync + 'static,
P: Pair + Send + Sync,
P::Public: Member + Encode + Decode + Hash,
P::Signature: Member + Encode + Decode + Hash + Debug,
SO: SyncOracle + Send + Clone,
Error: ::std::error::Error + Send + From<::sp_consensus::Error> + From<I::Error> + 'static,
Error: std::error::Error + Send + From<sp_consensus::Error> + 'static,
{
type BlockImport = I;
type SyncOracle = SO;
@@ -228,7 +229,11 @@ impl<H, B, C, E, I, P, Error, SO> sc_consensus_slots::SimpleSlotWorker<B> for Au
self.block_import.clone()
}
fn epoch_data(&self, header: &B::Header, _slot_number: u64) -> Result<Self::EpochData, sp_consensus::Error> {
fn epoch_data(
&self,
header: &B::Header,
_slot_number: u64,
) -> Result<Self::EpochData, sp_consensus::Error> {
authorities(self.client.as_ref(), &BlockId::Hash(header.hash()))
}
@@ -250,7 +255,11 @@ impl<H, B, C, E, I, P, Error, SO> sc_consensus_slots::SimpleSlotWorker<B> for Au
})
}
fn pre_digest_data(&self, slot_number: u64, _claim: &Self::Claim) -> Vec<sp_runtime::DigestItem<B::Hash>> {
fn pre_digest_data(
&self,
slot_number: u64,
_claim: &Self::Claim,
) -> Vec<sp_runtime::DigestItem<B::Hash>> {
vec![
<DigestItemFor<B> as CompatibleDigestItem<P>>::aura_pre_digest(slot_number),
]
@@ -260,9 +269,10 @@ impl<H, B, C, E, I, P, Error, SO> sc_consensus_slots::SimpleSlotWorker<B> for Au
B::Header,
&B::Hash,
Vec<B::Extrinsic>,
StorageChanges<sp_api::TransactionFor<C, B>, B>,
Self::Claim,
) -> sp_consensus::BlockImportParams<B> + Send> {
Box::new(|header, header_hash, body, pair| {
) -> sp_consensus::BlockImportParams<B, sp_api::TransactionFor<C, B>> + Send> {
Box::new(|header, header_hash, body, storage_changes, pair| {
// sign the pre-sealed hash of the block and then
// add it to a digest item.
let signature = pair.sign(header_hash.as_ref());
@@ -274,6 +284,7 @@ impl<H, B, C, E, I, P, Error, SO> sc_consensus_slots::SimpleSlotWorker<B> for Au
justification: None,
post_digests: vec![signature_digest_item],
body: Some(body),
storage_changes: Some(storage_changes),
finalized: false,
auxiliary: Vec::new(),
fork_choice: ForkChoiceStrategy::LongestChain,
@@ -324,20 +335,18 @@ impl<H, B, C, E, I, P, Error, SO> sc_consensus_slots::SimpleSlotWorker<B> for Au
}
}
impl<H, B: BlockT, C, E, I, P, Error, SO> SlotWorker<B> for AuraWorker<C, E, I, P, SO> where
B: BlockT<Header=H>,
C: ProvideRuntimeApi + BlockOf + ProvideCache<B> + Sync + Send,
impl<B: BlockT, C, E, I, P, Error, SO> SlotWorker<B> for AuraWorker<C, E, I, P, SO> where
B: BlockT,
C: ProvideRuntimeApi<B> + BlockOf + ProvideCache<B> + Sync + Send,
C::Api: AuraApi<B, AuthorityId<P>>,
E: Environment<B, Error=Error> + Send + Sync,
E::Proposer: Proposer<B, Error=Error>,
<E::Proposer as Proposer<B>>::Create: Unpin + Send + 'static,
H: Header<Hash=B::Hash>,
I: BlockImport<B> + Send + Sync + 'static,
E: Environment<B, Error = Error> + Send + Sync,
E::Proposer: Proposer<B, Error = Error, Transaction = sp_api::TransactionFor<C, B>>,
I: BlockImport<B, Transaction = sp_api::TransactionFor<C, B>> + Send + Sync + 'static,
P: Pair + Send + Sync,
P::Public: Member + Encode + Decode + Hash,
P::Signature: Member + Encode + Decode + Hash + Debug,
SO: SyncOracle + Send + Sync + Clone,
Error: ::std::error::Error + Send + From<::sp_consensus::Error> + From<I::Error> + 'static,
Error: std::error::Error + Send + From<sp_consensus::Error> + 'static,
{
type OnSlot = Pin<Box<dyn Future<Output = Result<(), sp_consensus::Error>> + Send>>;
@@ -489,7 +498,7 @@ impl<C, P, T> AuraVerifier<C, P, T>
inherent_data: InherentData,
timestamp_now: u64,
) -> Result<(), Error<B>>
where C: ProvideRuntimeApi, C::Api: BlockBuilderApi<B, Error = sp_blockchain::Error>
where C: ProvideRuntimeApi<B>, C::Api: BlockBuilderApi<B, Error = sp_blockchain::Error>
{
const MAX_TIMESTAMP_DRIFT_SECS: u64 = 60;
@@ -535,7 +544,12 @@ impl<C, P, T> AuraVerifier<C, P, T>
#[forbid(deprecated)]
impl<B: BlockT, C, P, T> Verifier<B> for AuraVerifier<C, P, T> where
C: ProvideRuntimeApi + Send + Sync + sc_client_api::backend::AuxStore + ProvideCache<B> + BlockOf,
C: ProvideRuntimeApi<B> +
Send +
Sync +
sc_client_api::backend::AuxStore +
ProvideCache<B> +
BlockOf,
C::Api: BlockBuilderApi<B> + AuraApi<B, AuthorityId<P>> + ApiExt<B, Error = sp_blockchain::Error>,
DigestItemFor<B>: CompatibleDigestItem<P>,
P: Pair + Send + Sync + 'static,
@@ -549,7 +563,7 @@ impl<B: BlockT, C, P, T> Verifier<B> for AuraVerifier<C, P, T> where
header: B::Header,
justification: Option<Justification>,
mut body: Option<Vec<B::Extrinsic>>,
) -> Result<(BlockImportParams<B>, Option<Vec<(CacheKeyId, Vec<u8>)>>), String> {
) -> Result<(BlockImportParams<B, ()>, Option<Vec<(CacheKeyId, Vec<u8>)>>), String> {
let mut inherent_data = self.inherent_data_providers
.create_inherent_data()
.map_err(|e| e.into_string())?;
@@ -623,6 +637,7 @@ impl<B: BlockT, C, P, T> Verifier<B> for AuraVerifier<C, P, T> where
header: pre_header,
post_digests: vec![seal],
body,
storage_changes: None,
finalized: false,
justification,
auxiliary: Vec::new(),
@@ -647,7 +662,7 @@ impl<B: BlockT, C, P, T> Verifier<B> for AuraVerifier<C, P, T> where
fn initialize_authorities_cache<A, B, C>(client: &C) -> Result<(), ConsensusError> where
A: Codec,
B: BlockT,
C: ProvideRuntimeApi + BlockOf + ProvideCache<B>,
C: ProvideRuntimeApi<B> + BlockOf + ProvideCache<B>,
C::Api: AuraApi<B, A>,
{
// no cache => no initialization
@@ -681,7 +696,7 @@ fn initialize_authorities_cache<A, B, C>(client: &C) -> Result<(), ConsensusErro
fn authorities<A, B, C>(client: &C, at: &BlockId<B>) -> Result<Vec<A>, ConsensusError> where
A: Codec,
B: BlockT,
C: ProvideRuntimeApi + BlockOf + ProvideCache<B>,
C: ProvideRuntimeApi<B> + BlockOf + ProvideCache<B>,
C::Api: AuraApi<B, A>,
{
client
@@ -695,7 +710,7 @@ fn authorities<A, B, C>(client: &C, at: &BlockId<B>) -> Result<Vec<A>, Consensus
}
/// The Aura import queue type.
pub type AuraImportQueue<B> = BasicQueue<B>;
pub type AuraImportQueue<B, Transaction> = BasicQueue<B, Transaction>;
/// Register the aura inherent data provider, if not registered already.
fn register_aura_inherent_data_provider(
@@ -744,14 +759,15 @@ impl<Block: BlockT, C, I: BlockImport<Block>, P> AuraBlockImport<Block, C, I, P>
}
impl<Block: BlockT, C, I, P> BlockImport<Block> for AuraBlockImport<Block, C, I, P> where
I: BlockImport<Block> + Send + Sync,
I: BlockImport<Block, Transaction = sp_api::TransactionFor<C, Block>> + Send + Sync,
I::Error: Into<ConsensusError>,
C: HeaderBackend<Block>,
C: HeaderBackend<Block> + ProvideRuntimeApi<Block>,
P: Pair + Send + Sync + 'static,
P::Public: Clone + Eq + Send + Sync + Hash + Debug + Encode + Decode,
P::Signature: Encode + Decode,
{
type Error = ConsensusError;
type Transaction = sp_api::TransactionFor<C, Block>;
fn check_block(
&mut self,
@@ -762,7 +778,7 @@ impl<Block: BlockT, C, I, P> BlockImport<Block> for AuraBlockImport<Block, C, I,
fn import_block(
&mut self,
block: BlockImportParams<Block>,
block: BlockImportParams<Block, Self::Transaction>,
new_cache: HashMap<CacheKeyId, Vec<u8>>,
) -> Result<ImportResult, Self::Error> {
let hash = block.post_header().hash();
@@ -790,8 +806,7 @@ impl<Block: BlockT, C, I, P> BlockImport<Block> for AuraBlockImport<Block, C, I,
);
}
self.inner.import_block(block, new_cache)
.map_err(Into::into)
self.inner.import_block(block, new_cache).map_err(Into::into)
}
}
@@ -804,11 +819,11 @@ pub fn import_queue<B, I, C, P, T>(
client: Arc<C>,
inherent_data_providers: InherentDataProviders,
transaction_pool: Option<Arc<T>>,
) -> Result<AuraImportQueue<B>, sp_consensus::Error> where
) -> Result<AuraImportQueue<B, sp_api::TransactionFor<C, B>>, sp_consensus::Error> where
B: BlockT,
C::Api: BlockBuilderApi<B> + AuraApi<B, AuthorityId<P>> + ApiExt<B, Error = sp_blockchain::Error>,
C: 'static + ProvideRuntimeApi + BlockOf + ProvideCache<B> + Send + Sync + AuxStore + HeaderBackend<B>,
I: BlockImport<B,Error=ConsensusError> + Send + Sync + 'static,
C: 'static + ProvideRuntimeApi<B> + BlockOf + ProvideCache<B> + Send + Sync + AuxStore + HeaderBackend<B>,
I: BlockImport<B, Error=ConsensusError, Transaction = sp_api::TransactionFor<C, B>> + Send + Sync + 'static,
DigestItemFor<B>: CompatibleDigestItem<P>,
P: Pair + Send + Sync + 'static,
P::Public: Clone + Eq + Send + Sync + Hash + Debug + Encode + Decode,
@@ -835,7 +850,7 @@ pub fn import_queue<B, I, C, P, T>(
#[cfg(test)]
mod tests {
use super::*;
use sp_consensus::NoNetwork as DummyOracle;
use sp_consensus::{NoNetwork as DummyOracle, Proposal, RecordProof};
use sc_network_test::{Block as TestBlock, *};
use sp_runtime::traits::{Block as BlockT, DigestFor};
use sc_network::config::ProtocolConfig;
@@ -870,16 +885,26 @@ mod tests {
impl Proposer<TestBlock> for DummyProposer {
type Error = Error;
type Create = future::Ready<Result<TestBlock, Error>>;
type Transaction = sc_client_api::TransactionFor<
substrate_test_runtime_client::Backend,
TestBlock
>;
type Proposal = future::Ready<Result<Proposal<TestBlock, Self::Transaction>, Error>>;
fn propose(
&mut self,
_: InherentData,
digests: DigestFor<TestBlock>,
_: Duration,
) -> Self::Create {
let r = self.1.new_block(digests).unwrap().bake().map_err(|e| e.into());
future::ready(r)
_: RecordProof,
) -> Self::Proposal {
let r = self.1.new_block(digests).unwrap().build().map_err(|e| e.into());
future::ready(r.map(|b| Proposal {
block: b.block,
proof: b.proof,
storage_changes: b.storage_changes,
}))
}
}
@@ -983,7 +1008,7 @@ mod tests {
&inherent_data_providers, slot_duration.get()
).expect("Registers aura inherent data provider");
let aura = start_aura::<_, _, _, _, _, AuthorityPair, _, _, _, _>(
let aura = start_aura::<_, _, _, _, _, AuthorityPair, _, _, _>(
slot_duration,
client.clone(),
select_chain,
@@ -27,7 +27,6 @@ use sp_runtime::traits::{Block as BlockT, NumberFor, One, Zero};
use codec::{Encode, Decode};
use sc_client_api::utils::is_descendent_of;
use sp_blockchain::{HeaderMetadata, HeaderBackend, Error as ClientError};
use sp_core::H256;
use std::ops::Add;
/// A builder for `is_descendent_of` functions.
@@ -57,17 +56,15 @@ pub(crate) fn descendent_query<H, Block>(client: &H) -> HeaderBackendDescendentB
/// `IsDescendentOfBuilder` for header backends.
pub(crate) struct HeaderBackendDescendentBuilder<H, Block>(H, std::marker::PhantomData<Block>);
// TODO: relying on Hash = H256 is awful.
// https://github.com/paritytech/substrate/issues/3624
impl<'a, H, Block> IsDescendentOfBuilder<H256>
impl<'a, H, Block> IsDescendentOfBuilder<Block::Hash>
for HeaderBackendDescendentBuilder<&'a H, Block> where
H: HeaderBackend<Block> + HeaderMetadata<Block, Error=ClientError>,
Block: BlockT<Hash = H256>,
Block: BlockT,
{
type Error = ClientError;
type IsDescendentOf = Box<dyn Fn(&H256, &H256) -> Result<bool, ClientError> + 'a>;
type IsDescendentOf = Box<dyn Fn(&Block::Hash, &Block::Hash) -> Result<bool, ClientError> + 'a>;
fn build_is_descendent_of(&self, current: Option<(H256, H256)>)
fn build_is_descendent_of(&self, current: Option<(Block::Hash, Block::Hash)>)
-> Self::IsDescendentOf
{
Box::new(is_descendent_of(self.0, current))
+89 -64
View File
@@ -69,14 +69,14 @@ use sp_consensus::{ImportResult, CanAuthorWith};
use sp_consensus::import_queue::{
BoxJustificationImport, BoxFinalityProofImport,
};
use sp_runtime::{generic::{BlockId, OpaqueDigestItemId}, Justification};
use sp_runtime::traits::{
Block as BlockT, Header, DigestItemFor, ProvideRuntimeApi,
Zero,
use sp_runtime::{
generic::{BlockId, OpaqueDigestItemId}, Justification,
traits::{Block as BlockT, Header, DigestItemFor, Zero},
};
use sp_api::ProvideRuntimeApi;
use sc_keystore::KeyStorePtr;
use parking_lot::Mutex;
use sp_core::{Blake2Hasher, H256, Pair};
use sp_core::Pair;
use sp_inherents::{InherentDataProviders, InherentData};
use sc_telemetry::{telemetry, CONSENSUS_TRACE, CONSENSUS_DEBUG};
use sp_consensus::{
@@ -96,10 +96,11 @@ use sc_client::Client;
use sp_block_builder::BlockBuilder as BlockBuilderApi;
use sc_consensus_slots::{CheckedHeader, check_equivocation};
use futures::prelude::*;
use log::{warn, debug, info, trace};
use sc_consensus_slots::{SlotWorker, SlotInfo, SlotCompatible};
use sc_consensus_slots::{
SlotWorker, SlotInfo, SlotCompatible, StorageChanges, CheckedHeader, check_equivocation,
};
use epoch_changes::descendent_query;
use sp_blockchain::{
Result as ClientResult, Error as ClientError,
@@ -207,7 +208,7 @@ impl Config {
/// Either fetch the slot duration from disk or compute it from the genesis
/// state.
pub fn get_or_compute<B: BlockT, C>(client: &C) -> ClientResult<Self> where
C: AuxStore + ProvideRuntimeApi, C::Api: BabeApi<B, Error = sp_blockchain::Error>,
C: AuxStore + ProvideRuntimeApi<B>, C::Api: BabeApi<B, Error = sp_blockchain::Error>,
{
trace!(target: "babe", "Getting slot duration");
match sc_consensus_slots::SlotDuration::get_or_compute(client, |a, b| a.configuration(b)).map(Self) {
@@ -291,16 +292,16 @@ pub fn start_babe<B, C, SC, E, I, SO, CAW, Error>(BabeParams {
impl futures01::Future<Item=(), Error=()>,
sp_consensus::Error,
> where
B: BlockT<Hash=H256>,
C: ProvideRuntimeApi + ProvideCache<B> + ProvideUncles<B> + BlockchainEvents<B>
+ HeaderBackend<B> + HeaderMetadata<B, Error=ClientError> + Send + Sync + 'static,
B: BlockT,
C: ProvideRuntimeApi<B> + ProvideCache<B> + ProvideUncles<B> + BlockchainEvents<B>
+ HeaderBackend<B> + HeaderMetadata<B, Error = ClientError> + Send + Sync + 'static,
C::Api: BabeApi<B>,
SC: SelectChain<B> + 'static,
E: Environment<B, Error=Error> + Send + Sync,
E::Proposer: Proposer<B, Error=Error>,
<E::Proposer as Proposer<B>>::Create: Unpin + Send + 'static,
I: BlockImport<B,Error=ConsensusError> + Send + Sync + 'static,
Error: std::error::Error + Send + From<::sp_consensus::Error> + From<I::Error> + 'static,
E: Environment<B, Error = Error> + Send + Sync,
E::Proposer: Proposer<B, Error = Error, Transaction = sp_api::TransactionFor<C, B>>,
I: BlockImport<B, Error = ConsensusError, Transaction = sp_api::TransactionFor<C, B>> + Send
+ Sync + 'static,
Error: std::error::Error + Send + From<ConsensusError> + From<I::Error> + 'static,
SO: SyncOracle + Send + Sync + Clone,
CAW: CanAuthorWith<B> + Send,
{
@@ -349,15 +350,17 @@ struct BabeWorker<B: BlockT, C, E, I, SO> {
}
impl<B, C, E, I, Error, SO> sc_consensus_slots::SimpleSlotWorker<B> for BabeWorker<B, C, E, I, SO> where
B: BlockT<Hash=H256>,
C: ProvideRuntimeApi + ProvideCache<B> + HeaderBackend<B> + HeaderMetadata<B, Error=ClientError>,
B: BlockT,
C: ProvideRuntimeApi<B> +
ProvideCache<B> +
HeaderBackend<B> +
HeaderMetadata<B, Error = ClientError>,
C::Api: BabeApi<B>,
E: Environment<B, Error=Error>,
E::Proposer: Proposer<B, Error=Error>,
<E::Proposer as Proposer<B>>::Create: Unpin + Send + 'static,
I: BlockImport<B> + Send + Sync + 'static,
E: Environment<B, Error = Error>,
E::Proposer: Proposer<B, Error = Error, Transaction = sp_api::TransactionFor<C, B>>,
I: BlockImport<B, Transaction = sp_api::TransactionFor<C, B>> + Send + Sync + 'static,
SO: SyncOracle + Send + Clone,
Error: std::error::Error + Send + From<::sp_consensus::Error> + From<I::Error> + 'static,
Error: std::error::Error + Send + From<ConsensusError> + From<I::Error> + 'static,
{
type EpochData = Epoch;
type Claim = (BabePreDigest, AuthorityPair);
@@ -373,7 +376,11 @@ impl<B, C, E, I, Error, SO> sc_consensus_slots::SimpleSlotWorker<B> for BabeWork
self.block_import.clone()
}
fn epoch_data(&self, parent: &B::Header, slot_number: u64) -> Result<Self::EpochData, sp_consensus::Error> {
fn epoch_data(
&self,
parent: &B::Header,
slot_number: u64,
) -> Result<Self::EpochData, ConsensusError> {
self.epoch_changes.lock().epoch_for_child_of(
descendent_query(&*self.client),
&parent.hash(),
@@ -411,7 +418,11 @@ impl<B, C, E, I, Error, SO> sc_consensus_slots::SimpleSlotWorker<B> for BabeWork
s
}
fn pre_digest_data(&self, _slot_number: u64, claim: &Self::Claim) -> Vec<sp_runtime::DigestItem<B::Hash>> {
fn pre_digest_data(
&self,
_slot_number: u64,
claim: &Self::Claim,
) -> Vec<sp_runtime::DigestItem<B::Hash>> {
vec![
<DigestItemFor<B> as CompatibleDigestItem>::babe_pre_digest(claim.0.clone()),
]
@@ -421,20 +432,22 @@ impl<B, C, E, I, Error, SO> sc_consensus_slots::SimpleSlotWorker<B> for BabeWork
B::Header,
&B::Hash,
Vec<B::Extrinsic>,
StorageChanges<I::Transaction, B>,
Self::Claim,
) -> sp_consensus::BlockImportParams<B> + Send> {
Box::new(|header, header_hash, body, (_, pair)| {
) -> sp_consensus::BlockImportParams<B, I::Transaction> + Send> {
Box::new(|header, header_hash, body, storage_changes, (_, pair)| {
// sign the pre-sealed hash of the block and then
// add it to a digest item.
let signature = pair.sign(header_hash.as_ref());
let signature_digest_item = <DigestItemFor<B> as CompatibleDigestItem>::babe_seal(signature);
let digest_item = <DigestItemFor<B> as CompatibleDigestItem>::babe_seal(signature);
BlockImportParams {
origin: BlockOrigin::Own,
header,
justification: None,
post_digests: vec![signature_digest_item],
post_digests: vec![digest_item],
body: Some(body),
storage_changes: Some(storage_changes),
finalized: false,
auxiliary: Vec::new(), // block-weight is written in block import.
// TODO: block-import handles fork choice and this shouldn't even have the
@@ -500,15 +513,17 @@ impl<B, C, E, I, Error, SO> sc_consensus_slots::SimpleSlotWorker<B> for BabeWork
}
impl<B, C, E, I, Error, SO> SlotWorker<B> for BabeWorker<B, C, E, I, SO> where
B: BlockT<Hash=H256>,
C: ProvideRuntimeApi + ProvideCache<B> + HeaderBackend<B> + HeaderMetadata<B, Error=ClientError> + Send + Sync,
B: BlockT,
C: ProvideRuntimeApi<B> +
ProvideCache<B> +
HeaderBackend<B> +
HeaderMetadata<B, Error = ClientError> + Send + Sync,
C::Api: BabeApi<B>,
E: Environment<B, Error=Error> + Send + Sync,
E::Proposer: Proposer<B, Error=Error>,
<E::Proposer as Proposer<B>>::Create: Unpin + Send + 'static,
I: BlockImport<B> + Send + Sync + 'static,
E: Environment<B, Error = Error> + Send + Sync,
E::Proposer: Proposer<B, Error = Error, Transaction = sp_api::TransactionFor<C, B>>,
I: BlockImport<B, Transaction = sp_api::TransactionFor<C, B>> + Send + Sync + 'static,
SO: SyncOracle + Send + Sync + Clone,
Error: std::error::Error + Send + From<::sp_consensus::Error> + From<I::Error> + 'static,
Error: std::error::Error + Send + From<sp_consensus::Error> + From<I::Error> + 'static,
{
type OnSlot = Pin<Box<dyn Future<Output = Result<(), sp_consensus::Error>> + Send>>;
@@ -603,7 +618,9 @@ impl<B, E, Block: BlockT, RA, PRA> BabeVerifier<B, E, Block, RA, PRA> {
block_id: BlockId<Block>,
inherent_data: InherentData,
) -> Result<(), Error<Block>>
where PRA: ProvideRuntimeApi, PRA::Api: BlockBuilderApi<Block, Error = sp_blockchain::Error>
where
PRA: ProvideRuntimeApi<Block>,
PRA::Api: BlockBuilderApi<Block, Error = sp_blockchain::Error>
{
let inherent_res = self.api.runtime_api().check_inherents(
&block_id,
@@ -667,11 +684,11 @@ fn median_algorithm(
}
impl<B, E, Block, RA, PRA> Verifier<Block> for BabeVerifier<B, E, Block, RA, PRA> where
Block: BlockT<Hash=H256>,
B: Backend<Block, Blake2Hasher> + 'static,
E: CallExecutor<Block, Blake2Hasher> + 'static + Clone + Send + Sync,
Block: BlockT,
B: Backend<Block> + 'static,
E: CallExecutor<Block> + 'static + Clone + Send + Sync,
RA: Send + Sync,
PRA: ProvideRuntimeApi + Send + Sync + AuxStore + ProvideCache<Block>,
PRA: ProvideRuntimeApi<Block> + Send + Sync + AuxStore + ProvideCache<Block>,
PRA::Api: BlockBuilderApi<Block, Error = sp_blockchain::Error>
+ BabeApi<Block, Error = sp_blockchain::Error>,
{
@@ -681,7 +698,7 @@ impl<B, E, Block, RA, PRA> Verifier<Block> for BabeVerifier<B, E, Block, RA, PRA
header: Block::Header,
justification: Option<Justification>,
mut body: Option<Vec<Block::Extrinsic>>,
) -> Result<(BlockImportParams<Block>, Option<Vec<(CacheKeyId, Vec<u8>)>>), String> {
) -> Result<(BlockImportParams<Block, ()>, Option<Vec<(CacheKeyId, Vec<u8>)>>), String> {
trace!(
target: "babe",
"Verifying origin: {:?} header: {:?} justification: {:?} body: {:?}",
@@ -785,6 +802,7 @@ impl<B, E, Block, RA, PRA> Verifier<Block> for BabeVerifier<B, E, Block, RA, PRA
header: pre_header,
post_digests: vec![verified_info.seal],
body,
storage_changes: None,
finalized: false,
justification,
auxiliary: Vec::new(),
@@ -810,7 +828,7 @@ impl<B, E, Block, RA, PRA> Verifier<Block> for BabeVerifier<B, E, Block, RA, PRA
}
/// The BABE import queue type.
pub type BabeImportQueue<B> = BasicQueue<B>;
pub type BabeImportQueue<B, Transaction> = BasicQueue<B, Transaction>;
/// Register the babe inherent data provider, if not registered already.
fn register_babe_inherent_data_provider(
@@ -875,20 +893,22 @@ impl<B, E, Block: BlockT, I, RA, PRA> BabeBlockImport<B, E, Block, I, RA, PRA> {
}
impl<B, E, Block, I, RA, PRA> BlockImport<Block> for BabeBlockImport<B, E, Block, I, RA, PRA> where
Block: BlockT<Hash=H256>,
I: BlockImport<Block> + Send + Sync,
Block: BlockT,
I: BlockImport<Block, Transaction = sp_api::TransactionFor<PRA, Block>> + Send + Sync,
I::Error: Into<ConsensusError>,
B: Backend<Block, Blake2Hasher> + 'static,
E: CallExecutor<Block, Blake2Hasher> + 'static + Clone + Send + Sync,
B: Backend<Block> + 'static,
E: CallExecutor<Block> + 'static + Clone + Send + Sync,
Client<B, E, Block, RA>: AuxStore,
RA: Send + Sync,
PRA: ProvideRuntimeApi + ProvideCache<Block>,
PRA::Api: BabeApi<Block>,
PRA: ProvideRuntimeApi<Block> + ProvideCache<Block>,
PRA::Api: BabeApi<Block> + ApiExt<Block, StateBackend = B::State>,
{
type Error = ConsensusError;
type Transaction = sp_api::TransactionFor<PRA, Block>;
fn import_block(
&mut self,
mut block: BlockImportParams<Block>,
mut block: BlockImportParams<Block, Self::Transaction>,
new_cache: HashMap<CacheKeyId, Vec<u8>>,
) -> Result<ImportResult, Self::Error> {
let hash = block.post_header().hash();
@@ -1099,9 +1119,9 @@ fn prune_finalized<B, E, Block, RA>(
client: &Client<B, E, Block, RA>,
epoch_changes: &mut EpochChangesFor<Block>,
) -> Result<(), ConsensusError> where
Block: BlockT<Hash=H256>,
E: CallExecutor<Block, Blake2Hasher> + Send + Sync,
B: Backend<Block, Blake2Hasher>,
Block: BlockT,
E: CallExecutor<Block> + Send + Sync,
B: Backend<Block>,
RA: Send + Sync,
{
let info = client.chain_info();
@@ -1133,15 +1153,16 @@ fn prune_finalized<B, E, Block, RA>(
///
/// Also returns a link object used to correctly instantiate the import queue
/// and background worker.
pub fn block_import<B, E, Block: BlockT<Hash=H256>, I, RA, PRA>(
pub fn block_import<B, E, Block: BlockT, I, RA, PRA>(
config: Config,
wrapped_block_import: I,
client: Arc<Client<B, E, Block, RA>>,
api: Arc<PRA>,
) -> ClientResult<(BabeBlockImport<B, E, Block, I, RA, PRA>, BabeLink<Block>)> where
B: Backend<Block, Blake2Hasher>,
E: CallExecutor<Block, Blake2Hasher> + Send + Sync,
B: Backend<Block>,
E: CallExecutor<Block> + Send + Sync,
RA: Send + Sync,
Client<B, E, Block, RA>: AuxStore,
{
let epoch_changes = aux_schema::load_epoch_changes(&*client)?;
let link = BabeLink {
@@ -1178,7 +1199,7 @@ pub fn block_import<B, E, Block: BlockT<Hash=H256>, I, RA, PRA>(
///
/// The block import object provided must be the `BabeBlockImport` or a wrapper
/// of it, otherwise crucial import logic will be omitted.
pub fn import_queue<B, E, Block: BlockT<Hash=H256>, I, RA, PRA>(
pub fn import_queue<B, E, Block: BlockT, I, RA, PRA>(
babe_link: BabeLink<Block>,
block_import: I,
justification_import: Option<BoxJustificationImport<Block>>,
@@ -1186,12 +1207,13 @@ pub fn import_queue<B, E, Block: BlockT<Hash=H256>, I, RA, PRA>(
client: Arc<Client<B, E, Block, RA>>,
api: Arc<PRA>,
inherent_data_providers: InherentDataProviders,
) -> ClientResult<BabeImportQueue<Block>> where
B: Backend<Block, Blake2Hasher> + 'static,
I: BlockImport<Block,Error=ConsensusError> + Send + Sync + 'static,
E: CallExecutor<Block, Blake2Hasher> + Clone + Send + Sync + 'static,
) -> ClientResult<BabeImportQueue<Block, sp_api::TransactionFor<PRA, Block>>> where
B: Backend<Block> + 'static,
I: BlockImport<Block, Error = ConsensusError, Transaction = sp_api::TransactionFor<PRA, Block>>
+ Send + Sync + 'static,
E: CallExecutor<Block> + Clone + Send + Sync + 'static,
RA: Send + Sync + 'static,
PRA: ProvideRuntimeApi + ProvideCache<Block> + Send + Sync + AuxStore + 'static,
PRA: ProvideRuntimeApi<Block> + ProvideCache<Block> + Send + Sync + AuxStore + 'static,
PRA::Api: BlockBuilderApi<Block> + BabeApi<Block> + ApiExt<Block, Error = sp_blockchain::Error>,
{
register_babe_inherent_data_provider(&inherent_data_providers, babe_link.config.slot_duration)?;
@@ -1227,8 +1249,11 @@ pub mod test_helpers {
keystore: &KeyStorePtr,
link: &BabeLink<B>,
) -> Option<BabePreDigest> where
B: BlockT<Hash=H256>,
C: ProvideRuntimeApi + ProvideCache<B> + HeaderBackend<B> + HeaderMetadata<B, Error=ClientError>,
B: BlockT,
C: ProvideRuntimeApi<B> +
ProvideCache<B> +
HeaderBackend<B> +
HeaderMetadata<B, Error = ClientError>,
C::Api: BabeApi<B>,
{
let epoch = link.epoch_changes.lock().epoch_for_child_of(
+40 -23
View File
@@ -24,16 +24,16 @@ use authorship::claim_slot;
use sp_consensus_babe::{AuthorityPair, SlotNumber};
use sc_block_builder::BlockBuilder;
use sp_consensus::NoNetwork as DummyOracle;
use sp_consensus::import_queue::{
BoxBlockImport, BoxJustificationImport, BoxFinalityProofImport,
use sp_consensus::{
NoNetwork as DummyOracle, Proposal, RecordProof,
import_queue::{BoxBlockImport, BoxJustificationImport, BoxFinalityProofImport},
};
use sc_network_test::*;
use sc_network_test::{Block as TestBlock, PeersClient};
use sc_network::config::{BoxFinalityProofRequestBuilder, ProtocolConfig};
use sp_runtime::{generic::DigestItem, traits::{Block as BlockT, DigestFor}};
use tokio::runtime::current_thread;
use sc_client_api::BlockchainEvents;
use sc_client_api::{BlockchainEvents, backend::TransactionFor};
use log::debug;
use std::{time::Duration, cell::RefCell};
@@ -94,16 +94,25 @@ impl Environment<TestBlock> for DummyFactory {
impl DummyProposer {
fn propose_with(&mut self, pre_digests: DigestFor<TestBlock>)
-> future::Ready<Result<TestBlock, Error>>
-> future::Ready<
Result<
Proposal<
TestBlock,
sc_client_api::TransactionFor<substrate_test_runtime_client::Backend, TestBlock>
>,
Error
>
>
{
use codec::Encode;
let block_builder = self.factory.client.new_block_at(
&BlockId::Hash(self.parent_hash),
pre_digests,
false,
).unwrap();
let mut block = match block_builder.bake().map_err(|e| e.into()) {
Ok(b) => b,
let mut block = match block_builder.build().map_err(|e| e.into()) {
Ok(b) => b.block,
Err(e) => return future::ready(Err(e)),
};
@@ -142,20 +151,22 @@ impl DummyProposer {
// mutate the block header according to the mutator.
(self.factory.mutator)(&mut block.header, Stage::PreSeal);
future::ready(Ok(block))
future::ready(Ok(Proposal { block, proof: None, storage_changes: Default::default() }))
}
}
impl Proposer<TestBlock> for DummyProposer {
type Error = Error;
type Create = future::Ready<Result<TestBlock, Error>>;
type Transaction = sc_client_api::TransactionFor<substrate_test_runtime_client::Backend, TestBlock>;
type Proposal = future::Ready<Result<Proposal<TestBlock, Self::Transaction>, Error>>;
fn propose(
&mut self,
_: InherentData,
pre_digests: DigestFor<TestBlock>,
_: Duration,
) -> Self::Create {
_: RecordProof,
) -> Self::Proposal {
self.propose_with(pre_digests)
}
}
@@ -169,10 +180,11 @@ struct PanickingBlockImport<B>(B);
impl<B: BlockImport<TestBlock>> BlockImport<TestBlock> for PanickingBlockImport<B> {
type Error = B::Error;
type Transaction = B::Transaction;
fn import_block(
&mut self,
block: BlockImportParams<TestBlock>,
block: BlockImportParams<TestBlock, Self::Transaction>,
new_cache: HashMap<CacheKeyId, Vec<u8>>,
) -> Result<ImportResult, Self::Error> {
Ok(self.0.import_block(block, new_cache).expect("importing block failed"))
@@ -214,7 +226,7 @@ impl Verifier<TestBlock> for TestVerifier {
mut header: TestHeader,
justification: Option<Justification>,
body: Option<Vec<TestExtrinsic>>,
) -> Result<(BlockImportParams<TestBlock>, Option<Vec<(CacheKeyId, Vec<u8>)>>), String> {
) -> Result<(BlockImportParams<TestBlock, ()>, Option<Vec<(CacheKeyId, Vec<u8>)>>), String> {
// apply post-sealing mutations (i.e. stripping seal, if desired).
(self.mutator)(&mut header, Stage::PostSeal);
Ok(self.inner.verify(origin, header, justification, body).expect("verification failed!"))
@@ -224,7 +236,9 @@ impl Verifier<TestBlock> for TestVerifier {
pub struct PeerData {
link: BabeLink<TestBlock>,
inherent_data_providers: InherentDataProviders,
block_import: Mutex<Option<BoxBlockImport<TestBlock>>>,
block_import: Mutex<
Option<BoxBlockImport<TestBlock, TransactionFor<substrate_test_runtime_client::Backend, TestBlock>>>
>,
}
impl TestNetFactory for BabeTestNet {
@@ -240,9 +254,9 @@ impl TestNetFactory for BabeTestNet {
}
}
fn make_block_import(&self, client: PeersClient)
fn make_block_import<Transaction>(&self, client: PeersClient)
-> (
BoxBlockImport<Block>,
BlockImportAdapter<Transaction>,
Option<BoxJustificationImport<Block>>,
Option<BoxFinalityProofImport<Block>>,
Option<BoxFinalityProofRequestBuilder<Block>>,
@@ -262,9 +276,11 @@ impl TestNetFactory for BabeTestNet {
let block_import = PanickingBlockImport(block_import);
let data_block_import = Mutex::new(Some(Box::new(block_import.clone()) as BoxBlockImport<_>));
let data_block_import = Mutex::new(
Some(Box::new(block_import.clone()) as BoxBlockImport<_, _>)
);
(
Box::new(block_import),
BlockImportAdapter::new_full(block_import),
None,
None,
None,
@@ -322,8 +338,8 @@ impl TestNetFactory for BabeTestNet {
fn rejects_empty_block() {
env_logger::try_init().unwrap();
let mut net = BabeTestNet::new(3);
let block_builder = |builder: BlockBuilder<_, _>| {
builder.bake().unwrap()
let block_builder = |builder: BlockBuilder<_, _, _>| {
builder.build().unwrap().block
};
net.mut_peers(|peer| {
peer[0].generate_blocks(1, BlockOrigin::NetworkInitialSync, block_builder);
@@ -525,12 +541,12 @@ fn can_author_block() {
}
// Propose and import a new BABE block on top of the given parent.
fn propose_and_import_block(
fn propose_and_import_block<Transaction>(
parent: &TestHeader,
slot_number: Option<SlotNumber>,
proposer_factory: &mut DummyFactory,
block_import: &mut BoxBlockImport<TestBlock>,
) -> H256 {
block_import: &mut BoxBlockImport<TestBlock, Transaction>,
) -> sp_core::H256 {
let mut proposer = proposer_factory.init(parent).unwrap();
let slot_number = slot_number.unwrap_or_else(|| {
@@ -549,7 +565,7 @@ fn propose_and_import_block(
],
};
let mut block = futures::executor::block_on(proposer.propose_with(pre_digest)).unwrap();
let mut block = futures::executor::block_on(proposer.propose_with(pre_digest)).unwrap().block;
let seal = {
// sign the pre-sealed hash of the block and then
@@ -574,6 +590,7 @@ fn propose_and_import_block(
justification: None,
post_digests: vec![seal],
body: Some(block.extrinsics),
storage_changes: None,
finalized: false,
auxiliary: Vec::new(),
fork_choice: ForkChoiceStrategy::LongestChain,
@@ -10,6 +10,7 @@ codec = { package = "parity-scale-codec", version = "1.0.0", features = ["derive
sp-core = { version = "2.0.0", path = "../../../primitives/core" }
sp-blockchain = { version = "2.0.0", path = "../../../primitives/blockchain" }
sp-runtime = { version = "2.0.0", path = "../../../primitives/runtime" }
sp-api = { version = "2.0.0", path = "../../../primitives/api" }
sc-client-api = { version = "2.0.0", path = "../../api" }
sp-block-builder = { version = "2.0.0", path = "../../../primitives/block-builder" }
sp-inherents = { version = "2.0.0", path = "../../../primitives/inherents" }
+45 -36
View File
@@ -37,19 +37,19 @@ use sp_blockchain::{HeaderBackend, ProvideCache, well_known_cache_keys::Id as Ca
use sp_block_builder::BlockBuilder as BlockBuilderApi;
use sp_runtime::{Justification, RuntimeString};
use sp_runtime::generic::{BlockId, Digest, DigestItem};
use sp_runtime::traits::{Block as BlockT, Header as HeaderT, ProvideRuntimeApi};
use sp_timestamp::{TimestampInherentData, InherentError as TIError};
use sp_runtime::traits::{Block as BlockT, Header as HeaderT};
use sp_api::ProvideRuntimeApi;
use sp_consensus_pow::{Seal, TotalDifficulty, POW_ENGINE_ID};
use sp_core::H256;
use sp_inherents::{InherentDataProviders, InherentData};
use sp_consensus::{
BlockImportParams, BlockOrigin, ForkChoiceStrategy, SyncOracle, Environment, Proposer,
SelectChain, Error as ConsensusError, CanAuthorWith,
SelectChain, Error as ConsensusError, CanAuthorWith, RecordProof,
};
use sp_consensus::import_queue::{BoxBlockImport, BasicQueue, Verifier};
use codec::{Encode, Decode};
use sc_client_api;
use log::*;
use sp_timestamp::{InherentError as TIError, TimestampInherentData};
#[derive(derive_more::Display, Debug)]
pub enum Error<B: BlockT> {
@@ -93,9 +93,8 @@ impl<B: BlockT> std::convert::From<Error<B>> for String {
pub const POW_AUX_PREFIX: [u8; 4] = *b"PoW:";
/// Get the auxiliary storage key used by engine to store total difficulty.
fn aux_key(hash: &H256) -> Vec<u8> {
POW_AUX_PREFIX.iter().chain(&hash[..])
.cloned().collect::<Vec<_>>()
fn aux_key<T: AsRef<[u8]>>(hash: &T) -> Vec<u8> {
POW_AUX_PREFIX.iter().chain(hash.as_ref()).copied().collect()
}
/// Auxiliary storage data for PoW.
@@ -111,12 +110,11 @@ impl<Difficulty> PowAux<Difficulty> where
Difficulty: Decode + Default,
{
/// Read the auxiliary from client.
pub fn read<C: AuxStore, B: BlockT>(client: &C, hash: &H256) -> Result<Self, Error<B>> {
let key = aux_key(hash);
pub fn read<C: AuxStore, B: BlockT>(client: &C, hash: &B::Hash) -> Result<Self, Error<B>> {
let key = aux_key(&hash);
match client.get_aux(&key).map_err(Error::Client)? {
Some(bytes) => Self::decode(&mut &bytes[..])
.map_err(Error::Codec),
Some(bytes) => Self::decode(&mut &bytes[..]).map_err(Error::Codec),
None => Ok(Self::default()),
}
}
@@ -133,7 +131,7 @@ pub trait PowAlgorithm<B: BlockT> {
fn verify(
&self,
parent: &BlockId<B>,
pre_hash: &H256,
pre_hash: &B::Hash,
seal: &Seal,
difficulty: Self::Difficulty,
) -> Result<bool, Error<B>>;
@@ -141,14 +139,14 @@ pub trait PowAlgorithm<B: BlockT> {
fn mine(
&self,
parent: &BlockId<B>,
pre_hash: &H256,
pre_hash: &B::Hash,
difficulty: Self::Difficulty,
round: u32,
) -> Result<Option<Seal>, Error<B>>;
}
/// A verifier for PoW blocks.
pub struct PowVerifier<B: BlockT<Hash=H256>, C, S, Algorithm> {
pub struct PowVerifier<B: BlockT, C, S, Algorithm> {
client: Arc<C>,
algorithm: Algorithm,
inherent_data_providers: sp_inherents::InherentDataProviders,
@@ -156,7 +154,7 @@ pub struct PowVerifier<B: BlockT<Hash=H256>, C, S, Algorithm> {
check_inherents_after: <<B as BlockT>::Header as HeaderT>::Number,
}
impl<B: BlockT<Hash=H256>, C, S, Algorithm> PowVerifier<B, C, S, Algorithm> {
impl<B: BlockT, C, S, Algorithm> PowVerifier<B, C, S, Algorithm> {
pub fn new(
client: Arc<C>,
algorithm: Algorithm,
@@ -171,7 +169,7 @@ impl<B: BlockT<Hash=H256>, C, S, Algorithm> PowVerifier<B, C, S, Algorithm> {
&self,
mut header: B::Header,
parent_block_id: BlockId<B>,
) -> Result<(B::Header, Algorithm::Difficulty, DigestItem<H256>), Error<B>> where
) -> Result<(B::Header, Algorithm::Difficulty, DigestItem<B::Hash>), Error<B>> where
Algorithm: PowAlgorithm<B>,
{
let hash = header.hash();
@@ -209,7 +207,7 @@ impl<B: BlockT<Hash=H256>, C, S, Algorithm> PowVerifier<B, C, S, Algorithm> {
inherent_data: InherentData,
timestamp_now: u64,
) -> Result<(), Error<B>> where
C: ProvideRuntimeApi, C::Api: BlockBuilderApi<B, Error = sp_blockchain::Error>
C: ProvideRuntimeApi<B>, C::Api: BlockBuilderApi<B, Error = sp_blockchain::Error>
{
const MAX_TIMESTAMP_DRIFT_SECS: u64 = 60;
@@ -245,8 +243,8 @@ impl<B: BlockT<Hash=H256>, C, S, Algorithm> PowVerifier<B, C, S, Algorithm> {
}
}
impl<B: BlockT<Hash=H256>, C, S, Algorithm> Verifier<B> for PowVerifier<B, C, S, Algorithm> where
C: ProvideRuntimeApi + Send + Sync + HeaderBackend<B> + AuxStore + ProvideCache<B> + BlockOf,
impl<B: BlockT, C, S, Algorithm> Verifier<B> for PowVerifier<B, C, S, Algorithm> where
C: ProvideRuntimeApi<B> + Send + Sync + HeaderBackend<B> + AuxStore + ProvideCache<B> + BlockOf,
C::Api: BlockBuilderApi<B, Error = sp_blockchain::Error>,
S: SelectChain<B>,
Algorithm: PowAlgorithm<B> + Send + Sync,
@@ -257,7 +255,7 @@ impl<B: BlockT<Hash=H256>, C, S, Algorithm> Verifier<B> for PowVerifier<B, C, S,
header: B::Header,
justification: Option<Justification>,
mut body: Option<Vec<B::Extrinsic>>,
) -> Result<(BlockImportParams<B>, Option<Vec<(CacheKeyId, Vec<u8>)>>), String> {
) -> Result<(BlockImportParams<B, ()>, Option<Vec<(CacheKeyId, Vec<u8>)>>), String> {
let inherent_data = self.inherent_data_providers
.create_inherent_data().map_err(|e| e.into_string())?;
let timestamp_now = inherent_data.timestamp_inherent_data().map_err(|e| e.into_string())?;
@@ -290,19 +288,22 @@ impl<B: BlockT<Hash=H256>, C, S, Algorithm> Verifier<B> for PowVerifier<B, C, S,
timestamp_now
)?;
let (_, inner_body) = block.deconstruct();
body = Some(inner_body);
body = Some(block.deconstruct().1);
}
let key = aux_key(&hash);
let import_block = BlockImportParams {
origin,
header: checked_header,
post_digests: vec![seal],
body,
storage_changes: None,
finalized: false,
justification,
auxiliary: vec![(key, Some(aux.encode()))],
fork_choice: ForkChoiceStrategy::Custom(aux.total_difficulty > best_aux.total_difficulty),
fork_choice: ForkChoiceStrategy::Custom(
aux.total_difficulty > best_aux.total_difficulty
),
allow_missing_state: false,
import_existing: false,
};
@@ -326,19 +327,22 @@ pub fn register_pow_inherent_data_provider(
}
/// The PoW import queue type.
pub type PowImportQueue<B> = BasicQueue<B>;
pub type PowImportQueue<B, Transaction> = BasicQueue<B, Transaction>;
/// Import queue for PoW engine.
pub fn import_queue<B, C, S, Algorithm>(
block_import: BoxBlockImport<B>,
block_import: BoxBlockImport<B, sp_api::TransactionFor<C, B>>,
client: Arc<C>,
algorithm: Algorithm,
check_inherents_after: <<B as BlockT>::Header as HeaderT>::Number,
select_chain: Option<S>,
inherent_data_providers: InherentDataProviders,
) -> Result<PowImportQueue<B>, sp_consensus::Error> where
B: BlockT<Hash=H256>,
C: ProvideRuntimeApi + HeaderBackend<B> + BlockOf + ProvideCache<B> + AuxStore,
) -> Result<
PowImportQueue<B, sp_api::TransactionFor<C, B>>,
sp_consensus::Error
> where
B: BlockT,
C: ProvideRuntimeApi<B> + HeaderBackend<B> + BlockOf + ProvideCache<B> + AuxStore,
C: Send + Sync + AuxStore + 'static,
C::Api: BlockBuilderApi<B, Error = sp_blockchain::Error>,
Algorithm: PowAlgorithm<B> + Send + Sync + 'static,
@@ -372,8 +376,8 @@ pub fn import_queue<B, C, S, Algorithm>(
/// information, or just be a graffiti. `round` is for number of rounds the
/// CPU miner runs each time. This parameter should be tweaked so that each
/// mining round is within sub-second time.
pub fn start_mine<B: BlockT<Hash=H256>, C, Algorithm, E, SO, S, CAW>(
mut block_import: BoxBlockImport<B>,
pub fn start_mine<B: BlockT, C, Algorithm, E, SO, S, CAW>(
mut block_import: BoxBlockImport<B, sp_api::TransactionFor<C, B>>,
client: Arc<C>,
algorithm: Algorithm,
mut env: E,
@@ -385,10 +389,11 @@ pub fn start_mine<B: BlockT<Hash=H256>, C, Algorithm, E, SO, S, CAW>(
inherent_data_providers: sp_inherents::InherentDataProviders,
can_author_with: CAW,
) where
C: HeaderBackend<B> + AuxStore + 'static,
C: HeaderBackend<B> + AuxStore + ProvideRuntimeApi<B> + 'static,
Algorithm: PowAlgorithm<B> + Send + Sync + 'static,
E: Environment<B> + Send + Sync + 'static,
E::Error: std::fmt::Debug,
E::Proposer: Proposer<B, Transaction = sp_api::TransactionFor<C, B>>,
SO: SyncOracle + Send + Sync + 'static,
S: SelectChain<B> + 'static,
CAW: CanAuthorWith<B> + Send + 'static,
@@ -423,8 +428,8 @@ pub fn start_mine<B: BlockT<Hash=H256>, C, Algorithm, E, SO, S, CAW>(
});
}
fn mine_loop<B: BlockT<Hash=H256>, C, Algorithm, E, SO, S, CAW>(
block_import: &mut BoxBlockImport<B>,
fn mine_loop<B: BlockT, C, Algorithm, E, SO, S, CAW>(
block_import: &mut BoxBlockImport<B, sp_api::TransactionFor<C, B>>,
client: &C,
algorithm: &Algorithm,
env: &mut E,
@@ -436,12 +441,14 @@ fn mine_loop<B: BlockT<Hash=H256>, C, Algorithm, E, SO, S, CAW>(
inherent_data_providers: &sp_inherents::InherentDataProviders,
can_author_with: &CAW,
) -> Result<(), Error<B>> where
C: HeaderBackend<B> + AuxStore,
C: HeaderBackend<B> + AuxStore + ProvideRuntimeApi<B>,
Algorithm: PowAlgorithm<B>,
E: Environment<B>,
E::Proposer: Proposer<B, Transaction = sp_api::TransactionFor<C, B>>,
E::Error: std::fmt::Debug,
SO: SyncOracle,
S: SelectChain<B>,
sp_api::TransactionFor<C, B>: 'static,
CAW: CanAuthorWith<B>,
{
'outer: loop {
@@ -488,13 +495,14 @@ fn mine_loop<B: BlockT<Hash=H256>, C, Algorithm, E, SO, S, CAW>(
if let Some(preruntime) = &preruntime {
inherent_digest.push(DigestItem::PreRuntime(POW_ENGINE_ID, preruntime.to_vec()));
}
let block = futures::executor::block_on(proposer.propose(
let proposal = futures::executor::block_on(proposer.propose(
inherent_data,
inherent_digest,
build_time.clone(),
RecordProof::No,
)).map_err(|e| Error::BlockProposingError(format!("{:?}", e)))?;
let (header, body) = block.deconstruct();
let (header, body) = proposal.block.deconstruct();
let (difficulty, seal) = {
let difficulty = algorithm.difficulty(
&BlockId::Hash(best_hash),
@@ -546,6 +554,7 @@ fn mine_loop<B: BlockT<Hash=H256>, C, Algorithm, E, SO, S, CAW>(
justification: None,
post_digests: vec![DigestItem::Seal(POW_ENGINE_ID, seal)],
body: Some(body),
storage_changes: Some(proposal.storage_changes),
finalized: false,
auxiliary: vec![(key, Some(aux.encode()))],
fork_choice: ForkChoiceStrategy::Custom(true),
@@ -12,6 +12,8 @@ sc-client-api = { version = "2.0.0", path = "../../api" }
sp-core = { version = "2.0.0", path = "../../../primitives/core" }
sp-blockchain = { version = "2.0.0", path = "../../../primitives/blockchain" }
sp-runtime = { version = "2.0.0", path = "../../../primitives/runtime" }
sp-state-machine = { version = "2.0.0", path = "../../../primitives/state-machine" }
sp-api = { version = "2.0.0", path = "../../../primitives/api" }
sc-telemetry = { version = "2.0.0", path = "../../telemetry" }
sp-consensus = { version = "0.8", path = "../../../primitives/consensus/common" }
sp-inherents = { version = "2.0.0", path = "../../../primitives/inherents" }
+40 -19
View File
@@ -31,17 +31,23 @@ use slots::Slots;
pub use aux_schema::{check_equivocation, MAX_SLOT_CAPACITY, PRUNING_BOUND};
use codec::{Decode, Encode};
use sp_consensus::{BlockImport, Proposer, SyncOracle, SelectChain, CanAuthorWith, SlotData};
use sp_consensus::{BlockImport, Proposer, SyncOracle, SelectChain, CanAuthorWith, SlotData, RecordProof};
use futures::{prelude::*, future::{self, Either}};
use futures_timer::Delay;
use sp_inherents::{InherentData, InherentDataProviders};
use log::{debug, error, info, warn};
use sp_runtime::generic::BlockId;
use sp_runtime::traits::{ApiRef, Block as BlockT, Header, ProvideRuntimeApi};
use sp_runtime::traits::{Block as BlockT, Header, HasherFor, NumberFor};
use sp_api::{ProvideRuntimeApi, ApiRef};
use std::{fmt::Debug, ops::Deref, pin::Pin, sync::Arc, time::{Instant, Duration}};
use sc_telemetry::{telemetry, CONSENSUS_DEBUG, CONSENSUS_WARN, CONSENSUS_INFO};
use parking_lot::Mutex;
use sc_client_api;
/// The changes that need to applied to the storage to create the state for a block.
///
/// See [`state_machine::StorageChanges`] for more information.
pub type StorageChanges<Transaction, Block> =
sp_state_machine::StorageChanges<Transaction, HasherFor<Block>, NumberFor<Block>>;
/// A worker that should be invoked at every new slot.
pub trait SlotWorker<B: BlockT> {
@@ -58,7 +64,8 @@ pub trait SlotWorker<B: BlockT> {
/// out if block production takes too long.
pub trait SimpleSlotWorker<B: BlockT> {
/// A handle to a `BlockImport`.
type BlockImport: BlockImport<B> + Send + 'static;
type BlockImport: BlockImport<B, Transaction = <Self::Proposer as Proposer<B>>::Transaction>
+ Send + 'static;
/// A handle to a `SyncOracle`.
type SyncOracle: SyncOracle;
@@ -94,15 +101,26 @@ pub trait SimpleSlotWorker<B: BlockT> {
) -> Option<Self::Claim>;
/// Return the pre digest data to include in a block authored with the given claim.
fn pre_digest_data(&self, slot_number: u64, claim: &Self::Claim) -> Vec<sp_runtime::DigestItem<B::Hash>>;
fn pre_digest_data(
&self,
slot_number: u64,
claim: &Self::Claim,
) -> Vec<sp_runtime::DigestItem<B::Hash>>;
/// Returns a function which produces a `BlockImportParams`.
fn block_import_params(&self) -> Box<dyn Fn(
B::Header,
&B::Hash,
Vec<B::Extrinsic>,
Self::Claim,
) -> sp_consensus::BlockImportParams<B> + Send>;
fn block_import_params(&self) -> Box<
dyn Fn(
B::Header,
&B::Hash,
Vec<B::Extrinsic>,
StorageChanges<<Self::BlockImport as BlockImport<B>>::Transaction, B>,
Self::Claim,
) -> sp_consensus::BlockImportParams<
B,
<Self::BlockImport as BlockImport<B>>::Transaction
>
+ Send
>;
/// Whether to force authoring if offline.
fn force_authoring(&self) -> bool;
@@ -136,7 +154,7 @@ pub trait SimpleSlotWorker<B: BlockT> {
fn on_slot(&mut self, chain_head: B::Header, slot_info: SlotInfo)
-> Pin<Box<dyn Future<Output = Result<(), sp_consensus::Error>> + Send>> where
Self: Send + Sync,
<Self::Proposer as Proposer<B>>::Create: Unpin + Send + 'static,
<Self::Proposer as Proposer<B>>::Proposal: Unpin + Send + 'static,
{
let (timestamp, slot_number, slot_duration) =
(slot_info.timestamp, slot_info.number, slot_info.duration);
@@ -222,6 +240,7 @@ pub trait SimpleSlotWorker<B: BlockT> {
logs,
},
slot_remaining_duration,
RecordProof::No,
).map_err(|e| sp_consensus::Error::ClientImport(format!("{:?}", e)));
let delay: Box<dyn Future<Output=()> + Unpin + Send> = match proposing_remaining_duration {
Some(r) => Box::new(Delay::new(r)),
@@ -247,8 +266,8 @@ pub trait SimpleSlotWorker<B: BlockT> {
let block_import = self.block_import();
let logging_target = self.logging_target();
Box::pin(proposal_work.map_ok(move |(block, claim)| {
let (header, body) = block.deconstruct();
Box::pin(proposal_work.map_ok(move |(proposal, claim)| {
let (header, body) = proposal.block.deconstruct();
let header_num = *header.number();
let header_hash = header.hash();
let parent_hash = *header.parent_hash();
@@ -257,13 +276,15 @@ pub trait SimpleSlotWorker<B: BlockT> {
header,
&header_hash,
body,
proposal.storage_changes,
claim,
);
info!("Pre-sealed block for proposal at {}. Hash now {:?}, previously {:?}.",
header_num,
block_import_params.post_header().hash(),
header_hash,
info!(
"Pre-sealed block for proposal at {}. Hash now {:?}, previously {:?}.",
header_num,
block_import_params.post_header().hash(),
header_hash,
);
telemetry!(CONSENSUS_INFO; "slots.pre_sealed_block";
@@ -418,7 +439,7 @@ impl<T: Clone> SlotDuration<T> {
/// compile-time constant.
pub fn get_or_compute<B: BlockT, C, CB>(client: &C, cb: CB) -> sp_blockchain::Result<Self> where
C: sc_client_api::backend::AuxStore,
C: ProvideRuntimeApi,
C: ProvideRuntimeApi<B>,
CB: FnOnce(ApiRef<C::Api>, &BlockId<B>) -> sp_blockchain::Result<T>,
T: SlotData + Encode + Decode + Debug,
{
+134 -101
View File
@@ -47,18 +47,18 @@ use sp_blockchain::{
well_known_cache_keys, HeaderBackend,
};
use codec::{Decode, Encode};
use hash_db::{Hasher, Prefix};
use hash_db::Prefix;
use kvdb::{KeyValueDB, DBTransaction};
use sp_trie::{MemoryDB, PrefixedMemoryDB, prefixed_key};
use parking_lot::{Mutex, RwLock};
use sp_core::{H256, Blake2Hasher, ChangesTrieConfiguration, convert_hash, traits::CodeExecutor};
use sp_core::{ChangesTrieConfiguration, convert_hash, traits::CodeExecutor};
use sp_core::storage::{well_known_keys, ChildInfo};
use sp_runtime::{
generic::{BlockId, DigestItem}, Justification, Storage,
BuildStorage,
};
use sp_runtime::traits::{
Block as BlockT, Header as HeaderT, NumberFor, Zero, One, SaturatedConversion
Block as BlockT, Header as HeaderT, NumberFor, Zero, One, SaturatedConversion, HasherFor,
};
use sc_executor::RuntimeInfo;
use sp_state_machine::{
@@ -83,7 +83,9 @@ const MIN_BLOCKS_TO_KEEP_CHANGES_TRIES_FOR: u32 = 32768;
const DEFAULT_CHILD_RATIO: (usize, usize) = (1, 10);
/// DB-backed patricia trie state, transaction type is an overlay of changes to commit.
pub type DbState = sp_state_machine::TrieBackend<Arc<dyn sp_state_machine::Storage<Blake2Hasher>>, Blake2Hasher>;
pub type DbState<B> = sp_state_machine::TrieBackend<
Arc<dyn sp_state_machine::Storage<HasherFor<B>>>, HasherFor<B>
>;
/// Re-export the KVDB trait so that one can pass an implementation of it.
pub use kvdb;
@@ -93,17 +95,13 @@ pub use kvdb;
/// It makes sure that the hash we are using stays pinned in storage
/// until this structure is dropped.
pub struct RefTrackingState<Block: BlockT> {
state: DbState,
state: DbState<Block>,
storage: Arc<StorageDb<Block>>,
parent_hash: Option<Block::Hash>,
}
impl<B: BlockT> RefTrackingState<B> {
fn new(
state: DbState,
storage: Arc<StorageDb<B>>,
parent_hash: Option<B::Hash>,
) -> RefTrackingState<B> {
fn new(state: DbState<B>, storage: Arc<StorageDb<B>>, parent_hash: Option<B::Hash>) -> Self {
RefTrackingState {
state,
parent_hash,
@@ -126,16 +124,16 @@ impl<Block: BlockT> std::fmt::Debug for RefTrackingState<Block> {
}
}
impl<B: BlockT> StateBackend<Blake2Hasher> for RefTrackingState<B> {
type Error = <DbState as StateBackend<Blake2Hasher>>::Error;
type Transaction = <DbState as StateBackend<Blake2Hasher>>::Transaction;
type TrieBackendStorage = <DbState as StateBackend<Blake2Hasher>>::TrieBackendStorage;
impl<B: BlockT> StateBackend<HasherFor<B>> for RefTrackingState<B> {
type Error = <DbState<B> as StateBackend<HasherFor<B>>>::Error;
type Transaction = <DbState<B> as StateBackend<HasherFor<B>>>::Transaction;
type TrieBackendStorage = <DbState<B> as StateBackend<HasherFor<B>>>::TrieBackendStorage;
fn storage(&self, key: &[u8]) -> Result<Option<Vec<u8>>, Self::Error> {
self.state.storage(key)
}
fn storage_hash(&self, key: &[u8]) -> Result<Option<H256>, Self::Error> {
fn storage_hash(&self, key: &[u8]) -> Result<Option<B::Hash>, Self::Error> {
self.state.storage_hash(key)
}
@@ -201,7 +199,7 @@ impl<B: BlockT> StateBackend<Blake2Hasher> for RefTrackingState<B> {
self.state.for_child_keys_with_prefix(storage_key, child_info, prefix, f)
}
fn storage_root<I>(&self, delta: I) -> (H256, Self::Transaction)
fn storage_root<I>(&self, delta: I) -> (B::Hash, Self::Transaction)
where
I: IntoIterator<Item=(Vec<u8>, Option<Vec<u8>>)>
{
@@ -213,7 +211,7 @@ impl<B: BlockT> StateBackend<Blake2Hasher> for RefTrackingState<B> {
storage_key: &[u8],
child_info: ChildInfo,
delta: I,
) -> (H256, bool, Self::Transaction)
) -> (B::Hash, bool, Self::Transaction)
where
I: IntoIterator<Item=(Vec<u8>, Option<Vec<u8>>)>,
{
@@ -237,9 +235,9 @@ impl<B: BlockT> StateBackend<Blake2Hasher> for RefTrackingState<B> {
self.state.child_keys(storage_key, child_info, prefix)
}
fn as_trie_backend(
&mut self,
) -> Option<&sp_state_machine::TrieBackend<Self::TrieBackendStorage, Blake2Hasher>> {
fn as_trie_backend(&mut self)
-> Option<&sp_state_machine::TrieBackend<Self::TrieBackendStorage, HasherFor<B>>>
{
self.state.as_trie_backend()
}
}
@@ -290,7 +288,7 @@ pub fn new_client<E, S, Block, RA>(
sp_blockchain::Error,
>
where
Block: BlockT<Hash=H256>,
Block: BlockT,
E: CodeExecutor + RuntimeInfo,
S: BuildStorage,
{
@@ -505,13 +503,13 @@ impl<Block: BlockT> HeaderMetadata<Block> for BlockchainDb<Block> {
}
/// Database transaction
pub struct BlockImportOperation<Block: BlockT, H: Hasher> {
old_state: CachingState<Blake2Hasher, RefTrackingState<Block>, Block>,
db_updates: PrefixedMemoryDB<H>,
pub struct BlockImportOperation<Block: BlockT> {
old_state: CachingState<RefTrackingState<Block>, Block>,
db_updates: PrefixedMemoryDB<HasherFor<Block>>,
storage_updates: StorageCollection,
child_storage_updates: ChildStorageCollection,
changes_trie_updates: MemoryDB<H>,
changes_trie_cache_update: Option<ChangesTrieCacheAction<H::Out, NumberFor<Block>>>,
changes_trie_updates: MemoryDB<HasherFor<Block>>,
changes_trie_cache_update: Option<ChangesTrieCacheAction<Block::Hash, NumberFor<Block>>>,
pending_block: Option<PendingBlock<Block>>,
aux_ops: Vec<(Vec<u8>, Option<Vec<u8>>)>,
finalized_blocks: Vec<(BlockId<Block>, Option<Justification>)>,
@@ -519,7 +517,7 @@ pub struct BlockImportOperation<Block: BlockT, H: Hasher> {
commit_state: bool,
}
impl<Block: BlockT, H: Hasher> BlockImportOperation<Block, H> {
impl<Block: BlockT> BlockImportOperation<Block> {
fn apply_aux(&mut self, transaction: &mut DBTransaction) {
for (key, maybe_val) in self.aux_ops.drain(..) {
match maybe_val {
@@ -530,10 +528,8 @@ impl<Block: BlockT, H: Hasher> BlockImportOperation<Block, H> {
}
}
impl<Block> sc_client_api::backend::BlockImportOperation<Block, Blake2Hasher>
for BlockImportOperation<Block, Blake2Hasher> where Block: BlockT<Hash=H256>,
{
type State = CachingState<Blake2Hasher, RefTrackingState<Block>, Block>;
impl<Block: BlockT> sc_client_api::backend::BlockImportOperation<Block> for BlockImportOperation<Block> {
type State = CachingState<RefTrackingState<Block>, Block>;
fn state(&self) -> ClientResult<Option<&Self::State>> {
Ok(Some(&self.old_state))
@@ -560,7 +556,7 @@ impl<Block> sc_client_api::backend::BlockImportOperation<Block, Blake2Hasher>
// Currently cache isn't implemented on full nodes.
}
fn update_db_storage(&mut self, update: PrefixedMemoryDB<Blake2Hasher>) -> ClientResult<()> {
fn update_db_storage(&mut self, update: PrefixedMemoryDB<HasherFor<Block>>) -> ClientResult<()> {
self.db_updates = update;
Ok(())
}
@@ -568,7 +564,7 @@ impl<Block> sc_client_api::backend::BlockImportOperation<Block, Blake2Hasher>
fn reset_storage(
&mut self,
storage: Storage,
) -> ClientResult<H256> {
) -> ClientResult<Block::Hash> {
if storage.top.iter().any(|(k, _)| well_known_keys::is_child_storage_key(k)) {
return Err(sp_blockchain::Error::GenesisInvalid.into());
@@ -597,7 +593,7 @@ impl<Block> sc_client_api::backend::BlockImportOperation<Block, Blake2Hasher>
fn update_changes_trie(
&mut self,
update: ChangesTrieTransaction<Blake2Hasher, NumberFor<Block>>,
update: ChangesTrieTransaction<HasherFor<Block>, NumberFor<Block>>,
) -> ClientResult<()> {
self.changes_trie_updates = update.0;
self.changes_trie_cache_update = Some(update.1);
@@ -621,7 +617,11 @@ impl<Block> sc_client_api::backend::BlockImportOperation<Block, Blake2Hasher>
Ok(())
}
fn mark_finalized(&mut self, block: BlockId<Block>, justification: Option<Justification>) -> ClientResult<()> {
fn mark_finalized(
&mut self,
block: BlockId<Block>,
justification: Option<Justification>,
) -> ClientResult<()> {
self.finalized_blocks.push((block, justification));
Ok(())
}
@@ -638,9 +638,9 @@ struct StorageDb<Block: BlockT> {
pub state_db: StateDb<Block::Hash, Vec<u8>>,
}
impl<Block: BlockT> sp_state_machine::Storage<Blake2Hasher> for StorageDb<Block> {
fn get(&self, key: &H256, prefix: Prefix) -> Result<Option<DBValue>, String> {
let key = prefixed_key::<Blake2Hasher>(key, prefix);
impl<Block: BlockT> sp_state_machine::Storage<HasherFor<Block>> for StorageDb<Block> {
fn get(&self, key: &Block::Hash, prefix: Prefix) -> Result<Option<DBValue>, String> {
let key = prefixed_key::<HasherFor<Block>>(key, prefix);
self.state_db.get(&key, self)
.map_err(|e| format!("Database backend error: {:?}", e))
}
@@ -655,19 +655,19 @@ impl<Block: BlockT> sc_state_db::NodeDb for StorageDb<Block> {
}
}
struct DbGenesisStorage(pub H256);
struct DbGenesisStorage<Block: BlockT>(pub Block::Hash);
impl DbGenesisStorage {
impl<Block: BlockT> DbGenesisStorage<Block> {
pub fn new() -> Self {
let mut root = H256::default();
let mut mdb = MemoryDB::<Blake2Hasher>::default();
sp_state_machine::TrieDBMut::<Blake2Hasher>::new(&mut mdb, &mut root);
let mut root = Block::Hash::default();
let mut mdb = MemoryDB::<HasherFor<Block>>::default();
sp_state_machine::TrieDBMut::<HasherFor<Block>>::new(&mut mdb, &mut root);
DbGenesisStorage(root)
}
}
impl sp_state_machine::Storage<Blake2Hasher> for DbGenesisStorage {
fn get(&self, _key: &H256, _prefix: Prefix) -> Result<Option<DBValue>, String> {
impl<Block: BlockT> sp_state_machine::Storage<HasherFor<Block>> for DbGenesisStorage<Block> {
fn get(&self, _key: &Block::Hash, _prefix: Prefix) -> Result<Option<DBValue>, String> {
Ok(None)
}
}
@@ -678,14 +678,13 @@ pub struct DbChangesTrieStorage<Block: BlockT> {
meta: Arc<RwLock<Meta<NumberFor<Block>, Block::Hash>>>,
min_blocks_to_keep: Option<u32>,
cache: RwLock<ChangesTrieBuildCache<Block::Hash, NumberFor<Block>>>,
_phantom: ::std::marker::PhantomData<Block>,
}
impl<Block: BlockT<Hash=H256>> DbChangesTrieStorage<Block> {
impl<Block: BlockT> DbChangesTrieStorage<Block> {
/// Commit new changes trie.
pub fn commit(&self, tx: &mut DBTransaction, mut changes_trie: MemoryDB<Blake2Hasher>) {
pub fn commit(&self, tx: &mut DBTransaction, mut changes_trie: MemoryDB<HasherFor<Block>>) {
for (key, (val, _)) in changes_trie.drain() {
tx.put(columns::CHANGES_TRIE, &key[..], &val);
tx.put(columns::CHANGES_TRIE, key.as_ref(), &val);
}
}
@@ -720,10 +719,8 @@ impl<Block: BlockT<Hash=H256>> DbChangesTrieStorage<Block> {
}
}
impl<Block> sc_client_api::backend::PrunableStateChangesTrieStorage<Block, Blake2Hasher>
impl<Block: BlockT> sc_client_api::backend::PrunableStateChangesTrieStorage<Block>
for DbChangesTrieStorage<Block>
where
Block: BlockT<Hash=H256>,
{
fn oldest_changes_trie_block(
&self,
@@ -741,16 +738,19 @@ where
}
}
impl<Block> sp_state_machine::ChangesTrieRootsStorage<Blake2Hasher, NumberFor<Block>>
impl<Block: BlockT> sp_state_machine::ChangesTrieRootsStorage<HasherFor<Block>, NumberFor<Block>>
for DbChangesTrieStorage<Block>
where
Block: BlockT<Hash=H256>,
{
fn build_anchor(
&self,
hash: H256,
) -> Result<sp_state_machine::ChangesTrieAnchorBlockId<H256, NumberFor<Block>>, String> {
utils::read_header::<Block>(&*self.db, columns::KEY_LOOKUP, columns::HEADER, BlockId::Hash(hash))
hash: Block::Hash,
) -> Result<sp_state_machine::ChangesTrieAnchorBlockId<Block::Hash, NumberFor<Block>>, String> {
utils::read_header::<Block>(
&*self.db,
columns::KEY_LOOKUP,
columns::HEADER,
BlockId::Hash(hash),
)
.map_err(|e| e.to_string())
.and_then(|maybe_header| maybe_header.map(|header|
sp_state_machine::ChangesTrieAnchorBlockId {
@@ -762,12 +762,14 @@ where
fn root(
&self,
anchor: &sp_state_machine::ChangesTrieAnchorBlockId<H256, NumberFor<Block>>,
anchor: &sp_state_machine::ChangesTrieAnchorBlockId<Block::Hash, NumberFor<Block>>,
block: NumberFor<Block>,
) -> Result<Option<H256>, String> {
) -> Result<Option<Block::Hash>, String> {
// check API requirement: we can't get NEXT block(s) based on anchor
if block > anchor.number {
return Err(format!("Can't get changes trie root at {} using anchor at {}", block, anchor.number));
return Err(
format!("Can't get changes trie root at {} using anchor at {}", block, anchor.number)
)
}
// we need to get hash of the block to resolve changes trie root
@@ -801,33 +803,40 @@ where
}
};
Ok(utils::require_header::<Block>(&*self.db, columns::KEY_LOOKUP, columns::HEADER, block_id)
Ok(
utils::require_header::<Block>(
&*self.db,
columns::KEY_LOOKUP,
columns::HEADER,
block_id,
)
.map_err(|e| e.to_string())?
.digest().log(DigestItem::as_changes_trie_root)
.map(|root| H256::from_slice(root.as_ref())))
.digest()
.log(DigestItem::as_changes_trie_root)
.cloned()
)
}
}
impl<Block> sp_state_machine::ChangesTrieStorage<Blake2Hasher, NumberFor<Block>>
impl<Block: BlockT> sp_state_machine::ChangesTrieStorage<HasherFor<Block>, NumberFor<Block>>
for DbChangesTrieStorage<Block>
where
Block: BlockT<Hash=H256>,
{
fn as_roots_storage(&self) -> &dyn sp_state_machine::ChangesTrieRootsStorage<Blake2Hasher, NumberFor<Block>> {
fn as_roots_storage(&self)
-> &dyn sp_state_machine::ChangesTrieRootsStorage<HasherFor<Block>, NumberFor<Block>>
{
self
}
fn with_cached_changed_keys(
&self,
root: &H256,
root: &Block::Hash,
functor: &mut dyn FnMut(&HashMap<Option<Vec<u8>>, HashSet<Vec<u8>>>),
) -> bool {
self.cache.read().with_changed_keys(root, functor)
}
fn get(&self, key: &H256, _prefix: Prefix) -> Result<Option<DBValue>, String> {
self.db.get(columns::CHANGES_TRIE, &key[..])
.map_err(|err| format!("{}", err))
fn get(&self, key: &Block::Hash, _prefix: Prefix) -> Result<Option<DBValue>, String> {
self.db.get(columns::CHANGES_TRIE, key.as_ref()).map_err(|err| format!("{}", err))
}
}
@@ -883,13 +892,13 @@ pub struct Backend<Block: BlockT> {
changes_trie_config: Mutex<Option<Option<ChangesTrieConfiguration>>>,
blockchain: BlockchainDb<Block>,
canonicalization_delay: u64,
shared_cache: SharedCache<Block, Blake2Hasher>,
shared_cache: SharedCache<Block>,
import_lock: RwLock<()>,
is_archive: bool,
io_stats: FrozenForDuration<kvdb::IoStats>,
}
impl<Block: BlockT<Hash=H256>> Backend<Block> {
impl<Block: BlockT> Backend<Block> {
/// Create a new instance of database backend.
///
/// The pruning window is how old a block must be before the state is pruned.
@@ -915,13 +924,16 @@ impl<Block: BlockT<Hash=H256>> Backend<Block> {
fn from_kvdb(
db: Arc<dyn KeyValueDB>,
canonicalization_delay: u64,
config: &DatabaseSettings
config: &DatabaseSettings,
) -> ClientResult<Self> {
let is_archive_pruning = config.pruning.is_archive();
let blockchain = BlockchainDb::new(db.clone())?;
let meta = blockchain.meta.clone();
let map_e = |e: sc_state_db::Error<io::Error>| ::sp_blockchain::Error::from(format!("State database error: {:?}", e));
let state_db: StateDb<_, _> = StateDb::new(config.pruning.clone(), &StateMetaDb(&*db)).map_err(map_e)?;
let map_e = |e: sc_state_db::Error<io::Error>| sp_blockchain::Error::from(
format!("State database error: {:?}", e)
);
let state_db: StateDb<_, _> = StateDb::new(config.pruning.clone(), &StateMetaDb(&*db))
.map_err(map_e)?;
let storage_db = StorageDb {
db: db.clone(),
state_db,
@@ -930,9 +942,12 @@ impl<Block: BlockT<Hash=H256>> Backend<Block> {
let changes_tries_storage = DbChangesTrieStorage {
db,
meta,
min_blocks_to_keep: if is_archive_pruning { None } else { Some(MIN_BLOCKS_TO_KEEP_CHANGES_TRIES_FOR) },
min_blocks_to_keep: if is_archive_pruning {
None
} else {
Some(MIN_BLOCKS_TO_KEEP_CHANGES_TRIES_FOR)
},
cache: RwLock::new(ChangesTrieBuildCache::new()),
_phantom: Default::default(),
};
Ok(Backend {
@@ -952,13 +967,13 @@ impl<Block: BlockT<Hash=H256>> Backend<Block> {
})
}
/// Returns in-memory blockchain that contains the same set of blocks that the self.
/// Returns in-memory blockchain that contains the same set of blocks as self.
#[cfg(feature = "test-helpers")]
pub fn as_in_memory(&self) -> InMemoryBackend<Block, Blake2Hasher> {
pub fn as_in_memory(&self) -> InMemoryBackend<Block> {
use sc_client_api::backend::{Backend as ClientBackend, BlockImportOperation};
use sc_client::blockchain::Backend as BlockchainBackend;
let inmem = InMemoryBackend::<Block, Blake2Hasher>::new();
let inmem = InMemoryBackend::<Block>::new();
// get all headers hashes && sort them by number (could be duplicate)
let mut headers: Vec<(NumberFor<Block>, Block::Hash, Block::Header)> = Vec::new();
@@ -1174,7 +1189,7 @@ impl<Block: BlockT<Hash=H256>> Backend<Block> {
Ok(())
}
fn try_commit_operation(&self, mut operation: BlockImportOperation<Block, Blake2Hasher>)
fn try_commit_operation(&self, mut operation: BlockImportOperation<Block>)
-> ClientResult<()>
{
let mut transaction = DBTransaction::new();
@@ -1375,9 +1390,7 @@ impl<Block: BlockT<Hash=H256>> Backend<Block> {
f_header: &Block::Header,
f_hash: Block::Hash,
displaced: &mut Option<FinalizationDisplaced<Block::Hash, NumberFor<Block>>>
) -> ClientResult<()> where
Block: BlockT<Hash=H256>,
{
) -> ClientResult<()> {
let f_num = f_header.number().clone();
if self.storage.state_db.best_canonical().map(|c| f_num.saturated_into::<u64>() > c).unwrap_or(true) {
@@ -1421,7 +1434,7 @@ fn apply_state_commit(transaction: &mut DBTransaction, commit: sc_state_db::Comm
}
}
impl<Block> sc_client_api::backend::AuxStore for Backend<Block> where Block: BlockT<Hash=H256> {
impl<Block> sc_client_api::backend::AuxStore for Backend<Block> where Block: BlockT {
fn insert_aux<
'a,
'b: 'a,
@@ -1445,10 +1458,10 @@ impl<Block> sc_client_api::backend::AuxStore for Backend<Block> where Block: Blo
}
}
impl<Block> sc_client_api::backend::Backend<Block, Blake2Hasher> for Backend<Block> where Block: BlockT<Hash=H256> {
type BlockImportOperation = BlockImportOperation<Block, Blake2Hasher>;
impl<Block: BlockT> sc_client_api::backend::Backend<Block> for Backend<Block> {
type BlockImportOperation = BlockImportOperation<Block>;
type Blockchain = BlockchainDb<Block>;
type State = CachingState<Blake2Hasher, RefTrackingState<Block>, Block>;
type State = CachingState<RefTrackingState<Block>, Block>;
type ChangesTrieStorage = DbChangesTrieStorage<Block>;
type OffchainStorage = offchain::LocalStorage;
@@ -1634,9 +1647,9 @@ impl<Block> sc_client_api::backend::Backend<Block, Blake2Hasher> for Backend<Blo
// special case for genesis initialization
match block {
BlockId::Hash(h) if h == Default::default() => {
let genesis_storage = DbGenesisStorage::new();
let genesis_storage = DbGenesisStorage::<Block>::new();
let root = genesis_storage.0.clone();
let db_state = DbState::new(Arc::new(genesis_storage), root);
let db_state = DbState::<Block>::new(Arc::new(genesis_storage), root);
let state = RefTrackingState::new(db_state, self.storage.clone(), None);
return Ok(CachingState::new(state, self.shared_cache.clone(), None));
},
@@ -1647,18 +1660,34 @@ impl<Block> sc_client_api::backend::Backend<Block, Blake2Hasher> for Backend<Blo
Ok(Some(ref hdr)) => {
let hash = hdr.hash();
if !self.have_state_at(&hash, *hdr.number()) {
return Err(sp_blockchain::Error::UnknownBlock(format!("State already discarded for {:?}", block)))
return Err(
sp_blockchain::Error::UnknownBlock(
format!("State already discarded for {:?}", block)
)
)
}
if let Ok(()) = self.storage.state_db.pin(&hash) {
let root = H256::from_slice(hdr.state_root().as_ref());
let db_state = DbState::new(self.storage.clone(), root);
let state = RefTrackingState::new(db_state, self.storage.clone(), Some(hash.clone()));
let root = hdr.state_root();
let db_state = DbState::<Block>::new(self.storage.clone(), *root);
let state = RefTrackingState::new(
db_state,
self.storage.clone(),
Some(hash.clone()),
);
Ok(CachingState::new(state, self.shared_cache.clone(), Some(hash)))
} else {
Err(sp_blockchain::Error::UnknownBlock(format!("State already discarded for {:?}", block)))
Err(
sp_blockchain::Error::UnknownBlock(
format!("State already discarded for {:?}", block)
)
)
}
},
Ok(None) => Err(sp_blockchain::Error::UnknownBlock(format!("Unknown state for block {:?}", block))),
Ok(None) => Err(
sp_blockchain::Error::UnknownBlock(
format!("Unknown state for block {:?}", block)
)
),
Err(e) => Err(e),
}
}
@@ -1667,7 +1696,11 @@ impl<Block> sc_client_api::backend::Backend<Block, Blake2Hasher> for Backend<Blo
if self.is_archive {
match self.blockchain.header(BlockId::Hash(hash.clone())) {
Ok(Some(header)) => {
sp_state_machine::Storage::get(self.storage.as_ref(), &header.state_root(), (&[], None)).unwrap_or(None).is_some()
sp_state_machine::Storage::get(
self.storage.as_ref(),
&header.state_root(),
(&[], None),
).unwrap_or(None).is_some()
},
_ => false,
}
@@ -1689,8 +1722,7 @@ impl<Block> sc_client_api::backend::Backend<Block, Blake2Hasher> for Backend<Blo
}
}
impl<Block> sc_client_api::backend::LocalBackend<Block, Blake2Hasher> for Backend<Block>
where Block: BlockT<Hash=H256> {}
impl<Block: BlockT> sc_client_api::backend::LocalBackend<Block> for Backend<Block> {}
/// TODO: remove me in #3201
pub fn unused_sink<Block: BlockT>(cache_tx: crate::cache::DbCacheTransaction<Block>) {
@@ -1703,6 +1735,7 @@ mod tests {
use hash_db::{HashDB, EMPTY_PREFIX};
use super::*;
use crate::columns;
use sp_core::{Blake2Hasher, H256};
use sc_client_api::backend::{Backend as BTrait, BlockImportOperation as Op};
use sc_client::blockchain::Backend as BLBTrait;
use sp_runtime::testing::{Header, Block as RawBlock, ExtrinsicWrapper};
+3 -4
View File
@@ -35,9 +35,8 @@ use sp_blockchain::{
};
use sc_client::light::blockchain::Storage as LightBlockchainStorage;
use codec::{Decode, Encode};
use sp_core::Blake2Hasher;
use sp_runtime::generic::{DigestItem, BlockId};
use sp_runtime::traits::{Block as BlockT, Header as HeaderT, Zero, One, NumberFor};
use sp_runtime::traits::{Block as BlockT, Header as HeaderT, Zero, One, NumberFor, HasherFor};
use crate::cache::{DbCacheSync, DbCache, ComplexBlockId, EntryType as CacheEntryType};
use crate::utils::{self, meta_keys, Meta, db_err, read_db, block_id_to_lookup_key, read_meta};
use crate::{DatabaseSettings, FrozenForDuration};
@@ -306,7 +305,7 @@ impl<Block: BlockT> LightStorage<Block> {
Some(old_current_num)
});
let new_header_cht_root = cht::compute_root::<Block::Header, Blake2Hasher, _>(
let new_header_cht_root = cht::compute_root::<Block::Header, HasherFor<Block>, _>(
cht::size(), new_cht_number, cht_range.map(|num| self.hash(num))
)?;
transaction.put(
@@ -323,7 +322,7 @@ impl<Block: BlockT> LightStorage<Block> {
current_num = current_num + One::one();
Some(old_current_num)
});
let new_changes_trie_cht_root = cht::compute_root::<Block::Header, Blake2Hasher, _>(
let new_changes_trie_cht_root = cht::compute_root::<Block::Header, HasherFor<Block>, _>(
cht::size(), new_cht_number, cht_range
.map(|num| self.changes_trie_root(BlockId::Number(num)))
)?;
+310 -92
View File
@@ -21,7 +21,7 @@ use std::sync::Arc;
use parking_lot::{Mutex, RwLock, RwLockUpgradableReadGuard};
use linked_hash_map::{LinkedHashMap, Entry};
use hash_db::Hasher;
use sp_runtime::traits::{Block as BlockT, Header};
use sp_runtime::traits::{Block as BlockT, Header, HasherFor, NumberFor};
use sp_core::hexdisplay::HexDisplay;
use sp_core::storage::ChildInfo;
use sp_state_machine::{backend::Backend as StateBackend, TrieBackend};
@@ -36,11 +36,11 @@ type ChildStorageKey = (Vec<u8>, Vec<u8>);
type StorageValue = Vec<u8>;
/// Shared canonical state cache.
pub struct Cache<B: BlockT, H: Hasher> {
pub struct Cache<B: BlockT> {
/// Storage cache. `None` indicates that key is known to be missing.
lru_storage: LRUMap<StorageKey, Option<StorageValue>>,
/// Storage hashes cache. `None` indicates that key is known to be missing.
lru_hashes: LRUMap<StorageKey, OptionHOut<H::Out>>,
lru_hashes: LRUMap<StorageKey, OptionHOut<B::Hash>>,
/// Storage cache for child trie. `None` indicates that key is known to be missing.
lru_child_storage: LRUMap<ChildStorageKey, Option<StorageValue>>,
/// Information on the modifications in recently committed blocks; specifically which keys
@@ -147,7 +147,7 @@ impl<K: EstimateSize + Eq + StdHash, V: EstimateSize> LRUMap<K, V> {
}
impl<B: BlockT, H: Hasher> Cache<B, H> {
impl<B: BlockT> Cache<B> {
/// Returns the used memory size of the storage cache in bytes.
pub fn used_storage_cache_size(&self) -> usize {
self.lru_storage.used_size()
@@ -215,25 +215,31 @@ impl<B: BlockT, H: Hasher> Cache<B, H> {
}
}
pub type SharedCache<B, H> = Arc<Mutex<Cache<B, H>>>;
pub type SharedCache<B> = Arc<Mutex<Cache<B>>>;
/// Fix lru storage size for hash (small 64ko).
const FIX_LRU_HASH_SIZE: usize = 65_536;
/// Create a new shared cache instance with given max memory usage.
pub fn new_shared_cache<B: BlockT, H: Hasher>(
pub fn new_shared_cache<B: BlockT>(
shared_cache_size: usize,
child_ratio: (usize, usize),
) -> SharedCache<B, H> {
) -> SharedCache<B> {
let top = child_ratio.1.saturating_sub(child_ratio.0);
Arc::new(Mutex::new(Cache {
lru_storage: LRUMap(LinkedHashMap::new(), 0,
shared_cache_size * top / child_ratio.1),
lru_hashes: LRUMap(LinkedHashMap::new(), 0, FIX_LRU_HASH_SIZE),
lru_child_storage: LRUMap(LinkedHashMap::new(), 0,
shared_cache_size * child_ratio.0 / child_ratio.1),
modifications: VecDeque::new(),
}))
Arc::new(
Mutex::new(
Cache {
lru_storage: LRUMap(
LinkedHashMap::new(), 0, shared_cache_size * top / child_ratio.1
),
lru_hashes: LRUMap(LinkedHashMap::new(), 0, FIX_LRU_HASH_SIZE),
lru_child_storage: LRUMap(
LinkedHashMap::new(), 0, shared_cache_size * child_ratio.0 / child_ratio.1
),
modifications: VecDeque::new(),
}
)
)
}
#[derive(Debug)]
@@ -270,11 +276,11 @@ struct LocalCache<H: Hasher> {
}
/// Cache changes.
pub struct CacheChanges<H: Hasher, B: BlockT> {
pub struct CacheChanges<B: BlockT> {
/// Shared canonical state cache.
shared_cache: SharedCache<B, H>,
shared_cache: SharedCache<B>,
/// Local cache of values for this state.
local_cache: RwLock<LocalCache<H>>,
local_cache: RwLock<LocalCache<HasherFor<B>>>,
/// Hash of the block on top of which this instance was created or
/// `None` if cache is disabled
pub parent_hash: Option<B::Hash>,
@@ -289,20 +295,20 @@ pub struct CacheChanges<H: Hasher, B: BlockT> {
/// For canonical instances local cache is accumulated and applied
/// in `sync_cache` along with the change overlay.
/// For non-canonical clones local cache and changes are dropped.
pub struct CachingState<H: Hasher, S: StateBackend<H>, B: BlockT> {
pub struct CachingState<S: StateBackend<HasherFor<B>>, B: BlockT> {
/// Backing state.
state: S,
/// Cache data.
pub cache: CacheChanges<H, B>
pub cache: CacheChanges<B>,
}
impl<H: Hasher, S: StateBackend<H>, B: BlockT> std::fmt::Debug for CachingState<H, S, B> {
impl<S: StateBackend<HasherFor<B>>, B: BlockT> std::fmt::Debug for CachingState<S, B> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "Block {:?}", self.cache.parent_hash)
}
}
impl<H: Hasher, B: BlockT> CacheChanges<H, B> {
impl<B: BlockT> CacheChanges<B> {
/// Propagate local cache into the shared cache and synchronize
/// the shared cache with the best block state.
///
@@ -317,11 +323,17 @@ impl<H: Hasher, B: BlockT> CacheChanges<H, B> {
changes: StorageCollection,
child_changes: ChildStorageCollection,
commit_hash: Option<B::Hash>,
commit_number: Option<<B::Header as Header>::Number>,
commit_number: Option<NumberFor<B>>,
is_best: bool,
) {
let mut cache = self.shared_cache.lock();
trace!("Syncing cache, id = (#{:?}, {:?}), parent={:?}, best={}", commit_number, commit_hash, self.parent_hash, is_best);
trace!(
"Syncing cache, id = (#{:?}, {:?}), parent={:?}, best={}",
commit_number,
commit_hash,
self.parent_hash,
is_best,
);
let cache = &mut *cache;
// Filter out commiting block if any.
let enacted: Vec<_> = enacted
@@ -405,9 +417,9 @@ impl<H: Hasher, B: BlockT> CacheChanges<H, B> {
}
impl<H: Hasher, S: StateBackend<H>, B: BlockT> CachingState<H, S, B> {
impl<S: StateBackend<HasherFor<B>>, B: BlockT> CachingState<S, B> {
/// Create a new instance wrapping generic State and shared cache.
pub fn new(state: S, shared_cache: SharedCache<B, H>, parent_hash: Option<B::Hash>) -> CachingState<H, S, B> {
pub fn new(state: S, shared_cache: SharedCache<B>, parent_hash: Option<B::Hash>) -> Self {
CachingState {
state,
cache: CacheChanges {
@@ -468,12 +480,12 @@ impl<H: Hasher, S: StateBackend<H>, B: BlockT> CachingState<H, S, B> {
}
/// Dispose state and return cache data.
pub fn release(self) -> CacheChanges<H, B> {
pub fn release(self) -> CacheChanges<B> {
self.cache
}
}
impl<H: Hasher, S: StateBackend<H>, B: BlockT> StateBackend<H> for CachingState<H, S, B> {
impl<S: StateBackend<HasherFor<B>>, B: BlockT> StateBackend<HasherFor<B>> for CachingState<S, B> {
type Error = S::Error;
type Transaction = S::Transaction;
type TrieBackendStorage = S::TrieBackendStorage;
@@ -498,7 +510,7 @@ impl<H: Hasher, S: StateBackend<H>, B: BlockT> StateBackend<H> for CachingState<
Ok(value)
}
fn storage_hash(&self, key: &[u8]) -> Result<Option<H::Out>, Self::Error> {
fn storage_hash(&self, key: &[u8]) -> Result<Option<B::Hash>, Self::Error> {
let local_cache = self.cache.local_cache.upgradable_read();
if let Some(entry) = local_cache.hashes.get(key).cloned() {
trace!("Found hash in local cache: {:?}", HexDisplay::from(&key));
@@ -595,10 +607,9 @@ impl<H: Hasher, S: StateBackend<H>, B: BlockT> StateBackend<H> for CachingState<
self.state.for_child_keys_with_prefix(storage_key, child_info, prefix, f)
}
fn storage_root<I>(&self, delta: I) -> (H::Out, Self::Transaction)
fn storage_root<I>(&self, delta: I) -> (B::Hash, Self::Transaction)
where
I: IntoIterator<Item=(Vec<u8>, Option<Vec<u8>>)>,
H::Out: Ord
{
self.state.storage_root(delta)
}
@@ -608,10 +619,9 @@ impl<H: Hasher, S: StateBackend<H>, B: BlockT> StateBackend<H> for CachingState<
storage_key: &[u8],
child_info: ChildInfo,
delta: I,
) -> (H::Out, bool, Self::Transaction)
) -> (B::Hash, bool, Self::Transaction)
where
I: IntoIterator<Item=(Vec<u8>, Option<Vec<u8>>)>,
H::Out: Ord
{
self.state.child_storage_root(storage_key, child_info, delta)
}
@@ -633,7 +643,7 @@ impl<H: Hasher, S: StateBackend<H>, B: BlockT> StateBackend<H> for CachingState<
self.state.child_keys(storage_key, child_info, prefix)
}
fn as_trie_backend(&mut self) -> Option<&TrieBackend<Self::TrieBackendStorage, H>> {
fn as_trie_backend(&mut self) -> Option<&TrieBackend<Self::TrieBackendStorage, HasherFor<B>>> {
self.state.as_trie_backend()
}
}
@@ -642,7 +652,7 @@ impl<H: Hasher, S: StateBackend<H>, B: BlockT> StateBackend<H> for CachingState<
mod tests {
use super::*;
use sp_runtime::testing::{H256, Block as RawBlock, ExtrinsicWrapper};
use sp_state_machine::backend::InMemory;
use sp_state_machine::InMemoryBackend;
use sp_core::Blake2Hasher;
type Block = RawBlock<ExtrinsicWrapper<u32>>;
@@ -660,43 +670,119 @@ mod tests {
let h3a = H256::random();
let h3b = H256::random();
let shared = new_shared_cache::<Block, Blake2Hasher>(256*1024, (0,1));
let shared = new_shared_cache::<Block>(256 * 1024, (0, 1));
// blocks [ 3a(c) 2a(c) 2b 1b 1a(c) 0 ]
// state [ 5 5 4 3 2 2 ]
let mut s = CachingState::new(InMemory::<Blake2Hasher>::default(), shared.clone(), Some(root_parent));
s.cache.sync_cache(&[], &[], vec![(key.clone(), Some(vec![2]))], vec![], Some(h0), Some(0), true);
let mut s = CachingState::new(
InMemoryBackend::<Blake2Hasher>::default(),
shared.clone(),
Some(root_parent),
);
s.cache.sync_cache(
&[],
&[],
vec![(key.clone(), Some(vec![2]))],
vec![],
Some(h0),
Some(0),
true,
);
let mut s = CachingState::new(InMemory::<Blake2Hasher>::default(), shared.clone(), Some(h0));
let mut s = CachingState::new(
InMemoryBackend::<Blake2Hasher>::default(),
shared.clone(),
Some(h0),
);
s.cache.sync_cache(&[], &[], vec![], vec![], Some(h1a), Some(1), true);
let mut s = CachingState::new(InMemory::<Blake2Hasher>::default(), shared.clone(), Some(h0));
s.cache.sync_cache(&[], &[], vec![(key.clone(), Some(vec![3]))], vec![], Some(h1b), Some(1), false);
let mut s = CachingState::new(
InMemoryBackend::<Blake2Hasher>::default(),
shared.clone(),
Some(h0),
);
s.cache.sync_cache(
&[],
&[],
vec![(key.clone(), Some(vec![3]))],
vec![],
Some(h1b),
Some(1),
false,
);
let mut s = CachingState::new(InMemory::<Blake2Hasher>::default(), shared.clone(), Some(h1b.clone()));
s.cache.sync_cache(&[], &[], vec![(key.clone(), Some(vec![4]))], vec![], Some(h2b), Some(2), false);
let mut s = CachingState::new(
InMemoryBackend::<Blake2Hasher>::default(),
shared.clone(),
Some(h1b),
);
s.cache.sync_cache(
&[],
&[],
vec![(key.clone(), Some(vec![4]))],
vec![],
Some(h2b),
Some(2),
false,
);
let mut s = CachingState::new(InMemory::<Blake2Hasher>::default(), shared.clone(), Some(h1a.clone()));
s.cache.sync_cache(&[], &[], vec![(key.clone(), Some(vec![5]))], vec![], Some(h2a), Some(2), true);
let mut s = CachingState::new(
InMemoryBackend::<Blake2Hasher>::default(),
shared.clone(),
Some(h1a),
);
s.cache.sync_cache(
&[],
&[],
vec![(key.clone(), Some(vec![5]))],
vec![],
Some(h2a),
Some(2),
true,
);
let mut s = CachingState::new(InMemory::<Blake2Hasher>::default(), shared.clone(), Some(h2a));
let mut s = CachingState::new(
InMemoryBackend::<Blake2Hasher>::default(),
shared.clone(),
Some(h2a),
);
s.cache.sync_cache(&[], &[], vec![], vec![], Some(h3a), Some(3), true);
let s = CachingState::new(InMemory::<Blake2Hasher>::default(), shared.clone(), Some(h3a));
let s = CachingState::new(
InMemoryBackend::<Blake2Hasher>::default(),
shared.clone(),
Some(h3a),
);
assert_eq!(s.storage(&key).unwrap().unwrap(), vec![5]);
let s = CachingState::new(InMemory::<Blake2Hasher>::default(), shared.clone(), Some(h1a));
let s = CachingState::new(
InMemoryBackend::<Blake2Hasher>::default(),
shared.clone(),
Some(h1a),
);
assert!(s.storage(&key).unwrap().is_none());
let s = CachingState::new(InMemory::<Blake2Hasher>::default(), shared.clone(), Some(h2b));
let s = CachingState::new(
InMemoryBackend::<Blake2Hasher>::default(),
shared.clone(),
Some(h2b),
);
assert!(s.storage(&key).unwrap().is_none());
let s = CachingState::new(InMemory::<Blake2Hasher>::default(), shared.clone(), Some(h1b));
let s = CachingState::new(
InMemoryBackend::<Blake2Hasher>::default(),
shared.clone(),
Some(h1b),
);
assert!(s.storage(&key).unwrap().is_none());
// reorg to 3b
// blocks [ 3b(c) 3a 2a 2b(c) 1b 1a 0 ]
let mut s = CachingState::new(InMemory::<Blake2Hasher>::default(), shared.clone(), Some(h2b));
let mut s = CachingState::new(
InMemoryBackend::<Blake2Hasher>::default(),
shared.clone(),
Some(h2b),
);
s.cache.sync_cache(
&[h1b, h2b, h3b],
&[h1a, h2a, h3a],
@@ -706,7 +792,11 @@ mod tests {
Some(3),
true,
);
let s = CachingState::new(InMemory::<Blake2Hasher>::default(), shared.clone(), Some(h3a));
let s = CachingState::new(
InMemoryBackend::<Blake2Hasher>::default(),
shared.clone(),
Some(h3a),
);
assert!(s.storage(&key).unwrap().is_none());
}
@@ -721,21 +811,65 @@ mod tests {
let h2b = H256::random();
let h3b = H256::random();
let shared = new_shared_cache::<Block, Blake2Hasher>(256*1024, (0,1));
let shared = new_shared_cache::<Block>(256*1024, (0,1));
let mut s = CachingState::new(InMemory::<Blake2Hasher>::default(), shared.clone(), Some(root_parent));
s.cache.sync_cache(&[], &[], vec![(key.clone(), Some(vec![2]))], vec![], Some(h1), Some(1), true);
let mut s = CachingState::new(
InMemoryBackend::<Blake2Hasher>::default(),
shared.clone(),
Some(root_parent),
);
s.cache.sync_cache(
&[],
&[],
vec![(key.clone(), Some(vec![2]))],
vec![],
Some(h1),
Some(1),
true,
);
let mut s = CachingState::new(InMemory::<Blake2Hasher>::default(), shared.clone(), Some(h1));
let mut s = CachingState::new(
InMemoryBackend::<Blake2Hasher>::default(),
shared.clone(),
Some(h1),
);
s.cache.sync_cache(&[], &[], vec![], vec![], Some(h2a), Some(2), true);
let mut s = CachingState::new(InMemory::<Blake2Hasher>::default(), shared.clone(), Some(h1));
s.cache.sync_cache(&[], &[], vec![(key.clone(), Some(vec![3]))], vec![], Some(h2b), Some(2), false);
let mut s = CachingState::new(
InMemoryBackend::<Blake2Hasher>::default(),
shared.clone(),
Some(h1),
);
s.cache.sync_cache(
&[],
&[],
vec![(key.clone(), Some(vec![3]))],
vec![],
Some(h2b),
Some(2),
false,
);
let mut s = CachingState::new(InMemory::<Blake2Hasher>::default(), shared.clone(), Some(h2b));
s.cache.sync_cache(&[], &[], vec![(key.clone(), Some(vec![3]))], vec![], Some(h3b), Some(2), false);
let mut s = CachingState::new(
InMemoryBackend::<Blake2Hasher>::default(),
shared.clone(),
Some(h2b),
);
s.cache.sync_cache(
&[],
&[],
vec![(key.clone(), Some(vec![3]))],
vec![],
Some(h3b),
Some(2),
false,
);
let s = CachingState::new(InMemory::<Blake2Hasher>::default(), shared.clone(), Some(h2a));
let s = CachingState::new(
InMemoryBackend::<Blake2Hasher>::default(),
shared.clone(),
Some(h2a),
);
assert_eq!(s.storage(&key).unwrap().unwrap(), vec![2]);
}
@@ -749,34 +883,76 @@ mod tests {
let h3a = H256::random();
let h3b = H256::random();
let shared = new_shared_cache::<Block, Blake2Hasher>(256*1024, (0,1));
let shared = new_shared_cache::<Block>(256*1024, (0,1));
let mut s = CachingState::new(InMemory::<Blake2Hasher>::default(), shared.clone(), Some(root_parent));
let mut s = CachingState::new(
InMemoryBackend::<Blake2Hasher>::default(),
shared.clone(),
Some(root_parent),
);
s.cache.sync_cache(&[], &[], vec![], vec![], Some(h1), Some(1), true);
let mut s = CachingState::new(InMemory::<Blake2Hasher>::default(), shared.clone(), Some(h1));
let mut s = CachingState::new(
InMemoryBackend::<Blake2Hasher>::default(),
shared.clone(),
Some(h1),
);
s.cache.sync_cache(&[], &[], vec![], vec![], Some(h2a), Some(2), true);
let mut s = CachingState::new(InMemory::<Blake2Hasher>::default(), shared.clone(), Some(h2a));
s.cache.sync_cache(&[], &[], vec![(key.clone(), Some(vec![2]))], vec![], Some(h3a), Some(3), true);
let mut s = CachingState::new(
InMemoryBackend::<Blake2Hasher>::default(),
shared.clone(),
Some(h2a),
);
s.cache.sync_cache(
&[],
&[],
vec![(key.clone(), Some(vec![2]))],
vec![],
Some(h3a),
Some(3),
true,
);
let mut s = CachingState::new(InMemory::<Blake2Hasher>::default(), shared.clone(), Some(h1));
let mut s = CachingState::new(
InMemoryBackend::<Blake2Hasher>::default(),
shared.clone(),
Some(h1),
);
s.cache.sync_cache(&[], &[], vec![], vec![], Some(h2b), Some(2), false);
let mut s = CachingState::new(InMemory::<Blake2Hasher>::default(), shared.clone(), Some(h2b));
s.cache.sync_cache(&[], &[], vec![(key.clone(), Some(vec![3]))], vec![], Some(h3b), Some(3), false);
let mut s = CachingState::new(
InMemoryBackend::<Blake2Hasher>::default(),
shared.clone(),
Some(h2b),
);
s.cache.sync_cache(
&[],
&[],
vec![(key.clone(), Some(vec![3]))],
vec![],
Some(h3b),
Some(3),
false,
);
let s = CachingState::new(InMemory::<Blake2Hasher>::default(), shared.clone(), Some(h3a));
let s = CachingState::new(
InMemoryBackend::<Blake2Hasher>::default(),
shared.clone(),
Some(h3a),
);
assert_eq!(s.storage(&key).unwrap().unwrap(), vec![2]);
}
#[test]
fn should_track_used_size_correctly() {
let root_parent = H256::random();
let shared = new_shared_cache::<Block, Blake2Hasher>(109, ((109-36), 109));
let shared = new_shared_cache::<Block>(109, ((109-36), 109));
let h0 = H256::random();
let mut s = CachingState::new(InMemory::<Blake2Hasher>::default(), shared.clone(), Some(root_parent));
let mut s = CachingState::new(
InMemoryBackend::<Blake2Hasher>::default(), shared.clone(), Some(root_parent.clone()),
);
let key = H256::random()[..].to_vec();
let s_key = H256::random()[..].to_vec();
@@ -809,10 +985,14 @@ mod tests {
#[test]
fn should_remove_lru_items_based_on_tracking_used_size() {
let root_parent = H256::random();
let shared = new_shared_cache::<Block, Blake2Hasher>(36*3, (2,3));
let shared = new_shared_cache::<Block>(36*3, (2,3));
let h0 = H256::random();
let mut s = CachingState::new(InMemory::<Blake2Hasher>::default(), shared.clone(), Some(root_parent));
let mut s = CachingState::new(
InMemoryBackend::<Blake2Hasher>::default(),
shared.clone(),
Some(root_parent),
);
let key = H256::random()[..].to_vec();
s.cache.sync_cache(
@@ -851,14 +1031,42 @@ mod tests {
let h0 = H256::random();
let h1 = H256::random();
let shared = new_shared_cache::<Block, Blake2Hasher>(256*1024, (0, 1));
let mut s = CachingState::new(InMemory::<Blake2Hasher>::default(), shared.clone(), Some(root_parent));
s.cache.sync_cache(&[], &[], vec![(key.clone(), Some(vec![2]))], vec![], Some(h0), Some(0), true);
let shared = new_shared_cache::<Block>(256 * 1024, (0, 1));
let mut s = CachingState::new(
InMemoryBackend::<Blake2Hasher>::default(),
shared.clone(),
Some(root_parent.clone()),
);
s.cache.sync_cache(
&[],
&[],
vec![(key.clone(), Some(vec![2]))],
vec![],
Some(h0.clone()),
Some(0),
true,
);
let mut s = CachingState::new(InMemory::<Blake2Hasher>::default(), shared.clone(), Some(h0));
s.cache.sync_cache(&[], &[], vec![(key.clone(), Some(vec![3]))], vec![], Some(h1), Some(1), true);
let mut s = CachingState::new(
InMemoryBackend::<Blake2Hasher>::default(),
shared.clone(),
Some(h0),
);
s.cache.sync_cache(
&[],
&[],
vec![(key.clone(), Some(vec![3]))],
vec![],
Some(h1),
Some(1),
true,
);
let mut s = CachingState::new(InMemory::<Blake2Hasher>::default(), shared.clone(), Some(h1));
let mut s = CachingState::new(
InMemoryBackend::<Blake2Hasher>::default(),
shared.clone(),
Some(h1),
);
assert_eq!(s.storage(&key).unwrap(), Some(vec![3]));
// Restart (or unknown block?), clear caches.
@@ -877,7 +1085,11 @@ mod tests {
// New value is propagated.
s.cache.sync_cache(&[], &[], vec![], vec![], None, None, true);
let s = CachingState::new(InMemory::<Blake2Hasher>::default(), shared.clone(), Some(h1));
let s = CachingState::new(
InMemoryBackend::<Blake2Hasher>::default(),
shared.clone(),
Some(h1),
);
assert_eq!(s.storage(&key).unwrap(), None);
}
}
@@ -890,7 +1102,7 @@ mod qc {
use super::*;
use sp_runtime::testing::{H256, Block as RawBlock, ExtrinsicWrapper};
use sp_state_machine::backend::InMemory;
use sp_state_machine::InMemoryBackend;
use sp_core::Blake2Hasher;
type Block = RawBlock<ExtrinsicWrapper<u32>>;
@@ -1002,14 +1214,14 @@ mod qc {
}
struct Mutator {
shared: SharedCache<Block, Blake2Hasher>,
shared: SharedCache<Block>,
canon: Vec<Node>,
forks: HashMap<H256, Vec<Node>>,
}
impl Mutator {
fn new_empty() -> Self {
let shared = new_shared_cache::<Block, Blake2Hasher>(256*1024, (0,1));
let shared = new_shared_cache::<Block>(256*1024, (0,1));
Self {
shared,
@@ -1018,19 +1230,22 @@ mod qc {
}
}
fn head_state(&self, hash: H256) -> CachingState<Blake2Hasher, InMemory<Blake2Hasher>, Block> {
fn head_state(&self, hash: H256) -> CachingState<InMemoryBackend<Blake2Hasher>, Block> {
CachingState::new(
InMemory::<Blake2Hasher>::default(),
InMemoryBackend::<Blake2Hasher>::default(),
self.shared.clone(),
Some(hash)
)
}
fn canon_head_state(&self) -> CachingState<Blake2Hasher, InMemory<Blake2Hasher>, Block> {
fn canon_head_state(&self) -> CachingState<InMemoryBackend<Blake2Hasher>, Block> {
self.head_state(self.canon.last().expect("Expected to be one commit").hash)
}
fn mutate_static(&mut self, action: Action) -> CachingState<Blake2Hasher, InMemory<Blake2Hasher>, Block> {
fn mutate_static(
&mut self,
action: Action,
) -> CachingState<InMemoryBackend<Blake2Hasher>, Block> {
self.mutate(action).expect("Expected to provide only valid actions to the mutate_static")
}
@@ -1046,7 +1261,10 @@ mod qc {
(0u8..255).map(|x| vec![x]).collect()
}
fn mutate(&mut self, action: Action) -> Result<CachingState<Blake2Hasher, InMemory<Blake2Hasher>, Block>, ()> {
fn mutate(
&mut self,
action: Action,
) -> Result<CachingState<InMemoryBackend<Blake2Hasher>, Block>, ()> {
let state = match action {
Action::Fork { depth, hash, changes } => {
let pos = self.canon.len() as isize - depth as isize;
@@ -1083,7 +1301,7 @@ mod qc {
};
let mut state = CachingState::new(
InMemory::<Blake2Hasher>::default(),
InMemoryBackend::<Blake2Hasher>::default(),
self.shared.clone(),
Some(parent)
);
@@ -1122,7 +1340,7 @@ mod qc {
}
let mut state = CachingState::new(
InMemory::<Blake2Hasher>::default(),
InMemoryBackend::<Blake2Hasher>::default(),
self.shared.clone(),
Some(parent_hash)
);
@@ -1169,7 +1387,7 @@ mod qc {
self.canon.push(node);
let mut state = CachingState::new(
InMemory::<Blake2Hasher>::default(),
InMemoryBackend::<Blake2Hasher>::default(),
self.shared.clone(),
Some(fork_at)
);
@@ -29,7 +29,7 @@ use sp_blockchain::{HeaderBackend, Error as ClientError};
use sc_client_api::{
BlockchainEvents,
backend::{Backend},
backend::{AuxStore, Backend},
Finalizer,
call_executor::CallExecutor,
utils::is_descendent_of,
@@ -41,7 +41,7 @@ use finality_grandpa::{
BlockNumberOps, Equivocation, Error as GrandpaError, round::State as RoundState,
voter, voter_set::VoterSet,
};
use sp_core::{Blake2Hasher, H256, Pair};
use sp_core::Pair;
use sp_runtime::generic::BlockId;
use sp_runtime::traits::{
Block as BlockT, Header as HeaderT, NumberFor, One, Zero,
@@ -406,13 +406,13 @@ impl<B, E, Block: BlockT, N: NetworkT<Block>, RA, SC, VR> Environment<B, E, Bloc
}
}
impl<Block: BlockT<Hash=H256>, B, E, N, RA, SC, VR>
impl<Block: BlockT, B, E, N, RA, SC, VR>
finality_grandpa::Chain<Block::Hash, NumberFor<Block>>
for Environment<B, E, Block, N, RA, SC, VR>
where
Block: 'static,
B: Backend<Block, Blake2Hasher> + 'static,
E: CallExecutor<Block, Blake2Hasher> + Send + Sync + 'static,
B: Backend<Block> + 'static,
E: CallExecutor<Block> + Send + Sync + 'static,
N: NetworkT<Block> + 'static + Send,
SC: SelectChain<Block> + 'static,
VR: VotingRule<Block, Client<B, E, Block, RA>>,
@@ -519,13 +519,13 @@ where
}
pub(crate) fn ancestry<B, Block: BlockT<Hash=H256>, E, RA>(
pub(crate) fn ancestry<B, Block: BlockT, E, RA>(
client: &Client<B, E, Block, RA>,
base: Block::Hash,
block: Block::Hash,
) -> Result<Vec<Block::Hash>, GrandpaError> where
B: Backend<Block, Blake2Hasher>,
E: CallExecutor<Block, Blake2Hasher>,
B: Backend<Block>,
E: CallExecutor<Block>,
{
if base == block { return Err(GrandpaError::NotDescendent) }
@@ -550,18 +550,19 @@ pub(crate) fn ancestry<B, Block: BlockT<Hash=H256>, E, RA>(
Ok(tree_route.retracted().iter().skip(1).map(|e| e.hash).collect())
}
impl<B, E, Block: BlockT<Hash=H256>, N, RA, SC, VR>
impl<B, E, Block: BlockT, N, RA, SC, VR>
voter::Environment<Block::Hash, NumberFor<Block>>
for Environment<B, E, Block, N, RA, SC, VR>
where
Block: 'static,
B: Backend<Block, Blake2Hasher> + 'static,
E: CallExecutor<Block, Blake2Hasher> + 'static + Send + Sync,
B: Backend<Block> + 'static,
E: CallExecutor<Block> + 'static + Send + Sync,
N: NetworkT<Block> + 'static + Send,
RA: 'static + Send + Sync,
SC: SelectChain<Block> + 'static,
VR: VotingRule<Block, Client<B, E, Block, RA>>,
NumberFor<Block>: BlockNumberOps,
Client<B, E, Block, RA>: AuxStore,
{
type Timer = Box<dyn Future<Item = (), Error = Self::Error> + Send>;
type Id = AuthorityId;
@@ -940,7 +941,7 @@ impl<Block: BlockT> From<GrandpaJustification<Block>> for JustificationOrCommit<
/// authority set change is enacted then a justification is created (if not
/// given) and stored with the block when finalizing it.
/// This method assumes that the block being finalized has already been imported.
pub(crate) fn finalize_block<B, Block: BlockT<Hash=H256>, E, RA>(
pub(crate) fn finalize_block<B, Block: BlockT, E, RA>(
client: &Client<B, E, Block, RA>,
authority_set: &SharedAuthoritySet<Block::Hash, NumberFor<Block>>,
consensus_changes: &SharedConsensusChanges<Block::Hash, NumberFor<Block>>,
@@ -949,8 +950,8 @@ pub(crate) fn finalize_block<B, Block: BlockT<Hash=H256>, E, RA>(
number: NumberFor<Block>,
justification_or_commit: JustificationOrCommit<Block>,
) -> Result<(), CommandOrError<Block::Hash, NumberFor<Block>>> where
B: Backend<Block, Blake2Hasher>,
E: CallExecutor<Block, Blake2Hasher> + Send + Sync,
B: Backend<Block>,
E: CallExecutor<Block> + Send + Sync,
RA: Send + Sync,
{
// NOTE: lock must be held through writing to DB to avoid race. this lock
@@ -988,7 +989,7 @@ pub(crate) fn finalize_block<B, Block: BlockT<Hash=H256>, E, RA>(
let status = authority_set.apply_standard_changes(
hash,
number,
&is_descendent_of::<_, _, Block::Hash>(client, None),
&is_descendent_of::<Block, _>(client, None),
).map_err(|e| Error::Safety(e.to_string()))?;
// check if this is this is the first finalization of some consensus changes
@@ -1124,8 +1125,8 @@ pub(crate) fn finalize_block<B, Block: BlockT<Hash=H256>, E, RA>(
/// Using the given base get the block at the given height on this chain. The
/// target block must be an ancestor of base, therefore `height <= base.height`.
pub(crate) fn canonical_at_height<Block: BlockT<Hash=H256>, C: HeaderBackend<Block>>(
provider: C,
pub(crate) fn canonical_at_height<Block: BlockT, C: HeaderBackend<Block>>(
provider: &C,
base: (Block::Hash, NumberFor<Block>),
base_is_canonical: bool,
height: NumberFor<Block>,
@@ -50,7 +50,7 @@ use sp_runtime::{
Justification, generic::BlockId,
traits::{NumberFor, Block as BlockT, Header as HeaderT, One},
};
use sp_core::{H256, Blake2Hasher, storage::StorageKey};
use sp_core::storage::StorageKey;
use sc_telemetry::{telemetry, CONSENSUS_INFO};
use sp_finality_grandpa::{AuthorityId, AuthorityList, VersionedAuthorityList, GRANDPA_AUTHORITIES_KEY};
@@ -68,10 +68,10 @@ pub trait AuthoritySetForFinalityProver<Block: BlockT>: Send + Sync {
}
/// Client-based implementation of AuthoritySetForFinalityProver.
impl<B, E, Block: BlockT<Hash=H256>, RA> AuthoritySetForFinalityProver<Block> for Client<B, E, Block, RA>
impl<B, E, Block: BlockT, RA> AuthoritySetForFinalityProver<Block> for Client<B, E, Block, RA>
where
B: Backend<Block, Blake2Hasher> + Send + Sync + 'static,
E: CallExecutor<Block, Blake2Hasher> + 'static + Clone + Send + Sync,
B: Backend<Block> + Send + Sync + 'static,
E: CallExecutor<Block> + 'static + Clone + Send + Sync,
RA: Send + Sync,
{
fn authorities(&self, block: &BlockId<Block>) -> ClientResult<AuthorityList> {
@@ -134,13 +134,13 @@ impl<Block: BlockT> AuthoritySetForFinalityChecker<Block> for Arc<dyn FetchCheck
}
/// Finality proof provider for serving network requests.
pub struct FinalityProofProvider<B, Block: BlockT<Hash=H256>> {
pub struct FinalityProofProvider<B, Block: BlockT> {
backend: Arc<B>,
authority_provider: Arc<dyn AuthoritySetForFinalityProver<Block>>,
}
impl<B, Block: BlockT<Hash=H256>> FinalityProofProvider<B, Block>
where B: Backend<Block, Blake2Hasher> + Send + Sync + 'static
impl<B, Block: BlockT> FinalityProofProvider<B, Block>
where B: Backend<Block> + Send + Sync + 'static
{
/// Create new finality proof provider using:
///
@@ -156,9 +156,9 @@ impl<B, Block: BlockT<Hash=H256>> FinalityProofProvider<B, Block>
impl<B, Block> sc_network::FinalityProofProvider<Block> for FinalityProofProvider<B, Block>
where
Block: BlockT<Hash=H256>,
Block: BlockT,
NumberFor<Block>: BlockNumberOps,
B: Backend<Block, Blake2Hasher> + Send + Sync + 'static,
B: Backend<Block> + Send + Sync + 'static,
{
fn prove_finality(
&self,
@@ -252,7 +252,7 @@ pub(crate) fn make_finality_proof_request<H: Encode + Decode>(last_finalized: H,
/// It is assumed that the caller already knows all blocks in the range (begin; end].
///
/// Returns None if there are no finalized blocks unknown to the caller.
pub(crate) fn prove_finality<Block: BlockT<Hash=H256>, B: BlockchainBackend<Block>, J>(
pub(crate) fn prove_finality<Block: BlockT, B: BlockchainBackend<Block>, J>(
blockchain: &B,
authorities_provider: &dyn AuthoritySetForFinalityProver<Block>,
authorities_set_id: u64,
@@ -410,7 +410,7 @@ pub(crate) fn prove_finality<Block: BlockT<Hash=H256>, B: BlockchainBackend<Bloc
///
/// Returns the vector of headers that MUST be validated + imported
/// AND if at least one of those headers is invalid, all other MUST be considered invalid.
pub(crate) fn check_finality_proof<Block: BlockT<Hash=H256>, B>(
pub(crate) fn check_finality_proof<Block: BlockT, B>(
blockchain: &B,
current_set_id: u64,
current_authorities: AuthorityList,
@@ -429,7 +429,7 @@ pub(crate) fn check_finality_proof<Block: BlockT<Hash=H256>, B>(
remote_proof)
}
fn do_check_finality_proof<Block: BlockT<Hash=H256>, B, J>(
fn do_check_finality_proof<Block: BlockT, B, J>(
blockchain: &B,
current_set_id: u64,
current_authorities: AuthorityList,
@@ -484,7 +484,7 @@ fn do_check_finality_proof<Block: BlockT<Hash=H256>, B, J>(
}
/// Check finality proof for the single block.
fn check_finality_proof_fragment<Block: BlockT<Hash=H256>, B, J>(
fn check_finality_proof_fragment<Block: BlockT, B, J>(
blockchain: &B,
authority_set: AuthoritiesOrEffects<Block::Header>,
authorities_provider: &dyn AuthoritySetForFinalityChecker<Block>,
@@ -569,7 +569,7 @@ pub(crate) trait ProvableJustification<Header: HeaderT>: Encode + Decode {
}
}
impl<Block: BlockT<Hash=H256>> ProvableJustification<Block::Header> for GrandpaJustification<Block>
impl<Block: BlockT> ProvableJustification<Block::Header> for GrandpaJustification<Block>
where
NumberFor<Block>: BlockNumberOps,
{
+36 -26
View File
@@ -22,7 +22,7 @@ use futures::sync::mpsc;
use parking_lot::RwLockWriteGuard;
use sp_blockchain::{HeaderBackend, BlockStatus, well_known_cache_keys};
use sc_client_api::{backend::Backend, CallExecutor, utils::is_descendent_of};
use sc_client_api::{backend::{TransactionFor, Backend}, CallExecutor, utils::is_descendent_of};
use sc_client::Client;
use sp_consensus::{
BlockImport, Error as ConsensusError,
@@ -35,7 +35,6 @@ use sp_runtime::generic::{BlockId, OpaqueDigestItemId};
use sp_runtime::traits::{
Block as BlockT, DigestFor, Header as HeaderT, NumberFor, Zero,
};
use sp_core::{H256, Blake2Hasher};
use crate::{Error, CommandOrError, NewAuthoritySet, VoterCommand};
use crate::authorities::{AuthoritySet, SharedAuthoritySet, DelayKind, PendingChange};
@@ -52,7 +51,7 @@ use crate::justification::GrandpaJustification;
///
/// When using GRANDPA, the block import worker should be using this block import
/// object.
pub struct GrandpaBlockImport<B, E, Block: BlockT<Hash=H256>, RA, SC> {
pub struct GrandpaBlockImport<B, E, Block: BlockT, RA, SC> {
inner: Arc<Client<B, E, Block, RA>>,
select_chain: SC,
authority_set: SharedAuthoritySet<Block::Hash, NumberFor<Block>>,
@@ -60,7 +59,7 @@ pub struct GrandpaBlockImport<B, E, Block: BlockT<Hash=H256>, RA, SC> {
consensus_changes: SharedConsensusChanges<Block::Hash, NumberFor<Block>>,
}
impl<B, E, Block: BlockT<Hash=H256>, RA, SC: Clone> Clone for
impl<B, E, Block: BlockT, RA, SC: Clone> Clone for
GrandpaBlockImport<B, E, Block, RA, SC>
{
fn clone(&self) -> Self {
@@ -74,11 +73,11 @@ impl<B, E, Block: BlockT<Hash=H256>, RA, SC: Clone> Clone for
}
}
impl<B, E, Block: BlockT<Hash=H256>, RA, SC> JustificationImport<Block>
impl<B, E, Block: BlockT, RA, SC> JustificationImport<Block>
for GrandpaBlockImport<B, E, Block, RA, SC> where
NumberFor<Block>: finality_grandpa::BlockNumberOps,
B: Backend<Block, Blake2Hasher> + 'static,
E: CallExecutor<Block, Blake2Hasher> + 'static + Clone + Send + Sync,
B: Backend<Block> + 'static,
E: CallExecutor<Block> + 'static + Clone + Send + Sync,
DigestFor<Block>: Encode,
RA: Send + Sync,
SC: SelectChain<Block>,
@@ -201,12 +200,12 @@ fn find_forced_change<B: BlockT>(header: &B::Header)
header.digest().convert_first(|l| l.try_to(id).and_then(filter_log))
}
impl<B, E, Block: BlockT<Hash=H256>, RA, SC>
impl<B, E, Block: BlockT, RA, SC>
GrandpaBlockImport<B, E, Block, RA, SC>
where
NumberFor<Block>: finality_grandpa::BlockNumberOps,
B: Backend<Block, Blake2Hasher> + 'static,
E: CallExecutor<Block, Blake2Hasher> + 'static + Clone + Send + Sync,
B: Backend<Block> + 'static,
E: CallExecutor<Block> + 'static + Clone + Send + Sync,
DigestFor<Block>: Encode,
RA: Send + Sync,
{
@@ -236,9 +235,11 @@ where
})
}
fn make_authorities_changes<'a>(&'a self, block: &mut BlockImportParams<Block>, hash: Block::Hash)
-> Result<PendingSetChanges<'a, Block>, ConsensusError>
{
fn make_authorities_changes<'a>(
&'a self,
block: &mut BlockImportParams<Block, TransactionFor<B, Block>>,
hash: Block::Hash,
) -> Result<PendingSetChanges<'a, Block>, ConsensusError> {
// when we update the authorities, we need to hold the lock
// until the block is written to prevent a race if we need to restore
// the old authority set on error or panic.
@@ -285,7 +286,7 @@ where
// returns a function for checking whether a block is a descendent of another
// consistent with querying client directly after importing the block.
let parent_hash = *block.header.parent_hash();
let is_descendent_of = is_descendent_of(&*self.inner, Some((&hash, &parent_hash)));
let is_descendent_of = is_descendent_of(&*self.inner, Some((hash, parent_hash)));
let mut guard = InnerGuard {
guard: Some(self.authority_set.inner().write()),
@@ -379,19 +380,22 @@ where
}
}
impl<B, E, Block: BlockT<Hash=H256>, RA, SC> BlockImport<Block>
impl<B, E, Block: BlockT, RA, SC> BlockImport<Block>
for GrandpaBlockImport<B, E, Block, RA, SC> where
NumberFor<Block>: finality_grandpa::BlockNumberOps,
B: Backend<Block, Blake2Hasher> + 'static,
E: CallExecutor<Block, Blake2Hasher> + 'static + Clone + Send + Sync,
B: Backend<Block> + 'static,
E: CallExecutor<Block> + 'static + Clone + Send + Sync,
DigestFor<Block>: Encode,
RA: Send + Sync,
for<'a> &'a Client<B, E, Block, RA>:
BlockImport<Block, Error = ConsensusError, Transaction = TransactionFor<B, Block>>,
{
type Error = ConsensusError;
type Transaction = TransactionFor<B, Block>;
fn import_block(
&mut self,
mut block: BlockImportParams<Block>,
mut block: BlockImportParams<Block, Self::Transaction>,
new_cache: HashMap<well_known_cache_keys::Id, Vec<u8>>,
) -> Result<ImportResult, Self::Error> {
let hash = block.post_header().hash();
@@ -416,12 +420,20 @@ impl<B, E, Block: BlockT<Hash=H256>, RA, SC> BlockImport<Block>
match import_result {
Ok(ImportResult::Imported(aux)) => aux,
Ok(r) => {
debug!(target: "afg", "Restoring old authority set after block import result: {:?}", r);
debug!(
target: "afg",
"Restoring old authority set after block import result: {:?}",
r,
);
pending_changes.revert();
return Ok(r);
},
Err(e) => {
debug!(target: "afg", "Restoring old authority set after block import error: {:?}", e);
debug!(
target: "afg",
"Restoring old authority set after block import error: {:?}",
e,
);
pending_changes.revert();
return Err(ConsensusError::ClientImport(e.to_string()).into());
},
@@ -509,9 +521,7 @@ impl<B, E, Block: BlockT<Hash=H256>, RA, SC> BlockImport<Block>
}
}
impl<B, E, Block: BlockT<Hash=H256>, RA, SC>
GrandpaBlockImport<B, E, Block, RA, SC>
{
impl<B, E, Block: BlockT, RA, SC> GrandpaBlockImport<B, E, Block, RA, SC> {
pub(crate) fn new(
inner: Arc<Client<B, E, Block, RA>>,
select_chain: SC,
@@ -529,12 +539,12 @@ impl<B, E, Block: BlockT<Hash=H256>, RA, SC>
}
}
impl<B, E, Block: BlockT<Hash=H256>, RA, SC>
impl<B, E, Block: BlockT, RA, SC>
GrandpaBlockImport<B, E, Block, RA, SC>
where
NumberFor<Block>: finality_grandpa::BlockNumberOps,
B: Backend<Block, Blake2Hasher> + 'static,
E: CallExecutor<Block, Blake2Hasher> + 'static + Clone + Send + Sync,
B: Backend<Block> + 'static,
E: CallExecutor<Block> + 'static + Clone + Send + Sync,
RA: Send + Sync,
{
@@ -24,7 +24,6 @@ use finality_grandpa::voter_set::VoterSet;
use finality_grandpa::{Error as GrandpaError};
use sp_runtime::generic::BlockId;
use sp_runtime::traits::{NumberFor, Block as BlockT, Header as HeaderT};
use sp_core::{H256, Blake2Hasher};
use sp_finality_grandpa::AuthorityId;
use crate::{Commit, Error};
@@ -45,7 +44,7 @@ pub struct GrandpaJustification<Block: BlockT> {
votes_ancestries: Vec<Block::Header>,
}
impl<Block: BlockT<Hash=H256>> GrandpaJustification<Block> {
impl<Block: BlockT> GrandpaJustification<Block> {
/// Create a GRANDPA justification from the given commit. This method
/// assumes the commit is valid and well-formed.
pub(crate) fn from_commit<B, E, RA>(
@@ -53,8 +52,8 @@ impl<Block: BlockT<Hash=H256>> GrandpaJustification<Block> {
round: u64,
commit: Commit<Block>,
) -> Result<GrandpaJustification<Block>, Error> where
B: Backend<Block, Blake2Hasher>,
E: CallExecutor<Block, Blake2Hasher> + Send + Sync,
B: Backend<Block>,
E: CallExecutor<Block> + Send + Sync,
RA: Send + Sync,
{
let mut votes_ancestries_hashes = HashSet::new();
+44 -39
View File
@@ -55,7 +55,7 @@
use futures::prelude::*;
use log::{debug, error, info};
use futures::sync::mpsc;
use sc_client_api::{BlockchainEvents, CallExecutor, backend::Backend, ExecutionStrategy};
use sc_client_api::{BlockchainEvents, CallExecutor, backend::{AuxStore, Backend}, ExecutionStrategy};
use sp_blockchain::{HeaderBackend, Error as ClientError};
use sc_client::Client;
use parity_scale_codec::{Decode, Encode};
@@ -64,7 +64,7 @@ use sp_runtime::traits::{NumberFor, Block as BlockT, DigestFor, Zero};
use sc_keystore::KeyStorePtr;
use sp_inherents::InherentDataProviders;
use sp_consensus::SelectChain;
use sp_core::{H256, Blake2Hasher, Pair};
use sp_core::Pair;
use sc_telemetry::{telemetry, CONSENSUS_INFO, CONSENSUS_DEBUG, CONSENSUS_WARN};
use serde_json;
@@ -252,9 +252,9 @@ pub(crate) trait BlockStatus<Block: BlockT> {
fn block_number(&self, hash: Block::Hash) -> Result<Option<NumberFor<Block>>, Error>;
}
impl<B, E, Block: BlockT<Hash=H256>, RA> BlockStatus<Block> for Arc<Client<B, E, Block, RA>> where
B: Backend<Block, Blake2Hasher>,
E: CallExecutor<Block, Blake2Hasher> + Send + Sync,
impl<B, E, Block: BlockT, RA> BlockStatus<Block> for Arc<Client<B, E, Block, RA>> where
B: Backend<Block>,
E: CallExecutor<Block> + Send + Sync,
RA: Send + Sync,
NumberFor<Block>: BlockNumberOps,
{
@@ -355,7 +355,7 @@ impl<H, N> fmt::Display for CommandOrError<H, N> {
}
}
pub struct LinkHalf<B, E, Block: BlockT<Hash=H256>, RA, SC> {
pub struct LinkHalf<B, E, Block: BlockT, RA, SC> {
client: Arc<Client<B, E, Block, RA>>,
select_chain: SC,
persistent_data: PersistentData<Block>,
@@ -368,10 +368,10 @@ pub trait GenesisAuthoritySetProvider<Block: BlockT> {
fn get(&self) -> Result<AuthorityList, ClientError>;
}
impl<B, E, Block: BlockT<Hash=H256>, RA> GenesisAuthoritySetProvider<Block> for Client<B, E, Block, RA>
impl<B, E, Block: BlockT, RA> GenesisAuthoritySetProvider<Block> for Client<B, E, Block, RA>
where
B: Backend<Block, Blake2Hasher> + Send + Sync + 'static,
E: CallExecutor<Block, Blake2Hasher> + 'static + Clone + Send + Sync,
B: Backend<Block> + Send + Sync + 'static,
E: CallExecutor<Block> + 'static + Clone + Send + Sync,
RA: Send + Sync,
{
fn get(&self) -> Result<AuthorityList, ClientError> {
@@ -397,7 +397,7 @@ impl<B, E, Block: BlockT<Hash=H256>, RA> GenesisAuthoritySetProvider<Block> for
/// Make block importer and link half necessary to tie the background voter
/// to it.
pub fn block_import<B, E, Block: BlockT<Hash=H256>, RA, SC>(
pub fn block_import<B, E, Block: BlockT, RA, SC>(
client: Arc<Client<B, E, Block, RA>>,
genesis_authorities_provider: &dyn GenesisAuthoritySetProvider<Block>,
select_chain: SC,
@@ -406,10 +406,11 @@ pub fn block_import<B, E, Block: BlockT<Hash=H256>, RA, SC>(
LinkHalf<B, E, Block, RA, SC>
), ClientError>
where
B: Backend<Block, Blake2Hasher> + 'static,
E: CallExecutor<Block, Blake2Hasher> + 'static + Clone + Send + Sync,
B: Backend<Block> + 'static,
E: CallExecutor<Block> + 'static + Clone + Send + Sync,
RA: Send + Sync,
SC: SelectChain<Block>,
Client<B, E, Block, RA>: AuxStore,
{
let chain_info = client.chain_info();
let genesis_hash = chain_info.genesis_hash;
@@ -446,7 +447,7 @@ where
))
}
fn global_communication<Block: BlockT<Hash=H256>, B, E, N, RA>(
fn global_communication<Block: BlockT, B, E, N, RA>(
set_id: SetId,
voters: &Arc<VoterSet<AuthorityId>>,
client: &Arc<Client<B, E, Block, RA>>,
@@ -454,16 +455,16 @@ fn global_communication<Block: BlockT<Hash=H256>, B, E, N, RA>(
keystore: &Option<KeyStorePtr>,
) -> (
impl Stream<
Item = CommunicationInH<Block, H256>,
Error = CommandOrError<H256, NumberFor<Block>>,
Item = CommunicationInH<Block, Block::Hash>,
Error = CommandOrError<Block::Hash, NumberFor<Block>>,
>,
impl Sink<
SinkItem = CommunicationOutH<Block, H256>,
SinkError = CommandOrError<H256, NumberFor<Block>>,
SinkItem = CommunicationOutH<Block, Block::Hash>,
SinkError = CommandOrError<Block::Hash, NumberFor<Block>>,
>,
) where
B: Backend<Block, Blake2Hasher>,
E: CallExecutor<Block, Blake2Hasher> + Send + Sync,
B: Backend<Block>,
E: CallExecutor<Block> + Send + Sync,
N: NetworkT<Block>,
RA: Send + Sync,
NumberFor<Block>: BlockNumberOps,
@@ -494,12 +495,12 @@ fn global_communication<Block: BlockT<Hash=H256>, B, E, N, RA>(
/// Register the finality tracker inherent data provider (which is used by
/// GRANDPA), if not registered already.
fn register_finality_tracker_inherent_data_provider<B, E, Block: BlockT<Hash=H256>, RA>(
fn register_finality_tracker_inherent_data_provider<B, E, Block: BlockT, RA>(
client: Arc<Client<B, E, Block, RA>>,
inherent_data_providers: &InherentDataProviders,
) -> Result<(), sp_consensus::Error> where
B: Backend<Block, Blake2Hasher> + 'static,
E: CallExecutor<Block, Blake2Hasher> + Send + Sync + 'static,
B: Backend<Block> + 'static,
E: CallExecutor<Block> + Send + Sync + 'static,
RA: Send + Sync + 'static,
{
if !inherent_data_providers.has_provider(&sp_finality_tracker::INHERENT_IDENTIFIER) {
@@ -522,7 +523,7 @@ fn register_finality_tracker_inherent_data_provider<B, E, Block: BlockT<Hash=H25
}
/// Parameters used to run Grandpa.
pub struct GrandpaParams<B, E, Block: BlockT<Hash=H256>, N, RA, SC, VR, X, Sp> {
pub struct GrandpaParams<B, E, Block: BlockT, N, RA, SC, VR, X, Sp> {
/// Configuration for the GRANDPA service.
pub config: Config,
/// A link to the block import worker.
@@ -543,12 +544,12 @@ pub struct GrandpaParams<B, E, Block: BlockT<Hash=H256>, N, RA, SC, VR, X, Sp> {
/// Run a GRANDPA voter as a task. Provide configuration and a link to a
/// block import worker that has already been instantiated with `block_import`.
pub fn run_grandpa_voter<B, E, Block: BlockT<Hash=H256>, N, RA, SC, VR, X, Sp>(
pub fn run_grandpa_voter<B, E, Block: BlockT, N, RA, SC, VR, X, Sp>(
grandpa_params: GrandpaParams<B, E, Block, N, RA, SC, VR, X, Sp>,
) -> sp_blockchain::Result<impl Future<Item=(),Error=()> + Send + 'static> where
Block::Hash: Ord,
B: Backend<Block, Blake2Hasher> + 'static,
E: CallExecutor<Block, Blake2Hasher> + Send + Sync + 'static,
B: Backend<Block> + 'static,
E: CallExecutor<Block> + Send + Sync + 'static,
N: NetworkT<Block> + Send + Sync + Clone + 'static,
SC: SelectChain<Block> + 'static,
VR: VotingRule<Block, Client<B, E, Block, RA>> + Clone + 'static,
@@ -556,6 +557,7 @@ pub fn run_grandpa_voter<B, E, Block: BlockT<Hash=H256>, N, RA, SC, VR, X, Sp>(
DigestFor<Block>: Encode,
RA: Send + Sync + 'static,
X: futures03::Future<Output=()> + Clone + Send + Unpin + 'static,
Client<B, E, Block, RA>: AuxStore,
Sp: futures03::task::Spawn + 'static,
{
let GrandpaParams {
@@ -650,14 +652,15 @@ struct VoterWork<B, E, Block: BlockT, N: NetworkT<Block>, RA, SC, VR> {
impl<B, E, Block, N, RA, SC, VR> VoterWork<B, E, Block, N, RA, SC, VR>
where
Block: BlockT<Hash=H256>,
Block: BlockT,
N: NetworkT<Block> + Sync,
NumberFor<Block>: BlockNumberOps,
RA: 'static + Send + Sync,
E: CallExecutor<Block, Blake2Hasher> + Send + Sync + 'static,
B: Backend<Block, Blake2Hasher> + 'static,
E: CallExecutor<Block> + Send + Sync + 'static,
B: Backend<Block> + 'static,
SC: SelectChain<Block> + 'static,
VR: VotingRule<Block, Client<B, E, Block, RA>> + Clone + 'static,
Client<B, E, Block, RA>: AuxStore,
{
fn new(
client: Arc<Client<B, E, Block, RA>>,
@@ -825,14 +828,15 @@ where
impl<B, E, Block, N, RA, SC, VR> Future for VoterWork<B, E, Block, N, RA, SC, VR>
where
Block: BlockT<Hash=H256>,
Block: BlockT,
N: NetworkT<Block> + Sync,
NumberFor<Block>: BlockNumberOps,
RA: 'static + Send + Sync,
E: CallExecutor<Block, Blake2Hasher> + Send + Sync + 'static,
B: Backend<Block, Blake2Hasher> + 'static,
E: CallExecutor<Block> + Send + Sync + 'static,
B: Backend<Block> + 'static,
SC: SelectChain<Block> + 'static,
VR: VotingRule<Block, Client<B, E, Block, RA>> + Clone + 'static,
Client<B, E, Block, RA>: AuxStore,
{
type Item = ();
type Error = Error;
@@ -877,12 +881,12 @@ where
}
#[deprecated(since = "1.1.0", note = "Please switch to run_grandpa_voter.")]
pub fn run_grandpa<B, E, Block: BlockT<Hash=H256>, N, RA, SC, VR, X, Sp>(
pub fn run_grandpa<B, E, Block: BlockT, N, RA, SC, VR, X, Sp>(
grandpa_params: GrandpaParams<B, E, Block, N, RA, SC, VR, X, Sp>,
) -> ::sp_blockchain::Result<impl Future<Item=(),Error=()> + Send + 'static> where
) -> sp_blockchain::Result<impl Future<Item=(),Error=()> + Send + 'static> where
Block::Hash: Ord,
B: Backend<Block, Blake2Hasher> + 'static,
E: CallExecutor<Block, Blake2Hasher> + Send + Sync + 'static,
B: Backend<Block> + 'static,
E: CallExecutor<Block> + Send + Sync + 'static,
N: NetworkT<Block> + Send + Sync + Clone + 'static,
SC: SelectChain<Block> + 'static,
NumberFor<Block>: BlockNumberOps,
@@ -890,6 +894,7 @@ pub fn run_grandpa<B, E, Block: BlockT<Hash=H256>, N, RA, SC, VR, X, Sp>(
RA: Send + Sync + 'static,
VR: VotingRule<Block, Client<B, E, Block, RA>> + Clone + 'static,
X: futures03::Future<Output=()> + Clone + Send + Unpin + 'static,
Client<B, E, Block, RA>: AuxStore,
Sp: futures03::task::Spawn + 'static,
{
run_grandpa_voter(grandpa_params)
@@ -901,13 +906,13 @@ pub fn run_grandpa<B, E, Block: BlockT<Hash=H256>, N, RA, SC, VR, X, Sp>(
/// discards all GRANDPA messages (otherwise, we end up banning nodes that send
/// us a `Neighbor` message, since there is no registered gossip validator for
/// the engine id defined in the message.)
pub fn setup_disabled_grandpa<B, E, Block: BlockT<Hash=H256>, RA, N>(
pub fn setup_disabled_grandpa<B, E, Block: BlockT, RA, N>(
client: Arc<Client<B, E, Block, RA>>,
inherent_data_providers: &InherentDataProviders,
network: N,
) -> Result<(), sp_consensus::Error> where
B: Backend<Block, Blake2Hasher> + 'static,
E: CallExecutor<Block, Blake2Hasher> + Send + Sync + 'static,
B: Backend<Block> + 'static,
E: CallExecutor<Block> + Send + Sync + 'static,
RA: Send + Sync + 'static,
N: NetworkT<Block> + Send + Clone + 'static,
{
@@ -19,7 +19,7 @@ use std::sync::Arc;
use log::{info, trace, warn};
use parking_lot::RwLock;
use sc_client::Client;
use sc_client_api::{CallExecutor, backend::{AuxStore, Backend, Finalizer}};
use sc_client_api::{CallExecutor, backend::{AuxStore, Backend, Finalizer, TransactionFor}};
use sp_blockchain::{HeaderBackend, Error as ClientError, well_known_cache_keys};
use parity_scale_codec::{Encode, Decode};
use sp_consensus::{
@@ -32,7 +32,6 @@ use sp_runtime::Justification;
use sp_runtime::traits::{NumberFor, Block as BlockT, Header as HeaderT, DigestFor};
use sp_finality_grandpa::{self, AuthorityList};
use sp_runtime::generic::BlockId;
use sp_core::{H256, Blake2Hasher};
use crate::GenesisAuthoritySetProvider;
use crate::aux_schema::load_decode;
@@ -49,16 +48,17 @@ const LIGHT_AUTHORITY_SET_KEY: &[u8] = b"grandpa_voters";
const LIGHT_CONSENSUS_CHANGES_KEY: &[u8] = b"grandpa_consensus_changes";
/// Create light block importer.
pub fn light_block_import<B, E, Block: BlockT<Hash=H256>, RA>(
pub fn light_block_import<B, E, Block: BlockT, RA>(
client: Arc<Client<B, E, Block, RA>>,
backend: Arc<B>,
genesis_authorities_provider: &dyn GenesisAuthoritySetProvider<Block>,
authority_set_provider: Arc<dyn AuthoritySetForFinalityChecker<Block>>,
) -> Result<GrandpaLightBlockImport<B, E, Block, RA>, ClientError>
where
B: Backend<Block, Blake2Hasher> + 'static,
E: CallExecutor<Block, Blake2Hasher> + 'static + Clone + Send + Sync,
B: Backend<Block> + 'static,
E: CallExecutor<Block> + 'static + Clone + Send + Sync,
RA: Send + Sync,
Client<B, E, Block, RA>: AuxStore,
{
let info = client.info();
let import_data = load_aux_import_data(
@@ -79,14 +79,14 @@ pub fn light_block_import<B, E, Block: BlockT<Hash=H256>, RA>(
/// It is responsible for:
/// - checking GRANDPA justifications;
/// - fetching finality proofs for blocks that are enacting consensus changes.
pub struct GrandpaLightBlockImport<B, E, Block: BlockT<Hash=H256>, RA> {
pub struct GrandpaLightBlockImport<B, E, Block: BlockT, RA> {
client: Arc<Client<B, E, Block, RA>>,
backend: Arc<B>,
authority_set_provider: Arc<dyn AuthoritySetForFinalityChecker<Block>>,
data: Arc<RwLock<LightImportData<Block>>>,
}
impl<B, E, Block: BlockT<Hash=H256>, RA> Clone for GrandpaLightBlockImport<B, E, Block, RA> {
impl<B, E, Block: BlockT, RA> Clone for GrandpaLightBlockImport<B, E, Block, RA> {
fn clone(&self) -> Self {
GrandpaLightBlockImport {
client: self.client.clone(),
@@ -98,7 +98,7 @@ impl<B, E, Block: BlockT<Hash=H256>, RA> Clone for GrandpaLightBlockImport<B, E,
}
/// Mutable data of light block importer.
struct LightImportData<Block: BlockT<Hash=H256>> {
struct LightImportData<Block: BlockT> {
last_finalized: Block::Hash,
authority_set: LightAuthoritySet,
consensus_changes: ConsensusChanges<Block::Hash, NumberFor<Block>>,
@@ -111,26 +111,31 @@ struct LightAuthoritySet {
authorities: AuthorityList,
}
impl<B, E, Block: BlockT<Hash=H256>, RA> GrandpaLightBlockImport<B, E, Block, RA> {
impl<B, E, Block: BlockT, RA> GrandpaLightBlockImport<B, E, Block, RA> {
/// Create finality proof request builder.
pub fn create_finality_proof_request_builder(&self) -> BoxFinalityProofRequestBuilder<Block> {
Box::new(GrandpaFinalityProofRequestBuilder(self.data.clone())) as _
}
}
impl<B, E, Block: BlockT<Hash=H256>, RA> BlockImport<Block>
impl<B, E, Block: BlockT, RA> BlockImport<Block>
for GrandpaLightBlockImport<B, E, Block, RA> where
NumberFor<Block>: finality_grandpa::BlockNumberOps,
B: Backend<Block, Blake2Hasher> + 'static,
E: CallExecutor<Block, Blake2Hasher> + 'static + Clone + Send + Sync,
B: Backend<Block> + 'static,
E: CallExecutor<Block> + 'static + Clone + Send + Sync,
DigestFor<Block>: Encode,
RA: Send + Sync,
for<'a> &'a Client<B, E, Block, RA>:
BlockImport<Block, Error = ConsensusError, Transaction = TransactionFor<B, Block>>
+ Finalizer<Block, B>
+ AuxStore,
{
type Error = ConsensusError;
type Transaction = TransactionFor<B, Block>;
fn import_block(
&mut self,
block: BlockImportParams<Block>,
block: BlockImportParams<Block, Self::Transaction>,
new_cache: HashMap<well_known_cache_keys::Id, Vec<u8>>,
) -> Result<ImportResult, Self::Error> {
do_import_block::<_, _, _, GrandpaJustification<Block>>(
@@ -146,13 +151,17 @@ impl<B, E, Block: BlockT<Hash=H256>, RA> BlockImport<Block>
}
}
impl<B, E, Block: BlockT<Hash=H256>, RA> FinalityProofImport<Block>
impl<B, E, Block: BlockT, RA> FinalityProofImport<Block>
for GrandpaLightBlockImport<B, E, Block, RA> where
NumberFor<Block>: finality_grandpa::BlockNumberOps,
B: Backend<Block, Blake2Hasher> + 'static,
E: CallExecutor<Block, Blake2Hasher> + 'static + Clone + Send + Sync,
B: Backend<Block> + 'static,
E: CallExecutor<Block> + 'static + Clone + Send + Sync,
DigestFor<Block>: Encode,
RA: Send + Sync,
for<'a> &'a Client<B, E, Block, RA>:
BlockImport<Block, Error = ConsensusError, Transaction = TransactionFor<B, Block>>
+ Finalizer<Block, B>
+ AuxStore,
{
type Error = ConsensusError;
@@ -162,7 +171,9 @@ impl<B, E, Block: BlockT<Hash=H256>, RA> FinalityProofImport<Block>
let data = self.data.read();
for (pending_number, pending_hash) in data.consensus_changes.pending_changes() {
if *pending_number > chain_info.finalized_number && *pending_number <= chain_info.best_number {
if *pending_number > chain_info.finalized_number
&& *pending_number <= chain_info.best_number
{
out.push((pending_hash.clone(), *pending_number));
}
}
@@ -216,9 +227,9 @@ impl LightAuthoritySet {
}
}
struct GrandpaFinalityProofRequestBuilder<B: BlockT<Hash=H256>>(Arc<RwLock<LightImportData<B>>>);
struct GrandpaFinalityProofRequestBuilder<B: BlockT>(Arc<RwLock<LightImportData<B>>>);
impl<B: BlockT<Hash=H256>> FinalityProofRequestBuilder<B> for GrandpaFinalityProofRequestBuilder<B> {
impl<B: BlockT> FinalityProofRequestBuilder<B> for GrandpaFinalityProofRequestBuilder<B> {
fn build_request_data(&mut self, _hash: &B::Hash) -> Vec<u8> {
let data = self.0.read();
make_finality_proof_request(
@@ -229,19 +240,19 @@ impl<B: BlockT<Hash=H256>> FinalityProofRequestBuilder<B> for GrandpaFinalityPro
}
/// Try to import new block.
fn do_import_block<B, C, Block: BlockT<Hash=H256>, J>(
fn do_import_block<B, C, Block: BlockT, J>(
mut client: C,
data: &mut LightImportData<Block>,
mut block: BlockImportParams<Block>,
mut block: BlockImportParams<Block, TransactionFor<B, Block>>,
new_cache: HashMap<well_known_cache_keys::Id, Vec<u8>>,
) -> Result<ImportResult, ConsensusError>
where
C: HeaderBackend<Block>
+ AuxStore
+ Finalizer<Block, Blake2Hasher, B>
+ BlockImport<Block>
+ Finalizer<Block, B>
+ BlockImport<Block, Transaction = TransactionFor<B, Block>>
+ Clone,
B: Backend<Block, Blake2Hasher> + 'static,
B: Backend<Block> + 'static,
NumberFor<Block>: finality_grandpa::BlockNumberOps,
DigestFor<Block>: Encode,
J: ProvableJustification<Block::Header>,
@@ -288,7 +299,7 @@ fn do_import_block<B, C, Block: BlockT<Hash=H256>, J>(
}
/// Try to import finality proof.
fn do_import_finality_proof<B, C, Block: BlockT<Hash=H256>, J>(
fn do_import_finality_proof<B, C, Block: BlockT, J>(
client: C,
backend: Arc<B>,
authority_set_provider: &dyn AuthoritySetForFinalityChecker<Block>,
@@ -301,10 +312,10 @@ fn do_import_finality_proof<B, C, Block: BlockT<Hash=H256>, J>(
where
C: HeaderBackend<Block>
+ AuxStore
+ Finalizer<Block, Blake2Hasher, B>
+ BlockImport<Block>
+ Finalizer<Block, B>
+ BlockImport<Block, Transaction = TransactionFor<B, Block>>
+ Clone,
B: Backend<Block, Blake2Hasher> + 'static,
B: Backend<Block> + 'static,
DigestFor<Block>: Encode,
NumberFor<Block>: finality_grandpa::BlockNumberOps,
J: ProvableJustification<Block::Header>,
@@ -322,15 +333,27 @@ fn do_import_finality_proof<B, C, Block: BlockT<Hash=H256>, J>(
// try to import all new headers
let block_origin = BlockOrigin::NetworkBroadcast;
for header_to_import in finality_effects.headers_to_import {
let (block_to_import, new_authorities) = verifier.verify(block_origin, header_to_import, None, None)
.map_err(|e| ConsensusError::ClientImport(e))?;
assert!(block_to_import.justification.is_none(), "We have passed None as justification to verifier.verify");
let (block_to_import, new_authorities) = verifier.verify(
block_origin,
header_to_import,
None,
None,
).map_err(|e| ConsensusError::ClientImport(e))?;
assert!(
block_to_import.justification.is_none(),
"We have passed None as justification to verifier.verify",
);
let mut cache = HashMap::new();
if let Some(authorities) = new_authorities {
cache.insert(well_known_cache_keys::AUTHORITIES, authorities.encode());
}
do_import_block::<_, _, _, J>(client.clone(), data, block_to_import, cache)?;
do_import_block::<_, _, _, J>(
client.clone(),
data,
block_to_import.convert_transaction(),
cache,
)?;
}
// try to import latest justification
@@ -356,7 +379,7 @@ fn do_import_finality_proof<B, C, Block: BlockT<Hash=H256>, J>(
}
/// Try to import justification.
fn do_import_justification<B, C, Block: BlockT<Hash=H256>, J>(
fn do_import_justification<B, C, Block: BlockT, J>(
client: C,
data: &mut LightImportData<Block>,
hash: Block::Hash,
@@ -366,9 +389,9 @@ fn do_import_justification<B, C, Block: BlockT<Hash=H256>, J>(
where
C: HeaderBackend<Block>
+ AuxStore
+ Finalizer<Block, Blake2Hasher, B>
+ Finalizer<Block, B>
+ Clone,
B: Backend<Block, Blake2Hasher> + 'static,
B: Backend<Block> + 'static,
NumberFor<Block>: finality_grandpa::BlockNumberOps,
J: ProvableJustification<Block::Header>,
{
@@ -427,7 +450,7 @@ fn do_import_justification<B, C, Block: BlockT<Hash=H256>, J>(
}
/// Finalize the block.
fn do_finalize_block<B, C, Block: BlockT<Hash=H256>>(
fn do_finalize_block<B, C, Block: BlockT>(
client: C,
data: &mut LightImportData<Block>,
hash: Block::Hash,
@@ -437,9 +460,9 @@ fn do_finalize_block<B, C, Block: BlockT<Hash=H256>>(
where
C: HeaderBackend<Block>
+ AuxStore
+ Finalizer<Block, Blake2Hasher, B>
+ Finalizer<Block, B>
+ Clone,
B: Backend<Block, Blake2Hasher> + 'static,
B: Backend<Block> + 'static,
NumberFor<Block>: finality_grandpa::BlockNumberOps,
{
// finalize the block
@@ -450,7 +473,10 @@ fn do_finalize_block<B, C, Block: BlockT<Hash=H256>>(
// forget obsoleted consensus changes
let consensus_finalization_res = data.consensus_changes
.finalize((number, hash), |at_height| canonical_at_height(client.clone(), (hash, number), true, at_height));
.finalize(
(number, hash),
|at_height| canonical_at_height(&client, (hash, number), true, at_height)
);
match consensus_finalization_res {
Ok((true, _)) => require_insert_aux(
&client,
@@ -470,13 +496,14 @@ fn do_finalize_block<B, C, Block: BlockT<Hash=H256>>(
}
/// Load light import aux data from the store.
fn load_aux_import_data<B, Block: BlockT<Hash=H256>>(
fn load_aux_import_data<B, Block>(
last_finalized: Block::Hash,
aux_store: &B,
genesis_authorities_provider: &dyn GenesisAuthoritySetProvider<Block>,
) -> Result<LightImportData<Block>, ClientError>
where
B: AuxStore,
Block: BlockT,
{
let authority_set = match load_decode(aux_store, LIGHT_AUTHORITY_SET_KEY)? {
Some(authority_set) => authority_set,
@@ -548,15 +575,15 @@ pub mod tests {
use crate::tests::TestApi;
use crate::finality_proof::tests::TestJustification;
pub struct NoJustificationsImport<B, E, Block: BlockT<Hash=H256>, RA>(
pub struct NoJustificationsImport<B, E, Block: BlockT, RA>(
pub GrandpaLightBlockImport<B, E, Block, RA>
);
impl<B, E, Block: BlockT<Hash=H256>, RA> Clone
impl<B, E, Block: BlockT, RA> Clone
for NoJustificationsImport<B, E, Block, RA> where
NumberFor<Block>: finality_grandpa::BlockNumberOps,
B: Backend<Block, Blake2Hasher> + 'static,
E: CallExecutor<Block, Blake2Hasher> + 'static + Clone + Send + Sync,
B: Backend<Block> + 'static,
E: CallExecutor<Block> + 'static + Clone + Send + Sync,
DigestFor<Block>: Encode,
RA: Send + Sync,
{
@@ -565,19 +592,24 @@ pub mod tests {
}
}
impl<B, E, Block: BlockT<Hash=H256>, RA> BlockImport<Block>
impl<B, E, Block: BlockT, RA> BlockImport<Block>
for NoJustificationsImport<B, E, Block, RA> where
NumberFor<Block>: finality_grandpa::BlockNumberOps,
B: Backend<Block, Blake2Hasher> + 'static,
E: CallExecutor<Block, Blake2Hasher> + 'static + Clone + Send + Sync,
B: Backend<Block> + 'static,
E: CallExecutor<Block> + 'static + Clone + Send + Sync,
DigestFor<Block>: Encode,
RA: Send + Sync,
for<'a> &'a Client<B, E, Block, RA>:
BlockImport<Block, Error = ConsensusError, Transaction = TransactionFor<B, Block>>
+ Finalizer<Block, B>
+ AuxStore,
{
type Error = ConsensusError;
type Transaction = TransactionFor<B, Block>;
fn import_block(
&mut self,
mut block: BlockImportParams<Block>,
mut block: BlockImportParams<Block, Self::Transaction>,
new_cache: HashMap<well_known_cache_keys::Id, Vec<u8>>,
) -> Result<ImportResult, Self::Error> {
block.justification.take();
@@ -592,13 +624,17 @@ pub mod tests {
}
}
impl<B, E, Block: BlockT<Hash=H256>, RA> FinalityProofImport<Block>
impl<B, E, Block: BlockT, RA> FinalityProofImport<Block>
for NoJustificationsImport<B, E, Block, RA> where
NumberFor<Block>: finality_grandpa::BlockNumberOps,
B: Backend<Block, Blake2Hasher> + 'static,
E: CallExecutor<Block, Blake2Hasher> + 'static + Clone + Send + Sync,
B: Backend<Block> + 'static,
E: CallExecutor<Block> + 'static + Clone + Send + Sync,
DigestFor<Block>: Encode,
RA: Send + Sync,
for<'a> &'a Client<B, E, Block, RA>:
BlockImport<Block, Error = ConsensusError, Transaction = TransactionFor<B, Block>>
+ Finalizer<Block, B>
+ AuxStore,
{
type Error = ConsensusError;
@@ -618,16 +654,19 @@ pub mod tests {
}
/// Creates light block import that ignores justifications that came outside of finality proofs.
pub fn light_block_import_without_justifications<B, E, Block: BlockT<Hash=H256>, RA>(
pub fn light_block_import_without_justifications<B, E, Block: BlockT, RA>(
client: Arc<Client<B, E, Block, RA>>,
backend: Arc<B>,
genesis_authorities_provider: &dyn GenesisAuthoritySetProvider<Block>,
authority_set_provider: Arc<dyn AuthoritySetForFinalityChecker<Block>>,
) -> Result<NoJustificationsImport<B, E, Block, RA>, ClientError>
where
B: Backend<Block, Blake2Hasher> + 'static,
E: CallExecutor<Block, Blake2Hasher> + 'static + Clone + Send + Sync,
B: Backend<Block> + 'static,
E: CallExecutor<Block> + 'static + Clone + Send + Sync,
RA: Send + Sync,
Client<B, E, Block, RA>: BlockImport<Block, Error = ConsensusError>
+ Finalizer<Block, B>
+ AuxStore,
{
light_block_import(client, backend, genesis_authorities_provider, authority_set_provider)
.map(NoJustificationsImport)
@@ -655,6 +694,7 @@ pub mod tests {
justification,
post_digests: Vec::new(),
body: None,
storage_changes: None,
finalized: false,
auxiliary: Vec::new(),
fork_choice: ForkChoiceStrategy::LongestChain,
@@ -25,10 +25,9 @@ use finality_grandpa::{
use log::{debug, info, warn};
use sp_consensus::SelectChain;
use sc_client_api::{CallExecutor, backend::Backend};
use sc_client_api::{CallExecutor, backend::{Backend, AuxStore}};
use sc_client::Client;
use sp_runtime::traits::{NumberFor, Block as BlockT};
use sp_core::{H256, Blake2Hasher};
use crate::{
global_communication, CommandOrError, CommunicationIn, Config, environment,
@@ -41,10 +40,10 @@ use sp_finality_grandpa::AuthorityId;
struct ObserverChain<'a, Block: BlockT, B, E, RA>(&'a Client<B, E, Block, RA>);
impl<'a, Block: BlockT<Hash=H256>, B, E, RA> finality_grandpa::Chain<Block::Hash, NumberFor<Block>>
impl<'a, Block: BlockT, B, E, RA> finality_grandpa::Chain<Block::Hash, NumberFor<Block>>
for ObserverChain<'a, Block, B, E, RA> where
B: Backend<Block, Blake2Hasher>,
E: CallExecutor<Block, Blake2Hasher>,
B: Backend<Block>,
E: CallExecutor<Block>,
NumberFor<Block>: BlockNumberOps,
{
fn ancestry(&self, base: Block::Hash, block: Block::Hash) -> Result<Vec<Block::Hash>, GrandpaError> {
@@ -57,7 +56,7 @@ impl<'a, Block: BlockT<Hash=H256>, B, E, RA> finality_grandpa::Chain<Block::Hash
}
}
fn grandpa_observer<B, E, Block: BlockT<Hash=H256>, RA, S, F>(
fn grandpa_observer<B, E, Block: BlockT, RA, S, F>(
client: &Arc<Client<B, E, Block, RA>>,
authority_set: &SharedAuthoritySet<Block::Hash, NumberFor<Block>>,
consensus_changes: &SharedConsensusChanges<Block::Hash, NumberFor<Block>>,
@@ -65,10 +64,10 @@ fn grandpa_observer<B, E, Block: BlockT<Hash=H256>, RA, S, F>(
last_finalized_number: NumberFor<Block>,
commits: S,
note_round: F,
) -> impl Future<Item=(), Error=CommandOrError<H256, NumberFor<Block>>> where
) -> impl Future<Item=(), Error=CommandOrError<Block::Hash, NumberFor<Block>>> where
NumberFor<Block>: BlockNumberOps,
B: Backend<Block, Blake2Hasher>,
E: CallExecutor<Block, Blake2Hasher> + Send + Sync,
B: Backend<Block>,
E: CallExecutor<Block> + Send + Sync,
RA: Send + Sync,
S: Stream<
Item = CommunicationIn<Block>,
@@ -151,20 +150,21 @@ fn grandpa_observer<B, E, Block: BlockT<Hash=H256>, RA, S, F>(
/// listening for and validating GRANDPA commits instead of following the full
/// protocol. Provide configuration and a link to a block import worker that has
/// already been instantiated with `block_import`.
pub fn run_grandpa_observer<B, E, Block: BlockT<Hash=H256>, N, RA, SC, Sp>(
pub fn run_grandpa_observer<B, E, Block: BlockT, N, RA, SC, Sp>(
config: Config,
link: LinkHalf<B, E, Block, RA, SC>,
network: N,
on_exit: impl futures03::Future<Output=()> + Clone + Send + Unpin + 'static,
executor: Sp,
) -> ::sp_blockchain::Result<impl Future<Item=(),Error=()> + Send + 'static> where
B: Backend<Block, Blake2Hasher> + 'static,
E: CallExecutor<Block, Blake2Hasher> + Send + Sync + 'static,
) -> sp_blockchain::Result<impl Future<Item=(), Error=()> + Send + 'static> where
B: Backend<Block> + 'static,
E: CallExecutor<Block> + Send + Sync + 'static,
N: NetworkT<Block> + Send + Clone + 'static,
SC: SelectChain<Block> + 'static,
NumberFor<Block>: BlockNumberOps,
RA: Send + Sync + 'static,
Sp: futures03::task::Spawn + 'static,
Client<B, E, Block, RA>: AuxStore,
{
let LinkHalf {
client,
@@ -202,7 +202,7 @@ pub fn run_grandpa_observer<B, E, Block: BlockT<Hash=H256>, N, RA, SC, Sp>(
/// Future that powers the observer.
#[must_use]
struct ObserverWork<B: BlockT<Hash=H256>, N: NetworkT<B>, E, Backend, RA> {
struct ObserverWork<B: BlockT, N: NetworkT<B>, E, Backend, RA> {
observer: Box<dyn Future<Item = (), Error = CommandOrError<B::Hash, NumberFor<B>>> + Send>,
client: Arc<Client<Backend, E, B, RA>>,
network: NetworkBridge<B, N>,
@@ -213,12 +213,13 @@ struct ObserverWork<B: BlockT<Hash=H256>, N: NetworkT<B>, E, Backend, RA> {
impl<B, N, E, Bk, RA> ObserverWork<B, N, E, Bk, RA>
where
B: BlockT<Hash=H256>,
B: BlockT,
N: NetworkT<B>,
NumberFor<B>: BlockNumberOps,
RA: 'static + Send + Sync,
E: CallExecutor<B, Blake2Hasher> + Send + Sync + 'static,
Bk: Backend<B, Blake2Hasher> + 'static,
E: CallExecutor<B> + Send + Sync + 'static,
Bk: Backend<B> + 'static,
Client<Bk, E, B, RA>: AuxStore,
{
fn new(
client: Arc<Client<Bk, E, B, RA>>,
@@ -328,12 +329,13 @@ where
impl<B, N, E, Bk, RA> Future for ObserverWork<B, N, E, Bk, RA>
where
B: BlockT<Hash=H256>,
B: BlockT,
N: NetworkT<B>,
NumberFor<B>: BlockNumberOps,
RA: 'static + Send + Sync,
E: CallExecutor<B, Blake2Hasher> + Send + Sync + 'static,
Bk: Backend<B, Blake2Hasher> + 'static,
E: CallExecutor<B> + Send + Sync + 'static,
Bk: Backend<B> + 'static,
Client<Bk, E, B, RA>: AuxStore,
{
type Item = ();
type Error = Error;
+93 -38
View File
@@ -18,8 +18,10 @@
use super::*;
use environment::HasVoted;
use sc_network_test::{Block, DummySpecialization, Hash, TestNetFactory, Peer, PeersClient};
use sc_network_test::{PassThroughVerifier};
use sc_network_test::{
Block, DummySpecialization, Hash, TestNetFactory, BlockImportAdapter, Peer,
PeersClient, PassThroughVerifier,
};
use sc_network::config::{ProtocolConfig, Roles, BoxFinalityProofRequestBuilder};
use parking_lot::Mutex;
use futures_timer::Delay;
@@ -27,23 +29,28 @@ use futures03::{StreamExt as _, TryStreamExt as _};
use tokio::runtime::current_thread;
use sp_keyring::Ed25519Keyring;
use sc_client::LongestChain;
use sc_client_api::backend::TransactionFor;
use sp_blockchain::Result;
use sp_api::{Core, RuntimeVersion, ApiExt, StorageProof};
use substrate_test_runtime_client::{self, runtime::BlockNumber};
use sp_consensus::{BlockOrigin, ForkChoiceStrategy, ImportedAux, BlockImportParams, ImportResult};
use sp_consensus::import_queue::{BoxBlockImport, BoxJustificationImport, BoxFinalityProofImport};
use sp_api::{ApiRef, ApiErrorExt, Core, RuntimeVersion, ApiExt, StorageProof, ProvideRuntimeApi};
use substrate_test_runtime_client::runtime::BlockNumber;
use sp_consensus::{
BlockOrigin, ForkChoiceStrategy, ImportedAux, BlockImportParams, ImportResult, BlockImport,
import_queue::{BoxJustificationImport, BoxFinalityProofImport},
};
use std::collections::{HashMap, HashSet};
use std::result;
use parity_scale_codec::Decode;
use sp_runtime::traits::{ApiRef, ProvideRuntimeApi, Header as HeaderT};
use sp_runtime::traits::{Header as HeaderT, HasherFor};
use sp_runtime::generic::{BlockId, DigestItem};
use sp_core::{NativeOrEncoded, ExecutionContext, crypto::Public};
use sp_core::{H256, NativeOrEncoded, ExecutionContext, crypto::Public};
use sp_finality_grandpa::{GRANDPA_ENGINE_ID, AuthorityList, GrandpaApi};
use sp_state_machine::{backend::InMemory, prove_read, read_proof_check};
use sp_state_machine::{InMemoryBackend, prove_read, read_proof_check};
use std::{pin::Pin, task};
use authorities::AuthoritySet;
use finality_proof::{FinalityProofProvider, AuthoritySetForFinalityProver, AuthoritySetForFinalityChecker};
use finality_proof::{
FinalityProofProvider, AuthoritySetForFinalityProver, AuthoritySetForFinalityChecker,
};
use consensus_changes::ConsensusChanges;
type PeerData =
@@ -108,9 +115,9 @@ impl TestNetFactory for GrandpaTestNet {
PassThroughVerifier(false) // use non-instant finality.
}
fn make_block_import(&self, client: PeersClient)
fn make_block_import<Transaction>(&self, client: PeersClient)
-> (
BoxBlockImport<Block>,
BlockImportAdapter<Transaction>,
Option<BoxJustificationImport<Block>>,
Option<BoxFinalityProofImport<Block>>,
Option<BoxFinalityProofRequestBuilder<Block>>,
@@ -125,8 +132,13 @@ impl TestNetFactory for GrandpaTestNet {
LongestChain::new(backend.clone()),
).expect("Could not create block import for fresh peer.");
let justification_import = Box::new(import.clone());
let block_import = Box::new(import);
(block_import, Some(justification_import), None, None, Mutex::new(Some(link)))
(
BlockImportAdapter::new_full(import),
Some(justification_import),
None,
None,
Mutex::new(Some(link)),
)
},
PeersClient::Light(ref client, ref backend) => {
use crate::light_import::tests::light_block_import_without_justifications;
@@ -142,8 +154,13 @@ impl TestNetFactory for GrandpaTestNet {
).expect("Could not create block import for fresh peer.");
let finality_proof_req_builder = import.0.create_finality_proof_request_builder();
let proof_import = Box::new(import.clone());
let block_import = Box::new(import);
(block_import, None, Some(proof_import), Some(finality_proof_req_builder), Mutex::new(None))
(
BlockImportAdapter::new_light(import),
None,
Some(proof_import),
Some(finality_proof_req_builder),
Mutex::new(None),
)
},
}
}
@@ -202,7 +219,7 @@ pub(crate) struct RuntimeApi {
inner: TestApi,
}
impl ProvideRuntimeApi for TestApi {
impl ProvideRuntimeApi<Block> for TestApi {
type Api = RuntimeApi;
fn runtime_api<'a>(&'a self) -> ApiRef<'a, Self::Api> {
@@ -242,8 +259,14 @@ impl Core<Block> for RuntimeApi {
}
}
impl ApiExt<Block> for RuntimeApi {
impl ApiErrorExt for RuntimeApi {
type Error = sp_blockchain::Error;
}
impl ApiExt<Block> for RuntimeApi {
type StateBackend = <
substrate_test_runtime_client::Backend as sc_client_api::backend::Backend<Block>
>::State;
fn map_api_result<F: FnOnce(&Self) -> result::Result<R, E>, R, E>(
&self,
@@ -263,6 +286,19 @@ impl ApiExt<Block> for RuntimeApi {
fn extract_proof(&mut self) -> Option<StorageProof> {
unimplemented!("Not required for testing!")
}
fn into_storage_changes<
T: sp_api::ChangesTrieStorage<sp_api::HasherFor<Block>, sp_api::NumberFor<Block>>
>(
&self,
_: &Self::StateBackend,
_: Option<&T>,
_: <Block as sp_api::BlockT>::Hash,
) -> std::result::Result<sp_api::StorageChanges<Self::StateBackend, Block>, String>
where Self: Sized
{
unimplemented!("Not required for testing!")
}
}
impl GrandpaApi<Block> for RuntimeApi {
@@ -290,7 +326,7 @@ impl AuthoritySetForFinalityProver<Block> for TestApi {
fn prove_authorities(&self, block: &BlockId<Block>) -> Result<StorageProof> {
let authorities = self.authorities(block)?;
let backend = <InMemory<Blake2Hasher>>::from(vec![
let backend = <InMemoryBackend<HasherFor<Block>>>::from(vec![
(None, vec![(b"authorities".to_vec(), Some(authorities.encode()))])
]);
let proof = prove_read(backend, vec![b"authorities"])
@@ -306,7 +342,7 @@ impl AuthoritySetForFinalityChecker<Block> for TestApi {
header: <Block as BlockT>::Header,
proof: StorageProof,
) -> Result<AuthorityList> {
let results = read_proof_check::<Blake2Hasher, _>(
let results = read_proof_check::<HasherFor<Block>, _>(
*header.state_root(), proof, vec![b"authorities"]
)
.expect("failure checking read proof for authorities");
@@ -629,7 +665,7 @@ fn transition_3_voters_twice_1_full_observer() {
14 => {
// generate transition at block 15, applied at 20.
net.lock().peer(0).generate_blocks(1, BlockOrigin::File, |builder| {
let mut block = builder.bake().unwrap();
let mut block = builder.build().unwrap().block;
add_scheduled_change(&mut block, ScheduledChange {
next_authorities: make_ids(peers_b),
delay: 4,
@@ -643,7 +679,7 @@ fn transition_3_voters_twice_1_full_observer() {
// at block 21 we do another transition, but this time instant.
// add more until we have 30.
net.lock().peer(0).generate_blocks(1, BlockOrigin::File, |builder| {
let mut block = builder.bake().unwrap();
let mut block = builder.build().unwrap().block;
add_scheduled_change(&mut block, ScheduledChange {
next_authorities: make_ids(&peers_c),
delay: 0,
@@ -808,7 +844,7 @@ fn sync_justifications_on_change_blocks() {
// at block 21 we do add a transition which is instant
net.peer(0).generate_blocks(1, BlockOrigin::File, |builder| {
let mut block = builder.bake().unwrap();
let mut block = builder.build().unwrap().block;
add_scheduled_change(&mut block, ScheduledChange {
next_authorities: make_ids(peers_b),
delay: 0,
@@ -870,7 +906,7 @@ fn finalizes_multiple_pending_changes_in_order() {
// at block 21 we do add a transition which is instant
net.peer(0).generate_blocks(1, BlockOrigin::File, |builder| {
let mut block = builder.bake().unwrap();
let mut block = builder.build().unwrap().block;
add_scheduled_change(&mut block, ScheduledChange {
next_authorities: make_ids(peers_b),
delay: 0,
@@ -883,7 +919,7 @@ fn finalizes_multiple_pending_changes_in_order() {
// at block 26 we add another which is enacted at block 30
net.peer(0).generate_blocks(1, BlockOrigin::File, |builder| {
let mut block = builder.bake().unwrap();
let mut block = builder.build().unwrap().block;
add_scheduled_change(&mut block, ScheduledChange {
next_authorities: make_ids(peers_c),
delay: 4,
@@ -927,7 +963,7 @@ fn force_change_to_new_set() {
let net = Arc::new(Mutex::new(net));
net.lock().peer(0).generate_blocks(1, BlockOrigin::File, |builder| {
let mut block = builder.bake().unwrap();
let mut block = builder.build().unwrap().block;
// add a forced transition at block 12.
add_forced_change(&mut block, 0, ScheduledChange {
@@ -973,11 +1009,15 @@ fn allows_reimporting_change_blocks() {
let mut net = GrandpaTestNet::new(api.clone(), 3);
let client = net.peer(0).client().clone();
let (mut block_import, ..) = net.make_block_import(client.clone());
let (mut block_import, ..) = net.make_block_import::<
TransactionFor<substrate_test_runtime_client::Backend, Block>
>(
client.clone(),
);
let full_client = client.as_full().unwrap();
let builder = full_client.new_block_at(&BlockId::Number(0), Default::default()).unwrap();
let mut block = builder.bake().unwrap();
let builder = full_client.new_block_at(&BlockId::Number(0), Default::default(), false).unwrap();
let mut block = builder.build().unwrap().block;
add_scheduled_change(&mut block, ScheduledChange {
next_authorities: make_ids(peers_b),
delay: 0,
@@ -991,6 +1031,7 @@ fn allows_reimporting_change_blocks() {
justification: None,
post_digests: Vec::new(),
body: Some(block.extrinsics),
storage_changes: None,
finalized: false,
auxiliary: Vec::new(),
fork_choice: ForkChoiceStrategy::LongestChain,
@@ -1026,11 +1067,15 @@ fn test_bad_justification() {
let mut net = GrandpaTestNet::new(api.clone(), 3);
let client = net.peer(0).client().clone();
let (mut block_import, ..) = net.make_block_import(client.clone());
let (mut block_import, ..) = net.make_block_import::<
TransactionFor<substrate_test_runtime_client::Backend, Block>
>(
client.clone(),
);
let full_client = client.as_full().expect("only full clients are used in test");
let builder = full_client.new_block_at(&BlockId::Number(0), Default::default()).unwrap();
let mut block = builder.bake().unwrap();
let builder = full_client.new_block_at(&BlockId::Number(0), Default::default(), false).unwrap();
let mut block = builder.build().unwrap().block;
add_scheduled_change(&mut block, ScheduledChange {
next_authorities: make_ids(peers_b),
@@ -1045,6 +1090,7 @@ fn test_bad_justification() {
justification: Some(Vec::new()),
post_digests: Vec::new(),
body: Some(block.extrinsics),
storage_changes: None,
finalized: false,
auxiliary: Vec::new(),
fork_choice: ForkChoiceStrategy::LongestChain,
@@ -1136,7 +1182,10 @@ fn voter_persists_its_votes() {
Ok(Async::NotReady) => {}
Ok(Async::Ready(Some(()))) => {
let (_block_import, _, _, _, link) =
self.net.lock().make_block_import(self.client.clone());
self.net.lock()
.make_block_import::<
TransactionFor<substrate_test_runtime_client::Backend, Block>
>(self.client.clone());
let link = link.lock().take().unwrap();
let grandpa_params = GrandpaParams {
@@ -1209,7 +1258,10 @@ fn voter_persists_its_votes() {
};
let set_state = {
let (_, _, _, _, link) = net.lock().make_block_import(client);
let (_, _, _, _, link) = net.lock()
.make_block_import::<
TransactionFor<substrate_test_runtime_client::Backend, Block>
>(client);
let LinkHalf { persistent_data, .. } = link.lock().take().unwrap();
let PersistentData { set_state, .. } = persistent_data;
set_state
@@ -1439,7 +1491,7 @@ fn empty_finality_proof_is_returned_to_light_client_when_authority_set_is_differ
// best is #1
net.lock().peer(0).generate_blocks(1, BlockOrigin::File, |builder| {
// add a forced transition at block 5.
let mut block = builder.bake().unwrap();
let mut block = builder.build().unwrap().block;
if FORCE_CHANGE {
add_forced_change(&mut block, 0, ScheduledChange {
next_authorities: voters.clone(),
@@ -1728,11 +1780,13 @@ fn imports_justification_for_regular_blocks_on_import() {
let mut net = GrandpaTestNet::new(api.clone(), 1);
let client = net.peer(0).client().clone();
let (mut block_import, ..) = net.make_block_import(client.clone());
let (mut block_import, ..) = net.make_block_import::<
TransactionFor<substrate_test_runtime_client::Backend, Block>
>(client.clone());
let full_client = client.as_full().expect("only full clients are used in test");
let builder = full_client.new_block_at(&BlockId::Number(0), Default::default()).unwrap();
let block = builder.bake().unwrap();
let builder = full_client.new_block_at(&BlockId::Number(0), Default::default(), false).unwrap();
let block = builder.build().unwrap().block;
let block_hash = block.hash();
@@ -1776,6 +1830,7 @@ fn imports_justification_for_regular_blocks_on_import() {
justification: Some(justification.encode()),
post_digests: Vec::new(),
body: Some(block.extrinsics),
storage_changes: None,
finalized: false,
auxiliary: Vec::new(),
fork_choice: ForkChoiceStrategy::LongestChain,
+21 -10
View File
@@ -20,10 +20,9 @@ use sc_client::Client as SubstrateClient;
use sp_blockchain::{Error, Info as BlockchainInfo};
use sc_client_api::{ChangesProof, StorageProof, CallExecutor};
use sp_consensus::{BlockImport, BlockStatus, Error as ConsensusError};
use sp_runtime::traits::{Block as BlockT, Header as HeaderT};
use sp_runtime::traits::{Block as BlockT, Header as HeaderT, NumberFor};
use sp_runtime::generic::{BlockId};
use sp_runtime::Justification;
use sp_core::{H256, Blake2Hasher};
use sp_core::storage::{StorageKey, ChildInfo};
/// Local client abstraction for the network.
@@ -35,7 +34,7 @@ pub trait Client<Block: BlockT>: Send + Sync {
fn block_status(&self, id: &BlockId<Block>) -> Result<BlockStatus, Error>;
/// Get block hash by number.
fn block_hash(&self, block_number: <Block::Header as HeaderT>::Number) -> Result<Option<Block::Hash>, Error>;
fn block_hash(&self, block_number: NumberFor<Block>) -> Result<Option<Block::Hash>, Error>;
/// Get block header.
fn header(&self, id: &BlockId<Block>) -> Result<Option<Block::Header>, Error>;
@@ -47,7 +46,7 @@ pub trait Client<Block: BlockT>: Send + Sync {
fn justification(&self, id: &BlockId<Block>) -> Result<Option<Justification>, Error>;
/// Get block header proof.
fn header_proof(&self, block_number: <Block::Header as HeaderT>::Number)
fn header_proof(&self, block_number: NumberFor<Block>)
-> Result<(Block::Header, StorageProof), Error>;
/// Get storage read execution proof.
@@ -93,10 +92,10 @@ impl<Block: BlockT> FinalityProofProvider<Block> for () {
}
impl<B, E, Block, RA> Client<Block> for SubstrateClient<B, E, Block, RA> where
B: sc_client_api::backend::Backend<Block, Blake2Hasher> + Send + Sync + 'static,
E: CallExecutor<Block, Blake2Hasher> + Send + Sync + 'static,
B: sc_client_api::backend::Backend<Block> + Send + Sync + 'static,
E: CallExecutor<Block> + Send + Sync + 'static,
Self: BlockImport<Block, Error=ConsensusError>,
Block: BlockT<Hash=H256>,
Block: BlockT,
RA: Send + Sync
{
fn info(&self) -> BlockchainInfo<Block> {
@@ -107,7 +106,10 @@ impl<B, E, Block, RA> Client<Block> for SubstrateClient<B, E, Block, RA> where
(self as &SubstrateClient<B, E, Block, RA>).block_status(id)
}
fn block_hash(&self, block_number: <Block::Header as HeaderT>::Number) -> Result<Option<Block::Hash>, Error> {
fn block_hash(
&self,
block_number: <Block::Header as HeaderT>::Number,
) -> Result<Option<Block::Hash>, Error> {
(self as &SubstrateClient<B, E, Block, RA>).block_hash(block_number)
}
@@ -144,8 +146,17 @@ impl<B, E, Block, RA> Client<Block> for SubstrateClient<B, E, Block, RA> where
.read_child_proof(&BlockId::Hash(block.clone()), storage_key, child_info, keys)
}
fn execution_proof(&self, block: &Block::Hash, method: &str, data: &[u8]) -> Result<(Vec<u8>, StorageProof), Error> {
(self as &SubstrateClient<B, E, Block, RA>).execution_proof(&BlockId::Hash(block.clone()), method, data)
fn execution_proof(
&self,
block: &Block::Hash,
method: &str,
data: &[u8],
) -> Result<(Vec<u8>, StorageProof), Error> {
(self as &SubstrateClient<B, E, Block, RA>).execution_proof(
&BlockId::Hash(block.clone()),
method,
data,
)
}
fn key_changes_proof(
@@ -21,9 +21,10 @@ use std::{collections::HashMap, pin::Pin, sync::Arc, task::Context, task::Poll};
use futures::{prelude::*, channel::mpsc, channel::oneshot};
use parking_lot::Mutex;
use sp_blockchain::Error as ClientError;
use sc_client_api::{Fetcher, FetchChecker, RemoteHeaderRequest,
RemoteCallRequest, RemoteReadRequest, RemoteChangesRequest,
RemoteReadChildRequest, RemoteBodyRequest};
use sc_client_api::{
Fetcher, FetchChecker, RemoteHeaderRequest, RemoteCallRequest, RemoteReadRequest,
RemoteChangesRequest, RemoteReadChildRequest, RemoteBodyRequest,
};
use sp_runtime::traits::{Block as BlockT, Header as HeaderT, NumberFor};
/// Implements the `Fetcher` trait of the client. Makes it possible for the light client to perform
@@ -26,8 +26,8 @@ use sp_runtime::generic::BlockId;
use super::*;
fn prepare_good_block() -> (TestClient, Hash, u64, PeerId, IncomingBlock<Block>) {
let client = substrate_test_runtime_client::new();
let block = client.new_block(Default::default()).unwrap().bake().unwrap();
let mut client = substrate_test_runtime_client::new();
let block = client.new_block(Default::default()).unwrap().build().unwrap().block;
client.import(BlockOrigin::File, block).unwrap();
let (hash, number) = (client.block_hash(1).unwrap().unwrap(), 1);
+136 -48
View File
@@ -21,9 +21,7 @@ mod block_import;
#[cfg(test)]
mod sync;
use std::collections::HashMap;
use std::pin::Pin;
use std::sync::Arc;
use std::{collections::HashMap, pin::Pin, sync::Arc, marker::PhantomData};
use libp2p::build_multiaddr;
use log::trace;
@@ -35,15 +33,14 @@ use sc_client_api::{
BlockchainEvents, BlockImportNotification,
FinalityNotifications, ImportNotifications,
FinalityNotification,
backend::{AuxStore, Backend, Finalizer}
backend::{TransactionFor, AuxStore, Backend, Finalizer},
};
use sc_block_builder::BlockBuilder;
use sc_client::LongestChain;
use sc_network::config::Roles;
use sp_consensus::block_validation::DefaultBlockAnnounceValidator;
use sp_consensus::import_queue::BasicQueue;
use sp_consensus::import_queue::{
BoxBlockImport, BoxJustificationImport, Verifier, BoxFinalityProofImport,
BasicQueue, BoxJustificationImport, Verifier, BoxFinalityProofImport,
};
use sp_consensus::block_import::{BlockImport, ImportResult};
use sp_consensus::Error as ConsensusError;
@@ -57,7 +54,7 @@ use parking_lot::Mutex;
use sp_core::H256;
use sc_network::{Context, ProtocolConfig};
use sp_runtime::generic::{BlockId, OpaqueDigestItemId};
use sp_runtime::traits::{Block as BlockT, Header, NumberFor};
use sp_runtime::traits::{Block as BlockT, Header as HeaderT, NumberFor};
use sp_runtime::Justification;
use sc_network::TransactionPool;
use sc_network::specialization::NetworkSpecialization;
@@ -81,7 +78,7 @@ impl<B: BlockT> Verifier<B> for PassThroughVerifier {
header: B::Header,
justification: Option<Justification>,
body: Option<Vec<B::Extrinsic>>
) -> Result<(BlockImportParams<B>, Option<Vec<(CacheKeyId, Vec<u8>)>>), String> {
) -> Result<(BlockImportParams<B, ()>, Option<Vec<(CacheKeyId, Vec<u8>)>>), String> {
let maybe_keys = header.digest()
.log(|l| l.try_as_raw(OpaqueDigestItemId::Consensus(b"aura"))
.or_else(|| l.try_as_raw(OpaqueDigestItemId::Consensus(b"babe")))
@@ -92,6 +89,7 @@ impl<B: BlockT> Verifier<B> for PassThroughVerifier {
origin,
header,
body,
storage_changes: None,
finalized: self.0,
justification,
post_digests: vec![],
@@ -148,10 +146,12 @@ impl PeersClient {
}
}
pub fn as_block_import(&self) -> BoxBlockImport<Block> {
pub fn as_block_import<Transaction>(&self) -> BlockImportAdapter<Transaction> {
match *self {
PeersClient::Full(ref client, ref _backend) => Box::new(client.clone()) as _,
PeersClient::Light(ref client, ref _backend) => Box::new(client.clone()) as _,
PeersClient::Full(ref client, ref _backend) =>
BlockImportAdapter::new_full(client.clone()),
PeersClient::Light(ref client, ref _backend) =>
BlockImportAdapter::Light(Arc::new(Mutex::new(client.clone())), PhantomData),
}
}
@@ -218,7 +218,7 @@ pub struct Peer<D, S: NetworkSpecialization<Block>> {
verifier: VerifierAdapter<dyn Verifier<Block>>,
/// We keep a copy of the block_import so that we can invoke it for locally-generated blocks,
/// instead of going through the import queue.
block_import: Box<dyn BlockImport<Block, Error = ConsensusError>>,
block_import: BlockImportAdapter<()>,
select_chain: Option<LongestChain<substrate_test_runtime_client::Backend, Block>>,
backend: Option<Arc<substrate_test_runtime_client::Backend>>,
network: NetworkWorker<Block, S, <Block as BlockT>::Hash>,
@@ -269,7 +269,7 @@ impl<D, S: NetworkSpecialization<Block>> Peer<D, S> {
/// Add blocks to the peer -- edit the block before adding
pub fn generate_blocks<F>(&mut self, count: usize, origin: BlockOrigin, edit_block: F) -> H256
where F: FnMut(BlockBuilder<Block, PeersFullClient>) -> Block
where F: FnMut(BlockBuilder<Block, PeersFullClient, substrate_test_runtime_client::Backend>) -> Block
{
let best_hash = self.client.info().best_hash;
self.generate_blocks_at(BlockId::Hash(best_hash), count, origin, edit_block)
@@ -283,11 +283,15 @@ impl<D, S: NetworkSpecialization<Block>> Peer<D, S> {
count: usize,
origin: BlockOrigin,
mut edit_block: F
) -> H256 where F: FnMut(BlockBuilder<Block, PeersFullClient>) -> Block {
let full_client = self.client.as_full().expect("blocks could only be generated by full clients");
) -> H256 where F: FnMut(BlockBuilder<Block, PeersFullClient, substrate_test_runtime_client::Backend>) -> Block {
let full_client = self.client.as_full()
.expect("blocks could only be generated by full clients");
let mut at = full_client.header(&at).unwrap().unwrap().hash();
for _ in 0..count {
let builder = full_client.new_block_at(&BlockId::Hash(at), Default::default()
let builder = full_client.new_block_at(
&BlockId::Hash(at),
Default::default(),
false,
).unwrap();
let block = edit_block(builder);
let hash = block.header.hash();
@@ -296,7 +300,7 @@ impl<D, S: NetworkSpecialization<Block>> Peer<D, S> {
"Generating {}, (#{}, parent={})",
hash,
block.header.number,
block.header.parent_hash
block.header.parent_hash,
);
let header = block.header.clone();
let (import_block, cache) = self.verifier.verify(
@@ -339,17 +343,22 @@ impl<D, S: NetworkSpecialization<Block>> Peer<D, S> {
};
builder.push(transfer.into_signed_tx()).unwrap();
nonce = nonce + 1;
builder.bake().unwrap()
builder.build().unwrap().block
})
} else {
self.generate_blocks_at(at, count, BlockOrigin::File, |builder| builder.bake().unwrap())
self.generate_blocks_at(
at,
count,
BlockOrigin::File,
|builder| builder.build().unwrap().block,
)
}
}
pub fn push_authorities_change_block(&mut self, new_authorities: Vec<AuthorityId>) -> H256 {
self.generate_blocks(1, BlockOrigin::File, |mut builder| {
builder.push(Extrinsic::AuthoritiesChange(new_authorities.clone())).unwrap();
builder.bake().unwrap()
builder.build().unwrap().block
})
}
@@ -418,33 +427,90 @@ impl SpecializationFactory for DummySpecialization {
}
}
/// Implements `BlockImport` on an `Arc<Mutex<impl BlockImport>>`. Used internally. Necessary to overcome the way the
/// `TestNet` trait is designed, more specifically `make_block_import` returning a `Box<BlockImport>` makes it
/// impossible to clone the underlying object.
struct BlockImportAdapter<T: ?Sized>(Arc<Mutex<Box<T>>>);
/// Implements `BlockImport` for any `Transaction`. Internally the transaction is
/// "converted", aka the field is set to `None`.
///
/// This is required as the `TestNetFactory` trait does not distinguish between
/// full and light nodes.
pub enum BlockImportAdapter<Transaction> {
Full(
Arc<Mutex<dyn BlockImport<
Block,
Transaction = TransactionFor<substrate_test_runtime_client::Backend, Block>,
Error = ConsensusError
> + Send>>,
PhantomData<Transaction>,
),
Light(
Arc<Mutex<dyn BlockImport<
Block,
Transaction = TransactionFor<substrate_test_runtime_client::LightBackend, Block>,
Error = ConsensusError
> + Send>>,
PhantomData<Transaction>,
),
}
impl<T: ?Sized> Clone for BlockImportAdapter<T> {
fn clone(&self) -> Self {
BlockImportAdapter(self.0.clone())
impl<Transaction> BlockImportAdapter<Transaction> {
/// Create a new instance of `Self::Full`.
pub fn new_full(
full: impl BlockImport<
Block,
Transaction = TransactionFor<substrate_test_runtime_client::Backend, Block>,
Error = ConsensusError
>
+ 'static
+ Send
) -> Self {
Self::Full(Arc::new(Mutex::new(full)), PhantomData)
}
/// Create a new instance of `Self::Light`.
pub fn new_light(
light: impl BlockImport<
Block,
Transaction = TransactionFor<substrate_test_runtime_client::LightBackend, Block>,
Error = ConsensusError
>
+ 'static
+ Send
) -> Self {
Self::Light(Arc::new(Mutex::new(light)), PhantomData)
}
}
impl<T: ?Sized + BlockImport<Block>> BlockImport<Block> for BlockImportAdapter<T> {
type Error = T::Error;
impl<Transaction> Clone for BlockImportAdapter<Transaction> {
fn clone(&self) -> Self {
match self {
Self::Full(full, _) => Self::Full(full.clone(), PhantomData),
Self::Light(light, _) => Self::Light(light.clone(), PhantomData),
}
}
}
impl<Transaction> BlockImport<Block> for BlockImportAdapter<Transaction> {
type Error = ConsensusError;
type Transaction = Transaction;
fn check_block(
&mut self,
block: BlockCheckParams<Block>,
) -> Result<ImportResult, Self::Error> {
self.0.lock().check_block(block)
match self {
Self::Full(full, _) => full.lock().check_block(block),
Self::Light(light, _) => light.lock().check_block(block),
}
}
fn import_block(
&mut self,
block: BlockImportParams<Block>,
block: BlockImportParams<Block, Transaction>,
cache: HashMap<well_known_cache_keys::Id, Vec<u8>>,
) -> Result<ImportResult, Self::Error> {
self.0.lock().import_block(block, cache)
match self {
Self::Full(full, _) => full.lock().import_block(block.convert_transaction(), cache),
Self::Light(light, _) => light.lock().import_block(block.convert_transaction(), cache),
}
}
}
@@ -464,7 +530,7 @@ impl<B: BlockT, T: ?Sized + Verifier<B>> Verifier<B> for VerifierAdapter<T> {
header: B::Header,
justification: Option<Justification>,
body: Option<Vec<B::Extrinsic>>
) -> Result<(BlockImportParams<B>, Option<Vec<(CacheKeyId, Vec<u8>)>>), String> {
) -> Result<(BlockImportParams<B, ()>, Option<Vec<(CacheKeyId, Vec<u8>)>>), String> {
self.0.lock().verify(origin, header, justification, body)
}
}
@@ -486,12 +552,15 @@ pub trait TestNetFactory: Sized {
/// Get reference to peer.
fn peer(&mut self, i: usize) -> &mut Peer<Self::PeerData, Self::Specialization>;
fn peers(&self) -> &Vec<Peer<Self::PeerData, Self::Specialization>>;
fn mut_peers<F: FnOnce(&mut Vec<Peer<Self::PeerData, Self::Specialization>>)>(&mut self, closure: F);
fn mut_peers<F: FnOnce(&mut Vec<Peer<Self::PeerData, Self::Specialization>>)>(
&mut self,
closure: F,
);
/// Get custom block import handle for fresh client, along with peer data.
fn make_block_import(&self, client: PeersClient)
fn make_block_import<Transaction>(&self, client: PeersClient)
-> (
BoxBlockImport<Block>,
BlockImportAdapter<Transaction>,
Option<BoxJustificationImport<Block>>,
Option<BoxFinalityProofImport<Block>>,
Option<BoxFinalityProofRequestBuilder<Block>>,
@@ -502,7 +571,10 @@ pub trait TestNetFactory: Sized {
}
/// Get finality proof provider (if supported).
fn make_finality_proof_provider(&self, _client: PeersClient) -> Option<Arc<dyn FinalityProofProvider<Block>>> {
fn make_finality_proof_provider(
&self,
_client: PeersClient,
) -> Option<Arc<dyn FinalityProofProvider<Block>>> {
None
}
@@ -544,7 +616,6 @@ pub trait TestNetFactory: Sized {
finality_proof_request_builder,
data,
) = self.make_block_import(PeersClient::Full(client.clone(), backend.clone()));
let block_import = BlockImportAdapter(Arc::new(Mutex::new(block_import)));
let verifier = self.make_verifier(
PeersClient::Full(client.clone(), backend.clone()),
@@ -570,7 +641,9 @@ pub trait TestNetFactory: Sized {
..NetworkConfiguration::default()
},
chain: client.clone(),
finality_proof_provider: self.make_finality_proof_provider(PeersClient::Full(client.clone(), backend.clone())),
finality_proof_provider: self.make_finality_proof_provider(
PeersClient::Full(client.clone(), backend.clone()),
),
finality_proof_request_builder,
on_demand: None,
transaction_pool: Arc::new(EmptyTransactionPool),
@@ -597,7 +670,7 @@ pub trait TestNetFactory: Sized {
backend: Some(backend),
imported_blocks_stream,
finality_notification_stream,
block_import: Box::new(block_import),
block_import,
verifier,
network,
});
@@ -618,7 +691,6 @@ pub trait TestNetFactory: Sized {
finality_proof_request_builder,
data,
) = self.make_block_import(PeersClient::Light(client.clone(), backend.clone()));
let block_import = BlockImportAdapter(Arc::new(Mutex::new(block_import)));
let verifier = self.make_verifier(
PeersClient::Light(client.clone(), backend.clone()),
@@ -644,7 +716,9 @@ pub trait TestNetFactory: Sized {
..NetworkConfiguration::default()
},
chain: client.clone(),
finality_proof_provider: self.make_finality_proof_provider(PeersClient::Light(client.clone(), backend.clone())),
finality_proof_provider: self.make_finality_proof_provider(
PeersClient::Light(client.clone(), backend.clone())
),
finality_proof_request_builder,
on_demand: None,
transaction_pool: Arc::new(EmptyTransactionPool),
@@ -669,7 +743,7 @@ pub trait TestNetFactory: Sized {
verifier,
select_chain: None,
backend: None,
block_import: Box::new(block_import),
block_import,
client: PeersClient::Light(client, backend),
imported_blocks_stream,
finality_notification_stream,
@@ -721,7 +795,12 @@ pub trait TestNetFactory: Sized {
// We poll `imported_blocks_stream`.
while let Ok(Async::Ready(Some(notification))) = peer.imported_blocks_stream.poll() {
peer.network.on_block_imported(notification.hash, notification.header, Vec::new(), true);
peer.network.on_block_imported(
notification.hash,
notification.header,
Vec::new(),
true,
);
}
// We poll `finality_notification_stream`, but we only take the last event.
@@ -811,19 +890,28 @@ impl TestNetFactory for JustificationTestNet {
self.0.peers()
}
fn mut_peers<F: FnOnce(&mut Vec<Peer<Self::PeerData, Self::Specialization>>)>(&mut self, closure: F) {
fn mut_peers<F: FnOnce(
&mut Vec<Peer<Self::PeerData,
Self::Specialization>>,
)>(&mut self, closure: F) {
self.0.mut_peers(closure)
}
fn make_block_import(&self, client: PeersClient)
fn make_block_import<Transaction>(&self, client: PeersClient)
-> (
BoxBlockImport<Block>,
BlockImportAdapter<Transaction>,
Option<BoxJustificationImport<Block>>,
Option<BoxFinalityProofImport<Block>>,
Option<BoxFinalityProofRequestBuilder<Block>>,
Self::PeerData,
)
{
(client.as_block_import(), Some(Box::new(ForceFinalized(client))), None, None, Default::default())
(
client.as_block_import(),
Some(Box::new(ForceFinalized(client))),
None,
None,
Default::default(),
)
}
}
+1 -1
View File
@@ -370,7 +370,7 @@ fn own_blocks_are_announced() {
let mut runtime = current_thread::Runtime::new().unwrap();
let mut net = TestNet::new(3);
net.block_until_sync(&mut runtime); // connect'em
net.peer(0).generate_blocks(1, BlockOrigin::Own, |builder| builder.bake().unwrap());
net.peer(0).generate_blocks(1, BlockOrigin::Own, |builder| builder.build().unwrap().block);
net.block_until_sync(&mut runtime);
+3 -3
View File
@@ -37,12 +37,12 @@ use std::{fmt, marker::PhantomData, sync::Arc};
use parking_lot::Mutex;
use threadpool::ThreadPool;
use sp_api::ApiExt;
use sp_api::{ApiExt, ProvideRuntimeApi};
use futures::future::Future;
use log::{debug, warn};
use sc_network::NetworkStateInfo;
use sp_core::{offchain::{self, OffchainStorage}, ExecutionContext};
use sp_runtime::{generic::BlockId, traits::{self, ProvideRuntimeApi, Header}};
use sp_runtime::{generic::BlockId, traits::{self, Header}};
mod api;
@@ -84,7 +84,7 @@ impl<Client, Storage, Block> OffchainWorkers<
Block,
> where
Block: traits::Block,
Client: ProvideRuntimeApi + Send + Sync + 'static,
Client: ProvideRuntimeApi<Block> + Send + Sync + 'static,
Client::Api: OffchainWorkerApi<Block>,
Storage: OffchainStorage + 'static,
{
+15 -12
View File
@@ -34,9 +34,9 @@ use futures::future::{ready, FutureExt, TryFutureExt};
use sc_rpc_api::Subscriptions;
use jsonrpc_pubsub::{typed::Subscriber, SubscriptionId};
use codec::{Encode, Decode};
use sp_core::{Bytes, Blake2Hasher, H256, traits::BareCryptoStorePtr};
use sp_api::ConstructRuntimeApi;
use sp_runtime::{generic, traits::{self, ProvideRuntimeApi}};
use sp_core::{Bytes, traits::BareCryptoStorePtr};
use sp_api::ProvideRuntimeApi;
use sp_runtime::{generic, traits};
use sp_transaction_pool::{
TransactionPool, InPoolTransaction, TransactionStatus,
BlockHash, TxHash, TransactionFor, error::IntoPoolError,
@@ -76,15 +76,18 @@ impl<B, E, P, Block: traits::Block, RA> Author<B, E, P, Block, RA> {
}
}
impl<B, E, P, Block, RA> AuthorApi<Block::Hash, Block::Hash> for Author<B, E, P, Block, RA> where
Block: traits::Block<Hash=H256>,
B: sc_client_api::backend::Backend<Block, Blake2Hasher> + Send + Sync + 'static,
E: sc_client_api::CallExecutor<Block, Blake2Hasher> + Clone + Send + Sync + 'static,
P: TransactionPool<Block=Block, Hash=Block::Hash> + Sync + Send + 'static,
RA: ConstructRuntimeApi<Block, Client<B, E, Block, RA>> + Send + Sync + 'static,
Client<B, E, Block, RA>: ProvideRuntimeApi,
<Client<B, E, Block, RA> as ProvideRuntimeApi>::Api:
SessionKeys<Block, Error = ClientError>,
impl<B, E, P, RA> AuthorApi<TxHash<P>, BlockHash<P>>
for Author<B, E, P, <P as TransactionPool>::Block, RA>
where
B: sc_client_api::backend::Backend<<P as TransactionPool>::Block> + Send + Sync + 'static,
E: sc_client::CallExecutor<<P as TransactionPool>::Block> + Send + Sync + 'static,
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;
+4 -8
View File
@@ -22,11 +22,7 @@ use rpc::futures::future::result;
use sc_rpc_api::Subscriptions;
use sc_client_api::{CallExecutor, backend::Backend};
use sc_client::Client;
use sp_core::{H256, Blake2Hasher};
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};
@@ -49,9 +45,9 @@ impl<B, E, Block: BlockT, RA> FullChain<B, E, Block, RA> {
}
impl<B, E, Block, RA> ChainBackend<B, E, Block, RA> for FullChain<B, E, Block, RA> where
Block: BlockT<Hash=H256> + 'static,
B: Backend<Block, Blake2Hasher> + Send + Sync + 'static,
E: CallExecutor<Block, Blake2Hasher> + Send + Sync + 'static,
Block: BlockT + 'static,
B: Backend<Block> + Send + Sync + 'static,
E: CallExecutor<Block> + Send + Sync + 'static,
RA: Send + Sync + 'static,
{
fn client(&self) -> &Arc<Client<B, E, Block, RA>> {
@@ -22,13 +22,8 @@ use rpc::futures::future::{result, Future, Either};
use sc_rpc_api::Subscriptions;
use sc_client::{
self, Client,
light::{
fetcher::{Fetcher, RemoteBodyRequest},
blockchain::RemoteBlockchain,
},
Client, light::{fetcher::{Fetcher, RemoteBodyRequest}, blockchain::RemoteBlockchain},
};
use sp_core::{H256, Blake2Hasher};
use sp_runtime::{
generic::{BlockId, SignedBlock},
traits::{Block as BlockT},
@@ -67,9 +62,9 @@ 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
Block: BlockT<Hash=H256> + 'static,
B: sc_client_api::backend::Backend<Block, Blake2Hasher> + Send + Sync + 'static,
E: sc_client::CallExecutor<Block, Blake2Hasher> + Send + Sync + 'static,
Block: BlockT + 'static,
B: sc_client_api::backend::Backend<Block> + Send + Sync + 'static,
E: sc_client::CallExecutor<Block> + Send + Sync + 'static,
RA: Send + Sync + 'static,
F: Fetcher<Block> + Send + Sync + 'static,
{
+15 -16
View File
@@ -36,7 +36,6 @@ use sc_client::{
light::{fetcher::Fetcher, blockchain::RemoteBlockchain},
};
use jsonrpc_pubsub::{typed::Subscriber, SubscriptionId};
use sp_core::{H256, Blake2Hasher};
use sp_rpc::{number::NumberOrHex, list::ListOrValue};
use sp_runtime::{
generic::{BlockId, SignedBlock},
@@ -50,9 +49,9 @@ pub use sc_rpc_api::chain::*;
/// Blockchain backend API
trait ChainBackend<B, E, Block: BlockT, RA>: Send + Sync + 'static
where
Block: BlockT<Hash=H256> + 'static,
B: sc_client_api::backend::Backend<Block, Blake2Hasher> + Send + Sync + 'static,
E: sc_client::CallExecutor<Block, Blake2Hasher> + Send + Sync + 'static,
Block: BlockT + 'static,
B: sc_client_api::backend::Backend<Block> + Send + Sync + 'static,
E: sc_client::CallExecutor<Block> + Send + Sync + 'static,
{
/// Get client reference.
fn client(&self) -> &Arc<Client<B, E, Block, RA>>;
@@ -155,9 +154,9 @@ pub fn new_full<B, E, Block: BlockT, RA>(
subscriptions: Subscriptions,
) -> Chain<B, E, Block, RA>
where
Block: BlockT<Hash=H256> + 'static,
B: sc_client_api::backend::Backend<Block, Blake2Hasher> + Send + Sync + 'static,
E: sc_client::CallExecutor<Block, Blake2Hasher> + Send + Sync + 'static + Clone,
Block: BlockT + 'static,
B: sc_client_api::backend::Backend<Block> + Send + Sync + 'static,
E: sc_client::CallExecutor<Block> + Send + Sync + 'static + Clone,
RA: Send + Sync + 'static,
{
Chain {
@@ -173,9 +172,9 @@ pub fn new_light<B, E, Block: BlockT, RA, F: Fetcher<Block>>(
fetcher: Arc<F>,
) -> Chain<B, E, Block, RA>
where
Block: BlockT<Hash=H256> + 'static,
B: sc_client_api::backend::Backend<Block, Blake2Hasher> + Send + Sync + 'static,
E: sc_client::CallExecutor<Block, Blake2Hasher> + Send + Sync + 'static + Clone,
Block: BlockT + 'static,
B: sc_client_api::backend::Backend<Block> + Send + Sync + 'static,
E: sc_client::CallExecutor<Block> + Send + Sync + 'static + Clone,
RA: Send + Sync + 'static,
F: Send + Sync + 'static,
{
@@ -195,9 +194,9 @@ pub struct Chain<B, E, Block: BlockT, RA> {
}
impl<B, E, Block, RA> ChainApi<NumberFor<Block>, Block::Hash, Block::Header, SignedBlock<Block>> for Chain<B, E, Block, RA> where
Block: BlockT<Hash=H256> + 'static,
B: sc_client_api::backend::Backend<Block, Blake2Hasher> + Send + Sync + 'static,
E: sc_client::CallExecutor<Block, Blake2Hasher> + Send + Sync + 'static,
Block: BlockT + 'static,
B: sc_client_api::backend::Backend<Block> + Send + Sync + 'static,
E: sc_client::CallExecutor<Block> + Send + Sync + 'static,
RA: Send + Sync + 'static
{
type Metadata = crate::metadata::Metadata;
@@ -255,9 +254,9 @@ fn subscribe_headers<B, E, Block, RA, F, G, S, ERR>(
best_block_hash: G,
stream: F,
) where
Block: BlockT<Hash=H256> + 'static,
B: sc_client_api::backend::Backend<Block, Blake2Hasher> + Send + Sync + 'static,
E: sc_client::CallExecutor<Block, Blake2Hasher> + Send + Sync + 'static,
Block: BlockT + 'static,
B: sc_client_api::backend::Backend<Block> + Send + Sync + 'static,
E: sc_client::CallExecutor<Block> + Send + Sync + 'static,
F: FnOnce() -> S,
G: FnOnce() -> Block::Hash,
ERR: ::std::fmt::Debug,
+24 -23
View File
@@ -25,7 +25,7 @@ use sp_rpc::list::ListOrValue;
#[test]
fn should_return_header() {
let core = ::tokio::runtime::Runtime::new().unwrap();
let core = tokio::runtime::Runtime::new().unwrap();
let remote = core.executor();
let client = Arc::new(substrate_test_runtime_client::new());
@@ -37,7 +37,8 @@ fn should_return_header() {
parent_hash: H256::from_low_u64_be(0),
number: 0,
state_root: x.state_root.clone(),
extrinsics_root: "03170a2e7597b7b7e3d84c05391d139a62b157e78786d8c082f29dcf4c111314".parse().unwrap(),
extrinsics_root:
"03170a2e7597b7b7e3d84c05391d139a62b157e78786d8c082f29dcf4c111314".parse().unwrap(),
digest: Default::default(),
}
);
@@ -48,26 +49,24 @@ fn should_return_header() {
parent_hash: H256::from_low_u64_be(0),
number: 0,
state_root: x.state_root.clone(),
extrinsics_root: "03170a2e7597b7b7e3d84c05391d139a62b157e78786d8c082f29dcf4c111314".parse().unwrap(),
extrinsics_root:
"03170a2e7597b7b7e3d84c05391d139a62b157e78786d8c082f29dcf4c111314".parse().unwrap(),
digest: Default::default(),
}
);
assert_matches!(
api.header(Some(H256::from_low_u64_be(5)).into()).wait(),
Ok(None)
);
assert_matches!(api.header(Some(H256::from_low_u64_be(5)).into()).wait(), Ok(None));
}
#[test]
fn should_return_a_block() {
let core = ::tokio::runtime::Runtime::new().unwrap();
let core = tokio::runtime::Runtime::new().unwrap();
let remote = core.executor();
let client = Arc::new(substrate_test_runtime_client::new());
let mut client = Arc::new(substrate_test_runtime_client::new());
let api = new_full(client.clone(), Subscriptions::new(Arc::new(remote)));
let block = client.new_block(Default::default()).unwrap().bake().unwrap();
let block = client.new_block(Default::default()).unwrap().build().unwrap().block;
let block_hash = block.hash();
client.import(BlockOrigin::Own, block).unwrap();
@@ -84,7 +83,8 @@ fn should_return_a_block() {
parent_hash: client.genesis_hash(),
number: 1,
state_root: x.block.header.state_root.clone(),
extrinsics_root: "03170a2e7597b7b7e3d84c05391d139a62b157e78786d8c082f29dcf4c111314".parse().unwrap(),
extrinsics_root:
"03170a2e7597b7b7e3d84c05391d139a62b157e78786d8c082f29dcf4c111314".parse().unwrap(),
digest: Default::default(),
},
extrinsics: vec![],
@@ -98,7 +98,8 @@ fn should_return_a_block() {
parent_hash: client.genesis_hash(),
number: 1,
state_root: x.block.header.state_root.clone(),
extrinsics_root: "03170a2e7597b7b7e3d84c05391d139a62b157e78786d8c082f29dcf4c111314".parse().unwrap(),
extrinsics_root:
"03170a2e7597b7b7e3d84c05391d139a62b157e78786d8c082f29dcf4c111314".parse().unwrap(),
digest: Default::default(),
},
extrinsics: vec![],
@@ -116,7 +117,7 @@ fn should_return_block_hash() {
let core = ::tokio::runtime::Runtime::new().unwrap();
let remote = core.executor();
let client = Arc::new(substrate_test_runtime_client::new());
let mut client = Arc::new(substrate_test_runtime_client::new());
let api = new_full(client.clone(), Subscriptions::new(Arc::new(remote)));
assert_matches!(
@@ -135,7 +136,7 @@ fn should_return_block_hash() {
Ok(ListOrValue::Value(None))
);
let block = client.new_block(Default::default()).unwrap().bake().unwrap();
let block = client.new_block(Default::default()).unwrap().build().unwrap().block;
client.import(BlockOrigin::Own, block.clone()).unwrap();
assert_matches!(
@@ -163,7 +164,7 @@ fn should_return_finalized_hash() {
let core = ::tokio::runtime::Runtime::new().unwrap();
let remote = core.executor();
let client = Arc::new(substrate_test_runtime_client::new());
let mut client = Arc::new(substrate_test_runtime_client::new());
let api = new_full(client.clone(), Subscriptions::new(Arc::new(remote)));
assert_matches!(
@@ -172,8 +173,8 @@ fn should_return_finalized_hash() {
);
// import new block
let builder = client.new_block(Default::default()).unwrap();
client.import(BlockOrigin::Own, builder.bake().unwrap()).unwrap();
let block = client.new_block(Default::default()).unwrap().build().unwrap().block;
client.import(BlockOrigin::Own, block).unwrap();
// no finalization yet
assert_matches!(
api.finalized_head(),
@@ -195,7 +196,7 @@ fn should_notify_about_latest_block() {
let (subscriber, id, transport) = Subscriber::new_test("test");
{
let client = Arc::new(substrate_test_runtime_client::new());
let mut client = Arc::new(substrate_test_runtime_client::new());
let api = new_full(client.clone(), Subscriptions::new(Arc::new(remote)));
api.subscribe_new_heads(Default::default(), subscriber);
@@ -203,8 +204,8 @@ fn should_notify_about_latest_block() {
// assert id assigned
assert_eq!(core.block_on(id), Ok(Ok(SubscriptionId::Number(1))));
let builder = client.new_block(Default::default()).unwrap();
client.import(BlockOrigin::Own, builder.bake().unwrap()).unwrap();
let block = client.new_block(Default::default()).unwrap().build().unwrap().block;
client.import(BlockOrigin::Own, block).unwrap();
}
// assert initial head sent.
@@ -224,7 +225,7 @@ fn should_notify_about_finalized_block() {
let (subscriber, id, transport) = Subscriber::new_test("test");
{
let client = Arc::new(substrate_test_runtime_client::new());
let mut client = Arc::new(substrate_test_runtime_client::new());
let api = new_full(client.clone(), Subscriptions::new(Arc::new(remote)));
api.subscribe_finalized_heads(Default::default(), subscriber);
@@ -232,8 +233,8 @@ fn should_notify_about_finalized_block() {
// assert id assigned
assert_eq!(core.block_on(id), Ok(Ok(SubscriptionId::Number(1))));
let builder = client.new_block(Default::default()).unwrap();
client.import(BlockOrigin::Own, builder.bake().unwrap()).unwrap();
let block = client.new_block(Default::default()).unwrap().build().unwrap().block;
client.import(BlockOrigin::Own, block).unwrap();
client.finalize_block(BlockId::number(1), None).unwrap();
}
+17 -22
View File
@@ -28,16 +28,11 @@ use rpc::{Result as RpcResult, futures::Future};
use sc_rpc_api::Subscriptions;
use sc_client::{Client, CallExecutor, light::{blockchain::RemoteBlockchain, fetcher::Fetcher}};
use sp_core::{
Blake2Hasher, Bytes, H256,
storage::{StorageKey, StorageData, StorageChangeSet},
};
use sp_core::{Bytes, storage::{StorageKey, StorageData, StorageChangeSet}};
use sp_version::RuntimeVersion;
use sp_runtime::{
traits::{Block as BlockT, ProvideRuntimeApi},
};
use sp_runtime::traits::Block as BlockT;
use sp_api::Metadata;
use sp_api::{Metadata, ProvideRuntimeApi};
use self::error::{Error, FutureResult};
@@ -46,9 +41,9 @@ pub use sc_rpc_api::state::*;
/// State backend API.
pub trait StateBackend<B, E, Block: BlockT, RA>: Send + Sync + 'static
where
Block: BlockT<Hash=H256> + 'static,
B: sc_client_api::backend::Backend<Block, Blake2Hasher> + Send + Sync + 'static,
E: sc_client::CallExecutor<Block, Blake2Hasher> + Send + Sync + 'static,
Block: BlockT + 'static,
B: sc_client_api::backend::Backend<Block> + Send + Sync + 'static,
E: sc_client::CallExecutor<Block> + Send + Sync + 'static,
RA: Send + Sync + 'static,
{
/// Call runtime method at given block.
@@ -186,12 +181,12 @@ pub fn new_full<B, E, Block: BlockT, RA>(
subscriptions: Subscriptions,
) -> State<B, E, Block, RA>
where
Block: BlockT<Hash=H256> + 'static,
B: sc_client_api::backend::Backend<Block, Blake2Hasher> + Send + Sync + 'static,
E: CallExecutor<Block, Blake2Hasher> + Send + Sync + 'static + Clone,
Block: BlockT + 'static,
B: sc_client_api::backend::Backend<Block> + Send + Sync + 'static,
E: CallExecutor<Block> + Send + Sync + 'static + Clone,
RA: Send + Sync + 'static,
Client<B, E, Block, RA>: ProvideRuntimeApi,
<Client<B, E, Block, RA> as ProvideRuntimeApi>::Api:
Client<B, E, Block, RA>: ProvideRuntimeApi<Block>,
<Client<B, E, Block, RA> as ProvideRuntimeApi<Block>>::Api:
Metadata<Block, Error = sp_blockchain::Error>,
{
State {
@@ -207,9 +202,9 @@ pub fn new_light<B, E, Block: BlockT, RA, F: Fetcher<Block>>(
fetcher: Arc<F>,
) -> State<B, E, Block, RA>
where
Block: BlockT<Hash=H256> + 'static,
B: sc_client_api::backend::Backend<Block, Blake2Hasher> + Send + Sync + 'static,
E: CallExecutor<Block, Blake2Hasher> + Send + Sync + 'static + Clone,
Block: BlockT + 'static,
B: sc_client_api::backend::Backend<Block> + Send + Sync + 'static,
E: CallExecutor<Block> + Send + Sync + 'static + Clone,
RA: Send + Sync + 'static,
F: Send + Sync + 'static,
{
@@ -230,9 +225,9 @@ pub struct State<B, E, Block, RA> {
impl<B, E, Block, RA> StateApi<Block::Hash> for State<B, E, Block, RA>
where
Block: BlockT<Hash=H256> + 'static,
B: sc_client_api::backend::Backend<Block, Blake2Hasher> + Send + Sync + 'static,
E: CallExecutor<Block, Blake2Hasher> + Send + Sync + 'static + Clone,
Block: BlockT + 'static,
B: sc_client_api::backend::Backend<Block> + Send + Sync + 'static,
E: CallExecutor<Block> + Send + Sync + 'static + Clone,
RA: Send + Sync + 'static,
{
type Metadata = crate::metadata::Metadata;
+12 -17
View File
@@ -22,10 +22,7 @@ use std::ops::Range;
use futures::{future, StreamExt as _, TryStreamExt as _};
use log::warn;
use jsonrpc_pubsub::{typed::Subscriber, SubscriptionId};
use rpc::{
Result as RpcResult,
futures::{stream, Future, Sink, Stream, future::result},
};
use rpc::{Result as RpcResult, futures::{stream, Future, Sink, Stream, future::result}};
use sc_rpc_api::Subscriptions;
use sc_client_api::backend::Backend;
@@ -36,17 +33,15 @@ use sc_client::{
Client, CallExecutor, BlockchainEvents,
};
use sp_core::{
H256, Blake2Hasher, Bytes,
storage::{well_known_keys, StorageKey, StorageData, StorageChangeSet, ChildInfo},
Bytes, storage::{well_known_keys, StorageKey, StorageData, StorageChangeSet, ChildInfo},
};
use sp_version::RuntimeVersion;
use sp_state_machine::ExecutionStrategy;
use sp_runtime::{
generic::BlockId,
traits::{Block as BlockT, NumberFor, ProvideRuntimeApi, SaturatedConversion},
generic::BlockId, traits::{Block as BlockT, NumberFor, SaturatedConversion},
};
use sp_api::Metadata;
use sp_api::{Metadata, ProvideRuntimeApi};
use super::{StateBackend, error::{FutureResult, Error, Result}, client_err, child_resolution_error};
@@ -72,9 +67,9 @@ pub struct FullState<B, E, Block: BlockT, RA> {
impl<B, E, Block: BlockT, RA> FullState<B, E, Block, RA>
where
Block: BlockT<Hash=H256> + 'static,
B: Backend<Block, Blake2Hasher> + Send + Sync + 'static,
E: CallExecutor<Block, Blake2Hasher> + Send + Sync + 'static + Clone,
Block: BlockT + 'static,
B: Backend<Block> + Send + Sync + 'static,
E: CallExecutor<Block> + Send + Sync + 'static + Clone,
{
/// Create new state API backend for full nodes.
pub fn new(client: Arc<Client<B, E, Block, RA>>, subscriptions: Subscriptions) -> Self {
@@ -220,12 +215,12 @@ 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
Block: BlockT<Hash=H256> + 'static,
B: Backend<Block, Blake2Hasher> + Send + Sync + 'static,
E: CallExecutor<Block, Blake2Hasher> + Send + Sync + 'static + Clone,
Block: BlockT + 'static,
B: Backend<Block> + Send + Sync + 'static,
E: CallExecutor<Block> + Send + Sync + 'static + Clone,
RA: Send + Sync + 'static,
Client<B, E, Block, RA>: ProvideRuntimeApi,
<Client<B, E, Block, RA> as ProvideRuntimeApi>::Api:
Client<B, E, Block, RA>: ProvideRuntimeApi<Block>,
<Client<B, E, Block, RA> as ProvideRuntimeApi<Block>>::Api:
Metadata<Block, Error = sp_blockchain::Error>,
{
fn call(
+12 -15
View File
@@ -49,14 +49,10 @@ use sc_client::{
},
};
use sp_core::{
H256, Blake2Hasher, Bytes, OpaqueMetadata,
storage::{StorageKey, StorageData, StorageChangeSet},
Bytes, OpaqueMetadata, storage::{StorageKey, StorageData, StorageChangeSet},
};
use sp_version::RuntimeVersion;
use sp_runtime::{
generic::BlockId,
traits::Block as BlockT,
};
use sp_runtime::{generic::BlockId, traits::{Block as BlockT, HasherFor}};
use super::{StateBackend, error::{FutureResult, Error}, client_err};
@@ -140,9 +136,9 @@ 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>
where
Block: BlockT<Hash=H256>,
B: Backend<Block, Blake2Hasher> + Send + Sync + 'static,
E: CallExecutor<Block, Blake2Hasher> + Send + Sync + 'static + Clone,
Block: BlockT,
B: Backend<Block> + Send + Sync + 'static,
E: CallExecutor<Block> + Send + Sync + 'static + Clone,
RA: Send + Sync + 'static,
{
/// Create new state API backend for light nodes.
@@ -174,9 +170,9 @@ impl<Block: BlockT, F: Fetcher<Block> + 'static, B, E, RA> LightState<Block, F,
impl<Block, F, B, E, RA> StateBackend<B, E, Block, RA> for LightState<Block, F, B, E, RA>
where
Block: BlockT<Hash=H256>,
B: Backend<Block, Blake2Hasher> + Send + Sync + 'static,
E: CallExecutor<Block, Blake2Hasher> + Send + Sync + 'static + Clone,
Block: BlockT,
B: Backend<Block> + Send + Sync + 'static,
E: CallExecutor<Block> + Send + Sync + 'static + Clone,
RA: Send + Sync + 'static,
F: Fetcher<Block> + 'static
{
@@ -227,7 +223,7 @@ impl<Block, F, B, E, RA> StateBackend<B, E, Block, RA> for LightState<Block, F,
Box::new(self
.storage(block, key)
.and_then(|maybe_storage|
result(Ok(maybe_storage.map(|storage| Blake2Hasher::hash(&storage.0))))
result(Ok(maybe_storage.map(|storage| HasherFor::<Block>::hash(&storage.0))))
)
)
}
@@ -288,7 +284,7 @@ impl<Block, F, B, E, RA> StateBackend<B, E, Block, RA> for LightState<Block, F,
Box::new(self
.child_storage(block, child_storage_key, child_info, child_type, key)
.and_then(|maybe_storage|
result(Ok(maybe_storage.map(|storage| Blake2Hasher::hash(&storage.0))))
result(Ok(maybe_storage.map(|storage| HasherFor::<Block>::hash(&storage.0))))
)
)
}
@@ -602,7 +598,7 @@ fn subscription_stream<
issue_request: IssueRequest,
compare_values: CompareValues,
) -> impl Stream<Item=N, Error=()> where
Block: BlockT<Hash=H256>,
Block: BlockT,
Requests: 'static + SharedRequests<Block::Hash, V>,
FutureBlocksStream: Stream<Item=Block::Hash, Error=()>,
V: Send + 'static + Clone,
@@ -712,6 +708,7 @@ fn ignore_error<F, T>(future: F) -> impl std::future::Future<Output=Result<Optio
mod tests {
use rpc::futures::stream::futures_ordered;
use substrate_test_runtime_client::runtime::Block;
use sp_core::H256;
use super::*;
#[test]
+9 -7
View File
@@ -143,7 +143,7 @@ fn should_notify_about_storage_changes() {
let (subscriber, id, transport) = Subscriber::new_test("test");
{
let client = Arc::new(substrate_test_runtime_client::new());
let mut client = Arc::new(substrate_test_runtime_client::new());
let api = new_full(client.clone(), Subscriptions::new(Arc::new(remote)));
api.subscribe_storage(Default::default(), subscriber, None.into());
@@ -158,7 +158,8 @@ fn should_notify_about_storage_changes() {
amount: 42,
nonce: 0,
}).unwrap();
client.import(BlockOrigin::Own, builder.bake().unwrap()).unwrap();
let block = builder.build().unwrap().block;
client.import(BlockOrigin::Own, block).unwrap();
}
// assert notification sent to transport
@@ -175,7 +176,7 @@ fn should_send_initial_storage_changes_and_notifications() {
let (subscriber, id, transport) = Subscriber::new_test("test");
{
let client = Arc::new(substrate_test_runtime_client::new());
let mut client = Arc::new(substrate_test_runtime_client::new());
let api = new_full(client.clone(), Subscriptions::new(Arc::new(remote)));
let alice_balance_key = blake2_256(&runtime::system::balance_of_key(AccountKeyring::Alice.into()));
@@ -194,7 +195,8 @@ fn should_send_initial_storage_changes_and_notifications() {
amount: 42,
nonce: 0,
}).unwrap();
client.import(BlockOrigin::Own, builder.bake().unwrap()).unwrap();
let block = builder.build().unwrap().block;
client.import(BlockOrigin::Own, block).unwrap();
}
// assert initial values sent to transport
@@ -209,11 +211,11 @@ fn should_send_initial_storage_changes_and_notifications() {
#[test]
fn should_query_storage() {
fn run_tests(client: Arc<TestClient>) {
fn run_tests(mut client: Arc<TestClient>) {
let core = tokio::runtime::Runtime::new().unwrap();
let api = new_full(client.clone(), Subscriptions::new(Arc::new(core.executor())));
let add_block = |nonce| {
let mut add_block = |nonce| {
let mut builder = client.new_block(Default::default()).unwrap();
// fake change: None -> None -> None
builder.push_storage_change(vec![1], None).unwrap();
@@ -225,7 +227,7 @@ fn should_query_storage() {
builder.push_storage_change(vec![4], if nonce == 0 { None } else { Some(vec![4]) }).unwrap();
// actual change: Some(value1) -> Some(value2)
builder.push_storage_change(vec![5], Some(vec![nonce as u8])).unwrap();
let block = builder.bake().unwrap();
let block = builder.build().unwrap().block;
let hash = block.header.hash();
client.import(BlockOrigin::Own, block).unwrap();
hash
+25 -21
View File
@@ -38,13 +38,11 @@ use log::{info, warn, error};
use sc_network::{FinalityProofProvider, OnDemand, NetworkService, NetworkStateInfo};
use sc_network::{config::BoxFinalityProofRequestBuilder, specialization::NetworkSpecialization};
use parking_lot::{Mutex, RwLock};
use sp_core::{Blake2Hasher, H256, Hasher};
use sc_rpc;
use sp_api::ConstructRuntimeApi;
use sp_runtime::generic::BlockId;
use sp_runtime::traits::{
Block as BlockT, ProvideRuntimeApi, NumberFor, SaturatedConversion,
Block as BlockT, NumberFor, SaturatedConversion, HasherFor,
};
use sp_api::ProvideRuntimeApi;
use sc_executor::{NativeExecutor, NativeExecutionDispatch};
use std::{
io::{Read, Write, Seek},
@@ -121,19 +119,19 @@ pub type TLightClient<TBl, TRtApi, TExecDisp> = Client<
/// Light client backend type.
pub type TLightBackend<TBl> = sc_client::light::backend::Backend<
sc_client_db::light::LightStorage<TBl>,
Blake2Hasher,
HasherFor<TBl>,
>;
/// Light call executor type.
pub type TLightCallExecutor<TBl, TExecDisp> = sc_client::light::call_executor::GenesisCallExecutor<
sc_client::light::backend::Backend<
sc_client_db::light::LightStorage<TBl>,
Blake2Hasher
HasherFor<TBl>
>,
sc_client::LocalCallExecutor<
sc_client::light::backend::Backend<
sc_client_db::light::LightStorage<TBl>,
Blake2Hasher
HasherFor<TBl>
>,
NativeExecutor<TExecDisp>
>,
@@ -149,7 +147,7 @@ type TFullParts<TBl, TRtApi, TExecDisp> = (
pub fn new_full_client<TBl, TRtApi, TExecDisp, TCfg, TGen, TCSExt>(
config: &Configuration<TCfg, TGen, TCSExt>,
) -> Result<TFullClient<TBl, TRtApi, TExecDisp>, Error> where
TBl: BlockT<Hash=H256>,
TBl: BlockT,
TExecDisp: NativeExecutionDispatch,
TGen: sp_runtime::BuildStorage + serde::Serialize + for<'de> serde::Deserialize<'de>,
TCSExt: Extension,
@@ -160,7 +158,7 @@ pub fn new_full_client<TBl, TRtApi, TExecDisp, TCfg, TGen, TCSExt>(
fn new_full_parts<TBl, TRtApi, TExecDisp, TCfg, TGen, TCSExt>(
config: &Configuration<TCfg, TGen, TCSExt>,
) -> Result<TFullParts<TBl, TRtApi, TExecDisp>, Error> where
TBl: BlockT<Hash=H256>,
TBl: BlockT,
TExecDisp: NativeExecutionDispatch,
TGen: sp_runtime::BuildStorage + serde::Serialize + for<'de> serde::Deserialize<'de>,
TCSExt: Extension,
@@ -228,7 +226,7 @@ fn new_full_parts<TBl, TRtApi, TExecDisp, TCfg, TGen, TCSExt>(
impl<TCfg, TGen, TCSExt> ServiceBuilder<(), (), TCfg, TGen, TCSExt, (), (), (), (), (), (), (), (), (), ()>
where TGen: RuntimeGenesis, TCSExt: Extension {
/// Start the service builder with a configuration.
pub fn new_full<TBl: BlockT<Hash=H256>, TRtApi, TExecDisp: NativeExecutionDispatch>(
pub fn new_full<TBl: BlockT, TRtApi, TExecDisp: NativeExecutionDispatch>(
config: Configuration<TCfg, TGen, TCSExt>
) -> Result<ServiceBuilder<
TBl,
@@ -270,7 +268,7 @@ where TGen: RuntimeGenesis, TCSExt: Extension {
}
/// Start the service builder with a configuration.
pub fn new_light<TBl: BlockT<Hash=H256>, TRtApi, TExecDisp: NativeExecutionDispatch + 'static>(
pub fn new_light<TBl: BlockT, TRtApi, TExecDisp: NativeExecutionDispatch + 'static>(
config: Configuration<TCfg, TGen, TCSExt>
) -> Result<ServiceBuilder<
TBl,
@@ -321,7 +319,12 @@ where TGen: RuntimeGenesis, TCSExt: Extension {
sc_client_db::light::LightStorage::new(db_settings)?
};
let light_blockchain = sc_client::light::new_light_blockchain(db_storage);
let fetch_checker = Arc::new(sc_client::light::new_fetch_checker(light_blockchain.clone(), executor.clone()));
let fetch_checker = Arc::new(
sc_client::light::new_fetch_checker::<_, TBl, _>(
light_blockchain.clone(),
executor.clone(),
),
);
let fetcher = Arc::new(sc_network::OnDemand::new(fetch_checker));
let backend = sc_client::light::new_light_backend(light_blockchain);
let remote_blockchain = backend.remote_blockchain();
@@ -718,20 +721,21 @@ ServiceBuilder<
TRpc,
TBackend,
> where
Client<TBackend, TExec, TBl, TRtApi>: ProvideRuntimeApi,
<Client<TBackend, TExec, TBl, TRtApi> as ProvideRuntimeApi>::Api:
Client<TBackend, TExec, TBl, TRtApi>: ProvideRuntimeApi<TBl>,
<Client<TBackend, TExec, TBl, TRtApi> as ProvideRuntimeApi<TBl>>::Api:
sp_api::Metadata<TBl> +
sc_offchain::OffchainWorkerApi<TBl> +
sp_transaction_pool::runtime_api::TaggedTransactionQueue<TBl> +
sp_session::SessionKeys<TBl> +
sp_api::ApiExt<TBl, Error = sp_blockchain::Error>,
TBl: BlockT<Hash = <Blake2Hasher as Hasher>::Out>,
TRtApi: ConstructRuntimeApi<TBl, Client<TBackend, TExec, TBl, TRtApi>> + 'static + Send + Sync,
sp_api::ApiErrorExt<Error = sp_blockchain::Error> +
sp_api::ApiExt<TBl, StateBackend = TBackend::State>,
TBl: BlockT,
TRtApi: 'static + Send + Sync,
TCfg: Default,
TGen: RuntimeGenesis,
TCSExt: Extension,
TBackend: 'static + sc_client_api::backend::Backend<TBl, Blake2Hasher> + Send,
TExec: 'static + sc_client::CallExecutor<TBl, Blake2Hasher> + Send + Sync + Clone,
TBackend: 'static + sc_client_api::backend::Backend<TBl> + Send,
TExec: 'static + sc_client::CallExecutor<TBl> + Send + Sync + Clone,
TSc: Clone,
TImpQu: 'static + ImportQueue<TBl>,
TNetP: NetworkSpecialization<TBl>,
@@ -850,7 +854,7 @@ ServiceBuilder<
Some(Arc::new(sc_offchain::OffchainWorkers::new(client.clone(), db)))
},
(true, None) => {
log::warn!("Offchain workers disabled, due to lack of offchain storage support in backend.");
warn!("Offchain workers disabled, due to lack of offchain storage support in backend.");
None
},
_ => None,
@@ -1124,7 +1128,7 @@ ServiceBuilder<
}).compat();
let _ = to_spawn_tx.unbounded_send(Box::new(future));
}
}
// Instrumentation
if let Some(tracing_targets) = config.tracing_targets.as_ref() {
+3 -5
View File
@@ -25,7 +25,6 @@ use futures::{future, prelude::*};
use futures03::{
TryFutureExt as _,
};
use sp_core::{Blake2Hasher, Hasher};
use sp_runtime::traits::{
Block as BlockT, NumberFor, One, Zero, Header, SaturatedConversion
};
@@ -57,9 +56,9 @@ impl<
TBl, TRtApi, TCfg, TGen, TCSExt, Client<TBackend, TExec, TBl, TRtApi>,
TFchr, TSc, TImpQu, TFprb, TFpp, TNetP, TExPool, TRpc, Backend
> where
TBl: BlockT<Hash = <Blake2Hasher as Hasher>::Out>,
TBackend: 'static + sc_client_api::backend::Backend<TBl, Blake2Hasher> + Send,
TExec: 'static + sc_client::CallExecutor<TBl, Blake2Hasher> + Send + Sync + Clone,
TBl: BlockT,
TBackend: 'static + sc_client_api::backend::Backend<TBl> + Send,
TExec: 'static + sc_client::CallExecutor<TBl> + Send + Sync + Clone,
TImpQu: 'static + ImportQueue<TBl>,
TRtApi: 'static + Send + Sync,
{
@@ -310,4 +309,3 @@ impl<
}
}
}
+12 -10
View File
@@ -48,7 +48,6 @@ use sc_network::{
};
use log::{log, warn, debug, error, Level};
use codec::{Encode, Decode};
use sp_core::{Blake2Hasher, H256};
use sp_runtime::generic::BlockId;
use sp_runtime::traits::{NumberFor, Block as BlockT};
@@ -147,11 +146,11 @@ impl futures03::task::Spawn for SpawnTaskHandle {
pub trait AbstractService: 'static + Future<Item = (), Error = Error> +
Executor<Box<dyn Future<Item = (), Error = ()> + Send>> + Send {
/// Type of block of this chain.
type Block: BlockT<Hash = H256>;
type Block: BlockT;
/// Backend storage for the client.
type Backend: 'static + sc_client_api::backend::Backend<Self::Block, Blake2Hasher>;
type Backend: 'static + sc_client_api::backend::Backend<Self::Block>;
/// How to execute calls towards the runtime.
type CallExecutor: 'static + sc_client::CallExecutor<Self::Block, Blake2Hasher> + Send + Sync + Clone;
type CallExecutor: 'static + sc_client::CallExecutor<Self::Block> + Send + Sync + Clone;
/// API that the runtime provides.
type RuntimeApi: Send + Sync;
/// Chain selection algorithm.
@@ -200,7 +199,8 @@ pub trait AbstractService: 'static + Future<Item = (), Error = Error> +
fn select_chain(&self) -> Option<Self::SelectChain>;
/// Get shared network instance.
fn network(&self) -> Arc<NetworkService<Self::Block, Self::NetworkSpecialization, H256>>;
fn network(&self)
-> Arc<NetworkService<Self::Block, Self::NetworkSpecialization, <Self::Block as BlockT>::Hash>>;
/// Returns a receiver that periodically receives a status of the network.
fn network_status(&self, interval: Duration) -> mpsc::UnboundedReceiver<(NetworkStatus<Self::Block>, NetworkState)>;
@@ -214,11 +214,11 @@ pub trait AbstractService: 'static + Future<Item = (), Error = Error> +
impl<TBl, TBackend, TExec, TRtApi, TSc, TNetSpec, TExPool, TOc> AbstractService for
Service<TBl, Client<TBackend, TExec, TBl, TRtApi>, TSc, NetworkStatus<TBl>,
NetworkService<TBl, TNetSpec, H256>, TExPool, TOc>
NetworkService<TBl, TNetSpec, TBl::Hash>, TExPool, TOc>
where
TBl: BlockT<Hash = H256>,
TBackend: 'static + sc_client_api::backend::Backend<TBl, Blake2Hasher>,
TExec: 'static + sc_client::CallExecutor<TBl, Blake2Hasher> + Send + Sync + Clone,
TBl: BlockT,
TBackend: 'static + sc_client_api::backend::Backend<TBl>,
TExec: 'static + sc_client::CallExecutor<TBl> + Send + Sync + Clone,
TRtApi: 'static + Send + Sync,
TSc: sp_consensus::SelectChain<TBl> + 'static + Clone + Send,
TExPool: 'static + TransactionPool<Block = TBl>
@@ -288,7 +288,9 @@ where
self.select_chain.clone()
}
fn network(&self) -> Arc<NetworkService<Self::Block, Self::NetworkSpecialization, H256>> {
fn network(&self)
-> Arc<NetworkService<Self::Block, Self::NetworkSpecialization, <Self::Block as BlockT>::Hash>>
{
self.network.clone()
}
+29 -76
View File
@@ -17,20 +17,16 @@
use std::{sync::Arc, panic::UnwindSafe, result, cell::RefCell};
use codec::{Encode, Decode};
use sp_runtime::{
generic::BlockId, traits::Block as BlockT, traits::NumberFor,
generic::BlockId, traits::{Block as BlockT, HasherFor},
};
use sp_state_machine::{
self, OverlayedChanges, Ext, ExecutionManager, StateMachine, ExecutionStrategy,
backend::Backend as _, ChangesTrieTransaction, StorageProof,
backend::Backend as _, StorageProof,
};
use sc_executor::{RuntimeVersion, RuntimeInfo, NativeVersion};
use sp_externalities::Extensions;
use hash_db::Hasher;
use sp_core::{
H256, Blake2Hasher, NativeOrEncoded, NeverNativeValue,
traits::CodeExecutor,
};
use sp_api::{ProofRecorder, InitializeBlock};
use sp_core::{NativeOrEncoded, NeverNativeValue, traits::CodeExecutor};
use sp_api::{ProofRecorder, InitializeBlock, StorageTransactionCache};
use sc_client_api::{backend, call_executor::CallExecutor};
/// Call executor that executes methods locally, querying all required
@@ -62,14 +58,16 @@ impl<B, E> Clone for LocalCallExecutor<B, E> where E: Clone {
}
}
impl<B, E, Block> CallExecutor<Block, Blake2Hasher> for LocalCallExecutor<B, E>
where
B: backend::Backend<Block, Blake2Hasher>,
E: CodeExecutor + RuntimeInfo,
Block: BlockT<Hash=H256>,
impl<B, E, Block> CallExecutor<Block> for LocalCallExecutor<B, E>
where
B: backend::Backend<Block>,
E: CodeExecutor + RuntimeInfo,
Block: BlockT,
{
type Error = E::Error;
type Backend = B;
fn call(
&self,
id: &BlockId<Block>,
@@ -90,10 +88,8 @@ impl<B, E, Block> CallExecutor<Block, Blake2Hasher> for LocalCallExecutor<B, E>
extensions.unwrap_or_default(),
).execute_using_consensus_failure_handler::<_, NeverNativeValue, fn() -> _>(
strategy.get_manager(),
false,
None,
)
.map(|(result, _, _)| result)?;
)?;
{
let _lock = self.backend.get_import_lock().read();
self.backend.destroy_state(state)?;
@@ -117,6 +113,9 @@ impl<B, E, Block> CallExecutor<Block, Blake2Hasher> for LocalCallExecutor<B, E>
method: &str,
call_data: &[u8],
changes: &RefCell<OverlayedChanges>,
storage_transaction_cache: Option<&RefCell<
StorageTransactionCache<Block, B::State>
>>,
initialize_block: InitializeBlock<'a, Block>,
execution_manager: ExecutionManager<EM>,
native_call: Option<NC>,
@@ -134,6 +133,8 @@ impl<B, E, Block> CallExecutor<Block, Blake2Hasher> for LocalCallExecutor<B, E>
let mut state = self.backend.state_at(*at)?;
let mut storage_transaction_cache = storage_transaction_cache.map(|c| c.borrow_mut());
let result = match recorder {
Some(recorder) => {
let trie_state = state.as_trie_backend()
@@ -144,7 +145,7 @@ impl<B, E, Block> CallExecutor<Block, Blake2Hasher> for LocalCallExecutor<B, E>
let backend = sp_state_machine::ProvingBackend::new_with_recorder(
trie_state,
recorder.clone()
recorder.clone(),
);
StateMachine::new(
@@ -156,13 +157,9 @@ impl<B, E, Block> CallExecutor<Block, Blake2Hasher> for LocalCallExecutor<B, E>
call_data,
extensions.unwrap_or_default(),
)
.execute_using_consensus_failure_handler(
execution_manager,
false,
native_call,
)
.map(|(result, _, _)| result)
.map_err(Into::into)
// TODO: https://github.com/paritytech/substrate/issues/4455
// .with_storage_transaction_cache(storage_transaction_cache.as_mut().map(|c| &mut **c))
.execute_using_consensus_failure_handler(execution_manager, native_call)
}
None => StateMachine::new(
&state,
@@ -173,12 +170,8 @@ impl<B, E, Block> CallExecutor<Block, Blake2Hasher> for LocalCallExecutor<B, E>
call_data,
extensions.unwrap_or_default(),
)
.execute_using_consensus_failure_handler(
execution_manager,
false,
native_call,
)
.map(|(result, _, _)| result)
.with_storage_transaction_cache(storage_transaction_cache.as_mut().map(|c| &mut **c))
.execute_using_consensus_failure_handler(execution_manager, native_call)
}?;
{
let _lock = self.backend.get_import_lock().read();
@@ -190,9 +183,11 @@ impl<B, E, Block> CallExecutor<Block, Blake2Hasher> for LocalCallExecutor<B, E>
fn runtime_version(&self, id: &BlockId<Block>) -> sp_blockchain::Result<RuntimeVersion> {
let mut overlay = OverlayedChanges::default();
let state = self.backend.state_at(*id)?;
let mut cache = StorageTransactionCache::<Block, B::State>::default();
let mut ext = Ext::new(
&mut overlay,
&mut cache,
&state,
self.backend.changes_trie_storage(),
None,
@@ -205,51 +200,9 @@ impl<B, E, Block> CallExecutor<Block, Blake2Hasher> for LocalCallExecutor<B, E>
version.map_err(|e| sp_blockchain::Error::VersionInvalid(format!("{:?}", e)).into())
}
fn call_at_state<
S: sp_state_machine::Backend<Blake2Hasher>,
F: FnOnce(
Result<NativeOrEncoded<R>, Self::Error>,
Result<NativeOrEncoded<R>, Self::Error>,
) -> Result<NativeOrEncoded<R>, Self::Error>,
R: Encode + Decode + PartialEq,
NC: FnOnce() -> result::Result<R, String> + UnwindSafe,
>(&self,
state: &S,
changes: &mut OverlayedChanges,
method: &str,
call_data: &[u8],
manager: ExecutionManager<F>,
native_call: Option<NC>,
extensions: Option<Extensions>,
) -> sp_blockchain::Result<(
NativeOrEncoded<R>,
(S::Transaction, <Blake2Hasher as Hasher>::Out),
Option<ChangesTrieTransaction<Blake2Hasher, NumberFor<Block>>>,
)> {
StateMachine::new(
state,
self.backend.changes_trie_storage(),
changes,
&self.executor,
method,
call_data,
extensions.unwrap_or_default(),
).execute_using_consensus_failure_handler(
manager,
true,
native_call,
)
.map(|(result, storage_tx, changes_tx)| (
result,
storage_tx.expect("storage_tx is always computed when compute_tx is true; qed"),
changes_tx,
))
.map_err(Into::into)
}
fn prove_at_trie_state<S: sp_state_machine::TrieBackendStorage<Blake2Hasher>>(
fn prove_at_trie_state<S: sp_state_machine::TrieBackendStorage<HasherFor<Block>>>(
&self,
trie_state: &sp_state_machine::TrieBackend<S, Blake2Hasher>,
trie_state: &sp_state_machine::TrieBackend<S, HasherFor<Block>>,
overlay: &mut OverlayedChanges,
method: &str,
call_data: &[u8]
@@ -271,9 +224,9 @@ impl<B, E, Block> CallExecutor<Block, Blake2Hasher> for LocalCallExecutor<B, E>
impl<B, E, Block> sp_version::GetRuntimeVersion<Block> for LocalCallExecutor<B, E>
where
B: backend::Backend<Block, Blake2Hasher>,
B: backend::Backend<Block>,
E: CodeExecutor + RuntimeInfo,
Block: BlockT<Hash=H256>,
Block: BlockT,
{
fn native_version(&self) -> &sp_version::NativeVersion {
self.executor.native_version()
+6 -5
View File
@@ -29,9 +29,10 @@ use sp_trie;
use sp_core::{H256, convert_hash};
use sp_runtime::traits::{Header as HeaderT, SimpleArithmetic, Zero, One};
use sp_state_machine::backend::InMemory as InMemoryState;
use sp_state_machine::{MemoryDB, TrieBackend, Backend as StateBackend, StorageProof,
prove_read_on_trie_backend, read_proof_check, read_proof_check_on_proving_backend};
use sp_state_machine::{
MemoryDB, TrieBackend, Backend as StateBackend, StorageProof, InMemoryBackend,
prove_read_on_trie_backend, read_proof_check, read_proof_check_on_proving_backend
};
use sp_blockchain::{Error as ClientError, Result as ClientResult};
@@ -113,7 +114,7 @@ pub fn build_proof<Header, Hasher, BlocksI, HashesI>(
.into_iter()
.map(|(k, v)| (k, Some(v)))
.collect::<Vec<_>>();
let mut storage = InMemoryState::<Hasher>::default().update(vec![(None, transaction)]);
let mut storage = InMemoryBackend::<Hasher>::default().update(vec![(None, transaction)]);
let trie_storage = storage.as_trie_backend()
.expect("InMemoryState::as_trie_backend always returns Some; qed");
prove_read_on_trie_backend(
@@ -330,7 +331,7 @@ pub fn decode_cht_value(value: &[u8]) -> Option<H256> {
#[cfg(test)]
mod tests {
use sp_core::{Blake2Hasher};
use sp_core::Blake2Hasher;
use substrate_test_runtime_client::runtime::Header;
use super::*;
File diff suppressed because it is too large Load Diff
+9 -8
View File
@@ -46,8 +46,8 @@ mod tests {
use sc_executor::native_executor_instance;
use sp_state_machine::{
StateMachine, OverlayedChanges, ExecutionStrategy, InMemoryChangesTrieStorage,
InMemoryBackend,
};
use sp_state_machine::backend::InMemory;
use substrate_test_runtime_client::{
runtime::genesismap::{GenesisConfig, insert_genesis_block},
runtime::{Hash, Transfer, Block, BlockNumber, Header, Digest},
@@ -67,7 +67,7 @@ mod tests {
}
fn construct_block(
backend: &InMemory<Blake2Hasher>,
backend: &InMemoryBackend<Blake2Hasher>,
number: BlockNumber,
parent_hash: Hash,
state_root: Hash,
@@ -116,7 +116,7 @@ mod tests {
).unwrap();
}
let (ret_data, _, _) = StateMachine::new(
let ret_data = StateMachine::new(
backend,
Some(&InMemoryChangesTrieStorage::<_, u64>::new()),
&mut overlay,
@@ -132,7 +132,7 @@ mod tests {
(vec![].and(&Block { header, extrinsics: transactions }), hash)
}
fn block1(genesis_hash: Hash, backend: &InMemory<Blake2Hasher>) -> (Vec<u8>, Hash) {
fn block1(genesis_hash: Hash, backend: &InMemoryBackend<Blake2Hasher>) -> (Vec<u8>, Hash) {
construct_block(
backend,
1,
@@ -149,7 +149,8 @@ mod tests {
#[test]
fn construct_genesis_should_work_with_native() {
let mut storage = GenesisConfig::new(false,
let mut storage = GenesisConfig::new(
false,
vec![Sr25519Keyring::One.public().into(), Sr25519Keyring::Two.public().into()],
vec![AccountKeyring::One.into(), AccountKeyring::Two.into()],
1000,
@@ -158,7 +159,7 @@ mod tests {
).genesis_map();
let genesis_hash = insert_genesis_block(&mut storage);
let backend = InMemory::from(storage);
let backend = InMemoryBackend::from(storage);
let (b1data, _b1hash) = block1(genesis_hash, &backend);
let mut overlay = OverlayedChanges::default();
@@ -186,7 +187,7 @@ mod tests {
).genesis_map();
let genesis_hash = insert_genesis_block(&mut storage);
let backend = InMemory::from(storage);
let backend = InMemoryBackend::from(storage);
let (b1data, _b1hash) = block1(genesis_hash, &backend);
let mut overlay = OverlayedChanges::default();
@@ -214,7 +215,7 @@ mod tests {
).genesis_map();
let genesis_hash = insert_genesis_block(&mut storage);
let backend = InMemory::from(storage);
let backend = InMemoryBackend::from(storage);
let (b1data, _b1hash) = block1(genesis_hash, &backend);
let mut overlay = OverlayedChanges::default();
+73 -84
View File
@@ -24,11 +24,13 @@ use sp_core::offchain::storage::{
InMemOffchainStorage as OffchainStorage
};
use sp_runtime::generic::{BlockId, DigestItem};
use sp_runtime::traits::{Block as BlockT, Header as HeaderT, Zero, NumberFor};
use sp_runtime::traits::{Block as BlockT, Header as HeaderT, Zero, NumberFor, HasherFor};
use sp_runtime::{Justification, Storage};
use sp_state_machine::backend::{Backend as StateBackend, InMemory};
use sp_state_machine::{self, InMemoryChangesTrieStorage, ChangesTrieAnchorBlockId, ChangesTrieTransaction};
use hash_db::{Hasher, Prefix};
use sp_state_machine::{
InMemoryChangesTrieStorage, ChangesTrieAnchorBlockId, ChangesTrieTransaction,
InMemoryBackend, Backend as StateBackend,
};
use hash_db::Prefix;
use sp_trie::MemoryDB;
use sp_blockchain::{CachedHeaderMetadata, HeaderMetadata};
@@ -459,25 +461,21 @@ impl<Block: BlockT> sc_client_api::light::Storage<Block> for Blockchain<Block>
}
/// In-memory operation.
pub struct BlockImportOperation<Block: BlockT, H: Hasher> {
pub struct BlockImportOperation<Block: BlockT> {
pending_block: Option<PendingBlock<Block>>,
pending_cache: HashMap<CacheKeyId, Vec<u8>>,
old_state: InMemory<H>,
new_state: Option<InMemory<H>>,
changes_trie_update: Option<MemoryDB<H>>,
old_state: InMemoryBackend<HasherFor<Block>>,
new_state: Option<InMemoryBackend<HasherFor<Block>>>,
changes_trie_update: Option<MemoryDB<HasherFor<Block>>>,
aux: Vec<(Vec<u8>, Option<Vec<u8>>)>,
finalized_blocks: Vec<(BlockId<Block>, Option<Justification>)>,
set_head: Option<BlockId<Block>>,
}
impl<Block, H> backend::BlockImportOperation<Block, H> for BlockImportOperation<Block, H>
where
Block: BlockT,
H: Hasher<Out=Block::Hash>,
H::Out: Ord,
impl<Block: BlockT> backend::BlockImportOperation<Block> for BlockImportOperation<Block> where
Block::Hash: Ord,
{
type State = InMemory<H>;
type State = InMemoryBackend<HasherFor<Block>>;
fn state(&self) -> sp_blockchain::Result<Option<&Self::State>> {
Ok(Some(&self.old_state))
@@ -502,17 +500,23 @@ where
self.pending_cache = cache;
}
fn update_db_storage(&mut self, update: <InMemory<H> as StateBackend<H>>::Transaction) -> sp_blockchain::Result<()> {
fn update_db_storage(
&mut self,
update: <InMemoryBackend<HasherFor<Block>> as StateBackend<HasherFor<Block>>>::Transaction,
) -> sp_blockchain::Result<()> {
self.new_state = Some(self.old_state.update(update));
Ok(())
}
fn update_changes_trie(&mut self, update: ChangesTrieTransaction<H, NumberFor<Block>>) -> sp_blockchain::Result<()> {
fn update_changes_trie(
&mut self,
update: ChangesTrieTransaction<HasherFor<Block>, NumberFor<Block>>,
) -> sp_blockchain::Result<()> {
self.changes_trie_update = Some(update.0);
Ok(())
}
fn reset_storage(&mut self, storage: Storage) -> sp_blockchain::Result<H::Out> {
fn reset_storage(&mut self, storage: Storage) -> sp_blockchain::Result<Block::Hash> {
check_genesis_storage(&storage)?;
let child_delta = storage.children.into_iter()
@@ -524,7 +528,7 @@ where
child_delta
);
self.new_state = Some(InMemory::from(transaction));
self.new_state = Some(InMemoryBackend::from(transaction));
Ok(root)
}
@@ -543,7 +547,11 @@ where
Ok(())
}
fn mark_finalized(&mut self, block: BlockId<Block>, justification: Option<Justification>) -> sp_blockchain::Result<()> {
fn mark_finalized(
&mut self,
block: BlockId<Block>,
justification: Option<Justification>,
) -> sp_blockchain::Result<()> {
self.finalized_blocks.push((block, justification));
Ok(())
}
@@ -559,26 +567,16 @@ where
///
/// > **Warning**: Doesn't support all the features necessary for a proper database. Only use this
/// > struct for testing purposes. Do **NOT** use in production.
pub struct Backend<Block, H>
where
Block: BlockT,
H: Hasher<Out=Block::Hash>,
H::Out: Ord,
{
states: RwLock<HashMap<Block::Hash, InMemory<H>>>,
changes_trie_storage: ChangesTrieStorage<Block, H>,
pub struct Backend<Block: BlockT> where Block::Hash: Ord {
states: RwLock<HashMap<Block::Hash, InMemoryBackend<HasherFor<Block>>>>,
changes_trie_storage: ChangesTrieStorage<Block>,
blockchain: Blockchain<Block>,
import_lock: RwLock<()>,
}
impl<Block, H> Backend<Block, H>
where
Block: BlockT,
H: Hasher<Out=Block::Hash>,
H::Out: Ord,
{
impl<Block: BlockT> Backend<Block> where Block::Hash: Ord {
/// Create a new instance of in-mem backend.
pub fn new() -> Backend<Block, H> {
pub fn new() -> Self {
Backend {
states: RwLock::new(HashMap::new()),
changes_trie_storage: ChangesTrieStorage(InMemoryChangesTrieStorage::new()),
@@ -588,12 +586,7 @@ where
}
}
impl<Block, H> backend::AuxStore for Backend<Block, H>
where
Block: BlockT,
H: Hasher<Out=Block::Hash>,
H::Out: Ord,
{
impl<Block: BlockT> backend::AuxStore for Backend<Block> where Block::Hash: Ord {
fn insert_aux<
'a,
'b: 'a,
@@ -609,16 +602,11 @@ where
}
}
impl<Block, H> backend::Backend<Block, H> for Backend<Block, H>
where
Block: BlockT,
H: Hasher<Out=Block::Hash>,
H::Out: Ord,
{
type BlockImportOperation = BlockImportOperation<Block, H>;
impl<Block: BlockT> backend::Backend<Block> for Backend<Block> where Block::Hash: Ord {
type BlockImportOperation = BlockImportOperation<Block>;
type Blockchain = Blockchain<Block>;
type State = InMemory<H>;
type ChangesTrieStorage = ChangesTrieStorage<Block, H>;
type State = InMemoryBackend<HasherFor<Block>>;
type ChangesTrieStorage = ChangesTrieStorage<Block>;
type OffchainStorage = OffchainStorage;
fn begin_operation(&self) -> sp_blockchain::Result<Self::BlockImportOperation> {
@@ -635,7 +623,11 @@ where
})
}
fn begin_state_operation(&self, operation: &mut Self::BlockImportOperation, block: BlockId<Block>) -> sp_blockchain::Result<()> {
fn begin_state_operation(
&self,
operation: &mut Self::BlockImportOperation,
block: BlockId<Block>,
) -> sp_blockchain::Result<()> {
operation.old_state = self.state_at(block)?;
Ok(())
}
@@ -680,7 +672,11 @@ where
Ok(())
}
fn finalize_block(&self, block: BlockId<Block>, justification: Option<Justification>) -> sp_blockchain::Result<()> {
fn finalize_block(
&self,
block: BlockId<Block>,
justification: Option<Justification>,
) -> sp_blockchain::Result<()> {
self.blockchain.finalize_header(block, justification)
}
@@ -727,19 +723,9 @@ where
}
}
impl<Block, H> backend::LocalBackend<Block, H> for Backend<Block, H>
where
Block: BlockT,
H: Hasher<Out=Block::Hash>,
H::Out: Ord,
{}
impl<Block: BlockT> backend::LocalBackend<Block> for Backend<Block> where Block::Hash: Ord {}
impl<Block, H> backend::RemoteBackend<Block, H> for Backend<Block, H>
where
Block: BlockT,
H: Hasher<Out=Block::Hash>,
H::Out: Ord,
{
impl<Block: BlockT> backend::RemoteBackend<Block> for Backend<Block> where Block::Hash: Ord {
fn is_local_state_available(&self, block: &BlockId<Block>) -> bool {
self.blockchain.expect_block_number_from_id(block)
.map(|num| num.is_zero())
@@ -752,8 +738,11 @@ where
}
/// Prunable in-memory changes trie storage.
pub struct ChangesTrieStorage<Block: BlockT, H: Hasher>(InMemoryChangesTrieStorage<H, NumberFor<Block>>);
impl<Block: BlockT, H: Hasher> backend::PrunableStateChangesTrieStorage<Block, H> for ChangesTrieStorage<Block, H> {
pub struct ChangesTrieStorage<Block: BlockT>(
InMemoryChangesTrieStorage<HasherFor<Block>, NumberFor<Block>>
);
impl<Block: BlockT> backend::PrunableStateChangesTrieStorage<Block> for ChangesTrieStorage<Block> {
fn oldest_changes_trie_block(
&self,
_config: &ChangesTrieConfiguration,
@@ -763,45 +752,47 @@ impl<Block: BlockT, H: Hasher> backend::PrunableStateChangesTrieStorage<Block, H
}
}
impl<Block, H> sp_state_machine::ChangesTrieRootsStorage<H, NumberFor<Block>> for ChangesTrieStorage<Block, H>
where
Block: BlockT,
H: Hasher,
impl<Block: BlockT> sp_state_machine::ChangesTrieRootsStorage<HasherFor<Block>, NumberFor<Block>> for
ChangesTrieStorage<Block>
{
fn build_anchor(
&self,
_hash: H::Out,
) -> Result<sp_state_machine::ChangesTrieAnchorBlockId<H::Out, NumberFor<Block>>, String> {
_hash: Block::Hash,
) -> Result<sp_state_machine::ChangesTrieAnchorBlockId<Block::Hash, NumberFor<Block>>, String> {
Err("Dummy implementation".into())
}
fn root(
&self,
_anchor: &ChangesTrieAnchorBlockId<H::Out, NumberFor<Block>>,
_anchor: &ChangesTrieAnchorBlockId<Block::Hash, NumberFor<Block>>,
_block: NumberFor<Block>,
) -> Result<Option<H::Out>, String> {
) -> Result<Option<Block::Hash>, String> {
Err("Dummy implementation".into())
}
}
impl<Block, H> sp_state_machine::ChangesTrieStorage<H, NumberFor<Block>> for ChangesTrieStorage<Block, H>
where
Block: BlockT,
H: Hasher,
impl<Block: BlockT> sp_state_machine::ChangesTrieStorage<HasherFor<Block>, NumberFor<Block>> for
ChangesTrieStorage<Block>
{
fn as_roots_storage(&self) -> &dyn sp_state_machine::ChangesTrieRootsStorage<H, NumberFor<Block>> {
fn as_roots_storage(&self)
-> &dyn sp_state_machine::ChangesTrieRootsStorage<HasherFor<Block>, NumberFor<Block>>
{
self
}
fn with_cached_changed_keys(
&self,
_root: &H::Out,
_root: &Block::Hash,
_functor: &mut dyn FnMut(&HashMap<Option<Vec<u8>>, HashSet<Vec<u8>>>),
) -> bool {
false
}
fn get(&self, key: &H::Out, prefix: Prefix) -> Result<Option<sp_state_machine::DBValue>, String> {
fn get(
&self,
key: &Block::Hash,
prefix: Prefix,
) -> Result<Option<sp_state_machine::DBValue>, String> {
self.0.get(key, prefix)
}
}
@@ -823,10 +814,8 @@ pub fn check_genesis_storage(storage: &Storage) -> sp_blockchain::Result<()> {
mod tests {
use sp_core::offchain::{OffchainStorage, storage::InMemOffchainStorage};
use std::sync::Arc;
use substrate_test_runtime_client;
use sp_core::Blake2Hasher;
type TestBackend = substrate_test_runtime_client::sc_client::in_mem::Backend<substrate_test_runtime_client::runtime::Block, Blake2Hasher>;
type TestBackend = substrate_test_runtime_client::sc_client::in_mem::Backend<substrate_test_runtime_client::runtime::Block>;
#[test]
fn test_leaves_with_complex_block_tree() {
+1 -1
View File
@@ -57,7 +57,7 @@
//! // from your runtime.
//! use substrate_test_runtime_client::{LocalExecutor, runtime::Block, runtime::RuntimeApi};
//!
//! let backend = Arc::new(Backend::<Block, Blake2Hasher>::new());
//! let backend = Arc::new(Backend::<Block>::new());
//! let client = Client::<_, _, _, RuntimeApi>::new(
//! backend.clone(),
//! LocalCallExecutor::new(
+50 -42
View File
@@ -24,12 +24,12 @@ use parking_lot::RwLock;
use sp_core::storage::{ChildInfo, OwnedChildInfo};
use sp_core::offchain::storage::InMemOffchainStorage;
use sp_state_machine::{
Backend as StateBackend, TrieBackend, backend::InMemory as InMemoryState, ChangesTrieTransaction
Backend as StateBackend, TrieBackend, InMemoryBackend, ChangesTrieTransaction
};
use sp_runtime::{generic::BlockId, Justification, Storage};
use sp_runtime::traits::{Block as BlockT, NumberFor, Zero, Header};
use sp_runtime::traits::{Block as BlockT, NumberFor, Zero, Header, HasherFor};
use crate::in_mem::{self, check_genesis_storage};
use sp_blockchain::{ Error as ClientError, Result as ClientResult };
use sp_blockchain::{Error as ClientError, Result as ClientResult};
use sc_client_api::{
backend::{
AuxStore, Backend as ClientBackend, BlockImportOperation, RemoteBackend, NewBlockState,
@@ -43,33 +43,32 @@ use sc_client_api::{
};
use crate::light::blockchain::Blockchain;
use hash_db::Hasher;
use sp_trie::MemoryDB;
const IN_MEMORY_EXPECT_PROOF: &str = "InMemory state backend has Void error type and always succeeds; qed";
/// Light client backend.
pub struct Backend<S, H: Hasher> {
blockchain: Arc<Blockchain<S>>,
genesis_state: RwLock<Option<InMemoryState<H>>>,
genesis_state: RwLock<Option<InMemoryBackend<H>>>,
import_lock: RwLock<()>,
}
/// Light block (header and justification) import operation.
pub struct ImportOperation<Block: BlockT, S, H: Hasher> {
pub struct ImportOperation<Block: BlockT, S> {
header: Option<Block::Header>,
cache: HashMap<well_known_cache_keys::Id, Vec<u8>>,
leaf_state: NewBlockState,
aux_ops: Vec<(Vec<u8>, Option<Vec<u8>>)>,
finalized_blocks: Vec<BlockId<Block>>,
set_head: Option<BlockId<Block>>,
storage_update: Option<InMemoryState<H>>,
_phantom: ::std::marker::PhantomData<S>,
storage_update: Option<InMemoryBackend<HasherFor<Block>>>,
_phantom: std::marker::PhantomData<S>,
}
/// Either in-memory genesis state, or locally-unavailable state.
pub enum GenesisOrUnavailableState<H: Hasher> {
/// Genesis state - storage values are stored in-memory.
Genesis(InMemoryState<H>),
Genesis(InMemoryBackend<H>),
/// We know that state exists, but all calls will fail with error, because it
/// isn't locally available.
Unavailable,
@@ -107,16 +106,16 @@ impl<S: AuxStore, H: Hasher> AuxStore for Backend<S, H> {
}
}
impl<S, Block, H> ClientBackend<Block, H> for Backend<S, H> where
Block: BlockT,
S: BlockchainStorage<Block>,
H: Hasher<Out=Block::Hash>,
H::Out: Ord,
impl<S, Block> ClientBackend<Block> for Backend<S, HasherFor<Block>>
where
Block: BlockT,
S: BlockchainStorage<Block>,
Block::Hash: Ord,
{
type BlockImportOperation = ImportOperation<Block, S, H>;
type BlockImportOperation = ImportOperation<Block, S>;
type Blockchain = Blockchain<S>;
type State = GenesisOrUnavailableState<H>;
type ChangesTrieStorage = in_mem::ChangesTrieStorage<Block, H>;
type State = GenesisOrUnavailableState<HasherFor<Block>>;
type ChangesTrieStorage = in_mem::ChangesTrieStorage<Block>;
type OffchainStorage = InMemOffchainStorage;
fn begin_operation(&self) -> ClientResult<Self::BlockImportOperation> {
@@ -179,7 +178,11 @@ impl<S, Block, H> ClientBackend<Block, H> for Backend<S, H> where
Ok(())
}
fn finalize_block(&self, block: BlockId<Block>, _justification: Option<Justification>) -> ClientResult<()> {
fn finalize_block(
&self,
block: BlockId<Block>,
_justification: Option<Justification>,
) -> ClientResult<()> {
self.blockchain.storage().finalize_header(block)
}
@@ -227,12 +230,11 @@ impl<S, Block, H> ClientBackend<Block, H> for Backend<S, H> where
}
}
impl<S, Block, H> RemoteBackend<Block, H> for Backend<S, H>
impl<S, Block> RemoteBackend<Block> for Backend<S, HasherFor<Block>>
where
Block: BlockT,
S: BlockchainStorage<Block> + 'static,
H: Hasher<Out=Block::Hash>,
H::Out: Ord,
Block::Hash: Ord,
{
fn is_local_state_available(&self, block: &BlockId<Block>) -> bool {
self.genesis_state.read().is_some()
@@ -246,14 +248,13 @@ where
}
}
impl<S, Block, H> BlockImportOperation<Block, H> for ImportOperation<Block, S, H>
where
Block: BlockT,
S: BlockchainStorage<Block>,
H: Hasher<Out=Block::Hash>,
H::Out: Ord,
impl<S, Block> BlockImportOperation<Block> for ImportOperation<Block, S>
where
Block: BlockT,
S: BlockchainStorage<Block>,
Block::Hash: Ord,
{
type State = GenesisOrUnavailableState<H>;
type State = GenesisOrUnavailableState<HasherFor<Block>>;
fn state(&self) -> ClientResult<Option<&Self::State>> {
// None means 'locally-stateless' backend
@@ -276,17 +277,23 @@ where
self.cache = cache;
}
fn update_db_storage(&mut self, _update: <Self::State as StateBackend<H>>::Transaction) -> ClientResult<()> {
fn update_db_storage(
&mut self,
_update: <Self::State as StateBackend<HasherFor<Block>>>::Transaction,
) -> ClientResult<()> {
// we're not storing anything locally => ignore changes
Ok(())
}
fn update_changes_trie(&mut self, _update: ChangesTrieTransaction<H, NumberFor<Block>>) -> ClientResult<()> {
fn update_changes_trie(
&mut self,
_update: ChangesTrieTransaction<HasherFor<Block>, NumberFor<Block>>,
) -> ClientResult<()> {
// we're not storing anything locally => ignore changes
Ok(())
}
fn reset_storage(&mut self, input: Storage) -> ClientResult<H::Out> {
fn reset_storage(&mut self, input: Storage) -> ClientResult<Block::Hash> {
check_genesis_storage(&input)?;
// this is only called when genesis block is imported => shouldn't be performance bottleneck
@@ -303,8 +310,8 @@ where
storage.insert(Some((child_key, storage_child.child_info)), storage_child.data);
}
let storage_update: InMemoryState<H> = storage.into();
let (storage_root, _) = storage_update.full_storage_root(::std::iter::empty(), child_delta);
let storage_update = InMemoryBackend::from(storage);
let (storage_root, _) = storage_update.full_storage_root(std::iter::empty(), child_delta);
self.storage_update = Some(storage_update);
Ok(storage_root)
@@ -351,8 +358,8 @@ impl<H: Hasher> StateBackend<H> for GenesisOrUnavailableState<H>
H::Out: Ord + codec::Codec,
{
type Error = ClientError;
type Transaction = ();
type TrieBackendStorage = MemoryDB<H>;
type Transaction = <InMemoryBackend<H> as StateBackend<H>>::Transaction;
type TrieBackendStorage = <InMemoryBackend<H> as StateBackend<H>>::TrieBackendStorage;
fn storage(&self, key: &[u8]) -> ClientResult<Option<Vec<u8>>> {
match *self {
@@ -445,8 +452,8 @@ impl<H: Hasher> StateBackend<H> for GenesisOrUnavailableState<H>
{
match *self {
GenesisOrUnavailableState::Genesis(ref state) =>
(state.storage_root(delta).0, ()),
GenesisOrUnavailableState::Unavailable => (H::Out::default(), ()),
state.storage_root(delta),
GenesisOrUnavailableState::Unavailable => Default::default(),
}
}
@@ -462,9 +469,10 @@ impl<H: Hasher> StateBackend<H> for GenesisOrUnavailableState<H>
match *self {
GenesisOrUnavailableState::Genesis(ref state) => {
let (root, is_equal, _) = state.child_storage_root(storage_key, child_info, delta);
(root, is_equal, ())
(root, is_equal, Default::default())
},
GenesisOrUnavailableState::Unavailable => (H::Out::default(), true, ()),
GenesisOrUnavailableState::Unavailable =>
(H::Out::default(), true, Default::default()),
}
}
@@ -528,9 +536,9 @@ mod tests {
#[test]
fn light_aux_store_is_updated_via_non_importing_op() {
let backend = Backend::new(Arc::new(DummyBlockchain::new(DummyStorage::new())));
let mut op = ClientBackend::<Block, Blake2Hasher>::begin_operation(&backend).unwrap();
BlockImportOperation::<Block, Blake2Hasher>::insert_aux(&mut op, vec![(vec![1], Some(vec![2]))]).unwrap();
ClientBackend::<Block, Blake2Hasher>::commit_operation(&backend, op).unwrap();
let mut op = ClientBackend::<Block>::begin_operation(&backend).unwrap();
BlockImportOperation::<Block>::insert_aux(&mut op, vec![(vec![1], Some(vec![2]))]).unwrap();
ClientBackend::<Block>::commit_operation(&backend, op).unwrap();
assert_eq!(AuxStore::get_aux(&backend, &[1]).unwrap(), Some(vec![2]));
}
+50 -80
View File
@@ -21,22 +21,19 @@ use std::{
};
use codec::{Encode, Decode};
use sp_core::{
H256, Blake2Hasher, convert_hash, NativeOrEncoded,
traits::CodeExecutor,
};
use sp_core::{convert_hash, NativeOrEncoded, traits::CodeExecutor};
use sp_runtime::{
generic::BlockId, traits::{One, Block as BlockT, Header as HeaderT, NumberFor},
generic::BlockId, traits::{One, Block as BlockT, Header as HeaderT, HasherFor},
};
use sp_externalities::Extensions;
use sp_state_machine::{
self, Backend as StateBackend, OverlayedChanges, ExecutionStrategy, create_proof_check_backend,
execution_proof_check_on_trie_backend, ExecutionManager, ChangesTrieTransaction, StorageProof,
execution_proof_check_on_trie_backend, ExecutionManager, StorageProof,
merge_storage_proofs,
};
use hash_db::Hasher;
use sp_api::{ProofRecorder, InitializeBlock};
use sp_api::{ProofRecorder, InitializeBlock, StorageTransactionCache};
use sp_blockchain::{Error as ClientError, Result as ClientResult};
@@ -71,15 +68,17 @@ impl<B, L: Clone> Clone for GenesisCallExecutor<B, L> {
}
}
impl<Block, B, Local> CallExecutor<Block, Blake2Hasher> for
impl<Block, B, Local> CallExecutor<Block> for
GenesisCallExecutor<B, Local>
where
Block: BlockT<Hash=H256>,
B: RemoteBackend<Block, Blake2Hasher>,
Local: CallExecutor<Block, Blake2Hasher>,
Block: BlockT,
B: RemoteBackend<Block>,
Local: CallExecutor<Block>,
{
type Error = ClientError;
type Backend = B;
fn call(
&self,
id: &BlockId<Block>,
@@ -110,6 +109,7 @@ impl<Block, B, Local> CallExecutor<Block, Blake2Hasher> for
method: &str,
call_data: &[u8],
changes: &RefCell<OverlayedChanges>,
_: Option<&RefCell<StorageTransactionCache<Block, B::State>>>,
initialize_block: InitializeBlock<'a, Block>,
_manager: ExecutionManager<EM>,
native_call: Option<NC>,
@@ -135,6 +135,7 @@ impl<Block, B, Local> CallExecutor<Block, Blake2Hasher> for
method,
call_data,
changes,
None,
initialize_block,
ExecutionManager::NativeWhenPossible,
native_call,
@@ -152,36 +153,12 @@ impl<Block, B, Local> CallExecutor<Block, Blake2Hasher> for
}
}
fn call_at_state<
S: StateBackend<Blake2Hasher>,
FF: FnOnce(
Result<NativeOrEncoded<R>, Self::Error>,
Result<NativeOrEncoded<R>, Self::Error>
) -> Result<NativeOrEncoded<R>, Self::Error>,
R: Encode + Decode + PartialEq,
NC: FnOnce() -> result::Result<R, String> + UnwindSafe,
>(&self,
_state: &S,
fn prove_at_trie_state<S: sp_state_machine::TrieBackendStorage<HasherFor<Block>>>(
&self,
_state: &sp_state_machine::TrieBackend<S, HasherFor<Block>>,
_changes: &mut OverlayedChanges,
_method: &str,
_call_data: &[u8],
_manager: ExecutionManager<FF>,
_native_call: Option<NC>,
_extensions: Option<Extensions>,
) -> ClientResult<(
NativeOrEncoded<R>,
(S::Transaction, <Blake2Hasher as Hasher>::Out),
Option<ChangesTrieTransaction<Blake2Hasher, NumberFor<Block>>>,
)> {
Err(ClientError::NotAvailableOnLightClient)
}
fn prove_at_trie_state<S: sp_state_machine::TrieBackendStorage<Blake2Hasher>>(
&self,
_state: &sp_state_machine::TrieBackend<S, Blake2Hasher>,
_changes: &mut OverlayedChanges,
_method: &str,
_call_data: &[u8]
) -> ClientResult<(Vec<u8>, StorageProof)> {
Err(ClientError::NotAvailableOnLightClient)
}
@@ -203,12 +180,15 @@ pub fn prove_execution<Block, S, E>(
call_data: &[u8],
) -> ClientResult<(Vec<u8>, StorageProof)>
where
Block: BlockT<Hash=H256>,
S: StateBackend<Blake2Hasher>,
E: CallExecutor<Block, Blake2Hasher>,
Block: BlockT,
S: StateBackend<HasherFor<Block>>,
E: CallExecutor<Block>,
{
let trie_state = state.as_trie_backend()
.ok_or_else(|| Box::new(sp_state_machine::ExecutionError::UnableToGenerateProof) as Box<dyn sp_state_machine::Error>)?;
.ok_or_else(||
Box::new(sp_state_machine::ExecutionError::UnableToGenerateProof) as
Box<dyn sp_state_machine::Error>
)?;
// prepare execution environment + record preparation proof
let mut changes = Default::default();
@@ -220,7 +200,12 @@ pub fn prove_execution<Block, S, E>(
)?;
// execute method + record execution proof
let (result, exec_proof) = executor.prove_at_trie_state(&trie_state, &mut changes, method, call_data)?;
let (result, exec_proof) = executor.prove_at_trie_state(
&trie_state,
&mut changes,
method,
call_data,
)?;
let total_proof = merge_storage_proofs(vec![init_proof, exec_proof]);
Ok((result, total_proof))
@@ -238,7 +223,8 @@ pub fn check_execution_proof<Header, E, H>(
where
Header: HeaderT,
E: CodeExecutor,
H: Hasher<Out=H256>,
H: Hasher,
H::Out: Ord + codec::Codec + 'static,
{
check_execution_proof_with_make_header::<Header, E, H, _>(
executor,
@@ -263,7 +249,8 @@ fn check_execution_proof_with_make_header<Header, E, H, MakeNextHeader: Fn(&Head
where
Header: HeaderT,
E: CodeExecutor,
H: Hasher<Out=H256>,
H: Hasher,
H::Out: Ord + codec::Codec + 'static,
{
let local_state_root = request.header.state_root();
let root: H::Out = convert_hash(&local_state_root);
@@ -294,17 +281,21 @@ fn check_execution_proof_with_make_header<Header, E, H, MakeNextHeader: Fn(&Head
mod tests {
use super::*;
use sp_consensus::BlockOrigin;
use substrate_test_runtime_client::{self, runtime::{Header, Digest, Block}, ClientExt, TestClient};
use substrate_test_runtime_client::{
runtime::{Header, Digest, Block}, TestClient, ClientBlockImportExt,
};
use sc_executor::{NativeExecutor, WasmExecutionMethod};
use sp_core::Blake2Hasher;
use sp_core::{Blake2Hasher, H256};
use sc_client_api::backend::{Backend, NewBlockState};
use crate::in_mem::Backend as InMemBackend;
struct DummyCallExecutor;
impl CallExecutor<Block, Blake2Hasher> for DummyCallExecutor {
impl CallExecutor<Block> for DummyCallExecutor {
type Error = ClientError;
type Backend = substrate_test_runtime_client::Backend;
fn call(
&self,
_id: &BlockId<Block>,
@@ -332,6 +323,12 @@ mod tests {
_method: &str,
_call_data: &[u8],
_changes: &RefCell<OverlayedChanges>,
_storage_transaction_cache: Option<&RefCell<
StorageTransactionCache<
Block,
<Self::Backend as sc_client_api::backend::Backend<Block>>::State,
>
>>,
_initialize_block: InitializeBlock<'a, Block>,
_execution_manager: ExecutionManager<EM>,
_native_call: Option<NC>,
@@ -345,36 +342,9 @@ mod tests {
unreachable!()
}
fn call_at_state<
S: sp_state_machine::Backend<Blake2Hasher>,
F: FnOnce(
Result<NativeOrEncoded<R>, Self::Error>,
Result<NativeOrEncoded<R>, Self::Error>
) -> Result<NativeOrEncoded<R>, Self::Error>,
R: Encode + Decode + PartialEq,
NC: FnOnce() -> result::Result<R, String> + UnwindSafe,
>(&self,
_state: &S,
_overlay: &mut OverlayedChanges,
_method: &str,
_call_data: &[u8],
_manager: ExecutionManager<F>,
_native_call: Option<NC>,
_extensions: Option<Extensions>,
) -> Result<
(
NativeOrEncoded<R>,
(S::Transaction, H256),
Option<ChangesTrieTransaction<Blake2Hasher, NumberFor<Block>>>,
),
ClientError,
> {
unreachable!()
}
fn prove_at_trie_state<S: sp_state_machine::TrieBackendStorage<Blake2Hasher>>(
fn prove_at_trie_state<S: sp_state_machine::TrieBackendStorage<HasherFor<Block>>>(
&self,
_trie_state: &sp_state_machine::TrieBackend<S, Blake2Hasher>,
_trie_state: &sp_state_machine::TrieBackend<S, HasherFor<Block>>,
_overlay: &mut OverlayedChanges,
_method: &str,
_call_data: &[u8]
@@ -457,13 +427,13 @@ mod tests {
}
// prepare remote client
let remote_client = substrate_test_runtime_client::new();
let mut remote_client = substrate_test_runtime_client::new();
for i in 1u32..3u32 {
let mut digest = Digest::default();
digest.push(sp_runtime::generic::DigestItem::Other::<H256>(i.to_le_bytes().to_vec()));
remote_client.import_justified(
BlockOrigin::Own,
remote_client.new_block(digest).unwrap().bake().unwrap(),
remote_client.new_block(digest).unwrap().build().unwrap().block,
Default::default(),
).unwrap();
}
@@ -494,7 +464,7 @@ mod tests {
#[test]
fn code_is_executed_at_genesis_only() {
let backend = Arc::new(InMemBackend::<Block, Blake2Hasher>::new());
let backend = Arc::new(InMemBackend::<Block>::new());
let def = H256::default();
let header0 = substrate_test_runtime_client::runtime::Header::new(0, def, def, def, Default::default());
let hash0 = header0.hash();
+13 -10
View File
@@ -22,7 +22,7 @@ use std::marker::PhantomData;
use hash_db::{HashDB, Hasher, EMPTY_PREFIX};
use codec::{Decode, Encode};
use sp_core::{convert_hash, traits::CodeExecutor, H256};
use sp_core::{convert_hash, traits::CodeExecutor};
use sp_runtime::traits::{
Block as BlockT, Header as HeaderT, Hash, HashFor, NumberFor,
SimpleArithmetic, CheckedConversion, Zero,
@@ -198,7 +198,8 @@ impl<E, Block, H, S> FetchChecker<Block> for LightDataChecker<E, H, Block, S>
where
Block: BlockT,
E: CodeExecutor,
H: Hasher<Out=H256>,
H: Hasher,
H::Out: Ord + codec::Codec + 'static,
S: BlockchainStorage<Block>,
{
fn check_header_proof(
@@ -214,8 +215,8 @@ impl<E, Block, H, S> FetchChecker<Block> for LightDataChecker<E, H, Block, S>
request.cht_root,
request.block,
remote_header_hash,
remote_proof)
.map(|_| remote_header)
remote_proof,
).map(|_| remote_header)
}
fn check_read_proof(
@@ -331,7 +332,7 @@ pub mod tests {
use sp_blockchain::Error as ClientError;
use sc_client_api::backend::NewBlockState;
use substrate_test_runtime_client::{
self, ClientExt, blockchain::HeaderBackend, AccountKeyring,
blockchain::HeaderBackend, AccountKeyring, ClientBlockImportExt,
runtime::{self, Hash, Block, Header, Extrinsic}
};
use sp_consensus::BlockOrigin;
@@ -442,13 +443,15 @@ pub mod tests {
fn prepare_for_header_proof_check(insert_cht: bool) -> (TestChecker, Hash, Header, StorageProof) {
// prepare remote client
let remote_client = substrate_test_runtime_client::new();
let mut remote_client = substrate_test_runtime_client::new();
let mut local_headers_hashes = Vec::new();
for i in 0..4 {
let builder = remote_client.new_block(Default::default()).unwrap();
remote_client.import(BlockOrigin::Own, builder.bake().unwrap()).unwrap();
local_headers_hashes.push(remote_client.block_hash(i + 1)
.map_err(|_| ClientError::Backend("TestError".into())));
let block = remote_client.new_block(Default::default()).unwrap().build().unwrap().block;
remote_client.import(BlockOrigin::Own, block).unwrap();
local_headers_hashes.push(
remote_client.block_hash(i + 1)
.map_err(|_| ClientError::Backend("TestError".into()))
);
}
// 'fetch' header proof from remote node
+17 -10
View File
@@ -24,9 +24,9 @@ pub mod fetcher;
use std::sync::Arc;
use sc_executor::RuntimeInfo;
use sp_core::{H256, Blake2Hasher, traits::CodeExecutor};
use sp_core::traits::CodeExecutor;
use sp_runtime::BuildStorage;
use sp_runtime::traits::Block as BlockT;
use sp_runtime::traits::{Block as BlockT, HasherFor};
use sp_blockchain::Result as ClientResult;
use crate::call_executor::LocalCallExecutor;
@@ -45,7 +45,7 @@ pub fn new_light_blockchain<B: BlockT, S: BlockchainStorage<B>>(storage: S) -> A
}
/// Create an instance of light client backend.
pub fn new_light_backend<B, S>(blockchain: Arc<Blockchain<S>>) -> Arc<Backend<S, Blake2Hasher>>
pub fn new_light_backend<B, S>(blockchain: Arc<Blockchain<S>>) -> Arc<Backend<S, HasherFor<B>>>
where
B: BlockT,
S: BlockchainStorage<B>,
@@ -55,15 +55,22 @@ pub fn new_light_backend<B, S>(blockchain: Arc<Blockchain<S>>) -> Arc<Backend<S,
/// Create an instance of light client.
pub fn new_light<B, S, GS, RA, E>(
backend: Arc<Backend<S, Blake2Hasher>>,
backend: Arc<Backend<S, HasherFor<B>>>,
genesis_storage: GS,
code_executor: E,
) -> ClientResult<Client<Backend<S, Blake2Hasher>, GenesisCallExecutor<
Backend<S, Blake2Hasher>,
LocalCallExecutor<Backend<S, Blake2Hasher>, E>
>, B, RA>>
) -> ClientResult<
Client<
Backend<S, HasherFor<B>>,
GenesisCallExecutor<
Backend<S, HasherFor<B>>,
LocalCallExecutor<Backend<S, HasherFor<B>>, E>
>,
B,
RA
>
>
where
B: BlockT<Hash=H256>,
B: BlockT,
S: BlockchainStorage<B> + 'static,
GS: BuildStorage,
E: CodeExecutor + RuntimeInfo,
@@ -84,7 +91,7 @@ pub fn new_light<B, S, GS, RA, E>(
pub fn new_fetch_checker<E, B: BlockT, S: BlockchainStorage<B>>(
blockchain: Arc<Blockchain<S>>,
executor: E,
) -> LightDataChecker<E, Blake2Hasher, B, S>
) -> LightDataChecker<E, HasherFor<B>, B, S>
where
E: CodeExecutor,
{
+15 -12
View File
@@ -18,19 +18,21 @@
use std::{marker::PhantomData, pin::Pin, sync::Arc};
use codec::{Decode, Encode};
use futures::{channel::oneshot, executor::{ThreadPool, ThreadPoolBuilder}, future::{Future, FutureExt, ready}};
use futures::{
channel::oneshot, executor::{ThreadPool, ThreadPoolBuilder}, future::{Future, FutureExt, ready},
};
use sc_client_api::{
blockchain::HeaderBackend,
light::{Fetcher, RemoteCallRequest}
};
use sp_core::{H256, Blake2Hasher, Hasher};
use sp_core::Hasher;
use sp_runtime::{
generic::BlockId,
traits::{Block as BlockT, BlockIdTo, ProvideRuntimeApi},
generic::BlockId, traits::{self, Block as BlockT, BlockIdTo, Header as HeaderT, Hash as HashT},
transaction_validity::TransactionValidity,
};
use sp_transaction_pool::runtime_api::TaggedTransactionQueue;
use sp_api::ProvideRuntimeApi;
use crate::error::{self, Error};
@@ -43,7 +45,8 @@ pub struct FullChainApi<Client, Block> {
impl<Client, Block> FullChainApi<Client, Block> where
Block: BlockT,
Client: ProvideRuntimeApi + BlockIdTo<Block> {
Client: ProvideRuntimeApi<Block> + BlockIdTo<Block>,
{
/// Create new transaction pool logic.
pub fn new(client: Arc<Client>) -> Self {
FullChainApi {
@@ -59,13 +62,13 @@ impl<Client, Block> FullChainApi<Client, Block> where
}
impl<Client, Block> sc_transaction_graph::ChainApi for FullChainApi<Client, Block> where
Block: BlockT<Hash = H256>,
Client: ProvideRuntimeApi + BlockIdTo<Block> + 'static + Send + Sync,
Block: BlockT,
Client: ProvideRuntimeApi<Block> + BlockIdTo<Block> + 'static + Send + Sync,
Client::Api: TaggedTransactionQueue<Block>,
sp_api::ApiErrorFor<Client, Block>: Send,
{
type Block = Block;
type Hash = H256;
type Hash = Block::Hash;
type Error = error::Error;
type ValidationFuture = Pin<Box<dyn Future<Output = error::Result<TransactionValidity>> + Send>>;
@@ -110,7 +113,7 @@ impl<Client, Block> sc_transaction_graph::ChainApi for FullChainApi<Client, Bloc
fn hash_and_length(&self, ex: &sc_transaction_graph::ExtrinsicFor<Self>) -> (Self::Hash, usize) {
ex.using_encoded(|x| {
(Blake2Hasher::hash(x), x.len())
(traits::HasherFor::<Block>::hash(x), x.len())
})
}
}
@@ -138,12 +141,12 @@ impl<Client, F, Block> LightChainApi<Client, F, Block> where
}
impl<Client, F, Block> sc_transaction_graph::ChainApi for LightChainApi<Client, F, Block> where
Block: BlockT<Hash=H256>,
Block: BlockT,
Client: HeaderBackend<Block> + 'static,
F: Fetcher<Block> + 'static,
{
type Block = Block;
type Hash = H256;
type Hash = Block::Hash;
type Error = error::Error;
type ValidationFuture = Box<dyn Future<Output = error::Result<TransactionValidity>> + Send + Unpin>;
@@ -191,7 +194,7 @@ impl<Client, F, Block> sc_transaction_graph::ChainApi for LightChainApi<Client,
fn hash_and_length(&self, ex: &sc_transaction_graph::ExtrinsicFor<Self>) -> (Self::Hash, usize) {
ex.using_encoded(|x| {
(Blake2Hasher::hash(x), x.len())
(<<Block::Header as HeaderT>::Hashing as HashT>::hash(x), x.len())
})
}
}
@@ -30,14 +30,13 @@ use sc_client_api::{
client::BlockBody,
light::{Fetcher, RemoteBodyRequest},
};
use sp_core::{Blake2Hasher, H256};
use sp_runtime::{
generic::BlockId,
traits::{Block as BlockT, Extrinsic, Header, NumberFor, ProvideRuntimeApi, SimpleArithmetic},
traits::{Block as BlockT, Extrinsic, Header, NumberFor, SimpleArithmetic},
};
use sp_blockchain::HeaderBackend;
use sp_transaction_pool::TransactionPoolMaintainer;
use sp_transaction_pool::runtime_api::TaggedTransactionQueue;
use sp_transaction_pool::{TransactionPoolMaintainer, runtime_api::TaggedTransactionQueue};
use sp_api::ProvideRuntimeApi;
use sc_transaction_graph::{self, ChainApi};
@@ -61,10 +60,10 @@ impl<Block, Client, PoolApi> TransactionPoolMaintainer
for
FullBasicPoolMaintainer<Client, PoolApi>
where
Block: BlockT<Hash = <Blake2Hasher as sp_core::Hasher>::Out>,
Client: ProvideRuntimeApi + HeaderBackend<Block> + BlockBody<Block> + 'static,
Block: BlockT,
Client: ProvideRuntimeApi<Block> + HeaderBackend<Block> + BlockBody<Block> + 'static,
Client::Api: TaggedTransactionQueue<Block>,
PoolApi: ChainApi<Block = Block, Hash = H256> + 'static,
PoolApi: ChainApi<Block = Block, Hash = Block::Hash> + 'static,
{
type Block = Block;
type Hash = Block::Hash;
@@ -154,10 +153,10 @@ pub struct LightBasicPoolMaintainer<Block: BlockT, Client, PoolApi: ChainApi, F>
impl<Block, Client, PoolApi, F> LightBasicPoolMaintainer<Block, Client, PoolApi, F>
where
Block: BlockT<Hash = <Blake2Hasher as sp_core::Hasher>::Out>,
Client: ProvideRuntimeApi + HeaderBackend<Block> + BlockBody<Block> + 'static,
Block: BlockT,
Client: ProvideRuntimeApi<Block> + HeaderBackend<Block> + BlockBody<Block> + 'static,
Client::Api: TaggedTransactionQueue<Block>,
PoolApi: ChainApi<Block = Block, Hash = H256> + 'static,
PoolApi: ChainApi<Block = Block, Hash = Block::Hash> + 'static,
F: Fetcher<Block> + 'static,
{
/// Create light pool maintainer with default constants.
@@ -261,10 +260,10 @@ impl<Block, Client, PoolApi, F> TransactionPoolMaintainer
for
LightBasicPoolMaintainer<Block, Client, PoolApi, F>
where
Block: BlockT<Hash = <Blake2Hasher as sp_core::Hasher>::Out>,
Client: ProvideRuntimeApi + HeaderBackend<Block> + BlockBody<Block> + 'static,
Block: BlockT,
Client: ProvideRuntimeApi<Block> + HeaderBackend<Block> + BlockBody<Block> + 'static,
Client::Api: TaggedTransactionQueue<Block>,
PoolApi: ChainApi<Block = Block, Hash = H256> + 'static,
PoolApi: ChainApi<Block = Block, Hash = Block::Hash> + 'static,
F: Fetcher<Block> + 'static,
{
type Block = Block;
@@ -362,7 +361,7 @@ mod tests {
#[test]
fn should_remove_transactions_from_the_full_pool() {
let (client, longest_chain) = TestClientBuilder::new().build_with_longest_chain();
let client = Arc::new(client);
let mut client = Arc::new(client);
let pool = sc_transaction_graph::Pool::new(Default::default(), FullChainApi::new(client.clone()));
let pool = Arc::new(pool);
let transaction = Transfer {
@@ -379,7 +378,7 @@ mod tests {
// import the block
let mut builder = client.new_block(Default::default()).unwrap();
builder.push(transaction.clone()).unwrap();
let block = builder.bake().unwrap();
let block = builder.build().unwrap().block;
let id = BlockId::hash(block.header().hash());
client.import(BlockOrigin::Own, block).unwrap();
@@ -562,7 +561,7 @@ mod tests {
#[test]
fn should_add_reverted_transactions_to_the_pool() {
let (client, longest_chain) = TestClientBuilder::new().build_with_longest_chain();
let client = Arc::new(client);
let mut client = Arc::new(client);
let pool = sc_transaction_graph::Pool::new(Default::default(), FullChainApi::new(client.clone()));
let pool = Arc::new(pool);
let transaction = Transfer {
@@ -579,7 +578,7 @@ mod tests {
// import the block
let mut builder = client.new_block(Default::default()).unwrap();
builder.push(transaction.clone()).unwrap();
let block = builder.bake().unwrap();
let block = builder.build().unwrap().block;
let block1_hash = block.header().hash();
let id = BlockId::hash(block1_hash.clone());
client.import(BlockOrigin::Own, block).unwrap();
@@ -593,8 +592,12 @@ mod tests {
assert_eq!(pool.status().future, 0);
// import second block
let builder = client.new_block_at(&BlockId::hash(best.hash()), Default::default()).unwrap();
let block = builder.bake().unwrap();
let builder = client.new_block_at(
&BlockId::hash(best.hash()),
Default::default(),
false,
).unwrap();
let block = builder.build().unwrap().block;
let id = BlockId::hash(block.header().hash());
client.import(BlockOrigin::Own, block).unwrap();
+1
View File
@@ -14,6 +14,7 @@ sp-core = { version = "2.0.0", path = "../../../primitives/core" }
sp-rpc = { version = "2.0.0", path = "../../../primitives/rpc" }
serde = { version = "1.0.101", features = ["derive"] }
sp-runtime = { version = "2.0.0", path = "../../../primitives/runtime" }
sp-api = { version = "2.0.0", path = "../../../primitives/api" }
pallet-contracts-rpc-runtime-api = { version = "2.0.0", path = "./runtime-api" }
[dev-dependencies]
+3 -7
View File
@@ -25,10 +25,8 @@ use jsonrpc_derive::rpc;
use sp_core::{H256, Bytes};
use sp_rpc::number;
use serde::{Deserialize, Serialize};
use sp_runtime::{
generic::BlockId,
traits::{Block as BlockT, ProvideRuntimeApi},
};
use sp_runtime::{generic::BlockId, traits::Block as BlockT};
use sp_api::ProvideRuntimeApi;
pub use self::gen_client::Client as ContractsClient;
pub use pallet_contracts_rpc_runtime_api::{
@@ -156,9 +154,7 @@ impl<C, Block, AccountId, Balance> ContractsApi<<Block as BlockT>::Hash, Account
for Contracts<C, Block>
where
Block: BlockT,
C: Send + Sync + 'static,
C: ProvideRuntimeApi,
C: HeaderBackend<Block>,
C: Send + Sync + 'static + ProvideRuntimeApi<Block> + HeaderBackend<Block>,
C::Api: ContractsRuntimeApi<Block, AccountId, Balance>,
AccountId: Codec,
Balance: Codec,
-1
View File
@@ -231,7 +231,6 @@ mod tests {
assert_ok, assert_noop, impl_outer_origin, parameter_types, weights::Weight,
ord_parameter_types
};
use frame_support::traits::Contains;
use sp_core::H256;
// The testing primitives are very useful for avoiding having to work with signatures
// or public keys. `u64` is used as the `AccountId` and no `Signature`s are requried.
+1 -1
View File
@@ -178,7 +178,7 @@ pub trait Trait: 'static + Eq + Clone {
/// The output of the `Hashing` function.
type Hash:
Parameter + Member + MaybeSerializeDeserialize + Debug + MaybeDisplay + SimpleBitOps
Parameter + Member + MaybeSerializeDeserialize + Debug + MaybeDisplay + SimpleBitOps + Ord
+ Default + Copy + CheckEqual + sp_std::hash::Hash + AsRef<[u8]> + AsMut<[u8]>;
/// The hashing system (algorithm) being used in the runtime (e.g. Blake2).
@@ -13,5 +13,6 @@ sp-core = { version = "2.0.0", path = "../../../primitives/core" }
sp-rpc = { version = "2.0.0", path = "../../../primitives/rpc" }
serde = { version = "1.0.101", features = ["derive"] }
sp-runtime = { version = "2.0.0", path = "../../../primitives/runtime" }
sp-api = { version = "2.0.0", path = "../../../primitives/api" }
sp-blockchain = { version = "2.0.0", path = "../../../primitives/blockchain" }
pallet-transaction-payment-rpc-runtime-api = { version = "2.0.0", path = "./runtime-api" }
@@ -21,10 +21,8 @@ use codec::{Codec, Decode};
use sp_blockchain::HeaderBackend;
use jsonrpc_core::{Error as RpcError, ErrorCode, Result};
use jsonrpc_derive::rpc;
use sp_runtime::{
generic::BlockId,
traits::{Block as BlockT, ProvideRuntimeApi, UniqueSaturatedInto},
};
use sp_runtime::{generic::BlockId, traits::{Block as BlockT, UniqueSaturatedInto}};
use sp_api::ProvideRuntimeApi;
use sp_core::Bytes;
use pallet_transaction_payment_rpc_runtime_api::CappedDispatchInfo;
pub use pallet_transaction_payment_rpc_runtime_api::TransactionPaymentApi as TransactionPaymentRuntimeApi;
@@ -74,9 +72,7 @@ impl<C, Block, Balance, Extrinsic> TransactionPaymentApi<<Block as BlockT>::Hash
for TransactionPayment<C, (Block, Extrinsic)>
where
Block: BlockT,
C: Send + Sync + 'static,
C: ProvideRuntimeApi,
C: HeaderBackend<Block>,
C: Send + Sync + 'static + ProvideRuntimeApi<Block> + HeaderBackend<Block>,
C::Api: TransactionPaymentRuntimeApi<Block, Balance, Extrinsic>,
Balance: Codec + UniqueSaturatedInto<u64>,
Extrinsic: Codec + Send + Sync + 'static,
+2
View File
@@ -12,6 +12,7 @@ sp-std = { version = "2.0.0", default-features = false, path = "../std" }
sp-runtime = { version = "2.0.0", default-features = false, path = "../runtime" }
sp-version = { version = "2.0.0", default-features = false, path = "../version" }
sp-state-machine = { version = "2.0.0", optional = true, path = "../../primitives/state-machine" }
hash-db = { version = "0.15.2", optional = true }
[dev-dependencies]
sp-test-primitives = { version = "2.0.0", path = "../test-primitives" }
@@ -25,4 +26,5 @@ std = [
"sp-runtime/std",
"sp-state-machine",
"sp-version/std",
"hash-db",
]
@@ -16,7 +16,7 @@
use crate::utils::{
generate_crate_access, generate_hidden_includes, generate_runtime_mod_name_for_trait,
fold_fn_decl_for_client_side, unwrap_or_error, extract_parameter_names_types_and_borrows,
fold_fn_decl_for_client_side, extract_parameter_names_types_and_borrows,
generate_native_call_generator_fn_name, return_type_extract_type,
generate_method_runtime_api_impl_name, generate_call_api_at_fn_name, prefix_function_with_trait,
replace_wild_card_parameter_names,
@@ -399,7 +399,7 @@ fn generate_call_api_at_calls(decl: &ItemTrait) -> Result<TokenStream> {
R: #crate_::Encode + #crate_::Decode + PartialEq,
NC: FnOnce() -> std::result::Result<R, String> + std::panic::UnwindSafe,
Block: #crate_::BlockT,
T: #crate_::CallRuntimeAt<Block>,
T: #crate_::CallApiAt<Block>,
C: #crate_::Core<Block, Error = T::Error>,
>(
call_runtime_at: &T,
@@ -407,6 +407,9 @@ fn generate_call_api_at_calls(decl: &ItemTrait) -> Result<TokenStream> {
at: &#crate_::BlockId<Block>,
args: Vec<u8>,
changes: &std::cell::RefCell<#crate_::OverlayedChanges>,
storage_transaction_cache: &std::cell::RefCell<
#crate_::StorageTransactionCache<Block, T::StateBackend>
>,
initialized_block: &std::cell::RefCell<Option<#crate_::BlockId<Block>>>,
native_call: Option<NC>,
context: #crate_::ExecutionContext,
@@ -426,34 +429,40 @@ fn generate_call_api_at_calls(decl: &ItemTrait) -> Result<TokenStream> {
if version.apis.iter().any(|(s, v)| {
s == &ID && *v < #versions
}) {
let ret = call_runtime_at.call_api_at::<R, fn() -> _, _>(
let params = #crate_::CallApiAtParams::<_, _, fn() -> _, _> {
core_api,
at,
#old_names,
args,
changes,
function: #old_names,
native_call: None,
arguments: args,
overlayed_changes: changes,
storage_transaction_cache,
initialize_block,
None,
context,
recorder,
)?;
};
let ret = call_runtime_at.call_api_at(params)?;
update_initialized_block();
return Ok(ret);
return Ok(ret)
}
)*
let ret = call_runtime_at.call_api_at(
let params = #crate_::CallApiAtParams {
core_api,
at,
#trait_fn_name,
args,
changes,
initialize_block,
function: #trait_fn_name,
native_call,
arguments: args,
overlayed_changes: changes,
storage_transaction_cache,
initialize_block,
context,
recorder,
)?;
};
let ret = call_runtime_at.call_api_at(params)?;
update_initialized_block();
Ok(ret)
@@ -465,7 +474,7 @@ fn generate_call_api_at_calls(decl: &ItemTrait) -> Result<TokenStream> {
}
/// Generate the declaration of the trait for the runtime.
fn generate_runtime_decls(decls: &[ItemTrait]) -> TokenStream {
fn generate_runtime_decls(decls: &[ItemTrait]) -> Result<TokenStream> {
let mut result = Vec::new();
for decl in decls {
@@ -473,12 +482,12 @@ fn generate_runtime_decls(decls: &[ItemTrait]) -> TokenStream {
extend_generics_with_block(&mut decl.generics);
let mod_name = generate_runtime_mod_name_for_trait(&decl.ident);
let found_attributes = remove_supported_attributes(&mut decl.attrs);
let api_version = unwrap_or_error(get_api_version(&found_attributes).map(|v| {
let api_version = get_api_version(&found_attributes).map(|v| {
generate_runtime_api_version(v as u32)
}));
})?;
let id = generate_runtime_api_id(&decl.ident.to_string());
let call_api_at_calls = unwrap_or_error(generate_call_api_at_calls(&decl));
let call_api_at_calls = generate_call_api_at_calls(&decl)?;
// Remove methods that have the `changed_in` attribute as they are not required for the
// runtime anymore.
@@ -495,7 +504,7 @@ fn generate_runtime_decls(decls: &[ItemTrait]) -> TokenStream {
r => Some(r.clone()),
}).collect();
let native_call_generators = unwrap_or_error(generate_native_call_generators(&decl));
let native_call_generators = generate_native_call_generators(&decl)?;
result.push(quote!(
#[doc(hidden)]
@@ -517,7 +526,7 @@ fn generate_runtime_decls(decls: &[ItemTrait]) -> TokenStream {
));
}
quote!( #( #result )* )
Ok(quote!( #( #result )* ))
}
/// Modify the given runtime api declaration to be usable on the client side.
@@ -722,7 +731,7 @@ impl<'a> Fold for ToClientSideDecl<'a> {
'static
+ Send
+ Sync
+ #crate_::ApiExt<#block_ident>
+ #crate_::ApiErrorExt
);
} else {
// Add the `Core` runtime api as super trait.
@@ -823,7 +832,7 @@ fn get_api_version(found_attributes: &HashMap<&'static str, Attribute>) -> Resul
}
/// Generate the declaration of the trait for the client side.
fn generate_client_side_decls(decls: &[ItemTrait]) -> TokenStream {
fn generate_client_side_decls(decls: &[ItemTrait]) -> Result<TokenStream> {
let mut result = Vec::new();
for decl in decls {
@@ -848,14 +857,12 @@ fn generate_client_side_decls(decls: &[ItemTrait]) -> TokenStream {
let api_version = get_api_version(&found_attributes);
let runtime_info = unwrap_or_error(
api_version.map(|v| generate_runtime_info_impl(&decl, v))
);
let runtime_info = api_version.map(|v| generate_runtime_info_impl(&decl, v))?;
result.push(quote!( #decl #runtime_info #( #errors )* ));
}
quote!( #( #result )* )
Ok(quote!( #( #result )* ))
}
/// Checks that a trait declaration is in the format we expect.
@@ -908,15 +915,17 @@ impl<'ast> Visit<'ast> for CheckTraitDecl {
}
/// Check that the trait declarations are in the format we expect.
fn check_trait_decls(decls: &[ItemTrait]) -> Option<TokenStream> {
fn check_trait_decls(decls: &[ItemTrait]) -> Result<()> {
let mut checker = CheckTraitDecl { errors: Vec::new() };
decls.iter().for_each(|decl| visit::visit_item_trait(&mut checker, &decl));
if checker.errors.is_empty() {
None
if let Some(err) = checker.errors.pop() {
Err(checker.errors.into_iter().fold(err, |mut err, other| {
err.combine(other);
err
}))
} else {
let errors = checker.errors.into_iter().map(|e| e.to_compile_error());
Some(quote!( #( #errors )* ))
Ok(())
}
}
@@ -925,19 +934,23 @@ pub fn decl_runtime_apis_impl(input: proc_macro::TokenStream) -> proc_macro::Tok
// Parse all trait declarations
let RuntimeApiDecls { decls: api_decls } = parse_macro_input!(input as RuntimeApiDecls);
if let Some(errors) = check_trait_decls(&api_decls) {
return errors.into();
}
decl_runtime_apis_impl_inner(&api_decls).unwrap_or_else(|e| e.to_compile_error()).into()
}
fn decl_runtime_apis_impl_inner(api_decls: &[ItemTrait]) -> Result<TokenStream> {
check_trait_decls(&api_decls)?;
let hidden_includes = generate_hidden_includes(HIDDEN_INCLUDES_ID);
let runtime_decls = generate_runtime_decls(&api_decls);
let client_side_decls = generate_client_side_decls(&api_decls);
let runtime_decls = generate_runtime_decls(api_decls)?;
let client_side_decls = generate_client_side_decls(api_decls)?;
quote!(
#hidden_includes
Ok(
quote!(
#hidden_includes
#runtime_decls
#runtime_decls
#client_side_decls
).into()
#client_side_decls
)
)
}
@@ -15,10 +15,11 @@
// along with Substrate. If not, see <http://www.gnu.org/licenses/>.
use crate::utils::{
unwrap_or_error, generate_crate_access, generate_hidden_includes,
generate_crate_access, generate_hidden_includes,
generate_runtime_mod_name_for_trait, generate_method_runtime_api_impl_name,
extract_parameter_names_types_and_borrows, generate_native_call_generator_fn_name,
return_type_extract_type, generate_call_api_at_fn_name, prefix_function_with_trait,
extract_all_signature_types,
};
use proc_macro2::{Span, TokenStream};
@@ -28,7 +29,7 @@ use quote::quote;
use syn::{
spanned::Spanned, parse_macro_input, Ident, Type, ItemImpl, Path, Signature,
ImplItem, parse::{Parse, ParseStream, Result, Error}, PathArguments, GenericArgument, TypePath,
fold::{self, Fold}, parse_quote
fold::{self, Fold}, parse_quote,
};
use std::{collections::HashSet, iter};
@@ -49,7 +50,11 @@ impl Parse for RuntimeApiImpls {
impls.push(ItemImpl::parse(input)?);
}
Ok(Self { impls })
if impls.is_empty() {
Err(Error::new(Span::call_site(), "No api implementation given!"))
} else {
Ok(Self { impls })
}
}
}
@@ -222,59 +227,69 @@ fn generate_wasm_interface(impls: &[ItemImpl]) -> Result<TokenStream> {
Ok(quote!( #( #impl_calls )* ))
}
fn generate_block_and_block_id_ty(
runtime: &Type,
trait_: &'static str,
assoc_type: &'static str,
) -> (TokenStream, TokenStream) {
fn generate_runtime_api_base_structures() -> Result<TokenStream> {
let crate_ = generate_crate_access(HIDDEN_INCLUDES_ID);
let trait_ = Ident::new(trait_, Span::call_site());
let assoc_type = Ident::new(assoc_type, Span::call_site());
let block = quote!( <#runtime as #crate_::#trait_>::#assoc_type );
let block_id = quote!( #crate_::BlockId<#block> );
(block, block_id)
}
fn generate_node_block_and_block_id_ty(runtime: &Type) -> (TokenStream, TokenStream) {
generate_block_and_block_id_ty(runtime, "GetNodeBlockType", "NodeBlock")
}
fn generate_runtime_api_base_structures(impls: &[ItemImpl]) -> Result<TokenStream> {
let crate_ = generate_crate_access(HIDDEN_INCLUDES_ID);
let runtime = &impls.get(0).ok_or_else(||
Error::new(Span::call_site(), "No api implementation given!")
)?.self_ty;
let (block, block_id) = generate_node_block_and_block_id_ty(runtime);
Ok(quote!(
pub struct RuntimeApi {}
/// Implements all runtime apis for the client side.
#[cfg(any(feature = "std", test))]
pub struct RuntimeApiImpl<C: #crate_::CallRuntimeAt<#block> + 'static> {
pub struct RuntimeApiImpl<Block: #crate_::BlockT, C: #crate_::CallApiAt<Block> + 'static>
where
// Rust bug: https://github.com/rust-lang/rust/issues/24159
C::StateBackend: #crate_::StateBackend<#crate_::HasherFor<Block>>,
{
call: &'static C,
commit_on_success: std::cell::RefCell<bool>,
initialized_block: std::cell::RefCell<Option<#block_id>>,
initialized_block: std::cell::RefCell<Option<#crate_::BlockId<Block>>>,
changes: std::cell::RefCell<#crate_::OverlayedChanges>,
recorder: Option<#crate_::ProofRecorder<#block>>,
storage_transaction_cache: std::cell::RefCell<
#crate_::StorageTransactionCache<Block, C::StateBackend>
>,
recorder: Option<#crate_::ProofRecorder<Block>>,
}
// `RuntimeApi` itself is not threadsafe. However, an instance is only available in a
// `ApiRef` object and `ApiRef` also has an associated lifetime. This lifetimes makes it
// impossible to move `RuntimeApi` into another thread.
#[cfg(any(feature = "std", test))]
unsafe impl<C: #crate_::CallRuntimeAt<#block>> Send for RuntimeApiImpl<C> {}
#[cfg(any(feature = "std", test))]
unsafe impl<C: #crate_::CallRuntimeAt<#block>> Sync for RuntimeApiImpl<C> {}
unsafe impl<Block: #crate_::BlockT, C: #crate_::CallApiAt<Block>> Send
for RuntimeApiImpl<Block, C>
where
// Rust bug: https://github.com/rust-lang/rust/issues/24159
C::StateBackend: #crate_::StateBackend<#crate_::HasherFor<Block>>,
{}
#[cfg(any(feature = "std", test))]
impl<C: #crate_::CallRuntimeAt<#block>> #crate_::ApiExt<#block> for RuntimeApiImpl<C> {
unsafe impl<Block: #crate_::BlockT, C: #crate_::CallApiAt<Block>> Sync
for RuntimeApiImpl<Block, C>
where
// Rust bug: https://github.com/rust-lang/rust/issues/24159
C::StateBackend: #crate_::StateBackend<#crate_::HasherFor<Block>>,
{}
#[cfg(any(feature = "std", test))]
impl<Block: #crate_::BlockT, C: #crate_::CallApiAt<Block>> #crate_::ApiErrorExt
for RuntimeApiImpl<Block, C>
where
// Rust bug: https://github.com/rust-lang/rust/issues/24159
C::StateBackend: #crate_::StateBackend<#crate_::HasherFor<Block>>,
{
type Error = C::Error;
}
#[cfg(any(feature = "std", test))]
impl<Block: #crate_::BlockT, C: #crate_::CallApiAt<Block>> #crate_::ApiExt<Block> for
RuntimeApiImpl<Block, C>
where
// Rust bug: https://github.com/rust-lang/rust/issues/24159
C::StateBackend: #crate_::StateBackend<#crate_::HasherFor<Block>>,
{
type StateBackend = C::StateBackend;
fn map_api_result<F: FnOnce(&Self) -> std::result::Result<R, E>, R, E>(
&self,
map_call: F
map_call: F,
) -> std::result::Result<R, E> where Self: Sized {
*self.commit_on_success.borrow_mut() = false;
let res = map_call(self);
@@ -287,7 +302,7 @@ fn generate_runtime_api_base_structures(impls: &[ItemImpl]) -> Result<TokenStrea
fn runtime_version_at(
&self,
at: &#block_id
at: &#crate_::BlockId<Block>,
) -> std::result::Result<#crate_::RuntimeVersion, C::Error> {
self.call.runtime_version_at(at)
}
@@ -307,13 +322,37 @@ fn generate_runtime_api_base_structures(impls: &[ItemImpl]) -> Result<TokenStrea
#crate_::StorageProof::new(trie_nodes)
})
}
fn into_storage_changes<
T: #crate_::ChangesTrieStorage<#crate_::HasherFor<Block>, #crate_::NumberFor<Block>>
>(
&self,
backend: &Self::StateBackend,
changes_trie_storage: Option<&T>,
parent_hash: Block::Hash,
) -> std::result::Result<
#crate_::StorageChanges<Self::StateBackend, Block>,
String
> where Self: Sized {
self.initialized_block.borrow_mut().take();
self.changes.replace(Default::default()).into_storage_changes(
backend,
changes_trie_storage,
parent_hash,
self.storage_transaction_cache.replace(Default::default()),
)
}
}
#[cfg(any(feature = "std", test))]
impl<C: #crate_::CallRuntimeAt<#block> + 'static> #crate_::ConstructRuntimeApi<#block, C>
impl<Block: #crate_::BlockT, C> #crate_::ConstructRuntimeApi<Block, C>
for RuntimeApi
where
C: #crate_::CallApiAt<Block> + 'static,
// Rust bug: https://github.com/rust-lang/rust/issues/24159
C::StateBackend: #crate_::StateBackend<#crate_::HasherFor<Block>>,
{
type RuntimeApi = RuntimeApiImpl<C>;
type RuntimeApi = RuntimeApiImpl<Block, C>;
fn construct_runtime_api<'a>(
call: &'a C,
@@ -324,20 +363,26 @@ fn generate_runtime_api_base_structures(impls: &[ItemImpl]) -> Result<TokenStrea
initialized_block: None.into(),
changes: Default::default(),
recorder: Default::default(),
storage_transaction_cache: Default::default(),
}.into()
}
}
#[cfg(any(feature = "std", test))]
impl<C: #crate_::CallRuntimeAt<#block>> RuntimeApiImpl<C> {
impl<Block: #crate_::BlockT, C: #crate_::CallApiAt<Block>> RuntimeApiImpl<Block, C>
where
// Rust bug: https://github.com/rust-lang/rust/issues/24159
C::StateBackend: #crate_::StateBackend<#crate_::HasherFor<Block>>,
{
fn call_api_at<
R: #crate_::Encode + #crate_::Decode + PartialEq,
F: FnOnce(
&C,
&Self,
&std::cell::RefCell<#crate_::OverlayedChanges>,
&std::cell::RefCell<Option<#crate_::BlockId<#block>>>,
&Option<#crate_::ProofRecorder<#block>>,
&std::cell::RefCell<#crate_::StorageTransactionCache<Block, C::StateBackend>>,
&std::cell::RefCell<Option<#crate_::BlockId<Block>>>,
&Option<#crate_::ProofRecorder<Block>>,
) -> std::result::Result<#crate_::NativeOrEncoded<R>, E>,
E,
>(
@@ -348,6 +393,7 @@ fn generate_runtime_api_base_structures(impls: &[ItemImpl]) -> Result<TokenStrea
&self.call,
self,
&self.changes,
&self.storage_transaction_cache,
&self.initialized_block,
&self.recorder,
);
@@ -413,9 +459,7 @@ fn generate_api_impl_for_runtime(impls: &[ItemImpl]) -> Result<TokenStream> {
/// `impl Api for Runtime` with `impl Api for RuntimeApi` and replace the method implementations
/// with code that calls into the runtime.
struct ApiRuntimeImplToApiRuntimeApiImpl<'a> {
node_block: &'a TokenStream,
runtime_block: &'a TypePath,
node_block_id: &'a TokenStream,
runtime_mod_path: &'a Path,
runtime_type: &'a Type,
trait_generic_arguments: &'a [GenericArgument],
@@ -425,8 +469,7 @@ struct ApiRuntimeImplToApiRuntimeApiImpl<'a> {
impl<'a> Fold for ApiRuntimeImplToApiRuntimeApiImpl<'a> {
fn fold_type_path(&mut self, input: TypePath) -> TypePath {
let new_ty_path = if input == *self.runtime_block {
let node_block = self.node_block;
parse_quote!( #node_block )
parse_quote!( __SR_API_BLOCK__ )
} else {
input
};
@@ -442,9 +485,7 @@ impl<'a> Fold for ApiRuntimeImplToApiRuntimeApiImpl<'a> {
generate_native_call_generator_fn_name(&input.sig.ident);
let call_api_at_call = generate_call_api_at_fn_name(&input.sig.ident);
let trait_generic_arguments = self.trait_generic_arguments;
let node_block = self.node_block;
let crate_ = generate_crate_access(HIDDEN_INCLUDES_ID);
let block_id = self.node_block_id;
// Generate the access to the native parameters
let param_tuple_access = if input.sig.inputs.len() == 1 {
@@ -471,7 +512,7 @@ impl<'a> Fold for ApiRuntimeImplToApiRuntimeApiImpl<'a> {
// Rewrite the input parameters.
input.sig.inputs = parse_quote! {
&self,
at: &#block_id,
at: &#crate_::BlockId<__SR_API_BLOCK__>,
context: #crate_::ExecutionContext,
params: Option<( #( #param_types ),* )>,
params_encoded: Vec<u8>,
@@ -495,17 +536,25 @@ impl<'a> Fold for ApiRuntimeImplToApiRuntimeApiImpl<'a> {
#error
self.call_api_at(
|call_runtime_at, core_api, changes, initialized_block, recorder| {
|
call_runtime_at,
core_api,
changes,
storage_transaction_cache,
initialized_block,
recorder
| {
#runtime_mod_path #call_api_at_call(
call_runtime_at,
core_api,
at,
params_encoded,
changes,
storage_transaction_cache,
initialized_block,
params.map(|p| {
#runtime_mod_path #native_call_generator_ident ::
<#runtime, #node_block #(, #trait_generic_arguments )*> (
<#runtime, __SR_API_BLOCK__ #(, #trait_generic_arguments )*> (
#( #param_tuple_access ),*
)
}),
@@ -526,13 +575,50 @@ impl<'a> Fold for ApiRuntimeImplToApiRuntimeApiImpl<'a> {
}
fn fold_item_impl(&mut self, mut input: ItemImpl) -> ItemImpl {
// Implement the trait for the `RuntimeApiImpl`
input.self_ty = Box::new(parse_quote!( RuntimeApiImpl<RuntimeApiImplCall> ));
// All this `UnwindSafe` magic below here is required for this rust bug:
// https://github.com/rust-lang/rust/issues/24159
// Before we directly had the final block type and rust could determine that it is unwind
// safe, but now we just have a generic parameter `Block`.
let crate_ = generate_crate_access(HIDDEN_INCLUDES_ID);
let block = self.node_block;
// Implement the trait for the `RuntimeApiImpl`
input.self_ty = Box::new(
parse_quote!( RuntimeApiImpl<__SR_API_BLOCK__, RuntimeApiImplCall> )
);
input.generics.params.push(
parse_quote!( RuntimeApiImplCall: #crate_::CallRuntimeAt<#block> + 'static )
parse_quote!(
__SR_API_BLOCK__: #crate_::BlockT + std::panic::UnwindSafe +
std::panic::RefUnwindSafe
)
);
input.generics.params.push(
parse_quote!( RuntimeApiImplCall: #crate_::CallApiAt<__SR_API_BLOCK__> + 'static )
);
let where_clause = input.generics.make_where_clause();
where_clause.predicates.push(
parse_quote! {
RuntimeApiImplCall::StateBackend:
#crate_::StateBackend<#crate_::HasherFor<__SR_API_BLOCK__>>
}
);
// Require that all types used in the function signatures are unwind safe.
extract_all_signature_types(&input.items).iter().for_each(|i| {
where_clause.predicates.push(
parse_quote! {
#i: std::panic::UnwindSafe + std::panic::RefUnwindSafe
}
);
});
where_clause.predicates.push(
parse_quote! {
__SR_API_BLOCK__::Header: std::panic::UnwindSafe + std::panic::RefUnwindSafe
}
);
// The implementation for the `RuntimeApiImpl` is only required when compiling with
@@ -555,7 +641,6 @@ fn generate_api_impl_for_runtime_api(impls: &[ItemImpl]) -> Result<TokenStream>
.ok_or_else(|| Error::new(impl_trait_path.span(), "Empty trait path not possible!"))?
.clone();
let runtime_block = extract_runtime_block_ident(impl_trait_path)?;
let (node_block, node_block_id) = generate_node_block_and_block_id_ty(&impl_.self_ty);
let runtime_type = &impl_.self_ty;
let mut runtime_mod_path = extend_with_runtime_decl_path(impl_trait_path.clone());
// remove the trait to get just the module path
@@ -568,8 +653,6 @@ fn generate_api_impl_for_runtime_api(impls: &[ItemImpl]) -> Result<TokenStream>
let mut visitor = ApiRuntimeImplToApiRuntimeApiImpl {
runtime_block,
node_block: &node_block,
node_block_id: &node_block_id,
runtime_mod_path: &runtime_mod_path,
runtime_type: &*runtime_type,
trait_generic_arguments: &trait_generic_arguments,
@@ -627,31 +710,37 @@ pub fn impl_runtime_apis_impl(input: proc_macro::TokenStream) -> proc_macro::Tok
// Parse all impl blocks
let RuntimeApiImpls { impls: api_impls } = parse_macro_input!(input as RuntimeApiImpls);
let dispatch_impl = unwrap_or_error(generate_dispatch_function(&api_impls));
let api_impls_for_runtime = unwrap_or_error(generate_api_impl_for_runtime(&api_impls));
let base_runtime_api = unwrap_or_error(generate_runtime_api_base_structures(&api_impls));
let hidden_includes = generate_hidden_includes(HIDDEN_INCLUDES_ID);
let runtime_api_versions = unwrap_or_error(generate_runtime_api_versions(&api_impls));
let wasm_interface = unwrap_or_error(generate_wasm_interface(&api_impls));
let api_impls_for_runtime_api = unwrap_or_error(generate_api_impl_for_runtime_api(&api_impls));
quote!(
#hidden_includes
#base_runtime_api
#api_impls_for_runtime
#api_impls_for_runtime_api
#runtime_api_versions
pub mod api {
use super::*;
#dispatch_impl
#wasm_interface
}
).into()
impl_runtime_apis_impl_inner(&api_impls).unwrap_or_else(|e| e.to_compile_error()).into()
}
fn impl_runtime_apis_impl_inner(api_impls: &[ItemImpl]) -> Result<TokenStream> {
let dispatch_impl = generate_dispatch_function(api_impls)?;
let api_impls_for_runtime = generate_api_impl_for_runtime(api_impls)?;
let base_runtime_api = generate_runtime_api_base_structures()?;
let hidden_includes = generate_hidden_includes(HIDDEN_INCLUDES_ID);
let runtime_api_versions = generate_runtime_api_versions(api_impls)?;
let wasm_interface = generate_wasm_interface(api_impls)?;
let api_impls_for_runtime_api = generate_api_impl_for_runtime_api(api_impls)?;
Ok(
quote!(
#hidden_includes
#base_runtime_api
#api_impls_for_runtime
#api_impls_for_runtime_api
#runtime_api_versions
pub mod api {
use super::*;
#dispatch_impl
#wasm_interface
}
)
)
}
@@ -18,6 +18,7 @@ use proc_macro2::{TokenStream, Span};
use syn::{
Result, Ident, Signature, parse_quote, Type, Pat, spanned::Spanned, FnArg, Error, token::And,
ImplItem, ReturnType,
};
use quote::quote;
@@ -26,11 +27,6 @@ use std::env;
use proc_macro_crate::crate_name;
/// Unwrap the given result, if it is an error, `compile_error!` will be generated.
pub fn unwrap_or_error(res: Result<TokenStream>) -> TokenStream {
res.unwrap_or_else(|e| e.to_compile_error())
}
fn generate_hidden_includes_mod_name(unique_id: &'static str) -> Ident {
Ident::new(&format!("sp_api_hidden_includes_{}", unique_id), Span::call_site())
}
@@ -81,10 +77,10 @@ pub fn generate_method_runtime_api_impl_name(trait_: &Ident, method: &Ident) ->
}
/// Get the type of a `syn::ReturnType`.
pub fn return_type_extract_type(rt: &syn::ReturnType) -> Type {
pub fn return_type_extract_type(rt: &ReturnType) -> Type {
match rt {
syn::ReturnType::Default => parse_quote!( () ),
syn::ReturnType::Type(_, ref ty) => *ty.clone(),
ReturnType::Default => parse_quote!( () ),
ReturnType::Type(_, ref ty) => *ty.clone(),
}
}
@@ -176,3 +172,30 @@ pub fn generate_call_api_at_fn_name(fn_name: &Ident) -> Ident {
pub fn prefix_function_with_trait<F: ToString>(trait_: &Ident, function: &F) -> String {
format!("{}_{}", trait_.to_string(), function.to_string())
}
/// Extract all types that appear in signatures in the given `ImplItem`'s.
///
/// If a type is a reference, the inner type is extracted (without the reference).
pub fn extract_all_signature_types(items: &[ImplItem]) -> Vec<Type> {
items.iter()
.filter_map(|i| match i {
ImplItem::Method(method) => Some(&method.sig),
_ => None,
})
.map(|sig| {
let ret_ty = match &sig.output {
ReturnType::Default => None,
ReturnType::Type(_, ty) => Some((**ty).clone()),
};
sig.inputs.iter().filter_map(|i| match i {
FnArg::Typed(arg) => Some(&arg.ty),
_ => None,
}).map(|ty| match &**ty {
Type::Reference(t) => (*t.elem).clone(),
_ => (**ty).clone(),
}).chain(ret_ty)
})
.flatten()
.collect()
}
+156 -32
View File
@@ -26,7 +26,7 @@
//! functionality that every runtime needs to export.
//!
//! Besides the macros and the [`Core`] runtime api, this crates provides the [`Metadata`] runtime
//! api, the [`ApiExt`] trait, the [`CallRuntimeAt`] trait and the [`ConstructRuntimeApi`] trait.
//! api, the [`ApiExt`] trait, the [`CallApiAt`] trait and the [`ConstructRuntimeApi`] trait.
#![cfg_attr(not(feature = "std"), no_std)]
@@ -35,18 +35,23 @@ extern crate self as sp_api;
#[doc(hidden)]
#[cfg(feature = "std")]
pub use sp_state_machine::{OverlayedChanges, StorageProof};
pub use sp_state_machine::{
OverlayedChanges, StorageProof, Backend as StateBackend, ChangesTrieStorage,
};
#[doc(hidden)]
#[cfg(feature = "std")]
pub use sp_core::NativeOrEncoded;
#[doc(hidden)]
#[cfg(feature = "std")]
pub use hash_db::Hasher;
#[doc(hidden)]
#[cfg(not(feature = "std"))]
pub use sp_core::to_substrate_wasm_fn_return_value;
#[doc(hidden)]
pub use sp_runtime::{
traits::{
Block as BlockT, GetNodeBlockType, GetRuntimeBlockType,
Header as HeaderT, ApiRef, RuntimeApiInfo, Hash as HashT,
Block as BlockT, GetNodeBlockType, GetRuntimeBlockType, HasherFor, NumberFor,
Header as HeaderT, Hash as HashT,
},
generic::BlockId, transaction_validity::TransactionValidity,
};
@@ -157,8 +162,8 @@ pub use sp_api_proc_macro::decl_runtime_apis;
/// ```rust
/// use sp_version::create_runtime_str;
/// #
/// # use sp_runtime::traits::GetNodeBlockType;
/// # use sp_test_primitives::{Block, Header};
/// # use sp_runtime::traits::{GetNodeBlockType, Block as BlockT};
/// # use sp_test_primitives::Block;
/// #
/// # /// The declaration of the `Runtime` type and the implementation of the `GetNodeBlockType`
/// # /// trait are done by the `construct_runtime!` macro in a real runtime.
@@ -187,7 +192,7 @@ pub use sp_api_proc_macro::decl_runtime_apis;
/// # unimplemented!()
/// # }
/// # fn execute_block(_block: Block) {}
/// # fn initialize_block(_header: &Header) {}
/// # fn initialize_block(_header: &<Block as BlockT>::Header) {}
/// # }
///
/// impl self::Balance<Block> for Runtime {
@@ -221,27 +226,60 @@ pub use sp_api_proc_macro::decl_runtime_apis;
/// ```
pub use sp_api_proc_macro::impl_runtime_apis;
#[cfg(feature = "std")]
/// A type that records all accessed trie nodes and generates a proof out of it.
#[cfg(feature = "std")]
pub type ProofRecorder<B> = sp_state_machine::ProofRecorder<
<<<B as BlockT>::Header as HeaderT>::Hashing as HashT>::Hasher
>;
/// A type that is used as cache for the storage transactions.
#[cfg(feature = "std")]
pub type StorageTransactionCache<Block, Backend> =
sp_state_machine::StorageTransactionCache<
<Backend as StateBackend<HasherFor<Block>>>::Transaction, HasherFor<Block>, NumberFor<Block>
>;
#[cfg(feature = "std")]
pub type StorageChanges<SBackend, Block> =
sp_state_machine::StorageChanges<
<SBackend as StateBackend<HasherFor<Block>>>::Transaction,
HasherFor<Block>,
NumberFor<Block>
>;
/// Extract the state backend type for a type that implements `ProvideRuntimeApi`.
#[cfg(feature = "std")]
pub type StateBackendFor<P, Block> =
<<P as ProvideRuntimeApi<Block>>::Api as ApiExt<Block>>::StateBackend;
/// Extract the state backend transaction type for a type that implements `ProvideRuntimeApi`.
#[cfg(feature = "std")]
pub type TransactionFor<P, Block> =
<StateBackendFor<P, Block> as StateBackend<HasherFor<Block>>>::Transaction;
/// Something that can be constructed to a runtime api.
#[cfg(feature = "std")]
pub trait ConstructRuntimeApi<Block: BlockT, C: CallRuntimeAt<Block>> {
pub trait ConstructRuntimeApi<Block: BlockT, C: CallApiAt<Block>> {
/// The actual runtime api that will be constructed.
type RuntimeApi;
type RuntimeApi: ApiExt<Block>;
/// Construct an instance of the runtime api.
fn construct_runtime_api<'a>(call: &'a C) -> ApiRef<'a, Self::RuntimeApi>;
}
/// An extension for the `RuntimeApi`.
/// Extends the runtime api traits with an associated error type. This trait is given as super
/// trait to every runtime api trait.
#[cfg(feature = "std")]
pub trait ApiExt<Block: BlockT> {
/// Error type used by the interface.
pub trait ApiErrorExt {
/// Error type used by the runtime apis.
type Error: std::fmt::Debug + From<String>;
}
/// Extends the runtime api implementation with some common functionality.
#[cfg(feature = "std")]
pub trait ApiExt<Block: BlockT>: ApiErrorExt {
/// The state backend that is used to store the block states.
type StateBackend: StateBackend<HasherFor<Block>>;
/// The given closure will be called with api instance. Inside the closure any api call is
/// allowed. After doing the api call, the closure is allowed to map the `Result` to a
@@ -250,15 +288,15 @@ pub trait ApiExt<Block: BlockT> {
/// On `Ok`, the structure commits the changes to an internal buffer.
fn map_api_result<F: FnOnce(&Self) -> result::Result<R, E>, R, E>(
&self,
map_call: F
map_call: F,
) -> result::Result<R, E> where Self: Sized;
/// Checks if the given api is implemented and versions match.
fn has_api<A: RuntimeApiInfo + ?Sized>(
&self,
at: &BlockId<Block>
at: &BlockId<Block>,
) -> Result<bool, Self::Error> where Self: Sized {
self.runtime_version_at(at).map(|v| v.has_api::<A>())
self.runtime_version_at(at).map(|v| v.has_api_with(&A::ID, |v| v == A::VERSION))
}
/// Check if the given api is implemented and the version passes a predicate.
@@ -267,7 +305,7 @@ pub trait ApiExt<Block: BlockT> {
at: &BlockId<Block>,
pred: P,
) -> Result<bool, Self::Error> where Self: Sized {
self.runtime_version_at(at).map(|v| v.has_api_with::<A, _>(pred))
self.runtime_version_at(at).map(|v| v.has_api_with(&A::ID, pred))
}
/// Returns the runtime version at the given block id.
@@ -277,8 +315,22 @@ pub trait ApiExt<Block: BlockT> {
fn record_proof(&mut self);
/// Extract the recorded proof.
///
/// This stops the proof recording.
///
/// If `record_proof` was not called before, this will return `None`.
fn extract_proof(&mut self) -> Option<StorageProof>;
/// Convert the api object into the storage changes that were done while executing runtime
/// api functions.
///
/// After executing this function, all collected changes are reset.
fn into_storage_changes<T: ChangesTrieStorage<HasherFor<Block>, NumberFor<Block>>>(
&self,
backend: &Self::StateBackend,
changes_trie_storage: Option<&T>,
parent_hash: Block::Hash,
) -> Result<StorageChanges<Self::StateBackend, Block>, String> where Self: Sized;
}
/// Before calling any runtime api function, the runtime need to be initialized
@@ -301,12 +353,44 @@ pub enum InitializeBlock<'a, Block: BlockT> {
Do(&'a RefCell<Option<BlockId<Block>>>),
}
/// Something that can call into the runtime at a given block.
/// Parameters for [`CallApiAt::call_api_at`].
#[cfg(feature = "std")]
pub trait CallRuntimeAt<Block: BlockT> {
/// Error type used by the interface.
pub struct CallApiAtParams<'a, Block: BlockT, C, NC, Backend: StateBackend<HasherFor<Block>>> {
/// A reference to something that implements the [`Core`] api.
pub core_api: &'a C,
/// The block id that determines the state that should be setup when calling the function.
pub at: &'a BlockId<Block>,
/// The name of the function that should be called.
pub function: &'static str,
/// An optional native call that calls the `function`. This is an optimization to call into a
/// native runtime without requiring to encode/decode the parameters. The native runtime can
/// still be called when this value is `None`, we then just fallback to encoding/decoding the
/// parameters.
pub native_call: Option<NC>,
/// The encoded arguments of the function.
pub arguments: Vec<u8>,
/// The overlayed changes that are on top of the state.
pub overlayed_changes: &'a RefCell<OverlayedChanges>,
/// The cache for storage transactions.
pub storage_transaction_cache: &'a RefCell<StorageTransactionCache<Block, Backend>>,
/// Determines if the function requires that `initialize_block` should be called before calling
/// the actual function.
pub initialize_block: InitializeBlock<'a, Block>,
/// The context this function is executed in.
pub context: ExecutionContext,
/// The optional proof recorder for recording storage accesses.
pub recorder: &'a Option<ProofRecorder<Block>>,
}
/// Something that can call into the an api at a given block.
#[cfg(feature = "std")]
pub trait CallApiAt<Block: BlockT> {
/// Error type used by the implementation.
type Error: std::fmt::Debug + From<String>;
/// The state backend that is used to store the block states.
type StateBackend: StateBackend<HasherFor<Block>>;
/// Calls the given api function with the given encoded arguments at the given block and returns
/// the encoded result.
fn call_api_at<
@@ -316,26 +400,66 @@ pub trait CallRuntimeAt<Block: BlockT> {
C: Core<Block, Error = Self::Error>,
>(
&self,
core_api: &C,
at: &BlockId<Block>,
function: &'static str,
args: Vec<u8>,
changes: &RefCell<OverlayedChanges>,
initialize_block: InitializeBlock<'a, Block>,
native_call: Option<NC>,
context: ExecutionContext,
recorder: &Option<ProofRecorder<Block>>,
params: CallApiAtParams<'a, Block, C, NC, Self::StateBackend>,
) -> Result<NativeOrEncoded<R>, Self::Error>;
/// Returns the runtime version at the given block.
fn runtime_version_at(&self, at: &BlockId<Block>) -> Result<RuntimeVersion, Self::Error>;
}
/// Auxiliary wrapper that holds an api instance and binds it to the given lifetime.
#[cfg(feature = "std")]
pub struct ApiRef<'a, T>(T, std::marker::PhantomData<&'a ()>);
#[cfg(feature = "std")]
impl<'a, T> From<T> for ApiRef<'a, T> {
fn from(api: T) -> Self {
ApiRef(api, Default::default())
}
}
#[cfg(feature = "std")]
impl<'a, T> std::ops::Deref for ApiRef<'a, T> {
type Target = T;
fn deref(&self) -> &Self::Target {
&self.0
}
}
#[cfg(feature = "std")]
impl<'a, T> std::ops::DerefMut for ApiRef<'a, T> {
fn deref_mut(&mut self) -> &mut T {
&mut self.0
}
}
/// Something that provides a runtime api.
#[cfg(feature = "std")]
pub trait ProvideRuntimeApi<Block: BlockT> {
/// The concrete type that provides the api.
type Api: ApiExt<Block>;
/// Returns the runtime api.
/// The returned instance will keep track of modifications to the storage. Any successful
/// call to an api function, will `commit` its changes to an internal buffer. Otherwise,
/// the modifications will be `discarded`. The modifications will not be applied to the
/// storage, even on a `commit`.
fn runtime_api<'a>(&'a self) -> ApiRef<'a, Self::Api>;
}
/// Something that provides information about a runtime api.
#[cfg(feature = "std")]
pub trait RuntimeApiInfo {
/// The identifier of the runtime api.
const ID: [u8; 8];
/// The version of the runtime api.
const VERSION: u32;
}
/// Extracts the `Api::Error` for a type that provides a runtime api.
#[cfg(feature = "std")]
pub type ApiErrorFor<T, Block> = <
<T as sp_runtime::traits::ProvideRuntimeApi>::Api as ApiExt<Block>
>::Error;
pub type ApiErrorFor<T, Block> = <<T as ProvideRuntimeApi<Block>>::Api as ApiErrorExt>::Error;
decl_runtime_apis! {
/// The `Core` runtime api that every Substrate runtime needs to implement.
@@ -19,8 +19,9 @@ use substrate_test_runtime_client::{
DefaultTestClientBuilderExt, TestClientBuilder,
TestClientBuilderExt, runtime::TestAPI,
};
use sp_runtime::{generic::BlockId, traits::ProvideRuntimeApi};
use sp_runtime::generic::BlockId;
use sp_state_machine::ExecutionStrategy;
use sp_api::ProvideRuntimeApi;
fn sp_api_benchmark(c: &mut Criterion) {
c.bench_function("add one with same runtime api", |b| {
@@ -90,16 +90,16 @@ type TestClient = substrate_test_runtime_client::sc_client::Client<
#[test]
fn test_client_side_function_signature() {
let _test: fn(&RuntimeApiImpl<TestClient>, &BlockId<Block>, u64) -> Result<()> =
RuntimeApiImpl::<TestClient>::test;
let _test: fn(&RuntimeApiImpl<Block, TestClient>, &BlockId<Block>, u64) -> Result<()> =
RuntimeApiImpl::<Block, TestClient>::test;
let _something_with_block:
fn(&RuntimeApiImpl<TestClient>, &BlockId<Block>, Block) -> Result<Block> =
RuntimeApiImpl::<TestClient>::something_with_block;
fn(&RuntimeApiImpl<Block, TestClient>, &BlockId<Block>, Block) -> Result<Block> =
RuntimeApiImpl::<Block, TestClient>::something_with_block;
#[allow(deprecated)]
let _same_name_before_version_2:
fn(&RuntimeApiImpl<TestClient>, &BlockId<Block>) -> Result<String> =
RuntimeApiImpl::<TestClient>::same_name_before_version_2;
fn(&RuntimeApiImpl<Block, TestClient>, &BlockId<Block>) -> Result<String> =
RuntimeApiImpl::<Block, TestClient>::same_name_before_version_2;
}
#[test]
@@ -14,15 +14,13 @@
// You should have received a copy of the GNU General Public License
// along with Substrate. If not, see <http://www.gnu.org/licenses/>.
use sp_api::ProvideRuntimeApi;
use substrate_test_runtime_client::{
prelude::*,
DefaultTestClientBuilderExt, TestClientBuilder,
runtime::{TestAPI, DecodeFails, Transfer, Header},
};
use sp_runtime::{
generic::BlockId,
traits::{ProvideRuntimeApi, Header as HeaderT, Hash as HashT},
};
use sp_runtime::{generic::BlockId, traits::{Header as HeaderT, Hash as HashT}};
use sp_state_machine::{
ExecutionStrategy, create_proof_check_backend,
execution_proof_check_on_trie_backend,
@@ -174,10 +172,10 @@ fn record_proof_works() {
// Build the block and record proof
let mut builder = client
.new_block_at_with_proof_recording(&block_id, Default::default())
.new_block_at(&block_id, Default::default(), true)
.expect("Creates block builder");
builder.push(transaction.clone()).unwrap();
let (block, proof) = builder.bake_and_extract_proof().expect("Bake block");
let (block, _, proof) = builder.build().expect("Bake block").into_inner();
let backend = create_proof_check_backend::<<<Header as HeaderT>::Hashing as HashT>::Hasher>(
storage_root,
@@ -1,15 +1,15 @@
error: `Block: BlockT` generic parameter will be added automatically by the `decl_runtime_apis!` macro!
--> $DIR/declaring_old_block.rs:4:16
|
4 | pub trait Api<Block: BlockT> {
| ^^^^^
error: `Block: BlockT` generic parameter will be added automatically by the `decl_runtime_apis!` macro! If you try to use a different trait than the substrate `Block` trait, please rename it locally.
--> $DIR/declaring_old_block.rs:4:23
|
4 | pub trait Api<Block: BlockT> {
| ^^^^^^
error: `Block: BlockT` generic parameter will be added automatically by the `decl_runtime_apis!` macro!
--> $DIR/declaring_old_block.rs:4:16
|
4 | pub trait Api<Block: BlockT> {
| ^^^^^
warning: unused import: `sp_runtime::traits::Block as BlockT`
--> $DIR/declaring_old_block.rs:1:5
|
@@ -20,7 +20,7 @@ sp_api::impl_runtime_apis! {
}
impl sp_api::Core<Block> for Runtime {
fn version() -> runtime_api::RuntimeVersion {
fn version() -> sp_api::RuntimeVersion {
unimplemented!()
}
fn execute_block(_: Block) {
@@ -1,9 +1,3 @@
error[E0433]: failed to resolve: use of undeclared type or module `runtime_api`
--> $DIR/impl_incorrect_method_signature.rs:23:19
|
23 | fn version() -> runtime_api::RuntimeVersion {
| ^^^^^^^^^^^ use of undeclared type or module `runtime_api`
error[E0053]: method `test` has an incompatible type for trait
--> $DIR/impl_incorrect_method_signature.rs:19:17
|
@@ -39,8 +33,8 @@ error[E0053]: method `Api_test_runtime_api_impl` has an incompatible type for tr
33 | | }
| |_- in this macro invocation
|
= note: expected type `fn(&RuntimeApiImpl<RuntimeApiImplCall>, &sp_api_hidden_includes_DECL_RUNTIME_APIS::sp_api::BlockId<sp_runtime::generic::block::Block<sp_runtime::generic::header::Header<u64, sp_runtime::traits::BlakeTwo256>, substrate_test_runtime::Extrinsic>>, sp_api_hidden_includes_DECL_RUNTIME_APIS::sp_api::ExecutionContext, std::option::Option<u64>, std::vec::Vec<u8>) -> std::result::Result<sp_api_hidden_includes_DECL_RUNTIME_APIS::sp_api::NativeOrEncoded<()>, <RuntimeApiImplCall as sp_api_hidden_includes_DECL_RUNTIME_APIS::sp_api::CallRuntimeAt<sp_runtime::generic::block::Block<sp_runtime::generic::header::Header<u64, sp_runtime::traits::BlakeTwo256>, substrate_test_runtime::Extrinsic>>>::Error>`
found type `fn(&RuntimeApiImpl<RuntimeApiImplCall>, &sp_api_hidden_includes_DECL_RUNTIME_APIS::sp_api::BlockId<sp_runtime::generic::block::Block<sp_runtime::generic::header::Header<u64, sp_runtime::traits::BlakeTwo256>, substrate_test_runtime::Extrinsic>>, sp_api_hidden_includes_DECL_RUNTIME_APIS::sp_api::ExecutionContext, std::option::Option<std::string::String>, std::vec::Vec<u8>) -> std::result::Result<sp_api_hidden_includes_DECL_RUNTIME_APIS::sp_api::NativeOrEncoded<()>, <RuntimeApiImplCall as sp_api_hidden_includes_DECL_RUNTIME_APIS::sp_api::CallRuntimeAt<sp_runtime::generic::block::Block<sp_runtime::generic::header::Header<u64, sp_runtime::traits::BlakeTwo256>, substrate_test_runtime::Extrinsic>>>::Error>`
= note: expected type `fn(&RuntimeApiImpl<__SR_API_BLOCK__, RuntimeApiImplCall>, &sp_api_hidden_includes_DECL_RUNTIME_APIS::sp_api::BlockId<__SR_API_BLOCK__>, sp_api_hidden_includes_DECL_RUNTIME_APIS::sp_api::ExecutionContext, std::option::Option<u64>, std::vec::Vec<u8>) -> std::result::Result<sp_api_hidden_includes_DECL_RUNTIME_APIS::sp_api::NativeOrEncoded<()>, <RuntimeApiImplCall as sp_api_hidden_includes_DECL_RUNTIME_APIS::sp_api::CallApiAt<__SR_API_BLOCK__>>::Error>`
found type `fn(&RuntimeApiImpl<__SR_API_BLOCK__, RuntimeApiImplCall>, &sp_api_hidden_includes_DECL_RUNTIME_APIS::sp_api::BlockId<__SR_API_BLOCK__>, sp_api_hidden_includes_DECL_RUNTIME_APIS::sp_api::ExecutionContext, std::option::Option<std::string::String>, std::vec::Vec<u8>) -> std::result::Result<sp_api_hidden_includes_DECL_RUNTIME_APIS::sp_api::NativeOrEncoded<()>, <RuntimeApiImplCall as sp_api_hidden_includes_DECL_RUNTIME_APIS::sp_api::CallApiAt<__SR_API_BLOCK__>>::Error>`
error[E0308]: mismatched types
--> $DIR/impl_incorrect_method_signature.rs:17:1
@@ -17,7 +17,7 @@ sp_api::decl_runtime_apis! {
mod second {
use super::*;
decl_runtime_apis! {
sp_api::decl_runtime_apis! {
pub trait Api {
fn test2(data: u64);
}
@@ -4,74 +4,10 @@ error: Two traits with the same name detected! The trait name is used to generat
32 | impl second::Api<Block> for Runtime {
| ^^^
error: cannot find macro `decl_runtime_apis` in this scope
--> $DIR/impl_two_traits_with_same_name.rs:20:2
warning: unused import: `super::*`
--> $DIR/impl_two_traits_with_same_name.rs:18:6
|
20 | decl_runtime_apis! {
| ^^^^^^^^^^^^^^^^^
error[E0425]: cannot find function `test2_call_api_at` in `second::runtime_decl_for_Api`
--> $DIR/impl_two_traits_with_same_name.rs:27:1
18 | use super::*;
| ^^^^^^^^
|
27 | / sp_api::impl_runtime_apis! {
28 | | impl self::Api<Block> for Runtime {
29 | | fn test(data: u64) {}
30 | | }
... |
34 | | }
35 | | }
| | ^
| | |
| |_not found in `second::runtime_decl_for_Api`
| in this macro invocation
error[E0425]: cannot find function `test2_native_call_generator` in `second::runtime_decl_for_Api`
--> $DIR/impl_two_traits_with_same_name.rs:27:1
|
27 | / sp_api::impl_runtime_apis! {
28 | | impl self::Api<Block> for Runtime {
29 | | fn test(data: u64) {}
30 | | }
... |
34 | | }
35 | | }
| | ^
| | |
| |_not found in `second::runtime_decl_for_Api`
| in this macro invocation
error[E0576]: cannot find method or associated constant `test2` in `second::runtime_decl_for_Api::Api`
--> $DIR/impl_two_traits_with_same_name.rs:33:6
|
33 | fn test2(data: u64) {}
| ^^^^^ not found in `second::runtime_decl_for_Api::Api`
error[E0603]: module `runtime_decl_for_Api` is private
--> $DIR/impl_two_traits_with_same_name.rs:27:1
|
27 | / sp_api::impl_runtime_apis! {
28 | | impl self::Api<Block> for Runtime {
29 | | fn test(data: u64) {}
30 | | }
... |
34 | | }
35 | | }
| |_^
error[E0119]: conflicting implementations of trait `runtime_decl_for_Api::Api<sp_runtime::generic::block::Block<sp_runtime::generic::header::Header<u64, sp_runtime::traits::BlakeTwo256>, substrate_test_runtime::Extrinsic>>` for type `Runtime`:
--> $DIR/impl_two_traits_with_same_name.rs:32:2
|
28 | impl self::Api<Block> for Runtime {
| --------------------------------- first implementation here
...
32 | impl second::Api<Block> for Runtime {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `Runtime`
error[E0119]: conflicting implementations of trait `Api<sp_runtime::generic::block::Block<sp_runtime::generic::header::Header<u64, sp_runtime::traits::BlakeTwo256>, substrate_test_runtime::Extrinsic>>` for type `RuntimeApiImpl<_>`:
--> $DIR/impl_two_traits_with_same_name.rs:32:2
|
28 | impl self::Api<Block> for Runtime {
| --------------------------------- first implementation here
...
32 | impl second::Api<Block> for Runtime {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `RuntimeApiImpl<_>`
= note: `#[warn(unused_imports)]` on by default
@@ -1,31 +1,3 @@
error: can't qualify macro invocation with `pub`
--> $DIR/invalid_api_version.rs:1:1
|
1 | / sp_api::decl_runtime_apis! {
2 | | #[api_version]
3 | | pub trait Api {
4 | | fn test(data: u64);
5 | | }
6 | | }
| | ^ in this macro invocation
| |_|
|
|
= help: try adjusting the macro to put `pub` inside the invocation
error: Unexpected `api_version` attribute. The supported format is `api_version(1)`
--> $DIR/invalid_api_version.rs:1:1
|
1 | / sp_api::decl_runtime_apis! {
2 | | #[api_version]
3 | | pub trait Api {
4 | | fn test(data: u64);
5 | | }
6 | | }
| | ^ in this macro invocation
| |_|
|
error: Unexpected `api_version` attribute. The supported format is `api_version(1)`
--> $DIR/invalid_api_version.rs:2:4
|
@@ -1,31 +1,3 @@
error: can't qualify macro invocation with `pub`
--> $DIR/invalid_api_version_2.rs:1:1
|
1 | / sp_api::decl_runtime_apis! {
2 | | #[api_version("1")]
3 | | pub trait Api {
4 | | fn test(data: u64);
5 | | }
6 | | }
| | ^ in this macro invocation
| |_|
|
|
= help: try adjusting the macro to put `pub` inside the invocation
error: Unexpected `api_version` attribute. The supported format is `api_version(1)`
--> $DIR/invalid_api_version_2.rs:1:1
|
1 | / sp_api::decl_runtime_apis! {
2 | | #[api_version("1")]
3 | | pub trait Api {
4 | | fn test(data: u64);
5 | | }
6 | | }
| | ^ in this macro invocation
| |_|
|
error: Unexpected `api_version` attribute. The supported format is `api_version(1)`
--> $DIR/invalid_api_version_2.rs:2:4
|
@@ -1,31 +1,3 @@
error: can't qualify macro invocation with `pub`
--> $DIR/invalid_api_version_3.rs:1:1
|
1 | / sp_api::decl_runtime_apis! {
2 | | #[api_version()]
3 | | pub trait Api {
4 | | fn test(data: u64);
5 | | }
6 | | }
| | ^ in this macro invocation
| |_|
|
|
= help: try adjusting the macro to put `pub` inside the invocation
error: Unexpected `api_version` attribute. The supported format is `api_version(1)`
--> $DIR/invalid_api_version_3.rs:1:1
|
1 | / sp_api::decl_runtime_apis! {
2 | | #[api_version()]
3 | | pub trait Api {
4 | | fn test(data: u64);
5 | | }
6 | | }
| | ^ in this macro invocation
| |_|
|
error: Unexpected `api_version` attribute. The supported format is `api_version(1)`
--> $DIR/invalid_api_version_3.rs:2:4
|
@@ -3,9 +3,3 @@ error: Missing `Block` generic parameter.
|
18 | impl self::Api for Runtime {
| ^^^
error[E0107]: wrong number of type arguments: expected 1, found 0
--> $DIR/missing_block_generic_parameter.rs:18:7
|
18 | impl self::Api for Runtime {
| ^^^^^^^^^ expected 1 type argument
@@ -22,7 +22,7 @@ sp_api::impl_runtime_apis! {
}
impl sp_api::Core<Block> for Runtime {
fn version() -> runtime_api::RuntimeVersion {
fn version() -> sp_api::RuntimeVersion {
unimplemented!()
}
fn execute_block(_: Block) {
@@ -1,9 +1,3 @@
error[E0433]: failed to resolve: use of undeclared type or module `runtime_api`
--> $DIR/type_reference_in_impl_runtime_apis_call.rs:25:19
|
25 | fn version() -> runtime_api::RuntimeVersion {
| ^^^^^^^^^^^ use of undeclared type or module `runtime_api`
error[E0053]: method `test` has an incompatible type for trait
--> $DIR/type_reference_in_impl_runtime_apis_call.rs:19:17
|
@@ -39,8 +33,8 @@ error[E0053]: method `Api_test_runtime_api_impl` has an incompatible type for tr
35 | | }
| |_- in this macro invocation
|
= note: expected type `fn(&RuntimeApiImpl<RuntimeApiImplCall>, &sp_api_hidden_includes_DECL_RUNTIME_APIS::sp_api::BlockId<sp_runtime::generic::block::Block<sp_runtime::generic::header::Header<u64, sp_runtime::traits::BlakeTwo256>, substrate_test_runtime::Extrinsic>>, sp_api_hidden_includes_DECL_RUNTIME_APIS::sp_api::ExecutionContext, std::option::Option<u64>, std::vec::Vec<u8>) -> std::result::Result<sp_api_hidden_includes_DECL_RUNTIME_APIS::sp_api::NativeOrEncoded<()>, <RuntimeApiImplCall as sp_api_hidden_includes_DECL_RUNTIME_APIS::sp_api::CallRuntimeAt<sp_runtime::generic::block::Block<sp_runtime::generic::header::Header<u64, sp_runtime::traits::BlakeTwo256>, substrate_test_runtime::Extrinsic>>>::Error>`
found type `fn(&RuntimeApiImpl<RuntimeApiImplCall>, &sp_api_hidden_includes_DECL_RUNTIME_APIS::sp_api::BlockId<sp_runtime::generic::block::Block<sp_runtime::generic::header::Header<u64, sp_runtime::traits::BlakeTwo256>, substrate_test_runtime::Extrinsic>>, sp_api_hidden_includes_DECL_RUNTIME_APIS::sp_api::ExecutionContext, std::option::Option<&u64>, std::vec::Vec<u8>) -> std::result::Result<sp_api_hidden_includes_DECL_RUNTIME_APIS::sp_api::NativeOrEncoded<()>, <RuntimeApiImplCall as sp_api_hidden_includes_DECL_RUNTIME_APIS::sp_api::CallRuntimeAt<sp_runtime::generic::block::Block<sp_runtime::generic::header::Header<u64, sp_runtime::traits::BlakeTwo256>, substrate_test_runtime::Extrinsic>>>::Error>`
= note: expected type `fn(&RuntimeApiImpl<__SR_API_BLOCK__, RuntimeApiImplCall>, &sp_api_hidden_includes_DECL_RUNTIME_APIS::sp_api::BlockId<__SR_API_BLOCK__>, sp_api_hidden_includes_DECL_RUNTIME_APIS::sp_api::ExecutionContext, std::option::Option<u64>, std::vec::Vec<u8>) -> std::result::Result<sp_api_hidden_includes_DECL_RUNTIME_APIS::sp_api::NativeOrEncoded<()>, <RuntimeApiImplCall as sp_api_hidden_includes_DECL_RUNTIME_APIS::sp_api::CallApiAt<__SR_API_BLOCK__>>::Error>`
found type `fn(&RuntimeApiImpl<__SR_API_BLOCK__, RuntimeApiImplCall>, &sp_api_hidden_includes_DECL_RUNTIME_APIS::sp_api::BlockId<__SR_API_BLOCK__>, sp_api_hidden_includes_DECL_RUNTIME_APIS::sp_api::ExecutionContext, std::option::Option<&u64>, std::vec::Vec<u8>) -> std::result::Result<sp_api_hidden_includes_DECL_RUNTIME_APIS::sp_api::NativeOrEncoded<()>, <RuntimeApiImplCall as sp_api_hidden_includes_DECL_RUNTIME_APIS::sp_api::CallApiAt<__SR_API_BLOCK__>>::Error>`
error[E0308]: mismatched types
--> $DIR/type_reference_in_impl_runtime_apis_call.rs:17:1

Some files were not shown because too many files have changed in this diff Show More