diff --git a/substrate/Cargo.lock b/substrate/Cargo.lock
index ce65894b13..8194c0a1b1 100644
--- a/substrate/Cargo.lock
+++ b/substrate/Cargo.lock
@@ -1200,7 +1200,7 @@ dependencies = [
"cranelift-codegen 0.76.0",
"cranelift-entity 0.76.0",
"cranelift-frontend 0.76.0",
- "itertools 0.10.0",
+ "itertools",
"log 0.4.14",
"serde",
"smallvec 1.7.0",
@@ -1219,16 +1219,17 @@ dependencies = [
[[package]]
name = "criterion"
-version = "0.3.4"
+version = "0.3.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ab327ed7354547cc2ef43cbe20ef68b988e70b4b593cbd66a2a61733123a3d23"
+checksum = "1604dafd25fba2fe2d5895a9da139f8dc9b319a5fe5354ca137cbbce4e178d10"
dependencies = [
"atty",
"cast",
"clap",
"criterion-plot",
"csv",
- "itertools 0.10.0",
+ "futures 0.3.16",
+ "itertools",
"lazy_static",
"num-traits",
"oorandom",
@@ -1240,17 +1241,18 @@ dependencies = [
"serde_derive",
"serde_json",
"tinytemplate",
+ "tokio",
"walkdir",
]
[[package]]
name = "criterion-plot"
-version = "0.4.3"
+version = "0.4.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e022feadec601fba1649cfa83586381a4ad31c6bf3a9ab7d408118b05dd9889d"
+checksum = "d00996de9f2f7559f7f4dc286073197f83e92256a59ed395f9aac01fe717da57"
dependencies = [
"cast",
- "itertools 0.9.0",
+ "itertools",
]
[[package]]
@@ -2943,15 +2945,6 @@ version = "2.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "47be2f14c678be2fdcab04ab1171db51b2762ce6f0a8ee87c8dd4a04ed216135"
-[[package]]
-name = "itertools"
-version = "0.9.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "284f18f85651fe11e8a991b2adb42cb078325c996ed026d994719efcfca1d54b"
-dependencies = [
- "either",
-]
-
[[package]]
name = "itertools"
version = "0.10.0"
@@ -2978,9 +2971,9 @@ dependencies = [
[[package]]
name = "js-sys"
-version = "0.3.50"
+version = "0.3.54"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2d99f9e3e84b8f67f846ef5b4cbbc3b1c29f6c759fcbce6f01aa0e73d932a24c"
+checksum = "1866b355d9c878e5e607473cbe3f63282c0b7aad2db1dbebf55076c686918254"
dependencies = [
"wasm-bindgen",
]
@@ -4469,8 +4462,10 @@ version = "3.0.0-dev"
dependencies = [
"assert_cmd",
"async-std",
+ "criterion",
"frame-benchmarking-cli",
"frame-system",
+ "frame-system-rpc-runtime-api",
"futures 0.3.16",
"hex-literal",
"jsonrpsee-ws-client",
@@ -4481,6 +4476,7 @@ dependencies = [
"node-primitives",
"node-rpc",
"node-runtime",
+ "pallet-balances",
"pallet-im-online",
"pallet-transaction-payment",
"parity-scale-codec",
@@ -4513,6 +4509,7 @@ dependencies = [
"serde",
"serde_json",
"soketto 0.4.2",
+ "sp-api",
"sp-authority-discovery",
"sp-authorship",
"sp-consensus",
@@ -6538,9 +6535,9 @@ checksum = "989d43012e2ca1c4a02507c67282691a0a3207f9dc67cec596b43fe925b3d325"
[[package]]
name = "plotters"
-version = "0.3.0"
+version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "45ca0ae5f169d0917a7c7f5a9c1a3d3d9598f18f529dd2b8373ed988efea307a"
+checksum = "32a3fd9ec30b9749ce28cd91f255d569591cdf937fe280c312143e3c4bad6f2a"
dependencies = [
"num-traits",
"plotters-backend",
@@ -6780,7 +6777,7 @@ checksum = "355f634b43cdd80724ee7848f95770e7e70eefa6dcf14fea676216573b8fd603"
dependencies = [
"bytes 1.0.1",
"heck",
- "itertools 0.10.0",
+ "itertools",
"log 0.4.14",
"multimap",
"petgraph",
@@ -6797,7 +6794,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "600d2f334aa05acb02a755e217ef1ab6dea4d51b58b7846588b747edec04efba"
dependencies = [
"anyhow",
- "itertools 0.10.0",
+ "itertools",
"proc-macro2",
"quote",
"syn",
@@ -11115,9 +11112,9 @@ checksum = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f"
[[package]]
name = "wasm-bindgen"
-version = "0.2.73"
+version = "0.2.77"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "83240549659d187488f91f33c0f8547cbfef0b2088bc470c116d1d260ef623d9"
+checksum = "5e68338db6becec24d3c7977b5bf8a48be992c934b5d07177e3931f5dc9b076c"
dependencies = [
"cfg-if 1.0.0",
"wasm-bindgen-macro",
@@ -11125,9 +11122,9 @@ dependencies = [
[[package]]
name = "wasm-bindgen-backend"
-version = "0.2.73"
+version = "0.2.77"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ae70622411ca953215ca6d06d3ebeb1e915f0f6613e3b495122878d7ebec7dae"
+checksum = "f34c405b4f0658583dba0c1c7c9b694f3cac32655db463b56c254a1c75269523"
dependencies = [
"bumpalo",
"lazy_static",
@@ -11152,9 +11149,9 @@ dependencies = [
[[package]]
name = "wasm-bindgen-macro"
-version = "0.2.73"
+version = "0.2.77"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3e734d91443f177bfdb41969de821e15c516931c3c3db3d318fa1b68975d0f6f"
+checksum = "b9d5a6580be83b19dc570a8f9c324251687ab2184e57086f71625feb57ec77c8"
dependencies = [
"quote",
"wasm-bindgen-macro-support",
@@ -11162,9 +11159,9 @@ dependencies = [
[[package]]
name = "wasm-bindgen-macro-support"
-version = "0.2.73"
+version = "0.2.77"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d53739ff08c8a68b0fdbcd54c372b8ab800b1449ab3c9d706503bc7dd1621b2c"
+checksum = "e3775a030dc6f5a0afd8a84981a21cc92a781eb429acef9ecce476d0c9113e92"
dependencies = [
"proc-macro2",
"quote",
@@ -11175,9 +11172,9 @@ dependencies = [
[[package]]
name = "wasm-bindgen-shared"
-version = "0.2.73"
+version = "0.2.77"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d9a543ae66aa233d14bb765ed9af4a33e81b8b58d1584cf1b47ff8cd0b9e4489"
+checksum = "c279e376c7a8e8752a8f1eaa35b7b0bee6bb9fb0cdacfa97cc3f1f289c87e2b4"
[[package]]
name = "wasm-gc-api"
@@ -11648,9 +11645,9 @@ dependencies = [
[[package]]
name = "web-sys"
-version = "0.3.47"
+version = "0.3.54"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c40dc691fc48003eba817c38da7113c15698142da971298003cac3ef175680b3"
+checksum = "0a84d70d1ec7d2da2d26a5bd78f4bca1b8c3254805363ce743b7a05bc30d195a"
dependencies = [
"js-sys",
"wasm-bindgen",
diff --git a/substrate/bin/node/cli/Cargo.toml b/substrate/bin/node/cli/Cargo.toml
index 42bc48e824..8b14f1cbee 100644
--- a/substrate/bin/node/cli/Cargo.toml
+++ b/substrate/bin/node/cli/Cargo.toml
@@ -46,6 +46,7 @@ structopt = { version = "0.3.8", optional = true }
sp-authority-discovery = { version = "4.0.0-dev", path = "../../../primitives/authority-discovery" }
sp-consensus-babe = { version = "0.10.0-dev", path = "../../../primitives/consensus/babe" }
grandpa-primitives = { version = "4.0.0-dev", package = "sp-finality-grandpa", path = "../../../primitives/finality-grandpa" }
+sp-api = { version = "4.0.0-dev", path = "../../../primitives/api" }
sp-core = { version = "4.0.0-dev", path = "../../../primitives/core" }
sp-runtime = { version = "4.0.0-dev", path = "../../../primitives/runtime" }
sp-timestamp = { version = "4.0.0-dev", path = "../../../primitives/timestamp" }
@@ -78,6 +79,7 @@ sc-sync-state-rpc = { version = "0.10.0-dev", path = "../../../client/sync-state
# frame dependencies
frame-system = { version = "4.0.0-dev", path = "../../../frame/system" }
+frame-system-rpc-runtime-api = { version = "4.0.0-dev", path = "../../../frame/system/rpc/runtime-api" }
pallet-transaction-payment = { version = "4.0.0-dev", path = "../../../frame/transaction-payment" }
pallet-im-online = { version = "4.0.0-dev", default-features = false, path = "../../../frame/im-online" }
@@ -124,8 +126,9 @@ regex = "1"
platforms = "1.1"
async-std = { version = "1.10.0", features = ["attributes"] }
soketto = "0.4.2"
-jsonrpsee-ws-client = { version = "0.3.0", default-features = false, features = ["tokio1"] }
+criterion = { version = "0.3.5", features = [ "async_tokio" ] }
tokio = { version = "1.10", features = ["macros", "time"] }
+jsonrpsee-ws-client = { version = "0.3.0", default-features = false, features = ["tokio1"] }
wait-timeout = "0.2"
remote-externalities = { path = "../../../utils/frame/remote-externalities" }
@@ -137,6 +140,7 @@ substrate-build-script-utils = { version = "3.0.0", optional = true, path = "../
substrate-frame-cli = { version = "4.0.0-dev", optional = true, path = "../../../utils/frame/frame-utilities-cli" }
try-runtime-cli = { version = "0.10.0-dev", optional = true, path = "../../../utils/frame/try-runtime/cli" }
sc-cli = { version = "0.10.0-dev", path = "../../../client/cli", optional = true }
+pallet-balances = { version = "4.0.0-dev", path = "../../../frame/balances" }
[features]
default = ["cli"]
@@ -158,3 +162,7 @@ runtime-benchmarks = [
# Enable features that allow the runtime to be tried and debugged. Name might be subject to change
# in the near future.
try-runtime = ["node-runtime/try-runtime", "try-runtime-cli"]
+
+[[bench]]
+name = "transaction_pool"
+harness = false
diff --git a/substrate/bin/node/cli/benches/transaction_pool.rs b/substrate/bin/node/cli/benches/transaction_pool.rs
new file mode 100644
index 0000000000..c435012e9f
--- /dev/null
+++ b/substrate/bin/node/cli/benches/transaction_pool.rs
@@ -0,0 +1,274 @@
+// This file is part of Substrate.
+
+// Copyright (C) 2021 Parity Technologies (UK) Ltd.
+// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0
+
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see .
+
+use criterion::{criterion_group, criterion_main, BatchSize, Criterion, Throughput};
+use futures::{future, StreamExt};
+use node_cli::service::{create_extrinsic, fetch_nonce, FullClient, TransactionPool};
+use node_primitives::AccountId;
+use node_runtime::{constants::currency::*, BalancesCall, SudoCall};
+use sc_client_api::execution_extensions::ExecutionStrategies;
+use sc_service::{
+ config::{
+ DatabaseSource, KeepBlocks, KeystoreConfig, NetworkConfiguration, OffchainWorkerConfig,
+ PruningMode, TransactionPoolOptions, TransactionStorageMode, WasmExecutionMethod,
+ },
+ BasePath, Configuration, Role,
+};
+use sc_transaction_pool::PoolLimit;
+use sc_transaction_pool_api::{TransactionPool as _, TransactionSource, TransactionStatus};
+use sp_core::{crypto::Pair, sr25519};
+use sp_keyring::Sr25519Keyring;
+use sp_runtime::{generic::BlockId, OpaqueExtrinsic};
+use tokio::runtime::Handle;
+
+fn new_node(tokio_handle: Handle) -> node_cli::service::NewFullBase {
+ let base_path = BasePath::new_temp_dir().expect("Creates base path");
+ let root = base_path.path().to_path_buf();
+
+ let network_config = NetworkConfiguration::new(
+ Sr25519Keyring::Alice.to_seed(),
+ "network/test/0.1",
+ Default::default(),
+ None,
+ );
+
+ let spec = Box::new(node_cli::chain_spec::development_config());
+
+ let config = Configuration {
+ impl_name: "BenchmarkImpl".into(),
+ impl_version: "1.0".into(),
+ role: Role::Authority,
+ tokio_handle,
+ transaction_pool: TransactionPoolOptions {
+ ready: PoolLimit { count: 100_000, total_bytes: 100 * 1024 * 1024 },
+ future: PoolLimit { count: 100_000, total_bytes: 100 * 1024 * 1024 },
+ reject_future_transactions: false,
+ },
+ network: network_config,
+ keystore: KeystoreConfig::InMemory,
+ keystore_remote: Default::default(),
+ database: DatabaseSource::RocksDb { path: root.join("db"), cache_size: 128 },
+ state_cache_size: 67108864,
+ state_cache_child_ratio: None,
+ state_pruning: PruningMode::ArchiveAll,
+ keep_blocks: KeepBlocks::All,
+ transaction_storage: TransactionStorageMode::BlockBody,
+ chain_spec: spec,
+ wasm_method: WasmExecutionMethod::Interpreted,
+ // NOTE: we enforce the use of the native runtime to make the errors more debuggable
+ 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,
+ },
+ rpc_http: None,
+ rpc_ws: None,
+ rpc_ipc: None,
+ rpc_ws_max_connections: None,
+ rpc_cors: None,
+ rpc_methods: Default::default(),
+ rpc_max_payload: None,
+ prometheus_config: None,
+ telemetry_endpoints: None,
+ default_heap_pages: None,
+ offchain_worker: OffchainWorkerConfig { enabled: true, indexing_enabled: false },
+ force_authoring: false,
+ disable_grandpa: false,
+ dev_key_seed: Some(Sr25519Keyring::Alice.to_seed()),
+ tracing_targets: None,
+ tracing_receiver: Default::default(),
+ max_runtime_instances: 8,
+ announce_block: true,
+ base_path: Some(base_path),
+ informant_output_format: Default::default(),
+ wasm_runtime_overrides: None,
+ disable_log_reloading: false,
+ };
+
+ node_cli::service::new_full_base(config, |_, _| ()).expect("Creates node")
+}
+
+fn create_accounts(num: usize) -> Vec {
+ (0..num)
+ .map(|i| {
+ Pair::from_string(&format!("{}/{}", Sr25519Keyring::Alice.to_seed(), i), None)
+ .expect("Creates account pair")
+ })
+ .collect()
+}
+
+/// Create the extrinsics that will initialize the accounts from the sudo account (Alice).
+///
+/// `start_nonce` is the current nonce of Alice.
+fn create_account_extrinsics(
+ client: &FullClient,
+ accounts: &[sr25519::Pair],
+) -> Vec {
+ let start_nonce = fetch_nonce(client, Sr25519Keyring::Alice.pair());
+
+ accounts
+ .iter()
+ .enumerate()
+ .map(|(i, a)| {
+ vec![
+ // Reset the nonce by removing any funds
+ create_extrinsic(
+ client,
+ Sr25519Keyring::Alice.pair(),
+ SudoCall::sudo {
+ call: Box::new(
+ BalancesCall::set_balance {
+ who: AccountId::from(a.public()).into(),
+ new_free: 0,
+ new_reserved: 0,
+ }
+ .into(),
+ ),
+ },
+ Some(start_nonce + (i as u32) * 2),
+ ),
+ // Give back funds
+ create_extrinsic(
+ client,
+ Sr25519Keyring::Alice.pair(),
+ SudoCall::sudo {
+ call: Box::new(
+ BalancesCall::set_balance {
+ who: AccountId::from(a.public()).into(),
+ new_free: 1_000_000 * DOLLARS,
+ new_reserved: 0,
+ }
+ .into(),
+ ),
+ },
+ Some(start_nonce + (i as u32) * 2 + 1),
+ ),
+ ]
+ })
+ .flatten()
+ .map(OpaqueExtrinsic::from)
+ .collect()
+}
+
+fn create_benchmark_extrinsics(
+ client: &FullClient,
+ accounts: &[sr25519::Pair],
+ extrinsics_per_account: usize,
+) -> Vec {
+ accounts
+ .iter()
+ .map(|account| {
+ (0..extrinsics_per_account).map(move |nonce| {
+ create_extrinsic(
+ client,
+ account.clone(),
+ BalancesCall::transfer {
+ dest: Sr25519Keyring::Bob.to_account_id().into(),
+ value: 1 * DOLLARS,
+ },
+ Some(nonce as u32),
+ )
+ })
+ })
+ .flatten()
+ .map(OpaqueExtrinsic::from)
+ .collect()
+}
+
+async fn submit_tx_and_wait_for_inclusion(
+ tx_pool: &TransactionPool,
+ tx: OpaqueExtrinsic,
+ client: &FullClient,
+ wait_for_finalized: bool,
+) {
+ let best_hash = client.chain_info().best_hash;
+
+ let mut watch = tx_pool
+ .submit_and_watch(&BlockId::Hash(best_hash), TransactionSource::External, tx.clone())
+ .await
+ .expect("Submits tx to pool")
+ .fuse();
+
+ loop {
+ match watch.select_next_some().await {
+ TransactionStatus::Finalized(_) => break,
+ TransactionStatus::InBlock(_) if !wait_for_finalized => break,
+ _ => {},
+ }
+ }
+}
+
+fn transaction_pool_benchmarks(c: &mut Criterion) {
+ sp_tracing::try_init_simple();
+
+ let runtime = tokio::runtime::Runtime::new().expect("Creates tokio runtime");
+ let tokio_handle = runtime.handle().clone();
+
+ let node = new_node(tokio_handle.clone());
+
+ let account_num = 10;
+ let extrinsics_per_account = 2000;
+ let accounts = create_accounts(account_num);
+
+ let mut group = c.benchmark_group("Transaction pool");
+
+ group.sample_size(10);
+ group.throughput(Throughput::Elements(account_num as u64 * extrinsics_per_account as u64));
+
+ let mut counter = 1;
+ group.bench_function(
+ format!("{} transfers from {} accounts", account_num * extrinsics_per_account, account_num),
+ move |b| {
+ b.iter_batched(
+ || {
+ let prepare_extrinsics = create_account_extrinsics(&*node.client, &accounts);
+
+ runtime.block_on(future::join_all(prepare_extrinsics.into_iter().map(|tx| {
+ submit_tx_and_wait_for_inclusion(
+ &node.transaction_pool,
+ tx,
+ &*node.client,
+ true,
+ )
+ })));
+
+ create_benchmark_extrinsics(&*node.client, &accounts, extrinsics_per_account)
+ },
+ |extrinsics| {
+ runtime.block_on(future::join_all(extrinsics.into_iter().map(|tx| {
+ submit_tx_and_wait_for_inclusion(
+ &node.transaction_pool,
+ tx,
+ &*node.client,
+ false,
+ )
+ })));
+
+ println!("Finished {}", counter);
+ counter += 1;
+ },
+ BatchSize::SmallInput,
+ )
+ },
+ );
+}
+
+criterion_group!(benches, transaction_pool_benchmarks);
+criterion_main!(benches);
diff --git a/substrate/bin/node/cli/src/lib.rs b/substrate/bin/node/cli/src/lib.rs
index 1a4c1b0eab..ae851c6cdf 100644
--- a/substrate/bin/node/cli/src/lib.rs
+++ b/substrate/bin/node/cli/src/lib.rs
@@ -33,7 +33,7 @@
pub mod chain_spec;
#[macro_use]
-mod service;
+pub mod service;
#[cfg(feature = "cli")]
mod cli;
#[cfg(feature = "cli")]
diff --git a/substrate/bin/node/cli/src/service.rs b/substrate/bin/node/cli/src/service.rs
index ec5497ab47..938f359368 100644
--- a/substrate/bin/node/cli/src/service.rs
+++ b/substrate/bin/node/cli/src/service.rs
@@ -20,20 +20,25 @@
//! Service implementation. Specialized wrapper over substrate service.
+use codec::Encode;
+use frame_system_rpc_runtime_api::AccountNonceApi;
use futures::prelude::*;
use node_executor::ExecutorDispatch;
use node_primitives::Block;
use node_runtime::RuntimeApi;
-use sc_client_api::{ExecutorProvider, RemoteBackend};
+use sc_client_api::{BlockBackend, ExecutorProvider, RemoteBackend};
use sc_consensus_babe::{self, SlotProportion};
use sc_executor::NativeElseWasmExecutor;
use sc_network::{Event, NetworkService};
use sc_service::{config::Configuration, error::Error as ServiceError, RpcHandlers, TaskManager};
use sc_telemetry::{Telemetry, TelemetryWorker};
-use sp_runtime::traits::Block as BlockT;
+use sp_api::ProvideRuntimeApi;
+use sp_core::crypto::Pair;
+use sp_runtime::{generic, traits::Block as BlockT, SaturatedConversion};
use std::sync::Arc;
-type FullClient =
+/// The full client type definition.
+pub type FullClient =
sc_service::TFullClient>;
type FullBackend = sc_service::TFullBackend;
type FullSelectChain = sc_consensus::LongestChain;
@@ -41,7 +46,80 @@ type FullGrandpaBlockImport =
grandpa::GrandpaBlockImport;
type LightClient =
sc_service::TLightClient>;
+/// The transaction pool type defintion.
+pub type TransactionPool = sc_transaction_pool::FullPool;
+/// Fetch the nonce of the given `account` from the chain state.
+///
+/// Note: Should only be used for tests.
+pub fn fetch_nonce(client: &FullClient, account: sp_core::sr25519::Pair) -> u32 {
+ let best_hash = client.chain_info().best_hash;
+ client
+ .runtime_api()
+ .account_nonce(&generic::BlockId::Hash(best_hash), account.public().into())
+ .expect("Fetching account nonce works; qed")
+}
+
+/// Create a transaction using the given `call`.
+///
+/// The transaction will be signed by `sender`. If `nonce` is `None` it will be fetched from the
+/// state of the best block.
+///
+/// Note: Should only be used for tests.
+pub fn create_extrinsic(
+ client: &FullClient,
+ sender: sp_core::sr25519::Pair,
+ function: impl Into,
+ nonce: Option,
+) -> node_runtime::UncheckedExtrinsic {
+ let function = function.into();
+ let genesis_hash = client.block_hash(0).ok().flatten().expect("Genesis block exists; qed");
+ let best_hash = client.chain_info().best_hash;
+ let best_block = client.chain_info().best_number;
+ let nonce = nonce.unwrap_or_else(|| fetch_nonce(client, sender.clone()));
+
+ let period = node_runtime::BlockHashCount::get()
+ .checked_next_power_of_two()
+ .map(|c| c / 2)
+ .unwrap_or(2) as u64;
+ let tip = 0;
+ let extra: node_runtime::SignedExtra = (
+ frame_system::CheckSpecVersion::::new(),
+ frame_system::CheckTxVersion::::new(),
+ frame_system::CheckGenesis::::new(),
+ frame_system::CheckEra::::from(generic::Era::mortal(
+ period,
+ best_block.saturated_into(),
+ )),
+ frame_system::CheckNonce::::from(nonce),
+ frame_system::CheckWeight::::new(),
+ pallet_transaction_payment::ChargeTransactionPayment::::from(tip),
+ );
+
+ let raw_payload = node_runtime::SignedPayload::from_raw(
+ function.clone(),
+ extra.clone(),
+ (
+ node_runtime::VERSION.spec_version,
+ node_runtime::VERSION.transaction_version,
+ genesis_hash,
+ best_hash,
+ (),
+ (),
+ (),
+ ),
+ );
+ let signature = raw_payload.using_encoded(|e| sender.sign(e));
+
+ node_runtime::UncheckedExtrinsic::new_signed(
+ function.clone(),
+ sp_runtime::AccountId32::from(sender.public()).into(),
+ node_runtime::Signature::Sr25519(signature.clone()),
+ extra.clone(),
+ )
+}
+
+/// Creates a new partial node.
pub fn new_partial(
config: &Configuration,
) -> Result<
@@ -211,11 +289,16 @@ pub fn new_partial(
})
}
+/// Result of [`new_full_base`].
pub struct NewFullBase {
+ /// The task manager of the node.
pub task_manager: TaskManager,
+ /// The client instance of the node.
pub client: Arc,
+ /// The networking service of the node.
pub network: Arc::Hash>>,
- pub transaction_pool: Arc>,
+ /// The transaction pool of the node.
+ pub transaction_pool: Arc,
}
/// Creates a full service from the configuration.
@@ -433,6 +516,7 @@ pub fn new_full(config: Configuration) -> Result {
new_full_base(config, |_, _| ()).map(|NewFullBase { task_manager, .. }| task_manager)
}
+/// Creates a light service from the configuration.
pub fn new_light_base(
mut config: Configuration,
) -> Result<
diff --git a/substrate/bin/node/runtime/src/lib.rs b/substrate/bin/node/runtime/src/lib.rs
index 9fac468519..4f620976c3 100644
--- a/substrate/bin/node/runtime/src/lib.rs
+++ b/substrate/bin/node/runtime/src/lib.rs
@@ -81,6 +81,8 @@ pub use pallet_balances::Call as BalancesCall;
#[cfg(any(feature = "std", test))]
pub use pallet_staking::StakerStatus;
#[cfg(any(feature = "std", test))]
+pub use pallet_sudo::Call as SudoCall;
+#[cfg(any(feature = "std", test))]
pub use sp_runtime::BuildStorage;
/// Implementations of some helper traits passed into runtime modules as associated types.
diff --git a/substrate/client/transaction-pool/src/graph/ready.rs b/substrate/client/transaction-pool/src/graph/ready.rs
index 99a034689c..92adf2e62d 100644
--- a/substrate/client/transaction-pool/src/graph/ready.rs
+++ b/substrate/client/transaction-pool/src/graph/ready.rs
@@ -31,7 +31,7 @@ use sp_runtime::{traits::Member, transaction_validity::TransactionTag as Tag};
use super::{
base_pool::Transaction,
future::WaitingTransaction,
- tracked_map::{self, ReadOnlyTrackedMap, TrackedMap},
+ tracked_map::{self, TrackedMap},
};
/// An in-pool transaction reference.
@@ -162,7 +162,7 @@ impl ReadyTransactions {
/// skipped.
pub fn get(&self) -> BestIterator {
BestIterator {
- all: self.ready.clone(),
+ all: self.ready.clone_map(),
best: self.best.clone(),
awaiting: Default::default(),
invalid: Default::default(),
@@ -484,7 +484,7 @@ impl ReadyTransactions {
/// Iterator of ready transactions ordered by priority.
pub struct BestIterator {
- all: ReadOnlyTrackedMap>,
+ all: HashMap>,
awaiting: HashMap)>,
best: BTreeSet>,
invalid: HashSet,
@@ -519,7 +519,7 @@ impl BestIterator {
/// When given transaction is not in the pool it has no effect.
/// When invoked on a fully drained iterator it has no effect either.
pub fn report_invalid(&mut self, tx: &Arc>) {
- if let Some(to_report) = self.all.read().get(&tx.hash) {
+ if let Some(to_report) = self.all.get(&tx.hash) {
debug!(
target: "txpool",
"[{:?}] Reported as invalid. Will skip sub-chains while iterating.",
@@ -551,8 +551,7 @@ impl Iterator for BestIterator {
continue
}
- let next = self.all.read().get(hash).cloned();
- let ready = match next {
+ let ready = match self.all.get(&hash).cloned() {
Some(ready) => ready,
// The transaction is not in all, maybe it was removed in the meantime?
None => continue,
@@ -567,7 +566,6 @@ impl Iterator for BestIterator {
// then get from the pool
} else {
self.all
- .read()
.get(hash)
.map(|next| (next.requires_offset + 1, next.transaction.clone()))
};
diff --git a/substrate/client/transaction-pool/src/graph/tracked_map.rs b/substrate/client/transaction-pool/src/graph/tracked_map.rs
index c1fdda227c..2f560d1c56 100644
--- a/substrate/client/transaction-pool/src/graph/tracked_map.rs
+++ b/substrate/client/transaction-pool/src/graph/tracked_map.rs
@@ -57,11 +57,6 @@ impl TrackedMap {
std::cmp::max(self.bytes.load(AtomicOrdering::Relaxed), 0) as usize
}
- /// Read-only clone of the interior.
- pub fn clone(&self) -> ReadOnlyTrackedMap {
- ReadOnlyTrackedMap(self.index.clone())
- }
-
/// Lock map for read.
pub fn read(&self) -> TrackedMapReadAccess {
TrackedMapReadAccess { inner_guard: self.index.read() }
@@ -77,18 +72,10 @@ impl TrackedMap {
}
}
-/// Read-only access to map.
-///
-/// The only thing can be done is .read().
-pub struct ReadOnlyTrackedMap(Arc>>);
-
-impl ReadOnlyTrackedMap
-where
- K: Eq + std::hash::Hash,
-{
- /// Lock map for read.
- pub fn read(&self) -> TrackedMapReadAccess {
- TrackedMapReadAccess { inner_guard: self.0.read() }
+impl TrackedMap {
+ /// Clone the inner map.
+ pub fn clone_map(&self) -> HashMap {
+ self.index.read().clone()
}
}
diff --git a/substrate/client/transaction-pool/src/lib.rs b/substrate/client/transaction-pool/src/lib.rs
index 4d355df22d..8af73c3fe5 100644
--- a/substrate/client/transaction-pool/src/lib.rs
+++ b/substrate/client/transaction-pool/src/lib.rs
@@ -44,7 +44,7 @@ use futures::{
future::{self, ready},
prelude::*,
};
-pub use graph::{ChainApi, Options, Pool, Transaction};
+pub use graph::{base_pool::Limit as PoolLimit, ChainApi, Options, Pool, Transaction};
use parking_lot::Mutex;
use std::{
collections::{HashMap, HashSet},