mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-06-14 13:21:10 +00:00
Transaction eras (#758)
* Initial groundwork * A mess. * Integrate * Fix tests * Unit tests * Tests for unchecked_extrisnic * fix tab * Improve binary format. * fix tests * Rename extrinsic-pool -> transaction-pool Closes #770 * Implement unimplemented. * typo
This commit is contained in:
Generated
+20
-20
@@ -1610,9 +1610,9 @@ dependencies = [
|
|||||||
"parking_lot 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
"parking_lot 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"sr-primitives 0.1.0",
|
"sr-primitives 0.1.0",
|
||||||
"substrate-client 0.1.0",
|
"substrate-client 0.1.0",
|
||||||
"substrate-extrinsic-pool 0.1.0",
|
|
||||||
"substrate-keyring 0.1.0",
|
"substrate-keyring 0.1.0",
|
||||||
"substrate-primitives 0.1.0",
|
"substrate-primitives 0.1.0",
|
||||||
|
"substrate-transaction-pool 0.1.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -2795,23 +2795,6 @@ dependencies = [
|
|||||||
"wasmi 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"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]]
|
[[package]]
|
||||||
name = "substrate-keyring"
|
name = "substrate-keyring"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
@@ -2956,10 +2939,10 @@ dependencies = [
|
|||||||
"sr-version 0.1.0",
|
"sr-version 0.1.0",
|
||||||
"substrate-client 0.1.0",
|
"substrate-client 0.1.0",
|
||||||
"substrate-executor 0.1.0",
|
"substrate-executor 0.1.0",
|
||||||
"substrate-extrinsic-pool 0.1.0",
|
|
||||||
"substrate-primitives 0.1.0",
|
"substrate-primitives 0.1.0",
|
||||||
"substrate-state-machine 0.1.0",
|
"substrate-state-machine 0.1.0",
|
||||||
"substrate-test-client 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)",
|
"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 0.1.0",
|
||||||
"substrate-client-db 0.1.0",
|
"substrate-client-db 0.1.0",
|
||||||
"substrate-executor 0.1.0",
|
"substrate-executor 0.1.0",
|
||||||
"substrate-extrinsic-pool 0.1.0",
|
|
||||||
"substrate-keystore 0.1.0",
|
"substrate-keystore 0.1.0",
|
||||||
"substrate-network 0.1.0",
|
"substrate-network 0.1.0",
|
||||||
"substrate-primitives 0.1.0",
|
"substrate-primitives 0.1.0",
|
||||||
"substrate-rpc 0.1.0",
|
"substrate-rpc 0.1.0",
|
||||||
"substrate-rpc-servers 0.1.0",
|
"substrate-rpc-servers 0.1.0",
|
||||||
"substrate-telemetry 0.3.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)",
|
"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)",
|
"tokio 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
@@ -3096,6 +3079,23 @@ dependencies = [
|
|||||||
"substrate-primitives 0.1.0",
|
"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]]
|
[[package]]
|
||||||
name = "subtle"
|
name = "subtle"
|
||||||
version = "0.5.1"
|
version = "0.5.1"
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ members = [
|
|||||||
"core/client",
|
"core/client",
|
||||||
"core/client/db",
|
"core/client/db",
|
||||||
"core/executor",
|
"core/executor",
|
||||||
"core/extrinsic-pool",
|
"core/transaction-pool",
|
||||||
"core/keyring",
|
"core/keyring",
|
||||||
"core/misbehavior-check",
|
"core/misbehavior-check",
|
||||||
"core/network",
|
"core/network",
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ pub fn start<C>(service: &Service<C>, exit: ::exit_future::Exit, handle: TaskExe
|
|||||||
|
|
||||||
let network = service.network();
|
let network = service.network();
|
||||||
let client = service.client();
|
let client = service.client();
|
||||||
let txpool = service.extrinsic_pool();
|
let txpool = service.transaction_pool();
|
||||||
let mut last_number = None;
|
let mut last_number = None;
|
||||||
|
|
||||||
let mut sys = System::new();
|
let mut sys = System::new();
|
||||||
@@ -98,7 +98,7 @@ pub fn start<C>(service: &Service<C>, exit: ::exit_future::Exit, handle: TaskExe
|
|||||||
Ok(())
|
Ok(())
|
||||||
});
|
});
|
||||||
|
|
||||||
let txpool = service.extrinsic_pool();
|
let txpool = service.transaction_pool();
|
||||||
let display_txpool_import = txpool.import_notification_stream().for_each(move |_| {
|
let display_txpool_import = txpool.import_notification_stream().for_each(move |_| {
|
||||||
let status = txpool.light_status();
|
let status = txpool.light_status();
|
||||||
telemetry!("txpool.import"; "mem_usage" => status.mem_usage, "count" => status.transaction_count, "sender" => status.senders);
|
telemetry!("txpool.import"; "mem_usage" => status.mem_usage, "count" => status.transaction_count, "sender" => status.senders);
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ use futures::sync::mpsc;
|
|||||||
use parking_lot::{Mutex, RwLock};
|
use parking_lot::{Mutex, RwLock};
|
||||||
use primitives::AuthorityId;
|
use primitives::AuthorityId;
|
||||||
use runtime_primitives::{bft::Justification, generic::{BlockId, SignedBlock, Block as RuntimeBlock}};
|
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 runtime_primitives::BuildStorage;
|
||||||
use primitives::{Blake2Hasher, RlpCodec, H256};
|
use primitives::{Blake2Hasher, RlpCodec, H256};
|
||||||
use primitives::storage::{StorageKey, StorageData};
|
use primitives::storage::{StorageKey, StorageData};
|
||||||
@@ -568,6 +568,29 @@ impl<B, E, Block> Client<B, E, Block> where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<B, E, Block> GetHeight for Client<B, E, Block> where
|
||||||
|
B: backend::Backend<Block, Blake2Hasher, RlpCodec>,
|
||||||
|
E: CallExecutor<Block, Blake2Hasher, RlpCodec> + Clone,
|
||||||
|
Block: BlockT,
|
||||||
|
{
|
||||||
|
type BlockNumber = <Block::Header as HeaderT>::Number;
|
||||||
|
fn get_height(&self) -> Self::BlockNumber {
|
||||||
|
self.backend.blockchain().info().map(|i| i.best_number).unwrap_or_else(|_| Zero::zero())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<B, E, Block> BlockNumberToHash for Client<B, E, Block> where
|
||||||
|
B: backend::Backend<Block, Blake2Hasher, RlpCodec>,
|
||||||
|
E: CallExecutor<Block, Blake2Hasher, RlpCodec> + Clone,
|
||||||
|
Block: BlockT,
|
||||||
|
{
|
||||||
|
type BlockNumber = <Block::Header as HeaderT>::Number;
|
||||||
|
type Hash = Block::Hash;
|
||||||
|
fn block_number_to_hash(&self, n: Self::BlockNumber) -> Option<Self::Hash> {
|
||||||
|
self.block_hash(n).unwrap_or(None)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<B, E, Block> bft::BlockImport<Block> for Client<B, E, Block>
|
impl<B, E, Block> bft::BlockImport<Block> for Client<B, E, Block>
|
||||||
where
|
where
|
||||||
B: backend::Backend<Block, Blake2Hasher, RlpCodec>,
|
B: backend::Backend<Block, Blake2Hasher, RlpCodec>,
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ parking_lot = "0.4"
|
|||||||
parity-codec = { version = "1.1" }
|
parity-codec = { version = "1.1" }
|
||||||
substrate-client = { path = "../client" }
|
substrate-client = { path = "../client" }
|
||||||
substrate-executor = { path = "../executor" }
|
substrate-executor = { path = "../executor" }
|
||||||
substrate-extrinsic-pool = { path = "../extrinsic-pool" }
|
substrate-transaction-pool = { path = "../transaction-pool" }
|
||||||
substrate-primitives = { path = "../primitives" }
|
substrate-primitives = { path = "../primitives" }
|
||||||
sr-primitives = { path = "../sr-primitives" }
|
sr-primitives = { path = "../sr-primitives" }
|
||||||
sr-version = { path = "../sr-version" }
|
sr-version = { path = "../sr-version" }
|
||||||
|
|||||||
@@ -17,14 +17,14 @@
|
|||||||
//! Authoring RPC module errors.
|
//! Authoring RPC module errors.
|
||||||
|
|
||||||
use client;
|
use client;
|
||||||
use extrinsic_pool;
|
use transaction_pool;
|
||||||
use rpc;
|
use rpc;
|
||||||
|
|
||||||
use errors;
|
use errors;
|
||||||
|
|
||||||
error_chain! {
|
error_chain! {
|
||||||
links {
|
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"];
|
Client(client::error::Error, client::error::ErrorKind) #[doc = "Client error"];
|
||||||
}
|
}
|
||||||
errors {
|
errors {
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ use std::sync::Arc;
|
|||||||
|
|
||||||
use client::{self, Client};
|
use client::{self, Client};
|
||||||
use codec::Decode;
|
use codec::Decode;
|
||||||
use extrinsic_pool::{
|
use transaction_pool::{
|
||||||
Pool,
|
Pool,
|
||||||
IntoPoolError,
|
IntoPoolError,
|
||||||
ChainApi as PoolChainApi,
|
ChainApi as PoolChainApi,
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ use super::*;
|
|||||||
|
|
||||||
use std::{sync::Arc, result::Result};
|
use std::{sync::Arc, result::Result};
|
||||||
use codec::Encode;
|
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};
|
Readiness, ExtrinsicFor, VerifiedFor};
|
||||||
use test_client::runtime::{Block, Extrinsic, Transfer};
|
use test_client::runtime::{Block, Extrinsic, Transfer};
|
||||||
use test_client;
|
use test_client;
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ extern crate jsonrpc_pubsub;
|
|||||||
extern crate parking_lot;
|
extern crate parking_lot;
|
||||||
extern crate parity_codec as codec;
|
extern crate parity_codec as codec;
|
||||||
extern crate substrate_client as client;
|
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 substrate_primitives as primitives;
|
||||||
extern crate sr_primitives as runtime_primitives;
|
extern crate sr_primitives as runtime_primitives;
|
||||||
extern crate substrate_state_machine as state_machine;
|
extern crate substrate_state_machine as state_machine;
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ substrate-client = { path = "../../core/client" }
|
|||||||
substrate-client-db = { path = "../../core/client/db" }
|
substrate-client-db = { path = "../../core/client/db" }
|
||||||
parity-codec = { version = "1.1" }
|
parity-codec = { version = "1.1" }
|
||||||
substrate-executor = { path = "../../core/executor" }
|
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 = { path = "../../core/rpc" }
|
||||||
substrate-rpc-servers = { path = "../../core/rpc-servers" }
|
substrate-rpc-servers = { path = "../../core/rpc-servers" }
|
||||||
substrate-telemetry = { path = "../../core/telemetry" }
|
substrate-telemetry = { path = "../../core/telemetry" }
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ use client::{self, Client};
|
|||||||
use error;
|
use error;
|
||||||
use network::{self, OnDemand};
|
use network::{self, OnDemand};
|
||||||
use substrate_executor::{NativeExecutor, NativeExecutionDispatch};
|
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 runtime_primitives::{traits::Block as BlockT, traits::Header as HeaderT, BuildStorage};
|
||||||
use config::Configuration;
|
use config::Configuration;
|
||||||
use primitives::{Blake2Hasher, RlpCodec, H256};
|
use primitives::{Blake2Hasher, RlpCodec, H256};
|
||||||
@@ -101,13 +101,13 @@ pub type ComponentClient<C> = Client<
|
|||||||
pub type ComponentBlock<C> = <<C as Components>::Factory as ServiceFactory>::Block;
|
pub type ComponentBlock<C> = <<C as Components>::Factory as ServiceFactory>::Block;
|
||||||
|
|
||||||
/// Extrinsic hash type for `Components`
|
/// Extrinsic hash type for `Components`
|
||||||
pub type ComponentExHash<C> = <<C as Components>::ExtrinsicPoolApi as extrinsic_pool::ChainApi>::Hash;
|
pub type ComponentExHash<C> = <<C as Components>::TransactionPoolApi as transaction_pool::ChainApi>::Hash;
|
||||||
|
|
||||||
/// Extrinsic type.
|
/// Extrinsic type.
|
||||||
pub type ComponentExtrinsic<C> = <ComponentBlock<C> as BlockT>::Extrinsic;
|
pub type ComponentExtrinsic<C> = <ComponentBlock<C> as BlockT>::Extrinsic;
|
||||||
|
|
||||||
/// Extrinsic pool API type for `Components`.
|
/// Extrinsic pool API type for `Components`.
|
||||||
pub type PoolApi<C> = <C as Components>::ExtrinsicPoolApi;
|
pub type PoolApi<C> = <C as Components>::TransactionPoolApi;
|
||||||
|
|
||||||
/// A set of traits for the runtime genesis config.
|
/// A set of traits for the runtime genesis config.
|
||||||
pub trait RuntimeGenesis: Serialize + DeserializeOwned + BuildStorage {}
|
pub trait RuntimeGenesis: Serialize + DeserializeOwned + BuildStorage {}
|
||||||
@@ -124,9 +124,9 @@ pub trait ServiceFactory: 'static {
|
|||||||
/// Chain runtime.
|
/// Chain runtime.
|
||||||
type RuntimeDispatch: NativeExecutionDispatch + Send + Sync + 'static;
|
type RuntimeDispatch: NativeExecutionDispatch + Send + Sync + 'static;
|
||||||
/// Extrinsic pool backend type for the full client.
|
/// Extrinsic pool backend type for the full client.
|
||||||
type FullExtrinsicPoolApi: extrinsic_pool::ChainApi<Hash=Self::ExtrinsicHash, Block=Self::Block> + Send + 'static;
|
type FullTransactionPoolApi: transaction_pool::ChainApi<Hash=Self::ExtrinsicHash, Block=Self::Block> + Send + 'static;
|
||||||
/// Extrinsic pool backend type for the light client.
|
/// Extrinsic pool backend type for the light client.
|
||||||
type LightExtrinsicPoolApi: extrinsic_pool::ChainApi<Hash=Self::ExtrinsicHash, Block=Self::Block> + 'static;
|
type LightTransactionPoolApi: transaction_pool::ChainApi<Hash=Self::ExtrinsicHash, Block=Self::Block> + 'static;
|
||||||
/// Genesis configuration for the runtime.
|
/// Genesis configuration for the runtime.
|
||||||
type Genesis: RuntimeGenesis;
|
type Genesis: RuntimeGenesis;
|
||||||
/// Other configuration for service members.
|
/// Other configuration for service members.
|
||||||
@@ -135,13 +135,13 @@ pub trait ServiceFactory: 'static {
|
|||||||
/// Network protocol id.
|
/// Network protocol id.
|
||||||
const NETWORK_PROTOCOL_ID: network::ProtocolId;
|
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.
|
/// Extrinsic pool constructor for the full client.
|
||||||
fn build_full_extrinsic_pool(config: ExtrinsicPoolOptions, client: Arc<FullClient<Self>>)
|
fn build_full_transaction_pool(config: TransactionPoolOptions, client: Arc<FullClient<Self>>)
|
||||||
-> Result<ExtrinsicPool<Self::FullExtrinsicPoolApi>, error::Error>;
|
-> Result<TransactionPool<Self::FullTransactionPoolApi>, error::Error>;
|
||||||
/// Extrinsic pool constructor for the light client.
|
/// Extrinsic pool constructor for the light client.
|
||||||
fn build_light_extrinsic_pool(config: ExtrinsicPoolOptions, client: Arc<LightClient<Self>>)
|
fn build_light_transaction_pool(config: TransactionPoolOptions, client: Arc<LightClient<Self>>)
|
||||||
-> Result<ExtrinsicPool<Self::LightExtrinsicPoolApi>, error::Error>;
|
-> Result<TransactionPool<Self::LightTransactionPoolApi>, error::Error>;
|
||||||
|
|
||||||
/// Build network protocol.
|
/// Build network protocol.
|
||||||
fn build_network_protocol(config: &FactoryFullConfiguration<Self>)
|
fn build_network_protocol(config: &FactoryFullConfiguration<Self>)
|
||||||
@@ -157,7 +157,7 @@ pub trait Components: 'static {
|
|||||||
/// Client executor.
|
/// Client executor.
|
||||||
type Executor: 'static + client::CallExecutor<FactoryBlock<Self::Factory>, Blake2Hasher, RlpCodec> + Send + Sync;
|
type Executor: 'static + client::CallExecutor<FactoryBlock<Self::Factory>, Blake2Hasher, RlpCodec> + Send + Sync;
|
||||||
/// Extrinsic pool type.
|
/// Extrinsic pool type.
|
||||||
type ExtrinsicPoolApi: 'static + extrinsic_pool::ChainApi<Hash=<Self::Factory as ServiceFactory>::ExtrinsicHash, Block=FactoryBlock<Self::Factory>>;
|
type TransactionPoolApi: 'static + transaction_pool::ChainApi<Hash=<Self::Factory as ServiceFactory>::ExtrinsicHash, Block=FactoryBlock<Self::Factory>>;
|
||||||
|
|
||||||
/// Create client.
|
/// Create client.
|
||||||
fn build_client(
|
fn build_client(
|
||||||
@@ -170,8 +170,8 @@ pub trait Components: 'static {
|
|||||||
), error::Error>;
|
), error::Error>;
|
||||||
|
|
||||||
/// Create extrinsic pool.
|
/// Create extrinsic pool.
|
||||||
fn build_extrinsic_pool(config: ExtrinsicPoolOptions, client: Arc<ComponentClient<Self>>)
|
fn build_transaction_pool(config: TransactionPoolOptions, client: Arc<ComponentClient<Self>>)
|
||||||
-> Result<ExtrinsicPool<Self::ExtrinsicPoolApi>, error::Error>;
|
-> Result<TransactionPool<Self::TransactionPoolApi>, error::Error>;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A struct that implement `Components` for the full client.
|
/// A struct that implement `Components` for the full client.
|
||||||
@@ -183,7 +183,7 @@ impl<Factory: ServiceFactory> Components for FullComponents<Factory> {
|
|||||||
type Factory = Factory;
|
type Factory = Factory;
|
||||||
type Executor = FullExecutor<Factory>;
|
type Executor = FullExecutor<Factory>;
|
||||||
type Backend = FullBackend<Factory>;
|
type Backend = FullBackend<Factory>;
|
||||||
type ExtrinsicPoolApi = <Factory as ServiceFactory>::FullExtrinsicPoolApi;
|
type TransactionPoolApi = <Factory as ServiceFactory>::FullTransactionPoolApi;
|
||||||
|
|
||||||
fn build_client(
|
fn build_client(
|
||||||
config: &FactoryFullConfiguration<Factory>,
|
config: &FactoryFullConfiguration<Factory>,
|
||||||
@@ -202,10 +202,10 @@ impl<Factory: ServiceFactory> Components for FullComponents<Factory> {
|
|||||||
Ok((Arc::new(client_db::new_client(db_settings, executor, &config.chain_spec, config.execution_strategy)?), None))
|
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<ComponentClient<Self>>)
|
fn build_transaction_pool(config: TransactionPoolOptions, client: Arc<ComponentClient<Self>>)
|
||||||
-> Result<ExtrinsicPool<Self::ExtrinsicPoolApi>, error::Error>
|
-> Result<TransactionPool<Self::TransactionPoolApi>, error::Error>
|
||||||
{
|
{
|
||||||
Factory::build_full_extrinsic_pool(config, client)
|
Factory::build_full_transaction_pool(config, client)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -222,7 +222,7 @@ impl<Factory: ServiceFactory> Components for LightComponents<Factory>
|
|||||||
type Factory = Factory;
|
type Factory = Factory;
|
||||||
type Executor = LightExecutor<Factory>;
|
type Executor = LightExecutor<Factory>;
|
||||||
type Backend = LightBackend<Factory>;
|
type Backend = LightBackend<Factory>;
|
||||||
type ExtrinsicPoolApi = <Factory as ServiceFactory>::LightExtrinsicPoolApi;
|
type TransactionPoolApi = <Factory as ServiceFactory>::LightTransactionPoolApi;
|
||||||
|
|
||||||
fn build_client(
|
fn build_client(
|
||||||
config: &FactoryFullConfiguration<Factory>,
|
config: &FactoryFullConfiguration<Factory>,
|
||||||
@@ -248,9 +248,9 @@ impl<Factory: ServiceFactory> Components for LightComponents<Factory>
|
|||||||
Ok((Arc::new(client), Some(fetcher)))
|
Ok((Arc::new(client), Some(fetcher)))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn build_extrinsic_pool(config: ExtrinsicPoolOptions, client: Arc<ComponentClient<Self>>)
|
fn build_transaction_pool(config: TransactionPoolOptions, client: Arc<ComponentClient<Self>>)
|
||||||
-> Result<ExtrinsicPool<Self::ExtrinsicPoolApi>, error::Error>
|
-> Result<TransactionPool<Self::TransactionPoolApi>, error::Error>
|
||||||
{
|
{
|
||||||
Factory::build_light_extrinsic_pool(config, client)
|
Factory::build_light_transaction_pool(config, client)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,7 +17,7 @@
|
|||||||
//! Service configuration.
|
//! Service configuration.
|
||||||
|
|
||||||
use std::net::SocketAddr;
|
use std::net::SocketAddr;
|
||||||
use extrinsic_pool;
|
use transaction_pool;
|
||||||
use chain_spec::ChainSpec;
|
use chain_spec::ChainSpec;
|
||||||
pub use client::ExecutionStrategy;
|
pub use client::ExecutionStrategy;
|
||||||
pub use network::Roles;
|
pub use network::Roles;
|
||||||
@@ -38,7 +38,7 @@ pub struct Configuration<C, G: Serialize + DeserializeOwned + BuildStorage> {
|
|||||||
/// Node roles.
|
/// Node roles.
|
||||||
pub roles: Roles,
|
pub roles: Roles,
|
||||||
/// Extrinsic pool configuration.
|
/// Extrinsic pool configuration.
|
||||||
pub extrinsic_pool: extrinsic_pool::Options,
|
pub transaction_pool: transaction_pool::Options,
|
||||||
/// Network configuration.
|
/// Network configuration.
|
||||||
pub network: NetworkConfiguration,
|
pub network: NetworkConfiguration,
|
||||||
/// Path to key files.
|
/// Path to key files.
|
||||||
@@ -77,7 +77,7 @@ impl<C: Default, G: Serialize + DeserializeOwned + BuildStorage> Configuration<C
|
|||||||
chain_spec,
|
chain_spec,
|
||||||
name: Default::default(),
|
name: Default::default(),
|
||||||
roles: Roles::FULL,
|
roles: Roles::FULL,
|
||||||
extrinsic_pool: Default::default(),
|
transaction_pool: Default::default(),
|
||||||
network: Default::default(),
|
network: Default::default(),
|
||||||
keystore_path: Default::default(),
|
keystore_path: Default::default(),
|
||||||
database_path: Default::default(),
|
database_path: Default::default(),
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ extern crate substrate_executor;
|
|||||||
extern crate substrate_client as client;
|
extern crate substrate_client as client;
|
||||||
extern crate substrate_client_db as client_db;
|
extern crate substrate_client_db as client_db;
|
||||||
extern crate parity_codec as codec;
|
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_rpc;
|
extern crate substrate_rpc;
|
||||||
extern crate substrate_rpc_servers as rpc;
|
extern crate substrate_rpc_servers as rpc;
|
||||||
extern crate target_info;
|
extern crate target_info;
|
||||||
@@ -73,7 +73,7 @@ use codec::{Encode, Decode};
|
|||||||
pub use self::error::{ErrorKind, Error};
|
pub use self::error::{ErrorKind, Error};
|
||||||
pub use config::{Configuration, Roles, PruningMode};
|
pub use config::{Configuration, Roles, PruningMode};
|
||||||
pub use chain_spec::ChainSpec;
|
pub use chain_spec::ChainSpec;
|
||||||
pub use extrinsic_pool::{Pool as ExtrinsicPool, Options as ExtrinsicPoolOptions, ChainApi, VerifiedTransaction, IntoPoolError};
|
pub use transaction_pool::{Pool as TransactionPool, Options as TransactionPoolOptions, ChainApi, VerifiedTransaction, IntoPoolError};
|
||||||
pub use client::ExecutionStrategy;
|
pub use client::ExecutionStrategy;
|
||||||
|
|
||||||
pub use components::{ServiceFactory, FullBackend, FullExecutor, LightBackend,
|
pub use components::{ServiceFactory, FullBackend, FullExecutor, LightBackend,
|
||||||
@@ -88,7 +88,7 @@ pub use components::{ServiceFactory, FullBackend, FullExecutor, LightBackend,
|
|||||||
pub struct Service<Components: components::Components> {
|
pub struct Service<Components: components::Components> {
|
||||||
client: Arc<ComponentClient<Components>>,
|
client: Arc<ComponentClient<Components>>,
|
||||||
network: Option<Arc<components::NetworkService<Components::Factory>>>,
|
network: Option<Arc<components::NetworkService<Components::Factory>>>,
|
||||||
extrinsic_pool: Arc<ExtrinsicPool<Components::ExtrinsicPoolApi>>,
|
transaction_pool: Arc<TransactionPool<Components::TransactionPoolApi>>,
|
||||||
keystore: Keystore,
|
keystore: Keystore,
|
||||||
exit: ::exit_future::Exit,
|
exit: ::exit_future::Exit,
|
||||||
signal: Option<Signal>,
|
signal: Option<Signal>,
|
||||||
@@ -150,12 +150,12 @@ impl<Components> Service<Components>
|
|||||||
telemetry!("node.start"; "height" => best_header.number().as_(), "best" => ?best_header.hash());
|
telemetry!("node.start"; "height" => best_header.number().as_(), "best" => ?best_header.hash());
|
||||||
|
|
||||||
let network_protocol = <Components::Factory>::build_network_protocol(&config)?;
|
let network_protocol = <Components::Factory>::build_network_protocol(&config)?;
|
||||||
let extrinsic_pool = Arc::new(
|
let transaction_pool = Arc::new(
|
||||||
Components::build_extrinsic_pool(config.extrinsic_pool, client.clone())?
|
Components::build_transaction_pool(config.transaction_pool, client.clone())?
|
||||||
);
|
);
|
||||||
let extrinsic_pool_adapter = ExtrinsicPoolAdapter::<Components> {
|
let transaction_pool_adapter = TransactionPoolAdapter::<Components> {
|
||||||
imports_external_transactions: !config.roles == Roles::LIGHT,
|
imports_external_transactions: !config.roles == Roles::LIGHT,
|
||||||
pool: extrinsic_pool.clone(),
|
pool: transaction_pool.clone(),
|
||||||
client: client.clone(),
|
client: client.clone(),
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -167,7 +167,7 @@ impl<Components> Service<Components>
|
|||||||
chain: client.clone(),
|
chain: client.clone(),
|
||||||
on_demand: on_demand.clone()
|
on_demand: on_demand.clone()
|
||||||
.map(|d| d as Arc<network::OnDemandService<ComponentBlock<Components>>>),
|
.map(|d| d as Arc<network::OnDemandService<ComponentBlock<Components>>>),
|
||||||
transaction_pool: Arc::new(extrinsic_pool_adapter),
|
transaction_pool: Arc::new(transaction_pool_adapter),
|
||||||
specialization: network_protocol,
|
specialization: network_protocol,
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -177,7 +177,7 @@ impl<Components> Service<Components>
|
|||||||
{
|
{
|
||||||
// block notifications
|
// block notifications
|
||||||
let network = network.clone();
|
let network = network.clone();
|
||||||
let txpool = extrinsic_pool.clone();
|
let txpool = transaction_pool.clone();
|
||||||
|
|
||||||
let events = client.import_notification_stream()
|
let events = client.import_notification_stream()
|
||||||
.for_each(move |notification| {
|
.for_each(move |notification| {
|
||||||
@@ -194,7 +194,7 @@ impl<Components> Service<Components>
|
|||||||
{
|
{
|
||||||
// extrinsic notifications
|
// extrinsic notifications
|
||||||
let network = network.clone();
|
let network = network.clone();
|
||||||
let events = extrinsic_pool.import_notification_stream()
|
let events = transaction_pool.import_notification_stream()
|
||||||
// TODO [ToDr] Consider throttling?
|
// TODO [ToDr] Consider throttling?
|
||||||
.for_each(move |_| {
|
.for_each(move |_| {
|
||||||
network.trigger_repropagate();
|
network.trigger_repropagate();
|
||||||
@@ -218,7 +218,7 @@ impl<Components> Service<Components>
|
|||||||
let client = client.clone();
|
let client = client.clone();
|
||||||
let chain = rpc::apis::chain::Chain::new(client.clone(), task_executor.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 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::<ComponentBlock<Components>, ComponentExHash<Components>, _, _, _, _, _>(
|
rpc::rpc_handler::<ComponentBlock<Components>, ComponentExHash<Components>, _, _, _, _, _>(
|
||||||
state,
|
state,
|
||||||
chain,
|
chain,
|
||||||
@@ -262,7 +262,7 @@ impl<Components> Service<Components>
|
|||||||
Ok(Service {
|
Ok(Service {
|
||||||
client: client,
|
client: client,
|
||||||
network: Some(network),
|
network: Some(network),
|
||||||
extrinsic_pool: extrinsic_pool,
|
transaction_pool: transaction_pool,
|
||||||
signal: Some(signal),
|
signal: Some(signal),
|
||||||
keystore: keystore,
|
keystore: keystore,
|
||||||
exit,
|
exit,
|
||||||
@@ -283,8 +283,8 @@ impl<Components> Service<Components>
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Get shared extrinsic pool instance.
|
/// Get shared extrinsic pool instance.
|
||||||
pub fn extrinsic_pool(&self) -> Arc<ExtrinsicPool<Components::ExtrinsicPoolApi>> {
|
pub fn transaction_pool(&self) -> Arc<TransactionPool<Components::TransactionPoolApi>> {
|
||||||
self.extrinsic_pool.clone()
|
self.transaction_pool.clone()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get shared keystore.
|
/// Get shared keystore.
|
||||||
@@ -350,13 +350,13 @@ impl substrate_rpc::system::SystemApi for RpcConfig {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Transaction pool adapter.
|
/// Transaction pool adapter.
|
||||||
pub struct ExtrinsicPoolAdapter<C: Components> {
|
pub struct TransactionPoolAdapter<C: Components> {
|
||||||
imports_external_transactions: bool,
|
imports_external_transactions: bool,
|
||||||
pool: Arc<ExtrinsicPool<C::ExtrinsicPoolApi>>,
|
pool: Arc<TransactionPool<C::TransactionPoolApi>>,
|
||||||
client: Arc<ComponentClient<C>>,
|
client: Arc<ComponentClient<C>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<C: Components> ExtrinsicPoolAdapter<C> {
|
impl<C: Components> TransactionPoolAdapter<C> {
|
||||||
fn best_block_id(&self) -> Option<BlockId<ComponentBlock<C>>> {
|
fn best_block_id(&self) -> Option<BlockId<ComponentBlock<C>>> {
|
||||||
self.client.info()
|
self.client.info()
|
||||||
.map(|info| BlockId::hash(info.chain.best_hash))
|
.map(|info| BlockId::hash(info.chain.best_hash))
|
||||||
@@ -367,7 +367,7 @@ impl<C: Components> ExtrinsicPoolAdapter<C> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<C: Components> network::TransactionPool<ComponentExHash<C>, ComponentBlock<C>> for ExtrinsicPoolAdapter<C> {
|
impl<C: Components> network::TransactionPool<ComponentExHash<C>, ComponentBlock<C>> for TransactionPoolAdapter<C> {
|
||||||
fn transactions(&self) -> Vec<(ComponentExHash<C>, ComponentExtrinsic<C>)> {
|
fn transactions(&self) -> Vec<(ComponentExHash<C>, ComponentExtrinsic<C>)> {
|
||||||
let best_block_id = match self.best_block_id() {
|
let best_block_id = match self.best_block_id() {
|
||||||
Some(id) => id,
|
Some(id) => id,
|
||||||
@@ -398,7 +398,7 @@ impl<C: Components> network::TransactionPool<ComponentExHash<C>, ComponentBlock<
|
|||||||
Ok(xt) => Some(*xt.hash()),
|
Ok(xt) => Some(*xt.hash()),
|
||||||
Err(e) => match e.into_pool_error() {
|
Err(e) => match e.into_pool_error() {
|
||||||
Ok(e) => match e.kind() {
|
Ok(e) => match e.kind() {
|
||||||
extrinsic_pool::ErrorKind::AlreadyImported(hash) =>
|
transaction_pool::ErrorKind::AlreadyImported(hash) =>
|
||||||
Some(::std::str::FromStr::from_str(&hash).map_err(|_| {})
|
Some(::std::str::FromStr::from_str(&hash).map_err(|_| {})
|
||||||
.expect("Hash string is always valid")),
|
.expect("Hash string is always valid")),
|
||||||
_ => {
|
_ => {
|
||||||
|
|||||||
@@ -25,10 +25,9 @@ use traits::{self, Member, SimpleArithmetic, MaybeDisplay};
|
|||||||
#[derive(PartialEq, Eq, Clone)]
|
#[derive(PartialEq, Eq, Clone)]
|
||||||
#[cfg_attr(feature = "std", derive(Serialize, Deserialize, Debug))]
|
#[cfg_attr(feature = "std", derive(Serialize, Deserialize, Debug))]
|
||||||
pub struct CheckedExtrinsic<AccountId, Index, Call> {
|
pub struct CheckedExtrinsic<AccountId, Index, Call> {
|
||||||
/// Who this purports to be from, if anyone (note this is not a signature).
|
/// Who this purports to be from and the number of extrinsics have come before
|
||||||
pub signed: Option<AccountId>,
|
/// from the same signer, if anyone (note this is not a signature).
|
||||||
/// The number of extrinsics have come before from the same signer.
|
pub signed: Option<(AccountId, Index)>,
|
||||||
pub index: Index,
|
|
||||||
/// The function that should be called.
|
/// The function that should be called.
|
||||||
pub function: Call,
|
pub function: Call,
|
||||||
}
|
}
|
||||||
@@ -44,15 +43,15 @@ where
|
|||||||
type AccountId = AccountId;
|
type AccountId = AccountId;
|
||||||
type Call = Call;
|
type Call = Call;
|
||||||
|
|
||||||
fn index(&self) -> &Self::Index {
|
fn index(&self) -> Option<&Self::Index> {
|
||||||
&self.index
|
self.signed.as_ref().map(|x| &x.1)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn sender(&self) -> Option<&Self::AccountId> {
|
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::AccountId>) {
|
fn deconstruct(self) -> (Self::Call, Option<Self::AccountId>) {
|
||||||
(self.function, self.signed)
|
(self.function, self.signed.map(|x| x.0))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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 <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
//! 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<T: Output>(&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<I: Input>(input: &mut I) -> Option<Self> {
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -19,6 +19,8 @@
|
|||||||
// end::description[]
|
// end::description[]
|
||||||
|
|
||||||
mod unchecked_extrinsic;
|
mod unchecked_extrinsic;
|
||||||
|
mod unchecked_mortal_extrinsic;
|
||||||
|
mod era;
|
||||||
mod checked_extrinsic;
|
mod checked_extrinsic;
|
||||||
mod header;
|
mod header;
|
||||||
mod block;
|
mod block;
|
||||||
@@ -27,6 +29,8 @@ mod digest;
|
|||||||
mod tests;
|
mod tests;
|
||||||
|
|
||||||
pub use self::unchecked_extrinsic::UncheckedExtrinsic;
|
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::checked_extrinsic::CheckedExtrinsic;
|
||||||
pub use self::header::Header;
|
pub use self::header::Header;
|
||||||
pub use self::block::{Block, SignedBlock, BlockId};
|
pub use self::block::{Block, SignedBlock, BlockId};
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ use std::fmt;
|
|||||||
|
|
||||||
use rstd::prelude::*;
|
use rstd::prelude::*;
|
||||||
use codec::{Decode, Encode, Input};
|
use codec::{Decode, Encode, Input};
|
||||||
use traits::{self, Member, SimpleArithmetic, MaybeDisplay};
|
use traits::{self, Member, SimpleArithmetic, MaybeDisplay, Lookup};
|
||||||
use super::CheckedExtrinsic;
|
use super::CheckedExtrinsic;
|
||||||
|
|
||||||
/// A extrinsic right from the external world. This is unchecked and so
|
/// A extrinsic right from the external world. This is unchecked and so
|
||||||
@@ -29,10 +29,9 @@ use super::CheckedExtrinsic;
|
|||||||
#[derive(PartialEq, Eq, Clone)]
|
#[derive(PartialEq, Eq, Clone)]
|
||||||
#[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
|
#[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
|
||||||
pub struct UncheckedExtrinsic<Address, Index, Call, Signature> {
|
pub struct UncheckedExtrinsic<Address, Index, Call, Signature> {
|
||||||
/// The signature and address, if this is a signed extrinsic.
|
/// The signature, address and number of extrinsics have come before from
|
||||||
pub signature: Option<(Address, Signature)>,
|
/// the same signer, if this is a signed extrinsic.
|
||||||
/// The number of extrinsics have come before from the same signer.
|
pub signature: Option<(Address, Signature, Index)>,
|
||||||
pub index: Index,
|
|
||||||
/// The function that should be called.
|
/// The function that should be called.
|
||||||
pub function: Call,
|
pub function: Call,
|
||||||
}
|
}
|
||||||
@@ -41,17 +40,15 @@ impl<Address, Index, Call, Signature> UncheckedExtrinsic<Address, Index, Call, S
|
|||||||
/// New instance of a signed extrinsic aka "transaction".
|
/// New instance of a signed extrinsic aka "transaction".
|
||||||
pub fn new_signed(index: Index, function: Call, signed: Address, signature: Signature) -> Self {
|
pub fn new_signed(index: Index, function: Call, signed: Address, signature: Signature) -> Self {
|
||||||
UncheckedExtrinsic {
|
UncheckedExtrinsic {
|
||||||
signature: Some((signed, signature)),
|
signature: Some((signed, signature, index)),
|
||||||
index,
|
|
||||||
function,
|
function,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// New instance of an unsigned extrinsic aka "inherent".
|
/// 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 {
|
UncheckedExtrinsic {
|
||||||
signature: None,
|
signature: None,
|
||||||
index,
|
|
||||||
function,
|
function,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -62,7 +59,7 @@ impl<Address, Index, Call, Signature> UncheckedExtrinsic<Address, Index, Call, S
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<Address, AccountId, Index, Call, Signature, ThisLookup> traits::Checkable<ThisLookup>
|
impl<Address, AccountId, Index, Call, Signature, Context> traits::Checkable<Context>
|
||||||
for UncheckedExtrinsic<Address, Index, Call, Signature>
|
for UncheckedExtrinsic<Address, Index, Call, Signature>
|
||||||
where
|
where
|
||||||
Address: Member + MaybeDisplay,
|
Address: Member + MaybeDisplay,
|
||||||
@@ -70,27 +67,25 @@ where
|
|||||||
Call: Encode + Member,
|
Call: Encode + Member,
|
||||||
Signature: Member + traits::Verify<Signer=AccountId>,
|
Signature: Member + traits::Verify<Signer=AccountId>,
|
||||||
AccountId: Member + MaybeDisplay,
|
AccountId: Member + MaybeDisplay,
|
||||||
ThisLookup: FnOnce(Address) -> Result<AccountId, &'static str>,
|
Context: Lookup<Source=Address, Target=AccountId>,
|
||||||
{
|
{
|
||||||
type Checked = CheckedExtrinsic<AccountId, Index, Call>;
|
type Checked = CheckedExtrinsic<AccountId, Index, Call>;
|
||||||
|
|
||||||
fn check_with(self, lookup: ThisLookup) -> Result<Self::Checked, &'static str> {
|
fn check(self, context: &Context) -> Result<Self::Checked, &'static str> {
|
||||||
Ok(match self.signature {
|
Ok(match self.signature {
|
||||||
Some((signed, signature)) => {
|
Some((signed, signature, index)) => {
|
||||||
let payload = (self.index, self.function);
|
let payload = (index, self.function);
|
||||||
let signed = lookup(signed)?;
|
let signed = context.lookup(signed)?;
|
||||||
if !::verify_encoded_lazy(&signature, &payload, &signed) {
|
if !::verify_encoded_lazy(&signature, &payload, &signed) {
|
||||||
return Err("bad signature in extrinsic")
|
return Err("bad signature in extrinsic")
|
||||||
}
|
}
|
||||||
CheckedExtrinsic {
|
CheckedExtrinsic {
|
||||||
signed: Some(signed),
|
signed: Some((signed, payload.0)),
|
||||||
index: payload.0,
|
|
||||||
function: payload.1,
|
function: payload.1,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
None => CheckedExtrinsic {
|
None => CheckedExtrinsic {
|
||||||
signed: None,
|
signed: None,
|
||||||
index: self.index,
|
|
||||||
function: self.function,
|
function: self.function,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
@@ -114,7 +109,6 @@ where
|
|||||||
|
|
||||||
Some(UncheckedExtrinsic {
|
Some(UncheckedExtrinsic {
|
||||||
signature: Decode::decode(input)?,
|
signature: Decode::decode(input)?,
|
||||||
index: Decode::decode(input)?,
|
|
||||||
function: Decode::decode(input)?,
|
function: Decode::decode(input)?,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -136,7 +130,6 @@ where
|
|||||||
v.extend(&[0u8; 4]);
|
v.extend(&[0u8; 4]);
|
||||||
|
|
||||||
self.signature.encode_to(&mut v);
|
self.signature.encode_to(&mut v);
|
||||||
self.index.encode_to(&mut v);
|
|
||||||
self.function.encode_to(&mut v);
|
self.function.encode_to(&mut v);
|
||||||
|
|
||||||
let length = (v.len() - 4) as u32;
|
let length = (v.len() - 4) as u32;
|
||||||
@@ -154,6 +147,6 @@ impl<Address, Index, Call, Signature> fmt::Debug for UncheckedExtrinsic<Address,
|
|||||||
Call: fmt::Debug,
|
Call: fmt::Debug,
|
||||||
{
|
{
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter) -> 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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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 <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
//! 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<Address, Index, Call, Signature> {
|
||||||
|
/// 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<Address, Index, Call, Signature> UncheckedMortalExtrinsic<Address, Index, Call, Signature> {
|
||||||
|
/// 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<Address, AccountId, Index, Call, Signature, Context, Hash, BlockNumber> Checkable<Context>
|
||||||
|
for UncheckedMortalExtrinsic<Address, Index, Call, Signature>
|
||||||
|
where
|
||||||
|
Address: Member + MaybeDisplay,
|
||||||
|
Index: Encode + Member + MaybeDisplay + SimpleArithmetic,
|
||||||
|
Call: Encode + Member,
|
||||||
|
Signature: Member + traits::Verify<Signer=AccountId>,
|
||||||
|
AccountId: Member + MaybeDisplay,
|
||||||
|
BlockNumber: SimpleArithmetic,
|
||||||
|
Hash: Encode,
|
||||||
|
Context: Lookup<Source=Address, Target=AccountId>
|
||||||
|
+ GetHeight<BlockNumber=BlockNumber>
|
||||||
|
+ BlockNumberToHash<BlockNumber=BlockNumber, Hash=Hash>,
|
||||||
|
{
|
||||||
|
type Checked = CheckedExtrinsic<AccountId, Index, Call>;
|
||||||
|
|
||||||
|
fn check(self, context: &Context) -> Result<Self::Checked, &'static str> {
|
||||||
|
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<Address, Index, Call, Signature> Decode
|
||||||
|
for UncheckedMortalExtrinsic<Address, Index, Call, Signature>
|
||||||
|
where
|
||||||
|
Address: Decode,
|
||||||
|
Signature: Decode,
|
||||||
|
Index: Decode,
|
||||||
|
Call: Decode,
|
||||||
|
{
|
||||||
|
fn decode<I: Input>(input: &mut I) -> Option<Self> {
|
||||||
|
// This is a little more complicated than usual since the binary format must be compatible
|
||||||
|
// with substrate's generic `Vec<u8>` 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<Address, Index, Call, Signature> Encode
|
||||||
|
for UncheckedMortalExtrinsic<Address, Index, Call, Signature>
|
||||||
|
where
|
||||||
|
Address: Encode,
|
||||||
|
Signature: Encode,
|
||||||
|
Index: Encode,
|
||||||
|
Call: Encode,
|
||||||
|
{
|
||||||
|
fn encode(&self) -> Vec<u8> {
|
||||||
|
let mut v = Vec::new();
|
||||||
|
|
||||||
|
// need to prefix with the total length as u32 to ensure it's binary comptible with
|
||||||
|
// Vec<u8>. 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<Address, Index, Call, Signature> fmt::Debug for UncheckedMortalExtrinsic<Address, Index, Call, Signature> 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<u64, &'static str> { 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<u64> { Some(n) }
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Eq, PartialEq, Clone, Debug, Serialize, Deserialize, Encode, Decode)]
|
||||||
|
struct TestSig(u64, Vec<u8>);
|
||||||
|
impl traits::Verify for TestSig {
|
||||||
|
type Signer = u64;
|
||||||
|
fn verify<L: traits::Lazy<[u8]>>(&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<u64, u64, u64, TestSig>;
|
||||||
|
type CEx = CheckedExtrinsic<u64, u64, u64>;
|
||||||
|
|
||||||
|
#[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!(<Ex as Checkable<TestContext>>::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!(<Ex as Checkable<TestContext>>::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!(<Ex as Checkable<TestContext>>::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!(<Ex as Checkable<TestContext>>::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!(<Ex as Checkable<TestContext>>::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!(<Ex as Checkable<TestContext>>::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!(<Ex as Checkable<TestContext>>::check(ux, &TestContext), Err("bad signature in extrinsic"));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -123,7 +123,7 @@ pub struct TestXt<Call>(pub Option<u64>, pub u64, pub Call);
|
|||||||
|
|
||||||
impl<Call: Codec + Sync + Send + Serialize, Context> Checkable<Context> for TestXt<Call> {
|
impl<Call: Codec + Sync + Send + Serialize, Context> Checkable<Context> for TestXt<Call> {
|
||||||
type Checked = Self;
|
type Checked = Self;
|
||||||
fn check_with(self, _: Context) -> Result<Self::Checked, &'static str> { Ok(self) }
|
fn check(self, _: &Context) -> Result<Self::Checked, &'static str> { Ok(self) }
|
||||||
}
|
}
|
||||||
impl<Call> Applyable for TestXt<Call> where
|
impl<Call> Applyable for TestXt<Call> where
|
||||||
Call: 'static + Sized + Send + Sync + Clone + Eq + Codec + Debug + Serialize + DeserializeOwned,
|
Call: 'static + Sized + Send + Sync + Clone + Eq + Codec + Debug + Serialize + DeserializeOwned,
|
||||||
@@ -132,7 +132,7 @@ impl<Call> Applyable for TestXt<Call> where
|
|||||||
type Index = u64;
|
type Index = u64;
|
||||||
type Call = Call;
|
type Call = Call;
|
||||||
fn sender(&self) -> Option<&u64> { self.0.as_ref() }
|
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::AccountId>) {
|
fn deconstruct(self) -> (Self::Call, Option<Self::AccountId>) {
|
||||||
(self.2, self.0)
|
(self.2, self.0)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -60,7 +60,33 @@ pub trait Lookup {
|
|||||||
/// Type to lookup into.
|
/// Type to lookup into.
|
||||||
type Target;
|
type Target;
|
||||||
/// Attempt a lookup.
|
/// Attempt a lookup.
|
||||||
fn lookup(s: Self::Source) -> result::Result<Self::Target, &'static str>;
|
fn lookup(&self, s: Self::Source) -> result::Result<Self::Target, &'static str>;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 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<Self::Hash>;
|
||||||
|
|
||||||
|
/// 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.
|
/// Simple payment making trait, operating on a single generic `AccountId` type.
|
||||||
@@ -407,10 +433,11 @@ pub type NumberFor<B> = <<B as Block>::Header as Header>::Number;
|
|||||||
/// Implement for pieces of information that require some additional context `Context` in order to be
|
/// Implement for pieces of information that require some additional context `Context` in order to be
|
||||||
/// checked.
|
/// checked.
|
||||||
pub trait Checkable<Context>: Sized {
|
pub trait Checkable<Context>: Sized {
|
||||||
/// Returned if `check_with` succeeds.
|
/// Returned if `check` succeeds.
|
||||||
type Checked;
|
type Checked;
|
||||||
|
|
||||||
fn check_with(self, context: Context) -> Result<Self::Checked, &'static str>;
|
/// Check self, given an instance of Context.
|
||||||
|
fn check(self, c: &Context) -> Result<Self::Checked, &'static str>;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A "checkable" piece of information, used by the standard Substrate Executive in order to
|
/// 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.
|
/// Returned if `check` succeeds.
|
||||||
type Checked;
|
type Checked;
|
||||||
|
|
||||||
|
/// Check self.
|
||||||
fn check(self) -> Result<Self::Checked, &'static str>;
|
fn check(self) -> Result<Self::Checked, &'static str>;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Every `BlindCheckable` is also a `Checkable` for arbitrary `Context`.
|
// Every `BlindCheckable` is also a `StaticCheckable` for arbitrary `Context`.
|
||||||
impl<T: BlindCheckable, Context> Checkable<Context> for T {
|
impl<T: BlindCheckable, Context> Checkable<Context> for T {
|
||||||
type Checked = <Self as BlindCheckable>::Checked;
|
type Checked = <Self as BlindCheckable>::Checked;
|
||||||
fn check_with(self, _: Context) -> Result<Self::Checked, &'static str> {
|
fn check(self, _c: &Context) -> Result<Self::Checked, &'static str> {
|
||||||
BlindCheckable::check(self)
|
BlindCheckable::check(self)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -442,7 +470,7 @@ pub trait Applyable: Sized + Send + Sync {
|
|||||||
type AccountId: Member + MaybeDisplay;
|
type AccountId: Member + MaybeDisplay;
|
||||||
type Index: Member + MaybeDisplay + SimpleArithmetic;
|
type Index: Member + MaybeDisplay + SimpleArithmetic;
|
||||||
type Call: Member;
|
type Call: Member;
|
||||||
fn index(&self) -> &Self::Index;
|
fn index(&self) -> Option<&Self::Index>;
|
||||||
fn sender(&self) -> Option<&Self::AccountId>;
|
fn sender(&self) -> Option<&Self::AccountId>;
|
||||||
fn deconstruct(self) -> (Self::Call, Option<Self::AccountId>);
|
fn deconstruct(self) -> (Self::Call, Option<Self::AccountId>);
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -1,5 +1,5 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "substrate-extrinsic-pool"
|
name = "substrate-transaction-pool"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
authors = ["Parity Technologies <admin@parity.io>"]
|
authors = ["Parity Technologies <admin@parity.io>"]
|
||||||
|
|
||||||
+1
-1
@@ -1,5 +1,5 @@
|
|||||||
|
|
||||||
= extrinsic-pool
|
= transaction-pool
|
||||||
|
|
||||||
.Summary
|
.Summary
|
||||||
[source, toml]
|
[source, toml]
|
||||||
+3
-3
@@ -76,15 +76,15 @@ impl<H, T> txpool::Listener<T> for Listener<H> where
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn rejected(&mut self, tx: &Arc<T>, reason: &txpool::ErrorKind) {
|
fn rejected(&mut self, tx: &Arc<T>, 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<T>) {
|
fn invalid(&mut self, tx: &Arc<T>) {
|
||||||
warn!(target: "extrinsic-pool", "Extrinsic invalid: {:?}", tx);
|
warn!(target: "transaction-pool", "Extrinsic invalid: {:?}", tx);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn canceled(&mut self, tx: &Arc<T>) {
|
fn canceled(&mut self, tx: &Arc<T>) {
|
||||||
debug!(target: "extrinsic-pool", "Extrinsic canceled: {:?}", tx);
|
debug!(target: "transaction-pool", "Extrinsic canceled: {:?}", tx);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn culled(&mut self, tx: &Arc<T>) {
|
fn culled(&mut self, tx: &Arc<T>) {
|
||||||
+1
-1
@@ -133,7 +133,7 @@ pub struct Ready<'a, 'b, B: 'a + ChainApi> {
|
|||||||
impl<'a, 'b, B: ChainApi> txpool::Ready<VerifiedFor<B>> for Ready<'a, 'b, B> {
|
impl<'a, 'b, B: ChainApi> txpool::Ready<VerifiedFor<B>> for Ready<'a, 'b, B> {
|
||||||
fn is_ready(&mut self, xt: &VerifiedFor<B>) -> Readiness {
|
fn is_ready(&mut self, xt: &VerifiedFor<B>) -> Readiness {
|
||||||
if self.rotator.ban_if_stale(&self.now, xt) {
|
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;
|
return Readiness::Stale;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -15,7 +15,7 @@ include::../../environmental/README.adoc[]
|
|||||||
|
|
||||||
include::../../core/executor/README.adoc[]
|
include::../../core/executor/README.adoc[]
|
||||||
|
|
||||||
include::../../core/extrinsic-pool/README.adoc[]
|
include::../../core/transaction-pool/README.adoc[]
|
||||||
|
|
||||||
include::../../core/keyring/README.adoc[]
|
include::../../core/keyring/README.adoc[]
|
||||||
|
|
||||||
|
|||||||
@@ -31,10 +31,9 @@ use client::backend::Backend;
|
|||||||
use client::block_builder::BlockBuilder as ClientBlockBuilder;
|
use client::block_builder::BlockBuilder as ClientBlockBuilder;
|
||||||
use client::{Client, CallExecutor};
|
use client::{Client, CallExecutor};
|
||||||
use primitives::{
|
use primitives::{
|
||||||
AccountId, Block, BlockId, Hash, Index, InherentData,
|
AccountId, Block, BlockId, BlockNumber, Hash, Index, InherentData, SessionKey, Timestamp, UncheckedExtrinsic
|
||||||
SessionKey, Timestamp, UncheckedExtrinsic
|
|
||||||
};
|
};
|
||||||
use sr_primitives::transaction_validity::TransactionValidity;
|
use sr_primitives::{transaction_validity::TransactionValidity, traits::{GetHeight, BlockNumberToHash}};
|
||||||
use substrate_primitives::{Blake2Hasher, RlpCodec};
|
use substrate_primitives::{Blake2Hasher, RlpCodec};
|
||||||
|
|
||||||
/// Build new blocks.
|
/// Build new blocks.
|
||||||
@@ -49,7 +48,7 @@ pub trait BlockBuilder {
|
|||||||
/// Trait encapsulating the node API.
|
/// Trait encapsulating the node API.
|
||||||
///
|
///
|
||||||
/// All calls should fail when the exact runtime is unknown.
|
/// All calls should fail when the exact runtime is unknown.
|
||||||
pub trait Api {
|
pub trait Api: GetHeight<BlockNumber=BlockNumber> + BlockNumberToHash<BlockNumber=BlockNumber,Hash=Hash> {
|
||||||
/// The block builder for this API type.
|
/// The block builder for this API type.
|
||||||
type BlockBuilder: BlockBuilder;
|
type BlockBuilder: BlockBuilder;
|
||||||
|
|
||||||
@@ -91,7 +90,7 @@ pub trait Api {
|
|||||||
impl<B, E> BlockBuilder for ClientBlockBuilder<B, E, Block, Blake2Hasher, RlpCodec>
|
impl<B, E> BlockBuilder for ClientBlockBuilder<B, E, Block, Blake2Hasher, RlpCodec>
|
||||||
where
|
where
|
||||||
B: Backend<Block, Blake2Hasher, RlpCodec>,
|
B: Backend<Block, Blake2Hasher, RlpCodec>,
|
||||||
E: CallExecutor<Block, Blake2Hasher, RlpCodec>+ Clone,
|
E: CallExecutor<Block, Blake2Hasher, RlpCodec> + Clone,
|
||||||
{
|
{
|
||||||
fn push_extrinsic(&mut self, extrinsic: UncheckedExtrinsic) -> Result<()> {
|
fn push_extrinsic(&mut self, extrinsic: UncheckedExtrinsic) -> Result<()> {
|
||||||
self.push(extrinsic).map_err(Into::into)
|
self.push(extrinsic).map_err(Into::into)
|
||||||
|
|||||||
@@ -48,6 +48,7 @@ use std::time::{self, Duration, Instant};
|
|||||||
use codec::{Decode, Encode};
|
use codec::{Decode, Encode};
|
||||||
use node_api::Api;
|
use node_api::Api;
|
||||||
use node_primitives::{AccountId, Hash, Block, BlockId, BlockNumber, Header, Timestamp, SessionKey};
|
use node_primitives::{AccountId, Hash, Block, BlockId, BlockNumber, Header, Timestamp, SessionKey};
|
||||||
|
use runtime_primitives::generic::Era;
|
||||||
use primitives::{AuthorityId, ed25519};
|
use primitives::{AuthorityId, ed25519};
|
||||||
use transaction_pool::TransactionPool;
|
use transaction_pool::TransactionPool;
|
||||||
use tokio::runtime::TaskExecutor;
|
use tokio::runtime::TaskExecutor;
|
||||||
@@ -400,14 +401,13 @@ impl<C> bft::Proposer<Block> for Proposer<C>
|
|||||||
=> MisbehaviorKind::BftDoubleCommit(round as u32, (h1, s1.signature), (h2, s2.signature)),
|
=> 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();
|
let signature = self.local_key.sign(&payload.encode()).into();
|
||||||
next_index += 1;
|
next_index += 1;
|
||||||
|
|
||||||
let local_id = self.local_key.public().0.into();
|
let local_id = self.local_key.public().0.into();
|
||||||
let extrinsic = UncheckedExtrinsic {
|
let extrinsic = UncheckedExtrinsic {
|
||||||
signature: Some((node_runtime::RawAddress::Id(local_id), signature)),
|
signature: Some((node_runtime::RawAddress::Id(local_id), signature, payload.0, Era::immortal())),
|
||||||
index: payload.0,
|
|
||||||
function: payload.1,
|
function: payload.1,
|
||||||
};
|
};
|
||||||
let uxt: GenericExtrinsic = Decode::decode(&mut extrinsic.encode().as_slice()).expect("Encoded extrinsic is valid");
|
let uxt: GenericExtrinsic = Decode::decode(&mut extrinsic.encode().as_slice()).expect("Encoded extrinsic is valid");
|
||||||
|
|||||||
@@ -54,7 +54,7 @@ mod tests {
|
|||||||
ed25519::{Public, Pair}};
|
ed25519::{Public, Pair}};
|
||||||
use node_primitives::{Hash, BlockNumber, AccountId};
|
use node_primitives::{Hash, BlockNumber, AccountId};
|
||||||
use runtime_primitives::traits::{Header as HeaderT, Digest as DigestT};
|
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 {balances, staking, session, system, consensus, timestamp, treasury};
|
||||||
use system::{EventRecord, Phase};
|
use system::{EventRecord, Phase};
|
||||||
use node_runtime::{Header, Block, UncheckedExtrinsic, CheckedExtrinsic, Call, Runtime, Balances,
|
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 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 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.
|
// TODO: move into own crate.
|
||||||
macro_rules! map {
|
macro_rules! map {
|
||||||
@@ -81,19 +82,17 @@ mod tests {
|
|||||||
|
|
||||||
fn sign(xt: CheckedExtrinsic) -> UncheckedExtrinsic {
|
fn sign(xt: CheckedExtrinsic) -> UncheckedExtrinsic {
|
||||||
match xt.signed {
|
match xt.signed {
|
||||||
Some(signed) => {
|
Some((signed, index)) => {
|
||||||
let payload = (xt.index, xt.function);
|
let payload = (index, xt.function, GENESIS_HASH);
|
||||||
let pair = Pair::from(Keyring::from_public(Public::from_raw(signed.clone().into())).unwrap());
|
let pair = Pair::from(Keyring::from_public(Public::from_raw(signed.clone().into())).unwrap());
|
||||||
let signature = pair.sign(&payload.encode()).into();
|
let signature = pair.sign(&payload.encode()).into();
|
||||||
UncheckedExtrinsic {
|
UncheckedExtrinsic {
|
||||||
signature: Some((balances::address::Address::Id(signed), signature)),
|
signature: Some((balances::address::Address::Id(signed), signature, payload.0, Era::mortal(256, 0))),
|
||||||
index: payload.0,
|
|
||||||
function: payload.1,
|
function: payload.1,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
None => UncheckedExtrinsic {
|
None => UncheckedExtrinsic {
|
||||||
signature: None,
|
signature: None,
|
||||||
index: xt.index,
|
|
||||||
function: xt.function,
|
function: xt.function,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@@ -101,8 +100,7 @@ mod tests {
|
|||||||
|
|
||||||
fn xt() -> UncheckedExtrinsic {
|
fn xt() -> UncheckedExtrinsic {
|
||||||
sign(CheckedExtrinsic {
|
sign(CheckedExtrinsic {
|
||||||
signed: Some(alice()),
|
signed: Some((alice(), 0)),
|
||||||
index: 0,
|
|
||||||
function: Call::Balances(balances::Call::transfer::<Runtime>(bob().into(), 69)),
|
function: Call::Balances(balances::Call::transfer::<Runtime>(bob().into(), 69)),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -283,7 +281,7 @@ mod tests {
|
|||||||
fn block1(support_changes_trie: bool) -> (Vec<u8>, Hash) {
|
fn block1(support_changes_trie: bool) -> (Vec<u8>, Hash) {
|
||||||
construct_block(
|
construct_block(
|
||||||
1,
|
1,
|
||||||
[69u8; 32].into(),
|
GENESIS_HASH.into(),
|
||||||
if support_changes_trie {
|
if support_changes_trie {
|
||||||
hex!("1755be7303767b4d3855694b4f0ebd9d64b7011124d0ec1ad3e17c2a0d65e245").into()
|
hex!("1755be7303767b4d3855694b4f0ebd9d64b7011124d0ec1ad3e17c2a0d65e245").into()
|
||||||
} else {
|
} else {
|
||||||
@@ -297,12 +295,10 @@ mod tests {
|
|||||||
vec![
|
vec![
|
||||||
CheckedExtrinsic {
|
CheckedExtrinsic {
|
||||||
signed: None,
|
signed: None,
|
||||||
index: 0,
|
|
||||||
function: Call::Timestamp(timestamp::Call::set(42)),
|
function: Call::Timestamp(timestamp::Call::set(42)),
|
||||||
},
|
},
|
||||||
CheckedExtrinsic {
|
CheckedExtrinsic {
|
||||||
signed: Some(alice()),
|
signed: Some((alice(), 0)),
|
||||||
index: 0,
|
|
||||||
function: Call::Balances(balances::Call::transfer(bob().into(), 69)),
|
function: Call::Balances(balances::Call::transfer(bob().into(), 69)),
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
@@ -313,22 +309,19 @@ mod tests {
|
|||||||
construct_block(
|
construct_block(
|
||||||
2,
|
2,
|
||||||
block1(false).1,
|
block1(false).1,
|
||||||
hex!("29fa1d0aa83662c571315af54b106c73823a31f759793803bf8929960b67b138").into(),
|
hex!("60efe1a65e7c79041b02e56ec122d6eaedfa476e0a9f6f1f68eb0c8f402c4514").into(),
|
||||||
None,
|
None,
|
||||||
vec![
|
vec![
|
||||||
CheckedExtrinsic {
|
CheckedExtrinsic {
|
||||||
signed: None,
|
signed: None,
|
||||||
index: 0,
|
|
||||||
function: Call::Timestamp(timestamp::Call::set(52)),
|
function: Call::Timestamp(timestamp::Call::set(52)),
|
||||||
},
|
},
|
||||||
CheckedExtrinsic {
|
CheckedExtrinsic {
|
||||||
signed: Some(bob()),
|
signed: Some((bob(), 0)),
|
||||||
index: 0,
|
|
||||||
function: Call::Balances(balances::Call::transfer(alice().into(), 5)),
|
function: Call::Balances(balances::Call::transfer(alice().into(), 5)),
|
||||||
},
|
},
|
||||||
CheckedExtrinsic {
|
CheckedExtrinsic {
|
||||||
signed: Some(alice()),
|
signed: Some((alice(), 1)),
|
||||||
index: 1,
|
|
||||||
function: Call::Balances(balances::Call::transfer(bob().into(), 15)),
|
function: Call::Balances(balances::Call::transfer(bob().into(), 15)),
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
@@ -338,18 +331,16 @@ mod tests {
|
|||||||
fn block1big() -> (Vec<u8>, Hash) {
|
fn block1big() -> (Vec<u8>, Hash) {
|
||||||
construct_block(
|
construct_block(
|
||||||
1,
|
1,
|
||||||
[69u8; 32].into(),
|
GENESIS_HASH.into(),
|
||||||
hex!("fe0e07c7b054fe186387461d455d536860e9c71d6979fd9dbf755e96ce070d04").into(),
|
hex!("fe0e07c7b054fe186387461d455d536860e9c71d6979fd9dbf755e96ce070d04").into(),
|
||||||
None,
|
None,
|
||||||
vec![
|
vec![
|
||||||
CheckedExtrinsic {
|
CheckedExtrinsic {
|
||||||
signed: None,
|
signed: None,
|
||||||
index: 0,
|
|
||||||
function: Call::Timestamp(timestamp::Call::set(42)),
|
function: Call::Timestamp(timestamp::Call::set(42)),
|
||||||
},
|
},
|
||||||
CheckedExtrinsic {
|
CheckedExtrinsic {
|
||||||
signed: Some(alice()),
|
signed: Some((alice(), 0)),
|
||||||
index: 0,
|
|
||||||
function: Call::Consensus(consensus::Call::remark(vec![0; 120000])),
|
function: Call::Consensus(consensus::Call::remark(vec![0; 120000])),
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -223,11 +223,11 @@ pub type Block = generic::Block<Header, UncheckedExtrinsic>;
|
|||||||
/// BlockId type as expected by this runtime.
|
/// BlockId type as expected by this runtime.
|
||||||
pub type BlockId = generic::BlockId<Block>;
|
pub type BlockId = generic::BlockId<Block>;
|
||||||
/// Unchecked extrinsic type as expected by this runtime.
|
/// Unchecked extrinsic type as expected by this runtime.
|
||||||
pub type UncheckedExtrinsic = generic::UncheckedExtrinsic<Address, Index, Call, Signature>;
|
pub type UncheckedExtrinsic = generic::UncheckedMortalExtrinsic<Address, Index, Call, Signature>;
|
||||||
/// Extrinsic type that has already been checked.
|
/// Extrinsic type that has already been checked.
|
||||||
pub type CheckedExtrinsic = generic::CheckedExtrinsic<AccountId, Index, Call>;
|
pub type CheckedExtrinsic = generic::CheckedExtrinsic<AccountId, Index, Call>;
|
||||||
/// Executive: handles dispatch to the various modules.
|
/// Executive: handles dispatch to the various modules.
|
||||||
pub type Executive = executive::Executive<Runtime, Block, Balances, Balances, AllModules>;
|
pub type Executive = executive::Executive<Runtime, Block, balances::ChainContext<Runtime>, Balances, AllModules>;
|
||||||
|
|
||||||
pub mod api {
|
pub mod api {
|
||||||
impl_stubs!(
|
impl_stubs!(
|
||||||
@@ -251,19 +251,13 @@ pub mod api {
|
|||||||
|
|
||||||
/// Produces the list of inherent extrinsics.
|
/// Produces the list of inherent extrinsics.
|
||||||
fn inherent_extrinsics(data: InherentData) -> Vec<UncheckedExtrinsic> {
|
fn inherent_extrinsics(data: InherentData) -> Vec<UncheckedExtrinsic> {
|
||||||
let make_inherent = |function| UncheckedExtrinsic {
|
let mut inherent = vec![generic::UncheckedMortalExtrinsic::new_unsigned(
|
||||||
signature: Default::default(),
|
Call::Timestamp(TimestampCall::set(data.timestamp))
|
||||||
function,
|
)];
|
||||||
index: 0,
|
|
||||||
};
|
|
||||||
|
|
||||||
let mut inherent = vec![
|
|
||||||
make_inherent(Call::Timestamp(TimestampCall::set(data.timestamp))),
|
|
||||||
];
|
|
||||||
|
|
||||||
if !data.offline_indices.is_empty() {
|
if !data.offline_indices.is_empty() {
|
||||||
inherent.push(make_inherent(
|
inherent.push(generic::UncheckedMortalExtrinsic::new_unsigned(
|
||||||
Call::Consensus(ConsensusCall::note_offline(data.offline_indices))
|
Call::Consensus(ConsensusCall::note_offline(data.offline_indices))
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -50,7 +50,7 @@ use tokio::runtime::TaskExecutor;
|
|||||||
use service::FactoryFullConfiguration;
|
use service::FactoryFullConfiguration;
|
||||||
use primitives::{Blake2Hasher, RlpCodec};
|
use primitives::{Blake2Hasher, RlpCodec};
|
||||||
|
|
||||||
pub use service::{Roles, PruningMode, ExtrinsicPoolOptions,
|
pub use service::{Roles, PruningMode, TransactionPoolOptions,
|
||||||
ErrorKind, Error, ComponentBlock, LightComponents, FullComponents};
|
ErrorKind, Error, ComponentBlock, LightComponents, FullComponents};
|
||||||
pub use client::ExecutionStrategy;
|
pub use client::ExecutionStrategy;
|
||||||
|
|
||||||
@@ -97,20 +97,20 @@ impl service::ServiceFactory for Factory {
|
|||||||
type ExtrinsicHash = Hash;
|
type ExtrinsicHash = Hash;
|
||||||
type NetworkProtocol = DemoProtocol;
|
type NetworkProtocol = DemoProtocol;
|
||||||
type RuntimeDispatch = node_executor::Executor;
|
type RuntimeDispatch = node_executor::Executor;
|
||||||
type FullExtrinsicPoolApi = transaction_pool::ChainApi<service::FullClient<Self>>;
|
type FullTransactionPoolApi = transaction_pool::ChainApi<service::FullClient<Self>>;
|
||||||
type LightExtrinsicPoolApi = transaction_pool::ChainApi<service::LightClient<Self>>;
|
type LightTransactionPoolApi = transaction_pool::ChainApi<service::LightClient<Self>>;
|
||||||
type Genesis = GenesisConfig;
|
type Genesis = GenesisConfig;
|
||||||
type Configuration = CustomConfiguration;
|
type Configuration = CustomConfiguration;
|
||||||
|
|
||||||
const NETWORK_PROTOCOL_ID: network::ProtocolId = ::node_network::PROTOCOL_ID;
|
const NETWORK_PROTOCOL_ID: network::ProtocolId = ::node_network::PROTOCOL_ID;
|
||||||
|
|
||||||
fn build_full_extrinsic_pool(config: ExtrinsicPoolOptions, client: Arc<service::FullClient<Self>>)
|
fn build_full_transaction_pool(config: TransactionPoolOptions, client: Arc<service::FullClient<Self>>)
|
||||||
-> Result<TransactionPool<service::FullClient<Self>>, Error>
|
-> Result<TransactionPool<service::FullClient<Self>>, Error>
|
||||||
{
|
{
|
||||||
Ok(TransactionPool::new(config, transaction_pool::ChainApi::new(client)))
|
Ok(TransactionPool::new(config, transaction_pool::ChainApi::new(client)))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn build_light_extrinsic_pool(config: ExtrinsicPoolOptions, client: Arc<service::LightClient<Self>>)
|
fn build_light_transaction_pool(config: TransactionPoolOptions, client: Arc<service::LightClient<Self>>)
|
||||||
-> Result<TransactionPool<service::LightClient<Self>>, Error>
|
-> Result<TransactionPool<service::LightClient<Self>>, Error>
|
||||||
{
|
{
|
||||||
Ok(TransactionPool::new(config, transaction_pool::ChainApi::new(client)))
|
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(),
|
||||||
client.clone(),
|
client.clone(),
|
||||||
consensus_net,
|
consensus_net,
|
||||||
service.extrinsic_pool(),
|
service.transaction_pool(),
|
||||||
executor,
|
executor,
|
||||||
key,
|
key,
|
||||||
))
|
))
|
||||||
|
|||||||
@@ -13,6 +13,6 @@ node-runtime = { path = "../runtime" }
|
|||||||
substrate-client = { path = "../../core/client" }
|
substrate-client = { path = "../../core/client" }
|
||||||
parity-codec = { version = "1.1" }
|
parity-codec = { version = "1.1" }
|
||||||
substrate-keyring = { path = "../../core/keyring" }
|
substrate-keyring = { path = "../../core/keyring" }
|
||||||
substrate-extrinsic-pool = { path = "../../core/extrinsic-pool" }
|
substrate-transaction-pool = { path = "../../core/transaction-pool" }
|
||||||
substrate-primitives = { path = "../../core/primitives" }
|
substrate-primitives = { path = "../../core/primitives" }
|
||||||
sr-primitives = { path = "../../core/sr-primitives" }
|
sr-primitives = { path = "../../core/sr-primitives" }
|
||||||
|
|||||||
@@ -14,14 +14,14 @@
|
|||||||
// You should have received a copy of the GNU General Public License
|
// You should have received a copy of the GNU General Public License
|
||||||
// along with Substrate. If not, see <http://www.gnu.org/licenses/>.
|
// along with Substrate. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
use extrinsic_pool;
|
use transaction_pool;
|
||||||
use node_api;
|
use node_api;
|
||||||
use primitives::Hash;
|
use primitives::Hash;
|
||||||
use runtime::{Address, UncheckedExtrinsic};
|
use runtime::{Address, UncheckedExtrinsic};
|
||||||
|
|
||||||
error_chain! {
|
error_chain! {
|
||||||
links {
|
links {
|
||||||
Pool(extrinsic_pool::Error, extrinsic_pool::ErrorKind);
|
Pool(transaction_pool::Error, transaction_pool::ErrorKind);
|
||||||
Api(node_api::Error, node_api::ErrorKind);
|
Api(node_api::Error, node_api::ErrorKind);
|
||||||
}
|
}
|
||||||
errors {
|
errors {
|
||||||
@@ -63,10 +63,10 @@ error_chain! {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl extrinsic_pool::IntoPoolError for Error {
|
impl transaction_pool::IntoPoolError for Error {
|
||||||
fn into_pool_error(self) -> ::std::result::Result<extrinsic_pool::Error, Self> {
|
fn into_pool_error(self) -> ::std::result::Result<transaction_pool::Error, Self> {
|
||||||
match self {
|
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),
|
e => Err(e),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,7 +16,7 @@
|
|||||||
|
|
||||||
extern crate substrate_client as client;
|
extern crate substrate_client as client;
|
||||||
extern crate parity_codec as codec;
|
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 substrate_primitives;
|
||||||
extern crate sr_primitives;
|
extern crate sr_primitives;
|
||||||
extern crate node_runtime as runtime;
|
extern crate node_runtime as runtime;
|
||||||
@@ -42,20 +42,20 @@ use std::{
|
|||||||
};
|
};
|
||||||
|
|
||||||
use codec::{Decode, Encode};
|
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 node_api::Api;
|
||||||
use primitives::{AccountId, BlockId, Block, Hash, Index};
|
use primitives::{AccountId, BlockId, Block, Hash, Index, BlockNumber};
|
||||||
use runtime::{UncheckedExtrinsic, RawAddress};
|
use runtime::{Address, UncheckedExtrinsic};
|
||||||
use sr_primitives::traits::{Bounded, Checkable, Hash as HashT, BlakeTwo256};
|
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};
|
pub use error::{Error, ErrorKind, Result};
|
||||||
|
|
||||||
/// Maximal size of a single encoded extrinsic.
|
/// Maximal size of a single encoded extrinsic.
|
||||||
const MAX_TRANSACTION_SIZE: usize = 4 * 1024 * 1024;
|
const MAX_TRANSACTION_SIZE: usize = 4 * 1024 * 1024;
|
||||||
|
|
||||||
/// Type alias for the transaction pool.
|
/// Type alias for the transaction pool.
|
||||||
pub type TransactionPool<A> = extrinsic_pool::Pool<ChainApi<A>>;
|
pub type TransactionPool<A> = transaction_pool::Pool<ChainApi<A>>;
|
||||||
|
|
||||||
/// A verified transaction which should be includable and non-inherent.
|
/// A verified transaction which should be includable and non-inherent.
|
||||||
#[derive(Clone, Debug)]
|
#[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 Hash = Hash;
|
||||||
type Sender = AccountId;
|
type Sender = AccountId;
|
||||||
|
|
||||||
@@ -119,8 +119,32 @@ impl<A> ChainApi<A> 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<A>);
|
||||||
|
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<Hash> {
|
||||||
|
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<AccountId, &'static str> {
|
||||||
|
self.0.lookup(&BlockId::number(self.get_height()), a).unwrap_or(None).ok_or("error with lookup")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<A> extrinsic_pool::ChainApi for ChainApi<A> where
|
impl<A> transaction_pool::ChainApi for ChainApi<A> where
|
||||||
A: Api + Send + Sync,
|
A: Api + Send + Sync,
|
||||||
{
|
{
|
||||||
type Block = Block;
|
type Block = Block;
|
||||||
@@ -145,13 +169,8 @@ impl<A> extrinsic_pool::ChainApi for ChainApi<A> where
|
|||||||
}
|
}
|
||||||
|
|
||||||
debug!(target: "transaction-pool", "Transaction submitted: {}", ::substrate_primitives::hexdisplay::HexDisplay::from(&encoded));
|
debug!(target: "transaction-pool", "Transaction submitted: {}", ::substrate_primitives::hexdisplay::HexDisplay::from(&encoded));
|
||||||
let checked = uxt.clone().check_with(|a| {
|
let checked = uxt.clone().check(&LocalContext(&self.api))?;
|
||||||
match a {
|
let (sender, index) = checked.signed.expect("function previously bailed unless uxt.is_signed(); qed");
|
||||||
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");
|
|
||||||
|
|
||||||
|
|
||||||
if encoded_size < 1024 {
|
if encoded_size < 1024 {
|
||||||
@@ -161,7 +180,7 @@ impl<A> extrinsic_pool::ChainApi for ChainApi<A> where
|
|||||||
}
|
}
|
||||||
|
|
||||||
Ok(VerifiedTransaction {
|
Ok(VerifiedTransaction {
|
||||||
index: checked.index,
|
index,
|
||||||
sender,
|
sender,
|
||||||
hash,
|
hash,
|
||||||
encoded_size,
|
encoded_size,
|
||||||
@@ -214,7 +233,7 @@ impl<A> extrinsic_pool::ChainApi for ChainApi<A> where
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn update_scores(
|
fn update_scores(
|
||||||
xts: &[extrinsic_pool::Transaction<VerifiedFor<Self>>],
|
xts: &[transaction_pool::Transaction<VerifiedFor<Self>>],
|
||||||
scores: &mut [Self::Score],
|
scores: &mut [Self::Score],
|
||||||
_change: Change<()>
|
_change: Change<()>
|
||||||
) {
|
) {
|
||||||
|
|||||||
@@ -46,7 +46,7 @@ use codec::{Encode, Decode, Codec, Input, Output};
|
|||||||
use runtime_support::{StorageValue, StorageMap, Parameter};
|
use runtime_support::{StorageValue, StorageMap, Parameter};
|
||||||
use runtime_support::dispatch::Result;
|
use runtime_support::dispatch::Result;
|
||||||
use primitives::traits::{Zero, One, SimpleArithmetic, OnFinalise, MakePayment,
|
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 address::Address as RawAddress;
|
||||||
use system::ensure_signed;
|
use system::ensure_signed;
|
||||||
|
|
||||||
@@ -630,6 +630,13 @@ impl<T: Trait> Module<T> {
|
|||||||
<TotalIssuance<T>>::put(v);
|
<TotalIssuance<T>>::put(v);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn lookup(a: address::Address<T::AccountId, T::AccountIndex>) -> result::Result<T::AccountId, &'static str> {
|
||||||
|
match a {
|
||||||
|
address::Address::Id(i) => Ok(i),
|
||||||
|
address::Address::Index(i) => <Module<T>>::lookup_index(i).ok_or("invalid account index"),
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: Trait> OnFinalise<T::BlockNumber> for Module<T> {
|
impl<T: Trait> OnFinalise<T::BlockNumber> for Module<T> {
|
||||||
@@ -637,14 +644,33 @@ impl<T: Trait> OnFinalise<T::BlockNumber> for Module<T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: Trait> Lookup for Module<T> {
|
pub struct ChainContext<T>(::rstd::marker::PhantomData<T>);
|
||||||
|
impl<T> Default for ChainContext<T> {
|
||||||
|
fn default() -> Self {
|
||||||
|
ChainContext(::rstd::marker::PhantomData)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: Trait> Lookup for ChainContext<T> {
|
||||||
type Source = address::Address<T::AccountId, T::AccountIndex>;
|
type Source = address::Address<T::AccountId, T::AccountIndex>;
|
||||||
type Target = T::AccountId;
|
type Target = T::AccountId;
|
||||||
fn lookup(a: Self::Source) -> result::Result<Self::Target, &'static str> {
|
fn lookup(&self, a: Self::Source) -> result::Result<Self::Target, &'static str> {
|
||||||
match a {
|
<Module<T>>::lookup(a)
|
||||||
address::Address::Id(i) => Ok(i),
|
}
|
||||||
address::Address::Index(i) => <Module<T>>::lookup_index(i).ok_or("invalid account index"),
|
}
|
||||||
}
|
|
||||||
|
impl<T: Trait> GetHeight for ChainContext<T> {
|
||||||
|
type BlockNumber = T::BlockNumber;
|
||||||
|
fn get_height(&self) -> Self::BlockNumber {
|
||||||
|
<system::Module<T>>::block_number()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: Trait> BlockNumberToHash for ChainContext<T> {
|
||||||
|
type BlockNumber = T::BlockNumber;
|
||||||
|
type Hash = T::Hash;
|
||||||
|
fn block_number_to_hash(&self, n: Self::BlockNumber) -> Option<Self::Hash> {
|
||||||
|
Some(<system::Module<T>>::block_hash(n))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -17,7 +17,7 @@
|
|||||||
//! Council system: Handles the voting in and maintenance of council members.
|
//! Council system: Handles the voting in and maintenance of council members.
|
||||||
|
|
||||||
use rstd::prelude::*;
|
use rstd::prelude::*;
|
||||||
use primitives::traits::{Zero, One, As, Lookup, OnFinalise};
|
use primitives::traits::{Zero, One, As, OnFinalise};
|
||||||
use runtime_io::print;
|
use runtime_io::print;
|
||||||
use srml_support::{StorageValue, StorageMap, dispatch::Result};
|
use srml_support::{StorageValue, StorageMap, dispatch::Result};
|
||||||
use democracy;
|
use democracy;
|
||||||
|
|||||||
@@ -76,23 +76,22 @@ mod internal {
|
|||||||
pub struct Executive<
|
pub struct Executive<
|
||||||
System,
|
System,
|
||||||
Block,
|
Block,
|
||||||
Lookup,
|
Context,
|
||||||
Payment,
|
Payment,
|
||||||
Finalisation,
|
Finalisation,
|
||||||
>(PhantomData<(System, Block, Lookup, Payment, Finalisation)>);
|
>(PhantomData<(System, Block, Context, Payment, Finalisation)>);
|
||||||
|
|
||||||
impl<
|
impl<
|
||||||
Address,
|
Context: Default,
|
||||||
System: system::Trait,
|
System: system::Trait,
|
||||||
Block: traits::Block<Header=System::Header, Hash=System::Hash>,
|
Block: traits::Block<Header=System::Header, Hash=System::Hash>,
|
||||||
Lookup: traits::Lookup<Source=Address, Target=System::AccountId>,
|
|
||||||
Payment: MakePayment<System::AccountId>,
|
Payment: MakePayment<System::AccountId>,
|
||||||
Finalisation: OnFinalise<System::BlockNumber>,
|
Finalisation: OnFinalise<System::BlockNumber>,
|
||||||
> Executive<System, Block, Lookup, Payment, Finalisation> where
|
> Executive<System, Block, Context, Payment, Finalisation> where
|
||||||
Block::Extrinsic: Checkable<fn(Address) -> Result<System::AccountId, &'static str>> + Codec,
|
Block::Extrinsic: Checkable<Context> + Codec,
|
||||||
<Block::Extrinsic as Checkable<fn(Address) -> Result<System::AccountId, &'static str>>>::Checked: Applyable<Index=System::Index, AccountId=System::AccountId>,
|
<Block::Extrinsic as Checkable<Context>>::Checked: Applyable<Index=System::Index, AccountId=System::AccountId>,
|
||||||
<<Block::Extrinsic as Checkable<fn(Address) -> Result<System::AccountId, &'static str>>>::Checked as Applyable>::Call: Dispatchable,
|
<<Block::Extrinsic as Checkable<Context>>::Checked as Applyable>::Call: Dispatchable,
|
||||||
<<<Block::Extrinsic as Checkable<fn(Address) -> Result<System::AccountId, &'static str>>>::Checked as Applyable>::Call as Dispatchable>::Origin: From<Option<System::AccountId>>
|
<<<Block::Extrinsic as Checkable<Context>>::Checked as Applyable>::Call as Dispatchable>::Origin: From<Option<System::AccountId>>
|
||||||
{
|
{
|
||||||
/// Start the execution of a particular block.
|
/// Start the execution of a particular block.
|
||||||
pub fn initialise_block(header: &System::Header) {
|
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.
|
/// 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<internal::ApplyOutcome, internal::ApplyError> {
|
fn apply_extrinsic_no_note_with_len(uxt: Block::Extrinsic, encoded_len: usize) -> result::Result<internal::ApplyOutcome, internal::ApplyError> {
|
||||||
// Verify the signature is good.
|
// 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
|
// check index
|
||||||
let expected_index = <system::Module<System>>::account_nonce(sender);
|
let expected_index = <system::Module<System>>::account_nonce(sender);
|
||||||
if xt.index() != &expected_index { return Err(
|
if index != &expected_index { return Err(
|
||||||
if xt.index() < &expected_index { internal::ApplyError::Stale } else { internal::ApplyError::Future }
|
if index < &expected_index { internal::ApplyError::Stale } else { internal::ApplyError::Future }
|
||||||
) }
|
) }
|
||||||
|
|
||||||
// pay any fees.
|
// pay any fees.
|
||||||
@@ -223,7 +222,7 @@ impl<
|
|||||||
pub fn validate_transaction(uxt: Block::Extrinsic) -> TransactionValidity {
|
pub fn validate_transaction(uxt: Block::Extrinsic) -> TransactionValidity {
|
||||||
let encoded_len = uxt.encode().len();
|
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.
|
// Checks out. Carry on.
|
||||||
Ok(xt) => xt,
|
Ok(xt) => xt,
|
||||||
// An unknown account index implies that the transaction may yet become valid.
|
// An unknown account index implies that the transaction may yet become valid.
|
||||||
@@ -233,7 +232,7 @@ impl<
|
|||||||
Err(_) => return TransactionValidity::Invalid,
|
Err(_) => return TransactionValidity::Invalid,
|
||||||
};
|
};
|
||||||
|
|
||||||
if let Some(sender) = xt.sender() {
|
if let (Some(sender), Some(index)) = (xt.sender(), xt.index()) {
|
||||||
// pay any fees.
|
// pay any fees.
|
||||||
if Payment::make_payment(sender, encoded_len).is_err() {
|
if Payment::make_payment(sender, encoded_len).is_err() {
|
||||||
return TransactionValidity::Invalid
|
return TransactionValidity::Invalid
|
||||||
@@ -241,20 +240,20 @@ impl<
|
|||||||
|
|
||||||
// check index
|
// check index
|
||||||
let mut expected_index = <system::Module<System>>::account_nonce(sender);
|
let mut expected_index = <system::Module<System>>::account_nonce(sender);
|
||||||
if xt.index() < &expected_index {
|
if index < &expected_index {
|
||||||
return TransactionValidity::Invalid
|
return TransactionValidity::Invalid
|
||||||
}
|
}
|
||||||
if *xt.index() > expected_index + As::sa(256) {
|
if *index > expected_index + As::sa(256) {
|
||||||
return TransactionValidity::Unknown
|
return TransactionValidity::Unknown
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut deps = Vec::new();
|
let mut deps = Vec::new();
|
||||||
while expected_index < *xt.index() {
|
while expected_index < *index {
|
||||||
deps.push((sender, expected_index).encode());
|
deps.push((sender, expected_index).encode());
|
||||||
expected_index = expected_index + One::one();
|
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 {
|
} else {
|
||||||
return TransactionValidity::Invalid
|
return TransactionValidity::Invalid
|
||||||
}
|
}
|
||||||
@@ -268,19 +267,10 @@ mod tests {
|
|||||||
use runtime_io::with_externalities;
|
use runtime_io::with_externalities;
|
||||||
use substrate_primitives::{H256, Blake2Hasher, RlpCodec};
|
use substrate_primitives::{H256, Blake2Hasher, RlpCodec};
|
||||||
use primitives::BuildStorage;
|
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 primitives::testing::{Digest, DigestItem, Header, Block};
|
||||||
use system;
|
use system;
|
||||||
|
|
||||||
struct NullLookup;
|
|
||||||
impl Lookup for NullLookup {
|
|
||||||
type Source = u64;
|
|
||||||
type Target = u64;
|
|
||||||
fn lookup(s: Self::Source) -> Result<Self::Target, &'static str> {
|
|
||||||
Ok(s)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl_outer_origin! {
|
impl_outer_origin! {
|
||||||
pub enum Origin for Runtime {
|
pub enum Origin for Runtime {
|
||||||
}
|
}
|
||||||
@@ -316,7 +306,7 @@ mod tests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type TestXt = primitives::testing::TestXt<Call<Runtime>>;
|
type TestXt = primitives::testing::TestXt<Call<Runtime>>;
|
||||||
type Executive = super::Executive<Runtime, Block<TestXt>, NullLookup, balances::Module<Runtime>, ()>;
|
type Executive = super::Executive<Runtime, Block<TestXt>, balances::ChainContext<Runtime>, balances::Module<Runtime>, ()>;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn balance_transfer_dispatch_works() {
|
fn balance_transfer_dispatch_works() {
|
||||||
|
|||||||
@@ -52,8 +52,7 @@ use rstd::cmp;
|
|||||||
use runtime_support::{Parameter, StorageValue, StorageMap};
|
use runtime_support::{Parameter, StorageValue, StorageMap};
|
||||||
use runtime_support::dispatch::Result;
|
use runtime_support::dispatch::Result;
|
||||||
use session::OnSessionChange;
|
use session::OnSessionChange;
|
||||||
use primitives::traits::{Zero, One, Bounded, OnFinalise,
|
use primitives::traits::{Zero, One, Bounded, OnFinalise, As};
|
||||||
As, Lookup};
|
|
||||||
use balances::{address::Address, OnDilution};
|
use balances::{address::Address, OnDilution};
|
||||||
use system::ensure_signed;
|
use system::ensure_signed;
|
||||||
|
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ extern crate safe_mix;
|
|||||||
|
|
||||||
use rstd::prelude::*;
|
use rstd::prelude::*;
|
||||||
use primitives::traits::{self, CheckEqual, SimpleArithmetic, SimpleBitOps, Zero, One, Bounded,
|
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 substrate_primitives::storage::well_known_keys;
|
||||||
use runtime_support::{storage, StorageValue, StorageMap, Parameter};
|
use runtime_support::{storage, StorageValue, StorageMap, Parameter};
|
||||||
use safe_mix::TripletMix;
|
use safe_mix::TripletMix;
|
||||||
@@ -384,6 +384,21 @@ impl<T: Trait> Module<T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<T: Trait> GetHeight for Module<T> {
|
||||||
|
type BlockNumber = T::BlockNumber;
|
||||||
|
fn get_height(&self) -> Self::BlockNumber {
|
||||||
|
<Module<T>>::block_number()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: Trait> BlockNumberToHash for Module<T> {
|
||||||
|
type BlockNumber = T::BlockNumber;
|
||||||
|
type Hash = T::Hash;
|
||||||
|
fn block_number_to_hash(&self, n: Self::BlockNumber) -> Option<Self::Hash> {
|
||||||
|
Some(<Module<T>>::block_hash(n))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(any(feature = "std", test))]
|
#[cfg(any(feature = "std", test))]
|
||||||
#[derive(Serialize, Deserialize)]
|
#[derive(Serialize, Deserialize)]
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(rename_all = "camelCase")]
|
||||||
|
|||||||
Reference in New Issue
Block a user