From 34ea521e009115e6bd3184d8f16e96c6ed907941 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Mon, 14 Oct 2019 16:55:29 +0300 Subject: [PATCH 01/38] recover tx pool on light client --- Cargo.lock | 1 + core/client/src/light/fetcher.rs | 25 +- core/service/src/builder.rs | 318 +++++----- core/service/src/lib.rs | 16 +- core/service/src/pool_maintainer.rs | 564 ++++++++++++++++++ .../tests/ui/declaring_old_block.stderr | 2 +- ...aring_own_block_with_different_name.stderr | 2 +- core/test-runtime/client/Cargo.toml | 1 + core/test-runtime/client/src/lib.rs | 90 ++- core/transaction-pool/graph/src/base_pool.rs | 48 +- core/transaction-pool/graph/src/error.rs | 3 + core/transaction-pool/graph/src/pool.rs | 154 ++++- .../graph/src/validated_pool.rs | 134 ++++- core/transaction-pool/src/api.rs | 103 +++- core/transaction-pool/src/lib.rs | 2 +- node-template/src/service.rs | 12 +- node/cli/src/service.rs | 24 +- node/rpc/Cargo.toml | 3 +- node/rpc/src/accounts.rs | 181 ++++-- node/rpc/src/lib.rs | 35 +- 20 files changed, 1421 insertions(+), 297 deletions(-) create mode 100644 core/service/src/pool_maintainer.rs diff --git a/Cargo.lock b/Cargo.lock index 5a17eaed3199d..13cf1ac1c48f8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5555,6 +5555,7 @@ dependencies = [ name = "substrate-test-runtime-client" version = "2.0.0" dependencies = [ + "futures-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", "parity-scale-codec 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", "sr-primitives 2.0.0", "substrate-primitives 2.0.0", diff --git a/core/client/src/light/fetcher.rs b/core/client/src/light/fetcher.rs index dbf6d41c38f16..769715497c7b0 100644 --- a/core/client/src/light/fetcher.rs +++ b/core/client/src/light/fetcher.rs @@ -145,15 +145,30 @@ pub struct RemoteBodyRequest { /// is correct (see FetchedDataChecker) and return already checked data. pub trait Fetcher: Send + Sync { /// Remote header future. - type RemoteHeaderResult: Future> + Send + 'static; + type RemoteHeaderResult: Future> + Unpin + Send + 'static; /// Remote storage read future. - type RemoteReadResult: Future, Option>>, ClientError>> + Send + 'static; + type RemoteReadResult: Future, Option>>, + ClientError, + >> + Unpin + Send + 'static; /// Remote call result future. - type RemoteCallResult: Future, ClientError>> + Send + 'static; + type RemoteCallResult: Future, + ClientError, + >> + Unpin + Send + 'static; /// Remote changes result future. - type RemoteChangesResult: Future, u32)>, ClientError>> + Send + 'static; + type RemoteChangesResult: Future, u32)>, + ClientError, + >> + Unpin + Send + 'static; /// Remote block body result future. - type RemoteBodyResult: Future, ClientError>> + Send + 'static; + type RemoteBodyResult: Future, + ClientError, + >> + Unpin + Send + 'static; /// Fetch remote header. fn remote_header(&self, request: RemoteHeaderRequest) -> Self::RemoteHeaderResult; diff --git a/core/service/src/builder.rs b/core/service/src/builder.rs index e4b02150bf238..5ce8b68dc06eb 100644 --- a/core/service/src/builder.rs +++ b/core/service/src/builder.rs @@ -18,9 +18,13 @@ use crate::{NewService, NetworkStatus, NetworkState, error::{self, Error}, DEFAU use crate::{SpawnTaskHandle, start_rpc_servers, build_network_future, TransactionPoolAdapter}; use crate::TaskExecutor; use crate::config::Configuration; +use crate::pool_maintainer::{ + TransactionPoolMaintainer, DefaultFullTransactionPoolMaintainer, DefaultLightTransactionPoolMaintainer, +}; use client::{ BlockchainEvents, Client, runtime_api, - backend::RemoteBackend, light::blockchain::RemoteBlockchain, + backend::RemoteBackend, + light::blockchain::RemoteBlockchain, }; use chain_spec::{RuntimeGenesis, Extension}; use codec::{Decode, Encode, IoReader}; @@ -28,8 +32,7 @@ use consensus_common::import_queue::ImportQueue; use futures::{prelude::*, sync::mpsc}; use futures03::{ compat::Compat, - future::ready, - FutureExt as _, TryFutureExt as _, + FutureExt as _, StreamExt as _, TryStreamExt as _, }; use keystore::{Store as Keystore, KeyStorePtr}; @@ -41,7 +44,8 @@ use primitives::{Blake2Hasher, H256, Hasher}; use rpc::{self, system::SystemInfo}; use sr_primitives::generic::BlockId; use sr_primitives::traits::{ - Block as BlockT, Extrinsic, ProvideRuntimeApi, NumberFor, One, Zero, Header, SaturatedConversion + Block as BlockT, ProvideRuntimeApi, NumberFor, One, + Zero, Header, SaturatedConversion, }; use substrate_executor::{NativeExecutor, NativeExecutionDispatch}; use std::{io::{Read, Write, Seek}, marker::PhantomData, sync::Arc, sync::atomic::AtomicBool}; @@ -68,19 +72,21 @@ use transaction_pool::txpool::{self, ChainApi, Pool as TransactionPool}; /// generics is done when you call `build`. /// pub struct ServiceBuilder + TNetP, TExPool, TExPoolM, TRpc, TRpcB, Backend> { config: Configuration, client: Arc, backend: Arc, keystore: Arc>, fetcher: Option, + remote_blockchain: Option>>, select_chain: Option, import_queue: TImpQu, finality_proof_request_builder: Option, finality_proof_provider: Option, network_protocol: TNetP, transaction_pool: Arc, + transaction_pool_maintainer: TExPoolM, rpc_extensions: TRpc, rpc_builder: TRpcB, dht_event_tx: Option>, @@ -133,7 +139,7 @@ type TLightCallExecutor = client::light::call_executor::GenesisC >, >; -impl ServiceBuilder<(), (), TCfg, TGen, TCSExt, (), (), (), (), (), (), (), (), (), (), ()> +impl ServiceBuilder<(), (), TCfg, TGen, TCSExt, (), (), (), (), (), (), (), (), (), (), (), ()> where TGen: RuntimeGenesis, TCSExt: Extension { /// Start the service builder with a configuration. pub fn new_full, TRtApi, TExecDisp: NativeExecutionDispatch>( @@ -152,6 +158,7 @@ where TGen: RuntimeGenesis, TCSExt: Extension { (), (), (), + DefaultFullTransactionPoolMaintainer, (), FullRpcBuilder, TFullBackend, @@ -197,12 +204,14 @@ where TGen: RuntimeGenesis, TCSExt: Extension { backend, keystore, fetcher: None, + remote_blockchain: None, select_chain: None, import_queue: (), finality_proof_request_builder: None, finality_proof_provider: None, network_protocol: (), transaction_pool: Arc::new(()), + transaction_pool_maintainer: DefaultFullTransactionPoolMaintainer, rpc_extensions: Default::default(), rpc_builder, dht_event_tx: None, @@ -227,6 +236,7 @@ where TGen: RuntimeGenesis, TCSExt: Extension { (), (), (), + DefaultLightTransactionPoolMaintainer>, (), LightRpcBuilder, TLightBackend, @@ -260,7 +270,7 @@ where TGen: RuntimeGenesis, TCSExt: Extension { )?); let rpc_builder = LightRpcBuilder { client: client.clone(), - remote_blockchain, + remote_blockchain: remote_blockchain.clone(), fetcher: fetcher.clone(), }; @@ -269,13 +279,15 @@ where TGen: RuntimeGenesis, TCSExt: Extension { client, backend, keystore, - fetcher: Some(fetcher), + fetcher: Some(fetcher.clone()), + remote_blockchain: Some(remote_blockchain), select_chain: None, import_queue: (), finality_proof_request_builder: None, finality_proof_provider: None, network_protocol: (), transaction_pool: Arc::new(()), + transaction_pool_maintainer: DefaultLightTransactionPoolMaintainer::with_defaults(fetcher), rpc_extensions: Default::default(), rpc_builder, dht_event_tx: None, @@ -284,9 +296,10 @@ where TGen: RuntimeGenesis, TCSExt: Extension { } } -impl +impl ServiceBuilder { + TNetP, TExPool, TExPoolM, TRpc, TRpcB, Backend> { /// Returns a reference to the client that was stored in this builder. pub fn client(&self) -> &Arc { @@ -310,7 +323,7 @@ impl, &Arc ) -> Result, Error> ) -> Result, Error> { + TNetP, TExPool, TExPoolM, TRpc, TRpcB, Backend>, Error> { let select_chain = select_chain_builder(&self.config, &self.backend)?; Ok(ServiceBuilder { @@ -319,12 +332,14 @@ impl, &Arc) -> Result ) -> Result, Error> { + TNetP, TExPool, TExPoolM, TRpc, TRpcB, Backend>, Error> { self.with_opt_select_chain(|cfg, b| builder(cfg, b).map(Option::Some)) } @@ -347,7 +362,7 @@ impl, Arc, Option, Arc) -> Result ) -> Result, Error> + TNetP, TExPool, TExPoolM, TRpc, TRpcB, Backend>, Error> where TSc: Clone { let import_queue = builder( &self.config, @@ -362,12 +377,14 @@ impl) -> Result ) -> Result, Error> { + UNetP, TExPool, TExPoolM, TRpc, TRpcB, Backend>, Error> { let network_protocol = network_protocol_builder(&self.config)?; Ok(ServiceBuilder { @@ -389,12 +406,14 @@ impl>, TNetP, TExPool, + TExPoolM, TRpc, TRpcB, Backend, @@ -432,12 +452,14 @@ impl>, TNetP, TExPool, + TExPoolM, TRpc, TRpcB, Backend, @@ -482,7 +505,7 @@ impl, ) -> Result<(UImpQu, Option), Error> ) -> Result, Error> + TNetP, TExPool, TExPoolM, TRpc, TRpcB, Backend>, Error> where TSc: Clone, TFchr: Clone { let (import_queue, fprb) = builder( &self.config, @@ -499,12 +522,14 @@ impl, ) -> Result<(UImpQu, UFprb), Error> ) -> Result, Error> + TNetP, TExPool, TExPoolM, TRpc, TRpcB, Backend>, Error> where TSc: Clone, TFchr: Clone { self.with_import_queue_and_opt_fprb(|cfg, cl, b, f, sc, tx| builder(cfg, cl, b, f, sc, tx) @@ -535,10 +560,19 @@ impl( self, - transaction_pool_builder: impl FnOnce(transaction_pool::txpool::Options, Arc) -> Result + transaction_pool_builder: impl FnOnce( + transaction_pool::txpool::Options, + Arc, + Option, + ) -> Result ) -> Result, Error> { - let transaction_pool = transaction_pool_builder(self.config.transaction_pool.clone(), self.client.clone())?; + TNetP, UExPool, TExPoolM, TRpc, TRpcB, Backend>, Error> + where TFchr: Clone { + let transaction_pool = transaction_pool_builder( + self.config.transaction_pool.clone(), + self.client.clone(), + self.fetcher.clone(), + )?; Ok(ServiceBuilder { config: self.config, @@ -546,12 +580,58 @@ impl( + self, + transaction_pool_maintainer_builder: impl FnOnce( + Arc, + Arc, + Option, + Option>>, + ) -> Result, + ) -> Result, Error> + where TFchr: Clone { + let transaction_pool_maintainer = transaction_pool_maintainer_builder( + self.client.clone(), + self.transaction_pool.clone(), + self.fetcher.clone(), + self.remote_blockchain.clone(), + )?; + + Ok(ServiceBuilder { + config: self.config, + client: self.client, + backend: self.backend, + keystore: self.keystore, + fetcher: self.fetcher, + remote_blockchain: self.remote_blockchain, + select_chain: self.select_chain, + import_queue: self.import_queue, + finality_proof_request_builder: self.finality_proof_request_builder, + finality_proof_provider: self.finality_proof_provider, + network_protocol: self.network_protocol, + transaction_pool: self.transaction_pool, + transaction_pool_maintainer, rpc_extensions: self.rpc_extensions, rpc_builder: self.rpc_builder, dht_event_tx: self.dht_event_tx, @@ -562,10 +642,21 @@ impl( self, - rpc_ext_builder: impl FnOnce(Arc, Arc) -> URpc + rpc_ext_builder: impl FnOnce( + Arc, + Arc, + Option, + Option>>, + ) -> Result, ) -> Result, Error> { - let rpc_extensions = rpc_ext_builder(self.client.clone(), self.transaction_pool.clone()); + TNetP, TExPool, TExPoolM, URpc, TRpcB, Backend>, Error> + where TFchr: Clone { + let rpc_extensions = rpc_ext_builder( + self.client.clone(), + self.transaction_pool.clone(), + self.fetcher.clone(), + self.remote_blockchain.clone(), + )?; Ok(ServiceBuilder { config: self.config, @@ -573,12 +664,14 @@ impl, ) -> Result, Error> { + TNetP, TExPool, TExPoolM, TRpc, TRpcB, Backend>, Error> { Ok(ServiceBuilder { config: self.config, client: self.client, backend: self.backend, keystore: self.keystore, fetcher: self.fetcher, + remote_blockchain: self.remote_blockchain, select_chain: self.select_chain, import_queue: self.import_queue, finality_proof_request_builder: self.finality_proof_request_builder, finality_proof_provider: self.finality_proof_provider, network_protocol: self.network_protocol, transaction_pool: self.transaction_pool, + transaction_pool_maintainer: self.transaction_pool_maintainer, rpc_extensions: self.rpc_extensions, rpc_builder: self.rpc_builder, dht_event_tx: Some(dht_event_tx), @@ -735,10 +830,10 @@ pub trait ServiceBuilderRevert { impl< TBl, TRtApi, TCfg, TGen, TCSExt, TBackend, TExec, TFchr, TSc, TImpQu, TFprb, TFpp, TNetP, - TExPool, TRpc, TRpcB, Backend + TExPool, TExPoolM, TRpc, TRpcB, Backend > ServiceBuilderImport for ServiceBuilder< TBl, TRtApi, TCfg, TGen, TCSExt, Client, - TFchr, TSc, TImpQu, TFprb, TFpp, TNetP, TExPool, TRpc, TRpcB, Backend + TFchr, TSc, TImpQu, TFprb, TFpp, TNetP, TExPool, TExPoolM, TRpc, TRpcB, Backend > where TBl: BlockT::Out>, TBackend: 'static + client::backend::Backend + Send, @@ -758,9 +853,10 @@ impl< } } -impl +impl ServiceBuilderExport for ServiceBuilder, - TFchr, TSc, TImpQu, TFprb, TFpp, TNetP, TExPool, TRpc, TRpcB, TBackend> + TFchr, TSc, TImpQu, TFprb, TFpp, TNetP, TExPool, TExPoolM, TRpc, TRpcB, TBackend> where TBl: BlockT::Out>, TBackend: 'static + client::backend::Backend + Send, @@ -781,9 +877,10 @@ where } } -impl +impl ServiceBuilderRevert for ServiceBuilder, - TFchr, TSc, TImpQu, TFprb, TFpp, TNetP, TExPool, TRpc, TRpcB, TBackend> + TFchr, TSc, TImpQu, TFprb, TFpp, TNetP, TExPool, TExPoolM, TRpc, TRpcB, TBackend> where TBl: BlockT::Out>, TBackend: 'static + client::backend::Backend + Send, @@ -800,7 +897,7 @@ where } } -impl +impl ServiceBuilder< TBl, TRtApi, @@ -815,6 +912,7 @@ ServiceBuilder< Arc>, TNetP, TransactionPool, + TExPoolM, TRpc, TRpcB, TBackend, @@ -836,6 +934,7 @@ ServiceBuilder< TImpQu: 'static + ImportQueue, TNetP: NetworkSpecialization, TExPoolApi: 'static + ChainApi::Hash>, + TExPoolM: TransactionPoolMaintainer, TRpc: rpc::RpcExtension + Clone, TRpcB: RpcBuilder, { @@ -858,6 +957,7 @@ ServiceBuilder< mut config, client, fetcher, + remote_blockchain, backend, keystore, select_chain, @@ -866,6 +966,7 @@ ServiceBuilder< finality_proof_provider, network_protocol, transaction_pool, + transaction_pool_maintainer, rpc_extensions, dht_event_tx, rpc_builder, @@ -883,6 +984,7 @@ ServiceBuilder< Ok(( client, fetcher, + remote_blockchain, backend, keystore, select_chain, @@ -891,17 +993,18 @@ ServiceBuilder< finality_proof_provider, network_protocol, transaction_pool, + transaction_pool_maintainer, rpc_extensions, dht_event_tx, )) }, - |h, c, tx, r| maintain_transaction_pool(h, c, tx, r), |n, o, p, ns, v| offchain_workers(n, o, p, ns, v), |c, ssb, si, te, tp, ext, ks| start_rpc(&rpc_builder, c, ssb, si, te, tp, ext, ks), ) } } + pub(crate) fn start_rpc( rpc_builder: &RpcB, client: Arc>, @@ -944,58 +1047,6 @@ where )) } -pub(crate) fn maintain_transaction_pool( - id: &BlockId, - client: &Arc>, - transaction_pool: &TransactionPool, - retracted: &[Block::Hash], -) -> error::Result + Send>> where - Block: BlockT::Out>, - Backend: 'static + client::backend::Backend, - Client: ProvideRuntimeApi, - as ProvideRuntimeApi>::Api: runtime_api::TaggedTransactionQueue, - Executor: 'static + client::CallExecutor, - PoolApi: 'static + txpool::ChainApi, - Api: 'static, -{ - // Put transactions from retracted blocks back into the pool. - let client_copy = client.clone(); - let retracted_transactions = retracted.to_vec().into_iter() - .filter_map(move |hash| client_copy.block(&BlockId::hash(hash)).ok().unwrap_or(None)) - .flat_map(|block| block.block.deconstruct().1.into_iter()) - .filter(|tx| tx.is_signed().unwrap_or(false)); - let resubmit_future = transaction_pool - .submit_at(id, retracted_transactions, true) - .then(|resubmit_result| ready(match resubmit_result { - Ok(_) => Ok(()), - Err(e) => { - warn!("Error re-submitting transactions: {:?}", e); - Ok(()) - } - })) - .compat(); - - // Avoid calling into runtime if there is nothing to prune from the pool anyway. - if transaction_pool.status().is_empty() { - return Ok(Box::new(resubmit_future)) - } - - let block = client.block(id)?; - Ok(match block { - Some(block) => { - let parent_id = BlockId::hash(*block.block.header().parent_hash()); - let prune_future = transaction_pool - .prune(id, &parent_id, block.block.extrinsics()) - .boxed() - .compat() - .map_err(|e| { format!("{:?}", e); }); - - Box::new(resubmit_future.and_then(|_| prune_future)) - }, - None => Box::new(resubmit_future), - }) -} - pub(crate) fn offchain_workers( number: &NumberFor, offchain: &offchain::OffchainWorkers< @@ -1021,104 +1072,3 @@ where .map(|()| Ok(())); Ok(Box::new(Compat::new(future))) } - -#[cfg(test)] -mod tests { - use super::*; - use futures03::executor::block_on; - use consensus_common::{BlockOrigin, SelectChain}; - use substrate_test_runtime_client::{prelude::*, runtime::Transfer}; - - #[test] - fn should_remove_transactions_from_the_pool() { - let (client, longest_chain) = TestClientBuilder::new().build_with_longest_chain(); - let client = Arc::new(client); - let pool = TransactionPool::new(Default::default(), ::transaction_pool::FullChainApi::new(client.clone())); - let transaction = Transfer { - amount: 5, - nonce: 0, - from: AccountKeyring::Alice.into(), - to: Default::default(), - }.into_signed_tx(); - let best = longest_chain.best_chain().unwrap(); - - // store the transaction in the pool - block_on(pool.submit_one(&BlockId::hash(best.hash()), transaction.clone())).unwrap(); - - // import the block - let mut builder = client.new_block(Default::default()).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); - maintain_transaction_pool( - &id, - &client, - &pool, - &[] - ).unwrap().wait().unwrap(); - - // then - assert_eq!(pool.status().ready, 0); - assert_eq!(pool.status().future, 0); - } - - #[test] - fn should_add_reverted_transactions_to_the_pool() { - let (client, longest_chain) = TestClientBuilder::new().build_with_longest_chain(); - let client = Arc::new(client); - let pool = TransactionPool::new(Default::default(), ::transaction_pool::FullChainApi::new(client.clone())); - let transaction = Transfer { - amount: 5, - nonce: 0, - from: AccountKeyring::Alice.into(), - to: Default::default(), - }.into_signed_tx(); - let best = longest_chain.best_chain().unwrap(); - - // store the transaction in the pool - block_on(pool.submit_one(&BlockId::hash(best.hash()), transaction.clone())).unwrap(); - - // import the block - let mut builder = client.new_block(Default::default()).unwrap(); - builder.push(transaction.clone()).unwrap(); - let block = builder.bake().unwrap(); - let block1_hash = block.header().hash(); - let id = BlockId::hash(block1_hash.clone()); - client.import(BlockOrigin::Own, block).unwrap(); - - // fire notification - this should clean up the queue - assert_eq!(pool.status().ready, 1); - maintain_transaction_pool( - &id, - &client, - &pool, - &[] - ).unwrap().wait().unwrap(); - - // then - assert_eq!(pool.status().ready, 0); - assert_eq!(pool.status().future, 0); - - // import second block - let builder = client.new_block_at(&BlockId::hash(best.hash()), Default::default()).unwrap(); - let block = builder.bake().unwrap(); - let id = BlockId::hash(block.header().hash()); - client.import(BlockOrigin::Own, block).unwrap(); - - // fire notification - this should add the transaction back to the pool. - maintain_transaction_pool( - &id, - &client, - &pool, - &[block1_hash] - ).unwrap().wait().unwrap(); - - // then - assert_eq!(pool.status().ready, 1); - assert_eq!(pool.status().future, 0); - } -} diff --git a/core/service/src/lib.rs b/core/service/src/lib.rs index fccf04d8a1345..1aabd981b15d0 100644 --- a/core/service/src/lib.rs +++ b/core/service/src/lib.rs @@ -51,7 +51,13 @@ use sr_primitives::generic::BlockId; use sr_primitives::traits::NumberFor; pub use self::error::Error; -pub use self::builder::{ServiceBuilder, ServiceBuilderExport, ServiceBuilderImport, ServiceBuilderRevert}; +pub use self::builder::{ + ServiceBuilder, ServiceBuilderExport, ServiceBuilderImport, ServiceBuilderRevert, +}; +pub use self::pool_maintainer:: { + TransactionPoolMaintainer, + DefaultLightTransactionPoolMaintainer, DefaultFullTransactionPoolMaintainer, +}; pub use config::{Configuration, Roles, PruningMode}; pub use chain_spec::{ChainSpec, Properties, RuntimeGenesis, Extension as ChainSpecExtension}; pub use transaction_pool::txpool::{ @@ -133,7 +139,6 @@ macro_rules! new_impl { $block:ty, $config:ident, $build_components:expr, - $maintain_transaction_pool:expr, $offchain_workers:expr, $start_rpc:expr, ) => {{ @@ -147,6 +152,7 @@ macro_rules! new_impl { let ( client, on_demand, + _remote_blockchain, backend, keystore, select_chain, @@ -155,6 +161,7 @@ macro_rules! new_impl { finality_proof_provider, network_protocol, transaction_pool, + transaction_pool_maintainer, rpc_extensions, dht_event_tx, ) = $build_components(&$config)?; @@ -240,10 +247,10 @@ macro_rules! new_impl { let txpool = txpool.upgrade(); if let (Some(txpool), Some(client)) = (txpool.as_ref(), wclient.upgrade()) { - let future = $maintain_transaction_pool( + let future = transaction_pool_maintainer.maintain( &BlockId::hash(notification.hash), &client, - &*txpool, + &txpool, ¬ification.retracted, ).map_err(|e| warn!("Pool error processing new block: {:?}", e))?; let _ = to_spawn_tx_.unbounded_send(future); @@ -446,6 +453,7 @@ macro_rules! new_impl { } mod builder; +mod pool_maintainer; /// Abstraction over a Substrate service. pub trait AbstractService: 'static + Future + diff --git a/core/service/src/pool_maintainer.rs b/core/service/src/pool_maintainer.rs new file mode 100644 index 0000000000000..891466a4181e6 --- /dev/null +++ b/core/service/src/pool_maintainer.rs @@ -0,0 +1,564 @@ +// Copyright 2019 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate 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. + +// Substrate 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 Substrate. If not, see . + +use crate::error; +use client::{ + Client, runtime_api, + light::fetcher::{Fetcher, RemoteBodyRequest}, +}; +use futures::prelude::*; +use futures03::{ + future::{ready, Either}, + FutureExt as _, TryFutureExt as _, +}; +use log::warn; +use parking_lot::Mutex; +use primitives::Blake2Hasher; +use sr_primitives::generic::BlockId; +use sr_primitives::traits::{ + Block as BlockT, Extrinsic, ProvideRuntimeApi, NumberFor, + Header, SimpleArithmetic, +}; +use std::{marker::PhantomData, sync::Arc, time::Instant}; +use transaction_pool::txpool::{self, Pool as TransactionPool}; + +/// Transaction pool maintainer. +/// +/// In brief, the task of transaction pool maintainer is to: +/// 1) make sure that ready in-pool transactions are valid; +/// 2) move 'future' transactions to the 'ready' queue; +/// 3) prune transactions that have been included in some block. +pub trait TransactionPoolMaintainer: Send + 'static where + Block: BlockT::Out>, +{ + /// Maintain transaction pool. + fn maintain( + &self, + id: &BlockId, + client: &Arc>, + transaction_pool: &Arc>, + retracted: &[Block::Hash], + ) -> error::Result + Send>> where + Backend: 'static + client::backend::Backend, + Client: ProvideRuntimeApi, + as ProvideRuntimeApi>::Api: runtime_api::TaggedTransactionQueue, + Executor: 'static + client::CallExecutor, + PoolApi: 'static + txpool::ChainApi, + Api: 'static; +} + +/// Default transaction pool maintainer for full clients. +pub struct DefaultFullTransactionPoolMaintainer; + +impl TransactionPoolMaintainer for DefaultFullTransactionPoolMaintainer where + Block: BlockT::Out>, +{ + fn maintain( + &self, + id: &BlockId, + client: &Arc>, + transaction_pool: &Arc>, + retracted: &[Block::Hash], + ) -> error::Result + Send>> where + Backend: 'static + client::backend::Backend, + Client: ProvideRuntimeApi, + as ProvideRuntimeApi>::Api: runtime_api::TaggedTransactionQueue, + Executor: 'static + client::CallExecutor, + PoolApi: 'static + txpool::ChainApi, + Api: 'static, + { + // Put transactions from retracted blocks back into the pool. + let client_copy = client.clone(); + let retracted_transactions = retracted.to_vec().into_iter() + .filter_map(move |hash| client_copy.block(&BlockId::hash(hash)).ok().unwrap_or(None)) + .flat_map(|block| block.block.deconstruct().1.into_iter()) + .filter(|tx| tx.is_signed().unwrap_or(false)); + let resubmit_future = transaction_pool + .submit_at(id, retracted_transactions, true) + .then(|resubmit_result| ready(match resubmit_result { + Ok(_) => Ok(()), + Err(e) => { + warn!("Error re-submitting transactions: {:?}", e); + Ok(()) + } + })) + .compat(); + + // Avoid calling into runtime if there is nothing to prune from the pool anyway. + if transaction_pool.status().is_empty() { + return Ok(Box::new(resubmit_future)) + } + + let block = client.block(id)?; + Ok(match block { + Some(block) => { + let parent_id = BlockId::hash(*block.block.header().parent_hash()); + let prune_future = transaction_pool + .prune(id, &parent_id, block.block.extrinsics()) + .boxed() + .compat() + .map_err(|e| { warn!("{:?}", e); }); + + Box::new(resubmit_future.and_then(|_| prune_future)) + }, + None => Box::new(resubmit_future), + }) + } +} + +/// Default transaction pool maintainer for light clients. +pub struct DefaultLightTransactionPoolMaintainer { + fetcher: Arc, + revalidate_time_period: Option, + revalidate_block_period: Option>, + revalidation_status: Arc>>>, + _phantom: PhantomData, +} + +impl> DefaultLightTransactionPoolMaintainer { + /// Create light pool maintainer with default constants. + pub fn with_defaults(fetcher: Arc) -> Self { + // default constants are: revalidate every 60 seconds or every 20 blocks + Self::new( + fetcher, + Some(std::time::Duration::from_secs(60)), + Some(20.into()), + ) + } + + /// Create light pool maintainer with passed constants. + pub fn new( + fetcher: Arc, + revalidate_time_period: Option, + revalidate_block_period: Option>, + ) -> Self { + Self { + fetcher, + revalidate_time_period, + revalidate_block_period, + revalidation_status: Arc::new(Mutex::new(TxPoolRevalidationStatus::NotScheduled)), + _phantom: Default::default(), + } + } + + /// Returns future that prunes block transactions from the pool. + fn prune( + &self, + id: &BlockId, + header: &Block::Header, + transaction_pool: &Arc>, + ) -> impl futures03::Future where + PoolApi: 'static + txpool::ChainApi, + { + // fetch transactions (possible future optimization: proofs of inclusion) that + // have been included into new block and prune these from the pool + let id = id.clone(); + let transaction_pool = transaction_pool.clone(); + self.fetcher.remote_body(RemoteBodyRequest { + header: header.clone(), + retry_count: None, + }) + .then(move |transactions| ready( + transactions + .map_err(|e| format!("{}", e)) + .and_then(|transactions| { + let hashes = transactions + .into_iter() + .map(|tx| transaction_pool.hash_of(&tx)) + .collect::>(); + transaction_pool.prune_known(&id, &hashes) + .map_err(|e| format!("{}", e)) + }) + )) + .then(|r| { + if let Err(e) = r { + warn!("Error pruning known transactions: {}", e) + } + ready(()) + }) + } + + /// Returns future that performs in-pool transations revalidation, if required. + fn revalidate( + &self, + id: &BlockId, + header: &Block::Header, + transaction_pool: &Arc>, + ) -> impl futures03::Future where + PoolApi: 'static + txpool::ChainApi, + { + // to determine whether ready transaction is still valid, we perform periodic revalidaton + // of ready transactions + let is_revalidation_required = self.revalidation_status.lock().is_required( + *header.number(), + self.revalidate_time_period, + self.revalidate_block_period, + ); + match is_revalidation_required { + true => { + let revalidation_status = self.revalidation_status.clone(); + Either::Left(transaction_pool + .revalidate_ready(id) + .map(|r| r.map_err(|e| warn!("Error revalidating known transactions: {}", e))) + .map(move |_| revalidation_status.lock().clear())) + }, + false => Either::Right(ready(())), + } + } +} + +impl TransactionPoolMaintainer for DefaultLightTransactionPoolMaintainer + where + Block: BlockT::Out>, + F: Fetcher + 'static, +{ + fn maintain( + &self, + id: &BlockId, + client: &Arc>, + transaction_pool: &Arc>, + _retracted: &[Block::Hash], + ) -> error::Result + Send>> where + Backend: 'static + client::backend::Backend, + Client: ProvideRuntimeApi, + as ProvideRuntimeApi>::Api: runtime_api::TaggedTransactionQueue, + Executor: 'static + client::CallExecutor, + PoolApi: 'static + txpool::ChainApi, + Api: 'static, + { + // Do nothing if transaction pool is empty. + if transaction_pool.status().is_empty() { + self.revalidation_status.lock().clear(); + return Ok(Box::new(ready(Ok(())).compat())); + } + let header = client.header(id).and_then(|h| h.ok_or(client::error::Error::UnknownBlock(format!("{}", id))))?; + + // else prune block transactions from the pool + let prune_future = self.prune(id, &header, transaction_pool); + + // and then (optionally) revalidate in-pool transactions + let revalidate_future = self.revalidate(id, &header, transaction_pool); + + let maintain_future = futures03::future::join( + prune_future, + revalidate_future, + ).map(|_| Ok(())); + + Ok(Box::new(maintain_future.compat())) + } +} + +/// The status of transactions revalidation at light tx pool. +#[cfg_attr(test, derive(Debug))] +enum TxPoolRevalidationStatus { + /// The revalidation has never been completed. + NotScheduled, + /// The revalidation is scheduled. + Scheduled(Option, Option), + /// The revalidation is in progress. + InProgress, +} + +impl TxPoolRevalidationStatus { + /// Called when revalidation is completed. + pub fn clear(&mut self) { + *self = TxPoolRevalidationStatus::NotScheduled; + } + + /// Returns true if revalidation is required. + pub fn is_required( + &mut self, + block: N, + revalidate_time_period: Option, + revalidate_block_period: Option, + ) -> bool { + match *self { + TxPoolRevalidationStatus::NotScheduled => { + *self = TxPoolRevalidationStatus::Scheduled( + revalidate_time_period.map(|period| Instant::now() + period), + revalidate_block_period.map(|period| block + period), + ); + false + }, + TxPoolRevalidationStatus::Scheduled(revalidate_at_time, revalidate_at_block) => { + let is_required = revalidate_at_time.map(|at| Instant::now() >= at).unwrap_or(false) + || revalidate_at_block.map(|at| block >= at).unwrap_or(false); + if is_required { + *self = TxPoolRevalidationStatus::InProgress; + } + is_required + }, + TxPoolRevalidationStatus::InProgress => false, + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + use futures03::executor::block_on; + use codec::Encode; + use consensus_common::{BlockOrigin, SelectChain}; + use substrate_test_runtime_client::{prelude::*, runtime::{Block, Transfer}}; + + #[test] + fn should_remove_transactions_from_the_full_pool() { + let (client, longest_chain) = TestClientBuilder::new().build_with_longest_chain(); + let client = Arc::new(client); + let pool = TransactionPool::new(Default::default(), ::transaction_pool::FullChainApi::new(client.clone())); + let pool = Arc::new(pool); + let transaction = Transfer { + amount: 5, + nonce: 0, + from: AccountKeyring::Alice.into(), + to: Default::default(), + }.into_signed_tx(); + let best = longest_chain.best_chain().unwrap(); + + // store the transaction in the pool + block_on(pool.submit_one(&BlockId::hash(best.hash()), transaction.clone())).unwrap(); + + // import the block + let mut builder = client.new_block(Default::default()).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); + DefaultFullTransactionPoolMaintainer.maintain( + &id, + &client, + &pool, + &[] + ).unwrap().wait().unwrap(); + + // then + assert_eq!(pool.status().ready, 0); + assert_eq!(pool.status().future, 0); + } + + #[test] + fn should_remove_transactions_from_the_light_pool() { + let transaction = Transfer { + amount: 5, + nonce: 0, + from: AccountKeyring::Alice.into(), + to: Default::default(), + }.into_signed_tx(); + let fetcher_transaction = transaction.clone(); + let fetcher = Arc::new(substrate_test_runtime_client::new_light_fetcher() + .with_remote_body(Some(Box::new(move |_| Ok(vec![fetcher_transaction.clone()])))) + .with_remote_call(Some(Box::new(move |_| { + let validity: sr_primitives::transaction_validity::TransactionValidity = + Ok(sr_primitives::transaction_validity::ValidTransaction { + priority: 0, + requires: Vec::new(), + provides: vec![vec![42]], + longevity: 0, + propagate: true, + }); + Ok(validity.encode()) + })))); + + let (client, longest_chain) = TestClientBuilder::new().build_with_longest_chain(); + let client = Arc::new(client); + let pool = TransactionPool::new(Default::default(), ::transaction_pool::LightChainApi::new( + client.clone(), + fetcher.clone(), + )); + let pool = Arc::new(pool); + let best = longest_chain.best_chain().unwrap(); + + // store the transaction in the pool + block_on(pool.submit_one(&BlockId::hash(best.hash()), transaction.clone())).unwrap(); + + // fire notification - this should clean up the queue + assert_eq!(pool.status().ready, 1); + DefaultLightTransactionPoolMaintainer::with_defaults(fetcher).maintain( + &BlockId::Number(0), + &client, + &pool, + &[] + ).unwrap().wait().unwrap(); + + // then + assert_eq!(pool.status().ready, 0); + assert_eq!(pool.status().future, 0); + } + + #[test] + fn should_schedule_transactions_revalidation_at_light_pool() { + // when revalidation is not scheduled, it became scheduled + let mut status = TxPoolRevalidationStatus::NotScheduled; + assert!(!status.is_required(10u32, None, None)); + match status { + TxPoolRevalidationStatus::Scheduled(_, _) => (), + _ => panic!("Unexpected status: {:?}", status), + } + + // revalidation required at time + let mut status = TxPoolRevalidationStatus::Scheduled(Some(Instant::now()), None); + assert!(status.is_required(10u32, None, None)); + match status { + TxPoolRevalidationStatus::InProgress => (), + _ => panic!("Unexpected status: {:?}", status), + } + + // revalidation required at block + let mut status = TxPoolRevalidationStatus::Scheduled(None, Some(10)); + assert!(status.is_required(10u32, None, None)); + match status { + TxPoolRevalidationStatus::InProgress => (), + _ => panic!("Unexpected status: {:?}", status), + } + } + + #[test] + fn should_revalidate_transactions_at_light_pool() { + let build_fetcher = || { + let validated = Arc::new(std::sync::atomic::AtomicBool::new(false)); + Arc::new(substrate_test_runtime_client::new_light_fetcher() + .with_remote_body(Some(Box::new(move |_| Ok(vec![])))) + .with_remote_call(Some(Box::new(move |_| { + let is_inserted = validated.swap(true, std::sync::atomic::Ordering::SeqCst); + let validity: sr_primitives::transaction_validity::TransactionValidity = if is_inserted { + Err(sr_primitives::transaction_validity::TransactionValidityError::Invalid( + sr_primitives::transaction_validity::InvalidTransaction::Custom(0) + )) + } else { + Ok(sr_primitives::transaction_validity::ValidTransaction { + priority: 0, + requires: Vec::new(), + provides: vec![vec![42]], + longevity: 0, + propagate: true, + }) + }; + Ok(validity.encode()) + })))) + }; + + fn with_fetcher_maintain + 'static>( + fetcher: Arc, + maintainer: &DefaultLightTransactionPoolMaintainer, + ) -> transaction_pool::txpool::Status { + // now let's prepare pool + let (client, longest_chain) = TestClientBuilder::new().build_with_longest_chain(); + let client = Arc::new(client); + let pool = TransactionPool::new(Default::default(), ::transaction_pool::LightChainApi::new( + client.clone(), + fetcher, + )); + let pool = Arc::new(pool); + let best = longest_chain.best_chain().unwrap(); + + // store the transaction in the pool + block_on(pool.submit_one( + &BlockId::hash(best.hash()), + Transfer { + amount: 5, + nonce: 0, + from: AccountKeyring::Alice.into(), + to: Default::default(), + }.into_signed_tx(), + )).unwrap(); + + // and run maintain procedures + maintainer.maintain(&BlockId::Number(0), &client, &pool, &[]).unwrap().wait().unwrap(); + + pool.status() + } + + // when revalidation is never required - nothing happens + let fetcher = build_fetcher(); + let maintainer = DefaultLightTransactionPoolMaintainer::new(fetcher.clone(), None, None); + let status = with_fetcher_maintain(fetcher, &maintainer); + assert_eq!(status.ready, 1); + + // when revalidation is scheduled by time - it is performed + let fetcher = build_fetcher(); + let maintainer = DefaultLightTransactionPoolMaintainer::new(fetcher.clone(), None, None); + *maintainer.revalidation_status.lock() = TxPoolRevalidationStatus::Scheduled(Some(Instant::now()), None); + let status = with_fetcher_maintain(fetcher, &maintainer); + assert_eq!(status.ready, 0); + + // when revalidation is scheduled by block number - it is performed + let fetcher = build_fetcher(); + let maintainer = DefaultLightTransactionPoolMaintainer::new(fetcher.clone(), None, None); + *maintainer.revalidation_status.lock() = TxPoolRevalidationStatus::Scheduled(None, Some(0)); + let status = with_fetcher_maintain(fetcher, &maintainer); + assert_eq!(status.ready, 0); + } + + #[test] + fn should_add_reverted_transactions_to_the_pool() { + let (client, longest_chain) = TestClientBuilder::new().build_with_longest_chain(); + let client = Arc::new(client); + let pool = TransactionPool::new(Default::default(), ::transaction_pool::FullChainApi::new(client.clone())); + let pool = Arc::new(pool); + let transaction = Transfer { + amount: 5, + nonce: 0, + from: AccountKeyring::Alice.into(), + to: Default::default(), + }.into_signed_tx(); + let best = longest_chain.best_chain().unwrap(); + + // store the transaction in the pool + block_on(pool.submit_one(&BlockId::hash(best.hash()), transaction.clone())).unwrap(); + + // import the block + let mut builder = client.new_block(Default::default()).unwrap(); + builder.push(transaction.clone()).unwrap(); + let block = builder.bake().unwrap(); + let block1_hash = block.header().hash(); + let id = BlockId::hash(block1_hash.clone()); + client.import(BlockOrigin::Own, block).unwrap(); + + // fire notification - this should clean up the queue + assert_eq!(pool.status().ready, 1); + DefaultFullTransactionPoolMaintainer.maintain( + &id, + &client, + &pool, + &[] + ).unwrap().wait().unwrap(); + + // then + assert_eq!(pool.status().ready, 0); + assert_eq!(pool.status().future, 0); + + // import second block + let builder = client.new_block_at(&BlockId::hash(best.hash()), Default::default()).unwrap(); + let block = builder.bake().unwrap(); + let id = BlockId::hash(block.header().hash()); + client.import(BlockOrigin::Own, block).unwrap(); + + // fire notification - this should add the transaction back to the pool. + DefaultFullTransactionPoolMaintainer.maintain( + &id, + &client, + &pool, + &[block1_hash] + ).unwrap().wait().unwrap(); + + // then + assert_eq!(pool.status().ready, 1); + assert_eq!(pool.status().future, 0); + } +} diff --git a/core/sr-api-macros/tests/ui/declaring_old_block.stderr b/core/sr-api-macros/tests/ui/declaring_old_block.stderr index 999a50cc96977..181aa2a3ca783 100644 --- a/core/sr-api-macros/tests/ui/declaring_old_block.stderr +++ b/core/sr-api-macros/tests/ui/declaring_old_block.stderr @@ -16,4 +16,4 @@ warning: unused import: `sr_primitives::traits::Block as BlockT` 1 | use sr_primitives::traits::Block as BlockT; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: `#[warn(unused_imports)]` on by default + = note: #[warn(unused_imports)] on by default diff --git a/core/sr-api-macros/tests/ui/declaring_own_block_with_different_name.stderr b/core/sr-api-macros/tests/ui/declaring_own_block_with_different_name.stderr index ec033f2e09d23..a591d0448c50d 100644 --- a/core/sr-api-macros/tests/ui/declaring_own_block_with_different_name.stderr +++ b/core/sr-api-macros/tests/ui/declaring_own_block_with_different_name.stderr @@ -10,4 +10,4 @@ warning: unused import: `sr_primitives::traits::Block as BlockT` 1 | use sr_primitives::traits::Block as BlockT; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: `#[warn(unused_imports)]` on by default + = note: #[warn(unused_imports)] on by default diff --git a/core/test-runtime/client/Cargo.toml b/core/test-runtime/client/Cargo.toml index 6545048759687..0bff905105689 100644 --- a/core/test-runtime/client/Cargo.toml +++ b/core/test-runtime/client/Cargo.toml @@ -10,6 +10,7 @@ primitives = { package = "substrate-primitives", path = "../../primitives" } runtime = { package = "substrate-test-runtime", path = "../../test-runtime", default-features = false } sr-primitives = { path = "../../sr-primitives" } codec = { package = "parity-scale-codec", version = "1.0.0", default-features = false } +futures03 = { package = "futures-preview", version = "0.3.0-alpha.19" } [features] default = [ diff --git a/core/test-runtime/client/src/lib.rs b/core/test-runtime/client/src/lib.rs index affbae62c22e7..53252560377ab 100644 --- a/core/test-runtime/client/src/lib.rs +++ b/core/test-runtime/client/src/lib.rs @@ -30,7 +30,15 @@ pub use runtime; use primitives::sr25519; use runtime::genesismap::{GenesisConfig, additional_storage_with_genesis}; -use sr_primitives::traits::{Block as BlockT, Header as HeaderT, Hash as HashT}; +use sr_primitives::traits::{Block as BlockT, Header as HeaderT, Hash as HashT, NumberFor}; +use client::{ + light::fetcher::{ + Fetcher, + RemoteHeaderRequest, RemoteReadRequest, RemoteReadChildRequest, + RemoteCallRequest, RemoteChangesRequest, RemoteBodyRequest, + }, +}; + /// A prelude to import in tests. pub mod prelude { @@ -247,6 +255,81 @@ impl TestClientBuilderExt for TestClientBuilder< } } +/// Type of optional fetch callback. +type MaybeFetcherCallback = Option Result + Send + Sync>>; + +/// Type of fetcher future result. +type FetcherFutureResult = futures03::future::Ready>; + +/// Implementation of light client fetcher used in tests. +#[derive(Default)] +pub struct LightFetcher { + call: MaybeFetcherCallback, Vec>, + body: MaybeFetcherCallback, Vec>, +} + +impl LightFetcher { + /// Sets remote call callback. + pub fn with_remote_call( + self, + call: MaybeFetcherCallback, Vec>, + ) -> Self { + LightFetcher { + call, + body: self.body, + } + } + + /// Sets remote body callback. + pub fn with_remote_body( + self, + body: MaybeFetcherCallback, Vec>, + ) -> Self { + LightFetcher { + call: self.call, + body, + } + } +} + +impl Fetcher for LightFetcher { + type RemoteHeaderResult = FetcherFutureResult; + type RemoteReadResult = FetcherFutureResult, Option>>>; + type RemoteCallResult = FetcherFutureResult>; + type RemoteChangesResult = FetcherFutureResult, u32)>>; + type RemoteBodyResult = FetcherFutureResult>; + + fn remote_header(&self, _: RemoteHeaderRequest) -> Self::RemoteHeaderResult { + unimplemented!() + } + + fn remote_read(&self, _: RemoteReadRequest) -> Self::RemoteReadResult { + unimplemented!() + } + + fn remote_read_child(&self, _: RemoteReadChildRequest) -> Self::RemoteReadResult { + unimplemented!() + } + + fn remote_call(&self, req: RemoteCallRequest) -> Self::RemoteCallResult { + match self.call { + Some(ref call) => futures03::future::ready(call(req)), + None => unimplemented!(), + } + } + + fn remote_changes(&self, _: RemoteChangesRequest) -> Self::RemoteChangesResult { + unimplemented!() + } + + fn remote_body(&self, req: RemoteBodyRequest) -> Self::RemoteBodyResult { + match self.body { + Some(ref body) => futures03::future::ready(body(req)), + None => unimplemented!(), + } + } +} + /// Creates new client instance used for tests. pub fn new() -> Client { TestClientBuilder::new().build() @@ -275,3 +358,8 @@ pub fn new_light() -> ( backend, ) } + +/// Creates new light client fetcher used for tests. +pub fn new_light_fetcher() -> LightFetcher { + LightFetcher::default() +} diff --git a/core/transaction-pool/graph/src/base_pool.rs b/core/transaction-pool/graph/src/base_pool.rs index cb37aee07f4b8..27e566ec9212e 100644 --- a/core/transaction-pool/graph/src/base_pool.rs +++ b/core/transaction-pool/graph/src/base_pool.rs @@ -83,8 +83,7 @@ pub struct PruneStatus { } /// Immutable transaction -#[cfg_attr(test, derive(Clone))] -#[derive(PartialEq, Eq)] +#[derive(Clone, PartialEq, Eq)] pub struct Transaction { /// Raw extrinsic representing that transaction. pub data: Extrinsic, @@ -159,6 +158,7 @@ const RECENTLY_PRUNED_TAGS: usize = 2; /// required tags. #[derive(Debug)] pub struct BasePool { + reject_future_transactions: bool, future: FutureTransactions, ready: ReadyTransactions, /// Store recently pruned tags (for last two invocations). @@ -172,6 +172,7 @@ pub struct BasePool { impl Default for BasePool { fn default() -> Self { BasePool { + reject_future_transactions: false, future: Default::default(), ready: Default::default(), recently_pruned: Default::default(), @@ -181,6 +182,11 @@ impl Default for BasePool { } impl BasePool { + /// Start rejecting future transactions. + pub fn reject_future_transactions(&mut self) { + self.reject_future_transactions = true; + } + /// Imports transaction to the pool. /// /// The pool consists of two parts: Future and Ready. @@ -206,6 +212,10 @@ impl BasePool BasePool Vec>> { + self.ready.remove_invalid(&[hash.clone()]) + } + /// Removes all transactions represented by the hashes and all other transactions /// that depend on them. /// @@ -972,4 +990,30 @@ requires: [03,02], provides: [04], data: [4]}".to_owned() propagate: false, }.is_propagateable(), false); } + + #[test] + fn should_reject_future_transactions() { + // given + let mut pool = pool(); + + // when + pool.reject_future_transactions(); + + // then + let err = pool.import(Transaction { + data: vec![5u8], + bytes: 1, + hash: 5, + priority: 5u64, + valid_till: 64u64, + requires: vec![vec![0]], + provides: vec![], + propagate: true, + }); + + if let Err(error::Error::RejectedFutureTransaction) = err { + } else { + assert!(false, "Invalid error kind: {:?}", err); + } + } } diff --git a/core/transaction-pool/graph/src/error.rs b/core/transaction-pool/graph/src/error.rs index 79006461c6e37..e1709c793bc6d 100644 --- a/core/transaction-pool/graph/src/error.rs +++ b/core/transaction-pool/graph/src/error.rs @@ -60,6 +60,9 @@ pub enum Error { ImmediatelyDropped, /// Invalid block id. InvalidBlockId(String), + /// The pool is not accepting future transactions. + #[display(fmt="The pool is not accepting future tranasctions")] + RejectedFutureTransaction, } impl std::error::Error for Error {} diff --git a/core/transaction-pool/graph/src/pool.rs b/core/transaction-pool/graph/src/pool.rs index 53b2a62cbee89..4e8ba50b4b252 100644 --- a/core/transaction-pool/graph/src/pool.rs +++ b/core/transaction-pool/graph/src/pool.rs @@ -122,6 +122,11 @@ impl Pool { } } + /// Start rejecting future transactions. + pub fn reject_future_transactions(&self) { + self.validated_pool.reject_future_transactions(); + } + /// Imports a bunch of unverified extrinsics to the pool pub fn submit_at(&self, at: &BlockId, xts: T, force: bool) -> impl Future, B::Error>>, B::Error>> @@ -131,7 +136,9 @@ impl Pool { let validated_pool = self.validated_pool.clone(); self.verify(at, xts, force) .map(move |validated_transactions| validated_transactions - .map(|validated_transactions| validated_pool.submit(validated_transactions))) + .map(|validated_transactions| validated_pool.submit(validated_transactions + .into_iter() + .map(|(_, tx)| tx)))) } /// Imports one unverified extrinsic to the pool @@ -165,6 +172,36 @@ impl Pool { ) } + /// Revalidate all ready transactions. + /// + /// Returns future that performs validation of all ready transactions and + /// then resubmits all transactions back to the pool. + pub fn revalidate_ready(&self, at: &BlockId) -> impl Future> { + let validated_pool = self.validated_pool.clone(); + let ready = self.validated_pool.ready().map(|tx| tx.data.clone()); + self.verify(at, ready, false) + .map(move |revalidated_transactions| revalidated_transactions.map( + move |revalidated_transactions| validated_pool.resubmit(revalidated_transactions) + )) + } + + /// Prunes known ready transactions. + /// + /// Used to clear the pool from transactions that were part of recently imported block. + /// The main difference from the `prune` is that we do not revalidate any transactions + /// and ignore unknown passed hashes. + pub fn prune_known(&self, at: &BlockId, hashes: &[ExHash]) -> Result<(), B::Error> { + // Get details of all extrinsics that are already in the pool + let in_pool_tags = self.validated_pool.extrinsics_tags(hashes) + .into_iter().filter_map(|x| x).flat_map(|x| x); + + // Prune all transactions that provide given tags + let prune_status = self.validated_pool.prune_tags(in_pool_tags)?; + let pruned_transactions = hashes.into_iter().cloned() + .chain(prune_status.pruned.iter().map(|tx| tx.hash.clone())); + self.validated_pool.fire_pruned(at, pruned_transactions) + } + /// Prunes ready transactions. /// /// Used to clear the pool from transactions that were part of recently imported block. @@ -178,7 +215,8 @@ impl Pool { extrinsics: &[ExtrinsicFor], ) -> impl Future> { // Get details of all extrinsics that are already in the pool - let (in_pool_hashes, in_pool_tags) = self.validated_pool.extrinsics_tags(extrinsics); + let in_pool_hashes = extrinsics.iter().map(|extrinsic| self.hash_of(extrinsic)).collect::>(); + let in_pool_tags = self.validated_pool.extrinsics_tags(&in_pool_hashes); // Zip the ones from the pool with the full list (we get pairs `(Extrinsic, Option>)`) let all = extrinsics.iter().zip(in_pool_tags.into_iter()); @@ -266,7 +304,7 @@ impl Pool { &at, known_imported_hashes, pruned_hashes, - reverified_transactions, + reverified_transactions.into_iter().map(|(_, xt)| xt).collect(), )) ))) } @@ -314,7 +352,7 @@ impl Pool { at: &BlockId, xts: impl IntoIterator>, force: bool, - ) -> impl Future>, B::Error>> { + ) -> impl Future, ValidatedTransactionFor>, B::Error>> { // we need a block number to compute tx validity let block_number = match self.resolve_block_number(at) { Ok(block_number) => block_number, @@ -322,12 +360,14 @@ impl Pool { }; // for each xt, prepare a validation future - let validation_futures = xts.into_iter().map(move |xt| + let validation_futures = xts.into_iter().map(move |xt| { + let hash = self.validated_pool.api().hash_and_length(&xt).0; self.verify_one(at, block_number, xt, force) - ); + .map(|v| (hash, v)) + }); // make single validation future that waits all until all extrinsics are validated - Either::Right(join_all(validation_futures).then(|x| ready(Ok(x)))) + Either::Right(join_all(validation_futures).then(|x| ready(Ok(x.into_iter().collect())))) } /// Returns future that validates single transaction at given block. @@ -383,7 +423,7 @@ impl Clone for Pool { #[cfg(test)] mod tests { use std::{ - collections::HashMap, + collections::{HashMap, HashSet}, time::Instant, }; use parking_lot::Mutex; @@ -401,6 +441,9 @@ mod tests { #[derive(Clone, Debug, Default)] struct TestApi { delay: Arc>>>, + invalidate: Arc>>, + clear_requirements: Arc>>, + add_requirements: Arc>>, } impl ChainApi for TestApi { @@ -415,6 +458,7 @@ mod tests { at: &BlockId, uxt: ExtrinsicFor, ) -> Self::ValidationFuture { + let hash = self.hash_and_length(&uxt).0; let block_number = self.block_id_to_number(at).unwrap().unwrap(); let nonce = uxt.transfer().nonce; @@ -428,16 +472,30 @@ mod tests { } } + if self.invalidate.lock().contains(&hash) { + return futures::future::ready(Ok(InvalidTransaction::Custom(0).into())); + } + futures::future::ready(if nonce < block_number { Ok(InvalidTransaction::Stale.into()) } else { - Ok(Ok(ValidTransaction { + let mut transaction = ValidTransaction { priority: 4, requires: if nonce > block_number { vec![vec![nonce as u8 - 1]] } else { vec![] }, provides: if nonce == INVALID_NONCE { vec![] } else { vec![vec![nonce as u8]] }, longevity: 3, propagate: true, - })) + }; + + if self.clear_requirements.lock().contains(&hash) { + transaction.requires.clear(); + } + + if self.add_requirements.lock().contains(&hash) { + transaction.requires.push(vec![128]); + } + + Ok(Ok(transaction)) }) } @@ -908,4 +966,80 @@ mod tests { assert_eq!(pool.status().future, 0); } } + + #[test] + fn should_revalidate_ready_transactions() { + fn transfer(nonce: u64) -> Extrinsic { + uxt(Transfer { + from: AccountId::from_h256(H256::from_low_u64_be(1)), + to: AccountId::from_h256(H256::from_low_u64_be(2)), + amount: 5, + nonce, + }) + } + + // given + let pool = pool(); + let tx0 = transfer(0); + let hash0 = pool.validated_pool.api().hash_and_length(&tx0).0; + let watcher0 = block_on(pool.submit_and_watch(&BlockId::Number(0), tx0)).unwrap(); + let tx1 = transfer(1); + let hash1 = pool.validated_pool.api().hash_and_length(&tx1).0; + let watcher1 = block_on(pool.submit_and_watch(&BlockId::Number(0), tx1)).unwrap(); + let tx2 = transfer(2); + let hash2 = pool.validated_pool.api().hash_and_length(&tx2).0; + let watcher2 = block_on(pool.submit_and_watch(&BlockId::Number(0), tx2)).unwrap(); + let tx3 = transfer(3); + let hash3 = pool.validated_pool.api().hash_and_length(&tx3).0; + let watcher3 = block_on(pool.submit_and_watch(&BlockId::Number(0), tx3)).unwrap(); + let tx4 = transfer(4); + let hash4 = pool.validated_pool.api().hash_and_length(&tx4).0; + let watcher4 = block_on(pool.submit_and_watch(&BlockId::Number(0), tx4)).unwrap(); + assert_eq!(pool.status().ready, 5); + + // when + pool.validated_pool.api().invalidate.lock().insert(hash3); + pool.validated_pool.api().clear_requirements.lock().insert(hash1); + pool.validated_pool.api().add_requirements.lock().insert(hash0); + block_on(pool.revalidate_ready(&BlockId::Number(0))).unwrap(); + + // then + // hash0 now has unsatisfied requirements => it is moved to the future queue + // hash1 is now independent of hash0 => it is in ready queue + // hash2 still depends on hash1 => it is in ready queue + // hash3 is now invalid => it is removed from the pool + // hash4 now depends on invalidated hash3 => it is moved to the future queue + // + // events for hash3 are: Ready, Invalid + // events for hash4 are: Ready, Invalid + assert_eq!(pool.status().ready, 2); + assert_eq!( + futures::executor::block_on_stream(watcher3.into_stream()).collect::>(), + vec![watcher::Status::Ready, watcher::Status::Invalid], + ); + + // when + pool.validated_pool.remove_invalid(&[hash0, hash1, hash2, hash4]); + + // then + // events for hash0 are: Ready, Future, Invalid + // events for hash1 are: Ready, Invalid + // events for hash2 are: Ready, Invalid + assert_eq!( + futures::executor::block_on_stream(watcher0.into_stream()).collect::>(), + vec![watcher::Status::Ready, watcher::Status::Future, watcher::Status::Invalid], + ); + assert_eq!( + futures::executor::block_on_stream(watcher1.into_stream()).collect::>(), + vec![watcher::Status::Ready, watcher::Status::Invalid], + ); + assert_eq!( + futures::executor::block_on_stream(watcher2.into_stream()).collect::>(), + vec![watcher::Status::Ready, watcher::Status::Invalid], + ); + assert_eq!( + futures::executor::block_on_stream(watcher4.into_stream()).collect::>(), + vec![watcher::Status::Ready, watcher::Status::Future, watcher::Status::Invalid], + ); + } } diff --git a/core/transaction-pool/graph/src/validated_pool.rs b/core/transaction-pool/graph/src/validated_pool.rs index 9bf1012628645..81d990c61f9bb 100644 --- a/core/transaction-pool/graph/src/validated_pool.rs +++ b/core/transaction-pool/graph/src/validated_pool.rs @@ -85,6 +85,11 @@ impl ValidatedPool { } } + /// Start rejecting future transactions. + pub fn reject_future_transactions(&self) { + self.pool.write().reject_future_transactions(); + } + /// Bans given set of hashes. pub fn ban(&self, now: &std::time::Instant, hashes: impl IntoIterator>) { self.rotator.ban(now, hashes) @@ -182,18 +187,100 @@ impl ValidatedPool { } } + /// Resubmits transactions in the pool. + /// + /// Removes and then submits passed transactions and all dependent transactions. + /// Transactions that are missing from the pool are not submitted. + pub fn resubmit(&self, mut transactions: HashMap, ValidatedTransactionFor>) { + #[derive(Debug, Clone, Copy, PartialEq)] + enum Status { Future, Ready, Failed, Dropped }; + + let (initial_statuses, final_statuses) = { + let mut pool = self.pool.write(); + + // remove all passed transactions from the ready/future queues + // (this may remove additional transactions as well) + let mut initial_statuses = HashMap::new(); + let mut txs_to_resubmit = Vec::with_capacity(transactions.len()); + while !transactions.is_empty() { + let hash = transactions.keys().next().cloned().expect("transactions is not empty; qed"); + + let removed = pool.remove_from_ready(&hash); + for removed_tx in removed { + let removed_hash = removed_tx.hash.clone(); + let tx_to_resubmit = if let Some(updated_tx) = transactions.remove(&removed_hash) { + updated_tx + } else { + ValidatedTransaction::Valid((*removed_tx).clone()) + }; + + initial_statuses.insert(removed_hash.clone(), Status::Ready); + txs_to_resubmit.push((removed_hash, tx_to_resubmit)); + } + } + + // now resubmit all removed transactions back to the pool + let mut final_statuses = HashMap::new(); + for (hash, tx_to_resubmit) in txs_to_resubmit { + match tx_to_resubmit { + ValidatedTransaction::Valid(tx) => match pool.import(tx) { + Ok(imported) => match imported { + base::Imported::Ready { promoted, failed, removed, .. } => { + final_statuses.insert(hash, Status::Ready); + for hash in promoted { + final_statuses.insert(hash, Status::Ready); + } + for hash in failed { + final_statuses.insert(hash, Status::Failed); + } + for tx in removed { + final_statuses.insert(tx.hash.clone(), Status::Dropped); + } + }, + base::Imported::Future { .. } => { + final_statuses.insert(hash, Status::Future); + }, + }, + Err(err) => { + // we do not want to fail if single transaction import has failed + // nor we do want to propagate this error, because it could tx unknown to caller + // => let's just notify listeners (and issue debug message) + debug!(target: "txpool", "[{:?}] Removing invalid transaction from update: {}", hash, err); + final_statuses.insert(hash, Status::Failed); + }, + }, + ValidatedTransaction::Invalid(_) | ValidatedTransaction::Unknown(_, _) => { + final_statuses.insert(hash, Status::Failed); + }, + } + } + + (initial_statuses, final_statuses) + }; + + // and now let's notify listeners about status changes + let mut listener = self.listener.write(); + for (hash, final_status) in final_statuses { + let initial_status = initial_statuses.get(&hash).cloned(); + if initial_status.is_none() || Some(final_status) != initial_status { + match final_status { + Status::Future => listener.future(&hash), + Status::Ready => listener.ready(&hash, None), + Status::Failed => listener.invalid(&hash), + Status::Dropped => listener.dropped(&hash, None), + } + } + } + } + /// For each extrinsic, returns tags that it provides (if known), or None (if it is unknown). - pub fn extrinsics_tags(&self, extrinsics: &[ExtrinsicFor]) -> (Vec>, Vec>>) { - let hashes = extrinsics.iter().map(|extrinsic| self.api.hash_and_length(extrinsic).0).collect::>(); - let in_pool = self.pool.read().by_hash(&hashes); - ( - hashes, - in_pool.into_iter() - .map(|existing_in_pool| existing_in_pool - .map(|transaction| transaction.provides.iter().cloned() - .collect())) - .collect(), - ) + pub fn extrinsics_tags(&self, hashes: &[ExHash]) -> Vec>> { + self.pool.read().by_hash(&hashes) + .into_iter() + .map(|existing_in_pool| existing_in_pool + .map(|transaction| transaction.provides.iter().cloned() + .collect())) + .collect() } /// Prunes ready transactions that provide given list of tags. @@ -242,20 +329,29 @@ impl ValidatedPool { // Fire `pruned` notifications for collected hashes and make sure to include // `known_imported_hashes` since they were just imported as part of the block. let hashes = hashes.chain(known_imported_hashes.into_iter()); - { - let header_hash = self.api.block_id_to_hash(at)? - .ok_or_else(|| error::Error::InvalidBlockId(format!("{:?}", at)).into())?; - let mut listener = self.listener.write(); - for h in hashes { - listener.pruned(header_hash, &h); - } - } + self.fire_pruned(at, hashes)?; + // perform regular cleanup of old transactions in the pool // and update temporary bans. self.clear_stale(at)?; Ok(()) } + /// Fire notifications for pruned transactions. + pub fn fire_pruned( + &self, + at: &BlockId, + hashes: impl Iterator>, + ) -> Result<(), B::Error> { + let header_hash = self.api.block_id_to_hash(at)? + .ok_or_else(|| error::Error::InvalidBlockId(format!("{:?}", at)).into())?; + let mut listener = self.listener.write(); + for h in hashes { + listener.pruned(header_hash, &h); + } + Ok(()) + } + /// Removes stale transactions from the pool. /// /// Stale transactions are transaction beyond their longevity period. diff --git a/core/transaction-pool/src/api.rs b/core/transaction-pool/src/api.rs index 96403bd3f876f..8ba3adbab84ba 100644 --- a/core/transaction-pool/src/api.rs +++ b/core/transaction-pool/src/api.rs @@ -18,10 +18,18 @@ use std::{ sync::Arc, - marker::PhantomData, + marker::{PhantomData, Unpin}, }; -use client::{runtime_api::TaggedTransactionQueue, blockchain::HeaderBackend}; -use codec::Encode; +use futures::{ + future::{ready, Future, FutureExt, Ready}, +}; +use client::{ + error::Error as ClientError, + runtime_api::TaggedTransactionQueue, + blockchain::HeaderBackend, + light::fetcher::{Fetcher, RemoteCallRequest}, +}; +use codec::{Decode, Encode}; use txpool; use primitives::{ H256, @@ -30,20 +38,20 @@ use primitives::{ }; use sr_primitives::{ generic::BlockId, - traits, + traits::{self, Block as BlockT}, transaction_validity::TransactionValidity, }; use crate::error; -/// The transaction pool logic +/// The transaction pool logic for full client. pub struct FullChainApi { client: Arc, _marker: PhantomData, } impl FullChainApi where - Block: traits::Block, + Block: BlockT, T: traits::ProvideRuntimeApi + HeaderBackend { /// Create new transaction pool logic. pub fn new(client: Arc) -> Self { @@ -55,14 +63,14 @@ impl FullChainApi where } impl txpool::ChainApi for FullChainApi where - Block: traits::Block, + Block: BlockT, T: traits::ProvideRuntimeApi + HeaderBackend, T::Api: TaggedTransactionQueue { type Block = Block; type Hash = H256; type Error = error::Error; - type ValidationFuture = futures::future::Ready>; + type ValidationFuture = Ready>; fn validate_transaction( &self, @@ -86,3 +94,82 @@ impl txpool::ChainApi for FullChainApi where }) } } + +/// The transaction pool logic for light client. +pub struct LightChainApi { + client: Arc, + fetcher: Arc, + _phantom: PhantomData, +} + +impl LightChainApi where + Block: BlockT, + T: HeaderBackend, + F: Fetcher, +{ + /// Create new transaction pool logic. + pub fn new(client: Arc, fetcher: Arc) -> Self { + LightChainApi { + client, + fetcher, + _phantom: Default::default(), + } + } +} + +impl txpool::ChainApi for LightChainApi where + Block: BlockT, + T: HeaderBackend + 'static, + F: Fetcher + 'static, +{ + type Block = Block; + type Hash = H256; + type Error = error::Error; + type ValidationFuture = Box> + Send + Unpin>; + + fn validate_transaction( + &self, + at: &BlockId, + uxt: txpool::ExtrinsicFor, + ) -> Self::ValidationFuture { + let header_hash = self.client.expect_block_hash_from_id(at); + let header_and_hash = header_hash + .and_then(|header_hash| self.client.expect_header(BlockId::Hash(header_hash)) + .map(|header| (header_hash, header))); + let (block, header) = match header_and_hash { + Ok((header_hash, header)) => (header_hash, header), + Err(err) => return Box::new(ready(Err(err.into()))), + }; + let remote_validation_request = self.fetcher.remote_call(RemoteCallRequest { + block, + header, + method: "TaggedTransactionQueue_validate_transaction".into(), + call_data: uxt.encode(), + retry_count: None, + }); + let remote_validation_request = remote_validation_request.then(move |result| { + let result: error::Result = result + .and_then(|result| Decode::decode(&mut &result[..]) + .map_err(|e| ClientError::CallResultDecode("Error decoding tx validation result", e)) + ) + .map_err(Into::into); + ready(result) + }); + + Box::new(remote_validation_request) + } + + fn block_id_to_number(&self, at: &BlockId) -> error::Result>> { + Ok(self.client.block_number_from_id(at)?) + } + + fn block_id_to_hash(&self, at: &BlockId) -> error::Result>> { + Ok(self.client.block_hash_from_id(at)?) + } + + fn hash_and_length(&self, ex: &txpool::ExtrinsicFor) -> (Self::Hash, usize) { + ex.using_encoded(|x| { + (Blake2Hasher::hash(x), x.len()) + }) + } +} diff --git a/core/transaction-pool/src/lib.rs b/core/transaction-pool/src/lib.rs index 6938166299d85..d0e19eced815d 100644 --- a/core/transaction-pool/src/lib.rs +++ b/core/transaction-pool/src/lib.rs @@ -25,5 +25,5 @@ mod tests; pub mod error; -pub use api::FullChainApi; +pub use api::{FullChainApi, LightChainApi}; pub use txpool; diff --git a/node-template/src/service.rs b/node-template/src/service.rs index 24b22082c5de7..4fec1659db3b9 100644 --- a/node-template/src/service.rs +++ b/node-template/src/service.rs @@ -41,7 +41,7 @@ macro_rules! new_full_start { .with_select_chain(|_config, backend| { Ok(substrate_client::LongestChain::new(backend.clone())) })? - .with_transaction_pool(|config, client| + .with_transaction_pool(|config, client, _fetcher| Ok(transaction_pool::txpool::Pool::new(config, transaction_pool::FullChainApi::new(client))) )? .with_import_queue(|_config, client, mut select_chain, _transaction_pool| { @@ -186,9 +186,13 @@ pub fn new_light(config: Configuration RpcExtension { - node_rpc::create(client, pool) + .with_rpc_extensions(|client, pool, _fetcher, _remote_blockchain| -> Result { + Ok(node_rpc::create_full(client, pool)) })?; (builder, import_setup, inherent_data_providers) @@ -273,9 +273,13 @@ pub fn new_light(config: NodeConfiguration) .with_select_chain(|_config, backend| { Ok(LongestChain::new(backend.clone())) })? - .with_transaction_pool(|config, client| - Ok(TransactionPool::new(config, transaction_pool::FullChainApi::new(client))) - )? + .with_transaction_pool(|config, client, fetcher| { + let fetcher = fetcher + .ok_or_else(|| "Trying to start light transaction pool without active fetcher")?; + let pool = TransactionPool::new(config, transaction_pool::LightChainApi::new(client, fetcher)); + pool.reject_future_transactions(); + Ok(pool) + })? .with_import_queue_and_fprb(|_config, client, backend, fetcher, _select_chain, _tx_pool| { let fetch_checker = fetcher .map(|fetcher| fetcher.checker().clone()) @@ -311,8 +315,12 @@ pub fn new_light(config: NodeConfiguration) .with_finality_proof_provider(|client, backend| Ok(Arc::new(GrandpaFinalityProofProvider::new(backend, client)) as _) )? - .with_rpc_extensions(|client, pool| -> RpcExtension { - node_rpc::create(client, pool) + .with_rpc_extensions(|client, pool, fetcher, remote_blockchain| -> Result { + let fetcher = fetcher + .ok_or_else(|| "Trying to start node RPC without active fetcher")?; + let remote_blockchain = remote_blockchain + .ok_or_else(|| "Trying to start node RPC without active remote blockchain")?; + Ok(node_rpc::create_light(client, remote_blockchain, fetcher, pool)) })? .build()?; diff --git a/node/rpc/Cargo.toml b/node/rpc/Cargo.toml index 6985d94e54f32..242067fb01ee2 100644 --- a/node/rpc/Cargo.toml +++ b/node/rpc/Cargo.toml @@ -19,9 +19,10 @@ sr-primitives = { path = "../../core/sr-primitives" } substrate-primitives = { path = "../../core/primitives" } rpc-primitives = { package = "substrate-rpc-primitives", path = "../../core/rpc/primitives" } transaction_pool = { package = "substrate-transaction-pool", path = "../../core/transaction-pool" } +futures03 = { package = "futures-preview", version = "=0.3.0-alpha.19" } [dev-dependencies] node-testing = { path = "../testing" } node-runtime = { path = "../runtime" } env_logger = "0.7.0" -futures03 = { package = "futures-preview", version = "=0.3.0-alpha.19" } + diff --git a/node/rpc/src/accounts.rs b/node/rpc/src/accounts.rs index 6c8e60736ac53..38650704f6e28 100644 --- a/node/rpc/src/accounts.rs +++ b/node/rpc/src/accounts.rs @@ -18,19 +18,31 @@ use std::sync::Arc; -use client::blockchain::HeaderBackend; -use jsonrpc_core::{Result, Error, ErrorCode}; +use client::{ + blockchain::HeaderBackend, + error::Error as ClientError, + light::blockchain::{future_header, RemoteBlockchain}, + light::fetcher::{Fetcher, RemoteCallRequest}, +}; +use jsonrpc_core::{ + Error, ErrorCode, + futures::future::{result, Future}, +}; use jsonrpc_derive::rpc; +use futures03::future::{ready, TryFutureExt}; use node_primitives::{ AccountId, Index, AccountNonceApi, Block, BlockId, }; -use codec::Encode; +use codec::{Decode, Encode}; use sr_primitives::traits; use substrate_primitives::hexdisplay::HexDisplay; use transaction_pool::txpool::{self, Pool}; pub use self::gen_client::Client as AccountsClient; +/// Future that resolves to account nonce. +pub type FutureResult = Box + Send>; + /// Accounts RPC methods. #[rpc] pub trait AccountsApi { @@ -40,26 +52,26 @@ pub trait AccountsApi { /// currently in the pool and if no transactions are found in the pool /// it fallbacks to query the index from the runtime (aka. state nonce). #[rpc(name = "account_nextIndex")] - fn nonce(&self, account: AccountId) -> Result; + fn nonce(&self, account: AccountId) -> FutureResult; } -/// An implementation of Accounts specific RPC methods. -pub struct Accounts { +/// An implementation of Accounts specific RPC methods on full client. +pub struct FullAccounts { client: Arc, pool: Arc>, } -impl Accounts { - /// Create new `Accounts` given client and transaction pool. +impl FullAccounts { + /// Create new `FullAccounts` given client and transaction pool. pub fn new(client: Arc, pool: Arc>) -> Self { - Accounts { + FullAccounts { client, pool } } } -impl AccountsApi for Accounts +impl AccountsApi for FullAccounts where C: traits::ProvideRuntimeApi, C: HeaderBackend, @@ -67,46 +79,127 @@ where C::Api: AccountNonceApi, P: txpool::ChainApi + Sync + Send + 'static, { - fn nonce(&self, account: AccountId) -> Result { - let api = self.client.runtime_api(); - let best = self.client.info().best_hash; - let at = BlockId::hash(best); + fn nonce(&self, account: AccountId) -> FutureResult { + let get_nonce = || { + let api = self.client.runtime_api(); + let best = self.client.info().best_hash; + let at = BlockId::hash(best); + + let nonce = api.account_nonce(&at, account.clone()).map_err(|e| Error { + code: ErrorCode::ServerError(crate::constants::RUNTIME_ERROR), + message: "Unable to query nonce.".into(), + data: Some(format!("{:?}", e).into()), + })?; + + Ok(adjust_nonce(&*self.pool, account, nonce)) + }; + + Box::new(result(get_nonce())) + } +} + +/// An implementation of Accounts specific RPC methods on light client. +pub struct LightAccounts { + client: Arc, + remote_blockchain: Arc>, + fetcher: Arc, + pool: Arc>, +} + +impl LightAccounts { + /// Create new `LightAccounts` given client and transaction pool. + pub fn new( + client: Arc, + remote_blockchain: Arc>, + fetcher: Arc, + pool: Arc>, + ) -> Self { + LightAccounts { + client, + remote_blockchain, + fetcher, + pool, + } + } +} - let nonce = api.account_nonce(&at, account.clone()).map_err(|e| Error { +impl AccountsApi for LightAccounts +where + P: txpool::ChainApi + Sync + Send + 'static, + C: HeaderBackend + 'static, + F: Fetcher + 'static, +{ + fn nonce(&self, account: AccountId) -> FutureResult { + let best_hash = self.client.info().best_hash; + let best_id = BlockId::hash(best_hash); + let future_best_header = future_header(&*self.remote_blockchain, &*self.fetcher, best_id); + let fetcher = self.fetcher.clone(); + let call_data = account.encode(); + let future_best_header = future_best_header.and_then(move |maybe_best_header| ready( + match maybe_best_header { + Some(best_header) => Ok(best_header), + None => Err(ClientError::UnknownBlock(format!("{}", best_hash))), + } + )); + let future_nonce = future_best_header.and_then(move |best_header| + fetcher.remote_call(RemoteCallRequest { + block: best_hash, + header: best_header, + method: "AccountNonceApi_account_nonce".into(), + call_data, + retry_count: None, + }) + ).compat(); + let future_nonce = future_nonce.and_then(|nonce| Decode::decode(&mut &nonce[..]) + .map_err(|e| ClientError::CallResultDecode("Cannot decode account nonce", e))); + let future_nonce = future_nonce.map_err(|e| Error { code: ErrorCode::ServerError(crate::constants::RUNTIME_ERROR), message: "Unable to query nonce.".into(), data: Some(format!("{:?}", e).into()), - })?; - - log::debug!(target: "rpc", "State nonce for {}: {}", account, nonce); - // Now we need to query the transaction pool - // and find transactions originating from the same sender. - // - // Since extrinsics are opaque to us, we look for them using - // `provides` tag. And increment the nonce if we find a transaction - // that matches the current one. - let mut current_nonce = nonce; - let mut current_tag = (account.clone(), nonce).encode(); - for tx in self.pool.ready() { - log::debug!( - target: "rpc", - "Current nonce to {:?}, checking {} vs {:?}", - current_nonce, - HexDisplay::from(¤t_tag), - tx.provides.iter().map(|x| format!("{}", HexDisplay::from(x))).collect::>(), - ); - // since transactions in `ready()` need to be ordered by nonce - // it's fine to continue with current iterator. - if tx.provides.get(0) == Some(¤t_tag) { - current_nonce += 1; - current_tag = (account.clone(), current_nonce).encode(); - } - } + }); + + let pool = self.pool.clone(); + let future_nonce = future_nonce.map(move |nonce| adjust_nonce(&*pool, account, nonce)); - Ok(current_nonce) + Box::new(future_nonce) } } +/// Adjust account nonce from state, so that tx with the nonce will be +/// placed after all ready txpool transactions. +fn adjust_nonce( + pool: &Pool

, + account: AccountId, + nonce: Index, +) -> Index { + log::debug!(target: "rpc", "State nonce for {}: {}", account, nonce); + // Now we need to query the transaction pool + // and find transactions originating from the same sender. + // + // Since extrinsics are opaque to us, we look for them using + // `provides` tag. And increment the nonce if we find a transaction + // that matches the current one. + let mut current_nonce = nonce; + let mut current_tag = (account.clone(), nonce).encode(); + for tx in pool.ready() { + log::debug!( + target: "rpc", + "Current nonce to {:?}, checking {} vs {:?}", + current_nonce, + HexDisplay::from(¤t_tag), + tx.provides.iter().map(|x| format!("{}", HexDisplay::from(x))).collect::>(), + ); + // since transactions in `ready()` need to be ordered by nonce + // it's fine to continue with current iterator. + if tx.provides.get(0) == Some(¤t_tag) { + current_nonce += 1; + current_tag = (account.clone(), current_nonce).encode(); + } + } + + current_nonce +} + #[cfg(test)] mod tests { use super::*; @@ -144,12 +237,12 @@ mod tests { let ext1 = new_transaction(signed_extra(1, 0)); block_on(pool.submit_one(&BlockId::number(0), ext1)).unwrap(); - let accounts = Accounts::new(client, pool); + let accounts = FullAccounts::new(client, pool); // when let nonce = accounts.nonce(alice().into()); // then - assert_eq!(nonce.unwrap(), 2); + assert_eq!(nonce.wait().unwrap(), 2); } } diff --git a/node/rpc/src/lib.rs b/node/rpc/src/lib.rs index 43f723f7964bc..8c9e87d6e7616 100644 --- a/node/rpc/src/lib.rs +++ b/node/rpc/src/lib.rs @@ -45,8 +45,8 @@ mod constants { pub const RUNTIME_ERROR: i64 = 1; } -/// Instantiate all RPC extensions. -pub fn create(client: Arc, pool: Arc>) -> jsonrpc_core::IoHandler where +/// Instantiate all RPC extensions for full node. +pub fn create_full(client: Arc, pool: Arc>) -> jsonrpc_core::IoHandler where C: ProvideRuntimeApi, C: client::blockchain::HeaderBackend, C: Send + Sync + 'static, @@ -55,16 +55,43 @@ pub fn create(client: Arc, pool: Arc>) -> jsonrpc_core::IoHa M: jsonrpc_core::Metadata + Default, { use self::{ - accounts::{Accounts, AccountsApi}, + accounts::{FullAccounts, AccountsApi}, contracts::{Contracts, ContractsApi}, }; let mut io = jsonrpc_core::IoHandler::default(); io.extend_with( - AccountsApi::to_delegate(Accounts::new(client.clone(), pool)) + AccountsApi::to_delegate(FullAccounts::new(client.clone(), pool)) ); io.extend_with( ContractsApi::to_delegate(Contracts::new(client)) ); io } + +/// Instantiate all RPC extensions for light node. +pub fn create_light( + client: Arc, + remote_blockchain: Arc>, + fetcher: Arc, + pool: Arc>, +) -> jsonrpc_core::IoHandler + where + C: ProvideRuntimeApi, + C: client::blockchain::HeaderBackend, + C: Send + Sync + 'static, + C::Api: AccountNonceApi + ContractsApi, + P: ChainApi + Sync + Send + 'static, + M: jsonrpc_core::Metadata + Default, + F: client::light::fetcher::Fetcher + 'static, +{ + use self::{ + accounts::{LightAccounts, AccountsApi}, + }; + + let mut io = jsonrpc_core::IoHandler::default(); + io.extend_with( + AccountsApi::to_delegate(LightAccounts::new(client, remote_blockchain, fetcher, pool)) + ); + io +} From 5b207b9c9c3419e1b793c2b415a60a678f9cac9a Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Wed, 16 Oct 2019 15:02:16 +0300 Subject: [PATCH 02/38] revert local tests fix --- core/sr-api-macros/tests/ui/declaring_old_block.stderr | 2 +- .../tests/ui/declaring_own_block_with_different_name.stderr | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/core/sr-api-macros/tests/ui/declaring_old_block.stderr b/core/sr-api-macros/tests/ui/declaring_old_block.stderr index 181aa2a3ca783..999a50cc96977 100644 --- a/core/sr-api-macros/tests/ui/declaring_old_block.stderr +++ b/core/sr-api-macros/tests/ui/declaring_old_block.stderr @@ -16,4 +16,4 @@ warning: unused import: `sr_primitives::traits::Block as BlockT` 1 | use sr_primitives::traits::Block as BlockT; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: #[warn(unused_imports)] on by default + = note: `#[warn(unused_imports)]` on by default diff --git a/core/sr-api-macros/tests/ui/declaring_own_block_with_different_name.stderr b/core/sr-api-macros/tests/ui/declaring_own_block_with_different_name.stderr index a591d0448c50d..ec033f2e09d23 100644 --- a/core/sr-api-macros/tests/ui/declaring_own_block_with_different_name.stderr +++ b/core/sr-api-macros/tests/ui/declaring_own_block_with_different_name.stderr @@ -10,4 +10,4 @@ warning: unused import: `sr_primitives::traits::Block as BlockT` 1 | use sr_primitives::traits::Block as BlockT; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: #[warn(unused_imports)] on by default + = note: `#[warn(unused_imports)]` on by default From 28b0388427af693d3aa38c86be034d246ac04a2c Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Tue, 22 Oct 2019 10:23:53 +0300 Subject: [PATCH 03/38] removed import renamings --- core/service/src/builder.rs | 4 ++-- core/service/src/pool_maintainer.rs | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/core/service/src/builder.rs b/core/service/src/builder.rs index 5ce8b68dc06eb..e0ee018193d59 100644 --- a/core/service/src/builder.rs +++ b/core/service/src/builder.rs @@ -32,8 +32,8 @@ use consensus_common::import_queue::ImportQueue; use futures::{prelude::*, sync::mpsc}; use futures03::{ compat::Compat, - FutureExt as _, - StreamExt as _, TryStreamExt as _, + FutureExt, + StreamExt, TryStreamExt, }; use keystore::{Store as Keystore, KeyStorePtr}; use log::{info, warn}; diff --git a/core/service/src/pool_maintainer.rs b/core/service/src/pool_maintainer.rs index 891466a4181e6..f75b4d73963eb 100644 --- a/core/service/src/pool_maintainer.rs +++ b/core/service/src/pool_maintainer.rs @@ -22,7 +22,7 @@ use client::{ use futures::prelude::*; use futures03::{ future::{ready, Either}, - FutureExt as _, TryFutureExt as _, + FutureExt, TryFutureExt, }; use log::warn; use parking_lot::Mutex; From 736cabed1fba41dc0ec8d5c873d2631c71d8a8ec Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Tue, 22 Oct 2019 11:03:36 +0300 Subject: [PATCH 04/38] futures03::Future -> std::future::Future --- core/service/src/pool_maintainer.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/service/src/pool_maintainer.rs b/core/service/src/pool_maintainer.rs index f75b4d73963eb..fad060ccb2551 100644 --- a/core/service/src/pool_maintainer.rs +++ b/core/service/src/pool_maintainer.rs @@ -160,7 +160,7 @@ impl> DefaultLightTransactionPoolMaintainer, header: &Block::Header, transaction_pool: &Arc>, - ) -> impl futures03::Future where + ) -> impl std::future::Future where PoolApi: 'static + txpool::ChainApi, { // fetch transactions (possible future optimization: proofs of inclusion) that @@ -197,7 +197,7 @@ impl> DefaultLightTransactionPoolMaintainer, header: &Block::Header, transaction_pool: &Arc>, - ) -> impl futures03::Future where + ) -> impl std::future::Future where PoolApi: 'static + txpool::ChainApi, { // to determine whether ready transaction is still valid, we perform periodic revalidaton From 2d485e75d8ef15a2bb2d4fabef4cf5dfe33d1694 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Tue, 22 Oct 2019 11:12:11 +0300 Subject: [PATCH 05/38] Update core/transaction-pool/graph/src/error.rs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Tomasz DrwiÄ™ga --- core/transaction-pool/graph/src/error.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/transaction-pool/graph/src/error.rs b/core/transaction-pool/graph/src/error.rs index e1709c793bc6d..19270f349a460 100644 --- a/core/transaction-pool/graph/src/error.rs +++ b/core/transaction-pool/graph/src/error.rs @@ -61,7 +61,7 @@ pub enum Error { /// Invalid block id. InvalidBlockId(String), /// The pool is not accepting future transactions. - #[display(fmt="The pool is not accepting future tranasctions")] + #[display(fmt="The pool is not accepting future transactions")] RejectedFutureTransaction, } From eecb81955e2620f69466328ab5bc0715de0eb268 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Tue, 22 Oct 2019 11:30:26 +0300 Subject: [PATCH 06/38] replace remove_from_ready with remove_invalid --- core/transaction-pool/graph/src/base_pool.rs | 8 -------- core/transaction-pool/graph/src/validated_pool.rs | 5 ++++- 2 files changed, 4 insertions(+), 9 deletions(-) diff --git a/core/transaction-pool/graph/src/base_pool.rs b/core/transaction-pool/graph/src/base_pool.rs index 27e566ec9212e..3580812815295 100644 --- a/core/transaction-pool/graph/src/base_pool.rs +++ b/core/transaction-pool/graph/src/base_pool.rs @@ -366,14 +366,6 @@ impl BasePool Vec>> { - self.ready.remove_invalid(&[hash.clone()]) - } - /// Removes all transactions represented by the hashes and all other transactions /// that depend on them. /// diff --git a/core/transaction-pool/graph/src/validated_pool.rs b/core/transaction-pool/graph/src/validated_pool.rs index 81d990c61f9bb..640026cc4094b 100644 --- a/core/transaction-pool/graph/src/validated_pool.rs +++ b/core/transaction-pool/graph/src/validated_pool.rs @@ -205,7 +205,10 @@ impl ValidatedPool { while !transactions.is_empty() { let hash = transactions.keys().next().cloned().expect("transactions is not empty; qed"); - let removed = pool.remove_from_ready(&hash); + // note we are not considering tx with hash invalid here - we just want + // to remove it along with dependent transactions and `remove_invalid()` + // does exactly what we need + let removed = pool.remove_invalid(&[hash.clone()]); for removed_tx in removed { let removed_hash = removed_tx.hash.clone(); let tx_to_resubmit = if let Some(updated_tx) = transactions.remove(&removed_hash) { From b5cdc4e53271bc57d78ad42d88ef79ea81ce4fc7 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Tue, 22 Oct 2019 11:30:33 +0300 Subject: [PATCH 07/38] avoid excess hashing --- core/transaction-pool/graph/src/pool.rs | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/core/transaction-pool/graph/src/pool.rs b/core/transaction-pool/graph/src/pool.rs index bc362ed84d439..6b66f657daec4 100644 --- a/core/transaction-pool/graph/src/pool.rs +++ b/core/transaction-pool/graph/src/pool.rs @@ -168,7 +168,7 @@ impl Pool { let validated_pool = self.validated_pool.clone(); Either::Right( self.verify_one(at, block_number, xt, false) - .map(move |validated_transactions| validated_pool.submit_and_watch(validated_transactions)) + .map(move |validated_transactions| validated_pool.submit_and_watch(validated_transactions.1)) ) } @@ -360,11 +360,9 @@ impl Pool { }; // for each xt, prepare a validation future - let validation_futures = xts.into_iter().map(move |xt| { - let hash = self.validated_pool.api().hash_and_length(&xt).0; + let validation_futures = xts.into_iter().map(move |xt| self.verify_one(at, block_number, xt, force) - .map(|v| (hash, v)) - }); + ); // make single validation future that waits all until all extrinsics are validated Either::Right(join_all(validation_futures).then(|x| ready(Ok(x.into_iter().collect())))) @@ -377,14 +375,14 @@ impl Pool { block_number: NumberFor, xt: ExtrinsicFor, force: bool, - ) -> impl Future> { + ) -> impl Future, ValidatedTransactionFor)> { let (hash, bytes) = self.validated_pool.api().hash_and_length(&xt); if !force && self.validated_pool.is_banned(&hash) { - return Either::Left(ready(ValidatedTransaction::Invalid(error::Error::TemporarilyBanned.into()))) + return Either::Left(ready((hash, ValidatedTransaction::Invalid(error::Error::TemporarilyBanned.into())))) } Either::Right(self.validated_pool.api().validate_transaction(block_id, xt.clone()) - .then(move |validation_result| ready(match validation_result { + .then(move |validation_result| ready((hash.clone(), match validation_result { Ok(validity) => match validity { Ok(validity) => if validity.provides.is_empty() { ValidatedTransaction::Invalid(error::Error::NoTagsProvided.into()) @@ -408,7 +406,7 @@ impl Pool { ValidatedTransaction::Unknown(hash, error::Error::UnknownTransaction(e).into()), }, Err(e) => ValidatedTransaction::Invalid(e), - }))) + })))) } } From bf9d91bc3506d03e018c9981275a31706d64e572 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Tue, 22 Oct 2019 12:11:21 +0300 Subject: [PATCH 08/38] debug -> warn --- core/transaction-pool/graph/src/validated_pool.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/transaction-pool/graph/src/validated_pool.rs b/core/transaction-pool/graph/src/validated_pool.rs index 640026cc4094b..d37671af2dadc 100644 --- a/core/transaction-pool/graph/src/validated_pool.rs +++ b/core/transaction-pool/graph/src/validated_pool.rs @@ -26,7 +26,7 @@ use crate::listener::Listener; use crate::rotator::PoolRotator; use crate::watcher::Watcher; use serde::Serialize; -use log::debug; +use log::{debug, warn}; use futures::channel::mpsc; use parking_lot::{Mutex, RwLock}; @@ -248,7 +248,7 @@ impl ValidatedPool { // we do not want to fail if single transaction import has failed // nor we do want to propagate this error, because it could tx unknown to caller // => let's just notify listeners (and issue debug message) - debug!(target: "txpool", "[{:?}] Removing invalid transaction from update: {}", hash, err); + warn!(target: "txpool", "[{:?}] Removing invalid transaction from update: {}", hash, err); final_statuses.insert(hash, Status::Failed); }, }, From e9f0d33ace3ad7fdc97cb0c9da8c07187e8252af Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Wed, 23 Oct 2019 11:28:06 +0300 Subject: [PATCH 09/38] TransactionPool + BasicTransactionPool --- Cargo.lock | 2 + core/basic-authorship/src/basic_authorship.rs | 20 +- core/basic-authorship/src/lib.rs | 5 +- core/offchain/src/api.rs | 25 +- core/offchain/src/lib.rs | 11 +- core/rpc/src/author/mod.rs | 27 +- core/rpc/src/author/tests.rs | 21 +- core/service/src/builder.rs | 126 ++----- core/service/src/lib.rs | 61 ++-- core/service/test/Cargo.toml | 1 + core/service/test/src/lib.rs | 1 + .../tests/ui/declaring_old_block.stderr | 2 +- ...aring_own_block_with_different_name.stderr | 2 +- core/transaction-pool/Cargo.toml | 1 + core/transaction-pool/graph/src/base_pool.rs | 24 +- core/transaction-pool/graph/src/lib.rs | 1 + core/transaction-pool/graph/src/pool.rs | 14 +- core/transaction-pool/graph/src/ready.rs | 3 +- .../graph/src/validated_pool.rs | 11 +- core/transaction-pool/src/lib.rs | 238 ++++++++++++- .../src/maintainer.rs} | 320 ++++++++++-------- node-template/src/service.rs | 6 +- node/cli/src/service.rs | 21 +- node/rpc/src/lib.rs | 10 +- srml/system/rpc/src/lib.rs | 29 +- 25 files changed, 599 insertions(+), 383 deletions(-) rename core/{service/src/pool_maintainer.rs => transaction-pool/src/maintainer.rs} (64%) diff --git a/Cargo.lock b/Cargo.lock index 7b65adaf663e5..8e9e7a8c8853e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5476,6 +5476,7 @@ dependencies = [ "substrate-network 2.0.0", "substrate-primitives 2.0.0", "substrate-service 2.0.0", + "substrate-transaction-pool 2.0.0", "tempdir 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", "tokio 0.1.22 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -5634,6 +5635,7 @@ dependencies = [ "parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", "sr-primitives 2.0.0", "substrate-client 2.0.0", + "substrate-consensus-common 2.0.0", "substrate-keyring 2.0.0", "substrate-primitives 2.0.0", "substrate-test-runtime-client 2.0.0", diff --git a/core/basic-authorship/src/basic_authorship.rs b/core/basic-authorship/src/basic_authorship.rs index 7f8b343f6512c..a1fa930f2bf91 100644 --- a/core/basic-authorship/src/basic_authorship.rs +++ b/core/basic-authorship/src/basic_authorship.rs @@ -35,21 +35,21 @@ use sr_primitives::{ }, generic::BlockId, }; -use transaction_pool::txpool::{self, Pool as TransactionPool}; +use transaction_pool::TransactionPool; use substrate_telemetry::{telemetry, CONSENSUS_INFO}; /// Proposer factory. -pub struct ProposerFactory where A: txpool::ChainApi { +pub struct ProposerFactory where A: TransactionPool { /// The client instance. pub client: Arc, /// The transaction pool. - pub transaction_pool: Arc>, + pub transaction_pool: Arc, } impl consensus_common::Environment for ProposerFactory, A> where - A: txpool::ChainApi, + A: TransactionPool, B: client::backend::Backend + Send + Sync + 'static, E: CallExecutor + Send + Sync + Clone + 'static, Block: BlockT, @@ -84,19 +84,19 @@ where } /// The proposer logic. -pub struct Proposer { +pub struct Proposer { client: Arc, parent_hash: ::Hash, parent_id: BlockId, parent_number: <::Header as HeaderT>::Number, - transaction_pool: Arc>, + transaction_pool: Arc, now: Box time::Instant>, } impl consensus_common::Proposer for Proposer, A> where - A: txpool::ChainApi, + A: TransactionPool, B: client::backend::Backend + Send + Sync + 'static, E: CallExecutor + Send + Sync + Clone + 'static, Block: BlockT, @@ -120,7 +120,7 @@ where } impl Proposer, A> where - A: txpool::ChainApi, + A: TransactionPool, B: client::backend::Backend + Send + Sync + 'static, E: CallExecutor + Send + Sync + Clone + 'static, Block: BlockT, @@ -233,6 +233,7 @@ mod tests { use std::cell::RefCell; use consensus_common::{Environment, Proposer}; use test_client::{self, runtime::{Extrinsic, Transfer}, AccountKeyring}; + use transaction_pool::BasicTransactionPool; fn extrinsic(nonce: u64) -> Extrinsic { Transfer { @@ -247,8 +248,7 @@ mod tests { fn should_cease_building_block_when_deadline_is_reached() { // given let client = Arc::new(test_client::new()); - let chain_api = transaction_pool::FullChainApi::new(client.clone()); - let txpool = Arc::new(TransactionPool::new(Default::default(), chain_api)); + let txpool = Arc::new(BasicTransactionPool::default_full(Default::default(), client.clone())); futures::executor::block_on( txpool.submit_at(&BlockId::number(0), vec![extrinsic(0), extrinsic(1)], false) diff --git a/core/basic-authorship/src/lib.rs b/core/basic-authorship/src/lib.rs index 7961e4fe9e9df..9860f84c0e3a1 100644 --- a/core/basic-authorship/src/lib.rs +++ b/core/basic-authorship/src/lib.rs @@ -24,10 +24,9 @@ //! # use sr_primitives::generic::BlockId; //! # use std::{sync::Arc, time::Duration}; //! # use test_client::{self, runtime::{Extrinsic, Transfer}, AccountKeyring}; -//! # use transaction_pool::txpool::{self, Pool as TransactionPool}; +//! # use transaction_pool::BasicTransactionPool; //! # let client = Arc::new(test_client::new()); -//! # let chain_api = transaction_pool::FullChainApi::new(client.clone()); -//! # let txpool = Arc::new(TransactionPool::new(Default::default(), chain_api)); +//! # let txpool = Arc::new(BasicTransactionPool::default_full(Default::default(), client.clone())); //! // The first step is to create a `ProposerFactory`. //! let mut proposer_factory = ProposerFactory { //! client: client.clone(), diff --git a/core/offchain/src/api.rs b/core/offchain/src/api.rs index d17a892d975e1..9b1ce51945d68 100644 --- a/core/offchain/src/api.rs +++ b/core/offchain/src/api.rs @@ -31,7 +31,7 @@ use primitives::offchain::{ OpaqueNetworkState, OpaquePeerId, OpaqueMultiaddr, StorageKind, }; use sr_primitives::{generic::BlockId, traits::{self, Extrinsic}}; -use transaction_pool::txpool::{Pool, ChainApi}; +use transaction_pool::TransactionPool; mod http; mod timestamp; @@ -253,23 +253,23 @@ impl TryFrom for NetworkState { /// Offchain extensions implementation API /// /// This is the asynchronous processing part of the API. -pub(crate) struct AsyncApi { +pub(crate) struct AsyncApi { receiver: Option>, - transaction_pool: Arc>, - at: BlockId, + transaction_pool: Arc

, + at: BlockId, /// Everything HTTP-related is handled by a different struct. http: Option, } -impl AsyncApi { +impl AsyncApi

{ /// Creates new Offchain extensions API implementation an the asynchronous processing part. pub fn new( - transaction_pool: Arc>, + transaction_pool: Arc

, db: S, - at: BlockId, + at: BlockId, network_state: Arc, is_validator: bool, - ) -> (Api, AsyncApi) { + ) -> (Api, AsyncApi

) { let (sender, rx) = mpsc::unbounded(); let (http_api, http_worker) = http::http(); @@ -309,7 +309,7 @@ impl AsyncApi { } fn submit_extrinsic(&mut self, ext: Vec) -> impl Future { - let xt = match ::Extrinsic::decode(&mut &*ext) { + let xt = match ::Extrinsic::decode(&mut &*ext) { Ok(xt) => xt, Err(e) => { warn!("Unable to decode extrinsic: {:?}: {}", ext, e.what()); @@ -335,6 +335,7 @@ mod tests { use client_db::offchain::LocalStorage; use network::PeerId; use test_client::runtime::Block; + use transaction_pool::BasicTransactionPool; struct MockNetworkStateInfo(); @@ -348,13 +349,11 @@ mod tests { } } - fn offchain_api() -> (Api, AsyncApi) { + fn offchain_api() -> (Api, AsyncApi) { let _ = env_logger::try_init(); let db = LocalStorage::new_test(); let client = Arc::new(test_client::new()); - let pool = Arc::new( - Pool::new(Default::default(), transaction_pool::FullChainApi::new(client.clone())) - ); + let pool = Arc::new(BasicTransactionPool::default_full(Default::default(), client.clone())); let mock = Arc::new(MockNetworkStateInfo()); AsyncApi::new( diff --git a/core/offchain/src/lib.rs b/core/offchain/src/lib.rs index 79c6df04ea109..c3d627895ba18 100644 --- a/core/offchain/src/lib.rs +++ b/core/offchain/src/lib.rs @@ -45,7 +45,7 @@ use log::{debug, warn}; use network::NetworkStateInfo; use primitives::{offchain, ExecutionContext}; use sr_primitives::{generic::BlockId, traits::{self, ProvideRuntimeApi}}; -use transaction_pool::txpool::{Pool, ChainApi}; +use transaction_pool::TransactionPool; mod api; @@ -93,13 +93,13 @@ impl OffchainWorkers< { /// Start the offchain workers after given block. #[must_use] - pub fn on_block_imported( + pub fn on_block_imported

( &self, number: &::Number, - pool: &Arc>, + pool: &Arc

, network_state: Arc, is_validator: bool, - ) -> impl Future where A: ChainApi + 'static { + ) -> impl Future where P: TransactionPool + 'static { let runtime = self.client.runtime_api(); let at = BlockId::number(*number); let has_api = runtime.has_api::>(&at); @@ -153,6 +153,7 @@ fn spawn_worker(f: impl FnOnce() -> () + Send + 'static) { mod tests { use super::*; use network::{Multiaddr, PeerId}; + use transaction_pool::BasicTransactionPool; struct MockNetworkStateInfo(); @@ -171,7 +172,7 @@ mod tests { // given let _ = env_logger::try_init(); let client = Arc::new(test_client::new()); - let pool = Arc::new(Pool::new(Default::default(), transaction_pool::FullChainApi::new(client.clone()))); + let pool = Arc::new(BasicTransactionPool::default_full(Default::default(), client.clone())); let db = client_db::offchain::LocalStorage::new_test(); let network_state = Arc::new(MockNetworkStateInfo()); diff --git a/core/rpc/src/author/mod.rs b/core/rpc/src/author/mod.rs index 82122dcf3d21f..eec0f472274db 100644 --- a/core/rpc/src/author/mod.rs +++ b/core/rpc/src/author/mod.rs @@ -35,12 +35,11 @@ use codec::{Encode, Decode}; use primitives::{Bytes, Blake2Hasher, H256, traits::BareCryptoStorePtr}; use sr_primitives::{generic, traits::{self, ProvideRuntimeApi}}; use transaction_pool::{ + TransactionPool, + BlockHash, + ExHash, txpool::{ - ChainApi as PoolChainApi, - BlockHash, - ExHash, IntoPoolError, - Pool, watcher::Status, }, }; @@ -51,22 +50,22 @@ pub use api::author::*; use self::error::{Error, FutureResult, Result}; /// Authoring API -pub struct Author where P: PoolChainApi + Sync + Send + 'static { +pub struct Author where P: TransactionPool + Sync + Send + 'static { /// Substrate client - client: Arc::Block, RA>>, + client: Arc::Block, RA>>, /// Transactions pool - pool: Arc>, + pool: Arc

, /// Subscriptions manager subscriptions: Subscriptions, /// The key store. keystore: BareCryptoStorePtr, } -impl Author where P: PoolChainApi + Sync + Send + 'static { +impl Author where P: TransactionPool + Sync + Send + 'static { /// Create new instance of Authoring API. pub fn new( - client: Arc::Block, RA>>, - pool: Arc>, + client: Arc::Block, RA>>, + pool: Arc

, subscriptions: Subscriptions, keystore: BareCryptoStorePtr, ) -> Self { @@ -80,9 +79,9 @@ impl Author where P: PoolChainApi + Sync + Send + 'sta } impl AuthorApi, BlockHash

> for Author where - B: client::backend::Backend<

::Block, Blake2Hasher> + Send + Sync + 'static, - E: client::CallExecutor<

::Block, Blake2Hasher> + Send + Sync + 'static, - P: PoolChainApi + Sync + Send + 'static, + B: client::backend::Backend<

::Block, Blake2Hasher> + Send + Sync + 'static, + E: client::CallExecutor<

::Block, Blake2Hasher> + Send + Sync + 'static, + P: TransactionPool + Sync + Send + 'static, P::Block: traits::Block, P::Error: 'static, RA: Send + Sync + 'static, @@ -159,7 +158,7 @@ impl AuthorApi, BlockHash

> for Author whe ) { let submit = || -> Result<_> { let best_block_hash = self.client.info().chain.best_hash; - let dxt = <

::Block as traits::Block>::Extrinsic::decode(&mut &xt[..]) + let dxt = <

::Block as traits::Block>::Extrinsic::decode(&mut &xt[..]) .map_err(error::Error::from)?; Ok( self.pool diff --git a/core/rpc/src/author/tests.rs b/core/rpc/src/author/tests.rs index e8ba4c132a0ea..a66e8305ac7f9 100644 --- a/core/rpc/src/author/tests.rs +++ b/core/rpc/src/author/tests.rs @@ -28,10 +28,7 @@ use test_client::{ self, AccountKeyring, runtime::{Extrinsic, Transfer, SessionKeys}, DefaultTestClientBuilderExt, TestClientBuilderExt, }; -use transaction_pool::{ - txpool::Pool, - FullChainApi, -}; +use transaction_pool::BasicTransactionPool; use tokio::runtime; fn uxt(sender: AccountKeyring, nonce: u64) -> Extrinsic { @@ -51,7 +48,7 @@ fn submit_transaction_should_not_cause_error() { let keystore = KeyStore::new(); let p = Author { client: client.clone(), - pool: Arc::new(Pool::new(Default::default(), FullChainApi::new(client))), + pool: Arc::new(BasicTransactionPool::default_full(Default::default(), client)), subscriptions: Subscriptions::new(Arc::new(runtime.executor())), keystore: keystore.clone(), }; @@ -74,7 +71,7 @@ fn submit_rich_transaction_should_not_cause_error() { let keystore = KeyStore::new(); let p = Author { client: client.clone(), - pool: Arc::new(Pool::new(Default::default(), FullChainApi::new(client.clone()))), + pool: Arc::new(BasicTransactionPool::default_full(Default::default(), client)), subscriptions: Subscriptions::new(Arc::new(runtime.executor())), keystore: keystore.clone(), }; @@ -95,7 +92,7 @@ fn should_watch_extrinsic() { //given let mut runtime = runtime::Runtime::new().unwrap(); let client = Arc::new(test_client::new()); - let pool = Arc::new(Pool::new(Default::default(), FullChainApi::new(client.clone()))); + let pool = Arc::new(BasicTransactionPool::default_full(Default::default(), client.clone())); let keystore = KeyStore::new(); let p = Author { client, @@ -138,7 +135,7 @@ fn should_return_watch_validation_error() { //given let mut runtime = runtime::Runtime::new().unwrap(); let client = Arc::new(test_client::new()); - let pool = Arc::new(Pool::new(Default::default(), FullChainApi::new(client.clone()))); + let pool = Arc::new(BasicTransactionPool::default_full(Default::default(), client.clone())); let keystore = KeyStore::new(); let p = Author { client, @@ -160,7 +157,7 @@ fn should_return_watch_validation_error() { fn should_return_pending_extrinsics() { let runtime = runtime::Runtime::new().unwrap(); let client = Arc::new(test_client::new()); - let pool = Arc::new(Pool::new(Default::default(), FullChainApi::new(client.clone()))); + let pool = Arc::new(BasicTransactionPool::default_full(Default::default(), client.clone())); let keystore = KeyStore::new(); let p = Author { client, @@ -180,7 +177,7 @@ fn should_return_pending_extrinsics() { fn should_remove_extrinsics() { let runtime = runtime::Runtime::new().unwrap(); let client = Arc::new(test_client::new()); - let pool = Arc::new(Pool::new(Default::default(), FullChainApi::new(client.clone()))); + let pool = Arc::new(BasicTransactionPool::default_full(Default::default(), client.clone())); let keystore = KeyStore::new(); let p = Author { client, @@ -213,7 +210,7 @@ fn should_insert_key() { let keystore = KeyStore::new(); let p = Author { client: client.clone(), - pool: Arc::new(Pool::new(Default::default(), FullChainApi::new(client))), + pool: Arc::new(BasicTransactionPool::default_full(Default::default(), client)), subscriptions: Subscriptions::new(Arc::new(runtime.executor())), keystore: keystore.clone(), }; @@ -241,7 +238,7 @@ fn should_rotate_keys() { ); let p = Author { client: client.clone(), - pool: Arc::new(Pool::new(Default::default(), FullChainApi::new(client))), + pool: Arc::new(BasicTransactionPool::default_full(Default::default(), client)), subscriptions: Subscriptions::new(Arc::new(runtime.executor())), keystore: keystore.clone(), }; diff --git a/core/service/src/builder.rs b/core/service/src/builder.rs index e0ee018193d59..3364610e111f8 100644 --- a/core/service/src/builder.rs +++ b/core/service/src/builder.rs @@ -18,9 +18,6 @@ use crate::{NewService, NetworkStatus, NetworkState, error::{self, Error}, DEFAU use crate::{SpawnTaskHandle, start_rpc_servers, build_network_future, TransactionPoolAdapter}; use crate::TaskExecutor; use crate::config::Configuration; -use crate::pool_maintainer::{ - TransactionPoolMaintainer, DefaultFullTransactionPoolMaintainer, DefaultLightTransactionPoolMaintainer, -}; use client::{ BlockchainEvents, Client, runtime_api, backend::RemoteBackend, @@ -51,7 +48,7 @@ use substrate_executor::{NativeExecutor, NativeExecutionDispatch}; use std::{io::{Read, Write, Seek}, marker::PhantomData, sync::Arc, sync::atomic::AtomicBool}; use sysinfo::{get_current_pid, ProcessExt, System, SystemExt}; use tel::{telemetry, SUBSTRATE_INFO}; -use transaction_pool::txpool::{self, ChainApi, Pool as TransactionPool}; +use transaction_pool::TransactionPool; /// Aggregator for the components required to build a service. /// @@ -72,7 +69,7 @@ use transaction_pool::txpool::{self, ChainApi, Pool as TransactionPool}; /// generics is done when you call `build`. /// pub struct ServiceBuilder + TNetP, TExPool, TRpc, TRpcB, Backend> { config: Configuration, client: Arc, @@ -86,7 +83,6 @@ pub struct ServiceBuilder, network_protocol: TNetP, transaction_pool: Arc, - transaction_pool_maintainer: TExPoolM, rpc_extensions: TRpc, rpc_builder: TRpcB, dht_event_tx: Option>, @@ -139,7 +135,7 @@ type TLightCallExecutor = client::light::call_executor::GenesisC >, >; -impl ServiceBuilder<(), (), TCfg, TGen, TCSExt, (), (), (), (), (), (), (), (), (), (), (), ()> +impl ServiceBuilder<(), (), TCfg, TGen, TCSExt, (), (), (), (), (), (), (), (), (), (), ()> where TGen: RuntimeGenesis, TCSExt: Extension { /// Start the service builder with a configuration. pub fn new_full, TRtApi, TExecDisp: NativeExecutionDispatch>( @@ -158,7 +154,6 @@ where TGen: RuntimeGenesis, TCSExt: Extension { (), (), (), - DefaultFullTransactionPoolMaintainer, (), FullRpcBuilder, TFullBackend, @@ -211,7 +206,6 @@ where TGen: RuntimeGenesis, TCSExt: Extension { finality_proof_provider: None, network_protocol: (), transaction_pool: Arc::new(()), - transaction_pool_maintainer: DefaultFullTransactionPoolMaintainer, rpc_extensions: Default::default(), rpc_builder, dht_event_tx: None, @@ -236,7 +230,6 @@ where TGen: RuntimeGenesis, TCSExt: Extension { (), (), (), - DefaultLightTransactionPoolMaintainer>, (), LightRpcBuilder, TLightBackend, @@ -287,7 +280,6 @@ where TGen: RuntimeGenesis, TCSExt: Extension { finality_proof_provider: None, network_protocol: (), transaction_pool: Arc::new(()), - transaction_pool_maintainer: DefaultLightTransactionPoolMaintainer::with_defaults(fetcher), rpc_extensions: Default::default(), rpc_builder, dht_event_tx: None, @@ -297,9 +289,9 @@ where TGen: RuntimeGenesis, TCSExt: Extension { } impl + TImpQu, TFprb, TFpp, TNetP, TExPool, TRpc, TRpcB, Backend> ServiceBuilder { + TNetP, TExPool, TRpc, TRpcB, Backend> { /// Returns a reference to the client that was stored in this builder. pub fn client(&self) -> &Arc { @@ -323,7 +315,7 @@ impl, &Arc ) -> Result, Error> ) -> Result, Error> { + TNetP, TExPool, TRpc, TRpcB, Backend>, Error> { let select_chain = select_chain_builder(&self.config, &self.backend)?; Ok(ServiceBuilder { @@ -339,7 +331,6 @@ impl, &Arc) -> Result ) -> Result, Error> { + TNetP, TExPool, TRpc, TRpcB, Backend>, Error> { self.with_opt_select_chain(|cfg, b| builder(cfg, b).map(Option::Some)) } @@ -362,7 +353,7 @@ impl, Arc, Option, Arc) -> Result ) -> Result, Error> + TNetP, TExPool, TRpc, TRpcB, Backend>, Error> where TSc: Clone { let import_queue = builder( &self.config, @@ -384,7 +375,6 @@ impl) -> Result ) -> Result, Error> { + UNetP, TExPool, TRpc, TRpcB, Backend>, Error> { let network_protocol = network_protocol_builder(&self.config)?; Ok(ServiceBuilder { @@ -413,7 +403,6 @@ impl>, TNetP, TExPool, - TExPoolM, TRpc, TRpcB, Backend, @@ -459,7 +447,6 @@ impl>, TNetP, TExPool, - TExPoolM, TRpc, TRpcB, Backend, @@ -505,7 +491,7 @@ impl, ) -> Result<(UImpQu, Option), Error> ) -> Result, Error> + TNetP, TExPool, TRpc, TRpcB, Backend>, Error> where TSc: Clone, TFchr: Clone { let (import_queue, fprb) = builder( &self.config, @@ -529,7 +515,6 @@ impl, ) -> Result<(UImpQu, UFprb), Error> ) -> Result, Error> + TNetP, TExPool, TRpc, TRpcB, Backend>, Error> where TSc: Clone, TFchr: Clone { self.with_import_queue_and_opt_fprb(|cfg, cl, b, f, sc, tx| builder(cfg, cl, b, f, sc, tx) @@ -566,7 +551,7 @@ impl, ) -> Result ) -> Result, Error> + TNetP, UExPool, TRpc, TRpcB, Backend>, Error> where TFchr: Clone { let transaction_pool = transaction_pool_builder( self.config.transaction_pool.clone(), @@ -587,51 +572,6 @@ impl( - self, - transaction_pool_maintainer_builder: impl FnOnce( - Arc, - Arc, - Option, - Option>>, - ) -> Result, - ) -> Result, Error> - where TFchr: Clone { - let transaction_pool_maintainer = transaction_pool_maintainer_builder( - self.client.clone(), - self.transaction_pool.clone(), - self.fetcher.clone(), - self.remote_blockchain.clone(), - )?; - - Ok(ServiceBuilder { - config: self.config, - client: self.client, - backend: self.backend, - keystore: self.keystore, - fetcher: self.fetcher, - remote_blockchain: self.remote_blockchain, - select_chain: self.select_chain, - import_queue: self.import_queue, - finality_proof_request_builder: self.finality_proof_request_builder, - finality_proof_provider: self.finality_proof_provider, - network_protocol: self.network_protocol, - transaction_pool: self.transaction_pool, - transaction_pool_maintainer, rpc_extensions: self.rpc_extensions, rpc_builder: self.rpc_builder, dht_event_tx: self.dht_event_tx, @@ -649,7 +589,7 @@ impl>>, ) -> Result, ) -> Result, Error> + TNetP, TExPool, URpc, TRpcB, Backend>, Error> where TFchr: Clone { let rpc_extensions = rpc_ext_builder( self.client.clone(), @@ -671,7 +611,6 @@ impl, ) -> Result, Error> { + TNetP, TExPool, TRpc, TRpcB, Backend>, Error> { Ok(ServiceBuilder { config: self.config, client: self.client, @@ -699,7 +638,6 @@ impl ServiceBuilderImport for ServiceBuilder< TBl, TRtApi, TCfg, TGen, TCSExt, Client, - TFchr, TSc, TImpQu, TFprb, TFpp, TNetP, TExPool, TExPoolM, TRpc, TRpcB, Backend + TFchr, TSc, TImpQu, TFprb, TFpp, TNetP, TExPool, TRpc, TRpcB, Backend > where TBl: BlockT::Out>, TBackend: 'static + client::backend::Backend + Send, @@ -854,9 +792,9 @@ impl< } impl + TImpQu, TFprb, TFpp, TNetP, TExPool, TRpc, TRpcB> ServiceBuilderExport for ServiceBuilder, - TFchr, TSc, TImpQu, TFprb, TFpp, TNetP, TExPool, TExPoolM, TRpc, TRpcB, TBackend> + TFchr, TSc, TImpQu, TFprb, TFpp, TNetP, TExPool, TRpc, TRpcB, TBackend> where TBl: BlockT::Out>, TBackend: 'static + client::backend::Backend + Send, @@ -878,9 +816,9 @@ where } impl + TImpQu, TFprb, TFpp, TNetP, TExPool, TRpc, TRpcB> ServiceBuilderRevert for ServiceBuilder, - TFchr, TSc, TImpQu, TFprb, TFpp, TNetP, TExPool, TExPoolM, TRpc, TRpcB, TBackend> + TFchr, TSc, TImpQu, TFprb, TFpp, TNetP, TExPool, TRpc, TRpcB, TBackend> where TBl: BlockT::Out>, TBackend: 'static + client::backend::Backend + Send, @@ -897,7 +835,7 @@ where } } -impl +impl ServiceBuilder< TBl, TRtApi, @@ -911,8 +849,7 @@ ServiceBuilder< BoxFinalityProofRequestBuilder, Arc>, TNetP, - TransactionPool, - TExPoolM, + TExPool, TRpc, TRpcB, TBackend, @@ -933,8 +870,7 @@ ServiceBuilder< TSc: Clone, TImpQu: 'static + ImportQueue, TNetP: NetworkSpecialization, - TExPoolApi: 'static + ChainApi::Hash>, - TExPoolM: TransactionPoolMaintainer, + TExPool: 'static + TransactionPool::Hash>, TRpc: rpc::RpcExtension + Clone, TRpcB: RpcBuilder, { @@ -945,7 +881,7 @@ ServiceBuilder< TSc, NetworkStatus, NetworkService::Hash>, - TransactionPool, + TExPool, offchain::OffchainWorkers< Client, TBackend::OffchainStorage, @@ -966,7 +902,6 @@ ServiceBuilder< finality_proof_provider, network_protocol, transaction_pool, - transaction_pool_maintainer, rpc_extensions, dht_event_tx, rpc_builder, @@ -993,7 +928,6 @@ ServiceBuilder< finality_proof_provider, network_protocol, transaction_pool, - transaction_pool_maintainer, rpc_extensions, dht_event_tx, )) @@ -1005,13 +939,13 @@ ServiceBuilder< } -pub(crate) fn start_rpc( +pub(crate) fn start_rpc( rpc_builder: &RpcB, client: Arc>, system_send_back: futures03::channel::mpsc::UnboundedSender>, rpc_system_info: SystemInfo, task_executor: TaskExecutor, - transaction_pool: Arc>, + transaction_pool: Arc, rpc_extensions: impl rpc::RpcExtension, keystore: KeyStorePtr, ) -> rpc_servers::RpcHandler @@ -1023,7 +957,7 @@ where runtime_api::Metadata + session::SessionKeys, Api: Send + Sync + 'static, Executor: client::CallExecutor + Send + Sync + Clone + 'static, - PoolApi: txpool::ChainApi + 'static, + ExPool: TransactionPool + 'static, RpcB: RpcBuilder, { use rpc::{chain, state, author, system}; @@ -1047,14 +981,14 @@ where )) } -pub(crate) fn offchain_workers( +pub(crate) fn offchain_workers( number: &NumberFor, offchain: &offchain::OffchainWorkers< Client, >::OffchainStorage, Block >, - pool: &Arc>, + pool: &Arc, network_state: &Arc, is_validator: bool, ) -> error::Result + Send>> @@ -1066,7 +1000,7 @@ where Client: ProvideRuntimeApi + Send + Sync, as ProvideRuntimeApi>::Api: offchain::OffchainWorkerApi, Executor: client::CallExecutor + 'static, - PoolApi: txpool::ChainApi + 'static, + ExPool: TransactionPool + 'static, { let future = offchain.on_block_imported(number, pool, network_state.clone(), is_validator) .map(|()| Ok(())); diff --git a/core/service/src/lib.rs b/core/service/src/lib.rs index e0ba8de18a107..787192e0fb799 100644 --- a/core/service/src/lib.rs +++ b/core/service/src/lib.rs @@ -54,14 +54,11 @@ pub use self::error::Error; pub use self::builder::{ ServiceBuilder, ServiceBuilderExport, ServiceBuilderImport, ServiceBuilderRevert, }; -pub use self::pool_maintainer:: { - TransactionPoolMaintainer, - DefaultLightTransactionPoolMaintainer, DefaultFullTransactionPoolMaintainer, -}; pub use config::{Configuration, Roles, PruningMode}; pub use chain_spec::{ChainSpec, Properties, RuntimeGenesis, Extension as ChainSpecExtension}; +pub use transaction_pool::TransactionPool; pub use transaction_pool::txpool::{ - self, Pool as TransactionPool, Options as TransactionPoolOptions, ChainApi, IntoPoolError + self, Options as TransactionPoolOptions, IntoPoolError }; pub use client::FinalityNotifications; pub use rpc::Metadata as RpcMetadata; @@ -161,7 +158,6 @@ macro_rules! new_impl { finality_proof_provider, network_protocol, transaction_pool, - transaction_pool_maintainer, rpc_extensions, dht_event_tx, ) = $build_components(&$config)?; @@ -234,7 +230,6 @@ macro_rules! new_impl { { // block notifications let txpool = Arc::downgrade(&transaction_pool); - let wclient = Arc::downgrade(&client); let offchain = offchain_workers.as_ref().map(Arc::downgrade); let to_spawn_tx_ = to_spawn_tx.clone(); let network_state_info: Arc = network.clone(); @@ -246,14 +241,13 @@ macro_rules! new_impl { let number = *notification.header.number(); let txpool = txpool.upgrade(); - if let (Some(txpool), Some(client)) = (txpool.as_ref(), wclient.upgrade()) { - let future = transaction_pool_maintainer.maintain( + if let Some(txpool) = txpool.as_ref() { + use futures03::TryFutureExt; + let future = txpool.maintain( &BlockId::hash(notification.hash), - &client, - &txpool, - ¬ification.retracted, - ).map_err(|e| warn!("Pool error processing new block: {:?}", e))?; - let _ = to_spawn_tx_.unbounded_send(future); + ¬ification.retracted[..], + ).map(|_| Ok(())).compat(); + let _ = to_spawn_tx_.unbounded_send(Box::new(future)); } let offchain = offchain.as_ref().and_then(|o| o.upgrade()); @@ -454,7 +448,6 @@ macro_rules! new_impl { } mod builder; -mod pool_maintainer; /// Abstraction over a Substrate service. pub trait AbstractService: 'static + Future + @@ -469,8 +462,8 @@ pub trait AbstractService: 'static + Future + type RuntimeApi: Send + Sync; /// Chain selection algorithm. type SelectChain: consensus_common::SelectChain; - /// API of the transaction pool. - type TransactionPoolApi: ChainApi; + /// Transaction pool. + type TransactionPool: TransactionPool; /// Network specialization. type NetworkSpecialization: NetworkSpecialization; @@ -518,22 +511,22 @@ pub trait AbstractService: 'static + Future + fn network_status(&self) -> mpsc::UnboundedReceiver<(NetworkStatus, NetworkState)>; /// Get shared transaction pool instance. - fn transaction_pool(&self) -> Arc>; + fn transaction_pool(&self) -> Arc; /// Get a handle to a future that will resolve on exit. fn on_exit(&self) -> ::exit_future::Exit; } -impl AbstractService for +impl AbstractService for NewService, TSc, NetworkStatus, - NetworkService, TransactionPool, TOc> + NetworkService, TExPool, TOc> where TBl: BlockT, TBackend: 'static + client::backend::Backend, TExec: 'static + client::CallExecutor + Send + Sync + Clone, TRtApi: 'static + Send + Sync, TSc: consensus_common::SelectChain + 'static + Clone + Send, - TExPoolApi: 'static + ChainApi, + TExPool: 'static + TransactionPool, TOc: 'static + Send + Sync, TNetSpec: NetworkSpecialization, { @@ -542,7 +535,7 @@ where type CallExecutor = TExec; type RuntimeApi = TRtApi; type SelectChain = TSc; - type TransactionPoolApi = TExPoolApi; + type TransactionPool = TExPool; type NetworkSpecialization = TNetSpec; fn telemetry_on_connect_stream(&self) -> mpsc::UnboundedReceiver<()> { @@ -604,7 +597,7 @@ where stream } - fn transaction_pool(&self) -> Arc> { + fn transaction_pool(&self) -> Arc { self.transaction_pool.clone() } @@ -910,10 +903,10 @@ pub struct TransactionPoolAdapter { /// Get transactions for propagation. /// /// Function extracted to simplify the test and prevent creating `ServiceFactory`. -fn transactions_to_propagate(pool: &TransactionPool) +fn transactions_to_propagate(pool: &Pool) -> Vec<(H, B::Extrinsic)> where - PoolApi: ChainApi, + Pool: TransactionPool, B: BlockT, H: std::hash::Hash + Eq + sr_primitives::traits::Member + sr_primitives::traits::MaybeSerialize, E: txpool::error::IntoPoolError + From, @@ -928,17 +921,17 @@ where .collect() } -impl network::TransactionPool for - TransactionPoolAdapter> +impl network::TransactionPool for + TransactionPoolAdapter where C: network::ClientHandle + Send + Sync, - PoolApi: 'static + ChainApi, + Pool: 'static + TransactionPool, B: BlockT, H: std::hash::Hash + Eq + sr_primitives::traits::Member + sr_primitives::traits::MaybeSerialize, - E: txpool::error::IntoPoolError + From, + E: 'static + txpool::error::IntoPoolError + From, { fn transactions(&self) -> Vec<(H, ::Extrinsic)> { - transactions_to_propagate(&self.pool) + transactions_to_propagate(&*self.pool) } fn hash_of(&self, transaction: &B::Extrinsic) -> H { @@ -990,16 +983,14 @@ mod tests { use consensus_common::SelectChain; use sr_primitives::traits::BlindCheckable; use substrate_test_runtime_client::{prelude::*, runtime::{Extrinsic, Transfer}}; + use transaction_pool::BasicTransactionPool; #[test] fn should_not_propagate_transactions_that_are_marked_as_such() { // given let (client, longest_chain) = TestClientBuilder::new().build_with_longest_chain(); let client = Arc::new(client); - let pool = Arc::new(TransactionPool::new( - Default::default(), - transaction_pool::FullChainApi::new(client.clone()) - )); + let pool = Arc::new(BasicTransactionPool::default_full(Default::default(), client.clone())); let best = longest_chain.best_chain().unwrap(); let transaction = Transfer { amount: 5, @@ -1012,7 +1003,7 @@ mod tests { assert_eq!(pool.status().ready, 2); // when - let transactions = transactions_to_propagate(&pool); + let transactions = transactions_to_propagate(&*pool); // then assert_eq!(transactions.len(), 1); diff --git a/core/service/test/Cargo.toml b/core/service/test/Cargo.toml index 872d63415f4e8..96abf389bb4fc 100644 --- a/core/service/test/Cargo.toml +++ b/core/service/test/Cargo.toml @@ -18,3 +18,4 @@ consensus = { package = "substrate-consensus-common", path = "../../../core/cons client = { package = "substrate-client", path = "../../../core/client" } sr-primitives = { path = "../../../core/sr-primitives" } primitives = { package = "substrate-primitives", path = "../../../core/primitives" } +transaction_pool = { package = "substrate-transaction-pool", path = "../../../core/transaction-pool" } diff --git a/core/service/test/src/lib.rs b/core/service/test/src/lib.rs index 806996576ff90..f3ef45da045d5 100644 --- a/core/service/test/src/lib.rs +++ b/core/service/test/src/lib.rs @@ -35,6 +35,7 @@ use service::{ use network::{multiaddr, Multiaddr}; use network::config::{NetworkConfiguration, TransportConfig, NodeKeyConfig, Secret, NonReservedPeerMode}; use sr_primitives::{generic::BlockId, traits::Block as BlockT}; +use transaction_pool::TransactionPool; /// Maximum duration of single wait call. const MAX_WAIT_TIME: Duration = Duration::from_secs(60 * 3); diff --git a/core/sr-api-macros/tests/ui/declaring_old_block.stderr b/core/sr-api-macros/tests/ui/declaring_old_block.stderr index 999a50cc96977..181aa2a3ca783 100644 --- a/core/sr-api-macros/tests/ui/declaring_old_block.stderr +++ b/core/sr-api-macros/tests/ui/declaring_old_block.stderr @@ -16,4 +16,4 @@ warning: unused import: `sr_primitives::traits::Block as BlockT` 1 | use sr_primitives::traits::Block as BlockT; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: `#[warn(unused_imports)]` on by default + = note: #[warn(unused_imports)] on by default diff --git a/core/sr-api-macros/tests/ui/declaring_own_block_with_different_name.stderr b/core/sr-api-macros/tests/ui/declaring_own_block_with_different_name.stderr index ec033f2e09d23..a591d0448c50d 100644 --- a/core/sr-api-macros/tests/ui/declaring_own_block_with_different_name.stderr +++ b/core/sr-api-macros/tests/ui/declaring_own_block_with_different_name.stderr @@ -10,4 +10,4 @@ warning: unused import: `sr_primitives::traits::Block as BlockT` 1 | use sr_primitives::traits::Block as BlockT; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: `#[warn(unused_imports)]` on by default + = note: #[warn(unused_imports)] on by default diff --git a/core/transaction-pool/Cargo.toml b/core/transaction-pool/Cargo.toml index 33ec9e9ece176..a11d19505c0a9 100644 --- a/core/transaction-pool/Cargo.toml +++ b/core/transaction-pool/Cargo.toml @@ -18,3 +18,4 @@ txpool = { package = "substrate-transaction-graph", path = "./graph" } [dev-dependencies] keyring = { package = "substrate-keyring", path = "../../core/keyring" } test-client = { package = "substrate-test-runtime-client", path = "../../core/test-runtime/client" } +consensus_common = { package = "substrate-consensus-common", path = "../../core/consensus/common" } diff --git a/core/transaction-pool/graph/src/base_pool.rs b/core/transaction-pool/graph/src/base_pool.rs index 3580812815295..c12b7d833a888 100644 --- a/core/transaction-pool/graph/src/base_pool.rs +++ b/core/transaction-pool/graph/src/base_pool.rs @@ -37,7 +37,7 @@ use sr_primitives::transaction_validity::{ use crate::error; use crate::future::{FutureTransactions, WaitingTransaction}; -use crate::ready::ReadyTransactions; +use crate::ready::{ReadyTransactions, BestIterator}; /// Successful import result. #[derive(Debug, PartialEq, Eq)] @@ -169,23 +169,23 @@ pub struct BasePool { recently_pruned_index: usize, } -impl Default for BasePool { +impl Default for BasePool { fn default() -> Self { + Self::new(false) + } +} + +impl BasePool { + /// Create new pool given reject_future_transactions flag. + pub fn new(reject_future_transactions: bool) -> Self { BasePool { - reject_future_transactions: false, + reject_future_transactions, future: Default::default(), ready: Default::default(), recently_pruned: Default::default(), recently_pruned_index: 0, } } -} - -impl BasePool { - /// Start rejecting future transactions. - pub fn reject_future_transactions(&mut self) { - self.reject_future_transactions = true; - } /// Imports transaction to the pool. /// @@ -290,7 +290,7 @@ impl BasePool impl Iterator>> { + pub fn ready(&self) -> BestIterator { self.ready.get() } @@ -989,7 +989,7 @@ requires: [03,02], provides: [04], data: [4]}".to_owned() let mut pool = pool(); // when - pool.reject_future_transactions(); + pool.reject_future_transactions = true; // then let err = pool.import(Transaction { diff --git a/core/transaction-pool/graph/src/lib.rs b/core/transaction-pool/graph/src/lib.rs index 715e60874be95..28308d70bf2bd 100644 --- a/core/transaction-pool/graph/src/lib.rs +++ b/core/transaction-pool/graph/src/lib.rs @@ -37,6 +37,7 @@ pub mod watcher; pub use self::error::IntoPoolError; pub use self::base_pool::{Transaction, Status}; +pub use self::ready::BestIterator; pub use self::pool::{ Pool, Options, ChainApi, EventStream, ExtrinsicFor, diff --git a/core/transaction-pool/graph/src/pool.rs b/core/transaction-pool/graph/src/pool.rs index 6b66f657daec4..11ac48986fbff 100644 --- a/core/transaction-pool/graph/src/pool.rs +++ b/core/transaction-pool/graph/src/pool.rs @@ -22,6 +22,7 @@ use std::{ use crate::base_pool as base; use crate::error; +use crate::ready::BestIterator; use crate::watcher::Watcher; use serde::Serialize; @@ -92,6 +93,8 @@ pub struct Options { pub ready: base::Limit, /// Future queue limits. pub future: base::Limit, + /// Reject future transactions. + pub reject_future_transactions: bool, } impl Default for Options { @@ -105,6 +108,7 @@ impl Default for Options { count: 128, total_bytes: 1 * 1024 * 1024, }, + reject_future_transactions: false, } } } @@ -122,11 +126,6 @@ impl Pool { } } - /// Start rejecting future transactions. - pub fn reject_future_transactions(&self) { - self.validated_pool.reject_future_transactions(); - } - /// Imports a bunch of unverified extrinsics to the pool pub fn submit_at(&self, at: &BlockId, xts: T, force: bool) -> impl Future, B::Error>>, B::Error>> @@ -325,7 +324,7 @@ impl Pool { } /// Get an iterator for ready transactions ordered by priority - pub fn ready(&self) -> impl Iterator> { + pub fn ready(&self) -> BestIterator, ExtrinsicFor> { self.validated_pool.ready() } @@ -674,6 +673,7 @@ mod tests { let pool = Pool::new(Options { ready: limit.clone(), future: limit.clone(), + ..Default::default() }, TestApi::default()); let hash1 = block_on(pool.submit_one(&BlockId::Number(0), uxt(Transfer { @@ -708,6 +708,7 @@ mod tests { let pool = Pool::new(Options { ready: limit.clone(), future: limit.clone(), + ..Default::default() }, TestApi::default()); // when @@ -883,6 +884,7 @@ mod tests { let pool = Pool::new(Options { ready: limit.clone(), future: limit.clone(), + ..Default::default() }, TestApi::default()); let xt = uxt(Transfer { diff --git a/core/transaction-pool/graph/src/ready.rs b/core/transaction-pool/graph/src/ready.rs index 85bb4dd783c42..af8e9a9d117ad 100644 --- a/core/transaction-pool/graph/src/ready.rs +++ b/core/transaction-pool/graph/src/ready.rs @@ -144,7 +144,7 @@ impl ReadyTransactions { /// - transactions that are valid for a shorter time go first /// 4. Lastly we sort by the time in the queue /// - transactions that are longer in the queue go first - pub fn get(&self) -> impl Iterator>> { + pub fn get(&self) -> BestIterator { BestIterator { all: self.ready.clone(), best: self.best.clone(), @@ -420,6 +420,7 @@ impl ReadyTransactions { } } +/// Iterator of ready transactions ordered by priority. pub struct BestIterator { all: Arc>>>, awaiting: HashMap)>, diff --git a/core/transaction-pool/graph/src/validated_pool.rs b/core/transaction-pool/graph/src/validated_pool.rs index d37671af2dadc..90163afe22f23 100644 --- a/core/transaction-pool/graph/src/validated_pool.rs +++ b/core/transaction-pool/graph/src/validated_pool.rs @@ -23,6 +23,7 @@ use std::{ use crate::base_pool as base; use crate::error; use crate::listener::Listener; +use crate::ready::BestIterator; use crate::rotator::PoolRotator; use crate::watcher::Watcher; use serde::Serialize; @@ -75,21 +76,17 @@ pub(crate) struct ValidatedPool { impl ValidatedPool { /// Create a new transaction pool. pub fn new(options: Options, api: B) -> Self { + let base_pool = base::BasePool::new(options.reject_future_transactions); ValidatedPool { api, options, listener: Default::default(), - pool: Default::default(), + pool: RwLock::new(base_pool), import_notification_sinks: Default::default(), rotator: Default::default(), } } - /// Start rejecting future transactions. - pub fn reject_future_transactions(&self) { - self.pool.write().reject_future_transactions(); - } - /// Bans given set of hashes. pub fn ban(&self, now: &std::time::Instant, hashes: impl IntoIterator>) { self.rotator.ban(now, hashes) @@ -433,7 +430,7 @@ impl ValidatedPool { } /// Get an iterator for ready transactions ordered by priority - pub fn ready(&self) -> impl Iterator> { + pub fn ready(&self) -> BestIterator, ExtrinsicFor> { self.pool.read().ready() } diff --git a/core/transaction-pool/src/lib.rs b/core/transaction-pool/src/lib.rs index d0e19eced815d..b5a601a9c3539 100644 --- a/core/transaction-pool/src/lib.rs +++ b/core/transaction-pool/src/lib.rs @@ -20,10 +20,246 @@ #![warn(unused_extern_crates)] mod api; +mod maintainer; #[cfg(test)] mod tests; pub mod error; -pub use api::{FullChainApi, LightChainApi}; pub use txpool; +pub use crate::api::{FullChainApi, LightChainApi}; +pub use crate::maintainer::{ + TransactionPoolMaintainer, + DefaultFullTransactionPoolMaintainer, DefaultLightTransactionPoolMaintainer, +}; + +use std::{collections::HashMap, hash::Hash, sync::Arc}; +use futures::Future; + +use client::{ + Client, + light::fetcher::Fetcher, + runtime_api::TaggedTransactionQueue, +}; +use primitives::{Blake2Hasher, H256}; +use sr_primitives::{ + serde::Serialize, + generic::BlockId, + traits::{Block as BlockT, Member, ProvideRuntimeApi}, +}; + +use txpool::{BestIterator, EventStream, Options, watcher::Watcher}; + +/// Extrinsic hash type for a pool. +pub type ExHash

=

::Hash; +/// Block hash type for a pool. +pub type BlockHash

= <

::Block as BlockT>::Hash; +/// Extrinsic type for a pool. +pub type ExtrinsicFor

= <

::Block as BlockT>::Extrinsic; + +/// Transaction pool interface. +pub trait TransactionPool: Send + Sync { + /// Block type. + type Block: BlockT; + /// Transaction Hash type. + type Hash: Hash + Eq + Member + Serialize; + /// Error type. + type Error: From + txpool::error::IntoPoolError; + + /// Returns a future that imports a bunch of unverified extrinsics to the pool. + fn submit_at( + &self, + at: &BlockId, + xts: impl IntoIterator> + 'static, + force: bool, + ) -> Box>, Self::Error>> + Send + Unpin>; + + /// Returns a future that imports one unverified extrinsic to the pool. + fn submit_one( + &self, + at: &BlockId, + xt: ExtrinsicFor, + ) -> Box> + Send + Unpin>; + + /// Returns a future that import a single extrinsic and starts to watch their progress in the pool. + fn submit_and_watch( + &self, + at: &BlockId, + xt: ExtrinsicFor, + ) -> Box>, Self::Error>> + Send + Unpin>; + + /// Remove extrinsics identified by given hashes (and dependent extrinsics) from the pool. + fn remove_invalid( + &self, + hashes: &[Self::Hash], + ) -> Vec>>>; + + /// Returns pool status. + fn status(&self) -> txpool::base_pool::Status; + + /// Get an iterator for ready transactions ordered by priority + fn ready(&self) -> BestIterator>; + + /// Return an event stream of transactions imported to the pool. + fn import_notification_stream(&self) -> EventStream; + + /// Returns transaction hash + fn hash_of(&self, xt: &ExtrinsicFor) -> Self::Hash; + + /// Notify the pool about transactions broadcast. + fn on_broadcasted(&self, propagations: HashMap>); + + /// Returns a future that performs maintenance procedures on the pool. + fn maintain( + &self, + id: &BlockId, + retracted: &[BlockHash], + ) -> Box + Send + Unpin>; +} + +/// Basic implementation of transaction pool that can be customized by providing +/// different PoolApi and Maintainer. +pub struct BasicTransactionPool + where + Block: BlockT, + PoolApi: txpool::ChainApi, + Maintainer: TransactionPoolMaintainer, +{ + pool: Arc>, + maintainer: Maintainer, +} + +impl BasicTransactionPool + where + Block: BlockT, + PoolApi: txpool::ChainApi, + Maintainer: TransactionPoolMaintainer, +{ + /// Create new basic transaction pool with given api and maintainer. + pub fn new(options: Options, pool_api: PoolApi, maintainer: Maintainer) -> Self { + BasicTransactionPool { + pool: Arc::new(txpool::Pool::new(options, pool_api)), + maintainer, + } + } +} + +impl BasicTransactionPool< + api::FullChainApi, Block>, + DefaultFullTransactionPoolMaintainer, + Block, +> where + Block: BlockT, + Backend: 'static + client::backend::Backend, + Client: ProvideRuntimeApi, + as ProvideRuntimeApi>::Api: TaggedTransactionQueue, + Executor: 'static + Send + Sync + client::CallExecutor, + Api: 'static + Send + Sync, +{ + /// Create new basic full transaction pool with default API and maintainer. + pub fn default_full(options: Options, client: Arc>) -> Self { + Self::new( + options, + FullChainApi::new(client.clone()), + DefaultFullTransactionPoolMaintainer::new(client), + ) + } +} + +impl BasicTransactionPool< + api::LightChainApi, F, Block>, + DefaultLightTransactionPoolMaintainer, + Block, +> where + Block: BlockT, + Backend: 'static + client::backend::Backend, + Client: ProvideRuntimeApi, + as ProvideRuntimeApi>::Api: TaggedTransactionQueue, + Executor: 'static + Send + Sync + client::CallExecutor, + Api: 'static + Send + Sync, + F: 'static + Fetcher, +{ + /// Create new basic light transaction pool with default API and maintainer. + pub fn default_light( + options: Options, + client: Arc>, + fetcher: Arc, + ) -> Self { + Self::new( + options, + LightChainApi::new(client.clone(), fetcher.clone()), + DefaultLightTransactionPoolMaintainer::with_defaults(client, fetcher), + ) + } +} + +impl TransactionPool for BasicTransactionPool + where + Block: BlockT, + PoolApi: 'static + txpool::ChainApi, + Maintainer: TransactionPoolMaintainer + Sync, +{ + type Block = Block; + type Hash = Block::Hash; + type Error = error::Error; + + fn submit_at( + &self, + at: &BlockId, + xts: impl IntoIterator> + 'static, + force: bool, + ) -> Box>, Self::Error>> + Send + Unpin> { + Box::new(self.pool.submit_at(at, xts, force)) + } + + fn submit_one( + &self, + at: &BlockId, + xt: ExtrinsicFor, + ) -> Box> + Send + Unpin> { + Box::new(self.pool.submit_one(at, xt)) + } + + fn submit_and_watch( + &self, + at: &BlockId, + xt: ExtrinsicFor, + ) -> Box>, Self::Error>> + Send + Unpin> { + Box::new(self.pool.submit_and_watch(at, xt)) + } + + fn remove_invalid( + &self, + hashes: &[Self::Hash], + ) -> Vec>>> { + self.pool.remove_invalid(hashes) + } + + fn status(&self) -> txpool::base_pool::Status { + self.pool.status() + } + + fn ready(&self) -> BestIterator> { + self.pool.ready() + } + + fn import_notification_stream(&self) -> EventStream { + self.pool.import_notification_stream() + } + + fn hash_of(&self, xt: &ExtrinsicFor) -> Self::Hash { + self.pool.hash_of(xt) + } + + fn on_broadcasted(&self, propagations: HashMap>) { + self.pool.on_broadcasted(propagations) + } + + fn maintain( + &self, + id: &BlockId, + retracted: &[Block::Hash], + ) -> Box + Send + Unpin> { + self.maintainer.maintain(id, retracted, &self.pool) + } +} diff --git a/core/service/src/pool_maintainer.rs b/core/transaction-pool/src/maintainer.rs similarity index 64% rename from core/service/src/pool_maintainer.rs rename to core/transaction-pool/src/maintainer.rs index fad060ccb2551..f0ad0f6dc57f2 100644 --- a/core/service/src/pool_maintainer.rs +++ b/core/transaction-pool/src/maintainer.rs @@ -14,26 +14,31 @@ // You should have received a copy of the GNU General Public License // along with Substrate. If not, see . -use crate::error; -use client::{ - Client, runtime_api, - light::fetcher::{Fetcher, RemoteBodyRequest}, +use std::{ + marker::{PhantomData, Unpin}, + sync::Arc, + time::Instant, }; -use futures::prelude::*; -use futures03::{ - future::{ready, Either}, - FutureExt, TryFutureExt, +use futures::{ + Future, FutureExt, + future::{Either, join, ready}, }; use log::warn; use parking_lot::Mutex; + +use client::{ + Client, + light::fetcher::{Fetcher, RemoteBodyRequest}, + runtime_api::TaggedTransactionQueue, +}; use primitives::Blake2Hasher; -use sr_primitives::generic::BlockId; -use sr_primitives::traits::{ - Block as BlockT, Extrinsic, ProvideRuntimeApi, NumberFor, - Header, SimpleArithmetic, +use sr_primitives::{ + generic::BlockId, + traits::{Block as BlockT, Extrinsic, Header, NumberFor, ProvideRuntimeApi, SimpleArithmetic}, }; -use std::{marker::PhantomData, sync::Arc, time::Instant}; -use transaction_pool::txpool::{self, Pool as TransactionPool}; + +use txpool::{self, BlockHash}; +use crate::api::{FullChainApi, LightChainApi}; /// Transaction pool maintainer. /// @@ -41,86 +46,96 @@ use transaction_pool::txpool::{self, Pool as TransactionPool}; /// 1) make sure that ready in-pool transactions are valid; /// 2) move 'future' transactions to the 'ready' queue; /// 3) prune transactions that have been included in some block. -pub trait TransactionPoolMaintainer: Send + 'static where - Block: BlockT::Out>, -{ +/// +/// This trait is extracted from `TransactionPool` so that the maintainance +/// algorithm could be customized easily, without touching the core' pool code. +pub trait TransactionPoolMaintainer: Send + 'static { /// Maintain transaction pool. - fn maintain( + fn maintain( &self, - id: &BlockId, - client: &Arc>, - transaction_pool: &Arc>, - retracted: &[Block::Hash], - ) -> error::Result + Send>> where - Backend: 'static + client::backend::Backend, - Client: ProvideRuntimeApi, - as ProvideRuntimeApi>::Api: runtime_api::TaggedTransactionQueue, - Executor: 'static + client::CallExecutor, - PoolApi: 'static + txpool::ChainApi, - Api: 'static; + id: &BlockId, + retracted: &[BlockHash], + pool: &Arc>, + ) -> Box + Send + Unpin>; } /// Default transaction pool maintainer for full clients. -pub struct DefaultFullTransactionPoolMaintainer; +pub struct DefaultFullTransactionPoolMaintainer { + client: Arc>, +} -impl TransactionPoolMaintainer for DefaultFullTransactionPoolMaintainer where +impl DefaultFullTransactionPoolMaintainer { + /// Create new default full pool maintainer. + pub fn new(client: Arc>) -> Self { + DefaultFullTransactionPoolMaintainer { client } + } +} + +impl TransactionPoolMaintainer< + FullChainApi, Block> +> for DefaultFullTransactionPoolMaintainer where Block: BlockT::Out>, + Backend: 'static + client::backend::Backend, + Client: ProvideRuntimeApi, + as ProvideRuntimeApi>::Api: TaggedTransactionQueue, + Executor: 'static + Send + Sync + client::CallExecutor, + Api: 'static + Send + Sync, { - fn maintain( + fn maintain( &self, id: &BlockId, - client: &Arc>, - transaction_pool: &Arc>, retracted: &[Block::Hash], - ) -> error::Result + Send>> where - Backend: 'static + client::backend::Backend, - Client: ProvideRuntimeApi, - as ProvideRuntimeApi>::Api: runtime_api::TaggedTransactionQueue, - Executor: 'static + client::CallExecutor, - PoolApi: 'static + txpool::ChainApi, - Api: 'static, - { + pool: &Arc, Block>>>, + ) -> Box + Send + Unpin> { // Put transactions from retracted blocks back into the pool. - let client_copy = client.clone(); + let client_copy = self.client.clone(); let retracted_transactions = retracted.to_vec().into_iter() .filter_map(move |hash| client_copy.block(&BlockId::hash(hash)).ok().unwrap_or(None)) .flat_map(|block| block.block.deconstruct().1.into_iter()) .filter(|tx| tx.is_signed().unwrap_or(false)); - let resubmit_future = transaction_pool + let resubmit_future = pool .submit_at(id, retracted_transactions, true) .then(|resubmit_result| ready(match resubmit_result { - Ok(_) => Ok(()), + Ok(_) => (), Err(e) => { warn!("Error re-submitting transactions: {:?}", e); - Ok(()) + () } - })) - .compat(); + })); // Avoid calling into runtime if there is nothing to prune from the pool anyway. - if transaction_pool.status().is_empty() { - return Ok(Box::new(resubmit_future)) + if pool.status().is_empty() { + return Box::new(resubmit_future) } - let block = client.block(id)?; - Ok(match block { - Some(block) => { + let block = self.client.block(id); + match block { + Ok(Some(block)) => { let parent_id = BlockId::hash(*block.block.header().parent_hash()); - let prune_future = transaction_pool + let prune_future = pool .prune(id, &parent_id, block.block.extrinsics()) - .boxed() - .compat() - .map_err(|e| { warn!("{:?}", e); }); - - Box::new(resubmit_future.and_then(|_| prune_future)) + .then(|prune_result| ready(match prune_result { + Ok(_) => (), + Err(e) => { + warn!("Error pruning transactions: {:?}", e); + () + } + })); + + Box::new(resubmit_future.then(|_| prune_future)) }, - None => Box::new(resubmit_future), - }) + Ok(None) => Box::new(resubmit_future), + Err(err) => { + warn!("Error reading block body: {:?}", err); + Box::new(resubmit_future) + }, + } } } /// Default transaction pool maintainer for light clients. -pub struct DefaultLightTransactionPoolMaintainer { +pub struct DefaultLightTransactionPoolMaintainer { + client: Arc>, fetcher: Arc, revalidate_time_period: Option, revalidate_block_period: Option>, @@ -128,11 +143,24 @@ pub struct DefaultLightTransactionPoolMaintainer { _phantom: PhantomData, } -impl> DefaultLightTransactionPoolMaintainer { +impl DefaultLightTransactionPoolMaintainer + where + Block: BlockT::Out>, + Backend: 'static + client::backend::Backend, + Client: ProvideRuntimeApi, + as ProvideRuntimeApi>::Api: TaggedTransactionQueue, + Executor: 'static + Send + Sync + client::CallExecutor, + Api: 'static + Send + Sync, + F: Fetcher + 'static, +{ /// Create light pool maintainer with default constants. - pub fn with_defaults(fetcher: Arc) -> Self { + pub fn with_defaults( + client: Arc>, + fetcher: Arc, + ) -> Self { // default constants are: revalidate every 60 seconds or every 20 blocks Self::new( + client, fetcher, Some(std::time::Duration::from_secs(60)), Some(20.into()), @@ -141,11 +169,13 @@ impl> DefaultLightTransactionPoolMaintainer>, fetcher: Arc, revalidate_time_period: Option, revalidate_block_period: Option>, ) -> Self { Self { + client, fetcher, revalidate_time_period, revalidate_block_period, @@ -155,18 +185,16 @@ impl> DefaultLightTransactionPoolMaintainer( + fn prune( &self, id: &BlockId, header: &Block::Header, - transaction_pool: &Arc>, - ) -> impl std::future::Future where - PoolApi: 'static + txpool::ChainApi, - { + pool: &Arc, F, Block>>>, + ) -> impl std::future::Future { // fetch transactions (possible future optimization: proofs of inclusion) that // have been included into new block and prune these from the pool let id = id.clone(); - let transaction_pool = transaction_pool.clone(); + let pool = pool.clone(); self.fetcher.remote_body(RemoteBodyRequest { header: header.clone(), retry_count: None, @@ -177,9 +205,9 @@ impl> DefaultLightTransactionPoolMaintainer>(); - transaction_pool.prune_known(&id, &hashes) + pool.prune_known(&id, &hashes) .map_err(|e| format!("{}", e)) }) )) @@ -192,14 +220,12 @@ impl> DefaultLightTransactionPoolMaintainer( + fn revalidate( &self, id: &BlockId, header: &Block::Header, - transaction_pool: &Arc>, - ) -> impl std::future::Future where - PoolApi: 'static + txpool::ChainApi, - { + pool: &Arc, F, Block>>>, + ) -> impl std::future::Future { // to determine whether ready transaction is still valid, we perform periodic revalidaton // of ready transactions let is_revalidation_required = self.revalidation_status.lock().is_required( @@ -210,7 +236,7 @@ impl> DefaultLightTransactionPoolMaintainer { let revalidation_status = self.revalidation_status.clone(); - Either::Left(transaction_pool + Either::Left(pool .revalidate_ready(id) .map(|r| r.map_err(|e| warn!("Error revalidating known transactions: {}", e))) .map(move |_| revalidation_status.lock().clear())) @@ -220,44 +246,50 @@ impl> DefaultLightTransactionPoolMaintainer TransactionPoolMaintainer for DefaultLightTransactionPoolMaintainer - where - Block: BlockT::Out>, - F: Fetcher + 'static, +impl TransactionPoolMaintainer< + LightChainApi, F, Block> +> for DefaultLightTransactionPoolMaintainer where + Block: BlockT::Out>, + Backend: 'static + client::backend::Backend, + Client: ProvideRuntimeApi, + as ProvideRuntimeApi>::Api: TaggedTransactionQueue, + Executor: 'static + Send + Sync + client::CallExecutor, + Api: 'static + Send + Sync, + F: Fetcher + 'static, { - fn maintain( + fn maintain( &self, id: &BlockId, - client: &Arc>, - transaction_pool: &Arc>, _retracted: &[Block::Hash], - ) -> error::Result + Send>> where - Backend: 'static + client::backend::Backend, - Client: ProvideRuntimeApi, - as ProvideRuntimeApi>::Api: runtime_api::TaggedTransactionQueue, - Executor: 'static + client::CallExecutor, - PoolApi: 'static + txpool::ChainApi, - Api: 'static, - { + pool: &Arc, F, Block>>>, + ) -> Box + Send + Unpin> { // Do nothing if transaction pool is empty. - if transaction_pool.status().is_empty() { + if pool.status().is_empty() { self.revalidation_status.lock().clear(); - return Ok(Box::new(ready(Ok(())).compat())); + return Box::new(ready(())); } - let header = client.header(id).and_then(|h| h.ok_or(client::error::Error::UnknownBlock(format!("{}", id))))?; + let header = self.client.header(id) + .and_then(|h| h.ok_or(client::error::Error::UnknownBlock(format!("{}", id)))); + let header = match header { + Ok(header) => header, + Err(err) => { + println!("Failed to maintain light tx pool: {:?}", err); + return Box::new(ready(())); + } + }; // else prune block transactions from the pool - let prune_future = self.prune(id, &header, transaction_pool); + let prune_future = self.prune(id, &header, pool); // and then (optionally) revalidate in-pool transactions - let revalidate_future = self.revalidate(id, &header, transaction_pool); + let revalidate_future = self.revalidate(id, &header, pool); - let maintain_future = futures03::future::join( + let maintain_future = join( prune_future, revalidate_future, - ).map(|_| Ok(())); + ).map(|_| ()); - Ok(Box::new(maintain_future.compat())) + Box::new(maintain_future) } } @@ -309,16 +341,17 @@ impl TxPoolRevalidationStatus { #[cfg(test)] mod tests { use super::*; - use futures03::executor::block_on; + use futures::executor::block_on; use codec::Encode; use consensus_common::{BlockOrigin, SelectChain}; - use substrate_test_runtime_client::{prelude::*, runtime::{Block, Transfer}}; + use test_client::{prelude::*, runtime::{Block, Transfer}}; + use crate::api::{FullChainApi, LightChainApi}; #[test] fn should_remove_transactions_from_the_full_pool() { let (client, longest_chain) = TestClientBuilder::new().build_with_longest_chain(); let client = Arc::new(client); - let pool = TransactionPool::new(Default::default(), ::transaction_pool::FullChainApi::new(client.clone())); + let pool = txpool::Pool::new(Default::default(), FullChainApi::new(client.clone())); let pool = Arc::new(pool); let transaction = Transfer { amount: 5, @@ -340,12 +373,11 @@ mod tests { // fire notification - this should clean up the queue assert_eq!(pool.status().ready, 1); - DefaultFullTransactionPoolMaintainer.maintain( + block_on(DefaultFullTransactionPoolMaintainer::new(client).maintain( &id, - &client, + &[], &pool, - &[] - ).unwrap().wait().unwrap(); + )); // then assert_eq!(pool.status().ready, 0); @@ -361,7 +393,7 @@ mod tests { to: Default::default(), }.into_signed_tx(); let fetcher_transaction = transaction.clone(); - let fetcher = Arc::new(substrate_test_runtime_client::new_light_fetcher() + let fetcher = Arc::new(test_client::new_light_fetcher() .with_remote_body(Some(Box::new(move |_| Ok(vec![fetcher_transaction.clone()])))) .with_remote_call(Some(Box::new(move |_| { let validity: sr_primitives::transaction_validity::TransactionValidity = @@ -377,7 +409,7 @@ mod tests { let (client, longest_chain) = TestClientBuilder::new().build_with_longest_chain(); let client = Arc::new(client); - let pool = TransactionPool::new(Default::default(), ::transaction_pool::LightChainApi::new( + let pool = txpool::Pool::new(Default::default(), LightChainApi::new( client.clone(), fetcher.clone(), )); @@ -389,12 +421,11 @@ mod tests { // fire notification - this should clean up the queue assert_eq!(pool.status().ready, 1); - DefaultLightTransactionPoolMaintainer::with_defaults(fetcher).maintain( + block_on(DefaultLightTransactionPoolMaintainer::with_defaults(client.clone(), fetcher).maintain( &BlockId::Number(0), - &client, + &[], &pool, - &[] - ).unwrap().wait().unwrap(); + )); // then assert_eq!(pool.status().ready, 0); @@ -432,7 +463,7 @@ mod tests { fn should_revalidate_transactions_at_light_pool() { let build_fetcher = || { let validated = Arc::new(std::sync::atomic::AtomicBool::new(false)); - Arc::new(substrate_test_runtime_client::new_light_fetcher() + Arc::new(test_client::new_light_fetcher() .with_remote_body(Some(Box::new(move |_| Ok(vec![])))) .with_remote_call(Some(Box::new(move |_| { let is_inserted = validated.swap(true, std::sync::atomic::Ordering::SeqCst); @@ -455,12 +486,25 @@ mod tests { fn with_fetcher_maintain + 'static>( fetcher: Arc, - maintainer: &DefaultLightTransactionPoolMaintainer, - ) -> transaction_pool::txpool::Status { - // now let's prepare pool + revalidate_time_period: Option, + revalidate_block_period: Option, + prepare_maintainer: impl Fn(&Mutex>), + ) -> txpool::Status { let (client, longest_chain) = TestClientBuilder::new().build_with_longest_chain(); let client = Arc::new(client); - let pool = TransactionPool::new(Default::default(), ::transaction_pool::LightChainApi::new( + + // let's prepare maintainer + let maintainer = DefaultLightTransactionPoolMaintainer::new( + client.clone(), + fetcher.clone(), + revalidate_time_period, + revalidate_block_period, + ); + prepare_maintainer(&*maintainer.revalidation_status); + + // now let's prepare pool + + let pool = txpool::Pool::new(Default::default(), LightChainApi::new( client.clone(), fetcher, )); @@ -479,29 +523,33 @@ mod tests { )).unwrap(); // and run maintain procedures - maintainer.maintain(&BlockId::Number(0), &client, &pool, &[]).unwrap().wait().unwrap(); + block_on(maintainer.maintain(&BlockId::Number(0), &[], &pool)); pool.status() } // when revalidation is never required - nothing happens let fetcher = build_fetcher(); - let maintainer = DefaultLightTransactionPoolMaintainer::new(fetcher.clone(), None, None); - let status = with_fetcher_maintain(fetcher, &maintainer); + //let maintainer = DefaultLightTransactionPoolMaintainer::new(client.clone(), fetcher.clone(), None, None); + let status = with_fetcher_maintain(fetcher, None, None, |_revalidation_status| {}); assert_eq!(status.ready, 1); // when revalidation is scheduled by time - it is performed let fetcher = build_fetcher(); - let maintainer = DefaultLightTransactionPoolMaintainer::new(fetcher.clone(), None, None); - *maintainer.revalidation_status.lock() = TxPoolRevalidationStatus::Scheduled(Some(Instant::now()), None); - let status = with_fetcher_maintain(fetcher, &maintainer); + //let maintainer = DefaultLightTransactionPoolMaintainer::new(fetcher.clone(), None, None); + //*maintainer.revalidation_status.lock() = TxPoolRevalidationStatus::Scheduled(Some(Instant::now()), None); + let status = with_fetcher_maintain(fetcher, None, None, |revalidation_status| + *revalidation_status.lock() = TxPoolRevalidationStatus::Scheduled(Some(Instant::now()), None) + ); assert_eq!(status.ready, 0); // when revalidation is scheduled by block number - it is performed let fetcher = build_fetcher(); - let maintainer = DefaultLightTransactionPoolMaintainer::new(fetcher.clone(), None, None); - *maintainer.revalidation_status.lock() = TxPoolRevalidationStatus::Scheduled(None, Some(0)); - let status = with_fetcher_maintain(fetcher, &maintainer); + //let maintainer = DefaultLightTransactionPoolMaintainer::new(fetcher.clone(), None, None); + //*maintainer.revalidation_status.lock() = TxPoolRevalidationStatus::Scheduled(None, Some(0)); + let status = with_fetcher_maintain(fetcher, None, None, |revalidation_status| + *revalidation_status.lock() = TxPoolRevalidationStatus::Scheduled(None, Some(0)) + ); assert_eq!(status.ready, 0); } @@ -509,7 +557,7 @@ mod tests { fn should_add_reverted_transactions_to_the_pool() { let (client, longest_chain) = TestClientBuilder::new().build_with_longest_chain(); let client = Arc::new(client); - let pool = TransactionPool::new(Default::default(), ::transaction_pool::FullChainApi::new(client.clone())); + let pool = txpool::Pool::new(Default::default(), FullChainApi::new(client.clone())); let pool = Arc::new(pool); let transaction = Transfer { amount: 5, @@ -532,12 +580,11 @@ mod tests { // fire notification - this should clean up the queue assert_eq!(pool.status().ready, 1); - DefaultFullTransactionPoolMaintainer.maintain( + block_on(DefaultFullTransactionPoolMaintainer::new(client.clone()).maintain( &id, - &client, + &[], &pool, - &[] - ).unwrap().wait().unwrap(); + )); // then assert_eq!(pool.status().ready, 0); @@ -550,12 +597,11 @@ mod tests { client.import(BlockOrigin::Own, block).unwrap(); // fire notification - this should add the transaction back to the pool. - DefaultFullTransactionPoolMaintainer.maintain( + block_on(DefaultFullTransactionPoolMaintainer::new(client).maintain( &id, - &client, + &[block1_hash], &pool, - &[block1_hash] - ).unwrap().wait().unwrap(); + )); // then assert_eq!(pool.status().ready, 1); diff --git a/node-template/src/service.rs b/node-template/src/service.rs index 4fec1659db3b9..13fc3cf71cbcb 100644 --- a/node-template/src/service.rs +++ b/node-template/src/service.rs @@ -8,7 +8,6 @@ use grandpa::{self, FinalityProofProvider as GrandpaFinalityProofProvider}; use futures::prelude::*; use node_template_runtime::{self, GenesisConfig, opaque::Block, RuntimeApi}; use substrate_service::{error::{Error as ServiceError}, AbstractService, Configuration, ServiceBuilder}; -use transaction_pool::{self, txpool::{Pool as TransactionPool}}; use inherents::InherentDataProviders; use network::construct_simple_protocol; use substrate_executor::native_executor_instance; @@ -42,7 +41,7 @@ macro_rules! new_full_start { Ok(substrate_client::LongestChain::new(backend.clone())) })? .with_transaction_pool(|config, client, _fetcher| - Ok(transaction_pool::txpool::Pool::new(config, transaction_pool::FullChainApi::new(client))) + Ok(transaction_pool::BasicTransactionPool::default_full(config, client)) )? .with_import_queue(|_config, client, mut select_chain, _transaction_pool| { let select_chain = select_chain.take() @@ -189,8 +188,7 @@ pub fn new_light(config: Configuration; #[allow(dead_code)] type ConcreteBackend = Backend; +#[allow(dead_code)] +type ConcreteTransactionPool = BasicTransactionPool< + FullChainApi, + DefaultFullTransactionPoolMaintainer< + ConcreteBackend, + LocalCallExecutor, NativeExecutor>, + Block, + node_runtime::RuntimeApi, + >, + Block, + >; /// A specialized configuration object for setting up the node.. pub type NodeConfiguration = Configuration; @@ -250,7 +261,7 @@ pub fn new_full(config: NodeConfiguration) LongestChain, NetworkStatus, NetworkService::Hash>, - TransactionPool>, + ConcreteTransactionPool, OffchainWorkers< ConcreteClient, >::OffchainStorage, @@ -276,9 +287,7 @@ pub fn new_light(config: NodeConfiguration) .with_transaction_pool(|config, client, fetcher| { let fetcher = fetcher .ok_or_else(|| "Trying to start light transaction pool without active fetcher")?; - let pool = TransactionPool::new(config, transaction_pool::LightChainApi::new(client, fetcher)); - pool.reject_future_transactions(); - Ok(pool) + Ok(transaction_pool::BasicTransactionPool::default_light(config, client, fetcher)) })? .with_import_queue_and_fprb(|_config, client, backend, fetcher, _select_chain, _tx_pool| { let fetch_checker = fetcher diff --git a/node/rpc/src/lib.rs b/node/rpc/src/lib.rs index c57d06f683741..7b6f76e359f51 100644 --- a/node/rpc/src/lib.rs +++ b/node/rpc/src/lib.rs @@ -33,16 +33,16 @@ use std::sync::Arc; use node_primitives::{Block, AccountId, Index, Balance}; use sr_primitives::traits::ProvideRuntimeApi; -use transaction_pool::txpool::{ChainApi, Pool}; +use transaction_pool::TransactionPool; /// Instantiate all RPC extensions for full node. -pub fn create_full(client: Arc, pool: Arc>) -> jsonrpc_core::IoHandler where +pub fn create_full(client: Arc, pool: Arc

) -> jsonrpc_core::IoHandler where C: ProvideRuntimeApi, C: client::blockchain::HeaderBackend, C: Send + Sync + 'static, C::Api: srml_system_rpc::AccountNonceApi, C::Api: srml_contracts_rpc::ContractsRuntimeApi, - P: ChainApi + Sync + Send + 'static, + P: TransactionPool + Sync + Send + 'static, M: jsonrpc_core::Metadata + Default, { use srml_system_rpc::{FullSystem, SystemApi}; @@ -63,14 +63,14 @@ pub fn create_light( client: Arc, remote_blockchain: Arc>, fetcher: Arc, - pool: Arc>, + pool: Arc

, ) -> jsonrpc_core::IoHandler where C: ProvideRuntimeApi, C: client::blockchain::HeaderBackend, C: Send + Sync + 'static, C::Api: srml_system_rpc::AccountNonceApi, - P: ChainApi + Sync + Send + 'static, + P: TransactionPool + Sync + Send + 'static, M: jsonrpc_core::Metadata + Default, F: client::light::fetcher::Fetcher + 'static, { diff --git a/srml/system/rpc/src/lib.rs b/srml/system/rpc/src/lib.rs index 29dd9a691bc8f..c173caa4899c5 100644 --- a/srml/system/rpc/src/lib.rs +++ b/srml/system/rpc/src/lib.rs @@ -36,7 +36,7 @@ use sr_primitives::{ traits, }; use substrate_primitives::hexdisplay::HexDisplay; -use transaction_pool::txpool::{self, Pool}; +use transaction_pool::TransactionPool; pub use srml_system_rpc_runtime_api::AccountNonceApi; pub use self::gen_client::Client as SystemClient; @@ -59,15 +59,15 @@ pub trait SystemApi { const RUNTIME_ERROR: i64 = 1; /// An implementation of System-specific RPC methods on full client. -pub struct FullSystem { +pub struct FullSystem { client: Arc, - pool: Arc>, + pool: Arc

, _marker: std::marker::PhantomData, } -impl FullSystem { +impl FullSystem { /// Create new `FullSystem` given client and transaction pool. - pub fn new(client: Arc, pool: Arc>) -> Self { + pub fn new(client: Arc, pool: Arc

) -> Self { FullSystem { client, pool, @@ -82,7 +82,7 @@ where C: HeaderBackend, C: Send + Sync + 'static, C::Api: AccountNonceApi, - P: txpool::ChainApi + Sync + Send + 'static, + P: TransactionPool + Sync + Send + 'static, Block: traits::Block, AccountId: Clone + std::fmt::Display + Codec, Index: Clone + std::fmt::Display + Codec + Send + traits::SimpleArithmetic + 'static, @@ -107,20 +107,20 @@ where } /// An implementation of System-specific RPC methods on light client. -pub struct LightSystem { +pub struct LightSystem { client: Arc, remote_blockchain: Arc>, fetcher: Arc, - pool: Arc>, + pool: Arc

, } -impl LightSystem { +impl LightSystem { /// Create new `LightSystem`. pub fn new( client: Arc, remote_blockchain: Arc>, fetcher: Arc, - pool: Arc>, + pool: Arc

, ) -> Self { LightSystem { client, @@ -133,7 +133,7 @@ impl LightSystem { impl SystemApi for LightSystem where - P: txpool::ChainApi + Sync + Send + 'static, + P: TransactionPool + Sync + Send + 'static, C: HeaderBackend, C: Send + Sync + 'static, F: Fetcher + 'static, @@ -180,8 +180,8 @@ where /// Adjust account nonce from state, so that tx with the nonce will be /// placed after all ready txpool transactions. -fn adjust_nonce( - pool: &Pool

, +fn adjust_nonce( + pool: &P, account: AccountId, nonce: Index, ) -> Index where @@ -225,13 +225,14 @@ mod tests { runtime::Transfer, AccountKeyring, }; + use transaction_pool::BasicTransactionPool; #[test] fn should_return_next_nonce_for_some_account() { // given let _ = env_logger::try_init(); let client = Arc::new(test_client::new()); - let pool = Arc::new(Pool::new(Default::default(), transaction_pool::FullChainApi::new(client.clone()))); + let pool = Arc::new(BasicTransactionPool::default_full(Default::default(), client.clone())); let new_transaction = |nonce: u64| { let t = Transfer { From fc5406e21ab21bc38cfd931a7e209ec733c0ac1b Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Wed, 23 Oct 2019 11:50:29 +0300 Subject: [PATCH 10/38] pause future tx reject when resubmitting --- core/transaction-pool/graph/src/base_pool.rs | 39 +++++++++++++++++++ core/transaction-pool/graph/src/future.rs | 6 +++ .../graph/src/validated_pool.rs | 15 +++++++ 3 files changed, 60 insertions(+) diff --git a/core/transaction-pool/graph/src/base_pool.rs b/core/transaction-pool/graph/src/base_pool.rs index c12b7d833a888..4aa5c0d283d94 100644 --- a/core/transaction-pool/graph/src/base_pool.rs +++ b/core/transaction-pool/graph/src/base_pool.rs @@ -187,6 +187,13 @@ impl BasePool bool { + let previous = self.reject_future_transactions; + self.reject_future_transactions = reject; + previous + } + /// Imports transaction to the pool. /// /// The pool consists of two parts: Future and Ready. @@ -380,6 +387,11 @@ impl BasePool Vec>> { + self.future.clear() + } + /// Prunes transactions that provide given list of tags. /// /// This will cause all transactions that provide these tags to be removed from the pool, @@ -1008,4 +1020,31 @@ requires: [03,02], provides: [04], data: [4]}".to_owned() assert!(false, "Invalid error kind: {:?}", err); } } + + #[test] + fn should_clear_future_queue() { + // given + let mut pool = pool(); + + // when + pool.import(Transaction { + data: vec![5u8], + bytes: 1, + hash: 5, + priority: 5u64, + valid_till: 64u64, + requires: vec![vec![0]], + provides: vec![], + propagate: true, + }).unwrap(); + + // then + assert_eq!(pool.future.len(), 1); + + // and then when + assert_eq!(pool.clear_future().len(), 1); + + // then + assert_eq!(pool.future.len(), 0); + } } diff --git a/core/transaction-pool/graph/src/future.rs b/core/transaction-pool/graph/src/future.rs index c7b13c912df18..8b01e9d654144 100644 --- a/core/transaction-pool/graph/src/future.rs +++ b/core/transaction-pool/graph/src/future.rs @@ -227,6 +227,12 @@ impl FutureTransactions { self.waiting.values().map(|waiting| &*waiting.transaction) } + /// Removes and returns all future transactions. + pub fn clear(&mut self) -> Vec>> { + self.wanted_tags.clear(); + self.waiting.drain().map(|(_, tx)| tx.transaction).collect() + } + /// Returns number of transactions in the Future queue. pub fn len(&self) -> usize { self.waiting.len() diff --git a/core/transaction-pool/graph/src/validated_pool.rs b/core/transaction-pool/graph/src/validated_pool.rs index 90163afe22f23..07d98885ada80 100644 --- a/core/transaction-pool/graph/src/validated_pool.rs +++ b/core/transaction-pool/graph/src/validated_pool.rs @@ -219,6 +219,12 @@ impl ValidatedPool { } } + // if we're rejecting future transactions, then insertion order matters here: + // if tx1 depends on tx2, then if tx1 is inserted before tx2, then it goes + // to the future queue and gets rejected immediately + // => let's temporary stop rejection and clear future queue before return + let reject_future_transactions = pool.reject_future_transactions(false); + // now resubmit all removed transactions back to the pool let mut final_statuses = HashMap::new(); for (hash, tx_to_resubmit) in txs_to_resubmit { @@ -255,6 +261,15 @@ impl ValidatedPool { } } + // if the pool is configured to reject future transactions, let's clear the future + // queue, updating final statuses as required + if reject_future_transactions { + for future_tx in pool.clear_future() { + final_statuses.insert(future_tx.hash.clone(), Status::Dropped); + } + } + pool.reject_future_transactions(reject_future_transactions); + (initial_statuses, final_statuses) }; From a349d203eee918fb07f324a90367f1793ee6b3fa Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Wed, 23 Oct 2019 12:16:38 +0300 Subject: [PATCH 11/38] bump impl_version to make CI happy --- node/runtime/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/node/runtime/src/lib.rs b/node/runtime/src/lib.rs index fd31969efa02f..11acd4f99f7b0 100644 --- a/node/runtime/src/lib.rs +++ b/node/runtime/src/lib.rs @@ -85,7 +85,7 @@ pub const VERSION: RuntimeVersion = RuntimeVersion { // implementation changes and behavior does not, then leave spec_version as // is and increment impl_version. spec_version: 176, - impl_version: 176, + impl_version: 177, apis: RUNTIME_API_VERSIONS, }; From 30c2a05db43c64cfc47dd4b7c297fb7058c6dcb4 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Wed, 23 Oct 2019 12:31:39 +0300 Subject: [PATCH 12/38] and revert back local test fixes --- core/sr-api-macros/tests/ui/declaring_old_block.stderr | 2 +- .../tests/ui/declaring_own_block_with_different_name.stderr | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/core/sr-api-macros/tests/ui/declaring_old_block.stderr b/core/sr-api-macros/tests/ui/declaring_old_block.stderr index 181aa2a3ca783..999a50cc96977 100644 --- a/core/sr-api-macros/tests/ui/declaring_old_block.stderr +++ b/core/sr-api-macros/tests/ui/declaring_old_block.stderr @@ -16,4 +16,4 @@ warning: unused import: `sr_primitives::traits::Block as BlockT` 1 | use sr_primitives::traits::Block as BlockT; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: #[warn(unused_imports)] on by default + = note: `#[warn(unused_imports)]` on by default diff --git a/core/sr-api-macros/tests/ui/declaring_own_block_with_different_name.stderr b/core/sr-api-macros/tests/ui/declaring_own_block_with_different_name.stderr index a591d0448c50d..ec033f2e09d23 100644 --- a/core/sr-api-macros/tests/ui/declaring_own_block_with_different_name.stderr +++ b/core/sr-api-macros/tests/ui/declaring_own_block_with_different_name.stderr @@ -10,4 +10,4 @@ warning: unused import: `sr_primitives::traits::Block as BlockT` 1 | use sr_primitives::traits::Block as BlockT; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: #[warn(unused_imports)] on by default + = note: `#[warn(unused_imports)]` on by default From b1340ab93ee10bbd715058cedb6ef4173f59c0e2 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Wed, 23 Oct 2019 13:20:11 +0300 Subject: [PATCH 13/38] alter doc to restart CI --- core/transaction-pool/src/maintainer.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/core/transaction-pool/src/maintainer.rs b/core/transaction-pool/src/maintainer.rs index f0ad0f6dc57f2..14463e3fe37a4 100644 --- a/core/transaction-pool/src/maintainer.rs +++ b/core/transaction-pool/src/maintainer.rs @@ -154,11 +154,13 @@ impl DefaultLightTransactionPoolMaintainer + 'static, { /// Create light pool maintainer with default constants. + /// + /// Default constants are: revalidate every 60 seconds or every 20 blocks + /// (whatever happens first). pub fn with_defaults( client: Arc>, fetcher: Arc, ) -> Self { - // default constants are: revalidate every 60 seconds or every 20 blocks Self::new( client, fetcher, From b283fc333d99948a7c49c13e280959657b2d5e48 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Thu, 24 Oct 2019 11:47:05 +0300 Subject: [PATCH 14/38] Transaction::clone() -> Transaction::duplicate() --- core/transaction-pool/graph/src/base_pool.rs | 23 ++++++++++++++++++- .../graph/src/validated_pool.rs | 9 +++++++- 2 files changed, 30 insertions(+), 2 deletions(-) diff --git a/core/transaction-pool/graph/src/base_pool.rs b/core/transaction-pool/graph/src/base_pool.rs index 4aa5c0d283d94..97da350aedd01 100644 --- a/core/transaction-pool/graph/src/base_pool.rs +++ b/core/transaction-pool/graph/src/base_pool.rs @@ -83,7 +83,8 @@ pub struct PruneStatus { } /// Immutable transaction -#[derive(Clone, PartialEq, Eq)] +#[cfg_attr(test, derive(Clone))] +#[derive(PartialEq, Eq)] pub struct Transaction { /// Raw extrinsic representing that transaction. pub data: Extrinsic, @@ -110,6 +111,26 @@ impl Transaction { } } +impl Transaction { + /// Explicit transaction clone. + /// + /// Transaction should be cloned only if absolutely necessary && we want + /// every reason to be commented. That's why we `Transaction` is not `Clone`, + /// but there's explicit `duplicate` method. + pub fn duplicate(&self) -> Self { + Transaction { + data: self.data.clone(), + bytes: self.bytes.clone(), + hash: self.hash.clone(), + priority: self.priority.clone(), + valid_till: self.valid_till.clone(), + requires: self.requires.clone(), + provides: self.provides.clone(), + propagate: self.propagate, + } + } +} + impl fmt::Debug for Transaction where Hash: fmt::Debug, Extrinsic: fmt::Debug, diff --git a/core/transaction-pool/graph/src/validated_pool.rs b/core/transaction-pool/graph/src/validated_pool.rs index 07d98885ada80..52556567e3f7d 100644 --- a/core/transaction-pool/graph/src/validated_pool.rs +++ b/core/transaction-pool/graph/src/validated_pool.rs @@ -17,6 +17,7 @@ use std::{ collections::{HashSet, HashMap}, hash, + sync::Arc, time, }; @@ -211,7 +212,13 @@ impl ValidatedPool { let tx_to_resubmit = if let Some(updated_tx) = transactions.remove(&removed_hash) { updated_tx } else { - ValidatedTransaction::Valid((*removed_tx).clone()) + // in most cases we'll end up in successful `try_unwrap`, but if not + // we still need to reinsert transaction back to the pool => duplicate call + let transaction = match Arc::try_unwrap(removed_tx) { + Ok(transaction) => transaction, + Err(transaction) => transaction.duplicate(), + }; + ValidatedTransaction::Valid(transaction) }; initial_statuses.insert(removed_hash.clone(), Status::Ready); From 92c4eeab419204d72fc1f80aaaefc6a6aecd365b Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Thu, 24 Oct 2019 11:51:47 +0300 Subject: [PATCH 15/38] transactions -> updated_tranasctions --- .../graph/src/validated_pool.rs | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/core/transaction-pool/graph/src/validated_pool.rs b/core/transaction-pool/graph/src/validated_pool.rs index 52556567e3f7d..0526c637200f6 100644 --- a/core/transaction-pool/graph/src/validated_pool.rs +++ b/core/transaction-pool/graph/src/validated_pool.rs @@ -185,11 +185,11 @@ impl ValidatedPool { } } - /// Resubmits transactions in the pool. + /// Resubmits revalidated transactions back to the pool. /// /// Removes and then submits passed transactions and all dependent transactions. /// Transactions that are missing from the pool are not submitted. - pub fn resubmit(&self, mut transactions: HashMap, ValidatedTransactionFor>) { + pub fn resubmit(&self, mut updated_transactions: HashMap, ValidatedTransactionFor>) { #[derive(Debug, Clone, Copy, PartialEq)] enum Status { Future, Ready, Failed, Dropped }; @@ -198,10 +198,15 @@ impl ValidatedPool { // remove all passed transactions from the ready/future queues // (this may remove additional transactions as well) + // + // for every transaction that has an entry in the `updated_transactions`, + // we store updated validation result in txs_to_resubmit + // for every transaction that has no entry in the `updated_transactions`, + // we store last validation result (i.e. the pool entry) in txs_to_resubmit let mut initial_statuses = HashMap::new(); - let mut txs_to_resubmit = Vec::with_capacity(transactions.len()); - while !transactions.is_empty() { - let hash = transactions.keys().next().cloned().expect("transactions is not empty; qed"); + let mut txs_to_resubmit = Vec::with_capacity(updated_transactions.len()); + while !updated_transactions.is_empty() { + let hash = updated_transactions.keys().next().cloned().expect("transactions is not empty; qed"); // note we are not considering tx with hash invalid here - we just want // to remove it along with dependent transactions and `remove_invalid()` @@ -209,7 +214,8 @@ impl ValidatedPool { let removed = pool.remove_invalid(&[hash.clone()]); for removed_tx in removed { let removed_hash = removed_tx.hash.clone(); - let tx_to_resubmit = if let Some(updated_tx) = transactions.remove(&removed_hash) { + let updated_transaction = updated_transactions.remove(&removed_hash); + let tx_to_resubmit = if let Some(updated_tx) = updated_transaction { updated_tx } else { // in most cases we'll end up in successful `try_unwrap`, but if not From 1faa209af82f404b2365db2b9572e6b1af6a8495 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Thu, 24 Oct 2019 12:00:55 +0300 Subject: [PATCH 16/38] remove explicit consensus-common ref --- Cargo.lock | 1 - core/transaction-pool/Cargo.toml | 1 - core/transaction-pool/src/maintainer.rs | 3 +-- 3 files changed, 1 insertion(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 8cb97ce8b65a0..e88795a3f942e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5717,7 +5717,6 @@ dependencies = [ "parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", "sr-primitives 2.0.0", "substrate-client 2.0.0", - "substrate-consensus-common 2.0.0", "substrate-keyring 2.0.0", "substrate-primitives 2.0.0", "substrate-test-runtime-client 2.0.0", diff --git a/core/transaction-pool/Cargo.toml b/core/transaction-pool/Cargo.toml index a11d19505c0a9..33ec9e9ece176 100644 --- a/core/transaction-pool/Cargo.toml +++ b/core/transaction-pool/Cargo.toml @@ -18,4 +18,3 @@ txpool = { package = "substrate-transaction-graph", path = "./graph" } [dev-dependencies] keyring = { package = "substrate-keyring", path = "../../core/keyring" } test-client = { package = "substrate-test-runtime-client", path = "../../core/test-runtime/client" } -consensus_common = { package = "substrate-consensus-common", path = "../../core/consensus/common" } diff --git a/core/transaction-pool/src/maintainer.rs b/core/transaction-pool/src/maintainer.rs index 14463e3fe37a4..0c206f1c0824e 100644 --- a/core/transaction-pool/src/maintainer.rs +++ b/core/transaction-pool/src/maintainer.rs @@ -345,8 +345,7 @@ mod tests { use super::*; use futures::executor::block_on; use codec::Encode; - use consensus_common::{BlockOrigin, SelectChain}; - use test_client::{prelude::*, runtime::{Block, Transfer}}; + use test_client::{prelude::*, runtime::{Block, Transfer}, consensus::{BlockOrigin, SelectChain}}; use crate::api::{FullChainApi, LightChainApi}; #[test] From a8318bacc029370322f38abb71e460b7d237dc8a Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Thu, 24 Oct 2019 12:05:40 +0300 Subject: [PATCH 17/38] ::std:: -> std:: --- core/transaction-pool/graph/src/base_pool.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/core/transaction-pool/graph/src/base_pool.rs b/core/transaction-pool/graph/src/base_pool.rs index 97da350aedd01..eedede7428a3c 100644 --- a/core/transaction-pool/graph/src/base_pool.rs +++ b/core/transaction-pool/graph/src/base_pool.rs @@ -190,13 +190,13 @@ pub struct BasePool { recently_pruned_index: usize, } -impl Default for BasePool { +impl Default for BasePool { fn default() -> Self { Self::new(false) } } -impl BasePool { +impl BasePool { /// Create new pool given reject_future_transactions flag. pub fn new(reject_future_transactions: bool) -> Self { BasePool { @@ -428,7 +428,7 @@ impl BasePool Date: Thu, 24 Oct 2019 12:18:48 +0300 Subject: [PATCH 18/38] manual set/unset flag -> calling clusore with given flag value --- core/transaction-pool/graph/src/base_pool.rs | 42 +++++++++- .../graph/src/validated_pool.rs | 80 ++++++++++--------- 2 files changed, 80 insertions(+), 42 deletions(-) diff --git a/core/transaction-pool/graph/src/base_pool.rs b/core/transaction-pool/graph/src/base_pool.rs index eedede7428a3c..fc5b0204faf9e 100644 --- a/core/transaction-pool/graph/src/base_pool.rs +++ b/core/transaction-pool/graph/src/base_pool.rs @@ -208,11 +208,17 @@ impl BasePool bool { + /// Temporary enables future transactions, runs closure and then restores + /// `reject_future_transactions` flag back to previous value. + /// + /// The closure accepts the mutable reference to the pool and original value + /// of the `reject_future_transactions` flag. + pub(crate) fn with_futures_enabled(&mut self, closure: impl FnOnce(&mut Self, bool) -> T) -> T { let previous = self.reject_future_transactions; - self.reject_future_transactions = reject; - previous + self.reject_future_transactions = false; + let return_value = closure(self, previous); + self.reject_future_transactions = previous; + return_value } /// Imports transaction to the pool. @@ -1068,4 +1074,32 @@ requires: [03,02], provides: [04], data: [4]}".to_owned() // then assert_eq!(pool.future.len(), 0); } + + #[test] + fn should_accept_future_transactions_when_explcitly_asked_to() { + // given + let mut pool = pool(); + pool.reject_future_transactions = true; + + // when + let flag_value = pool.with_futures_enabled(|pool, flag| { + pool.import(Transaction { + data: vec![5u8], + bytes: 1, + hash: 5, + priority: 5u64, + valid_till: 64u64, + requires: vec![vec![0]], + provides: vec![], + propagate: true, + }).unwrap(); + + flag + }); + + // then + assert_eq!(flag_value, true); + assert_eq!(pool.reject_future_transactions, true); + assert_eq!(pool.future.len(), 1); + } } diff --git a/core/transaction-pool/graph/src/validated_pool.rs b/core/transaction-pool/graph/src/validated_pool.rs index 0526c637200f6..37a5c5c3e7eca 100644 --- a/core/transaction-pool/graph/src/validated_pool.rs +++ b/core/transaction-pool/graph/src/validated_pool.rs @@ -236,54 +236,58 @@ impl ValidatedPool { // if tx1 depends on tx2, then if tx1 is inserted before tx2, then it goes // to the future queue and gets rejected immediately // => let's temporary stop rejection and clear future queue before return - let reject_future_transactions = pool.reject_future_transactions(false); - - // now resubmit all removed transactions back to the pool - let mut final_statuses = HashMap::new(); - for (hash, tx_to_resubmit) in txs_to_resubmit { - match tx_to_resubmit { - ValidatedTransaction::Valid(tx) => match pool.import(tx) { - Ok(imported) => match imported { - base::Imported::Ready { promoted, failed, removed, .. } => { - final_statuses.insert(hash, Status::Ready); - for hash in promoted { + pool.with_futures_enabled(|pool, reject_future_transactions| { + // now resubmit all removed transactions back to the pool + let mut final_statuses = HashMap::new(); + for (hash, tx_to_resubmit) in txs_to_resubmit { + match tx_to_resubmit { + ValidatedTransaction::Valid(tx) => match pool.import(tx) { + Ok(imported) => match imported { + base::Imported::Ready { promoted, failed, removed, .. } => { final_statuses.insert(hash, Status::Ready); - } - for hash in failed { - final_statuses.insert(hash, Status::Failed); - } - for tx in removed { - final_statuses.insert(tx.hash.clone(), Status::Dropped); - } + for hash in promoted { + final_statuses.insert(hash, Status::Ready); + } + for hash in failed { + final_statuses.insert(hash, Status::Failed); + } + for tx in removed { + final_statuses.insert(tx.hash.clone(), Status::Dropped); + } + }, + base::Imported::Future { .. } => { + final_statuses.insert(hash, Status::Future); + }, }, - base::Imported::Future { .. } => { - final_statuses.insert(hash, Status::Future); + Err(err) => { + // we do not want to fail if single transaction import has failed + // nor we do want to propagate this error, because it could tx unknown to caller + // => let's just notify listeners (and issue debug message) + warn!( + target: "txpool", + "[{:?}] Removing invalid transaction from update: {}", + hash, + err, + ); + final_statuses.insert(hash, Status::Failed); }, }, - Err(err) => { - // we do not want to fail if single transaction import has failed - // nor we do want to propagate this error, because it could tx unknown to caller - // => let's just notify listeners (and issue debug message) - warn!(target: "txpool", "[{:?}] Removing invalid transaction from update: {}", hash, err); + ValidatedTransaction::Invalid(_) | ValidatedTransaction::Unknown(_, _) => { final_statuses.insert(hash, Status::Failed); }, - }, - ValidatedTransaction::Invalid(_) | ValidatedTransaction::Unknown(_, _) => { - final_statuses.insert(hash, Status::Failed); - }, + } } - } - // if the pool is configured to reject future transactions, let's clear the future - // queue, updating final statuses as required - if reject_future_transactions { - for future_tx in pool.clear_future() { - final_statuses.insert(future_tx.hash.clone(), Status::Dropped); + // if the pool is configured to reject future transactions, let's clear the future + // queue, updating final statuses as required + if reject_future_transactions { + for future_tx in pool.clear_future() { + final_statuses.insert(future_tx.hash.clone(), Status::Dropped); + } } - } - pool.reject_future_transactions(reject_future_transactions); - (initial_statuses, final_statuses) + (initial_statuses, final_statuses) + }) }; // and now let's notify listeners about status changes From 1c2f75e0bb82dd2217900b7002abfbb68f0eec9f Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Thu, 24 Oct 2019 12:25:02 +0300 Subject: [PATCH 19/38] removed comments --- core/transaction-pool/src/maintainer.rs | 4 ---- 1 file changed, 4 deletions(-) diff --git a/core/transaction-pool/src/maintainer.rs b/core/transaction-pool/src/maintainer.rs index 0c206f1c0824e..8a14470039f6e 100644 --- a/core/transaction-pool/src/maintainer.rs +++ b/core/transaction-pool/src/maintainer.rs @@ -537,8 +537,6 @@ mod tests { // when revalidation is scheduled by time - it is performed let fetcher = build_fetcher(); - //let maintainer = DefaultLightTransactionPoolMaintainer::new(fetcher.clone(), None, None); - //*maintainer.revalidation_status.lock() = TxPoolRevalidationStatus::Scheduled(Some(Instant::now()), None); let status = with_fetcher_maintain(fetcher, None, None, |revalidation_status| *revalidation_status.lock() = TxPoolRevalidationStatus::Scheduled(Some(Instant::now()), None) ); @@ -546,8 +544,6 @@ mod tests { // when revalidation is scheduled by block number - it is performed let fetcher = build_fetcher(); - //let maintainer = DefaultLightTransactionPoolMaintainer::new(fetcher.clone(), None, None); - //*maintainer.revalidation_status.lock() = TxPoolRevalidationStatus::Scheduled(None, Some(0)); let status = with_fetcher_maintain(fetcher, None, None, |revalidation_status| *revalidation_status.lock() = TxPoolRevalidationStatus::Scheduled(None, Some(0)) ); From f645a41811d0b9ecc8705f57900fb866c6ea9ad2 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Thu, 24 Oct 2019 12:29:14 +0300 Subject: [PATCH 20/38] removed force argument --- core/basic-authorship/src/basic_authorship.rs | 2 +- core/transaction-pool/graph/src/pool.rs | 2 +- core/transaction-pool/src/lib.rs | 4 +--- 3 files changed, 3 insertions(+), 5 deletions(-) diff --git a/core/basic-authorship/src/basic_authorship.rs b/core/basic-authorship/src/basic_authorship.rs index a1fa930f2bf91..a9cf6b441ca15 100644 --- a/core/basic-authorship/src/basic_authorship.rs +++ b/core/basic-authorship/src/basic_authorship.rs @@ -251,7 +251,7 @@ mod tests { let txpool = Arc::new(BasicTransactionPool::default_full(Default::default(), client.clone())); futures::executor::block_on( - txpool.submit_at(&BlockId::number(0), vec![extrinsic(0), extrinsic(1)], false) + txpool.submit_at(&BlockId::number(0), vec![extrinsic(0), extrinsic(1)]) ).unwrap(); let mut proposer_factory = ProposerFactory { diff --git a/core/transaction-pool/graph/src/pool.rs b/core/transaction-pool/graph/src/pool.rs index 11ac48986fbff..7b8b775544a57 100644 --- a/core/transaction-pool/graph/src/pool.rs +++ b/core/transaction-pool/graph/src/pool.rs @@ -146,7 +146,7 @@ impl Pool { at: &BlockId, xt: ExtrinsicFor, ) -> impl Future, B::Error>> { - self.submit_at(at, std::iter::once(xt), false) + self.submit_at(at, std::iter::once(xt)) .map(|import_result| import_result.and_then(|mut import_result| import_result .pop() .expect("One extrinsic passed; one result returned; qed") diff --git a/core/transaction-pool/src/lib.rs b/core/transaction-pool/src/lib.rs index b5a601a9c3539..f76af8ee6fc59 100644 --- a/core/transaction-pool/src/lib.rs +++ b/core/transaction-pool/src/lib.rs @@ -71,7 +71,6 @@ pub trait TransactionPool: Send + Sync { &self, at: &BlockId, xts: impl IntoIterator> + 'static, - force: bool, ) -> Box>, Self::Error>> + Send + Unpin>; /// Returns a future that imports one unverified extrinsic to the pool. @@ -207,9 +206,8 @@ impl TransactionPool for BasicTransactionPool, xts: impl IntoIterator> + 'static, - force: bool, ) -> Box>, Self::Error>> + Send + Unpin> { - Box::new(self.pool.submit_at(at, xts, force)) + Box::new(self.pool.submit_at(at, xts, false)) } fn submit_one( From 441a77158301443d354374b0e9756d9bc6760e15 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Thu, 24 Oct 2019 12:34:51 +0300 Subject: [PATCH 21/38] BestIterator -> Box --- core/transaction-pool/graph/src/base_pool.rs | 4 ++-- core/transaction-pool/graph/src/lib.rs | 1 - core/transaction-pool/graph/src/pool.rs | 5 ++--- core/transaction-pool/graph/src/ready.rs | 2 +- core/transaction-pool/graph/src/validated_pool.rs | 3 +-- core/transaction-pool/src/lib.rs | 8 ++++---- 6 files changed, 10 insertions(+), 13 deletions(-) diff --git a/core/transaction-pool/graph/src/base_pool.rs b/core/transaction-pool/graph/src/base_pool.rs index fc5b0204faf9e..086f67ec29394 100644 --- a/core/transaction-pool/graph/src/base_pool.rs +++ b/core/transaction-pool/graph/src/base_pool.rs @@ -37,7 +37,7 @@ use sr_primitives::transaction_validity::{ use crate::error; use crate::future::{FutureTransactions, WaitingTransaction}; -use crate::ready::{ReadyTransactions, BestIterator}; +use crate::ready::ReadyTransactions; /// Successful import result. #[derive(Debug, PartialEq, Eq)] @@ -324,7 +324,7 @@ impl BasePool BestIterator { + pub fn ready(&self) -> impl Iterator>> { self.ready.get() } diff --git a/core/transaction-pool/graph/src/lib.rs b/core/transaction-pool/graph/src/lib.rs index 28308d70bf2bd..715e60874be95 100644 --- a/core/transaction-pool/graph/src/lib.rs +++ b/core/transaction-pool/graph/src/lib.rs @@ -37,7 +37,6 @@ pub mod watcher; pub use self::error::IntoPoolError; pub use self::base_pool::{Transaction, Status}; -pub use self::ready::BestIterator; pub use self::pool::{ Pool, Options, ChainApi, EventStream, ExtrinsicFor, diff --git a/core/transaction-pool/graph/src/pool.rs b/core/transaction-pool/graph/src/pool.rs index 7b8b775544a57..cbfff6ef32736 100644 --- a/core/transaction-pool/graph/src/pool.rs +++ b/core/transaction-pool/graph/src/pool.rs @@ -22,7 +22,6 @@ use std::{ use crate::base_pool as base; use crate::error; -use crate::ready::BestIterator; use crate::watcher::Watcher; use serde::Serialize; @@ -146,7 +145,7 @@ impl Pool { at: &BlockId, xt: ExtrinsicFor, ) -> impl Future, B::Error>> { - self.submit_at(at, std::iter::once(xt)) + self.submit_at(at, std::iter::once(xt), false) .map(|import_result| import_result.and_then(|mut import_result| import_result .pop() .expect("One extrinsic passed; one result returned; qed") @@ -324,7 +323,7 @@ impl Pool { } /// Get an iterator for ready transactions ordered by priority - pub fn ready(&self) -> BestIterator, ExtrinsicFor> { + pub fn ready(&self) -> impl Iterator> { self.validated_pool.ready() } diff --git a/core/transaction-pool/graph/src/ready.rs b/core/transaction-pool/graph/src/ready.rs index af8e9a9d117ad..0006ad1884620 100644 --- a/core/transaction-pool/graph/src/ready.rs +++ b/core/transaction-pool/graph/src/ready.rs @@ -144,7 +144,7 @@ impl ReadyTransactions { /// - transactions that are valid for a shorter time go first /// 4. Lastly we sort by the time in the queue /// - transactions that are longer in the queue go first - pub fn get(&self) -> BestIterator { + pub fn get(&self) -> impl Iterator>> { BestIterator { all: self.ready.clone(), best: self.best.clone(), diff --git a/core/transaction-pool/graph/src/validated_pool.rs b/core/transaction-pool/graph/src/validated_pool.rs index 37a5c5c3e7eca..36fc4514c3e08 100644 --- a/core/transaction-pool/graph/src/validated_pool.rs +++ b/core/transaction-pool/graph/src/validated_pool.rs @@ -24,7 +24,6 @@ use std::{ use crate::base_pool as base; use crate::error; use crate::listener::Listener; -use crate::ready::BestIterator; use crate::rotator::PoolRotator; use crate::watcher::Watcher; use serde::Serialize; @@ -462,7 +461,7 @@ impl ValidatedPool { } /// Get an iterator for ready transactions ordered by priority - pub fn ready(&self) -> BestIterator, ExtrinsicFor> { + pub fn ready(&self) -> impl Iterator> { self.pool.read().ready() } diff --git a/core/transaction-pool/src/lib.rs b/core/transaction-pool/src/lib.rs index f76af8ee6fc59..828ce6a98ca43 100644 --- a/core/transaction-pool/src/lib.rs +++ b/core/transaction-pool/src/lib.rs @@ -48,7 +48,7 @@ use sr_primitives::{ traits::{Block as BlockT, Member, ProvideRuntimeApi}, }; -use txpool::{BestIterator, EventStream, Options, watcher::Watcher}; +use txpool::{EventStream, Options, watcher::Watcher}; /// Extrinsic hash type for a pool. pub type ExHash

=

::Hash; @@ -97,7 +97,7 @@ pub trait TransactionPool: Send + Sync { fn status(&self) -> txpool::base_pool::Status; /// Get an iterator for ready transactions ordered by priority - fn ready(&self) -> BestIterator>; + fn ready(&self) -> Box>>>>; /// Return an event stream of transactions imported to the pool. fn import_notification_stream(&self) -> EventStream; @@ -237,8 +237,8 @@ impl TransactionPool for BasicTransactionPool BestIterator> { - self.pool.ready() + fn ready(&self) -> Box>>>> { + Box::new(self.pool.ready()) } fn import_notification_stream(&self) -> EventStream { From 8d67a59de56cfbe628922969ca3ed39bb79fee53 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Fri, 25 Oct 2019 15:24:06 +0300 Subject: [PATCH 22/38] separate crate for TxPool + Maintainer trait --- Cargo.lock | 27 +- Cargo.toml | 1 + core/basic-authorship/Cargo.toml | 3 +- core/basic-authorship/src/basic_authorship.rs | 24 +- core/offchain/Cargo.toml | 3 +- core/offchain/src/api.rs | 6 +- core/offchain/src/lib.rs | 7 +- core/rpc/Cargo.toml | 3 +- core/rpc/api/Cargo.toml | 2 +- core/rpc/api/src/author/error.rs | 4 +- core/rpc/api/src/author/mod.rs | 8 +- core/rpc/src/author/mod.rs | 52 ++-- core/rpc/src/author/tests.rs | 18 +- core/service/Cargo.toml | 3 +- core/service/src/builder.rs | 8 +- core/service/src/config.rs | 4 +- core/service/src/lib.rs | 24 +- core/service/test/Cargo.toml | 2 +- core/service/test/src/lib.rs | 2 +- core/transaction-pool/Cargo.toml | 1 + core/transaction-pool/api/Cargo.toml | 13 + .../{graph => api}/src/error.rs | 0 core/transaction-pool/api/src/lib.rs | 277 ++++++++++++++++++ core/transaction-pool/graph/Cargo.toml | 1 + core/transaction-pool/graph/src/base_pool.rs | 64 ++-- core/transaction-pool/graph/src/lib.rs | 4 +- core/transaction-pool/graph/src/pool.rs | 41 +-- core/transaction-pool/graph/src/ready.rs | 2 +- .../graph/src/validated_pool.rs | 8 +- core/transaction-pool/graph/src/watcher.rs | 45 +-- core/transaction-pool/src/error.rs | 7 +- core/transaction-pool/src/lib.rs | 219 +++----------- core/transaction-pool/src/maintainer.rs | 147 +++++----- node-template/Cargo.toml | 3 +- node-template/src/service.rs | 17 +- node/cli/Cargo.toml | 3 +- node/cli/src/service.rs | 40 ++- node/rpc/Cargo.toml | 2 +- node/rpc/src/lib.rs | 6 +- srml/system/rpc/Cargo.toml | 3 +- srml/system/rpc/src/lib.rs | 17 +- 41 files changed, 647 insertions(+), 474 deletions(-) create mode 100644 core/transaction-pool/api/Cargo.toml rename core/transaction-pool/{graph => api}/src/error.rs (100%) create mode 100644 core/transaction-pool/api/src/lib.rs diff --git a/Cargo.lock b/Cargo.lock index e88795a3f942e..beb871d2e0add 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2392,6 +2392,7 @@ dependencies = [ "substrate-service-test 2.0.0", "substrate-telemetry 2.0.0", "substrate-transaction-pool 2.0.0", + "substrate-transaction-pool-api 2.0.0", "tempfile 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "tokio 0.1.22 (registry+https://github.com/rust-lang/crates.io-index)", "transaction-factory 0.0.1", @@ -2446,7 +2447,7 @@ dependencies = [ "srml-contracts-rpc 2.0.0", "srml-system-rpc 2.0.0", "substrate-client 2.0.0", - "substrate-transaction-pool 2.0.0", + "substrate-transaction-pool-api 2.0.0", ] [[package]] @@ -2540,6 +2541,7 @@ dependencies = [ "substrate-primitives 2.0.0", "substrate-service 2.0.0", "substrate-transaction-pool 2.0.0", + "substrate-transaction-pool-api 2.0.0", "tokio 0.1.22 (registry+https://github.com/rust-lang/crates.io-index)", "trie-root 0.15.2 (registry+https://github.com/rust-lang/crates.io-index)", "vergen 3.0.4 (registry+https://github.com/rust-lang/crates.io-index)", @@ -4516,6 +4518,7 @@ dependencies = [ "substrate-primitives 2.0.0", "substrate-test-runtime-client 2.0.0", "substrate-transaction-pool 2.0.0", + "substrate-transaction-pool-api 2.0.0", ] [[package]] @@ -4753,6 +4756,7 @@ dependencies = [ "substrate-telemetry 2.0.0", "substrate-test-runtime-client 2.0.0", "substrate-transaction-pool 2.0.0", + "substrate-transaction-pool-api 2.0.0", ] [[package]] @@ -5307,6 +5311,7 @@ dependencies = [ "substrate-primitives 2.0.0", "substrate-test-runtime-client 2.0.0", "substrate-transaction-pool 2.0.0", + "substrate-transaction-pool-api 2.0.0", "threadpool 1.7.1 (registry+https://github.com/rust-lang/crates.io-index)", "tokio 0.1.22 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -5429,6 +5434,7 @@ dependencies = [ "substrate-state-machine 2.0.0", "substrate-test-runtime-client 2.0.0", "substrate-transaction-pool 2.0.0", + "substrate-transaction-pool-api 2.0.0", "tokio 0.1.22 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -5450,7 +5456,7 @@ dependencies = [ "sr-version 2.0.0", "substrate-primitives 2.0.0", "substrate-rpc-primitives 2.0.0", - "substrate-transaction-graph 2.0.0", + "substrate-transaction-pool-api 2.0.0", ] [[package]] @@ -5537,6 +5543,7 @@ dependencies = [ "substrate-telemetry 2.0.0", "substrate-test-runtime-client 2.0.0", "substrate-transaction-pool 2.0.0", + "substrate-transaction-pool-api 2.0.0", "sysinfo 0.9.5 (registry+https://github.com/rust-lang/crates.io-index)", "target_info 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-executor 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", @@ -5558,7 +5565,7 @@ dependencies = [ "substrate-network 2.0.0", "substrate-primitives 2.0.0", "substrate-service 2.0.0", - "substrate-transaction-pool 2.0.0", + "substrate-transaction-pool-api 2.0.0", "tempdir 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", "tokio 0.1.22 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -5704,6 +5711,7 @@ dependencies = [ "sr-primitives 2.0.0", "substrate-primitives 2.0.0", "substrate-test-runtime 2.0.0", + "substrate-transaction-pool-api 2.0.0", ] [[package]] @@ -5721,6 +5729,19 @@ dependencies = [ "substrate-primitives 2.0.0", "substrate-test-runtime-client 2.0.0", "substrate-transaction-graph 2.0.0", + "substrate-transaction-pool-api 2.0.0", +] + +[[package]] +name = "substrate-transaction-pool-api" +version = "2.0.0" +dependencies = [ + "derive_more 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-scale-codec 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", + "sr-primitives 2.0.0", + "substrate-primitives 2.0.0", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index 8d3d04c4d0595..7beadf6da4786 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -66,6 +66,7 @@ members = [ "core/test-runtime", "core/test-runtime/client", "core/transaction-pool", + "core/transaction-pool/api", "core/transaction-pool/graph", "core/trie", "core/utils/fork-tree", diff --git a/core/basic-authorship/Cargo.toml b/core/basic-authorship/Cargo.toml index 0a98c151d6eaf..67ceed226b9dd 100644 --- a/core/basic-authorship/Cargo.toml +++ b/core/basic-authorship/Cargo.toml @@ -14,7 +14,8 @@ client = { package = "substrate-client", path = "../../core/client" } consensus_common = { package = "substrate-consensus-common", path = "../../core/consensus/common" } inherents = { package = "substrate-inherents", path = "../inherents" } substrate-telemetry = { path = "../telemetry" } -transaction_pool = { package = "substrate-transaction-pool", path = "../../core/transaction-pool" } +txpoolapi = { package = "substrate-transaction-pool-api", path = "../../core/transaction-pool/api" } [dev-dependencies] test-client = { package = "substrate-test-runtime-client", path = "../../core/test-runtime/client" } +txpool = { package = "substrate-transaction-pool", path = "../../core/transaction-pool" } diff --git a/core/basic-authorship/src/basic_authorship.rs b/core/basic-authorship/src/basic_authorship.rs index a9cf6b441ca15..bdfdb78083b43 100644 --- a/core/basic-authorship/src/basic_authorship.rs +++ b/core/basic-authorship/src/basic_authorship.rs @@ -35,7 +35,7 @@ use sr_primitives::{ }, generic::BlockId, }; -use transaction_pool::TransactionPool; +use txpoolapi::{TransactionPool, InPoolTransaction}; use substrate_telemetry::{telemetry, CONSENSUS_INFO}; /// Proposer factory. @@ -160,21 +160,23 @@ impl Proposer, A> wh let pending_iterator = self.transaction_pool.ready(); debug!("Attempting to push transactions from the pool."); - for pending in pending_iterator { + for pending_tx in pending_iterator { if (self.now)() > deadline { debug!("Consensus deadline reached when pushing block transactions, proceeding with proposing."); break; } - trace!("[{:?}] Pushing to the block.", pending.hash); - match client::block_builder::BlockBuilder::push(&mut block_builder, pending.data.clone()) { + let pending_tx_data = pending_tx.data().clone(); + let pending_tx_hash = pending_tx.hash().clone(); + trace!("[{:?}] Pushing to the block.", pending_tx_hash); + match client::block_builder::BlockBuilder::push(&mut block_builder, pending_tx_data) { Ok(()) => { - debug!("[{:?}] Pushed to the block.", pending.hash); + debug!("[{:?}] Pushed to the block.", pending_tx_hash); } Err(error::Error::ApplyExtrinsicFailed(e)) if e.exhausted_resources() => { if is_first { - debug!("[{:?}] Invalid transaction: FullBlock on empty block", pending.hash); - unqueue_invalid.push(pending.hash.clone()); + debug!("[{:?}] Invalid transaction: FullBlock on empty block", pending_tx_hash); + unqueue_invalid.push(pending_tx_hash); } else if skipped < MAX_SKIPPED_TRANSACTIONS { skipped += 1; debug!( @@ -187,8 +189,8 @@ impl Proposer, A> wh } } Err(e) => { - debug!("[{:?}] Invalid transaction: {}", pending.hash, e); - unqueue_invalid.push(pending.hash.clone()); + debug!("[{:?}] Invalid transaction: {}", pending_tx_hash, e); + unqueue_invalid.push(pending_tx_hash); } } @@ -233,7 +235,7 @@ mod tests { use std::cell::RefCell; use consensus_common::{Environment, Proposer}; use test_client::{self, runtime::{Extrinsic, Transfer}, AccountKeyring}; - use transaction_pool::BasicTransactionPool; + use txpool::{BasicPool, FullChainApi}; fn extrinsic(nonce: u64) -> Extrinsic { Transfer { @@ -248,7 +250,7 @@ mod tests { fn should_cease_building_block_when_deadline_is_reached() { // given let client = Arc::new(test_client::new()); - let txpool = Arc::new(BasicTransactionPool::default_full(Default::default(), client.clone())); + let txpool = Arc::new(BasicPool::new(Default::default(), FullChainApi::new(client.clone()))); futures::executor::block_on( txpool.submit_at(&BlockId::number(0), vec![extrinsic(0), extrinsic(1)]) diff --git a/core/offchain/Cargo.toml b/core/offchain/Cargo.toml index 678d943c597ce..e1510c1688eac 100644 --- a/core/offchain/Cargo.toml +++ b/core/offchain/Cargo.toml @@ -24,7 +24,7 @@ parking_lot = "0.9.0" primitives = { package = "substrate-primitives", path = "../../core/primitives" } rand = "0.7.2" sr-primitives = { path = "../../core/sr-primitives" } -transaction_pool = { package = "substrate-transaction-pool", path = "../../core/transaction-pool" } +txpoolapi = { package = "substrate-transaction-pool-api", path = "../../core/transaction-pool/api" } network = { package = "substrate-network", path = "../../core/network" } keystore = { package = "substrate-keystore", path = "../keystore" } @@ -33,6 +33,7 @@ env_logger = "0.7.0" client-db = { package = "substrate-client-db", path = "../../core/client/db/", default-features = true } test-client = { package = "substrate-test-runtime-client", path = "../../core/test-runtime/client" } tokio = "0.1.22" +txpool = { package = "substrate-transaction-pool", path = "../../core/transaction-pool" } [features] default = [] diff --git a/core/offchain/src/api.rs b/core/offchain/src/api.rs index 484af832d227f..8635c40a2cf17 100644 --- a/core/offchain/src/api.rs +++ b/core/offchain/src/api.rs @@ -31,7 +31,7 @@ use primitives::offchain::{ OpaqueNetworkState, OpaquePeerId, OpaqueMultiaddr, StorageKind, }; use sr_primitives::{generic::BlockId, traits::{self, Extrinsic}}; -use transaction_pool::TransactionPool; +use txpoolapi::TransactionPool; mod http; mod timestamp; @@ -335,7 +335,7 @@ mod tests { use client_db::offchain::LocalStorage; use network::PeerId; use test_client::runtime::Block; - use transaction_pool::BasicTransactionPool; + use txpool::{BasicPool, FullChainApi}; struct MockNetworkStateInfo(); @@ -353,7 +353,7 @@ mod tests { let _ = env_logger::try_init(); let db = LocalStorage::new_test(); let client = Arc::new(test_client::new()); - let pool = Arc::new(BasicTransactionPool::default_full(Default::default(), client.clone())); + let pool = Arc::new(BasicPool::new(Default::default(), FullChainApi::new(client.clone()))); let mock = Arc::new(MockNetworkStateInfo()); AsyncApi::new( diff --git a/core/offchain/src/lib.rs b/core/offchain/src/lib.rs index af33735314ec7..000b4093e7256 100644 --- a/core/offchain/src/lib.rs +++ b/core/offchain/src/lib.rs @@ -47,7 +47,7 @@ use log::{debug, warn}; use network::NetworkStateInfo; use primitives::{offchain, ExecutionContext}; use sr_primitives::{generic::BlockId, traits::{self, ProvideRuntimeApi}}; -use transaction_pool::TransactionPool; +use txpoolapi::TransactionPool; mod api; @@ -156,7 +156,8 @@ impl OffchainWorkers< mod tests { use super::*; use network::{Multiaddr, PeerId}; - use transaction_pool::BasicTransactionPool; + use txpool::{BasicPool, FullChainApi}; + use txpoolapi::InPoolTransaction; struct MockNetworkStateInfo(); @@ -175,7 +176,7 @@ mod tests { // given let _ = env_logger::try_init(); let client = Arc::new(test_client::new()); - let pool = Arc::new(BasicTransactionPool::default_full(Default::default(), client.clone())); + let pool = Arc::new(BasicPool::new(Default::default(), FullChainApi::new(client.clone()))); let db = client_db::offchain::LocalStorage::new_test(); let network_state = Arc::new(MockNetworkStateInfo()); diff --git a/core/rpc/Cargo.toml b/core/rpc/Cargo.toml index 85998feb1b887..c22beb929543c 100644 --- a/core/rpc/Cargo.toml +++ b/core/rpc/Cargo.toml @@ -21,7 +21,7 @@ rpc-primitives = { package = "substrate-rpc-primitives", path = "primitives" } state_machine = { package = "substrate-state-machine", path = "../state-machine" } substrate-executor = { path = "../executor" } substrate-keystore = { path = "../keystore" } -transaction_pool = { package = "substrate-transaction-pool", path = "../transaction-pool" } +txpoolapi = { package = "substrate-transaction-pool-api", path = "../transaction-pool/api" } hash-db = { version = "0.15.2", default-features = false } parking_lot = { version = "0.9.0" } @@ -33,3 +33,4 @@ rustc-hex = "2.0.1" sr-io = { path = "../sr-io" } test-client = { package = "substrate-test-runtime-client", path = "../test-runtime/client" } tokio = "0.1.22" +txpool = { package = "substrate-transaction-pool", path = "../transaction-pool" } diff --git a/core/rpc/api/Cargo.toml b/core/rpc/api/Cargo.toml index bccafc2a85dd7..8f0db0aad27f1 100644 --- a/core/rpc/api/Cargo.toml +++ b/core/rpc/api/Cargo.toml @@ -18,5 +18,5 @@ primitives = { package = "substrate-primitives", path = "../../primitives" } runtime_version = { package = "sr-version", path = "../../sr-version" } serde = { version = "1.0.101", features = ["derive"] } serde_json = "1.0.41" -txpool = { package = "substrate-transaction-graph", path = "../../transaction-pool/graph" } +txpoolapi = { package = "substrate-transaction-pool-api", path = "../../transaction-pool/api" } rpc-primitives = { package = "substrate-rpc-primitives", path = "../../rpc/primitives" } diff --git a/core/rpc/api/src/author/error.rs b/core/rpc/api/src/author/error.rs index 8e4f8877682b3..b7f526fbff689 100644 --- a/core/rpc/api/src/author/error.rs +++ b/core/rpc/api/src/author/error.rs @@ -33,7 +33,7 @@ pub enum Error { Client(Box), /// Transaction pool error, #[display(fmt="Transaction pool error: {}", _0)] - Pool(txpool::error::Error), + Pool(txpoolapi::error::Error), /// Verification error #[display(fmt="Extrinsic verification error: {}", _0)] Verification(Box), @@ -91,7 +91,7 @@ const UNSUPPORTED_KEY_TYPE: i64 = POOL_INVALID_TX + 7; impl From for rpc::Error { fn from(e: Error) -> Self { - use txpool::error::{Error as PoolError}; + use txpoolapi::error::{Error as PoolError}; match e { Error::BadFormat(e) => rpc::Error { diff --git a/core/rpc/api/src/author/mod.rs b/core/rpc/api/src/author/mod.rs index 4ea96cb3c6122..09b227f2bedb6 100644 --- a/core/rpc/api/src/author/mod.rs +++ b/core/rpc/api/src/author/mod.rs @@ -21,11 +21,9 @@ pub mod hash; use jsonrpc_derive::rpc; use jsonrpc_pubsub::{typed::Subscriber, SubscriptionId}; -use primitives::{ - Bytes -}; +use primitives::Bytes; +use txpoolapi::TransactionStatus; use self::error::{FutureResult, Result}; -use txpool::watcher::Status; pub use self::gen_client::Client as AuthorClient; @@ -69,7 +67,7 @@ pub trait AuthorApi { )] fn watch_extrinsic(&self, metadata: Self::Metadata, - subscriber: Subscriber>, + subscriber: Subscriber>, bytes: Bytes ); diff --git a/core/rpc/src/author/mod.rs b/core/rpc/src/author/mod.rs index eec0f472274db..c90ae955e4b82 100644 --- a/core/rpc/src/author/mod.rs +++ b/core/rpc/src/author/mod.rs @@ -34,14 +34,9 @@ use jsonrpc_pubsub::{typed::Subscriber, SubscriptionId}; use codec::{Encode, Decode}; use primitives::{Bytes, Blake2Hasher, H256, traits::BareCryptoStorePtr}; use sr_primitives::{generic, traits::{self, ProvideRuntimeApi}}; -use transaction_pool::{ - TransactionPool, - BlockHash, - ExHash, - txpool::{ - IntoPoolError, - watcher::Status, - }, +use txpoolapi::{ + TransactionPool, InPoolTransaction, TransactionStatus, + BlockHash, TxHash, TransactionFor, IntoPoolError, }; use session::SessionKeys; @@ -50,9 +45,9 @@ pub use api::author::*; use self::error::{Error, FutureResult, Result}; /// Authoring API -pub struct Author where P: TransactionPool + Sync + Send + 'static { +pub struct Author { /// Substrate client - client: Arc::Block, RA>>, + client: Arc>, /// Transactions pool pool: Arc

, /// Subscriptions manager @@ -61,10 +56,10 @@ pub struct Author where P: TransactionPool + Sync + Send + 'static keystore: BareCryptoStorePtr, } -impl Author where P: TransactionPool + Sync + Send + 'static { +impl Author { /// Create new instance of Authoring API. pub fn new( - client: Arc::Block, RA>>, + client: Arc>, pool: Arc

, subscriptions: Subscriptions, keystore: BareCryptoStorePtr, @@ -78,15 +73,15 @@ impl Author where P: TransactionPool + Sync + Send + ' } } -impl AuthorApi, BlockHash

> for Author where - B: client::backend::Backend<

::Block, Blake2Hasher> + Send + Sync + 'static, - E: client::CallExecutor<

::Block, Blake2Hasher> + Send + Sync + 'static, - P: TransactionPool + Sync + Send + 'static, - P::Block: traits::Block, +impl AuthorApi for Author where + Block: traits::Block, + B: client::backend::Backend + Send + Sync + 'static, + E: client::CallExecutor + Send + Sync + 'static, + P: TransactionPool + Sync + Send + 'static, P::Error: 'static, RA: Send + Sync + 'static, - Client: ProvideRuntimeApi, - as ProvideRuntimeApi>::Api: SessionKeys, + Client: ProvideRuntimeApi, + as ProvideRuntimeApi>::Api: SessionKeys, { type Metadata = crate::metadata::Metadata; @@ -111,7 +106,7 @@ impl AuthorApi, BlockHash

> for Author whe ).map(Into::into).map_err(|e| Error::Client(Box::new(e))) } - fn submit_extrinsic(&self, ext: Bytes) -> FutureResult> { + fn submit_extrinsic(&self, ext: Bytes) -> FutureResult> { let xt = match Decode::decode(&mut &ext[..]) { Ok(xt) => xt, Err(err) => return Box::new(result(Err(err.into()))), @@ -127,12 +122,12 @@ impl AuthorApi, BlockHash

> for Author whe } fn pending_extrinsics(&self) -> Result> { - Ok(self.pool.ready().map(|tx| tx.data.encode().into()).collect()) + Ok(self.pool.ready().map(|tx| tx.data().encode().into()).collect()) } fn remove_extrinsic(&self, - bytes_or_hash: Vec>> - ) -> Result>> { + bytes_or_hash: Vec>> + ) -> Result>> { let hashes = bytes_or_hash.into_iter() .map(|x| match x { hash::ExtrinsicOrHash::Hash(h) => Ok(h), @@ -144,21 +139,22 @@ impl AuthorApi, BlockHash

> for Author whe .collect::>>()?; Ok( - self.pool.remove_invalid(&hashes) + self.pool + .remove_invalid(&hashes) .into_iter() - .map(|tx| tx.hash.clone()) + .map(|tx| tx.hash().clone()) .collect() ) } fn watch_extrinsic(&self, _metadata: Self::Metadata, - subscriber: Subscriber, BlockHash

>>, + subscriber: Subscriber, BlockHash

>>, xt: Bytes ) { let submit = || -> Result<_> { let best_block_hash = self.client.info().chain.best_hash; - let dxt = <

::Block as traits::Block>::Extrinsic::decode(&mut &xt[..]) + let dxt = TransactionFor::

::decode(&mut &xt[..]) .map_err(error::Error::from)?; Ok( self.pool @@ -174,7 +170,7 @@ impl AuthorApi, BlockHash

> for Author whe let future = ready(submit()) .and_then(|res| res) // convert the watcher into a `Stream` - .map(|res| res.map(|watcher| watcher.into_stream().map(|v| Ok::<_, ()>(Ok(v))))) + .map(|res| res.map(|stream| stream.map(|v| Ok::<_, ()>(Ok(v))))) // now handle the import result, // start a new subscrition .map(move |result| match result { diff --git a/core/rpc/src/author/tests.rs b/core/rpc/src/author/tests.rs index d48fb9b4ceb02..14aa03a643ca6 100644 --- a/core/rpc/src/author/tests.rs +++ b/core/rpc/src/author/tests.rs @@ -25,10 +25,10 @@ use primitives::{ }; use rpc::futures::Stream as _; use test_client::{ - self, AccountKeyring, runtime::{Extrinsic, Transfer, SessionKeys, RuntimeApi, Block}, DefaultTestClientBuilderExt, - TestClientBuilderExt, Backend, Client, Executor, NativeExecutor, + self, AccountKeyring, runtime::{Extrinsic, Transfer, SessionKeys, RuntimeApi, Block}, + DefaultTestClientBuilderExt, TestClientBuilderExt, Backend, Client, Executor, }; -use transaction_pool::{BasicTransactionPool, FullChainApi, DefaultFullTransactionPoolMaintainer}; +use txpool::{BasicPool, FullChainApi}; use tokio::runtime; fn uxt(sender: AccountKeyring, nonce: u64) -> Extrinsic { @@ -41,14 +41,8 @@ fn uxt(sender: AccountKeyring, nonce: u64) -> Extrinsic { tx.into_signed_tx() } -type FullTransactionPool = BasicTransactionPool< +type FullTransactionPool = BasicPool< FullChainApi, Block>, - DefaultFullTransactionPoolMaintainer< - Backend, - test_client::client::LocalCallExecutor>, - Block, - RuntimeApi, - >, Block, >; @@ -63,7 +57,7 @@ impl Default for TestSetup { fn default() -> Self { let keystore = KeyStore::new(); let client = Arc::new(test_client::TestClientBuilder::new().set_keystore(keystore.clone()).build()); - let pool = Arc::new(BasicTransactionPool::default_full(Default::default(), client.clone())); + let pool = Arc::new(BasicPool::new(Default::default(), FullChainApi::new(client.clone()))); TestSetup { runtime: runtime::Runtime::new().expect("Failed to create runtime in test setup"), client, @@ -74,7 +68,7 @@ impl Default for TestSetup { } impl TestSetup { - fn author(&self) -> Author { + fn author(&self) -> Author { Author { client: self.client.clone(), pool: self.pool.clone(), diff --git a/core/service/Cargo.toml b/core/service/Cargo.toml index 5f5f1322332db..6f0a659877120 100644 --- a/core/service/Cargo.toml +++ b/core/service/Cargo.toml @@ -33,7 +33,8 @@ client_db = { package = "substrate-client-db", path = "../../core/client/db", fe codec = { package = "parity-scale-codec", version = "1.0.0" } substrate-executor = { path = "../../core/executor" } substrate-authority-discovery = { path = "../../core/authority-discovery"} -transaction_pool = { package = "substrate-transaction-pool", path = "../../core/transaction-pool" } +txpool = { package = "substrate-transaction-pool", path = "../../core/transaction-pool" } +txpoolapi = { package = "substrate-transaction-pool-api", path = "../../core/transaction-pool/api" } rpc-servers = { package = "substrate-rpc-servers", path = "../../core/rpc-servers" } rpc = { package = "substrate-rpc", path = "../../core/rpc" } tel = { package = "substrate-telemetry", path = "../../core/telemetry" } diff --git a/core/service/src/builder.rs b/core/service/src/builder.rs index 174a79b3fba4f..dafef472e9384 100644 --- a/core/service/src/builder.rs +++ b/core/service/src/builder.rs @@ -48,7 +48,7 @@ use substrate_executor::{NativeExecutor, NativeExecutionDispatch}; use std::{io::{Read, Write, Seek}, marker::PhantomData, sync::Arc, sync::atomic::AtomicBool}; use sysinfo::{get_current_pid, ProcessExt, System, SystemExt}; use tel::{telemetry, SUBSTRATE_INFO}; -use transaction_pool::TransactionPool; +use txpoolapi::{TransactionPool, TransactionPoolMaintainer}; /// Aggregator for the components required to build a service. /// @@ -546,7 +546,7 @@ impl( self, transaction_pool_builder: impl FnOnce( - transaction_pool::txpool::Options, + txpool::txpool::Options, Arc, Option, ) -> Result @@ -870,7 +870,9 @@ ServiceBuilder< TSc: Clone, TImpQu: 'static + ImportQueue, TNetP: NetworkSpecialization, - TExPool: 'static + TransactionPool::Hash>, + TExPool: 'static + + TransactionPool::Hash> + + TransactionPoolMaintainer::Hash>, TRpc: rpc::RpcExtension + Clone, TRpcB: RpcBuilder, { diff --git a/core/service/src/config.rs b/core/service/src/config.rs index a1ba83753f402..2837bad2f802a 100644 --- a/core/service/src/config.rs +++ b/core/service/src/config.rs @@ -22,7 +22,7 @@ pub use network::config::{ExtTransport, NetworkConfiguration, Roles}; pub use substrate_executor::WasmExecutionMethod; use std::{path::PathBuf, net::SocketAddr}; -use transaction_pool; +pub use txpool::txpool::Options as TransactionPoolOptions; use chain_spec::{ChainSpec, RuntimeGenesis, Extension, NoExtension}; use primitives::crypto::Protected; use target_info::Target; @@ -40,7 +40,7 @@ pub struct Configuration { /// Node roles. pub roles: Roles, /// Extrinsic pool configuration. - pub transaction_pool: transaction_pool::txpool::Options, + pub transaction_pool: TransactionPoolOptions, /// Network configuration. pub network: NetworkConfiguration, /// Path to key files. diff --git a/core/service/src/lib.rs b/core/service/src/lib.rs index 787192e0fb799..dbf4d64841cc5 100644 --- a/core/service/src/lib.rs +++ b/core/service/src/lib.rs @@ -56,10 +56,8 @@ pub use self::builder::{ }; pub use config::{Configuration, Roles, PruningMode}; pub use chain_spec::{ChainSpec, Properties, RuntimeGenesis, Extension as ChainSpecExtension}; -pub use transaction_pool::TransactionPool; -pub use transaction_pool::txpool::{ - self, Options as TransactionPoolOptions, IntoPoolError -}; +pub use txpoolapi::{TransactionPool, TransactionPoolMaintainer, InPoolTransaction, IntoPoolError}; +pub use txpool::txpool::Options as TransactionPoolOptions; pub use client::FinalityNotifications; pub use rpc::Metadata as RpcMetadata; #[doc(hidden)] @@ -463,7 +461,7 @@ pub trait AbstractService: 'static + Future + /// Chain selection algorithm. type SelectChain: consensus_common::SelectChain; /// Transaction pool. - type TransactionPool: TransactionPool; + type TransactionPool: TransactionPool + TransactionPoolMaintainer; /// Network specialization. type NetworkSpecialization: NetworkSpecialization; @@ -526,7 +524,7 @@ where TExec: 'static + client::CallExecutor + Send + Sync + Clone, TRtApi: 'static + Send + Sync, TSc: consensus_common::SelectChain + 'static + Clone + Send, - TExPool: 'static + TransactionPool, + TExPool: 'static + TransactionPool + TransactionPoolMaintainer, TOc: 'static + Send + Sync, TNetSpec: NetworkSpecialization, { @@ -909,13 +907,13 @@ where Pool: TransactionPool, B: BlockT, H: std::hash::Hash + Eq + sr_primitives::traits::Member + sr_primitives::traits::MaybeSerialize, - E: txpool::error::IntoPoolError + From, + E: IntoPoolError + From, { pool.ready() .filter(|t| t.is_propagateable()) .map(|t| { - let hash = t.hash.clone(); - let ex: B::Extrinsic = t.data.clone(); + let hash = t.hash().clone(); + let ex: B::Extrinsic = t.data().clone(); (hash, ex) }) .collect() @@ -928,7 +926,7 @@ where Pool: 'static + TransactionPool, B: BlockT, H: std::hash::Hash + Eq + sr_primitives::traits::Member + sr_primitives::traits::MaybeSerialize, - E: 'static + txpool::error::IntoPoolError + From, + E: 'static + IntoPoolError + From, { fn transactions(&self) -> Vec<(H, ::Extrinsic)> { transactions_to_propagate(&*self.pool) @@ -954,7 +952,7 @@ where match import_result { Ok(_) => report_handle.report_peer(who, reputation_change), Err(e) => match e.into_pool_error() { - Ok(txpool::error::Error::AlreadyImported(_)) => (), + Ok(txpoolapi::error::Error::AlreadyImported(_)) => (), Ok(e) => debug!("Error adding transaction to the pool: {:?}", e), Err(e) => debug!("Error converting pool error: {:?}", e), } @@ -983,14 +981,14 @@ mod tests { use consensus_common::SelectChain; use sr_primitives::traits::BlindCheckable; use substrate_test_runtime_client::{prelude::*, runtime::{Extrinsic, Transfer}}; - use transaction_pool::BasicTransactionPool; + use txpool::{BasicPool, FullChainApi}; #[test] fn should_not_propagate_transactions_that_are_marked_as_such() { // given let (client, longest_chain) = TestClientBuilder::new().build_with_longest_chain(); let client = Arc::new(client); - let pool = Arc::new(BasicTransactionPool::default_full(Default::default(), client.clone())); + let pool = Arc::new(BasicPool::new(Default::default(), FullChainApi::new(client.clone()))); let best = longest_chain.best_chain().unwrap(); let transaction = Transfer { amount: 5, diff --git a/core/service/test/Cargo.toml b/core/service/test/Cargo.toml index 96abf389bb4fc..968291add4a54 100644 --- a/core/service/test/Cargo.toml +++ b/core/service/test/Cargo.toml @@ -18,4 +18,4 @@ consensus = { package = "substrate-consensus-common", path = "../../../core/cons client = { package = "substrate-client", path = "../../../core/client" } sr-primitives = { path = "../../../core/sr-primitives" } primitives = { package = "substrate-primitives", path = "../../../core/primitives" } -transaction_pool = { package = "substrate-transaction-pool", path = "../../../core/transaction-pool" } +txpoolapi = { package = "substrate-transaction-pool-api", path = "../../../core/transaction-pool/api" } diff --git a/core/service/test/src/lib.rs b/core/service/test/src/lib.rs index f3ef45da045d5..dfb05a0f49c88 100644 --- a/core/service/test/src/lib.rs +++ b/core/service/test/src/lib.rs @@ -35,7 +35,7 @@ use service::{ use network::{multiaddr, Multiaddr}; use network::config::{NetworkConfiguration, TransportConfig, NodeKeyConfig, Secret, NonReservedPeerMode}; use sr_primitives::{generic::BlockId, traits::Block as BlockT}; -use transaction_pool::TransactionPool; +use txpoolapi::TransactionPool; /// Maximum duration of single wait call. const MAX_WAIT_TIME: Duration = Duration::from_secs(60 * 3); diff --git a/core/transaction-pool/Cargo.toml b/core/transaction-pool/Cargo.toml index 33ec9e9ece176..8344f0e3c45ac 100644 --- a/core/transaction-pool/Cargo.toml +++ b/core/transaction-pool/Cargo.toml @@ -14,6 +14,7 @@ sr-primitives = { path = "../sr-primitives" } client = { package = "substrate-client", path = "../client" } primitives = { package = "substrate-primitives", path = "../primitives" } txpool = { package = "substrate-transaction-graph", path = "./graph" } +txpoolapi = { package = "substrate-transaction-pool-api", path = "api" } [dev-dependencies] keyring = { package = "substrate-keyring", path = "../../core/keyring" } diff --git a/core/transaction-pool/api/Cargo.toml b/core/transaction-pool/api/Cargo.toml new file mode 100644 index 0000000000000..1d5eb9e983b50 --- /dev/null +++ b/core/transaction-pool/api/Cargo.toml @@ -0,0 +1,13 @@ +[package] +name = "substrate-transaction-pool-api" +version = "2.0.0" +authors = ["Parity Technologies "] +edition = "2018" + +[dependencies] +derive_more = "0.15.0" +futures-preview = "0.3.0-alpha.19" +serde = { version = "1.0.101", features = ["derive"] } +codec = { package = "parity-scale-codec", version = "1.0.0" } +primitives = { package = "substrate-primitives", path = "../../primitives" } +sr-primitives = { path = "../../sr-primitives" } diff --git a/core/transaction-pool/graph/src/error.rs b/core/transaction-pool/api/src/error.rs similarity index 100% rename from core/transaction-pool/graph/src/error.rs rename to core/transaction-pool/api/src/error.rs diff --git a/core/transaction-pool/api/src/lib.rs b/core/transaction-pool/api/src/lib.rs new file mode 100644 index 0000000000000..b95c3340ddbdf --- /dev/null +++ b/core/transaction-pool/api/src/lib.rs @@ -0,0 +1,277 @@ +// Copyright 2019 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate 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. + +// Substrate 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 Substrate. If not, see . + +//! Transaction pool types. + +pub mod error; + +pub use error::IntoPoolError; +pub use sr_primitives::transaction_validity::{ + TransactionLongevity, TransactionPriority, TransactionTag, +}; + +use std::{ + collections::HashMap, + hash::Hash, + sync::Arc, +}; +use futures::{ + Future, Stream, + channel::mpsc, +}; +use serde::{Deserialize, Serialize}; + +use sr_primitives::{ + generic::BlockId, + traits::{Block as BlockT, Member}, +}; + +/// Transaction pool status. +#[derive(Debug)] +pub struct PoolStatus { + /// Number of transactions in the ready queue. + pub ready: usize, + /// Sum of bytes of ready transaction encodings. + pub ready_bytes: usize, + /// Number of transactions in the future queue. + pub future: usize, + /// Sum of bytes of ready transaction encodings. + pub future_bytes: usize, +} + +impl PoolStatus { + /// Returns true if the are no transactions in the pool. + pub fn is_empty(&self) -> bool { + self.ready == 0 && self.future == 0 + } +} + +/// Possible transaction status events. +#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub enum TransactionStatus { + /// Transaction is part of the future queue. + Future, + /// Transaction is part of the ready queue. + Ready, + /// Transaction has been finalized in block with given hash. + Finalized(BlockHash), + /// Some state change (perhaps another transaction was included) rendered this transaction invalid. + Usurped(Hash), + /// The transaction has been broadcast to the given peers. + Broadcast(Vec), + /// Transaction has been dropped from the pool because of the limit. + Dropped, + /// Transaction was detected as invalid. + Invalid, +} + +/// The stream of transaction events. +pub type TransactionStatusStream = dyn Stream> + Send + Unpin; + +/// The import notification event stream. +pub type ImportNotificationStream = mpsc::UnboundedReceiver<()>; + +/// Transaction hash type for a pool. +pub type TxHash

=

::Hash; +/// Block hash type for a pool. +pub type BlockHash

= <

::Block as BlockT>::Hash; +/// Transaction type for a pool. +pub type TransactionFor

= <

::Block as BlockT>::Extrinsic; +/// Type of transactions event stream for a pool. +pub type TransactionStatusStreamFor

= TransactionStatusStream, BlockHash

>; + +/// In-pool transaction interface. +/// +/// The pool is container of transactions that are implementing this trait. +/// See `sr_primitives::ValidTransaction` for details about every field. +pub trait InPoolTransaction { + /// Transaction type. + type Transaction; + /// Transaction hash type. + type Hash; + + /// Get the reference to the transaction data. + fn data(&self) -> &Self::Transaction; + /// Get hash of the transaction. + fn hash(&self) -> &Self::Hash; + /// Get priority of the transaction. + fn priority(&self) -> &TransactionPriority; + /// Get longevity of the transaction. + fn longevity(&self) ->&TransactionLongevity; + /// Get transaction dependencies. + fn requires(&self) -> &[TransactionTag]; + /// Get tags that transaction provides. + fn provides(&self) -> &[TransactionTag]; + /// Return a flag indicating if the transaction should be propagated to other peers. + fn is_propagateable(&self) -> bool; +} + +/// Transaction pool interface. +pub trait TransactionPool: Send + Sync { + /// Block type. + type Block: BlockT; + /// Transaction hash type. + type Hash: Hash + Eq + Member + Serialize; + /// In-pool transaction type. + type InPoolTransaction: InPoolTransaction, Hash = TxHash>; + /// Error type. + type Error: From + IntoPoolError; + + /// Returns a future that imports a bunch of unverified transactions to the pool. + fn submit_at( + &self, + at: &BlockId, + xts: impl IntoIterator> + 'static, + ) -> Box, Self::Error>>, Self::Error>> + Send + Unpin>; + + /// Returns a future that imports one unverified transaction to the pool. + fn submit_one( + &self, + at: &BlockId, + xt: TransactionFor, + ) -> Box, Self::Error>> + Send + Unpin>; + + /// Returns a future that import a single transaction and starts to watch their progress in the pool. + fn submit_and_watch( + &self, + at: &BlockId, + xt: TransactionFor, + ) -> Box>, Self::Error>> + Send + Unpin>; + + /// Remove transactions identified by given hashes (and dependent transactions) from the pool. + fn remove_invalid(&self, hashes: &[TxHash]) -> Vec>; + + /// Returns pool status. + fn status(&self) -> PoolStatus; + + /// Get an iterator for ready transactions ordered by priority + fn ready(&self) -> Box>>; + + /// Return an event stream of transactions imported to the pool. + fn import_notification_stream(&self) -> ImportNotificationStream; + + /// Returns transaction hash + fn hash_of(&self, xt: &TransactionFor) -> TxHash; + + /// Notify the pool about transactions broadcast. + fn on_broadcasted(&self, propagations: HashMap, Vec>); +} + +/// Transaction pool maintainer interface. +pub trait TransactionPoolMaintainer: Send + Sync { + /// Block type. + type Block: BlockT; + /// Transaction Hash type. + type Hash: Hash + Eq + Member + Serialize; + + /// Returns a future that performs maintenance procedures on the pool when + /// with given hash is imported. + fn maintain( + &self, + id: &BlockId, + retracted: &[Self::Hash], + ) -> Box + Send + Unpin>; +} + +/// Maintainable pool implementation. +pub struct MaintainableTransactionPool { + pool: Pool, + maintainer: Maintainer, +} + +impl MaintainableTransactionPool { + /// Create new maintainable pool using underlying pool and maintainer. + pub fn new(pool: Pool, maintainer: Maintainer) -> Self { + MaintainableTransactionPool { pool, maintainer } + } +} + +impl TransactionPool for MaintainableTransactionPool + where + Pool: TransactionPool, + Maintainer: Send + Sync, +{ + type Block = Pool::Block; + type Hash = Pool::Hash; + type InPoolTransaction = Pool::InPoolTransaction; + type Error = Pool::Error; + + fn submit_at( + &self, + at: &BlockId, + xts: impl IntoIterator> + 'static, + ) -> Box, Self::Error>>, Self::Error>> + Send + Unpin> { + self.pool.submit_at(at, xts) + } + + fn submit_one( + &self, + at: &BlockId, + xt: TransactionFor, + ) -> Box, Self::Error>> + Send + Unpin> { + self.pool.submit_one(at, xt) + } + + fn submit_and_watch( + &self, + at: &BlockId, + xt: TransactionFor, + ) -> Box>, Self::Error>> + Send + Unpin> { + self.pool.submit_and_watch(at, xt) + } + + fn remove_invalid(&self, hashes: &[TxHash]) -> Vec> { + self.pool.remove_invalid(hashes) + } + + fn status(&self) -> PoolStatus { + self.pool.status() + } + + fn ready(&self) -> Box>> { + self.pool.ready() + } + + fn import_notification_stream(&self) -> ImportNotificationStream { + self.pool.import_notification_stream() + } + + fn hash_of(&self, xt: &TransactionFor) -> TxHash { + self.pool.hash_of(xt) + } + + fn on_broadcasted(&self, propagations: HashMap, Vec>) { + self.pool.on_broadcasted(propagations) + } +} + +impl TransactionPoolMaintainer for MaintainableTransactionPool + where + Pool: Send + Sync, + Maintainer: TransactionPoolMaintainer +{ + type Block = Maintainer::Block; + type Hash = Maintainer::Hash; + + fn maintain( + &self, + id: &BlockId, + retracted: &[Self::Hash], + ) -> Box + Send + Unpin> { + self.maintainer.maintain(id, retracted) + } +} diff --git a/core/transaction-pool/graph/Cargo.toml b/core/transaction-pool/graph/Cargo.toml index fa0d6f14b6f32..22bbd197e8ffe 100644 --- a/core/transaction-pool/graph/Cargo.toml +++ b/core/transaction-pool/graph/Cargo.toml @@ -12,6 +12,7 @@ parking_lot = "0.9.0" serde = { version = "1.0.101", features = ["derive"] } primitives = { package = "substrate-primitives", path = "../../primitives" } sr-primitives = { path = "../../sr-primitives" } +txpoolapi = { package = "substrate-transaction-pool-api", path = "../api" } [dev-dependencies] assert_matches = "1.3.0" diff --git a/core/transaction-pool/graph/src/base_pool.rs b/core/transaction-pool/graph/src/base_pool.rs index 086f67ec29394..4b57ee7cabb35 100644 --- a/core/transaction-pool/graph/src/base_pool.rs +++ b/core/transaction-pool/graph/src/base_pool.rs @@ -34,8 +34,8 @@ use sr_primitives::transaction_validity::{ TransactionLongevity as Longevity, TransactionPriority as Priority, }; +use txpoolapi::{error, PoolStatus, InPoolTransaction}; -use crate::error; use crate::future::{FutureTransactions, WaitingTransaction}; use crate::ready::ReadyTransactions; @@ -104,9 +104,41 @@ pub struct Transaction { pub propagate: bool, } -impl Transaction { - /// Returns `true` if the transaction should be propagated to other peers. - pub fn is_propagateable(&self) -> bool { +impl AsRef for Transaction { + fn as_ref(&self) -> &Extrinsic { + &self.data + } +} + +impl InPoolTransaction for Transaction { + type Transaction = Extrinsic; + type Hash = Hash; + + fn data(&self) -> &Extrinsic { + &self.data + } + + fn hash(&self) -> &Hash { + &self.hash + } + + fn priority(&self) -> &Priority { + &self.priority + } + + fn longevity(&self) ->&Longevity { + &self.valid_till + } + + fn requires(&self) -> &[Tag] { + &self.requires + } + + fn provides(&self) -> &[Tag] { + &self.provides + } + + fn is_propagateable(&self) -> bool { self.propagate } } @@ -462,8 +494,8 @@ impl BasePool Status { - Status { + pub fn status(&self) -> PoolStatus { + PoolStatus { ready: self.ready.len(), ready_bytes: self.ready.bytes(), future: self.future.len(), @@ -472,26 +504,6 @@ impl BasePool bool { - self.ready == 0 && self.future == 0 - } -} - /// Queue limits #[derive(Debug, Clone)] pub struct Limit { diff --git a/core/transaction-pool/graph/src/lib.rs b/core/transaction-pool/graph/src/lib.rs index 715e60874be95..db92bef2728ec 100644 --- a/core/transaction-pool/graph/src/lib.rs +++ b/core/transaction-pool/graph/src/lib.rs @@ -32,11 +32,9 @@ mod rotator; mod validated_pool; pub mod base_pool; -pub mod error; pub mod watcher; -pub use self::error::IntoPoolError; -pub use self::base_pool::{Transaction, Status}; +pub use self::base_pool::Transaction; pub use self::pool::{ Pool, Options, ChainApi, EventStream, ExtrinsicFor, diff --git a/core/transaction-pool/graph/src/pool.rs b/core/transaction-pool/graph/src/pool.rs index cbfff6ef32736..206858b31bf7b 100644 --- a/core/transaction-pool/graph/src/pool.rs +++ b/core/transaction-pool/graph/src/pool.rs @@ -21,7 +21,6 @@ use std::{ }; use crate::base_pool as base; -use crate::error; use crate::watcher::Watcher; use serde::Serialize; @@ -35,6 +34,8 @@ use sr_primitives::{ traits::{self, SaturatedConversion}, transaction_validity::{TransactionValidity, TransactionTag as Tag, TransactionValidityError}, }; +use txpoolapi::{error, PoolStatus}; + use crate::validated_pool::{ValidatedPool, ValidatedTransaction}; /// Modification notification event stream type; @@ -328,7 +329,7 @@ impl Pool { } /// Returns pool status. - pub fn status(&self) -> base::Status { + pub fn status(&self) -> PoolStatus { self.validated_pool.status() } @@ -425,12 +426,12 @@ mod tests { use parking_lot::Mutex; use futures::executor::block_on; use super::*; + use txpoolapi::TransactionStatus; use sr_primitives::transaction_validity::{ValidTransaction, InvalidTransaction}; use codec::Encode; use test_runtime::{Block, Extrinsic, Transfer, H256, AccountId}; use assert_matches::assert_matches; use crate::base_pool::Limit; - use crate::watcher; const INVALID_NONCE: u64 = 254; @@ -765,8 +766,8 @@ mod tests { // then let mut stream = futures::executor::block_on_stream(watcher.into_stream()); - assert_eq!(stream.next(), Some(watcher::Status::Ready)); - assert_eq!(stream.next(), Some(watcher::Status::Finalized(H256::from_low_u64_be(2).into()))); + assert_eq!(stream.next(), Some(TransactionStatus::Ready)); + assert_eq!(stream.next(), Some(TransactionStatus::Finalized(H256::from_low_u64_be(2).into()))); assert_eq!(stream.next(), None); } @@ -790,8 +791,8 @@ mod tests { // then let mut stream = futures::executor::block_on_stream(watcher.into_stream()); - assert_eq!(stream.next(), Some(watcher::Status::Ready)); - assert_eq!(stream.next(), Some(watcher::Status::Finalized(H256::from_low_u64_be(2).into()))); + assert_eq!(stream.next(), Some(TransactionStatus::Ready)); + assert_eq!(stream.next(), Some(TransactionStatus::Finalized(H256::from_low_u64_be(2).into()))); assert_eq!(stream.next(), None); } @@ -819,8 +820,8 @@ mod tests { // then let mut stream = futures::executor::block_on_stream(watcher.into_stream()); - assert_eq!(stream.next(), Some(watcher::Status::Future)); - assert_eq!(stream.next(), Some(watcher::Status::Ready)); + assert_eq!(stream.next(), Some(TransactionStatus::Future)); + assert_eq!(stream.next(), Some(TransactionStatus::Ready)); } #[test] @@ -842,8 +843,8 @@ mod tests { // then let mut stream = futures::executor::block_on_stream(watcher.into_stream()); - assert_eq!(stream.next(), Some(watcher::Status::Ready)); - assert_eq!(stream.next(), Some(watcher::Status::Invalid)); + assert_eq!(stream.next(), Some(TransactionStatus::Ready)); + assert_eq!(stream.next(), Some(TransactionStatus::Invalid)); assert_eq!(stream.next(), None); } @@ -869,8 +870,8 @@ mod tests { // then let mut stream = futures::executor::block_on_stream(watcher.into_stream()); - assert_eq!(stream.next(), Some(watcher::Status::Ready)); - assert_eq!(stream.next(), Some(watcher::Status::Broadcast(peers))); + assert_eq!(stream.next(), Some(TransactionStatus::Ready)); + assert_eq!(stream.next(), Some(TransactionStatus::Broadcast(peers))); } #[test] @@ -907,8 +908,8 @@ mod tests { // then let mut stream = futures::executor::block_on_stream(watcher.into_stream()); - assert_eq!(stream.next(), Some(watcher::Status::Ready)); - assert_eq!(stream.next(), Some(watcher::Status::Dropped)); + assert_eq!(stream.next(), Some(TransactionStatus::Ready)); + assert_eq!(stream.next(), Some(TransactionStatus::Dropped)); } #[test] @@ -1014,7 +1015,7 @@ mod tests { assert_eq!(pool.status().ready, 2); assert_eq!( futures::executor::block_on_stream(watcher3.into_stream()).collect::>(), - vec![watcher::Status::Ready, watcher::Status::Invalid], + vec![TransactionStatus::Ready, TransactionStatus::Invalid], ); // when @@ -1026,19 +1027,19 @@ mod tests { // events for hash2 are: Ready, Invalid assert_eq!( futures::executor::block_on_stream(watcher0.into_stream()).collect::>(), - vec![watcher::Status::Ready, watcher::Status::Future, watcher::Status::Invalid], + vec![TransactionStatus::Ready, TransactionStatus::Future, TransactionStatus::Invalid], ); assert_eq!( futures::executor::block_on_stream(watcher1.into_stream()).collect::>(), - vec![watcher::Status::Ready, watcher::Status::Invalid], + vec![TransactionStatus::Ready, TransactionStatus::Invalid], ); assert_eq!( futures::executor::block_on_stream(watcher2.into_stream()).collect::>(), - vec![watcher::Status::Ready, watcher::Status::Invalid], + vec![TransactionStatus::Ready, TransactionStatus::Invalid], ); assert_eq!( futures::executor::block_on_stream(watcher4.into_stream()).collect::>(), - vec![watcher::Status::Ready, watcher::Status::Future, watcher::Status::Invalid], + vec![TransactionStatus::Ready, TransactionStatus::Future, TransactionStatus::Invalid], ); } } diff --git a/core/transaction-pool/graph/src/ready.rs b/core/transaction-pool/graph/src/ready.rs index 0006ad1884620..8227db80e49f0 100644 --- a/core/transaction-pool/graph/src/ready.rs +++ b/core/transaction-pool/graph/src/ready.rs @@ -28,8 +28,8 @@ use sr_primitives::traits::Member; use sr_primitives::transaction_validity::{ TransactionTag as Tag, }; +use txpoolapi::error; -use crate::error; use crate::future::WaitingTransaction; use crate::base_pool::Transaction; diff --git a/core/transaction-pool/graph/src/validated_pool.rs b/core/transaction-pool/graph/src/validated_pool.rs index 36fc4514c3e08..2e8911df756c8 100644 --- a/core/transaction-pool/graph/src/validated_pool.rs +++ b/core/transaction-pool/graph/src/validated_pool.rs @@ -22,7 +22,6 @@ use std::{ }; use crate::base_pool as base; -use crate::error; use crate::listener::Listener; use crate::rotator::PoolRotator; use crate::watcher::Watcher; @@ -36,6 +35,7 @@ use sr_primitives::{ traits::{self, SaturatedConversion}, transaction_validity::TransactionTag as Tag, }; +use txpoolapi::{error, PoolStatus}; use crate::base_pool::PruneStatus; use crate::pool::{EventStream, Options, ChainApi, BlockHash, ExHash, ExtrinsicFor, TransactionFor}; @@ -390,8 +390,8 @@ impl ValidatedPool { /// See `prune_tags` if you want this. pub fn clear_stale(&self, at: &BlockId) -> Result<(), B::Error> { let block_number = self.api.block_id_to_number(at)? - .ok_or_else(|| error::Error::InvalidBlockId(format!("{:?}", at)).into())? - .saturated_into::(); + .ok_or_else(|| error::Error::InvalidBlockId(format!("{:?}", at)).into())? + .saturated_into::(); let now = time::Instant::now(); let to_remove = { self.ready() @@ -466,7 +466,7 @@ impl ValidatedPool { } /// Returns pool status. - pub fn status(&self) -> base::Status { + pub fn status(&self) -> PoolStatus { self.pool.read().status() } } diff --git a/core/transaction-pool/graph/src/watcher.rs b/core/transaction-pool/graph/src/watcher.rs index 11d6b9f40742a..3e075abda5c29 100644 --- a/core/transaction-pool/graph/src/watcher.rs +++ b/core/transaction-pool/graph/src/watcher.rs @@ -20,34 +20,14 @@ use futures::{ Stream, channel::mpsc, }; -use serde::{Serialize, Deserialize}; - -/// Possible extrinsic status events -#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] -#[serde(rename_all = "camelCase")] -pub enum Status { - /// Extrinsic is part of the future queue. - Future, - /// Extrinsic is part of the ready queue. - Ready, - /// Extrinsic has been finalized in block with given hash. - Finalized(H2), - /// Some state change (perhaps another extrinsic was included) rendered this extrinsic invalid. - Usurped(H), - /// The extrinsic has been broadcast to the given peers. - Broadcast(Vec), - /// Extrinsic has been dropped from the pool because of the limit. - Dropped, - /// Extrinsic was detected as invalid. - Invalid, -} +use txpoolapi::TransactionStatus; /// Extrinsic watcher. /// /// Represents a stream of status updates for particular extrinsic. #[derive(Debug)] pub struct Watcher { - receiver: mpsc::UnboundedReceiver>, + receiver: mpsc::UnboundedReceiver>, hash: H, } @@ -60,7 +40,7 @@ impl Watcher { /// Pipe the notifications to given sink. /// /// Make sure to drive the future to completion. - pub fn into_stream(self) -> impl Stream> { + pub fn into_stream(self) -> impl Stream> { self.receiver } } @@ -68,7 +48,7 @@ impl Watcher { /// Sender part of the watcher. Exposed only for testing purposes. #[derive(Debug)] pub struct Sender { - receivers: Vec>>, + receivers: Vec>>, finalized: bool, } @@ -94,49 +74,48 @@ impl Sender { /// Transaction became ready. pub fn ready(&mut self) { - self.send(Status::Ready) + self.send(TransactionStatus::Ready) } /// Transaction was moved to future. pub fn future(&mut self) { - self.send(Status::Future) + self.send(TransactionStatus::Future) } /// Some state change (perhaps another extrinsic was included) rendered this extrinsic invalid. pub fn usurped(&mut self, hash: H) { - self.send(Status::Usurped(hash)) + self.send(TransactionStatus::Usurped(hash)) } /// Extrinsic has been finalized in block with given hash. pub fn finalized(&mut self, hash: H2) { - self.send(Status::Finalized(hash)); + self.send(TransactionStatus::Finalized(hash)); self.finalized = true; } /// Extrinsic has been marked as invalid by the block builder. pub fn invalid(&mut self) { - self.send(Status::Invalid); + self.send(TransactionStatus::Invalid); // we mark as finalized as there are no more notifications self.finalized = true; } /// Transaction has been dropped from the pool because of the limit. pub fn dropped(&mut self) { - self.send(Status::Dropped); + self.send(TransactionStatus::Dropped); } /// The extrinsic has been broadcast to the given peers. pub fn broadcast(&mut self, peers: Vec) { - self.send(Status::Broadcast(peers)) + self.send(TransactionStatus::Broadcast(peers)) } - /// Returns true if the are no more listeners for this extrinsic or it was finalized. pub fn is_done(&self) -> bool { self.finalized || self.receivers.is_empty() } - fn send(&mut self, status: Status) { + fn send(&mut self, status: TransactionStatus) { self.receivers.retain(|sender| sender.unbounded_send(status.clone()).is_ok()) } } diff --git a/core/transaction-pool/src/error.rs b/core/transaction-pool/src/error.rs index f3641aa8ecee3..f33ca4811f581 100644 --- a/core/transaction-pool/src/error.rs +++ b/core/transaction-pool/src/error.rs @@ -17,7 +17,6 @@ //! Transaction pool error. use client; -use txpool; /// Transaction pool result. pub type Result = std::result::Result; @@ -28,7 +27,7 @@ pub enum Error { /// Client error. Client(client::error::Error), /// Pool error. - Pool(txpool::error::Error), + Pool(txpoolapi::error::Error), } impl std::error::Error for Error { @@ -40,8 +39,8 @@ impl std::error::Error for Error { } } -impl txpool::IntoPoolError for Error { - fn into_pool_error(self) -> std::result::Result { +impl txpoolapi::IntoPoolError for Error { + fn into_pool_error(self) -> std::result::Result { match self { Error::Pool(e) => Ok(e), e => Err(e), diff --git a/core/transaction-pool/src/lib.rs b/core/transaction-pool/src/lib.rs index 828ce6a98ca43..4c9d9d82e7d68 100644 --- a/core/transaction-pool/src/lib.rs +++ b/core/transaction-pool/src/lib.rs @@ -14,7 +14,7 @@ // You should have received a copy of the GNU General Public License // along with Substrate. If not, see . -//! Substrate transaction pool. +//! Substrate transaction pool implementation. #![warn(missing_docs)] #![warn(unused_extern_crates)] @@ -28,236 +28,105 @@ pub mod error; pub use txpool; pub use crate::api::{FullChainApi, LightChainApi}; -pub use crate::maintainer::{ - TransactionPoolMaintainer, - DefaultFullTransactionPoolMaintainer, DefaultLightTransactionPoolMaintainer, -}; +pub use crate::maintainer::{FullBasicPoolMaintainer, LightBasicPoolMaintainer}; -use std::{collections::HashMap, hash::Hash, sync::Arc}; -use futures::Future; +use std::{collections::HashMap, sync::Arc}; +use futures::{Future, FutureExt}; -use client::{ - Client, - light::fetcher::Fetcher, - runtime_api::TaggedTransactionQueue, -}; -use primitives::{Blake2Hasher, H256}; use sr_primitives::{ - serde::Serialize, generic::BlockId, - traits::{Block as BlockT, Member, ProvideRuntimeApi}, + traits::Block as BlockT, +}; +use txpoolapi::{ + TransactionPool, PoolStatus, ImportNotificationStream, + TxHash, TransactionFor, TransactionStatusStreamFor, }; -use txpool::{EventStream, Options, watcher::Watcher}; - -/// Extrinsic hash type for a pool. -pub type ExHash

=

::Hash; -/// Block hash type for a pool. -pub type BlockHash

= <

::Block as BlockT>::Hash; -/// Extrinsic type for a pool. -pub type ExtrinsicFor

= <

::Block as BlockT>::Extrinsic; - -/// Transaction pool interface. -pub trait TransactionPool: Send + Sync { - /// Block type. - type Block: BlockT; - /// Transaction Hash type. - type Hash: Hash + Eq + Member + Serialize; - /// Error type. - type Error: From + txpool::error::IntoPoolError; - - /// Returns a future that imports a bunch of unverified extrinsics to the pool. - fn submit_at( - &self, - at: &BlockId, - xts: impl IntoIterator> + 'static, - ) -> Box>, Self::Error>> + Send + Unpin>; - - /// Returns a future that imports one unverified extrinsic to the pool. - fn submit_one( - &self, - at: &BlockId, - xt: ExtrinsicFor, - ) -> Box> + Send + Unpin>; - - /// Returns a future that import a single extrinsic and starts to watch their progress in the pool. - fn submit_and_watch( - &self, - at: &BlockId, - xt: ExtrinsicFor, - ) -> Box>, Self::Error>> + Send + Unpin>; - - /// Remove extrinsics identified by given hashes (and dependent extrinsics) from the pool. - fn remove_invalid( - &self, - hashes: &[Self::Hash], - ) -> Vec>>>; - - /// Returns pool status. - fn status(&self) -> txpool::base_pool::Status; - - /// Get an iterator for ready transactions ordered by priority - fn ready(&self) -> Box>>>>; - - /// Return an event stream of transactions imported to the pool. - fn import_notification_stream(&self) -> EventStream; - - /// Returns transaction hash - fn hash_of(&self, xt: &ExtrinsicFor) -> Self::Hash; - - /// Notify the pool about transactions broadcast. - fn on_broadcasted(&self, propagations: HashMap>); - - /// Returns a future that performs maintenance procedures on the pool. - fn maintain( - &self, - id: &BlockId, - retracted: &[BlockHash], - ) -> Box + Send + Unpin>; -} - -/// Basic implementation of transaction pool that can be customized by providing -/// different PoolApi and Maintainer. -pub struct BasicTransactionPool +/// Basic implementation of transaction pool that can be customized by providing PoolApi. +pub struct BasicPool where - Block: BlockT, - PoolApi: txpool::ChainApi, - Maintainer: TransactionPoolMaintainer, + Block: BlockT, + PoolApi: txpool::ChainApi, { pool: Arc>, - maintainer: Maintainer, } -impl BasicTransactionPool +impl BasicPool where - Block: BlockT, - PoolApi: txpool::ChainApi, - Maintainer: TransactionPoolMaintainer, + Block: BlockT, + PoolApi: txpool::ChainApi, { - /// Create new basic transaction pool with given api and maintainer. - pub fn new(options: Options, pool_api: PoolApi, maintainer: Maintainer) -> Self { - BasicTransactionPool { + /// Create new basic transaction pool with provided api. + pub fn new(options: txpool::Options, pool_api: PoolApi) -> Self { + BasicPool { pool: Arc::new(txpool::Pool::new(options, pool_api)), - maintainer, } } -} - -impl BasicTransactionPool< - api::FullChainApi, Block>, - DefaultFullTransactionPoolMaintainer, - Block, -> where - Block: BlockT, - Backend: 'static + client::backend::Backend, - Client: ProvideRuntimeApi, - as ProvideRuntimeApi>::Api: TaggedTransactionQueue, - Executor: 'static + Send + Sync + client::CallExecutor, - Api: 'static + Send + Sync, -{ - /// Create new basic full transaction pool with default API and maintainer. - pub fn default_full(options: Options, client: Arc>) -> Self { - Self::new( - options, - FullChainApi::new(client.clone()), - DefaultFullTransactionPoolMaintainer::new(client), - ) - } -} -impl BasicTransactionPool< - api::LightChainApi, F, Block>, - DefaultLightTransactionPoolMaintainer, - Block, -> where - Block: BlockT, - Backend: 'static + client::backend::Backend, - Client: ProvideRuntimeApi, - as ProvideRuntimeApi>::Api: TaggedTransactionQueue, - Executor: 'static + Send + Sync + client::CallExecutor, - Api: 'static + Send + Sync, - F: 'static + Fetcher, -{ - /// Create new basic light transaction pool with default API and maintainer. - pub fn default_light( - options: Options, - client: Arc>, - fetcher: Arc, - ) -> Self { - Self::new( - options, - LightChainApi::new(client.clone(), fetcher.clone()), - DefaultLightTransactionPoolMaintainer::with_defaults(client, fetcher), - ) + /// Gets shared reference to the underlying pool. + pub fn pool(&self) -> &Arc> { + &self.pool } } -impl TransactionPool for BasicTransactionPool +impl TransactionPool for BasicPool where - Block: BlockT, - PoolApi: 'static + txpool::ChainApi, - Maintainer: TransactionPoolMaintainer + Sync, + Block: BlockT, + PoolApi: 'static + txpool::ChainApi, { - type Block = Block; - type Hash = Block::Hash; + type Block = PoolApi::Block; + type Hash = txpool::ExHash; + type InPoolTransaction = txpool::base_pool::Transaction, TransactionFor>; type Error = error::Error; fn submit_at( &self, at: &BlockId, - xts: impl IntoIterator> + 'static, - ) -> Box>, Self::Error>> + Send + Unpin> { + xts: impl IntoIterator> + 'static, + ) -> Box, Self::Error>>, Self::Error>> + Send + Unpin> { Box::new(self.pool.submit_at(at, xts, false)) } fn submit_one( &self, at: &BlockId, - xt: ExtrinsicFor, - ) -> Box> + Send + Unpin> { + xt: TransactionFor, + ) -> Box, Self::Error>> + Send + Unpin> { Box::new(self.pool.submit_one(at, xt)) } fn submit_and_watch( &self, at: &BlockId, - xt: ExtrinsicFor, - ) -> Box>, Self::Error>> + Send + Unpin> { - Box::new(self.pool.submit_and_watch(at, xt)) + xt: TransactionFor, + ) -> Box>, Self::Error>> + Send + Unpin> { + Box::new( + self.pool.submit_and_watch(at, xt) + .map(|result| result.map(|watcher| Box::new(watcher.into_stream()) as _)) + ) } - fn remove_invalid( - &self, - hashes: &[Self::Hash], - ) -> Vec>>> { + fn remove_invalid(&self, hashes: &[TxHash]) -> Vec> { self.pool.remove_invalid(hashes) } - fn status(&self) -> txpool::base_pool::Status { + fn status(&self) -> PoolStatus { self.pool.status() } - fn ready(&self) -> Box>>>> { + fn ready(&self) -> Box>> { Box::new(self.pool.ready()) } - fn import_notification_stream(&self) -> EventStream { + fn import_notification_stream(&self) -> ImportNotificationStream { self.pool.import_notification_stream() } - fn hash_of(&self, xt: &ExtrinsicFor) -> Self::Hash { + fn hash_of(&self, xt: &TransactionFor) -> TxHash { self.pool.hash_of(xt) } - fn on_broadcasted(&self, propagations: HashMap>) { + fn on_broadcasted(&self, propagations: HashMap, Vec>) { self.pool.on_broadcasted(propagations) } - - fn maintain( - &self, - id: &BlockId, - retracted: &[Block::Hash], - ) -> Box + Send + Unpin> { - self.maintainer.maintain(id, retracted, &self.pool) - } } diff --git a/core/transaction-pool/src/maintainer.rs b/core/transaction-pool/src/maintainer.rs index 8a14470039f6e..8a32c36935e62 100644 --- a/core/transaction-pool/src/maintainer.rs +++ b/core/transaction-pool/src/maintainer.rs @@ -31,61 +31,50 @@ use client::{ light::fetcher::{Fetcher, RemoteBodyRequest}, runtime_api::TaggedTransactionQueue, }; -use primitives::Blake2Hasher; +use primitives::{Blake2Hasher, H256}; use sr_primitives::{ generic::BlockId, traits::{Block as BlockT, Extrinsic, Header, NumberFor, ProvideRuntimeApi, SimpleArithmetic}, }; +use txpoolapi::TransactionPoolMaintainer; -use txpool::{self, BlockHash}; -use crate::api::{FullChainApi, LightChainApi}; - -/// Transaction pool maintainer. -/// -/// In brief, the task of transaction pool maintainer is to: -/// 1) make sure that ready in-pool transactions are valid; -/// 2) move 'future' transactions to the 'ready' queue; -/// 3) prune transactions that have been included in some block. -/// -/// This trait is extracted from `TransactionPool` so that the maintainance -/// algorithm could be customized easily, without touching the core' pool code. -pub trait TransactionPoolMaintainer: Send + 'static { - /// Maintain transaction pool. - fn maintain( - &self, - id: &BlockId, - retracted: &[BlockHash], - pool: &Arc>, - ) -> Box + Send + Unpin>; -} +use txpool::{self, ChainApi}; -/// Default transaction pool maintainer for full clients. -pub struct DefaultFullTransactionPoolMaintainer { +/// Basic transaction pool maintainer for full clients. +pub struct FullBasicPoolMaintainer { + pool: Arc>, client: Arc>, } -impl DefaultFullTransactionPoolMaintainer { - /// Create new default full pool maintainer. - pub fn new(client: Arc>) -> Self { - DefaultFullTransactionPoolMaintainer { client } +impl FullBasicPoolMaintainer { + /// Create new basic full pool maintainer. + pub fn new( + pool: Arc>, + client: Arc>, + ) -> Self { + FullBasicPoolMaintainer { pool, client } } } -impl TransactionPoolMaintainer< - FullChainApi, Block> -> for DefaultFullTransactionPoolMaintainer where - Block: BlockT::Out>, +impl TransactionPoolMaintainer +for + FullBasicPoolMaintainer +where + Block: BlockT, Backend: 'static + client::backend::Backend, Client: ProvideRuntimeApi, as ProvideRuntimeApi>::Api: TaggedTransactionQueue, Executor: 'static + Send + Sync + client::CallExecutor, Api: 'static + Send + Sync, + PoolApi: 'static + ChainApi, { + type Block = Block; + type Hash = Block::Hash; + fn maintain( &self, id: &BlockId, retracted: &[Block::Hash], - pool: &Arc, Block>>>, ) -> Box + Send + Unpin> { // Put transactions from retracted blocks back into the pool. let client_copy = self.client.clone(); @@ -93,7 +82,7 @@ impl TransactionPoolMaintainer< .filter_map(move |hash| client_copy.block(&BlockId::hash(hash)).ok().unwrap_or(None)) .flat_map(|block| block.block.deconstruct().1.into_iter()) .filter(|tx| tx.is_signed().unwrap_or(false)); - let resubmit_future = pool + let resubmit_future = self.pool .submit_at(id, retracted_transactions, true) .then(|resubmit_result| ready(match resubmit_result { Ok(_) => (), @@ -104,7 +93,7 @@ impl TransactionPoolMaintainer< })); // Avoid calling into runtime if there is nothing to prune from the pool anyway. - if pool.status().is_empty() { + if self.pool.status().is_empty() { return Box::new(resubmit_future) } @@ -112,7 +101,7 @@ impl TransactionPoolMaintainer< match block { Ok(Some(block)) => { let parent_id = BlockId::hash(*block.block.header().parent_hash()); - let prune_future = pool + let prune_future = self.pool .prune(id, &parent_id, block.block.extrinsics()) .then(|prune_result| ready(match prune_result { Ok(_) => (), @@ -133,8 +122,9 @@ impl TransactionPoolMaintainer< } } -/// Default transaction pool maintainer for light clients. -pub struct DefaultLightTransactionPoolMaintainer { +/// Basic transaction pool maintainer for light clients. +pub struct LightBasicPoolMaintainer { + pool: Arc>, client: Arc>, fetcher: Arc, revalidate_time_period: Option, @@ -143,14 +133,15 @@ pub struct DefaultLightTransactionPoolMaintainer, } -impl DefaultLightTransactionPoolMaintainer +impl LightBasicPoolMaintainer where - Block: BlockT::Out>, + Block: BlockT, Backend: 'static + client::backend::Backend, Client: ProvideRuntimeApi, as ProvideRuntimeApi>::Api: TaggedTransactionQueue, Executor: 'static + Send + Sync + client::CallExecutor, Api: 'static + Send + Sync, + PoolApi: 'static + ChainApi, F: Fetcher + 'static, { /// Create light pool maintainer with default constants. @@ -158,10 +149,12 @@ impl DefaultLightTransactionPoolMaintainer>, client: Arc>, fetcher: Arc, ) -> Self { Self::new( + pool, client, fetcher, Some(std::time::Duration::from_secs(60)), @@ -171,12 +164,14 @@ impl DefaultLightTransactionPoolMaintainer>, client: Arc>, fetcher: Arc, revalidate_time_period: Option, revalidate_block_period: Option>, ) -> Self { Self { + pool, client, fetcher, revalidate_time_period, @@ -191,12 +186,11 @@ impl DefaultLightTransactionPoolMaintainer, header: &Block::Header, - pool: &Arc, F, Block>>>, ) -> impl std::future::Future { // fetch transactions (possible future optimization: proofs of inclusion) that // have been included into new block and prune these from the pool let id = id.clone(); - let pool = pool.clone(); + let pool = self.pool.clone(); self.fetcher.remote_body(RemoteBodyRequest { header: header.clone(), retry_count: None, @@ -226,7 +220,6 @@ impl DefaultLightTransactionPoolMaintainer, header: &Block::Header, - pool: &Arc, F, Block>>>, ) -> impl std::future::Future { // to determine whether ready transaction is still valid, we perform periodic revalidaton // of ready transactions @@ -238,7 +231,7 @@ impl DefaultLightTransactionPoolMaintainer { let revalidation_status = self.revalidation_status.clone(); - Either::Left(pool + Either::Left(self.pool .revalidate_ready(id) .map(|r| r.map_err(|e| warn!("Error revalidating known transactions: {}", e))) .map(move |_| revalidation_status.lock().clear())) @@ -248,25 +241,29 @@ impl DefaultLightTransactionPoolMaintainer TransactionPoolMaintainer< - LightChainApi, F, Block> -> for DefaultLightTransactionPoolMaintainer where +impl TransactionPoolMaintainer +for + LightBasicPoolMaintainer +where Block: BlockT::Out>, Backend: 'static + client::backend::Backend, Client: ProvideRuntimeApi, as ProvideRuntimeApi>::Api: TaggedTransactionQueue, Executor: 'static + Send + Sync + client::CallExecutor, Api: 'static + Send + Sync, + PoolApi: 'static + ChainApi, F: Fetcher + 'static, { + type Block = Block; + type Hash = Block::Hash; + fn maintain( &self, id: &BlockId, _retracted: &[Block::Hash], - pool: &Arc, F, Block>>>, ) -> Box + Send + Unpin> { // Do nothing if transaction pool is empty. - if pool.status().is_empty() { + if self.pool.status().is_empty() { self.revalidation_status.lock().clear(); return Box::new(ready(())); } @@ -281,10 +278,10 @@ impl TransactionPoolMaintainer< }; // else prune block transactions from the pool - let prune_future = self.prune(id, &header, pool); + let prune_future = self.prune(id, &header); // and then (optionally) revalidate in-pool transactions - let revalidate_future = self.revalidate(id, &header, pool); + let revalidate_future = self.revalidate(id, &header); let maintain_future = join( prune_future, @@ -346,6 +343,7 @@ mod tests { use futures::executor::block_on; use codec::Encode; use test_client::{prelude::*, runtime::{Block, Transfer}, consensus::{BlockOrigin, SelectChain}}; + use txpoolapi::PoolStatus; use crate::api::{FullChainApi, LightChainApi}; #[test] @@ -374,11 +372,7 @@ mod tests { // fire notification - this should clean up the queue assert_eq!(pool.status().ready, 1); - block_on(DefaultFullTransactionPoolMaintainer::new(client).maintain( - &id, - &[], - &pool, - )); + block_on(FullBasicPoolMaintainer::new(pool.clone(), client).maintain(&id, &[])); // then assert_eq!(pool.status().ready, 0); @@ -422,10 +416,9 @@ mod tests { // fire notification - this should clean up the queue assert_eq!(pool.status().ready, 1); - block_on(DefaultLightTransactionPoolMaintainer::with_defaults(client.clone(), fetcher).maintain( + block_on(LightBasicPoolMaintainer::with_defaults(pool.clone(), client.clone(), fetcher).maintain( &BlockId::Number(0), &[], - &pool, )); // then @@ -490,28 +483,28 @@ mod tests { revalidate_time_period: Option, revalidate_block_period: Option, prepare_maintainer: impl Fn(&Mutex>), - ) -> txpool::Status { + ) -> PoolStatus { let (client, longest_chain) = TestClientBuilder::new().build_with_longest_chain(); let client = Arc::new(client); - // let's prepare maintainer - let maintainer = DefaultLightTransactionPoolMaintainer::new( - client.clone(), - fetcher.clone(), - revalidate_time_period, - revalidate_block_period, - ); - prepare_maintainer(&*maintainer.revalidation_status); - // now let's prepare pool - let pool = txpool::Pool::new(Default::default(), LightChainApi::new( client.clone(), - fetcher, + fetcher.clone(), )); let pool = Arc::new(pool); let best = longest_chain.best_chain().unwrap(); + // let's prepare maintainer + let maintainer = LightBasicPoolMaintainer::new( + pool.clone(), + client, + fetcher, + revalidate_time_period, + revalidate_block_period, + ); + prepare_maintainer(&*maintainer.revalidation_status); + // store the transaction in the pool block_on(pool.submit_one( &BlockId::hash(best.hash()), @@ -524,7 +517,7 @@ mod tests { )).unwrap(); // and run maintain procedures - block_on(maintainer.maintain(&BlockId::Number(0), &[], &pool)); + block_on(maintainer.maintain(&BlockId::Number(0), &[])); pool.status() } @@ -577,11 +570,7 @@ mod tests { // fire notification - this should clean up the queue assert_eq!(pool.status().ready, 1); - block_on(DefaultFullTransactionPoolMaintainer::new(client.clone()).maintain( - &id, - &[], - &pool, - )); + block_on(FullBasicPoolMaintainer::new(pool.clone(), client.clone()).maintain(&id, &[])); // then assert_eq!(pool.status().ready, 0); @@ -594,11 +583,7 @@ mod tests { client.import(BlockOrigin::Own, block).unwrap(); // fire notification - this should add the transaction back to the pool. - block_on(DefaultFullTransactionPoolMaintainer::new(client).maintain( - &id, - &[block1_hash], - &pool, - )); + block_on(FullBasicPoolMaintainer::new(pool.clone(), client).maintain(&id, &[block1_hash])); // then assert_eq!(pool.status().ready, 1); diff --git a/node-template/Cargo.toml b/node-template/Cargo.toml index 2c01655dc2eae..b6857c708127a 100644 --- a/node-template/Cargo.toml +++ b/node-template/Cargo.toml @@ -25,7 +25,8 @@ primitives = { package = "substrate-primitives", path = "../core/primitives" } substrate-executor = { path = "../core/executor" } substrate-service = { path = "../core/service" } inherents = { package = "substrate-inherents", path = "../core/inherents" } -transaction-pool = { package = "substrate-transaction-pool", path = "../core/transaction-pool" } +txpool = { package = "substrate-transaction-pool", path = "../core/transaction-pool" } +txpoolapi = { package = "substrate-transaction-pool-api", path = "../core/transaction-pool/api" } network = { package = "substrate-network", path = "../core/network" } aura = { package = "substrate-consensus-aura", path = "../core/consensus/aura" } aura-primitives = { package = "substrate-consensus-aura-primitives", path = "../core/consensus/aura/primitives" } diff --git a/node-template/src/service.rs b/node-template/src/service.rs index 9722e8851b9a7..f8c228512708e 100644 --- a/node-template/src/service.rs +++ b/node-template/src/service.rs @@ -40,9 +40,13 @@ macro_rules! new_full_start { .with_select_chain(|_config, backend| { Ok(substrate_client::LongestChain::new(backend.clone())) })? - .with_transaction_pool(|config, client, _fetcher| - Ok(transaction_pool::BasicTransactionPool::default_full(config, client)) - )? + .with_transaction_pool(|config, client, _fetcher| { + let pool_api = txpool::FullChainApi::new(client.clone()); + let pool = txpool::BasicPool::new(config, pool_api); + let maintainer = txpool::FullBasicPoolMaintainer::new(pool.pool().clone(), client); + let maintainable_pool = txpoolapi::MaintainableTransactionPool::new(pool, maintainer); + Ok(maintainable_pool) + })? .with_import_queue(|_config, client, mut select_chain, transaction_pool| { let select_chain = select_chain.take() .ok_or_else(|| substrate_service::Error::SelectChainRequired)?; @@ -180,8 +184,11 @@ pub fn new_light(config: Configuration; #[allow(dead_code)] -type ConcreteTransactionPool = BasicTransactionPool< - FullChainApi, - DefaultFullTransactionPoolMaintainer< - ConcreteBackend, - LocalCallExecutor, NativeExecutor>, - Block, - node_runtime::RuntimeApi, - >, - Block, - >; +type ConcreteTransactionPool = txpoolapi::MaintainableTransactionPool< + txpool::BasicPool< + txpool::FullChainApi, + ConcreteBlock + >, + txpool::FullBasicPoolMaintainer< + ConcreteBackend, + LocalCallExecutor, NativeExecutor>, + ConcreteBlock, + node_runtime::RuntimeApi, + txpool::FullChainApi + > +>; /// A specialized configuration object for setting up the node.. pub type NodeConfiguration = Configuration; @@ -288,7 +294,11 @@ pub fn new_light(config: NodeConfiguration) .with_transaction_pool(|config, client, fetcher| { let fetcher = fetcher .ok_or_else(|| "Trying to start light transaction pool without active fetcher")?; - Ok(transaction_pool::BasicTransactionPool::default_light(config, client, fetcher)) + let pool_api = txpool::LightChainApi::new(client.clone(), fetcher.clone()); + let pool = txpool::BasicPool::new(config, pool_api); + let maintainer = txpool::LightBasicPoolMaintainer::with_defaults(pool.pool().clone(), client, fetcher); + let maintainable_pool = txpoolapi::MaintainableTransactionPool::new(pool, maintainer); + Ok(maintainable_pool) })? .with_import_queue_and_fprb(|_config, client, backend, fetcher, _select_chain, _tx_pool| { let fetch_checker = fetcher diff --git a/node/rpc/Cargo.toml b/node/rpc/Cargo.toml index 5d2ca81e0ff84..8c366ef0312a0 100644 --- a/node/rpc/Cargo.toml +++ b/node/rpc/Cargo.toml @@ -11,4 +11,4 @@ node-primitives = { path = "../primitives" } sr-primitives = { path = "../../core/sr-primitives" } srml-contracts-rpc = { path = "../../srml/contracts/rpc/" } srml-system-rpc = { path = "../../srml/system/rpc/" } -transaction_pool = { package = "substrate-transaction-pool", path = "../../core/transaction-pool" } +txpoolapi = { package = "substrate-transaction-pool-api", path = "../../core/transaction-pool/api" } diff --git a/node/rpc/src/lib.rs b/node/rpc/src/lib.rs index 7b6f76e359f51..501920b65ca3a 100644 --- a/node/rpc/src/lib.rs +++ b/node/rpc/src/lib.rs @@ -33,7 +33,7 @@ use std::sync::Arc; use node_primitives::{Block, AccountId, Index, Balance}; use sr_primitives::traits::ProvideRuntimeApi; -use transaction_pool::TransactionPool; +use txpoolapi::TransactionPool; /// Instantiate all RPC extensions for full node. pub fn create_full(client: Arc, pool: Arc

) -> jsonrpc_core::IoHandler where @@ -42,7 +42,7 @@ pub fn create_full(client: Arc, pool: Arc

) -> jsonrpc_core::IoHan C: Send + Sync + 'static, C::Api: srml_system_rpc::AccountNonceApi, C::Api: srml_contracts_rpc::ContractsRuntimeApi, - P: TransactionPool + Sync + Send + 'static, + P: TransactionPool + 'static, M: jsonrpc_core::Metadata + Default, { use srml_system_rpc::{FullSystem, SystemApi}; @@ -70,7 +70,7 @@ pub fn create_light( C: client::blockchain::HeaderBackend, C: Send + Sync + 'static, C::Api: srml_system_rpc::AccountNonceApi, - P: TransactionPool + Sync + Send + 'static, + P: TransactionPool + 'static, M: jsonrpc_core::Metadata + Default, F: client::light::fetcher::Fetcher + 'static, { diff --git a/srml/system/rpc/Cargo.toml b/srml/system/rpc/Cargo.toml index e2ab48ed1136a..1521e2e26da80 100644 --- a/srml/system/rpc/Cargo.toml +++ b/srml/system/rpc/Cargo.toml @@ -16,8 +16,9 @@ serde = { version = "1.0.101", features = ["derive"] } sr-primitives = { path = "../../../core/sr-primitives" } srml-system-rpc-runtime-api = { path = "./runtime-api" } substrate-primitives = { path = "../../../core/primitives" } -transaction_pool = { package = "substrate-transaction-pool", path = "../../../core/transaction-pool" } +txpoolapi = { package = "substrate-transaction-pool-api", path = "../../../core/transaction-pool/api" } [dev-dependencies] test-client = { package = "substrate-test-runtime-client", path = "../../../core/test-runtime/client" } env_logger = "0.7.0" +txpool = { package = "substrate-transaction-pool", path = "../../../core/transaction-pool" } diff --git a/srml/system/rpc/src/lib.rs b/srml/system/rpc/src/lib.rs index c173caa4899c5..772810c246a95 100644 --- a/srml/system/rpc/src/lib.rs +++ b/srml/system/rpc/src/lib.rs @@ -36,7 +36,7 @@ use sr_primitives::{ traits, }; use substrate_primitives::hexdisplay::HexDisplay; -use transaction_pool::TransactionPool; +use txpoolapi::{TransactionPool, InPoolTransaction}; pub use srml_system_rpc_runtime_api::AccountNonceApi; pub use self::gen_client::Client as SystemClient; @@ -82,7 +82,7 @@ where C: HeaderBackend, C: Send + Sync + 'static, C::Api: AccountNonceApi, - P: TransactionPool + Sync + Send + 'static, + P: TransactionPool + 'static, Block: traits::Block, AccountId: Clone + std::fmt::Display + Codec, Index: Clone + std::fmt::Display + Codec + Send + traits::SimpleArithmetic + 'static, @@ -133,7 +133,7 @@ impl LightSystem { impl SystemApi for LightSystem where - P: TransactionPool + Sync + Send + 'static, + P: TransactionPool + 'static, C: HeaderBackend, C: Send + Sync + 'static, F: Fetcher + 'static, @@ -180,11 +180,12 @@ where /// Adjust account nonce from state, so that tx with the nonce will be /// placed after all ready txpool transactions. -fn adjust_nonce( +fn adjust_nonce( pool: &P, account: AccountId, nonce: Index, ) -> Index where + P: TransactionPool, AccountId: Clone + std::fmt::Display + Encode, Index: Clone + std::fmt::Display + Encode + traits::SimpleArithmetic + 'static, { @@ -203,11 +204,11 @@ fn adjust_nonce( "Current nonce to {}, checking {} vs {:?}", current_nonce, HexDisplay::from(¤t_tag), - tx.provides.iter().map(|x| format!("{}", HexDisplay::from(x))).collect::>(), + tx.provides().iter().map(|x| format!("{}", HexDisplay::from(x))).collect::>(), ); // since transactions in `ready()` need to be ordered by nonce // it's fine to continue with current iterator. - if tx.provides.get(0) == Some(¤t_tag) { + if tx.provides().get(0) == Some(¤t_tag) { current_nonce += traits::One::one(); current_tag = (account.clone(), current_nonce.clone()).encode(); } @@ -225,14 +226,14 @@ mod tests { runtime::Transfer, AccountKeyring, }; - use transaction_pool::BasicTransactionPool; + use txpool::{BasicPool, FullChainApi}; #[test] fn should_return_next_nonce_for_some_account() { // given let _ = env_logger::try_init(); let client = Arc::new(test_client::new()); - let pool = Arc::new(BasicTransactionPool::default_full(Default::default(), client.clone())); + let pool = Arc::new(BasicPool::new(Default::default(), FullChainApi::new(client.clone()))); let new_transaction = |nonce: u64| { let t = Transfer { From 3db29ecc5b22a816c8f58d0943d65860852e262b Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Fri, 25 Oct 2019 15:29:37 +0300 Subject: [PATCH 23/38] long line fix --- core/transaction-pool/src/maintainer.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/core/transaction-pool/src/maintainer.rs b/core/transaction-pool/src/maintainer.rs index 8a32c36935e62..66eab98aeb5b2 100644 --- a/core/transaction-pool/src/maintainer.rs +++ b/core/transaction-pool/src/maintainer.rs @@ -46,7 +46,11 @@ pub struct FullBasicPoolMaintainer>, } -impl FullBasicPoolMaintainer { +impl FullBasicPoolMaintainer + where + Block: BlockT, + PoolApi: ChainApi, +{ /// Create new basic full pool maintainer. pub fn new( pool: Arc>, From 0edc89320d456c4f3f7cbd602672bf4ae194ead9 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Tue, 12 Nov 2019 14:08:12 +0300 Subject: [PATCH 24/38] pos-merge fix --- core/transaction-pool/graph/src/validated_pool.rs | 2 +- core/transaction-pool/src/maintainer.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/core/transaction-pool/graph/src/validated_pool.rs b/core/transaction-pool/graph/src/validated_pool.rs index 91c5fd8f0c218..45fc4388f2ae0 100644 --- a/core/transaction-pool/graph/src/validated_pool.rs +++ b/core/transaction-pool/graph/src/validated_pool.rs @@ -278,7 +278,7 @@ impl ValidatedPool { final_statuses.insert(hash, Status::Failed); }, }, - ValidatedTransaction::Invalid(_) | ValidatedTransaction::Unknown(_, _) => { + ValidatedTransaction::Invalid(_, _) | ValidatedTransaction::Unknown(_, _) => { final_statuses.insert(hash, Status::Failed); }, } diff --git a/core/transaction-pool/src/maintainer.rs b/core/transaction-pool/src/maintainer.rs index 66eab98aeb5b2..08b333a2e03d6 100644 --- a/core/transaction-pool/src/maintainer.rs +++ b/core/transaction-pool/src/maintainer.rs @@ -29,7 +29,6 @@ use parking_lot::Mutex; use client::{ Client, light::fetcher::{Fetcher, RemoteBodyRequest}, - runtime_api::TaggedTransactionQueue, }; use primitives::{Blake2Hasher, H256}; use sr_primitives::{ @@ -37,6 +36,7 @@ use sr_primitives::{ traits::{Block as BlockT, Extrinsic, Header, NumberFor, ProvideRuntimeApi, SimpleArithmetic}, }; use txpoolapi::TransactionPoolMaintainer; +use tx_runtime_api::TaggedTransactionQueue; use txpool::{self, ChainApi}; From 3a26f364bf8612e36df94452c445bea82e3adf39 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Tue, 12 Nov 2019 14:59:47 +0300 Subject: [PATCH 25/38] fix benches compilation --- core/transaction-pool/graph/benches/basics.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/transaction-pool/graph/benches/basics.rs b/core/transaction-pool/graph/benches/basics.rs index dcd725ce465f4..c96feed31e15a 100644 --- a/core/transaction-pool/graph/benches/basics.rs +++ b/core/transaction-pool/graph/benches/basics.rs @@ -48,8 +48,8 @@ fn to_tag(nonce: u64, from: AccountId) -> Tag { impl ChainApi for TestApi { type Block = Block; type Hash = H256; - type Error = error::Error; - type ValidationFuture = futures::future::Ready>; + type Error = txpoolapi::error::Error; + type ValidationFuture = futures::future::Ready>; fn validate_transaction( &self, From 50e99f2eeaf1feaa079677126ce9f894cef66676 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Fri, 22 Nov 2019 15:48:50 +0100 Subject: [PATCH 26/38] Rename txpoolapi to txpool_api --- core/basic-authorship/Cargo.toml | 2 +- core/basic-authorship/src/basic_authorship.rs | 2 +- core/offchain/Cargo.toml | 2 +- core/offchain/src/api.rs | 2 +- core/offchain/src/lib.rs | 4 ++-- core/rpc/Cargo.toml | 2 +- core/rpc/api/Cargo.toml | 2 +- core/rpc/api/src/author/error.rs | 4 ++-- core/rpc/api/src/author/mod.rs | 2 +- core/rpc/src/author/mod.rs | 2 +- core/service/Cargo.toml | 2 +- core/service/src/builder.rs | 2 +- core/service/src/lib.rs | 8 ++++---- core/service/test/Cargo.toml | 2 +- core/service/test/src/lib.rs | 2 +- core/transaction-pool/Cargo.toml | 2 +- core/transaction-pool/graph/Cargo.toml | 2 +- core/transaction-pool/graph/benches/basics.rs | 4 ++-- core/transaction-pool/graph/src/base_pool.rs | 2 +- core/transaction-pool/graph/src/pool.rs | 4 ++-- core/transaction-pool/graph/src/ready.rs | 2 +- core/transaction-pool/graph/src/validated_pool.rs | 6 +++--- core/transaction-pool/graph/src/watcher.rs | 2 +- core/transaction-pool/src/error.rs | 6 +++--- core/transaction-pool/src/lib.rs | 2 +- core/transaction-pool/src/maintainer.rs | 4 ++-- node-template/Cargo.toml | 2 +- node-template/src/service.rs | 4 ++-- node/cli/Cargo.toml | 2 +- node/cli/src/service.rs | 6 +++--- node/rpc/Cargo.toml | 2 +- node/rpc/src/lib.rs | 2 +- srml/system/rpc/Cargo.toml | 2 +- srml/system/rpc/src/lib.rs | 2 +- 34 files changed, 49 insertions(+), 49 deletions(-) diff --git a/core/basic-authorship/Cargo.toml b/core/basic-authorship/Cargo.toml index 02dd4cb9a0705..d2afb0f2b95bc 100644 --- a/core/basic-authorship/Cargo.toml +++ b/core/basic-authorship/Cargo.toml @@ -14,7 +14,7 @@ client = { package = "substrate-client", path = "../../core/client" } consensus_common = { package = "substrate-consensus-common", path = "../../core/consensus/common" } inherents = { package = "substrate-inherents", path = "../inherents" } substrate-telemetry = { path = "../telemetry" } -txpoolapi = { package = "substrate-transaction-pool-api", path = "../../core/transaction-pool/api" } +txpool-api = { package = "substrate-transaction-pool-api", path = "../../core/transaction-pool/api" } block-builder = { package = "substrate-block-builder", path = "../block-builder" } [dev-dependencies] diff --git a/core/basic-authorship/src/basic_authorship.rs b/core/basic-authorship/src/basic_authorship.rs index aac297e96da8a..71b339c29c11c 100644 --- a/core/basic-authorship/src/basic_authorship.rs +++ b/core/basic-authorship/src/basic_authorship.rs @@ -32,7 +32,7 @@ use sr_primitives::{ }, generic::BlockId, }; -use txpoolapi::{TransactionPool, InPoolTransaction}; +use txpool_api::{TransactionPool, InPoolTransaction}; use substrate_telemetry::{telemetry, CONSENSUS_INFO}; use block_builder::BlockBuilderApi; diff --git a/core/offchain/Cargo.toml b/core/offchain/Cargo.toml index 433769ffa85b8..8a7073630c41f 100644 --- a/core/offchain/Cargo.toml +++ b/core/offchain/Cargo.toml @@ -23,7 +23,7 @@ parking_lot = "0.9.0" primitives = { package = "substrate-primitives", path = "../../core/primitives" } rand = "0.7.2" sr-primitives = { path = "../../core/sr-primitives" } -txpoolapi = { package = "substrate-transaction-pool-api", path = "../../core/transaction-pool/api" } +txpool-api = { package = "substrate-transaction-pool-api", path = "../../core/transaction-pool/api" } network = { package = "substrate-network", path = "../../core/network" } keystore = { package = "substrate-keystore", path = "../keystore" } diff --git a/core/offchain/src/api.rs b/core/offchain/src/api.rs index 3b6d6c0eb87ba..d5e70c495d851 100644 --- a/core/offchain/src/api.rs +++ b/core/offchain/src/api.rs @@ -32,7 +32,7 @@ use primitives::offchain::{ }; pub use offchain_primitives::STORAGE_PREFIX; use sr_primitives::{generic::BlockId, traits::{self, Extrinsic}}; -use txpoolapi::TransactionPool; +use txpool_api::TransactionPool; #[cfg(not(target_os = "unknown"))] mod http; diff --git a/core/offchain/src/lib.rs b/core/offchain/src/lib.rs index c48076d53031c..e24cfb9971229 100644 --- a/core/offchain/src/lib.rs +++ b/core/offchain/src/lib.rs @@ -43,7 +43,7 @@ use log::{debug, warn}; use network::NetworkStateInfo; use primitives::{offchain, ExecutionContext}; use sr_primitives::{generic::BlockId, traits::{self, ProvideRuntimeApi}}; -use txpoolapi::TransactionPool; +use txpool_api::TransactionPool; mod api; @@ -153,7 +153,7 @@ mod tests { use super::*; use network::{Multiaddr, PeerId}; use txpool::{BasicPool, FullChainApi}; - use txpoolapi::InPoolTransaction; + use txpool_api::InPoolTransaction; struct MockNetworkStateInfo(); diff --git a/core/rpc/Cargo.toml b/core/rpc/Cargo.toml index 07af3b8a9404e..8c1c1c4a547e0 100644 --- a/core/rpc/Cargo.toml +++ b/core/rpc/Cargo.toml @@ -22,7 +22,7 @@ rpc-primitives = { package = "substrate-rpc-primitives", path = "primitives" } state_machine = { package = "substrate-state-machine", path = "../state-machine" } substrate-executor = { path = "../executor" } substrate-keystore = { path = "../keystore" } -txpoolapi = { package = "substrate-transaction-pool-api", path = "../transaction-pool/api" } +txpool-api = { package = "substrate-transaction-pool-api", path = "../transaction-pool/api" } hash-db = { version = "0.15.2", default-features = false } parking_lot = { version = "0.9.0" } diff --git a/core/rpc/api/Cargo.toml b/core/rpc/api/Cargo.toml index 55327070dc4ac..8dff3ae089a3f 100644 --- a/core/rpc/api/Cargo.toml +++ b/core/rpc/api/Cargo.toml @@ -18,5 +18,5 @@ primitives = { package = "substrate-primitives", path = "../../primitives" } runtime_version = { package = "sr-version", path = "../../sr-version" } serde = { version = "1.0.101", features = ["derive"] } serde_json = "1.0.41" -txpoolapi = { package = "substrate-transaction-pool-api", path = "../../transaction-pool/api" } +txpool-api = { package = "substrate-transaction-pool-api", path = "../../transaction-pool/api" } rpc-primitives = { package = "substrate-rpc-primitives", path = "../../rpc/primitives" } diff --git a/core/rpc/api/src/author/error.rs b/core/rpc/api/src/author/error.rs index b7f526fbff689..b22aa005e315f 100644 --- a/core/rpc/api/src/author/error.rs +++ b/core/rpc/api/src/author/error.rs @@ -33,7 +33,7 @@ pub enum Error { Client(Box), /// Transaction pool error, #[display(fmt="Transaction pool error: {}", _0)] - Pool(txpoolapi::error::Error), + Pool(txpool_api::error::Error), /// Verification error #[display(fmt="Extrinsic verification error: {}", _0)] Verification(Box), @@ -91,7 +91,7 @@ const UNSUPPORTED_KEY_TYPE: i64 = POOL_INVALID_TX + 7; impl From for rpc::Error { fn from(e: Error) -> Self { - use txpoolapi::error::{Error as PoolError}; + use txpool_api::error::{Error as PoolError}; match e { Error::BadFormat(e) => rpc::Error { diff --git a/core/rpc/api/src/author/mod.rs b/core/rpc/api/src/author/mod.rs index 09b227f2bedb6..927bb530eab0f 100644 --- a/core/rpc/api/src/author/mod.rs +++ b/core/rpc/api/src/author/mod.rs @@ -22,7 +22,7 @@ pub mod hash; use jsonrpc_derive::rpc; use jsonrpc_pubsub::{typed::Subscriber, SubscriptionId}; use primitives::Bytes; -use txpoolapi::TransactionStatus; +use txpool_api::TransactionStatus; use self::error::{FutureResult, Result}; pub use self::gen_client::Client as AuthorClient; diff --git a/core/rpc/src/author/mod.rs b/core/rpc/src/author/mod.rs index 406bf0c7ab359..b37c7bdb42891 100644 --- a/core/rpc/src/author/mod.rs +++ b/core/rpc/src/author/mod.rs @@ -36,7 +36,7 @@ use codec::{Encode, Decode}; use primitives::{Bytes, Blake2Hasher, H256, traits::BareCryptoStorePtr}; use sr_api::ConstructRuntimeApi; use sr_primitives::{generic, traits::{self, ProvideRuntimeApi}}; -use txpoolapi::{ +use txpool_api::{ TransactionPool, InPoolTransaction, TransactionStatus, BlockHash, TxHash, TransactionFor, IntoPoolError, }; diff --git a/core/service/Cargo.toml b/core/service/Cargo.toml index 0be128419c861..ceeb58a67ca86 100644 --- a/core/service/Cargo.toml +++ b/core/service/Cargo.toml @@ -44,7 +44,7 @@ client_db = { package = "substrate-client-db", path = "../../core/client/db" } codec = { package = "parity-scale-codec", version = "1.0.0" } substrate-executor = { path = "../../core/executor" } txpool = { package = "substrate-transaction-pool", path = "../../core/transaction-pool" } -txpoolapi = { package = "substrate-transaction-pool-api", path = "../../core/transaction-pool/api" } +txpool-api = { package = "substrate-transaction-pool-api", path = "../../core/transaction-pool/api" } rpc-servers = { package = "substrate-rpc-servers", path = "../../core/rpc-servers" } rpc = { package = "substrate-rpc", path = "../../core/rpc" } tel = { package = "substrate-telemetry", path = "../../core/telemetry" } diff --git a/core/service/src/builder.rs b/core/service/src/builder.rs index ea840154d83e0..c32a00bd48200 100644 --- a/core/service/src/builder.rs +++ b/core/service/src/builder.rs @@ -50,7 +50,7 @@ use std::{ }; use sysinfo::{get_current_pid, ProcessExt, System, SystemExt}; use tel::{telemetry, SUBSTRATE_INFO}; -use txpoolapi::{TransactionPool, TransactionPoolMaintainer}; +use txpool_api::{TransactionPool, TransactionPoolMaintainer}; /// Aggregator for the components required to build a service. /// diff --git a/core/service/src/lib.rs b/core/service/src/lib.rs index 27ba326e8abd6..cc256ea5750bb 100644 --- a/core/service/src/lib.rs +++ b/core/service/src/lib.rs @@ -59,7 +59,7 @@ pub use self::builder::{ }; pub use config::{Configuration, Roles, PruningMode}; pub use chain_spec::{ChainSpec, Properties, RuntimeGenesis, Extension as ChainSpecExtension}; -pub use txpoolapi::{TransactionPool, TransactionPoolMaintainer, InPoolTransaction, IntoPoolError}; +pub use txpool_api::{TransactionPool, TransactionPoolMaintainer, InPoolTransaction, IntoPoolError}; pub use txpool::txpool::Options as TransactionPoolOptions; pub use client::FinalityNotifications; pub use rpc::Metadata as RpcMetadata; @@ -587,7 +587,7 @@ where Pool: TransactionPool, B: BlockT, H: std::hash::Hash + Eq + sr_primitives::traits::Member + sr_primitives::traits::MaybeSerialize, - E: IntoPoolError + From, + E: IntoPoolError + From, { pool.ready() .filter(|t| t.is_propagateable()) @@ -606,7 +606,7 @@ where Pool: 'static + TransactionPool, B: BlockT, H: std::hash::Hash + Eq + sr_primitives::traits::Member + sr_primitives::traits::MaybeSerialize, - E: 'static + IntoPoolError + From, + E: 'static + IntoPoolError + From, { fn transactions(&self) -> Vec<(H, ::Extrinsic)> { transactions_to_propagate(&*self.pool) @@ -639,7 +639,7 @@ where match import_result { Ok(_) => report_handle.report_peer(who, reputation_change_good), Err(e) => match e.into_pool_error() { - Ok(txpoolapi::error::Error::AlreadyImported(_)) => (), + Ok(txpool_api::error::Error::AlreadyImported(_)) => (), Ok(e) => { report_handle.report_peer(who, reputation_change_bad); debug!("Error adding transaction to the pool: {:?}", e) diff --git a/core/service/test/Cargo.toml b/core/service/test/Cargo.toml index b422537eaa948..90d0e66a883c3 100644 --- a/core/service/test/Cargo.toml +++ b/core/service/test/Cargo.toml @@ -18,4 +18,4 @@ consensus = { package = "substrate-consensus-common", path = "../../../core/cons client = { package = "substrate-client", path = "../../../core/client" } sr-primitives = { path = "../../../core/sr-primitives" } primitives = { package = "substrate-primitives", path = "../../../core/primitives" } -txpoolapi = { package = "substrate-transaction-pool-api", path = "../../../core/transaction-pool/api" } +txpool-api = { package = "substrate-transaction-pool-api", path = "../../../core/transaction-pool/api" } diff --git a/core/service/test/src/lib.rs b/core/service/test/src/lib.rs index f0dcd552c8147..0479985f56113 100644 --- a/core/service/test/src/lib.rs +++ b/core/service/test/src/lib.rs @@ -36,7 +36,7 @@ use service::{ use network::{multiaddr, Multiaddr}; use network::config::{NetworkConfiguration, TransportConfig, NodeKeyConfig, Secret, NonReservedPeerMode}; use sr_primitives::{generic::BlockId, traits::Block as BlockT}; -use txpoolapi::TransactionPool; +use txpool_api::TransactionPool; /// Maximum duration of single wait call. const MAX_WAIT_TIME: Duration = Duration::from_secs(60 * 3); diff --git a/core/transaction-pool/Cargo.toml b/core/transaction-pool/Cargo.toml index 0efd8b91ddab0..9d94c938aa717 100644 --- a/core/transaction-pool/Cargo.toml +++ b/core/transaction-pool/Cargo.toml @@ -13,7 +13,7 @@ parking_lot = "0.9.0" sr-primitives = { path = "../sr-primitives" } primitives = { package = "substrate-primitives", path = "../primitives" } txpool = { package = "substrate-transaction-graph", path = "./graph" } -txpoolapi = { package = "substrate-transaction-pool-api", path = "api" } +txpool-api = { package = "substrate-transaction-pool-api", path = "api" } tx-runtime-api = { package = "substrate-transaction-pool-runtime-api", path = "runtime-api" } sr-api = { path = "../sr-api" } client = { package = "substrate-client", path = "../client" } diff --git a/core/transaction-pool/graph/Cargo.toml b/core/transaction-pool/graph/Cargo.toml index d6b2238b94481..efeb0b97295b5 100644 --- a/core/transaction-pool/graph/Cargo.toml +++ b/core/transaction-pool/graph/Cargo.toml @@ -12,7 +12,7 @@ parking_lot = "0.9.0" serde = { version = "1.0.101", features = ["derive"] } primitives = { package = "substrate-primitives", path = "../../primitives" } sr-primitives = { path = "../../sr-primitives" } -txpoolapi = { package = "substrate-transaction-pool-api", path = "../api" } +txpool-api = { package = "substrate-transaction-pool-api", path = "../api" } [dev-dependencies] assert_matches = "1.3.0" diff --git a/core/transaction-pool/graph/benches/basics.rs b/core/transaction-pool/graph/benches/basics.rs index c96feed31e15a..dc670a196e9b6 100644 --- a/core/transaction-pool/graph/benches/basics.rs +++ b/core/transaction-pool/graph/benches/basics.rs @@ -48,8 +48,8 @@ fn to_tag(nonce: u64, from: AccountId) -> Tag { impl ChainApi for TestApi { type Block = Block; type Hash = H256; - type Error = txpoolapi::error::Error; - type ValidationFuture = futures::future::Ready>; + type Error = txpool_api::error::Error; + type ValidationFuture = futures::future::Ready>; fn validate_transaction( &self, diff --git a/core/transaction-pool/graph/src/base_pool.rs b/core/transaction-pool/graph/src/base_pool.rs index 4b57ee7cabb35..a683741aa4076 100644 --- a/core/transaction-pool/graph/src/base_pool.rs +++ b/core/transaction-pool/graph/src/base_pool.rs @@ -34,7 +34,7 @@ use sr_primitives::transaction_validity::{ TransactionLongevity as Longevity, TransactionPriority as Priority, }; -use txpoolapi::{error, PoolStatus, InPoolTransaction}; +use txpool_api::{error, PoolStatus, InPoolTransaction}; use crate::future::{FutureTransactions, WaitingTransaction}; use crate::ready::ReadyTransactions; diff --git a/core/transaction-pool/graph/src/pool.rs b/core/transaction-pool/graph/src/pool.rs index 4a556183b093e..69761ab53a08d 100644 --- a/core/transaction-pool/graph/src/pool.rs +++ b/core/transaction-pool/graph/src/pool.rs @@ -34,7 +34,7 @@ use sr_primitives::{ traits::{self, SaturatedConversion}, transaction_validity::{TransactionValidity, TransactionTag as Tag, TransactionValidityError}, }; -use txpoolapi::{error, PoolStatus}; +use txpool_api::{error, PoolStatus}; use crate::validated_pool::{ValidatedPool, ValidatedTransaction}; @@ -437,7 +437,7 @@ mod tests { use parking_lot::Mutex; use futures::executor::block_on; use super::*; - use txpoolapi::TransactionStatus; + use txpool_api::TransactionStatus; use sr_primitives::transaction_validity::{ValidTransaction, InvalidTransaction}; use codec::Encode; use test_runtime::{Block, Extrinsic, Transfer, H256, AccountId}; diff --git a/core/transaction-pool/graph/src/ready.rs b/core/transaction-pool/graph/src/ready.rs index e2dba4fafc174..3684572bd0233 100644 --- a/core/transaction-pool/graph/src/ready.rs +++ b/core/transaction-pool/graph/src/ready.rs @@ -28,7 +28,7 @@ use sr_primitives::traits::Member; use sr_primitives::transaction_validity::{ TransactionTag as Tag, }; -use txpoolapi::error; +use txpool_api::error; use crate::future::WaitingTransaction; use crate::base_pool::Transaction; diff --git a/core/transaction-pool/graph/src/validated_pool.rs b/core/transaction-pool/graph/src/validated_pool.rs index 45fc4388f2ae0..2aca2adb72f3a 100644 --- a/core/transaction-pool/graph/src/validated_pool.rs +++ b/core/transaction-pool/graph/src/validated_pool.rs @@ -36,7 +36,7 @@ use sr_primitives::{ traits::{self, SaturatedConversion}, transaction_validity::TransactionTag as Tag, }; -use txpoolapi::{error, PoolStatus}; +use txpool_api::{error, PoolStatus}; use crate::base_pool::PruneStatus; use crate::pool::{EventStream, Options, ChainApi, BlockHash, ExHash, ExtrinsicFor, TransactionFor}; @@ -199,7 +199,7 @@ impl ValidatedPool { #[derive(Debug, Clone, Copy, PartialEq)] enum Status { Future, Ready, Failed, Dropped }; - let (initial_statuses, final_statuses) = { + let (mut initial_statuses, final_statuses) = { let mut pool = self.pool.write(); // remove all passed transactions from the ready/future queues @@ -299,7 +299,7 @@ impl ValidatedPool { // and now let's notify listeners about status changes let mut listener = self.listener.write(); for (hash, final_status) in final_statuses { - let initial_status = initial_statuses.get(&hash).cloned(); + let initial_status = initial_statuses.remove(&hash); if initial_status.is_none() || Some(final_status) != initial_status { match final_status { Status::Future => listener.future(&hash), diff --git a/core/transaction-pool/graph/src/watcher.rs b/core/transaction-pool/graph/src/watcher.rs index 3e075abda5c29..fa93386c8cad9 100644 --- a/core/transaction-pool/graph/src/watcher.rs +++ b/core/transaction-pool/graph/src/watcher.rs @@ -20,7 +20,7 @@ use futures::{ Stream, channel::mpsc, }; -use txpoolapi::TransactionStatus; +use txpool_api::TransactionStatus; /// Extrinsic watcher. /// diff --git a/core/transaction-pool/src/error.rs b/core/transaction-pool/src/error.rs index 99388b1ade02e..a58da4d7c9d2b 100644 --- a/core/transaction-pool/src/error.rs +++ b/core/transaction-pool/src/error.rs @@ -23,7 +23,7 @@ pub type Result = std::result::Result; #[derive(Debug, derive_more::Display, derive_more::From)] pub enum Error { /// Pool error. - Pool(txpoolapi::error::Error), + Pool(txpool_api::error::Error), /// Client error. Client(client::error::Error), /// Error while converting a `BlockId`. @@ -43,8 +43,8 @@ impl std::error::Error for Error { } } -impl txpoolapi::IntoPoolError for Error { - fn into_pool_error(self) -> std::result::Result { +impl txpool_api::IntoPoolError for Error { + fn into_pool_error(self) -> std::result::Result { match self { Error::Pool(e) => Ok(e), e => Err(e), diff --git a/core/transaction-pool/src/lib.rs b/core/transaction-pool/src/lib.rs index 262650a353d24..1499ab26d4bfc 100644 --- a/core/transaction-pool/src/lib.rs +++ b/core/transaction-pool/src/lib.rs @@ -37,7 +37,7 @@ use sr_primitives::{ generic::BlockId, traits::Block as BlockT, }; -use txpoolapi::{ +use txpool_api::{ TransactionPool, PoolStatus, ImportNotificationStream, TxHash, TransactionFor, TransactionStatusStreamFor, }; diff --git a/core/transaction-pool/src/maintainer.rs b/core/transaction-pool/src/maintainer.rs index 08b333a2e03d6..03696d22dc148 100644 --- a/core/transaction-pool/src/maintainer.rs +++ b/core/transaction-pool/src/maintainer.rs @@ -35,7 +35,7 @@ use sr_primitives::{ generic::BlockId, traits::{Block as BlockT, Extrinsic, Header, NumberFor, ProvideRuntimeApi, SimpleArithmetic}, }; -use txpoolapi::TransactionPoolMaintainer; +use txpool_api::TransactionPoolMaintainer; use tx_runtime_api::TaggedTransactionQueue; use txpool::{self, ChainApi}; @@ -347,7 +347,7 @@ mod tests { use futures::executor::block_on; use codec::Encode; use test_client::{prelude::*, runtime::{Block, Transfer}, consensus::{BlockOrigin, SelectChain}}; - use txpoolapi::PoolStatus; + use txpool_api::PoolStatus; use crate::api::{FullChainApi, LightChainApi}; #[test] diff --git a/node-template/Cargo.toml b/node-template/Cargo.toml index 80d1251e57533..3450defaf9d0c 100644 --- a/node-template/Cargo.toml +++ b/node-template/Cargo.toml @@ -26,7 +26,7 @@ substrate-executor = { path = "../core/executor" } substrate-service = { path = "../core/service" } inherents = { package = "substrate-inherents", path = "../core/inherents" } txpool = { package = "substrate-transaction-pool", path = "../core/transaction-pool" } -txpoolapi = { package = "substrate-transaction-pool-api", path = "../core/transaction-pool/api" } +txpool-api = { package = "substrate-transaction-pool-api", path = "../core/transaction-pool/api" } network = { package = "substrate-network", path = "../core/network" } aura = { package = "substrate-consensus-aura", path = "../core/consensus/aura" } aura-primitives = { package = "substrate-consensus-aura-primitives", path = "../core/consensus/aura/primitives" } diff --git a/node-template/src/service.rs b/node-template/src/service.rs index fa21bdae7e27c..f576166cd41a0 100644 --- a/node-template/src/service.rs +++ b/node-template/src/service.rs @@ -43,7 +43,7 @@ macro_rules! new_full_start { let pool_api = txpool::FullChainApi::new(client.clone()); let pool = txpool::BasicPool::new(config, pool_api); let maintainer = txpool::FullBasicPoolMaintainer::new(pool.pool().clone(), client); - let maintainable_pool = txpoolapi::MaintainableTransactionPool::new(pool, maintainer); + let maintainable_pool = txpool_api::MaintainableTransactionPool::new(pool, maintainer); Ok(maintainable_pool) })? .with_import_queue(|_config, client, mut select_chain, transaction_pool| { @@ -199,7 +199,7 @@ pub fn new_light(config: Configuration; #[allow(dead_code)] -type ConcreteTransactionPool = txpoolapi::MaintainableTransactionPool< +type ConcreteTransactionPool = txpool_api::MaintainableTransactionPool< txpool::BasicPool< txpool::FullChainApi, ConcreteBlock @@ -308,7 +308,7 @@ pub fn new_light(config: NodeConfiguration) let pool_api = txpool::LightChainApi::new(client.clone(), fetcher.clone()); let pool = txpool::BasicPool::new(config, pool_api); let maintainer = txpool::LightBasicPoolMaintainer::with_defaults(pool.pool().clone(), client, fetcher); - let maintainable_pool = txpoolapi::MaintainableTransactionPool::new(pool, maintainer); + let maintainable_pool = txpool_api::MaintainableTransactionPool::new(pool, maintainer); Ok(maintainable_pool) })? .with_import_queue_and_fprb(|_config, client, backend, fetcher, _select_chain, _tx_pool| { diff --git a/node/rpc/Cargo.toml b/node/rpc/Cargo.toml index 31098d2492a6b..77c156bb1f347 100644 --- a/node/rpc/Cargo.toml +++ b/node/rpc/Cargo.toml @@ -13,4 +13,4 @@ sr-primitives = { path = "../../core/sr-primitives" } srml-contracts-rpc = { path = "../../srml/contracts/rpc/" } srml-transaction-payment-rpc = { path = "../../srml/transaction-payment/rpc/" } srml-system-rpc = { path = "../../srml/system/rpc/" } -txpoolapi = { package = "substrate-transaction-pool-api", path = "../../core/transaction-pool/api" } +txpool-api = { package = "substrate-transaction-pool-api", path = "../../core/transaction-pool/api" } diff --git a/node/rpc/src/lib.rs b/node/rpc/src/lib.rs index 78891db85a229..486894b5242b9 100644 --- a/node/rpc/src/lib.rs +++ b/node/rpc/src/lib.rs @@ -34,7 +34,7 @@ use std::sync::Arc; use node_primitives::{Block, AccountId, Index, Balance}; use node_runtime::UncheckedExtrinsic; use sr_primitives::traits::ProvideRuntimeApi; -use txpoolapi::TransactionPool; +use txpool_api::TransactionPool; /// Instantiate all RPC extensions for full node. pub fn create_full(client: Arc, pool: Arc

) -> jsonrpc_core::IoHandler where diff --git a/srml/system/rpc/Cargo.toml b/srml/system/rpc/Cargo.toml index 085dacb3b4471..6ce3461a31836 100644 --- a/srml/system/rpc/Cargo.toml +++ b/srml/system/rpc/Cargo.toml @@ -16,7 +16,7 @@ serde = { version = "1.0.101", features = ["derive"] } sr-primitives = { path = "../../../core/sr-primitives" } srml-system-rpc-runtime-api = { path = "./runtime-api" } substrate-primitives = { path = "../../../core/primitives" } -txpoolapi = { package = "substrate-transaction-pool-api", path = "../../../core/transaction-pool/api" } +txpool-api = { package = "substrate-transaction-pool-api", path = "../../../core/transaction-pool/api" } [dev-dependencies] test-client = { package = "substrate-test-runtime-client", path = "../../../core/test-runtime/client" } diff --git a/srml/system/rpc/src/lib.rs b/srml/system/rpc/src/lib.rs index 772810c246a95..52127013147c0 100644 --- a/srml/system/rpc/src/lib.rs +++ b/srml/system/rpc/src/lib.rs @@ -36,7 +36,7 @@ use sr_primitives::{ traits, }; use substrate_primitives::hexdisplay::HexDisplay; -use txpoolapi::{TransactionPool, InPoolTransaction}; +use txpool_api::{TransactionPool, InPoolTransaction}; pub use srml_system_rpc_runtime_api::AccountNonceApi; pub use self::gen_client::Client as SystemClient; From d7e67a582e9dfae2482b90bcb690aad7662b35d3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Fri, 22 Nov 2019 16:28:19 +0100 Subject: [PATCH 27/38] Clean up. --- .gitignore | 5 +--- .maintain/common.sh | 21 ------------- .maintain/update.sh | 29 ------------------ Cargo.lock | 72 ++++++++++++++++++++++++++++++++++++++++++++- 4 files changed, 72 insertions(+), 55 deletions(-) delete mode 100644 .maintain/common.sh delete mode 100755 .maintain/update.sh diff --git a/.gitignore b/.gitignore index 6c79bfaf62ed1..aadaa13912c19 100644 --- a/.gitignore +++ b/.gitignore @@ -2,14 +2,11 @@ **/*.rs.bk *.swp .wasm-binaries -polkadot/runtime/wasm/target/ -core/executor/wasm/target/ -core/test-runtime/wasm/target/ pwasm-alloc/target/ pwasm-libc/target/ pwasm-alloc/Cargo.lock pwasm-libc/Cargo.lock -node/runtime/wasm/target/ +bin/node/runtime/wasm/target/ **/._* **/.criterion/ .vscode diff --git a/.maintain/common.sh b/.maintain/common.sh deleted file mode 100644 index 8aff9acc578ec..0000000000000 --- a/.maintain/common.sh +++ /dev/null @@ -1,21 +0,0 @@ -#!/usr/bin/env bash - -ROOT=`dirname "$0"` - -# A list of directories which contain wasm projects. -SRCS=( - "core/executor/wasm" - "node/runtime/wasm" - "node-template/runtime/wasm" - "core/test-runtime/wasm" -) - -# Make pushd/popd silent. - -pushd () { - command pushd "$@" > /dev/null -} - -popd () { - command popd "$@" > /dev/null -} diff --git a/.maintain/update.sh b/.maintain/update.sh deleted file mode 100755 index a264fab43df30..0000000000000 --- a/.maintain/update.sh +++ /dev/null @@ -1,29 +0,0 @@ -#!/usr/bin/env bash - -# This script assumes that all pre-requisites are installed. - -set -e - -PROJECT_ROOT=`git rev-parse --show-toplevel` -source `dirname "$0"`/common.sh - -export CARGO_INCREMENTAL=0 - -# Save current directory. -pushd . - -cd $ROOT - -for SRC in "${SRCS[@]}" -do - echo "*** Updating and building wasm binaries in $SRC" - cd "$PROJECT_ROOT/$SRC" - - cargo update - ./build.sh "$@" - - cd - >> /dev/null -done - -# Restore initial directory. -popd diff --git a/Cargo.lock b/Cargo.lock index a2c0c6904c553..8ccee0368b474 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1265,6 +1265,15 @@ dependencies = [ "futures-sink 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "futures-channel-preview" +version = "0.3.0-alpha.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "futures-core-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-sink-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "futures-core" version = "0.3.1" @@ -1295,11 +1304,26 @@ dependencies = [ "num_cpus 1.11.1 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "futures-executor-preview" +version = "0.3.0-alpha.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "futures-core-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-util-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", + "num_cpus 1.11.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "futures-io" version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "futures-io-preview" +version = "0.3.0-alpha.19" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "futures-macro" version = "0.3.1" @@ -1311,11 +1335,29 @@ dependencies = [ "syn 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "futures-preview" +version = "0.3.0-alpha.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "futures-channel-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-core-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-executor-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-io-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-sink-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-util-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "futures-sink" version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "futures-sink-preview" +version = "0.3.0-alpha.19" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "futures-task" version = "0.3.1" @@ -1360,7 +1402,11 @@ name = "futures-util-preview" version = "0.3.0-alpha.19" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ + "futures-channel-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", "futures-core-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-io-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-sink-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", + "memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "pin-utils 0.1.0-alpha.4 (registry+https://github.com/rust-lang/crates.io-index)", "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -3239,6 +3285,7 @@ version = "2.0.0" dependencies = [ "env_logger 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", "jsonrpc-core 14.0.3 (registry+https://github.com/rust-lang/crates.io-index)", "jsonrpc-core-client 14.0.3 (registry+https://github.com/rust-lang/crates.io-index)", "jsonrpc-derive 14.0.3 (registry+https://github.com/rust-lang/crates.io-index)", @@ -3251,6 +3298,7 @@ dependencies = [ "substrate-primitives 2.0.0", "substrate-test-runtime-client 2.0.0", "substrate-transaction-pool 2.0.0", + "substrate-transaction-pool-api 2.0.0", ] [[package]] @@ -5358,6 +5406,7 @@ dependencies = [ "substrate-telemetry 2.0.0", "substrate-test-runtime-client 2.0.0", "substrate-transaction-pool 2.0.0", + "substrate-transaction-pool-api 2.0.0", ] [[package]] @@ -5982,6 +6031,7 @@ dependencies = [ "substrate-primitives 2.0.0", "substrate-test-runtime-client 2.0.0", "substrate-transaction-pool 2.0.0", + "substrate-transaction-pool-api 2.0.0", "threadpool 1.7.1 (registry+https://github.com/rust-lang/crates.io-index)", "tokio 0.1.22 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -6109,6 +6159,7 @@ dependencies = [ "substrate-state-machine 2.0.0", "substrate-test-runtime-client 2.0.0", "substrate-transaction-pool 2.0.0", + "substrate-transaction-pool-api 2.0.0", "tokio 0.1.22 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -6130,7 +6181,7 @@ dependencies = [ "sr-version 2.0.0", "substrate-primitives 2.0.0", "substrate-rpc-primitives 2.0.0", - "substrate-transaction-graph 2.0.0", + "substrate-transaction-pool-api 2.0.0", ] [[package]] @@ -6462,6 +6513,7 @@ dependencies = [ "sr-primitives 2.0.0", "substrate-primitives 2.0.0", "substrate-test-runtime 2.0.0", + "substrate-transaction-pool-api 2.0.0", ] [[package]] @@ -6479,9 +6531,22 @@ dependencies = [ "substrate-primitives 2.0.0", "substrate-test-runtime-client 2.0.0", "substrate-transaction-graph 2.0.0", + "substrate-transaction-pool-api 2.0.0", "substrate-transaction-pool-runtime-api 2.0.0", ] +[[package]] +name = "substrate-transaction-pool-api" +version = "2.0.0" +dependencies = [ + "derive_more 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-scale-codec 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.102 (registry+https://github.com/rust-lang/crates.io-index)", + "sr-primitives 2.0.0", + "substrate-primitives 2.0.0", +] + [[package]] name = "substrate-transaction-pool-runtime-api" version = "2.0.0" @@ -7857,13 +7922,18 @@ dependencies = [ "checksum futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)" = "1b980f2816d6ee8673b6517b52cb0e808a180efc92e5c19d02cdda79066703ef" "checksum futures 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b6f16056ecbb57525ff698bb955162d0cd03bee84e6241c27ff75c08d8ca5987" "checksum futures-channel 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "fcae98ca17d102fd8a3603727b9259fcf7fa4239b603d2142926189bc8999b86" +"checksum futures-channel-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)" = "d5e5f4df964fa9c1c2f8bddeb5c3611631cacd93baf810fc8bb2fb4b495c263a" "checksum futures-core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "79564c427afefab1dfb3298535b21eda083ef7935b4f0ecbfcb121f0aec10866" "checksum futures-core-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)" = "b35b6263fb1ef523c3056565fa67b1d16f0a8604ff12b11b08c25f28a734c60a" "checksum futures-cpupool 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "ab90cde24b3319636588d0c35fe03b1333857621051837ed769faefb4c2162e4" "checksum futures-executor 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1e274736563f686a837a0568b478bdabfeaec2dca794b5649b04e2fe1627c231" +"checksum futures-executor-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)" = "75236e88bd9fe88e5e8bfcd175b665d0528fe03ca4c5207fabc028c8f9d93e98" "checksum futures-io 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e676577d229e70952ab25f3945795ba5b16d63ca794ca9d2c860e5595d20b5ff" +"checksum futures-io-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)" = "f4914ae450db1921a56c91bde97a27846287d062087d4a652efc09bb3a01ebda" "checksum futures-macro 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "52e7c56c15537adb4f76d0b7a76ad131cb4d2f4f32d3b0bcabcbe1c7c5e87764" +"checksum futures-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)" = "3b1dce2a0267ada5c6ff75a8ba864b4e679a9e2aa44262af7a3b5516d530d76e" "checksum futures-sink 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "171be33efae63c2d59e6dbba34186fe0d6394fb378069a76dfd80fdcffd43c16" +"checksum futures-sink-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)" = "86f148ef6b69f75bb610d4f9a2336d4fc88c4b5b67129d1a340dd0fd362efeec" "checksum futures-task 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0bae52d6b29cf440e298856fec3965ee6fa71b06aa7495178615953fd669e5f9" "checksum futures-timer 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "878f1d2fc31355fa02ed2372e741b0c17e58373341e6a122569b4623a14a7d33" "checksum futures-timer 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a1de7508b218029b0f01662ed8f61b1c964b3ae99d6f25462d0f55a595109df6" From deaedd2f5df43f1cef652c2fd6803d4860c71c24 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Sat, 23 Nov 2019 08:12:47 +0100 Subject: [PATCH 28/38] Finalize merge. --- Cargo.lock | 63 +++---------------- bin/node-template/Cargo.toml | 3 +- bin/node/cli/Cargo.toml | 3 +- bin/node/rpc/Cargo.toml | 2 +- bin/node/rpc/src/lib.rs | 6 +- client/api/src/light.rs | 25 ++++++-- .../basic-authorship/src/basic_authorship.rs | 10 --- client/rpc/src/author/mod.rs | 11 ++-- client/service/Cargo.toml | 3 +- client/service/src/builder.rs | 2 +- client/service/test/Cargo.toml | 1 + client/transaction-pool/Cargo.toml | 5 +- client/transaction-pool/src/api.rs | 33 ++-------- client/transaction-pool/src/error.rs | 2 +- client/transaction-pool/src/maintainer.rs | 21 ++++--- palette/system/rpc/Cargo.toml | 4 +- palette/system/rpc/src/lib.rs | 2 +- primitives/transaction-pool/api/Cargo.toml | 2 +- test/utils/runtime/client/Cargo.toml | 1 + test/utils/runtime/client/src/lib.rs | 6 +- 20 files changed, 76 insertions(+), 129 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 8ccee0368b474..bf6929a6bdc77 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1265,15 +1265,6 @@ dependencies = [ "futures-sink 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "futures-channel-preview" -version = "0.3.0-alpha.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "futures-core-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-sink-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "futures-core" version = "0.3.1" @@ -1304,26 +1295,11 @@ dependencies = [ "num_cpus 1.11.1 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "futures-executor-preview" -version = "0.3.0-alpha.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "futures-core-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-util-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", - "num_cpus 1.11.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "futures-io" version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "futures-io-preview" -version = "0.3.0-alpha.19" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "futures-macro" version = "0.3.1" @@ -1335,29 +1311,11 @@ dependencies = [ "syn 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "futures-preview" -version = "0.3.0-alpha.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "futures-channel-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-core-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-executor-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-io-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-sink-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-util-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "futures-sink" version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "futures-sink-preview" -version = "0.3.0-alpha.19" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "futures-task" version = "0.3.1" @@ -1402,11 +1360,7 @@ name = "futures-util-preview" version = "0.3.0-alpha.19" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "futures-channel-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", "futures-core-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-io-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-sink-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", - "memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "pin-utils 0.1.0-alpha.4 (registry+https://github.com/rust-lang/crates.io-index)", "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2779,6 +2733,7 @@ dependencies = [ "substrate-service-test 2.0.0", "substrate-telemetry 2.0.0", "substrate-transaction-pool 2.0.0", + "substrate-transaction-pool-api 2.0.0", "tempfile 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "tokio 0.1.22 (registry+https://github.com/rust-lang/crates.io-index)", "transaction-factory 0.0.1", @@ -2839,7 +2794,7 @@ dependencies = [ "pallet-transaction-payment-rpc 2.0.0", "sr-primitives 2.0.0", "substrate-client 2.0.0", - "substrate-transaction-pool 2.0.0", + "substrate-transaction-pool-api 2.0.0", ] [[package]] @@ -2941,6 +2896,7 @@ dependencies = [ "substrate-primitives 2.0.0", "substrate-service 2.0.0", "substrate-transaction-pool 2.0.0", + "substrate-transaction-pool-api 2.0.0", "tokio 0.1.22 (registry+https://github.com/rust-lang/crates.io-index)", "trie-root 0.15.2 (registry+https://github.com/rust-lang/crates.io-index)", "vergen 3.0.4 (registry+https://github.com/rust-lang/crates.io-index)", @@ -3285,7 +3241,6 @@ version = "2.0.0" dependencies = [ "env_logger 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", "jsonrpc-core 14.0.3 (registry+https://github.com/rust-lang/crates.io-index)", "jsonrpc-core-client 14.0.3 (registry+https://github.com/rust-lang/crates.io-index)", "jsonrpc-derive 14.0.3 (registry+https://github.com/rust-lang/crates.io-index)", @@ -6315,6 +6270,7 @@ dependencies = [ "substrate-test-runtime-client 2.0.0", "substrate-tracing 2.0.0", "substrate-transaction-pool 2.0.0", + "substrate-transaction-pool-api 2.0.0", "substrate-transaction-pool-runtime-api 2.0.0", "sysinfo 0.9.6 (registry+https://github.com/rust-lang/crates.io-index)", "target_info 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -6339,6 +6295,7 @@ dependencies = [ "substrate-network 2.0.0", "substrate-primitives 2.0.0", "substrate-service 2.0.0", + "substrate-transaction-pool-api 2.0.0", "tempdir 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", "tokio 0.1.22 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -6476,6 +6433,7 @@ dependencies = [ name = "substrate-test-runtime-client" version = "2.0.0" dependencies = [ + "futures 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "parity-scale-codec 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "sr-primitives 2.0.0", "substrate-block-builder 2.0.0", @@ -6527,6 +6485,8 @@ dependencies = [ "parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", "sr-api 2.0.0", "sr-primitives 2.0.0", + "substrate-client 2.0.0", + "substrate-client-api 2.0.0", "substrate-keyring 2.0.0", "substrate-primitives 2.0.0", "substrate-test-runtime-client 2.0.0", @@ -6540,7 +6500,7 @@ name = "substrate-transaction-pool-api" version = "2.0.0" dependencies = [ "derive_more 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "parity-scale-codec 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.102 (registry+https://github.com/rust-lang/crates.io-index)", "sr-primitives 2.0.0", @@ -7922,18 +7882,13 @@ dependencies = [ "checksum futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)" = "1b980f2816d6ee8673b6517b52cb0e808a180efc92e5c19d02cdda79066703ef" "checksum futures 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b6f16056ecbb57525ff698bb955162d0cd03bee84e6241c27ff75c08d8ca5987" "checksum futures-channel 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "fcae98ca17d102fd8a3603727b9259fcf7fa4239b603d2142926189bc8999b86" -"checksum futures-channel-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)" = "d5e5f4df964fa9c1c2f8bddeb5c3611631cacd93baf810fc8bb2fb4b495c263a" "checksum futures-core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "79564c427afefab1dfb3298535b21eda083ef7935b4f0ecbfcb121f0aec10866" "checksum futures-core-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)" = "b35b6263fb1ef523c3056565fa67b1d16f0a8604ff12b11b08c25f28a734c60a" "checksum futures-cpupool 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "ab90cde24b3319636588d0c35fe03b1333857621051837ed769faefb4c2162e4" "checksum futures-executor 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1e274736563f686a837a0568b478bdabfeaec2dca794b5649b04e2fe1627c231" -"checksum futures-executor-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)" = "75236e88bd9fe88e5e8bfcd175b665d0528fe03ca4c5207fabc028c8f9d93e98" "checksum futures-io 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e676577d229e70952ab25f3945795ba5b16d63ca794ca9d2c860e5595d20b5ff" -"checksum futures-io-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)" = "f4914ae450db1921a56c91bde97a27846287d062087d4a652efc09bb3a01ebda" "checksum futures-macro 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "52e7c56c15537adb4f76d0b7a76ad131cb4d2f4f32d3b0bcabcbe1c7c5e87764" -"checksum futures-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)" = "3b1dce2a0267ada5c6ff75a8ba864b4e679a9e2aa44262af7a3b5516d530d76e" "checksum futures-sink 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "171be33efae63c2d59e6dbba34186fe0d6394fb378069a76dfd80fdcffd43c16" -"checksum futures-sink-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)" = "86f148ef6b69f75bb610d4f9a2336d4fc88c4b5b67129d1a340dd0fd362efeec" "checksum futures-task 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0bae52d6b29cf440e298856fec3965ee6fa71b06aa7495178615953fd669e5f9" "checksum futures-timer 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "878f1d2fc31355fa02ed2372e741b0c17e58373341e6a122569b4623a14a7d33" "checksum futures-timer 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a1de7508b218029b0f01662ed8f61b1c964b3ae99d6f25462d0f55a595109df6" diff --git a/bin/node-template/Cargo.toml b/bin/node-template/Cargo.toml index ff393730761bb..85e241ccb0cd9 100644 --- a/bin/node-template/Cargo.toml +++ b/bin/node-template/Cargo.toml @@ -25,7 +25,8 @@ primitives = { package = "substrate-primitives", path = "../../primitives/core" substrate-executor = { path = "../../client/executor" } substrate-service = { path = "../../client/service" } inherents = { package = "substrate-inherents", path = "../../primitives/inherents" } -transaction-pool = { package = "substrate-transaction-pool", path = "../../client/transaction-pool" } +txpool = { package = "substrate-transaction-pool", path = "../../client/transaction-pool" } +txpool-api = { package = "substrate-transaction-pool-api", path = "../../primitives/transaction-pool/api" } network = { package = "substrate-network", path = "../../client/network" } aura = { package = "substrate-consensus-aura", path = "../../client/consensus/aura" } aura-primitives = { package = "substrate-consensus-aura-primitives", path = "../../primitives/consensus/aura" } diff --git a/bin/node/cli/Cargo.toml b/bin/node/cli/Cargo.toml index a6ba2d6d9ec60..ced830666ad17 100644 --- a/bin/node/cli/Cargo.toml +++ b/bin/node/cli/Cargo.toml @@ -47,7 +47,8 @@ client-api = { package = "substrate-client-api", path = "../../../client/api" } client = { package = "substrate-client", path = "../../../client/" } inherents = { package = "substrate-inherents", path = "../../../primitives/inherents" } chain-spec = { package = "substrate-chain-spec", path = "../../../client/chain-spec" } -transaction_pool = { package = "substrate-transaction-pool", path = "../../../client/transaction-pool" } +txpool = { package = "substrate-transaction-pool", path = "../../../client/transaction-pool" } +txpool-api = { package = "substrate-transaction-pool-api", path = "../../../primitives/transaction-pool/api" } network = { package = "substrate-network", path = "../../../client/network" } babe = { package = "substrate-consensus-babe", path = "../../../client/consensus/babe" } grandpa = { package = "substrate-finality-grandpa", path = "../../../client/finality-grandpa" } diff --git a/bin/node/rpc/Cargo.toml b/bin/node/rpc/Cargo.toml index d89b805777449..925d575156db0 100644 --- a/bin/node/rpc/Cargo.toml +++ b/bin/node/rpc/Cargo.toml @@ -13,4 +13,4 @@ sr-primitives = { path = "../../../primitives/sr-primitives" } pallet-contracts-rpc = { path = "../../../palette/contracts/rpc/" } pallet-transaction-payment-rpc = { path = "../../../palette/transaction-payment/rpc/" } palette-system-rpc = { path = "../../../palette/system/rpc/" } -transaction_pool = { package = "substrate-transaction-pool", path = "../../../client/transaction-pool" } +txpool-api = { package = "substrate-transaction-pool-api", path = "../../../primitives/transaction-pool/api" } diff --git a/bin/node/rpc/src/lib.rs b/bin/node/rpc/src/lib.rs index 8217b0fce474c..7aed8bf4d69ae 100644 --- a/bin/node/rpc/src/lib.rs +++ b/bin/node/rpc/src/lib.rs @@ -47,7 +47,7 @@ pub fn create_full(client: Arc, pool: Arc

) -> jsonrpc_core::IoHan P: TransactionPool + 'static, M: jsonrpc_core::Metadata + Default, { - use palette_system_rpc::{System, SystemApi}; + use palette_system_rpc::{FullSystem, SystemApi}; use pallet_contracts_rpc::{Contracts, ContractsApi}; use pallet_transaction_payment_rpc::{TransactionPayment, TransactionPaymentApi}; @@ -75,12 +75,12 @@ pub fn create_light( C: ProvideRuntimeApi, C: client::blockchain::HeaderBackend, C: Send + Sync + 'static, - C::Api: srml_system_rpc::AccountNonceApi, + C::Api: palette_system_rpc::AccountNonceApi, P: TransactionPool + 'static, M: jsonrpc_core::Metadata + Default, F: client::light::fetcher::Fetcher + 'static, { - use srml_system_rpc::{LightSystem, SystemApi}; + use palette_system_rpc::{LightSystem, SystemApi}; let mut io = jsonrpc_core::IoHandler::default(); io.extend_with( diff --git a/client/api/src/light.rs b/client/api/src/light.rs index 433d1dbec10e6..d9a01f2e91f59 100644 --- a/client/api/src/light.rs +++ b/client/api/src/light.rs @@ -144,15 +144,30 @@ pub struct RemoteBodyRequest { /// is correct (see FetchedDataChecker) and return already checked data. pub trait Fetcher: Send + Sync { /// Remote header future. - type RemoteHeaderResult: Future> + Send + 'static; + type RemoteHeaderResult: Future> + Unpin + Send + 'static; /// Remote storage read future. - type RemoteReadResult: Future, Option>>, ClientError>> + Send + 'static; + type RemoteReadResult: Future, Option>>, + ClientError, + >> + Unpin + Send + 'static; /// Remote call result future. - type RemoteCallResult: Future, ClientError>> + Send + 'static; + type RemoteCallResult: Future, + ClientError, + >> + Unpin + Send + 'static; /// Remote changes result future. - type RemoteChangesResult: Future, u32)>, ClientError>> + Send + 'static; + type RemoteChangesResult: Future, u32)>, + ClientError, + >> + Unpin + Send + 'static; /// Remote block body result future. - type RemoteBodyResult: Future, ClientError>> + Send + 'static; + type RemoteBodyResult: Future, + ClientError, + >> + Unpin + Send + 'static; /// Fetch remote header. fn remote_header(&self, request: RemoteHeaderRequest) -> Self::RemoteHeaderResult; diff --git a/client/basic-authorship/src/basic_authorship.rs b/client/basic-authorship/src/basic_authorship.rs index 3d15612e2a1b5..5f40d4946d000 100644 --- a/client/basic-authorship/src/basic_authorship.rs +++ b/client/basic-authorship/src/basic_authorship.rs @@ -96,13 +96,8 @@ pub struct Proposer { impl consensus_common::Proposer for Proposer, A> where -<<<<<<< HEAD:core/basic-authorship/src/basic_authorship.rs A: TransactionPool, - B: client::backend::Backend + Send + Sync + 'static, -======= - A: txpool::ChainApi, B: client_api::backend::Backend + Send + Sync + 'static, ->>>>>>> master:client/basic-authorship/src/basic_authorship.rs E: CallExecutor + Send + Sync + Clone + 'static, Block: BlockT, RA: Send + Sync + 'static, @@ -126,13 +121,8 @@ where } impl Proposer, A> where -<<<<<<< HEAD:core/basic-authorship/src/basic_authorship.rs A: TransactionPool, - B: client::backend::Backend + Send + Sync + 'static, -======= - A: txpool::ChainApi, B: client_api::backend::Backend + Send + Sync + 'static, ->>>>>>> master:client/basic-authorship/src/basic_authorship.rs E: CallExecutor + Send + Sync + Clone + 'static, Block: BlockT, RA: Send + Sync + 'static, diff --git a/client/rpc/src/author/mod.rs b/client/rpc/src/author/mod.rs index 31bdc1ec39a54..256acd6460d19 100644 --- a/client/rpc/src/author/mod.rs +++ b/client/rpc/src/author/mod.rs @@ -20,7 +20,6 @@ mod tests; use std::{sync::Arc, convert::TryInto}; -use futures::future::{FutureExt, TryFutureExt}; use log::warn; use client::Client; @@ -30,7 +29,8 @@ use rpc::futures::{ Sink, Future, future::result, }; -use futures::{StreamExt as _, compat::Compat, future::ready}; +use futures::{StreamExt as _, compat::Compat}; +use futures::future::{ready, FutureExt, TryFutureExt}; use api::Subscriptions; use jsonrpc_pubsub::{typed::Subscriber, SubscriptionId}; use codec::{Encode, Decode}; @@ -76,9 +76,10 @@ impl Author { } } -impl AuthorApi, BlockHash

> for Author where - B: client_api::backend::Backend<

::Block, Blake2Hasher> + Send + Sync + 'static, - E: client_api::CallExecutor<

::Block, Blake2Hasher> + Send + Sync + 'static, +impl AuthorApi for Author where + Block: traits::Block, + B: client_api::backend::Backend + Send + Sync + 'static, + E: client_api::CallExecutor + Clone + Send + Sync + 'static, P: TransactionPool + Sync + Send + 'static, RA: ConstructRuntimeApi> + Send + Sync + 'static, Client: ProvideRuntimeApi, diff --git a/client/service/Cargo.toml b/client/service/Cargo.toml index ae04da8c26476..e26681b4fadd6 100644 --- a/client/service/Cargo.toml +++ b/client/service/Cargo.toml @@ -44,7 +44,8 @@ tx-pool-api = { package = "substrate-transaction-pool-runtime-api", path = "../. client_db = { package = "substrate-client-db", path = "../db" } codec = { package = "parity-scale-codec", version = "1.0.0" } substrate-executor = { path = "../executor" } -transaction_pool = { package = "substrate-transaction-pool", path = "../transaction-pool" } +txpool = { package = "substrate-transaction-pool", path = "../transaction-pool" } +txpool-api = { package = "substrate-transaction-pool-api", path = "../../primitives/transaction-pool/api" } rpc-servers = { package = "substrate-rpc-servers", path = "../rpc-servers" } rpc = { package = "substrate-rpc", path = "../rpc" } tel = { package = "substrate-telemetry", path = "../telemetry" } diff --git a/client/service/src/builder.rs b/client/service/src/builder.rs index 05cc2dc14226d..5faa95d847ca3 100644 --- a/client/service/src/builder.rs +++ b/client/service/src/builder.rs @@ -30,6 +30,7 @@ use consensus_common::import_queue::ImportQueue; use futures::{prelude::*, sync::mpsc}; use futures03::{ compat::Compat, + TryFutureExt, FutureExt, StreamExt, TryStreamExt, }; @@ -923,7 +924,6 @@ ServiceBuilder< let txpool = txpool.upgrade(); if let Some(txpool) = txpool.as_ref() { - use futures03::TryFutureExt; let future = txpool.maintain( &BlockId::hash(notification.hash), ¬ification.retracted, diff --git a/client/service/test/Cargo.toml b/client/service/test/Cargo.toml index 365fd87bfec86..4fe654a9afcb7 100644 --- a/client/service/test/Cargo.toml +++ b/client/service/test/Cargo.toml @@ -18,3 +18,4 @@ consensus = { package = "substrate-consensus-common", path = "../../../primitive client = { package = "substrate-client", path = "../../" } sr-primitives = { path = "../../../primitives/sr-primitives" } primitives = { package = "substrate-primitives", path = "../../../primitives/core" } +txpool_api = { package = "substrate-transaction-pool-api", path = "../../../primitives/transaction-pool/api" } diff --git a/client/transaction-pool/Cargo.toml b/client/transaction-pool/Cargo.toml index b0ed09b04dfe2..a9df8d1d312f7 100644 --- a/client/transaction-pool/Cargo.toml +++ b/client/transaction-pool/Cargo.toml @@ -7,7 +7,7 @@ edition = "2018" [dependencies] codec = { package = "parity-scale-codec", version = "1.0.0" } derive_more = "0.15.0" -futures = { version = "0.3.1", features = ["thread-pool"] } +futures = { version = "0.3.1", features = ["compat"] } log = "0.4.8" parking_lot = "0.9.0" primitives = { package = "substrate-primitives", path = "../../primitives/core" } @@ -16,6 +16,9 @@ sr-primitives = { path = "../../primitives/sr-primitives" } tx-runtime-api = { package = "substrate-transaction-pool-runtime-api", path = "../../primitives/transaction-pool/runtime-api" } txpool = { package = "substrate-transaction-graph", path = "./graph" } txpool-api = { package = "substrate-transaction-pool-api", path = "../../primitives/transaction-pool/api" } +client-api = { package = "substrate-client-api", path = "../api" } +# TODO [ToDr] USe traits instead? +client = { package = "substrate-client", path = "../" } [dev-dependencies] keyring = { package = "substrate-keyring", path = "../../primitives/keyring" } diff --git a/client/transaction-pool/src/api.rs b/client/transaction-pool/src/api.rs index 713881ef56dc4..5694681926650 100644 --- a/client/transaction-pool/src/api.rs +++ b/client/transaction-pool/src/api.rs @@ -16,38 +16,15 @@ //! Chain api required for the transaction pool. -/*use std::{ - sync::Arc, - marker::{PhantomData, Unpin}, -}; -use futures::{ - future::{ready, Future, FutureExt, Ready}, -}; -use client::{ - error::Error as ClientError, - runtime_api::TaggedTransactionQueue, - blockchain::HeaderBackend, - light::fetcher::{Fetcher, RemoteCallRequest}, -}; -use codec::{Decode, Encode}; -use txpool; -use primitives::{ - H256, - Blake2Hasher, - Hasher, -}; -use sr_primitives::{ - generic::BlockId, - traits::{self, Block as BlockT}, - transaction_validity::TransactionValidity, -}; - -use crate::error;*/ use std::{marker::PhantomData, pin::Pin, sync::Arc}; use codec::{Decode, Encode}; use futures::{channel::oneshot, executor::{ThreadPool, ThreadPoolBuilder}, future::{Future, FutureExt, ready}}; -use client::{error::Error as ClientError, blockchain::HeaderBackend, light::fetcher::{Fetcher, RemoteCallRequest}}; +use client_api::{ + error::Error as ClientError, + blockchain::HeaderBackend, + light::{Fetcher, RemoteCallRequest} +}; use primitives::{H256, Blake2Hasher, Hasher}; use sr_primitives::{generic::BlockId, traits::{self, Block as BlockT}, transaction_validity::TransactionValidity}; use tx_runtime_api::TaggedTransactionQueue; diff --git a/client/transaction-pool/src/error.rs b/client/transaction-pool/src/error.rs index a58da4d7c9d2b..575046b8214c5 100644 --- a/client/transaction-pool/src/error.rs +++ b/client/transaction-pool/src/error.rs @@ -25,7 +25,7 @@ pub enum Error { /// Pool error. Pool(txpool_api::error::Error), /// Client error. - Client(client::error::Error), + Client(client_api::error::Error), /// Error while converting a `BlockId`. BlockIdConversion(String), /// Error while calling the runtime api. diff --git a/client/transaction-pool/src/maintainer.rs b/client/transaction-pool/src/maintainer.rs index 03696d22dc148..3d4f77eb55e68 100644 --- a/client/transaction-pool/src/maintainer.rs +++ b/client/transaction-pool/src/maintainer.rs @@ -26,9 +26,10 @@ use futures::{ use log::warn; use parking_lot::Mutex; -use client::{ - Client, - light::fetcher::{Fetcher, RemoteBodyRequest}, +use client::Client; +use client_api::{ + CallExecutor, + light::{Fetcher, RemoteBodyRequest}, }; use primitives::{Blake2Hasher, H256}; use sr_primitives::{ @@ -65,10 +66,10 @@ for FullBasicPoolMaintainer where Block: BlockT, - Backend: 'static + client::backend::Backend, + Backend: 'static + client_api::backend::Backend, Client: ProvideRuntimeApi, as ProvideRuntimeApi>::Api: TaggedTransactionQueue, - Executor: 'static + Send + Sync + client::CallExecutor, + Executor: 'static + Send + Sync + CallExecutor, Api: 'static + Send + Sync, PoolApi: 'static + ChainApi, { @@ -140,10 +141,10 @@ pub struct LightBasicPoolMaintainer LightBasicPoolMaintainer where Block: BlockT, - Backend: 'static + client::backend::Backend, + Backend: 'static + client_api::backend::Backend, Client: ProvideRuntimeApi, as ProvideRuntimeApi>::Api: TaggedTransactionQueue, - Executor: 'static + Send + Sync + client::CallExecutor, + Executor: 'static + Send + Sync + CallExecutor, Api: 'static + Send + Sync, PoolApi: 'static + ChainApi, F: Fetcher + 'static, @@ -250,10 +251,10 @@ for LightBasicPoolMaintainer where Block: BlockT::Out>, - Backend: 'static + client::backend::Backend, + Backend: 'static + client_api::backend::Backend, Client: ProvideRuntimeApi, as ProvideRuntimeApi>::Api: TaggedTransactionQueue, - Executor: 'static + Send + Sync + client::CallExecutor, + Executor: 'static + Send + Sync + CallExecutor, Api: 'static + Send + Sync, PoolApi: 'static + ChainApi, F: Fetcher + 'static, @@ -272,7 +273,7 @@ where return Box::new(ready(())); } let header = self.client.header(id) - .and_then(|h| h.ok_or(client::error::Error::UnknownBlock(format!("{}", id)))); + .and_then(|h| h.ok_or(client_api::error::Error::UnknownBlock(format!("{}", id)))); let header = match header { Ok(header) => header, Err(err) => { diff --git a/palette/system/rpc/Cargo.toml b/palette/system/rpc/Cargo.toml index 092472863a7d7..21fdb3be9ea1b 100644 --- a/palette/system/rpc/Cargo.toml +++ b/palette/system/rpc/Cargo.toml @@ -7,14 +7,14 @@ edition = "2018" [dependencies] client = { package = "substrate-client", path = "../../../client/" } codec = { package = "parity-scale-codec", version = "1.0.0" } -futures03 = { package = "futures-preview", version = "=0.3.0-alpha.19" } +futures = "0.3.1" jsonrpc-core = "14.0.3" jsonrpc-core-client = "14.0.3" jsonrpc-derive = "14.0.3" log = "0.4.8" +palette-system-rpc-runtime-api = { path = "./runtime-api" } serde = { version = "1.0.101", features = ["derive"] } sr-primitives = { path = "../../../primitives/sr-primitives" } -palette-system-rpc-runtime-api = { path = "./runtime-api" } substrate-primitives = { path = "../../../primitives/core" } txpool-api = { package = "substrate-transaction-pool-api", path = "../../../primitives/transaction-pool/api" } diff --git a/palette/system/rpc/src/lib.rs b/palette/system/rpc/src/lib.rs index 697bfe5680af7..0b6eacce8b4c8 100644 --- a/palette/system/rpc/src/lib.rs +++ b/palette/system/rpc/src/lib.rs @@ -30,7 +30,7 @@ use jsonrpc_core::{ futures::future::{result, Future}, }; use jsonrpc_derive::rpc; -use futures03::future::{ready, TryFutureExt}; +use futures::future::{ready, TryFutureExt}; use sr_primitives::{ generic::BlockId, traits, diff --git a/primitives/transaction-pool/api/Cargo.toml b/primitives/transaction-pool/api/Cargo.toml index 258cffcb0aaa9..944b249530bf8 100644 --- a/primitives/transaction-pool/api/Cargo.toml +++ b/primitives/transaction-pool/api/Cargo.toml @@ -6,7 +6,7 @@ edition = "2018" [dependencies] derive_more = "0.15.0" -futures-preview = "0.3.0-alpha.19" +futures = "0.3.1" serde = { version = "1.0.101", features = ["derive"] } codec = { package = "parity-scale-codec", version = "1.0.0" } primitives = { package = "substrate-primitives", path = "../../core" } diff --git a/test/utils/runtime/client/Cargo.toml b/test/utils/runtime/client/Cargo.toml index 68f5820062100..94f6dc3efc356 100644 --- a/test/utils/runtime/client/Cargo.toml +++ b/test/utils/runtime/client/Cargo.toml @@ -13,3 +13,4 @@ sr-primitives = { path = "../../../../primitives/sr-primitives" } codec = { package = "parity-scale-codec", version = "1.0.0" } client-api = { package = "substrate-client-api", path = "../../../../client/api" } client = { package = "substrate-client", path = "../../../../client/" } +futures = "0.3.1" diff --git a/test/utils/runtime/client/src/lib.rs b/test/utils/runtime/client/src/lib.rs index f60058eace6d3..4f8888ea3d784 100644 --- a/test/utils/runtime/client/src/lib.rs +++ b/test/utils/runtime/client/src/lib.rs @@ -259,7 +259,7 @@ impl TestClientBuilderExt for TestClientBuilder< type MaybeFetcherCallback = Option Result + Send + Sync>>; /// Type of fetcher future result. -type FetcherFutureResult = futures03::future::Ready>; +type FetcherFutureResult = futures::future::Ready>; /// Implementation of light client fetcher used in tests. #[derive(Default)] @@ -313,7 +313,7 @@ impl Fetcher for LightFetcher { fn remote_call(&self, req: RemoteCallRequest) -> Self::RemoteCallResult { match self.call { - Some(ref call) => futures03::future::ready(call(req)), + Some(ref call) => futures::future::ready(call(req)), None => unimplemented!(), } } @@ -324,7 +324,7 @@ impl Fetcher for LightFetcher { fn remote_body(&self, req: RemoteBodyRequest) -> Self::RemoteBodyResult { match self.body { - Some(ref body) => futures03::future::ready(body(req)), + Some(ref body) => futures::future::ready(body(req)), None => unimplemented!(), } } From b6b4473571ba60bb0c2fa05afd726e7fc2ed00c2 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Mon, 25 Nov 2019 11:37:03 +0300 Subject: [PATCH 29/38] post-merge fix --- client/offchain/src/lib.rs | 21 ++++++++++++++++++--- client/transaction-pool/src/lib.rs | 27 --------------------------- 2 files changed, 18 insertions(+), 30 deletions(-) diff --git a/client/offchain/src/lib.rs b/client/offchain/src/lib.rs index 3c868cb5852f6..3ca279e0df816 100644 --- a/client/offchain/src/lib.rs +++ b/client/offchain/src/lib.rs @@ -147,6 +147,7 @@ mod tests { use super::*; use std::sync::Arc; use network::{Multiaddr, PeerId}; + use test_client::runtime::Block; use txpool::{BasicPool, FullChainApi}; use txpool_api::{TransactionPool, InPoolTransaction}; @@ -162,12 +163,26 @@ mod tests { } } + struct TestPool(BasicPool, Block>); + + impl sr_primitives::offchain::TransactionPool for TestPool { + fn submit_at( + &self, + at: &BlockId, + extrinsic: ::Extrinsic, + ) -> Result<(), ()> { + futures::executor::block_on(self.0.submit_one(&at, extrinsic)) + .map(|_| ()) + .map_err(|_| ()) + } + } + #[test] fn should_call_into_runtime_and_produce_extrinsic() { // given let _ = env_logger::try_init(); let client = Arc::new(test_client::new()); - let pool = Arc::new(BasicPool::new(Default::default(), FullChainApi::new(client.clone()))); + let pool = Arc::new(TestPool(BasicPool::new(Default::default(), FullChainApi::new(client.clone())))); client.execution_extensions() .register_transaction_pool(Arc::downgrade(&pool.clone()) as _); let db = client_db::offchain::LocalStorage::new_test(); @@ -178,7 +193,7 @@ mod tests { futures::executor::block_on(offchain.on_block_imported(&0u64, network_state, false)); // then - assert_eq!(pool.status().ready, 1); - assert_eq!(pool.ready().next().unwrap().is_propagateable(), false); + assert_eq!(pool.0.status().ready, 1); + assert_eq!(pool.0.ready().next().unwrap().is_propagateable(), false); } } diff --git a/client/transaction-pool/src/lib.rs b/client/transaction-pool/src/lib.rs index 7084c3ab35f6a..1499ab26d4bfc 100644 --- a/client/transaction-pool/src/lib.rs +++ b/client/transaction-pool/src/lib.rs @@ -130,30 +130,3 @@ impl TransactionPool for BasicPool self.pool.on_broadcasted(propagations) } } - -impl sr_primitives::offchain::TransactionPool for BasicPool - where - Block: BlockT, - PoolApi: 'static + txpool::ChainApi, -{ - fn submit_at( - &self, - at: &BlockId, - extrinsic: ::Extrinsic, - ) -> Result<(), ()> { - log::debug!( - target: "txpool", - "(offchain call) Submitting a transaction to the pool: {:?}", - extrinsic - ); - - let result = futures::executor::block_on(self.submit_one(&at, extrinsic)); - - result.map(|_| ()) - .map_err(|e| log::warn!( - target: "txpool", - "(offchain call) Error submitting a transaction to the pool: {:?}", - e - )) - } -} From d36edbcf2d5861a64b63394e1f3eee39284b6b77 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Mon, 25 Nov 2019 10:51:08 +0100 Subject: [PATCH 30/38] Move transaction pool api to primitives directly. --- Cargo.toml | 2 +- bin/node-template/Cargo.toml | 2 +- bin/node/cli/Cargo.toml | 2 +- bin/node/rpc/Cargo.toml | 2 +- client/basic-authorship/Cargo.toml | 2 +- client/offchain/Cargo.toml | 2 +- client/rpc/Cargo.toml | 2 +- client/rpc/api/Cargo.toml | 2 +- client/service/Cargo.toml | 2 +- client/service/test/Cargo.toml | 2 +- client/transaction-pool/Cargo.toml | 2 +- client/transaction-pool/graph/Cargo.toml | 2 +- frame/system/rpc/Cargo.toml | 2 +- primitives/transaction-pool/{api => }/Cargo.toml | 4 ++-- primitives/transaction-pool/{api => }/src/error.rs | 0 primitives/transaction-pool/{api => }/src/lib.rs | 0 16 files changed, 15 insertions(+), 15 deletions(-) rename primitives/transaction-pool/{api => }/Cargo.toml (72%) rename primitives/transaction-pool/{api => }/src/error.rs (100%) rename primitives/transaction-pool/{api => }/src/lib.rs (100%) diff --git a/Cargo.toml b/Cargo.toml index 9a1e7d21353df..ec2f33456fca9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -128,7 +128,7 @@ members = [ "primitives/sr-version", "primitives/state-machine", "primitives/timestamp", - "primitives/transaction-pool/api", + "primitives/transaction-pool", "primitives/transaction-pool/runtime-api", "primitives/trie", "primitives/wasm-interface", diff --git a/bin/node-template/Cargo.toml b/bin/node-template/Cargo.toml index 85e241ccb0cd9..300b8f704d1d4 100644 --- a/bin/node-template/Cargo.toml +++ b/bin/node-template/Cargo.toml @@ -26,7 +26,7 @@ substrate-executor = { path = "../../client/executor" } substrate-service = { path = "../../client/service" } inherents = { package = "substrate-inherents", path = "../../primitives/inherents" } txpool = { package = "substrate-transaction-pool", path = "../../client/transaction-pool" } -txpool-api = { package = "substrate-transaction-pool-api", path = "../../primitives/transaction-pool/api" } +txpool-api = { package = "substrate-transaction-pool-api", path = "../../primitives/transaction-pool" } network = { package = "substrate-network", path = "../../client/network" } aura = { package = "substrate-consensus-aura", path = "../../client/consensus/aura" } aura-primitives = { package = "substrate-consensus-aura-primitives", path = "../../primitives/consensus/aura" } diff --git a/bin/node/cli/Cargo.toml b/bin/node/cli/Cargo.toml index 3eb541460a876..b5b80ad9b346c 100644 --- a/bin/node/cli/Cargo.toml +++ b/bin/node/cli/Cargo.toml @@ -48,7 +48,7 @@ client = { package = "substrate-client", path = "../../../client/" } inherents = { package = "substrate-inherents", path = "../../../primitives/inherents" } chain-spec = { package = "substrate-chain-spec", path = "../../../client/chain-spec" } txpool = { package = "substrate-transaction-pool", path = "../../../client/transaction-pool" } -txpool-api = { package = "substrate-transaction-pool-api", path = "../../../primitives/transaction-pool/api" } +txpool-api = { package = "substrate-transaction-pool-api", path = "../../../primitives/transaction-pool" } network = { package = "substrate-network", path = "../../../client/network" } babe = { package = "substrate-consensus-babe", path = "../../../client/consensus/babe" } grandpa = { package = "substrate-finality-grandpa", path = "../../../client/finality-grandpa" } diff --git a/bin/node/rpc/Cargo.toml b/bin/node/rpc/Cargo.toml index fb0d34590690e..bce7030e6740d 100644 --- a/bin/node/rpc/Cargo.toml +++ b/bin/node/rpc/Cargo.toml @@ -13,4 +13,4 @@ sr-primitives = { path = "../../../primitives/sr-primitives" } pallet-contracts-rpc = { path = "../../../frame/contracts/rpc/" } pallet-transaction-payment-rpc = { path = "../../../frame/transaction-payment/rpc/" } frame-system-rpc = { path = "../../../frame/system/rpc/" } -txpool-api = { package = "substrate-transaction-pool-api", path = "../../../primitives/transaction-pool/api" } +txpool-api = { package = "substrate-transaction-pool-api", path = "../../../primitives/transaction-pool" } diff --git a/client/basic-authorship/Cargo.toml b/client/basic-authorship/Cargo.toml index c9c725cdde71f..c7cfad3ad51c7 100644 --- a/client/basic-authorship/Cargo.toml +++ b/client/basic-authorship/Cargo.toml @@ -15,7 +15,7 @@ client-api = { package = "substrate-client-api", path = "../api" } consensus_common = { package = "substrate-consensus-common", path = "../../primitives/consensus/common" } inherents = { package = "substrate-inherents", path = "../../primitives/inherents" } substrate-telemetry = { path = "../telemetry" } -txpool-api = { package = "substrate-transaction-pool-api", path = "../../primitives/transaction-pool/api" } +txpool-api = { package = "substrate-transaction-pool-api", path = "../../primitives/transaction-pool" } block-builder = { package = "substrate-block-builder", path = "../block-builder" } [dev-dependencies] diff --git a/client/offchain/Cargo.toml b/client/offchain/Cargo.toml index 9448216254030..0a8058765964f 100644 --- a/client/offchain/Cargo.toml +++ b/client/offchain/Cargo.toml @@ -36,7 +36,7 @@ env_logger = "0.7.0" test-client = { package = "substrate-test-runtime-client", path = "../../test/utils/runtime/client" } tokio = "0.1.22" txpool = { package = "substrate-transaction-pool", path = "../../client/transaction-pool" } -txpool-api = { package = "substrate-transaction-pool-api", path = "../../primitives/transaction-pool/api" } +txpool-api = { package = "substrate-transaction-pool-api", path = "../../primitives/transaction-pool" } [features] default = [] diff --git a/client/rpc/Cargo.toml b/client/rpc/Cargo.toml index 60beb9f5f9faa..08ec1fd579b90 100644 --- a/client/rpc/Cargo.toml +++ b/client/rpc/Cargo.toml @@ -23,7 +23,7 @@ rpc-primitives = { package = "substrate-rpc-primitives", path = "../../primitive state_machine = { package = "substrate-state-machine", path = "../../primitives/state-machine" } substrate-executor = { path = "../executor" } substrate-keystore = { path = "../keystore" } -txpool-api = { package = "substrate-transaction-pool-api", path = "../../primitives/transaction-pool/api" } +txpool-api = { package = "substrate-transaction-pool-api", path = "../../primitives/transaction-pool" } hash-db = { version = "0.15.2", default-features = false } parking_lot = { version = "0.9.0" } diff --git a/client/rpc/api/Cargo.toml b/client/rpc/api/Cargo.toml index d1540d1d4e473..d648f94aea4a6 100644 --- a/client/rpc/api/Cargo.toml +++ b/client/rpc/api/Cargo.toml @@ -18,5 +18,5 @@ primitives = { package = "substrate-primitives", path = "../../../primitives/cor runtime_version = { package = "sr-version", path = "../../../primitives/sr-version" } serde = { version = "1.0.101", features = ["derive"] } serde_json = "1.0.41" -txpool-api = { package = "substrate-transaction-pool-api", path = "../../../primitives/transaction-pool/api" } +txpool-api = { package = "substrate-transaction-pool-api", path = "../../../primitives/transaction-pool" } rpc-primitives = { package = "substrate-rpc-primitives", path = "../../../primitives/rpc" } diff --git a/client/service/Cargo.toml b/client/service/Cargo.toml index a88c2cdd5c109..9fb1f30f26a43 100644 --- a/client/service/Cargo.toml +++ b/client/service/Cargo.toml @@ -45,7 +45,7 @@ client_db = { package = "substrate-client-db", path = "../db" } codec = { package = "parity-scale-codec", version = "1.0.0" } substrate-executor = { path = "../executor" } txpool = { package = "substrate-transaction-pool", path = "../transaction-pool" } -txpool-api = { package = "substrate-transaction-pool-api", path = "../../primitives/transaction-pool/api" } +txpool-api = { package = "substrate-transaction-pool-api", path = "../../primitives/transaction-pool" } rpc-servers = { package = "substrate-rpc-servers", path = "../rpc-servers" } rpc = { package = "substrate-rpc", path = "../rpc" } tel = { package = "substrate-telemetry", path = "../telemetry" } diff --git a/client/service/test/Cargo.toml b/client/service/test/Cargo.toml index 4fe654a9afcb7..612ec80343708 100644 --- a/client/service/test/Cargo.toml +++ b/client/service/test/Cargo.toml @@ -18,4 +18,4 @@ consensus = { package = "substrate-consensus-common", path = "../../../primitive client = { package = "substrate-client", path = "../../" } sr-primitives = { path = "../../../primitives/sr-primitives" } primitives = { package = "substrate-primitives", path = "../../../primitives/core" } -txpool_api = { package = "substrate-transaction-pool-api", path = "../../../primitives/transaction-pool/api" } +txpool_api = { package = "substrate-transaction-pool-api", path = "../../../primitives/transaction-pool" } diff --git a/client/transaction-pool/Cargo.toml b/client/transaction-pool/Cargo.toml index a9df8d1d312f7..c5364bb7d581e 100644 --- a/client/transaction-pool/Cargo.toml +++ b/client/transaction-pool/Cargo.toml @@ -15,7 +15,7 @@ sr-api = { path = "../../primitives/sr-api" } sr-primitives = { path = "../../primitives/sr-primitives" } tx-runtime-api = { package = "substrate-transaction-pool-runtime-api", path = "../../primitives/transaction-pool/runtime-api" } txpool = { package = "substrate-transaction-graph", path = "./graph" } -txpool-api = { package = "substrate-transaction-pool-api", path = "../../primitives/transaction-pool/api" } +txpool-api = { package = "substrate-transaction-pool-api", path = "../../primitives/transaction-pool" } client-api = { package = "substrate-client-api", path = "../api" } # TODO [ToDr] USe traits instead? client = { package = "substrate-client", path = "../" } diff --git a/client/transaction-pool/graph/Cargo.toml b/client/transaction-pool/graph/Cargo.toml index 3055a5a931523..c2d833af923e4 100644 --- a/client/transaction-pool/graph/Cargo.toml +++ b/client/transaction-pool/graph/Cargo.toml @@ -12,7 +12,7 @@ parking_lot = "0.9.0" serde = { version = "1.0.101", features = ["derive"] } primitives = { package = "substrate-primitives", path = "../../../primitives/core" } sr-primitives = { path = "../../../primitives/sr-primitives" } -txpool-api = { package = "substrate-transaction-pool-api", path = "../../../primitives/transaction-pool/api" } +txpool-api = { package = "substrate-transaction-pool-api", path = "../../../primitives/transaction-pool" } [dev-dependencies] assert_matches = "1.3.0" diff --git a/frame/system/rpc/Cargo.toml b/frame/system/rpc/Cargo.toml index f2f586ce60efe..0d7cb819f3cb5 100644 --- a/frame/system/rpc/Cargo.toml +++ b/frame/system/rpc/Cargo.toml @@ -16,7 +16,7 @@ serde = { version = "1.0.101", features = ["derive"] } sr-primitives = { path = "../../../primitives/sr-primitives" } frame-system-rpc-runtime-api = { path = "./runtime-api" } substrate-primitives = { path = "../../../primitives/core" } -txpool-api = { package = "substrate-transaction-pool-api", path = "../../../primitives/transaction-pool/api" } +txpool-api = { package = "substrate-transaction-pool-api", path = "../../../primitives/transaction-pool" } [dev-dependencies] test-client = { package = "substrate-test-runtime-client", path = "../../../test/utils/runtime/client" } diff --git a/primitives/transaction-pool/api/Cargo.toml b/primitives/transaction-pool/Cargo.toml similarity index 72% rename from primitives/transaction-pool/api/Cargo.toml rename to primitives/transaction-pool/Cargo.toml index 921f7bf2ec94a..8f29c37d88216 100644 --- a/primitives/transaction-pool/api/Cargo.toml +++ b/primitives/transaction-pool/Cargo.toml @@ -10,5 +10,5 @@ futures = "0.3.1" log = "0.4.8" serde = { version = "1.0.101", features = ["derive"] } codec = { package = "parity-scale-codec", version = "1.0.0" } -primitives = { package = "substrate-primitives", path = "../../core" } -sr-primitives = { path = "../../sr-primitives" } +primitives = { package = "substrate-primitives", path = "../core" } +sr-primitives = { path = "../sr-primitives" } diff --git a/primitives/transaction-pool/api/src/error.rs b/primitives/transaction-pool/src/error.rs similarity index 100% rename from primitives/transaction-pool/api/src/error.rs rename to primitives/transaction-pool/src/error.rs diff --git a/primitives/transaction-pool/api/src/lib.rs b/primitives/transaction-pool/src/lib.rs similarity index 100% rename from primitives/transaction-pool/api/src/lib.rs rename to primitives/transaction-pool/src/lib.rs From 53b86fc4c707599060155e450ece9b4ab568a35c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Mon, 25 Nov 2019 11:47:35 +0100 Subject: [PATCH 31/38] Consistent naming for txpool-runtime-api --- bin/node-template/runtime/Cargo.toml | 4 +- bin/node-template/runtime/src/lib.rs | 2 +- bin/node/runtime/Cargo.toml | 4 +- bin/node/runtime/src/lib.rs | 2 +- client/service/Cargo.toml | 2 +- client/service/src/builder.rs | 4 +- client/service/test/Cargo.toml | 2 +- client/transaction-pool/Cargo.toml | 2 +- client/transaction-pool/graph/src/listener.rs | 2 +- client/transaction-pool/src/api.rs | 2 +- client/transaction-pool/src/maintainer.rs | 2 +- docs/CODEOWNERS | 1 + test/utils/primitives/Cargo.toml | 50 ------------------- test/utils/primitives/src/lib.rs | 2 +- test/utils/runtime/Cargo.toml | 4 +- test/utils/runtime/src/lib.rs | 4 +- 16 files changed, 20 insertions(+), 69 deletions(-) diff --git a/bin/node-template/runtime/Cargo.toml b/bin/node-template/runtime/Cargo.toml index f71c238d4c524..9a2cad17d02cf 100644 --- a/bin/node-template/runtime/Cargo.toml +++ b/bin/node-template/runtime/Cargo.toml @@ -29,7 +29,7 @@ support = { package = "frame-support", path = "../../../frame/support", default- system = { package = "frame-system", path = "../../../frame/system", default-features = false } timestamp = { package = "pallet-timestamp", path = "../../../frame/timestamp", default-features = false } transaction-payment = { package = "pallet-transaction-payment", path = "../../../frame/transaction-payment", default-features = false } -tx-pool-api = { package = "substrate-transaction-pool-runtime-api", path = "../../../primitives/transaction-pool/runtime-api", default-features = false } +txpool-runtime-api = { package = "substrate-transaction-pool-runtime-api", path = "../../../primitives/transaction-pool/runtime-api", default-features = false } version = { package = "sr-version", path = "../../../primitives/sr-version", default-features = false } [build-dependencies] @@ -62,6 +62,6 @@ std = [ "system/std", "timestamp/std", "transaction-payment/std", - "tx-pool-api/std", + "txpool-runtime-api/std", "version/std", ] diff --git a/bin/node-template/runtime/src/lib.rs b/bin/node-template/runtime/src/lib.rs index 170874bfcbd54..1cb14f52bd06c 100644 --- a/bin/node-template/runtime/src/lib.rs +++ b/bin/node-template/runtime/src/lib.rs @@ -328,7 +328,7 @@ impl_runtime_apis! { } } - impl tx_pool_api::TaggedTransactionQueue for Runtime { + impl txpool_runtime_api::TaggedTransactionQueue for Runtime { fn validate_transaction(tx: ::Extrinsic) -> TransactionValidity { Executive::validate_transaction(tx) } diff --git a/bin/node/runtime/Cargo.toml b/bin/node/runtime/Cargo.toml index 3844fa336fd69..a94923475a2da 100644 --- a/bin/node/runtime/Cargo.toml +++ b/bin/node/runtime/Cargo.toml @@ -27,7 +27,7 @@ sr-primitives = { path = "../../../primitives/sr-primitives", default-features = sr-staking-primitives = { path = "../../../primitives/sr-staking-primitives", default-features = false } substrate-keyring = { path = "../../../primitives/keyring", optional = true } substrate-session = { path = "../../../primitives/session", default-features = false } -tx-pool-api = { package = "substrate-transaction-pool-runtime-api", path = "../../../primitives/transaction-pool/runtime-api", default-features = false } +txpool-runtime-api = { package = "substrate-transaction-pool-runtime-api", path = "../../../primitives/transaction-pool/runtime-api", default-features = false } version = { package = "sr-version", path = "../../../primitives/sr-version", default-features = false } # frame dependencies @@ -116,7 +116,7 @@ std = [ "transaction-payment-rpc-runtime-api/std", "transaction-payment/std", "treasury/std", - "tx-pool-api/std", + "txpool-runtime-api/std", "utility/std", "version/std", ] diff --git a/bin/node/runtime/src/lib.rs b/bin/node/runtime/src/lib.rs index fbb690a622e29..5ae80dfd15e13 100644 --- a/bin/node/runtime/src/lib.rs +++ b/bin/node/runtime/src/lib.rs @@ -605,7 +605,7 @@ impl_runtime_apis! { } } - impl tx_pool_api::TaggedTransactionQueue for Runtime { + impl txpool_runtime_api::TaggedTransactionQueue for Runtime { fn validate_transaction(tx: ::Extrinsic) -> TransactionValidity { Executive::validate_transaction(tx) } diff --git a/client/service/Cargo.toml b/client/service/Cargo.toml index 9fb1f30f26a43..d6107d96678df 100644 --- a/client/service/Cargo.toml +++ b/client/service/Cargo.toml @@ -40,7 +40,7 @@ chain-spec = { package = "substrate-chain-spec", path = "../chain-spec" } client-api = { package = "substrate-client-api", path = "../api" } client = { package = "substrate-client", path = "../" } sr-api = { path = "../../primitives/sr-api" } -tx-pool-api = { package = "substrate-transaction-pool-runtime-api", path = "../../primitives/transaction-pool/runtime-api" } +txpool-runtime-api = { package = "substrate-transaction-pool-runtime-api", path = "../../primitives/transaction-pool/runtime-api" } client_db = { package = "substrate-client-db", path = "../db" } codec = { package = "parity-scale-codec", version = "1.0.0" } substrate-executor = { path = "../executor" } diff --git a/client/service/src/builder.rs b/client/service/src/builder.rs index 085d580e3e475..04c480c71edbc 100644 --- a/client/service/src/builder.rs +++ b/client/service/src/builder.rs @@ -786,7 +786,7 @@ ServiceBuilder< as ProvideRuntimeApi>::Api: sr_api::Metadata + offchain::OffchainWorkerApi + - tx_pool_api::TaggedTransactionQueue + + txpool_runtime_api::TaggedTransactionQueue + session::SessionKeys + sr_api::ApiExt, TBl: BlockT::Out>, @@ -1186,7 +1186,7 @@ ServiceBuilder< let _ = to_spawn_tx.unbounded_send(Box::new(future)); } - + // Instrumentation if let Some(tracing_targets) = config.tracing_targets.as_ref() { let subscriber = substrate_tracing::ProfilingSubscriber::new( diff --git a/client/service/test/Cargo.toml b/client/service/test/Cargo.toml index 612ec80343708..295747ac18101 100644 --- a/client/service/test/Cargo.toml +++ b/client/service/test/Cargo.toml @@ -18,4 +18,4 @@ consensus = { package = "substrate-consensus-common", path = "../../../primitive client = { package = "substrate-client", path = "../../" } sr-primitives = { path = "../../../primitives/sr-primitives" } primitives = { package = "substrate-primitives", path = "../../../primitives/core" } -txpool_api = { package = "substrate-transaction-pool-api", path = "../../../primitives/transaction-pool" } +txpool-api = { package = "substrate-transaction-pool-api", path = "../../../primitives/transaction-pool" } diff --git a/client/transaction-pool/Cargo.toml b/client/transaction-pool/Cargo.toml index c5364bb7d581e..8202960eab7ba 100644 --- a/client/transaction-pool/Cargo.toml +++ b/client/transaction-pool/Cargo.toml @@ -13,9 +13,9 @@ parking_lot = "0.9.0" primitives = { package = "substrate-primitives", path = "../../primitives/core" } sr-api = { path = "../../primitives/sr-api" } sr-primitives = { path = "../../primitives/sr-primitives" } -tx-runtime-api = { package = "substrate-transaction-pool-runtime-api", path = "../../primitives/transaction-pool/runtime-api" } txpool = { package = "substrate-transaction-graph", path = "./graph" } txpool-api = { package = "substrate-transaction-pool-api", path = "../../primitives/transaction-pool" } +txpool-runtime-api = { package = "substrate-transaction-pool-runtime-api", path = "../../primitives/transaction-pool/runtime-api" } client-api = { package = "substrate-client-api", path = "../api" } # TODO [ToDr] USe traits instead? client = { package = "substrate-client", path = "../" } diff --git a/client/transaction-pool/graph/src/listener.rs b/client/transaction-pool/graph/src/listener.rs index a96c31544fc75..f9b71555e264f 100644 --- a/client/transaction-pool/graph/src/listener.rs +++ b/client/transaction-pool/graph/src/listener.rs @@ -92,7 +92,7 @@ impl Listene /// Transaction was removed as invalid. pub fn invalid(&mut self, tx: &H) { - warn!(target: "transaction-pool", "Extrinsic invalid: {:?}", tx); + warn!(target: "txpool", "Extrinsic invalid: {:?}", tx); self.fire(tx, |watcher| watcher.invalid()); } diff --git a/client/transaction-pool/src/api.rs b/client/transaction-pool/src/api.rs index 5694681926650..552a998a95f99 100644 --- a/client/transaction-pool/src/api.rs +++ b/client/transaction-pool/src/api.rs @@ -27,7 +27,7 @@ use client_api::{ }; use primitives::{H256, Blake2Hasher, Hasher}; use sr_primitives::{generic::BlockId, traits::{self, Block as BlockT}, transaction_validity::TransactionValidity}; -use tx_runtime_api::TaggedTransactionQueue; +use txpool_runtime_api::TaggedTransactionQueue; use crate::error::{self, Error}; diff --git a/client/transaction-pool/src/maintainer.rs b/client/transaction-pool/src/maintainer.rs index 3d4f77eb55e68..9a0153ff704ce 100644 --- a/client/transaction-pool/src/maintainer.rs +++ b/client/transaction-pool/src/maintainer.rs @@ -37,7 +37,7 @@ use sr_primitives::{ traits::{Block as BlockT, Extrinsic, Header, NumberFor, ProvideRuntimeApi, SimpleArithmetic}, }; use txpool_api::TransactionPoolMaintainer; -use tx_runtime_api::TaggedTransactionQueue; +use txpool_runtime_api::TaggedTransactionQueue; use txpool::{self, ChainApi}; diff --git a/docs/CODEOWNERS b/docs/CODEOWNERS index 5ad126c3f6503..29f510a55661d 100644 --- a/docs/CODEOWNERS +++ b/docs/CODEOWNERS @@ -28,6 +28,7 @@ # Transaction pool /client/transaction-pool/ @tomusdrw +/primitives/transaction-pool/ @tomusdrw # Offchain /client/offchain/ @tomusdrw diff --git a/test/utils/primitives/Cargo.toml b/test/utils/primitives/Cargo.toml index d82226d347aa1..92917fdd265e6 100644 --- a/test/utils/primitives/Cargo.toml +++ b/test/utils/primitives/Cargo.toml @@ -7,31 +7,9 @@ edition = "2018" [dependencies] app-crypto = { package = "substrate-application-crypto", path = "../../../primitives/application-crypto", default-features = false } codec = { package = "parity-scale-codec", version = "1.0.0", default-features = false, features = ["derive"] } -# aura-primitives = { package = "substrate-consensus-aura-primitives", path = "../../../primitives/consensus/aura", default-features = false } -# babe-primitives = { package = "substrate-consensus-babe-primitives", path = "../../../primitives/consensus/babe", default-features = false } -# block-builder-api = { package = "substrate-block-builder-runtime-api", path = "../../../primitives/block-builder/runtime-api", default-features = false } -# inherents = { package = "substrate-inherents", path = "../../../primitives/inherents", default-features = false } -# log = { version = "0.4.8", optional = true } -# memory-db = { version = "0.15.2", default-features = false } -# offchain-primitives = { package = "substrate-offchain-primitives", path = "../../../primitives/offchain", default-features = false} primitives = { package = "substrate-primitives", path = "../../../primitives/core", default-features = false } -# rstd = { package = "sr-std", path = "../../../primitives/sr-std", default-features = false } -# runtime-interface = { package = "substrate-runtime-interface", path = "../../../primitives/runtime-interface", default-features = false} -# runtime_io = { package = "sr-io", path = "../../../primitives/sr-io", default-features = false } -# runtime_support = { package = "frame-support", path = "../../../frame/support", default-features = false } -# runtime_version = { package = "sr-version", path = "../../../primitives/sr-version", default-features = false } serde = { version = "1.0.101", optional = true, features = ["derive"] } -# session = { package = "substrate-session", path = "../../../primitives/session", default-features = false } -# sr-api = { path = "../../../primitives/sr-api", default-features = false } sr-primitives = { path = "../../../primitives/sr-primitives", default-features = false } -# pallet-babe = { path = "../../../frame/babe", default-features = false } -# frame-system = { path = "../../../frame/system", default-features = false } -# frame-system-rpc-runtime-api = { path = "../../../frame/system/rpc/runtime-api", default-features = false } -# pallet-timestamp = { path = "../../../frame/timestamp", default-features = false } -# substrate-client = { path = "../../../client", optional = true } -# substrate-trie = { path = "../../../primitives/trie", default-features = false } -# transaction-pool-api = { package = "substrate-transaction-pool-runtime-api", path = "../../../primitives/transaction-pool/runtime-api", default-features = false } -# trie-db = { version = "0.15.2", default-features = false } [features] default = [ @@ -39,33 +17,5 @@ default = [ ] std = [ "app-crypto/std", - # "aura-primitives/std", - # "babe-primitives/std", - # "block-builder-api/std", - # "codec/std", - # "executive/std", - # "inherents/std", - # "keyring", - # "log", - # "memory-db/std", - # "offchain-primitives/std", - # "primitives/std", - # "primitives/std", - # "rstd/std", - # "runtime-interface/std", - # "runtime_io/std", - # "runtime_support/std", - # "runtime_version/std", "serde", - # "session/std", - # "sr-api/std", - # "sr-primitives/std", - # "pallet-babe/std", - # "frame-system-rpc-runtime-api/std", - # "frame-system/std", - # "pallet-timestamp/std", - # "substrate-client", - # "substrate-trie/std", - # "transaction-pool-api/std", - # "trie-db/std", ] diff --git a/test/utils/primitives/src/lib.rs b/test/utils/primitives/src/lib.rs index d30b9eabf6fa8..eebdbb165ff5d 100644 --- a/test/utils/primitives/src/lib.rs +++ b/test/utils/primitives/src/lib.rs @@ -14,7 +14,7 @@ // You should have received a copy of the GNU General Public License // along with Substrate. If not, see . -//! The Substrate test primitives to share +//! The Substrate test primitives to share #![cfg_attr(not(feature = "std"), no_std)] diff --git a/test/utils/runtime/Cargo.toml b/test/utils/runtime/Cargo.toml index f89524d2846cd..6c8ade133c4c7 100644 --- a/test/utils/runtime/Cargo.toml +++ b/test/utils/runtime/Cargo.toml @@ -34,7 +34,7 @@ frame-system-rpc-runtime-api = { path = "../../../frame/system/rpc/runtime-api", pallet-timestamp = { path = "../../../frame/timestamp", default-features = false } substrate-client = { path = "../../../client", optional = true } substrate-trie = { path = "../../../primitives/trie", default-features = false } -transaction-pool-api = { package = "substrate-transaction-pool-runtime-api", path = "../../../primitives/transaction-pool/runtime-api", default-features = false } +txpool-runtime-api = { package = "substrate-transaction-pool-runtime-api", path = "../../../primitives/transaction-pool/runtime-api", default-features = false } trie-db = { version = "0.16.0", default-features = false } [dev-dependencies] @@ -78,6 +78,6 @@ std = [ "pallet-timestamp/std", "substrate-client", "substrate-trie/std", - "transaction-pool-api/std", + "txpool-runtime-api/std", "trie-db/std", ] diff --git a/test/utils/runtime/src/lib.rs b/test/utils/runtime/src/lib.rs index 58caae2098d07..7dd98c56c0cf9 100644 --- a/test/utils/runtime/src/lib.rs +++ b/test/utils/runtime/src/lib.rs @@ -477,7 +477,7 @@ cfg_if! { } } - impl transaction_pool_api::TaggedTransactionQueue for Runtime { + impl txpool_runtime_api::TaggedTransactionQueue for Runtime { fn validate_transaction(utx: ::Extrinsic) -> TransactionValidity { if let Extrinsic::IncludeData(data) = utx { return Ok(ValidTransaction { @@ -662,7 +662,7 @@ cfg_if! { } } - impl transaction_pool_api::TaggedTransactionQueue for Runtime { + impl txpool_runtime_api::TaggedTransactionQueue for Runtime { fn validate_transaction(utx: ::Extrinsic) -> TransactionValidity { if let Extrinsic::IncludeData(data) = utx { return Ok(ValidTransaction{ From 2ce206b10f70af30c6686336cf25b766cd021048 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Mon, 25 Nov 2019 12:10:55 +0100 Subject: [PATCH 32/38] Warn about missing docs. --- primitives/transaction-pool/src/lib.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/primitives/transaction-pool/src/lib.rs b/primitives/transaction-pool/src/lib.rs index e1917f52615c9..796077a8148d2 100644 --- a/primitives/transaction-pool/src/lib.rs +++ b/primitives/transaction-pool/src/lib.rs @@ -16,6 +16,8 @@ //! Transaction pool types. +#![warn(missing_docs)] + pub mod error; pub use error::IntoPoolError; @@ -33,7 +35,6 @@ use futures::{ channel::mpsc, }; use serde::{Deserialize, Serialize}; - use sr_primitives::{ generic::BlockId, traits::{Block as BlockT, Member}, From 446647d598e8afa4a8a4b1456a5e2a764ad4e040 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Mon, 25 Nov 2019 12:36:57 +0100 Subject: [PATCH 33/38] Move abstraction for offchain calls to tx-pool-api. --- Cargo.lock | 1 + client/api/Cargo.toml | 1 + client/api/src/execution_extensions.rs | 7 +- client/offchain/src/lib.rs | 2 +- client/service/src/builder.rs | 3 +- client/service/src/lib.rs | 6 +- primitives/sr-primitives/src/offchain/mod.rs | 23 ------ primitives/transaction-pool/src/lib.rs | 85 ++++++++++++-------- 8 files changed, 62 insertions(+), 66 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index ca9cfd693dee8..1cad424ebcb61 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5713,6 +5713,7 @@ dependencies = [ "substrate-telemetry 2.0.0", "substrate-test-primitives 2.0.0", "substrate-test-runtime-client 2.0.0", + "substrate-transaction-pool-api 2.0.0", "substrate-trie 2.0.0", "tempfile 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] diff --git a/client/api/Cargo.toml b/client/api/Cargo.toml index 4757d7af81138..f4db4d40d371c 100644 --- a/client/api/Cargo.toml +++ b/client/api/Cargo.toml @@ -29,6 +29,7 @@ sr-primitives = { path = "../../primitives/sr-primitives", default-features = fa state-machine = { package = "substrate-state-machine", path = "../../primitives/state-machine" } substrate-telemetry = { path = "../telemetry" } trie = { package = "substrate-trie", path = "../../primitives/trie" } +txpool-api = { package = "substrate-transaction-pool-api", path = "../../primitives/transaction-pool" } [dev-dependencies] env_logger = "0.7.0" diff --git a/client/api/src/execution_extensions.rs b/client/api/src/execution_extensions.rs index 83d70998e16aa..94ce6c573e5e3 100644 --- a/client/api/src/execution_extensions.rs +++ b/client/api/src/execution_extensions.rs @@ -30,7 +30,6 @@ use primitives::{ use sr_primitives::{ generic::BlockId, traits, - offchain::{TransactionPool}, }; use state_machine::{ExecutionStrategy, ExecutionManager, DefaultHandler}; use externalities::Extensions; @@ -71,7 +70,7 @@ impl Default for ExecutionStrategies { pub struct ExecutionExtensions { strategies: ExecutionStrategies, keystore: Option, - transaction_pool: RwLock>>>, + transaction_pool: RwLock>>>, } impl Default for ExecutionExtensions { @@ -105,7 +104,7 @@ impl ExecutionExtensions { /// extension to be a `Weak` reference. /// That's also the reason why it's being registered lazily instead of /// during initialisation. - pub fn register_transaction_pool(&self, pool: Weak>) { + pub fn register_transaction_pool(&self, pool: Weak>) { *self.transaction_pool.write() = Some(pool); } @@ -166,7 +165,7 @@ impl ExecutionExtensions { /// A wrapper type to pass `BlockId` to the actual transaction pool. struct TransactionPoolAdapter { at: BlockId, - pool: Arc>, + pool: Arc>, } impl offchain::TransactionPool for TransactionPoolAdapter { diff --git a/client/offchain/src/lib.rs b/client/offchain/src/lib.rs index 3ca279e0df816..bf7965d308412 100644 --- a/client/offchain/src/lib.rs +++ b/client/offchain/src/lib.rs @@ -165,7 +165,7 @@ mod tests { struct TestPool(BasicPool, Block>); - impl sr_primitives::offchain::TransactionPool for TestPool { + impl txpool_api::OffchainSubmitTransaction for TestPool { fn submit_at( &self, at: &BlockId, diff --git a/client/service/src/builder.rs b/client/service/src/builder.rs index 04c480c71edbc..c8d224f59428f 100644 --- a/client/service/src/builder.rs +++ b/client/service/src/builder.rs @@ -801,8 +801,7 @@ ServiceBuilder< TNetP: NetworkSpecialization, TExPool: 'static + TransactionPool::Hash> - + TransactionPoolMaintainer::Hash> - + sr_primitives::offchain::TransactionPool, + + TransactionPoolMaintainer::Hash>, TRpc: rpc::RpcExtension + Clone, { /// Builds the service. diff --git a/client/service/src/lib.rs b/client/service/src/lib.rs index 325ad59ff40b1..c6bd7ce7f4267 100644 --- a/client/service/src/lib.rs +++ b/client/service/src/lib.rs @@ -146,8 +146,7 @@ pub trait AbstractService: 'static + Future + type SelectChain: consensus_common::SelectChain; /// Transaction pool. type TransactionPool: TransactionPool - + TransactionPoolMaintainer - + sr_primitives::offchain::TransactionPool; + + TransactionPoolMaintainer; /// Network specialization. type NetworkSpecialization: NetworkSpecialization; @@ -211,8 +210,7 @@ where TRtApi: 'static + Send + Sync, TSc: consensus_common::SelectChain + 'static + Clone + Send, TExPool: 'static + TransactionPool - + TransactionPoolMaintainer - + sr_primitives::offchain::TransactionPool, + + TransactionPoolMaintainer, TOc: 'static + Send + Sync, TNetSpec: NetworkSpecialization, { diff --git a/primitives/sr-primitives/src/offchain/mod.rs b/primitives/sr-primitives/src/offchain/mod.rs index 51dc19bc12d60..07c25570eef8c 100644 --- a/primitives/sr-primitives/src/offchain/mod.rs +++ b/primitives/sr-primitives/src/offchain/mod.rs @@ -16,27 +16,4 @@ //! A collection of higher lever helpers for offchain calls. -use crate::{ - traits, - generic::BlockId, -}; - pub mod http; - -/// An abstraction for transaction pool. -/// -/// This trait is used by offchain calls to be able to submit transactions. -/// The main use case is for offchain workers, to feed back the results of computations, -/// but since the transaction pool access is a separate `ExternalitiesExtension` it can -/// be also used in context of other offchain calls. For one may generate and submit -/// a transaction for some misbehavior reports (say equivocation). -pub trait TransactionPool: Send + Sync { - /// Submit transaction. - /// - /// The transaction will end up in the pool and be propagated to others. - fn submit_at( - &self, - at: &BlockId, - extrinsic: Block::Extrinsic, - ) -> Result<(), ()>; -} diff --git a/primitives/transaction-pool/src/lib.rs b/primitives/transaction-pool/src/lib.rs index 796077a8148d2..30671d4b1a16d 100644 --- a/primitives/transaction-pool/src/lib.rs +++ b/primitives/transaction-pool/src/lib.rs @@ -128,7 +128,10 @@ pub trait TransactionPool: Send + Sync { /// Transaction hash type. type Hash: Hash + Eq + Member + Serialize; /// In-pool transaction type. - type InPoolTransaction: InPoolTransaction, Hash = TxHash>; + type InPoolTransaction: InPoolTransaction< + Transaction = TransactionFor, + Hash = TxHash + >; /// Error type. type Error: From + IntoPoolError; @@ -137,14 +140,20 @@ pub trait TransactionPool: Send + Sync { &self, at: &BlockId, xts: impl IntoIterator> + 'static, - ) -> Box, Self::Error>>, Self::Error>> + Send + Unpin>; + ) -> Box, Self::Error>>, + Self::Error + >> + Send + Unpin>; /// Returns a future that imports one unverified transaction to the pool. fn submit_one( &self, at: &BlockId, xt: TransactionFor, - ) -> Box, Self::Error>> + Send + Unpin>; + ) -> Box, + Self::Error + >> + Send + Unpin>; /// Returns a future that import a single transaction and starts to watch their progress in the pool. fn submit_and_watch( @@ -172,6 +181,47 @@ pub trait TransactionPool: Send + Sync { fn on_broadcasted(&self, propagations: HashMap, Vec>); } +/// An abstraction for transaction pool. +/// +/// This trait is used by offchain calls to be able to submit transactions. +/// The main use case is for offchain workers, to feed back the results of computations, +/// but since the transaction pool access is a separate `ExternalitiesExtension` it can +/// be also used in context of other offchain calls. For one may generate and submit +/// a transaction for some misbehavior reports (say equivocation). +pub trait OffchainSubmitTransaction: Send + Sync { + /// Submit transaction. + /// + /// The transaction will end up in the pool and be propagated to others. + fn submit_at( + &self, + at: &BlockId, + extrinsic: Block::Extrinsic, + ) -> Result<(), ()>; +} + +impl OffchainSubmitTransaction for TPool { + fn submit_at( + &self, + at: &BlockId, + extrinsic: ::Extrinsic, + ) -> Result<(), ()> { + log::debug!( + target: "txpool", + "(offchain call) Submitting a transaction to the pool: {:?}", + extrinsic + ); + + let result = futures::executor::block_on(self.submit_one(&at, extrinsic)); + + result.map(|_| ()) + .map_err(|e| log::warn!( + target: "txpool", + "(offchain call) Error submitting a transaction to the pool: {:?}", + e + )) + } +} + /// Transaction pool maintainer interface. pub trait TransactionPoolMaintainer: Send + Sync { /// Block type. @@ -276,32 +326,3 @@ impl TransactionPoolMaintainer for MaintainableTransactionPool self.maintainer.maintain(id, retracted) } } - -impl sr_primitives::offchain::TransactionPool - for - MaintainableTransactionPool - where - Pool: TransactionPool, - Maintainer: Send + Sync, -{ - fn submit_at( - &self, - at: &BlockId, - extrinsic: ::Extrinsic, - ) -> Result<(), ()> { - log::debug!( - target: "txpool", - "(offchain call) Submitting a transaction to the pool: {:?}", - extrinsic - ); - - let result = futures::executor::block_on(self.submit_one(&at, extrinsic)); - - result.map(|_| ()) - .map_err(|e| log::warn!( - target: "txpool", - "(offchain call) Error submitting a transaction to the pool: {:?}", - e - )) - } -} From 1bd6c2809e26c960bd36812335c4ae824492648a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Mon, 25 Nov 2019 14:13:00 +0100 Subject: [PATCH 34/38] Merge RPC instantiation. --- bin/node/cli/src/service.rs | 8 ++-- bin/node/rpc/src/lib.rs | 82 +++++++++++++++++++++---------------- 2 files changed, 51 insertions(+), 39 deletions(-) diff --git a/bin/node/cli/src/service.rs b/bin/node/cli/src/service.rs index ab92864c921f6..11574cacc6fa8 100644 --- a/bin/node/cli/src/service.rs +++ b/bin/node/cli/src/service.rs @@ -99,8 +99,8 @@ macro_rules! new_full_start { import_setup = Some((block_import, grandpa_link, babe_link)); Ok(import_queue) })? - .with_rpc_extensions(|client, pool, _backend, _fetcher, _remote_blockchain| -> Result { - Ok(node_rpc::create_full(client, pool)) + .with_rpc_extensions(|client, pool, _backend, fetcher, _remote_blockchain| -> Result { + Ok(node_rpc::create(client, pool, node_rpc::LightDeps::none(fetcher))) })?; (builder, import_setup, inherent_data_providers) @@ -372,7 +372,9 @@ pub fn new_light(config: NodeConfiguration) .ok_or_else(|| "Trying to start node RPC without active fetcher")?; let remote_blockchain = remote_blockchain .ok_or_else(|| "Trying to start node RPC without active remote blockchain")?; - Ok(node_rpc::create_light(client, remote_blockchain, fetcher, pool)) + + let light_deps = node_rpc::LightDeps { remote_blockchain, fetcher }; + Ok(node_rpc::create(client, pool, Some(light_deps))) })? .build()?; diff --git a/bin/node/rpc/src/lib.rs b/bin/node/rpc/src/lib.rs index 5b596524d1cf4..3314225c16cbe 100644 --- a/bin/node/rpc/src/lib.rs +++ b/bin/node/rpc/src/lib.rs @@ -36,56 +36,66 @@ use node_runtime::UncheckedExtrinsic; use sr_primitives::traits::ProvideRuntimeApi; use txpool_api::TransactionPool; -/// Instantiate all RPC extensions for full node. -pub fn create_full(client: Arc, pool: Arc

) -> jsonrpc_core::IoHandler where +/// Light client extra dependencies. +pub struct LightDeps { + /// Remote access to the blockchain (async). + pub remote_blockchain: Arc>, + /// Fetcher instance. + pub fetcher: Arc, +} + +impl LightDeps { + /// Create empty `LightDeps` with given `F` type. + /// + /// This is a convenience method to be used in the service builder, + /// to make sure the type of the `LightDeps` is matching. + pub fn none(_: Option>) -> Option { + None + } +} + +/// Instantiate all RPC extensions. +/// +/// If you provide `LightDeps`, the system is configured for light client. +pub fn create( + client: Arc, + pool: Arc

, + light_deps: Option>, +) -> jsonrpc_core::IoHandler where C: ProvideRuntimeApi, C: client::blockchain::HeaderBackend, C: Send + Sync + 'static, C::Api: frame_system_rpc::AccountNonceApi, C::Api: pallet_contracts_rpc::ContractsRuntimeApi, C::Api: pallet_transaction_payment_rpc::TransactionPaymentRuntimeApi, + F: client::light::fetcher::Fetcher + 'static, P: TransactionPool + 'static, M: jsonrpc_core::Metadata + Default, { - use frame_system_rpc::{FullSystem, SystemApi}; - + use frame_system_rpc::{FullSystem, LightSystem, SystemApi}; use pallet_contracts_rpc::{Contracts, ContractsApi}; use pallet_transaction_payment_rpc::{TransactionPayment, TransactionPaymentApi}; let mut io = jsonrpc_core::IoHandler::default(); - io.extend_with( - SystemApi::to_delegate(FullSystem::new(client.clone(), pool)) - ); - io.extend_with( - ContractsApi::to_delegate(Contracts::new(client.clone())) - ); - io.extend_with( - TransactionPaymentApi::to_delegate(TransactionPayment::new(client)) - ); - io -} -/// Instantiate all RPC extensions for light node. -pub fn create_light( - client: Arc, - remote_blockchain: Arc>, - fetcher: Arc, - pool: Arc

, -) -> jsonrpc_core::IoHandler - where - C: ProvideRuntimeApi, - C: client::blockchain::HeaderBackend, - C: Send + Sync + 'static, - C::Api: frame_system_rpc::AccountNonceApi, - P: TransactionPool + 'static, - M: jsonrpc_core::Metadata + Default, - F: client::light::fetcher::Fetcher + 'static, -{ - use frame_system_rpc::{LightSystem, SystemApi}; + if let Some(LightDeps { remote_blockchain, fetcher }) = light_deps { + io.extend_with( + SystemApi::::to_delegate(LightSystem::new(client, remote_blockchain, fetcher, pool)) + ); + } else { + io.extend_with( + SystemApi::to_delegate(FullSystem::new(client.clone(), pool)) + ); - let mut io = jsonrpc_core::IoHandler::default(); - io.extend_with( - SystemApi::::to_delegate(LightSystem::new(client, remote_blockchain, fetcher, pool)) - ); + // Making synchronous calls in light client freezes the browser currently, + // more context: https://github.com/paritytech/substrate/pull/3480 + // These RPCs should use an asynchronous caller instead. + io.extend_with( + ContractsApi::to_delegate(Contracts::new(client.clone())) + ); + io.extend_with( + TransactionPaymentApi::to_delegate(TransactionPayment::new(client)) + ); + } io } From f141a456274b7ac2468ca2091a89fa0e2ddd9b80 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Tue, 26 Nov 2019 14:38:40 +0100 Subject: [PATCH 35/38] Update cargo.lock --- Cargo.lock | 15 +-------------- 1 file changed, 1 insertion(+), 14 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 7ee61a8894060..4e364cbd1d1a6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -6565,7 +6565,7 @@ dependencies = [ "substrate-transaction-pool-runtime-api 2.0.0", "substrate-trie 2.0.0", "substrate-wasm-builder-runner 1.0.4", - "trie-db 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)", + "trie-db 0.15.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -7255,18 +7255,6 @@ dependencies = [ "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "trie-db" -version = "0.16.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "elastic-array 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)", - "hash-db 0.15.2 (registry+https://github.com/rust-lang/crates.io-index)", - "hashbrown 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "trie-root" version = "0.15.2" @@ -8453,7 +8441,6 @@ dependencies = [ "checksum traitobject 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "efd1f82c56340fdf16f2a953d7bda4f8fdffba13d93b00844c25572110b26079" "checksum trie-bench 0.16.2 (registry+https://github.com/rust-lang/crates.io-index)" = "3073600c543ed001319d7e092c46dfd8c245af1a218ec5c75eb01582660a2b3e" "checksum trie-db 0.15.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d0b62d27e8aa1c07414549ac872480ac82380bab39e730242ab08d82d7cc098a" -"checksum trie-db 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)" = "784a9813d23f18bccab728ab039c39b8a87d0d6956dcdece39e92f5cffe5076e" "checksum trie-root 0.15.2 (registry+https://github.com/rust-lang/crates.io-index)" = "0b779f7c1c8fe9276365d9d5be5c4b5adeacf545117bb3f64c974305789c5c0b" "checksum trie-standardmap 0.15.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c3161ba520ab28cd8e6b68e1126f1009f6e335339d1a73b978139011703264c8" "checksum try-lock 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e604eb7b43c06650e854be16a2a03155743d3752dd1c943f6829e26b7a36e382" From aa37301d7a89ca112e549b423b9d73cd896d622b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Wed, 27 Nov 2019 13:32:01 +0100 Subject: [PATCH 36/38] Post merge fixes. --- Cargo.lock | 4 +++- bin/node/rpc/src/lib.rs | 2 +- client/basic-authorship/src/basic_authorship.rs | 10 +++++----- client/transaction-pool/Cargo.toml | 1 + client/transaction-pool/src/api.rs | 9 +++++---- client/transaction-pool/src/error.rs | 6 +++--- client/transaction-pool/src/maintainer.rs | 17 ++++++++++------- test/utils/runtime/client/src/lib.rs | 4 ++-- utils/frame/rpc/system/src/lib.rs | 7 ++++--- 9 files changed, 34 insertions(+), 26 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 0d03336acd2f7..304d7b6681895 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4894,6 +4894,7 @@ dependencies = [ "parity-scale-codec 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", "sc-transaction-graph 2.0.0", + "sp-blockchain 2.0.0", "sp-transaction-pool-api 2.0.0", "sp-transaction-pool-runtime-api 2.0.0", "sr-api 2.0.0", @@ -6111,11 +6112,12 @@ dependencies = [ "jsonrpc-derive 14.0.3 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "parity-scale-codec 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "sc-transaction-graph 2.0.0", "sc-transaction-pool 2.0.0", "serde 1.0.102 (registry+https://github.com/rust-lang/crates.io-index)", "sp-blockchain 2.0.0", + "sp-transaction-pool-api 2.0.0", "sr-primitives 2.0.0", + "substrate-client 2.0.0", "substrate-primitives 2.0.0", "substrate-test-runtime-client 2.0.0", ] diff --git a/bin/node/rpc/src/lib.rs b/bin/node/rpc/src/lib.rs index d14b427bd60e2..06b0e33606483 100644 --- a/bin/node/rpc/src/lib.rs +++ b/bin/node/rpc/src/lib.rs @@ -72,7 +72,7 @@ pub fn create( P: TransactionPool + 'static, M: jsonrpc_core::Metadata + Default, { - use substrate_frame_system_rpc::{FullSystem, LightSystem, SystemApi}; + use substrate_frame_rpc_system::{FullSystem, LightSystem, SystemApi}; use pallet_contracts_rpc::{Contracts, ContractsApi}; use pallet_transaction_payment_rpc::{TransactionPayment, TransactionPaymentApi}; diff --git a/client/basic-authorship/src/basic_authorship.rs b/client/basic-authorship/src/basic_authorship.rs index fa7dbfec50dc4..abffe8ee4007d 100644 --- a/client/basic-authorship/src/basic_authorship.rs +++ b/client/basic-authorship/src/basic_authorship.rs @@ -47,7 +47,7 @@ pub struct ProposerFactory where A: TransactionPool { impl ProposerFactory, A> where - A: TransactionPool, + A: TransactionPool + 'static, B: client_api::backend::Backend + Send + Sync + 'static, E: CallExecutor + Send + Sync + Clone + 'static, Block: BlockT, @@ -85,7 +85,7 @@ where impl consensus_common::Environment for ProposerFactory, A> where - A: txpool::ChainApi + 'static, + A: TransactionPool + 'static, B: client_api::backend::Backend + Send + Sync + 'static, E: CallExecutor + Send + Sync + Clone + 'static, Block: BlockT, @@ -111,7 +111,7 @@ pub struct Proposer { } /// Proposer inner, to wrap parameters under Arc. -struct ProposerInner { +struct ProposerInner { client: Arc, parent_hash: ::Hash, parent_id: BlockId, @@ -123,7 +123,7 @@ struct ProposerInner { impl consensus_common::Proposer for Proposer, A> where - A: TransactionPool, + A: TransactionPool + 'static, B: client_api::backend::Backend + Send + Sync + 'static, E: CallExecutor + Send + Sync + Clone + 'static, Block: BlockT, @@ -151,7 +151,7 @@ where } impl ProposerInner, A> where - A: TransactionPool, + A: TransactionPool + 'static, B: client_api::backend::Backend + Send + Sync + 'static, E: CallExecutor + Send + Sync + Clone + 'static, Block: BlockT, diff --git a/client/transaction-pool/Cargo.toml b/client/transaction-pool/Cargo.toml index 67203c3b4c1d9..07395179aa283 100644 --- a/client/transaction-pool/Cargo.toml +++ b/client/transaction-pool/Cargo.toml @@ -17,6 +17,7 @@ txpool = { package = "sc-transaction-graph", path = "./graph" } txpool-api = { package = "sp-transaction-pool-api", path = "../../primitives/transaction-pool" } txpool-runtime-api = { package = "sp-transaction-pool-runtime-api", path = "../../primitives/transaction-pool/runtime-api" } client-api = { package = "substrate-client-api", path = "../api" } +sp-blockchain = { path = "../../primitives/blockchain" } # TODO [ToDr] USe traits instead? client = { package = "substrate-client", path = "../" } diff --git a/client/transaction-pool/src/api.rs b/client/transaction-pool/src/api.rs index 552a998a95f99..87b494201d5e3 100644 --- a/client/transaction-pool/src/api.rs +++ b/client/transaction-pool/src/api.rs @@ -21,7 +21,6 @@ use codec::{Decode, Encode}; use futures::{channel::oneshot, executor::{ThreadPool, ThreadPoolBuilder}, future::{Future, FutureExt, ready}}; use client_api::{ - error::Error as ClientError, blockchain::HeaderBackend, light::{Fetcher, RemoteCallRequest} }; @@ -166,10 +165,12 @@ impl txpool::ChainApi for LightChainApi where }); let remote_validation_request = remote_validation_request.then(move |result| { let result: error::Result = result + .map_err(Into::into) .and_then(|result| Decode::decode(&mut &result[..]) - .map_err(|e| ClientError::CallResultDecode("Error decoding tx validation result", e)) - ) - .map_err(Into::into); + .map_err(|e| Error::RuntimeApi( + format!("Error decoding tx validation result: {:?}", e) + )) + ); ready(result) }); diff --git a/client/transaction-pool/src/error.rs b/client/transaction-pool/src/error.rs index 81283297ac1c7..d769944ad6a59 100644 --- a/client/transaction-pool/src/error.rs +++ b/client/transaction-pool/src/error.rs @@ -24,8 +24,8 @@ pub type Result = std::result::Result; pub enum Error { /// Pool error. Pool(txpool_api::error::Error), - /// Client error. - Client(client_api::error::Error), + /// Blockchain error. + Blockchain(sp_blockchain::Error), /// Error while converting a `BlockId`. #[from(ignore)] BlockIdConversion(String), @@ -38,7 +38,7 @@ impl std::error::Error for Error { fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { match self { Error::Pool(ref err) => Some(err), - Error::Client(ref err) => Some(err), + Error::Blockchain(ref err) => Some(err), Error::BlockIdConversion(_) => None, Error::RuntimeApi(_) => None, } diff --git a/client/transaction-pool/src/maintainer.rs b/client/transaction-pool/src/maintainer.rs index 9a0153ff704ce..c4d662c452b40 100644 --- a/client/transaction-pool/src/maintainer.rs +++ b/client/transaction-pool/src/maintainer.rs @@ -273,7 +273,7 @@ where return Box::new(ready(())); } let header = self.client.header(id) - .and_then(|h| h.ok_or(client_api::error::Error::UnknownBlock(format!("{}", id)))); + .and_then(|h| h.ok_or(sp_blockchain::Error::UnknownBlock(format!("{}", id)))); let header = match header { Ok(header) => header, Err(err) => { @@ -460,18 +460,21 @@ mod tests { #[test] fn should_revalidate_transactions_at_light_pool() { + use std::sync::atomic; + use sr_primitives::transaction_validity::*; + let build_fetcher = || { - let validated = Arc::new(std::sync::atomic::AtomicBool::new(false)); + let validated = Arc::new(atomic::AtomicBool::new(false)); Arc::new(test_client::new_light_fetcher() .with_remote_body(Some(Box::new(move |_| Ok(vec![])))) .with_remote_call(Some(Box::new(move |_| { - let is_inserted = validated.swap(true, std::sync::atomic::Ordering::SeqCst); - let validity: sr_primitives::transaction_validity::TransactionValidity = if is_inserted { - Err(sr_primitives::transaction_validity::TransactionValidityError::Invalid( - sr_primitives::transaction_validity::InvalidTransaction::Custom(0) + let is_inserted = validated.swap(true, atomic::Ordering::SeqCst); + let validity: TransactionValidity = if is_inserted { + Err(TransactionValidityError::Invalid( + InvalidTransaction::Custom(0) )) } else { - Ok(sr_primitives::transaction_validity::ValidTransaction { + Ok(ValidTransaction { priority: 0, requires: Vec::new(), provides: vec![vec![42]], diff --git a/test/utils/runtime/client/src/lib.rs b/test/utils/runtime/client/src/lib.rs index e244eb9a5fda9..57be949bcaf98 100644 --- a/test/utils/runtime/client/src/lib.rs +++ b/test/utils/runtime/client/src/lib.rs @@ -256,10 +256,10 @@ impl TestClientBuilderExt for TestClientBuilder< } /// Type of optional fetch callback. -type MaybeFetcherCallback = Option Result + Send + Sync>>; +type MaybeFetcherCallback = Option Result + Send + Sync>>; /// Type of fetcher future result. -type FetcherFutureResult = futures::future::Ready>; +type FetcherFutureResult = futures::future::Ready>; /// Implementation of light client fetcher used in tests. #[derive(Default)] diff --git a/utils/frame/rpc/system/src/lib.rs b/utils/frame/rpc/system/src/lib.rs index 8a85f1c70ef9b..ebda962031921 100644 --- a/utils/frame/rpc/system/src/lib.rs +++ b/utils/frame/rpc/system/src/lib.rs @@ -20,7 +20,6 @@ use std::sync::Arc; use codec::{self, Codec, Decode, Encode}; use client::{ - error::Error as ClientError, light::blockchain::{future_header, RemoteBlockchain}, light::fetcher::{Fetcher, RemoteCallRequest}, }; @@ -30,7 +29,10 @@ use jsonrpc_core::{ }; use jsonrpc_derive::rpc; use futures::future::{ready, TryFutureExt}; -use sp_blockchain::HeaderBackend; +use sp_blockchain::{ + HeaderBackend, + Error as ClientError +}; use sr_primitives::{ generic::BlockId, traits, @@ -220,7 +222,6 @@ fn adjust_nonce( #[cfg(test)] mod tests { use super::*; - use sc_transaction_pool; use futures::executor::block_on; use test_client::{ From 564d1f0afce3dd9abba20941e821b89b9d6c60b7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Wed, 27 Nov 2019 14:35:25 +0100 Subject: [PATCH 37/38] Avoid depending on client. --- Cargo.lock | 1 - bin/node/cli/src/service.rs | 5 +- client/transaction-pool/Cargo.toml | 2 - client/transaction-pool/src/maintainer.rs | 85 ++++++++++------------- 4 files changed, 37 insertions(+), 56 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 304d7b6681895..f9424b323b2d4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4899,7 +4899,6 @@ dependencies = [ "sp-transaction-pool-runtime-api 2.0.0", "sr-api 2.0.0", "sr-primitives 2.0.0", - "substrate-client 2.0.0", "substrate-client-api 2.0.0", "substrate-keyring 2.0.0", "substrate-primitives 2.0.0", diff --git a/bin/node/cli/src/service.rs b/bin/node/cli/src/service.rs index 11574cacc6fa8..405e0c89df4ea 100644 --- a/bin/node/cli/src/service.rs +++ b/bin/node/cli/src/service.rs @@ -277,10 +277,7 @@ type ConcreteTransactionPool = txpool_api::MaintainableTransactionPool< ConcreteBlock >, txpool::FullBasicPoolMaintainer< - ConcreteBackend, - LocalCallExecutor, NativeExecutor>, - ConcreteBlock, - node_runtime::RuntimeApi, + ConcreteClient, txpool::FullChainApi > >; diff --git a/client/transaction-pool/Cargo.toml b/client/transaction-pool/Cargo.toml index 07395179aa283..3f1c80c2de4af 100644 --- a/client/transaction-pool/Cargo.toml +++ b/client/transaction-pool/Cargo.toml @@ -18,8 +18,6 @@ txpool-api = { package = "sp-transaction-pool-api", path = "../../primitives/tra txpool-runtime-api = { package = "sp-transaction-pool-runtime-api", path = "../../primitives/transaction-pool/runtime-api" } client-api = { package = "substrate-client-api", path = "../api" } sp-blockchain = { path = "../../primitives/blockchain" } -# TODO [ToDr] USe traits instead? -client = { package = "substrate-client", path = "../" } [dev-dependencies] keyring = { package = "substrate-keyring", path = "../../primitives/keyring" } diff --git a/client/transaction-pool/src/maintainer.rs b/client/transaction-pool/src/maintainer.rs index c4d662c452b40..a390dde88b765 100644 --- a/client/transaction-pool/src/maintainer.rs +++ b/client/transaction-pool/src/maintainer.rs @@ -26,9 +26,8 @@ use futures::{ use log::warn; use parking_lot::Mutex; -use client::Client; use client_api::{ - CallExecutor, + client::BlockBody, light::{Fetcher, RemoteBodyRequest}, }; use primitives::{Blake2Hasher, H256}; @@ -36,42 +35,36 @@ use sr_primitives::{ generic::BlockId, traits::{Block as BlockT, Extrinsic, Header, NumberFor, ProvideRuntimeApi, SimpleArithmetic}, }; +use sp_blockchain::HeaderBackend; use txpool_api::TransactionPoolMaintainer; use txpool_runtime_api::TaggedTransactionQueue; use txpool::{self, ChainApi}; /// Basic transaction pool maintainer for full clients. -pub struct FullBasicPoolMaintainer { +pub struct FullBasicPoolMaintainer { pool: Arc>, - client: Arc>, + client: Arc, } -impl FullBasicPoolMaintainer - where - Block: BlockT, - PoolApi: ChainApi, -{ +impl FullBasicPoolMaintainer { /// Create new basic full pool maintainer. pub fn new( pool: Arc>, - client: Arc>, + client: Arc, ) -> Self { FullBasicPoolMaintainer { pool, client } } } -impl TransactionPoolMaintainer +impl TransactionPoolMaintainer for - FullBasicPoolMaintainer + FullBasicPoolMaintainer where - Block: BlockT, - Backend: 'static + client_api::backend::Backend, - Client: ProvideRuntimeApi, - as ProvideRuntimeApi>::Api: TaggedTransactionQueue, - Executor: 'static + Send + Sync + CallExecutor, - Api: 'static + Send + Sync, - PoolApi: 'static + ChainApi, + Block: BlockT::Out>, + Client: ProvideRuntimeApi + HeaderBackend + BlockBody + 'static, + Client::Api: TaggedTransactionQueue, + PoolApi: ChainApi + 'static, { type Block = Block; type Hash = Block::Hash; @@ -84,8 +77,8 @@ where // Put transactions from retracted blocks back into the pool. let client_copy = self.client.clone(); let retracted_transactions = retracted.to_vec().into_iter() - .filter_map(move |hash| client_copy.block(&BlockId::hash(hash)).ok().unwrap_or(None)) - .flat_map(|block| block.block.deconstruct().1.into_iter()) + .filter_map(move |hash| client_copy.block_body(&BlockId::hash(hash)).ok().unwrap_or(None)) + .flat_map(|block| block.into_iter()) .filter(|tx| tx.is_signed().unwrap_or(false)); let resubmit_future = self.pool .submit_at(id, retracted_transactions, true) @@ -102,12 +95,12 @@ where return Box::new(resubmit_future) } - let block = self.client.block(id); + let block = (self.client.header(*id), self.client.block_body(id)); match block { - Ok(Some(block)) => { - let parent_id = BlockId::hash(*block.block.header().parent_hash()); + (Ok(Some(header)), Ok(Some(extrinsics))) => { + let parent_id = BlockId::hash(*header.parent_hash()); let prune_future = self.pool - .prune(id, &parent_id, block.block.extrinsics()) + .prune(id, &parent_id, &extrinsics) .then(|prune_result| ready(match prune_result { Ok(_) => (), Err(e) => { @@ -118,9 +111,9 @@ where Box::new(resubmit_future.then(|_| prune_future)) }, - Ok(None) => Box::new(resubmit_future), - Err(err) => { - warn!("Error reading block body: {:?}", err); + (Ok(_), Ok(_)) => Box::new(resubmit_future), + err => { + warn!("Error reading block: {:?}", err); Box::new(resubmit_future) }, } @@ -128,9 +121,9 @@ where } /// Basic transaction pool maintainer for light clients. -pub struct LightBasicPoolMaintainer { +pub struct LightBasicPoolMaintainer { pool: Arc>, - client: Arc>, + client: Arc, fetcher: Arc, revalidate_time_period: Option, revalidate_block_period: Option>, @@ -138,15 +131,12 @@ pub struct LightBasicPoolMaintainer, } -impl LightBasicPoolMaintainer +impl LightBasicPoolMaintainer where - Block: BlockT, - Backend: 'static + client_api::backend::Backend, - Client: ProvideRuntimeApi, - as ProvideRuntimeApi>::Api: TaggedTransactionQueue, - Executor: 'static + Send + Sync + CallExecutor, - Api: 'static + Send + Sync, - PoolApi: 'static + ChainApi, + Block: BlockT::Out>, + Client: ProvideRuntimeApi + HeaderBackend + BlockBody + 'static, + Client::Api: TaggedTransactionQueue, + PoolApi: ChainApi + 'static, F: Fetcher + 'static, { /// Create light pool maintainer with default constants. @@ -155,7 +145,7 @@ impl LightBasicPoolMaintainer>, - client: Arc>, + client: Arc, fetcher: Arc, ) -> Self { Self::new( @@ -170,7 +160,7 @@ impl LightBasicPoolMaintainer>, - client: Arc>, + client: Arc, fetcher: Arc, revalidate_time_period: Option, revalidate_block_period: Option>, @@ -246,17 +236,14 @@ impl LightBasicPoolMaintainer TransactionPoolMaintainer +impl TransactionPoolMaintainer for - LightBasicPoolMaintainer + LightBasicPoolMaintainer where Block: BlockT::Out>, - Backend: 'static + client_api::backend::Backend, - Client: ProvideRuntimeApi, - as ProvideRuntimeApi>::Api: TaggedTransactionQueue, - Executor: 'static + Send + Sync + CallExecutor, - Api: 'static + Send + Sync, - PoolApi: 'static + ChainApi, + Client: ProvideRuntimeApi + HeaderBackend + BlockBody + 'static, + Client::Api: TaggedTransactionQueue, + PoolApi: ChainApi + 'static, F: Fetcher + 'static, { type Block = Block; @@ -272,7 +259,7 @@ where self.revalidation_status.lock().clear(); return Box::new(ready(())); } - let header = self.client.header(id) + let header = self.client.header(*id) .and_then(|h| h.ok_or(sp_blockchain::Error::UnknownBlock(format!("{}", id)))); let header = match header { Ok(header) => header, From a90a7cd36b0e317c1d4d7310d49b7f7d41fc77e3 Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Wed, 27 Nov 2019 19:52:04 +0000 Subject: [PATCH 38/38] Fix build --- test/utils/runtime/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/utils/runtime/Cargo.toml b/test/utils/runtime/Cargo.toml index eb94f775c96fc..f51bceb095fc9 100644 --- a/test/utils/runtime/Cargo.toml +++ b/test/utils/runtime/Cargo.toml @@ -34,7 +34,7 @@ frame-system-rpc-runtime-api = { path = "../../../frame/system/rpc/runtime-api", pallet-timestamp = { path = "../../../frame/timestamp", default-features = false } substrate-client = { path = "../../../client", optional = true } substrate-trie = { path = "../../../primitives/trie", default-features = false } -transaction-pool-api = { package = "substrate-transaction-pool-runtime-api", path = "../../../primitives/transaction-pool/runtime-api", default-features = false } +txpool-runtime-api = { package = "sp-transaction-pool-runtime-api", path = "../../../primitives/transaction-pool/runtime-api", default-features = false } trie-db = { version = "0.16.0", default-features = false } [dev-dependencies]