diff --git a/substrate/Cargo.lock b/substrate/Cargo.lock index 978af7a4ab..abd2e63f1b 100644 --- a/substrate/Cargo.lock +++ b/substrate/Cargo.lock @@ -4238,7 +4238,6 @@ dependencies = [ "sr-primitives 2.0.0", "substrate-client 2.0.0", "substrate-consensus-common 2.0.0", - "substrate-inherents 2.0.0", "substrate-offchain-primitives 2.0.0", "substrate-primitives 2.0.0", "substrate-test-client 2.0.0", @@ -4384,7 +4383,6 @@ dependencies = [ "substrate-consensus-common 2.0.0", "substrate-executor 2.0.0", "substrate-finality-grandpa 2.0.0", - "substrate-inherents 2.0.0", "substrate-keystore 2.0.0", "substrate-network 2.0.0", "substrate-offchain 2.0.0", diff --git a/substrate/core/basic-authorship/src/basic_authorship.rs b/substrate/core/basic-authorship/src/basic_authorship.rs index 62aad4c9c7..87d0b8f92b 100644 --- a/substrate/core/basic-authorship/src/basic_authorship.rs +++ b/substrate/core/basic-authorship/src/basic_authorship.rs @@ -20,7 +20,7 @@ // use std::{self, time, sync::Arc}; -use log::{info, debug, warn, trace}; +use log::{info, debug, trace}; use client::{ self, error, Client as SubstrateClient, CallExecutor, @@ -36,7 +36,7 @@ use runtime_primitives::traits::{ use runtime_primitives::generic::BlockId; use runtime_primitives::ApplyError; use transaction_pool::txpool::{self, Pool as TransactionPool}; -use inherents::{InherentData, pool::InherentsPool}; +use inherents::InherentData; use substrate_telemetry::{telemetry, CONSENSUS_INFO}; /// Build new blocks. @@ -119,8 +119,6 @@ pub struct ProposerFactory where A: txpool::ChainApi { pub client: Arc, /// The transaction pool. pub transaction_pool: Arc>, - /// The inherents pool - pub inherents_pool: Arc::Extrinsic>>, } impl consensus_common::Environment<::Block> for ProposerFactory where @@ -150,7 +148,6 @@ impl consensus_common::Environment<::Block> for Propose parent_id: id, parent_number: *parent_header.number(), transaction_pool: self.transaction_pool.clone(), - inherents_pool: self.inherents_pool.clone(), now: Box::new(time::Instant::now), }; @@ -165,7 +162,6 @@ pub struct Proposer { parent_id: BlockId, parent_number: <::Header as HeaderT>::Number, transaction_pool: Arc>, - inherents_pool: Arc::Extrinsic>>, now: Box time::Instant>, } @@ -218,14 +214,6 @@ impl Proposer where inherent_data, inherent_digests.clone(), |block_builder| { - // Add inherents from the internal pool - let inherents = self.inherents_pool.drain(); - debug!("Pushing {} queued inherent extrinsics.", inherents.len()); - for i in inherents { - if let Err(e) = block_builder.push_extrinsic(i) { - warn!("Error while pushing inherent extrinsic from the pool: {:?}", e); - } - } // proceed with transactions let mut is_first = true; let mut skipped = 0; @@ -328,7 +316,6 @@ mod tests { let proposer_factory = ProposerFactory { client: client.clone(), transaction_pool: txpool.clone(), - inherents_pool: Default::default(), }; let mut proposer = proposer_factory.init( @@ -350,33 +337,4 @@ mod tests { assert_eq!(block.extrinsics().len(), 1); assert_eq!(txpool.ready().count(), 2); } - - #[test] - fn should_include_inherents_from_the_pool() { - // given - let client = Arc::new(test_client::new()); - let chain_api = transaction_pool::ChainApi::new(client.clone()); - let txpool = Arc::new(TransactionPool::new(Default::default(), chain_api)); - let inpool = Arc::new(InherentsPool::default()); - - let proposer_factory = ProposerFactory { - client: client.clone(), - transaction_pool: txpool.clone(), - inherents_pool: inpool.clone(), - }; - - inpool.add(extrinsic(0)); - - let proposer = proposer_factory.init( - &client.header(&BlockId::number(0)).unwrap().unwrap(), - &[] - ).unwrap(); - - // when - let deadline = time::Duration::from_secs(3); - let block = proposer.propose(Default::default(), Default::default(), deadline).unwrap(); - - // then - assert_eq!(block.extrinsics().len(), 1); - } } diff --git a/substrate/core/inherents/src/lib.rs b/substrate/core/inherents/src/lib.rs index e851959ee0..7b99c7ba52 100644 --- a/substrate/core/inherents/src/lib.rs +++ b/substrate/core/inherents/src/lib.rs @@ -44,9 +44,6 @@ use parking_lot::RwLock; #[cfg(feature = "std")] use std::{sync::Arc, format}; -#[cfg(feature = "std")] -pub mod pool; - pub use runtime_primitives::RuntimeString; /// An identifier for an inherent. diff --git a/substrate/core/inherents/src/pool.rs b/substrate/core/inherents/src/pool.rs deleted file mode 100644 index 2c7e953696..0000000000 --- a/substrate/core/inherents/src/pool.rs +++ /dev/null @@ -1,75 +0,0 @@ -// 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 . - -//! Inherents Pool - -use std::{fmt, mem, vec}; -use parking_lot::Mutex; - -/// Inherents Pool -/// -/// The pool is responsible to collect inherents asynchronously generated -/// by some other parts of the code and make them ready for the next block production. -pub struct InherentsPool { - data: Mutex>, -} - -impl Default for InherentsPool { - fn default() -> Self { - InherentsPool { - data: Default::default(), - } - } -} - -impl fmt::Debug for InherentsPool { - fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { - let mut builder = fmt.debug_struct("InherentsPool"); - if let Some(data) = self.data.try_lock() { - builder.field("data", &*data); - } - builder.finish() - } -} - -impl InherentsPool { - /// Add inherent extrinsic to the pool. - /// - /// This inherent will be appended to the next produced block. - pub fn add(&self, extrinsic: T) { - self.data.lock().push(extrinsic); - } - - /// Drain all currently queued inherents. - pub fn drain(&self) -> Vec { - mem::replace(&mut *self.data.lock(), vec![]) - } -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn should_drain_inherents_to_given_data() { - let pool = InherentsPool::default(); - pool.add(5); - pool.add(7); - - assert_eq!(pool.drain(), vec![5, 7]); - assert_eq!(pool.drain(), vec![]); - } -} diff --git a/substrate/core/offchain/Cargo.toml b/substrate/core/offchain/Cargo.toml index 241edfea9f..14341e2458 100644 --- a/substrate/core/offchain/Cargo.toml +++ b/substrate/core/offchain/Cargo.toml @@ -10,7 +10,6 @@ edition = "2018" client = { package = "substrate-client", path = "../../core/client" } consensus = { package = "substrate-consensus-common", path = "../../core/consensus/common" } futures = "0.1.25" -inherents = { package = "substrate-inherents", path = "../../core/inherents" } log = "0.4" offchain-primitives = { package = "substrate-offchain-primitives", path = "./primitives" } parity-codec = { version = "3.3", features = ["derive"] } diff --git a/substrate/core/offchain/src/api.rs b/substrate/core/offchain/src/api.rs index 5d2a636be3..25a8a2ebaa 100644 --- a/substrate/core/offchain/src/api.rs +++ b/substrate/core/offchain/src/api.rs @@ -16,7 +16,6 @@ use std::sync::Arc; use futures::{Stream, Future, sync::mpsc}; -use inherents::pool::InherentsPool; use log::{info, debug, warn}; use parity_codec::Decode; use primitives::OffchainExt; @@ -46,21 +45,18 @@ impl OffchainExt for AsyncApi { pub(crate) struct Api { receiver: Option>, transaction_pool: Arc>, - inherents_pool: Arc::Extrinsic>>, at: BlockId, } impl Api { pub fn new( transaction_pool: Arc>, - inherents_pool: Arc::Extrinsic>>, at: BlockId, ) -> (AsyncApi, Self) { let (tx, rx) = mpsc::unbounded(); let api = Self { receiver: Some(rx), transaction_pool, - inherents_pool, at, }; (AsyncApi(tx), api) @@ -90,9 +86,8 @@ impl Api { info!("Submitting to the pool: {:?} (isSigned: {:?})", xt, xt.is_signed()); match self.transaction_pool.submit_one(&self.at, xt.clone()) { Ok(hash) => debug!("[{:?}] Offchain transaction added to the pool.", hash), - Err(_) => { - debug!("Offchain inherent added to the pool."); - self.inherents_pool.add(xt); + Err(e) => { + debug!("Couldn't submit transaction: {:?}", e); }, } } diff --git a/substrate/core/offchain/src/lib.rs b/substrate/core/offchain/src/lib.rs index cac960f250..f176fadd0d 100644 --- a/substrate/core/offchain/src/lib.rs +++ b/substrate/core/offchain/src/lib.rs @@ -19,8 +19,8 @@ //! The offchain workers is a special function of the runtime that //! gets executed after block is imported. During execution //! it's able to asynchronously submit extrinsics that will either -//! be propagated to other nodes (transactions) or will be -//! added to the next block produced by the node as inherents. +//! be propagated to other nodes added to the next block +//! produced by the node as unsigned transactions. //! //! Offchain workers can be used for computation-heavy tasks //! that are not feasible for execution during regular block processing. @@ -39,7 +39,6 @@ use std::{ }; use client::runtime_api::ApiExt; -use inherents::pool::InherentsPool; use log::{debug, warn}; use primitives::ExecutionContext; use runtime_primitives::{ @@ -57,7 +56,6 @@ pub use offchain_primitives::OffchainWorkerApi; #[derive(Debug)] pub struct OffchainWorkers { client: Arc, - inherents_pool: Arc::Extrinsic>>, executor: TaskExecutor, _block: PhantomData, } @@ -66,12 +64,10 @@ impl OffchainWorkers { /// Creates new `OffchainWorkers`. pub fn new( client: Arc, - inherents_pool: Arc::Extrinsic>>, executor: TaskExecutor, ) -> Self { Self { client, - inherents_pool, executor, _block: PhantomData, } @@ -97,7 +93,7 @@ impl OffchainWorkers where debug!("Checking offchain workers at {:?}: {:?}", at, has_api); if has_api.unwrap_or(false) { - let (api, runner) = api::Api::new(pool.clone(), self.inherents_pool.clone(), at.clone()); + let (api, runner) = api::Api::new(pool.clone(), at.clone()); self.executor.spawn(runner.process()); debug!("Running offchain workers at {:?}", at); @@ -119,14 +115,14 @@ mod tests { let runtime = tokio::runtime::Runtime::new().unwrap(); let client = Arc::new(test_client::new()); let pool = Arc::new(Pool::new(Default::default(), ::transaction_pool::ChainApi::new(client.clone()))); - let inherents = Arc::new(InherentsPool::default()); // when - let offchain = OffchainWorkers::new(client, inherents.clone(), runtime.executor()); + let offchain = OffchainWorkers::new(client, runtime.executor()); offchain.on_block_imported(&0u64, &pool); // then runtime.shutdown_on_idle().wait().unwrap(); - assert_eq!(inherents.drain().len(), 1); + assert_eq!(pool.status().ready, 1); + assert_eq!(pool.ready().next().unwrap().is_propagateable(), false); } } diff --git a/substrate/core/service/Cargo.toml b/substrate/core/service/Cargo.toml index bf13a51fac..89804166d6 100644 --- a/substrate/core/service/Cargo.toml +++ b/substrate/core/service/Cargo.toml @@ -16,7 +16,6 @@ exit-future = "0.1" serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" target_info = "0.1" -inherents = { package = "substrate-inherents", path = "../../core/inherents" } keystore = { package = "substrate-keystore", path = "../../core/keystore" } sr-io = { path = "../../core/sr-io" } runtime_primitives = { package = "sr-primitives", path = "../../core/sr-primitives" } diff --git a/substrate/core/service/src/components.rs b/substrate/core/service/src/components.rs index 0d9d7dcdfc..3876279cc7 100644 --- a/substrate/core/service/src/components.rs +++ b/substrate/core/service/src/components.rs @@ -635,7 +635,7 @@ mod tests { use super::*; use consensus_common::BlockOrigin; use client::LongestChain; - use substrate_test_client::{self, TestClient, AccountKeyring, runtime::Transfer}; + use substrate_test_client::{TestClient, AccountKeyring, runtime::Transfer}; #[test] fn should_remove_transactions_from_the_pool() { diff --git a/substrate/core/service/src/lib.rs b/substrate/core/service/src/lib.rs index 1eb59872ce..cb65ece34e 100644 --- a/substrate/core/service/src/lib.rs +++ b/substrate/core/service/src/lib.rs @@ -34,7 +34,6 @@ use parking_lot::Mutex; use client::BlockchainEvents; use exit_future::Signal; use futures::prelude::*; -use inherents::pool::InherentsPool; use keystore::Store as Keystore; use log::{info, warn, debug}; use parity_codec::{Encode, Decode}; @@ -76,7 +75,6 @@ pub struct Service { select_chain: Option<::SelectChain>, network: Option>>, transaction_pool: Arc>, - inherents_pool: Arc>>, keystore: Keystore, exit: ::exit_future::Exit, signal: Option, @@ -211,11 +209,9 @@ impl Service { .select(exit.clone()) .then(|_| Ok(()))); - let inherents_pool = Arc::new(InherentsPool::default()); let offchain_workers = if config.offchain_worker { Some(Arc::new(offchain::OffchainWorkers::new( client.clone(), - inherents_pool.clone(), task_executor.clone(), ))) } else { @@ -381,7 +377,6 @@ impl Service { network: Some(network), select_chain, transaction_pool, - inherents_pool, signal: Some(signal), keystore, config, @@ -433,11 +428,6 @@ impl Service where Components: components::Components { self.transaction_pool.clone() } - /// Get shared inherents pool instance. - pub fn inherents_pool(&self) -> Arc>> { - self.inherents_pool.clone() - } - /// Get shared keystore. pub fn keystore(&self) -> &Keystore { &self.keystore @@ -498,17 +488,32 @@ impl TransactionPoolAdapter { } } +/// Get transactions for propagation. +/// +/// Function extracted to simplify the test and prevent creating `ServiceFactory`. +fn transactions_to_propagate(pool: &TransactionPool) + -> Vec<(H, B::Extrinsic)> +where + PoolApi: ChainApi, + B: BlockT, + H: std::hash::Hash + Eq + runtime_primitives::traits::Member + serde::Serialize, + E: txpool::error::IntoPoolError + From, +{ + pool.ready() + .filter(|t| t.is_propagateable()) + .map(|t| { + let hash = t.hash.clone(); + let ex: B::Extrinsic = t.data.clone(); + (hash, ex) + }) + .collect() +} + impl network::TransactionPool, ComponentBlock> for TransactionPoolAdapter where ::RuntimeApi: Send + Sync { fn transactions(&self) -> Vec<(ComponentExHash, ComponentExtrinsic)> { - self.pool.ready() - .map(|t| { - let hash = t.hash.clone(); - let ex: ComponentExtrinsic = t.data.clone(); - (hash, ex) - }) - .collect() + transactions_to_propagate(&self.pool) } fn import(&self, transaction: &ComponentExtrinsic) -> Option> { @@ -745,3 +750,42 @@ macro_rules! construct_service_factory { } } } + +#[cfg(test)] +mod tests { + use super::*; + use client::LongestChain; + use consensus_common::SelectChain; + use runtime_primitives::traits::BlindCheckable; + use substrate_test_client::{AccountKeyring, runtime::{Extrinsic, Transfer}}; + + #[test] + fn should_not_propagate_transactions_that_are_marked_as_such() { + // given + let client = Arc::new(substrate_test_client::new()); + let pool = Arc::new(TransactionPool::new( + Default::default(), + transaction_pool::ChainApi::new(client.clone()) + )); + let best = LongestChain::new(client.backend().clone(), client.import_lock()) + .best_chain().unwrap(); + let transaction = Transfer { + amount: 5, + nonce: 0, + from: AccountKeyring::Alice.into(), + to: Default::default(), + }.into_signed_tx(); + pool.submit_one(&BlockId::hash(best.hash()), transaction.clone()).unwrap(); + pool.submit_one(&BlockId::hash(best.hash()), Extrinsic::IncludeData(vec![1])).unwrap(); + assert_eq!(pool.status().ready, 2); + + // when + let transactions = transactions_to_propagate(&pool); + + // then + assert_eq!(transactions.len(), 1); + assert!(transactions[0].1.clone().check().is_ok()); + // this should not panic + let _ = transactions[0].1.transfer(); + } +} diff --git a/substrate/core/sr-primitives/src/transaction_validity.rs b/substrate/core/sr-primitives/src/transaction_validity.rs index 29d2a82a24..f36599b67b 100644 --- a/substrate/core/sr-primitives/src/transaction_validity.rs +++ b/substrate/core/sr-primitives/src/transaction_validity.rs @@ -30,7 +30,7 @@ pub type TransactionLongevity = u64; pub type TransactionTag = Vec; /// Information on a transaction's validity and, if valid, on how it relates to other transactions. -#[derive(Clone, PartialEq, Eq, Encode, Decode)] +#[derive(Clone, PartialEq, Eq, Encode)] #[cfg_attr(feature = "std", derive(Debug))] pub enum TransactionValidity { /// Transaction is invalid. Details are described by the error code. @@ -59,7 +59,74 @@ pub enum TransactionValidity { /// Longevity describes minimum number of blocks the validity is correct. /// After this period transaction should be removed from the pool or revalidated. longevity: TransactionLongevity, + /// A flag indicating if the transaction should be propagated to other peers. + /// + /// By setting `false` here the transaction will still be considered for + /// including in blocks that are authored on the current node, but will + /// never be sent to other peers. + propagate: bool, }, /// Transaction validity can't be determined. Unknown(i8), } + +impl Decode for TransactionValidity { + fn decode(value: &mut I) -> Option { + match value.read_byte()? { + 0 => Some(TransactionValidity::Invalid(i8::decode(value)?)), + 1 => { + let priority = TransactionPriority::decode(value)?; + let requires = Vec::decode(value)?; + let provides = Vec::decode(value)?; + let longevity = TransactionLongevity::decode(value)?; + let propagate = bool::decode(value).unwrap_or(true); + + Some(TransactionValidity::Valid { + priority, requires, provides, longevity, propagate, + }) + }, + 2 => Some(TransactionValidity::Unknown(i8::decode(value)?)), + _ => None, + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn should_decode_with_backward_compat() { + let old_encoding = vec![ + 1, 5, 0, 0, 0, 0, 0, 0, 0, 4, 16, 1, 2, 3, 4, 4, 12, 4, 5, 6, 42, 0, 0, 0, 0, 0, 0, 0 + ]; + + assert_eq!(TransactionValidity::decode(&mut &*old_encoding), Some(TransactionValidity::Valid { + priority: 5, + requires: vec![vec![1, 2, 3, 4]], + provides: vec![vec![4, 5, 6]], + longevity: 42, + propagate: true, + })); + } + + #[test] + fn should_encode_and_decode() { + let v = TransactionValidity::Valid { + priority: 5, + requires: vec![vec![1, 2, 3, 4]], + provides: vec![vec![4, 5, 6]], + longevity: 42, + propagate: false, + }; + + let encoded = v.encode(); + assert_eq!( + encoded, + vec![1, 5, 0, 0, 0, 0, 0, 0, 0, 4, 16, 1, 2, 3, 4, 4, 12, 4, 5, 6, 42, 0, 0, 0, 0, 0, 0, 0, 0] + ); + + // decode back + assert_eq!(TransactionValidity::decode(&mut &*encoded), Some(v)); + } +} diff --git a/substrate/core/test-runtime/src/lib.rs b/substrate/core/test-runtime/src/lib.rs index e7c6348495..980ce810e4 100644 --- a/substrate/core/test-runtime/src/lib.rs +++ b/substrate/core/test-runtime/src/lib.rs @@ -34,8 +34,9 @@ use substrate_client::{ impl_runtime_apis, }; use runtime_primitives::{ - ApplyResult, transaction_validity::TransactionValidity, + ApplyResult, create_runtime_str, + transaction_validity::TransactionValidity, traits::{ BlindCheckable, BlakeTwo256, Block as BlockT, Extrinsic as ExtrinsicT, GetNodeBlockType, GetRuntimeBlockType, AuthorityIdFor, Verify, @@ -121,14 +122,18 @@ impl BlindCheckable for Extrinsic { Err(runtime_primitives::BAD_SIGNATURE) } }, - Extrinsic::IncludeData(data) => Ok(Extrinsic::IncludeData(data)), + Extrinsic::IncludeData(_) => Err(runtime_primitives::BAD_SIGNATURE), } } } impl ExtrinsicT for Extrinsic { fn is_signed(&self) -> Option { - Some(true) + if let Extrinsic::IncludeData(_) = *self { + Some(false) + } else { + Some(true) + } } } @@ -361,6 +366,16 @@ cfg_if! { impl client_api::TaggedTransactionQueue for Runtime { fn validate_transaction(utx: ::Extrinsic) -> TransactionValidity { + if let Extrinsic::IncludeData(data) = utx { + return TransactionValidity::Valid { + priority: data.len() as u64, + requires: vec![], + provides: vec![data], + longevity: 1, + propagate: false, + }; + } + system::validate_transaction(utx) } } @@ -499,6 +514,16 @@ cfg_if! { impl client_api::TaggedTransactionQueue for Runtime { fn validate_transaction(utx: ::Extrinsic) -> TransactionValidity { + if let Extrinsic::IncludeData(data) = utx { + return TransactionValidity::Valid { + priority: data.len() as u64, + requires: vec![], + provides: vec![data], + longevity: 1, + propagate: false, + }; + } + system::validate_transaction(utx) } } diff --git a/substrate/core/test-runtime/src/system.rs b/substrate/core/test-runtime/src/system.rs index d7dccd33be..491ca0db36 100644 --- a/substrate/core/test-runtime/src/system.rs +++ b/substrate/core/test-runtime/src/system.rs @@ -190,6 +190,7 @@ pub fn validate_transaction(utx: Extrinsic) -> TransactionValidity { requires, provides, longevity: 64, + propagate: true, } } diff --git a/substrate/core/transaction-pool/graph/src/base_pool.rs b/substrate/core/transaction-pool/graph/src/base_pool.rs index 74e499674a..b3a2cf0e54 100644 --- a/substrate/core/transaction-pool/graph/src/base_pool.rs +++ b/substrate/core/transaction-pool/graph/src/base_pool.rs @@ -100,6 +100,15 @@ pub struct Transaction { pub requires: Vec, /// Tags that this transaction provides. pub provides: Vec, + /// Should that transaction be propagated. + pub propagate: bool, +} + +impl Transaction { + /// Returns `true` if the transaction should be propagated to other peers. + pub fn is_propagateable(&self) -> bool { + self.propagate + } } impl fmt::Debug for Transaction where @@ -123,6 +132,7 @@ impl fmt::Debug for Transaction where write!(fmt, "priority: {:?}, ", &self.priority)?; write!(fmt, "valid_till: {:?}, ", &self.valid_till)?; write!(fmt, "bytes: {:?}, ", &self.bytes)?; + write!(fmt, "propagate: {:?}, ", &self.propagate)?; write!(fmt, "requires: [")?; print_tags(fmt, &self.requires)?; write!(fmt, "], provides: [")?; @@ -473,6 +483,7 @@ mod tests { valid_till: 64u64, requires: vec![], provides: vec![vec![1]], + propagate: true, }).unwrap(); // then @@ -494,6 +505,7 @@ mod tests { valid_till: 64u64, requires: vec![], provides: vec![vec![1]], + propagate: true, }).unwrap(); pool.import(Transaction { data: vec![1u8], @@ -503,6 +515,7 @@ mod tests { valid_till: 64u64, requires: vec![], provides: vec![vec![1]], + propagate: true, }).unwrap_err(); // then @@ -525,6 +538,7 @@ mod tests { valid_till: 64u64, requires: vec![vec![0]], provides: vec![vec![1]], + propagate: true, }).unwrap(); assert_eq!(pool.ready().count(), 0); assert_eq!(pool.ready.len(), 0); @@ -536,6 +550,7 @@ mod tests { valid_till: 64u64, requires: vec![], provides: vec![vec![0]], + propagate: true, }).unwrap(); // then @@ -557,6 +572,7 @@ mod tests { valid_till: 64u64, requires: vec![vec![0]], provides: vec![vec![1]], + propagate: true, }).unwrap(); pool.import(Transaction { data: vec![3u8], @@ -566,6 +582,7 @@ mod tests { valid_till: 64u64, requires: vec![vec![2]], provides: vec![], + propagate: true, }).unwrap(); pool.import(Transaction { data: vec![2u8], @@ -575,6 +592,7 @@ mod tests { valid_till: 64u64, requires: vec![vec![1]], provides: vec![vec![3], vec![2]], + propagate: true, }).unwrap(); pool.import(Transaction { data: vec![4u8], @@ -584,6 +602,7 @@ mod tests { valid_till: 64u64, requires: vec![vec![3], vec![4]], provides: vec![], + propagate: true, }).unwrap(); assert_eq!(pool.ready().count(), 0); assert_eq!(pool.ready.len(), 0); @@ -596,6 +615,7 @@ mod tests { valid_till: 64u64, requires: vec![], provides: vec![vec![0], vec![4]], + propagate: true, }).unwrap(); // then @@ -627,6 +647,7 @@ mod tests { valid_till: 64u64, requires: vec![vec![0]], provides: vec![vec![1]], + propagate: true, }).unwrap(); pool.import(Transaction { data: vec![3u8], @@ -636,6 +657,7 @@ mod tests { valid_till: 64u64, requires: vec![vec![1]], provides: vec![vec![2]], + propagate: true, }).unwrap(); assert_eq!(pool.ready().count(), 0); assert_eq!(pool.ready.len(), 0); @@ -649,6 +671,7 @@ mod tests { valid_till: 64u64, requires: vec![vec![2]], provides: vec![vec![0]], + propagate: true, }).unwrap(); // then @@ -668,6 +691,7 @@ mod tests { valid_till: 64u64, requires: vec![], provides: vec![vec![0]], + propagate: true, }).unwrap(); let mut it = pool.ready().into_iter().map(|tx| tx.data[0]); assert_eq!(it.next(), Some(4)); @@ -695,6 +719,7 @@ mod tests { valid_till: 64u64, requires: vec![vec![0]], provides: vec![vec![1]], + propagate: true, }).unwrap(); pool.import(Transaction { data: vec![3u8], @@ -704,6 +729,7 @@ mod tests { valid_till: 64u64, requires: vec![vec![1]], provides: vec![vec![2]], + propagate: true, }).unwrap(); assert_eq!(pool.ready().count(), 0); assert_eq!(pool.ready.len(), 0); @@ -717,6 +743,7 @@ mod tests { valid_till: 64u64, requires: vec![vec![2]], provides: vec![vec![0]], + propagate: true, }).unwrap(); // then @@ -736,6 +763,7 @@ mod tests { valid_till: 64u64, requires: vec![], provides: vec![vec![0]], + propagate: true, }).unwrap_err(); let mut it = pool.ready().into_iter().map(|tx| tx.data[0]); assert_eq!(it.next(), None); @@ -759,6 +787,7 @@ mod tests { valid_till: 64u64, requires: vec![], provides: vec![vec![0], vec![4]], + propagate: true, }).unwrap(); pool.import(Transaction { data: vec![1u8], @@ -768,6 +797,7 @@ mod tests { valid_till: 64u64, requires: vec![vec![0]], provides: vec![vec![1]], + propagate: true, }).unwrap(); pool.import(Transaction { data: vec![3u8], @@ -777,6 +807,7 @@ mod tests { valid_till: 64u64, requires: vec![vec![2]], provides: vec![], + propagate: true, }).unwrap(); pool.import(Transaction { data: vec![2u8], @@ -786,6 +817,7 @@ mod tests { valid_till: 64u64, requires: vec![vec![1]], provides: vec![vec![3], vec![2]], + propagate: true, }).unwrap(); pool.import(Transaction { data: vec![4u8], @@ -795,6 +827,7 @@ mod tests { valid_till: 64u64, requires: vec![vec![3], vec![4]], provides: vec![], + propagate: true, }).unwrap(); // future pool.import(Transaction { @@ -805,6 +838,7 @@ mod tests { valid_till: 64u64, requires: vec![vec![11]], provides: vec![], + propagate: true, }).unwrap(); assert_eq!(pool.ready().count(), 5); assert_eq!(pool.future.len(), 1); @@ -830,6 +864,7 @@ mod tests { valid_till: 64u64, requires: vec![vec![0]], provides: vec![vec![100]], + propagate: true, }).unwrap(); // ready pool.import(Transaction { @@ -840,6 +875,7 @@ mod tests { valid_till: 64u64, requires: vec![], provides: vec![vec![1]], + propagate: true, }).unwrap(); pool.import(Transaction { data: vec![2u8], @@ -849,6 +885,7 @@ mod tests { valid_till: 64u64, requires: vec![vec![2]], provides: vec![vec![3]], + propagate: true, }).unwrap(); pool.import(Transaction { data: vec![3u8], @@ -858,6 +895,7 @@ mod tests { valid_till: 64u64, requires: vec![vec![1]], provides: vec![vec![2]], + propagate: true, }).unwrap(); pool.import(Transaction { data: vec![4u8], @@ -867,6 +905,7 @@ mod tests { valid_till: 64u64, requires: vec![vec![3], vec![2]], provides: vec![vec![4]], + propagate: true, }).unwrap(); assert_eq!(pool.ready().count(), 4); @@ -901,8 +940,36 @@ mod tests { valid_till: 64u64, requires: vec![vec![3], vec![2]], provides: vec![vec![4]], + propagate: true, }), - r#"Transaction { hash: 4, priority: 1000, valid_till: 64, bytes: 1, requires: [03,02], provides: [04], data: [4]}"#.to_owned() + "Transaction { \ +hash: 4, priority: 1000, valid_till: 64, bytes: 1, propagate: true, \ +requires: [03,02], provides: [04], data: [4]}".to_owned() ); } + + #[test] + fn transaction_propagation() { + assert_eq!(Transaction { + data: vec![4u8], + bytes: 1, + hash: 4, + priority: 1_000u64, + valid_till: 64u64, + requires: vec![vec![3], vec![2]], + provides: vec![vec![4]], + propagate: true, + }.is_propagateable(), true); + + assert_eq!(Transaction { + data: vec![4u8], + bytes: 1, + hash: 4, + priority: 1_000u64, + valid_till: 64u64, + requires: vec![vec![3], vec![2]], + provides: vec![vec![4]], + propagate: false, + }.is_propagateable(), false); + } } diff --git a/substrate/core/transaction-pool/graph/src/pool.rs b/substrate/core/transaction-pool/graph/src/pool.rs index a5b7a3d2aa..61e234f156 100644 --- a/substrate/core/transaction-pool/graph/src/pool.rs +++ b/substrate/core/transaction-pool/graph/src/pool.rs @@ -129,7 +129,7 @@ impl Pool { } match self.api.validate_transaction(at, xt.clone())? { - TransactionValidity::Valid { priority, requires, provides, longevity } => { + TransactionValidity::Valid { priority, requires, provides, longevity, propagate } => { Ok(base::Transaction { data: xt, bytes, @@ -137,6 +137,7 @@ impl Pool { priority, requires, provides, + propagate, valid_till: block_number .saturated_into::() .saturating_add(longevity), @@ -491,6 +492,7 @@ mod tests { requires: if nonce > block_number { vec![vec![nonce as u8 - 1]] } else { vec![] }, provides: vec![vec![nonce as u8]], longevity: 3, + propagate: true, }) } } diff --git a/substrate/core/transaction-pool/graph/src/ready.rs b/substrate/core/transaction-pool/graph/src/ready.rs index ca3d7322cc..3497c1bc4b 100644 --- a/substrate/core/transaction-pool/graph/src/ready.rs +++ b/substrate/core/transaction-pool/graph/src/ready.rs @@ -499,6 +499,7 @@ mod tests { valid_till: 2, requires: vec![vec![1], vec![2]], provides: vec![vec![3], vec![4]], + propagate: true, } } @@ -558,6 +559,7 @@ mod tests { valid_till: u64::max_value(), // use the max_value() here for testing. requires: vec![tx1.provides[0].clone()], provides: vec![], + propagate: true, }; // when diff --git a/substrate/core/transaction-pool/graph/src/rotator.rs b/substrate/core/transaction-pool/graph/src/rotator.rs index 2ca51ef74e..41c1b5842a 100644 --- a/substrate/core/transaction-pool/graph/src/rotator.rs +++ b/substrate/core/transaction-pool/graph/src/rotator.rs @@ -120,6 +120,7 @@ mod tests { valid_till: 1, requires: vec![], provides: vec![], + propagate: true, }; (hash, tx) @@ -185,6 +186,7 @@ mod tests { valid_till, requires: vec![], provides: vec![], + propagate: true, } } diff --git a/substrate/core/transaction-pool/src/tests.rs b/substrate/core/transaction-pool/src/tests.rs index cab44f49cc..a1ee4a50df 100644 --- a/substrate/core/transaction-pool/src/tests.rs +++ b/substrate/core/transaction-pool/src/tests.rs @@ -53,6 +53,7 @@ impl txpool::ChainApi for TestApi { requires, provides, longevity: 64, + propagate: true, }) } diff --git a/substrate/node-template/src/service.rs b/substrate/node-template/src/service.rs index 48e26d1ca5..934cf87b9c 100644 --- a/substrate/node-template/src/service.rs +++ b/substrate/node-template/src/service.rs @@ -71,7 +71,6 @@ construct_service_factory! { let proposer = Arc::new(ProposerFactory { client: service.client(), transaction_pool: service.transaction_pool(), - inherents_pool: service.inherents_pool(), }); let client = service.client(); let select_chain = service.select_chain() diff --git a/substrate/node/cli/src/service.rs b/substrate/node/cli/src/service.rs index bb1c257155..e717166cd6 100644 --- a/substrate/node/cli/src/service.rs +++ b/substrate/node/cli/src/service.rs @@ -87,7 +87,6 @@ construct_service_factory! { let proposer = Arc::new(substrate_basic_authorship::ProposerFactory { client: service.client(), transaction_pool: service.transaction_pool(), - inherents_pool: service.inherents_pool(), }); let client = service.client(); diff --git a/substrate/node/runtime/src/lib.rs b/substrate/node/runtime/src/lib.rs index 6bc118bdc0..86c73307b8 100644 --- a/substrate/node/runtime/src/lib.rs +++ b/substrate/node/runtime/src/lib.rs @@ -59,7 +59,7 @@ pub const VERSION: RuntimeVersion = RuntimeVersion { impl_name: create_runtime_str!("substrate-node"), authoring_version: 10, spec_version: 88, - impl_version: 89, + impl_version: 90, apis: RUNTIME_API_VERSIONS, }; diff --git a/substrate/srml/executive/src/lib.rs b/substrate/srml/executive/src/lib.rs index 70285f7dfa..d1c22fcb6a 100644 --- a/substrate/srml/executive/src/lib.rs +++ b/substrate/srml/executive/src/lib.rs @@ -358,6 +358,7 @@ where requires, provides, longevity: TransactionLongevity::max_value(), + propagate: true, } }, (None, None) => UnsignedValidator::validate_unsigned(&xt.deconstruct().0), @@ -432,6 +433,7 @@ mod tests { requires: vec![], provides: vec![], longevity: std::u64::MAX, + propagate: false, }, _ => TransactionValidity::Invalid(0), } @@ -569,7 +571,8 @@ mod tests { priority: 0, requires: vec![], provides: vec![], - longevity: 18446744073709551615 + longevity: 18446744073709551615, + propagate: false, }; let mut t = new_test_ext();