mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-06-12 15:51:12 +00:00
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:
Generated
+15
-1
@@ -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",
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -37,7 +37,7 @@ wabt = "0.9.2"
|
||||
|
||||
[features]
|
||||
wasmtime = [
|
||||
"sc-executor/wasmtime",
|
||||
"sc-executor/wasmtime",
|
||||
]
|
||||
wasmi-errno = [
|
||||
"sc-executor/wasmi-errno",
|
||||
|
||||
@@ -27,4 +27,3 @@ native_executor_instance!(
|
||||
node_runtime::api::dispatch,
|
||||
node_runtime::native_version
|
||||
);
|
||||
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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]
|
||||
|
||||
@@ -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" }
|
||||
|
||||
@@ -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>,
|
||||
|
||||
@@ -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,
|
||||
{
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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]
|
||||
|
||||
@@ -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,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
//! ```
|
||||
//!
|
||||
|
||||
|
||||
@@ -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"] }
|
||||
|
||||
@@ -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,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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" }
|
||||
|
||||
@@ -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" }
|
||||
|
||||
@@ -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
@@ -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};
|
||||
|
||||
@@ -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)))
|
||||
)?;
|
||||
|
||||
@@ -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,
|
||||
{
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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(),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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,
|
||||
{
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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,
|
||||
{
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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]
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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() {
|
||||
|
||||
@@ -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<
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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()
|
||||
}
|
||||
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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::*;
|
||||
|
||||
|
||||
+552
-395
File diff suppressed because it is too large
Load Diff
@@ -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();
|
||||
|
||||
@@ -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() {
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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]));
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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,
|
||||
{
|
||||
|
||||
@@ -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();
|
||||
|
||||
|
||||
@@ -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]
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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()
|
||||
}
|
||||
|
||||
@@ -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) {
|
||||
|
||||
+2
-8
@@ -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
Reference in New Issue
Block a user