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

* Run cargo fmt on the whole code base

* Second run

* Add CI check

* Fix compilation

* More unnecessary braces

* Handle weights

* Use --all

* Use correct attributes...

* Fix UI tests

* AHHHHHHHHH

* 🤦

* Docs

* Fix compilation

* 🤷

* Please stop

* 🤦 x 2

* More

* make rustfmt.toml consistent with polkadot

Co-authored-by: André Silva <andrerfosilva@gmail.com>
This commit is contained in:
Bastian Köcher
2021-07-21 16:32:32 +02:00
committed by GitHub
parent d451c38c1c
commit 7b56ab15b4
1010 changed files with 53339 additions and 51208 deletions
+33 -38
View File
@@ -17,17 +17,13 @@
//! Client extension for tests.
use sc_service::client::Client;
use sc_client_api::backend::Finalizer;
use sc_client_api::client::BlockBackend;
use sp_consensus::{
BlockImportParams, BlockImport, BlockOrigin, Error as ConsensusError,
ForkChoiceStrategy,
};
use sp_runtime::{Justification, Justifications};
use sp_runtime::traits::{Block as BlockT};
use sp_runtime::generic::BlockId;
use codec::alloc::collections::hash_map::HashMap;
use sc_client_api::{backend::Finalizer, client::BlockBackend};
use sc_service::client::Client;
use sp_consensus::{
BlockImport, BlockImportParams, BlockOrigin, Error as ConsensusError, ForkChoiceStrategy,
};
use sp_runtime::{generic::BlockId, traits::Block as BlockT, Justification, Justifications};
/// Extension trait for a test client.
pub trait ClientExt<Block: BlockT>: Sized {
@@ -49,11 +45,18 @@ pub trait ClientBlockImportExt<Block: BlockT>: Sized {
async fn import(&mut self, origin: BlockOrigin, block: Block) -> Result<(), ConsensusError>;
/// Import a block and make it our best block if possible.
async fn import_as_best(&mut self, origin: BlockOrigin, block: Block) -> Result<(), ConsensusError>;
async fn import_as_best(
&mut self,
origin: BlockOrigin,
block: Block,
) -> Result<(), ConsensusError>;
/// Import a block and finalize it.
async fn import_as_final(&mut self, origin: BlockOrigin, block: Block)
-> Result<(), ConsensusError>;
async fn import_as_final(
&mut self,
origin: BlockOrigin,
block: Block,
) -> Result<(), ConsensusError>;
/// Import block with justification(s), finalizes block.
async fn import_justified(
@@ -65,11 +68,11 @@ pub trait ClientBlockImportExt<Block: BlockT>: Sized {
}
impl<B, E, RA, Block> ClientExt<Block> for Client<B, E, Block, RA>
where
B: sc_client_api::backend::Backend<Block>,
E: sc_client_api::CallExecutor<Block> + 'static,
Self: BlockImport<Block, Error = ConsensusError>,
Block: BlockT,
where
B: sc_client_api::backend::Backend<Block>,
E: sc_client_api::CallExecutor<Block> + 'static,
Self: BlockImport<Block, Error = ConsensusError>,
Block: BlockT,
{
fn finalize_block(
&self,
@@ -87,16 +90,12 @@ impl<B, E, RA, Block> ClientExt<Block> for Client<B, E, Block, RA>
/// This implementation is required, because of the weird api requirements around `BlockImport`.
#[async_trait::async_trait]
impl<Block: BlockT, T, Transaction> ClientBlockImportExt<Block> for std::sync::Arc<T>
where
for<'r> &'r T: BlockImport<Block, Error = ConsensusError, Transaction = Transaction>,
Transaction: Send + 'static,
T: Send + Sync,
where
for<'r> &'r T: BlockImport<Block, Error = ConsensusError, Transaction = Transaction>,
Transaction: Send + 'static,
T: Send + Sync,
{
async fn import(
&mut self,
origin: BlockOrigin,
block: Block,
) -> Result<(), ConsensusError> {
async fn import(&mut self, origin: BlockOrigin, block: Block) -> Result<(), ConsensusError> {
let (header, extrinsics) = block.deconstruct();
let mut import = BlockImportParams::new(origin, header);
import.body = Some(extrinsics);
@@ -151,18 +150,14 @@ impl<Block: BlockT, T, Transaction> ClientBlockImportExt<Block> for std::sync::A
#[async_trait::async_trait]
impl<B, E, RA, Block: BlockT> ClientBlockImportExt<Block> for Client<B, E, Block, RA>
where
Self: BlockImport<Block, Error = ConsensusError>,
RA: Send,
B: Send + Sync,
E: Send,
<Self as BlockImport<Block>>::Transaction: Send,
where
Self: BlockImport<Block, Error = ConsensusError>,
RA: Send,
B: Send + Sync,
E: Send,
<Self as BlockImport<Block>>::Transaction: Send,
{
async fn import(
&mut self,
origin: BlockOrigin,
block: Block,
) -> Result<(), ConsensusError> {
async fn import(&mut self, origin: BlockOrigin, block: Block) -> Result<(), ConsensusError> {
let (header, extrinsics) = block.deconstruct();
let mut import = BlockImportParams::new(origin, header);
import.body = Some(extrinsics);
+96 -84
View File
@@ -21,39 +21,44 @@
pub mod client_ext;
pub use self::client_ext::{ClientBlockImportExt, ClientExt};
pub use sc_client_api::{
execution_extensions::{ExecutionStrategies, ExecutionExtensions},
ForkBlocks, BadBlocks,
execution_extensions::{ExecutionExtensions, ExecutionStrategies},
BadBlocks, ForkBlocks,
};
pub use sc_client_db::{Backend, self};
pub use sc_client_db::{self, Backend};
pub use sc_executor::{self, NativeExecutor, WasmExecutionMethod};
pub use sc_service::{client, RpcHandlers, RpcSession};
pub use sp_consensus;
pub use sc_executor::{NativeExecutor, WasmExecutionMethod, self};
pub use sp_keyring::{
AccountKeyring,
ed25519::Keyring as Ed25519Keyring,
sr25519::Keyring as Sr25519Keyring,
ed25519::Keyring as Ed25519Keyring, sr25519::Keyring as Sr25519Keyring, AccountKeyring,
};
pub use sp_keystore::{SyncCryptoStorePtr, SyncCryptoStore};
pub use sp_keystore::{SyncCryptoStore, SyncCryptoStorePtr};
pub use sp_runtime::{Storage, StorageChild};
pub use sp_state_machine::ExecutionStrategy;
pub use sc_service::{RpcHandlers, RpcSession, client};
pub use self::client_ext::{ClientExt, ClientBlockImportExt};
use std::pin::Pin;
use std::sync::Arc;
use std::collections::{HashSet, HashMap};
use futures::{future::{Future, FutureExt}, stream::StreamExt};
use futures::{
future::{Future, FutureExt},
stream::StreamExt,
};
use sc_client_api::BlockchainEvents;
use sc_service::client::{ClientConfig, LocalCallExecutor};
use serde::Deserialize;
use sp_core::storage::ChildInfo;
use sp_runtime::{OpaqueExtrinsic, codec::Encode, traits::{Block as BlockT, BlakeTwo256}};
use sc_service::client::{LocalCallExecutor, ClientConfig};
use sc_client_api::BlockchainEvents;
use sp_runtime::{
codec::Encode,
traits::{BlakeTwo256, Block as BlockT},
OpaqueExtrinsic,
};
use std::{
collections::{HashMap, HashSet},
pin::Pin,
sync::Arc,
};
/// Test client light database backend.
pub type LightBackend<Block> = sc_light::Backend<
sc_client_db::light::LightStorage<Block>,
BlakeTwo256,
>;
pub type LightBackend<Block> =
sc_light::Backend<sc_client_db::light::LightStorage<Block>, BlakeTwo256>;
/// A genesis storage initialization trait.
pub trait GenesisInit: Default {
@@ -84,13 +89,16 @@ pub struct TestClientBuilder<Block: BlockT, Executor, Backend, G: GenesisInit> {
}
impl<Block: BlockT, Executor, G: GenesisInit> Default
for TestClientBuilder<Block, Executor, Backend<Block>, G> {
for TestClientBuilder<Block, Executor, Backend<Block>, G>
{
fn default() -> Self {
Self::with_default_backend()
}
}
impl<Block: BlockT, Executor, G: GenesisInit> TestClientBuilder<Block, Executor, Backend<Block>, G> {
impl<Block: BlockT, Executor, G: GenesisInit>
TestClientBuilder<Block, Executor, Backend<Block>, G>
{
/// Create new `TestClientBuilder` with default backend.
pub fn with_default_backend() -> Self {
let backend = Arc::new(Backend::new_test(std::u32::MAX, std::u64::MAX));
@@ -114,7 +122,9 @@ impl<Block: BlockT, Executor, G: GenesisInit> TestClientBuilder<Block, Executor,
}
}
impl<Block: BlockT, Executor, Backend, G: GenesisInit> TestClientBuilder<Block, Executor, Backend, G> {
impl<Block: BlockT, Executor, Backend, G: GenesisInit>
TestClientBuilder<Block, Executor, Backend, G>
{
/// Create a new instance of the test client builder.
pub fn with_backend(backend: Arc<Backend>) -> Self {
TestClientBuilder {
@@ -155,20 +165,15 @@ impl<Block: BlockT, Executor, Backend, G: GenesisInit> TestClientBuilder<Block,
value: impl AsRef<[u8]>,
) -> Self {
let storage_key = child_info.storage_key();
let entry = self.child_storage_extension.entry(storage_key.to_vec())
.or_insert_with(|| StorageChild {
data: Default::default(),
child_info: child_info.clone(),
});
let entry = self.child_storage_extension.entry(storage_key.to_vec()).or_insert_with(|| {
StorageChild { data: Default::default(), child_info: child_info.clone() }
});
entry.data.insert(key.as_ref().to_vec(), value.as_ref().to_vec());
self
}
/// Set the execution strategy that should be used by all contexts.
pub fn set_execution_strategy(
mut self,
execution_strategy: ExecutionStrategy
) -> Self {
pub fn set_execution_strategy(mut self, execution_strategy: ExecutionStrategy) -> Self {
self.execution_strategies = ExecutionStrategies {
syncing: execution_strategy,
importing: execution_strategy,
@@ -180,7 +185,8 @@ impl<Block: BlockT, Executor, Backend, G: GenesisInit> TestClientBuilder<Block,
}
/// Sets custom block rules.
pub fn set_block_rules(mut self,
pub fn set_block_rules(
mut self,
fork_blocks: ForkBlocks<Block>,
bad_blocks: BadBlocks<Block>,
) -> Self {
@@ -206,14 +212,10 @@ impl<Block: BlockT, Executor, Backend, G: GenesisInit> TestClientBuilder<Block,
self,
executor: Executor,
) -> (
client::Client<
Backend,
Executor,
Block,
RuntimeApi,
>,
client::Client<Backend, Executor, Block, RuntimeApi>,
sc_consensus::LongestChain<Backend, Block>,
) where
)
where
Executor: sc_client_api::CallExecutor<Block> + 'static,
Backend: sc_client_api::backend::Backend<Block>,
<Backend as sc_client_api::backend::Backend<Block>>::OffchainStorage: 'static,
@@ -253,7 +255,8 @@ impl<Block: BlockT, Executor, Backend, G: GenesisInit> TestClientBuilder<Block,
no_genesis: self.no_genesis,
..Default::default()
},
).expect("Creates new client");
)
.expect("Creates new client");
let longest_chain = sc_consensus::LongestChain::new(self.backend);
@@ -261,12 +264,9 @@ impl<Block: BlockT, Executor, Backend, G: GenesisInit> TestClientBuilder<Block,
}
}
impl<Block: BlockT, E, Backend, G: GenesisInit> TestClientBuilder<
Block,
client::LocalCallExecutor<Block, Backend, NativeExecutor<E>>,
Backend,
G,
> {
impl<Block: BlockT, E, Backend, G: GenesisInit>
TestClientBuilder<Block, client::LocalCallExecutor<Block, Backend, NativeExecutor<E>>, Backend, G>
{
/// Build the test client with the given native executor.
pub fn build_with_native_executor<RuntimeApi, I>(
self,
@@ -276,23 +276,25 @@ impl<Block: BlockT, E, Backend, G: GenesisInit> TestClientBuilder<
Backend,
client::LocalCallExecutor<Block, Backend, NativeExecutor<E>>,
Block,
RuntimeApi
RuntimeApi,
>,
sc_consensus::LongestChain<Backend, Block>,
) where
)
where
I: Into<Option<NativeExecutor<E>>>,
E: sc_executor::NativeExecutionDispatch + 'static,
Backend: sc_client_api::backend::Backend<Block> + 'static,
{
let executor = executor.into().unwrap_or_else(||
NativeExecutor::new(WasmExecutionMethod::Interpreted, None, 8)
);
let executor = executor
.into()
.unwrap_or_else(|| NativeExecutor::new(WasmExecutionMethod::Interpreted, None, 8));
let executor = LocalCallExecutor::new(
self.backend.clone(),
executor,
Box::new(sp_core::testing::TaskExecutor::new()),
Default::default(),
).expect("Creates LocalCallExecutor");
)
.expect("Creates LocalCallExecutor");
self.build_with_executor(executor)
}
@@ -347,8 +349,8 @@ impl RpcHandlersExt for RpcHandlers {
) -> Pin<Box<dyn Future<Output = Result<RpcTransactionOutput, RpcTransactionError>> + Send>> {
let (tx, rx) = futures01::sync::mpsc::channel(0);
let mem = RpcSession::new(tx.into());
Box::pin(self
.rpc_query(
Box::pin(
self.rpc_query(
&mem,
&format!(
r#"{{
@@ -360,7 +362,7 @@ impl RpcHandlersExt for RpcHandlers {
hex::encode(extrinsic.encode())
),
)
.map(move |result| parse_rpc_result(result, mem, rx))
.map(move |result| parse_rpc_result(result, mem, rx)),
)
}
}
@@ -371,26 +373,17 @@ pub(crate) fn parse_rpc_result(
receiver: futures01::sync::mpsc::Receiver<String>,
) -> Result<RpcTransactionOutput, RpcTransactionError> {
if let Some(ref result) = result {
let json: serde_json::Value = serde_json::from_str(result)
.expect("the result can only be a JSONRPC string; qed");
let error = json
.as_object()
.expect("JSON result is always an object; qed")
.get("error");
let json: serde_json::Value =
serde_json::from_str(result).expect("the result can only be a JSONRPC string; qed");
let error = json.as_object().expect("JSON result is always an object; qed").get("error");
if let Some(error) = error {
return Err(
serde_json::from_value(error.clone())
.expect("the JSONRPC result's error is always valid; qed")
)
return Err(serde_json::from_value(error.clone())
.expect("the JSONRPC result's error is always valid; qed"))
}
}
Ok(RpcTransactionOutput {
result,
session,
receiver,
})
Ok(RpcTransactionOutput { result, session, receiver })
}
/// An extension trait for `BlockchainEvents`.
@@ -420,7 +413,7 @@ where
if notification.is_new_best {
blocks.insert(notification.hash);
if blocks.len() == count {
break;
break
}
}
}
@@ -445,31 +438,45 @@ mod tests {
assert!(super::parse_rpc_result(None, mem, rx).is_ok());
let (mem, rx) = create_session_and_receiver();
assert!(
super::parse_rpc_result(Some(r#"{
assert!(super::parse_rpc_result(
Some(
r#"{
"jsonrpc": "2.0",
"result": 19,
"id": 1
}"#.to_string()), mem, rx)
.is_ok(),
);
}"#
.to_string()
),
mem,
rx
)
.is_ok(),);
let (mem, rx) = create_session_and_receiver();
let error = super::parse_rpc_result(Some(r#"{
let error = super::parse_rpc_result(
Some(
r#"{
"jsonrpc": "2.0",
"error": {
"code": -32601,
"message": "Method not found"
},
"id": 1
}"#.to_string()), mem, rx)
.unwrap_err();
}"#
.to_string(),
),
mem,
rx,
)
.unwrap_err();
assert_eq!(error.code, -32601);
assert_eq!(error.message, "Method not found");
assert!(error.data.is_none());
let (mem, rx) = create_session_and_receiver();
let error = super::parse_rpc_result(Some(r#"{
let error = super::parse_rpc_result(
Some(
r#"{
"jsonrpc": "2.0",
"error": {
"code": -32601,
@@ -477,8 +484,13 @@ mod tests {
"data": 42
},
"id": 1
}"#.to_string()), mem, rx)
.unwrap_err();
}"#
.to_string(),
),
mem,
rx,
)
.unwrap_err();
assert_eq!(error.code, -32601);
assert_eq!(error.message, "Method not found");
assert!(error.data.is_some());
+3 -3
View File
@@ -43,15 +43,15 @@ fn parse_knobs(
if sig.inputs.len() != 1 {
let msg = "the test function accepts only one argument of type sc_service::TaskExecutor";
return Err(syn::Error::new_spanned(&sig, msg));
return Err(syn::Error::new_spanned(&sig, msg))
}
let (task_executor_name, task_executor_type) = match sig.inputs.pop().map(|x| x.into_value()) {
Some(syn::FnArg::Typed(x)) => (x.pat, x.ty),
_ => {
let msg =
"the test function accepts only one argument of type sc_service::TaskExecutor";
return Err(syn::Error::new_spanned(&sig, msg));
}
return Err(syn::Error::new_spanned(&sig, msg))
},
};
let crate_name = match crate_name("substrate-test-utils") {
@@ -17,16 +17,19 @@
//! Block Builder extensions for tests.
use sc_client_api::backend;
use sp_api::{ApiExt, ProvideRuntimeApi};
use sp_core::ChangesTrieConfiguration;
use sc_client_api::backend;
use sc_block_builder::BlockBuilderApi;
/// Extension trait for test block builder.
pub trait BlockBuilderExt {
/// Add transfer extrinsic to the block.
fn push_transfer(&mut self, transfer: substrate_test_runtime::Transfer) -> Result<(), sp_blockchain::Error>;
fn push_transfer(
&mut self,
transfer: substrate_test_runtime::Transfer,
) -> Result<(), sp_blockchain::Error>;
/// Add storage change extrinsic to the block.
fn push_storage_change(
&mut self,
@@ -40,16 +43,21 @@ pub trait BlockBuilderExt {
) -> Result<(), sp_blockchain::Error>;
}
impl<'a, A, B> BlockBuilderExt for sc_block_builder::BlockBuilder<'a, substrate_test_runtime::Block, A, B> where
impl<'a, A, B> BlockBuilderExt
for sc_block_builder::BlockBuilder<'a, substrate_test_runtime::Block, A, B>
where
A: ProvideRuntimeApi<substrate_test_runtime::Block> + 'a,
A::Api: BlockBuilderApi<substrate_test_runtime::Block> +
ApiExt<
A::Api: BlockBuilderApi<substrate_test_runtime::Block>
+ ApiExt<
substrate_test_runtime::Block,
StateBackend = backend::StateBackendFor<B, substrate_test_runtime::Block>
StateBackend = backend::StateBackendFor<B, substrate_test_runtime::Block>,
>,
B: backend::Backend<substrate_test_runtime::Block>,
{
fn push_transfer(&mut self, transfer: substrate_test_runtime::Transfer) -> Result<(), sp_blockchain::Error> {
fn push_transfer(
&mut self,
transfer: substrate_test_runtime::Transfer,
) -> Result<(), sp_blockchain::Error> {
self.push(transfer.into_signed_tx())
}
+93 -59
View File
@@ -23,34 +23,36 @@ pub mod trait_tests;
mod block_builder_ext;
use std::sync::Arc;
use std::collections::HashMap;
pub use sc_consensus::LongestChain;
use std::{collections::HashMap, sync::Arc};
pub use substrate_test_client::*;
pub use substrate_test_runtime as runtime;
pub use sc_consensus::LongestChain;
pub use self::block_builder_ext::BlockBuilderExt;
use sp_core::{sr25519, ChangesTrieConfiguration};
use sp_core::storage::{ChildInfo, Storage, StorageChild};
use substrate_test_runtime::genesismap::{GenesisConfig, additional_storage_with_genesis};
use sp_runtime::traits::{Block as BlockT, Header as HeaderT, Hash as HashT, NumberFor, HashFor};
use sc_client_api::light::{
RemoteCallRequest, RemoteChangesRequest, RemoteBodyRequest,
Fetcher, RemoteHeaderRequest, RemoteReadRequest, RemoteReadChildRequest,
Fetcher, RemoteBodyRequest, RemoteCallRequest, RemoteChangesRequest, RemoteHeaderRequest,
RemoteReadChildRequest, RemoteReadRequest,
};
use sp_core::{
sr25519,
storage::{ChildInfo, Storage, StorageChild},
ChangesTrieConfiguration,
};
use sp_runtime::traits::{Block as BlockT, Hash as HashT, HashFor, Header as HeaderT, NumberFor};
use substrate_test_runtime::genesismap::{additional_storage_with_genesis, GenesisConfig};
/// A prelude to import in tests.
pub mod prelude {
// Trait extensions
pub use super::{
BlockBuilderExt, DefaultTestClientBuilderExt, TestClientBuilderExt, ClientExt,
ClientBlockImportExt,
BlockBuilderExt, ClientBlockImportExt, ClientExt, DefaultTestClientBuilderExt,
TestClientBuilderExt,
};
// Client structs
pub use super::{
TestClient, TestClientBuilder, Backend, LightBackend,
Executor, LightExecutor, LocalExecutor, NativeExecutor, WasmExecutionMethod,
Backend, Executor, LightBackend, LightExecutor, LocalExecutor, NativeExecutor, TestClient,
TestClientBuilder, WasmExecutionMethod,
};
// Keyring
pub use super::{AccountKeyring, Sr25519Keyring};
@@ -82,10 +84,10 @@ pub type LightExecutor = sc_light::GenesisCallExecutor<
substrate_test_runtime::Block,
sc_light::Backend<
sc_client_db::light::LightStorage<substrate_test_runtime::Block>,
HashFor<substrate_test_runtime::Block>
HashFor<substrate_test_runtime::Block>,
>,
NativeExecutor<LocalExecutor>
>
NativeExecutor<LocalExecutor>,
>,
>;
/// Parameters of test-client builder with test-runtime.
@@ -130,19 +132,23 @@ impl substrate_test_client::GenesisInit for GenesisParameters {
let mut storage = self.genesis_config().genesis_map();
if let Some(ref code) = self.wasm_code {
storage.top.insert(sp_core::storage::well_known_keys::CODE.to_vec(), code.clone());
storage
.top
.insert(sp_core::storage::well_known_keys::CODE.to_vec(), code.clone());
}
let child_roots = storage.children_default.iter().map(|(_sk, child_content)| {
let state_root = <<<runtime::Block as BlockT>::Header as HeaderT>::Hashing as HashT>::trie_root(
child_content.data.clone().into_iter().collect()
);
let state_root =
<<<runtime::Block as BlockT>::Header as HeaderT>::Hashing as HashT>::trie_root(
child_content.data.clone().into_iter().collect(),
);
let prefixed_storage_key = child_content.child_info.prefixed_storage_key();
(prefixed_storage_key.into_inner(), state_root.encode())
});
let state_root = <<<runtime::Block as BlockT>::Header as HeaderT>::Hashing as HashT>::trie_root(
storage.top.clone().into_iter().chain(child_roots).collect()
);
let state_root =
<<<runtime::Block as BlockT>::Header as HeaderT>::Hashing as HashT>::trie_root(
storage.top.clone().into_iter().chain(child_roots).collect(),
);
let block: runtime::Block = client::genesis::construct_genesis_block(state_root);
storage.top.extend(additional_storage_with_genesis(&block));
@@ -164,7 +170,7 @@ pub type Client<B> = client::Client<
client::LocalCallExecutor<
substrate_test_runtime::Block,
B,
sc_executor::NativeExecutor<LocalExecutor>
sc_executor::NativeExecutor<LocalExecutor>,
>,
substrate_test_runtime::Block,
substrate_test_runtime::RuntimeApi,
@@ -217,12 +223,16 @@ pub trait TestClientBuilderExt<B>: Sized {
let key = key.into();
assert!(!storage_key.is_empty());
assert!(!key.is_empty());
self.genesis_init_mut().extra_storage.children_default
self.genesis_init_mut()
.extra_storage
.children_default
.entry(storage_key)
.or_insert_with(|| StorageChild {
data: Default::default(),
child_info: child_info.clone(),
}).data.insert(key, value.into());
})
.data
.insert(key, value.into());
self
}
@@ -244,27 +254,32 @@ pub trait TestClientBuilderExt<B>: Sized {
}
/// Build the test client and longest chain selector.
fn build_with_longest_chain(self) -> (Client<B>, sc_consensus::LongestChain<B, substrate_test_runtime::Block>);
fn build_with_longest_chain(
self,
) -> (Client<B>, sc_consensus::LongestChain<B, substrate_test_runtime::Block>);
/// Build the test client and the backend.
fn build_with_backend(self) -> (Client<B>, Arc<B>);
}
impl<B> TestClientBuilderExt<B> for TestClientBuilder<
client::LocalCallExecutor<
substrate_test_runtime::Block,
impl<B> TestClientBuilderExt<B>
for TestClientBuilder<
client::LocalCallExecutor<
substrate_test_runtime::Block,
B,
sc_executor::NativeExecutor<LocalExecutor>,
>,
B,
sc_executor::NativeExecutor<LocalExecutor>
>,
B
> where
> where
B: sc_client_api::backend::Backend<substrate_test_runtime::Block> + 'static,
{
fn genesis_init_mut(&mut self) -> &mut GenesisParameters {
Self::genesis_init_mut(self)
}
fn build_with_longest_chain(self) -> (Client<B>, sc_consensus::LongestChain<B, substrate_test_runtime::Block>) {
fn build_with_longest_chain(
self,
) -> (Client<B>, sc_consensus::LongestChain<B, substrate_test_runtime::Block>) {
self.build_with_native_executor(None)
}
@@ -275,7 +290,8 @@ impl<B> TestClientBuilderExt<B> for TestClientBuilder<
}
/// Type of optional fetch callback.
type MaybeFetcherCallback<Req, Resp> = Option<Box<dyn Fn(Req) -> Result<Resp, sp_blockchain::Error> + Send + Sync>>;
type MaybeFetcherCallback<Req, Resp> =
Option<Box<dyn Fn(Req) -> Result<Resp, sp_blockchain::Error> + Send + Sync>>;
/// Type of fetcher future result.
type FetcherFutureResult<Resp> = futures::future::Ready<Result<Resp, sp_blockchain::Error>>;
@@ -284,7 +300,10 @@ type FetcherFutureResult<Resp> = futures::future::Ready<Result<Resp, sp_blockcha
#[derive(Default)]
pub struct LightFetcher {
call: MaybeFetcherCallback<RemoteCallRequest<substrate_test_runtime::Header>, Vec<u8>>,
body: MaybeFetcherCallback<RemoteBodyRequest<substrate_test_runtime::Header>, Vec<substrate_test_runtime::Extrinsic>>,
body: MaybeFetcherCallback<
RemoteBodyRequest<substrate_test_runtime::Header>,
Vec<substrate_test_runtime::Extrinsic>,
>,
}
impl LightFetcher {
@@ -293,21 +312,18 @@ impl LightFetcher {
self,
call: MaybeFetcherCallback<RemoteCallRequest<substrate_test_runtime::Header>, Vec<u8>>,
) -> Self {
LightFetcher {
call,
body: self.body,
}
LightFetcher { call, body: self.body }
}
/// Sets remote body callback.
pub fn with_remote_body(
self,
body: MaybeFetcherCallback<RemoteBodyRequest<substrate_test_runtime::Header>, Vec<substrate_test_runtime::Extrinsic>>,
body: MaybeFetcherCallback<
RemoteBodyRequest<substrate_test_runtime::Header>,
Vec<substrate_test_runtime::Extrinsic>,
>,
) -> Self {
LightFetcher {
call: self.call,
body,
}
LightFetcher { call: self.call, body }
}
}
@@ -315,14 +331,21 @@ impl Fetcher<substrate_test_runtime::Block> for LightFetcher {
type RemoteHeaderResult = FetcherFutureResult<substrate_test_runtime::Header>;
type RemoteReadResult = FetcherFutureResult<HashMap<Vec<u8>, Option<Vec<u8>>>>;
type RemoteCallResult = FetcherFutureResult<Vec<u8>>;
type RemoteChangesResult = FetcherFutureResult<Vec<(NumberFor<substrate_test_runtime::Block>, u32)>>;
type RemoteChangesResult =
FetcherFutureResult<Vec<(NumberFor<substrate_test_runtime::Block>, u32)>>;
type RemoteBodyResult = FetcherFutureResult<Vec<substrate_test_runtime::Extrinsic>>;
fn remote_header(&self, _: RemoteHeaderRequest<substrate_test_runtime::Header>) -> Self::RemoteHeaderResult {
fn remote_header(
&self,
_: RemoteHeaderRequest<substrate_test_runtime::Header>,
) -> Self::RemoteHeaderResult {
unimplemented!()
}
fn remote_read(&self, _: RemoteReadRequest<substrate_test_runtime::Header>) -> Self::RemoteReadResult {
fn remote_read(
&self,
_: RemoteReadRequest<substrate_test_runtime::Header>,
) -> Self::RemoteReadResult {
unimplemented!()
}
@@ -333,18 +356,27 @@ impl Fetcher<substrate_test_runtime::Block> for LightFetcher {
unimplemented!()
}
fn remote_call(&self, req: RemoteCallRequest<substrate_test_runtime::Header>) -> Self::RemoteCallResult {
fn remote_call(
&self,
req: RemoteCallRequest<substrate_test_runtime::Header>,
) -> Self::RemoteCallResult {
match self.call {
Some(ref call) => futures::future::ready(call(req)),
None => unimplemented!(),
}
}
fn remote_changes(&self, _: RemoteChangesRequest<substrate_test_runtime::Header>) -> Self::RemoteChangesResult {
fn remote_changes(
&self,
_: RemoteChangesRequest<substrate_test_runtime::Header>,
) -> Self::RemoteChangesResult {
unimplemented!()
}
fn remote_body(&self, req: RemoteBodyRequest<substrate_test_runtime::Header>) -> Self::RemoteBodyResult {
fn remote_body(
&self,
req: RemoteBodyRequest<substrate_test_runtime::Header>,
) -> Self::RemoteBodyResult {
match self.body {
Some(ref body) => futures::future::ready(body(req)),
None => unimplemented!(),
@@ -359,10 +391,14 @@ pub fn new() -> Client<Backend> {
/// Creates new light client instance used for tests.
pub fn new_light() -> (
client::Client<LightBackend, LightExecutor, substrate_test_runtime::Block, substrate_test_runtime::RuntimeApi>,
client::Client<
LightBackend,
LightExecutor,
substrate_test_runtime::Block,
substrate_test_runtime::RuntimeApi,
>,
Arc<LightBackend>,
) {
let storage = sc_client_db::light::LightStorage::new_test();
let blockchain = Arc::new(sc_light::Blockchain::new(storage));
let backend = Arc::new(LightBackend::new(blockchain));
@@ -372,11 +408,9 @@ pub fn new_light() -> (
executor,
Box::new(sp_core::testing::TaskExecutor::new()),
Default::default(),
).expect("Creates LocalCallExecutor");
let call_executor = LightExecutor::new(
backend.clone(),
local_call_executor,
);
)
.expect("Creates LocalCallExecutor");
let call_executor = LightExecutor::new(backend.clone(), local_call_executor);
(
TestClientBuilder::with_backend(backend.clone())
@@ -23,192 +23,169 @@
use std::sync::Arc;
use crate::{
AccountKeyring, ClientBlockImportExt, BlockBuilderExt, TestClientBuilder, TestClientBuilderExt,
AccountKeyring, BlockBuilderExt, ClientBlockImportExt, TestClientBuilder, TestClientBuilderExt,
};
use sc_client_api::backend;
use sc_client_api::blockchain::{Backend as BlockChainBackendT, HeaderBackend};
use sp_consensus::BlockOrigin;
use substrate_test_runtime::{self, Transfer};
use sp_runtime::generic::BlockId;
use sp_runtime::traits::Block as BlockT;
use sc_block_builder::BlockBuilderProvider;
use futures::executor::block_on;
use sc_block_builder::BlockBuilderProvider;
use sc_client_api::{
backend,
blockchain::{Backend as BlockChainBackendT, HeaderBackend},
};
use sp_consensus::BlockOrigin;
use sp_runtime::{generic::BlockId, traits::Block as BlockT};
use substrate_test_runtime::{self, Transfer};
/// helper to test the `leaves` implementation for various backends
pub fn test_leaves_for_backend<B: 'static>(backend: Arc<B>) where
pub fn test_leaves_for_backend<B: 'static>(backend: Arc<B>)
where
B: backend::Backend<substrate_test_runtime::Block>,
{
// block tree:
// G -> A1 -> A2 -> A3 -> A4 -> A5
// A1 -> B2 -> B3 -> B4
// B2 -> C3
// A1 -> D2
// A1 -> B2 -> B3 -> B4
// B2 -> C3
// A1 -> D2
let mut client = TestClientBuilder::with_backend(backend.clone()).build();
let blockchain = backend.blockchain();
let genesis_hash = client.chain_info().genesis_hash;
assert_eq!(
blockchain.leaves().unwrap(),
vec![genesis_hash]);
assert_eq!(blockchain.leaves().unwrap(), vec![genesis_hash]);
// G -> A1
let a1 = client.new_block(Default::default()).unwrap().build().unwrap().block;
block_on(client.import(BlockOrigin::Own, a1.clone())).unwrap();
assert_eq!(
blockchain.leaves().unwrap(),
vec![a1.hash()],
);
assert_eq!(blockchain.leaves().unwrap(), vec![a1.hash()],);
// A1 -> A2
let a2 = client.new_block_at(
&BlockId::Hash(a1.hash()),
Default::default(),
false,
).unwrap().build().unwrap().block;
let a2 = client
.new_block_at(&BlockId::Hash(a1.hash()), Default::default(), false)
.unwrap()
.build()
.unwrap()
.block;
block_on(client.import(BlockOrigin::Own, a2.clone())).unwrap();
#[allow(deprecated)]
assert_eq!(
blockchain.leaves().unwrap(),
vec![a2.hash()],
);
assert_eq!(blockchain.leaves().unwrap(), vec![a2.hash()],);
// A2 -> A3
let a3 = client.new_block_at(
&BlockId::Hash(a2.hash()),
Default::default(),
false,
).unwrap().build().unwrap().block;
let a3 = client
.new_block_at(&BlockId::Hash(a2.hash()), Default::default(), false)
.unwrap()
.build()
.unwrap()
.block;
block_on(client.import(BlockOrigin::Own, a3.clone())).unwrap();
assert_eq!(
blockchain.leaves().unwrap(),
vec![a3.hash()],
);
assert_eq!(blockchain.leaves().unwrap(), vec![a3.hash()],);
// A3 -> A4
let a4 = client.new_block_at(
&BlockId::Hash(a3.hash()),
Default::default(),
false,
).unwrap().build().unwrap().block;
let a4 = client
.new_block_at(&BlockId::Hash(a3.hash()), Default::default(), false)
.unwrap()
.build()
.unwrap()
.block;
block_on(client.import(BlockOrigin::Own, a4.clone())).unwrap();
assert_eq!(
blockchain.leaves().unwrap(),
vec![a4.hash()],
);
assert_eq!(blockchain.leaves().unwrap(), vec![a4.hash()],);
// A4 -> A5
let a5 = client.new_block_at(
&BlockId::Hash(a4.hash()),
Default::default(),
false,
).unwrap().build().unwrap().block;
let a5 = client
.new_block_at(&BlockId::Hash(a4.hash()), Default::default(), false)
.unwrap()
.build()
.unwrap()
.block;
block_on(client.import(BlockOrigin::Own, a5.clone())).unwrap();
assert_eq!(
blockchain.leaves().unwrap(),
vec![a5.hash()],
);
assert_eq!(blockchain.leaves().unwrap(), vec![a5.hash()],);
// A1 -> B2
let mut builder = client.new_block_at(
&BlockId::Hash(a1.hash()),
Default::default(),
false,
).unwrap();
let mut builder = client
.new_block_at(&BlockId::Hash(a1.hash()), Default::default(), false)
.unwrap();
// this push is required as otherwise B2 has the same hash as A2 and won't get imported
builder.push_transfer(Transfer {
from: AccountKeyring::Alice.into(),
to: AccountKeyring::Ferdie.into(),
amount: 41,
nonce: 0,
}).unwrap();
builder
.push_transfer(Transfer {
from: AccountKeyring::Alice.into(),
to: AccountKeyring::Ferdie.into(),
amount: 41,
nonce: 0,
})
.unwrap();
let b2 = builder.build().unwrap().block;
block_on(client.import(BlockOrigin::Own, b2.clone())).unwrap();
assert_eq!(
blockchain.leaves().unwrap(),
vec![a5.hash(), b2.hash()],
);
assert_eq!(blockchain.leaves().unwrap(), vec![a5.hash(), b2.hash()],);
// B2 -> B3
let b3 = client.new_block_at(
&BlockId::Hash(b2.hash()),
Default::default(),
false,
).unwrap().build().unwrap().block;
let b3 = client
.new_block_at(&BlockId::Hash(b2.hash()), Default::default(), false)
.unwrap()
.build()
.unwrap()
.block;
block_on(client.import(BlockOrigin::Own, b3.clone())).unwrap();
assert_eq!(
blockchain.leaves().unwrap(),
vec![a5.hash(), b3.hash()],
);
assert_eq!(blockchain.leaves().unwrap(), vec![a5.hash(), b3.hash()],);
// B3 -> B4
let b4 = client.new_block_at(
&BlockId::Hash(b3.hash()),
Default::default(),
false,
).unwrap().build().unwrap().block;
let b4 = client
.new_block_at(&BlockId::Hash(b3.hash()), Default::default(), false)
.unwrap()
.build()
.unwrap()
.block;
block_on(client.import(BlockOrigin::Own, b4.clone())).unwrap();
assert_eq!(
blockchain.leaves().unwrap(),
vec![a5.hash(), b4.hash()],
);
assert_eq!(blockchain.leaves().unwrap(), vec![a5.hash(), b4.hash()],);
// // B2 -> C3
let mut builder = client.new_block_at(
&BlockId::Hash(b2.hash()),
Default::default(),
false,
).unwrap();
let mut builder = client
.new_block_at(&BlockId::Hash(b2.hash()), Default::default(), false)
.unwrap();
// this push is required as otherwise C3 has the same hash as B3 and won't get imported
builder.push_transfer(Transfer {
from: AccountKeyring::Alice.into(),
to: AccountKeyring::Ferdie.into(),
amount: 1,
nonce: 1,
}).unwrap();
builder
.push_transfer(Transfer {
from: AccountKeyring::Alice.into(),
to: AccountKeyring::Ferdie.into(),
amount: 1,
nonce: 1,
})
.unwrap();
let c3 = builder.build().unwrap().block;
block_on(client.import(BlockOrigin::Own, c3.clone())).unwrap();
assert_eq!(
blockchain.leaves().unwrap(),
vec![a5.hash(), b4.hash(), c3.hash()],
);
assert_eq!(blockchain.leaves().unwrap(), vec![a5.hash(), b4.hash(), c3.hash()],);
// A1 -> D2
let mut builder = client.new_block_at(
&BlockId::Hash(a1.hash()),
Default::default(),
false,
).unwrap();
let mut builder = client
.new_block_at(&BlockId::Hash(a1.hash()), Default::default(), false)
.unwrap();
// this push is required as otherwise D2 has the same hash as B2 and won't get imported
builder.push_transfer(Transfer {
from: AccountKeyring::Alice.into(),
to: AccountKeyring::Ferdie.into(),
amount: 1,
nonce: 0,
}).unwrap();
builder
.push_transfer(Transfer {
from: AccountKeyring::Alice.into(),
to: AccountKeyring::Ferdie.into(),
amount: 1,
nonce: 0,
})
.unwrap();
let d2 = builder.build().unwrap().block;
block_on(client.import(BlockOrigin::Own, d2.clone())).unwrap();
assert_eq!(
blockchain.leaves().unwrap(),
vec![a5.hash(), b4.hash(), c3.hash(), d2.hash()],
);
assert_eq!(blockchain.leaves().unwrap(), vec![a5.hash(), b4.hash(), c3.hash(), d2.hash()],);
}
/// helper to test the `children` implementation for various backends
pub fn test_children_for_backend<B: 'static>(backend: Arc<B>) where
pub fn test_children_for_backend<B: 'static>(backend: Arc<B>)
where
B: backend::LocalBackend<substrate_test_runtime::Block>,
{
// block tree:
// G -> A1 -> A2 -> A3 -> A4 -> A5
// A1 -> B2 -> B3 -> B4
// B2 -> C3
// A1 -> D2
// A1 -> B2 -> B3 -> B4
// B2 -> C3
// A1 -> D2
let mut client = TestClientBuilder::with_backend(backend.clone()).build();
let blockchain = backend.blockchain();
@@ -218,98 +195,104 @@ pub fn test_children_for_backend<B: 'static>(backend: Arc<B>) where
block_on(client.import(BlockOrigin::Own, a1.clone())).unwrap();
// A1 -> A2
let a2 = client.new_block_at(
&BlockId::Hash(a1.hash()),
Default::default(),
false,
).unwrap().build().unwrap().block;
let a2 = client
.new_block_at(&BlockId::Hash(a1.hash()), Default::default(), false)
.unwrap()
.build()
.unwrap()
.block;
block_on(client.import(BlockOrigin::Own, a2.clone())).unwrap();
// A2 -> A3
let a3 = client.new_block_at(
&BlockId::Hash(a2.hash()),
Default::default(),
false,
).unwrap().build().unwrap().block;
let a3 = client
.new_block_at(&BlockId::Hash(a2.hash()), Default::default(), false)
.unwrap()
.build()
.unwrap()
.block;
block_on(client.import(BlockOrigin::Own, a3.clone())).unwrap();
// A3 -> A4
let a4 = client.new_block_at(
&BlockId::Hash(a3.hash()),
Default::default(),
false,
).unwrap().build().unwrap().block;
let a4 = client
.new_block_at(&BlockId::Hash(a3.hash()), Default::default(), false)
.unwrap()
.build()
.unwrap()
.block;
block_on(client.import(BlockOrigin::Own, a4.clone())).unwrap();
// A4 -> A5
let a5 = client.new_block_at(
&BlockId::Hash(a4.hash()),
Default::default(),
false,
).unwrap().build().unwrap().block;
let a5 = client
.new_block_at(&BlockId::Hash(a4.hash()), Default::default(), false)
.unwrap()
.build()
.unwrap()
.block;
block_on(client.import(BlockOrigin::Own, a5.clone())).unwrap();
// A1 -> B2
let mut builder = client.new_block_at(
&BlockId::Hash(a1.hash()),
Default::default(),
false,
).unwrap();
let mut builder = client
.new_block_at(&BlockId::Hash(a1.hash()), Default::default(), false)
.unwrap();
// this push is required as otherwise B2 has the same hash as A2 and won't get imported
builder.push_transfer(Transfer {
from: AccountKeyring::Alice.into(),
to: AccountKeyring::Ferdie.into(),
amount: 41,
nonce: 0,
}).unwrap();
builder
.push_transfer(Transfer {
from: AccountKeyring::Alice.into(),
to: AccountKeyring::Ferdie.into(),
amount: 41,
nonce: 0,
})
.unwrap();
let b2 = builder.build().unwrap().block;
block_on(client.import(BlockOrigin::Own, b2.clone())).unwrap();
// B2 -> B3
let b3 = client.new_block_at(
&BlockId::Hash(b2.hash()),
Default::default(),
false,
).unwrap().build().unwrap().block;
let b3 = client
.new_block_at(&BlockId::Hash(b2.hash()), Default::default(), false)
.unwrap()
.build()
.unwrap()
.block;
block_on(client.import(BlockOrigin::Own, b3.clone())).unwrap();
// B3 -> B4
let b4 = client.new_block_at(
&BlockId::Hash(b3.hash()),
Default::default(),
false,
).unwrap().build().unwrap().block;
let b4 = client
.new_block_at(&BlockId::Hash(b3.hash()), Default::default(), false)
.unwrap()
.build()
.unwrap()
.block;
block_on(client.import(BlockOrigin::Own, b4)).unwrap();
// // B2 -> C3
let mut builder = client.new_block_at(
&BlockId::Hash(b2.hash()),
Default::default(),
false,
).unwrap();
let mut builder = client
.new_block_at(&BlockId::Hash(b2.hash()), Default::default(), false)
.unwrap();
// this push is required as otherwise C3 has the same hash as B3 and won't get imported
builder.push_transfer(Transfer {
from: AccountKeyring::Alice.into(),
to: AccountKeyring::Ferdie.into(),
amount: 1,
nonce: 1,
}).unwrap();
builder
.push_transfer(Transfer {
from: AccountKeyring::Alice.into(),
to: AccountKeyring::Ferdie.into(),
amount: 1,
nonce: 1,
})
.unwrap();
let c3 = builder.build().unwrap().block;
block_on(client.import(BlockOrigin::Own, c3.clone())).unwrap();
// A1 -> D2
let mut builder = client.new_block_at(
&BlockId::Hash(a1.hash()),
Default::default(),
false,
).unwrap();
let mut builder = client
.new_block_at(&BlockId::Hash(a1.hash()), Default::default(), false)
.unwrap();
// this push is required as otherwise D2 has the same hash as B2 and won't get imported
builder.push_transfer(Transfer {
from: AccountKeyring::Alice.into(),
to: AccountKeyring::Ferdie.into(),
amount: 1,
nonce: 0,
}).unwrap();
builder
.push_transfer(Transfer {
from: AccountKeyring::Alice.into(),
to: AccountKeyring::Ferdie.into(),
amount: 1,
nonce: 0,
})
.unwrap();
let d2 = builder.build().unwrap().block;
block_on(client.import(BlockOrigin::Own, d2.clone())).unwrap();
@@ -334,9 +317,9 @@ where
{
// block tree:
// G -> A1 -> A2 -> A3 -> A4 -> A5
// A1 -> B2 -> B3 -> B4
// B2 -> C3
// A1 -> D2
// A1 -> B2 -> B3 -> B4
// B2 -> C3
// A1 -> D2
let mut client = TestClientBuilder::with_backend(backend.clone()).build();
let blockchain = backend.blockchain();
@@ -345,98 +328,104 @@ where
block_on(client.import(BlockOrigin::Own, a1.clone())).unwrap();
// A1 -> A2
let a2 = client.new_block_at(
&BlockId::Hash(a1.hash()),
Default::default(),
false,
).unwrap().build().unwrap().block;
let a2 = client
.new_block_at(&BlockId::Hash(a1.hash()), Default::default(), false)
.unwrap()
.build()
.unwrap()
.block;
block_on(client.import(BlockOrigin::Own, a2.clone())).unwrap();
// A2 -> A3
let a3 = client.new_block_at(
&BlockId::Hash(a2.hash()),
Default::default(),
false,
).unwrap().build().unwrap().block;
let a3 = client
.new_block_at(&BlockId::Hash(a2.hash()), Default::default(), false)
.unwrap()
.build()
.unwrap()
.block;
block_on(client.import(BlockOrigin::Own, a3.clone())).unwrap();
// A3 -> A4
let a4 = client.new_block_at(
&BlockId::Hash(a3.hash()),
Default::default(),
false,
).unwrap().build().unwrap().block;
let a4 = client
.new_block_at(&BlockId::Hash(a3.hash()), Default::default(), false)
.unwrap()
.build()
.unwrap()
.block;
block_on(client.import(BlockOrigin::Own, a4.clone())).unwrap();
// A4 -> A5
let a5 = client.new_block_at(
&BlockId::Hash(a4.hash()),
Default::default(),
false,
).unwrap().build().unwrap().block;
let a5 = client
.new_block_at(&BlockId::Hash(a4.hash()), Default::default(), false)
.unwrap()
.build()
.unwrap()
.block;
block_on(client.import(BlockOrigin::Own, a5.clone())).unwrap();
// A1 -> B2
let mut builder = client.new_block_at(
&BlockId::Hash(a1.hash()),
Default::default(),
false,
).unwrap();
let mut builder = client
.new_block_at(&BlockId::Hash(a1.hash()), Default::default(), false)
.unwrap();
// this push is required as otherwise B2 has the same hash as A2 and won't get imported
builder.push_transfer(Transfer {
from: AccountKeyring::Alice.into(),
to: AccountKeyring::Ferdie.into(),
amount: 41,
nonce: 0,
}).unwrap();
builder
.push_transfer(Transfer {
from: AccountKeyring::Alice.into(),
to: AccountKeyring::Ferdie.into(),
amount: 41,
nonce: 0,
})
.unwrap();
let b2 = builder.build().unwrap().block;
block_on(client.import(BlockOrigin::Own, b2.clone())).unwrap();
// B2 -> B3
let b3 = client.new_block_at(
&BlockId::Hash(b2.hash()),
Default::default(),
false,
).unwrap().build().unwrap().block;
let b3 = client
.new_block_at(&BlockId::Hash(b2.hash()), Default::default(), false)
.unwrap()
.build()
.unwrap()
.block;
block_on(client.import(BlockOrigin::Own, b3.clone())).unwrap();
// B3 -> B4
let b4 = client.new_block_at(
&BlockId::Hash(b3.hash()),
Default::default(),
false,
).unwrap().build().unwrap().block;
let b4 = client
.new_block_at(&BlockId::Hash(b3.hash()), Default::default(), false)
.unwrap()
.build()
.unwrap()
.block;
block_on(client.import(BlockOrigin::Own, b4)).unwrap();
// // B2 -> C3
let mut builder = client.new_block_at(
&BlockId::Hash(b2.hash()),
Default::default(),
false,
).unwrap();
let mut builder = client
.new_block_at(&BlockId::Hash(b2.hash()), Default::default(), false)
.unwrap();
// this push is required as otherwise C3 has the same hash as B3 and won't get imported
builder.push_transfer(Transfer {
from: AccountKeyring::Alice.into(),
to: AccountKeyring::Ferdie.into(),
amount: 1,
nonce: 1,
}).unwrap();
builder
.push_transfer(Transfer {
from: AccountKeyring::Alice.into(),
to: AccountKeyring::Ferdie.into(),
amount: 1,
nonce: 1,
})
.unwrap();
let c3 = builder.build().unwrap().block;
block_on(client.import(BlockOrigin::Own, c3)).unwrap();
// A1 -> D2
let mut builder = client.new_block_at(
&BlockId::Hash(a1.hash()),
Default::default(),
false,
).unwrap();
let mut builder = client
.new_block_at(&BlockId::Hash(a1.hash()), Default::default(), false)
.unwrap();
// this push is required as otherwise D2 has the same hash as B2 and won't get imported
builder.push_transfer(Transfer {
from: AccountKeyring::Alice.into(),
to: AccountKeyring::Ferdie.into(),
amount: 1,
nonce: 0,
}).unwrap();
builder
.push_transfer(Transfer {
from: AccountKeyring::Alice.into(),
to: AccountKeyring::Ferdie.into(),
amount: 1,
nonce: 0,
})
.unwrap();
let d2 = builder.build().unwrap().block;
block_on(client.import(BlockOrigin::Own, d2)).unwrap();
+38 -26
View File
@@ -17,14 +17,17 @@
//! Tool for creating the genesis block.
use std::collections::BTreeMap;
use sp_io::hashing::{blake2_256, twox_128};
use super::{AuthorityId, AccountId, wasm_binary_unwrap, system};
use codec::{Encode, KeyedVec, Joiner};
use sp_core::{ChangesTrieConfiguration, map};
use sp_core::storage::{well_known_keys, Storage};
use sp_runtime::traits::{Block as BlockT, Hash as HashT, Header as HeaderT};
use super::{system, wasm_binary_unwrap, AccountId, AuthorityId};
use codec::{Encode, Joiner, KeyedVec};
use sc_service::client::genesis;
use sp_core::{
map,
storage::{well_known_keys, Storage},
ChangesTrieConfiguration,
};
use sp_io::hashing::{blake2_256, twox_128};
use sp_runtime::traits::{Block as BlockT, Hash as HashT, Header as HeaderT};
use std::collections::BTreeMap;
/// Configuration of a general Substrate test genesis block.
pub struct GenesisConfig {
@@ -47,7 +50,7 @@ impl GenesisConfig {
) -> Self {
GenesisConfig {
changes_trie_config,
authorities: authorities,
authorities,
balances: endowed_accounts.into_iter().map(|a| (a, balance)).collect(),
heap_pages_override,
extra_storage,
@@ -56,16 +59,23 @@ impl GenesisConfig {
pub fn genesis_map(&self) -> Storage {
let wasm_runtime = wasm_binary_unwrap().to_vec();
let mut map: BTreeMap<Vec<u8>, Vec<u8>> = self.balances.iter()
.map(|&(ref account, balance)| (account.to_keyed_vec(b"balance:"), vec![].and(&balance)))
let mut map: BTreeMap<Vec<u8>, Vec<u8>> = self
.balances
.iter()
.map(|&(ref account, balance)| {
(account.to_keyed_vec(b"balance:"), vec![].and(&balance))
})
.map(|(k, v)| (blake2_256(&k[..])[..].to_vec(), v.to_vec()))
.chain(vec![
(well_known_keys::CODE.into(), wasm_runtime),
(
well_known_keys::HEAP_PAGES.into(),
vec![].and(&(self.heap_pages_override.unwrap_or(16 as u64))),
),
].into_iter())
.chain(
vec![
(well_known_keys::CODE.into(), wasm_runtime),
(
well_known_keys::HEAP_PAGES.into(),
vec![].and(&(self.heap_pages_override.unwrap_or(16 as u64))),
),
]
.into_iter(),
)
.collect();
if let Some(ref changes_trie_config) = self.changes_trie_config {
map.insert(well_known_keys::CHANGES_TRIE_CONFIG.to_vec(), changes_trie_config.encode());
@@ -75,28 +85,30 @@ impl GenesisConfig {
map.extend(self.extra_storage.top.clone().into_iter());
// Assimilate the system genesis config.
let mut storage = Storage { top: map, children_default: self.extra_storage.children_default.clone()};
let mut storage =
Storage { top: map, children_default: self.extra_storage.children_default.clone() };
let mut config = system::GenesisConfig::default();
config.authorities = self.authorities.clone();
config.assimilate_storage(&mut storage).expect("Adding `system::GensisConfig` to the genesis");
config
.assimilate_storage(&mut storage)
.expect("Adding `system::GensisConfig` to the genesis");
storage
}
}
pub fn insert_genesis_block(
storage: &mut Storage,
) -> sp_core::hash::H256 {
pub fn insert_genesis_block(storage: &mut Storage) -> sp_core::hash::H256 {
let child_roots = storage.children_default.iter().map(|(sk, child_content)| {
let state_root = <<<crate::Block as BlockT>::Header as HeaderT>::Hashing as HashT>::trie_root(
child_content.data.clone().into_iter().collect(),
);
let state_root =
<<<crate::Block as BlockT>::Header as HeaderT>::Hashing as HashT>::trie_root(
child_content.data.clone().into_iter().collect(),
);
(sk.clone(), state_root.encode())
});
// add child roots to storage
storage.top.extend(child_roots);
let state_root = <<<crate::Block as BlockT>::Header as HeaderT>::Hashing as HashT>::trie_root(
storage.top.clone().into_iter().collect()
storage.top.clone().into_iter().collect(),
);
let block: crate::Block = genesis::construct_genesis_block(state_root);
let genesis_hash = block.header.hash();
+86 -111
View File
@@ -23,45 +23,43 @@
pub mod genesismap;
pub mod system;
use sp_std::{prelude::*, marker::PhantomData};
use codec::{Encode, Decode, Input, Error};
use codec::{Decode, Encode, Error, Input};
use sp_std::{marker::PhantomData, prelude::*};
use sp_application_crypto::{ecdsa, ed25519, sr25519, RuntimeAppPublic};
use sp_core::{offchain::KeyTypeId, ChangesTrieConfiguration, OpaqueMetadata, RuntimeDebug};
use sp_application_crypto::{ed25519, sr25519, ecdsa, RuntimeAppPublic};
use trie_db::{TrieMut, Trie};
use sp_trie::{PrefixedMemoryDB, StorageProof};
use sp_trie::trie_types::{TrieDB, TrieDBMut};
use sp_api::{decl_runtime_apis, impl_runtime_apis};
use sp_runtime::{
create_runtime_str, impl_opaque_keys,
ApplyExtrinsicResult, Perbill,
transaction_validity::{
TransactionValidity, ValidTransaction, TransactionValidityError, InvalidTransaction,
TransactionSource,
},
traits::{
BlindCheckable, BlakeTwo256, Block as BlockT, Extrinsic as ExtrinsicT,
GetNodeBlockType, GetRuntimeBlockType, Verify, IdentityLookup,
},
use sp_trie::{
trie_types::{TrieDB, TrieDBMut},
PrefixedMemoryDB, StorageProof,
};
use trie_db::{Trie, TrieMut};
use cfg_if::cfg_if;
use frame_support::{parameter_types, traits::KeyOwnerProofSystem, weights::RuntimeDbWeight};
use frame_system::limits::{BlockLength, BlockWeights};
use sp_api::{decl_runtime_apis, impl_runtime_apis};
pub use sp_core::hash::H256;
use sp_inherents::{CheckInherentsResult, InherentData};
#[cfg(feature = "std")]
use sp_runtime::traits::NumberFor;
use sp_version::RuntimeVersion;
pub use sp_core::hash::H256;
use sp_runtime::{
create_runtime_str, impl_opaque_keys,
traits::{
BlakeTwo256, BlindCheckable, Block as BlockT, Extrinsic as ExtrinsicT, GetNodeBlockType,
GetRuntimeBlockType, IdentityLookup, Verify,
},
transaction_validity::{
InvalidTransaction, TransactionSource, TransactionValidity, TransactionValidityError,
ValidTransaction,
},
ApplyExtrinsicResult, Perbill,
};
#[cfg(any(feature = "std", test))]
use sp_version::NativeVersion;
use frame_support::{
parameter_types,
traits::KeyOwnerProofSystem,
weights::RuntimeDbWeight,
};
use frame_system::limits::{BlockWeights, BlockLength};
use sp_inherents::{CheckInherentsResult, InherentData};
use cfg_if::cfg_if;
use sp_version::RuntimeVersion;
// Ensure Babe and Aura use the same crypto to simplify things a bit.
pub use sp_consensus_babe::{AuthorityId, Slot, AllowedSlots};
pub use sp_consensus_babe::{AllowedSlots, AuthorityId, Slot};
pub type AuraId = sp_consensus_aura::sr25519::AuthorityId;
@@ -77,18 +75,19 @@ pub mod wasm_binary_logging_disabled {
/// Wasm binary unwrapped. If built with `SKIP_WASM_BUILD`, the function panics.
#[cfg(feature = "std")]
pub fn wasm_binary_unwrap() -> &'static [u8] {
WASM_BINARY.expect("Development wasm binary is not available. Testing is only \
supported with the flag disabled.")
WASM_BINARY.expect(
"Development wasm binary is not available. Testing is only \
supported with the flag disabled.",
)
}
/// Wasm binary unwrapped. If built with `SKIP_WASM_BUILD`, the function panics.
#[cfg(feature = "std")]
pub fn wasm_binary_logging_disabled_unwrap() -> &'static [u8] {
wasm_binary_logging_disabled::WASM_BINARY
.expect(
"Development wasm binary is not available. Testing is only supported with the flag \
disabled."
)
wasm_binary_logging_disabled::WASM_BINARY.expect(
"Development wasm binary is not available. Testing is only supported with the flag \
disabled.",
)
}
/// Test runtime version.
@@ -110,10 +109,7 @@ fn version() -> RuntimeVersion {
/// Native version.
#[cfg(any(feature = "std", test))]
pub fn native_version() -> NativeVersion {
NativeVersion {
runtime_version: VERSION,
can_author_with: Default::default(),
}
NativeVersion { runtime_version: VERSION, can_author_with: Default::default() }
}
/// Calls in transactions.
@@ -130,12 +126,10 @@ impl Transfer {
#[cfg(feature = "std")]
pub fn into_signed_tx(self) -> Extrinsic {
let signature = sp_keyring::AccountKeyring::from_public(&self.from)
.expect("Creates keyring from public key.").sign(&self.encode()).into();
Extrinsic::Transfer {
transfer: self,
signature,
exhaust_resources_when_not_first: false,
}
.expect("Creates keyring from public key.")
.sign(&self.encode())
.into();
Extrinsic::Transfer { transfer: self, signature, exhaust_resources_when_not_first: false }
}
/// Convert into a signed extrinsic, which will only end up included in the block
@@ -144,12 +138,10 @@ impl Transfer {
#[cfg(feature = "std")]
pub fn into_resources_exhausting_tx(self) -> Extrinsic {
let signature = sp_keyring::AccountKeyring::from_public(&self.from)
.expect("Creates keyring from public key.").sign(&self.encode()).into();
Extrinsic::Transfer {
transfer: self,
signature,
exhaust_resources_when_not_first: true,
}
.expect("Creates keyring from public key.")
.sign(&self.encode())
.into();
Extrinsic::Transfer { transfer: self, signature, exhaust_resources_when_not_first: true }
}
}
@@ -174,7 +166,10 @@ parity_util_mem::malloc_size_of_is_0!(Extrinsic); // non-opaque extrinsic does n
#[cfg(feature = "std")]
impl serde::Serialize for Extrinsic {
fn serialize<S>(&self, seq: S) -> Result<S::Ok, S::Error> where S: ::serde::Serializer {
fn serialize<S>(&self, seq: S) -> Result<S::Ok, S::Error>
where
S: ::serde::Serializer,
{
self.using_encoded(|bytes| seq.serialize_bytes(bytes))
}
}
@@ -185,21 +180,22 @@ impl BlindCheckable for Extrinsic {
fn check(self) -> Result<Self, TransactionValidityError> {
match self {
Extrinsic::AuthoritiesChange(new_auth) => Ok(Extrinsic::AuthoritiesChange(new_auth)),
Extrinsic::Transfer { transfer, signature, exhaust_resources_when_not_first } => {
Extrinsic::Transfer { transfer, signature, exhaust_resources_when_not_first } =>
if sp_runtime::verify_encoded_lazy(&signature, &transfer, &transfer.from) {
Ok(Extrinsic::Transfer { transfer, signature, exhaust_resources_when_not_first })
Ok(Extrinsic::Transfer {
transfer,
signature,
exhaust_resources_when_not_first,
})
} else {
Err(InvalidTransaction::BadProof.into())
}
},
},
Extrinsic::IncludeData(v) => Ok(Extrinsic::IncludeData(v)),
Extrinsic::StorageChange(key, value) => Ok(Extrinsic::StorageChange(key, value)),
Extrinsic::ChangesTrieConfigUpdate(new_config) =>
Ok(Extrinsic::ChangesTrieConfigUpdate(new_config)),
Extrinsic::OffchainIndexSet(key, value) =>
Ok(Extrinsic::OffchainIndexSet(key, value)),
Extrinsic::OffchainIndexClear(key) =>
Ok(Extrinsic::OffchainIndexClear(key)),
Extrinsic::OffchainIndexSet(key, value) => Ok(Extrinsic::OffchainIndexSet(key, value)),
Extrinsic::OffchainIndexClear(key) => Ok(Extrinsic::OffchainIndexClear(key)),
Extrinsic::Store(data) => Ok(Extrinsic::Store(data)),
}
}
@@ -301,9 +297,7 @@ impl<B: BlockT> codec::EncodeLike for DecodeFails<B> {}
impl<B: BlockT> DecodeFails<B> {
/// Create a new instance.
pub fn new() -> DecodeFails<B> {
DecodeFails {
_phantom: Default::default(),
}
DecodeFails { _phantom: Default::default() }
}
}
@@ -619,7 +613,8 @@ fn code_using_trie() -> u64 {
let pairs = [
(b"0103000000000000000464".to_vec(), b"0400000000".to_vec()),
(b"0103000000000000000469".to_vec(), b"0401000000".to_vec()),
].to_vec();
]
.to_vec();
let mut mdb = PrefixedMemoryDB::default();
let mut root = sp_std::default::Default::default();
@@ -627,10 +622,10 @@ fn code_using_trie() -> u64 {
let v = &pairs;
let mut t = TrieDBMut::<Hashing>::new(&mut mdb, &mut root);
for i in 0..v.len() {
let key: &[u8]= &v[i].0;
let key: &[u8] = &v[i].0;
let val: &[u8] = &v[i].1;
if !t.insert(key, val).is_ok() {
return 101;
return 101
}
}
t
@@ -645,8 +640,12 @@ fn code_using_trie() -> u64 {
}
}
iter_pairs.len() as u64
} else { 102 }
} else { 103 }
} else {
102
}
} else {
103
}
}
impl_opaque_keys! {
@@ -1206,29 +1205,15 @@ fn test_read_storage() {
fn test_read_child_storage() {
const STORAGE_KEY: &[u8] = b"unique_id_1";
const KEY: &[u8] = b":read_child_storage";
sp_io::default_child_storage::set(
STORAGE_KEY,
KEY,
b"test",
);
sp_io::default_child_storage::set(STORAGE_KEY, KEY, b"test");
let mut v = [0u8; 4];
let r = sp_io::default_child_storage::read(
STORAGE_KEY,
KEY,
&mut v,
0,
);
let r = sp_io::default_child_storage::read(STORAGE_KEY, KEY, &mut v, 0);
assert_eq!(r, Some(4));
assert_eq!(&v, b"test");
let mut v = [0u8; 4];
let r = sp_io::default_child_storage::read(
STORAGE_KEY,
KEY,
&mut v,
8,
);
let r = sp_io::default_child_storage::read(STORAGE_KEY, KEY, &mut v, 8);
assert_eq!(r, Some(0));
assert_eq!(&v, &[0, 0, 0, 0]);
}
@@ -1236,10 +1221,7 @@ fn test_read_child_storage() {
fn test_witness(proof: StorageProof, root: crate::Hash) {
use sp_externalities::Externalities;
let db: sp_trie::MemoryDB<crate::Hashing> = proof.into_memory_db();
let backend = sp_state_machine::TrieBackend::<_, crate::Hashing>::new(
db,
root,
);
let backend = sp_state_machine::TrieBackend::<_, crate::Hashing>::new(db, root);
let mut overlay = sp_state_machine::OverlayedChanges::default();
let mut cache = sp_state_machine::StorageTransactionCache::<_, _, BlockNumber>::default();
let mut ext = sp_state_machine::Ext::new(
@@ -1259,18 +1241,16 @@ fn test_witness(proof: StorageProof, root: crate::Hash) {
#[cfg(test)]
mod tests {
use substrate_test_runtime_client::{
prelude::*,
sp_consensus::BlockOrigin,
DefaultTestClientBuilderExt, TestClientBuilder,
runtime::TestAPI,
};
use sp_api::ProvideRuntimeApi;
use sp_runtime::generic::BlockId;
use sp_core::storage::well_known_keys::HEAP_PAGES;
use sp_state_machine::ExecutionStrategy;
use codec::Encode;
use sc_block_builder::BlockBuilderProvider;
use sp_api::ProvideRuntimeApi;
use sp_core::storage::well_known_keys::HEAP_PAGES;
use sp_runtime::generic::BlockId;
use sp_state_machine::ExecutionStrategy;
use substrate_test_runtime_client::{
prelude::*, runtime::TestAPI, sp_consensus::BlockOrigin, DefaultTestClientBuilderExt,
TestClientBuilder,
};
#[test]
fn heap_pages_is_respected() {
@@ -1307,9 +1287,8 @@ mod tests {
#[test]
fn test_storage() {
let client = TestClientBuilder::new()
.set_execution_strategy(ExecutionStrategy::Both)
.build();
let client =
TestClientBuilder::new().set_execution_strategy(ExecutionStrategy::Both).build();
let runtime_api = client.runtime_api();
let block_id = BlockId::Number(client.chain_info().best_number);
@@ -1331,14 +1310,10 @@ mod tests {
#[test]
fn witness_backend_works() {
let (db, root) = witness_backend();
let backend = sp_state_machine::TrieBackend::<_, crate::Hashing>::new(
db,
root,
);
let backend = sp_state_machine::TrieBackend::<_, crate::Hashing>::new(db, root);
let proof = sp_state_machine::prove_read(backend, vec![b"value3"]).unwrap();
let client = TestClientBuilder::new()
.set_execution_strategy(ExecutionStrategy::Both)
.build();
let client =
TestClientBuilder::new().set_execution_strategy(ExecutionStrategy::Both).build();
let runtime_api = client.runtime_api();
let block_id = BlockId::Number(client.chain_info().best_number);
+101 -98
View File
@@ -18,25 +18,27 @@
//! System manager: Handles all of the top-level stuff; executing block/transaction, setting code
//! and depositing logs.
use sp_std::prelude::*;
use sp_io::{
storage::root as storage_root, storage::changes_root as storage_changes_root,
hashing::blake2_256, trie,
};
use frame_support::storage;
use frame_support::{decl_storage, decl_module};
use sp_runtime::{
traits::Header as _, generic, ApplyExtrinsicResult,
transaction_validity::{
TransactionValidity, ValidTransaction, InvalidTransaction, TransactionValidityError,
},
};
use codec::{KeyedVec, Encode, Decode};
use frame_system::Config;
use crate::{
AccountId, BlockNumber, Extrinsic, Transfer, H256 as Hash, Block, Header, Digest, AuthorityId
AccountId, AuthorityId, Block, BlockNumber, Digest, Extrinsic, Header, Transfer, H256 as Hash,
};
use codec::{Decode, Encode, KeyedVec};
use frame_support::{decl_module, decl_storage, storage};
use frame_system::Config;
use sp_core::{storage::well_known_keys, ChangesTrieConfiguration};
use sp_io::{
hashing::blake2_256,
storage::{changes_root as storage_changes_root, root as storage_root},
trie,
};
use sp_runtime::{
generic,
traits::Header as _,
transaction_validity::{
InvalidTransaction, TransactionValidity, TransactionValidityError, ValidTransaction,
},
ApplyExtrinsicResult,
};
use sp_std::prelude::*;
const NONCE_OF: &[u8] = b"nonce:";
const BALANCE_OF: &[u8] = b"balance:";
@@ -159,17 +161,17 @@ impl frame_support::traits::ExecuteBlock<Block> for BlockExecutor {
/// This doesn't attempt to validate anything regarding the block.
pub fn validate_transaction(utx: Extrinsic) -> TransactionValidity {
if check_signature(&utx).is_err() {
return InvalidTransaction::BadProof.into();
return InvalidTransaction::BadProof.into()
}
let tx = utx.transfer();
let nonce_key = tx.from.to_keyed_vec(NONCE_OF);
let expected_nonce: u64 = storage::hashed::get_or(&blake2_256, &nonce_key, 0);
if tx.nonce < expected_nonce {
return InvalidTransaction::Stale.into();
return InvalidTransaction::Stale.into()
}
if tx.nonce > expected_nonce + 64 {
return InvalidTransaction::Future.into();
return InvalidTransaction::Future.into()
}
let encode = |from: &AccountId, nonce: u64| (from, nonce).encode();
@@ -181,20 +183,14 @@ pub fn validate_transaction(utx: Extrinsic) -> TransactionValidity {
let provides = vec![encode(&tx.from, tx.nonce)];
Ok(ValidTransaction {
priority: tx.amount,
requires,
provides,
longevity: 64,
propagate: true,
})
Ok(ValidTransaction { priority: tx.amount, requires, provides, longevity: 64, propagate: true })
}
/// Execute a transaction outside of the block execution function.
/// This doesn't attempt to validate anything regarding the block.
pub fn execute_transaction(utx: Extrinsic) -> ApplyExtrinsicResult {
let extrinsic_index: u32 = storage::unhashed::get(well_known_keys::EXTRINSIC_INDEX)
.unwrap_or_default();
let extrinsic_index: u32 =
storage::unhashed::get(well_known_keys::EXTRINSIC_INDEX).unwrap_or_default();
let result = execute_transaction_backend(&utx, extrinsic_index);
ExtrinsicData::insert(extrinsic_index, utx.encode());
storage::unhashed::put(well_known_keys::EXTRINSIC_INDEX, &(extrinsic_index + 1));
@@ -215,8 +211,8 @@ pub fn finalize_block() -> Header {
// This MUST come after all changes to storage are done. Otherwise we will fail the
// “Storage root does not match that calculated” assertion.
let storage_root = Hash::decode(&mut &storage_root()[..])
.expect("`storage_root` is a valid hash");
let storage_root =
Hash::decode(&mut &storage_root()[..]).expect("`storage_root` is a valid hash");
let storage_changes_root = storage_changes_root(&parent_hash.encode())
.map(|r| Hash::decode(&mut &r[..]).expect("`storage_changes_root` is a valid hash"));
@@ -231,17 +227,11 @@ pub fn finalize_block() -> Header {
if let Some(new_config) = new_changes_trie_config {
digest.push(generic::DigestItem::ChangesTrieSignal(
generic::ChangesTrieSignal::NewConfiguration(new_config)
generic::ChangesTrieSignal::NewConfiguration(new_config),
));
}
Header {
number,
extrinsics_root,
state_root: storage_root,
parent_hash,
digest,
}
Header { number, extrinsics_root, state_root: storage_root, parent_hash, digest }
}
#[inline(always)]
@@ -253,12 +243,11 @@ fn check_signature(utx: &Extrinsic) -> Result<(), TransactionValidityError> {
fn execute_transaction_backend(utx: &Extrinsic, extrinsic_index: u32) -> ApplyExtrinsicResult {
check_signature(utx)?;
match utx {
Extrinsic::Transfer { exhaust_resources_when_not_first: true, .. } if extrinsic_index != 0 =>
Extrinsic::Transfer { exhaust_resources_when_not_first: true, .. }
if extrinsic_index != 0 =>
Err(InvalidTransaction::ExhaustsResources.into()),
Extrinsic::Transfer { ref transfer, .. } =>
execute_transfer_backend(transfer),
Extrinsic::AuthoritiesChange(ref new_auth) =>
execute_new_authorities_backend(new_auth),
Extrinsic::Transfer { ref transfer, .. } => execute_transfer_backend(transfer),
Extrinsic::AuthoritiesChange(ref new_auth) => execute_new_authorities_backend(new_auth),
Extrinsic::IncludeData(_) => Ok(Ok(())),
Extrinsic::StorageChange(key, value) =>
execute_storage_change(key, value.as_ref().map(|v| &**v)),
@@ -271,9 +260,8 @@ fn execute_transaction_backend(utx: &Extrinsic, extrinsic_index: u32) -> ApplyEx
Extrinsic::OffchainIndexClear(key) => {
sp_io::offchain_index::clear(&key);
Ok(Ok(()))
}
Extrinsic::Store(data) =>
execute_store(data.clone()),
},
Extrinsic::Store(data) => execute_store(data.clone()),
}
}
@@ -282,7 +270,7 @@ fn execute_transfer_backend(tx: &Transfer) -> ApplyExtrinsicResult {
let nonce_key = tx.from.to_keyed_vec(NONCE_OF);
let expected_nonce: u64 = storage::hashed::get_or(&blake2_256, &nonce_key, 0);
if !(tx.nonce == expected_nonce) {
return Err(InvalidTransaction::Stale.into());
return Err(InvalidTransaction::Stale.into())
}
// increment nonce in storage
@@ -294,7 +282,7 @@ fn execute_transfer_backend(tx: &Transfer) -> ApplyExtrinsicResult {
// enact transfer
if !(tx.amount <= from_balance) {
return Err(InvalidTransaction::Payment.into());
return Err(InvalidTransaction::Payment.into())
}
let to_balance_key = tx.to.to_keyed_vec(BALANCE_OF);
let to_balance: u64 = storage::hashed::get_or(&blake2_256, &to_balance_key, 0);
@@ -323,12 +311,12 @@ fn execute_storage_change(key: &[u8], value: Option<&[u8]>) -> ApplyExtrinsicRes
Ok(Ok(()))
}
fn execute_changes_trie_config_update(new_config: Option<ChangesTrieConfiguration>) -> ApplyExtrinsicResult {
fn execute_changes_trie_config_update(
new_config: Option<ChangesTrieConfiguration>,
) -> ApplyExtrinsicResult {
match new_config.clone() {
Some(new_config) => storage::unhashed::put_raw(
well_known_keys::CHANGES_TRIE_CONFIG,
&new_config.encode(),
),
Some(new_config) =>
storage::unhashed::put_raw(well_known_keys::CHANGES_TRIE_CONFIG, &new_config.encode()),
None => storage::unhashed::kill(well_known_keys::CHANGES_TRIE_CONFIG),
}
<NewChangesTrieConfig>::put(new_config);
@@ -360,19 +348,18 @@ fn info_expect_equal_hash(given: &Hash, expected: &Hash) {
mod tests {
use super::*;
use sp_io::TestExternalities;
use crate::{wasm_binary_unwrap, Header, Transfer};
use sc_executor::{native_executor_instance, NativeExecutor, WasmExecutionMethod};
use sp_core::{
map,
traits::{CodeExecutor, RuntimeCode},
NeverNativeValue,
};
use sp_io::{hashing::twox_128, TestExternalities};
use substrate_test_runtime_client::{AccountKeyring, Sr25519Keyring};
use crate::{Header, Transfer, wasm_binary_unwrap};
use sp_core::{NeverNativeValue, map, traits::{CodeExecutor, RuntimeCode}};
use sc_executor::{NativeExecutor, WasmExecutionMethod, native_executor_instance};
use sp_io::hashing::twox_128;
// Declare an instance of the native executor dispatch for the test runtime.
native_executor_instance!(
NativeDispatch,
crate::api::dispatch,
crate::native_version
);
native_executor_instance!(NativeDispatch, crate::api::dispatch, crate::native_version);
fn executor() -> NativeExecutor<NativeDispatch> {
NativeExecutor::new(WasmExecutionMethod::Interpreted, None, 8)
@@ -382,7 +369,7 @@ mod tests {
let authorities = vec![
Sr25519Keyring::Alice.to_raw_public(),
Sr25519Keyring::Bob.to_raw_public(),
Sr25519Keyring::Charlie.to_raw_public()
Sr25519Keyring::Charlie.to_raw_public(),
];
TestExternalities::new_with_code(
wasm_binary_unwrap(),
@@ -399,7 +386,10 @@ mod tests {
)
}
fn block_import_works<F>(block_executor: F) where F: Fn(Block, &mut TestExternalities) {
fn block_import_works<F>(block_executor: F)
where
F: Fn(Block, &mut TestExternalities),
{
let h = Header {
parent_hash: [69u8; 32].into(),
number: 1,
@@ -407,10 +397,7 @@ mod tests {
extrinsics_root: Default::default(),
digest: Default::default(),
};
let mut b = Block {
header: h,
extrinsics: vec![],
};
let mut b = Block { header: h, extrinsics: vec![] };
new_test_ext().execute_with(|| polish_block(&mut b));
@@ -419,7 +406,11 @@ mod tests {
#[test]
fn block_import_works_native() {
block_import_works(|b, ext| ext.execute_with(|| { execute_block(b); }));
block_import_works(|b, ext| {
ext.execute_with(|| {
execute_block(b);
})
});
}
#[test]
@@ -432,19 +423,23 @@ mod tests {
heap_pages: None,
};
executor().call::<NeverNativeValue, fn() -> _>(
&mut ext,
&runtime_code,
"Core_execute_block",
&b.encode(),
false,
None,
).0.unwrap();
executor()
.call::<NeverNativeValue, fn() -> _>(
&mut ext,
&runtime_code,
"Core_execute_block",
&b.encode(),
false,
None,
)
.0
.unwrap();
})
}
fn block_import_with_transaction_works<F>(block_executor: F)
where F: Fn(Block, &mut TestExternalities)
where
F: Fn(Block, &mut TestExternalities),
{
let mut b1 = Block {
header: Header {
@@ -454,14 +449,13 @@ mod tests {
extrinsics_root: Default::default(),
digest: Default::default(),
},
extrinsics: vec![
Transfer {
from: AccountKeyring::Alice.into(),
to: AccountKeyring::Bob.into(),
amount: 69,
nonce: 0,
}.into_signed_tx()
],
extrinsics: vec![Transfer {
from: AccountKeyring::Alice.into(),
to: AccountKeyring::Bob.into(),
amount: 69,
nonce: 0,
}
.into_signed_tx()],
};
let mut dummy_ext = new_test_ext();
@@ -481,13 +475,15 @@ mod tests {
to: AccountKeyring::Alice.into(),
amount: 27,
nonce: 0,
}.into_signed_tx(),
}
.into_signed_tx(),
Transfer {
from: AccountKeyring::Alice.into(),
to: AccountKeyring::Charlie.into(),
amount: 69,
nonce: 1,
}.into_signed_tx(),
}
.into_signed_tx(),
],
};
@@ -519,7 +515,11 @@ mod tests {
#[test]
fn block_import_with_transaction_works_native() {
block_import_with_transaction_works(|b, ext| ext.execute_with(|| { execute_block(b); }));
block_import_with_transaction_works(|b, ext| {
ext.execute_with(|| {
execute_block(b);
})
});
}
#[test]
@@ -532,14 +532,17 @@ mod tests {
heap_pages: None,
};
executor().call::<NeverNativeValue, fn() -> _>(
&mut ext,
&runtime_code,
"Core_execute_block",
&b.encode(),
false,
None,
).0.unwrap();
executor()
.call::<NeverNativeValue, fn() -> _>(
&mut ext,
&runtime_code,
"Core_execute_block",
&b.encode(),
false,
None,
)
.0
.unwrap();
})
}
}
@@ -20,22 +20,22 @@
//! See [`TestApi`] for more information.
use codec::Encode;
use futures::future::ready;
use parking_lot::RwLock;
use sp_blockchain::CachedHeaderMetadata;
use sp_runtime::{
generic::{self, BlockId},
traits::{BlakeTwo256, Hash as HashT, Block as BlockT, Header as _},
traits::{BlakeTwo256, Block as BlockT, Hash as HashT, Header as _},
transaction_validity::{
TransactionValidity, ValidTransaction, TransactionValidityError, InvalidTransaction,
TransactionSource,
InvalidTransaction, TransactionSource, TransactionValidity, TransactionValidityError,
ValidTransaction,
},
};
use std::collections::{HashSet, HashMap, BTreeMap};
use std::collections::{BTreeMap, HashMap, HashSet};
use substrate_test_runtime_client::{
runtime::{Index, AccountId, Block, BlockNumber, Extrinsic, Hash, Header, Transfer},
runtime::{AccountId, Block, BlockNumber, Extrinsic, Hash, Header, Index, Transfer},
AccountKeyring::{self, *},
};
use sp_blockchain::CachedHeaderMetadata;
use futures::future::ready;
/// Error type used by [`TestApi`].
#[derive(Debug, derive_more::From, derive_more::Display)]
@@ -130,12 +130,9 @@ impl TestApi {
block_number
.checked_sub(1)
.and_then(|num| {
chain.block_by_number
.get(&num)
.map(|blocks| {
blocks[0].0.header.hash()
})
}).unwrap_or_default()
chain.block_by_number.get(&num).map(|blocks| blocks[0].0.header.hash())
})
.unwrap_or_default()
};
self.push_block_with_parent(parent_hash, xts, is_best_block)
@@ -154,7 +151,9 @@ impl TestApi {
let block_number = if parent == Hash::default() {
0
} else {
*self.chain.read()
*self
.chain
.read()
.block_by_hash
.get(&parent)
.expect("`parent` exists")
@@ -182,7 +181,11 @@ impl TestApi {
let mut chain = self.chain.write();
chain.block_by_hash.insert(hash, block.clone());
chain.block_by_number.entry(block_number).or_default().push((block, is_best_block.into()));
chain
.block_by_number
.entry(block_number)
.or_default()
.push((block, is_best_block.into()));
}
fn hash_and_length_inner(ex: &Extrinsic) -> (Hash, usize) {
@@ -195,9 +198,7 @@ impl TestApi {
/// Next time transaction pool will try to validate this
/// extrinsic, api will return invalid result.
pub fn add_invalid(&self, xts: &Extrinsic) {
self.chain.write().invalid_hashes.insert(
Self::hash_and_length_inner(xts).0
);
self.chain.write().invalid_hashes.insert(Self::hash_and_length_inner(xts).0);
}
/// Query validation requests received.
@@ -242,7 +243,8 @@ impl sc_transaction_pool::test_helpers::ChainApi for TestApi {
match self.block_id_to_number(at) {
Ok(Some(number)) => {
let found_best = self.chain
let found_best = self
.chain
.read()
.block_by_number
.get(&number)
@@ -253,24 +255,24 @@ impl sc_transaction_pool::test_helpers::ChainApi for TestApi {
// the transaction. (This is not required for this test function, but in real
// environment it would fail because of this).
if !found_best {
return ready(Ok(
Err(TransactionValidityError::Invalid(InvalidTransaction::Custom(1)).into())
))
return ready(Ok(Err(TransactionValidityError::Invalid(
InvalidTransaction::Custom(1),
)
.into())))
}
},
Ok(None) => return ready(Ok(
Err(TransactionValidityError::Invalid(InvalidTransaction::Custom(2)).into())
)),
Ok(None) =>
return ready(Ok(Err(TransactionValidityError::Invalid(
InvalidTransaction::Custom(2),
)
.into()))),
Err(e) => return ready(Err(e)),
}
let (requires, provides) = if let Some(transfer) = uxt.try_transfer() {
let chain_nonce = self.chain.read().nonces.get(&transfer.from).cloned().unwrap_or(0);
let requires = if chain_nonce == transfer.nonce {
vec![]
} else {
vec![vec![chain_nonce as u8]]
};
let requires =
if chain_nonce == transfer.nonce { vec![] } else { vec![vec![chain_nonce as u8]] };
let provides = vec![vec![transfer.nonce as u8]];
(requires, provides)
@@ -279,18 +281,13 @@ impl sc_transaction_pool::test_helpers::ChainApi for TestApi {
};
if self.chain.read().invalid_hashes.contains(&self.hash_and_length(&uxt).0) {
return ready(Ok(
Err(TransactionValidityError::Invalid(InvalidTransaction::Custom(0)).into())
))
return ready(Ok(Err(
TransactionValidityError::Invalid(InvalidTransaction::Custom(0)).into()
)))
}
let mut validity = ValidTransaction {
priority: 1,
requires,
provides,
longevity: 64,
propagate: true,
};
let mut validity =
ValidTransaction { priority: 1, requires, provides, longevity: 64, propagate: true };
(self.valid_modifier.read())(&mut validity);
@@ -302,11 +299,8 @@ impl sc_transaction_pool::test_helpers::ChainApi for TestApi {
at: &BlockId<Self::Block>,
) -> Result<Option<sc_transaction_pool::test_helpers::NumberFor<Self>>, Error> {
Ok(match at {
generic::BlockId::Hash(x) => self.chain
.read()
.block_by_hash
.get(x)
.map(|b| *b.header.number()),
generic::BlockId::Hash(x) =>
self.chain.read().block_by_hash.get(x).map(|b| *b.header.number()),
generic::BlockId::Number(num) => Some(*num),
})
}
@@ -317,11 +311,10 @@ impl sc_transaction_pool::test_helpers::ChainApi for TestApi {
) -> Result<Option<sc_transaction_pool::test_helpers::BlockHash<Self>>, Error> {
Ok(match at {
generic::BlockId::Hash(x) => Some(x.clone()),
generic::BlockId::Number(num) => self.chain
.read()
.block_by_number
.get(num)
.and_then(|blocks| blocks.iter().find(|b| b.1.is_best()).map(|b| b.0.header().hash())),
generic::BlockId::Number(num) =>
self.chain.read().block_by_number.get(num).and_then(|blocks| {
blocks.iter().find(|b| b.1.is_best()).map(|b| b.0.header().hash())
}),
})
}
@@ -334,16 +327,10 @@ impl sc_transaction_pool::test_helpers::ChainApi for TestApi {
fn block_body(&self, id: &BlockId<Self::Block>) -> Self::BodyFuture {
futures::future::ready(Ok(match id {
BlockId::Number(num) => self.chain
.read()
.block_by_number
.get(num)
.map(|b| b[0].0.extrinsics().to_vec()),
BlockId::Hash(hash) => self.chain
.read()
.block_by_hash
.get(hash)
.map(|b| b.extrinsics().to_vec()),
BlockId::Number(num) =>
self.chain.read().block_by_number.get(num).map(|b| b[0].0.extrinsics().to_vec()),
BlockId::Hash(hash) =>
self.chain.read().block_by_hash.get(hash).map(|b| b.extrinsics().to_vec()),
}))
}
@@ -352,16 +339,10 @@ impl sc_transaction_pool::test_helpers::ChainApi for TestApi {
at: &BlockId<Self::Block>,
) -> Result<Option<<Self::Block as BlockT>::Header>, Self::Error> {
Ok(match at {
BlockId::Number(num) => self.chain
.read()
.block_by_number
.get(num)
.map(|b| b[0].0.header().clone()),
BlockId::Hash(hash) => self.chain
.read()
.block_by_hash
.get(hash)
.map(|b| b.header().clone()),
BlockId::Number(num) =>
self.chain.read().block_by_number.get(num).map(|b| b[0].0.header().clone()),
BlockId::Hash(hash) =>
self.chain.read().block_by_hash.get(hash).map(|b| b.header().clone()),
})
}
}
@@ -369,21 +350,14 @@ impl sc_transaction_pool::test_helpers::ChainApi for TestApi {
impl sp_blockchain::HeaderMetadata<Block> for TestApi {
type Error = Error;
fn header_metadata(
&self,
hash: Hash,
) -> Result<CachedHeaderMetadata<Block>, Self::Error> {
fn header_metadata(&self, hash: Hash) -> Result<CachedHeaderMetadata<Block>, Self::Error> {
let chain = self.chain.read();
let block = chain.block_by_hash.get(&hash).expect("Hash exists");
Ok(block.header().into())
}
fn insert_header_metadata(
&self,
_: Hash,
_: CachedHeaderMetadata<Block>,
) {
fn insert_header_metadata(&self, _: Hash, _: CachedHeaderMetadata<Block>) {
unimplemented!("Not implemented for tests")
}
@@ -396,12 +370,7 @@ impl sp_blockchain::HeaderMetadata<Block> for TestApi {
///
/// Part of the test api.
pub fn uxt(who: AccountKeyring, nonce: Index) -> Extrinsic {
let transfer = Transfer {
from: who.into(),
to: AccountId::default(),
nonce,
amount: 1,
};
let transfer = Transfer { from: who.into(), to: AccountId::default(), nonce, amount: 1 };
let signature = transfer.using_encoded(|e| who.sign(e)).into();
Extrinsic::Transfer { transfer, signature, exhaust_resources_when_not_first: false }
}
+6 -4
View File
@@ -24,7 +24,7 @@ pub use futures;
///
/// # Requirements
///
/// You must have tokio in the `[dev-dependencies]` of your crate to use this macro.
/// You must have tokio in the `[dev-dependencies]` of your crate to use this macro.
///
/// # Example
///
@@ -64,7 +64,7 @@ macro_rules! assert_eq_uvec {
( $x:expr, $y:expr $(,)? ) => {
$crate::__assert_eq_uvec!($x, $y);
$crate::__assert_eq_uvec!($y, $x);
}
};
}
#[macro_export]
@@ -72,7 +72,9 @@ macro_rules! assert_eq_uvec {
macro_rules! __assert_eq_uvec {
( $x:expr, $y:expr ) => {
$x.iter().for_each(|e| {
if !$y.contains(e) { panic!("vectors not equal: {:?} != {:?}", $x, $y); }
if !$y.contains(e) {
panic!("vectors not equal: {:?} != {:?}", $x, $y);
}
});
}
};
}
+177 -163
View File
@@ -16,204 +16,218 @@
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
//! Client parts
use sp_transaction_pool::runtime_api::TaggedTransactionQueue;
use sp_consensus_babe::BabeApi;
use crate::{ChainInfo, default_config};
use manual_seal::consensus::babe::{BabeConsensusDataProvider, SlotTimestampProvider};
use sp_keyring::sr25519::Keyring::Alice;
use std::str::FromStr;
use sp_runtime::traits::Header;
use crate::{default_config, ChainInfo};
use futures::channel::mpsc;
use jsonrpc_core::MetaIoHandler;
use manual_seal::{run_manual_seal, EngineCommand, ManualSealParams, import_queue, rpc::{ManualSeal, ManualSealApi}};
use manual_seal::{
consensus::babe::{BabeConsensusDataProvider, SlotTimestampProvider},
import_queue,
rpc::{ManualSeal, ManualSealApi},
run_manual_seal, EngineCommand, ManualSealParams,
};
use sc_client_api::backend::Backend;
use sc_service::{
build_network, spawn_tasks, BuildNetworkParams, SpawnTasksParams, TFullBackend,
TFullClient, TaskManager, new_full_parts, Configuration, ChainSpec, TaskExecutor,
build_network, new_full_parts, spawn_tasks, BuildNetworkParams, ChainSpec, Configuration,
SpawnTasksParams, TFullBackend, TFullClient, TaskExecutor, TaskManager,
};
use sc_transaction_pool::BasicPool;
use sc_transaction_pool_api::TransactionPool;
use sp_api::{ApiExt, ConstructRuntimeApi, Core, Metadata};
use sp_block_builder::BlockBuilder;
use sp_runtime::traits::Block as BlockT;
use sp_session::SessionKeys;
use sp_consensus_babe::BabeApi;
use sp_keyring::sr25519::Keyring::Alice;
use sp_offchain::OffchainWorkerApi;
use std::sync::Arc;
use sp_runtime::traits::{Block as BlockT, Header};
use sp_session::SessionKeys;
use sp_transaction_pool::runtime_api::TaggedTransactionQueue;
use std::{str::FromStr, sync::Arc};
type ClientParts<T> = (
Arc<MetaIoHandler<sc_rpc::Metadata, sc_rpc_server::RpcMiddleware>>,
TaskManager,
Arc<TFullClient<<T as ChainInfo>::Block, <T as ChainInfo>::RuntimeApi, <T as ChainInfo>::Executor>>,
Arc<dyn TransactionPool<
Block = <T as ChainInfo>::Block,
Hash = <<T as ChainInfo>::Block as BlockT>::Hash,
Error = sc_transaction_pool::error::Error,
InPoolTransaction = sc_transaction_pool::Transaction<
<<T as ChainInfo>::Block as BlockT>::Hash,
<<T as ChainInfo>::Block as BlockT>::Extrinsic,
>,
>>,
mpsc::Sender<EngineCommand<<<T as ChainInfo>::Block as BlockT>::Hash>>,
Arc<TFullBackend<<T as ChainInfo>::Block>>,
Arc<MetaIoHandler<sc_rpc::Metadata, sc_rpc_server::RpcMiddleware>>,
TaskManager,
Arc<
TFullClient<
<T as ChainInfo>::Block,
<T as ChainInfo>::RuntimeApi,
<T as ChainInfo>::Executor,
>,
>,
Arc<
dyn TransactionPool<
Block = <T as ChainInfo>::Block,
Hash = <<T as ChainInfo>::Block as BlockT>::Hash,
Error = sc_transaction_pool::error::Error,
InPoolTransaction = sc_transaction_pool::Transaction<
<<T as ChainInfo>::Block as BlockT>::Hash,
<<T as ChainInfo>::Block as BlockT>::Extrinsic,
>,
>,
>,
mpsc::Sender<EngineCommand<<<T as ChainInfo>::Block as BlockT>::Hash>>,
Arc<TFullBackend<<T as ChainInfo>::Block>>,
);
/// Provide the config or chain spec for a given chain
pub enum ConfigOrChainSpec {
/// Configuration object
Config(Configuration),
/// Chain spec object
ChainSpec(Box<dyn ChainSpec>, TaskExecutor)
/// Configuration object
Config(Configuration),
/// Chain spec object
ChainSpec(Box<dyn ChainSpec>, TaskExecutor),
}
/// Creates all the client parts you need for [`Node`](crate::node::Node)
pub fn client_parts<T>(config_or_chain_spec: ConfigOrChainSpec) -> Result<ClientParts<T>, sc_service::Error>
where
T: ChainInfo + 'static,
<T::RuntimeApi as ConstructRuntimeApi<T::Block, TFullClient<T::Block, T::RuntimeApi, T::Executor>>>::RuntimeApi:
Core<T::Block> + Metadata<T::Block> + OffchainWorkerApi<T::Block> + SessionKeys<T::Block>
+ TaggedTransactionQueue<T::Block> + BlockBuilder<T::Block> + BabeApi<T::Block>
+ ApiExt<T::Block, StateBackend = <TFullBackend<T::Block> as Backend<T::Block>>::State>,
<T::Runtime as frame_system::Config>::Call: From<frame_system::Call<T::Runtime>>,
<<T as ChainInfo>::Block as BlockT>::Hash: FromStr,
<<<T as ChainInfo>::Block as BlockT>::Header as Header>::Number: num_traits::cast::AsPrimitive<usize>,
pub fn client_parts<T>(
config_or_chain_spec: ConfigOrChainSpec,
) -> Result<ClientParts<T>, sc_service::Error>
where
T: ChainInfo + 'static,
<T::RuntimeApi as ConstructRuntimeApi<
T::Block,
TFullClient<T::Block, T::RuntimeApi, T::Executor>,
>>::RuntimeApi: Core<T::Block>
+ Metadata<T::Block>
+ OffchainWorkerApi<T::Block>
+ SessionKeys<T::Block>
+ TaggedTransactionQueue<T::Block>
+ BlockBuilder<T::Block>
+ BabeApi<T::Block>
+ ApiExt<T::Block, StateBackend = <TFullBackend<T::Block> as Backend<T::Block>>::State>,
<T::Runtime as frame_system::Config>::Call: From<frame_system::Call<T::Runtime>>,
<<T as ChainInfo>::Block as BlockT>::Hash: FromStr,
<<<T as ChainInfo>::Block as BlockT>::Header as Header>::Number:
num_traits::cast::AsPrimitive<usize>,
{
use sp_consensus_babe::AuthorityId;
let config = match config_or_chain_spec {
ConfigOrChainSpec::Config(config) => config,
ConfigOrChainSpec::ChainSpec(chain_spec, task_executor) => {
default_config(task_executor, chain_spec)
},
};
use sp_consensus_babe::AuthorityId;
let config = match config_or_chain_spec {
ConfigOrChainSpec::Config(config) => config,
ConfigOrChainSpec::ChainSpec(chain_spec, task_executor) =>
default_config(task_executor, chain_spec),
};
let (client, backend, keystore, mut task_manager) =
new_full_parts::<T::Block, T::RuntimeApi, T::Executor>(&config, None)?;
let client = Arc::new(client);
let (client, backend, keystore, mut task_manager) =
new_full_parts::<T::Block, T::RuntimeApi, T::Executor>(&config, None)?;
let client = Arc::new(client);
let select_chain = sc_consensus::LongestChain::new(backend.clone());
let select_chain = sc_consensus::LongestChain::new(backend.clone());
let (grandpa_block_import, ..) =
grandpa::block_import(client.clone(), &(client.clone() as Arc<_>), select_chain.clone(), None)?;
let (grandpa_block_import, ..) = grandpa::block_import(
client.clone(),
&(client.clone() as Arc<_>),
select_chain.clone(),
None,
)?;
let slot_duration = sc_consensus_babe::Config::get_or_compute(&*client)?;
let (block_import, babe_link) = sc_consensus_babe::block_import(
slot_duration.clone(),
grandpa_block_import,
client.clone(),
)?;
let slot_duration = sc_consensus_babe::Config::get_or_compute(&*client)?;
let (block_import, babe_link) = sc_consensus_babe::block_import(
slot_duration.clone(),
grandpa_block_import,
client.clone(),
)?;
let consensus_data_provider = BabeConsensusDataProvider::new(
client.clone(),
keystore.sync_keystore(),
babe_link.epoch_changes().clone(),
vec![(AuthorityId::from(Alice.public()), 1000)],
)
.expect("failed to create ConsensusDataProvider");
let consensus_data_provider = BabeConsensusDataProvider::new(
client.clone(),
keystore.sync_keystore(),
babe_link.epoch_changes().clone(),
vec![(AuthorityId::from(Alice.public()), 1000)],
)
.expect("failed to create ConsensusDataProvider");
let import_queue =
import_queue(Box::new(block_import.clone()), &task_manager.spawn_essential_handle(), None);
let import_queue =
import_queue(Box::new(block_import.clone()), &task_manager.spawn_essential_handle(), None);
let transaction_pool = BasicPool::new_full(
config.transaction_pool.clone(),
true.into(),
config.prometheus_registry(),
task_manager.spawn_essential_handle(),
client.clone(),
);
let transaction_pool = BasicPool::new_full(
config.transaction_pool.clone(),
true.into(),
config.prometheus_registry(),
task_manager.spawn_essential_handle(),
client.clone(),
);
let (network, system_rpc_tx, network_starter) = {
let params = BuildNetworkParams {
config: &config,
client: client.clone(),
transaction_pool: transaction_pool.clone(),
spawn_handle: task_manager.spawn_handle(),
import_queue,
on_demand: None,
block_announce_validator_builder: None,
};
build_network(params)?
};
let (network, system_rpc_tx, network_starter) = {
let params = BuildNetworkParams {
config: &config,
client: client.clone(),
transaction_pool: transaction_pool.clone(),
spawn_handle: task_manager.spawn_handle(),
import_queue,
on_demand: None,
block_announce_validator_builder: None,
};
build_network(params)?
};
// offchain workers
sc_service::build_offchain_workers(
&config,
task_manager.spawn_handle(),
client.clone(),
network.clone(),
);
// offchain workers
sc_service::build_offchain_workers(
&config,
task_manager.spawn_handle(),
client.clone(),
network.clone(),
);
// Proposer object for block authorship.
let env = sc_basic_authorship::ProposerFactory::new(
task_manager.spawn_handle(),
client.clone(),
transaction_pool.clone(),
config.prometheus_registry(),
None
);
// Proposer object for block authorship.
let env = sc_basic_authorship::ProposerFactory::new(
task_manager.spawn_handle(),
client.clone(),
transaction_pool.clone(),
config.prometheus_registry(),
None,
);
// Channel for the rpc handler to communicate with the authorship task.
let (command_sink, commands_stream) = mpsc::channel(10);
// Channel for the rpc handler to communicate with the authorship task.
let (command_sink, commands_stream) = mpsc::channel(10);
let rpc_sink = command_sink.clone();
let rpc_sink = command_sink.clone();
let rpc_handlers = {
let params = SpawnTasksParams {
config,
client: client.clone(),
backend: backend.clone(),
task_manager: &mut task_manager,
keystore: keystore.sync_keystore(),
on_demand: None,
transaction_pool: transaction_pool.clone(),
rpc_extensions_builder: Box::new(move |_, _| {
let mut io = jsonrpc_core::IoHandler::default();
io.extend_with(
ManualSealApi::to_delegate(ManualSeal::new(rpc_sink.clone()))
);
io
}),
remote_blockchain: None,
network,
system_rpc_tx,
telemetry: None
};
spawn_tasks(params)?
};
let rpc_handlers = {
let params = SpawnTasksParams {
config,
client: client.clone(),
backend: backend.clone(),
task_manager: &mut task_manager,
keystore: keystore.sync_keystore(),
on_demand: None,
transaction_pool: transaction_pool.clone(),
rpc_extensions_builder: Box::new(move |_, _| {
let mut io = jsonrpc_core::IoHandler::default();
io.extend_with(ManualSealApi::to_delegate(ManualSeal::new(rpc_sink.clone())));
io
}),
remote_blockchain: None,
network,
system_rpc_tx,
telemetry: None,
};
spawn_tasks(params)?
};
let cloned_client = client.clone();
let create_inherent_data_providers = Box::new(move |_, _| {
let client = cloned_client.clone();
async move {
let timestamp = SlotTimestampProvider::new(client.clone()).map_err(|err| format!("{:?}", err))?;
let babe = sp_consensus_babe::inherents::InherentDataProvider::new(timestamp.slot().into());
Ok((timestamp, babe))
}
});
let cloned_client = client.clone();
let create_inherent_data_providers = Box::new(move |_, _| {
let client = cloned_client.clone();
async move {
let timestamp =
SlotTimestampProvider::new(client.clone()).map_err(|err| format!("{:?}", err))?;
let babe =
sp_consensus_babe::inherents::InherentDataProvider::new(timestamp.slot().into());
Ok((timestamp, babe))
}
});
// Background authorship future.
let authorship_future = run_manual_seal(ManualSealParams {
block_import,
env,
client: client.clone(),
pool: transaction_pool.clone(),
commands_stream,
select_chain,
consensus_data_provider: Some(Box::new(consensus_data_provider)),
create_inherent_data_providers,
});
// Background authorship future.
let authorship_future = run_manual_seal(ManualSealParams {
block_import,
env,
client: client.clone(),
pool: transaction_pool.clone(),
commands_stream,
select_chain,
consensus_data_provider: Some(Box::new(consensus_data_provider)),
create_inherent_data_providers,
});
// spawn the authorship task as an essential task.
task_manager
.spawn_essential_handle()
.spawn("manual-seal", authorship_future);
// spawn the authorship task as an essential task.
task_manager.spawn_essential_handle().spawn("manual-seal", authorship_future);
network_starter.start_network();
let rpc_handler = rpc_handlers.io_handler();
network_starter.start_network();
let rpc_handler = rpc_handlers.io_handler();
Ok((
rpc_handler,
task_manager,
client,
transaction_pool,
command_sink,
backend,
))
Ok((rpc_handler, task_manager, client, transaction_pool, command_sink, backend))
}
@@ -73,12 +73,16 @@ macro_rules! override_host_functions {
pub struct SignatureVerificationOverride;
impl sp_wasm_interface::HostFunctions for SignatureVerificationOverride {
fn host_functions() -> Vec<&'static dyn sp_wasm_interface::Function> {
override_host_functions!(
"ext_crypto_ecdsa_verify_version_1", EcdsaVerify,
"ext_crypto_ed25519_verify_version_1", Ed25519Verify,
"ext_crypto_sr25519_verify_version_1", Sr25519Verify,
"ext_crypto_sr25519_verify_version_2", Sr25519VerifyV2,
)
}
fn host_functions() -> Vec<&'static dyn sp_wasm_interface::Function> {
override_host_functions!(
"ext_crypto_ecdsa_verify_version_1",
EcdsaVerify,
"ext_crypto_ed25519_verify_version_1",
Ed25519Verify,
"ext_crypto_sr25519_verify_version_1",
Sr25519Verify,
"ext_crypto_sr25519_verify_version_2",
Sr25519VerifyV2,
)
}
}
+15 -10
View File
@@ -187,12 +187,12 @@
//! fn simple_balances_test() {
//! // given
//! let config = NodeConfig {
//! execution_strategies: ExecutionStrategies {
//! syncing: sc_client_api::ExecutionStrategy::NativeWhenPossible,
//! importing: sc_client_api::ExecutionStrategy::NativeWhenPossible,
//! block_construction: sc_client_api::ExecutionStrategy::NativeWhenPossible,
//! offchain_worker: sc_client_api::ExecutionStrategy::NativeWhenPossible,
//! other: sc_client_api::ExecutionStrategy::NativeWhenPossible,
//! execution_strategies: ExecutionStrategies {
//! syncing: sc_client_api::ExecutionStrategy::NativeWhenPossible,
//! importing: sc_client_api::ExecutionStrategy::NativeWhenPossible,
//! block_construction: sc_client_api::ExecutionStrategy::NativeWhenPossible,
//! offchain_worker: sc_client_api::ExecutionStrategy::NativeWhenPossible,
//! other: sc_client_api::ExecutionStrategy::NativeWhenPossible,
//! },
//! chain_spec: Box::new(development_config()),
//! log_targets: vec![],
@@ -235,14 +235,14 @@ use sp_inherents::InherentDataProvider;
use sp_runtime::traits::{Block as BlockT, SignedExtension};
mod client;
mod host_functions;
mod node;
mod utils;
mod host_functions;
pub use client::*;
pub use host_functions::*;
pub use node::*;
pub use utils::*;
pub use client::*;
/// Wrapper trait for concrete type required by this testing framework.
pub trait ChainInfo: Sized {
@@ -271,7 +271,10 @@ pub trait ChainInfo: Sized {
+ BlockImport<
Self::Block,
Error = sp_consensus::Error,
Transaction = TransactionFor<TFullClient<Self::Block, Self::RuntimeApi, Self::Executor>, Self::Block>,
Transaction = TransactionFor<
TFullClient<Self::Block, Self::RuntimeApi, Self::Executor>,
Self::Block,
>,
> + 'static;
/// The signed extras required by the runtime
@@ -281,5 +284,7 @@ pub trait ChainInfo: Sized {
type InherentDataProviders: InherentDataProvider + 'static;
/// Signed extras, this function is caled in an externalities provided environment.
fn signed_extras(from: <Self::Runtime as frame_system::Config>::AccountId) -> Self::SignedExtras;
fn signed_extras(
from: <Self::Runtime as frame_system::Config>::AccountId,
) -> Self::SignedExtras;
}
+72 -47
View File
@@ -18,21 +18,28 @@
use std::sync::Arc;
use futures::{FutureExt, SinkExt, channel::{mpsc, oneshot}};
use crate::ChainInfo;
use futures::{
channel::{mpsc, oneshot},
FutureExt, SinkExt,
};
use jsonrpc_core::MetaIoHandler;
use manual_seal::EngineCommand;
use sc_client_api::{backend::{self, Backend}, CallExecutor, ExecutorProvider};
use sc_client_api::{
backend::{self, Backend},
CallExecutor, ExecutorProvider,
};
use sc_service::{TFullBackend, TFullCallExecutor, TFullClient, TaskManager};
use sc_transaction_pool_api::TransactionPool;
use sp_api::{OverlayedChanges, StorageTransactionCache};
use sp_blockchain::HeaderBackend;
use sp_core::ExecutionContext;
use sp_runtime::{
generic::{BlockId, UncheckedExtrinsic},
traits::{Block as BlockT, Header, Extrinsic, NumberFor},
transaction_validity::TransactionSource, MultiSignature, MultiAddress
traits::{Block as BlockT, Extrinsic, Header, NumberFor},
transaction_validity::TransactionSource,
MultiAddress, MultiSignature,
};
use crate::ChainInfo;
use sc_transaction_pool_api::TransactionPool;
use sp_state_machine::Ext;
/// This holds a reference to a running node on another thread,
@@ -46,36 +53,8 @@ pub struct Node<T: ChainInfo> {
/// client instance
client: Arc<TFullClient<T::Block, T::RuntimeApi, T::Executor>>,
/// transaction pool
pool: Arc<dyn TransactionPool<
Block = <T as ChainInfo>::Block,
Hash = <<T as ChainInfo>::Block as BlockT>::Hash,
Error = sc_transaction_pool::error::Error,
InPoolTransaction = sc_transaction_pool::Transaction<
<<T as ChainInfo>::Block as BlockT>::Hash,
<<T as ChainInfo>::Block as BlockT>::Extrinsic,
>,
>>,
/// channel to communicate with manual seal on.
manual_seal_command_sink: mpsc::Sender<EngineCommand<<T::Block as BlockT>::Hash>>,
/// backend type.
backend: Arc<TFullBackend<T::Block>>,
/// Block number at initialization of this Node.
initial_block_number: NumberFor<T::Block>
}
type EventRecord<T> = frame_system::EventRecord<<T as frame_system::Config>::Event, <T as frame_system::Config>::Hash>;
impl<T> Node<T>
where
T: ChainInfo,
<<T::Block as BlockT>::Header as Header>::Number: From<u32>,
{
/// Creates a new node.
pub fn new(
rpc_handler: Arc<MetaIoHandler<sc_rpc::Metadata, sc_rpc_server::RpcMiddleware>>,
task_manager: TaskManager,
client: Arc<TFullClient<T::Block, T::RuntimeApi, T::Executor>>,
pool: Arc<dyn TransactionPool<
pool: Arc<
dyn TransactionPool<
Block = <T as ChainInfo>::Block,
Hash = <<T as ChainInfo>::Block as BlockT>::Hash,
Error = sc_transaction_pool::error::Error,
@@ -83,7 +62,42 @@ impl<T> Node<T>
<<T as ChainInfo>::Block as BlockT>::Hash,
<<T as ChainInfo>::Block as BlockT>::Extrinsic,
>,
>>,
>,
>,
/// channel to communicate with manual seal on.
manual_seal_command_sink: mpsc::Sender<EngineCommand<<T::Block as BlockT>::Hash>>,
/// backend type.
backend: Arc<TFullBackend<T::Block>>,
/// Block number at initialization of this Node.
initial_block_number: NumberFor<T::Block>,
}
type EventRecord<T> = frame_system::EventRecord<
<T as frame_system::Config>::Event,
<T as frame_system::Config>::Hash,
>;
impl<T> Node<T>
where
T: ChainInfo,
<<T::Block as BlockT>::Header as Header>::Number: From<u32>,
{
/// Creates a new node.
pub fn new(
rpc_handler: Arc<MetaIoHandler<sc_rpc::Metadata, sc_rpc_server::RpcMiddleware>>,
task_manager: TaskManager,
client: Arc<TFullClient<T::Block, T::RuntimeApi, T::Executor>>,
pool: Arc<
dyn TransactionPool<
Block = <T as ChainInfo>::Block,
Hash = <<T as ChainInfo>::Block as BlockT>::Hash,
Error = sc_transaction_pool::error::Error,
InPoolTransaction = sc_transaction_pool::Transaction<
<<T as ChainInfo>::Block as BlockT>::Hash,
<<T as ChainInfo>::Block as BlockT>::Extrinsic,
>,
>,
>,
command_sink: mpsc::Sender<EngineCommand<<T::Block as BlockT>::Hash>>,
backend: Arc<TFullBackend<T::Block>>,
) -> Self {
@@ -102,10 +116,12 @@ impl<T> Node<T>
/// eg
/// ```ignore
/// let request = r#"{"jsonrpc":"2.0","method":"engine_createBlock","params": [true, true],"id":1}"#;
/// let response = node.rpc_handler()
/// let response = node.rpc_handler()
/// .handle_request_sync(request, Default::default());
/// ```
pub fn rpc_handler(&self) -> Arc<MetaIoHandler<sc_rpc::Metadata, sc_rpc_server::RpcMiddleware>> {
pub fn rpc_handler(
&self,
) -> Arc<MetaIoHandler<sc_rpc::Metadata, sc_rpc_server::RpcMiddleware>> {
self.rpc_handler.clone()
}
@@ -117,13 +133,18 @@ impl<T> Node<T>
/// Executes closure in an externalities provided environment.
pub fn with_state<R>(&self, closure: impl FnOnce() -> R) -> R
where
<TFullCallExecutor<T::Block, T::Executor> as CallExecutor<T::Block>>::Error: std::fmt::Debug,
<TFullCallExecutor<T::Block, T::Executor> as CallExecutor<T::Block>>::Error:
std::fmt::Debug,
{
let id = BlockId::Hash(self.client.info().best_hash);
let mut overlay = OverlayedChanges::default();
let changes_trie = backend::changes_tries_state_at_block(&id, self.backend.changes_trie_storage()).unwrap();
let mut cache =
StorageTransactionCache::<T::Block, <TFullBackend<T::Block> as Backend<T::Block>>::State>::default();
let changes_trie =
backend::changes_tries_state_at_block(&id, self.backend.changes_trie_storage())
.unwrap();
let mut cache = StorageTransactionCache::<
T::Block,
<TFullBackend<T::Block> as Backend<T::Block>>::State,
>::default();
let mut extensions = self
.client
.execution_extensions()
@@ -176,7 +197,9 @@ impl<T> Node<T>
.expect("UncheckedExtrinsic::new() always returns Some");
let at = self.client.info().best_hash;
self.pool.submit_one(&BlockId::Hash(at), TransactionSource::Local, ext.into()).await
self.pool
.submit_one(&BlockId::Hash(at), TransactionSource::Local, ext.into())
.await
}
/// Get the events of the most recently produced block
@@ -186,7 +209,7 @@ impl<T> Node<T>
/// Instructs manual seal to seal new, possibly empty blocks.
pub async fn seal_blocks(&self, num: usize) {
let mut sink = self.manual_seal_command_sink.clone();
let mut sink = self.manual_seal_command_sink.clone();
for count in 0..num {
let (sender, future_block) = oneshot::channel();
@@ -201,8 +224,10 @@ impl<T> Node<T>
future.await.expect(ERROR);
match future_block.await.expect(ERROR) {
Ok(block) => log::info!("sealed {} (hash: {}) of {} blocks", count + 1, block.hash, num),
Err(err) => log::error!("failed to seal block {} of {}, error: {:?}", count + 1, num, err),
Ok(block) =>
log::info!("sealed {} (hash: {}) of {} blocks", count + 1, block.hash, num),
Err(err) =>
log::error!("failed to seal block {} of {}, error: {:?}", count + 1, num, err),
}
}
}
+19 -21
View File
@@ -16,18 +16,20 @@
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
use futures::FutureExt;
use sc_client_api::execution_extensions::ExecutionStrategies;
use sc_executor::WasmExecutionMethod;
use sc_informant::OutputFormat;
use sc_network::{
config::{NetworkConfiguration, Role, TransportConfig},
multiaddr,
};
use sc_service::{
BasePath, ChainSpec, Configuration, TaskExecutor,
DatabaseConfig, KeepBlocks, TransactionStorageMode, TaskType,
config::KeystoreConfig, BasePath, ChainSpec, Configuration, DatabaseConfig, KeepBlocks,
TaskExecutor, TaskType, TransactionStorageMode,
};
use sp_keyring::sr25519::Keyring::Alice;
use sc_network::{multiaddr, config::{NetworkConfiguration, TransportConfig, Role}};
use sc_informant::OutputFormat;
use sc_service::config::KeystoreConfig;
use sc_executor::WasmExecutionMethod;
use sc_client_api::execution_extensions::ExecutionStrategies;
use tokio::runtime::Handle;
use futures::FutureExt;
pub use sc_cli::build_runtime;
@@ -41,7 +43,10 @@ pub fn base_path() -> BasePath {
}
/// Produces a default configuration object, suitable for use with most set ups.
pub fn default_config(task_executor: TaskExecutor, mut chain_spec: Box<dyn ChainSpec>) -> Configuration {
pub fn default_config(
task_executor: TaskExecutor,
mut chain_spec: Box<dyn ChainSpec>,
) -> Configuration {
let base_path = base_path();
let root_path = base_path.path().to_path_buf().join("chains").join(chain_spec.id());
@@ -62,9 +67,7 @@ pub fn default_config(task_executor: TaskExecutor, mut chain_spec: Box<dyn Chain
let informant_output_format = OutputFormat { enable_color: false };
network_config.allow_non_globals_in_dht = true;
network_config
.listen_addresses
.push(multiaddr::Protocol::Memory(0).into());
network_config.listen_addresses.push(multiaddr::Protocol::Memory(0).into());
network_config.transport = TransportConfig::MemoryOnly;
@@ -75,14 +78,8 @@ pub fn default_config(task_executor: TaskExecutor, mut chain_spec: Box<dyn Chain
task_executor: task_executor.into(),
transaction_pool: Default::default(),
network: network_config,
keystore: KeystoreConfig::Path {
path: root_path.join("key"),
password: None,
},
database: DatabaseConfig::RocksDb {
path: root_path.join("db"),
cache_size: 128,
},
keystore: KeystoreConfig::Path { path: root_path.join("key"), password: None },
database: DatabaseConfig::RocksDb { path: root_path.join("db"), cache_size: 128 },
state_cache_size: 16777216,
state_cache_child_ratio: None,
chain_spec,
@@ -129,7 +126,8 @@ pub fn default_config(task_executor: TaskExecutor, mut chain_spec: Box<dyn Chain
pub fn task_executor(handle: Handle) -> TaskExecutor {
let task_executor = move |fut, task_type| match task_type {
TaskType::Async => handle.spawn(fut).map(drop),
TaskType::Blocking => handle.spawn_blocking(move || futures::executor::block_on(fut)).map(drop),
TaskType::Blocking =>
handle.spawn_blocking(move || futures::executor::block_on(fut)).map(drop),
};
task_executor.into()