diff --git a/substrate/Cargo.lock b/substrate/Cargo.lock index 1f7ede9b8b..0c315da5de 100644 --- a/substrate/Cargo.lock +++ b/substrate/Cargo.lock @@ -1610,9 +1610,9 @@ dependencies = [ "parking_lot 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "sr-primitives 0.1.0", "substrate-client 0.1.0", - "substrate-extrinsic-pool 0.1.0", "substrate-keyring 0.1.0", "substrate-primitives 0.1.0", + "substrate-transaction-pool 0.1.0", ] [[package]] @@ -2795,23 +2795,6 @@ dependencies = [ "wasmi 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "substrate-extrinsic-pool" -version = "0.1.0" -dependencies = [ - "error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)", - "sr-primitives 0.1.0", - "substrate-keyring 0.1.0", - "substrate-test-client 0.1.0", - "transaction-pool 1.13.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "substrate-keyring" version = "0.1.0" @@ -2956,10 +2939,10 @@ dependencies = [ "sr-version 0.1.0", "substrate-client 0.1.0", "substrate-executor 0.1.0", - "substrate-extrinsic-pool 0.1.0", "substrate-primitives 0.1.0", "substrate-state-machine 0.1.0", "substrate-test-client 0.1.0", + "substrate-transaction-pool 0.1.0", "tokio 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -3005,13 +2988,13 @@ dependencies = [ "substrate-client 0.1.0", "substrate-client-db 0.1.0", "substrate-executor 0.1.0", - "substrate-extrinsic-pool 0.1.0", "substrate-keystore 0.1.0", "substrate-network 0.1.0", "substrate-primitives 0.1.0", "substrate-rpc 0.1.0", "substrate-rpc-servers 0.1.0", "substrate-telemetry 0.3.0", + "substrate-transaction-pool 0.1.0", "target_info 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "tokio 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -3096,6 +3079,23 @@ dependencies = [ "substrate-primitives 0.1.0", ] +[[package]] +name = "substrate-transaction-pool" +version = "0.1.0" +dependencies = [ + "error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)", + "sr-primitives 0.1.0", + "substrate-keyring 0.1.0", + "substrate-test-client 0.1.0", + "transaction-pool 1.13.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "subtle" version = "0.5.1" diff --git a/substrate/Cargo.toml b/substrate/Cargo.toml index 1f345b3bd8..cabd3e22dc 100644 --- a/substrate/Cargo.toml +++ b/substrate/Cargo.toml @@ -26,7 +26,7 @@ members = [ "core/client", "core/client/db", "core/executor", - "core/extrinsic-pool", + "core/transaction-pool", "core/keyring", "core/misbehavior-check", "core/network", diff --git a/substrate/core/cli/src/informant.rs b/substrate/core/cli/src/informant.rs index eacc95c50d..eb2cc4617d 100644 --- a/substrate/core/cli/src/informant.rs +++ b/substrate/core/cli/src/informant.rs @@ -38,7 +38,7 @@ pub fn start(service: &Service, exit: ::exit_future::Exit, handle: TaskExe let network = service.network(); let client = service.client(); - let txpool = service.extrinsic_pool(); + let txpool = service.transaction_pool(); let mut last_number = None; let mut sys = System::new(); @@ -98,7 +98,7 @@ pub fn start(service: &Service, exit: ::exit_future::Exit, handle: TaskExe Ok(()) }); - let txpool = service.extrinsic_pool(); + let txpool = service.transaction_pool(); let display_txpool_import = txpool.import_notification_stream().for_each(move |_| { let status = txpool.light_status(); telemetry!("txpool.import"; "mem_usage" => status.mem_usage, "count" => status.transaction_count, "sender" => status.senders); diff --git a/substrate/core/client/src/client.rs b/substrate/core/client/src/client.rs index 5c27887376..350d51fead 100644 --- a/substrate/core/client/src/client.rs +++ b/substrate/core/client/src/client.rs @@ -21,7 +21,7 @@ use futures::sync::mpsc; use parking_lot::{Mutex, RwLock}; use primitives::AuthorityId; use runtime_primitives::{bft::Justification, generic::{BlockId, SignedBlock, Block as RuntimeBlock}}; -use runtime_primitives::traits::{Block as BlockT, Header as HeaderT, Zero, One, As, NumberFor}; +use runtime_primitives::traits::{Block as BlockT, Header as HeaderT, Zero, One, As, NumberFor, GetHeight, BlockNumberToHash}; use runtime_primitives::BuildStorage; use primitives::{Blake2Hasher, RlpCodec, H256}; use primitives::storage::{StorageKey, StorageData}; @@ -568,6 +568,29 @@ impl Client where } } +impl GetHeight for Client where + B: backend::Backend, + E: CallExecutor + Clone, + Block: BlockT, +{ + type BlockNumber = ::Number; + fn get_height(&self) -> Self::BlockNumber { + self.backend.blockchain().info().map(|i| i.best_number).unwrap_or_else(|_| Zero::zero()) + } +} + +impl BlockNumberToHash for Client where + B: backend::Backend, + E: CallExecutor + Clone, + Block: BlockT, +{ + type BlockNumber = ::Number; + type Hash = Block::Hash; + fn block_number_to_hash(&self, n: Self::BlockNumber) -> Option { + self.block_hash(n).unwrap_or(None) + } +} + impl bft::BlockImport for Client where B: backend::Backend, diff --git a/substrate/core/rpc/Cargo.toml b/substrate/core/rpc/Cargo.toml index d9fec2e4e2..8830f628fe 100644 --- a/substrate/core/rpc/Cargo.toml +++ b/substrate/core/rpc/Cargo.toml @@ -13,7 +13,7 @@ parking_lot = "0.4" parity-codec = { version = "1.1" } substrate-client = { path = "../client" } substrate-executor = { path = "../executor" } -substrate-extrinsic-pool = { path = "../extrinsic-pool" } +substrate-transaction-pool = { path = "../transaction-pool" } substrate-primitives = { path = "../primitives" } sr-primitives = { path = "../sr-primitives" } sr-version = { path = "../sr-version" } diff --git a/substrate/core/rpc/src/author/error.rs b/substrate/core/rpc/src/author/error.rs index e831770056..b3374676e6 100644 --- a/substrate/core/rpc/src/author/error.rs +++ b/substrate/core/rpc/src/author/error.rs @@ -17,14 +17,14 @@ //! Authoring RPC module errors. use client; -use extrinsic_pool; +use transaction_pool; use rpc; use errors; error_chain! { links { - Pool(extrinsic_pool::Error, extrinsic_pool::ErrorKind) #[doc = "Pool error"]; + Pool(transaction_pool::Error, transaction_pool::ErrorKind) #[doc = "Pool error"]; Client(client::error::Error, client::error::ErrorKind) #[doc = "Client error"]; } errors { diff --git a/substrate/core/rpc/src/author/mod.rs b/substrate/core/rpc/src/author/mod.rs index 5ba5140c5e..c54fe01d8b 100644 --- a/substrate/core/rpc/src/author/mod.rs +++ b/substrate/core/rpc/src/author/mod.rs @@ -20,7 +20,7 @@ use std::sync::Arc; use client::{self, Client}; use codec::Decode; -use extrinsic_pool::{ +use transaction_pool::{ Pool, IntoPoolError, ChainApi as PoolChainApi, diff --git a/substrate/core/rpc/src/author/tests.rs b/substrate/core/rpc/src/author/tests.rs index e5cdf759da..be15b2341e 100644 --- a/substrate/core/rpc/src/author/tests.rs +++ b/substrate/core/rpc/src/author/tests.rs @@ -18,7 +18,7 @@ use super::*; use std::{sync::Arc, result::Result}; use codec::Encode; -use extrinsic_pool::{VerifiedTransaction, scoring, Transaction, ChainApi, Error as PoolError, +use transaction_pool::{VerifiedTransaction, scoring, Transaction, ChainApi, Error as PoolError, Readiness, ExtrinsicFor, VerifiedFor}; use test_client::runtime::{Block, Extrinsic, Transfer}; use test_client; diff --git a/substrate/core/rpc/src/lib.rs b/substrate/core/rpc/src/lib.rs index a62c789551..b9254cc1a7 100644 --- a/substrate/core/rpc/src/lib.rs +++ b/substrate/core/rpc/src/lib.rs @@ -25,7 +25,7 @@ extern crate jsonrpc_pubsub; extern crate parking_lot; extern crate parity_codec as codec; extern crate substrate_client as client; -extern crate substrate_extrinsic_pool as extrinsic_pool; +extern crate substrate_transaction_pool as transaction_pool; extern crate substrate_primitives as primitives; extern crate sr_primitives as runtime_primitives; extern crate substrate_state_machine as state_machine; diff --git a/substrate/core/service/Cargo.toml b/substrate/core/service/Cargo.toml index 189b3c0b18..2d1a90bab8 100644 --- a/substrate/core/service/Cargo.toml +++ b/substrate/core/service/Cargo.toml @@ -25,7 +25,7 @@ substrate-client = { path = "../../core/client" } substrate-client-db = { path = "../../core/client/db" } parity-codec = { version = "1.1" } substrate-executor = { path = "../../core/executor" } -substrate-extrinsic-pool = { path = "../../core/extrinsic-pool" } +substrate-transaction-pool = { path = "../../core/transaction-pool" } substrate-rpc = { path = "../../core/rpc" } substrate-rpc-servers = { path = "../../core/rpc-servers" } substrate-telemetry = { path = "../../core/telemetry" } diff --git a/substrate/core/service/src/components.rs b/substrate/core/service/src/components.rs index 38088b9050..9badaa49fb 100644 --- a/substrate/core/service/src/components.rs +++ b/substrate/core/service/src/components.rs @@ -26,7 +26,7 @@ use client::{self, Client}; use error; use network::{self, OnDemand}; use substrate_executor::{NativeExecutor, NativeExecutionDispatch}; -use extrinsic_pool::{self, Options as ExtrinsicPoolOptions, Pool as ExtrinsicPool}; +use transaction_pool::{self, Options as TransactionPoolOptions, Pool as TransactionPool}; use runtime_primitives::{traits::Block as BlockT, traits::Header as HeaderT, BuildStorage}; use config::Configuration; use primitives::{Blake2Hasher, RlpCodec, H256}; @@ -101,13 +101,13 @@ pub type ComponentClient = Client< pub type ComponentBlock = <::Factory as ServiceFactory>::Block; /// Extrinsic hash type for `Components` -pub type ComponentExHash = <::ExtrinsicPoolApi as extrinsic_pool::ChainApi>::Hash; +pub type ComponentExHash = <::TransactionPoolApi as transaction_pool::ChainApi>::Hash; /// Extrinsic type. pub type ComponentExtrinsic = as BlockT>::Extrinsic; /// Extrinsic pool API type for `Components`. -pub type PoolApi = ::ExtrinsicPoolApi; +pub type PoolApi = ::TransactionPoolApi; /// A set of traits for the runtime genesis config. pub trait RuntimeGenesis: Serialize + DeserializeOwned + BuildStorage {} @@ -124,9 +124,9 @@ pub trait ServiceFactory: 'static { /// Chain runtime. type RuntimeDispatch: NativeExecutionDispatch + Send + Sync + 'static; /// Extrinsic pool backend type for the full client. - type FullExtrinsicPoolApi: extrinsic_pool::ChainApi + Send + 'static; + type FullTransactionPoolApi: transaction_pool::ChainApi + Send + 'static; /// Extrinsic pool backend type for the light client. - type LightExtrinsicPoolApi: extrinsic_pool::ChainApi + 'static; + type LightTransactionPoolApi: transaction_pool::ChainApi + 'static; /// Genesis configuration for the runtime. type Genesis: RuntimeGenesis; /// Other configuration for service members. @@ -135,13 +135,13 @@ pub trait ServiceFactory: 'static { /// Network protocol id. const NETWORK_PROTOCOL_ID: network::ProtocolId; - //TODO: replace these with a constructor trait. that ExtrinsicPool implements. + //TODO: replace these with a constructor trait. that TransactionPool implements. /// Extrinsic pool constructor for the full client. - fn build_full_extrinsic_pool(config: ExtrinsicPoolOptions, client: Arc>) - -> Result, error::Error>; + fn build_full_transaction_pool(config: TransactionPoolOptions, client: Arc>) + -> Result, error::Error>; /// Extrinsic pool constructor for the light client. - fn build_light_extrinsic_pool(config: ExtrinsicPoolOptions, client: Arc>) - -> Result, error::Error>; + fn build_light_transaction_pool(config: TransactionPoolOptions, client: Arc>) + -> Result, error::Error>; /// Build network protocol. fn build_network_protocol(config: &FactoryFullConfiguration) @@ -157,7 +157,7 @@ pub trait Components: 'static { /// Client executor. type Executor: 'static + client::CallExecutor, Blake2Hasher, RlpCodec> + Send + Sync; /// Extrinsic pool type. - type ExtrinsicPoolApi: 'static + extrinsic_pool::ChainApi::ExtrinsicHash, Block=FactoryBlock>; + type TransactionPoolApi: 'static + transaction_pool::ChainApi::ExtrinsicHash, Block=FactoryBlock>; /// Create client. fn build_client( @@ -170,8 +170,8 @@ pub trait Components: 'static { ), error::Error>; /// Create extrinsic pool. - fn build_extrinsic_pool(config: ExtrinsicPoolOptions, client: Arc>) - -> Result, error::Error>; + fn build_transaction_pool(config: TransactionPoolOptions, client: Arc>) + -> Result, error::Error>; } /// A struct that implement `Components` for the full client. @@ -183,7 +183,7 @@ impl Components for FullComponents { type Factory = Factory; type Executor = FullExecutor; type Backend = FullBackend; - type ExtrinsicPoolApi = ::FullExtrinsicPoolApi; + type TransactionPoolApi = ::FullTransactionPoolApi; fn build_client( config: &FactoryFullConfiguration, @@ -202,10 +202,10 @@ impl Components for FullComponents { Ok((Arc::new(client_db::new_client(db_settings, executor, &config.chain_spec, config.execution_strategy)?), None)) } - fn build_extrinsic_pool(config: ExtrinsicPoolOptions, client: Arc>) - -> Result, error::Error> + fn build_transaction_pool(config: TransactionPoolOptions, client: Arc>) + -> Result, error::Error> { - Factory::build_full_extrinsic_pool(config, client) + Factory::build_full_transaction_pool(config, client) } } @@ -222,7 +222,7 @@ impl Components for LightComponents type Factory = Factory; type Executor = LightExecutor; type Backend = LightBackend; - type ExtrinsicPoolApi = ::LightExtrinsicPoolApi; + type TransactionPoolApi = ::LightTransactionPoolApi; fn build_client( config: &FactoryFullConfiguration, @@ -248,9 +248,9 @@ impl Components for LightComponents Ok((Arc::new(client), Some(fetcher))) } - fn build_extrinsic_pool(config: ExtrinsicPoolOptions, client: Arc>) - -> Result, error::Error> + fn build_transaction_pool(config: TransactionPoolOptions, client: Arc>) + -> Result, error::Error> { - Factory::build_light_extrinsic_pool(config, client) + Factory::build_light_transaction_pool(config, client) } } diff --git a/substrate/core/service/src/config.rs b/substrate/core/service/src/config.rs index fd0db61f8d..2655a62525 100644 --- a/substrate/core/service/src/config.rs +++ b/substrate/core/service/src/config.rs @@ -17,7 +17,7 @@ //! Service configuration. use std::net::SocketAddr; -use extrinsic_pool; +use transaction_pool; use chain_spec::ChainSpec; pub use client::ExecutionStrategy; pub use network::Roles; @@ -38,7 +38,7 @@ pub struct Configuration { /// Node roles. pub roles: Roles, /// Extrinsic pool configuration. - pub extrinsic_pool: extrinsic_pool::Options, + pub transaction_pool: transaction_pool::Options, /// Network configuration. pub network: NetworkConfiguration, /// Path to key files. @@ -77,7 +77,7 @@ impl Configuration { client: Arc>, network: Option>>, - extrinsic_pool: Arc>, + transaction_pool: Arc>, keystore: Keystore, exit: ::exit_future::Exit, signal: Option, @@ -150,12 +150,12 @@ impl Service telemetry!("node.start"; "height" => best_header.number().as_(), "best" => ?best_header.hash()); let network_protocol = ::build_network_protocol(&config)?; - let extrinsic_pool = Arc::new( - Components::build_extrinsic_pool(config.extrinsic_pool, client.clone())? + let transaction_pool = Arc::new( + Components::build_transaction_pool(config.transaction_pool, client.clone())? ); - let extrinsic_pool_adapter = ExtrinsicPoolAdapter:: { + let transaction_pool_adapter = TransactionPoolAdapter:: { imports_external_transactions: !config.roles == Roles::LIGHT, - pool: extrinsic_pool.clone(), + pool: transaction_pool.clone(), client: client.clone(), }; @@ -167,7 +167,7 @@ impl Service chain: client.clone(), on_demand: on_demand.clone() .map(|d| d as Arc>>), - transaction_pool: Arc::new(extrinsic_pool_adapter), + transaction_pool: Arc::new(transaction_pool_adapter), specialization: network_protocol, }; @@ -177,7 +177,7 @@ impl Service { // block notifications let network = network.clone(); - let txpool = extrinsic_pool.clone(); + let txpool = transaction_pool.clone(); let events = client.import_notification_stream() .for_each(move |notification| { @@ -194,7 +194,7 @@ impl Service { // extrinsic notifications let network = network.clone(); - let events = extrinsic_pool.import_notification_stream() + let events = transaction_pool.import_notification_stream() // TODO [ToDr] Consider throttling? .for_each(move |_| { network.trigger_repropagate(); @@ -218,7 +218,7 @@ impl Service let client = client.clone(); let chain = rpc::apis::chain::Chain::new(client.clone(), task_executor.clone()); let state = rpc::apis::state::State::new(client.clone(), task_executor.clone()); - let author = rpc::apis::author::Author::new(client.clone(), extrinsic_pool.clone(), task_executor.clone()); + let author = rpc::apis::author::Author::new(client.clone(), transaction_pool.clone(), task_executor.clone()); rpc::rpc_handler::, ComponentExHash, _, _, _, _, _>( state, chain, @@ -262,7 +262,7 @@ impl Service Ok(Service { client: client, network: Some(network), - extrinsic_pool: extrinsic_pool, + transaction_pool: transaction_pool, signal: Some(signal), keystore: keystore, exit, @@ -283,8 +283,8 @@ impl Service } /// Get shared extrinsic pool instance. - pub fn extrinsic_pool(&self) -> Arc> { - self.extrinsic_pool.clone() + pub fn transaction_pool(&self) -> Arc> { + self.transaction_pool.clone() } /// Get shared keystore. @@ -350,13 +350,13 @@ impl substrate_rpc::system::SystemApi for RpcConfig { } /// Transaction pool adapter. -pub struct ExtrinsicPoolAdapter { +pub struct TransactionPoolAdapter { imports_external_transactions: bool, - pool: Arc>, + pool: Arc>, client: Arc>, } -impl ExtrinsicPoolAdapter { +impl TransactionPoolAdapter { fn best_block_id(&self) -> Option>> { self.client.info() .map(|info| BlockId::hash(info.chain.best_hash)) @@ -367,7 +367,7 @@ impl ExtrinsicPoolAdapter { } } -impl network::TransactionPool, ComponentBlock> for ExtrinsicPoolAdapter { +impl network::TransactionPool, ComponentBlock> for TransactionPoolAdapter { fn transactions(&self) -> Vec<(ComponentExHash, ComponentExtrinsic)> { let best_block_id = match self.best_block_id() { Some(id) => id, @@ -398,7 +398,7 @@ impl network::TransactionPool, ComponentBlock< Ok(xt) => Some(*xt.hash()), Err(e) => match e.into_pool_error() { Ok(e) => match e.kind() { - extrinsic_pool::ErrorKind::AlreadyImported(hash) => + transaction_pool::ErrorKind::AlreadyImported(hash) => Some(::std::str::FromStr::from_str(&hash).map_err(|_| {}) .expect("Hash string is always valid")), _ => { diff --git a/substrate/core/sr-primitives/src/generic/checked_extrinsic.rs b/substrate/core/sr-primitives/src/generic/checked_extrinsic.rs index e8be8dd534..05d0fe44a2 100644 --- a/substrate/core/sr-primitives/src/generic/checked_extrinsic.rs +++ b/substrate/core/sr-primitives/src/generic/checked_extrinsic.rs @@ -25,10 +25,9 @@ use traits::{self, Member, SimpleArithmetic, MaybeDisplay}; #[derive(PartialEq, Eq, Clone)] #[cfg_attr(feature = "std", derive(Serialize, Deserialize, Debug))] pub struct CheckedExtrinsic { - /// Who this purports to be from, if anyone (note this is not a signature). - pub signed: Option, - /// The number of extrinsics have come before from the same signer. - pub index: Index, + /// Who this purports to be from and the number of extrinsics have come before + /// from the same signer, if anyone (note this is not a signature). + pub signed: Option<(AccountId, Index)>, /// The function that should be called. pub function: Call, } @@ -44,15 +43,15 @@ where type AccountId = AccountId; type Call = Call; - fn index(&self) -> &Self::Index { - &self.index + fn index(&self) -> Option<&Self::Index> { + self.signed.as_ref().map(|x| &x.1) } fn sender(&self) -> Option<&Self::AccountId> { - self.signed.as_ref() + self.signed.as_ref().map(|x| &x.0) } fn deconstruct(self) -> (Self::Call, Option) { - (self.function, self.signed) + (self.function, self.signed.map(|x| x.0)) } } diff --git a/substrate/core/sr-primitives/src/generic/era.rs b/substrate/core/sr-primitives/src/generic/era.rs new file mode 100644 index 0000000000..afc4eba13d --- /dev/null +++ b/substrate/core/sr-primitives/src/generic/era.rs @@ -0,0 +1,192 @@ +// Copyright 2017 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 . + +//! Generic implementation of an unchecked (pre-verification) extrinsic. + +use codec::{Decode, Encode, Input, Output}; + +pub type Period = u64; +pub type Phase = u64; + +/// An era to describe the longevity of a transaction. +#[derive(PartialEq, Eq, Clone, Copy)] +#[cfg_attr(feature = "std", derive(Serialize, Deserialize, Debug))] +pub enum Era { + /// The transaction is valid forever. The genesis hash must be present in the signed content. + Immortal, + + /// Period and phase are encoded: + /// - The period of validity from the block hash found in the signing material. + /// - The phase in the period that this transaction's lifetime begins (and, importantly, + /// implies which block hash is included in the signature material). If the `period` is + /// greater than 1 << 12, then it will be a factor of the times greater than 1<<12 that + /// `period` is. + Mortal(Period, Phase), +} + +/* +E.g. with period == 4: +0 10 20 30 40 +0123456789012345678901234567890123456789012 + |...| + authored -/ \- expiry +phase = 1 +n = Q(current - phase, period) + phase +*/ +impl Era { + /// Create a new era based on a period (which should be a power of two between 4 and 65536 inclusive) + /// and a block number on which it should start (or, for long periods, be shortly after the start). + pub fn mortal(period: u64, current: u64) -> Self { + let period = period.checked_next_power_of_two() + .unwrap_or(1 << 16) + .max(4) + .min(1 << 16); + let phase = current % period; + let quantize_factor = (period >> 12).max(1); + let quantized_phase = phase / quantize_factor * quantize_factor; + + Era::Mortal(period, quantized_phase) + } + + /// Create an "immortal" transaction. + pub fn immortal() -> Self { + Era::Immortal + } + + /// `true` if this is an immortal transaction. + pub fn is_immortal(&self) -> bool { + match self { + Era::Immortal => true, + _ => false, + } + } + + /// Get the block number of the start of the era whose properties this object + /// describes that `current` belongs to. + pub fn birth(self, current: u64) -> u64 { + match self { + Era::Immortal => 0, + Era::Mortal(period, phase) => (current - phase) / period * period + phase, + } + } + + /// Get the block number of the first block at which the era has ended. + pub fn death(self, current: u64) -> u64 { + match self { + Era::Immortal => u64::max_value(), + Era::Mortal(period, _) => self.birth(current) + period, + } + } +} + +impl Encode for Era { + fn encode_to(&self, output: &mut T) { + match self { + Era::Immortal => output.push_byte(0), + Era::Mortal(period, phase) => { + let quantize_factor = (*period as u64 >> 12).max(1); + let encoded = (period.trailing_zeros() - 1).max(1).min(15) as u16 | ((phase / quantize_factor) << 4) as u16; + output.push(&encoded); + } + } + } +} + +impl Decode for Era { + fn decode(input: &mut I) -> Option { + let first = input.read_byte()?; + if first == 0 { + Some(Era::Immortal) + } else { + let encoded = first as u64 + ((input.read_byte()? as u64) << 8); + let period = 2 << (encoded % (1 << 4)); + let quantize_factor = (period >> 12).max(1); + let phase = (encoded >> 4) * quantize_factor; + if period >= 4 && phase < period { + Some(Era::Mortal(period, phase)) + } else { + None + } + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn immortal_works() { + let e = Era::immortal(); + assert_eq!(e.birth(0), 0); + assert_eq!(e.death(0), u64::max_value()); + assert_eq!(e.birth(1), 0); + assert_eq!(e.death(1), u64::max_value()); + assert_eq!(e.birth(u64::max_value()), 0); + assert_eq!(e.death(u64::max_value()), u64::max_value()); + assert!(e.is_immortal()); + + assert_eq!(e.encode(), vec![0u8]); + assert_eq!(e, Era::decode(&mut&[0u8][..]).unwrap()); + } + + #[test] + fn mortal_codec_works() { + let e = Era::mortal(64, 42); + assert!(!e.is_immortal()); + + let expected = vec![5 + 42 % 16 * 16, 42 / 16]; + assert_eq!(e.encode(), expected); + assert_eq!(e, Era::decode(&mut&expected[..]).unwrap()); + } + + #[test] + fn long_period_mortal_codec_works() { + let e = Era::mortal(32768, 20000); + + let expected = vec![(14 + 2500 % 16 * 16) as u8, (2500 / 16) as u8]; + assert_eq!(e.encode(), expected); + assert_eq!(e, Era::decode(&mut&expected[..]).unwrap()); + } + + #[test] + fn era_initialisation_works() { + assert_eq!(Era::mortal(64, 42), Era::Mortal(64, 42)); + assert_eq!(Era::mortal(32768, 20000), Era::Mortal(32768, 20000)); + assert_eq!(Era::mortal(200, 513), Era::Mortal(256, 1)); + assert_eq!(Era::mortal(2, 1), Era::Mortal(4, 1)); + assert_eq!(Era::mortal(4, 5), Era::Mortal(4, 1)); + } + + #[test] + fn quantised_clamped_era_initialisation_works() { + // clamp 1000000 to 65536, quantise 1000001 % 65536 to the nearest 4 + assert_eq!(Era::mortal(1000000, 1000001), Era::Mortal(65536, 1000001 % 65536 / 4 * 4)); + } + + #[test] + fn mortal_birth_death_works() { + let e = Era::mortal(4, 6); + for i in 6..10 { + assert_eq!(e.birth(i), 6); + assert_eq!(e.death(i), 10); + } + + // wrong because it's outside of the (current...current + period) range + assert_ne!(e.birth(10), 6); + assert_ne!(e.birth(5), 6); + } +} \ No newline at end of file diff --git a/substrate/core/sr-primitives/src/generic/mod.rs b/substrate/core/sr-primitives/src/generic/mod.rs index 23907d9f6c..6732722c4d 100644 --- a/substrate/core/sr-primitives/src/generic/mod.rs +++ b/substrate/core/sr-primitives/src/generic/mod.rs @@ -19,6 +19,8 @@ // end::description[] mod unchecked_extrinsic; +mod unchecked_mortal_extrinsic; +mod era; mod checked_extrinsic; mod header; mod block; @@ -27,6 +29,8 @@ mod digest; mod tests; pub use self::unchecked_extrinsic::UncheckedExtrinsic; +pub use self::unchecked_mortal_extrinsic::UncheckedMortalExtrinsic; +pub use self::era::Era; pub use self::checked_extrinsic::CheckedExtrinsic; pub use self::header::Header; pub use self::block::{Block, SignedBlock, BlockId}; diff --git a/substrate/core/sr-primitives/src/generic/unchecked_extrinsic.rs b/substrate/core/sr-primitives/src/generic/unchecked_extrinsic.rs index c7e3693fbf..4f3a32b34d 100644 --- a/substrate/core/sr-primitives/src/generic/unchecked_extrinsic.rs +++ b/substrate/core/sr-primitives/src/generic/unchecked_extrinsic.rs @@ -21,7 +21,7 @@ use std::fmt; use rstd::prelude::*; use codec::{Decode, Encode, Input}; -use traits::{self, Member, SimpleArithmetic, MaybeDisplay}; +use traits::{self, Member, SimpleArithmetic, MaybeDisplay, Lookup}; use super::CheckedExtrinsic; /// A extrinsic right from the external world. This is unchecked and so @@ -29,10 +29,9 @@ use super::CheckedExtrinsic; #[derive(PartialEq, Eq, Clone)] #[cfg_attr(feature = "std", derive(Serialize, Deserialize))] pub struct UncheckedExtrinsic { - /// The signature and address, if this is a signed extrinsic. - pub signature: Option<(Address, Signature)>, - /// The number of extrinsics have come before from the same signer. - pub index: Index, + /// The signature, address and number of extrinsics have come before from + /// the same signer, if this is a signed extrinsic. + pub signature: Option<(Address, Signature, Index)>, /// The function that should be called. pub function: Call, } @@ -41,17 +40,15 @@ impl UncheckedExtrinsic Self { UncheckedExtrinsic { - signature: Some((signed, signature)), - index, + signature: Some((signed, signature, index)), function, } } /// New instance of an unsigned extrinsic aka "inherent". - pub fn new_unsigned(index: Index, function: Call) -> Self { + pub fn new_unsigned(function: Call) -> Self { UncheckedExtrinsic { signature: None, - index, function, } } @@ -62,7 +59,7 @@ impl UncheckedExtrinsic traits::Checkable +impl traits::Checkable for UncheckedExtrinsic where Address: Member + MaybeDisplay, @@ -70,27 +67,25 @@ where Call: Encode + Member, Signature: Member + traits::Verify, AccountId: Member + MaybeDisplay, - ThisLookup: FnOnce(Address) -> Result, + Context: Lookup, { type Checked = CheckedExtrinsic; - fn check_with(self, lookup: ThisLookup) -> Result { + fn check(self, context: &Context) -> Result { Ok(match self.signature { - Some((signed, signature)) => { - let payload = (self.index, self.function); - let signed = lookup(signed)?; + Some((signed, signature, index)) => { + let payload = (index, self.function); + let signed = context.lookup(signed)?; if !::verify_encoded_lazy(&signature, &payload, &signed) { return Err("bad signature in extrinsic") } CheckedExtrinsic { - signed: Some(signed), - index: payload.0, + signed: Some((signed, payload.0)), function: payload.1, } } None => CheckedExtrinsic { signed: None, - index: self.index, function: self.function, }, }) @@ -114,7 +109,6 @@ where Some(UncheckedExtrinsic { signature: Decode::decode(input)?, - index: Decode::decode(input)?, function: Decode::decode(input)?, }) } @@ -136,7 +130,6 @@ where v.extend(&[0u8; 4]); self.signature.encode_to(&mut v); - self.index.encode_to(&mut v); self.function.encode_to(&mut v); let length = (v.len() - 4) as u32; @@ -154,6 +147,6 @@ impl fmt::Debug for UncheckedExtrinsic fmt::Result { - write!(f, "UncheckedExtrinsic({:?}, {:?}, {:?})", self.signature.as_ref().map(|x| &x.0), self.function, self.index) + write!(f, "UncheckedExtrinsic({:?}, {:?})", self.signature.as_ref().map(|x| (&x.0, &x.2)), self.function) } } diff --git a/substrate/core/sr-primitives/src/generic/unchecked_mortal_extrinsic.rs b/substrate/core/sr-primitives/src/generic/unchecked_mortal_extrinsic.rs new file mode 100644 index 0000000000..d2565f5f35 --- /dev/null +++ b/substrate/core/sr-primitives/src/generic/unchecked_mortal_extrinsic.rs @@ -0,0 +1,278 @@ +// Copyright 2017 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 . + +//! Generic implementation of an unchecked (pre-verification) extrinsic. + +#[cfg(feature = "std")] +use std::fmt; + +use rstd::prelude::*; +use codec::{Decode, Encode, Input}; +use traits::{self, Member, SimpleArithmetic, MaybeDisplay, GetHeight, BlockNumberToHash, Lookup, + Checkable}; +use super::{CheckedExtrinsic, Era}; + +const TRANSACTION_VERSION: u8 = 1; + +/// A extrinsic right from the external world. This is unchecked and so +/// can contain a signature. +#[derive(PartialEq, Eq, Clone)] +#[cfg_attr(feature = "std", derive(Serialize, Deserialize))] +pub struct UncheckedMortalExtrinsic { + /// The signature, address, number of extrinsics have come before from + /// the same signer and an era describing the longevity of this transaction, + /// if this is a signed extrinsic. + pub signature: Option<(Address, Signature, Index, Era)>, + /// The function that should be called. + pub function: Call, +} + +impl UncheckedMortalExtrinsic { + /// New instance of a signed extrinsic aka "transaction". + pub fn new_signed(index: Index, function: Call, signed: Address, signature: Signature, era: Era) -> Self { + UncheckedMortalExtrinsic { + signature: Some((signed, signature, index, era)), + function, + } + } + + /// New instance of an unsigned extrinsic aka "inherent". + pub fn new_unsigned(function: Call) -> Self { + UncheckedMortalExtrinsic { + signature: None, + function, + } + } + + /// `true` if there is a signature. + pub fn is_signed(&self) -> bool { + self.signature.is_some() + } +} + +impl Checkable + for UncheckedMortalExtrinsic +where + Address: Member + MaybeDisplay, + Index: Encode + Member + MaybeDisplay + SimpleArithmetic, + Call: Encode + Member, + Signature: Member + traits::Verify, + AccountId: Member + MaybeDisplay, + BlockNumber: SimpleArithmetic, + Hash: Encode, + Context: Lookup + + GetHeight + + BlockNumberToHash, +{ + type Checked = CheckedExtrinsic; + + fn check(self, context: &Context) -> Result { + Ok(match self.signature { + Some((signed, signature, index, era)) => { + let h = context.block_number_to_hash(BlockNumber::sa(era.birth(context.get_height().as_()))) + .ok_or("transaction birth block ancient")?; + let payload = (index, self.function, h); + let signed = context.lookup(signed)?; + if !::verify_encoded_lazy(&signature, &payload, &signed) { + return Err("bad signature in extrinsic") + } + CheckedExtrinsic { + signed: Some((signed, payload.0)), + function: payload.1, + } + } + None => CheckedExtrinsic { + signed: None, + function: self.function, + }, + }) + } +} + +impl Decode + for UncheckedMortalExtrinsic +where + Address: Decode, + Signature: Decode, + Index: Decode, + Call: Decode, +{ + fn decode(input: &mut I) -> Option { + // This is a little more complicated than usual since the binary format must be compatible + // with substrate's generic `Vec` type. Basically this just means accepting that there + // will be a prefix of u32, which has the total number of bytes following (we don't need + // to use this). + let _length_do_not_remove_me_see_above: u32 = Decode::decode(input)?; + + let version = input.read_byte()?; + + let is_signed = version & 0b1000_0000 != 0; + let version = version & 0b0111_1111; + if version != TRANSACTION_VERSION { + return None + } + + Some(UncheckedMortalExtrinsic { + signature: if is_signed { Some(Decode::decode(input)?) } else { None }, + function: Decode::decode(input)?, + }) + } +} + +impl Encode + for UncheckedMortalExtrinsic +where + Address: Encode, + Signature: Encode, + Index: Encode, + Call: Encode, +{ + fn encode(&self) -> Vec { + let mut v = Vec::new(); + + // need to prefix with the total length as u32 to ensure it's binary comptible with + // Vec. we'll make room for it here, then overwrite once we know the length. + v.extend(&[0u8; 4]); + + // 1 byte version id. + match self.signature.as_ref() { + Some(s) => { + v.push(TRANSACTION_VERSION | 0b1000_0000); + s.encode_to(&mut v); + } + None => { + v.push(TRANSACTION_VERSION & 0b0111_1111); + } + } + self.function.encode_to(&mut v); + + let length = (v.len() - 4) as u32; + length.using_encoded(|s| v[0..4].copy_from_slice(s)); + + v + } +} + +/// TODO: use derive when possible. +#[cfg(feature = "std")] +impl fmt::Debug for UncheckedMortalExtrinsic where + Address: fmt::Debug, + Index: fmt::Debug, + Call: fmt::Debug, +{ + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "UncheckedMortalExtrinsic({:?}, {:?})", self.signature.as_ref().map(|x| (&x.0, &x.2)), self.function) + } +} + +#[cfg(test)] +mod tests { + use super::*; + + struct TestContext; + impl Lookup for TestContext { + type Source = u64; + type Target = u64; + fn lookup(&self, s: u64) -> Result { Ok(s) } + } + impl GetHeight for TestContext { + type BlockNumber = u64; + fn get_height(&self) -> u64 { 42 } + } + impl BlockNumberToHash for TestContext { + type BlockNumber = u64; + type Hash = u64; + fn block_number_to_hash(&self, n: u64) -> Option { Some(n) } + } + + #[derive(Eq, PartialEq, Clone, Debug, Serialize, Deserialize, Encode, Decode)] + struct TestSig(u64, Vec); + impl traits::Verify for TestSig { + type Signer = u64; + fn verify>(&self, mut msg: L, signer: &Self::Signer) -> bool { + *signer == self.0 && msg.get() == &self.1[..] + } + } + + const DUMMY_FUNCTION: u64 = 0; + const DUMMY_ACCOUNTID: u64 = 0; + + type Ex = UncheckedMortalExtrinsic; + type CEx = CheckedExtrinsic; + + #[test] + fn unsigned_codec_should_work() { + let ux = Ex::new_unsigned(DUMMY_FUNCTION); + let encoded = ux.encode(); + assert_eq!(Ex::decode(&mut &encoded[..]), Some(ux)); + } + + #[test] + fn signed_codec_should_work() { + let ux = Ex::new_signed(0, DUMMY_FUNCTION, DUMMY_ACCOUNTID, TestSig(DUMMY_ACCOUNTID, (DUMMY_ACCOUNTID, DUMMY_FUNCTION, 0u64).encode()), Era::immortal()); + let encoded = ux.encode(); + assert_eq!(Ex::decode(&mut &encoded[..]), Some(ux)); + } + + #[test] + fn unsigned_check_should_work() { + let ux = Ex::new_unsigned(DUMMY_FUNCTION); + assert!(!ux.is_signed()); + assert!(>::check(ux, &TestContext).is_ok()); + } + + #[test] + fn badly_signed_check_should_fail() { + let ux = Ex::new_signed(0, DUMMY_FUNCTION, DUMMY_ACCOUNTID, TestSig(DUMMY_ACCOUNTID, vec![0u8]), Era::immortal()); + assert!(ux.is_signed()); + assert_eq!(>::check(ux, &TestContext), Err("bad signature in extrinsic")); + } + + #[test] + fn immortal_signed_check_should_work() { + let ux = Ex::new_signed(0, DUMMY_FUNCTION, DUMMY_ACCOUNTID, TestSig(DUMMY_ACCOUNTID, (DUMMY_ACCOUNTID, DUMMY_FUNCTION, 0u64).encode()), Era::immortal()); + assert!(ux.is_signed()); + assert_eq!(>::check(ux, &TestContext), Ok(CEx { signed: Some((DUMMY_ACCOUNTID, 0)), function: DUMMY_FUNCTION })); + } + + #[test] + fn mortal_signed_check_should_work() { + let ux = Ex::new_signed(0, DUMMY_FUNCTION, DUMMY_ACCOUNTID, TestSig(DUMMY_ACCOUNTID, (DUMMY_ACCOUNTID, DUMMY_FUNCTION, 42u64).encode()), Era::mortal(32, 42)); + assert!(ux.is_signed()); + assert_eq!(>::check(ux, &TestContext), Ok(CEx { signed: Some((DUMMY_ACCOUNTID, 0)), function: DUMMY_FUNCTION })); + } + + #[test] + fn later_mortal_signed_check_should_work() { + let ux = Ex::new_signed(0, DUMMY_FUNCTION, DUMMY_ACCOUNTID, TestSig(DUMMY_ACCOUNTID, (DUMMY_ACCOUNTID, DUMMY_FUNCTION, 11u64).encode()), Era::mortal(32, 11)); + assert!(ux.is_signed()); + assert_eq!(>::check(ux, &TestContext), Ok(CEx { signed: Some((DUMMY_ACCOUNTID, 0)), function: DUMMY_FUNCTION })); + } + + #[test] + fn too_late_mortal_signed_check_should_fail() { + let ux = Ex::new_signed(0, DUMMY_FUNCTION, DUMMY_ACCOUNTID, TestSig(DUMMY_ACCOUNTID, (DUMMY_ACCOUNTID, DUMMY_FUNCTION, 10u64).encode()), Era::mortal(32, 10)); + assert!(ux.is_signed()); + assert_eq!(>::check(ux, &TestContext), Err("bad signature in extrinsic")); + } + + #[test] + fn too_early_mortal_signed_check_should_fail() { + let ux = Ex::new_signed(0, DUMMY_FUNCTION, DUMMY_ACCOUNTID, TestSig(DUMMY_ACCOUNTID, (DUMMY_ACCOUNTID, DUMMY_FUNCTION, 43u64).encode()), Era::mortal(32, 43)); + assert!(ux.is_signed()); + assert_eq!(>::check(ux, &TestContext), Err("bad signature in extrinsic")); + } +} \ No newline at end of file diff --git a/substrate/core/sr-primitives/src/testing.rs b/substrate/core/sr-primitives/src/testing.rs index 7426161cb7..539c58be39 100644 --- a/substrate/core/sr-primitives/src/testing.rs +++ b/substrate/core/sr-primitives/src/testing.rs @@ -123,7 +123,7 @@ pub struct TestXt(pub Option, pub u64, pub Call); impl Checkable for TestXt { type Checked = Self; - fn check_with(self, _: Context) -> Result { Ok(self) } + fn check(self, _: &Context) -> Result { Ok(self) } } impl Applyable for TestXt where Call: 'static + Sized + Send + Sync + Clone + Eq + Codec + Debug + Serialize + DeserializeOwned, @@ -132,7 +132,7 @@ impl Applyable for TestXt where type Index = u64; type Call = Call; fn sender(&self) -> Option<&u64> { self.0.as_ref() } - fn index(&self) -> &u64 { &self.1 } + fn index(&self) -> Option<&u64> { self.0.as_ref().map(|_| &self.1) } fn deconstruct(self) -> (Self::Call, Option) { (self.2, self.0) } diff --git a/substrate/core/sr-primitives/src/traits.rs b/substrate/core/sr-primitives/src/traits.rs index f2be877e59..c7453e02bf 100644 --- a/substrate/core/sr-primitives/src/traits.rs +++ b/substrate/core/sr-primitives/src/traits.rs @@ -60,7 +60,33 @@ pub trait Lookup { /// Type to lookup into. type Target; /// Attempt a lookup. - fn lookup(s: Self::Source) -> result::Result; + fn lookup(&self, s: Self::Source) -> result::Result; +} + +/// Get the "current" block number. +pub trait GetHeight { + /// The type of the block number. + type BlockNumber; + + /// Return the current block number. Not allowed to fail. + fn get_height(&self) -> Self::BlockNumber; +} + +/// Translate a block number into a hash. +pub trait BlockNumberToHash { + /// The type of the block number. + type BlockNumber: Zero; + + /// The type of the hash. + type Hash; + + /// Get the hash for a given block number, or `None` if unknown. + fn block_number_to_hash(&self, n: Self::BlockNumber) -> Option; + + /// Get the genesis block hash; this should always be known. + fn genesis_hash(&self) -> Self::Hash { + self.block_number_to_hash(Zero::zero()).expect("All blockchains must know their genesis block hash; qed") + } } /// Simple payment making trait, operating on a single generic `AccountId` type. @@ -407,10 +433,11 @@ pub type NumberFor = <::Header as Header>::Number; /// Implement for pieces of information that require some additional context `Context` in order to be /// checked. pub trait Checkable: Sized { - /// Returned if `check_with` succeeds. + /// Returned if `check` succeeds. type Checked; - fn check_with(self, context: Context) -> Result; + /// Check self, given an instance of Context. + fn check(self, c: &Context) -> Result; } /// A "checkable" piece of information, used by the standard Substrate Executive in order to @@ -421,13 +448,14 @@ pub trait BlindCheckable: Sized { /// Returned if `check` succeeds. type Checked; + /// Check self. fn check(self) -> Result; } -// Every `BlindCheckable` is also a `Checkable` for arbitrary `Context`. +// Every `BlindCheckable` is also a `StaticCheckable` for arbitrary `Context`. impl Checkable for T { type Checked = ::Checked; - fn check_with(self, _: Context) -> Result { + fn check(self, _c: &Context) -> Result { BlindCheckable::check(self) } } @@ -442,7 +470,7 @@ pub trait Applyable: Sized + Send + Sync { type AccountId: Member + MaybeDisplay; type Index: Member + MaybeDisplay + SimpleArithmetic; type Call: Member; - fn index(&self) -> &Self::Index; + fn index(&self) -> Option<&Self::Index>; fn sender(&self) -> Option<&Self::AccountId>; fn deconstruct(self) -> (Self::Call, Option); } diff --git a/substrate/core/extrinsic-pool/Cargo.toml b/substrate/core/transaction-pool/Cargo.toml similarity index 92% rename from substrate/core/extrinsic-pool/Cargo.toml rename to substrate/core/transaction-pool/Cargo.toml index 427fd96463..2e476c5171 100644 --- a/substrate/core/extrinsic-pool/Cargo.toml +++ b/substrate/core/transaction-pool/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "substrate-extrinsic-pool" +name = "substrate-transaction-pool" version = "0.1.0" authors = ["Parity Technologies "] diff --git a/substrate/core/extrinsic-pool/README.adoc b/substrate/core/transaction-pool/README.adoc similarity index 87% rename from substrate/core/extrinsic-pool/README.adoc rename to substrate/core/transaction-pool/README.adoc index e128d64c9b..48052d0fde 100644 --- a/substrate/core/extrinsic-pool/README.adoc +++ b/substrate/core/transaction-pool/README.adoc @@ -1,5 +1,5 @@ -= extrinsic-pool += transaction-pool .Summary [source, toml] diff --git a/substrate/core/extrinsic-pool/src/error.rs b/substrate/core/transaction-pool/src/error.rs similarity index 100% rename from substrate/core/extrinsic-pool/src/error.rs rename to substrate/core/transaction-pool/src/error.rs diff --git a/substrate/core/extrinsic-pool/src/lib.rs b/substrate/core/transaction-pool/src/lib.rs similarity index 100% rename from substrate/core/extrinsic-pool/src/lib.rs rename to substrate/core/transaction-pool/src/lib.rs diff --git a/substrate/core/extrinsic-pool/src/listener.rs b/substrate/core/transaction-pool/src/listener.rs similarity index 92% rename from substrate/core/extrinsic-pool/src/listener.rs rename to substrate/core/transaction-pool/src/listener.rs index 8badb331a5..42ad6ef1c3 100644 --- a/substrate/core/extrinsic-pool/src/listener.rs +++ b/substrate/core/transaction-pool/src/listener.rs @@ -76,15 +76,15 @@ impl txpool::Listener for Listener where } fn rejected(&mut self, tx: &Arc, reason: &txpool::ErrorKind) { - warn!(target: "extrinsic-pool", "Extrinsic rejected ({}): {:?}", reason, tx); + warn!(target: "transaction-pool", "Extrinsic rejected ({}): {:?}", reason, tx); } fn invalid(&mut self, tx: &Arc) { - warn!(target: "extrinsic-pool", "Extrinsic invalid: {:?}", tx); + warn!(target: "transaction-pool", "Extrinsic invalid: {:?}", tx); } fn canceled(&mut self, tx: &Arc) { - debug!(target: "extrinsic-pool", "Extrinsic canceled: {:?}", tx); + debug!(target: "transaction-pool", "Extrinsic canceled: {:?}", tx); } fn culled(&mut self, tx: &Arc) { diff --git a/substrate/core/extrinsic-pool/src/pool.rs b/substrate/core/transaction-pool/src/pool.rs similarity index 99% rename from substrate/core/extrinsic-pool/src/pool.rs rename to substrate/core/transaction-pool/src/pool.rs index 642171b376..f812a5e544 100644 --- a/substrate/core/extrinsic-pool/src/pool.rs +++ b/substrate/core/transaction-pool/src/pool.rs @@ -133,7 +133,7 @@ pub struct Ready<'a, 'b, B: 'a + ChainApi> { impl<'a, 'b, B: ChainApi> txpool::Ready> for Ready<'a, 'b, B> { fn is_ready(&mut self, xt: &VerifiedFor) -> Readiness { if self.rotator.ban_if_stale(&self.now, xt) { - debug!(target: "extrinsic-pool", "[{:?}] Banning as stale.", txpool::VerifiedTransaction::hash(xt)); + debug!(target: "transaction-pool", "[{:?}] Banning as stale.", txpool::VerifiedTransaction::hash(xt)); return Readiness::Stale; } diff --git a/substrate/core/extrinsic-pool/src/rotator.rs b/substrate/core/transaction-pool/src/rotator.rs similarity index 100% rename from substrate/core/extrinsic-pool/src/rotator.rs rename to substrate/core/transaction-pool/src/rotator.rs diff --git a/substrate/core/extrinsic-pool/src/watcher.rs b/substrate/core/transaction-pool/src/watcher.rs similarity index 100% rename from substrate/core/extrinsic-pool/src/watcher.rs rename to substrate/core/transaction-pool/src/watcher.rs diff --git a/substrate/doc/packages/substrate.adoc b/substrate/doc/packages/substrate.adoc index 153900d783..ee246d0909 100644 --- a/substrate/doc/packages/substrate.adoc +++ b/substrate/doc/packages/substrate.adoc @@ -15,7 +15,7 @@ include::../../environmental/README.adoc[] include::../../core/executor/README.adoc[] -include::../../core/extrinsic-pool/README.adoc[] +include::../../core/transaction-pool/README.adoc[] include::../../core/keyring/README.adoc[] diff --git a/substrate/node/api/src/lib.rs b/substrate/node/api/src/lib.rs index aee45ac81d..01945537eb 100644 --- a/substrate/node/api/src/lib.rs +++ b/substrate/node/api/src/lib.rs @@ -31,10 +31,9 @@ use client::backend::Backend; use client::block_builder::BlockBuilder as ClientBlockBuilder; use client::{Client, CallExecutor}; use primitives::{ - AccountId, Block, BlockId, Hash, Index, InherentData, - SessionKey, Timestamp, UncheckedExtrinsic + AccountId, Block, BlockId, BlockNumber, Hash, Index, InherentData, SessionKey, Timestamp, UncheckedExtrinsic }; -use sr_primitives::transaction_validity::TransactionValidity; +use sr_primitives::{transaction_validity::TransactionValidity, traits::{GetHeight, BlockNumberToHash}}; use substrate_primitives::{Blake2Hasher, RlpCodec}; /// Build new blocks. @@ -49,7 +48,7 @@ pub trait BlockBuilder { /// Trait encapsulating the node API. /// /// All calls should fail when the exact runtime is unknown. -pub trait Api { +pub trait Api: GetHeight + BlockNumberToHash { /// The block builder for this API type. type BlockBuilder: BlockBuilder; @@ -91,7 +90,7 @@ pub trait Api { impl BlockBuilder for ClientBlockBuilder where B: Backend, - E: CallExecutor+ Clone, + E: CallExecutor + Clone, { fn push_extrinsic(&mut self, extrinsic: UncheckedExtrinsic) -> Result<()> { self.push(extrinsic).map_err(Into::into) diff --git a/substrate/node/consensus/src/lib.rs b/substrate/node/consensus/src/lib.rs index a807ad69a7..ecb57943ee 100644 --- a/substrate/node/consensus/src/lib.rs +++ b/substrate/node/consensus/src/lib.rs @@ -48,6 +48,7 @@ use std::time::{self, Duration, Instant}; use codec::{Decode, Encode}; use node_api::Api; use node_primitives::{AccountId, Hash, Block, BlockId, BlockNumber, Header, Timestamp, SessionKey}; +use runtime_primitives::generic::Era; use primitives::{AuthorityId, ed25519}; use transaction_pool::TransactionPool; use tokio::runtime::TaskExecutor; @@ -400,14 +401,13 @@ impl bft::Proposer for Proposer => MisbehaviorKind::BftDoubleCommit(round as u32, (h1, s1.signature), (h2, s2.signature)), } }; - let payload = (next_index, Call::Consensus(ConsensusCall::report_misbehavior(report))); + let payload = (next_index, Call::Consensus(ConsensusCall::report_misbehavior(report)), self.client.genesis_hash()); let signature = self.local_key.sign(&payload.encode()).into(); next_index += 1; let local_id = self.local_key.public().0.into(); let extrinsic = UncheckedExtrinsic { - signature: Some((node_runtime::RawAddress::Id(local_id), signature)), - index: payload.0, + signature: Some((node_runtime::RawAddress::Id(local_id), signature, payload.0, Era::immortal())), function: payload.1, }; let uxt: GenericExtrinsic = Decode::decode(&mut extrinsic.encode().as_slice()).expect("Encoded extrinsic is valid"); diff --git a/substrate/node/executor/src/lib.rs b/substrate/node/executor/src/lib.rs index 6c4ee9de3e..aa43e4e65e 100644 --- a/substrate/node/executor/src/lib.rs +++ b/substrate/node/executor/src/lib.rs @@ -54,7 +54,7 @@ mod tests { ed25519::{Public, Pair}}; use node_primitives::{Hash, BlockNumber, AccountId}; use runtime_primitives::traits::{Header as HeaderT, Digest as DigestT}; - use runtime_primitives::{generic, ApplyOutcome, ApplyError, ApplyResult}; + use runtime_primitives::{generic, generic::Era, ApplyOutcome, ApplyError, ApplyResult}; use {balances, staking, session, system, consensus, timestamp, treasury}; use system::{EventRecord, Phase}; use node_runtime::{Header, Block, UncheckedExtrinsic, CheckedExtrinsic, Call, Runtime, Balances, @@ -63,6 +63,7 @@ mod tests { const BLOATY_CODE: &[u8] = include_bytes!("../../runtime/wasm/target/wasm32-unknown-unknown/release/node_runtime.wasm"); const COMPACT_CODE: &[u8] = include_bytes!("../../runtime/wasm/target/wasm32-unknown-unknown/release/node_runtime.compact.wasm"); + const GENESIS_HASH: [u8; 32] = [69u8; 32]; // TODO: move into own crate. macro_rules! map { @@ -81,19 +82,17 @@ mod tests { fn sign(xt: CheckedExtrinsic) -> UncheckedExtrinsic { match xt.signed { - Some(signed) => { - let payload = (xt.index, xt.function); + Some((signed, index)) => { + let payload = (index, xt.function, GENESIS_HASH); let pair = Pair::from(Keyring::from_public(Public::from_raw(signed.clone().into())).unwrap()); let signature = pair.sign(&payload.encode()).into(); UncheckedExtrinsic { - signature: Some((balances::address::Address::Id(signed), signature)), - index: payload.0, + signature: Some((balances::address::Address::Id(signed), signature, payload.0, Era::mortal(256, 0))), function: payload.1, } } None => UncheckedExtrinsic { signature: None, - index: xt.index, function: xt.function, }, } @@ -101,8 +100,7 @@ mod tests { fn xt() -> UncheckedExtrinsic { sign(CheckedExtrinsic { - signed: Some(alice()), - index: 0, + signed: Some((alice(), 0)), function: Call::Balances(balances::Call::transfer::(bob().into(), 69)), }) } @@ -283,7 +281,7 @@ mod tests { fn block1(support_changes_trie: bool) -> (Vec, Hash) { construct_block( 1, - [69u8; 32].into(), + GENESIS_HASH.into(), if support_changes_trie { hex!("1755be7303767b4d3855694b4f0ebd9d64b7011124d0ec1ad3e17c2a0d65e245").into() } else { @@ -297,12 +295,10 @@ mod tests { vec![ CheckedExtrinsic { signed: None, - index: 0, function: Call::Timestamp(timestamp::Call::set(42)), }, CheckedExtrinsic { - signed: Some(alice()), - index: 0, + signed: Some((alice(), 0)), function: Call::Balances(balances::Call::transfer(bob().into(), 69)), }, ] @@ -313,22 +309,19 @@ mod tests { construct_block( 2, block1(false).1, - hex!("29fa1d0aa83662c571315af54b106c73823a31f759793803bf8929960b67b138").into(), + hex!("60efe1a65e7c79041b02e56ec122d6eaedfa476e0a9f6f1f68eb0c8f402c4514").into(), None, vec![ CheckedExtrinsic { signed: None, - index: 0, function: Call::Timestamp(timestamp::Call::set(52)), }, CheckedExtrinsic { - signed: Some(bob()), - index: 0, + signed: Some((bob(), 0)), function: Call::Balances(balances::Call::transfer(alice().into(), 5)), }, CheckedExtrinsic { - signed: Some(alice()), - index: 1, + signed: Some((alice(), 1)), function: Call::Balances(balances::Call::transfer(bob().into(), 15)), } ] @@ -338,18 +331,16 @@ mod tests { fn block1big() -> (Vec, Hash) { construct_block( 1, - [69u8; 32].into(), + GENESIS_HASH.into(), hex!("fe0e07c7b054fe186387461d455d536860e9c71d6979fd9dbf755e96ce070d04").into(), None, vec![ CheckedExtrinsic { signed: None, - index: 0, function: Call::Timestamp(timestamp::Call::set(42)), }, CheckedExtrinsic { - signed: Some(alice()), - index: 0, + signed: Some((alice(), 0)), function: Call::Consensus(consensus::Call::remark(vec![0; 120000])), } ] diff --git a/substrate/node/runtime/src/lib.rs b/substrate/node/runtime/src/lib.rs index 9068d95d35..27e8bc6d4e 100644 --- a/substrate/node/runtime/src/lib.rs +++ b/substrate/node/runtime/src/lib.rs @@ -223,11 +223,11 @@ pub type Block = generic::Block; /// BlockId type as expected by this runtime. pub type BlockId = generic::BlockId; /// Unchecked extrinsic type as expected by this runtime. -pub type UncheckedExtrinsic = generic::UncheckedExtrinsic; +pub type UncheckedExtrinsic = generic::UncheckedMortalExtrinsic; /// Extrinsic type that has already been checked. pub type CheckedExtrinsic = generic::CheckedExtrinsic; /// Executive: handles dispatch to the various modules. -pub type Executive = executive::Executive; +pub type Executive = executive::Executive, Balances, AllModules>; pub mod api { impl_stubs!( @@ -251,19 +251,13 @@ pub mod api { /// Produces the list of inherent extrinsics. fn inherent_extrinsics(data: InherentData) -> Vec { - let make_inherent = |function| UncheckedExtrinsic { - signature: Default::default(), - function, - index: 0, - }; - - let mut inherent = vec![ - make_inherent(Call::Timestamp(TimestampCall::set(data.timestamp))), - ]; + let mut inherent = vec![generic::UncheckedMortalExtrinsic::new_unsigned( + Call::Timestamp(TimestampCall::set(data.timestamp)) + )]; if !data.offline_indices.is_empty() { - inherent.push(make_inherent( - Call::Consensus(ConsensusCall::note_offline(data.offline_indices)) + inherent.push(generic::UncheckedMortalExtrinsic::new_unsigned( + Call::Consensus(ConsensusCall::note_offline(data.offline_indices)) )); } diff --git a/substrate/node/service/src/lib.rs b/substrate/node/service/src/lib.rs index 469349d1c4..5852ac29f7 100644 --- a/substrate/node/service/src/lib.rs +++ b/substrate/node/service/src/lib.rs @@ -50,7 +50,7 @@ use tokio::runtime::TaskExecutor; use service::FactoryFullConfiguration; use primitives::{Blake2Hasher, RlpCodec}; -pub use service::{Roles, PruningMode, ExtrinsicPoolOptions, +pub use service::{Roles, PruningMode, TransactionPoolOptions, ErrorKind, Error, ComponentBlock, LightComponents, FullComponents}; pub use client::ExecutionStrategy; @@ -97,20 +97,20 @@ impl service::ServiceFactory for Factory { type ExtrinsicHash = Hash; type NetworkProtocol = DemoProtocol; type RuntimeDispatch = node_executor::Executor; - type FullExtrinsicPoolApi = transaction_pool::ChainApi>; - type LightExtrinsicPoolApi = transaction_pool::ChainApi>; + type FullTransactionPoolApi = transaction_pool::ChainApi>; + type LightTransactionPoolApi = transaction_pool::ChainApi>; type Genesis = GenesisConfig; type Configuration = CustomConfiguration; const NETWORK_PROTOCOL_ID: network::ProtocolId = ::node_network::PROTOCOL_ID; - fn build_full_extrinsic_pool(config: ExtrinsicPoolOptions, client: Arc>) + fn build_full_transaction_pool(config: TransactionPoolOptions, client: Arc>) -> Result>, Error> { Ok(TransactionPool::new(config, transaction_pool::ChainApi::new(client))) } - fn build_light_extrinsic_pool(config: ExtrinsicPoolOptions, client: Arc>) + fn build_light_transaction_pool(config: TransactionPoolOptions, client: Arc>) -> Result>, Error> { Ok(TransactionPool::new(config, transaction_pool::ChainApi::new(client))) @@ -180,7 +180,7 @@ pub fn new_full(config: Configuration, executor: TaskExecutor) client.clone(), client.clone(), consensus_net, - service.extrinsic_pool(), + service.transaction_pool(), executor, key, )) diff --git a/substrate/node/transaction-pool/Cargo.toml b/substrate/node/transaction-pool/Cargo.toml index 1d410994f5..2c82b404c8 100644 --- a/substrate/node/transaction-pool/Cargo.toml +++ b/substrate/node/transaction-pool/Cargo.toml @@ -13,6 +13,6 @@ node-runtime = { path = "../runtime" } substrate-client = { path = "../../core/client" } parity-codec = { version = "1.1" } substrate-keyring = { path = "../../core/keyring" } -substrate-extrinsic-pool = { path = "../../core/extrinsic-pool" } +substrate-transaction-pool = { path = "../../core/transaction-pool" } substrate-primitives = { path = "../../core/primitives" } sr-primitives = { path = "../../core/sr-primitives" } diff --git a/substrate/node/transaction-pool/src/error.rs b/substrate/node/transaction-pool/src/error.rs index 7d1712a55a..6481ad07cd 100644 --- a/substrate/node/transaction-pool/src/error.rs +++ b/substrate/node/transaction-pool/src/error.rs @@ -14,14 +14,14 @@ // You should have received a copy of the GNU General Public License // along with Substrate. If not, see . -use extrinsic_pool; +use transaction_pool; use node_api; use primitives::Hash; use runtime::{Address, UncheckedExtrinsic}; error_chain! { links { - Pool(extrinsic_pool::Error, extrinsic_pool::ErrorKind); + Pool(transaction_pool::Error, transaction_pool::ErrorKind); Api(node_api::Error, node_api::ErrorKind); } errors { @@ -63,10 +63,10 @@ error_chain! { } } -impl extrinsic_pool::IntoPoolError for Error { - fn into_pool_error(self) -> ::std::result::Result { +impl transaction_pool::IntoPoolError for Error { + fn into_pool_error(self) -> ::std::result::Result { match self { - Error(ErrorKind::Pool(e), c) => Ok(extrinsic_pool::Error(e, c)), + Error(ErrorKind::Pool(e), c) => Ok(transaction_pool::Error(e, c)), e => Err(e), } } diff --git a/substrate/node/transaction-pool/src/lib.rs b/substrate/node/transaction-pool/src/lib.rs index 44b6ca3d03..5d9db24f45 100644 --- a/substrate/node/transaction-pool/src/lib.rs +++ b/substrate/node/transaction-pool/src/lib.rs @@ -16,7 +16,7 @@ extern crate substrate_client as client; extern crate parity_codec as codec; -extern crate substrate_extrinsic_pool as extrinsic_pool; +extern crate substrate_transaction_pool as transaction_pool; extern crate substrate_primitives; extern crate sr_primitives; extern crate node_runtime as runtime; @@ -42,20 +42,20 @@ use std::{ }; use codec::{Decode, Encode}; -use extrinsic_pool::{Readiness, scoring::{Change, Choice}, VerifiedFor, ExtrinsicFor}; +use transaction_pool::{Readiness, scoring::{Change, Choice}, VerifiedFor, ExtrinsicFor}; use node_api::Api; -use primitives::{AccountId, BlockId, Block, Hash, Index}; -use runtime::{UncheckedExtrinsic, RawAddress}; -use sr_primitives::traits::{Bounded, Checkable, Hash as HashT, BlakeTwo256}; +use primitives::{AccountId, BlockId, Block, Hash, Index, BlockNumber}; +use runtime::{Address, UncheckedExtrinsic}; +use sr_primitives::traits::{Bounded, Checkable, Hash as HashT, BlakeTwo256, Lookup, GetHeight, BlockNumberToHash}; -pub use extrinsic_pool::{Options, Status, LightStatus, VerifiedTransaction as VerifiedTransactionOps}; +pub use transaction_pool::{Options, Status, LightStatus, VerifiedTransaction as VerifiedTransactionOps}; pub use error::{Error, ErrorKind, Result}; /// Maximal size of a single encoded extrinsic. const MAX_TRANSACTION_SIZE: usize = 4 * 1024 * 1024; /// Type alias for the transaction pool. -pub type TransactionPool = extrinsic_pool::Pool>; +pub type TransactionPool = transaction_pool::Pool>; /// A verified transaction which should be includable and non-inherent. #[derive(Clone, Debug)] @@ -86,7 +86,7 @@ impl VerifiedTransaction { } } -impl extrinsic_pool::VerifiedTransaction for VerifiedTransaction { +impl transaction_pool::VerifiedTransaction for VerifiedTransaction { type Hash = Hash; type Sender = AccountId; @@ -119,8 +119,32 @@ impl ChainApi where } } +/// "Chain" context (used for checking transactions) which uses data local to our node/transaction pool. +/// +/// This is due for removal when #721 lands +pub struct LocalContext<'a, A: 'a>(&'a Arc); +impl<'a, A: 'a + Api> GetHeight for LocalContext<'a, A> { + type BlockNumber = BlockNumber; + fn get_height(&self) -> BlockNumber { + self.0.get_height() + } +} +impl<'a, A: 'a + Api> BlockNumberToHash for LocalContext<'a, A> { + type BlockNumber = BlockNumber; + type Hash = Hash; + fn block_number_to_hash(&self, n: BlockNumber) -> Option { + self.0.block_number_to_hash(n) + } +} +impl<'a, A: 'a + Api> Lookup for LocalContext<'a, A> { + type Source = Address; + type Target = AccountId; + fn lookup(&self, a: Address) -> ::std::result::Result { + self.0.lookup(&BlockId::number(self.get_height()), a).unwrap_or(None).ok_or("error with lookup") + } +} -impl extrinsic_pool::ChainApi for ChainApi where +impl transaction_pool::ChainApi for ChainApi where A: Api + Send + Sync, { type Block = Block; @@ -145,13 +169,8 @@ impl extrinsic_pool::ChainApi for ChainApi where } debug!(target: "transaction-pool", "Transaction submitted: {}", ::substrate_primitives::hexdisplay::HexDisplay::from(&encoded)); - let checked = uxt.clone().check_with(|a| { - match a { - RawAddress::Id(id) => Ok(id), - RawAddress::Index(_) => Err("Index based addresses are not supported".into()),// TODO: Make index addressing optional in substrate - } - })?; - let sender = checked.signed.expect("Only signed extrinsics are allowed at this point"); + let checked = uxt.clone().check(&LocalContext(&self.api))?; + let (sender, index) = checked.signed.expect("function previously bailed unless uxt.is_signed(); qed"); if encoded_size < 1024 { @@ -161,7 +180,7 @@ impl extrinsic_pool::ChainApi for ChainApi where } Ok(VerifiedTransaction { - index: checked.index, + index, sender, hash, encoded_size, @@ -214,7 +233,7 @@ impl extrinsic_pool::ChainApi for ChainApi where } fn update_scores( - xts: &[extrinsic_pool::Transaction>], + xts: &[transaction_pool::Transaction>], scores: &mut [Self::Score], _change: Change<()> ) { diff --git a/substrate/srml/balances/src/lib.rs b/substrate/srml/balances/src/lib.rs index c56b8d949a..b26904e0fb 100644 --- a/substrate/srml/balances/src/lib.rs +++ b/substrate/srml/balances/src/lib.rs @@ -46,7 +46,7 @@ use codec::{Encode, Decode, Codec, Input, Output}; use runtime_support::{StorageValue, StorageMap, Parameter}; use runtime_support::dispatch::Result; use primitives::traits::{Zero, One, SimpleArithmetic, OnFinalise, MakePayment, - As, Lookup, Member, CheckedAdd, CheckedSub}; + As, Lookup, Member, CheckedAdd, CheckedSub, GetHeight, BlockNumberToHash}; use address::Address as RawAddress; use system::ensure_signed; @@ -630,6 +630,13 @@ impl Module { >::put(v); } } + + pub fn lookup(a: address::Address) -> result::Result { + match a { + address::Address::Id(i) => Ok(i), + address::Address::Index(i) => >::lookup_index(i).ok_or("invalid account index"), + } + } } impl OnFinalise for Module { @@ -637,14 +644,33 @@ impl OnFinalise for Module { } } -impl Lookup for Module { +pub struct ChainContext(::rstd::marker::PhantomData); +impl Default for ChainContext { + fn default() -> Self { + ChainContext(::rstd::marker::PhantomData) + } +} + +impl Lookup for ChainContext { type Source = address::Address; type Target = T::AccountId; - fn lookup(a: Self::Source) -> result::Result { - match a { - address::Address::Id(i) => Ok(i), - address::Address::Index(i) => >::lookup_index(i).ok_or("invalid account index"), - } + fn lookup(&self, a: Self::Source) -> result::Result { + >::lookup(a) + } +} + +impl GetHeight for ChainContext { + type BlockNumber = T::BlockNumber; + fn get_height(&self) -> Self::BlockNumber { + >::block_number() + } +} + +impl BlockNumberToHash for ChainContext { + type BlockNumber = T::BlockNumber; + type Hash = T::Hash; + fn block_number_to_hash(&self, n: Self::BlockNumber) -> Option { + Some(>::block_hash(n)) } } diff --git a/substrate/srml/council/src/seats.rs b/substrate/srml/council/src/seats.rs index fd118bca09..a64dd4e0c7 100644 --- a/substrate/srml/council/src/seats.rs +++ b/substrate/srml/council/src/seats.rs @@ -17,7 +17,7 @@ //! Council system: Handles the voting in and maintenance of council members. use rstd::prelude::*; -use primitives::traits::{Zero, One, As, Lookup, OnFinalise}; +use primitives::traits::{Zero, One, As, OnFinalise}; use runtime_io::print; use srml_support::{StorageValue, StorageMap, dispatch::Result}; use democracy; diff --git a/substrate/srml/executive/src/lib.rs b/substrate/srml/executive/src/lib.rs index 19f42888fe..9eb0473a92 100644 --- a/substrate/srml/executive/src/lib.rs +++ b/substrate/srml/executive/src/lib.rs @@ -76,23 +76,22 @@ mod internal { pub struct Executive< System, Block, - Lookup, + Context, Payment, Finalisation, ->(PhantomData<(System, Block, Lookup, Payment, Finalisation)>); +>(PhantomData<(System, Block, Context, Payment, Finalisation)>); impl< - Address, + Context: Default, System: system::Trait, Block: traits::Block, - Lookup: traits::Lookup, Payment: MakePayment, Finalisation: OnFinalise, -> Executive where - Block::Extrinsic: Checkable Result> + Codec, - Result>>::Checked: Applyable, - < Result>>::Checked as Applyable>::Call: Dispatchable, - << Result>>::Checked as Applyable>::Call as Dispatchable>::Origin: From> +> Executive where + Block::Extrinsic: Checkable + Codec, + >::Checked: Applyable, + <>::Checked as Applyable>::Call: Dispatchable, + <<>::Checked as Applyable>::Call as Dispatchable>::Origin: From> { /// Start the execution of a particular block. pub fn initialise_block(header: &System::Header) { @@ -177,13 +176,13 @@ impl< /// Actually apply an extrinsic given its `encoded_len`; this doesn't note its hash. fn apply_extrinsic_no_note_with_len(uxt: Block::Extrinsic, encoded_len: usize) -> result::Result { // Verify the signature is good. - let xt = uxt.check_with(Lookup::lookup).map_err(internal::ApplyError::BadSignature)?; + let xt = uxt.check(&Default::default()).map_err(internal::ApplyError::BadSignature)?; - if let Some(sender) = xt.sender() { + if let (Some(sender), Some(index)) = (xt.sender(), xt.index()) { // check index let expected_index = >::account_nonce(sender); - if xt.index() != &expected_index { return Err( - if xt.index() < &expected_index { internal::ApplyError::Stale } else { internal::ApplyError::Future } + if index != &expected_index { return Err( + if index < &expected_index { internal::ApplyError::Stale } else { internal::ApplyError::Future } ) } // pay any fees. @@ -223,7 +222,7 @@ impl< pub fn validate_transaction(uxt: Block::Extrinsic) -> TransactionValidity { let encoded_len = uxt.encode().len(); - let xt = match uxt.check_with(Lookup::lookup) { + let xt = match uxt.check(&Default::default()) { // Checks out. Carry on. Ok(xt) => xt, // An unknown account index implies that the transaction may yet become valid. @@ -233,7 +232,7 @@ impl< Err(_) => return TransactionValidity::Invalid, }; - if let Some(sender) = xt.sender() { + if let (Some(sender), Some(index)) = (xt.sender(), xt.index()) { // pay any fees. if Payment::make_payment(sender, encoded_len).is_err() { return TransactionValidity::Invalid @@ -241,20 +240,20 @@ impl< // check index let mut expected_index = >::account_nonce(sender); - if xt.index() < &expected_index { + if index < &expected_index { return TransactionValidity::Invalid } - if *xt.index() > expected_index + As::sa(256) { + if *index > expected_index + As::sa(256) { return TransactionValidity::Unknown } let mut deps = Vec::new(); - while expected_index < *xt.index() { + while expected_index < *index { deps.push((sender, expected_index).encode()); expected_index = expected_index + One::one(); } - TransactionValidity::Valid(encoded_len as TransactionPriority, deps, vec![(sender, *xt.index()).encode()], TransactionLongevity::max_value()) + TransactionValidity::Valid(encoded_len as TransactionPriority, deps, vec![(sender, *index).encode()], TransactionLongevity::max_value()) } else { return TransactionValidity::Invalid } @@ -268,19 +267,10 @@ mod tests { use runtime_io::with_externalities; use substrate_primitives::{H256, Blake2Hasher, RlpCodec}; use primitives::BuildStorage; - use primitives::traits::{Header as HeaderT, BlakeTwo256, Lookup}; + use primitives::traits::{Header as HeaderT, BlakeTwo256}; use primitives::testing::{Digest, DigestItem, Header, Block}; use system; - struct NullLookup; - impl Lookup for NullLookup { - type Source = u64; - type Target = u64; - fn lookup(s: Self::Source) -> Result { - Ok(s) - } - } - impl_outer_origin! { pub enum Origin for Runtime { } @@ -316,7 +306,7 @@ mod tests { } type TestXt = primitives::testing::TestXt>; - type Executive = super::Executive, NullLookup, balances::Module, ()>; + type Executive = super::Executive, balances::ChainContext, balances::Module, ()>; #[test] fn balance_transfer_dispatch_works() { diff --git a/substrate/srml/staking/src/lib.rs b/substrate/srml/staking/src/lib.rs index 50b67332ac..11758e6576 100644 --- a/substrate/srml/staking/src/lib.rs +++ b/substrate/srml/staking/src/lib.rs @@ -52,8 +52,7 @@ use rstd::cmp; use runtime_support::{Parameter, StorageValue, StorageMap}; use runtime_support::dispatch::Result; use session::OnSessionChange; -use primitives::traits::{Zero, One, Bounded, OnFinalise, - As, Lookup}; +use primitives::traits::{Zero, One, Bounded, OnFinalise, As}; use balances::{address::Address, OnDilution}; use system::ensure_signed; diff --git a/substrate/srml/system/src/lib.rs b/substrate/srml/system/src/lib.rs index cf67f794b0..136bc3ec60 100644 --- a/substrate/srml/system/src/lib.rs +++ b/substrate/srml/system/src/lib.rs @@ -44,7 +44,7 @@ extern crate safe_mix; use rstd::prelude::*; use primitives::traits::{self, CheckEqual, SimpleArithmetic, SimpleBitOps, Zero, One, Bounded, - Hash, Member, MaybeDisplay, EnsureOrigin, Digest as DigestT, As}; + Hash, Member, MaybeDisplay, EnsureOrigin, Digest as DigestT, As, GetHeight, BlockNumberToHash}; use substrate_primitives::storage::well_known_keys; use runtime_support::{storage, StorageValue, StorageMap, Parameter}; use safe_mix::TripletMix; @@ -384,6 +384,21 @@ impl Module { } } +impl GetHeight for Module { + type BlockNumber = T::BlockNumber; + fn get_height(&self) -> Self::BlockNumber { + >::block_number() + } +} + +impl BlockNumberToHash for Module { + type BlockNumber = T::BlockNumber; + type Hash = T::Hash; + fn block_number_to_hash(&self, n: Self::BlockNumber) -> Option { + Some(>::block_hash(n)) + } +} + #[cfg(any(feature = "std", test))] #[derive(Serialize, Deserialize)] #[serde(rename_all = "camelCase")]