From 71343248cafcca0b3b1dfe71ddce01aa50813acf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= <tomusdrw@users.noreply.github.com> Date: Thu, 20 Dec 2018 15:28:14 +0100 Subject: [PATCH] Call a state before block was imported. (#1294) * Call a state before block was imported. * Add test to check if it works correctly. --- substrate/Cargo.lock | 1 + substrate/core/service/Cargo.toml | 3 + substrate/core/service/src/components.rs | 126 +++++++++++++++++------ substrate/core/service/src/lib.rs | 3 + 4 files changed, 103 insertions(+), 30 deletions(-) diff --git a/substrate/Cargo.lock b/substrate/Cargo.lock index 1e201f4ee53..89bfba8cb13 100644 --- a/substrate/Cargo.lock +++ b/substrate/Cargo.lock @@ -3661,6 +3661,7 @@ dependencies = [ "substrate-primitives 0.1.0", "substrate-rpc-servers 0.1.0", "substrate-telemetry 0.3.0", + "substrate-test-client 0.1.0", "substrate-transaction-pool 0.1.0", "target_info 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "tokio 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/substrate/core/service/Cargo.toml b/substrate/core/service/Cargo.toml index ca8766c707a..e9f165ed9d4 100644 --- a/substrate/core/service/Cargo.toml +++ b/substrate/core/service/Cargo.toml @@ -30,3 +30,6 @@ substrate-executor = { path = "../../core/executor" } substrate-transaction-pool = { path = "../../core/transaction-pool" } substrate-rpc-servers = { path = "../../core/rpc-servers" } substrate-telemetry = { path = "../../core/telemetry" } + +[dev-dependencies] +substrate-test-client = { path = "../test-client" } diff --git a/substrate/core/service/src/components.rs b/substrate/core/service/src/components.rs index 20f01676a36..df50d54529f 100644 --- a/substrate/core/service/src/components.rs +++ b/substrate/core/service/src/components.rs @@ -184,6 +184,51 @@ pub trait MaintainTransactionPool<C: Components> { ) -> error::Result<()>; } +fn on_block_imported<Api, Backend, Block, Executor, PoolApi>( + id: &BlockId<Block>, + client: &Client<Backend, Executor, Block, Api>, + transaction_pool: &TransactionPool<PoolApi>, +) -> error::Result<()> where + Api: TaggedTransactionQueue<Block>, + Block: BlockT<Hash = <Blake2Hasher as ::primitives::Hasher>::Out>, + Backend: client::backend::Backend<Block, Blake2Hasher>, + Client<Backend, Executor, Block, Api>: ProvideRuntimeApi<Api = Api>, + Executor: client::CallExecutor<Block, Blake2Hasher>, + PoolApi: txpool::ChainApi<Hash = Block::Hash, Block = Block>, +{ + use runtime_primitives::transaction_validity::TransactionValidity; + + // Avoid calling into runtime if there is nothing to prune from the pool anyway. + if transaction_pool.status().is_empty() { + return Ok(()) + } + + let block = client.block(id)?; + let tags = match block { + None => return Ok(()), + Some(block) => { + let parent_id = BlockId::hash(*block.block.header().parent_hash()); + let mut tags = vec![]; + for tx in block.block.extrinsics() { + let tx = client.runtime_api().validate_transaction(&parent_id, &tx)?; + match tx { + TransactionValidity::Valid { mut provides, .. } => { + tags.append(&mut provides); + }, + // silently ignore invalid extrinsics, + // cause they might just be inherent + _ => {} + } + + } + tags + } + }; + + transaction_pool.prune_tags(id, tags).map_err(|e| format!("{:?}", e))?; + Ok(()) +} + impl<C: Components> MaintainTransactionPool<Self> for C where ComponentClient<C>: ProvideRuntimeApi<Api = C::RuntimeApi>, C::RuntimeApi: TaggedTransactionQueue<ComponentBlock<C>>, @@ -194,36 +239,7 @@ impl<C: Components> MaintainTransactionPool<Self> for C where client: &ComponentClient<C>, transaction_pool: &TransactionPool<C::TransactionPoolApi>, ) -> error::Result<()> { - use runtime_primitives::transaction_validity::TransactionValidity; - - // Avoid calling into runtime if there is nothing to prune from the pool anyway. - if transaction_pool.status().is_empty() { - return Ok(()) - } - - let block = client.block(id)?; - let tags = match block { - None => return Ok(()), - Some(block) => { - let mut tags = vec![]; - for tx in block.block.extrinsics() { - let tx = client.runtime_api().validate_transaction(id, &tx)?; - match tx { - TransactionValidity::Valid { mut provides, .. } => { - tags.append(&mut provides); - }, - // silently ignore invalid extrinsics, - // cause they might just be inherent - _ => {} - } - - } - tags - } - }; - - transaction_pool.prune_tags(id, tags).map_err(|e| format!("{:?}", e))?; - Ok(()) + on_block_imported(id, client, transaction_pool) } } @@ -520,3 +536,53 @@ impl<Factory: ServiceFactory> Components for LightComponents<Factory> { Factory::build_light_import_queue(config, client) } } + +#[cfg(test)] +mod tests { + use super::*; + use codec::Encode; + use consensus_common::BlockOrigin; + use substrate_test_client::{ + self, + TestClient, + keyring::Keyring, + runtime::{Extrinsic, Transfer}, + }; + + #[test] + fn should_remove_transactions_from_the_pool() { + let client = Arc::new(substrate_test_client::new()); + let pool = TransactionPool::new(Default::default(), ::transaction_pool::ChainApi::new(client.clone())); + let transaction = { + let transfer = Transfer { + amount: 5, + nonce: 0, + from: Keyring::Alice.to_raw_public().into(), + to: Default::default(), + }; + let signature = Keyring::from_raw_public(transfer.from.to_fixed_bytes()).unwrap().sign(&transfer.encode()).into(); + Extrinsic { transfer, signature } + }; + // store the transaction in the pool + pool.submit_one(&BlockId::hash(client.best_block_header().unwrap().hash()), transaction.clone()).unwrap(); + + // import the block + let mut builder = client.new_block().unwrap(); + builder.push(transaction.clone()).unwrap(); + let block = builder.bake().unwrap(); + let id = BlockId::hash(block.header().hash()); + client.import(BlockOrigin::Own, block).unwrap(); + + // fire notification - this should clean up the queue + assert_eq!(pool.status().ready, 1); + on_block_imported( + &id, + &client, + &pool, + ).unwrap(); + + // then + assert_eq!(pool.status().ready, 0); + assert_eq!(pool.status().future, 0); + } +} diff --git a/substrate/core/service/src/lib.rs b/substrate/core/service/src/lib.rs index 9421fcb8d01..04d8e8582ae 100644 --- a/substrate/core/service/src/lib.rs +++ b/substrate/core/service/src/lib.rs @@ -50,6 +50,9 @@ extern crate log; #[macro_use] extern crate serde_derive; +#[cfg(test)] +extern crate substrate_test_client; + mod components; mod error; mod chain_spec; -- GitLab