diff --git a/Cargo.lock b/Cargo.lock index ddedd8ca97845..40ed4b6f19cb6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1126,8 +1126,11 @@ dependencies = [ "polkadot-primitives 0.1.0", "polkadot-runtime 0.1.0", "substrate-client 0.1.0", + "substrate-codec 0.1.0", "substrate-executor 0.1.0", "substrate-keyring 0.1.0", + "substrate-primitives 0.1.0", + "substrate-runtime-io 0.1.0", "substrate-state-machine 0.1.0", ] @@ -1177,6 +1180,7 @@ dependencies = [ "polkadot-api 0.1.0", "polkadot-collator 0.1.0", "polkadot-primitives 0.1.0", + "polkadot-runtime 0.1.0", "polkadot-statement-table 0.1.0", "polkadot-transaction-pool 0.1.0", "substrate-bft 0.1.0", @@ -1233,6 +1237,7 @@ dependencies = [ "serde_derive 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", "substrate-codec 0.1.0", "substrate-primitives 0.1.0", + "substrate-runtime-primitives 0.1.0", "substrate-runtime-std 0.1.0", "substrate-serializer 0.1.0", ] @@ -1245,13 +1250,25 @@ dependencies = [ "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", "polkadot-primitives 0.1.0", "rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "safe-mix 0.1.0", + "serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", "substrate-codec 0.1.0", "substrate-keyring 0.1.0", - "substrate-misbehavior-check 0.1.0", "substrate-primitives 0.1.0", + "substrate-runtime-consensus 0.1.0", + "substrate-runtime-council 0.1.0", + "substrate-runtime-democracy 0.1.0", + "substrate-runtime-executive 0.1.0", "substrate-runtime-io 0.1.0", + "substrate-runtime-primitives 0.1.0", + "substrate-runtime-session 0.1.0", + "substrate-runtime-staking 0.1.0", "substrate-runtime-std 0.1.0", "substrate-runtime-support 0.1.0", + "substrate-runtime-system 0.1.0", + "substrate-runtime-timestamp 0.1.0", + "substrate-serializer 0.1.0", ] [[package]] @@ -1261,6 +1278,7 @@ dependencies = [ "ed25519 0.1.0", "error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)", + "hex-literal 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "polkadot-api 0.1.0", @@ -1273,9 +1291,9 @@ dependencies = [ "substrate-client 0.1.0", "substrate-codec 0.1.0", "substrate-executor 0.1.0", - "substrate-keyring 0.1.0", "substrate-network 0.1.0", "substrate-primitives 0.1.0", + "substrate-runtime-io 0.1.0", "tokio-core 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-timer 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1297,8 +1315,10 @@ dependencies = [ "ethereum-types 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "polkadot-api 0.1.0", "polkadot-primitives 0.1.0", + "polkadot-runtime 0.1.0", "substrate-codec 0.1.0", "substrate-primitives 0.1.0", + "substrate-runtime-primitives 0.1.0", "transaction-pool 1.9.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1819,10 +1839,12 @@ dependencies = [ "hex-literal 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", "substrate-codec 0.1.0", + "substrate-primitives 0.1.0", "substrate-runtime-io 0.1.0", "substrate-runtime-primitives 0.1.0", "substrate-runtime-std 0.1.0", "substrate-runtime-support 0.1.0", + "substrate-runtime-system 0.1.0", ] [[package]] @@ -1995,10 +2017,12 @@ dependencies = [ "hex-literal 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", "substrate-codec 0.1.0", + "substrate-primitives 0.1.0", "substrate-runtime-io 0.1.0", "substrate-runtime-primitives 0.1.0", "substrate-runtime-std 0.1.0", "substrate-runtime-support 0.1.0", + "substrate-runtime-system 0.1.0", ] [[package]] diff --git a/demo/cli/src/lib.rs b/demo/cli/src/lib.rs index b58295775bc8b..7aa948f1a0485 100644 --- a/demo/cli/src/lib.rs +++ b/demo/cli/src/lib.rs @@ -75,6 +75,7 @@ pub fn run(args: I) -> error::Result<()> where let genesis_config = GenesisConfig { consensus: Some(ConsensusConfig { + code: vec![], // TODO authorities: vec![god_key.clone()], }), system: None, diff --git a/demo/executor/src/lib.rs b/demo/executor/src/lib.rs index c64855a3d35fc..17351de138ab5 100644 --- a/demo/executor/src/lib.rs +++ b/demo/executor/src/lib.rs @@ -197,7 +197,7 @@ mod tests { construct_block( 1, [69u8; 32].into(), - hex!("4d58afeca0dec7604a0bcfb29573e6ad202efe65c8535b013c0c79b5a8c9114d").into(), + hex!("57ba67304318efaee95c4f9ab95ed5704eafe030bc8db2df00acb08c2f4979c8").into(), vec![Extrinsic { signed: Alice.into(), index: 0, @@ -210,7 +210,7 @@ mod tests { construct_block( 2, block1().1, - hex!("218ce7bdf2350713aa52dbf0a12d1e8b0a3a9f1623e7c95aa4800886e96397d1").into(), + hex!("ead4c60c0cad06b7ee73e64efeec2d4eb82c651469fb2ec748cfe5026bea5c49").into(), vec![ Extrinsic { signed: Bob.into(), diff --git a/demo/primitives/src/lib.rs b/demo/primitives/src/lib.rs index ecfb5f7e7d214..86945c733f528 100644 --- a/demo/primitives/src/lib.rs +++ b/demo/primitives/src/lib.rs @@ -49,4 +49,4 @@ pub type Index = u64; pub type Hash = primitives::H256; /// Alias to 512-bit hash when used in the context of a signature on the relay chain. -pub type Signature = runtime_primitives::traits::Ed25519Signature; +pub type Signature = runtime_primitives::Ed25519Signature; diff --git a/demo/runtime/src/lib.rs b/demo/runtime/src/lib.rs index e6ac39823bdf4..1f7248f68e4df 100644 --- a/demo/runtime/src/lib.rs +++ b/demo/runtime/src/lib.rs @@ -54,20 +54,6 @@ impl HasPublicAux for Concrete { type PublicAux = AccountId; } -impl timestamp::Trait for Concrete { - type Value = u64; -} - -/// Timestamp module for this concrete runtime. -pub type Timestamp = timestamp::Module; - -impl consensus::Trait for Concrete { - type SessionKey = SessionKey; -} - -/// Consensus module for this concrete runtime. -pub type Consensus = consensus::Module; - impl system::Trait for Concrete { type Index = Index; type BlockNumber = BlockNumber; @@ -81,8 +67,22 @@ impl system::Trait for Concrete { /// System module for this concrete runtime. pub type System = system::Module; -impl session::Trait for Concrete { +impl consensus::Trait for Concrete { type PublicAux = ::PublicAux; + type SessionKey = SessionKey; +} + +/// Consensus module for this concrete runtime. +pub type Consensus = consensus::Module; + +impl timestamp::Trait for Concrete { + type Value = u64; +} + +/// Timestamp module for this concrete runtime. +pub type Timestamp = timestamp::Module; + +impl session::Trait for Concrete { type ConvertAccountIdToSessionKey = Identity; } @@ -113,6 +113,7 @@ pub type CouncilVoting = council::voting::Module; impl_outer_dispatch! { pub enum Call where aux: ::PublicAux { + Consensus = 0, Session = 1, Staking = 2, Timestamp = 3, diff --git a/demo/runtime/wasm/Cargo.lock b/demo/runtime/wasm/Cargo.lock index bc627b63e09c6..45cc1fee9aec3 100644 --- a/demo/runtime/wasm/Cargo.lock +++ b/demo/runtime/wasm/Cargo.lock @@ -666,10 +666,12 @@ dependencies = [ "hex-literal 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", "substrate-codec 0.1.0", + "substrate-primitives 0.1.0", "substrate-runtime-io 0.1.0", "substrate-runtime-primitives 0.1.0", "substrate-runtime-std 0.1.0", "substrate-runtime-support 0.1.0", + "substrate-runtime-system 0.1.0", ] [[package]] @@ -838,9 +840,12 @@ dependencies = [ "hex-literal 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", "substrate-codec 0.1.0", + "substrate-primitives 0.1.0", + "substrate-runtime-io 0.1.0", "substrate-runtime-primitives 0.1.0", "substrate-runtime-std 0.1.0", "substrate-runtime-support 0.1.0", + "substrate-runtime-system 0.1.0", ] [[package]] diff --git a/demo/runtime/wasm/target/wasm32-unknown-unknown/release/demo_runtime.compact.wasm b/demo/runtime/wasm/target/wasm32-unknown-unknown/release/demo_runtime.compact.wasm index e380c8c8f1656..678cce19cb9ae 100644 Binary files a/demo/runtime/wasm/target/wasm32-unknown-unknown/release/demo_runtime.compact.wasm and b/demo/runtime/wasm/target/wasm32-unknown-unknown/release/demo_runtime.compact.wasm differ diff --git a/demo/runtime/wasm/target/wasm32-unknown-unknown/release/demo_runtime.wasm b/demo/runtime/wasm/target/wasm32-unknown-unknown/release/demo_runtime.wasm old mode 100644 new mode 100755 index 528b6f61ec2d1..c386dfdcdd0eb Binary files a/demo/runtime/wasm/target/wasm32-unknown-unknown/release/demo_runtime.wasm and b/demo/runtime/wasm/target/wasm32-unknown-unknown/release/demo_runtime.wasm differ diff --git a/polkadot/api/Cargo.toml b/polkadot/api/Cargo.toml index 5e78af8c12068..13c19b7570f19 100644 --- a/polkadot/api/Cargo.toml +++ b/polkadot/api/Cargo.toml @@ -8,7 +8,10 @@ error-chain = "0.11" polkadot-executor = { path = "../executor" } polkadot-runtime = { path = "../runtime" } polkadot-primitives = { path = "../primitives" } +substrate-codec = { path = "../../substrate/codec" } +substrate-runtime-io = { path = "../../substrate/runtime-io" } substrate-client = { path = "../../substrate/client" } +substrate-primitives = { path = "../../substrate/primitives" } substrate-executor = { path = "../../substrate/executor" } substrate-state-machine = { path = "../../substrate/state-machine" } diff --git a/polkadot/api/src/lib.rs b/polkadot/api/src/lib.rs index 049e59e197648..848bf0c72c418 100644 --- a/polkadot/api/src/lib.rs +++ b/polkadot/api/src/lib.rs @@ -18,10 +18,13 @@ //! runtime. extern crate polkadot_executor; -extern crate polkadot_runtime; +extern crate polkadot_runtime as runtime; extern crate polkadot_primitives as primitives; +extern crate substrate_codec as codec; +extern crate substrate_runtime_io as runtime_io; extern crate substrate_client as client; extern crate substrate_executor as substrate_executor; +extern crate substrate_primitives; extern crate substrate_state_machine as state_machine; #[macro_use] @@ -32,14 +35,12 @@ extern crate substrate_keyring as keyring; use client::backend::Backend; use client::Client; -use polkadot_runtime::runtime; use polkadot_executor::Executor as LocalDispatch; use substrate_executor::{NativeExecutionDispatch, NativeExecutor}; use state_machine::OverlayedChanges; -use primitives::{AccountId, SessionKey, Timestamp, TxOrder}; -use primitives::block::{Id as BlockId, Block, Header, Body}; -use primitives::transaction::UncheckedTransaction; +use primitives::{AccountId, BlockId, Index, SessionKey, Timestamp}; use primitives::parachain::DutyRoster; +use runtime::{Block, Header, UncheckedExtrinsic, Extrinsic, Call, TimestampCall}; error_chain! { errors { @@ -53,15 +54,15 @@ error_chain! { description("Unknown block") display("Unknown block") } - /// Attempted to push an inherent transaction manually. - PushedInherentTransaction(tx: UncheckedTransaction) { - description("Attempted to push an inherent transaction to a block."), - display("Pushed inherent transaction to a block: {:?}", tx), + /// Attempted to push an inherent extrinsic manually. + PushedInherentTransaction(xt: UncheckedExtrinsic) { + description("Attempted to push an inherent extrinsic to a block."), + display("Pushed inherent extrinsic to a block: {:?}", xt), } - /// Badly-formed transaction. - BadlyFormedTransaction(tx: UncheckedTransaction) { - description("Attempted to push a badly-formed transaction to a block."), - display("Pushed badly-formed transaction to a block: {:?}", tx), + /// Badly-formed extrinsic. + BadlyFormedTransaction(xt: UncheckedExtrinsic) { + description("Attempted to push a badly-formed extrinsic to a block."), + display("Pushed badly-formed extrinsic to a block: {:?}", xt), } /// Some other error. // TODO: allow to be specified as associated type of PolkadotApi @@ -87,8 +88,8 @@ impl From for Error { /// A builder for blocks. pub trait BlockBuilder: Sized { - /// Push a non-inherent transaction. - fn push_transaction(&mut self, transaction: UncheckedTransaction) -> Result<()>; + /// Push a non-inherent extrinsic. + fn push_extrinsic(&mut self, extrinsic: UncheckedExtrinsic) -> Result<()>; /// Finalise the block. fn bake(self) -> Block; @@ -127,8 +128,8 @@ pub trait PolkadotApi { /// Get the timestamp registered at a block. fn timestamp(&self, at: &Self::CheckedBlockId) -> Result; - /// Get the nonce of an account at a block. - fn nonce(&self, at: &Self::CheckedBlockId, account: AccountId) -> Result; + /// Get the index of an account at a block. + fn index(&self, at: &Self::CheckedBlockId, account: AccountId) -> Result; /// Evaluate a block and see if it gives an error. @@ -179,27 +180,27 @@ impl PolkadotApi for Client> } fn session_keys(&self, at: &CheckedId) -> Result> { - with_runtime!(self, at, ::runtime::consensus::authorities) + with_runtime!(self, at, ::runtime::Consensus::authorities) } fn validators(&self, at: &CheckedId) -> Result> { - with_runtime!(self, at, ::runtime::session::validators) + with_runtime!(self, at, ::runtime::Session::validators) } fn duty_roster(&self, at: &CheckedId) -> Result { - with_runtime!(self, at, ::runtime::parachains::calculate_duty_roster) + with_runtime!(self, at, ::runtime::Parachains::calculate_duty_roster) } fn timestamp(&self, at: &CheckedId) -> Result { - with_runtime!(self, at, ::runtime::timestamp::get) + with_runtime!(self, at, ::runtime::Timestamp::now) } fn evaluate_block(&self, at: &CheckedId, block: Block) -> Result<()> { - with_runtime!(self, at, || ::runtime::system::internal::execute_block(block)) + with_runtime!(self, at, || ::runtime::Executive::execute_block(block)) } - fn nonce(&self, at: &Self::CheckedBlockId, account: AccountId) -> Result { - with_runtime!(self, at, || ::runtime::system::nonce(account)) + fn index(&self, at: &Self::CheckedBlockId, account: AccountId) -> Result { + with_runtime!(self, at, || ::runtime::System::account_index(account)) } fn build_block(&self, parent: &CheckedId, timestamp: Timestamp) -> Result { @@ -208,14 +209,20 @@ impl PolkadotApi for Client> parent_hash: self.block_hash_from_id(parent)?.ok_or(ErrorKind::UnknownBlock(*parent))?, number: self.block_number_from_id(parent)?.ok_or(ErrorKind::UnknownBlock(*parent))? + 1, state_root: Default::default(), - transaction_root: Default::default(), + extrinsics_root: Default::default(), digest: Default::default(), }; - let body = Body { - timestamp: timestamp, - transactions: Vec::new(), - }; + let extrinsics = vec![ + UncheckedExtrinsic { + extrinsic: Extrinsic { + signed: Default::default(), + index: Default::default(), + function: Call::Timestamp(TimestampCall::set(timestamp)), + }, + signature: Default::default(), + } + ]; let mut builder = ClientBlockBuilder { parent: *parent, @@ -223,11 +230,13 @@ impl PolkadotApi for Client> state: self.state_at(parent)?, header, timestamp, - transactions: Vec::new(), + extrinsics: extrinsics.clone(), }; - for inherent in body.inherent_transactions() { - builder.execute_transaction(inherent)?; + builder.initialise_block()?; + + for inherent in extrinsics { + builder.apply_extrinsic(inherent)?; } Ok(builder) @@ -242,34 +251,53 @@ pub struct ClientBlockBuilder { state: S, header: Header, timestamp: Timestamp, - transactions: Vec, + extrinsics: Vec, } impl ClientBlockBuilder where S::Error: Into { - // executes a transaction, inherent or otherwise, without appending to the list - fn execute_transaction(&mut self, transaction: UncheckedTransaction) -> Result<()> { - if !transaction.is_well_formed() { - bail!(ErrorKind::BadlyFormedTransaction(transaction)); + // executes a extrinsic, inherent or otherwise, without appending to the list + fn initialise_block(&mut self) -> Result<()> { + let mut ext = state_machine::Ext { + overlay: &mut self.changes, + backend: &self.state, + }; + + let h = self.header.clone(); + + let result = ::substrate_executor::with_native_environment( + &mut ext, + || runtime::Executive::initialise_block(&h), + ).map_err(Into::into); + + match result { + Ok(_) => { + ext.overlay.commit_prospective(); + Ok(()) + } + Err(e) => { + ext.overlay.discard_prospective(); + Err(e) + } } + } + // executes a extrinsic, inherent or otherwise, without appending to the list + fn apply_extrinsic(&mut self, extrinsic: UncheckedExtrinsic) -> Result<()> { let mut ext = state_machine::Ext { overlay: &mut self.changes, backend: &self.state, }; - // TODO: avoid clone - let header = self.header.clone(); let result = ::substrate_executor::with_native_environment( &mut ext, - move || runtime::system::internal::execute_transaction(transaction, header), + move || runtime::Executive::apply_extrinsic(extrinsic), ).map_err(Into::into); match result { - Ok(header) => { + Ok(_) => { ext.overlay.commit_prospective(); - self.header = header; Ok(()) } Err(e) => { @@ -283,12 +311,13 @@ impl ClientBlockBuilder impl BlockBuilder for ClientBlockBuilder where S::Error: Into { - fn push_transaction(&mut self, transaction: UncheckedTransaction) -> Result<()> { - if transaction.transaction.function.is_inherent() { - bail!(ErrorKind::PushedInherentTransaction(transaction)); + fn push_extrinsic(&mut self, extrinsic: UncheckedExtrinsic) -> Result<()> { + // Check that this is not an "inherent" extrinsic. + if extrinsic.signature == Default::default() { + bail!(ErrorKind::PushedInherentTransaction(extrinsic)); } else { - self.execute_transaction(transaction.clone())?; - self.transactions.push(transaction); + self.apply_extrinsic(extrinsic.clone())?; + self.extrinsics.push(extrinsic); Ok(()) } } @@ -299,18 +328,14 @@ impl BlockBuilder for ClientBlockBuilder backend: &self.state, }; - let old_header = self.header; let final_header = ::substrate_executor::with_native_environment( &mut ext, - move || runtime::system::internal::finalise_block(old_header) - ).expect("all inherent transactions pushed; all other transactions executed correctly; qed"); + move || runtime::Executive::finalise_block() + ).expect("all inherent extrinsics pushed; all other extrinsics executed correctly; qed"); Block { header: final_header, - body: Body { - timestamp: self.timestamp, - transactions: self.transactions, - } + extrinsics: self.extrinsics, } } } @@ -318,10 +343,12 @@ impl BlockBuilder for ClientBlockBuilder #[cfg(test)] mod tests { use super::*; + use runtime_io::with_externalities; + use keyring::Keyring; + use codec::Slicable; use client::in_mem::Backend as InMemory; - use polkadot_runtime::genesismap::{additional_storage_with_genesis, GenesisConfig}; use substrate_executor::NativeExecutionDispatch; - use keyring::Keyring; + use runtime::{GenesisConfig, ConsensusConfig, SessionConfig, BuildExternalities}; fn validators() -> Vec { vec![ @@ -331,20 +358,31 @@ mod tests { } fn client() -> Client> { + let genesis_config = GenesisConfig { + consensus: Some(ConsensusConfig { + code: LocalDispatch::native_equivalent().to_vec(), + authorities: validators(), + }), + system: None, + session: Some(SessionConfig { + validators: validators(), + session_length: 100, + }), + council: Some(Default::default()), + democracy: Some(Default::default()), + parachains: Some(Default::default()), + staking: Some(Default::default()), + }; ::client::new_in_mem( LocalDispatch::new(), || { - let config = GenesisConfig::new_simple(validators(), 100); - - // override code entry. - let mut storage = config.genesis_map(); - storage.insert(b":code".to_vec(), LocalDispatch::native_equivalent().to_vec()); - - let block = ::client::genesis::construct_genesis_block( - &config.genesis_map() + let mut storage = genesis_config.build_externalities(); + let block = ::client::genesis::construct_genesis_block(&storage); + with_externalities(&mut storage, || + // TODO: use api.rs to dispatch instead + runtime::System::initialise_genesis_state(&block.header) ); - storage.extend(additional_storage_with_genesis(&block)); - (block.header, storage.into_iter().collect()) + (substrate_primitives::block::Header::decode(&mut block.header.encode().as_ref()).expect("to_vec() always gives a valid serialisation; qed"), storage.into_iter().collect()) } ).unwrap() } diff --git a/polkadot/consensus/Cargo.toml b/polkadot/consensus/Cargo.toml index 103ae1a9132e7..f87a63b87e545 100644 --- a/polkadot/consensus/Cargo.toml +++ b/polkadot/consensus/Cargo.toml @@ -13,6 +13,7 @@ log = "0.4" polkadot-api = { path = "../api" } polkadot-collator = { path = "../collator" } polkadot-primitives = { path = "../primitives" } +polkadot-runtime = { path = "../runtime" } polkadot-statement-table = { path = "../statement-table" } polkadot-transaction-pool = { path = "../transaction-pool" } substrate-bft = { path = "../../substrate/bft" } diff --git a/polkadot/consensus/src/lib.rs b/polkadot/consensus/src/lib.rs index ba1e05b05e1ff..1fc6c441f20b6 100644 --- a/polkadot/consensus/src/lib.rs +++ b/polkadot/consensus/src/lib.rs @@ -38,6 +38,7 @@ extern crate polkadot_collator as collator; extern crate polkadot_statement_table as table; extern crate polkadot_primitives; extern crate polkadot_transaction_pool as transaction_pool; +extern crate polkadot_runtime; extern crate substrate_bft as bft; extern crate substrate_codec as codec; extern crate substrate_primitives as primitives; @@ -62,11 +63,11 @@ use table::generic::Statement as GenericStatement; use runtime_support::Hashable; use polkadot_api::{PolkadotApi, BlockBuilder}; use polkadot_primitives::{Hash, Timestamp}; -use polkadot_primitives::block::Block as PolkadotBlock; use polkadot_primitives::parachain::{Id as ParaId, DutyRoster, BlockData, Extrinsic, CandidateReceipt}; +use polkadot_runtime::Block as PolkadotGenericBlock; use primitives::block::{Block as SubstrateBlock, Header as SubstrateHeader, HeaderHash, Id as BlockId, Number as BlockNumber}; use primitives::AuthorityId; -use transaction_pool::{Ready, TransactionPool}; +use transaction_pool::{Ready, TransactionPool, PolkadotBlock}; use futures::prelude::*; use futures::future; @@ -152,7 +153,7 @@ impl TableContext { } fn sign_statement(&self, statement: table::Statement) -> table::SignedStatement { - let signature = sign_table_statement(&statement, &self.key, &self.parent_hash); + let signature = sign_table_statement(&statement, &self.key, &self.parent_hash).into(); let local_id = self.key.public().0; table::SignedStatement { @@ -552,7 +553,7 @@ impl bft::Proposer for Proposer { if pending_size + pending.encoded_size() >= MAX_TRANSACTIONS_SIZE { break } - match block_builder.push_transaction(pending.as_transaction().clone()) { + match block_builder.push_extrinsic(pending.as_transaction().clone()) { Ok(()) => { pending_size += pending.encoded_size(); } @@ -582,23 +583,23 @@ impl bft::Proposer for Proposer { fn import_misbehavior(&self, misbehavior: Vec<(AuthorityId, bft::Misbehavior)>) { use bft::generic::Misbehavior as GenericMisbehavior; use primitives::bft::{MisbehaviorKind, MisbehaviorReport}; - use polkadot_primitives::transaction::{Function, Transaction, UncheckedTransaction}; + use polkadot_runtime::{Call, Extrinsic, UncheckedExtrinsic, ConsensusCall}; let local_id = self.local_key.public().0; let mut pool = self.transaction_pool.lock(); - let mut next_nonce = { + let mut next_index = { let readiness_evaluator = Ready::create(self.parent_id.clone(), &*self.client); - let cur_nonce = pool.pending(readiness_evaluator) - .filter(|tx| tx.as_transaction().transaction.signed == local_id) + let cur_index = pool.pending(readiness_evaluator) + .filter(|tx| tx.as_ref().as_ref().signed == local_id) .last() - .map(|tx| Ok(tx.as_transaction().transaction.nonce)) - .unwrap_or_else(|| self.client.nonce(&self.parent_id, local_id)); + .map(|tx| Ok(tx.as_ref().as_ref().index)) + .unwrap_or_else(|| self.client.index(&self.parent_id, local_id)); - match cur_nonce { - Ok(cur_nonce) => cur_nonce + 1, + match cur_index { + Ok(cur_index) => cur_index + 1, Err(e) => { - warn!(target: "consensus", "Error computing next transaction nonce: {}", e); + warn!(target: "consensus", "Error computing next transaction index: {}", e); return; } } @@ -618,23 +619,18 @@ impl bft::Proposer for Proposer { => MisbehaviorKind::BftDoubleCommit(round as u32, (h1, s1.signature), (h2, s2.signature)), } }; - - let tx = Transaction { + let extrinsic = Extrinsic { signed: local_id, - nonce: next_nonce, - function: Function::ReportMisbehavior(report), + index: next_index, + function: Call::Consensus(ConsensusCall::report_misbehavior(report)), }; - next_nonce += 1; + next_index += 1; - let message = tx.encode(); - let signature = self.local_key.sign(&message); - let tx = UncheckedTransaction { - transaction: tx, - signature, - }; + let signature = self.local_key.sign(&extrinsic.encode()).into(); + let uxt = UncheckedExtrinsic { extrinsic, signature }; - pool.import(tx).expect("locally signed transaction is valid; qed"); + pool.import(uxt).expect("locally signed extrinsic is valid; qed"); } } } @@ -649,10 +645,11 @@ fn evaluate_proposal( const MAX_TIMESTAMP_DRIFT: Timestamp = 4; let encoded = Slicable::encode(proposal); - let proposal = PolkadotBlock::decode(&mut &encoded[..]) + let proposal = PolkadotGenericBlock::decode(&mut &encoded[..]) + .and_then(|b| PolkadotBlock::from(b).ok()) .ok_or_else(|| ErrorKind::ProposalNotForPolkadot)?; - let transactions_size = proposal.body.transactions.iter().fold(0, |a, tx| { + let transactions_size = proposal.extrinsics.iter().fold(0, |a, tx| { a + Slicable::encode(tx).len() }); @@ -668,7 +665,7 @@ fn evaluate_proposal( // a) we assume the parent is valid. // b) the runtime checks that `proposal.parent_hash` == `block_hash(proposal.number - 1)` - let block_timestamp = proposal.body.timestamp; + let block_timestamp = proposal.timestamp(); // TODO: just defer using `tokio_timer` to delay prepare vote. if block_timestamp > now + MAX_TIMESTAMP_DRIFT { @@ -676,6 +673,6 @@ fn evaluate_proposal( } // execute the block. - client.evaluate_block(parent_id, proposal)?; + client.evaluate_block(parent_id, proposal.into())?; Ok(true) } diff --git a/polkadot/executor/src/lib.rs b/polkadot/executor/src/lib.rs index 186e5469ccfda..e5e096418bec4 100644 --- a/polkadot/executor/src/lib.rs +++ b/polkadot/executor/src/lib.rs @@ -27,282 +27,4 @@ extern crate polkadot_primitives as polkadot_primitives; extern crate ed25519; extern crate triehash; -#[cfg(test)] extern crate substrate_keyring as keyring; -#[cfg(test)] extern crate substrate_runtime_support as runtime_support; -#[cfg(test)] #[macro_use] extern crate hex_literal; - native_executor_instance!(pub Executor, polkadot_runtime::api::dispatch, include_bytes!("../../runtime/wasm/target/wasm32-unknown-unknown/release/polkadot_runtime.compact.wasm")); - -#[cfg(test)] -mod tests { - use runtime_io; - use super::Executor; - use substrate_executor::WasmExecutor; - use codec::{KeyedVec, Slicable, Joiner}; - use keyring::Keyring; - use runtime_support::Hashable; - use polkadot_runtime::runtime::staking::balance; - use state_machine::{CodeExecutor, TestExternalities}; - use primitives::twox_128; - use polkadot_primitives::{ - Hash, Header, Body, BlockNumber, Block, Digest, Transaction, - UncheckedTransaction, Function, InherentFunction, - }; - use ed25519::{Public, Pair}; - - const BLOATY_CODE: &[u8] = include_bytes!("../../runtime/wasm/target/wasm32-unknown-unknown/release/polkadot_runtime.wasm"); - const COMPACT_CODE: &[u8] = include_bytes!("../../runtime/wasm/target/wasm32-unknown-unknown/release/polkadot_runtime.compact.wasm"); - - // TODO: move into own crate. - macro_rules! map { - ($( $name:expr => $value:expr ),*) => ( - vec![ $( ( $name, $value ) ),* ].into_iter().collect() - ) - } - - fn new_test_ext() -> TestExternalities { - let one = Keyring::One.to_raw_public(); - let two = Keyring::Two.to_raw_public(); - let three = [3u8; 32]; - - map![ - twox_128(&0u64.to_keyed_vec(b"sys:old:")).to_vec() => [69u8; 32].encode(), - twox_128(b"gov:apr").to_vec() => vec![].and(&667u32), - twox_128(b"ses:len").to_vec() => vec![].and(&2u64), - twox_128(b"ses:val:len").to_vec() => vec![].and(&3u32), - twox_128(&0u32.to_keyed_vec(b"ses:val:")).to_vec() => one.to_vec(), - twox_128(&1u32.to_keyed_vec(b"ses:val:")).to_vec() => two.to_vec(), - twox_128(&2u32.to_keyed_vec(b"ses:val:")).to_vec() => three.to_vec(), - twox_128(b"sta:wil:len").to_vec() => vec![].and(&3u32), - twox_128(&0u32.to_keyed_vec(b"sta:wil:")).to_vec() => one.to_vec(), - twox_128(&1u32.to_keyed_vec(b"sta:wil:")).to_vec() => two.to_vec(), - twox_128(&2u32.to_keyed_vec(b"sta:wil:")).to_vec() => three.to_vec(), - twox_128(b"sta:spe").to_vec() => vec![].and(&2u64), - twox_128(b"sta:vac").to_vec() => vec![].and(&3u64), - twox_128(b"sta:era").to_vec() => vec![].and(&0u64), - twox_128(&one.to_keyed_vec(b"sta:bal:")).to_vec() => vec![111u8, 0, 0, 0, 0, 0, 0, 0] - ] - } - - fn set_timestamp(timestamp: u64) -> UncheckedTransaction { - UncheckedTransaction::inherent(InherentFunction::TimestampSet(timestamp)) - } - - fn tx() -> UncheckedTransaction { - let transaction = Transaction { - signed: Keyring::One.to_raw_public(), - nonce: 0, - function: Function::StakingTransfer(Keyring::Two.to_raw_public(), 69), - }; - let signature = Keyring::from_raw_public(transaction.signed).unwrap() - .sign(&transaction.encode()); - - UncheckedTransaction { transaction, signature } - } - - fn execute_tx_on(executor: C, ext: &mut TestExternalities, code: &[u8], tx: UncheckedTransaction, header: Header) - -> Result, C::Error> - where C: CodeExecutor - { - let next_header = executor.call(ext, code, "execute_transaction", &vec![].and(&header).and(&set_timestamp(100_000))).unwrap(); - let next_input = next_header.and(&tx); - - executor.call(ext, code, "execute_transaction", &next_input[..]) - } - - fn construct_block(number: BlockNumber, parent_hash: Hash, state_root: Hash, timestamp: u64, txs: Vec) -> (Vec, Hash) { - use triehash::ordered_trie_root; - - - let transactions = txs.into_iter().map(|transaction| { - let signature = Pair::from(Keyring::from_public(Public::from_raw(transaction.signed)).unwrap()) - .sign(&transaction.encode()); - - UncheckedTransaction { transaction, signature } - }).collect(); - - let header = Header { - parent_hash, - number, - state_root, - transaction_root: Default::default(), - digest: Digest { logs: vec![], }, - }; - - let mut block = Block { - header, - body: Body { timestamp, transactions }, - }; - - let transaction_root = ordered_trie_root(block.all_transactions().map(|tx| Slicable::encode(&tx))).0.into(); - block.header.transaction_root = transaction_root; - - let hash = block.header.blake2_256(); - - (block.encode(), hash.into()) - } - - fn block1() -> (Vec, Hash) { - construct_block( - 1, - [69u8; 32].into(), - hex!("3df569d47a0d7f4a448486f04fba4eea3e9dfca001319c609f88b3a67b0dd1ea").into(), - 100_000, - vec![ - Transaction { - signed: Keyring::One.to_raw_public(), - nonce: 0, - function: Function::StakingTransfer(Keyring::Two.to_raw_public(), 69), - } - ] - ) - } - - fn block2() -> (Vec, Hash) { - construct_block( - 2, - block1().1, - hex!("5604fe023cd6effd93aec9b4a008398abdd32afb3fec988a19aa853ab0424a7c").into(), - 200_000, - vec![ - Transaction { - signed: Keyring::Two.to_raw_public(), - nonce: 0, - function: Function::StakingTransfer(Keyring::One.to_raw_public(), 5), - }, - Transaction { - signed: Keyring::One.to_raw_public(), - nonce: 1, - function: Function::StakingTransfer(Keyring::Two.to_raw_public(), 15), - } - ] - ) - } - - #[test] - fn panic_execution_with_foreign_code_gives_error() { - let one = Keyring::One.to_raw_public(); - let mut t: TestExternalities = map![ - twox_128(&one.to_keyed_vec(b"sta:bal:")).to_vec() => vec![68u8, 0, 0, 0, 0, 0, 0, 0] - ]; - - let r = execute_tx_on(Executor::new(), &mut t, BLOATY_CODE, tx(), Header::from_block_number(1)); - assert!(r.is_err()); - } - - #[test] - fn panic_execution_with_native_equivalent_code_gives_error() { - let one = Keyring::One.to_raw_public(); - let mut t: TestExternalities = map![ - twox_128(&one.to_keyed_vec(b"sta:bal:")).to_vec() => vec![68u8, 0, 0, 0, 0, 0, 0, 0] - ]; - - let r = execute_tx_on(Executor::new(), &mut t, COMPACT_CODE, tx(), Header::from_block_number(1)); - assert!(r.is_err()); - } - - #[test] - fn successful_execution_with_native_equivalent_code_gives_ok() { - let one = Keyring::One.to_raw_public(); - let two = Keyring::Two.to_raw_public(); - - let mut t: TestExternalities = map![ - twox_128(&one.to_keyed_vec(b"sta:bal:")).to_vec() => vec![111u8, 0, 0, 0, 0, 0, 0, 0] - ]; - - let r = execute_tx_on(Executor::new(), &mut t, COMPACT_CODE, tx(), Header::from_block_number(1)); - assert!(r.is_ok()); - - runtime_io::with_externalities(&mut t, || { - assert_eq!(balance(&one), 42); - assert_eq!(balance(&two), 69); - }); - } - - #[test] - fn successful_execution_with_foreign_code_gives_ok() { - let one = Keyring::One.to_raw_public(); - let two = Keyring::Two.to_raw_public(); - - let mut t: TestExternalities = map![ - twox_128(&one.to_keyed_vec(b"sta:bal:")).to_vec() => vec![111u8, 0, 0, 0, 0, 0, 0, 0] - ]; - - let r = execute_tx_on(Executor::new(), &mut t, BLOATY_CODE, tx(), Header::from_block_number(1)); - assert!(r.is_ok()); - - runtime_io::with_externalities(&mut t, || { - assert_eq!(balance(&one), 42); - assert_eq!(balance(&two), 69); - }); - } - - #[test] - fn full_native_block_import_works() { - let mut t = new_test_ext(); - - Executor::new().call(&mut t, COMPACT_CODE, "execute_block", &block1().0).unwrap(); - - runtime_io::with_externalities(&mut t, || { - assert_eq!(balance(&Keyring::One.to_raw_public()), 42); - assert_eq!(balance(&Keyring::Two.to_raw_public()), 69); - }); - - Executor::new().call(&mut t, COMPACT_CODE, "execute_block", &block2().0).unwrap(); - - runtime_io::with_externalities(&mut t, || { - assert_eq!(balance(&Keyring::One.to_raw_public()), 32); - assert_eq!(balance(&Keyring::Two.to_raw_public()), 79); - }); - } - - #[test] - fn full_wasm_block_import_works() { - let mut t = new_test_ext(); - - WasmExecutor.call(&mut t, COMPACT_CODE, "execute_block", &block1().0).unwrap(); - - runtime_io::with_externalities(&mut t, || { - assert_eq!(balance(&Keyring::One.to_raw_public()), 42); - assert_eq!(balance(&Keyring::Two.to_raw_public()), 69); - }); - - WasmExecutor.call(&mut t, COMPACT_CODE, "execute_block", &block2().0).unwrap(); - - runtime_io::with_externalities(&mut t, || { - assert_eq!(balance(&Keyring::One.to_raw_public()), 32); - assert_eq!(balance(&Keyring::Two.to_raw_public()), 79); - }); - } - - #[test] - fn panic_execution_gives_error() { - let one = Keyring::One.to_raw_public(); - let mut t: TestExternalities = map![ - twox_128(&one.to_keyed_vec(b"sta:bal:")).to_vec() => vec![68u8, 0, 0, 0, 0, 0, 0, 0] - ]; - - let foreign_code = include_bytes!("../../runtime/wasm/target/wasm32-unknown-unknown/release/polkadot_runtime.wasm"); - let r = execute_tx_on(WasmExecutor, &mut t, &foreign_code[..], tx(), Header::from_block_number(1)); - assert!(r.is_err()); - } - - #[test] - fn successful_execution_gives_ok() { - let one = Keyring::One.to_raw_public(); - let two = Keyring::Two.to_raw_public(); - - let mut t: TestExternalities = map![ - twox_128(&one.to_keyed_vec(b"sta:bal:")).to_vec() => vec![111u8, 0, 0, 0, 0, 0, 0, 0] - ]; - - let foreign_code = include_bytes!("../../runtime/wasm/target/wasm32-unknown-unknown/release/polkadot_runtime.compact.wasm"); - let r = execute_tx_on(WasmExecutor, &mut t, &foreign_code[..], tx(), Header::from_block_number(1)); - assert!(r.is_ok()); - - runtime_io::with_externalities(&mut t, || { - assert_eq!(balance(&one), 42); - assert_eq!(balance(&two), 69); - }); - } -} diff --git a/polkadot/primitives/Cargo.toml b/polkadot/primitives/Cargo.toml index ec2433c9a7935..dc424468dc18b 100644 --- a/polkadot/primitives/Cargo.toml +++ b/polkadot/primitives/Cargo.toml @@ -9,6 +9,7 @@ serde_derive = { version = "1.0", optional = true } substrate-codec = { path = "../../substrate/codec", default_features = false } substrate-primitives = { path = "../../substrate/primitives", default_features = false } substrate-runtime-std = { path = "../../substrate/runtime-std", default_features = false } +substrate-runtime-primitives = { path = "../../substrate/runtime/primitives", default_features = false } [dev-dependencies] substrate-serializer = { path = "../../substrate/serializer" } @@ -20,6 +21,7 @@ std = [ "substrate-codec/std", "substrate-primitives/std", "substrate-runtime-std/std", + "substrate-runtime-primitives/std", "serde_derive", "serde/std", ] diff --git a/polkadot/primitives/src/block.rs b/polkadot/primitives/src/block.rs deleted file mode 100644 index e74dd19f4c59b..0000000000000 --- a/polkadot/primitives/src/block.rs +++ /dev/null @@ -1,375 +0,0 @@ -// Copyright 2017 Parity Technologies (UK) Ltd. -// This file is part of Polkadot. - -// Polkadot 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. - -// Polkadot 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 Polkadot. If not, see . - -//! Block and header type definitions. - -#[cfg(feature = "std")] -use primitives::bytes; -use primitives::H256; -use rstd::vec::Vec; -use codec::{Input, Slicable}; -use transaction::{UncheckedTransaction, Function, InherentFunction}; - -pub use primitives::block::Id; - -/// Used to refer to a block number. -pub type Number = u64; - -/// Hash used to refer to a block hash. -pub type HeaderHash = H256; - -/// Hash used to refer to a transaction hash. -pub type TransactionHash = H256; - -/// Execution log (event) -#[derive(PartialEq, Eq, Clone)] -#[cfg_attr(feature = "std", derive(Serialize, Deserialize, Debug))] -pub struct Log(#[cfg_attr(feature = "std", serde(with="bytes"))] pub Vec); - -impl Slicable for Log { - fn decode(input: &mut I) -> Option { - Vec::::decode(input).map(Log) - } - - fn using_encoded R>(&self, f: F) -> R { - self.0.using_encoded(f) - } -} - - - -/// The digest of a block, useful for light-clients. -#[derive(Clone, Default, PartialEq, Eq)] -#[cfg_attr(feature = "std", derive(Serialize, Deserialize, Debug))] -pub struct Digest { - /// All logs that have happened in the block. - pub logs: Vec, -} - -impl Slicable for Digest { - fn decode(input: &mut I) -> Option { - Vec::::decode(input).map(|logs| Digest { logs }) - } - - fn using_encoded R>(&self, f: F) -> R { - self.logs.using_encoded(f) - } -} - -/// Iterator over all inherent transactions. -pub struct InherentTransactions<'a> { - number: u64, - body: &'a Body, -} - -impl<'a> Iterator for InherentTransactions<'a> { - type Item = UncheckedTransaction; - - fn next(&mut self) -> Option { - if self.number == InherentFunction::count() { - return None - } - - self.number += 1; - - let function = match self.number { - 1 => Some(InherentFunction::TimestampSet(self.body.timestamp)), - _ => None, - }; - - function.map(UncheckedTransaction::inherent) - } -} - -/// Type alias for an iterator over all transactions in a block. -pub type AllTransactions<'a> = ::rstd::iter::Chain< - InherentTransactions<'a>, - ::rstd::iter::Cloned<::rstd::slice::Iter<'a, UncheckedTransaction>>, ->; - -/// The block body. Contains timestamp and transactions. -// TODO: add candidates update as well. -#[derive(PartialEq, Eq, Clone)] -#[cfg_attr(feature = "std", derive(Serialize, Deserialize, Debug))] -#[cfg_attr(feature = "std", serde(rename_all = "camelCase"))] -#[cfg_attr(feature = "std", serde(deny_unknown_fields))] -pub struct Body { - /// The timestamp of the block. - pub timestamp: u64, - /// The transactions in the block. - pub transactions: Vec, -} - -impl Body { - /// Get an iterator over all inherent transactions of the body. - pub fn inherent_transactions(&self) -> InherentTransactions { - InherentTransactions { - number: 0, - body: self, - } - } - - /// Get an iterator over all transactions in a block. - pub fn all_transactions(&self) -> AllTransactions { - self.inherent_transactions().chain(self.transactions.iter().cloned()) - } -} - - -/// A Polkadot relay chain block. -#[derive(PartialEq, Eq, Clone)] -#[cfg_attr(feature = "std", derive(Serialize, Deserialize, Debug))] -pub struct Block { - /// The block header. - pub header: Header, - /// The block body. - pub body: Body, -} - -impl Block { - /// Get an iterator over all inherent transactions of the body. - pub fn inherent_transactions(&self) -> InherentTransactions { - self.body.inherent_transactions() - } - - /// Get an iterator over all transactions in a block. - pub fn all_transactions(&self) -> AllTransactions { - self.body.all_transactions() - } -} - -impl Slicable for Block { - fn decode(input: &mut I) -> Option { - let header = try_opt!(Slicable::decode(input)); - - let transactions_len: u32 = try_opt!(Slicable::decode(input)); - let regular_transactions_len = try_opt!(transactions_len.checked_sub(InherentFunction::count() as u32)); - - let timestamp_tx = try_opt!(UncheckedTransaction::decode(input)); - let timestamp = match timestamp_tx.transaction.function { - Function::Inherent(InherentFunction::TimestampSet(ref t)) if timestamp_tx.is_well_formed() => { t.clone() } - _ => return None, - }; - - let transactions: Option> = (0..regular_transactions_len) - .map(|_| UncheckedTransaction::decode(input)) - .filter(|tx| tx.as_ref().map_or(true, |tx| tx.is_well_formed())) - .collect(); - - let body = Body { - timestamp, - transactions: try_opt!(transactions), - }; - - Some(Block { header, body }) - } - - fn encode(&self) -> Vec { - let mut v = Vec::new(); - - v.extend(self.header.encode()); - - // encode inherent transactions before non-inherent. - let transactions_len = self.body.transactions.len() as u64 + InherentFunction::count(); - (transactions_len as u32).using_encoded(|s| v.extend(s)); - - let timestamp_set_tx = UncheckedTransaction::inherent( - InherentFunction::TimestampSet(self.body.timestamp) - ); - - v.extend(timestamp_set_tx.encode()); - for non_inherent_transaction in &self.body.transactions { - v.extend(non_inherent_transaction.encode()); - } - - v - } -} - -/// A relay chain block header. -/// -/// https://github.com/w3f/polkadot-spec/blob/master/spec.md#header -#[derive(PartialEq, Eq, Clone)] -#[cfg_attr(feature = "std", derive(Serialize, Deserialize, Debug))] -#[cfg_attr(feature = "std", serde(rename_all = "camelCase"))] -#[cfg_attr(feature = "std", serde(deny_unknown_fields))] -pub struct Header { - /// Block parent's hash. - pub parent_hash: HeaderHash, - /// Block number. - pub number: Number, - /// State root after this transition. - pub state_root: H256, - /// The root of the trie that represents this block's transactions, indexed by a 32-byte integer. - pub transaction_root: H256, - /// The digest of activity on the block. - pub digest: Digest, -} - -impl Header { - /// Create a new instance with default fields except `number`, which is given as an argument. - pub fn from_block_number(number: Number) -> Self { - Header { - parent_hash: Default::default(), - number, - state_root: Default::default(), - transaction_root: Default::default(), - digest: Default::default(), - } - } -} - -impl Slicable for Header { - fn decode(input: &mut I) -> Option { - Some(Header { - parent_hash: try_opt!(Slicable::decode(input)), - number: try_opt!(Slicable::decode(input)), - state_root: try_opt!(Slicable::decode(input)), - transaction_root: try_opt!(Slicable::decode(input)), - digest: try_opt!(Slicable::decode(input)), - }) - } - - fn encode(&self) -> Vec { - let mut v = Vec::new(); - - self.parent_hash.using_encoded(|s| v.extend(s)); - self.number.using_encoded(|s| v.extend(s)); - self.state_root.using_encoded(|s| v.extend(s)); - self.transaction_root.using_encoded(|s| v.extend(s)); - self.digest.using_encoded(|s| v.extend(s)); - - v - } -} - -#[cfg(test)] -mod tests { - use super::*; - use codec::Slicable; - use substrate_serializer as ser; - - #[test] - fn test_header_serialization() { - let header = Header { - parent_hash: 5.into(), - number: 67, - state_root: 3.into(), - transaction_root: 6.into(), - digest: Digest { logs: vec![Log(vec![1])] }, - }; - - assert_eq!(ser::to_string_pretty(&header), r#"{ - "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000005", - "number": 67, - "stateRoot": "0x0000000000000000000000000000000000000000000000000000000000000003", - "transactionRoot": "0x0000000000000000000000000000000000000000000000000000000000000006", - "digest": { - "logs": [ - "0x01" - ] - } -}"#); - - let v = header.encode(); - assert_eq!(Header::decode(&mut &v[..]).unwrap(), header); - } - - #[test] - fn block_encoding_round_trip() { - let mut block = Block { - header: Header::from_block_number(1), - body: Body { - timestamp: 100_000_000, - transactions: Vec::new(), - } - }; - - let raw = block.encode(); - let decoded = Block::decode(&mut &raw[..]).unwrap(); - - assert_eq!(block, decoded); - - block.body.transactions.push(UncheckedTransaction { - transaction: ::transaction::Transaction { - function: Function::StakingStake, - signed: Default::default(), - nonce: 10101, - }, - signature: Default::default(), - }); - - let raw = block.encode(); - let decoded = Block::decode(&mut &raw[..]).unwrap(); - - assert_eq!(block, decoded); - } - - #[test] - fn block_encoding_substrate_round_trip() { - let mut block = Block { - header: Header::from_block_number(1), - body: Body { - timestamp: 100_000_000, - transactions: Vec::new(), - } - }; - - block.body.transactions.push(UncheckedTransaction { - transaction: ::transaction::Transaction { - function: Function::StakingStake, - signed: Default::default(), - nonce: 10101, - }, - signature: Default::default(), - }); - - let raw = block.encode(); - let decoded_substrate = ::primitives::block::Block::decode(&mut &raw[..]).unwrap(); - let encoded_substrate = decoded_substrate.encode(); - let decoded = Block::decode(&mut &encoded_substrate[..]).unwrap(); - - assert_eq!(block, decoded); - } - - #[test] - fn decode_body_without_inherents_fails() { - let substrate_blank = ::primitives::block::Block { - header: ::primitives::block::Header::from_block_number(1), - transactions: Vec::new(), - }; - - let encoded_substrate = substrate_blank.encode(); - assert!(Block::decode(&mut &encoded_substrate[..]).is_none()); - } - - #[test] - fn inherent_transactions_iter_contains_all_inherent() { - let block = Block { - header: Header::from_block_number(1), - body: Body { - timestamp: 10101, - transactions: Vec::new(), - } - }; - - let mut iter = block.inherent_transactions(); - - assert_eq!(InherentFunction::count(), 1); // following depends on this assertion. - assert_eq!(iter.next().unwrap(), UncheckedTransaction::inherent(InherentFunction::TimestampSet(10101))); - assert!(iter.next().is_none()); - } -} diff --git a/polkadot/primitives/src/lib.rs b/polkadot/primitives/src/lib.rs index fb02e3d121117..012cf57b3d21a 100644 --- a/polkadot/primitives/src/lib.rs +++ b/polkadot/primitives/src/lib.rs @@ -21,7 +21,6 @@ #![cfg_attr(not(feature = "std"), no_std)] #![cfg_attr(not(feature = "std"), feature(alloc))] - #[cfg(feature = "std")] #[macro_use] extern crate serde_derive; @@ -30,34 +29,29 @@ extern crate serde; extern crate substrate_runtime_std as rstd; extern crate substrate_primitives as primitives; +extern crate substrate_runtime_primitives as runtime_primitives; #[cfg(test)] extern crate substrate_serializer; extern crate substrate_codec as codec; -macro_rules! try_opt { - ($e: expr) => { - match $e { - Some(x) => x, - None => return None, - } - } -} - pub mod parachain; pub mod validator; -pub mod block; -pub mod transaction; - -pub use self::block::{Header, Body, Block, Log, Digest}; -pub use self::block::Number as BlockNumber; -pub use self::transaction::{Transaction, UncheckedTransaction, Function, InherentFunction, Proposal}; /// Virtual account ID that represents the idea of a dispatch/statement being signed by everybody /// (who matters). Essentially this means that a majority of validators have decided it is /// "correct". pub const EVERYBODY: AccountId = [255u8; 32]; +/// Something that identifies a block. +pub use primitives::block::Id as BlockId; + +/// The type of digest item. +pub use primitives::block::Log as Log; + +/// An index to a block. +pub type BlockNumber = u64; + /// Alias to Ed25519 pubkey that identifies an account on the relay chain. This will almost /// certainly continue to be the same as the substrate's `AuthorityId`. pub type AccountId = primitives::AuthorityId; @@ -67,22 +61,19 @@ pub type AccountId = primitives::AuthorityId; pub type SessionKey = primitives::AuthorityId; /// Indentifier for a chain. -pub type ChainID = u64; +pub type ChainId = u64; /// Index of a transaction in the relay chain. -pub type TxOrder = u64; +pub type Index = u64; /// A hash of some data used by the relay chain. pub type Hash = primitives::H256; /// Alias to 512-bit hash when used in the context of a signature on the relay chain. -pub type Signature = primitives::hash::H512; +pub type Signature = runtime_primitives::Ed25519Signature; /// A timestamp: seconds since the unix epoch. pub type Timestamp = u64; /// The balance of an account. pub type Balance = u64; - -/// The amount of bonding period left in an account. Measured in eras. -pub type Bondage = u64; diff --git a/polkadot/primitives/src/parachain.rs b/polkadot/primitives/src/parachain.rs index e94ba03d28590..1dde3b508d1c3 100644 --- a/polkadot/primitives/src/parachain.rs +++ b/polkadot/primitives/src/parachain.rs @@ -26,7 +26,7 @@ use ::Hash; /// Unique identifier of a parachain. #[derive(PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Copy)] -#[cfg_attr(feature = "std", derive(Serialize, Deserialize, Debug))] +#[cfg_attr(feature = "std", derive(Serialize, Debug))] pub struct Id(u32); impl From for u32 { @@ -63,7 +63,7 @@ impl Slicable for Chain { match disc { 0 => Some(Chain::Relay), - 1 => Some(Chain::Parachain(try_opt!(Slicable::decode(input)))), + 1 => Some(Chain::Parachain(Slicable::decode(input)?)), _ => None, } } @@ -102,8 +102,8 @@ pub struct DutyRoster { impl Slicable for DutyRoster { fn decode(input: &mut I) -> Option { Some(DutyRoster { - validator_duty: try_opt!(Slicable::decode(input)), - guarantor_duty: try_opt!(Slicable::decode(input)), + validator_duty: Slicable::decode(input)?, + guarantor_duty: Slicable::decode(input)?, }) } @@ -123,7 +123,7 @@ impl Slicable for DutyRoster { /// Extrinsic data for a parachain. #[derive(PartialEq, Eq, Clone)] -#[cfg_attr(feature = "std", derive(Serialize, Deserialize, Debug))] +#[cfg_attr(feature = "std", derive(Serialize, Debug))] #[cfg_attr(feature = "std", serde(rename_all = "camelCase"))] #[cfg_attr(feature = "std", serde(deny_unknown_fields))] pub struct Extrinsic; @@ -132,7 +132,7 @@ pub struct Extrinsic; /// /// https://github.com/w3f/polkadot-spec/blob/master/spec.md#candidate-para-chain-block #[derive(PartialEq, Eq, Clone)] -#[cfg_attr(feature = "std", derive(Serialize, Deserialize, Debug))] +#[cfg_attr(feature = "std", derive(Serialize, Debug))] #[cfg_attr(feature = "std", serde(rename_all = "camelCase"))] #[cfg_attr(feature = "std", serde(deny_unknown_fields))] pub struct Candidate { @@ -150,7 +150,7 @@ pub struct Candidate { /// Candidate receipt type. #[derive(PartialEq, Eq, Clone)] -#[cfg_attr(feature = "std", derive(Debug, Serialize, Deserialize))] +#[cfg_attr(feature = "std", derive(Debug, Serialize))] #[cfg_attr(feature = "std", serde(rename_all = "camelCase"))] #[cfg_attr(feature = "std", serde(deny_unknown_fields))] pub struct CandidateReceipt { @@ -184,12 +184,12 @@ impl Slicable for CandidateReceipt { fn decode(input: &mut I) -> Option { Some(CandidateReceipt { - parachain_index: try_opt!(Slicable::decode(input)), - collator: try_opt!(Slicable::decode(input)), - head_data: try_opt!(Slicable::decode(input).map(HeadData)), - balance_uploads: try_opt!(Slicable::decode(input)), - egress_queue_roots: try_opt!(Slicable::decode(input)), - fees: try_opt!(Slicable::decode(input)), + parachain_index: Slicable::decode(input)?, + collator: Slicable::decode(input)?, + head_data: Slicable::decode(input).map(HeadData)?, + balance_uploads: Slicable::decode(input)?, + egress_queue_roots: Slicable::decode(input)?, + fees: Slicable::decode(input)?, }) } } @@ -219,7 +219,7 @@ impl Ord for CandidateReceipt { /// Parachain ingress queue message. #[derive(PartialEq, Eq, Clone)] -#[cfg_attr(feature = "std", derive(Serialize, Deserialize, Debug))] +#[cfg_attr(feature = "std", derive(Serialize, Debug))] pub struct Message(#[cfg_attr(feature = "std", serde(with="bytes"))] pub Vec); /// Consolidated ingress queue data. @@ -227,34 +227,34 @@ pub struct Message(#[cfg_attr(feature = "std", serde(with="bytes"))] pub Vec /// This is just an ordered vector of other parachains' egress queues, /// obtained according to the routing rules. #[derive(Default, PartialEq, Eq, Clone)] -#[cfg_attr(feature = "std", derive(Serialize, Deserialize, Debug))] +#[cfg_attr(feature = "std", derive(Serialize, Debug))] pub struct ConsolidatedIngress(pub Vec<(Id, Vec)>); /// Parachain block data. /// /// contains everything required to validate para-block, may contain block and witness data #[derive(PartialEq, Eq, Clone)] -#[cfg_attr(feature = "std", derive(Serialize, Deserialize, Debug))] +#[cfg_attr(feature = "std", derive(Serialize, Debug))] pub struct BlockData(#[cfg_attr(feature = "std", serde(with="bytes"))] pub Vec); /// Parachain header raw bytes wrapper type. #[derive(PartialEq, Eq)] -#[cfg_attr(feature = "std", derive(Serialize, Deserialize, Debug))] +#[cfg_attr(feature = "std", derive(Serialize, Debug))] pub struct Header(#[cfg_attr(feature = "std", serde(with="bytes"))] pub Vec); /// Parachain head data included in the chain. #[derive(PartialEq, Eq, Clone, PartialOrd, Ord)] -#[cfg_attr(feature = "std", derive(Serialize, Deserialize, Debug))] +#[cfg_attr(feature = "std", derive(Serialize, Debug))] pub struct HeadData(#[cfg_attr(feature = "std", serde(with="bytes"))] pub Vec); /// Parachain validation code. #[derive(PartialEq, Eq)] -#[cfg_attr(feature = "std", derive(Serialize, Deserialize, Debug))] +#[cfg_attr(feature = "std", derive(Serialize, Debug))] pub struct ValidationCode(#[cfg_attr(feature = "std", serde(with="bytes"))] pub Vec); /// Activitiy bit field #[derive(PartialEq, Eq, Clone, Default)] -#[cfg_attr(feature = "std", derive(Serialize, Deserialize, Debug))] +#[cfg_attr(feature = "std", derive(Serialize, Debug))] pub struct Activity(#[cfg_attr(feature = "std", serde(with="bytes"))] pub Vec); impl Slicable for Activity { @@ -344,7 +344,7 @@ mod tests { fn test_candidate() { assert_eq!(ser::to_string_pretty(&Candidate { parachain_index: 5.into(), - collator_signature: 10.into(), + collator_signature: primitives::hash::H512::from(10).into(), unprocessed_ingress: ConsolidatedIngress(vec![ (Id(1), vec![Message(vec![2])]), (Id(2), vec![Message(vec![2]), Message(vec![3])]), diff --git a/polkadot/primitives/src/transaction.rs b/polkadot/primitives/src/transaction.rs deleted file mode 100644 index f3637034b403d..0000000000000 --- a/polkadot/primitives/src/transaction.rs +++ /dev/null @@ -1,487 +0,0 @@ -// Copyright 2017 Parity Technologies (UK) Ltd. -// This file is part of Polkadot. - -// Polkadot 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. - -// Polkadot 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 Polkadot. If not, see . - -//! Transaction type. - -use rstd::vec::Vec; -use codec::{Input, Slicable}; -use primitives::bft::MisbehaviorReport; -use ::Signature; - -#[cfg(feature = "std")] -use std::fmt; - -use block::Number as BlockNumber; - -#[derive(Clone, Copy, PartialEq, Eq)] -#[cfg_attr(feature = "std", derive(Serialize, Deserialize, Debug))] -#[repr(u8)] -enum InternalFunctionId { - /// Set the system's code. - SystemSetCode = 0x00, - - /// Set the session length. - SessionSetLength = 0x10, - /// Force a new session. - SessionForceNewSession = 0x11, - - /// Set the number of sessions per era. - StakingSetSessionsPerEra = 0x20, - /// Set the minimum bonding duration for staking. - StakingSetBondingDuration = 0x21, - /// Set the validator count for staking. - StakingSetValidatorCount = 0x22, - /// Force a new staking era. - StakingForceNewEra = 0x23, - - /// Set the per-mille of validator approval required for governance changes. - GovernanceSetApprovalPpmRequired = 0x30, - -} - -impl InternalFunctionId { - /// Derive `Some` value from a `u8`, or `None` if it's invalid. - fn from_u8(value: u8) -> Option { - let functions = [ - InternalFunctionId::SystemSetCode, - InternalFunctionId::SessionSetLength, - InternalFunctionId::SessionForceNewSession, - InternalFunctionId::StakingSetSessionsPerEra, - InternalFunctionId::StakingSetBondingDuration, - InternalFunctionId::StakingSetValidatorCount, - InternalFunctionId::StakingForceNewEra, - InternalFunctionId::GovernanceSetApprovalPpmRequired, - ]; - functions.iter().map(|&f| f).find(|&f| value == f as u8) - } -} - -/// Internal functions that can be dispatched to. -#[derive(Clone, PartialEq, Eq)] -#[cfg_attr(feature = "std", derive(Serialize, Deserialize, Debug))] -pub enum Proposal { - /// Set the system's code. - SystemSetCode(Vec), - /// Set the session length. - SessionSetLength(BlockNumber), - /// Force a new session. - SessionForceNewSession, - /// Set the number of sessions per era. - StakingSetSessionsPerEra(BlockNumber), - /// Set the minimum bonding duration for staking. - StakingSetBondingDuration(BlockNumber), - /// Set the validator count for staking. - StakingSetValidatorCount(u32), - /// Force a new staking era. - StakingForceNewEra, - /// Set the per-mille of validator approval required for governance changes. - GovernanceSetApprovalPpmRequired(u32), - -} - -impl Slicable for Proposal { - fn decode(input: &mut I) -> Option { - let id = InternalFunctionId::from_u8(input.read_byte()?)?; - let function = match id { - InternalFunctionId::SystemSetCode => - Proposal::SystemSetCode(try_opt!(Slicable::decode(input))), - InternalFunctionId::SessionSetLength => - Proposal::SessionSetLength(try_opt!(Slicable::decode(input))), - InternalFunctionId::SessionForceNewSession => Proposal::SessionForceNewSession, - InternalFunctionId::StakingSetSessionsPerEra => - Proposal::StakingSetSessionsPerEra(try_opt!(Slicable::decode(input))), - InternalFunctionId::StakingSetBondingDuration => - Proposal::StakingSetBondingDuration(try_opt!(Slicable::decode(input))), - InternalFunctionId::StakingSetValidatorCount => - Proposal::StakingSetValidatorCount(try_opt!(Slicable::decode(input))), - InternalFunctionId::StakingForceNewEra => Proposal::StakingForceNewEra, - InternalFunctionId::GovernanceSetApprovalPpmRequired => - Proposal::GovernanceSetApprovalPpmRequired(try_opt!(Slicable::decode(input))), - }; - - Some(function) - } - - fn encode(&self) -> Vec { - let mut v = Vec::new(); - match *self { - Proposal::SystemSetCode(ref data) => { - v.push(InternalFunctionId::SystemSetCode as u8); - data.using_encoded(|s| v.extend(s)); - } - Proposal::SessionSetLength(ref data) => { - v.push(InternalFunctionId::SessionSetLength as u8); - data.using_encoded(|s| v.extend(s)); - } - Proposal::SessionForceNewSession => { - v.push(InternalFunctionId::SessionForceNewSession as u8); - } - Proposal::StakingSetSessionsPerEra(ref data) => { - v.push(InternalFunctionId::StakingSetSessionsPerEra as u8); - data.using_encoded(|s| v.extend(s)); - } - Proposal::StakingSetBondingDuration(ref data) => { - v.push(InternalFunctionId::StakingSetBondingDuration as u8); - data.using_encoded(|s| v.extend(s)); - } - Proposal::StakingSetValidatorCount(ref data) => { - v.push(InternalFunctionId::StakingSetValidatorCount as u8); - data.using_encoded(|s| v.extend(s)); - } - Proposal::StakingForceNewEra => { - v.push(InternalFunctionId::StakingForceNewEra as u8); - } - Proposal::GovernanceSetApprovalPpmRequired(ref data) => { - v.push(InternalFunctionId::GovernanceSetApprovalPpmRequired as u8); - data.using_encoded(|s| v.extend(s)); - } - } - - v - } -} - -/// Public functions that can be dispatched to. -#[derive(Clone, Copy, PartialEq, Eq)] -#[cfg_attr(feature = "std", derive(Serialize, Deserialize, Debug))] -#[repr(u8)] -enum FunctionId { - /// Set the timestamp. - TimestampSet = 0x00, - /// Set temporary session key as a validator. - SessionSetKey = 0x10, - /// Staking subsystem: begin staking. - StakingStake = 0x20, - /// Staking subsystem: stop staking. - StakingUnstake = 0x21, - /// Staking subsystem: transfer stake. - StakingTransfer = 0x22, - /// Report misbehavior. - StakingReportMisbehavior = 0x23, - /// Make a proposal for the governance system. - GovernancePropose = 0x30, - /// Approve a proposal for the governance system. - GovernanceApprove = 0x31, -} - -impl FunctionId { - /// Derive `Some` value from a `u8`, or `None` if it's invalid. - fn from_u8(value: u8) -> Option { - use self::*; - let functions = [ - FunctionId::StakingStake, - FunctionId::StakingUnstake, - FunctionId::StakingTransfer, - FunctionId::StakingReportMisbehavior, - FunctionId::SessionSetKey, - FunctionId::TimestampSet, - FunctionId::GovernancePropose, - FunctionId::GovernanceApprove, - ]; - functions.iter().map(|&f| f).find(|&f| value == f as u8) - } -} - -/// Inherent functions on the runtime. -/// These must be called each block by the `EVERYBODY` account. -#[derive(Clone, PartialEq, Eq)] -#[cfg_attr(feature = "std", derive(Serialize, Deserialize, Debug))] -pub enum InherentFunction { - /// Set the timestamp. - TimestampSet(u64), -} - -impl InherentFunction { - /// Get the number of inherent functions. - pub fn count() -> u64 { - 1 - } - - /// Get the index. - pub fn index(&self) -> u64 { - match *self { - InherentFunction::TimestampSet(_) => 0, - } - } -} - -/// Functions on the runtime. -#[derive(Clone, PartialEq, Eq)] -#[cfg_attr(feature = "std", derive(Serialize, Deserialize, Debug))] -pub enum Function { - /// An inherent function. - Inherent(InherentFunction), - /// Set temporary session key as a validator. - SessionSetKey(::SessionKey), - /// Staking subsystem: begin staking. - StakingStake, - /// Staking subsystem: stop staking. - StakingUnstake, - /// Staking subsystem: transfer stake. - StakingTransfer(::AccountId, u64), - /// Staking subsystem: report misbehavior of a validator. - ReportMisbehavior(MisbehaviorReport), - /// Make a proposal for the governance system. - GovernancePropose(Proposal), - /// Approve a proposal for the governance system. - GovernanceApprove(BlockNumber), -} - -impl Function { - /// The number of inherent functions. - pub fn inherent_functions() -> u64 { InherentFunction::count() } - - /// Whether this function is "inherent": that it must be part of every - /// block at the given index and no other. - /// - /// Transactions containing inherent functions should not be signed. - pub fn is_inherent(&self) -> bool { - match *self { - Function::Inherent(_) => true, - _ => false, - } - } - - /// If this function is inherent, returns the index it should occupy - /// in the block. Otherwise returns `None`. - pub fn inherent_index(&self) -> Option { - match *self { - Function::Inherent(ref inner) => Some(inner.index()), - _ => None, - } - } -} - -impl Slicable for Function { - fn decode(input: &mut I) -> Option { - let id = FunctionId::from_u8(input.read_byte()?)?; - Some(match id { - FunctionId::TimestampSet => - Function::Inherent(InherentFunction::TimestampSet(try_opt!(Slicable::decode(input)))), - FunctionId::SessionSetKey => - Function::SessionSetKey(try_opt!(Slicable::decode(input))), - FunctionId::StakingStake => Function::StakingStake, - FunctionId::StakingUnstake => Function::StakingUnstake, - FunctionId::StakingTransfer => { - let to = try_opt!(Slicable::decode(input)); - let amount = try_opt!(Slicable::decode(input)); - - Function::StakingTransfer(to, amount) - } - FunctionId::StakingReportMisbehavior => Function::ReportMisbehavior(MisbehaviorReport::decode(input)?), - FunctionId::GovernancePropose => - Function::GovernancePropose(try_opt!(Slicable::decode(input))), - FunctionId::GovernanceApprove => - Function::GovernanceApprove(try_opt!(Slicable::decode(input))), - }) - } - - fn encode(&self) -> Vec { - let mut v = Vec::new(); - match *self { - Function::Inherent(InherentFunction::TimestampSet(ref data)) => { - v.push(FunctionId::TimestampSet as u8); - data.using_encoded(|s| v.extend(s)); - } - Function::SessionSetKey(ref data) => { - v.push(FunctionId::SessionSetKey as u8); - data.using_encoded(|s| v.extend(s)); - } - Function::StakingStake => { - v.push(FunctionId::StakingStake as u8); - } - Function::StakingUnstake => { - v.push(FunctionId::StakingUnstake as u8); - } - Function::ReportMisbehavior(ref report) => { - v.push(FunctionId::StakingReportMisbehavior as u8); - report.using_encoded(|s| v.extend(s)); - } - Function::StakingTransfer(ref to, ref amount) => { - v.push(FunctionId::StakingTransfer as u8); - to.using_encoded(|s| v.extend(s)); - amount.using_encoded(|s| v.extend(s)); - } - Function::GovernancePropose(ref data) => { - v.push(FunctionId::GovernancePropose as u8); - data.using_encoded(|s| v.extend(s)); - } - Function::GovernanceApprove(ref data) => { - v.push(FunctionId::GovernanceApprove as u8); - data.using_encoded(|s| v.extend(s)); - } - } - - v - } - - fn using_encoded R>(&self, f: F) -> R { - f(self.encode().as_slice()) - } -} - -/// A vetted and verified transaction from the external world. -#[derive(PartialEq, Eq, Clone)] -#[cfg_attr(feature = "std", derive(Serialize, Deserialize, Debug))] -pub struct Transaction { - /// Who signed it (note this is not a signature). - pub signed: super::AccountId, - /// The number of transactions have come before from the same signer. - pub nonce: super::TxOrder, - /// The function that should be called. - pub function: Function, -} - -impl Slicable for Transaction { - fn decode(input: &mut I) -> Option { - Some(Transaction { - signed: try_opt!(Slicable::decode(input)), - nonce: try_opt!(Slicable::decode(input)), - function: try_opt!(Slicable::decode(input)), - }) - } - - fn encode(&self) -> Vec { - let mut v = Vec::new(); - - self.signed.using_encoded(|s| v.extend(s)); - self.nonce.using_encoded(|s| v.extend(s)); - self.function.using_encoded(|s| v.extend(s)); - - v - } -} - - - -/// A transactions right from the external world. Unchecked. -#[derive(Eq, Clone)] -#[cfg_attr(feature = "std", derive(Serialize, Deserialize))] -pub struct UncheckedTransaction { - /// The actual transaction information. - pub transaction: Transaction, - /// The signature; should be an Ed25519 signature applied to the serialised `transaction` field. - pub signature: Signature, -} - -impl UncheckedTransaction { - /// Whether the transaction is well-formed. In particular checks that - /// inherent transactions have the correct signed and signature fields. - /// - /// Does not check signatures on other transactions. - pub fn is_well_formed(&self) -> bool { - if self.transaction.function.is_inherent() { - self.transaction.signed == ::EVERYBODY && self.signature == Signature::zero() - } else { - true - } - } - - /// Whether this transaction invokes an inherent function. - pub fn is_inherent(&self) -> bool { - self.transaction.function.is_inherent() - } - - /// Create a new inherent-style transaction from the given function. - pub fn inherent(function: InherentFunction) -> Self { - UncheckedTransaction { - transaction: Transaction { - function: Function::Inherent(function), - nonce: 0, - signed: ::EVERYBODY - }, - signature: Signature::zero(), - } - } -} - -impl Slicable for UncheckedTransaction { - fn decode(input: &mut I) -> Option { - // This is a little more complicated than usual since the binary format must be compatible - // with substrate's generic `Vec` type. Basically this just means accepting that there - // will be a prefix of u32, which has the total number of bytes following (we don't need - // to use this). - let _length_do_not_remove_me_see_above: u32 = try_opt!(Slicable::decode(input)); - - Some(UncheckedTransaction { - transaction: try_opt!(Slicable::decode(input)), - signature: try_opt!(Slicable::decode(input)), - }) - } - - fn encode(&self) -> Vec { - let mut v = Vec::new(); - - // need to prefix with the total length as u32 to ensure it's binary comptible with - // Vec. we'll make room for it here, then overwrite once we know the length. - v.extend(&[0u8; 4]); - - self.transaction.signed.using_encoded(|s| v.extend(s)); - self.transaction.nonce.using_encoded(|s| v.extend(s)); - self.transaction.function.using_encoded(|s| v.extend(s)); - self.signature.using_encoded(|s| v.extend(s)); - - let length = (v.len() - 4) as u32; - length.using_encoded(|s| v[0..4].copy_from_slice(s)); - - v - } -} - - - -impl PartialEq for UncheckedTransaction { - fn eq(&self, other: &Self) -> bool { - self.signature.iter().eq(other.signature.iter()) && self.transaction == other.transaction - } -} - -#[cfg(feature = "std")] -impl fmt::Debug for UncheckedTransaction { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "UncheckedTransaction({:?})", self.transaction) - } -} - -#[cfg(test)] -mod tests { - use super::*; - use primitives; - use ::codec::Slicable; - use primitives::hexdisplay::HexDisplay; - - #[test] - fn serialize_unchecked() { - let tx = UncheckedTransaction { - transaction: Transaction { - signed: [1; 32], - nonce: 999u64, - function: Function::Inherent(InherentFunction::TimestampSet(135135)), - }, - signature: primitives::hash::H512([0; 64]), - }; - // 71000000 - // 0101010101010101010101010101010101010101010101010101010101010101 - // e703000000000000 - // 00 - // df0f0200 - // 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 - - let v = Slicable::encode(&tx); - println!("{}", HexDisplay::from(&v)); - assert_eq!(UncheckedTransaction::decode(&mut &v[..]).unwrap(), tx); - } -} diff --git a/polkadot/primitives/src/validator.rs b/polkadot/primitives/src/validator.rs index fa622fb629cf0..0bac607594c6a 100644 --- a/polkadot/primitives/src/validator.rs +++ b/polkadot/primitives/src/validator.rs @@ -23,22 +23,22 @@ use parachain; /// Parachain outgoing message. #[derive(PartialEq, Eq)] -#[cfg_attr(feature = "std", derive(Serialize, Deserialize, Debug))] +#[cfg_attr(feature = "std", derive(Serialize, Debug))] pub struct EgressPost(#[cfg_attr(feature = "std", serde(with="bytes"))] pub Vec); /// Balance upload. #[derive(PartialEq, Eq)] -#[cfg_attr(feature = "std", derive(Serialize, Deserialize, Debug))] +#[cfg_attr(feature = "std", derive(Serialize, Debug))] pub struct BalanceUpload(#[cfg_attr(feature = "std", serde(with="bytes"))] pub Vec); /// Balance download. #[derive(PartialEq, Eq)] -#[cfg_attr(feature = "std", derive(Serialize, Deserialize, Debug))] +#[cfg_attr(feature = "std", derive(Serialize, Debug))] pub struct BalanceDownload(#[cfg_attr(feature = "std", serde(with="bytes"))] pub Vec); /// The result of parachain validation. #[derive(PartialEq, Eq)] -#[cfg_attr(feature = "std", derive(Serialize, Deserialize, Debug))] +#[cfg_attr(feature = "std", derive(Serialize, Debug))] #[cfg_attr(feature = "std", serde(rename_all = "camelCase"))] #[cfg_attr(feature = "std", serde(deny_unknown_fields))] pub struct ValidationResult { diff --git a/polkadot/runtime/Cargo.toml b/polkadot/runtime/Cargo.toml index ce4565025a21e..cb6c99de354c0 100644 --- a/polkadot/runtime/Cargo.toml +++ b/polkadot/runtime/Cargo.toml @@ -7,26 +7,47 @@ authors = ["Parity Technologies "] rustc-hex = "1.0" hex-literal = "0.1.0" log = { version = "0.3", optional = true } +serde = { version = "1.0", default_features = false } +serde_derive = { version = "1.0", optional = true } +safe-mix = { path = "../../safe-mix", default_features = false} substrate-codec = { path = "../../substrate/codec" } +substrate-serializer = { path = "../../substrate/serializer" } substrate-runtime-std = { path = "../../substrate/runtime-std" } substrate-runtime-io = { path = "../../substrate/runtime-io" } substrate-runtime-support = { path = "../../substrate/runtime-support" } substrate-primitives = { path = "../../substrate/primitives" } -substrate-misbehavior-check = { path = "../../substrate/misbehavior-check" } -polkadot-primitives = { path = "../primitives" } - -[dev-dependencies] substrate-keyring = { path = "../../substrate/keyring" } +substrate-runtime-consensus = { path = "../../substrate/runtime/consensus" } +substrate-runtime-council = { path = "../../substrate/runtime/council" } +substrate-runtime-democracy = { path = "../../substrate/runtime/democracy" } +substrate-runtime-executive = { path = "../../substrate/runtime/executive" } +substrate-runtime-primitives = { path = "../../substrate/runtime/primitives" } +substrate-runtime-session = { path = "../../substrate/runtime/session" } +substrate-runtime-staking = { path = "../../substrate/runtime/staking" } +substrate-runtime-system = { path = "../../substrate/runtime/system" } +substrate-runtime-timestamp = { path = "../../substrate/runtime/timestamp" } +polkadot-primitives = { path = "../primitives" } [features] default = ["std"] std = [ "substrate-codec/std", + "substrate-primitives/std", "substrate-runtime-std/std", "substrate-runtime-io/std", "substrate-runtime-support/std", - "substrate-primitives/std", - "substrate-misbehavior-check/std", + "substrate-runtime-consensus/std", + "substrate-runtime-council/std", + "substrate-runtime-democracy/std", + "substrate-runtime-executive/std", + "substrate-runtime-primitives/std", + "substrate-runtime-session/std", + "substrate-runtime-staking/std", + "substrate-runtime-system/std", + "substrate-runtime-timestamp/std", "polkadot-primitives/std", - "log" + "serde_derive", + "serde/std", + "log", + "safe-mix/std" ] diff --git a/polkadot/runtime/src/api.rs b/polkadot/runtime/src/api.rs deleted file mode 100644 index 7ce51381e9d78..0000000000000 --- a/polkadot/runtime/src/api.rs +++ /dev/null @@ -1,29 +0,0 @@ -// Copyright 2017 Parity Technologies (UK) Ltd. -// This file is part of Polkadot. - -// Polkadot 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. - -// Polkadot 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 Polkadot. If not, see . - -use runtime::{system, parachains, consensus, session}; - -impl_stubs!( - execute_block => |block| system::internal::execute_block(block), - execute_transaction => |(header, utx)| system::internal::execute_transaction(utx, header), - finalise_block => |header| system::internal::finalise_block(header), - validator_count => |()| session::validator_count(), - validators => |()| session::validators(), - authorities => |()| consensus::authorities(), - duty_roster => |()| parachains::calculate_duty_roster(), - timestamp => |()| ::runtime::timestamp::get(), - nonce => |account_id| system::nonce(account_id) -); diff --git a/polkadot/runtime/src/environment.rs b/polkadot/runtime/src/environment.rs deleted file mode 100644 index b7fef7cdd87fd..0000000000000 --- a/polkadot/runtime/src/environment.rs +++ /dev/null @@ -1,81 +0,0 @@ -// Copyright 2017 Parity Technologies (UK) Ltd. -// This file is part of Polkadot. - -// Polkadot 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. - -// Polkadot 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 Polkadot. If not, see . - -//! Environment API: Allows certain information to be accessed throughout the runtime. - -use rstd::boxed::Box; -use rstd::cell::RefCell; -use rstd::rc::Rc; - -use polkadot_primitives::{BlockNumber, Digest, Hash}; - -#[derive(Default)] -/// The information that can be accessed globally. -pub struct Environment { - /// The current block number. - pub block_number: BlockNumber, - /// The current block's parent hash. - pub parent_hash: Hash, - /// The current block digest. - pub digest: Digest, -} - -/// Do something with the environment and return its value. Keep the function short. -pub fn with_env T>(f: F) -> T { - let e = env(); - let mut eb = e.borrow_mut(); - f(&mut *eb) -} - -#[cfg(target_arch = "wasm32")] -fn env() -> Rc> { - // Initialize it to a null value - static mut SINGLETON: *const Rc> = 0 as *const Rc>; - - unsafe { - if SINGLETON == 0 as *const Rc> { - // Make it - let singleton: Rc> = Rc::new(RefCell::new(Default::default())); - - // Put it in the heap so it can outlive this call - SINGLETON = Box::into_raw(Box::new(singleton)) as *const _; - } - - // Now we give out a copy of the data that is safe to use concurrently. - (*SINGLETON).clone() - } -} - -#[cfg(not(target_arch = "wasm32"))] -fn env() -> Rc> { - // Initialize it to a null value - thread_local!{ - static SINGLETON: RefCell<*const Rc>> = RefCell::new(0 as *const Rc>); - } - - SINGLETON.with(|s| unsafe { - if *s.borrow() == 0 as *const Rc> { - // Make it - let singleton: Rc> = Rc::new(RefCell::new(Default::default())); - - // Put it in the heap so it can outlive this call - *s.borrow_mut() = Box::into_raw(Box::new(singleton)) as *const _; - } - - // Now we give out a copy of the data that is safe to use concurrently. - (**s.borrow()).clone() - }) -} diff --git a/polkadot/runtime/src/genesismap.rs b/polkadot/runtime/src/genesismap.rs deleted file mode 100644 index d2b370fe4627b..0000000000000 --- a/polkadot/runtime/src/genesismap.rs +++ /dev/null @@ -1,91 +0,0 @@ -// Copyright 2017 Parity Technologies (UK) Ltd. -// This file is part of Polkadot. - -// Polkadot 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. - -// Polkadot 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 Polkadot. If not, see . - -//! Tool for creating the genesis block. - -use codec::{KeyedVec, Joiner}; -use std::collections::HashMap; -use runtime_io::twox_128; -use runtime_support::Hashable; -use primitives::Block; -use polkadot_primitives::{Balance, BlockNumber, AccountId}; - -/// Configuration of a general Polkadot genesis block. -pub struct GenesisConfig { - pub validators: Vec, - pub authorities: Vec, - pub balances: Vec<(AccountId, Balance)>, - pub block_time: u64, - pub session_length: BlockNumber, - pub sessions_per_era: BlockNumber, - pub bonding_duration: BlockNumber, - pub approval_ratio: u32, -} - -impl GenesisConfig { - pub fn new_simple(authorities_validators: Vec, balance: Balance) -> Self { - GenesisConfig { - validators: authorities_validators.clone(), - authorities: authorities_validators.clone(), - balances: authorities_validators.iter().map(|v| (v.clone(), balance)).collect(), - block_time: 5, // 5 second block time. - session_length: 720, // that's 1 hour per session. - sessions_per_era: 24, // 24 hours per era. - bonding_duration: 90, // 90 days per bond. - approval_ratio: 667, // 66.7% approvals required for legislation. - } - } - - pub fn genesis_map(&self) -> HashMap, Vec> { - let wasm_runtime = include_bytes!("../wasm/genesis.wasm").to_vec(); - vec![ - (&b"gov:apr"[..], vec![].and(&self.approval_ratio)), - (&b"ses:len"[..], vec![].and(&self.session_length)), - (&b"ses:val:len"[..], vec![].and(&(self.validators.len() as u32))), - (&b"sta:wil:len"[..], vec![].and(&0u32)), - (&b"sta:spe"[..], vec![].and(&self.sessions_per_era)), - (&b"sta:vac"[..], vec![].and(&(self.validators.len() as u32))), - (&b"sta:era"[..], vec![].and(&0u64)), - ].into_iter() - .map(|(k, v)| (k.into(), v)) - .chain(self.validators.iter() - .enumerate() - .map(|(i, account)| ((i as u32).to_keyed_vec(b"ses:val:"), vec![].and(account))) - ).chain(self.authorities.iter() - .enumerate() - .map(|(i, account)| ((i as u32).to_keyed_vec(b":auth:"), vec![].and(account))) - ).chain(self.balances.iter() - .map(|&(account, balance)| (account.to_keyed_vec(b"sta:bal:"), vec![].and(&balance))) - ) - .map(|(k, v)| (twox_128(&k[..])[..].to_vec(), v.to_vec())) - .chain(vec![ - (b":code"[..].into(), wasm_runtime), - (b":auth:len"[..].into(), vec![].and(&(self.authorities.len() as u32))), - ].into_iter()) - .chain(self.authorities.iter() - .enumerate() - .map(|(i, account)| ((i as u32).to_keyed_vec(b":auth:"), vec![].and(account))) - ) - .collect() - } -} - -pub fn additional_storage_with_genesis(genesis_block: &Block) -> HashMap, Vec> { - use codec::Slicable; - map![ - twox_128(&0u64.to_keyed_vec(b"sys:old:")).to_vec() => genesis_block.header.blake2_256().encode() - ] -} diff --git a/polkadot/runtime/src/lib.rs b/polkadot/runtime/src/lib.rs index caf8cb47c1e3b..11c21ac079b80 100644 --- a/polkadot/runtime/src/lib.rs +++ b/polkadot/runtime/src/lib.rs @@ -14,84 +14,288 @@ // You should have received a copy of the GNU General Public License // along with Polkadot. If not, see . -//! The Polkadot runtime. This can be compiled with #[no_std], ready for Wasm. +//! The Polkadot runtime. This can be compiled with ``#[no_std]`, ready for Wasm. #![cfg_attr(not(feature = "std"), no_std)] -extern crate substrate_runtime_std as rstd; +#[macro_use] +extern crate substrate_runtime_io as runtime_io; + +#[macro_use] extern crate substrate_runtime_support as runtime_support; + +#[macro_use] +extern crate substrate_runtime_primitives as runtime_primitives; + +#[cfg(test)] +extern crate substrate_serializer; + +#[cfg_attr(feature = "std", macro_use)] +extern crate substrate_primitives; + +extern crate substrate_runtime_std as rstd; extern crate substrate_codec as codec; -extern crate substrate_misbehavior_check as misbehavior_check; +extern crate substrate_runtime_consensus as consensus; +extern crate substrate_runtime_council as council; +extern crate substrate_runtime_democracy as democracy; +extern crate substrate_runtime_executive as executive; +extern crate substrate_runtime_session as session; +extern crate substrate_runtime_staking as staking; +extern crate substrate_runtime_system as system; +extern crate substrate_runtime_timestamp as timestamp; extern crate polkadot_primitives; -#[cfg(all(feature = "std", test))] -extern crate substrate_keyring as keyring; +mod parachains; -#[cfg(feature = "std")] -extern crate rustc_hex; +use runtime_io::BlakeTwo256; +use polkadot_primitives::{AccountId, Balance, BlockNumber, Hash, Index, Log, SessionKey, Signature}; +use runtime_primitives::generic; +use runtime_primitives::traits::{Identity, HasPublicAux}; +#[cfg(feature = "std")] pub use runtime_primitives::BuildExternalities; -#[cfg_attr(any(test, feature = "std"), macro_use)] -extern crate substrate_primitives as primitives; +/// Concrete runtime type used to parameterize the various modules. +pub struct Concrete; -#[macro_use] -extern crate substrate_runtime_io as runtime_io; +impl HasPublicAux for Concrete { + type PublicAux = AccountId; // TODO: Option +} + +impl system::Trait for Concrete { + type Index = Index; + type BlockNumber = BlockNumber; + type Hash = Hash; + type Hashing = BlakeTwo256; + type Digest = generic::Digest; + type AccountId = AccountId; + type Header = generic::Header; +} +/// System module for this concrete runtime. +pub type System = system::Module; + +impl consensus::Trait for Concrete { + type PublicAux = ::PublicAux; + type SessionKey = SessionKey; +} +/// Consensus module for this concrete runtime. +pub type Consensus = consensus::Module; +pub use consensus::Call as ConsensusCall; + +impl timestamp::Trait for Concrete { + type Value = u64; +} +/// Timestamp module for this concrete runtime. +pub type Timestamp = timestamp::Module; +pub use timestamp::Call as TimestampCall; + +impl session::Trait for Concrete { + type ConvertAccountIdToSessionKey = Identity; +} +/// Session module for this concrete runtime. +pub type Session = session::Module; + +impl staking::Trait for Concrete { + type Balance = Balance; + type DetermineContractAddress = BlakeTwo256; +} +/// Staking module for this concrete runtime. +pub type Staking = staking::Module; + +impl democracy::Trait for Concrete { + type Proposal = PrivCall; +} +/// Democracy module for this concrete runtime. +pub type Democracy = democracy::Module; + +impl council::Trait for Concrete {} +/// Council module for this concrete runtime. +pub type Council = council::Module; +/// Council voting module for this concrete runtime. +pub type CouncilVoting = council::voting::Module; + +impl parachains::Trait for Concrete {} +pub type Parachains = parachains::Module; + +impl_outer_dispatch! { + pub enum Call where aux: ::PublicAux { + Consensus = 0, + Session = 1, + Staking = 2, + Timestamp = 3, + Democracy = 5, + Council = 6, + CouncilVoting = 7, + } + + pub enum PrivCall { + Consensus = 0, + Session = 1, + Staking = 2, + Democracy = 5, + Council = 6, + CouncilVoting = 7, + } +} + +/// Block header type as expected by this runtime. +pub type Header = generic::Header; +/// Block type as expected by this runtime. +pub type Block = generic::Block; +/// Unchecked extrinsic type as expected by this runtime. +pub type UncheckedExtrinsic = generic::UncheckedExtrinsic; +/// Extrinsic type as expected by this runtime. +pub type Extrinsic = generic::Extrinsic; +/// Executive: handles dispatch to the various modules. +pub type Executive = executive::Executive; + +impl_outer_config! { + pub struct GenesisConfig for Concrete { + ConsensusConfig => consensus, + SystemConfig => system, + SessionConfig => session, + StakingConfig => staking, + DemocracyConfig => democracy, + CouncilConfig => council, + ParachainsConfig => parachains, + } +} + +pub mod api { + impl_stubs!( + authorities => |()| super::Consensus::authorities(), + initialise_block => |header| super::Executive::initialise_block(&header), + apply_extrinsic => |extrinsic| super::Executive::apply_extrinsic(extrinsic), + execute_block => |block| super::Executive::execute_block(block), + finalise_block => |()| super::Executive::finalise_block(), + validator_count => |()| super::Session::validator_count(), + validators => |()| super::Session::validators() + ); +} #[cfg(test)] -#[macro_use] -extern crate hex_literal; - -pub mod api; -pub mod environment; -pub mod runtime; - -#[cfg(feature = "std")] -pub mod genesismap; - -/// Type definitions and helpers for transactions. -pub mod transaction { - use rstd::ops; - use polkadot_primitives::Signature; - pub use polkadot_primitives::{Transaction, Function, UncheckedTransaction}; - - /// A type-safe indicator that a transaction has been checked. - #[derive(PartialEq, Eq, Clone)] - #[cfg_attr(feature = "std", derive(Debug))] - pub struct CheckedTransaction(UncheckedTransaction); - - impl CheckedTransaction { - /// Get a reference to the checked signature. - pub fn signature(&self) -> &Signature { - &self.0.signature - } +mod tests { + use super::*; + use substrate_primitives as primitives; + use ::codec::Slicable; + use substrate_primitives::hexdisplay::HexDisplay; + use substrate_serializer as ser; + use runtime_primitives::traits::{Digest as DigestT, Header as HeaderT}; + type Digest = generic::Digest; + + #[test] + fn test_header_serialization() { + let header = Header { + parent_hash: 5.into(), + number: 67, + state_root: 3.into(), + extrinsics_root: 6.into(), + digest: { let mut d = Digest::default(); d.push(Log(vec![1])); d }, + }; + + assert_eq!(ser::to_string_pretty(&header), r#"{ + "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000005", + "number": 67, + "stateRoot": "0x0000000000000000000000000000000000000000000000000000000000000003", + "extrinsicsRoot": "0x0000000000000000000000000000000000000000000000000000000000000006", + "digest": { + "logs": [ + "0x01" + ] + } +}"#); + + let v = header.encode(); + assert_eq!(Header::decode(&mut &v[..]).unwrap(), header); } - impl ops::Deref for CheckedTransaction { - type Target = Transaction; + #[test] + fn block_encoding_round_trip() { + let mut block = Block { + header: Header::new(1, Default::default(), Default::default(), Default::default(), Default::default()), + extrinsics: vec![ + UncheckedExtrinsic { + extrinsic: Extrinsic { + function: Call::Timestamp(timestamp::Call::set(100_000_000)), + signed: Default::default(), + index: Default::default(), + }, + signature: Default::default(), + } + ], + }; + + let raw = block.encode(); + let decoded = Block::decode(&mut &raw[..]).unwrap(); + + assert_eq!(block, decoded); + + block.extrinsics.push(UncheckedExtrinsic { + extrinsic: Extrinsic { + function: Call::Staking(staking::Call::stake()), + signed: Default::default(), + index: 10101, + }, + signature: Default::default(), + }); + + let raw = block.encode(); + let decoded = Block::decode(&mut &raw[..]).unwrap(); - fn deref(&self) -> &Transaction { - &self.0.transaction - } + assert_eq!(block, decoded); } - /// Check the validity of a transaction: whether it can appear at the given index - /// and whether it is correctly authenticated. - pub fn check(tx: UncheckedTransaction, index: u64) -> Result { - match tx.transaction.function.inherent_index() { - Some(correct_index) => { - if index != correct_index || !tx.is_well_formed() { return Err(tx) } - return Ok(CheckedTransaction(tx)); - } - None => { - // non-inherent functions must appear after inherent. - if index < Function::inherent_functions() { return Err(tx) } - } - } - - let msg = ::codec::Slicable::encode(&tx.transaction); - if ::runtime_io::ed25519_verify(&tx.signature.0, &msg, &tx.transaction.signed) { - Ok(CheckedTransaction(tx)) - } else { - Err(tx) - } + #[test] + fn block_encoding_substrate_round_trip() { + let mut block = Block { + header: Header::new(1, Default::default(), Default::default(), Default::default(), Default::default()), + extrinsics: vec![ + UncheckedExtrinsic { + extrinsic: Extrinsic { + function: Call::Timestamp(timestamp::Call::set(100_000_000)), + signed: Default::default(), + index: Default::default(), + }, + signature: Default::default(), + } + ], + }; + + block.extrinsics.push(UncheckedExtrinsic { + extrinsic: Extrinsic { + function: Call::Staking(staking::Call::stake()), + signed: Default::default(), + index: 10101, + }, + signature: Default::default(), + }); + + let raw = block.encode(); + let decoded_substrate = primitives::block::Block::decode(&mut &raw[..]).unwrap(); + let encoded_substrate = decoded_substrate.encode(); + let decoded = Block::decode(&mut &encoded_substrate[..]).unwrap(); + + assert_eq!(block, decoded); + } + + #[test] + fn serialize_unchecked() { + let tx = UncheckedExtrinsic { + extrinsic: Extrinsic { + signed: [1; 32], + index: 999u64, + function: Call::Timestamp(TimestampCall::set(135135)), + }, + signature: primitives::hash::H512([0; 64]).into(), + }; + // 71000000 + // 0101010101010101010101010101010101010101010101010101010101010101 + // e703000000000000 + // 00 + // df0f0200 + // 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 + + let v = Slicable::encode(&tx); + println!("{}", HexDisplay::from(&v)); + assert_eq!(UncheckedExtrinsic::decode(&mut &v[..]).unwrap(), tx); } } diff --git a/polkadot/runtime/src/parachains.rs b/polkadot/runtime/src/parachains.rs new file mode 100644 index 0000000000000..18137427a3e85 --- /dev/null +++ b/polkadot/runtime/src/parachains.rs @@ -0,0 +1,210 @@ +// Copyright 2017 Parity Technologies (UK) Ltd. +// This file is part of Polkadot. + +// Polkadot 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. + +// Polkadot 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 Polkadot. If not, see . + +//! Main parachains logic. For now this is just the determination of which validators do what. + +use polkadot_primitives; +#[cfg(any(feature = "std", test))] use {runtime_io, runtime_primitives}; +use rstd::prelude::*; +#[cfg(any(feature = "std", test))] use rstd::marker::PhantomData; +use codec::{Slicable, Joiner}; +use runtime_support::Hashable; +#[cfg(any(feature = "std", test))] use runtime_support::StorageValue; +use runtime_primitives::traits::Executable; +use polkadot_primitives::parachain::{Id, Chain, DutyRoster}; +use {system, session}; + +pub trait Trait: system::Trait + session::Trait {} + +decl_module! { + pub struct Module; +} + +decl_storage! { + pub trait Store for Module; + // The number of parachains registered at present. + pub Count get(count): b"para:count" => default u32; +} + +impl Module { + /// Calculate the current block's duty roster. + pub fn calculate_duty_roster() -> DutyRoster { + let parachain_count = Self::count(); + let validator_count = >::validator_count(); + let validators_per_parachain = (validator_count - 1) / parachain_count; + + let mut roles_val = (0..validator_count).map(|i| match i { + i if i < parachain_count * validators_per_parachain => + Chain::Parachain(Id::from(i / validators_per_parachain as u32)), + _ => Chain::Relay, + }).collect::>(); + let mut roles_gua = roles_val.clone(); + + let h = >::random_seed(); + let mut seed = h.to_vec().and(b"validator_role_pairs").blake2_256(); + + // shuffle + for i in 0..(validator_count - 1) { + // 8 bytes of entropy used per cycle, 32 bytes entropy per hash + let offset = (i * 8 % 32) as usize; + + // number of roles remaining to select from. + let remaining = (validator_count - i) as usize; + + // 4 * 2 32-bit ints per 256-bit seed. + let val_index = u32::decode(&mut &seed[offset..offset + 4]).expect("using 4 bytes for a 32-bit quantity") as usize % remaining; + let gua_index = u32::decode(&mut &seed[offset + 4..offset + 8]).expect("using 4 bytes for a 32-bit quantity") as usize % remaining; + + if offset == 24 { + // into the last 8 bytes - rehash to gather new entropy + seed = seed.blake2_256(); + } + + // exchange last item with randomly chosen first. + roles_val.swap(remaining - 1, val_index); + roles_gua.swap(remaining - 1, gua_index); + } + + DutyRoster { + validator_duty: roles_val, + guarantor_duty: roles_gua, + } + } +} + +impl Executable for Module { + fn execute() { + } +} + +#[cfg(any(feature = "std", test))] +pub struct GenesisConfig { + pub count: u32, + pub phantom: PhantomData, +} + +#[cfg(any(feature = "std", test))] +impl Default for GenesisConfig { + fn default() -> Self { + GenesisConfig { + count: 0, + phantom: PhantomData, + } + } +} + +#[cfg(any(feature = "std", test))] +impl runtime_primitives::BuildExternalities for GenesisConfig +{ + fn build_externalities(self) -> runtime_io::TestExternalities { + use runtime_io::twox_128; + use codec::Slicable; + map![ + twox_128(>::key()).to_vec() => self.count.encode() + ] + } +} + +#[cfg(test)] +mod tests { + use super::*; + use runtime_io::with_externalities; + use substrate_primitives::H256; + use runtime_primitives::BuildExternalities; + use runtime_primitives::traits::{HasPublicAux, Identity}; + use runtime_primitives::testing::{Digest, Header}; + use consensus; + + pub struct Test; + impl HasPublicAux for Test { + type PublicAux = u64; + } + impl consensus::Trait for Test { + type PublicAux = ::PublicAux; + type SessionKey = u64; + } + impl system::Trait for Test { + type Index = u64; + type BlockNumber = u64; + type Hash = H256; + type Hashing = runtime_io::BlakeTwo256; + type Digest = Digest; + type AccountId = u64; + type Header = Header; + } + impl session::Trait for Test { + type ConvertAccountIdToSessionKey = Identity; + } + impl Trait for Test {} + + type System = system::Module; + type Parachains = Module; + + fn new_test_ext() -> runtime_io::TestExternalities { + let mut t = system::GenesisConfig::::default().build_externalities(); + t.extend(consensus::GenesisConfig::{ + code: vec![], + authorities: vec![1, 2, 3], + }.build_externalities()); + t.extend(session::GenesisConfig::{ + session_length: 1000, + validators: vec![1, 2, 3, 4, 5, 6, 7, 8], + }.build_externalities()); + t.extend(GenesisConfig::{ + count: 2, + phantom: PhantomData, + }.build_externalities()); + t + } + + #[test] + fn simple_setup_should_work() { + with_externalities(&mut new_test_ext(), || { + assert_eq!(Parachains::count(), 2); + }); + } + + #[test] + fn should_work() { + with_externalities(&mut new_test_ext(), || { + let check_roster = |duty_roster: &DutyRoster| { + assert_eq!(duty_roster.validator_duty.len(), 8); + assert_eq!(duty_roster.guarantor_duty.len(), 8); + for i in (0..2).map(Id::from) { + assert_eq!(duty_roster.validator_duty.iter().filter(|&&j| j == Chain::Parachain(i)).count(), 3); + assert_eq!(duty_roster.guarantor_duty.iter().filter(|&&j| j == Chain::Parachain(i)).count(), 3); + } + assert_eq!(duty_roster.validator_duty.iter().filter(|&&j| j == Chain::Relay).count(), 2); + assert_eq!(duty_roster.guarantor_duty.iter().filter(|&&j| j == Chain::Relay).count(), 2); + }; + + System::set_random_seed([0u8; 32].into()); + let duty_roster_0 = Parachains::calculate_duty_roster(); + check_roster(&duty_roster_0); + + System::set_random_seed([1u8; 32].into()); + let duty_roster_1 = Parachains::calculate_duty_roster(); + check_roster(&duty_roster_1); + assert!(duty_roster_0 != duty_roster_1); + + System::set_random_seed([2u8; 32].into()); + let duty_roster_2 = Parachains::calculate_duty_roster(); + check_roster(&duty_roster_2); + assert!(duty_roster_0 != duty_roster_2); + assert!(duty_roster_1 != duty_roster_2); + }); + } +} diff --git a/polkadot/runtime/src/runtime/consensus.rs b/polkadot/runtime/src/runtime/consensus.rs deleted file mode 100644 index 7841f1d47d5bc..0000000000000 --- a/polkadot/runtime/src/runtime/consensus.rs +++ /dev/null @@ -1,48 +0,0 @@ -// Copyright 2017 Parity Technologies (UK) Ltd. -// This file is part of Polkadot. - -// Polkadot 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. - -// Polkadot 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 Polkadot. If not, see . - -//! Conensus module for runtime; manages the authority set ready for the native code. - -use rstd::prelude::*; -use runtime_support::storage::unhashed::StorageVec; -use polkadot_primitives::SessionKey; - -struct AuthorityStorageVec {} -impl StorageVec for AuthorityStorageVec { - type Item = SessionKey; - const PREFIX: &'static [u8] = b":auth:"; -} - -/// Get the current set of authorities. These are the session keys. -pub fn authorities() -> Vec { - AuthorityStorageVec::items() -} - -pub mod internal { - use super::*; - - /// Set the current set of authorities' session keys. - /// - /// Called by `next_session` only. - pub fn set_authorities<'a, I: IntoIterator>(authorities: I) { - AuthorityStorageVec::set_items(authorities); - } - - /// Set a single authority by index. - pub fn set_authority(index: u32, key: &SessionKey) { - AuthorityStorageVec::set_item(index, key); - } -} diff --git a/polkadot/runtime/src/runtime/governance.rs b/polkadot/runtime/src/runtime/governance.rs deleted file mode 100644 index 80620d578f857..0000000000000 --- a/polkadot/runtime/src/runtime/governance.rs +++ /dev/null @@ -1,371 +0,0 @@ -// Copyright 2017 Parity Technologies (UK) Ltd. -// This file is part of Polkadot. - -// Polkadot 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. - -// Polkadot 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 Polkadot. If not, see . - -//! Governance system: Handles administration and dispatch of sensitive operations including -//! setting new code, minting new tokens and changing parameters. -//! -//! For now this is limited to a simple qualified majority vote (whose parameter is retrieved from -//! storage) between validators. A single vote may be proposed per era, and at most one approval -//! vote may be cast by each validator. The tally is maintained through a simple tag in storage for -//! each validator that has approved. -//! -//! At the end of the era, all validators approvals are tallied and if there are sufficient to pass -//! the proposal then it is enacted. All items in storage concerning the proposal are reset. - -use rstd::prelude::*; -use codec::KeyedVec; -use runtime_support::storage; -use polkadot_primitives::{Proposal, AccountId, Hash, BlockNumber}; -use runtime::{staking, system, session}; - -const APPROVALS_REQUIRED: &[u8] = b"gov:apr"; -const CURRENT_PROPOSAL: &[u8] = b"gov:pro"; -const APPROVAL_OF: &[u8] = b"gov:app:"; - -/// The proportion of validators required for a propsal to be approved measured as the number out -/// of 1000. -pub fn approval_ppm_required() -> u32 { - storage::get_or(APPROVALS_REQUIRED, 1000) -} - -/// The number of concrete validator approvals required for a proposal to pass. -pub fn approvals_required() -> u32 { - approval_ppm_required() * session::validator_count() / 1000 -} - -pub mod public { - use super::*; - - /// Propose a sensitive action to be taken. Any action that is enactable by `Proposal` is valid. - /// Proposal is by the `transactor` and will automatically count as an approval. Transactor must - /// be a current validator. It is illegal to propose when there is already a proposal in effect. - pub fn propose(validator: &AccountId, proposal: &Proposal) { - if storage::exists(CURRENT_PROPOSAL) { - panic!("there may only be one proposal per era."); - } - storage::put(CURRENT_PROPOSAL, proposal); - approve(validator, staking::current_era()); - } - - /// Approve the current era's proposal. Transactor must be a validator. This may not be done more - /// than once for any validator in an era. - pub fn approve(validator: &AccountId, era_index: BlockNumber) { - if era_index != staking::current_era() { - panic!("approval vote applied on non-current era.") - } - if !storage::exists(CURRENT_PROPOSAL) { - panic!("there must be a proposal in order to approve."); - } - if session::validators().into_iter().position(|v| &v == validator).is_none() { - panic!("transactor must be a validator to approve."); - } - let key = validator.to_keyed_vec(APPROVAL_OF); - if storage::exists(&key) { - panic!("transactor may not approve a proposal twice in one era."); - } - storage::put(&key, &true); - } -} - -pub mod privileged { - use super::*; - - /// Set the proportion of validators that must approve for a proposal to be enacted at the end of - /// its era. The value, `ppm`, is measured as a fraction of 1000 rounded down to the nearest whole - /// validator. `1000` would require the approval of all validators; `667` would require two-thirds - /// (or there abouts) of validators. - pub fn set_approval_ppm_required(ppm: u32) { - storage::put(APPROVALS_REQUIRED, &ppm); - } -} - -pub mod internal { - use super::*; - use polkadot_primitives::Proposal; - - /// Current era is ending; we should finish up any proposals. - pub fn end_of_an_era() { - // tally up votes for the current proposal, if any. enact if there are sufficient approvals. - if let Some(proposal) = storage::take::(CURRENT_PROPOSAL) { - let approvals_required = approvals_required(); - let approved = session::validators().into_iter() - .filter_map(|v| storage::take::(&v.to_keyed_vec(APPROVAL_OF))) - .take(approvals_required as usize) - .count() as u32; - if approved == approvals_required { - enact_proposal(proposal); - } - } - } - - fn enact_proposal(proposal: Proposal) { - match proposal { - Proposal::SystemSetCode(code) => { - system::privileged::set_code(&code); - } - Proposal::SessionSetLength(value) => { - session::privileged::set_length(value); - } - Proposal::SessionForceNewSession => { - session::privileged::force_new_session(); - } - Proposal::StakingSetSessionsPerEra(value) => { - staking::privileged::set_sessions_per_era(value); - } - Proposal::StakingSetBondingDuration(value) => { - staking::privileged::set_bonding_duration(value); - } - Proposal::StakingSetValidatorCount(value) => { - staking::privileged::set_validator_count(value); - } - Proposal::StakingForceNewEra => { - staking::privileged::force_new_era() - } - Proposal::GovernanceSetApprovalPpmRequired(value) => { - self::privileged::set_approval_ppm_required(value); - } - - } - } -} - -#[cfg(test)] -mod tests { - use super::*; - use runtime_io::{with_externalities, twox_128, TestExternalities}; - use codec::{KeyedVec, Joiner}; - use keyring::Keyring; - use environment::with_env; - use polkadot_primitives::{AccountId, Proposal}; - use runtime::{staking, session}; - - fn new_test_ext() -> TestExternalities { - let one = Keyring::One.to_raw_public(); - let two = Keyring::Two.to_raw_public(); - let three = [3u8; 32]; - - map![ - twox_128(APPROVALS_REQUIRED).to_vec() => vec![].and(&667u32), - twox_128(b"ses:len").to_vec() => vec![].and(&1u64), - twox_128(b"ses:val:len").to_vec() => vec![].and(&3u32), - twox_128(&0u32.to_keyed_vec(b"ses:val:")).to_vec() => one.to_vec(), - twox_128(&1u32.to_keyed_vec(b"ses:val:")).to_vec() => two.to_vec(), - twox_128(&2u32.to_keyed_vec(b"ses:val:")).to_vec() => three.to_vec(), - twox_128(b"sta:wil:len").to_vec() => vec![].and(&3u32), - twox_128(&0u32.to_keyed_vec(b"sta:wil:")).to_vec() => one.to_vec(), - twox_128(&1u32.to_keyed_vec(b"sta:wil:")).to_vec() => two.to_vec(), - twox_128(&2u32.to_keyed_vec(b"sta:wil:")).to_vec() => three.to_vec(), - twox_128(b"sta:spe").to_vec() => vec![].and(&1u64), - twox_128(b"sta:vac").to_vec() => vec![].and(&3u64), - twox_128(b"sta:era").to_vec() => vec![].and(&1u64) - ] - } - - #[test] - fn majority_voting_should_work() { - let one = Keyring::One.to_raw_public(); - let two = Keyring::Two.to_raw_public(); - let three = [3u8; 32]; - let mut t = new_test_ext(); - - with_externalities(&mut t, || { - assert_eq!(staking::era_length(), 1u64); - assert_eq!(staking::current_era(), 1u64); - assert_eq!(session::validator_count(), 3u32); - assert_eq!(session::validators(), vec![one.clone(), two.clone(), three.clone()]); - assert!(!session::validators().into_iter().position(|v| &v == &one).is_none()); - - // Block 1: Make proposal. Approve it. Era length changes. - system::testing::set_block_number(1); - public::propose(&one, &Proposal::StakingSetSessionsPerEra(2)); - public::approve(&two, 1); - staking::internal::check_new_era(); - assert_eq!(staking::era_length(), 2); - }); - } - - #[test] - fn majority_voting_should_work_after_unsuccessful_previous() { - let one = Keyring::One.to_raw_public(); - let two = Keyring::Two.to_raw_public(); - let three = [3u8; 32]; - let mut t = new_test_ext(); - - with_externalities(&mut t, || { - assert_eq!(staking::era_length(), 1u64); - assert_eq!(staking::current_era(), 1u64); - assert_eq!(session::validator_count(), 3u32); - assert_eq!(session::validators(), vec![one.clone(), two.clone(), three.clone()]); - assert!(!session::validators().into_iter().position(|v| &v == &one).is_none()); - - // Block 1: Make proposal. Fail it. - system::testing::set_block_number(1); - public::propose(&one, &Proposal::StakingSetSessionsPerEra(2)); - staking::internal::check_new_era(); - assert_eq!(staking::era_length(), 1); - - // Block 2: Make proposal. Approve it. It should change era length. - system::testing::set_block_number(2); - public::propose(&one, &Proposal::StakingSetSessionsPerEra(2)); - public::approve(&two, 2); - staking::internal::check_new_era(); - assert_eq!(staking::era_length(), 2); - }); - } - - #[test] - fn minority_voting_should_not_succeed() { - let one = Keyring::One.to_raw_public(); - let two = Keyring::Two.to_raw_public(); - let three = [3u8; 32]; - let mut t = new_test_ext(); - - with_externalities(&mut t, || { - assert_eq!(staking::era_length(), 1u64); - assert_eq!(staking::current_era(), 1u64); - assert_eq!(session::validator_count(), 3u32); - assert_eq!(session::validators(), vec![one.clone(), two.clone(), three.clone()]); - assert!(!session::validators().into_iter().position(|v| &v == &one).is_none()); - - // Block 1: Make proposal. Will have only 1 vote. No change. - system::testing::set_block_number(1); - public::propose(&one, &Proposal::StakingSetSessionsPerEra(2)); - staking::internal::check_new_era(); - assert_eq!(staking::era_length(), 1); - }); - } - - #[test] - #[should_panic] - fn old_voting_should_be_illegal() { - let one = Keyring::One.to_raw_public(); - let two = Keyring::Two.to_raw_public(); - let three = [3u8; 32]; - let mut t = new_test_ext(); - - with_externalities(&mut t, || { - assert_eq!(staking::era_length(), 1u64); - assert_eq!(staking::current_era(), 1u64); - assert_eq!(session::validator_count(), 3u32); - assert_eq!(session::validators(), vec![one.clone(), two.clone(), three.clone()]); - assert!(!session::validators().into_iter().position(|v| &v == &one).is_none()); - - // Block 1: Make proposal. Will have only 1 vote. No change. - system::testing::set_block_number(1); - public::propose(&one, &Proposal::StakingSetSessionsPerEra(2)); - public::approve(&two, 0); - staking::internal::check_new_era(); - assert_eq!(staking::era_length(), 1); - }); - } - - #[test] - #[should_panic] - fn double_voting_should_be_illegal() { - let one = Keyring::One.to_raw_public(); - let two = Keyring::Two.to_raw_public(); - let three = [3u8; 32]; - let mut t = new_test_ext(); - - with_externalities(&mut t, || { - assert_eq!(staking::era_length(), 1u64); - assert_eq!(staking::current_era(), 1u64); - assert_eq!(session::validator_count(), 3u32); - assert_eq!(session::validators(), vec![one.clone(), two.clone(), three.clone()]); - assert!(!session::validators().into_iter().position(|v| &v == &one).is_none()); - - // Block 1: Make proposal. Will have only 1 vote. No change. - system::testing::set_block_number(1); - public::propose(&one, &Proposal::StakingSetSessionsPerEra(2)); - public::approve(&two, 1); - public::approve(&two, 1); - staking::internal::check_new_era(); - assert_eq!(staking::era_length(), 1); - }); - } - - #[test] - #[should_panic] - fn over_proposing_should_be_illegal() { - let one = Keyring::One.to_raw_public(); - let two = Keyring::Two.to_raw_public(); - let three = [3u8; 32]; - let mut t = new_test_ext(); - - with_externalities(&mut t, || { - assert_eq!(staking::era_length(), 1u64); - assert_eq!(staking::current_era(), 1u64); - assert_eq!(session::validator_count(), 3u32); - assert_eq!(session::validators(), vec![one.clone(), two.clone(), three.clone()]); - assert!(!session::validators().into_iter().position(|v| &v == &one).is_none()); - - // Block 1: Make proposal. Will have only 1 vote. No change. - system::testing::set_block_number(1); - public::propose(&one, &Proposal::StakingSetSessionsPerEra(2)); - public::propose(&two, &Proposal::StakingSetSessionsPerEra(2)); - staking::internal::check_new_era(); - assert_eq!(staking::era_length(), 1); - }); - } - - #[test] - #[should_panic] - fn approving_without_proposal_should_be_illegal() { - let one = Keyring::One.to_raw_public(); - let two = Keyring::Two.to_raw_public(); - let three = [3u8; 32]; - let mut t = new_test_ext(); - - with_externalities(&mut t, || { - assert_eq!(staking::era_length(), 1u64); - assert_eq!(staking::current_era(), 1u64); - assert_eq!(session::validator_count(), 3u32); - assert_eq!(session::validators(), vec![one.clone(), two.clone(), three.clone()]); - assert!(!session::validators().into_iter().position(|v| &v == &one).is_none()); - - // Block 1: Make proposal. Will have only 1 vote. No change. - system::testing::set_block_number(1); - public::approve(&two, 1); - staking::internal::check_new_era(); - assert_eq!(staking::era_length(), 1); - }); - } - - #[test] - #[should_panic] - fn non_validator_approving_should_be_illegal() { - let one = Keyring::One.to_raw_public(); - let two = Keyring::Two.to_raw_public(); - let three = [3u8; 32]; - let four = [4u8; 32]; - let mut t = new_test_ext(); - - with_externalities(&mut t, || { - assert_eq!(staking::era_length(), 1u64); - assert_eq!(staking::current_era(), 1u64); - assert_eq!(session::validator_count(), 3u32); - assert_eq!(session::validators(), vec![one.clone(), two.clone(), three.clone()]); - assert!(!session::validators().into_iter().position(|v| &v == &one).is_none()); - - // Block 1: Make proposal. Will have only 1 vote. No change. - system::testing::set_block_number(1); - public::propose(&one, &Proposal::StakingSetSessionsPerEra(2)); - public::approve(&four, 1); - staking::internal::check_new_era(); - assert_eq!(staking::era_length(), 1); - }); - } -} diff --git a/polkadot/runtime/src/runtime/mod.rs b/polkadot/runtime/src/runtime/mod.rs deleted file mode 100644 index 6a54fa7310dde..0000000000000 --- a/polkadot/runtime/src/runtime/mod.rs +++ /dev/null @@ -1,34 +0,0 @@ -// Copyright 2017 Parity Technologies (UK) Ltd. -// This file is part of Polkadot. - -// Polkadot 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. - -// Polkadot 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 Polkadot. If not, see . - -//! The Polkadot runtime. - -#[allow(unused)] -pub mod system; -#[allow(unused)] -pub mod consensus; -#[allow(unused)] -pub mod staking; -#[allow(unused)] -pub mod timestamp; -#[allow(unused)] -pub mod session; -#[allow(unused)] -pub mod governance; -#[allow(unused)] -pub mod parachains; - -// TODO: polkadao diff --git a/polkadot/runtime/src/runtime/parachains.rs b/polkadot/runtime/src/runtime/parachains.rs deleted file mode 100644 index 1cd4151cf9afc..0000000000000 --- a/polkadot/runtime/src/runtime/parachains.rs +++ /dev/null @@ -1,123 +0,0 @@ -// Copyright 2017 Parity Technologies (UK) Ltd. -// This file is part of Polkadot. - -// Polkadot 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. - -// Polkadot 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 Polkadot. If not, see . - -//! Main parachains logic. For now this is just the determination of which validators do what. - -use rstd::prelude::*; -use codec::{Slicable, Joiner}; -use runtime_support::{Hashable, storage}; -use environment::with_env; -use runtime::session; -use polkadot_primitives::parachain::{Id, Chain, DutyRoster}; - -const PARACHAIN_COUNT: &[u8] = b"par:cou"; - -/// Get the number of parachains registered at present. -pub fn parachain_count() -> u32 { - storage::get_or(PARACHAIN_COUNT, 0) -} - -/// Calculate the current block's duty roster. -pub fn calculate_duty_roster() -> DutyRoster { - let parachain_count = parachain_count(); - let validator_count = session::validator_count() as u32; - let validators_per_parachain = (validator_count - 1) / parachain_count; - - let mut roles_val = (0..validator_count).map(|i| match i { - i if i < parachain_count * validators_per_parachain => - Chain::Parachain(Id::from(i / validators_per_parachain as u32)), - _ => Chain::Relay, - }).collect::>(); - let mut roles_gua = roles_val.clone(); - - let h = with_env(|e| e.parent_hash.clone()); - let mut seed = Vec::::new().and(&h).and(b"validator_role_pairs").blake2_256(); - - // shuffle - for i in 0..(validator_count - 1) { - // 8 bytes of entropy used per cycle, 32 bytes entropy per hash - let offset = (i * 8 % 32) as usize; - - // number of roles remaining to select from. - let remaining = (validator_count - i) as usize; - - // 4 * 2 32-bit ints per 256-bit seed. - let val_index = u32::decode(&mut &seed[offset..offset + 4]).expect("using 4 bytes for a 32-bit quantity") as usize % remaining; - let gua_index = u32::decode(&mut &seed[offset + 4..offset + 8]).expect("using 4 bytes for a 32-bit quantity") as usize % remaining; - - if offset == 24 { - // into the last 8 bytes - rehash to gather new entropy - seed = seed.blake2_256(); - } - - // exchange last item with randomly chosen first. - roles_val.swap(remaining - 1, val_index); - roles_gua.swap(remaining - 1, gua_index); - } - - DutyRoster { - validator_duty: roles_val, - guarantor_duty: roles_gua, - } -} - -#[cfg(test)] -mod tests { - use super::*; - use runtime_io::{with_externalities, twox_128, TestExternalities}; - use codec::{KeyedVec, Joiner}; - use keyring::Keyring; - use runtime::{consensus, session}; - - fn simple_setup() -> TestExternalities { - map![ - twox_128(b"ses:val:len").to_vec() => vec![].and(&8u32), - twox_128(b"par:cou").to_vec() => vec![].and(&2u32) - ] - } - - #[test] - fn should_work() { - let mut t = simple_setup(); - with_externalities(&mut t, || { - let check_roster = |duty_roster: &DutyRoster| { - assert_eq!(duty_roster.validator_duty.len(), 8); - assert_eq!(duty_roster.guarantor_duty.len(), 8); - for i in (0..2).map(Id::from) { - assert_eq!(duty_roster.validator_duty.iter().filter(|&&j| j == Chain::Parachain(i)).count(), 3); - assert_eq!(duty_roster.guarantor_duty.iter().filter(|&&j| j == Chain::Parachain(i)).count(), 3); - } - assert_eq!(duty_roster.validator_duty.iter().filter(|&&j| j == Chain::Relay).count(), 2); - assert_eq!(duty_roster.guarantor_duty.iter().filter(|&&j| j == Chain::Relay).count(), 2); - }; - - with_env(|e| e.parent_hash = [0u8; 32].into()); - let duty_roster_0 = calculate_duty_roster(); - check_roster(&duty_roster_0); - - with_env(|e| e.parent_hash = [1u8; 32].into()); - let duty_roster_1 = calculate_duty_roster(); - check_roster(&duty_roster_1); - assert!(duty_roster_0 != duty_roster_1); - - with_env(|e| e.parent_hash = [2u8; 32].into()); - let duty_roster_2 = calculate_duty_roster(); - check_roster(&duty_roster_2); - assert!(duty_roster_0 != duty_roster_2); - assert!(duty_roster_1 != duty_roster_2); - }); - } -} diff --git a/polkadot/runtime/src/runtime/session.rs b/polkadot/runtime/src/runtime/session.rs deleted file mode 100644 index 4eb5bf50553b4..0000000000000 --- a/polkadot/runtime/src/runtime/session.rs +++ /dev/null @@ -1,294 +0,0 @@ -// Copyright 2017 Parity Technologies (UK) Ltd. -// This file is part of Polkadot. - -// Polkadot 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. - -// Polkadot 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 Polkadot. If not, see . - -//! Session manager: is told the validators and allows them to manage their session keys for the -//! consensus module. - -use rstd::prelude::*; -use codec::KeyedVec; -use runtime_support::{storage, StorageVec}; -use polkadot_primitives::{AccountId, SessionKey, BlockNumber}; -use runtime::{system, staking, consensus}; - -const SESSION_LENGTH: &[u8] = b"ses:len"; -const CURRENT_INDEX: &[u8] = b"ses:ind"; -const CURRENT_SESSION_START: &[u8] = b"ses:sta"; -const LAST_SESSION_START: &[u8] = b"ses:lst"; -const LAST_LENGTH_CHANGE: &[u8] = b"ses:llc"; -const NEXT_KEY_FOR: &[u8] = b"ses:nxt:"; -const NEXT_SESSION_LENGTH: &[u8] = b"ses:nln"; - -struct ValidatorStorageVec; -impl StorageVec for ValidatorStorageVec { - type Item = AccountId; - const PREFIX: &'static [u8] = b"ses:val:"; -} - -// the session keys before the previous. -struct LastValidators; -impl StorageVec for LastValidators { - type Item = (AccountId, SessionKey); - const PREFIX: &'static [u8] = b"ses:old:"; -} - -/// Get the current set of validators. -pub fn validators() -> Vec { - ValidatorStorageVec::items() -} - -/// The number of blocks in each session. -pub fn length() -> BlockNumber { - storage::get_or(SESSION_LENGTH, 0) -} - -/// The number of validators currently. -pub fn validator_count() -> u32 { - ValidatorStorageVec::count() as u32 -} - -/// The current session index. -pub fn current_index() -> BlockNumber { - storage::get_or(CURRENT_INDEX, 0) -} - -/// Get the starting block of the current session. -pub fn current_start_block() -> BlockNumber { - // this seems like it's computable just by examining the current block number, session length, - // and last length change, but it's not simple to tell whether we are before or after - // a session rotation on a block which will have one. - storage::get_or(CURRENT_SESSION_START, 0) -} - -/// Get the last session's validators, paired with their authority keys. -pub fn last_session_keys() -> Vec<(AccountId, SessionKey)> { - LastValidators::items() -} - -/// Get the start block of the last session. -/// In general this is computable from the session length, -/// but when the current session is the first with a new length it is uncomputable. -pub fn last_session_start() -> Option { - storage::get(LAST_SESSION_START) -} - -/// The block number at which the era length last changed. -pub fn last_length_change() -> BlockNumber { - storage::get_or(LAST_LENGTH_CHANGE, 0) -} - -pub mod public { - use super::*; - - /// Sets the session key of `_validator` to `_key`. This doesn't take effect until the next - /// session. - pub fn set_key(validator: &AccountId, key: &SessionKey) { - // set new value for next session - storage::put(&validator.to_keyed_vec(NEXT_KEY_FOR), key); - } -} - -pub mod privileged { - use super::*; - - /// Set a new era length. Won't kick in until the next era change (at current length). - pub fn set_length(new: BlockNumber) { - storage::put(NEXT_SESSION_LENGTH, &new); - } - - /// Forces a new session. - pub fn force_new_session() { - rotate_session(); - } -} - -// INTERNAL API (available to other runtime modules) - -pub mod internal { - use super::*; - - /// Transition to a new era, with a new set of valiators. - /// - /// Called by staking::next_era() only. `next_session` should be called after this in order to - /// update the session keys to the next validator set. - pub fn set_validators(new: &[AccountId]) { - LastValidators::set_items( - new.iter().cloned().zip(consensus::authorities()) - ); - ValidatorStorageVec::set_items(new); - consensus::internal::set_authorities(new); - } - - /// Hook to be called after transaction processing. - pub fn check_rotate_session() { - // do this last, after the staking system has had chance to switch out the authorities for the - // new set. - // check block number and call next_session if necessary. - if (system::block_number() - last_length_change()) % length() == 0 { - rotate_session(); - } - } -} - -/// Move onto next session: register the new authority set. -fn rotate_session() { - // Increment current session index. - storage::put(CURRENT_INDEX, &(current_index() + 1)); - // Enact era length change. - if let Some(next_len) = storage::get::(NEXT_SESSION_LENGTH) { - storage::put(SESSION_LENGTH, &next_len); - storage::put(LAST_LENGTH_CHANGE, &system::block_number()); - storage::kill(NEXT_SESSION_LENGTH); - } - - let validators = validators(); - - storage::put(LAST_SESSION_START, ¤t_start_block()); - storage::put(CURRENT_SESSION_START, &system::block_number()); - LastValidators::set_items( - validators.iter() - .cloned() - .zip(consensus::authorities()) - ); - - - // Update any changes in session keys. - validators.iter().enumerate().for_each(|(i, v)| { - let k = v.to_keyed_vec(NEXT_KEY_FOR); - if let Some(n) = storage::take(&k) { - // this is fine because the authorities vector currently - // matches the validators length perfectly. - consensus::internal::set_authority(i as u32, &n); - } - }); -} - -#[cfg(test)] -mod tests { - use super::*; - use super::public::*; - use super::privileged::*; - use super::internal::*; - use runtime_io::{with_externalities, twox_128, TestExternalities}; - use codec::{KeyedVec, Joiner}; - use keyring::Keyring; - use environment::with_env; - use polkadot_primitives::AccountId; - use runtime::{consensus, session}; - - fn simple_setup() -> TestExternalities { - map![ - twox_128(SESSION_LENGTH).to_vec() => vec![].and(&2u64), - // the validators (10, 20, ...) - twox_128(b"ses:val:len").to_vec() => vec![].and(&2u32), - twox_128(&0u32.to_keyed_vec(ValidatorStorageVec::PREFIX)).to_vec() => vec![10; 32], - twox_128(&1u32.to_keyed_vec(ValidatorStorageVec::PREFIX)).to_vec() => vec![20; 32], - // initial session keys (11, 21, ...) - b":auth:len".to_vec() => vec![].and(&2u32), - 0u32.to_keyed_vec(b":auth:") => vec![11; 32], - 1u32.to_keyed_vec(b":auth:") => vec![21; 32] - ] - } - - #[test] - fn simple_setup_should_work() { - let mut t = simple_setup(); - with_externalities(&mut t, || { - assert_eq!(consensus::authorities(), vec![[11u8; 32], [21u8; 32]]); - assert_eq!(length(), 2u64); - assert_eq!(validators(), vec![[10u8; 32], [20u8; 32]]); - }); - } - - #[test] - fn session_length_change_should_work() { - let mut t = simple_setup(); - with_externalities(&mut t, || { - // Block 1: Change to length 3; no visible change. - system::testing::set_block_number(1); - set_length(3); - check_rotate_session(); - assert_eq!(length(), 2); - assert_eq!(current_index(), 0); - - // Block 2: Length now changed to 3. Index incremented. - system::testing::set_block_number(2); - set_length(3); - check_rotate_session(); - assert_eq!(length(), 3); - assert_eq!(current_index(), 1); - - // Block 3: Length now changed to 3. Index incremented. - system::testing::set_block_number(3); - check_rotate_session(); - assert_eq!(length(), 3); - assert_eq!(current_index(), 1); - - // Block 4: Change to length 2; no visible change. - system::testing::set_block_number(4); - set_length(2); - check_rotate_session(); - assert_eq!(length(), 3); - assert_eq!(current_index(), 1); - - // Block 5: Length now changed to 2. Index incremented. - system::testing::set_block_number(5); - check_rotate_session(); - assert_eq!(length(), 2); - assert_eq!(current_index(), 2); - - // Block 6: No change. - system::testing::set_block_number(6); - check_rotate_session(); - assert_eq!(length(), 2); - assert_eq!(current_index(), 2); - - // Block 7: Next index. - system::testing::set_block_number(7); - check_rotate_session(); - assert_eq!(length(), 2); - assert_eq!(current_index(), 3); - }); - } - - #[test] - fn session_change_should_work() { - let mut t = simple_setup(); - with_externalities(&mut t, || { - // Block 1: No change - system::testing::set_block_number(1); - check_rotate_session(); - assert_eq!(consensus::authorities(), vec![[11u8; 32], [21u8; 32]]); - - // Block 2: Session rollover, but no change. - system::testing::set_block_number(2); - check_rotate_session(); - assert_eq!(consensus::authorities(), vec![[11u8; 32], [21u8; 32]]); - - // Block 3: Set new key for validator 2; no visible change. - system::testing::set_block_number(3); - set_key(&[20; 32], &[22; 32]); - assert_eq!(consensus::authorities(), vec![[11u8; 32], [21u8; 32]]); - - check_rotate_session(); - assert_eq!(consensus::authorities(), vec![[11u8; 32], [21u8; 32]]); - - // Block 4: Session rollover, authority 2 changes. - system::testing::set_block_number(4); - check_rotate_session(); - assert_eq!(consensus::authorities(), vec![[11u8; 32], [22u8; 32]]); - }); - } -} diff --git a/polkadot/runtime/src/runtime/staking.rs b/polkadot/runtime/src/runtime/staking.rs deleted file mode 100644 index 7ed94b920215e..0000000000000 --- a/polkadot/runtime/src/runtime/staking.rs +++ /dev/null @@ -1,496 +0,0 @@ -// Copyright 2017 Parity Technologies (UK) Ltd. -// This file is part of Polkadot. - -// Polkadot 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. - -// Polkadot 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 Polkadot. If not, see . - -//! Staking manager: Handles balances and periodically determines the best set of validators. - -use rstd::prelude::*; -use rstd::cell::RefCell; -use runtime_io::print; -use codec::KeyedVec; -use runtime_support::{storage, StorageVec}; -use polkadot_primitives::{BlockNumber, AccountId}; -use primitives::bft::{MisbehaviorReport, MisbehaviorKind}; -use runtime::{system, session, governance, consensus}; - -type Balance = u64; -type Bondage = u64; - -struct IntentionStorageVec {} -impl StorageVec for IntentionStorageVec { - type Item = AccountId; - const PREFIX: &'static [u8] = b"sta:wil:"; -} - -const BONDING_DURATION: &[u8] = b"sta:loc"; -const VALIDATOR_COUNT: &[u8] = b"sta:vac"; -const SESSIONS_PER_ERA: &[u8] = b"sta:spe"; -const NEXT_SESSIONS_PER_ERA: &[u8] = b"sta:nse"; -const CURRENT_ERA: &[u8] = b"sta:era"; -const LAST_ERA_LENGTH_CHANGE: &[u8] = b"sta:lec"; -const TOTAL_STAKE: &[u8] = b"sta:tot"; -const BALANCE_OF: &[u8] = b"sta:bal:"; -const BONDAGE_OF: &[u8] = b"sta:bon:"; - -/// The length of the bonding duration in eras. -pub fn bonding_duration() -> BlockNumber { - storage::get_or_default(BONDING_DURATION) -} - -/// The length of a staking era in sessions. -pub fn validator_count() -> usize { - storage::get_or_default::(VALIDATOR_COUNT) as usize -} - -/// The length of a staking era in blocks. -pub fn era_length() -> BlockNumber { - sessions_per_era() * session::length() -} - -/// The length of a staking era in sessions. -pub fn sessions_per_era() -> BlockNumber { - storage::get_or_default(SESSIONS_PER_ERA) -} - -/// The current era index. -pub fn current_era() -> BlockNumber { - storage::get_or_default(CURRENT_ERA) -} - -/// The block number at which the era length last changed. -pub fn last_era_length_change() -> BlockNumber { - storage::get_or_default(LAST_ERA_LENGTH_CHANGE) -} - -/// The balance of a given account. -pub fn balance(who: &AccountId) -> Balance { - storage::get_or_default(&who.to_keyed_vec(BALANCE_OF)) -} - -/// Gives the index of the era where the account's balance will no longer -/// be bonded. -pub fn bondage(who: &AccountId) -> Bondage { - storage::get_or_default(&who.to_keyed_vec(BONDAGE_OF)) -} - -fn set_balance(who: &AccountId, amount: Balance) { - storage::put(&who.to_keyed_vec(BALANCE_OF), &amount) -} - -// Each identity's stake may be in one of three bondage states, given by an integer: -// - n | n <= current_era(): inactive: free to be transferred. -// - ~0: active: currently representing a validator. -// - n | n > current_era(): deactivating: recently representing a validator and not yet -// ready for transfer. - -pub mod public { - use super::*; - - /// Transfer some unlocked staking balance to another staker. - pub fn transfer(transactor: &AccountId, dest: &AccountId, value: Balance) { - let from_key = transactor.to_keyed_vec(BALANCE_OF); - let from_balance = storage::get_or_default::(&from_key); - assert!(from_balance >= value); - let to_key = dest.to_keyed_vec(BALANCE_OF); - let to_balance: Balance = storage::get_or_default(&to_key); - assert!(bondage(transactor) <= bondage(dest)); - assert!(to_balance + value > to_balance); // no overflow - storage::put(&from_key, &(from_balance - value)); - storage::put(&to_key, &(to_balance + value)); - } - - /// Declare the desire to stake for the transactor. - /// - /// Effects will be felt at the beginning of the next era. - pub fn stake(transactor: &AccountId) { - let mut intentions = IntentionStorageVec::items(); - // can't be in the list twice. - assert!(intentions.iter().find(|t| t == &transactor).is_none(), "Cannot stake if already staked."); - intentions.push(transactor.clone()); - IntentionStorageVec::set_items(&intentions); - storage::put(&transactor.to_keyed_vec(BONDAGE_OF), &u64::max_value()); - } - - /// Retract the desire to stake for the transactor. - /// - /// Effects will be felt at the beginning of the next era. - pub fn unstake(transactor: &AccountId) { - let mut intentions = IntentionStorageVec::items(); - if let Some(position) = intentions.iter().position(|t| t == transactor) { - intentions.swap_remove(position); - } else { - panic!("Cannot unstake if not already staked."); - } - IntentionStorageVec::set_items(&intentions); - storage::put(&transactor.to_keyed_vec(BONDAGE_OF), &(current_era() + bonding_duration())); - } - - /// Report misbehavior. Only validators may do this, signing under - /// the authority key of the session the report corresponds to. - /// - /// Reports older than one session in the past will be ignored. - pub fn report_misbehavior(transactor: &AccountId, report: &MisbehaviorReport) { - let (validators, authorities) = if report.parent_number < session::last_session_start().unwrap_or(0) { - panic!("report is too old"); - } else if report.parent_number < session::current_start_block() { - session::last_session_keys().into_iter().unzip() - } else { - (session::validators(), consensus::authorities()) - }; - - if report.parent_hash != system::block_hash(report.parent_number) { - // report out of chain. - panic!("report not from this blockchain"); - } - - let reporting_validator = match authorities.iter().position(|x| x == transactor) { - None => panic!("only validators may report"), - Some(pos) => validators.get(pos).expect("validators and authorities have same cardinality; qed"), - }; - - // any invalidity beyond this point is actually its own misbehavior. - let target = match authorities.iter().position(|x| x == &report.target) { - None => { - slash(reporting_validator, None); - return; - } - Some(pos) => validators.get(pos).expect("validators and authorities have same cardinality; qed"), - }; - - let misbehaved = ::misbehavior_check::evaluate_misbehavior(&report.target, report.parent_hash, &report.misbehavior); - if misbehaved { - slash(target, Some(reporting_validator)) - } else { - slash(reporting_validator, None); - } - } -} - -pub mod privileged { - use super::*; - - /// Set the number of sessions in an era. - pub fn set_sessions_per_era(new: BlockNumber) { - storage::put(NEXT_SESSIONS_PER_ERA, &new); - } - - /// The length of the bonding duration in eras. - pub fn set_bonding_duration(new: BlockNumber) { - storage::put(BONDING_DURATION, &new); - } - - /// The length of a staking era in sessions. - pub fn set_validator_count(new: u32) { - storage::put(VALIDATOR_COUNT, &new); - } - - /// Force there to be a new era. This also forces a new session immediately after. - pub fn force_new_era() { - new_era(); - session::privileged::force_new_session(); - } -} - -pub mod internal { - use super::*; - - /// Hook to be called after to transaction processing. - pub fn check_new_era() { - // check block number and call new_era if necessary. - if (system::block_number() - last_era_length_change()) % era_length() == 0 { - new_era(); - } - } -} - -/// Slash a validator, with an optional benefactor. -fn slash(who: &AccountId, benefactor: Option<&AccountId>) { - // the reciprocal of the proportion of the amount slashed to give - // to the benefactor. - const SLASH_REWARD_DENOMINATOR: Balance = 10; - - let slashed = balance(who); - set_balance(who, 0); - - if let Some(benefactor) = benefactor { - let reward = slashed / SLASH_REWARD_DENOMINATOR; - - let prior = balance(benefactor); - set_balance(benefactor, prior + reward); - } -} - -/// The era has changed - enact new staking set. -/// -/// NOTE: This always happens immediately before a session change to ensure that new validators -/// get a chance to set their session keys. -fn new_era() { - // Inform governance module that it's the end of an era - governance::internal::end_of_an_era(); - - // Increment current era. - storage::put(CURRENT_ERA, &(current_era() + 1)); - - // Enact era length change. - let next_spe: u64 = storage::get_or_default(NEXT_SESSIONS_PER_ERA); - if next_spe > 0 && next_spe != sessions_per_era() { - storage::put(SESSIONS_PER_ERA, &next_spe); - storage::put(LAST_ERA_LENGTH_CHANGE, &system::block_number()); - } - - // evaluate desired staking amounts and nominations and optimise to find the best - // combination of validators, then use session::internal::set_validators(). - // for now, this just orders would-be stakers by their balances and chooses the top-most - // validator_count() of them. - let mut intentions = IntentionStorageVec::items() - .into_iter() - .map(|v| (balance(&v), v)) - .collect::>(); - intentions.sort_unstable_by(|&(b1, _), &(b2, _)| b2.cmp(&b1)); - session::internal::set_validators( - &intentions.into_iter() - .map(|(_, v)| v) - .take(validator_count()) - .collect::>() - ); -} - -#[cfg(test)] -mod tests { - use super::*; - use super::internal::*; - use super::public::*; - use super::privileged::*; - - use runtime_io::{with_externalities, twox_128, TestExternalities}; - use codec::{KeyedVec, Joiner}; - use keyring::Keyring; - use environment::with_env; - use polkadot_primitives::AccountId; - use runtime::{staking, session}; - - #[test] - fn staking_should_work() { - let one = Keyring::One.to_raw_public(); - let two = Keyring::Two.to_raw_public(); - let three = [3u8; 32]; - let four = [4u8; 32]; - - let mut t: TestExternalities = map![ - twox_128(b"ses:len").to_vec() => vec![].and(&1u64), - twox_128(b"ses:val:len").to_vec() => vec![].and(&2u32), - twox_128(&0u32.to_keyed_vec(b"ses:val:")).to_vec() => vec![10; 32], - twox_128(&1u32.to_keyed_vec(b"ses:val:")).to_vec() => vec![20; 32], - twox_128(SESSIONS_PER_ERA).to_vec() => vec![].and(&2u64), - twox_128(VALIDATOR_COUNT).to_vec() => vec![].and(&2u32), - twox_128(BONDING_DURATION).to_vec() => vec![].and(&3u64), - twox_128(TOTAL_STAKE).to_vec() => vec![].and(&100u64), - twox_128(&one.to_keyed_vec(BALANCE_OF)).to_vec() => vec![].and(&10u64), - twox_128(&two.to_keyed_vec(BALANCE_OF)).to_vec() => vec![].and(&20u64), - twox_128(&three.to_keyed_vec(BALANCE_OF)).to_vec() => vec![].and(&30u64), - twox_128(&four.to_keyed_vec(BALANCE_OF)).to_vec() => vec![].and(&40u64) - ]; - - with_externalities(&mut t, || { - assert_eq!(era_length(), 2u64); - assert_eq!(validator_count(), 2usize); - assert_eq!(bonding_duration(), 3u64); - assert_eq!(session::validators(), vec![[10u8; 32], [20u8; 32]]); - - // Block 1: Add three validators. No obvious change. - system::testing::set_block_number(1); - stake(&one); - stake(&two); - stake(&four); - check_new_era(); - assert_eq!(session::validators(), vec![[10u8; 32], [20u8; 32]]); - - // Block 2: New validator set now. - system::testing::set_block_number(2); - check_new_era(); - assert_eq!(session::validators(), vec![four.clone(), two.clone()]); - - // Block 3: Unstake highest, introduce another staker. No change yet. - system::testing::set_block_number(3); - stake(&three); - unstake(&four); - check_new_era(); - - // Block 4: New era - validators change. - system::testing::set_block_number(4); - check_new_era(); - assert_eq!(session::validators(), vec![three.clone(), two.clone()]); - - // Block 5: Transfer stake from highest to lowest. No change yet. - system::testing::set_block_number(5); - transfer(&four, &one, 40); - check_new_era(); - - // Block 6: Lowest now validator. - system::testing::set_block_number(6); - check_new_era(); - assert_eq!(session::validators(), vec![one.clone(), three.clone()]); - - // Block 7: Unstake three. No change yet. - system::testing::set_block_number(7); - unstake(&three); - check_new_era(); - assert_eq!(session::validators(), vec![one.clone(), three.clone()]); - - // Block 8: Back to one and two. - system::testing::set_block_number(8); - check_new_era(); - assert_eq!(session::validators(), vec![one.clone(), two.clone()]); - }); - } - - #[test] - fn staking_eras_work() { - let mut t: TestExternalities = map![ - twox_128(b"ses:len").to_vec() => vec![].and(&1u64), - twox_128(SESSIONS_PER_ERA).to_vec() => vec![].and(&2u64) - ]; - with_externalities(&mut t, || { - assert_eq!(era_length(), 2u64); - assert_eq!(sessions_per_era(), 2u64); - assert_eq!(last_era_length_change(), 0u64); - assert_eq!(current_era(), 0u64); - - // Block 1: No change. - system::testing::set_block_number(1); - check_new_era(); - assert_eq!(sessions_per_era(), 2u64); - assert_eq!(last_era_length_change(), 0u64); - assert_eq!(current_era(), 0u64); - - // Block 2: Simple era change. - system::testing::set_block_number(2); - check_new_era(); - assert_eq!(sessions_per_era(), 2u64); - assert_eq!(last_era_length_change(), 0u64); - assert_eq!(current_era(), 1u64); - - // Block 3: Schedule an era length change; no visible changes. - system::testing::set_block_number(3); - set_sessions_per_era(3); - check_new_era(); - assert_eq!(sessions_per_era(), 2u64); - assert_eq!(last_era_length_change(), 0u64); - assert_eq!(current_era(), 1u64); - - // Block 4: Era change kicks in. - system::testing::set_block_number(4); - check_new_era(); - assert_eq!(sessions_per_era(), 3u64); - assert_eq!(last_era_length_change(), 4u64); - assert_eq!(current_era(), 2u64); - - // Block 5: No change. - system::testing::set_block_number(5); - check_new_era(); - assert_eq!(sessions_per_era(), 3u64); - assert_eq!(last_era_length_change(), 4u64); - assert_eq!(current_era(), 2u64); - - // Block 6: No change. - system::testing::set_block_number(6); - check_new_era(); - assert_eq!(sessions_per_era(), 3u64); - assert_eq!(last_era_length_change(), 4u64); - assert_eq!(current_era(), 2u64); - - // Block 7: Era increment. - system::testing::set_block_number(7); - check_new_era(); - assert_eq!(sessions_per_era(), 3u64); - assert_eq!(last_era_length_change(), 4u64); - assert_eq!(current_era(), 3u64); - }); - } - - #[test] - fn staking_balance_works() { - let one = Keyring::One.to_raw_public(); - let two = Keyring::Two.to_raw_public(); - - let mut t: TestExternalities = map![ - twox_128(&one.to_keyed_vec(BALANCE_OF)).to_vec() => vec![].and(&42u64) - ]; - - with_externalities(&mut t, || { - assert_eq!(balance(&one), 42); - assert_eq!(balance(&two), 0); - }); - } - - #[test] - fn staking_balance_transfer_works() { - let one = Keyring::One.to_raw_public(); - let two = Keyring::Two.to_raw_public(); - - let mut t: TestExternalities = map![ - twox_128(&one.to_keyed_vec(BALANCE_OF)).to_vec() => vec![].and(&111u64) - ]; - - with_externalities(&mut t, || { - transfer(&one, &two, 69); - assert_eq!(balance(&one), 42); - assert_eq!(balance(&two), 69); - }); - } - - #[test] - #[should_panic] - fn staking_balance_transfer_when_bonded_doesnt_work() { - let one = Keyring::One.to_raw_public(); - let two = Keyring::Two.to_raw_public(); - - let mut t: TestExternalities = map![ - twox_128(&one.to_keyed_vec(BALANCE_OF)).to_vec() => vec![].and(&111u64) - ]; - - with_externalities(&mut t, || { - stake(&one); - transfer(&one, &two, 69); - }); - } - - #[test] - #[should_panic] - fn misbehavior_report_by_non_validator_panics() { - let one = Keyring::One.to_raw_public(); - let two = Keyring::Two.to_raw_public(); - - let mut t: TestExternalities = map![ - twox_128(&one.to_keyed_vec(BALANCE_OF)).to_vec() => vec![].and(&111u64) - ]; - - with_externalities(&mut t, || { - // the misbehavior report here is invalid, but that - // actually doesn't panic; instead it would slash the bad - // reporter. - report_misbehavior(&one, &MisbehaviorReport { - parent_hash: [0; 32].into(), - parent_number: 0, - target: two, - misbehavior: MisbehaviorKind::BftDoubleCommit( - 2, - ([1; 32].into(), [2; 64].into()), - ([3; 32].into(), [4; 64].into()), - ), - }) - }); - } -} diff --git a/polkadot/runtime/src/runtime/system.rs b/polkadot/runtime/src/runtime/system.rs deleted file mode 100644 index 935f801924594..0000000000000 --- a/polkadot/runtime/src/runtime/system.rs +++ /dev/null @@ -1,450 +0,0 @@ -// Copyright 2017 Parity Technologies (UK) Ltd. -// This file is part of Polkadot. - -// Polkadot 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. - -// Polkadot 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 Polkadot. If not, see . - -//! System manager: Handles all of the top-level stuff; executing block/transaction, setting code -//! and depositing logs. - -use rstd::mem; -use rstd::prelude::*; - -use codec::{KeyedVec, Slicable}; -use environment::with_env; -use polkadot_primitives::{ - AccountId, Hash, TxOrder, BlockNumber, Block, Header, - UncheckedTransaction, Function, InherentFunction, Log -}; - -use runtime_io::{print, storage_root, enumerated_trie_root}; -use runtime_support::{Hashable, storage}; -use runtime::{staking, session}; - -/// Prefixes account ID and stores u64 nonce. -pub const NONCE_OF: &[u8] = b"sys:non:"; -/// Prefixes block number and stores hash of that block. -pub const BLOCK_HASH_AT: &[u8] = b"sys:old:"; -/// Stores the temporary current transaction number. -pub const TEMP_TRANSACTION_NUMBER: &[u8] = b"temp:txcount"; - -/// The current block number being processed. Set by `execute_block`. -pub fn block_number() -> BlockNumber { - with_env(|e| e.block_number) -} - -/// Get the block hash of a given block (uses storage). -pub fn block_hash(number: BlockNumber) -> Hash { - storage::get_or_default(&number.to_keyed_vec(BLOCK_HASH_AT)) -} - -pub mod privileged { - use super::*; - - /// Set the new code. - pub fn set_code(new: &[u8]) { - storage::unhashed::put_raw(b":code", new); - } -} - -pub mod internal { - use super::*; - - /// Deposits a log and ensures it matches the blocks log data. - pub fn deposit_log(log: Log) { - with_env(|e| e.digest.logs.push(log)); - } - - /// Actually execute all transitioning for `block`. - pub fn execute_block(mut block: Block) { - // populate environment from header. - with_env(|e| { - e.block_number = block.header.number; - e.parent_hash = block.header.parent_hash; - }); - - // any initial checks - initial_checks(&block); - - // execute all transactions, inherent or otherwise. - for (tx_num, tx) in block.all_transactions().enumerate() { - super::execute_transaction(tx, tx_num as u64); - } - - // post-transactional book-keeping. - staking::internal::check_new_era(); - session::internal::check_rotate_session(); - - // any final checks - final_checks(&block); - - // any stuff that we do after taking the storage root. - post_finalise(&block.header); - } - - /// Execute a transaction outside of the block execution function. - /// This doesn't attempt to validate anything regarding the block. - /// Note that when building a block transaction by transaction, the - /// inherent methods must be called manually. - pub fn execute_transaction(utx: UncheckedTransaction, mut header: Header) -> Header { - // populate environment from header. - with_env(|e| { - e.block_number = header.number; - e.parent_hash = header.parent_hash; - mem::swap(&mut header.digest, &mut e.digest); - }); - - let tx_num: u64 = storage::get_or_default(TEMP_TRANSACTION_NUMBER); - - super::execute_transaction(utx, tx_num); - - with_env(|e| { - mem::swap(&mut header.digest, &mut e.digest); - }); - - storage::put(TEMP_TRANSACTION_NUMBER, &(tx_num + 1)); - - header - } - - /// Finalise the block - it is up the caller to ensure that all header fields are valid - /// except state-root. - pub fn finalise_block(mut header: Header) -> Header { - // populate environment from header. - with_env(|e| { - e.block_number = header.number; - e.parent_hash = header.parent_hash; - mem::swap(&mut header.digest, &mut e.digest); - }); - - let tx_count: u64 = storage::take_or_default(TEMP_TRANSACTION_NUMBER); - if tx_count < Function::inherent_functions() { - panic!("Not enough transactions provided to fulfill all inherent functions."); - } - - staking::internal::check_new_era(); - session::internal::check_rotate_session(); - - header.state_root = storage_root().into(); - with_env(|e| { - mem::swap(&mut header.digest, &mut e.digest); - }); - - post_finalise(&header); - - header - } -} - -/// Get an account's current nonce. -pub fn nonce(account: AccountId) -> TxOrder { - let nonce_key = account.to_keyed_vec(NONCE_OF); - storage::get_or(&nonce_key, 0) -} - -/// Dispatch a function. -fn dispatch_function(function: &Function, transactor: &AccountId) { - match *function { - Function::Inherent(InherentFunction::TimestampSet(t)) => { - ::runtime::timestamp::public::set(t); - } - Function::StakingStake => { - ::runtime::staking::public::stake(transactor); - } - Function::StakingUnstake => { - ::runtime::staking::public::unstake(transactor); - } - Function::StakingTransfer(dest, value) => { - ::runtime::staking::public::transfer(transactor, &dest, value); - } - Function::ReportMisbehavior(ref report) => { - ::runtime::staking::public::report_misbehavior(transactor, report) - } - Function::SessionSetKey(session) => { - ::runtime::session::public::set_key(transactor, &session); - } - Function::GovernancePropose(ref proposal) => { - ::runtime::governance::public::propose(transactor, proposal); - } - Function::GovernanceApprove(era_index) => { - ::runtime::governance::public::approve(transactor, era_index); - } - } -} - -fn execute_transaction(utx: UncheckedTransaction, tx_num: u64) { - use ::transaction; - - // Verify the transaction is authenticated at its position. - let tx = match transaction::check(utx, tx_num) { - Ok(tx) => tx, - Err(_) => panic!("Transaction at index {} not properly authenticated", tx_num), - }; - - // check nonce - let nonce_key = tx.signed.to_keyed_vec(NONCE_OF); - let (expected_nonce, increment_nonce) = if !tx.function.is_inherent() { - (storage::get_or(&nonce_key, 0), true) - } else { - (0, false) - }; - - assert!(tx.nonce == expected_nonce, "All transactions should have the correct nonce"); - - // increment nonce in storage, unless it's the EVERYBODY account. - if increment_nonce { - storage::put(&nonce_key, &(expected_nonce + 1)); - } - - // decode parameters and dispatch - dispatch_function(&tx.function, &tx.signed); -} - -fn initial_checks(block: &Block) { - let ref header = block.header; - - // check parent_hash is correct. - assert!( - header.number > 0 && block_hash(header.number - 1) == header.parent_hash, - "Parent hash should be valid." - ); - - // check transaction trie root represents the transactions. - let txs = block.all_transactions().map(|tx| Slicable::encode(&tx)).collect::>(); - let txs = txs.iter().map(Vec::as_slice).collect::>(); - let txs_root = enumerated_trie_root(&txs).into(); - info_expect_equal_hash(&header.transaction_root, &txs_root); - assert!(header.transaction_root == txs_root, "Transaction trie root must be valid."); -} - -fn final_checks(block: &Block) { - let ref header = block.header; - - // check digest - with_env(|e| { - assert!(header.digest == e.digest); - }); - - // check storage root. - let storage_root = storage_root().into(); - info_expect_equal_hash(&header.state_root, &storage_root); - assert!(header.state_root == storage_root, "Storage root must match that calculated."); -} - -fn post_finalise(header: &Header) { - // store the header hash in storage; we can't do it before otherwise there would be a - // cyclic dependency. - storage::put(&header.number.to_keyed_vec(BLOCK_HASH_AT), &header.blake2_256()); -} - -#[cfg(feature = "std")] -fn info_expect_equal_hash(given: &Hash, expected: &Hash) { - use primitives::hexdisplay::HexDisplay; - if given != expected { - println!("Hash: given={}, expected={}", HexDisplay::from(&given.0), HexDisplay::from(&expected.0)); - } -} - -#[cfg(not(feature = "std"))] -fn info_expect_equal_hash(given: &Hash, expected: &Hash) { - if given != expected { - print("Hash not equal"); - print(&given.0[..]); - print(&expected.0[..]); - } -} - -#[cfg(any(feature = "std", test))] -pub mod testing { - use super::*; - - pub fn set_block_number(n: BlockNumber) { - with_env(|e| e.block_number = n); - } -} - -#[cfg(test)] -mod tests { - use super::*; - use super::internal::*; - - use runtime_io::{with_externalities, twox_128, TestExternalities}; - use codec::{Joiner, KeyedVec, Slicable}; - use keyring::Keyring; - use environment::with_env; - use primitives::hexdisplay::HexDisplay; - use polkadot_primitives::{Header, Body, Digest, UncheckedTransaction, Transaction, Function, InherentFunction}; - use runtime::staking; - - fn set_timestamp() -> UncheckedTransaction { - UncheckedTransaction::inherent(InherentFunction::TimestampSet(100_000)) - } - - #[test] - #[should_panic] - fn fails_if_first_not_timestamp_set() { - let one = Keyring::One.to_raw_public(); - let two = Keyring::Two.to_raw_public(); - - let mut t: TestExternalities = map![ - twox_128(&one.to_keyed_vec(b"sta:bal:")).to_vec() => vec![111u8, 0, 0, 0, 0, 0, 0, 0] - ]; - - let tx = UncheckedTransaction { - transaction: Transaction { - signed: one.clone(), - nonce: 0, - function: Function::StakingTransfer(two, 69), - }, - signature: hex!("5f9832c5a4a39e2dd4a3a0c5b400e9836beb362cb8f7d845a8291a2ae6fe366612e080e4acd0b5a75c3d0b6ee69614a68fb63698c1e76bf1f2dcd8fa617ddf05").into(), - }; - - with_externalities(&mut t, || { - internal::execute_transaction(tx, Header::from_block_number(1)); - }); - } - - #[test] - fn staking_balance_transfer_dispatch_works() { - let one = Keyring::One.to_raw_public(); - let two = Keyring::Two.to_raw_public(); - - let mut t: TestExternalities = map![ - twox_128(&one.to_keyed_vec(b"sta:bal:")).to_vec() => vec![111u8, 0, 0, 0, 0, 0, 0, 0] - ]; - - let tx = UncheckedTransaction { - transaction: Transaction { - signed: one.clone(), - nonce: 0, - function: Function::StakingTransfer(two, 69), - }, - signature: hex!("5f9832c5a4a39e2dd4a3a0c5b400e9836beb362cb8f7d845a8291a2ae6fe366612e080e4acd0b5a75c3d0b6ee69614a68fb63698c1e76bf1f2dcd8fa617ddf05").into(), - }; - - with_externalities(&mut t, || { - let header = Header::from_block_number(1); - let header = internal::execute_transaction(set_timestamp(), header); - internal::execute_transaction(tx, header); - assert_eq!(staking::balance(&one), 42); - assert_eq!(staking::balance(&two), 69); - }); - } - - fn new_test_ext() -> TestExternalities { - let one = Keyring::One.to_raw_public(); - let two = Keyring::Two.to_raw_public(); - let three = [3u8; 32]; - - map![ - twox_128(&0u64.to_keyed_vec(b"sys:old:")).to_vec() => [69u8; 32].encode(), - twox_128(b"gov:apr").to_vec() => vec![].and(&667u32), - twox_128(b"ses:len").to_vec() => vec![].and(&2u64), - twox_128(b"ses:val:len").to_vec() => vec![].and(&3u32), - twox_128(&0u32.to_keyed_vec(b"ses:val:")).to_vec() => one.to_vec(), - twox_128(&1u32.to_keyed_vec(b"ses:val:")).to_vec() => two.to_vec(), - twox_128(&2u32.to_keyed_vec(b"ses:val:")).to_vec() => three.to_vec(), - twox_128(b"sta:wil:len").to_vec() => vec![].and(&3u32), - twox_128(&0u32.to_keyed_vec(b"sta:wil:")).to_vec() => one.to_vec(), - twox_128(&1u32.to_keyed_vec(b"sta:wil:")).to_vec() => two.to_vec(), - twox_128(&2u32.to_keyed_vec(b"sta:wil:")).to_vec() => three.to_vec(), - twox_128(b"sta:spe").to_vec() => vec![].and(&2u64), - twox_128(b"sta:vac").to_vec() => vec![].and(&3u64), - twox_128(b"sta:era").to_vec() => vec![].and(&0u64), - twox_128(&one.to_keyed_vec(b"sta:bal:")).to_vec() => vec![111u8, 0, 0, 0, 0, 0, 0, 0] - ] - } - - #[test] - fn block_import_works() { - let mut t = new_test_ext(); - - let h = Header { - parent_hash: [69u8; 32].into(), - number: 1, - state_root: hex!("aa4fbcdc09b21e4366aebccd9b9ec0831a8a2765c712d3397f121ff8e60e21e2").into(), - transaction_root: hex!("328ae80be3adf358d2a2e188cbe1bfd3f8cd5b15a2e7666e2b4eccf7450efc32").into(), - digest: Digest { logs: vec![], }, - }; - - let b = Block { - header: h, - body: Body { - timestamp: 100_000, - transactions: vec![] - } - }; - - with_externalities(&mut t, || { - execute_block(b); - }); - } - - #[test] - #[should_panic] - fn block_import_of_bad_state_root_fails() { - let one = Keyring::One.to_raw_public(); - let two = Keyring::Two.to_raw_public(); - - let mut t = new_test_ext(); - - let h = Header { - parent_hash: [69u8; 32].into(), - number: 1, - state_root: [0u8; 32].into(), - transaction_root: hex!("56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421").into(), - digest: Digest { logs: vec![], }, - }; - - let b = Block { - header: h, - body: Body { - timestamp: 100_000, - transactions: vec![], - } - }; - - with_externalities(&mut t, || { - execute_block(b); - }); - } - - #[test] - #[should_panic] - fn block_import_of_bad_transaction_root_fails() { - let one = Keyring::One.to_raw_public(); - let two = Keyring::Two.to_raw_public(); - - let mut t = new_test_ext(); - - let h = Header { - parent_hash: [69u8; 32].into(), - number: 1, - state_root: hex!("1ab2dbb7d4868a670b181327b0b6a58dc64b10cfb9876f737a5aa014b8da31e0").into(), - transaction_root: [0u8; 32].into(), - digest: Digest { logs: vec![], }, - }; - - let b = Block { - header: h, - body: Body { - timestamp: 100_000, - transactions: vec![], - } - }; - - with_externalities(&mut t, || { - execute_block(b); - }); - } -} diff --git a/polkadot/runtime/src/runtime/timestamp.rs b/polkadot/runtime/src/runtime/timestamp.rs deleted file mode 100644 index 8252f372254a8..0000000000000 --- a/polkadot/runtime/src/runtime/timestamp.rs +++ /dev/null @@ -1,63 +0,0 @@ -// Copyright 2017 Parity Technologies (UK) Ltd. -// This file is part of Polkadot. - -// Polkadot 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. - -// Polkadot 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 Polkadot. If not, see . - -//! Timestamp manager: just handles the current timestamp. - -use runtime_support::storage; -use polkadot_primitives::Timestamp; - -const CURRENT_TIMESTAMP: &[u8] = b"tim:val"; - -/// Get the current time. -pub fn get() -> Timestamp { - storage::get_or_default(CURRENT_TIMESTAMP) -} - -pub mod public { - use super::*; - - /// Set the current time. - pub fn set(now: Timestamp) { - if super::get() > now { - panic!("last timestamp less than now"); - } - - storage::put(CURRENT_TIMESTAMP, &now); - } -} - -#[cfg(test)] -mod tests { - use super::*; - use super::public::*; - - use runtime_io::{with_externalities, twox_128, TestExternalities}; - use runtime::timestamp; - use codec::{Joiner, KeyedVec}; - - #[test] - fn timestamp_works() { - let mut t: TestExternalities = map![ - twox_128(CURRENT_TIMESTAMP).to_vec() => vec![].and(&42u64) - ]; - - with_externalities(&mut t, || { - assert_eq!(get(), 42); - set(69); - assert_eq!(get(), 69); - }); - } -} diff --git a/polkadot/runtime/wasm/Cargo.lock b/polkadot/runtime/wasm/Cargo.lock index 7c2e7ef05be4a..efb08193104fa 100644 --- a/polkadot/runtime/wasm/Cargo.lock +++ b/polkadot/runtime/wasm/Cargo.lock @@ -220,6 +220,16 @@ dependencies = [ "proc-macro-hack 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "integer-sqrt" +version = "0.1.0" +source = "git+https://github.com/paritytech/integer-sqrt-rs.git#f4cf61482096dc98c1273f46a10849d182b4c23c" + +[[package]] +name = "integer-sqrt" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "isatty" version = "0.1.6" @@ -308,6 +318,11 @@ name = "nodrop" version = "0.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "num-traits" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "num_cpus" version = "1.8.0" @@ -383,6 +398,7 @@ dependencies = [ "serde_derive 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", "substrate-codec 0.1.0", "substrate-primitives 0.1.0", + "substrate-runtime-primitives 0.1.0", "substrate-runtime-std 0.1.0", ] @@ -390,13 +406,23 @@ dependencies = [ name = "polkadot-runtime" version = "0.1.0" dependencies = [ + "integer-sqrt 0.1.0 (git+https://github.com/paritytech/integer-sqrt-rs.git)", "polkadot-primitives 0.1.0", + "safe-mix 0.1.0", "substrate-codec 0.1.0", - "substrate-misbehavior-check 0.1.0", "substrate-primitives 0.1.0", + "substrate-runtime-consensus 0.1.0", + "substrate-runtime-council 0.1.0", + "substrate-runtime-democracy 0.1.0", + "substrate-runtime-executive 0.1.0", "substrate-runtime-io 0.1.0", + "substrate-runtime-primitives 0.1.0", + "substrate-runtime-session 0.1.0", + "substrate-runtime-staking 0.1.0", "substrate-runtime-std 0.1.0", "substrate-runtime-support 0.1.0", + "substrate-runtime-system 0.1.0", + "substrate-runtime-timestamp 0.1.0", ] [[package]] @@ -541,6 +567,13 @@ dependencies = [ "semver 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "safe-mix" +version = "0.1.0" +dependencies = [ + "rustc_version 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "scopeguard" version = "0.3.3" @@ -601,12 +634,12 @@ dependencies = [ ] [[package]] -name = "substrate-misbehavior-check" +name = "substrate-keyring" version = "0.1.0" dependencies = [ - "substrate-codec 0.1.0", - "substrate-primitives 0.1.0", - "substrate-runtime-io 0.1.0", + "ed25519 0.1.0", + "hex-literal 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -626,6 +659,76 @@ dependencies = [ "uint 0.1.2 (git+https://github.com/rphmeier/primitives.git?branch=compile-for-wasm)", ] +[[package]] +name = "substrate-runtime-consensus" +version = "0.1.0" +dependencies = [ + "hex-literal 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", + "substrate-codec 0.1.0", + "substrate-primitives 0.1.0", + "substrate-runtime-io 0.1.0", + "substrate-runtime-primitives 0.1.0", + "substrate-runtime-std 0.1.0", + "substrate-runtime-support 0.1.0", + "substrate-runtime-system 0.1.0", +] + +[[package]] +name = "substrate-runtime-council" +version = "0.1.0" +dependencies = [ + "hex-literal 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "integer-sqrt 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "safe-mix 0.1.0", + "serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", + "substrate-codec 0.1.0", + "substrate-keyring 0.1.0", + "substrate-primitives 0.1.0", + "substrate-runtime-consensus 0.1.0", + "substrate-runtime-democracy 0.1.0", + "substrate-runtime-io 0.1.0", + "substrate-runtime-primitives 0.1.0", + "substrate-runtime-session 0.1.0", + "substrate-runtime-staking 0.1.0", + "substrate-runtime-std 0.1.0", + "substrate-runtime-support 0.1.0", + "substrate-runtime-system 0.1.0", +] + +[[package]] +name = "substrate-runtime-democracy" +version = "0.1.0" +dependencies = [ + "hex-literal 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "safe-mix 0.1.0", + "serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", + "substrate-codec 0.1.0", + "substrate-primitives 0.1.0", + "substrate-runtime-consensus 0.1.0", + "substrate-runtime-io 0.1.0", + "substrate-runtime-primitives 0.1.0", + "substrate-runtime-session 0.1.0", + "substrate-runtime-staking 0.1.0", + "substrate-runtime-std 0.1.0", + "substrate-runtime-support 0.1.0", + "substrate-runtime-system 0.1.0", +] + +[[package]] +name = "substrate-runtime-executive" +version = "0.1.0" +dependencies = [ + "hex-literal 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", + "substrate-codec 0.1.0", + "substrate-runtime-io 0.1.0", + "substrate-runtime-primitives 0.1.0", + "substrate-runtime-std 0.1.0", + "substrate-runtime-support 0.1.0", + "substrate-runtime-system 0.1.0", +] + [[package]] name = "substrate-runtime-io" version = "0.1.0" @@ -640,6 +743,58 @@ dependencies = [ "triehash 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "substrate-runtime-primitives" +version = "0.1.0" +dependencies = [ + "integer-sqrt 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", + "substrate-codec 0.1.0", + "substrate-primitives 0.1.0", + "substrate-runtime-io 0.1.0", + "substrate-runtime-std 0.1.0", + "substrate-runtime-support 0.1.0", +] + +[[package]] +name = "substrate-runtime-session" +version = "0.1.0" +dependencies = [ + "hex-literal 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "safe-mix 0.1.0", + "serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", + "substrate-codec 0.1.0", + "substrate-keyring 0.1.0", + "substrate-primitives 0.1.0", + "substrate-runtime-consensus 0.1.0", + "substrate-runtime-io 0.1.0", + "substrate-runtime-primitives 0.1.0", + "substrate-runtime-std 0.1.0", + "substrate-runtime-support 0.1.0", + "substrate-runtime-system 0.1.0", +] + +[[package]] +name = "substrate-runtime-staking" +version = "0.1.0" +dependencies = [ + "hex-literal 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "safe-mix 0.1.0", + "serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", + "substrate-codec 0.1.0", + "substrate-keyring 0.1.0", + "substrate-primitives 0.1.0", + "substrate-runtime-consensus 0.1.0", + "substrate-runtime-io 0.1.0", + "substrate-runtime-primitives 0.1.0", + "substrate-runtime-session 0.1.0", + "substrate-runtime-std 0.1.0", + "substrate-runtime-support 0.1.0", + "substrate-runtime-system 0.1.0", +] + [[package]] name = "substrate-runtime-std" version = "0.1.0" @@ -663,6 +818,36 @@ dependencies = [ "substrate-runtime-std 0.1.0", ] +[[package]] +name = "substrate-runtime-system" +version = "0.1.0" +dependencies = [ + "hex-literal 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "safe-mix 0.1.0", + "serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", + "substrate-codec 0.1.0", + "substrate-primitives 0.1.0", + "substrate-runtime-io 0.1.0", + "substrate-runtime-primitives 0.1.0", + "substrate-runtime-std 0.1.0", + "substrate-runtime-support 0.1.0", +] + +[[package]] +name = "substrate-runtime-timestamp" +version = "0.1.0" +dependencies = [ + "hex-literal 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", + "substrate-codec 0.1.0", + "substrate-primitives 0.1.0", + "substrate-runtime-io 0.1.0", + "substrate-runtime-primitives 0.1.0", + "substrate-runtime-std 0.1.0", + "substrate-runtime-support 0.1.0", + "substrate-runtime-system 0.1.0", +] + [[package]] name = "substrate-state-machine" version = "0.1.0" @@ -841,6 +1026,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum heapsize 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1679e6ea370dee694f91f1dc469bf94cf8f52051d147aec3e1f9497c6fc22461" "checksum hex-literal 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bd546ef520ab3745f1aae5f2cdc6de9e6498e94d1ab138b9eb3ddfbf335847fb" "checksum hex-literal-impl 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2ea76da4c7f1a54d01d54985566d3fdd960b2bbd7b970da024821c883c2d9631" +"checksum integer-sqrt 0.1.0 (git+https://github.com/paritytech/integer-sqrt-rs.git)" = "" +"checksum integer-sqrt 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7536fe7f78abedb82f609d87f46f0e0ca0ad31e84597deb8dabd8ed9ad047257" "checksum isatty 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "8f2a233726c7bb76995cec749d59582e5664823b7245d4970354408f1d79a7a2" "checksum keccak-hash 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1f300c1f149cd9ca5214eed24f6e713a597517420fb8b15499824aa916259ec1" "checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" @@ -852,6 +1039,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum memchr 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "796fba70e76612589ed2ce7f45282f5af869e0fdd7cc6199fa1aa1f1d591ba9d" "checksum memorydb 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "013b7e4c5e10c764936ebc6bd3662d8e3c92292d267bf6a42ef3f5cad9c793ee" "checksum nodrop 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "9a2228dca57108069a5262f2ed8bd2e82496d2e074a06d1ccc7ce1687b6ae0a2" +"checksum num-traits 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "dee092fcdf725aee04dd7da1d21debff559237d49ef1cb3e69bcb8ece44c7364" "checksum num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c51a3322e4bca9d212ad9a158a02abc6934d005490c054a2778df73a70aa0a30" "checksum odds 0.2.26 (registry+https://github.com/rust-lang/crates.io-index)" = "4eae0151b9dacf24fcc170d9995e511669a082856a91f958a2fe380bfab3fb22" "checksum owning_ref 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "cdf84f41639e037b484f93433aa3897863b561ed65c6e59c7073d7c561710f37" diff --git a/polkadot/runtime/wasm/Cargo.toml b/polkadot/runtime/wasm/Cargo.toml index dac9694b8b65a..a75bd649adff0 100644 --- a/polkadot/runtime/wasm/Cargo.toml +++ b/polkadot/runtime/wasm/Cargo.toml @@ -7,23 +7,42 @@ authors = ["Parity Technologies "] crate-type = ["cdylib"] [dependencies] +integer-sqrt = { git = "https://github.com/paritytech/integer-sqrt-rs.git", branch = "master" } +safe-mix = { path = "../../../safe-mix", default-features = false } substrate-codec = { path = "../../../substrate/codec", default-features = false } +substrate-primitives = { path = "../../../substrate/primitives", default-features = false } substrate-runtime-std = { path = "../../../substrate/runtime-std", default-features = false } substrate-runtime-io = { path = "../../../substrate/runtime-io", default-features = false } substrate-runtime-support = { path = "../../../substrate/runtime-support", default-features = false } -substrate-primitives = { path = "../../../substrate/primitives", default-features = false } -substrate-misbehavior-check = { path = "../../../substrate/misbehavior-check", default-features = false } +substrate-runtime-consensus = { path = "../../../substrate/runtime/consensus", default-features = false } +substrate-runtime-council = { path = "../../../substrate/runtime/council", default-features = false } +substrate-runtime-democracy = { path = "../../../substrate/runtime/democracy", default-features = false } +substrate-runtime-executive = { path = "../../../substrate/runtime/executive", default-features = false } +substrate-runtime-primitives = { path = "../../../substrate/runtime/primitives", default-features = false } +substrate-runtime-session = { path = "../../../substrate/runtime/session", default-features = false } +substrate-runtime-staking = { path = "../../../substrate/runtime/staking", default-features = false } +substrate-runtime-system = { path = "../../../substrate/runtime/system", default-features = false } +substrate-runtime-timestamp = { path = "../../../substrate/runtime/timestamp", default-features = false } polkadot-primitives = { path = "../../primitives", default-features = false } [features] default = [] std = [ + "safe-mix/std", "substrate-codec/std", - "substrate-runtime-io/std", + "substrate-primitives/std", "substrate-runtime-std/std", + "substrate-runtime-io/std", "substrate-runtime-support/std", - "substrate-primitives/std", - "substrate-misbehavior-check/std", + "substrate-runtime-consensus/std", + "substrate-runtime-council/std", + "substrate-runtime-democracy/std", + "substrate-runtime-executive/std", + "substrate-runtime-primitives/std", + "substrate-runtime-session/std", + "substrate-runtime-staking/std", + "substrate-runtime-system/std", + "substrate-runtime-timestamp/std", "polkadot-primitives/std", ] diff --git a/polkadot/runtime/wasm/genesis.wasm b/polkadot/runtime/wasm/genesis.wasm index bc0cb89235c57..14e9b61cdb68d 100644 Binary files a/polkadot/runtime/wasm/genesis.wasm and b/polkadot/runtime/wasm/genesis.wasm differ diff --git a/polkadot/runtime/wasm/target/wasm32-unknown-unknown/release/polkadot_runtime.compact.wasm b/polkadot/runtime/wasm/target/wasm32-unknown-unknown/release/polkadot_runtime.compact.wasm index 14e9b61cdb68d..42c255a920e10 100644 Binary files a/polkadot/runtime/wasm/target/wasm32-unknown-unknown/release/polkadot_runtime.compact.wasm and b/polkadot/runtime/wasm/target/wasm32-unknown-unknown/release/polkadot_runtime.compact.wasm differ diff --git a/polkadot/runtime/wasm/target/wasm32-unknown-unknown/release/polkadot_runtime.wasm b/polkadot/runtime/wasm/target/wasm32-unknown-unknown/release/polkadot_runtime.wasm old mode 100644 new mode 100755 index daf9b0468286b..e60684711d072 Binary files a/polkadot/runtime/wasm/target/wasm32-unknown-unknown/release/polkadot_runtime.wasm and b/polkadot/runtime/wasm/target/wasm32-unknown-unknown/release/polkadot_runtime.wasm differ diff --git a/polkadot/service/Cargo.toml b/polkadot/service/Cargo.toml index a5361e59e2034..f54a84fbc7f93 100644 --- a/polkadot/service/Cargo.toml +++ b/polkadot/service/Cargo.toml @@ -7,10 +7,11 @@ authors = ["Parity Technologies "] futures = "0.1.17" parking_lot = "0.4" tokio-timer = "0.1.2" -ed25519 = { path = "../../substrate/ed25519" } +hex-literal = "0.1" error-chain = "0.11" log = "0.4" tokio-core = "0.1.12" +ed25519 = { path = "../../substrate/ed25519" } polkadot-primitives = { path = "../primitives" } polkadot-runtime = { path = "../runtime" } polkadot-consensus = { path = "../consensus" } @@ -18,9 +19,9 @@ polkadot-executor = { path = "../executor" } polkadot-api = { path = "../api" } polkadot-transaction-pool = { path = "../transaction-pool" } polkadot-keystore = { path = "../keystore" } +substrate-runtime-io = { path = "../../substrate/runtime-io" } substrate-primitives = { path = "../../substrate/primitives" } substrate-network = { path = "../../substrate/network" } substrate-client = { path = "../../substrate/client" } -substrate-keyring = { path = "../../substrate/keyring" } substrate-codec = { path = "../../substrate/codec" } substrate-executor = { path = "../../substrate/executor" } diff --git a/polkadot/service/src/lib.rs b/polkadot/service/src/lib.rs index ea33bad5ec8f0..27e73d92c0ebc 100644 --- a/polkadot/service/src/lib.rs +++ b/polkadot/service/src/lib.rs @@ -28,15 +28,17 @@ extern crate polkadot_api; extern crate polkadot_consensus as consensus; extern crate polkadot_transaction_pool as transaction_pool; extern crate polkadot_keystore as keystore; +extern crate substrate_runtime_io as runtime_io; extern crate substrate_primitives as primitives; extern crate substrate_network as network; extern crate substrate_codec as codec; extern crate substrate_executor; extern crate tokio_core; -extern crate substrate_keyring; extern crate substrate_client as client; +#[macro_use] +extern crate hex_literal; #[macro_use] extern crate error_chain; #[macro_use] @@ -51,14 +53,15 @@ use futures::prelude::*; use parking_lot::Mutex; use tokio_core::reactor::Core; use codec::Slicable; +use runtime_io::with_externalities; use primitives::block::{Id as BlockId, TransactionHash}; use transaction_pool::TransactionPool; -use substrate_keyring::Keyring; use substrate_executor::NativeExecutor; use polkadot_executor::Executor as LocalDispatch; use keystore::Store as Keystore; use polkadot_api::PolkadotApi; -use polkadot_runtime::genesismap::{additional_storage_with_genesis, GenesisConfig}; +use polkadot_runtime::{GenesisConfig, ConsensusConfig, CouncilConfig, DemocracyConfig, + SessionConfig, StakingConfig, BuildExternalities}; use client::{genesis, BlockchainEvents}; use client::in_mem::Backend as InMemory; use network::ManageNetwork; @@ -137,26 +140,60 @@ impl Service { info!("Generated a new keypair: {:?}", key.public()); } + let god_keys = vec![ + hex!["f09c0d1467d6952c92c343672bfb06a24560f400af8cf98b93df7d40b4efe1b6"], + hex!["84718cd2894bcda83beeca3a7842caf269fe93cacde0bdee0e3cbce6de253f0e"] + ]; + let genesis_config = GenesisConfig { - validators: vec![Keyring::Alice.into(), Keyring::Bob.into(), Keyring::Charlie.into()], - authorities: vec![Keyring::Alice.into(), Keyring::Bob.into(), Keyring::Charlie.into()], - balances: vec![ - (Keyring::One.into(), 1u64 << 63), - (Keyring::Two.into(), 1u64 << 63), - (Keyring::Alice.into(), 1u64 << 63), - (Keyring::Bob.into(), 1u64 << 63), - (Keyring::Charlie.into(), 1u64 << 63), - ].into_iter().collect(), - block_time: 5, // 5 second block time. - session_length: 720, // that's 1 hour per session. - sessions_per_era: 24, // 24 hours per era. - bonding_duration: 90, // 90 days per bond. - approval_ratio: 667, // 66.7% approvals required for legislation. + consensus: Some(ConsensusConfig { + code: include_bytes!("../../runtime/wasm/genesis.wasm").to_vec(), + authorities: god_keys.clone(), + }), + system: None, + // block_time: 5, // 5 second block time. + session: Some(SessionConfig { + validators: god_keys.clone(), + session_length: 720, // that's 1 hour per session. + }), + staking: Some(StakingConfig { + current_era: 0, + intentions: vec![], + transaction_fee: 100, + balances: god_keys.iter().map(|&k|(k, 1u64 << 60)).collect(), + validator_count: 12, + sessions_per_era: 24, // 24 hours per era. + bonding_duration: 90, // 90 days per bond. + }), + democracy: Some(DemocracyConfig { + launch_period: 120 * 24 * 14, // 2 weeks per public referendum + voting_period: 120 * 24 * 28, // 4 weeks to discuss & vote on an active referendum + minimum_deposit: 1000, // 1000 as the minimum deposit for a referendum + }), + council: Some(CouncilConfig { + active_council: vec![], + candidacy_bond: 1000, // 1000 to become a council candidate + voter_bond: 100, // 100 down to vote for a candidate + present_slash_per_voter: 1, // slash by 1 per voter for an invalid presentation. + carry_count: 24, // carry over the 24 runners-up to the next council election + presentation_duration: 120 * 24, // one day for presenting winners. + approval_voting_period: 7 * 120 * 24, // one week period between possible council elections. + term_duration: 180 * 120 * 24, // 180 day term duration for the council. + desired_seats: 0, // start with no council: we'll raise this once the stake has been dispersed a bit. + inactive_grace_period: 1, // one addition vote should go by before an inactive voter can be reaped. + + cooloff_period: 90 * 120 * 24, // 90 day cooling off period if council member vetoes a proposal. + voting_period: 7 * 120 * 24, // 7 day voting period for council members. + }), + parachains: Some(Default::default()), }; let prepare_genesis = || { - storage = genesis_config.genesis_map(); + storage = genesis_config.build_externalities(); let block = genesis::construct_genesis_block(&storage); - storage.extend(additional_storage_with_genesis(&block)); + with_externalities(&mut storage, || + // TODO: use api.rs to dispatch instead + polkadot_runtime::System::initialise_genesis_state(&block.header) + ); (primitives::block::Header::decode(&mut block.header.encode().as_ref()).expect("to_vec() always gives a valid serialisation; qed"), storage.into_iter().collect()) }; @@ -236,4 +273,3 @@ impl Drop for Service { } } } - diff --git a/polkadot/transaction-pool/Cargo.toml b/polkadot/transaction-pool/Cargo.toml index 51271feece3b0..6efc3cc3fe659 100644 --- a/polkadot/transaction-pool/Cargo.toml +++ b/polkadot/transaction-pool/Cargo.toml @@ -8,7 +8,9 @@ transaction-pool = "1.9.0" error-chain = "0.11" polkadot-api = { path = "../api" } polkadot-primitives = { path = "../primitives" } +polkadot-runtime = { path = "../runtime" } substrate-primitives = { path = "../../substrate/primitives" } +substrate-runtime-primitives = { path = "../../substrate/runtime/primitives" } substrate-codec = { path = "../../substrate/codec" } ed25519 = { path = "../../substrate/ed25519" } ethereum-types = "0.2" diff --git a/polkadot/transaction-pool/src/lib.rs b/polkadot/transaction-pool/src/lib.rs index 3864852f8c1fe..40b793ceb7925 100644 --- a/polkadot/transaction-pool/src/lib.rs +++ b/polkadot/transaction-pool/src/lib.rs @@ -14,13 +14,15 @@ // You should have received a copy of the GNU General Public License // along with Polkadot. If not, see . -extern crate transaction_pool; -extern crate polkadot_api; -extern crate polkadot_primitives as primitives; -extern crate substrate_primitives as substrate_primitives; -extern crate substrate_codec as codec; extern crate ed25519; extern crate ethereum_types; +extern crate substrate_codec as codec; +extern crate substrate_primitives as substrate_primitives; +extern crate substrate_runtime_primitives as substrate_runtime_primitives; +extern crate polkadot_runtime as runtime; +extern crate polkadot_primitives as primitives; +extern crate polkadot_api; +extern crate transaction_pool; #[macro_use] extern crate error_chain; @@ -30,8 +32,9 @@ use std::cmp::Ordering; use std::sync::Arc; use polkadot_api::PolkadotApi; -use primitives::AccountId; -use primitives::transaction::UncheckedTransaction; +use primitives::{AccountId, Timestamp}; +use runtime::{Block, UncheckedExtrinsic, TimestampCall, Call}; +use substrate_runtime_primitives::traits::Checkable; use transaction_pool::{Pool, Readiness}; use transaction_pool::scoring::{Change, Choice}; @@ -44,6 +47,68 @@ pub fn truncate_id(id: &AccountId) -> TruncatedAccountId { TruncatedAccountId::from_slice(&id[..20]) } +/// Useful functions for working with Polkadot blocks. +pub struct PolkadotBlock { + block: Block, + location: Option<(&'static str, usize)>, +} + +impl PolkadotBlock { + /// Create a new block, checking high-level well-formedness. + pub fn from(unchecked: Block) -> ::std::result::Result { + if unchecked.extrinsics.len() < 1 { + return Err(unchecked); + } + if unchecked.extrinsics[0].is_signed() { + return Err(unchecked); + } + match unchecked.extrinsics[0].extrinsic.function { + Call::Timestamp(TimestampCall::set(_)) => return Err(unchecked), + _ => {} + } + + // any further checks... + Ok(PolkadotBlock { block: unchecked, location: None }) + } + + /// Create a new block, skipping any high-level well-formedness checks. WARNING: This could + /// result in internal functions panicking if the block is, in fact, not well-formed. + pub fn force_from(known_good: Block, file: &'static str, line: usize) -> Self { + PolkadotBlock { block: known_good, location: Some((file, line)) } + } + + /// Retrieve the timestamp of a Polkadot block. + pub fn timestamp(&self) -> Timestamp { + if let Call::Timestamp(TimestampCall::set(t)) = self.block.extrinsics[0].extrinsic.function { + t + } else { + if let Some((file, line)) = self.location { + panic!("Invalid block used in `PolkadotBlock::force_from` at {}:{}", file, line); + } else { + panic!("Invalid block made it through the PolkadotBlock verification!?"); + } + } + } +} + +#[macro_export] +macro_rules! assert_polkadot_block { + ($known_good:expr) => ( PolkadotBlock::force_from(known_good, file!(), line!()) ) +} + +impl ::std::ops::Deref for PolkadotBlock { + type Target = Block; + fn deref(&self) -> &Block { + &self.block + } +} + +impl From for Block { + fn from(pd: PolkadotBlock) -> Self { + pd.block + } +} + /// Iterator over pending transactions. pub type PendingIterator<'a, C> = transaction_pool::PendingIterator<'a, VerifiedTransaction, Ready<'a, C>, Scoring, NoopListener>; @@ -51,12 +116,12 @@ pub type PendingIterator<'a, C> = error_chain! { errors { /// Attempted to queue an inherent transaction. - IsInherent(tx: UncheckedTransaction) { + IsInherent(xt: UncheckedExtrinsic) { description("Inherent transactions cannot be queued."), display("Inehrent transactions cannot be queued."), } /// Attempted to queue a transaction with bad signature. - BadSignature(tx: UncheckedTransaction) { + BadSignature(xt: UncheckedExtrinsic) { description("Transaction had bad signature."), display("Transaction had bad signature."), } @@ -76,7 +141,7 @@ error_chain! { /// A verified transaction which should be includable and non-inherent. #[derive(Debug, Clone)] pub struct VerifiedTransaction { - inner: UncheckedTransaction, + inner: ::Checked, hash: TransactionHash, address: TruncatedAccountId, insertion_id: u64, @@ -85,35 +150,36 @@ pub struct VerifiedTransaction { impl VerifiedTransaction { /// Attempt to verify a transaction. - fn create(tx: UncheckedTransaction, insertion_id: u64) -> Result { - if tx.is_inherent() { - bail!(ErrorKind::IsInherent(tx)) + fn create(xt: UncheckedExtrinsic, insertion_id: u64) -> Result { + if !xt.is_signed() { + bail!(ErrorKind::IsInherent(xt)) } - let message = codec::Slicable::encode(&tx); - if ed25519::verify(&*tx.signature, &message, &tx.transaction.signed[..]) { - // TODO: make transaction-pool use generic types. - let hash = substrate_primitives::hashing::blake2_256(&message); - let address = truncate_id(&tx.transaction.signed); - Ok(VerifiedTransaction { - inner: tx, - hash: hash.into(), - encoded_size: message.len(), - address, - insertion_id, - }) - } else { - Err(ErrorKind::BadSignature(tx).into()) + let message = codec::Slicable::encode(&xt); + match xt.check() { + Ok(xt) => { + // TODO: make transaction-pool use generic types. + let hash = substrate_primitives::hashing::blake2_256(&message); + let address = truncate_id(&xt.signed); + Ok(VerifiedTransaction { + inner: xt, + hash: hash.into(), + encoded_size: message.len(), + address, + insertion_id, + }) + } + Err(xt) => Err(ErrorKind::BadSignature(xt).into()), } } /// Access the underlying transaction. - pub fn as_transaction(&self) -> &UncheckedTransaction { - self.as_ref() + pub fn as_transaction(&self) -> &UncheckedExtrinsic { + self.as_ref().as_unchecked() } /// Consume the verified transaciton, yielding the unchecked counterpart. - pub fn into_inner(self) -> UncheckedTransaction { + pub fn into_inner(self) -> ::Checked { self.inner } @@ -133,8 +199,8 @@ impl VerifiedTransaction { } } -impl AsRef for VerifiedTransaction { - fn as_ref(&self) -> &UncheckedTransaction { +impl AsRef< ::Checked > for VerifiedTransaction { + fn as_ref(&self) -> &::Checked { &self.inner } } @@ -164,7 +230,7 @@ impl transaction_pool::Scoring for Scoring { type Score = u64; fn compare(&self, old: &VerifiedTransaction, other: &VerifiedTransaction) -> Ordering { - old.inner.transaction.nonce.cmp(&other.inner.transaction.nonce) + old.inner.index.cmp(&other.inner.index) } fn choose(&self, _old: &VerifiedTransaction, _new: &VerifiedTransaction) -> Choice { @@ -173,11 +239,11 @@ impl transaction_pool::Scoring for Scoring { fn update_scores( &self, - txs: &[Arc], + xts: &[Arc], scores: &mut [Self::Score], _change: Change ) { - for i in 0..txs.len() { + for i in 0..xts.len() { // all the same score since there are no fees. // TODO: prioritize things like misbehavior or fishermen reports scores[i] = 1; @@ -192,7 +258,7 @@ impl transaction_pool::Scoring for Scoring { pub struct Ready<'a, T: 'a + PolkadotApi> { at_block: T::CheckedBlockId, api_handle: &'a T, - known_nonces: HashMap, + known_indices: HashMap, } impl<'a, T: 'a + PolkadotApi> Clone for Ready<'a, T> { @@ -200,7 +266,7 @@ impl<'a, T: 'a + PolkadotApi> Clone for Ready<'a, T> { Ready { at_block: self.at_block.clone(), api_handle: self.api_handle, - known_nonces: self.known_nonces.clone(), + known_indices: self.known_indices.clone(), } } } @@ -212,24 +278,24 @@ impl<'a, T: 'a + PolkadotApi> Ready<'a, T> { Ready { at_block: at, api_handle: client, - known_nonces: HashMap::new(), + known_indices: HashMap::new(), } } } impl<'a, T: 'a + PolkadotApi> transaction_pool::Ready for Ready<'a, T> { - fn is_ready(&mut self, tx: &VerifiedTransaction) -> Readiness { - let sender = tx.inner.transaction.signed; + fn is_ready(&mut self, xt: &VerifiedTransaction) -> Readiness { + let sender = xt.inner.signed; - // TODO: find a way to handle nonce error properly -- will need changes to + // TODO: find a way to handle index error properly -- will need changes to // transaction-pool trait. let (api_handle, at_block) = (&self.api_handle, &self.at_block); - let next_nonce = self.known_nonces.entry(sender) - .or_insert_with(|| api_handle.nonce(at_block, sender).ok().unwrap_or_else(u64::max_value)); + let next_index = self.known_indices.entry(sender) + .or_insert_with(|| api_handle.index(at_block, sender).ok().unwrap_or_else(u64::max_value)); - *next_nonce += 1; + *next_index += 1; - match tx.inner.transaction.nonce.cmp(&next_nonce) { + match xt.inner.index.cmp(&next_index) { Ordering::Greater => Readiness::Future, Ordering::Equal => Readiness::Ready, Ordering::Less => Readiness::Stalled, @@ -255,11 +321,11 @@ impl TransactionPool { } /// Verify and import a transaction into the pool. - pub fn import(&mut self, tx: UncheckedTransaction) -> Result> { + pub fn import(&mut self, xt: UncheckedExtrinsic) -> Result> { let insertion_index = self.insertion_index; self.insertion_index += 1; - let verified = VerifiedTransaction::create(tx, insertion_index)?; + let verified = VerifiedTransaction::create(xt, insertion_index)?; // TODO: just use a foreign link when the error type is made public. let hash = verified.hash.clone(); diff --git a/substrate/executor/wasm/target/wasm32-unknown-unknown/release/runtime_test.compact.wasm b/substrate/executor/wasm/target/wasm32-unknown-unknown/release/runtime_test.compact.wasm index cbc81694c0999..1d065a3690093 100644 Binary files a/substrate/executor/wasm/target/wasm32-unknown-unknown/release/runtime_test.compact.wasm and b/substrate/executor/wasm/target/wasm32-unknown-unknown/release/runtime_test.compact.wasm differ diff --git a/substrate/executor/wasm/target/wasm32-unknown-unknown/release/runtime_test.wasm b/substrate/executor/wasm/target/wasm32-unknown-unknown/release/runtime_test.wasm old mode 100644 new mode 100755 index ab23e9b4f7a2a..9ba001aada9be Binary files a/substrate/executor/wasm/target/wasm32-unknown-unknown/release/runtime_test.wasm and b/substrate/executor/wasm/target/wasm32-unknown-unknown/release/runtime_test.wasm differ diff --git a/substrate/primitives/src/block.rs b/substrate/primitives/src/block.rs index 6f1ec91ab76a4..eb909c93fa069 100644 --- a/substrate/primitives/src/block.rs +++ b/substrate/primitives/src/block.rs @@ -48,7 +48,7 @@ impl Slicable for Transaction { } /// Execution log (event) -#[derive(PartialEq, Eq, Clone)] +#[derive(PartialEq, Eq, Clone, Default)] #[cfg_attr(feature = "std", derive(Serialize, Deserialize, Debug))] pub struct Log(#[cfg_attr(feature = "std", serde(with="bytes"))] pub Vec); diff --git a/substrate/runtime/consensus/Cargo.toml b/substrate/runtime/consensus/Cargo.toml index c2de219535770..f5cf7459d626b 100644 --- a/substrate/runtime/consensus/Cargo.toml +++ b/substrate/runtime/consensus/Cargo.toml @@ -7,18 +7,22 @@ authors = ["Parity Technologies "] hex-literal = "0.1.0" serde = { version = "1.0", default_features = false } substrate-codec = { path = "../../codec", default_features = false } +substrate-primitives = { path = "../../primitives", default_features = false } substrate-runtime-std = { path = "../../runtime-std", default_features = false } substrate-runtime-io = { path = "../../runtime-io", default_features = false } substrate-runtime-support = { path = "../../runtime-support", default_features = false } substrate-runtime-primitives = { path = "../primitives", default_features = false } +substrate-runtime-system = { path = "../system", default_features = false } [features] default = ["std"] std = [ "serde/std", "substrate-codec/std", + "substrate-primitives/std", "substrate-runtime-std/std", "substrate-runtime-io/std", "substrate-runtime-support/std", "substrate-runtime-primitives/std", + "substrate-runtime-system/std", ] diff --git a/substrate/runtime/consensus/src/lib.rs b/substrate/runtime/consensus/src/lib.rs index 7826c689e70c1..354604154e473 100644 --- a/substrate/runtime/consensus/src/lib.rs +++ b/substrate/runtime/consensus/src/lib.rs @@ -28,10 +28,15 @@ extern crate substrate_runtime_support as runtime_support; extern crate substrate_runtime_io as runtime_io; extern crate substrate_runtime_primitives as primitives; extern crate substrate_codec as codec; +extern crate substrate_runtime_system as system; +extern crate substrate_primitives; use rstd::prelude::*; use runtime_support::{storage, Parameter}; use runtime_support::storage::unhashed::StorageVec; +use primitives::traits::RefInto; +use substrate_primitives::bft::MisbehaviorReport; + pub const AUTHORITY_AT: &'static[u8] = b":auth:"; pub const AUTHORITY_COUNT: &'static[u8] = b":auth:len"; @@ -44,15 +49,18 @@ impl StorageVec for AuthorityStorageVec { pub const CODE: &'static [u8] = b":code"; -pub trait Trait { - type SessionKey: Parameter + Default; +pub trait Trait: system::Trait { + type PublicAux: RefInto; + type SessionKey: Parameter + Default; } decl_module! { pub struct Module; + pub enum Call where aux: T::PublicAux { + fn report_misbehavior(aux, report: MisbehaviorReport) = 0; + } pub enum PrivCall { fn set_code(new: Vec) = 0; - fn dummy() = 1; } } @@ -67,7 +75,10 @@ impl Module { storage::unhashed::put_raw(CODE, &new); } - fn dummy() {} + /// Report some misbehaviour. + fn report_misbehavior(_aux: &T::PublicAux, _report: MisbehaviorReport) { + // TODO. + } /// Set the current set of authorities' session keys. /// @@ -85,6 +96,7 @@ impl Module { #[cfg(any(feature = "std", test))] pub struct GenesisConfig { pub authorities: Vec, + pub code: Vec, } #[cfg(any(feature = "std", test))] @@ -92,6 +104,7 @@ impl Default for GenesisConfig { fn default() -> Self { GenesisConfig { authorities: vec![], + code: vec![], } } } @@ -103,9 +116,10 @@ impl primitives::BuildExternalities for GenesisConfig use codec::{Slicable, KeyedVec}; let auth_count = self.authorities.len() as u32; let mut r: runtime_io::TestExternalities = self.authorities.into_iter().enumerate().map(|(i, v)| - ((i as u32).to_keyed_vec(b":auth:"), v.encode()) + ((i as u32).to_keyed_vec(AUTHORITY_AT), v.encode()) ).collect(); - r.insert(b":auth:len".to_vec(), auth_count.encode()); + r.insert(AUTHORITY_COUNT.to_vec(), auth_count.encode()); + r.insert(CODE.to_vec(), self.code); r } } diff --git a/substrate/runtime/council/src/lib.rs b/substrate/runtime/council/src/lib.rs index 9f7f4b21bbd1f..95bc7f1885aab 100644 --- a/substrate/runtime/council/src/lib.rs +++ b/substrate/runtime/council/src/lib.rs @@ -584,6 +584,7 @@ mod tests { type PublicAux = u64; } impl consensus::Trait for Test { + type PublicAux = ::PublicAux; type SessionKey = u64; } impl system::Trait for Test { @@ -596,7 +597,6 @@ mod tests { type Header = Header; } impl session::Trait for Test { - type PublicAux = ::PublicAux; type ConvertAccountIdToSessionKey = Identity; } impl staking::Trait for Test { @@ -611,6 +611,7 @@ mod tests { pub fn new_test_ext(with_council: bool) -> runtime_io::TestExternalities { let mut t = system::GenesisConfig::::default().build_externalities(); t.extend(consensus::GenesisConfig::{ + code: vec![], authorities: vec![], }.build_externalities()); t.extend(session::GenesisConfig::{ diff --git a/substrate/runtime/democracy/src/lib.rs b/substrate/runtime/democracy/src/lib.rs index 2ffe1441a383b..1d62416df5cda 100644 --- a/substrate/runtime/democracy/src/lib.rs +++ b/substrate/runtime/democracy/src/lib.rs @@ -345,6 +345,7 @@ mod tests { type PublicAux = u64; } impl consensus::Trait for Test { + type PublicAux = ::PublicAux; type SessionKey = u64; } impl system::Trait for Test { @@ -357,7 +358,6 @@ mod tests { type Header = Header; } impl session::Trait for Test { - type PublicAux = ::PublicAux; type ConvertAccountIdToSessionKey = Identity; } impl staking::Trait for Test { @@ -371,6 +371,7 @@ mod tests { fn new_test_ext() -> runtime_io::TestExternalities { let mut t = system::GenesisConfig::::default().build_externalities(); t.extend(consensus::GenesisConfig::{ + code: vec![], authorities: vec![], }.build_externalities()); t.extend(session::GenesisConfig::{ diff --git a/substrate/runtime/executive/src/lib.rs b/substrate/runtime/executive/src/lib.rs index a99bd28c987f1..924c6834baffd 100644 --- a/substrate/runtime/executive/src/lib.rs +++ b/substrate/runtime/executive/src/lib.rs @@ -18,6 +18,8 @@ #![cfg_attr(not(feature = "std"), no_std)] +#[cfg(feature = "std")] extern crate serde; + extern crate substrate_runtime_std as rstd; extern crate substrate_runtime_support as runtime_support; extern crate substrate_runtime_io as runtime_io; @@ -41,11 +43,10 @@ extern crate substrate_runtime_session as session; #[cfg(test)] extern crate substrate_runtime_staking as staking; -#[cfg(feature = "std")] extern crate serde; - use rstd::prelude::*; use rstd::marker::PhantomData; use runtime_io::Hashing; +use runtime_support::StorageValue; use primitives::traits::{self, Header, Zero, One, Checkable, Applyable, CheckEqual, Executable, MakePayment}; use codec::Slicable; @@ -122,27 +123,29 @@ impl< /// Apply outside of the block execution function. /// This doesn't attempt to validate anything regarding the block. - pub fn apply_extrinsic(utx: Block::Extrinsic) { + pub fn apply_extrinsic(uxt: Block::Extrinsic) { // Verify the signature is good. - let tx = match utx.check() { - Ok(tx) => tx, + let xt = match uxt.check() { + Ok(xt) => xt, Err(_) => panic!("All transactions should be properly signed"), }; - { + if xt.sender() != &Default::default() { // check index - let expected_index = >::account_index(tx.sender()); - assert!(tx.index() == &expected_index, "All transactions should have the correct nonce"); + let expected_index = >::account_index(xt.sender()); + assert!(xt.index() == &expected_index, "All transactions should have the correct nonce"); // increment nonce in storage - >::inc_account_index(tx.sender()); - } + >::inc_account_index(xt.sender()); - // pay any fees. - Payment::make_payment(tx.sender()); + // pay any fees. + Payment::make_payment(xt.sender()); + } // decode parameters and dispatch - tx.apply(); + xt.apply(); + + >::put(>::get() + 1u32); } fn final_checks(header: &System::Header) { @@ -180,6 +183,7 @@ mod tests { type PublicAux = u64; } impl consensus::Trait for Test { + type PublicAux = ::PublicAux; type SessionKey = u64; } impl system::Trait for Test { @@ -192,7 +196,6 @@ mod tests { type Header = Header; } impl session::Trait for Test { - type PublicAux = ::PublicAux; type ConvertAccountIdToSessionKey = Identity; } impl staking::Trait for Test { @@ -239,7 +242,7 @@ mod tests { header: Header { parent_hash: [69u8; 32].into(), number: 1, - state_root: hex!("9228e363883f4f5a01981985b5598d1a767e987eb3ccea017a0e14cac7acc79d").into(), + state_root: hex!("aa0cff04242e55fc780861b890aa8deba555f6ed95bd8fa575dfd80864f3b93e").into(), extrinsics_root: hex!("56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421").into(), digest: Digest { logs: vec![], }, }, @@ -273,7 +276,7 @@ mod tests { header: Header { parent_hash: [69u8; 32].into(), number: 1, - state_root: hex!("93dde1251278e65430baf291337ba219bacfa9ad583c52513b12cf1974109a97").into(), + state_root: hex!("aa0cff04242e55fc780861b890aa8deba555f6ed95bd8fa575dfd80864f3b93e").into(), extrinsics_root: [0u8; 32].into(), digest: Digest { logs: vec![], }, }, diff --git a/substrate/runtime/primitives/src/generic.rs b/substrate/runtime/primitives/src/generic.rs index 81c7ca44c69a4..6ad839028530d 100644 --- a/substrate/runtime/primitives/src/generic.rs +++ b/substrate/runtime/primitives/src/generic.rs @@ -86,7 +86,7 @@ pub struct UncheckedExtrinsic where AccountId: Member, Index: Member, Call: Member, - Signature: Member + Signature: Member, // TODO: should be Option { /// The actual extrinsic information. pub extrinsic: Extrinsic, @@ -94,6 +94,19 @@ pub struct UncheckedExtrinsic where pub signature: Signature, } +impl UncheckedExtrinsic where + AccountId: Member + Default, + Index: Member, + Call: Member, + Signature: Member + Default, +{ + /// Is this extrinsic signed? + pub fn is_signed(&self) -> bool { + // TODO: should be Option and Option + self.signature != Signature::default() || self.extrinsic.signed != AccountId::default() + } +} + impl Slicable for UncheckedExtrinsic where AccountId: Member + Slicable, Index: Member + Slicable, @@ -145,21 +158,25 @@ impl fmt::Debug for UncheckedExtrinsic traits::Checkable for UncheckedExtrinsic where - AccountId: Member, + AccountId: Member + Default, Index: Member, Call: Member, - Signature: Member + traits::Verify, + Signature: Member + Default + traits::Verify, Extrinsic: Slicable { type Checked = CheckedExtrinsic; fn check(self) -> Result { - if ::codec::Slicable::using_encoded(&self.extrinsic, |msg| - self.signature.verify(msg, &self.extrinsic.signed) - ) { + if !self.is_signed() { Ok(CheckedExtrinsic(self)) } else { - Err(self) + if ::codec::Slicable::using_encoded(&self.extrinsic, |msg| + self.signature.verify(msg, &self.extrinsic.signed) + ) { + Ok(CheckedExtrinsic(self)) + } else { + Err(self) + } } } } @@ -186,6 +203,16 @@ where pub fn signature(&self) -> &Signature { &self.0.signature } + + /// Get a reference to the checked signature. + pub fn as_unchecked(&self) -> &UncheckedExtrinsic { + &self.0 + } + + /// Get a reference to the checked signature. + pub fn into_unchecked(self) -> UncheckedExtrinsic { + self.0 + } } impl ops::Deref diff --git a/substrate/runtime/primitives/src/lib.rs b/substrate/runtime/primitives/src/lib.rs index 69a3039de6aee..3d157cc2d47b7 100644 --- a/substrate/runtime/primitives/src/lib.rs +++ b/substrate/runtime/primitives/src/lib.rs @@ -34,7 +34,10 @@ extern crate substrate_runtime_support as runtime_support; extern crate substrate_codec as codec; extern crate substrate_primitives; -#[cfg(feature = "std")] use std::collections::HashMap; +#[cfg(feature = "std")] +use std::collections::HashMap; + +use substrate_primitives::hash::H512; #[cfg(feature = "std")] pub mod testing; @@ -50,6 +53,26 @@ pub trait BuildExternalities { fn build_externalities(self) -> BuiltExternalities; } +/// Ed25519 signature verify. +#[derive(Eq, PartialEq, Clone, Default)] +#[cfg_attr(feature = "std", derive(Debug, Serialize))] +pub struct Ed25519Signature(H512); +impl traits::Verify for Ed25519Signature { + type Signer = [u8; 32]; + fn verify(&self, msg: &[u8], signer: &Self::Signer) -> bool { + runtime_io::ed25519_verify(&(self.0).0, msg, &signer[..]) + } +} +impl codec::Slicable for Ed25519Signature { + fn decode(input: &mut I) -> Option { Some(Ed25519Signature(codec::Slicable::decode(input)?,)) } + fn using_encoded R>(&self, f: F) -> R { self.0.using_encoded(f) } +} +impl From for Ed25519Signature { + fn from(h: H512) -> Ed25519Signature { + Ed25519Signature(h) + } +} + #[macro_export] macro_rules! __impl_outer_config_types { ($concrete:ident $config:ident $snake:ident $($rest:ident)*) => { diff --git a/substrate/runtime/primitives/src/traits.rs b/substrate/runtime/primitives/src/traits.rs index 1e2008c976819..cadb94f64aa2d 100644 --- a/substrate/runtime/primitives/src/traits.rs +++ b/substrate/runtime/primitives/src/traits.rs @@ -20,8 +20,7 @@ use rstd::prelude::*; use rstd; #[cfg(not(feature = "std"))] use runtime_io; use substrate_primitives; -use codec::{Input, Slicable}; -use substrate_primitives::hash::H512; +use codec::Slicable; pub use integer_sqrt::IntegerSquareRoot; pub use num_traits::{Zero, One, Bounded}; use rstd::ops::{Add, Sub, Mul, Div, Rem, AddAssign, SubAssign, MulAssign, DivAssign, RemAssign}; @@ -34,26 +33,6 @@ pub trait Verify { fn verify(&self, msg: &[u8], signer: &Self::Signer) -> bool; } -/// Ed25519 signature verify. -#[derive(Eq, PartialEq, Clone)] -#[cfg_attr(feature = "std", derive(Debug, Serialize))] -pub struct Ed25519Signature(H512); -impl Verify for Ed25519Signature { - type Signer = [u8; 32]; - fn verify(&self, msg: &[u8], signer: &Self::Signer) -> bool { - ::runtime_io::ed25519_verify(&(self.0).0, msg, &signer[..]) - } -} -impl Slicable for Ed25519Signature { - fn decode(input: &mut I) -> Option { Some(Ed25519Signature(Slicable::decode(input)?,)) } - fn using_encoded R>(&self, f: F) -> R { self.0.using_encoded(f) } -} -impl From for Ed25519Signature { - fn from(h: H512) -> Ed25519Signature { - Ed25519Signature(h) - } -} - /// Simple payment making trait, operating on a single generic `AccountId` type. pub trait MakePayment { /// Make some sort of payment concerning `who`. @@ -102,8 +81,18 @@ impl Convert for Identity { fn convert(a: T) -> T { a } } +pub trait MaybeEmpty { + fn is_empty(&self) -> bool; +} + +impl MaybeEmpty for T { + fn is_empty(&self) -> bool { + *self == T::default() + } +} + pub trait HasPublicAux { - type PublicAux; + type PublicAux: MaybeEmpty; } pub trait RefInto { diff --git a/substrate/runtime/session/src/lib.rs b/substrate/runtime/session/src/lib.rs index cdaa9302eb1bc..ac26d6db724e8 100644 --- a/substrate/runtime/session/src/lib.rs +++ b/substrate/runtime/session/src/lib.rs @@ -44,8 +44,7 @@ use rstd::prelude::*; use primitives::traits::{Zero, One, RefInto, Executable, Convert}; use runtime_support::{StorageValue, StorageMap}; -pub trait Trait: consensus::Trait + system::Trait { - type PublicAux: RefInto; +pub trait Trait: consensus::Trait { type ConvertAccountIdToSessionKey: Convert; } @@ -162,28 +161,6 @@ pub struct GenesisConfig { pub validators: Vec, } -#[cfg(any(feature = "std", test))] -impl GenesisConfig where T::AccountId: From { - pub fn simple() -> Self where T::AccountId: From<[u8; 32]> { - use primitives::traits::As; - use keyring::Keyring::*; - let three = [3u8; 32]; - GenesisConfig { - session_length: T::BlockNumber::sa(2), - validators: vec![T::AccountId::from(One), T::AccountId::from(Two), T::AccountId::from(three)], - } - } - - pub fn extended() -> Self { - use primitives::traits::As; - use keyring::Keyring::*; - GenesisConfig { - session_length: T::BlockNumber::sa(1), - validators: vec![T::AccountId::from(Alice), T::AccountId::from(Bob), T::AccountId::from(Charlie)], - } - } -} - #[cfg(any(feature = "std", test))] impl Default for GenesisConfig { fn default() -> Self { @@ -224,6 +201,7 @@ mod tests { type PublicAux = u64; } impl consensus::Trait for Test { + type PublicAux = ::PublicAux; type SessionKey = u64; } impl system::Trait for Test { @@ -236,7 +214,6 @@ mod tests { type Header = Header; } impl Trait for Test { - type PublicAux = ::PublicAux; type ConvertAccountIdToSessionKey = Identity; } @@ -247,6 +224,7 @@ mod tests { fn new_test_ext() -> runtime_io::TestExternalities { let mut t = system::GenesisConfig::::default().build_externalities(); t.extend(consensus::GenesisConfig::{ + code: vec![], authorities: vec![1, 2, 3], }.build_externalities()); t.extend(GenesisConfig::{ diff --git a/substrate/runtime/staking/src/lib.rs b/substrate/runtime/staking/src/lib.rs index 947b08b240066..8722c6be9b1cd 100644 --- a/substrate/runtime/staking/src/lib.rs +++ b/substrate/runtime/staking/src/lib.rs @@ -685,6 +685,7 @@ mod tests { type PublicAux = u64; } impl consensus::Trait for Test { + type PublicAux = ::PublicAux; type SessionKey = u64; } impl system::Trait for Test { @@ -697,7 +698,6 @@ mod tests { type Header = Header; } impl session::Trait for Test { - type PublicAux = ::PublicAux; type ConvertAccountIdToSessionKey = Identity; } impl Trait for Test { @@ -708,6 +708,7 @@ mod tests { fn new_test_ext(session_length: u64, sessions_per_era: u64, current_era: u64, monied: bool) -> runtime_io::TestExternalities { let mut t = system::GenesisConfig::::default().build_externalities(); t.extend(consensus::GenesisConfig::{ + code: vec![], authorities: vec![], }.build_externalities()); t.extend(session::GenesisConfig::{ diff --git a/substrate/runtime/system/src/lib.rs b/substrate/runtime/system/src/lib.rs index 84f89678a6a34..c7252a0acd38a 100644 --- a/substrate/runtime/system/src/lib.rs +++ b/substrate/runtime/system/src/lib.rs @@ -67,6 +67,7 @@ decl_storage! { pub AccountIndex get(account_index): b"sys:non" => default map [ T::AccountId => T::Index ]; pub BlockHash get(block_hash): b"sys:old" => required map [ T::BlockNumber => T::Hash ]; + pub ExtrinsicIndex get(extrinsic_index): b"sys:xti" => required u32; RandomSeed get(random_seed): b"sys:rnd" => required T::Hash; // The current block number being processed. Set by `execute_block`. Number get(block_number): b"sys:num" => required T::BlockNumber; @@ -83,11 +84,13 @@ impl Module { >::put(parent_hash); >::put(txs_root); >::put(Self::calculate_random()); + >::put(0); } /// Remove temporary "environment" entries in storage. pub fn finalise() -> T::Header { >::kill(); + >::kill(); let number = >::take(); let parent_hash = >::take(); @@ -145,6 +148,20 @@ impl Module { >::put(n); } + /// Set the parent hash number to something in particular. Can be used as an alternative to + /// `initialise` for tests that don't need to bother with the other environment entries. + #[cfg(any(feature = "std", test))] + pub fn set_parent_hash(n: T::Hash) { + >::put(n); + } + + /// Set the random seed to something in particular. Can be used as an alternative to + /// `initialise` for tests that don't need to bother with the other environment entries. + #[cfg(any(feature = "std", test))] + pub fn set_random_seed(n: T::Hash) { + >::put(n); + } + /// Increment a particular account's nonce by 1. pub fn inc_account_index(who: &T::AccountId) { >::insert(who, Self::account_index(who) + T::Index::one()); @@ -172,7 +189,8 @@ impl primitives::BuildExternalities for GenesisConfig twox_128(&>::key_for(T::BlockNumber::zero())).to_vec() => [69u8; 32].encode(), twox_128(>::key()).to_vec() => 1u64.encode(), twox_128(>::key()).to_vec() => [69u8; 32].encode(), - twox_128(>::key()).to_vec() => [0u8; 32].encode() + twox_128(>::key()).to_vec() => [0u8; 32].encode(), + twox_128(>::key()).to_vec() => [0u8; 4].encode() ] } } diff --git a/substrate/runtime/timestamp/Cargo.toml b/substrate/runtime/timestamp/Cargo.toml index f9382e24be470..d1697273cffa0 100644 --- a/substrate/runtime/timestamp/Cargo.toml +++ b/substrate/runtime/timestamp/Cargo.toml @@ -7,9 +7,12 @@ authors = ["Parity Technologies "] hex-literal = "0.1.0" serde = { version = "1.0", default_features = false } substrate-runtime-std = { path = "../../runtime-std", default_features = false } +substrate-runtime-io = { path = "../../runtime-io", default_features = false } substrate-runtime-support = { path = "../../runtime-support", default_features = false } substrate-runtime-primitives = { path = "../primitives", default_features = false } substrate-codec = { path = "../../codec", default_features = false } +substrate-primitives = { path = "../../primitives", default_features = false } +substrate-runtime-system = { path = "../system", default_features = false } [dev-dependencies] substrate-runtime-io = { path = "../../runtime-io", default_features = true } @@ -18,8 +21,11 @@ substrate-runtime-io = { path = "../../runtime-io", default_features = true } default = ["std"] std = [ "substrate-runtime-std/std", + "substrate-runtime-io/std", "substrate-runtime-support/std", "substrate-runtime-primitives/std", "serde/std", "substrate-codec/std", + "substrate-primitives/std", + "substrate-runtime-system/std", ] diff --git a/substrate/runtime/timestamp/src/lib.rs b/substrate/runtime/timestamp/src/lib.rs index c651fd8753f43..ee6bad5c83188 100644 --- a/substrate/runtime/timestamp/src/lib.rs +++ b/substrate/runtime/timestamp/src/lib.rs @@ -18,22 +18,25 @@ #![cfg_attr(not(feature = "std"), no_std)] -#[cfg_attr(test, macro_use)] +#[cfg_attr(any(feature = "std", test), macro_use)] extern crate substrate_runtime_std as rstd; #[macro_use] extern crate substrate_runtime_support as runtime_support; -#[cfg(test)] +#[cfg(any(feature = "std", test))] extern crate substrate_runtime_io as runtime_io; +#[cfg(test)] +extern crate substrate_primitives; extern crate substrate_runtime_primitives as runtime_primitives; +extern crate substrate_runtime_system as system; extern crate substrate_codec as codec; use runtime_support::{StorageValue, Parameter}; -use runtime_primitives::traits::HasPublicAux; +use runtime_primitives::traits::{HasPublicAux, Executable, MaybeEmpty}; -pub trait Trait: HasPublicAux { +pub trait Trait: HasPublicAux + system::Trait { type Value: Parameter + Default; } @@ -45,8 +48,11 @@ decl_module! { } decl_storage! { - pub trait Store for Module; + trait Store for Module; pub Now get(now): b"tim:val" => required T::Value; + + // Did the timestamp get updated in this block? + DidUpdate: b"tim:did" => default bool; } impl Module { @@ -55,8 +61,36 @@ impl Module { } /// Set the current time. - fn set(_aux: &T::PublicAux, now: T::Value) { + fn set(aux: &T::PublicAux, now: T::Value) { + assert!(aux.is_empty()); + assert!(!::DidUpdate::exists(), "Timestamp must be updated only once in the block"); + assert!(>::extrinsic_index() == 0, "Timestamp must be first extrinsic in the block"); ::Now::put(now); + ::DidUpdate::put(true); + } +} + +impl Executable for Module { + fn execute() { + assert!(::DidUpdate::take(), "Timestamp must be updated once in the block"); + } +} + +#[cfg(any(feature = "std", test))] +#[derive(Default)] +pub struct GenesisConfig { + pub now: T::Value, +} + +#[cfg(any(feature = "std", test))] +impl runtime_primitives::BuildExternalities for GenesisConfig +{ + fn build_externalities(self) -> runtime_primitives::BuiltExternalities { + use runtime_io::twox_128; + use codec::Slicable; + map![ + twox_128(>::key()).to_vec() => self.now.encode() + ] } } @@ -64,25 +98,35 @@ impl Module { mod tests { use super::*; - use runtime_io::{with_externalities, twox_128, TestExternalities}; - use codec::Joiner; + use runtime_io::with_externalities; use runtime_support::storage::StorageValue; + use substrate_primitives::H256; + use runtime_primitives::BuildExternalities; + use runtime_primitives::traits::{HasPublicAux}; + use runtime_primitives::testing::{Digest, Header}; - struct TraitImpl; - impl HasPublicAux for TraitImpl { + pub struct Test; + impl HasPublicAux for Test { type PublicAux = u64; } - impl Trait for TraitImpl { + impl system::Trait for Test { + type Index = u64; + type BlockNumber = u64; + type Hash = H256; + type Hashing = runtime_io::BlakeTwo256; + type Digest = Digest; + type AccountId = u64; + type Header = Header; + } + impl Trait for Test { type Value = u64; } - type Timestamp = Module; + type Timestamp = Module; #[test] fn timestamp_works() { - - let mut t: TestExternalities = map![ - twox_128(::Now::key()).to_vec() => vec![].and(&42u64) - ]; + let mut t = system::GenesisConfig::::default().build_externalities(); + t.extend(GenesisConfig:: { now: 42 }.build_externalities()); with_externalities(&mut t, || { assert_eq!(::Now::get(), 42); diff --git a/substrate/test-runtime/wasm/target/wasm32-unknown-unknown/release/substrate_test_runtime.compact.wasm b/substrate/test-runtime/wasm/target/wasm32-unknown-unknown/release/substrate_test_runtime.compact.wasm index 1e934f702c35d..c9da182130b78 100644 Binary files a/substrate/test-runtime/wasm/target/wasm32-unknown-unknown/release/substrate_test_runtime.compact.wasm and b/substrate/test-runtime/wasm/target/wasm32-unknown-unknown/release/substrate_test_runtime.compact.wasm differ diff --git a/substrate/test-runtime/wasm/target/wasm32-unknown-unknown/release/substrate_test_runtime.wasm b/substrate/test-runtime/wasm/target/wasm32-unknown-unknown/release/substrate_test_runtime.wasm old mode 100644 new mode 100755 index b8bcd03d83941..f648f7d54edd9 Binary files a/substrate/test-runtime/wasm/target/wasm32-unknown-unknown/release/substrate_test_runtime.wasm and b/substrate/test-runtime/wasm/target/wasm32-unknown-unknown/release/substrate_test_runtime.wasm differ