diff --git a/Cargo.lock b/Cargo.lock
index 8b0273d199144..94f3f5effea98 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -3362,6 +3362,7 @@ version = "0.8.0-rc4"
dependencies = [
"derive_more",
"fs_extra",
+ "futures 0.3.5",
"hash-db",
"hex",
"kvdb",
@@ -3374,13 +3375,19 @@ dependencies = [
"parity-db",
"parity-util-mem",
"rand 0.7.3",
+ "sc-basic-authorship",
"sc-cli",
"sc-client-api",
"serde",
"serde_json",
+ "sp-consensus",
"sp-core",
+ "sp-finality-tracker",
+ "sp-inherents",
"sp-runtime",
"sp-state-machine",
+ "sp-timestamp",
+ "sp-transaction-pool",
"sp-trie",
"structopt",
"tempfile",
diff --git a/bin/node/bench/Cargo.toml b/bin/node/bench/Cargo.toml
index ab156635ec9aa..07db27a1f1809 100644
--- a/bin/node/bench/Cargo.toml
+++ b/bin/node/bench/Cargo.toml
@@ -25,6 +25,12 @@ kvdb = "0.6"
kvdb-rocksdb = "0.8"
sp-trie = { version = "2.0.0-rc4", path = "../../../primitives/trie" }
sp-core = { version = "2.0.0-rc4", path = "../../../primitives/core" }
+sp-consensus = { version = "0.8.0-rc4", path = "../../../primitives/consensus/common" }
+sp-transaction-pool = { version = "2.0.0-rc4", path = "../../../primitives/transaction-pool" }
+sc-basic-authorship = { version = "0.8.0-rc4", path = "../../../client/basic-authorship" }
+sp-inherents = { version = "2.0.0-rc4", path = "../../../primitives/inherents" }
+sp-finality-tracker = { version = "2.0.0-rc4", default-features = false, path = "../../../primitives/finality-tracker" }
+sp-timestamp = { version = "2.0.0-rc4", default-features = false, path = "../../../primitives/timestamp" }
hash-db = "0.15.2"
tempfile = "3.1.0"
fs_extra = "1"
@@ -33,3 +39,4 @@ rand = { version = "0.7.2", features = ["small_rng"] }
lazy_static = "1.4.0"
parity-util-mem = { version = "0.6.1", default-features = false, features = ["primitive-types"] }
parity-db = { version = "0.1.2" }
+futures = "0.3.1"
diff --git a/bin/node/bench/src/common.rs b/bin/node/bench/src/common.rs
new file mode 100644
index 0000000000000..2637d6e9bd04d
--- /dev/null
+++ b/bin/node/bench/src/common.rs
@@ -0,0 +1,48 @@
+
+// This file is part of Substrate.
+
+// Copyright (C) 2020 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 .
+
+#[derive(Clone, Copy, Debug, derive_more::Display)]
+pub enum SizeType {
+ #[display(fmt = "empty")]
+ Empty,
+ #[display(fmt = "small")]
+ Small,
+ #[display(fmt = "medium")]
+ Medium,
+ #[display(fmt = "large")]
+ Large,
+ #[display(fmt = "full")]
+ Full,
+ #[display(fmt = "custom")]
+ Custom(usize),
+}
+
+impl SizeType {
+ pub fn transactions(&self) -> Option {
+ match self {
+ SizeType::Empty => Some(0),
+ SizeType::Small => Some(10),
+ SizeType::Medium => Some(100),
+ SizeType::Large => Some(500),
+ SizeType::Full => None,
+ // Custom SizeType will use the `--transactions` input parameter
+ SizeType::Custom(val) => Some(*val),
+ }
+ }
+}
\ No newline at end of file
diff --git a/bin/node/bench/src/construct.rs b/bin/node/bench/src/construct.rs
new file mode 100644
index 0000000000000..e23594dd4364a
--- /dev/null
+++ b/bin/node/bench/src/construct.rs
@@ -0,0 +1,296 @@
+// This file is part of Substrate.
+
+// Copyright (C) 2020 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 .
+
+//! Block construction benchmark.
+//!
+//! This benchmark is expected to measure block construction.
+//! We want to protect against cold-cache attacks, and so this
+//! benchmark should not rely on any caching (except those entries that
+//! DO NOT depend on user input). Thus transaction generation should be
+//! based on randomized data.
+
+use std::{
+ borrow::Cow,
+ collections::HashMap,
+ pin::Pin,
+ sync::Arc,
+};
+use futures::Future;
+
+use node_primitives::Block;
+use node_testing::bench::{BenchDb, Profile, BlockType, KeyTypes, DatabaseType};
+use sp_runtime::{
+ generic::BlockId,
+ traits::NumberFor,
+ OpaqueExtrinsic,
+};
+use sp_transaction_pool::{
+ ImportNotificationStream,
+ PoolFuture,
+ PoolStatus,
+ TransactionFor,
+ TransactionSource,
+ TransactionStatusStreamFor,
+ TxHash,
+};
+use sp_consensus::{Environment, Proposer, RecordProof};
+
+use crate::{
+ common::SizeType,
+ core::{self, Path, Mode},
+};
+
+pub struct ConstructionBenchmarkDescription {
+ pub profile: Profile,
+ pub key_types: KeyTypes,
+ pub block_type: BlockType,
+ pub size: SizeType,
+ pub database_type: DatabaseType,
+}
+
+pub struct ConstructionBenchmark {
+ profile: Profile,
+ database: BenchDb,
+ transactions: Transactions,
+}
+
+impl core::BenchmarkDescription for ConstructionBenchmarkDescription {
+ fn path(&self) -> Path {
+
+ let mut path = Path::new(&["node", "proposer"]);
+
+ match self.profile {
+ Profile::Wasm => path.push("wasm"),
+ Profile::Native => path.push("native"),
+ }
+
+ match self.key_types {
+ KeyTypes::Sr25519 => path.push("sr25519"),
+ KeyTypes::Ed25519 => path.push("ed25519"),
+ }
+
+ match self.block_type {
+ BlockType::RandomTransfersKeepAlive => path.push("transfer"),
+ BlockType::RandomTransfersReaping => path.push("transfer_reaping"),
+ BlockType::Noop => path.push("noop"),
+ }
+
+ match self.database_type {
+ DatabaseType::RocksDb => path.push("rocksdb"),
+ DatabaseType::ParityDb => path.push("paritydb"),
+ }
+
+ path.push(&format!("{}", self.size));
+
+ path
+ }
+
+ fn setup(self: Box) -> Box {
+ let mut extrinsics: Vec> = Vec::new();
+
+ let mut bench_db = BenchDb::with_key_types(
+ self.database_type,
+ 50_000,
+ self.key_types
+ );
+
+ let client = bench_db.client();
+
+ let content_type = self.block_type.to_content(self.size.transactions());
+ for transaction in bench_db.block_content(content_type, &client) {
+ extrinsics.push(Arc::new(transaction.into()));
+ }
+
+ Box::new(ConstructionBenchmark {
+ profile: self.profile,
+ database: bench_db,
+ transactions: Transactions(extrinsics),
+ })
+ }
+
+ fn name(&self) -> Cow<'static, str> {
+ format!(
+ "Block construction ({:?}/{}, {:?}, {:?} backend)",
+ self.block_type,
+ self.size,
+ self.profile,
+ self.database_type,
+ ).into()
+ }
+}
+
+impl core::Benchmark for ConstructionBenchmark {
+ fn run(&mut self, mode: Mode) -> std::time::Duration {
+ let context = self.database.create_context(self.profile);
+
+ let _ = context.client.runtime_version_at(&BlockId::Number(0))
+ .expect("Failed to get runtime version")
+ .spec_version;
+
+ if mode == Mode::Profile {
+ std::thread::park_timeout(std::time::Duration::from_secs(3));
+ }
+
+ let mut proposer_factory = sc_basic_authorship::ProposerFactory::new(
+ context.client.clone(),
+ self.transactions.clone().into(),
+ None,
+ );
+ let inherent_data_providers = sp_inherents::InherentDataProviders::new();
+ inherent_data_providers
+ .register_provider(sp_timestamp::InherentDataProvider)
+ .expect("Failed to register timestamp data provider");
+
+ let start = std::time::Instant::now();
+
+ let proposer = futures::executor::block_on(proposer_factory.init(
+ &context.client.header(&BlockId::number(0))
+ .expect("Database error querying block #0")
+ .expect("Block #0 should exist"),
+ )).expect("Proposer initialization failed");
+
+ let _block = futures::executor::block_on(
+ proposer.propose(
+ inherent_data_providers.create_inherent_data().expect("Create inherent data failed"),
+ Default::default(),
+ std::time::Duration::from_secs(20),
+ RecordProof::Yes,
+ ),
+ ).map(|r| r.block).expect("Proposing failed");
+
+ let elapsed = start.elapsed();
+
+ if mode == Mode::Profile {
+ std::thread::park_timeout(std::time::Duration::from_secs(1));
+ }
+
+ elapsed
+ }
+}
+
+#[derive(Clone, Debug)]
+pub struct PoolTransaction {
+ data: OpaqueExtrinsic,
+ hash: node_primitives::Hash,
+}
+
+impl From for PoolTransaction {
+ fn from(e: OpaqueExtrinsic) -> Self {
+ PoolTransaction {
+ data: e,
+ hash: node_primitives::Hash::zero(),
+ }
+ }
+}
+
+impl sp_transaction_pool::InPoolTransaction for PoolTransaction {
+ type Transaction = OpaqueExtrinsic;
+ type Hash = node_primitives::Hash;
+
+ fn data(&self) -> &Self::Transaction {
+ &self.data
+ }
+
+ fn hash(&self) -> &Self::Hash {
+ &self.hash
+ }
+
+ fn priority(&self) -> &u64 { unimplemented!() }
+
+ fn longevity(&self) -> &u64 { unimplemented!() }
+
+ fn requires(&self) -> &[Vec] { unimplemented!() }
+
+ fn provides(&self) -> &[Vec] { unimplemented!() }
+
+ fn is_propagable(&self) -> bool { unimplemented!() }
+}
+
+#[derive(Clone, Debug)]
+pub struct Transactions(Vec>);
+
+impl sp_transaction_pool::TransactionPool for Transactions {
+ type Block = Block;
+ type Hash = node_primitives::Hash;
+ type InPoolTransaction = PoolTransaction;
+ type Error = sp_transaction_pool::error::Error;
+
+ /// Returns a future that imports a bunch of unverified transactions to the pool.
+ fn submit_at(
+ &self,
+ _at: &BlockId,
+ _source: TransactionSource,
+ _xts: Vec>,
+ ) -> PoolFuture>, Self::Error> {
+ unimplemented!()
+ }
+
+ /// Returns a future that imports one unverified transaction to the pool.
+ fn submit_one(
+ &self,
+ _at: &BlockId,
+ _source: TransactionSource,
+ _xt: TransactionFor,
+ ) -> PoolFuture, Self::Error> {
+ unimplemented!()
+ }
+
+ fn submit_and_watch(
+ &self,
+ _at: &BlockId,
+ _source: TransactionSource,
+ _xt: TransactionFor,
+ ) -> PoolFuture>, Self::Error> {
+ unimplemented!()
+ }
+
+ fn ready_at(&self, _at: NumberFor)
+ -> Pin> + Send>> + Send>>
+ {
+ let iter: Box> + Send> = Box::new(self.0.clone().into_iter());
+ Box::pin(futures::future::ready(iter))
+ }
+
+ fn ready(&self) -> Box> + Send> {
+ unimplemented!()
+ }
+
+ fn remove_invalid(&self, _hashes: &[TxHash]) -> Vec> {
+ Default::default()
+ }
+
+ fn status(&self) -> PoolStatus {
+ unimplemented!()
+ }
+
+ fn import_notification_stream(&self) -> ImportNotificationStream> {
+ unimplemented!()
+ }
+
+ fn on_broadcasted(&self, _propagations: HashMap, Vec>) {
+ unimplemented!()
+ }
+
+ fn hash_of(&self, _xt: &TransactionFor) -> TxHash {
+ unimplemented!()
+ }
+
+ fn ready_transaction(&self, _hash: &TxHash) -> Option> {
+ unimplemented!()
+ }
+}
\ No newline at end of file
diff --git a/bin/node/bench/src/import.rs b/bin/node/bench/src/import.rs
index c1b324c03cf2b..e49a359fb6af1 100644
--- a/bin/node/bench/src/import.rs
+++ b/bin/node/bench/src/import.rs
@@ -38,37 +38,10 @@ use sc_client_api::backend::Backend;
use sp_runtime::generic::BlockId;
use sp_state_machine::InspectState;
-use crate::core::{self, Path, Mode};
-
-#[derive(Clone, Copy, Debug, derive_more::Display)]
-pub enum SizeType {
- #[display(fmt = "empty")]
- Empty,
- #[display(fmt = "small")]
- Small,
- #[display(fmt = "medium")]
- Medium,
- #[display(fmt = "large")]
- Large,
- #[display(fmt = "full")]
- Full,
- #[display(fmt = "custom")]
- Custom(usize),
-}
-
-impl SizeType {
- pub fn transactions(&self) -> Option {
- match self {
- SizeType::Empty => Some(0),
- SizeType::Small => Some(10),
- SizeType::Medium => Some(100),
- SizeType::Large => Some(500),
- SizeType::Full => None,
- // Custom SizeType will use the `--transactions` input parameter
- SizeType::Custom(val) => Some(*val),
- }
- }
-}
+use crate::{
+ common::SizeType,
+ core::{self, Path, Mode},
+};
pub struct ImportBenchmarkDescription {
pub profile: Profile,
@@ -134,8 +107,9 @@ impl core::BenchmarkDescription for ImportBenchmarkDescription {
fn name(&self) -> Cow<'static, str> {
format!(
- "Import benchmark ({:?}, {:?}, {:?} backend)",
+ "Block import ({:?}/{}, {:?}, {:?} backend)",
self.block_type,
+ self.size,
self.profile,
self.database_type,
).into()
diff --git a/bin/node/bench/src/main.rs b/bin/node/bench/src/main.rs
index 5c5af3703857a..11820247112f8 100644
--- a/bin/node/bench/src/main.rs
+++ b/bin/node/bench/src/main.rs
@@ -16,21 +16,29 @@
// You should have received a copy of the GNU General Public License
// along with this program. If not, see .
+mod common;
+mod construct;
#[macro_use] mod core;
mod import;
-mod trie;
-mod simple_trie;
mod generator;
-mod tempdb;
+mod simple_trie;
mod state_sizes;
+mod tempdb;
+mod trie;
-use crate::core::{run_benchmark, Mode as BenchmarkMode};
-use crate::tempdb::DatabaseType;
-use import::{ImportBenchmarkDescription, SizeType};
-use trie::{TrieReadBenchmarkDescription, TrieWriteBenchmarkDescription, DatabaseSize};
-use node_testing::bench::{Profile, KeyTypes, BlockType, DatabaseType as BenchDataBaseType};
use structopt::StructOpt;
+use node_testing::bench::{Profile, KeyTypes, BlockType, DatabaseType as BenchDataBaseType};
+
+use crate::{
+ common::SizeType,
+ core::{run_benchmark, Mode as BenchmarkMode},
+ tempdb::DatabaseType,
+ import::ImportBenchmarkDescription,
+ trie::{TrieReadBenchmarkDescription, TrieWriteBenchmarkDescription, DatabaseSize},
+ construct::ConstructionBenchmarkDescription,
+};
+
#[derive(Debug, StructOpt)]
#[structopt(name = "node-bench", about = "Node integration benchmarks")]
struct Opt {
@@ -126,6 +134,20 @@ fn main() {
]
.iter().map(move |db_type| (size, db_type)))
=> TrieWriteBenchmarkDescription { database_size: *size, database_type: *db_type },
+ ConstructionBenchmarkDescription {
+ profile: Profile::Wasm,
+ key_types: KeyTypes::Sr25519,
+ block_type: BlockType::RandomTransfersKeepAlive,
+ size: SizeType::Medium,
+ database_type: BenchDataBaseType::RocksDb,
+ },
+ ConstructionBenchmarkDescription {
+ profile: Profile::Wasm,
+ key_types: KeyTypes::Sr25519,
+ block_type: BlockType::RandomTransfersKeepAlive,
+ size: SizeType::Large,
+ database_type: BenchDataBaseType::RocksDb,
+ },
);
if opt.list {
diff --git a/bin/node/testing/src/bench.rs b/bin/node/testing/src/bench.rs
index 5df2709f87053..507d3420d8354 100644
--- a/bin/node/testing/src/bench.rs
+++ b/bin/node/testing/src/bench.rs
@@ -152,20 +152,12 @@ impl BlockType {
}
/// Content of the generated block.
+#[derive(Clone, Debug)]
pub struct BlockContent {
block_type: BlockType,
size: Option,
}
-impl BlockContent {
- fn iter_while(&self, mut f: impl FnMut(usize) -> bool) {
- match self.size {
- Some(v) => { for i in 0..v { if !f(i) { break; }}}
- None => { for i in 0.. { if !f(i) { break; }}}
- }
- }
-}
-
/// Type of backend database.
#[derive(Debug, PartialEq, Clone, Copy)]
pub enum DatabaseType {
@@ -219,6 +211,93 @@ impl CloneableSpawn for TaskExecutor {
}
}
+/// Iterator for block content.
+pub struct BlockContentIterator<'a> {
+ iteration: usize,
+ content: BlockContent,
+ runtime_version: sc_executor::RuntimeVersion,
+ genesis_hash: node_primitives::Hash,
+ keyring: &'a BenchKeyring,
+}
+
+impl<'a> BlockContentIterator<'a> {
+ fn new(content: BlockContent, keyring: &'a BenchKeyring, client: &Client) -> Self {
+ let runtime_version = client.runtime_version_at(&BlockId::number(0))
+ .expect("There should be runtime version at 0");
+
+ let genesis_hash = client.block_hash(Zero::zero())
+ .expect("Database error?")
+ .expect("Genesis block always exists; qed")
+ .into();
+
+ BlockContentIterator {
+ iteration: 0,
+ content,
+ keyring,
+ runtime_version,
+ genesis_hash,
+ }
+ }
+}
+
+impl<'a> Iterator for BlockContentIterator<'a> {
+ type Item = OpaqueExtrinsic;
+
+ fn next(&mut self) -> Option {
+ if self.content.size.map(|size| size <= self.iteration).unwrap_or(false) {
+ return None;
+ }
+
+ let sender = self.keyring.at(self.iteration);
+ let receiver = get_account_id_from_seed::(
+ &format!("random-user//{}", self.iteration)
+ );
+
+ let signed = self.keyring.sign(
+ CheckedExtrinsic {
+ signed: Some((sender, signed_extra(0, node_runtime::ExistentialDeposit::get() + 1))),
+ function: match self.content.block_type {
+ BlockType::RandomTransfersKeepAlive => {
+ Call::Balances(
+ BalancesCall::transfer_keep_alive(
+ pallet_indices::address::Address::Id(receiver),
+ node_runtime::ExistentialDeposit::get() + 1,
+ )
+ )
+ },
+ BlockType::RandomTransfersReaping => {
+ Call::Balances(
+ BalancesCall::transfer(
+ pallet_indices::address::Address::Id(receiver),
+ // Transfer so that ending balance would be 1 less than existential deposit
+ // so that we kill the sender account.
+ 100*DOLLARS - (node_runtime::ExistentialDeposit::get() - 1),
+ )
+ )
+ },
+ BlockType::Noop => {
+ Call::System(
+ SystemCall::remark(Vec::new())
+ )
+ },
+ },
+ },
+ self.runtime_version.spec_version,
+ self.runtime_version.transaction_version,
+ self.genesis_hash.into(),
+ );
+
+ let encoded = Encode::encode(&signed);
+
+ let opaque = OpaqueExtrinsic::decode(&mut &encoded[..])
+ .expect("Failed to decode opaque");
+
+ self.iteration += 1;
+
+ Some(opaque)
+ }
+}
+
impl BenchDb {
/// New immutable benchmarking database.
///
@@ -288,8 +367,33 @@ impl BenchDb {
(client, backend)
}
- /// Generate new block using this database.
- pub fn generate_block(&mut self, content: BlockContent) -> Block {
+ /// Generate list of required inherents.
+ ///
+ /// Uses already instantiated Client.
+ pub fn generate_inherents(&mut self, client: &Client) -> Vec {
+ let mut inherent_data = InherentData::new();
+ let timestamp = 1 * MinimumPeriod::get();
+
+ inherent_data.put_data(sp_timestamp::INHERENT_IDENTIFIER, ×tamp)
+ .expect("Put timestamp failed");
+ inherent_data.put_data(sp_finality_tracker::INHERENT_IDENTIFIER, &0)
+ .expect("Put finality tracker failed");
+
+ client.runtime_api()
+ .inherent_extrinsics_with_context(
+ &BlockId::number(0),
+ ExecutionContext::BlockConstruction,
+ inherent_data,
+ ).expect("Get inherents failed")
+ }
+
+ /// Iterate over some block content with transaction signed using this database keyring.
+ pub fn block_content(&self, content: BlockContent, client: &Client) -> BlockContentIterator {
+ BlockContentIterator::new(content, &self.keyring, client)
+ }
+
+ /// Get cliet for this database operations.
+ pub fn client(&mut self) -> Client {
let (client, _backend) = Self::bench_client(
self.database_type,
self.directory_guard.path(),
@@ -297,92 +401,33 @@ impl BenchDb {
&self.keyring,
);
- let runtime_version = client.runtime_version_at(&BlockId::number(0))
- .expect("There should be runtime version at 0");
+ client
+ }
- let genesis_hash = client.block_hash(Zero::zero())
- .expect("Database error?")
- .expect("Genesis block always exists; qed")
- .into();
+ /// Generate new block using this database.
+ pub fn generate_block(&mut self, content: BlockContent) -> Block {
+ let client = self.client();
let mut block = client
.new_block(Default::default())
.expect("Block creation failed");
- let timestamp = 1 * MinimumPeriod::get();
-
- let mut inherent_data = InherentData::new();
- inherent_data.put_data(sp_timestamp::INHERENT_IDENTIFIER, ×tamp)
- .expect("Put timestamp failed");
- inherent_data.put_data(sp_finality_tracker::INHERENT_IDENTIFIER, &0)
- .expect("Put finality tracker failed");
-
- for extrinsic in client.runtime_api()
- .inherent_extrinsics_with_context(
- &BlockId::number(0),
- ExecutionContext::BlockConstruction,
- inherent_data,
- ).expect("Get inherents failed")
- {
+ for extrinsic in self.generate_inherents(&client) {
block.push(extrinsic).expect("Push inherent failed");
}
let start = std::time::Instant::now();
- content.iter_while(|iteration| {
- let sender = self.keyring.at(iteration);
- let receiver = get_account_id_from_seed::(
- &format!("random-user//{}", iteration)
- );
-
- let signed = self.keyring.sign(
- CheckedExtrinsic {
- signed: Some((sender, signed_extra(0, node_runtime::ExistentialDeposit::get() + 1))),
- function: match content.block_type {
- BlockType::RandomTransfersKeepAlive => {
- Call::Balances(
- BalancesCall::transfer_keep_alive(
- pallet_indices::address::Address::Id(receiver),
- node_runtime::ExistentialDeposit::get() + 1,
- )
- )
- },
- BlockType::RandomTransfersReaping => {
- Call::Balances(
- BalancesCall::transfer(
- pallet_indices::address::Address::Id(receiver),
- // Transfer so that ending balance would be 1 less than existential deposit
- // so that we kill the sender account.
- 100*DOLLARS - (node_runtime::ExistentialDeposit::get() - 1),
- )
- )
- },
- BlockType::Noop => {
- Call::System(
- SystemCall::remark(Vec::new())
- )
- },
- },
- },
- runtime_version.spec_version,
- runtime_version.transaction_version,
- genesis_hash,
- );
-
- let encoded = Encode::encode(&signed);
-
- let opaque = OpaqueExtrinsic::decode(&mut &encoded[..])
- .expect("Failed to decode opaque");
-
+ for opaque in self.block_content(content, &client) {
match block.push(opaque) {
Err(sp_blockchain::Error::ApplyExtrinsicFailed(
sp_blockchain::ApplyExtrinsicFailed::Validity(e)
)) if e.exhausted_resources() => {
- return false;
+ break;
},
Err(err) => panic!("Error pushing transaction: {:?}", err),
- Ok(_) => true,
+ Ok(_) => {},
}
- });
+ };
let block = block.build().expect("Block build failed").block;
@@ -411,7 +456,7 @@ impl BenchDb {
);
BenchContext {
- client, backend, db_guard: directory_guard,
+ client: Arc::new(client), backend, db_guard: directory_guard,
}
}
}
@@ -543,7 +588,7 @@ impl Guard {
/// Benchmarking/test context holding instantiated client and backend references.
pub struct BenchContext {
/// Node client.
- pub client: Client,
+ pub client: Arc,
/// Node backend.
pub backend: Arc,
diff --git a/primitives/transaction-pool/src/pool.rs b/primitives/transaction-pool/src/pool.rs
index b00c283ac743c..848c6f9e1786d 100644
--- a/primitives/transaction-pool/src/pool.rs
+++ b/primitives/transaction-pool/src/pool.rs
@@ -23,7 +23,7 @@ use std::{
sync::Arc,
pin::Pin,
};
-use futures::{Future, Stream,};
+use futures::{Future, Stream};
use serde::{Deserialize, Serialize};
use sp_utils::mpsc;
use sp_runtime::{
@@ -164,7 +164,7 @@ pub trait InPoolTransaction {
/// Get priority of the transaction.
fn priority(&self) -> &TransactionPriority;
/// Get longevity of the transaction.
- fn longevity(&self) ->&TransactionLongevity;
+ fn longevity(&self) -> &TransactionLongevity;
/// Get transaction dependencies.
fn requires(&self) -> &[TransactionTag];
/// Get tags that transaction provides.