From 296df2effb5f9ff1373e44b8d8fa3bd5950b02b7 Mon Sep 17 00:00:00 2001 From: Aton Date: Thu, 15 Nov 2018 17:05:23 +0800 Subject: [PATCH] Feature/block producer (#99) * cx system init * provide a new inherent tx for block_producer --- Cargo.lock | 18 +++++++++ Cargo.toml | 1 + consensus/src/lib.rs | 26 ++++++++---- cxrml/system/Cargo.toml | 34 ++++++++++++++++ cxrml/system/src/lib.rs | 78 ++++++++++++++++++++++++++++++++++++ cxrml/system/src/tests.rs | 4 ++ primitives/src/lib.rs | 2 + runtime/Cargo.toml | 2 + runtime/src/checked_block.rs | 13 +++++- runtime/src/lib.rs | 21 ++++++++-- runtime/wasm/Cargo.lock | 18 +++++++++ runtime/wasm/Cargo.toml | 2 + 12 files changed, 207 insertions(+), 12 deletions(-) create mode 100644 cxrml/system/Cargo.toml create mode 100644 cxrml/system/src/lib.rs create mode 100644 cxrml/system/src/tests.rs diff --git a/Cargo.lock b/Cargo.lock index 2b2a5a0bbbb2d..1e683be17bb74 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -462,6 +462,7 @@ dependencies = [ "cxrml-multisig 0.1.0", "cxrml-staking 0.1.0", "cxrml-support 0.1.0", + "cxrml-system 0.1.0", "cxrml-tokenbalances 0.1.0", "hex-literal 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "parity-codec 2.0.3 (registry+https://github.com/rust-lang/crates.io-index)", @@ -853,6 +854,23 @@ dependencies = [ "srml-system 0.1.0 (git+https://github.com/paritytech/substrate)", ] +[[package]] +name = "cxrml-system" +version = "0.1.0" +dependencies = [ + "hex-literal 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 2.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec-derive 2.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.79 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.79 (registry+https://github.com/rust-lang/crates.io-index)", + "sr-io 0.1.0 (git+https://github.com/paritytech/substrate)", + "sr-primitives 0.1.0 (git+https://github.com/paritytech/substrate)", + "sr-std 0.1.0 (git+https://github.com/paritytech/substrate)", + "srml-support 0.1.0 (git+https://github.com/paritytech/substrate)", + "srml-system 0.1.0 (git+https://github.com/paritytech/substrate)", + "substrate-primitives 0.1.0 (git+https://github.com/paritytech/substrate)", +] + [[package]] name = "cxrml-tokenbalances" version = "0.1.0" diff --git a/Cargo.toml b/Cargo.toml index 20e40723aea61..2080f718f9dea 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -64,6 +64,7 @@ members = [ "pool", "rpc", "api", + "cxrml/system", "cxrml/support", "cxrml/tokenbalances", "cxrml/staking", diff --git a/consensus/src/lib.rs b/consensus/src/lib.rs index cd8b2f5c22778..ddea24bc0230e 100644 --- a/consensus/src/lib.rs +++ b/consensus/src/lib.rs @@ -226,9 +226,12 @@ impl bft::Proposer for Proposer ) } + let block_producer: AccountId = self.local_key.public().0.into(); + let inherent_data = InherentData { timestamp, offline_indices, + block_producer: block_producer.clone(), }; let mut block_builder = self.client.build_block(&self.parent_id, inherent_data)?; @@ -259,15 +262,15 @@ impl bft::Proposer for Proposer } let block = block_builder.bake()?; - + info!("generate a new block#{:}, producer:[{:}]", block.header.number, block_producer); trace!("Proposing block [number: {}; hash: {}; parent_hash: {}; extrinsics: [{}]]", - block.header.number, - Hash::from(block.header.hash()), - block.header.parent_hash, - block.extrinsics.iter() - .map(|xt| format!("{}", BlakeTwo256::hash_of(xt))) - .collect::>() - .join(", ") + block.header.number, + Hash::from(block.header.hash()), + block.header.parent_hash, + block.extrinsics.iter() + .map(|xt| format!("{}", BlakeTwo256::hash_of(xt))) + .collect::>() + .join(", ") ); let substrate_block = Decode::decode(&mut block.encode().as_slice()) @@ -337,6 +340,13 @@ impl bft::Proposer for Proposer return Box::new(futures::empty()); } + // check block_producer + match proposal.block_producer() { + Some(a) => { info!("current block#{:}, producer is [{:}]", self.parent_number + 1, a); } + None => { info!("current block#{:}, not set producer", self.parent_number + 1); } + } + + // evaluate whether the block is actually valid. // TODO: is it better to delay this until the delays are finished? let evaluated = self.client diff --git a/cxrml/system/Cargo.toml b/cxrml/system/Cargo.toml new file mode 100644 index 0000000000000..b9ab2b83f055d --- /dev/null +++ b/cxrml/system/Cargo.toml @@ -0,0 +1,34 @@ +[package] +name = "cxrml-system" +version = "0.1.0" +authors = ["Chainpool "] + + +[dependencies] +hex-literal = "0.1.0" +serde = { version = "1.0", default_features = false } +serde_derive = { version = "1.0", optional = true } +parity-codec = { version = "2.0", default-features = false } +parity-codec-derive = { version = "2.0", default-features = false } +substrate-primitives = { git = "https://github.com/paritytech/substrate", default_features = false } +sr-std = { git = "https://github.com/paritytech/substrate", default_features = false } +sr-io = { git = "https://github.com/paritytech/substrate", default_features = false } +sr-primitives = { git = "https://github.com/paritytech/substrate", default_features = false } +srml-support = { git = "https://github.com/paritytech/substrate", default_features = false } +srml-system = { git = "https://github.com/paritytech/substrate", default_features = false } + + +[features] +default = ["std"] +std=[ + "serde/std", + "serde_derive", + "parity-codec/std", + "parity-codec-derive/std", + "substrate-primitives/std", + "sr-std/std", + "sr-io/std", + "sr-primitives/std", + "srml-support/std", + "srml-system/std", +] \ No newline at end of file diff --git a/cxrml/system/src/lib.rs b/cxrml/system/src/lib.rs new file mode 100644 index 0000000000000..01b422f09ee91 --- /dev/null +++ b/cxrml/system/src/lib.rs @@ -0,0 +1,78 @@ +//! this module is for bch-bridge + +#![cfg_attr(not(feature = "std"), no_std)] +// for encode/decode +// Needed for deriving `Serialize` and `Deserialize` for various types. +// We only implement the serde traits for std builds - they're unneeded +// in the wasm runtime. +#[cfg(feature = "std")] +#[macro_use] +extern crate serde_derive; + +// Needed for deriving `Encode` and `Decode` for `RawEvent`. +//#[macro_use] +//extern crate parity_codec_derive; +extern crate parity_codec as codec; + +// for substrate +// Needed for the set of mock primitives used in our tests. +#[cfg(feature = "std")] +extern crate substrate_primitives; + +// for substrate runtime +// map!, vec! marco. +extern crate sr_std as rstd; +// Needed for tests (`with_externalities`). +#[cfg(feature = "std")] +extern crate sr_io as runtime_io; +extern crate sr_primitives as runtime_primitives; +// for substrate runtime module lib +// Needed for type-safe access to storage DB. +#[macro_use] +extern crate srml_support as runtime_support; +extern crate srml_system as system; + +#[cfg(test)] +mod tests; + +//use codec::{Codec, Decode, Encode}; +use rstd::prelude::*; +//use rstd::marker::PhantomData; +//use rstd::result::Result as StdResult; +use runtime_support::dispatch::Result; +use runtime_support::StorageValue; +use runtime_primitives::traits::OnFinalise; + +use system::ensure_inherent; + + +pub trait Trait: system::Trait {} + + +decl_module! { + pub struct Module for enum Call where origin: T::Origin { + fn set_block_producer(origin, producer: T::AccountId) -> Result; + } +} + +impl OnFinalise for Module { + fn on_finalise(_: T::BlockNumber) { + BlockProdocer::::kill(); + } +} + +decl_storage! { + trait Store for Module as CXSystem { + pub BlockProdocer get(block_producer) config(): Option; + } +} + +impl Module { + fn set_block_producer(origin: T::Origin, producer: T::AccountId) -> Result { + ensure_inherent(origin)?; + BlockProdocer::::put(producer); + Ok(()) + } +} + + diff --git a/cxrml/system/src/tests.rs b/cxrml/system/src/tests.rs new file mode 100644 index 0000000000000..2aedef47d4b16 --- /dev/null +++ b/cxrml/system/src/tests.rs @@ -0,0 +1,4 @@ +#[test] +fn it_works() { + assert_eq!(2 + 2, 4); +} \ No newline at end of file diff --git a/primitives/src/lib.rs b/primitives/src/lib.rs index 312dce87f79f0..b07e4d46adab1 100644 --- a/primitives/src/lib.rs +++ b/primitives/src/lib.rs @@ -96,6 +96,8 @@ pub struct InherentData { pub timestamp: Timestamp, /// Indices of offline validators. pub offline_indices: Vec, + /// block producer + pub block_producer: AccountId, } /// Candidate receipt type. diff --git a/runtime/Cargo.toml b/runtime/Cargo.toml index 7d71d47197a63..21e68eebc8fe7 100644 --- a/runtime/Cargo.toml +++ b/runtime/Cargo.toml @@ -31,6 +31,7 @@ sr-version = { git = "https://github.com/paritytech/substrate" } chainx-primitives = { path = "../primitives" } # chainx runtime module +cxrml-system = { path = "../cxrml/system" } cxrml-support = { path = "../cxrml/support" } cxrml-staking = { path = "../cxrml/staking" } cxrml-tokenbalances = { path = "../cxrml/tokenbalances" } @@ -65,6 +66,7 @@ std = [ "serde_derive", "serde/std", "safe-mix/std", + "cxrml-system/std", "cxrml-support/std", "cxrml-staking/std", "cxrml-tokenbalances/std", diff --git a/runtime/src/checked_block.rs b/runtime/src/checked_block.rs index 389f4e8ff8302..54c7e874274e5 100644 --- a/runtime/src/checked_block.rs +++ b/runtime/src/checked_block.rs @@ -2,9 +2,10 @@ //! Typesafe block interaction. -use super::{Call, Block, TIMESTAMP_SET_POSITION, NOTE_OFFLINE_POSITION}; +use super::{Call, Block, AccountId, TIMESTAMP_SET_POSITION, NOTE_OFFLINE_POSITION, BLOCK_PRODUCER_POSITION}; use timestamp::Call as TimestampCall; //use session::Call as SessionCall; +use cxsystem::Call as CXSystemCall; /// Provides a type-safe wrapper around a structurally valid block. pub struct CheckedBlock { @@ -73,6 +74,16 @@ impl CheckedBlock { .unwrap_or(&[]) } + pub fn block_producer(&self) -> Option { + self.inner + .extrinsics + .get(BLOCK_PRODUCER_POSITION as usize) + .and_then(|xt| match xt.function { + Call::CXSystem(CXSystemCall::set_block_producer(x)) => Some(x), + _ => None, + }) + } + /// Convert into inner block. pub fn into_inner(self) -> Block { self.inner diff --git a/runtime/src/lib.rs b/runtime/src/lib.rs index e9c9361c28a17..378d18fb868bc 100644 --- a/runtime/src/lib.rs +++ b/runtime/src/lib.rs @@ -36,6 +36,7 @@ extern crate srml_system as system; extern crate srml_timestamp as timestamp; extern crate srml_treasury as treasury; // cx runtime module +extern crate cxrml_system as cxsystem; extern crate cxrml_support as cxsupport; extern crate cxrml_staking as staking; extern crate cxrml_tokenbalances as tokenbalances; @@ -60,7 +61,6 @@ mod checked_block; pub use balances::address::Address as RawAddress; #[cfg(feature = "std")] pub use checked_block::CheckedBlock; -pub use consensus::Call as ConsensusCall; pub use runtime_primitives::{Permill, Perbill}; pub use tokenbalances::Token; @@ -68,6 +68,8 @@ use rstd::prelude::*; use substrate_primitives::u32_trait::{_2, _4}; use chainx_primitives::{AccountId, AccountIndex, Balance, BlockNumber, Hash, Index, SessionKey, Signature}; use timestamp::Call as TimestampCall; +pub use consensus::Call as ConsensusCall; +use cxsystem::Call as CXSystemCall; use chainx_primitives::InherentData; use runtime_primitives::generic; use runtime_primitives::traits::{Convert, BlakeTwo256, DigestItem}; @@ -90,6 +92,10 @@ pub fn inherent_extrinsics(data: InherentData) -> Vec { Call::Timestamp(TimestampCall::set(data.timestamp)) )]; + inherent.push(generic::UncheckedMortalExtrinsic::new_unsigned( + Call::CXSystem(CXSystemCall::set_block_producer(data.block_producer)) + )); + if !data.offline_indices.is_empty() { inherent.push(generic::UncheckedMortalExtrinsic::new_unsigned( Call::Consensus(ConsensusCall::note_offline(data.offline_indices)) @@ -110,6 +116,8 @@ pub const TIMESTAMP_SET_POSITION: u32 = 0; /// The position of the offline nodes noting extrinsic. pub const NOTE_OFFLINE_POSITION: u32 = 2; +pub const BLOCK_PRODUCER_POSITION: u32 = 1; + /// Runtime version. pub const VERSION: RuntimeVersion = RuntimeVersion { spec_name: ver_str!("chainx"), @@ -215,6 +223,12 @@ impl council::motions::Trait for Runtime { type Event = Event; } +// cxrml trait + +impl cxsystem::Trait for Runtime {} + +impl cxsupport::Trait for Runtime {} + impl tokenbalances::Trait for Runtime { const CHAINX_SYMBOL: tokenbalances::SymbolString = b"pcx"; const CHAINX_TOKEN_DESC: tokenbalances::DescString = b"pcx token for ChainX"; @@ -250,8 +264,6 @@ impl matchorder::Trait for Runtime { type Event = Event; } -impl cxsupport::Trait for Runtime {} - impl DigestItem for Log { type Hash = Hash; @@ -286,6 +298,7 @@ construct_runtime!( CouncilMotions: council_motions::{Module, Call, Storage, Event, Origin}, Treasury: treasury, Contract: contract::{Module, Call, Config, Event}, + // chainx runtime module TokenBalances: tokenbalances, MultiSig: multisig, // funds @@ -299,6 +312,8 @@ construct_runtime!( // put end of this marco CXSupport: cxsupport::{Module}, + // must put end of all chainx runtime module + CXSystem: cxsystem::{Module, Call, Storage}, } ); diff --git a/runtime/wasm/Cargo.lock b/runtime/wasm/Cargo.lock index 46783a3eef736..91783b2833e6e 100644 --- a/runtime/wasm/Cargo.lock +++ b/runtime/wasm/Cargo.lock @@ -99,6 +99,7 @@ dependencies = [ "cxrml-multisig 0.1.0", "cxrml-staking 0.1.0", "cxrml-support 0.1.0", + "cxrml-system 0.1.0", "cxrml-tokenbalances 0.1.0", "integer-sqrt 0.1.0 (git+https://github.com/paritytech/integer-sqrt-rs.git)", "parity-codec 2.0.3 (registry+https://github.com/rust-lang/crates.io-index)", @@ -365,6 +366,23 @@ dependencies = [ "srml-system 0.1.0 (git+https://github.com/paritytech/substrate)", ] +[[package]] +name = "cxrml-system" +version = "0.1.0" +dependencies = [ + "hex-literal 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 2.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec-derive 2.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.79 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.79 (registry+https://github.com/rust-lang/crates.io-index)", + "sr-io 0.1.0 (git+https://github.com/paritytech/substrate)", + "sr-primitives 0.1.0 (git+https://github.com/paritytech/substrate)", + "sr-std 0.1.0 (git+https://github.com/paritytech/substrate)", + "srml-support 0.1.0 (git+https://github.com/paritytech/substrate)", + "srml-system 0.1.0 (git+https://github.com/paritytech/substrate)", + "substrate-primitives 0.1.0 (git+https://github.com/paritytech/substrate)", +] + [[package]] name = "cxrml-tokenbalances" version = "0.1.0" diff --git a/runtime/wasm/Cargo.toml b/runtime/wasm/Cargo.toml index c438419fc294f..22e4c8bc9ed10 100644 --- a/runtime/wasm/Cargo.toml +++ b/runtime/wasm/Cargo.toml @@ -30,6 +30,7 @@ sr-version = { git = "https://github.com/paritytech/substrate", default-features chainx-primitives = { path = "../../primitives", default-features = false } # chainx runtime module +cxrml-system = { path = "../../cxrml/system", default-features = false } cxrml-support = { path = "../../cxrml/support", default-features = false } cxrml-staking = { path = "../../cxrml/staking", default-features = false } cxrml-tokenbalances = { path = "../../cxrml/tokenbalances", default-features = false } @@ -64,6 +65,7 @@ std = [ "srml-treasury/std", "sr-version/std", "chainx-primitives/std", + "cxrml-system/std", "cxrml-support/std", "cxrml-staking/std", "cxrml-tokenbalances/std",