diff --git a/substrate/.gitlab-ci.yml b/substrate/.gitlab-ci.yml index c11d5ccfc2..55c83328d4 100644 --- a/substrate/.gitlab-ci.yml +++ b/substrate/.gitlab-ci.yml @@ -218,7 +218,7 @@ publish-docker-release: - docker build --build-arg VCS_REF="${CI_COMMIT_SHA}" --build-arg BUILD_DATE="$(date -u '+%Y-%m-%dT%H:%M:%SZ')" - --tag $CONTAINER_IMAGE:$VERSION + --tag $CONTAINER_IMAGE:$VERSION --tag $CONTAINER_IMAGE:latest . - docker push $CONTAINER_IMAGE:$VERSION - docker push $CONTAINER_IMAGE:latest @@ -272,7 +272,7 @@ publish-s3-doc: --human-readable --summarize .deploy-template: &deploy - stage: kubernetes + stage: kubernetes when: manual retry: 1 image: parity/kubetools:latest diff --git a/substrate/Cargo.lock b/substrate/Cargo.lock index 32bcf235ab..83a85c4d69 100644 --- a/substrate/Cargo.lock +++ b/substrate/Cargo.lock @@ -1211,6 +1211,14 @@ dependencies = [ "serde 1.0.90 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "impl-serde" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "serde 1.0.90 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "indexmap" version = "1.0.2" @@ -2514,13 +2522,13 @@ dependencies = [ [[package]] name = "primitive-types" -version = "0.2.1" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "fixed-hash 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "impl-codec 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "impl-serde 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "uint 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", + "impl-serde 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "uint 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -3196,7 +3204,7 @@ dependencies = [ "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", "parity-codec 3.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "primitive-types 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "primitive-types 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.90 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)", "sr-io 2.0.0", @@ -4279,7 +4287,7 @@ dependencies = [ "num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", "parity-codec 3.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "pretty_assertions 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", - "primitive-types 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "primitive-types 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", "regex 1.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-hex 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -5037,7 +5045,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "uint" -version = "0.6.1" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -5617,6 +5625,7 @@ dependencies = [ "checksum idna 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "38f09e0f0b1fb55fdee1f17470ad800da77af5186a1a76c026b679358b7e844e" "checksum impl-codec 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d2050d823639fbeae26b2b5ba09aca8907793117324858070ade0673c49f793b" "checksum impl-serde 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "5158079de9d4158e0ce1de3ae0bd7be03904efc40b3d7dd8b8c301cbf6b52b56" +"checksum impl-serde 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7d26be4b97d738552ea423f76c4f681012ff06c3fa36fa968656b3679f60b4a1" "checksum indexmap 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7e81a7c05f79578dbc15793d8b619db9ba32b4577003ef3af1a91c416798c58d" "checksum integer-sqrt 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "ea155abb3ba6f382a75f1418988c05fe82959ed9ce727de427f9cfd425b0c903" "checksum interleaved-ordered 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "141340095b15ed7491bd3d4ced9d20cebfb826174b6bb03386381f62b01e3d77" @@ -5722,7 +5731,7 @@ dependencies = [ "checksum pkg-config 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)" = "676e8eb2b1b4c9043511a9b7bea0915320d7e502b0a079fb03f9635a5252b18c" "checksum pretty_assertions 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3a029430f0d744bc3d15dd474d591bed2402b645d024583082b9f63bb936dac6" "checksum pretty_assertions 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3f81e1644e1b54f5a68959a29aa86cde704219254669da328ecfdf6a1f09d427" -"checksum primitive-types 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "edb92f1ebfc177432c03287b15d48c202e6e2c95993a7af3ba039abb43b1492e" +"checksum primitive-types 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "6e8612a8dc70f26276fed6131c153ca277cf275ee0a5e2a50cd8a69c697beb8f" "checksum proc-macro-crate 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "4c6cf4e5b00300d151dfffae39f529dfa5188f42eeb14201229aa420d6aad10c" "checksum proc-macro-hack 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2c725b36c99df7af7bf9324e9c999b9e37d92c8f8caf106d82e1d7953218d2d8" "checksum proc-macro-hack 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)" = "6a9bed9ebc40cf53e3a76d7486c54d05002eae6485b2711ab9104476fb2eb8bc" @@ -5858,7 +5867,7 @@ dependencies = [ "checksum typeable 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1410f6f91f21d1612654e7cc69193b0334f909dcf2c790c4826254fbb86f8887" "checksum typenum 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "612d636f949607bdf9b123b4a6f6d966dedf3ff669f7f045890d3a4a73948169" "checksum ucd-util 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "535c204ee4d8434478593480b8f86ab45ec9aae0e83c568ca81abf0fd0e88f86" -"checksum uint 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e7780bb27fd8a22295e0d9d53ae3be253f715a0dccb1808527f478f1c2603708" +"checksum uint 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2143cded94692b156c356508d92888acc824db5bffc0b4089732264c6fcf86d4" "checksum unicase 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7f4765f83163b74f957c797ad9253caf97f103fb064d3999aea9568d09fc8a33" "checksum unicase 2.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "41d17211f887da8e4a70a45b9536f26fc5de166b81e2d5d80de4a17fd22553bd" "checksum unicode-bidi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "49f2bd0c6468a8230e1db229cff8029217cf623c767ea5d60bfbd42729ea54d5" diff --git a/substrate/Dockerfile b/substrate/Dockerfile index df39db5abb..c5944dbab6 100644 --- a/substrate/Dockerfile +++ b/substrate/Dockerfile @@ -20,8 +20,8 @@ RUN curl https://sh.rustup.rs -sSf | sh -s -- -y && \ rustup target add wasm32-unknown-unknown --toolchain nightly && \ cargo install --git https://github.com/alexcrichton/wasm-gc && \ rustup default nightly && \ - ./scripts/build.sh && \ - rustup default stable && \ + ./scripts/build.sh && \ + rustup default stable && \ cargo build --$PROFILE # ===== SECOND STAGE ====== diff --git a/substrate/core/basic-authorship/src/basic_authorship.rs b/substrate/core/basic-authorship/src/basic_authorship.rs index 9f0db708da..62aad4c9c7 100644 --- a/substrate/core/basic-authorship/src/basic_authorship.rs +++ b/substrate/core/basic-authorship/src/basic_authorship.rs @@ -30,7 +30,8 @@ use codec::Decode; use consensus_common::{self, evaluation}; use primitives::{H256, Blake2Hasher, ExecutionContext}; use runtime_primitives::traits::{ - Block as BlockT, Hash as HashT, Header as HeaderT, ProvideRuntimeApi, AuthorityIdFor + Block as BlockT, Hash as HashT, Header as HeaderT, ProvideRuntimeApi, + AuthorityIdFor, DigestFor, }; use runtime_primitives::generic::BlockId; use runtime_primitives::ApplyError; @@ -53,11 +54,13 @@ pub trait AuthoringApi: Send + Sync + ProvideRuntimeApi where /// The error used by this API type. type Error: std::error::Error; - /// Build a block on top of the given, with inherent extrinsics pre-pushed. + /// Build a block on top of the given block, with inherent extrinsics and + /// inherent digests pre-pushed. fn build_block) -> ()>( &self, at: &BlockId, inherent_data: InherentData, + inherent_digests: DigestFor, build_ctx: F, ) -> Result; } @@ -92,9 +95,11 @@ impl AuthoringApi for SubstrateClient where &self, at: &BlockId, inherent_data: InherentData, + inherent_digests: DigestFor, mut build_ctx: F, ) -> Result { - let mut block_builder = self.new_block_at(at)?; + + let mut block_builder = self.new_block_at(at, inherent_digests)?; let runtime_api = self.runtime_api(); // We don't check the API versions any further here since the dispatch compatibility @@ -174,12 +179,16 @@ impl consensus_common::Proposer<::Block> for Pro type Create = Result<::Block, error::Error>; type Error = error::Error; - fn propose(&self, inherent_data: InherentData, max_duration: time::Duration) - -> Result<::Block, error::Error> + fn propose( + &self, + inherent_data: InherentData, + inherent_digests: DigestFor, + max_duration: time::Duration, + ) -> Result<::Block, error::Error> { // leave some time for evaluation and block finalization (33%) let deadline = (self.now)() + max_duration - max_duration / 3; - self.propose_with(inherent_data, deadline) + self.propose_with(inherent_data, inherent_digests, deadline) } } @@ -190,8 +199,12 @@ impl Proposer where A: txpool::ChainApi, client::error::Error: From<::Error>, { - fn propose_with(&self, inherent_data: InherentData, deadline: time::Instant) - -> Result<::Block, error::Error> + fn propose_with( + &self, + inherent_data: InherentData, + inherent_digests: DigestFor, + deadline: time::Instant, + ) -> Result<::Block, error::Error> { use runtime_primitives::traits::BlakeTwo256; @@ -203,17 +216,16 @@ impl Proposer where let block = self.client.build_block( &self.parent_id, inherent_data, + inherent_digests.clone(), |block_builder| { // Add inherents from the internal pool - let inherents = self.inherents_pool.drain(); - debug!("Pushing {} queued inherents.", inherents.len()); + debug!("Pushing {} queued inherent extrinsics.", inherents.len()); for i in inherents { if let Err(e) = block_builder.push_extrinsic(i) { warn!("Error while pushing inherent extrinsic from the pool: {:?}", e); } } - // proceed with transactions let mut is_first = true; let mut skipped = 0; @@ -331,7 +343,7 @@ mod tests { cell.replace(new) }); let deadline = time::Duration::from_secs(3); - let block = proposer.propose(Default::default(), deadline).unwrap(); + let block = proposer.propose(Default::default(), Default::default(), deadline).unwrap(); // then // block should have some extrinsics although we have some more in the pool. @@ -362,7 +374,7 @@ mod tests { // when let deadline = time::Duration::from_secs(3); - let block = proposer.propose(Default::default(), deadline).unwrap(); + let block = proposer.propose(Default::default(), Default::default(), deadline).unwrap(); // then assert_eq!(block.extrinsics().len(), 1); diff --git a/substrate/core/client/db/src/light.rs b/substrate/core/client/db/src/light.rs index e145e63cb7..16b0fc616a 100644 --- a/substrate/core/client/db/src/light.rs +++ b/substrate/core/client/db/src/light.rs @@ -708,7 +708,7 @@ pub(crate) mod tests { let mut prev_hash = insert_final_block(&db, HashMap::new(), || header_producer(&Default::default(), 0)); // insert SIZE blocks && ensure that nothing is pruned - + for number in 0..cht::size() { prev_hash = insert_block(&db, HashMap::new(), || header_producer(&prev_hash, 1 + number)); } diff --git a/substrate/core/client/src/block_builder/block_builder.rs b/substrate/core/client/src/block_builder/block_builder.rs index 995b303699..eb7d81f978 100644 --- a/substrate/core/client/src/block_builder/block_builder.rs +++ b/substrate/core/client/src/block_builder/block_builder.rs @@ -20,7 +20,7 @@ use parity_codec::Encode; use runtime_primitives::ApplyOutcome; use runtime_primitives::generic::BlockId; use runtime_primitives::traits::{ - Header as HeaderT, Hash, Block as BlockT, One, HashFor, ProvideRuntimeApi, ApiRef + Header as HeaderT, Hash, Block as BlockT, One, HashFor, ProvideRuntimeApi, ApiRef, DigestFor, }; use primitives::{H256, ExecutionContext}; use crate::blockchain::HeaderBackend; @@ -41,10 +41,11 @@ where A: ProvideRuntimeApi + HeaderBackend + 'a, A::Api: BlockBuilderApi, { - /// Create a new instance of builder from the given client, building on the latest block. - pub fn new(api: &'a A) -> error::Result { + /// Create a new instance of builder from the given client, building on the + /// latest block. + pub fn new(api: &'a A, inherent_digests: DigestFor) -> error::Result { api.info().and_then(|i| - Self::at_block(&BlockId::Hash(i.best_hash), api, false) + Self::at_block(&BlockId::Hash(i.best_hash), api, false, inherent_digests) ) } @@ -57,7 +58,8 @@ where pub fn at_block( block_id: &BlockId, api: &'a A, - proof_recording: bool + proof_recording: bool, + inherent_digests: DigestFor, ) -> error::Result { let number = api.block_number_from_id(block_id)? .ok_or_else(|| error::Error::UnknownBlock(format!("{}", block_id)))? @@ -70,7 +72,7 @@ where Default::default(), Default::default(), parent_hash, - Default::default() + inherent_digests, ); let mut api = api.runtime_api(); @@ -80,7 +82,7 @@ where } api.initialize_block_with_context( - block_id, ExecutionContext::BlockConstruction, &header + block_id, ExecutionContext::BlockConstruction, &header, )?; Ok(BlockBuilder { diff --git a/substrate/core/client/src/client.rs b/substrate/core/client/src/client.rs index f36992a14e..874cf7636b 100644 --- a/substrate/core/client/src/client.rs +++ b/substrate/core/client/src/client.rs @@ -37,7 +37,7 @@ use consensus::{ use runtime_primitives::traits::{ Block as BlockT, Header as HeaderT, Zero, NumberFor, CurrentHeight, BlockNumberToHash, ApiRef, ProvideRuntimeApi, Digest, DigestItem, - SaturatedConversion, One + SaturatedConversion, One, DigestFor, }; use runtime_primitives::BuildStorage; use crate::runtime_api::{ @@ -695,26 +695,29 @@ impl Client where /// Create a new block, built on the head of the chain. pub fn new_block( - &self + &self, + inherent_digests: DigestFor, ) -> error::Result> where E: Clone + Send + Sync, RA: Send + Sync, Self: ProvideRuntimeApi, ::Api: BlockBuilderAPI { - block_builder::BlockBuilder::new(self) + block_builder::BlockBuilder::new(self, inherent_digests) } /// Create a new block, built on top of `parent`. pub fn new_block_at( - &self, parent: &BlockId + &self, + parent: &BlockId, + inherent_digests: DigestFor, ) -> error::Result> where E: Clone + Send + Sync, RA: Send + Sync, Self: ProvideRuntimeApi, ::Api: BlockBuilderAPI { - block_builder::BlockBuilder::at_block(parent, &self, false) + block_builder::BlockBuilder::at_block(parent, &self, false, inherent_digests) } /// Create a new block, built on top of `parent` with proof recording enabled. @@ -723,14 +726,16 @@ impl Client where /// These recorded trie nodes can be used by a third party to proof the /// output of this block builder without having access to the full storage. pub fn new_block_at_with_proof_recording( - &self, parent: &BlockId + &self, + parent: &BlockId, + inherent_digests: DigestFor, ) -> error::Result> where E: Clone + Send + Sync, RA: Send + Sync, Self: ProvideRuntimeApi, ::Api: BlockBuilderAPI { - block_builder::BlockBuilder::at_block(parent, &self, true) + block_builder::BlockBuilder::at_block(parent, &self, true, inherent_digests) } /// Lock the import lock, and run operations inside. @@ -1272,11 +1277,12 @@ impl Client where /// Prepare in-memory header that is used in execution environment. fn prepare_environment_block(&self, parent: &BlockId) -> error::Result { + let parent_header = self.backend().blockchain().expect_header(*parent)?; Ok(<::Header as HeaderT>::new( self.backend.blockchain().expect_block_number_from_id(parent)? + One::one(), Default::default(), Default::default(), - self.backend.blockchain().expect_block_hash_from_id(&parent)?, + parent_header.hash(), Default::default(), )) } @@ -1753,7 +1759,7 @@ pub(crate) mod tests { let remote_client = test_client::new_with_changes_trie(); let mut nonces: HashMap<_, u64> = Default::default(); for (i, block_transfers) in blocks_transfers.into_iter().enumerate() { - let mut builder = remote_client.new_block().unwrap(); + let mut builder = remote_client.new_block(Default::default()).unwrap(); for (from, to) in block_transfers { builder.push_transfer(Transfer { from: from.into(), @@ -1828,7 +1834,7 @@ pub(crate) mod tests { fn block_builder_works_with_no_transactions() { let client = test_client::new(); - let builder = client.new_block().unwrap(); + let builder = client.new_block(Default::default()).unwrap(); client.import(BlockOrigin::Own, builder.bake().unwrap()).unwrap(); @@ -1839,7 +1845,7 @@ pub(crate) mod tests { fn block_builder_works_with_transactions() { let client = test_client::new(); - let mut builder = client.new_block().unwrap(); + let mut builder = client.new_block(Default::default()).unwrap(); builder.push_transfer(Transfer { from: AccountKeyring::Alice.into(), @@ -1872,7 +1878,7 @@ pub(crate) mod tests { fn block_builder_does_not_include_invalid() { let client = test_client::new(); - let mut builder = client.new_block().unwrap(); + let mut builder = client.new_block(Default::default()).unwrap(); builder.push_transfer(Transfer { from: AccountKeyring::Alice.into(), @@ -1921,7 +1927,7 @@ pub(crate) mod tests { let client = test_client::new(); - let uninserted_block = client.new_block().unwrap().bake().unwrap(); + let uninserted_block = client.new_block(Default::default()).unwrap().bake().unwrap(); #[allow(deprecated)] let backend = client.backend().as_in_memory(); #[allow(deprecated)] @@ -1940,11 +1946,11 @@ pub(crate) mod tests { let client = test_client::new(); // G -> A1 - let a1 = client.new_block().unwrap().bake().unwrap(); + let a1 = client.new_block(Default::default()).unwrap().bake().unwrap(); client.import(BlockOrigin::Own, a1.clone()).unwrap(); // A1 -> A2 - let a2 = client.new_block().unwrap().bake().unwrap(); + let a2 = client.new_block(Default::default()).unwrap().bake().unwrap(); client.import(BlockOrigin::Own, a2.clone()).unwrap(); let v: Vec = Vec::new(); assert_eq!(v, client.uncles(a2.hash(), 3).unwrap()); @@ -1960,27 +1966,27 @@ pub(crate) mod tests { let client = test_client::new(); // G -> A1 - let a1 = client.new_block().unwrap().bake().unwrap(); + let a1 = client.new_block(Default::default()).unwrap().bake().unwrap(); client.import(BlockOrigin::Own, a1.clone()).unwrap(); // A1 -> A2 - let a2 = client.new_block_at(&BlockId::Hash(a1.hash())).unwrap().bake().unwrap(); + let a2 = client.new_block_at(&BlockId::Hash(a1.hash()), Default::default()).unwrap().bake().unwrap(); client.import(BlockOrigin::Own, a2.clone()).unwrap(); // A2 -> A3 - let a3 = client.new_block_at(&BlockId::Hash(a2.hash())).unwrap().bake().unwrap(); + let a3 = client.new_block_at(&BlockId::Hash(a2.hash()), Default::default()).unwrap().bake().unwrap(); client.import(BlockOrigin::Own, a3.clone()).unwrap(); // A3 -> A4 - let a4 = client.new_block_at(&BlockId::Hash(a3.hash())).unwrap().bake().unwrap(); + let a4 = client.new_block_at(&BlockId::Hash(a3.hash()), Default::default()).unwrap().bake().unwrap(); client.import(BlockOrigin::Own, a4.clone()).unwrap(); // A4 -> A5 - let a5 = client.new_block_at(&BlockId::Hash(a4.hash())).unwrap().bake().unwrap(); + let a5 = client.new_block_at(&BlockId::Hash(a4.hash()), Default::default()).unwrap().bake().unwrap(); client.import(BlockOrigin::Own, a5.clone()).unwrap(); // A1 -> B2 - let mut builder = client.new_block_at(&BlockId::Hash(a1.hash())).unwrap(); + let mut builder = client.new_block_at(&BlockId::Hash(a1.hash()), Default::default()).unwrap(); // this push is required as otherwise B2 has the same hash as A2 and won't get imported builder.push_transfer(Transfer { from: AccountKeyring::Alice.into(), @@ -1992,15 +1998,15 @@ pub(crate) mod tests { client.import(BlockOrigin::Own, b2.clone()).unwrap(); // B2 -> B3 - let b3 = client.new_block_at(&BlockId::Hash(b2.hash())).unwrap().bake().unwrap(); + let b3 = client.new_block_at(&BlockId::Hash(b2.hash()), Default::default()).unwrap().bake().unwrap(); client.import(BlockOrigin::Own, b3.clone()).unwrap(); // B3 -> B4 - let b4 = client.new_block_at(&BlockId::Hash(b3.hash())).unwrap().bake().unwrap(); + let b4 = client.new_block_at(&BlockId::Hash(b3.hash()), Default::default()).unwrap().bake().unwrap(); client.import(BlockOrigin::Own, b4.clone()).unwrap(); // // B2 -> C3 - let mut builder = client.new_block_at(&BlockId::Hash(b2.hash())).unwrap(); + let mut builder = client.new_block_at(&BlockId::Hash(b2.hash()), Default::default()).unwrap(); // this push is required as otherwise C3 has the same hash as B3 and won't get imported builder.push_transfer(Transfer { from: AccountKeyring::Alice.into(), @@ -2012,7 +2018,7 @@ pub(crate) mod tests { client.import(BlockOrigin::Own, c3.clone()).unwrap(); // A1 -> D2 - let mut builder = client.new_block_at(&BlockId::Hash(a1.hash())).unwrap(); + let mut builder = client.new_block_at(&BlockId::Hash(a1.hash()), Default::default()).unwrap(); // this push is required as otherwise D2 has the same hash as B2 and won't get imported builder.push_transfer(Transfer { from: AccountKeyring::Alice.into(), @@ -2052,11 +2058,11 @@ pub(crate) mod tests { let client = test_client::new(); // G -> A1 - let a1 = client.new_block().unwrap().bake().unwrap(); + let a1 = client.new_block(Default::default()).unwrap().bake().unwrap(); client.import(BlockOrigin::Own, a1.clone()).unwrap(); // A1 -> A2 - let a2 = client.new_block().unwrap().bake().unwrap(); + let a2 = client.new_block(Default::default()).unwrap().bake().unwrap(); client.import(BlockOrigin::Own, a2.clone()).unwrap(); let genesis_hash = client.info().unwrap().chain.genesis_hash; @@ -2083,27 +2089,27 @@ pub(crate) mod tests { let client = test_client::new(); // G -> A1 - let a1 = client.new_block().unwrap().bake().unwrap(); + let a1 = client.new_block(Default::default()).unwrap().bake().unwrap(); client.import(BlockOrigin::Own, a1.clone()).unwrap(); // A1 -> A2 - let a2 = client.new_block_at(&BlockId::Hash(a1.hash())).unwrap().bake().unwrap(); + let a2 = client.new_block_at(&BlockId::Hash(a1.hash()), Default::default()).unwrap().bake().unwrap(); client.import(BlockOrigin::Own, a2.clone()).unwrap(); // A2 -> A3 - let a3 = client.new_block_at(&BlockId::Hash(a2.hash())).unwrap().bake().unwrap(); + let a3 = client.new_block_at(&BlockId::Hash(a2.hash()), Default::default()).unwrap().bake().unwrap(); client.import(BlockOrigin::Own, a3.clone()).unwrap(); // A3 -> A4 - let a4 = client.new_block_at(&BlockId::Hash(a3.hash())).unwrap().bake().unwrap(); + let a4 = client.new_block_at(&BlockId::Hash(a3.hash()), Default::default()).unwrap().bake().unwrap(); client.import(BlockOrigin::Own, a4.clone()).unwrap(); // A4 -> A5 - let a5 = client.new_block_at(&BlockId::Hash(a4.hash())).unwrap().bake().unwrap(); + let a5 = client.new_block_at(&BlockId::Hash(a4.hash()), Default::default()).unwrap().bake().unwrap(); client.import(BlockOrigin::Own, a5.clone()).unwrap(); // A1 -> B2 - let mut builder = client.new_block_at(&BlockId::Hash(a1.hash())).unwrap(); + let mut builder = client.new_block_at(&BlockId::Hash(a1.hash()), Default::default()).unwrap(); // this push is required as otherwise B2 has the same hash as A2 and won't get imported builder.push_transfer(Transfer { from: AccountKeyring::Alice.into(), @@ -2115,15 +2121,15 @@ pub(crate) mod tests { client.import(BlockOrigin::Own, b2.clone()).unwrap(); // B2 -> B3 - let b3 = client.new_block_at(&BlockId::Hash(b2.hash())).unwrap().bake().unwrap(); + let b3 = client.new_block_at(&BlockId::Hash(b2.hash()), Default::default()).unwrap().bake().unwrap(); client.import(BlockOrigin::Own, b3.clone()).unwrap(); // B3 -> B4 - let b4 = client.new_block_at(&BlockId::Hash(b3.hash())).unwrap().bake().unwrap(); + let b4 = client.new_block_at(&BlockId::Hash(b3.hash()), Default::default()).unwrap().bake().unwrap(); client.import(BlockOrigin::Own, b4.clone()).unwrap(); // // B2 -> C3 - let mut builder = client.new_block_at(&BlockId::Hash(b2.hash())).unwrap(); + let mut builder = client.new_block_at(&BlockId::Hash(b2.hash()), Default::default()).unwrap(); // this push is required as otherwise C3 has the same hash as B3 and won't get imported builder.push_transfer(Transfer { from: AccountKeyring::Alice.into(), @@ -2135,7 +2141,7 @@ pub(crate) mod tests { client.import(BlockOrigin::Own, c3.clone()).unwrap(); // A1 -> D2 - let mut builder = client.new_block_at(&BlockId::Hash(a1.hash())).unwrap(); + let mut builder = client.new_block_at(&BlockId::Hash(a1.hash()), Default::default()).unwrap(); // this push is required as otherwise D2 has the same hash as B2 and won't get imported builder.push_transfer(Transfer { from: AccountKeyring::Alice.into(), @@ -2372,11 +2378,11 @@ pub(crate) mod tests { let client = test_client::new(); // G -> A1 - let a1 = client.new_block().unwrap().bake().unwrap(); + let a1 = client.new_block(Default::default()).unwrap().bake().unwrap(); client.import(BlockOrigin::Own, a1.clone()).unwrap(); // A1 -> A2 - let a2 = client.new_block().unwrap().bake().unwrap(); + let a2 = client.new_block(Default::default()).unwrap().bake().unwrap(); client.import(BlockOrigin::Own, a2.clone()).unwrap(); let genesis_hash = client.info().unwrap().chain.genesis_hash; @@ -2412,16 +2418,16 @@ pub(crate) mod tests { let client = test_client::new(); // G -> A1 - let a1 = client.new_block().unwrap().bake().unwrap(); + let a1 = client.new_block(Default::default()).unwrap().bake().unwrap(); client.import(BlockOrigin::Own, a1.clone()).unwrap(); // A1 -> A2 - let a2 = client.new_block_at(&BlockId::Hash(a1.hash())).unwrap().bake().unwrap(); + let a2 = client.new_block_at(&BlockId::Hash(a1.hash()), Default::default()).unwrap().bake().unwrap(); client.import(BlockOrigin::Own, a2.clone()).unwrap(); // A2 -> A3 let justification = vec![1, 2, 3]; - let a3 = client.new_block_at(&BlockId::Hash(a2.hash())).unwrap().bake().unwrap(); + let a3 = client.new_block_at(&BlockId::Hash(a2.hash()), Default::default()).unwrap().bake().unwrap(); client.import_justified(BlockOrigin::Own, a3.clone(), justification.clone()).unwrap(); #[allow(deprecated)] diff --git a/substrate/core/client/src/light/call_executor.rs b/substrate/core/client/src/light/call_executor.rs index 982f106f2a..9959d29a1b 100644 --- a/substrate/core/client/src/light/call_executor.rs +++ b/substrate/core/client/src/light/call_executor.rs @@ -448,7 +448,7 @@ pub fn check_execution_proof( Default::default(), Default::default(), request.header.hash(), - Default::default(), + request.header.digest().clone(), ); execution_proof_check_on_trie_backend::( &trie_backend, @@ -525,7 +525,7 @@ mod tests { for _ in 1..3 { remote_client.import_justified( BlockOrigin::Own, - remote_client.new_block().unwrap().bake().unwrap(), + remote_client.new_block(Default::default()).unwrap().bake().unwrap(), Default::default(), ).unwrap(); } diff --git a/substrate/core/client/src/light/fetcher.rs b/substrate/core/client/src/light/fetcher.rs index 39563aa83c..0a8a05b850 100644 --- a/substrate/core/client/src/light/fetcher.rs +++ b/substrate/core/client/src/light/fetcher.rs @@ -588,7 +588,7 @@ pub mod tests { let remote_client = test_client::new(); let mut local_headers_hashes = Vec::new(); for i in 0..4 { - let builder = remote_client.new_block().unwrap(); + let builder = remote_client.new_block(Default::default()).unwrap(); remote_client.import(BlockOrigin::Own, builder.bake().unwrap()).unwrap(); local_headers_hashes.push(remote_client.block_hash(i + 1) .map_err(|_| ClientError::Backend("TestError".into()))); diff --git a/substrate/core/consensus/aura/src/digest.rs b/substrate/core/consensus/aura/src/digest.rs new file mode 100644 index 0000000000..fe85c5807e --- /dev/null +++ b/substrate/core/consensus/aura/src/digest.rs @@ -0,0 +1,67 @@ +// Copyright 2018-2019 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Aura (Authority-Round) digests +//! +//! This implements the digests for AuRa, to allow the private +//! `CompatibleDigestItem` trait to appear in public interfaces. +use primitives::Pair; +use aura_primitives::AURA_ENGINE_ID; +use runtime_primitives::generic::DigestItem; +use parity_codec::{Encode, Decode}; + +type Signature

=

::Signature; + +/// A digest item which is usable with aura consensus. +pub trait CompatibleDigestItem: Sized { + /// Construct a digest item which contains a signature on the hash. + fn aura_seal(signature: Signature) -> Self; + + /// If this item is an Aura seal, return the signature. + fn as_aura_seal(&self) -> Option<&Signature>; + + /// Construct a digest item which contains the slot number + fn aura_pre_digest(slot_num: u64) -> Self; + + /// If this item is an AuRa pre-digest, return the slot number + fn as_aura_pre_digest(&self) -> Option; +} + +impl CompatibleDigestItem

for DigestItem + where P: Pair, P::Signature: Clone + Encode + Decode, +{ + fn aura_seal(signature: Signature

) -> Self { + DigestItem::Seal(AURA_ENGINE_ID, signature) + } + + fn as_aura_seal(&self) -> Option<&Signature

> { + match self { + DigestItem::Seal(AURA_ENGINE_ID, ref sig) => Some(sig), + _ => None, + } + } + + fn aura_pre_digest(slot_num: u64) -> Self { + DigestItem::PreRuntime(AURA_ENGINE_ID, slot_num.encode()) + } + + fn as_aura_pre_digest(&self) -> Option { + match self { + DigestItem::PreRuntime(AURA_ENGINE_ID, ref buffer) => Decode::decode(&mut &buffer[..]), + _ => None, + } + } +} diff --git a/substrate/core/consensus/aura/src/lib.rs b/substrate/core/consensus/aura/src/lib.rs index 554a63de94..e3ab9e31cf 100644 --- a/substrate/core/consensus/aura/src/lib.rs +++ b/substrate/core/consensus/aura/src/lib.rs @@ -44,18 +44,20 @@ use client::{ error::Result as CResult, backend::AuxStore, }; -use aura_primitives::AURA_ENGINE_ID; -use runtime_primitives::{generic, generic::BlockId, Justification}; + +use runtime_primitives::{generic::{self, BlockId}, Justification}; use runtime_primitives::traits::{ - Block, Header, Digest, DigestItemFor, DigestItem, ProvideRuntimeApi, AuthorityIdFor, Zero, + Block, Header, Digest, DigestItemFor, DigestItem, ProvideRuntimeApi, AuthorityIdFor, + Zero, Member, }; + use primitives::Pair; use inherents::{InherentDataProviders, InherentData}; use authorities::AuthoritiesApi; -use futures::{Future, IntoFuture, future, stream::Stream}; +use futures::{Future, IntoFuture, future}; use tokio::timer::Timeout; -use log::{warn, debug, info, trace}; +use log::{error, warn, debug, info, trace}; use srml_aura::{ InherentType as AuraInherent, AuraInherentData, @@ -68,24 +70,10 @@ use slots::{CheckedHeader, SlotWorker, SlotInfo, SlotCompatible, slot_now, check pub use aura_primitives::*; pub use consensus_common::{SyncOracle, ExtraVerification}; +mod digest; +use digest::CompatibleDigestItem; + type AuthorityId

=

::Public; -type Signature

=

::Signature; - -/// A handle to the network. This is generally implemented by providing some -/// handle to a gossip service or similar. -/// -/// Intended to be a lightweight handle such as an `Arc`. -#[deprecated( - since = "1.0.1", - note = "This is dead code and will be removed in a future release", -)] -pub trait Network: Clone { - /// A stream of input messages for a topic. - type In: Stream,Error=()>; - - /// Send a message at a specific round out. - fn send_message(&self, slot: u64, message: Vec); -} /// A slot duration. Create with `get_or_compute`. #[derive(Clone, Copy, Debug, Encode, Decode, Hash, PartialOrd, Ord, PartialEq, Eq)] @@ -122,48 +110,6 @@ fn slot_author(slot_num: u64, authorities: &[AuthorityId

]) -> Option Some(current_author) } -/// A digest item which is usable with aura consensus. -pub trait CompatibleDigestItem: Sized { - /// Construct a digest item which contains a slot number and a signature on the - /// hash. - fn aura_seal(slot_num: u64, signature: Signature) -> Self; - - /// If this item is an Aura seal, return the slot number and signature. - fn as_aura_seal(&self) -> Option<(u64, Signature)>; - - /// Return `true` if this seal type is deprecated. Otherwise, return - /// `false`. - fn is_deprecated(&self) -> bool; -} - -impl CompatibleDigestItem

for generic::DigestItem - where P: Pair, P::Signature: Clone + Encode + Decode, -{ - /// Construct a digest item which is a slot number and a signature on the - /// hash. - fn aura_seal(slot_number: u64, signature: Signature

) -> Self { - generic::DigestItem::Consensus(AURA_ENGINE_ID, (slot_number, signature).encode()) - } - - /// If this item is an Aura seal, return the slot number and signature. - #[allow(deprecated)] - fn as_aura_seal(&self) -> Option<(u64, Signature

)> { - match self { - generic::DigestItem::Seal(slot, ref sig) => Some((*slot, (*sig).clone())), - generic::DigestItem::Consensus(AURA_ENGINE_ID, seal) => Decode::decode(&mut &seal[..]), - _ => None, - } - } - - #[allow(deprecated)] - fn is_deprecated(&self) -> bool { - match self { - generic::DigestItem::Seal(_, _) => true, - _ => false, - } - } -} - #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] struct AuraSlotCompatible; @@ -178,60 +124,8 @@ impl SlotCompatible for AuraSlotCompatible { } } -/// Start the aura worker in a separate thread. -#[deprecated(since = "1.1", note = "Please spawn a thread manually")] -pub fn start_aura_thread( - slot_duration: SlotDuration, - local_key: Arc

, - client: Arc, - select_chain: SC, - block_import: Arc, - env: Arc, - sync_oracle: SO, - on_exit: OnExit, - inherent_data_providers: InherentDataProviders, - force_authoring: bool, -) -> Result<(), consensus_common::Error> where - B: Block + 'static, - C: ProvideRuntimeApi + ProvideCache + AuxStore + Send + Sync + 'static, - C::Api: AuthoritiesApi, - SC: SelectChain + Clone + 'static, - E: Environment + Send + Sync + 'static, - E::Proposer: Proposer + Send + 'static, - <>::Create as IntoFuture>::Future: Send + 'static, - I: BlockImport + Send + Sync + 'static, - Error: From + 'static, - P: Pair + Send + Sync + 'static, - P::Public: Encode + Decode + Eq + Clone + Debug + Hash + Send + Sync + 'static, - P::Signature: Encode, - SO: SyncOracle + Send + Sync + Clone + 'static, - OnExit: Future + Send + 'static, - DigestItemFor: CompatibleDigestItem

+ DigestItem> + 'static, - Error: ::std::error::Error + Send + From<::consensus_common::Error> + 'static, -{ - let worker = AuraWorker { - client: client.clone(), - block_import, - env, - local_key, - inherent_data_providers: inherent_data_providers.clone(), - sync_oracle: sync_oracle.clone(), - force_authoring, - }; - - #[allow(deprecated)] // The function we are in is also deprecated. - slots::start_slot_worker_thread::<_, _, _, _, AuraSlotCompatible, u64, _>( - slot_duration.0, - select_chain, - Arc::new(worker), - sync_oracle, - on_exit, - inherent_data_providers - ) -} - /// Start the aura worker. The returned future should be run in a tokio runtime. -pub fn start_aura( +pub fn start_aura( slot_duration: SlotDuration, local_key: Arc

, client: Arc, @@ -243,20 +137,25 @@ pub fn start_aura( inherent_data_providers: InherentDataProviders, force_authoring: bool, ) -> Result, consensus_common::Error> where - B: Block, - C: ProvideRuntimeApi + ProvideCache + AuxStore, + B: Block, + C: ProvideRuntimeApi + ProvideCache + AuxStore + Send + Sync, C::Api: AuthoritiesApi, - SC: SelectChain + Clone, - E: Environment, + SC: SelectChain, + generic::DigestItem: DigestItem, E::Proposer: Proposer, <>::Create as IntoFuture>::Future: Send + 'static, - I: BlockImport + Send + Sync + 'static, P: Pair + Send + Sync + 'static, - P::Public: Hash + Eq + Send + Sync + Clone + Debug + Encode + Decode + 'static, - P::Signature: Encode, - SO: SyncOracle + Send + Sync + Clone, + P::Public: Hash + Member + Encode + Decode, + P::Signature: Hash + Member + Encode + Decode, DigestItemFor: CompatibleDigestItem

+ DigestItem>, + H: Header< + Digest=generic::Digest>, + Hash=B::Hash, + >, + E: Environment, + I: BlockImport + Send + Sync + 'static, Error: ::std::error::Error + Send + From<::consensus_common::Error> + From + 'static, + SO: SyncOracle + Send + Sync + Clone, OnExit: Future, { let worker = AuraWorker { @@ -288,18 +187,23 @@ struct AuraWorker { force_authoring: bool, } -impl SlotWorker for AuraWorker where - C: ProvideRuntimeApi + ProvideCache + AuxStore, +impl SlotWorker for AuraWorker where + B: Block, + C: ProvideRuntimeApi + ProvideCache + Sync, C::Api: AuthoritiesApi, E: Environment, E::Proposer: Proposer, <>::Create as IntoFuture>::Future: Send + 'static, + H: Header< + Digest=generic::Digest>, + Hash=B::Hash, + >, I: BlockImport + Send + Sync + 'static, P: Pair + Send + Sync + 'static, - P::Public: Hash + Eq + Send + Sync + Clone + Debug + Encode + Decode + 'static, - P::Signature: Encode, + P::Public: Member + Encode + Decode + Hash, + P::Signature: Member + Encode + Decode + Hash + Debug, SO: SyncOracle + Send + Clone, - DigestItemFor: CompatibleDigestItem

+ DigestItem>, + DigestItemFor: CompatibleDigestItem

+ DigestItem, Hash=B::Hash>, Error: ::std::error::Error + Send + From<::consensus_common::Error> + From + 'static, { type OnSlot = Box + Send>; @@ -376,7 +280,15 @@ impl SlotWorker for AuraWorker as CompatibleDigestItem

>::aura_pre_digest(slot_num), + ], + }, + remaining_duration, + ).into_future(), remaining_duration, ) } else { @@ -384,72 +296,98 @@ impl SlotWorker for AuraWorker slot_num - ); - return - } + Box::new(proposal_work.map(move |b| { + // minor hack since we don't have access to the timestamp + // that is actually set by the proposer. + let slot_after_building = slot_now(slot_duration); + if slot_after_building != Some(slot_num) { + info!( + "Discarding proposal for slot {}; block production took too long", + slot_num + ); + telemetry!(CONSENSUS_INFO; "aura.discarding_proposal_took_too_long"; + "slot" => slot_num + ); + return + } - let (header, body) = b.deconstruct(); - let header_num = header.number().clone(); - let pre_hash = header.hash(); - let parent_hash = header.parent_hash().clone(); + let (header, body) = b.deconstruct(); + let pre_digest: Result = find_pre_digest::(&header); + if let Err(e) = pre_digest { + error!(target: "aura", "FATAL ERROR: Invalid pre-digest: {}!", e); + return + } else { + trace!(target: "aura", "Got correct number of seals. Good!") + }; - // sign the pre-sealed hash of the block and then - // add it to a digest item. - let to_sign = (slot_num, pre_hash).encode(); - let signature = pair.sign(&to_sign[..]); - let item = as CompatibleDigestItem

>::aura_seal( - slot_num, - signature, - ); + let header_num = header.number().clone(); + let parent_hash = header.parent_hash().clone(); - let import_block: ImportBlock = ImportBlock { - origin: BlockOrigin::Own, - header, - justification: None, - post_digests: vec![item], - body: Some(body), - finalized: false, - auxiliary: Vec::new(), - fork_choice: ForkChoiceStrategy::LongestChain, - }; + // sign the pre-sealed hash of the block and then + // add it to a digest item. + let header_hash = header.hash(); + let signature = pair.sign(header_hash.as_ref()); + let signature_digest_item = as CompatibleDigestItem

>::aura_seal(signature); - info!("Pre-sealed block for proposal at {}. Hash now {:?}, previously {:?}.", - header_num, - import_block.post_header().hash(), - pre_hash - ); - telemetry!(CONSENSUS_INFO; "aura.pre_sealed_block"; - "header_num" => ?header_num, - "hash_now" => ?import_block.post_header().hash(), - "hash_previously" => ?pre_hash - ); + let import_block: ImportBlock = ImportBlock { + origin: BlockOrigin::Own, + header, + justification: None, + post_digests: vec![signature_digest_item], + body: Some(body), + finalized: false, + auxiliary: Vec::new(), + fork_choice: ForkChoiceStrategy::LongestChain, + }; - if let Err(e) = block_import.import_block(import_block, Default::default()) { - warn!(target: "aura", "Error with block built on {:?}: {:?}", - parent_hash, e); - telemetry!(CONSENSUS_WARN; "aura.err_with_block_built_on"; - "hash" => ?parent_hash, "err" => ?e - ); - } - }) - .map_err(|e| consensus_common::Error::ClientImport(format!("{:?}", e)).into()) - ) + info!("Pre-sealed block for proposal at {}. Hash now {:?}, previously {:?}.", + header_num, + import_block.post_header().hash(), + header_hash + ); + telemetry!(CONSENSUS_INFO; "aura.pre_sealed_block"; + "header_num" => ?header_num, + "hash_now" => ?import_block.post_header().hash(), + "hash_previously" => ?header_hash + ); + + if let Err(e) = block_import.import_block(import_block, Default::default()) { + warn!(target: "aura", "Error with block built on {:?}: {:?}", + parent_hash, e); + telemetry!(CONSENSUS_WARN; "aura.err_with_block_built_on"; + "hash" => ?parent_hash, "err" => ?e + ); + } + }).map_err(|e| consensus_common::Error::ClientImport(format!("{:?}", e)).into())) } } +macro_rules! aura_err { + ($($i: expr),+) => { + { debug!(target: "aura", $($i),+) + ; format!($($i),+) + } + }; +} + +fn find_pre_digest(header: &B::Header) -> Result + where DigestItemFor: CompatibleDigestItem

, + P::Signature: Decode, + P::Public: Encode + Decode + PartialEq + Clone, +{ + let mut pre_digest: Option = None; + for log in header.digest().logs() { + trace!(target: "aura", "Checking log {:?}", log); + match (log.as_aura_pre_digest(), pre_digest.is_some()) { + (Some(_), true) => Err(aura_err!("Multiple AuRa pre-runtime headers, rejecting!"))?, + (None, _) => trace!(target: "aura", "Ignoring digest not meant for us"), + (s, false) => pre_digest = s, + } + } + pre_digest.ok_or_else(|| aura_err!("No AuRa pre-runtime digest found")) +} + + /// check a header has been signed by the right key. If the slot is too far in the future, an error will be returned. /// if it's successful, returns the pre-header and the digest item containing the seal. /// @@ -462,30 +400,25 @@ fn check_header( mut header: B::Header, hash: B::Hash, authorities: &[AuthorityId

], - allow_old_seals: bool, -) -> Result>, String> - where DigestItemFor: CompatibleDigestItem

, - P::Signature: Decode, - C: client::backend::AuxStore, - P::Public: AsRef + Encode + Decode + PartialEq + Clone, +) -> Result)>, String> where + DigestItemFor: CompatibleDigestItem

, + P::Signature: Decode, + C: client::backend::AuxStore, + P::Public: AsRef + Encode + Decode + PartialEq + Clone, { - let digest_item = match header.digest_mut().pop() { + let seal = match header.digest_mut().pop() { Some(x) => x, None => return Err(format!("Header {:?} is unsealed", hash)), }; - if !allow_old_seals && digest_item.is_deprecated() { - debug!(target: "aura", "Header {:?} uses old seal format, rejecting", hash); - return Err(format!("Header {:?} uses old seal format, rejecting", hash)) - } - - let (slot_num, sig) = digest_item.as_aura_seal().ok_or_else(|| { - debug!(target: "aura", "Header {:?} is unsealed", hash); - format!("Header {:?} is unsealed", hash) + let sig = seal.as_aura_seal().ok_or_else(|| { + aura_err!("Header {:?} has a bad seal", hash) })?; + let slot_num = find_pre_digest::(&header)?; + if slot_num > slot_now { - header.digest_mut().push(digest_item); + header.digest_mut().push(seal); Ok(CheckedHeader::Deferred(header, slot_num)) } else { // check the signature is valid under the expected authority and @@ -496,16 +429,14 @@ fn check_header( }; let pre_hash = header.hash(); - let to_sign = (slot_num, pre_hash).encode(); - let public = expected_author; - if P::verify(&sig, &to_sign[..], public) { + if P::verify(&sig, pre_hash.as_ref(), expected_author) { match check_equivocation::<_, _,

::Public>( client, slot_now, slot_num, header.clone(), - public.clone(), + expected_author.clone(), ) { Ok(Some(equivocation_proof)) => { let log_str = format!( @@ -517,7 +448,7 @@ fn check_header( info!("{}", log_str); Err(log_str) }, - Ok(None) => Ok(CheckedHeader::Checked(header, digest_item)), + Ok(None) => Ok(CheckedHeader::Checked(header, (slot_num, seal))), Err(e) => Err(e.to_string()), } } else { @@ -532,7 +463,6 @@ pub struct AuraVerifier { extra: E, phantom: PhantomData

, inherent_data_providers: inherents::InherentDataProviders, - allow_old_seals: bool, } impl AuraVerifier @@ -631,20 +561,17 @@ impl Verifier for AuraVerifier where ); // we add one to allow for some small drift. - // FIXME #1019 in the future, alter this queue to allow deferring of headers + // FIXME #1019 in the future, alter this queue to allow deferring of + // headers let checked_header = check_header::( &self.client, slot_now + 1, header, hash, &authorities[..], - self.allow_old_seals, )?; match checked_header { - CheckedHeader::Checked(pre_header, seal) => { - let (slot_num, _) = seal.as_aura_seal() - .expect("check_header always returns a seal digest item; qed"); - + CheckedHeader::Checked(pre_header, (slot_num, seal)) => { // if the body is passed through, we need to use the runtime // to check that the internally-set timestamp in the inherents // actually matches the slot set in the seal. @@ -813,52 +740,6 @@ pub fn import_queue( extra, inherent_data_providers, phantom: PhantomData, - allow_old_seals: false, - } - ); - Ok(BasicQueue::new( - verifier, - block_import, - justification_import, - finality_proof_import, - finality_proof_request_builder, - )) -} - -/// Start an import queue for the Aura consensus algorithm with backwards compatibility. -#[deprecated( - since = "1.0.1", - note = "should not be used unless backwards compatibility with an older chain is needed.", -)] -pub fn import_queue_accept_old_seals( - slot_duration: SlotDuration, - block_import: SharedBlockImport, - justification_import: Option>, - finality_proof_import: Option>, - finality_proof_request_builder: Option>, - client: Arc, - extra: E, - inherent_data_providers: InherentDataProviders, -) -> Result, consensus_common::Error> where - B: Block, - C: 'static + ProvideRuntimeApi + ProvideCache + Send + Sync + AuxStore, - C::Api: BlockBuilderApi + AuthoritiesApi, - DigestItemFor: CompatibleDigestItem

+ DigestItem>, - E: 'static + ExtraVerification, - P: Pair + Send + Sync + 'static, - P::Public: Clone + Eq + Send + Sync + Hash + Debug + Encode + Decode + AsRef, - P::Signature: Encode + Decode, -{ - register_aura_inherent_data_provider(&inherent_data_providers, slot_duration.get())?; - initialize_authorities_cache(&*client)?; - - let verifier = Arc::new( - AuraVerifier { - client: client.clone(), - extra, - inherent_data_providers, - phantom: PhantomData, - allow_old_seals: true, } ); Ok(BasicQueue::new( @@ -873,10 +754,11 @@ pub fn import_queue_accept_old_seals( #[cfg(test)] mod tests { use super::*; + use futures::stream::Stream as _; use consensus_common::NoNetwork as DummyOracle; use network::test::*; use network::test::{Block as TestBlock, PeersClient, PeersFullClient}; - use runtime_primitives::traits::Block as BlockT; + use runtime_primitives::traits::{Block as BlockT, DigestFor}; use network::config::ProtocolConfig; use parking_lot::Mutex; use tokio::runtime::current_thread; @@ -910,8 +792,13 @@ mod tests { type Error = Error; type Create = Result; - fn propose(&self, _: InherentData, _: Duration) -> Result { - self.1.new_block().unwrap().bake().map_err(|e| e.into()) + fn propose( + &self, + _: InherentData, + digests: DigestFor, + _: Duration, + ) -> Result { + self.1.new_block(digests).unwrap().bake().map_err(|e| e.into()) } } @@ -955,7 +842,6 @@ mod tests { extra: NothingExtra, inherent_data_providers, phantom: Default::default(), - allow_old_seals: false, }) }, PeersClient::Light(_) => unreachable!("No (yet) tests for light client + Aura"), @@ -995,19 +881,18 @@ mod tests { extrinsics_root: Default::default(), digest: DigestTest { logs: vec![], }, }; + let item = as CompatibleDigestItem>::aura_pre_digest(slot_num); + header.digest_mut().push(item); let header_hash: H256 = header.hash(); - let to_sign = (slot_num, header_hash).encode(); - let signature = pair.sign(&to_sign[..]); + let signature = pair.sign(&header_hash[..]); - let item = as CompatibleDigestItem>::aura_seal( - slot_num, - signature, - ); + let item = CompatibleDigestItem::::aura_seal(signature); header.digest_mut().push(item); (header, header_hash) } #[test] + #[allow(deprecated)] fn authoring_blocks() { let _ = ::env_logger::try_init(); let mut net = AuraTestNet::new(3); @@ -1046,7 +931,7 @@ mod tests { &inherent_data_providers, slot_duration.get() ).expect("Registers aura inherent data provider"); - let aura = start_aura::<_, _, _, _, _, sr25519::Pair, _, _, _>( + let aura = start_aura::<_, _, _, _, _, sr25519::Pair, _, _, _, _>( slot_duration, Arc::new(key.clone().into()), client.clone(), @@ -1111,22 +996,22 @@ mod tests { let c = Arc::new(client); // It's ok to sign same headers. - assert!(check_header::<_, B, P>(&c, 2, header1.clone(), header1_hash, &authorities, false).is_ok()); - assert!(check_header::<_, B, P>(&c, 3, header1, header1_hash, &authorities, false).is_ok()); + check_header::<_, B, P>(&c, 2, header1.clone(), header1_hash, &authorities).unwrap(); + assert!(check_header::<_, B, P>(&c, 3, header1, header1_hash, &authorities).is_ok()); // But not two different headers at the same slot. - assert!(check_header::<_, B, P>(&c, 4, header2, header2_hash, &authorities, false).is_err()); + assert!(check_header::<_, B, P>(&c, 4, header2, header2_hash, &authorities).is_err()); // Different slot is ok. - assert!(check_header::<_, B, P>(&c, 5, header3, header3_hash, &authorities, false).is_ok()); + assert!(check_header::<_, B, P>(&c, 5, header3, header3_hash, &authorities).is_ok()); // Here we trigger pruning and save header 4. - assert!(check_header::<_, B, P>(&c, PRUNING_BOUND + 2, header4, header4_hash, &authorities, false).is_ok()); + assert!(check_header::<_, B, P>(&c, PRUNING_BOUND + 2, header4, header4_hash, &authorities).is_ok()); // This fails because header 5 is an equivocation of header 4. - assert!(check_header::<_, B, P>(&c, PRUNING_BOUND + 3, header5, header5_hash, &authorities, false).is_err()); + assert!(check_header::<_, B, P>(&c, PRUNING_BOUND + 3, header5, header5_hash, &authorities).is_err()); // This is ok because we pruned the corresponding header. Shows that we are pruning. - assert!(check_header::<_, B, P>(&c, PRUNING_BOUND + 4, header6, header6_hash, &authorities, false).is_ok()); + assert!(check_header::<_, B, P>(&c, PRUNING_BOUND + 4, header6, header6_hash, &authorities).is_ok()); } } diff --git a/substrate/core/consensus/babe/primitives/src/lib.rs b/substrate/core/consensus/babe/primitives/src/lib.rs index 83ba6ccba2..0e49c45198 100644 --- a/substrate/core/consensus/babe/primitives/src/lib.rs +++ b/substrate/core/consensus/babe/primitives/src/lib.rs @@ -15,7 +15,7 @@ // along with Substrate. If not, see . //! Primitives for BABE. -#![forbid(warnings, unsafe_code, missing_docs)] +#![deny(warnings, unsafe_code, missing_docs)] #![cfg_attr(not(feature = "std"), no_std)] use runtime_primitives::ConsensusEngineId; diff --git a/substrate/core/consensus/babe/src/digest.rs b/substrate/core/consensus/babe/src/digest.rs new file mode 100644 index 0000000000..b26a1508b5 --- /dev/null +++ b/substrate/core/consensus/babe/src/digest.rs @@ -0,0 +1,149 @@ +// Copyright 2019 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Private mplementation details of BABE digests. +use primitives::sr25519::{Public, Signature}; +use babe_primitives::BABE_ENGINE_ID; +use runtime_primitives::generic::DigestItem; +use std::fmt::Debug; +use parity_codec::{Decode, Encode, Input}; +use log::info; +use schnorrkel::{ + vrf::{VRFProof, VRFOutput, VRF_OUTPUT_LENGTH, VRF_PROOF_LENGTH}, + PUBLIC_KEY_LENGTH, +}; + +/// A BABE pre-digest. It includes: +/// +/// * The public key of the author. +/// * The VRF proof. +/// * The VRF output. +/// * The slot number. +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct BabePreDigest { + pub(super) vrf_output: VRFOutput, + pub(super) proof: VRFProof, + pub(super) author: Public, + pub(super) slot_num: u64, +} + +/// The prefix used by BABE for its VRF keys. +pub const BABE_VRF_PREFIX: &'static [u8] = b"substrate-babe-vrf"; + +type TmpDecode = ( + [u8; VRF_OUTPUT_LENGTH], + [u8; VRF_PROOF_LENGTH], + [u8; PUBLIC_KEY_LENGTH], + u64, +); + +impl Encode for BabePreDigest { + fn encode(&self) -> Vec { + let tmp: TmpDecode = ( + *self.vrf_output.as_bytes(), + self.proof.to_bytes(), + self.author.0, + self.slot_num, + ); + parity_codec::Encode::encode(&tmp) + } +} + +impl Decode for BabePreDigest { + fn decode(i: &mut R) -> Option { + let (output, proof, public_key, slot_num): TmpDecode = Decode::decode(i)?; + Some(BabePreDigest { + proof: VRFProof::from_bytes(&proof).ok()?, + vrf_output: VRFOutput::from_bytes(&output).ok()?, + author: Public(public_key), + slot_num, + }) + } +} + +/// A digest item which is usable with BABE consensus. +pub trait CompatibleDigestItem: Sized { + /// Construct a digest item which contains a BABE pre-digest. + fn babe_pre_digest(seal: BabePreDigest) -> Self; + + /// If this item is an BABE pre-digest, return it. + fn as_babe_pre_digest(&self) -> Option; + + /// Construct a digest item which contains a BABE seal. + fn babe_seal(signature: Signature) -> Self; + + /// If this item is a BABE signature, return the signature. + fn as_babe_seal(&self) -> Option; +} + +impl CompatibleDigestItem for DigestItem> +{ + fn babe_pre_digest(digest: BabePreDigest) -> Self { + DigestItem::PreRuntime(BABE_ENGINE_ID, digest.encode()) + } + + fn as_babe_pre_digest(&self) -> Option { + match self { + DigestItem::PreRuntime(BABE_ENGINE_ID, seal) => { + let decoded = Decode::decode(&mut &seal[..]); + if decoded.is_none() { + info!(target: "babe", "Failed to decode {:?}", seal) + } + decoded + } + _ => { + info!(target: "babe", "Invalid consensus: {:?}!", self); + None + } + } + } + + fn babe_seal(signature: Signature) -> Self { + DigestItem::Seal(BABE_ENGINE_ID, signature.encode()) + } + + fn as_babe_seal(&self) -> Option { + match self { + DigestItem::Seal(BABE_ENGINE_ID, signature) => Decode::decode(&mut &signature[..]), + _ => None, + } + } +} + +impl CompatibleDigestItem for DigestItem +{ + fn babe_pre_digest(digest: BabePreDigest) -> Self { + DigestItem::PreRuntime(BABE_ENGINE_ID, digest.encode()) + } + + fn as_babe_pre_digest(&self) -> Option { + match self { + DigestItem::PreRuntime(BABE_ENGINE_ID, seal) => Decode::decode(&mut &seal[..]), + _ => None, + } + } + + fn babe_seal(signature: Signature) -> Self { + DigestItem::Seal(BABE_ENGINE_ID, signature) + } + + fn as_babe_seal(&self) -> Option { + match self { + DigestItem::Seal(BABE_ENGINE_ID, signature) => Some(signature.clone()), + _ => None, + } + } +} \ No newline at end of file diff --git a/substrate/core/consensus/babe/src/lib.rs b/substrate/core/consensus/babe/src/lib.rs index 72a4e55a30..2d1afb0187 100644 --- a/substrate/core/consensus/babe/src/lib.rs +++ b/substrate/core/consensus/babe/src/lib.rs @@ -16,7 +16,7 @@ //! # BABE consensus //! -//! BABE (Blind Assignment for Blockchain Extension) consensus in substrate. +//! BABE (Blind Assignment for Blockchain Extension) consensus in Substrate. //! //! # Stability //! @@ -26,32 +26,42 @@ #![forbid(unsafe_code, missing_docs)] #![deny(warnings)] extern crate core; +mod digest; +use digest::CompatibleDigestItem; +pub use digest::{BabePreDigest, BABE_VRF_PREFIX}; pub use babe_primitives::*; pub use consensus_common::SyncOracle; use consensus_common::ExtraVerification; use runtime_primitives::{generic, generic::BlockId, Justification}; use runtime_primitives::traits::{ Block, Header, Digest, DigestItemFor, DigestItem, ProvideRuntimeApi, AuthorityIdFor, + SimpleBitOps, }; -use std::{sync::Arc, u64, fmt::Debug}; -use parity_codec::{Decode, Encode, Input}; +use std::{sync::Arc, u64, fmt::{Debug, Display}}; +use runtime_support::serde::{Serialize, Deserialize}; +use parity_codec::{Decode, Encode}; use primitives::{ crypto::Pair, - sr25519::{Public, Signature, LocalizedSignature, self}, + sr25519::{Public, Signature, self}, }; use merlin::Transcript; use inherents::{InherentDataProviders, InherentData}; -use substrate_telemetry::{telemetry, CONSENSUS_TRACE, CONSENSUS_DEBUG, CONSENSUS_WARN, CONSENSUS_INFO}; +use substrate_telemetry::{ + telemetry, + CONSENSUS_TRACE, + CONSENSUS_DEBUG, + CONSENSUS_WARN, + CONSENSUS_INFO, +}; use schnorrkel::{ keys::Keypair, vrf::{ - VRFProof, VRFProofBatchable, VRFInOut, VRFOutput, - VRF_OUTPUT_LENGTH, VRF_PROOF_LENGTH, + VRFProof, VRFProofBatchable, VRFInOut, }, - PUBLIC_KEY_LENGTH, SIGNATURE_LENGTH, }; use authorities::AuthoritiesApi; -use consensus_common::{self, Authorities, BlockImport, Environment, Proposer, +use consensus_common::{ + self, Authorities, BlockImport, Environment, Proposer, ForkChoiceStrategy, ImportBlock, BlockOrigin, Error as ConsensusError, }; use srml_babe::{ @@ -74,92 +84,10 @@ use log::{error, warn, debug, info, trace}; use slots::{SlotWorker, SlotInfo, SlotCompatible, slot_now}; -/// A BABE seal. It includes: -/// -/// * The public key -/// * The VRF proof -/// * The signature -/// * The slot number -#[derive(Clone, Debug, PartialEq, Eq)] -pub struct BabeSeal { - vrf_output: VRFOutput, - proof: VRFProof, - signature: LocalizedSignature, - slot_num: u64, -} - -/// The prefix used by BABE for its VRF keys. -pub const BABE_VRF_PREFIX: &'static [u8] = b"substrate-babe-vrf"; - -macro_rules! babe_assert_eq { - ($a: expr, $b: expr) => { - { - let ref a = $a; - let ref b = $b; - if a != b { - error!( - target: "babe", - "Expected {:?} to equal {:?}, but they were not", - stringify!($a), - stringify!($b), - ); - assert_eq!(a, b); - } - } - }; -} - -type TmpDecode = ( - [u8; VRF_OUTPUT_LENGTH], - [u8; VRF_PROOF_LENGTH], - [u8; SIGNATURE_LENGTH], - [u8; PUBLIC_KEY_LENGTH], - u64, -); - -impl Encode for BabeSeal { - fn encode(&self) -> Vec { - let tmp: TmpDecode = ( - *self.vrf_output.as_bytes(), - self.proof.to_bytes(), - self.signature.signature.0, - self.signature.signer.0, - self.slot_num, - ); - let encoded = parity_codec::Encode::encode(&tmp); - if cfg!(any(test, debug_assertions)) { - debug!(target: "babe", "Checking if encoding was correct"); - let decoded_version = Self::decode(&mut &encoded[..]) - .expect("we just encoded this ourselves, so it is correct; qed"); - babe_assert_eq!(decoded_version.proof, self.proof); - babe_assert_eq!(decoded_version.vrf_output, self.vrf_output); - babe_assert_eq!(decoded_version.signature.signature, self.signature.signature); - babe_assert_eq!(decoded_version.signature.signer, self.signature.signer); - babe_assert_eq!(decoded_version.slot_num, self.slot_num); - debug!(target: "babe", "Encoding was correct") - } - encoded - } -} - -impl Decode for BabeSeal { - fn decode(i: &mut R) -> Option { - let (output, proof, sig, public_key, slot_num): TmpDecode = Decode::decode(i)?; - Some(BabeSeal { - proof: VRFProof::from_bytes(&proof).ok()?, - vrf_output: VRFOutput::from_bytes(&output).ok()?, - signature: LocalizedSignature { - signature: Signature(sig), - signer: Public(public_key), - }, - slot_num, - }) - } -} /// A slot duration. Create with `get_or_compute`. // FIXME: Once Rust has higher-kinded types, the duplication between this -// and `super::aura::Config` can be eliminated. +// and `super::babe::Config` can be eliminated. // https://github.com/paritytech/substrate/issues/2434 pub struct Config(slots::SlotDuration); @@ -191,45 +119,6 @@ impl Config { } } -/// A digest item which is usable with BABE consensus. -pub trait CompatibleDigestItem: Sized { - /// Construct a digest item which contains a slot number and a signature - /// on the hash. - fn babe_seal(signature: BabeSeal) -> Self; - - /// If this item is an Babe seal, return the slot number and signature. - fn as_babe_seal(&self) -> Option; -} - -impl CompatibleDigestItem for generic::DigestItem - where T: Debug, Hash: Debug -{ - /// Construct a digest item which contains a slot number and a signature - /// on the hash. - fn babe_seal(signature: BabeSeal) -> Self { - generic::DigestItem::Consensus(BABE_ENGINE_ID, signature.encode()) - } - - /// If this item is an BABE seal, return the slot number and signature. - fn as_babe_seal(&self) -> Option { - match self { - generic::DigestItem::Consensus(BABE_ENGINE_ID, seal) => { - match Decode::decode(&mut &seal[..]) { - s @ Some(_) => s, - s @ None => { - info!(target: "babe", "Failed to decode {:?}", seal); - s - } - } - } - _ => { - info!(target: "babe", "Invalid consensus: {:?}!", self); - None - } - } - } -} - struct BabeSlotCompatible; impl SlotCompatible for BabeSlotCompatible { @@ -280,7 +169,7 @@ pub struct BabeParams { } /// Start the babe worker. The returned future should be run in a tokio runtime. -pub fn start_babe(BabeParams { +pub fn start_babe(BabeParams { config, local_key, client, @@ -295,17 +184,22 @@ pub fn start_babe(BabeParams { impl Future, consensus_common::Error, > where - B: Block, + B: Block, C: ProvideRuntimeApi + ProvideCache, C::Api: AuthoritiesApi, - E: Environment, + SC: SelectChain, + generic::DigestItem: DigestItem, E::Proposer: Proposer, <>::Create as IntoFuture>::Future: Send + 'static, - I: BlockImport + Send + Sync + 'static, - SO: SyncOracle + Send + Sync + Clone, - SC: SelectChain, DigestItemFor: CompatibleDigestItem + DigestItem, - Error: ::std::error::Error + Send + From<::consensus_common::Error> + From + 'static, + H: Header< + Digest=generic::Digest>, + Hash=B::Hash, + >, + E: Environment, + I: BlockImport + Send + Sync + 'static, + Error: std::error::Error + Send + From<::consensus_common::Error> + From + 'static, + SO: SyncOracle + Send + Sync + Clone, OnExit: Future, { let worker = BabeWorker { @@ -339,15 +233,22 @@ struct BabeWorker { threshold: u64, } -impl SlotWorker for BabeWorker where +impl SlotWorker for BabeWorker where + B: Block, C: ProvideRuntimeApi + ProvideCache, C::Api: AuthoritiesApi, E: Environment, E::Proposer: Proposer, <>::Create as IntoFuture>::Future: Send + 'static, + Hash: Debug + Eq + Copy + SimpleBitOps + Encode + Decode + Serialize + + for<'de> Deserialize<'de> + Debug + Default + AsRef<[u8]> + AsMut<[u8]> + + std::hash::Hash + Display + Send + Sync + 'static, + H: Header< + Digest=generic::Digest>, + Hash=B::Hash, + >, I: BlockImport + Send + Sync + 'static, SO: SyncOracle + Send + Clone, - DigestItemFor: CompatibleDigestItem + DigestItem, Error: std::error::Error + Send + From<::consensus_common::Error> + From + 'static, { type OnSlot = Box + Send>; @@ -399,7 +300,7 @@ impl SlotWorker for BabeWorker whe // FIXME replace the dummy empty slices with real data // https://github.com/paritytech/substrate/issues/2435 // https://github.com/paritytech/substrate/issues/2436 - let authoring_result = if let Some((inout, proof, _batchable_proof)) = claim_slot( + let proposal_work = if let Some((inout, proof, _batchable_proof)) = claim_slot( &[0u8; 0], slot_info.number, &[0u8; 0], @@ -429,105 +330,133 @@ impl SlotWorker for BabeWorker whe } }; + let inherent_digest = BabePreDigest { + proof, + vrf_output: inout.to_output(), + author: pair.public(), + slot_num, + }; + + // deadline our production to approx. the end of the slot let remaining_duration = slot_info.remaining_duration(); - // deadline our production to approx. the end of the - // slot - (Timeout::new( + Timeout::new( proposer.propose( slot_info.inherent_data, + generic::Digest { + logs: vec![ + generic::DigestItem::babe_pre_digest(inherent_digest.clone()), + ], + }, remaining_duration, ).into_future(), remaining_duration, - ), - inout.to_output(), - proof) + ) } else { return Box::new(future::ok(())); }; - let (proposal_work, vrf_output, proof) = authoring_result; + Box::new(proposal_work.map(move |b| { + // minor hack since we don't have access to the timestamp + // that is actually set by the proposer. + let slot_after_building = slot_now(slot_duration); + if slot_after_building != Some(slot_num) { + info!( + target: "babe", + "Discarding proposal for slot {}; block production took too long", + slot_num + ); + telemetry!(CONSENSUS_INFO; "babe.discarding_proposal_took_too_long"; + "slot" => slot_num + ); + return + } - Box::new( - proposal_work - .map(move |b| { - // minor hack since we don't have access to the timestamp - // that is actually set by the proposer. - let slot_after_building = slot_now(slot_duration); - if slot_after_building != Some(slot_num) { - info!( - target: "babe", - "Discarding proposal for slot {}; block production took too long", - slot_num - ); - telemetry!(CONSENSUS_INFO; "babe.discarding_proposal_took_too_long"; - "slot" => slot_num - ); - return - } + let (header, body) = b.deconstruct(); + let pre_digest: Result = find_pre_digest::(&header); + if let Err(e) = pre_digest { + error!(target: "babe", "FATAL ERROR: Invalid pre-digest: {}!", e); + return + } else { + trace!(target: "babe", "Got correct number of seals. Good!") + }; - let (header, body) = b.deconstruct(); - let header_num = header.number().clone(); - let pre_hash = header.hash(); - let parent_hash = header.parent_hash().clone(); + let header_num = header.number().clone(); + let parent_hash = header.parent_hash().clone(); - // sign the pre-sealed hash of the block and then - // add it to a digest item. - let to_sign = (slot_num, pre_hash, proof.to_bytes()).encode(); - let signature = pair.sign(&to_sign[..]); - let item = as CompatibleDigestItem>::babe_seal(BabeSeal { - proof, - signature: LocalizedSignature { - signature, - signer: pair.public(), - }, - slot_num, - vrf_output, - }); + // sign the pre-sealed hash of the block and then + // add it to a digest item. + let header_hash = header.hash(); + let signature = pair.sign(header_hash.as_ref()); + let signature_digest_item = DigestItemFor::::babe_seal(signature); - let import_block: ImportBlock = ImportBlock { - origin: BlockOrigin::Own, - header, - justification: None, - post_digests: vec![item], - body: Some(body), - finalized: false, - auxiliary: Vec::new(), - fork_choice: ForkChoiceStrategy::LongestChain, - }; + let import_block: ImportBlock = ImportBlock { + origin: BlockOrigin::Own, + header, + justification: None, + post_digests: vec![signature_digest_item], + body: Some(body), + finalized: false, + auxiliary: Vec::new(), + fork_choice: ForkChoiceStrategy::LongestChain, + }; - info!(target: "babe", - "Pre-sealed block for proposal at {}. Hash now {:?}, previously {:?}.", - header_num, - import_block.post_header().hash(), - pre_hash - ); - telemetry!(CONSENSUS_INFO; "babe.pre_sealed_block"; - "header_num" => ?header_num, - "hash_now" => ?import_block.post_header().hash(), - "hash_previously" => ?pre_hash - ); + info!(target: "babe", + "Pre-sealed block for proposal at {}. Hash now {:?}, previously {:?}.", + header_num, + import_block.post_header().hash(), + header_hash, + ); + telemetry!(CONSENSUS_INFO; "babe.pre_sealed_block"; + "header_num" => ?header_num, + "hash_now" => ?import_block.post_header().hash(), + "hash_previously" => ?header_hash, + ); - if let Err(e) = block_import.import_block(import_block, Default::default()) { - warn!(target: "babe", "Error with block built on {:?}: {:?}", - parent_hash, e); - telemetry!(CONSENSUS_WARN; "babe.err_with_block_built_on"; - "hash" => ?parent_hash, "err" => ?e - ); - } - }) - .map_err(|e| { - warn!("Client import failed: {:?}", e); - consensus_common::Error::ClientImport(format!("{:?}", e)) - }) - ) + if let Err(e) = block_import.import_block(import_block, Default::default()) { + warn!(target: "babe", "Error with block built on {:?}: {:?}", + parent_hash, e); + telemetry!(CONSENSUS_WARN; "babe.err_with_block_built_on"; + "hash" => ?parent_hash, "err" => ?e + ); + } + }).map_err(|e| { + warn!("Client import failed: {:?}", e); + consensus_common::Error::ClientImport(format!("{:?}", e)).into() + })) } } +macro_rules! babe_err { + ($($i: expr),+) => { + { debug!(target: "babe", $($i),+) + ; format!($($i),+) + } + }; +} + +fn find_pre_digest(header: &B::Header) -> Result + where DigestItemFor: CompatibleDigestItem, +{ + let mut pre_digest: Option<_> = None; + for log in header.digest().logs() { + trace!(target: "babe", "Checking log {:?}", log); + match (log.as_babe_pre_digest(), pre_digest.is_some()) { + (Some(_), true) => Err(babe_err!("Multiple BABE pre-runtime headers, rejecting!"))?, + (None, _) => trace!(target: "babe", "Ignoring digest not meant for us"), + (s, false) => pre_digest = s, + } + } + pre_digest.ok_or_else(|| babe_err!("No BABE pre-runtime digest found")) +} + /// check a header has been signed by the right key. If the slot is too far in /// the future, an error will be returned. If successful, returns the pre-header /// and the digest item containing the seal. /// -/// This digest item will always return `Some` when used with `as_babe_seal`. +/// The seal must be the last digest. Otherwise, the whole header is considered +/// unsigned. This is required for security and must not be changed. +/// +/// This digest item will always return `Some` when used with `as_babe_pre_digest`. // // FIXME #1018 needs misbehavior types #[forbid(warnings)] @@ -538,36 +467,31 @@ fn check_header( hash: B::Hash, authorities: &[Public], threshold: u64, -) -> Result>, String> +) -> Result, DigestItemFor)>, String> where DigestItemFor: CompatibleDigestItem, { trace!(target: "babe", "Checking header"); - let digest_item = match header.digest_mut().pop() { + let seal = match header.digest_mut().pop() { Some(x) => x, - None => return Err(format!("Header {:?} is unsealed", hash)), + None => return Err(babe_err!("Header {:?} is unsealed", hash)), }; - let BabeSeal { - slot_num, - signature: LocalizedSignature { signer, signature }, - proof, - vrf_output, - } = digest_item.as_babe_seal().ok_or_else(|| { - debug!(target: "babe", "Header {:?} is unsealed", hash); - format!("Header {:?} is unsealed", hash) + let sig = seal.as_babe_seal().ok_or_else(|| { + babe_err!("Header {:?} has a bad seal", hash) })?; + let pre_digest = find_pre_digest::(&header)?; + let BabePreDigest { slot_num, ref author, ref proof, ref vrf_output } = pre_digest; + if slot_num > slot_now { - header.digest_mut().push(digest_item); + header.digest_mut().push(seal); Ok(CheckedHeader::Deferred(header, slot_num)) - } else if !authorities.contains(&signer) { - debug!(target: "babe", "Slot Author not found"); - Err("Slot Author not found".to_string()) + } else if !authorities.contains(&author) { + Err(babe_err!("Slot author not found")) } else { let pre_hash = header.hash(); - let to_sign = (slot_num, pre_hash, proof.to_bytes()).encode(); - if sr25519::Pair::verify(&signature, &to_sign[..], &signer) { + if sr25519::Pair::verify(&sig, pre_hash, author) { let (inout, _batchable_proof) = { let transcript = make_transcript( Default::default(), @@ -575,41 +499,39 @@ fn check_header( Default::default(), 0, ); - schnorrkel::PublicKey::from_bytes(signer.as_slice()).and_then(|p| { - p.vrf_verify(transcript, &vrf_output, &proof) + schnorrkel::PublicKey::from_bytes(author.as_slice()).and_then(|p| { + p.vrf_verify(transcript, vrf_output, proof) }).map_err(|s| { - debug!(target: "babe", "VRF verification failed: {:?}", s); - format!("VRF verification failed") + babe_err!("VRF verification failed: {:?}", s) })? }; - if check(&inout, threshold) { - match check_equivocation(&client, slot_now, slot_num, header.clone(), signer.clone()) { - Ok(Some(equivocation_proof)) => { - let log_str = format!( - "Slot author {:?} is equivocating at slot {} with headers {:?} and {:?}", - signer, - slot_num, - equivocation_proof.fst_header().hash(), - equivocation_proof.snd_header().hash(), - ); - info!("{}", log_str); - Err(log_str) - }, - Ok(None) => { - Ok(CheckedHeader::Checked(header, digest_item)) - }, - Err(e) => { - Err(e.to_string()) - }, - } - } else { - debug!(target: "babe", "VRF verification failed: threshold {} exceeded", threshold); - Err(format!("Validator {:?} made seal when it wasn’t its turn", signer)) + if !check(&inout, threshold) { + return Err(babe_err!("VRF verification of block by author {:?} failed: \ + threshold {} exceeded", author, threshold)) + } + match check_equivocation(&client, slot_now, slot_num, header.clone(), author.clone()) { + Ok(Some(equivocation_proof)) => { + let log_str = format!( + "Slot author {:?} is equivocating at slot {} with headers {:?} and {:?}", + author, + slot_num, + equivocation_proof.fst_header().hash(), + equivocation_proof.snd_header().hash(), + ); + info!(target: "babe", "{}", log_str); + Err(log_str) + }, + Ok(None) => { + let pre_digest = CompatibleDigestItem::babe_pre_digest(pre_digest); + Ok(CheckedHeader::Checked(header, (pre_digest, seal))) + }, + Err(e) => { + Err(e.to_string()) + }, } } else { - debug!(target: "babe", "Bad signature on {:?}", hash); - Err(format!("Bad signature on {:?}", hash)) + Err(babe_err!("Bad signature on {:?}", hash)) } } } @@ -681,6 +603,8 @@ impl Verifier for BabeVerifier where justification, body, ); + + debug!(target: "babe", "We have {:?} logs in this header", header.digest().logs().len()); let mut inherent_data = self .inherent_data_providers .create_inherent_data() @@ -709,9 +633,9 @@ impl Verifier for BabeVerifier where self.threshold, )?; match checked_header { - CheckedHeader::Checked(pre_header, seal) => { - let BabeSeal { slot_num, .. } = seal.as_babe_seal() - .expect("check_header always returns a seal digest item; qed"); + CheckedHeader::Checked(pre_header, (pre_digest, seal)) => { + let BabePreDigest { slot_num, .. } = pre_digest.as_babe_pre_digest() + .expect("check_header always returns a pre-digest digest item; qed"); // if the body is passed through, we need to use the runtime // to check that the internally-set timestamp in the inherents @@ -738,6 +662,10 @@ impl Verifier for BabeVerifier where extra_verification.into_future().wait()?; + let new_authorities = pre_header.digest() + .log(DigestItem::as_authorities_change) + .map(|digest| digest.to_vec()); + let import_block = ImportBlock { origin, header: pre_header, @@ -750,7 +678,7 @@ impl Verifier for BabeVerifier where }; // FIXME #1019 extract authorities - Ok((import_block, None)) + Ok((import_block, new_authorities)) } CheckedHeader::Deferred(a, b) => { debug!(target: "babe", "Checking {:?} failed; {:?}, {:?}.", hash, a, b); @@ -820,6 +748,7 @@ fn get_keypair(q: &sr25519::Pair) -> &Keypair { q.as_ref() } +#[allow(deprecated)] fn make_transcript( randomness: &[u8], slot_number: u64, @@ -871,7 +800,8 @@ fn claim_slot( #[cfg(test)] #[allow(dead_code, unused_imports, deprecated)] -// FIXME #2532: need to allow deprecated until refactor is done https://github.com/paritytech/substrate/issues/2532 +// FIXME #2532: need to allow deprecated until refactor is done +// https://github.com/paritytech/substrate/issues/2532 mod tests { use super::*; @@ -880,16 +810,18 @@ mod tests { use consensus_common::NoNetwork as DummyOracle; use network::test::*; use network::test::{Block as TestBlock, PeersClient}; - use runtime_primitives::traits::Block as BlockT; + use runtime_primitives::traits::{Block as BlockT, DigestFor}; use network::config::ProtocolConfig; use parking_lot::Mutex; use tokio::runtime::current_thread; use keyring::sr25519::Keyring; + use super::generic::DigestItem; use client::BlockchainEvents; use test_client; use futures::stream::Stream; use log::debug; use std::time::Duration; + type Item = generic::DigestItem; use test_client::AuthorityKeyring; use primitives::hash::H256; use runtime_primitives::testing::{Header as HeaderTest, Digest as DigestTest, Block as RawBlock, ExtrinsicWrapper}; @@ -922,8 +854,8 @@ mod tests { type Error = Error; type Create = Result; - fn propose(&self, _: InherentData, _: Duration) -> Result { - self.1.new_block().unwrap().bake().map_err(|e| e.into()) + fn propose(&self, _: InherentData, digests: DigestFor, _: Duration) -> Result { + self.1.new_block(digests).unwrap().bake().map_err(|e| e.into()) } } @@ -1020,26 +952,30 @@ mod tests { let (inout, proof, _batchable_proof) = get_keypair(&pair).vrf_sign_n_check(transcript, |inout| check(inout, u64::MAX)).unwrap(); let pre_hash: H256 = header.hash(); - let to_sign = (slot_num, pre_hash, proof.to_bytes()).encode(); - let signature = pair.sign(&to_sign[..]); - let item = as CompatibleDigestItem>::babe_seal(BabeSeal { + let pre_digest = BabePreDigest { proof, - signature: LocalizedSignature { - signature, - signer: pair.public(), - }, + author: pair.public(), slot_num, vrf_output: inout.to_output(), - }); - + }; + assert_eq!( + Decode::decode(&mut &pre_digest.encode()[..]).as_ref(), + Some(&pre_digest), + "Pre-digest encoding and decoding did not round-trip", + ); + let item = generic::DigestItem::babe_pre_digest(pre_digest); header.digest_mut().push(item); + + let to_sign = header.hash(); + let signature = pair.sign(&to_sign[..]); + header.digest_mut().push(generic::DigestItem::babe_seal(signature)); (header, pre_hash) } #[test] fn can_serialize_block() { drop(env_logger::try_init()); - assert!(BabeSeal::decode(&mut &b""[..]).is_none()); + assert!(BabePreDigest::decode(&mut &b""[..]).is_none()); } #[test] @@ -1118,26 +1054,28 @@ mod tests { } #[test] - #[allow(deprecated)] - #[should_panic] - fn old_seals_rejected() { + fn wrong_consensus_engine_id_rejected() { drop(env_logger::try_init()); - generic::DigestItem::::Seal(0, Signature([0; 64])).as_babe_seal().unwrap(); - } - - #[test] - fn wrong_number_rejected() { - drop(env_logger::try_init()); - let bad_seal = generic::DigestItem::::Consensus([0; 4], Signature([0; 64]).encode()); + let sig = sr25519::Pair::generate().sign(b""); + let bad_seal: Item = DigestItem::Seal([0; 4], sig); + assert!(bad_seal.as_babe_pre_digest().is_none()); assert!(bad_seal.as_babe_seal().is_none()) } #[test] - #[should_panic] - fn bad_seal_rejected() { + fn malformed_pre_digest_rejected() { drop(env_logger::try_init()); - let bad_seal = generic::DigestItem::::Consensus(BABE_ENGINE_ID, Signature([0; 64]).encode()); - bad_seal.as_babe_seal().expect("we should not decode this successfully"); + let bad_seal: Item = DigestItem::Seal(BABE_ENGINE_ID, Signature([0; 64])); + assert!(bad_seal.as_babe_pre_digest().is_none()); + } + + #[test] + fn sig_is_not_pre_digest() { + drop(env_logger::try_init()); + let sig = sr25519::Pair::generate().sign(b""); + let bad_seal: Item = DigestItem::Seal(BABE_ENGINE_ID, sig); + assert!(bad_seal.as_babe_pre_digest().is_none()); + assert!(bad_seal.as_babe_seal().is_some()) } #[test] @@ -1172,6 +1110,7 @@ mod tests { #[test] fn check_header_works_with_equivocation() { + drop(env_logger::try_init()); let client = test_client::new(); let pair = sr25519::Pair::generate(); let public = pair.public(); diff --git a/substrate/core/consensus/common/src/import_queue.rs b/substrate/core/consensus/common/src/import_queue.rs index 26ae181b51..d44aa0b93a 100644 --- a/substrate/core/consensus/common/src/import_queue.rs +++ b/substrate/core/consensus/common/src/import_queue.rs @@ -37,7 +37,7 @@ use std::sync::Arc; use std::thread; use runtime_primitives::traits::{ - AuthorityIdFor, Block as BlockT, Header as HeaderT, NumberFor + AuthorityIdFor, Block as BlockT, Header as HeaderT, NumberFor, Digest, }; use runtime_primitives::Justification; @@ -873,6 +873,8 @@ pub fn import_single_block>( }, }; + trace!(target: "sync", "Header {} has {:?} logs", block.hash, header.digest().logs().len()); + let number = header.number().clone(); let hash = header.hash(); let parent = header.parent_hash().clone(); diff --git a/substrate/core/consensus/common/src/lib.rs b/substrate/core/consensus/common/src/lib.rs index 2d6c53d164..140aa57901 100644 --- a/substrate/core/consensus/common/src/lib.rs +++ b/substrate/core/consensus/common/src/lib.rs @@ -33,7 +33,7 @@ use std::sync::Arc; use std::time::Duration; use runtime_primitives::generic::BlockId; -use runtime_primitives::traits::{AuthorityIdFor, Block}; +use runtime_primitives::traits::{AuthorityIdFor, Block, DigestFor}; use futures::prelude::*; pub use inherents::InherentData; @@ -87,7 +87,12 @@ pub trait Proposer { /// Future that resolves to a committed proposal. type Create: IntoFuture; /// Create a proposal. - fn propose(&self, inherent_data: InherentData, max_duration: Duration) -> Self::Create; + fn propose( + &self, + inherent_data: InherentData, + inherent_digests: DigestFor, + max_duration: Duration, + ) -> Self::Create; } /// An oracle for when major synchronization work is being undertaken. diff --git a/substrate/core/consensus/common/src/select_chain.rs b/substrate/core/consensus/common/src/select_chain.rs index 47c65d1fe7..9ab21cba13 100644 --- a/substrate/core/consensus/common/src/select_chain.rs +++ b/substrate/core/consensus/common/src/select_chain.rs @@ -19,13 +19,13 @@ use runtime_primitives::traits::{Block as BlockT, NumberFor}; /// The SelectChain trait defines the strategy upon which the head is chosen -/// if multiple forks are present for an opaque definition of "best" in the +/// if multiple forks are present for an opaque definition of "best" in the /// specific chain build. /// /// The Strategy can be customised for the two use cases of authoring new blocks /// upon the best chain or which fork to finalise. Unless implemented differently /// by default finalisation methods fall back to use authoring, so as a minimum -/// `_authoring`-functions must be implemented. +/// `_authoring`-functions must be implemented. /// /// Any particular user must make explicit, however, whether they intend to finalise /// or author through the using the right function call, as these might differ in @@ -51,4 +51,4 @@ pub trait SelectChain: Sync + Send + Clone { ) -> Result::Hash>, Error> { Ok(Some(target_hash)) } -} \ No newline at end of file +} diff --git a/substrate/core/consensus/slots/src/aux_schema.rs b/substrate/core/consensus/slots/src/aux_schema.rs index 44f4ca5983..3d4a11d487 100644 --- a/substrate/core/consensus/slots/src/aux_schema.rs +++ b/substrate/core/consensus/slots/src/aux_schema.rs @@ -30,7 +30,7 @@ pub const MAX_SLOT_CAPACITY: u64 = 1000; /// We prune slots when they reach this number. pub const PRUNING_BOUND: u64 = 2 * MAX_SLOT_CAPACITY; -fn load_decode(backend: Arc, key: &[u8]) -> ClientResult> +fn load_decode(backend: Arc, key: &[u8]) -> ClientResult> where C: AuxStore, T: Decode, diff --git a/substrate/core/executor/src/allocator.rs b/substrate/core/executor/src/allocator.rs index 4b3f7d3219..bf01dd2e90 100644 --- a/substrate/core/executor/src/allocator.rs +++ b/substrate/core/executor/src/allocator.rs @@ -163,8 +163,7 @@ impl FreeingBumpHeapAllocator { } fn le_bytes_to_u32(arr: [u8; 4]) -> u32 { - let bytes = [arr[0], arr[1], arr[2], arr[3]]; - unsafe { std::mem::transmute::<[u8; 4], u32>(bytes) }.to_le() + u32::from_le_bytes(arr) } fn write_u32_into_le_bytes(bytes: u32, slice: &mut [u8]) { diff --git a/substrate/core/executor/src/wasm_executor.rs b/substrate/core/executor/src/wasm_executor.rs index bed60666f7..464531a5a1 100644 --- a/substrate/core/executor/src/wasm_executor.rs +++ b/substrate/core/executor/src/wasm_executor.rs @@ -483,10 +483,10 @@ impl_function_executor!(this: FunctionExecutor<'e, E>, let key = this.memory.get(data, len as usize).map_err(|_| UserError("Invalid attempt to get key in ext_twox_128"))?; let hashed_key = twox_128(&key); debug_trace!(target: "xxhash", "XXhash: {} -> {}", - if let Ok(_skey) = ::std::str::from_utf8(&key) { - _skey + &if let Ok(_skey) = ::std::str::from_utf8(&key) { + *_skey } else { - &format!("{}", HexDisplay::from(&key)) + format!("{}", HexDisplay::from(&key)) }, HexDisplay::from(&hashed_key) ); diff --git a/substrate/core/executor/wasm/Cargo.lock b/substrate/core/executor/wasm/Cargo.lock index 8c53b790d8..b2d77765f7 100644 --- a/substrate/core/executor/wasm/Cargo.lock +++ b/substrate/core/executor/wasm/Cargo.lock @@ -87,12 +87,12 @@ dependencies = [ [[package]] name = "primitive-types" -version = "0.2.1" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "fixed-hash 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "impl-codec 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "uint 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", + "uint 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -201,7 +201,7 @@ dependencies = [ "hash256-std-hasher 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", "num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", "parity-codec 3.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "primitive-types 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "primitive-types 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-hex 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "sr-std 2.0.0", ] @@ -226,7 +226,7 @@ dependencies = [ [[package]] name = "uint" -version = "0.6.1" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -252,7 +252,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "6ba9a427cfca2be13aa6f6403b0b7e7368fe982bfa16fccc450ce74c46cd9b32" "checksum parity-codec 3.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "dcb43c05fb71c03b4ea7327bf15694da1e0f23f19d5b1e95bab6c6d74097e336" "checksum parity-codec-derive 3.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "00a486fd383382ddcb2de928364b1f82571c1e48274fc43b7667a4738ee4056c" -"checksum primitive-types 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "edb92f1ebfc177432c03287b15d48c202e6e2c95993a7af3ba039abb43b1492e" +"checksum primitive-types 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "99d5a5fe9d93ddb394e2fb3fc49d0e31acb475fd45a30eeb8f3e76b767ecb7e1" "checksum proc-macro-crate 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "4c6cf4e5b00300d151dfffae39f529dfa5188f42eeb14201229aa420d6aad10c" "checksum proc-macro2 0.4.19 (registry+https://github.com/rust-lang/crates.io-index)" = "ffe022fb8c8bd254524b0b3305906c1921fa37a84a644e29079a9e62200c3901" "checksum quote 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)" = "dd636425967c33af890042c483632d33fa7a18f19ad1d7ea72e8998c6ef8dea5" @@ -264,5 +264,5 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum static_assertions 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "c19be23126415861cb3a23e501d34a708f7f9b2183c5252d690941c2e69199d5" "checksum syn 0.15.26 (registry+https://github.com/rust-lang/crates.io-index)" = "f92e629aa1d9c827b2bb8297046c1ccffc57c99b947a680d3ccff1f136a3bee9" "checksum toml 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)" = "758664fc71a3a69038656bee8b6be6477d2a6c315a6b81f7081f591bffa4111f" -"checksum uint 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e7780bb27fd8a22295e0d9d53ae3be253f715a0dccb1808527f478f1c2603708" +"checksum uint 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "91bb295c2c53c54742a6b8acb705114f6dfdf3c42becdb146a662cb77fcc0d02" "checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc" diff --git a/substrate/core/finality-grandpa/src/finality_proof.rs b/substrate/core/finality-grandpa/src/finality_proof.rs index c80b65741b..4ad1844358 100644 --- a/substrate/core/finality-grandpa/src/finality_proof.rs +++ b/substrate/core/finality-grandpa/src/finality_proof.rs @@ -117,7 +117,7 @@ impl AuthoritySetForFinalityChecker for Arc = Decode::decode(&mut &authorities[..]) diff --git a/substrate/core/finality-grandpa/src/import.rs b/substrate/core/finality-grandpa/src/import.rs index 6d64ad6778..e397bcf469 100644 --- a/substrate/core/finality-grandpa/src/import.rs +++ b/substrate/core/finality-grandpa/src/import.rs @@ -317,7 +317,7 @@ where // for the canon block the new authority set should start // with. we use the minimum between the median and the local // best finalized block. - + #[allow(deprecated)] let best_finalized_number = self.inner.backend().blockchain().info() .map_err(|e| ConsensusError::ClientImport(e.to_string()))? diff --git a/substrate/core/finality-grandpa/src/tests.rs b/substrate/core/finality-grandpa/src/tests.rs index 455afb865a..5b4fa9155a 100644 --- a/substrate/core/finality-grandpa/src/tests.rs +++ b/substrate/core/finality-grandpa/src/tests.rs @@ -1067,7 +1067,7 @@ fn allows_reimporting_change_blocks() { let (block_import, ..) = net.make_block_import(client.clone()); let full_client = client.as_full().unwrap(); - let builder = full_client.new_block_at(&BlockId::Number(0)).unwrap(); + let builder = full_client.new_block_at(&BlockId::Number(0), Default::default()).unwrap(); let block = builder.bake().unwrap(); api.scheduled_changes.lock().insert(*block.header.parent_hash(), ScheduledChange { next_authorities: make_ids(peers_b), @@ -1116,7 +1116,7 @@ fn test_bad_justification() { let (block_import, ..) = net.make_block_import(client.clone()); let full_client = client.as_full().expect("only full clients are used in test"); - let builder = full_client.new_block_at(&BlockId::Number(0)).unwrap(); + let builder = full_client.new_block_at(&BlockId::Number(0), Default::default()).unwrap(); let block = builder.bake().unwrap(); api.scheduled_changes.lock().insert(*block.header.parent_hash(), ScheduledChange { next_authorities: make_ids(peers_b), @@ -1480,7 +1480,7 @@ fn empty_finality_proof_is_returned_to_light_client_when_authority_set_is_differ runner_net.lock().add_light_peer(&GrandpaTestNet::default_config()); runner_net.lock().sync_without_disconnects(); - // check block, finalized on light client + // check block, finalized on light client assert_eq!( runner_net.lock().peer(3).client().info().unwrap().chain.finalized_number, if FORCE_CHANGE { 0 } else { 10 }, diff --git a/substrate/core/network/src/on_demand.rs b/substrate/core/network/src/on_demand.rs index 9ce75c4749..90051e9caf 100644 --- a/substrate/core/network/src/on_demand.rs +++ b/substrate/core/network/src/on_demand.rs @@ -297,7 +297,7 @@ impl OnDemandCore where self.idle_peers.push_back(peer.clone()); self.best_blocks.insert(peer, best_number); - + self.dispatch(network); } @@ -1010,7 +1010,7 @@ pub mod tests { assert_eq!(result, Some(vec![42])); }); - on_demand.on_remote_read_response(&mut network_interface, + on_demand.on_remote_read_response(&mut network_interface, peer0.clone(), message::RemoteReadResponse { id: 0, proof: vec![vec![2]], diff --git a/substrate/core/network/src/test/block_import.rs b/substrate/core/network/src/test/block_import.rs index 550d3c75ed..4cf639484f 100644 --- a/substrate/core/network/src/test/block_import.rs +++ b/substrate/core/network/src/test/block_import.rs @@ -26,9 +26,14 @@ struct TestLink {} impl Link for TestLink {} -fn prepare_good_block() -> (client::Client, Hash, u64, PeerId, IncomingBlock) { +fn prepare_good_block() -> (client::Client< + test_client::Backend, + test_client::Executor, + Block, + test_client::runtime::RuntimeApi, + >, Hash, u64, PeerId, IncomingBlock) { let client = test_client::new(); - let block = client.new_block().unwrap().bake().unwrap(); + let block = client.new_block(Default::default()).unwrap().bake().unwrap(); client.import(BlockOrigin::File, block).unwrap(); let (hash, number) = (client.block_hash(1).unwrap().unwrap(), 1); diff --git a/substrate/core/network/src/test/mod.rs b/substrate/core/network/src/test/mod.rs index 9e2059fd61..f31a93cf28 100644 --- a/substrate/core/network/src/test/mod.rs +++ b/substrate/core/network/src/test/mod.rs @@ -636,7 +636,8 @@ impl> Peer { let full_client = self.client.as_full().expect("blocks could only be generated by full clients"); let mut at = full_client.header(&at).unwrap().unwrap().hash(); for _ in 0..count { - let builder = full_client.new_block_at(&BlockId::Hash(at)).unwrap(); + let builder = full_client.new_block_at(&BlockId::Hash(at), Default::default() + ).unwrap(); let block = edit_block(builder); let hash = block.header.hash(); trace!( diff --git a/substrate/core/primitives/Cargo.toml b/substrate/core/primitives/Cargo.toml index 0875de55b7..ab34cfcd13 100644 --- a/substrate/core/primitives/Cargo.toml +++ b/substrate/core/primitives/Cargo.toml @@ -11,7 +11,7 @@ rustc-hex = { version = "2.0", default-features = false } serde = { version = "1.0", optional = true, features = ["derive"] } twox-hash = { version = "1.2.0", optional = true } byteorder = { version = "1.3.1", default-features = false } -primitive-types = { version = "0.2", default-features = false, features = ["codec"] } +primitive-types = { version = "0.2.3", default-features = false, features = ["codec"] } impl-serde = { version = "0.1", optional = true } wasmi = { version = "0.4.3", optional = true } hash-db = { version = "0.12", default-features = false } diff --git a/substrate/core/rpc/src/chain/tests.rs b/substrate/core/rpc/src/chain/tests.rs index 26b7202305..02507442d5 100644 --- a/substrate/core/rpc/src/chain/tests.rs +++ b/substrate/core/rpc/src/chain/tests.rs @@ -68,7 +68,7 @@ fn should_return_a_block() { subscriptions: Subscriptions::new(remote), }; - let block = api.client.new_block().unwrap().bake().unwrap(); + let block = api.client.new_block(Default::default()).unwrap().bake().unwrap(); let block_hash = block.hash(); api.client.import(BlockOrigin::Own, block).unwrap(); @@ -138,7 +138,7 @@ fn should_return_block_hash() { Ok(None) ); - let block = client.client.new_block().unwrap().bake().unwrap(); + let block = client.client.new_block(Default::default()).unwrap().bake().unwrap(); client.client.import(BlockOrigin::Own, block.clone()).unwrap(); assert_matches!( @@ -172,7 +172,7 @@ fn should_return_finalized_hash() { ); // import new block - let builder = client.client.new_block().unwrap(); + let builder = client.client.new_block(Default::default()).unwrap(); client.client.import(BlockOrigin::Own, builder.bake().unwrap()).unwrap(); // no finalization yet assert_matches!( @@ -205,7 +205,7 @@ fn should_notify_about_latest_block() { // assert id assigned assert_eq!(core.block_on(id), Ok(Ok(SubscriptionId::Number(1)))); - let builder = api.client.new_block().unwrap(); + let builder = api.client.new_block(Default::default()).unwrap(); api.client.import(BlockOrigin::Own, builder.bake().unwrap()).unwrap(); } @@ -236,7 +236,7 @@ fn should_notify_about_finalized_block() { // assert id assigned assert_eq!(core.block_on(id), Ok(Ok(SubscriptionId::Number(1)))); - let builder = api.client.new_block().unwrap(); + let builder = api.client.new_block(Default::default()).unwrap(); api.client.import(BlockOrigin::Own, builder.bake().unwrap()).unwrap(); api.client.finalize_block(BlockId::number(1), None, true).unwrap(); } diff --git a/substrate/core/rpc/src/state/tests.rs b/substrate/core/rpc/src/state/tests.rs index 14b6506f29..889c181415 100644 --- a/substrate/core/rpc/src/state/tests.rs +++ b/substrate/core/rpc/src/state/tests.rs @@ -99,7 +99,7 @@ fn should_notify_about_storage_changes() { // assert id assigned assert_eq!(core.block_on(id), Ok(Ok(SubscriptionId::Number(1)))); - let mut builder = api.client.new_block().unwrap(); + let mut builder = api.client.new_block(Default::default()).unwrap(); builder.push_transfer(runtime::Transfer { from: AccountKeyring::Alice.into(), to: AccountKeyring::Ferdie.into(), @@ -134,7 +134,7 @@ fn should_send_initial_storage_changes_and_notifications() { // assert id assigned assert_eq!(core.block_on(id), Ok(Ok(SubscriptionId::Number(1)))); - let mut builder = api.client.new_block().unwrap(); + let mut builder = api.client.new_block(Default::default()).unwrap(); builder.push_transfer(runtime::Transfer { from: AccountKeyring::Alice.into(), to: AccountKeyring::Ferdie.into(), @@ -168,7 +168,7 @@ fn should_query_storage() { let api = State::new(client.clone(), Subscriptions::new(core.executor())); let add_block = |nonce| { - let mut builder = client.new_block().unwrap(); + let mut builder = client.new_block(Default::default()).unwrap(); builder.push_transfer(runtime::Transfer { from: AccountKeyring::Alice.into(), to: AccountKeyring::Ferdie.into(), diff --git a/substrate/core/service/src/components.rs b/substrate/core/service/src/components.rs index 238d84b522..0d9d7dcdfc 100644 --- a/substrate/core/service/src/components.rs +++ b/substrate/core/service/src/components.rs @@ -655,7 +655,7 @@ mod tests { pool.submit_one(&BlockId::hash(best.hash()), transaction.clone()).unwrap(); // import the block - let mut builder = client.new_block().unwrap(); + let mut builder = client.new_block(Default::default()).unwrap(); builder.push(transaction.clone()).unwrap(); let block = builder.bake().unwrap(); let id = BlockId::hash(block.header().hash()); diff --git a/substrate/core/sr-api-macros/tests/runtime_calls.rs b/substrate/core/sr-api-macros/tests/runtime_calls.rs index ca008444e1..ff462d9e2a 100644 --- a/substrate/core/sr-api-macros/tests/runtime_calls.rs +++ b/substrate/core/sr-api-macros/tests/runtime_calls.rs @@ -171,7 +171,7 @@ fn record_proof_works() { // Build the block and record proof let mut builder = client - .new_block_at_with_proof_recording(&block_id) + .new_block_at_with_proof_recording(&block_id, Default::default()) .expect("Creates block builder"); builder.push(transaction.clone()).unwrap(); let (block, proof) = builder.bake_and_extract_proof().expect("Bake block"); diff --git a/substrate/core/sr-api-macros/tests/ui/invalid_api_version_2.rs b/substrate/core/sr-api-macros/tests/ui/invalid_api_version_2.rs index 7158630793..b887083800 100644 --- a/substrate/core/sr-api-macros/tests/ui/invalid_api_version_2.rs +++ b/substrate/core/sr-api-macros/tests/ui/invalid_api_version_2.rs @@ -8,4 +8,3 @@ decl_runtime_apis! { } fn main() {} - diff --git a/substrate/core/sr-primitives/src/generic/digest.rs b/substrate/core/sr-primitives/src/generic/digest.rs index 265ceb5941..8f7055b843 100644 --- a/substrate/core/sr-primitives/src/generic/digest.rs +++ b/substrate/core/sr-primitives/src/generic/digest.rs @@ -62,7 +62,6 @@ impl traits::Digest for Digest where /// provide opaque access to other items. #[derive(PartialEq, Eq, Clone)] #[cfg_attr(feature = "std", derive(Debug))] -#[allow(deprecated)] pub enum DigestItem { /// System digest item announcing that authorities set has been changed /// in the block. Contains the new set of authorities. @@ -71,14 +70,19 @@ pub enum DigestItem { /// block. It is created for every block iff runtime supports changes /// trie creation. ChangesTrieRoot(Hash), - /// The old way to put a Seal on it. Deprecated. - #[deprecated( - since = "1.0", - note = "New versions of Substrate will never generate this, and it will be rejected on new blockchains.", - )] - Seal(u64, SealSignature), - /// Put a Seal on it + /// A message from the runtime to the consensus engine. This should *never* + /// be generated by the native code of any consensus engine, but this is not + /// checked (yet). Consensus(ConsensusEngineId, Vec), + /// Put a Seal on it. + Seal(ConsensusEngineId, SealSignature), + /// A pre-runtime digest. + /// + /// These are messages from the consensus engine to the runtime, although + /// the consensus engine can (and should) read them itself to avoid + /// code and state duplication. It is erroneous for a runtime to produce + /// these, but this is not (yet) checked. + PreRuntime(ConsensusEngineId, Vec), /// Any 'non-system' digest item, opaque to the native code. Other(Vec), } @@ -97,20 +101,26 @@ impl ::serde::Serializ /// final runtime implementations for encoding/decoding its log items. #[derive(PartialEq, Eq, Clone)] #[cfg_attr(feature = "std", derive(Debug))] -#[allow(deprecated)] pub enum DigestItemRef<'a, Hash: 'a, AuthorityId: 'a, SealSignature: 'a> { /// Reference to `DigestItem::AuthoritiesChange`. AuthoritiesChange(&'a [AuthorityId]), /// Reference to `DigestItem::ChangesTrieRoot`. ChangesTrieRoot(&'a Hash), - /// A deprecated sealed signature for testing - #[deprecated] - Seal(&'a u64, &'a SealSignature), - /// A sealed signature for testing - Consensus(&'a ConsensusEngineId, &'a [u8]), + /// A message from the runtime to the consensus engine. This should *never* + /// be generated by the native code of any consensus engine, but this is not + /// checked (yet). + Consensus(&'a ConsensusEngineId, &'a Vec), + /// Put a Seal on it. + Seal(&'a ConsensusEngineId, &'a SealSignature), + /// A pre-runtime digest. + /// + /// These are messages from the consensus engine to the runtime, although + /// the consensus engine can (and should) read them itself to avoid + /// code and state duplication. It is erroneous for a runtime to produce + /// these, but this is not (yet) checked. + PreRuntime(&'a ConsensusEngineId, &'a Vec), /// Any 'non-system' digest item, opaque to the native code. - /// Reference to `DigestItem::Other`. - Other(&'a [u8]), + Other(&'a Vec), } /// Type of the digest item. Used to gain explicit control over `DigestItem` encoding @@ -123,8 +133,9 @@ enum DigestItemType { Other = 0, AuthoritiesChange = 1, ChangesTrieRoot = 2, - Seal = 3, Consensus = 4, + Seal = 5, + PreRuntime = 6, } impl DigestItem { @@ -137,13 +148,13 @@ impl DigestItem(&'a self) -> DigestItemRef<'a, Hash, AuthorityId, SealSignature> { match *self { DigestItem::AuthoritiesChange(ref v) => DigestItemRef::AuthoritiesChange(v), DigestItem::ChangesTrieRoot(ref v) => DigestItemRef::ChangesTrieRoot(v), - DigestItem::Seal(ref v, ref s) => DigestItemRef::Seal(v, s), DigestItem::Consensus(ref v, ref s) => DigestItemRef::Consensus(v, s), + DigestItem::Seal(ref v, ref s) => DigestItemRef::Seal(v, s), + DigestItem::PreRuntime(ref v, ref s) => DigestItemRef::PreRuntime(v, s), DigestItem::Other(ref v) => DigestItemRef::Other(v), } } @@ -164,6 +175,10 @@ impl< fn as_changes_trie_root(&self) -> Option<&Self::Hash> { self.dref().as_changes_trie_root() } + + fn as_pre_runtime(&self) -> Option<(ConsensusEngineId, &[u8])> { + self.dref().as_pre_runtime() + } } impl Encode for DigestItem { @@ -183,14 +198,18 @@ impl Decode for Digest DigestItemType::ChangesTrieRoot => Some(DigestItem::ChangesTrieRoot( Decode::decode(input)?, )), - DigestItemType::Seal => { - let vals: (u64, SealSignature) = Decode::decode(input)?; - Some(DigestItem::Seal(vals.0, vals.1)) - }, DigestItemType::Consensus => { let vals: (ConsensusEngineId, Vec) = Decode::decode(input)?; Some(DigestItem::Consensus(vals.0, vals.1)) } + DigestItemType::Seal => { + let vals: (ConsensusEngineId, SealSignature) = Decode::decode(input)?; + Some(DigestItem::Seal(vals.0, vals.1)) + }, + DigestItemType::PreRuntime => { + let vals: (ConsensusEngineId, Vec) = Decode::decode(input)?; + Some(DigestItem::PreRuntime(vals.0, vals.1)) + }, DigestItemType::Other => Some(DigestItem::Other( Decode::decode(input)?, )), @@ -214,9 +233,16 @@ impl<'a, Hash: Codec + Member, AuthorityId: Codec + Member, SealSignature: Codec _ => None, } } + + /// Cast this digest item into `PreRuntime` + pub fn as_pre_runtime(&self) -> Option<(ConsensusEngineId, &'a [u8])> { + match *self { + DigestItemRef::PreRuntime(consensus_engine_id, ref data) => Some((*consensus_engine_id, data)), + _ => None, + } + } } -#[allow(deprecated)] impl<'a, Hash: Encode, AuthorityId: Encode, SealSignature: Encode> Encode for DigestItemRef<'a, Hash, AuthorityId, SealSignature> { fn encode(&self) -> Vec { let mut v = Vec::new(); @@ -230,13 +256,17 @@ impl<'a, Hash: Encode, AuthorityId: Encode, SealSignature: Encode> Encode for Di DigestItemType::ChangesTrieRoot.encode_to(&mut v); changes_trie_root.encode_to(&mut v); }, + DigestItemRef::Consensus(val, data) => { + DigestItemType::Consensus.encode_to(&mut v); + (val, data).encode_to(&mut v); + }, DigestItemRef::Seal(val, sig) => { DigestItemType::Seal.encode_to(&mut v); (val, sig).encode_to(&mut v); }, - DigestItemRef::Consensus(val, sig) => { - DigestItemType::Consensus.encode_to(&mut v); - (val, sig).encode_to(&mut v); + DigestItemRef::PreRuntime(val, data) => { + DigestItemType::PreRuntime.encode_to(&mut v); + (val, data).encode_to(&mut v); }, DigestItemRef::Other(val) => { DigestItemType::Other.encode_to(&mut v); @@ -254,20 +284,19 @@ mod tests { use substrate_primitives::hash::H512 as Signature; #[test] - #[allow(deprecated)] fn should_serialize_digest() { let digest = Digest { logs: vec![ DigestItem::AuthoritiesChange(vec![1]), DigestItem::ChangesTrieRoot(4), - DigestItem::Seal(1, Signature::from_low_u64_be(15)), DigestItem::Other(vec![1, 2, 3]), + DigestItem::Seal(Default::default(), Signature::default()) ], }; assert_eq!( ::serde_json::to_string(&digest).unwrap(), - r#"{"logs":["0x010401000000","0x0204000000","0x0301000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000f","0x000c010203"]}"# + "{\"logs\":[\"0x010401000000\",\"0x0204000000\",\"0x000c010203\",\"0x050000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\"]}", ); } } diff --git a/substrate/core/sr-primitives/src/generic/header.rs b/substrate/core/sr-primitives/src/generic/header.rs index efcc7614ed..fa94d97c64 100644 --- a/substrate/core/sr-primitives/src/generic/header.rs +++ b/substrate/core/sr-primitives/src/generic/header.rs @@ -18,9 +18,12 @@ #[cfg(feature = "std")] use serde::Serialize; +#[cfg(feature = "std")] +use log::debug; use crate::codec::{Decode, Encode, Codec, Input, Output, HasCompact, EncodeAsRef}; use crate::traits::{self, Member, SimpleArithmetic, SimpleBitOps, MaybeDisplay, - Hash as HashT, DigestItem as DigestItemT, MaybeSerializeDebug, MaybeSerializeDebugButNotDeserialize}; + Hash as HashT, DigestItem as DigestItemT, MaybeSerializeDebug, + MaybeSerializeDebugButNotDeserialize}; use crate::generic::Digest; /// Abstraction over a block header for a substrate chain. @@ -107,22 +110,29 @@ impl traits::Header for Header &Self::Digest { &self.digest } + + #[cfg(feature = "std")] + fn digest_mut(&mut self) -> &mut Self::Digest { + debug!(target: "header", "Retrieving mutable reference to digest"); + &mut self.digest + } + + #[cfg(not(feature = "std"))] fn digest_mut(&mut self) -> &mut Self::Digest { &mut self.digest } - fn set_digest(&mut self, digest: Self::Digest) { self.digest = digest } fn new( number: Self::Number, extrinsics_root: Self::Hash, state_root: Self::Hash, parent_hash: Self::Hash, - digest: Self::Digest + digest: Self::Digest, ) -> Self { Header { number, extrinsics_root, state_root, parent_hash, - digest + digest, } } } diff --git a/substrate/core/sr-primitives/src/lib.rs b/substrate/core/sr-primitives/src/lib.rs index 05938a6a82..e6cf9142ad 100644 --- a/substrate/core/sr-primitives/src/lib.rs +++ b/substrate/core/sr-primitives/src/lib.rs @@ -681,6 +681,10 @@ macro_rules! impl_outer_log { fn as_changes_trie_root(&self) -> Option<&Self::Hash> { self.dref().and_then(|dref| dref.as_changes_trie_root()) } + + fn as_pre_runtime(&self) -> Option<($crate::ConsensusEngineId, &[u8])> { + self.dref().and_then(|dref| dref.as_pre_runtime()) + } } impl From<$crate::generic::DigestItem<$($genarg),*>> for $name { diff --git a/substrate/core/sr-primitives/src/testing.rs b/substrate/core/sr-primitives/src/testing.rs index e8e5aa20b4..18c65d011e 100644 --- a/substrate/core/sr-primitives/src/testing.rs +++ b/substrate/core/sr-primitives/src/testing.rs @@ -107,21 +107,20 @@ impl traits::Header for Header { fn digest(&self) -> &Self::Digest { &self.digest } fn digest_mut(&mut self) -> &mut Self::Digest { &mut self.digest } - fn set_digest(&mut self, digest: Self::Digest) { self.digest = digest } fn new( number: Self::Number, extrinsics_root: Self::Hash, state_root: Self::Hash, parent_hash: Self::Hash, - digest: Self::Digest + digest: Self::Digest, ) -> Self { Header { number, - extrinsics_root: extrinsics_root, + extrinsics_root, state_root, parent_hash, - digest + digest, } } } diff --git a/substrate/core/sr-primitives/src/traits.rs b/substrate/core/sr-primitives/src/traits.rs index dcfe8ffd24..5963450360 100644 --- a/substrate/core/sr-primitives/src/traits.rs +++ b/substrate/core/sr-primitives/src/traits.rs @@ -641,8 +641,6 @@ pub trait Header: Clone + Send + Sync + Codec + Eq + MaybeSerializeDebugButNotDe fn digest(&self) -> &Self::Digest; /// Get a mutable reference to the digest. fn digest_mut(&mut self) -> &mut Self::Digest; - /// Sets the digest. - fn set_digest(&mut self, digest: Self::Digest); /// Returns the hash of the header. fn hash(&self) -> Self::Hash { @@ -780,11 +778,14 @@ pub trait DigestItem: Codec + Member + MaybeSerializeDebugButNotDeserialize { /// `AuthorityChange` payload. type AuthorityId: Member + MaybeHash + crate::codec::Encode + crate::codec::Decode; - /// Returns Some if the entry is the `AuthoritiesChange` entry. + /// Returns `Some` if the entry is the `AuthoritiesChange` entry. fn as_authorities_change(&self) -> Option<&[Self::AuthorityId]>; - /// Returns Some if the entry is the `ChangesTrieRoot` entry. + /// Returns `Some` if the entry is the `ChangesTrieRoot` entry. fn as_changes_trie_root(&self) -> Option<&Self::Hash>; + + /// Returns `Some` if this entry is the `PreRuntime` entry. + fn as_pre_runtime(&self) -> Option<(super::ConsensusEngineId, &[u8])>; } /// Auxiliary wrapper that holds an api instance and binds it to the given lifetime. diff --git a/substrate/core/test-client/src/trait_tests.rs b/substrate/core/test-client/src/trait_tests.rs index a6da3b206b..c1df6ffdf8 100644 --- a/substrate/core/test-client/src/trait_tests.rs +++ b/substrate/core/test-client/src/trait_tests.rs @@ -50,14 +50,14 @@ pub fn test_leaves_for_backend(backend: Arc) where vec![genesis_hash]); // G -> A1 - let a1 = client.new_block().unwrap().bake().unwrap(); + let a1 = client.new_block(Default::default()).unwrap().bake().unwrap(); client.import(BlockOrigin::Own, a1.clone()).unwrap(); assert_eq!( blockchain.leaves().unwrap(), vec![a1.hash()]); // A1 -> A2 - let a2 = client.new_block_at(&BlockId::Hash(a1.hash())).unwrap().bake().unwrap(); + let a2 = client.new_block_at(&BlockId::Hash(a1.hash()), Default::default()).unwrap().bake().unwrap(); client.import(BlockOrigin::Own, a2.clone()).unwrap(); #[allow(deprecated)] @@ -66,28 +66,28 @@ pub fn test_leaves_for_backend(backend: Arc) where vec![a2.hash()]); // A2 -> A3 - let a3 = client.new_block_at(&BlockId::Hash(a2.hash())).unwrap().bake().unwrap(); + let a3 = client.new_block_at(&BlockId::Hash(a2.hash()), Default::default()).unwrap().bake().unwrap(); client.import(BlockOrigin::Own, a3.clone()).unwrap(); assert_eq!( blockchain.leaves().unwrap(), vec![a3.hash()]); // A3 -> A4 - let a4 = client.new_block_at(&BlockId::Hash(a3.hash())).unwrap().bake().unwrap(); + let a4 = client.new_block_at(&BlockId::Hash(a3.hash()), Default::default()).unwrap().bake().unwrap(); client.import(BlockOrigin::Own, a4.clone()).unwrap(); assert_eq!( blockchain.leaves().unwrap(), vec![a4.hash()]); // A4 -> A5 - let a5 = client.new_block_at(&BlockId::Hash(a4.hash())).unwrap().bake().unwrap(); + let a5 = client.new_block_at(&BlockId::Hash(a4.hash()), Default::default()).unwrap().bake().unwrap(); client.import(BlockOrigin::Own, a5.clone()).unwrap(); assert_eq!( blockchain.leaves().unwrap(), vec![a5.hash()]); // A1 -> B2 - let mut builder = client.new_block_at(&BlockId::Hash(a1.hash())).unwrap(); + let mut builder = client.new_block_at(&BlockId::Hash(a1.hash()), Default::default()).unwrap(); // this push is required as otherwise B2 has the same hash as A2 and won't get imported builder.push_transfer(Transfer { from: AccountKeyring::Alice.into(), @@ -102,21 +102,21 @@ pub fn test_leaves_for_backend(backend: Arc) where vec![a5.hash(), b2.hash()]); // B2 -> B3 - let b3 = client.new_block_at(&BlockId::Hash(b2.hash())).unwrap().bake().unwrap(); + let b3 = client.new_block_at(&BlockId::Hash(b2.hash()), Default::default()).unwrap().bake().unwrap(); client.import(BlockOrigin::Own, b3.clone()).unwrap(); assert_eq!( blockchain.leaves().unwrap(), vec![a5.hash(), b3.hash()]); // B3 -> B4 - let b4 = client.new_block_at(&BlockId::Hash(b3.hash())).unwrap().bake().unwrap(); + let b4 = client.new_block_at(&BlockId::Hash(b3.hash()), Default::default()).unwrap().bake().unwrap(); client.import(BlockOrigin::Own, b4.clone()).unwrap(); assert_eq!( blockchain.leaves().unwrap(), vec![a5.hash(), b4.hash()]); // // B2 -> C3 - let mut builder = client.new_block_at(&BlockId::Hash(b2.hash())).unwrap(); + let mut builder = client.new_block_at(&BlockId::Hash(b2.hash()), Default::default()).unwrap(); // this push is required as otherwise C3 has the same hash as B3 and won't get imported builder.push_transfer(Transfer { from: AccountKeyring::Alice.into(), @@ -131,7 +131,7 @@ pub fn test_leaves_for_backend(backend: Arc) where vec![a5.hash(), b4.hash(), c3.hash()]); // A1 -> D2 - let mut builder = client.new_block_at(&BlockId::Hash(a1.hash())).unwrap(); + let mut builder = client.new_block_at(&BlockId::Hash(a1.hash()), Default::default()).unwrap(); // this push is required as otherwise D2 has the same hash as B2 and won't get imported builder.push_transfer(Transfer { from: AccountKeyring::Alice.into(), @@ -160,27 +160,27 @@ pub fn test_children_for_backend(backend: Arc) where let blockchain = backend.blockchain(); // G -> A1 - let a1 = client.new_block().unwrap().bake().unwrap(); + let a1 = client.new_block(Default::default()).unwrap().bake().unwrap(); client.import(BlockOrigin::Own, a1.clone()).unwrap(); // A1 -> A2 - let a2 = client.new_block_at(&BlockId::Hash(a1.hash())).unwrap().bake().unwrap(); + let a2 = client.new_block_at(&BlockId::Hash(a1.hash()), Default::default()).unwrap().bake().unwrap(); client.import(BlockOrigin::Own, a2.clone()).unwrap(); // A2 -> A3 - let a3 = client.new_block_at(&BlockId::Hash(a2.hash())).unwrap().bake().unwrap(); + let a3 = client.new_block_at(&BlockId::Hash(a2.hash()), Default::default()).unwrap().bake().unwrap(); client.import(BlockOrigin::Own, a3.clone()).unwrap(); // A3 -> A4 - let a4 = client.new_block_at(&BlockId::Hash(a3.hash())).unwrap().bake().unwrap(); + let a4 = client.new_block_at(&BlockId::Hash(a3.hash()), Default::default()).unwrap().bake().unwrap(); client.import(BlockOrigin::Own, a4.clone()).unwrap(); // A4 -> A5 - let a5 = client.new_block_at(&BlockId::Hash(a4.hash())).unwrap().bake().unwrap(); + let a5 = client.new_block_at(&BlockId::Hash(a4.hash()), Default::default()).unwrap().bake().unwrap(); client.import(BlockOrigin::Own, a5.clone()).unwrap(); // A1 -> B2 - let mut builder = client.new_block_at(&BlockId::Hash(a1.hash())).unwrap(); + let mut builder = client.new_block_at(&BlockId::Hash(a1.hash()), Default::default()).unwrap(); // this push is required as otherwise B2 has the same hash as A2 and won't get imported builder.push_transfer(Transfer { from: AccountKeyring::Alice.into(), @@ -192,15 +192,15 @@ pub fn test_children_for_backend(backend: Arc) where client.import(BlockOrigin::Own, b2.clone()).unwrap(); // B2 -> B3 - let b3 = client.new_block_at(&BlockId::Hash(b2.hash())).unwrap().bake().unwrap(); + let b3 = client.new_block_at(&BlockId::Hash(b2.hash()), Default::default()).unwrap().bake().unwrap(); client.import(BlockOrigin::Own, b3.clone()).unwrap(); // B3 -> B4 - let b4 = client.new_block_at(&BlockId::Hash(b3.hash())).unwrap().bake().unwrap(); + let b4 = client.new_block_at(&BlockId::Hash(b3.hash()), Default::default()).unwrap().bake().unwrap(); client.import(BlockOrigin::Own, b4.clone()).unwrap(); // // B2 -> C3 - let mut builder = client.new_block_at(&BlockId::Hash(b2.hash())).unwrap(); + let mut builder = client.new_block_at(&BlockId::Hash(b2.hash()), Default::default()).unwrap(); // this push is required as otherwise C3 has the same hash as B3 and won't get imported builder.push_transfer(Transfer { from: AccountKeyring::Alice.into(), @@ -212,7 +212,7 @@ pub fn test_children_for_backend(backend: Arc) where client.import(BlockOrigin::Own, c3.clone()).unwrap(); // A1 -> D2 - let mut builder = client.new_block_at(&BlockId::Hash(a1.hash())).unwrap(); + let mut builder = client.new_block_at(&BlockId::Hash(a1.hash()), Default::default()).unwrap(); // this push is required as otherwise D2 has the same hash as B2 and won't get imported builder.push_transfer(Transfer { from: AccountKeyring::Alice.into(), @@ -250,27 +250,27 @@ pub fn test_blockchain_query_by_number_gets_canonical(backend: Arc A1 - let a1 = client.new_block().unwrap().bake().unwrap(); + let a1 = client.new_block(Default::default()).unwrap().bake().unwrap(); client.import(BlockOrigin::Own, a1.clone()).unwrap(); // A1 -> A2 - let a2 = client.new_block_at(&BlockId::Hash(a1.hash())).unwrap().bake().unwrap(); + let a2 = client.new_block_at(&BlockId::Hash(a1.hash()), Default::default()).unwrap().bake().unwrap(); client.import(BlockOrigin::Own, a2.clone()).unwrap(); // A2 -> A3 - let a3 = client.new_block_at(&BlockId::Hash(a2.hash())).unwrap().bake().unwrap(); + let a3 = client.new_block_at(&BlockId::Hash(a2.hash()), Default::default()).unwrap().bake().unwrap(); client.import(BlockOrigin::Own, a3.clone()).unwrap(); // A3 -> A4 - let a4 = client.new_block_at(&BlockId::Hash(a3.hash())).unwrap().bake().unwrap(); + let a4 = client.new_block_at(&BlockId::Hash(a3.hash()), Default::default()).unwrap().bake().unwrap(); client.import(BlockOrigin::Own, a4.clone()).unwrap(); // A4 -> A5 - let a5 = client.new_block_at(&BlockId::Hash(a4.hash())).unwrap().bake().unwrap(); + let a5 = client.new_block_at(&BlockId::Hash(a4.hash()), Default::default()).unwrap().bake().unwrap(); client.import(BlockOrigin::Own, a5.clone()).unwrap(); // A1 -> B2 - let mut builder = client.new_block_at(&BlockId::Hash(a1.hash())).unwrap(); + let mut builder = client.new_block_at(&BlockId::Hash(a1.hash()), Default::default()).unwrap(); // this push is required as otherwise B2 has the same hash as A2 and won't get imported builder.push_transfer(Transfer { from: AccountKeyring::Alice.into(), @@ -282,15 +282,15 @@ pub fn test_blockchain_query_by_number_gets_canonical(backend: Arc B3 - let b3 = client.new_block_at(&BlockId::Hash(b2.hash())).unwrap().bake().unwrap(); + let b3 = client.new_block_at(&BlockId::Hash(b2.hash()), Default::default()).unwrap().bake().unwrap(); client.import(BlockOrigin::Own, b3.clone()).unwrap(); // B3 -> B4 - let b4 = client.new_block_at(&BlockId::Hash(b3.hash())).unwrap().bake().unwrap(); + let b4 = client.new_block_at(&BlockId::Hash(b3.hash()), Default::default()).unwrap().bake().unwrap(); client.import(BlockOrigin::Own, b4.clone()).unwrap(); // // B2 -> C3 - let mut builder = client.new_block_at(&BlockId::Hash(b2.hash())).unwrap(); + let mut builder = client.new_block_at(&BlockId::Hash(b2.hash()), Default::default()).unwrap(); // this push is required as otherwise C3 has the same hash as B3 and won't get imported builder.push_transfer(Transfer { from: AccountKeyring::Alice.into(), @@ -302,7 +302,7 @@ pub fn test_blockchain_query_by_number_gets_canonical(backend: Arc D2 - let mut builder = client.new_block_at(&BlockId::Hash(a1.hash())).unwrap(); + let mut builder = client.new_block_at(&BlockId::Hash(a1.hash()), Default::default()).unwrap(); // this push is required as otherwise D2 has the same hash as B2 and won't get imported builder.push_transfer(Transfer { from: AccountKeyring::Alice.into(), diff --git a/substrate/core/test-runtime/src/system.rs b/substrate/core/test-runtime/src/system.rs index 804d5411d6..d7dccd33be 100644 --- a/substrate/core/test-runtime/src/system.rs +++ b/substrate/core/test-runtime/src/system.rs @@ -21,7 +21,7 @@ use rstd::prelude::*; use runtime_io::{storage_root, enumerated_trie_root, storage_changes_root, twox_128, blake2_256}; use runtime_support::storage::{self, StorageValue, StorageMap}; use runtime_support::storage_items; -use runtime_primitives::traits::{Hash as HashT, BlakeTwo256, Digest as DigestT}; +use runtime_primitives::traits::{Hash as HashT, BlakeTwo256, Digest as DigestT, Header as _}; use runtime_primitives::generic; use runtime_primitives::{ApplyError, ApplyOutcome, ApplyResult, transaction_validity::TransactionValidity}; use parity_codec::{KeyedVec, Encode}; @@ -38,6 +38,7 @@ storage_items! { Number: b"sys:num" => BlockNumber; ParentHash: b"sys:pha" => required Hash; NewAuthorities: b"sys:new_auth" => Vec; + StorageDigest: b"sys:digest" => Digest; } pub fn balance_of_key(who: AccountId) -> Vec { @@ -67,6 +68,7 @@ pub fn initialize_block(header: &Header) { // populate environment. ::put(&header.number); ::put(&header.parent_hash); + ::put(header.digest()); storage::unhashed::put(well_known_keys::EXTRINSIC_INDEX, &0u32); } @@ -99,18 +101,17 @@ pub fn polish_block(block: &mut Block) { header.state_root = storage_root().into(); // check digest - let mut digest = Digest::default(); + let digest = &mut header.digest; if let Some(storage_changes_root) = storage_changes_root(header.parent_hash.into()) { digest.push(generic::DigestItem::ChangesTrieRoot(storage_changes_root.into())); } if let Some(new_authorities) = ::take() { digest.push(generic::DigestItem::AuthoritiesChange(new_authorities)); } - header.digest = digest; } -pub fn execute_block(block: Block) { - let ref header = block.header; +pub fn execute_block(mut block: Block) { + let header = &mut block.header; // check transaction trie root represents the transactions. let txs = block.extrinsics.iter().map(Encode::encode).collect::>(); @@ -132,14 +133,13 @@ pub fn execute_block(block: Block) { assert!(storage_root == header.state_root, "Storage root must match that calculated."); // check digest - let mut digest = Digest::default(); + let digest = &mut header.digest; if let Some(storage_changes_root) = storage_changes_root(header.parent_hash.into()) { digest.push(generic::DigestItem::ChangesTrieRoot(storage_changes_root.into())); } if let Some(new_authorities) = ::take() { digest.push(generic::DigestItem::AuthoritiesChange(new_authorities)); } - assert!(digest == header.digest, "Header digest items must match that calculated."); } /// The block executor. @@ -209,13 +209,16 @@ pub fn finalize_block() -> Header { let txs: Vec<_> = (0..extrinsic_index).map(ExtrinsicData::take).collect(); let txs = txs.iter().map(Vec::as_slice).collect::>(); let extrinsics_root = enumerated_trie_root::(&txs).into(); - + // let mut digest = Digest::default(); let number = ::take().expect("Number is set by `initialize_block`"); let parent_hash = ::take(); + let mut digest = ::take().expect("StorageDigest is set by `initialize_block`"); + + // This MUST come after all changes to storage are done. Otherwise we will fail the + // “Storage root does not match that calculated” assertion. let storage_root = BlakeTwo256::storage_root(); let storage_changes_root = BlakeTwo256::storage_changes_root(parent_hash); - let mut digest = Digest::default(); if let Some(storage_changes_root) = storage_changes_root { digest.push(generic::DigestItem::ChangesTrieRoot(storage_changes_root)); } diff --git a/substrate/core/test-runtime/wasm/Cargo.lock b/substrate/core/test-runtime/wasm/Cargo.lock index eaa9acbd45..8439721da3 100644 --- a/substrate/core/test-runtime/wasm/Cargo.lock +++ b/substrate/core/test-runtime/wasm/Cargo.lock @@ -1615,13 +1615,13 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "primitive-types" -version = "0.2.1" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "fixed-hash 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "impl-codec 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "impl-serde 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "uint 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", + "uint 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2492,7 +2492,7 @@ dependencies = [ "hex 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "impl-serde 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "parity-codec 3.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "primitive-types 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "primitive-types 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", "regex 1.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-hex 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2937,7 +2937,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "uint" -version = "0.6.1" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -3409,7 +3409,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum pbkdf2 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "006c038a43a45995a9670da19e67600114740e8511d4333bf97a56e66a7542d9" "checksum percent-encoding 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "31010dd2e1ac33d5b46a5b413495239882813e0369f8ed8a5e266f173602f831" "checksum pkg-config 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)" = "676e8eb2b1b4c9043511a9b7bea0915320d7e502b0a079fb03f9635a5252b18c" -"checksum primitive-types 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "edb92f1ebfc177432c03287b15d48c202e6e2c95993a7af3ba039abb43b1492e" +"checksum primitive-types 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "99d5a5fe9d93ddb394e2fb3fc49d0e31acb475fd45a30eeb8f3e76b767ecb7e1" "checksum proc-macro-crate 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "4c6cf4e5b00300d151dfffae39f529dfa5188f42eeb14201229aa420d6aad10c" "checksum proc-macro-hack 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2c725b36c99df7af7bf9324e9c999b9e37d92c8f8caf106d82e1d7953218d2d8" "checksum proc-macro-hack 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)" = "3e90aa19cd73dedc2d0e1e8407473f073d735fef0ab521438de6da8ee449ab66" @@ -3508,7 +3508,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum twox-hash 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "09871da9f15424236082e0b220fd404a4eb6bebc7205c67653701229234ac64c" "checksum typenum 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "612d636f949607bdf9b123b4a6f6d966dedf3ff669f7f045890d3a4a73948169" "checksum ucd-util 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "535c204ee4d8434478593480b8f86ab45ec9aae0e83c568ca81abf0fd0e88f86" -"checksum uint 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e7780bb27fd8a22295e0d9d53ae3be253f715a0dccb1808527f478f1c2603708" +"checksum uint 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "91bb295c2c53c54742a6b8acb705114f6dfdf3c42becdb146a662cb77fcc0d02" "checksum unicode-bidi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "49f2bd0c6468a8230e1db229cff8029217cf623c767ea5d60bfbd42729ea54d5" "checksum unicode-normalization 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "141339a08b982d942be2ca06ff8b076563cbe223d1befd5450716790d44e2426" "checksum unicode-segmentation 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "aa6024fc12ddfd1c6dbc14a80fa2324d4568849869b779f6bd37e5e4c03344d1" diff --git a/substrate/node-template/runtime/wasm/Cargo.lock b/substrate/node-template/runtime/wasm/Cargo.lock index 5f46b360e4..c0d57e3fd9 100644 --- a/substrate/node-template/runtime/wasm/Cargo.lock +++ b/substrate/node-template/runtime/wasm/Cargo.lock @@ -1649,13 +1649,13 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "primitive-types" -version = "0.2.1" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "fixed-hash 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "impl-codec 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "impl-serde 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "uint 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", + "uint 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2619,7 +2619,7 @@ dependencies = [ "hex 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "impl-serde 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "parity-codec 3.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "primitive-types 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "primitive-types 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", "regex 1.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-hex 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -3030,7 +3030,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "uint" -version = "0.6.1" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -3502,7 +3502,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum pbkdf2 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "006c038a43a45995a9670da19e67600114740e8511d4333bf97a56e66a7542d9" "checksum percent-encoding 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "31010dd2e1ac33d5b46a5b413495239882813e0369f8ed8a5e266f173602f831" "checksum pkg-config 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)" = "676e8eb2b1b4c9043511a9b7bea0915320d7e502b0a079fb03f9635a5252b18c" -"checksum primitive-types 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "edb92f1ebfc177432c03287b15d48c202e6e2c95993a7af3ba039abb43b1492e" +"checksum primitive-types 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "99d5a5fe9d93ddb394e2fb3fc49d0e31acb475fd45a30eeb8f3e76b767ecb7e1" "checksum proc-macro-crate 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "4c6cf4e5b00300d151dfffae39f529dfa5188f42eeb14201229aa420d6aad10c" "checksum proc-macro-hack 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2c725b36c99df7af7bf9324e9c999b9e37d92c8f8caf106d82e1d7953218d2d8" "checksum proc-macro-hack 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)" = "3e90aa19cd73dedc2d0e1e8407473f073d735fef0ab521438de6da8ee449ab66" @@ -3601,7 +3601,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum twox-hash 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "09871da9f15424236082e0b220fd404a4eb6bebc7205c67653701229234ac64c" "checksum typenum 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "612d636f949607bdf9b123b4a6f6d966dedf3ff669f7f045890d3a4a73948169" "checksum ucd-util 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "535c204ee4d8434478593480b8f86ab45ec9aae0e83c568ca81abf0fd0e88f86" -"checksum uint 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e7780bb27fd8a22295e0d9d53ae3be253f715a0dccb1808527f478f1c2603708" +"checksum uint 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "91bb295c2c53c54742a6b8acb705114f6dfdf3c42becdb146a662cb77fcc0d02" "checksum unicode-bidi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "49f2bd0c6468a8230e1db229cff8029217cf623c767ea5d60bfbd42729ea54d5" "checksum unicode-normalization 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "141339a08b982d942be2ca06ff8b076563cbe223d1befd5450716790d44e2426" "checksum unicode-segmentation 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "aa6024fc12ddfd1c6dbc14a80fa2324d4568849869b779f6bd37e5e4c03344d1" diff --git a/substrate/node/executor/src/lib.rs b/substrate/node/executor/src/lib.rs index 8813850bbd..6c4b93b2ad 100644 --- a/substrate/node/executor/src/lib.rs +++ b/substrate/node/executor/src/lib.rs @@ -38,13 +38,13 @@ mod tests { NativeOrEncoded}; use node_primitives::{Hash, BlockNumber, AccountId}; use runtime_primitives::traits::{Header as HeaderT, Hash as HashT, Digest, DigestItem}; - use runtime_primitives::{generic::Era, ApplyOutcome, ApplyError, ApplyResult, Perbill}; + use runtime_primitives::{generic::{self, Era}, ApplyOutcome, ApplyError, ApplyResult, Perbill}; use {balances, indices, session, system, staking, consensus, timestamp, treasury, contract}; use contract::ContractAddressFor; use system::{EventRecord, Phase}; use node_runtime::{Header, Block, UncheckedExtrinsic, CheckedExtrinsic, Call, Runtime, Balances, BuildStorage, GenesisConfig, BalancesConfig, SessionConfig, StakingConfig, System, - SystemConfig, GrandpaConfig, IndicesConfig, Event}; + SystemConfig, GrandpaConfig, IndicesConfig, Event, Log}; use wabt; use primitives::map; diff --git a/substrate/node/runtime/src/lib.rs b/substrate/node/runtime/src/lib.rs index bb066b1b98..03b3f1caad 100644 --- a/substrate/node/runtime/src/lib.rs +++ b/substrate/node/runtime/src/lib.rs @@ -58,8 +58,8 @@ pub const VERSION: RuntimeVersion = RuntimeVersion { spec_name: create_runtime_str!("node"), impl_name: create_runtime_str!("substrate-node"), authoring_version: 10, - spec_version: 82, - impl_version: 82, + spec_version: 86, + impl_version: 87, apis: RUNTIME_API_VERSIONS, }; diff --git a/substrate/node/runtime/wasm/Cargo.lock b/substrate/node/runtime/wasm/Cargo.lock index 846857caa2..f564b3eca2 100644 --- a/substrate/node/runtime/wasm/Cargo.lock +++ b/substrate/node/runtime/wasm/Cargo.lock @@ -801,6 +801,14 @@ dependencies = [ "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "impl-serde" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "integer-sqrt" version = "0.1.2" @@ -1671,13 +1679,13 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "primitive-types" -version = "0.2.1" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "fixed-hash 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "impl-codec 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "impl-serde 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "uint 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", + "impl-serde 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "uint 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2674,6 +2682,7 @@ dependencies = [ "libp2p 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "parity-codec 3.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", "sr-primitives 2.0.0", "sr-std 2.0.0", "sr-version 2.0.0", @@ -2764,8 +2773,9 @@ dependencies = [ "hash256-std-hasher 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", "hex 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "impl-serde 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", "parity-codec 3.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "primitive-types 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "primitive-types 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", "regex 1.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-hex 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2793,6 +2803,7 @@ version = "2.0.0" dependencies = [ "hash-db 0.12.2 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", "parity-codec 3.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", "substrate-panic-handler 2.0.0", @@ -3176,7 +3187,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "uint" -version = "0.6.1" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -3584,6 +3595,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum idna 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "38f09e0f0b1fb55fdee1f17470ad800da77af5186a1a76c026b679358b7e844e" "checksum impl-codec 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d2050d823639fbeae26b2b5ba09aca8907793117324858070ade0673c49f793b" "checksum impl-serde 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "5158079de9d4158e0ce1de3ae0bd7be03904efc40b3d7dd8b8c301cbf6b52b56" +"checksum impl-serde 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7d26be4b97d738552ea423f76c4f681012ff06c3fa36fa968656b3679f60b4a1" "checksum integer-sqrt 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "ea155abb3ba6f382a75f1418988c05fe82959ed9ce727de427f9cfd425b0c903" "checksum iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "dbe6e417e7d0975db6512b90796e8ce223145ac4e33c377e4a42882a0e88bb08" "checksum itoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "1306f3464951f30e30d12373d31c79fbd52d236e5e896fd92f96ec7babbbe60b" @@ -3657,7 +3669,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum pbkdf2 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "006c038a43a45995a9670da19e67600114740e8511d4333bf97a56e66a7542d9" "checksum percent-encoding 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "31010dd2e1ac33d5b46a5b413495239882813e0369f8ed8a5e266f173602f831" "checksum pkg-config 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)" = "676e8eb2b1b4c9043511a9b7bea0915320d7e502b0a079fb03f9635a5252b18c" -"checksum primitive-types 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "edb92f1ebfc177432c03287b15d48c202e6e2c95993a7af3ba039abb43b1492e" +"checksum primitive-types 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "6e8612a8dc70f26276fed6131c153ca277cf275ee0a5e2a50cd8a69c697beb8f" "checksum proc-macro-crate 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "4c6cf4e5b00300d151dfffae39f529dfa5188f42eeb14201229aa420d6aad10c" "checksum proc-macro-hack 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2c725b36c99df7af7bf9324e9c999b9e37d92c8f8caf106d82e1d7953218d2d8" "checksum proc-macro-hack 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)" = "3e90aa19cd73dedc2d0e1e8407473f073d735fef0ab521438de6da8ee449ab66" @@ -3757,7 +3769,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum twox-hash 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "09871da9f15424236082e0b220fd404a4eb6bebc7205c67653701229234ac64c" "checksum typenum 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "612d636f949607bdf9b123b4a6f6d966dedf3ff669f7f045890d3a4a73948169" "checksum ucd-util 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "535c204ee4d8434478593480b8f86ab45ec9aae0e83c568ca81abf0fd0e88f86" -"checksum uint 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e7780bb27fd8a22295e0d9d53ae3be253f715a0dccb1808527f478f1c2603708" +"checksum uint 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2143cded94692b156c356508d92888acc824db5bffc0b4089732264c6fcf86d4" "checksum unicode-bidi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "49f2bd0c6468a8230e1db229cff8029217cf623c767ea5d60bfbd42729ea54d5" "checksum unicode-normalization 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "141339a08b982d942be2ca06ff8b076563cbe223d1befd5450716790d44e2426" "checksum unicode-segmentation 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "aa6024fc12ddfd1c6dbc14a80fa2324d4568849869b779f6bd37e5e4c03344d1" diff --git a/substrate/scripts/flamingfir-deploy.sh b/substrate/scripts/flamingfir-deploy.sh index ffd3cab9d8..13be56dfbd 100755 --- a/substrate/scripts/flamingfir-deploy.sh +++ b/substrate/scripts/flamingfir-deploy.sh @@ -13,12 +13,12 @@ JOB_ID=$(wget -O - --header "Authorization: Bearer ${AWX_TOKEN}" --header "Conte echo "Launched job: $JOB_ID" -while [ ${RETRY_ATTEMPT} -le ${RETRY_COUNT} ] ; do +while [ ${RETRY_ATTEMPT} -le ${RETRY_COUNT} ] ; do export RETRY_RESULT=$(wget -O - --header "Authorization: Bearer ${AWX_TOKEN}" https://ansible-awx.parity.io/api/v2/jobs/${JOB_ID}/ | jq .status) RETRY_ATTEMPT=$(( $RETRY_ATTEMPT +1 )) - sleep $SLEEP_TIME + sleep $SLEEP_TIME if [ $(echo $RETRY_RESULT | egrep -e successful -e failed) ] ; then - break + break fi done diff --git a/substrate/srml/aura/src/tests.rs b/substrate/srml/aura/src/tests.rs index e74c7dace2..3e20613c48 100644 --- a/substrate/srml/aura/src/tests.rs +++ b/substrate/srml/aura/src/tests.rs @@ -73,7 +73,7 @@ fn aura_reports_offline() { } with_externalities(&mut new_test_ext(vec![0, 1, 2, 3]), || { - System::initialize(&1, &Default::default(), &Default::default()); + System::initialize(&1, &Default::default(), &Default::default(), &Default::default()); let slot_duration = Aura::slot_duration(); Aura::on_timestamp_set::(5 * slot_duration, slot_duration); @@ -82,7 +82,7 @@ fn aura_reports_offline() { // no slashing when last step was 0. assert_eq!(SLASH_COUNTS.lock().as_slice(), &[0, 0, 0, 0]); - System::initialize(&2, &header.hash(), &Default::default()); + System::initialize(&2, &header.hash(), &Default::default(), &Default::default()); Aura::on_timestamp_set::(8 * slot_duration, slot_duration); let _header = System::finalize(); diff --git a/substrate/srml/consensus/src/tests.rs b/substrate/srml/consensus/src/tests.rs index bf8b3a09f3..471cdf4979 100644 --- a/substrate/srml/consensus/src/tests.rs +++ b/substrate/srml/consensus/src/tests.rs @@ -26,7 +26,7 @@ use inherents::{InherentData, ProvideInherent}; #[test] fn authorities_change_logged() { with_externalities(&mut new_test_ext(vec![1, 2, 3]), || { - System::initialize(&1, &Default::default(), &Default::default()); + System::initialize(&1, &Default::default(), &Default::default(), &Default::default()); Consensus::set_authorities(&[UintAuthorityId(4), UintAuthorityId(5), UintAuthorityId(6)]); Consensus::on_finalize(1); let header = System::finalize(); @@ -47,7 +47,7 @@ fn authorities_change_logged() { #[test] fn partial_authorities_change_logged() { with_externalities(&mut new_test_ext(vec![1, 2, 3]), || { - System::initialize(&2, &Default::default(), &Default::default()); + System::initialize(&2, &Default::default(), &Default::default(), &Default::default()); Consensus::set_authorities(&[UintAuthorityId(2), UintAuthorityId(4), UintAuthorityId(5)]); Consensus::on_finalize(2); let header = System::finalize(); @@ -68,7 +68,7 @@ fn partial_authorities_change_logged() { #[test] fn authorities_change_is_not_logged_when_not_changed() { with_externalities(&mut new_test_ext(vec![1, 2, 3]), || { - System::initialize(&1, &Default::default(), &Default::default()); + System::initialize(&1, &Default::default(), &Default::default(), &Default::default()); Consensus::on_finalize(1); let header = System::finalize(); assert_eq!(header.digest, testing::Digest { @@ -80,7 +80,7 @@ fn authorities_change_is_not_logged_when_not_changed() { #[test] fn authorities_change_is_not_logged_when_changed_back_to_original() { with_externalities(&mut new_test_ext(vec![1, 2, 3]), || { - System::initialize(&1, &Default::default(), &Default::default()); + System::initialize(&1, &Default::default(), &Default::default(), &Default::default()); Consensus::set_authorities(&[UintAuthorityId(4), UintAuthorityId(5), UintAuthorityId(6)]); Consensus::set_authorities(&[UintAuthorityId(1), UintAuthorityId(2), UintAuthorityId(3)]); Consensus::on_finalize(1); @@ -94,7 +94,7 @@ fn authorities_change_is_not_logged_when_changed_back_to_original() { #[test] fn offline_report_can_be_excluded() { with_externalities(&mut new_test_ext(vec![1, 2, 3]), || { - System::initialize(&1, &Default::default(), &Default::default()); + System::initialize(&1, &Default::default(), &Default::default(), &Default::default()); assert!(Consensus::create_inherent(&InherentData::new()).is_none()); let offline_report: Vec = vec![0]; @@ -110,7 +110,7 @@ fn set_and_kill_storage_work() { use srml_support::storage; with_externalities(&mut new_test_ext(vec![1, 2, 3]), || { - System::initialize(&1, &Default::default(), &Default::default()); + System::initialize(&1, &Default::default(), &Default::default(), &Default::default()); let item = (vec![42u8], vec![42u8]); diff --git a/substrate/srml/contract/src/tests.rs b/substrate/srml/contract/src/tests.rs index aeadc99353..29fc1d3a6d 100644 --- a/substrate/srml/contract/src/tests.rs +++ b/substrate/srml/contract/src/tests.rs @@ -736,7 +736,7 @@ fn deduct_blocks() { assert_eq!(bob_contract.rent_allowance, 1_000); // Advance 4 blocks - System::initialize(&5, &[0u8; 32].into(), &[0u8; 32].into()); + System::initialize(&5, &[0u8; 32].into(), &[0u8; 32].into(), &Default::default()); // Trigger rent through call assert_ok!(Contract::call(Origin::signed(ALICE), BOB, 0, 100_000, call::null())); @@ -751,7 +751,7 @@ fn deduct_blocks() { assert_eq!(Balances::free_balance(BOB), 30_000 - rent); // Advance 7 blocks more - System::initialize(&12, &[0u8; 32].into(), &[0u8; 32].into()); + System::initialize(&12, &[0u8; 32].into(), &[0u8; 32].into(), &Default::default()); // Trigger rent through call assert_ok!(Contract::call(Origin::signed(ALICE), BOB, 0, 100_000, call::null())); @@ -825,7 +825,7 @@ fn claim_surcharge(blocks: u64, trigger_call: impl Fn() -> bool, removes: bool) )); // Advance blocks - System::initialize(&blocks, &[0u8; 32].into(), &[0u8; 32].into()); + System::initialize(&blocks, &[0u8; 32].into(), &[0u8; 32].into(), &Default::default()); // Trigger rent through call assert!(trigger_call()); @@ -865,14 +865,14 @@ fn removals(trigger_call: impl Fn() -> bool) { assert_eq!(ContractInfoOf::::get(BOB).unwrap().get_alive().unwrap().rent_allowance, 1_000); // Advance blocks - System::initialize(&10, &[0u8; 32].into(), &[0u8; 32].into()); + System::initialize(&10, &[0u8; 32].into(), &[0u8; 32].into(), &Default::default()); // Trigger rent through call assert!(trigger_call()); assert!(ContractInfoOf::::get(BOB).unwrap().get_tombstone().is_some()); // Advance blocks - System::initialize(&20, &[0u8; 32].into(), &[0u8; 32].into()); + System::initialize(&20, &[0u8; 32].into(), &[0u8; 32].into(), &Default::default()); // Trigger rent must have no effect assert!(trigger_call()); @@ -899,14 +899,14 @@ fn removals(trigger_call: impl Fn() -> bool) { assert_eq!(ContractInfoOf::::get(BOB).unwrap().get_alive().unwrap().rent_allowance, 100); // Advance blocks - System::initialize(&10, &[0u8; 32].into(), &[0u8; 32].into()); + System::initialize(&10, &[0u8; 32].into(), &[0u8; 32].into(), &Default::default()); // Trigger rent through call assert!(trigger_call()); assert!(ContractInfoOf::::get(BOB).unwrap().get_tombstone().is_some()); // Advance blocks - System::initialize(&20, &[0u8; 32].into(), &[0u8; 32].into()); + System::initialize(&20, &[0u8; 32].into(), &[0u8; 32].into(), &Default::default()); // Trigger rent must have no effect assert!(trigger_call()); @@ -937,14 +937,14 @@ fn removals(trigger_call: impl Fn() -> bool) { assert_eq!(ContractInfoOf::::get(BOB).unwrap().get_alive().unwrap().rent_allowance, 1_000); // Advance blocks - System::initialize(&10, &[0u8; 32].into(), &[0u8; 32].into()); + System::initialize(&10, &[0u8; 32].into(), &[0u8; 32].into(), &Default::default()); // Trigger rent through call assert!(trigger_call()); assert!(ContractInfoOf::::get(BOB).is_none()); // Advance blocks - System::initialize(&20, &[0u8; 32].into(), &[0u8; 32].into()); + System::initialize(&20, &[0u8; 32].into(), &[0u8; 32].into(), &Default::default()); // Trigger rent must have no effect assert!(trigger_call()); @@ -1027,7 +1027,7 @@ fn default_rent_allowance_on_create() { assert_eq!(bob_contract.rent_allowance, >::max_value()); // Advance blocks - System::initialize(&5, &[0u8; 32].into(), &[0u8; 32].into()); + System::initialize(&5, &[0u8; 32].into(), &[0u8; 32].into(), &Default::default()); // Trigger rent through call assert_ok!(Contract::call(Origin::signed(ALICE), BOB, 0, 100_000, call::null())); @@ -1179,7 +1179,7 @@ fn restoration(test_different_storage: bool, test_restore_to_with_dirty_storage: } // Advance 4 blocks - System::initialize(&5, &[0u8; 32].into(), &[0u8; 32].into()); + System::initialize(&5, &[0u8; 32].into(), &[0u8; 32].into(), &Default::default()); // Trigger rent through call assert_ok!(Contract::call(Origin::signed(ALICE), BOB, 0, 100_000, call::null())); @@ -1198,7 +1198,7 @@ fn restoration(test_different_storage: bool, test_restore_to_with_dirty_storage: if !test_restore_to_with_dirty_storage { // Advance 1 blocks - System::initialize(&6, &[0u8; 32].into(), &[0u8; 32].into()); + System::initialize(&6, &[0u8; 32].into(), &[0u8; 32].into(), &Default::default()); } assert_ok!(Contract::call( diff --git a/substrate/srml/executive/src/lib.rs b/substrate/srml/executive/src/lib.rs index 33d26ce42f..70285f7dfa 100644 --- a/substrate/srml/executive/src/lib.rs +++ b/substrate/srml/executive/src/lib.rs @@ -80,7 +80,7 @@ use rstd::result; use primitives::traits::{ self, Header, Zero, One, Checkable, Applyable, CheckEqual, OnFinalize, OnInitialize, Digest, NumberFor, Block as BlockT, OffchainWorker, - ValidateUnsigned, + ValidateUnsigned, DigestItem, }; use srml_support::{Dispatchable, traits::MakePayment}; use parity_codec::{Codec, Encode}; @@ -152,11 +152,13 @@ where { /// Start the execution of a particular block. pub fn initialize_block(header: &System::Header) { - Self::initialize_block_impl(header.number(), header.parent_hash(), header.extrinsics_root()); + let mut digests = System::Digest::default(); + header.digest().logs().iter().for_each(|d| if d.as_pre_runtime().is_some() { digests.push(d.clone()) }); + Self::initialize_block_impl(header.number(), header.parent_hash(), header.extrinsics_root(), &digests); } - fn initialize_block_impl(block_number: &System::BlockNumber, parent_hash: &System::Hash, extrinsics_root: &System::Hash) { - >::initialize(block_number, parent_hash, extrinsics_root); + fn initialize_block_impl(block_number: &System::BlockNumber, parent_hash: &System::Hash, extrinsics_root: &System::Hash, digest: &System::Digest) { + >::initialize(block_number, parent_hash, extrinsics_root, digest); >::on_initialize(*block_number); } @@ -262,7 +264,8 @@ where Payment::make_payment(sender, encoded_len).map_err(|_| internal::ApplyError::CantPay)?; // AUDIT: Under no circumstances may this function panic from here onwards. - + // FIXME: ensure this at compile-time (such as by not defining a panic function, forcing + // a linker error unless the compiler can prove it cannot be called). // increment nonce in storage >::inc_account_nonce(sender); } diff --git a/substrate/srml/finality-tracker/src/lib.rs b/substrate/srml/finality-tracker/src/lib.rs index 2276ad3155..9e83198502 100644 --- a/substrate/srml/finality-tracker/src/lib.rs +++ b/substrate/srml/finality-tracker/src/lib.rs @@ -344,7 +344,7 @@ mod tests { with_externalities(&mut TestExternalities::new(t), || { let mut parent_hash = System::parent_hash(); for i in 2..106 { - System::initialize(&i, &parent_hash, &Default::default()); + System::initialize(&i, &parent_hash, &Default::default(), &Default::default()); FinalityTracker::on_finalize(i); let hdr = System::finalize(); parent_hash = hdr.hash(); @@ -369,7 +369,7 @@ mod tests { with_externalities(&mut TestExternalities::new(t), || { let mut parent_hash = System::parent_hash(); for i in 2..106 { - System::initialize(&i, &parent_hash, &Default::default()); + System::initialize(&i, &parent_hash, &Default::default(), &Default::default()); assert_ok!(FinalityTracker::dispatch( Call::final_hint(i-1), Origin::NONE, diff --git a/substrate/srml/grandpa/src/tests.rs b/substrate/srml/grandpa/src/tests.rs index 560766f8c6..d19c5c25b6 100644 --- a/substrate/srml/grandpa/src/tests.rs +++ b/substrate/srml/grandpa/src/tests.rs @@ -30,7 +30,7 @@ use super::*; #[test] fn authorities_change_logged() { with_externalities(&mut new_test_ext(vec![(1, 1), (2, 1), (3, 1)]), || { - System::initialize(&1, &Default::default(), &Default::default()); + System::initialize(&1, &Default::default(), &Default::default(), &Default::default()); Grandpa::schedule_change(vec![(4, 1), (5, 1), (6, 1)], 0, None).unwrap(); System::note_finished_extrinsics(); @@ -56,7 +56,7 @@ fn authorities_change_logged() { #[test] fn authorities_change_logged_after_delay() { with_externalities(&mut new_test_ext(vec![(1, 1), (2, 1), (3, 1)]), || { - System::initialize(&1, &Default::default(), &Default::default()); + System::initialize(&1, &Default::default(), &Default::default(), &Default::default()); Grandpa::schedule_change(vec![(4, 1), (5, 1), (6, 1)], 1, None).unwrap(); Grandpa::on_finalize(1); let header = System::finalize(); @@ -69,7 +69,7 @@ fn authorities_change_logged_after_delay() { // no change at this height. assert_eq!(System::events(), vec![]); - System::initialize(&2, &header.hash(), &Default::default()); + System::initialize(&2, &header.hash(), &Default::default(), &Default::default()); System::note_finished_extrinsics(); Grandpa::on_finalize(2); @@ -87,7 +87,7 @@ fn authorities_change_logged_after_delay() { #[test] fn cannot_schedule_change_when_one_pending() { with_externalities(&mut new_test_ext(vec![(1, 1), (2, 1), (3, 1)]), || { - System::initialize(&1, &Default::default(), &Default::default()); + System::initialize(&1, &Default::default(), &Default::default(), &Default::default()); Grandpa::schedule_change(vec![(4, 1), (5, 1), (6, 1)], 1, None).unwrap(); assert!(Grandpa::pending_change().is_some()); assert!(Grandpa::schedule_change(vec![(5, 1)], 1, None).is_err()); @@ -95,14 +95,14 @@ fn cannot_schedule_change_when_one_pending() { Grandpa::on_finalize(1); let header = System::finalize(); - System::initialize(&2, &header.hash(), &Default::default()); + System::initialize(&2, &header.hash(), &Default::default(), &Default::default()); assert!(Grandpa::pending_change().is_some()); assert!(Grandpa::schedule_change(vec![(5, 1)], 1, None).is_err()); Grandpa::on_finalize(2); let header = System::finalize(); - System::initialize(&3, &header.hash(), &Default::default()); + System::initialize(&3, &header.hash(), &Default::default(), &Default::default()); assert!(Grandpa::pending_change().is_none()); assert!(Grandpa::schedule_change(vec![(5, 1)], 1, None).is_ok()); @@ -130,7 +130,7 @@ fn new_decodes_from_old() { #[test] fn dispatch_forced_change() { with_externalities(&mut new_test_ext(vec![(1, 1), (2, 1), (3, 1)]), || { - System::initialize(&1, &Default::default(), &Default::default()); + System::initialize(&1, &Default::default(), &Default::default(), &Default::default()); Grandpa::schedule_change( vec![(4, 1), (5, 1), (6, 1)], 5, @@ -144,7 +144,7 @@ fn dispatch_forced_change() { let mut header = System::finalize(); for i in 2..7 { - System::initialize(&i, &header.hash(), &Default::default()); + System::initialize(&i, &header.hash(), &Default::default(), &Default::default()); assert!(Grandpa::pending_change().unwrap().forced.is_some()); assert_eq!(Grandpa::next_forced(), Some(11)); assert!(Grandpa::schedule_change(vec![(5, 1)], 1, None).is_err()); @@ -157,7 +157,7 @@ fn dispatch_forced_change() { // change has been applied at the end of block 6. // add a normal change. { - System::initialize(&7, &header.hash(), &Default::default()); + System::initialize(&7, &header.hash(), &Default::default(), &Default::default()); assert!(Grandpa::pending_change().is_none()); assert_eq!(Grandpa::grandpa_authorities(), vec![(4, 1), (5, 1), (6, 1)]); assert!(Grandpa::schedule_change(vec![(5, 1)], 1, None).is_ok()); @@ -167,7 +167,7 @@ fn dispatch_forced_change() { // run the normal change. { - System::initialize(&8, &header.hash(), &Default::default()); + System::initialize(&8, &header.hash(), &Default::default(), &Default::default()); assert!(Grandpa::pending_change().is_some()); assert_eq!(Grandpa::grandpa_authorities(), vec![(4, 1), (5, 1), (6, 1)]); assert!(Grandpa::schedule_change(vec![(5, 1)], 1, None).is_err()); @@ -178,7 +178,7 @@ fn dispatch_forced_change() { // normal change applied. but we can't apply a new forced change for some // time. for i in 9..11 { - System::initialize(&i, &header.hash(), &Default::default()); + System::initialize(&i, &header.hash(), &Default::default(), &Default::default()); assert!(Grandpa::pending_change().is_none()); assert_eq!(Grandpa::grandpa_authorities(), vec![(5, 1)]); assert_eq!(Grandpa::next_forced(), Some(11)); @@ -188,7 +188,7 @@ fn dispatch_forced_change() { } { - System::initialize(&11, &header.hash(), &Default::default()); + System::initialize(&11, &header.hash(), &Default::default(), &Default::default()); assert!(Grandpa::pending_change().is_none()); assert!(Grandpa::schedule_change(vec![(5, 1), (6, 1), (7, 1)], 5, Some(0)).is_ok()); assert_eq!(Grandpa::next_forced(), Some(21)); diff --git a/substrate/srml/system/src/lib.rs b/substrate/srml/system/src/lib.rs index cf5f473bdc..7c4a95a30f 100644 --- a/substrate/srml/system/src/lib.rs +++ b/substrate/srml/system/src/lib.rs @@ -465,10 +465,16 @@ impl Module { } /// Start the execution of a particular block. - pub fn initialize(number: &T::BlockNumber, parent_hash: &T::Hash, txs_root: &T::Hash) { + pub fn initialize( + number: &T::BlockNumber, + parent_hash: &T::Hash, + txs_root: &T::Hash, + digest: &T::Digest, + ) { // populate environment storage::unhashed::put(well_known_keys::EXTRINSIC_INDEX, &0u32); >::put(number); + >::put(digest); >::put(parent_hash); >::insert(*number - One::one(), parent_hash); >::put(txs_root); @@ -553,38 +559,51 @@ impl Module { /// Get the basic random seed. /// - /// In general you won't want to use this, but rather `Self::random` which allows you to give a subject for the - /// random result and whose value will be independently low-influence random from any other such seeds. + /// In general you won't want to use this, but rather `Self::random` which + /// allows you to give a subject for the random result and whose value will + /// be independently low-influence random from any other such seeds. pub fn random_seed() -> T::Hash { Self::random(&[][..]) } /// Get a low-influence "random" value. /// - /// Being a deterministic block chain, real randomness is difficult to come by. This gives you something that - /// approximates it. `subject` is a context identifier and allows you to get a different result to other callers - /// of this function; use it like `random(&b"my context"[..])`. + /// Being a deterministic block chain, real randomness is difficult to come + /// by. This gives you something that approximates it. `subject` is a + /// context identifier and allows you to get a different result to other + /// callers of this function; use it like `random(&b"my context"[..])`. /// - /// This is initially implemented through a low-influence "triplet mix" convolution of previous block hash values. - /// In the future it will be generated from a secure "VRF". + /// This is initially implemented through a low-influence "triplet mix" + /// convolution of previous block hash values. In the future it will be + /// generated from a secure verifiable random function (VRF). /// /// ### Security Notes - /// This randomness uses a low-influence function, drawing upon the block hashes from the previous 81 blocks. Its - /// result for any given subject will be known in advance by the block producer of this block (and, indeed, anyone - /// who knows the block's `parent_hash`). However, it is mostly impossible for the producer of this block *alone* - /// to influence the value of this hash. A sizable minority of dishonest and coordinating block producers would be - /// required in order to affect this value. If that is an insufficient security guarantee then two things can be - /// used to improve this randomness: - /// - Name, in advance, the block number whose random value will be used; ensure your module retains a buffer of - /// previous random values for its subject and then index into these in order to obviate the ability of your user - /// to look up the parent hash and choose when to transact based upon it. - /// - Require your user to first commit to an additional value by first posting its hash. Require them to reveal - /// the value to determine the final result, hashing it with the output of this random function. This reduces the - /// ability of a cabal of block producers from conspiring against individuals. /// - /// WARNING: Hashing the result of this function will remove any low-infleunce properties it has and mean that - /// all bits of the resulting value are entirely manipulatable by the author of the parent block, who can determine - /// the value of `parent_hash`. + /// This randomness uses a low-influence function, drawing upon the block + /// hashes from the previous 81 blocks. Its result for any given subject + /// will be known in advance by the block producer of this block (and, + /// indeed, anyone who knows the block's `parent_hash`). However, it is + /// mostly impossible for the producer of this block *alone* to influence + /// the value of this hash. A sizable minority of dishonest and coordinating + /// block producers would be required in order to affect this value. If that + /// is an insufficient security guarantee then two things can be used to + /// improve this randomness: + /// + /// - Name, in advance, the block number whose random value will be used; + /// ensure your module retains a buffer of previous random values for its + /// subject and then index into these in order to obviate the ability of + /// your user to look up the parent hash and choose when to transact based + /// upon it. + /// - Require your user to first commit to an additional value by first + /// posting its hash. Require them to reveal the value to determine the + /// final result, hashing it with the output of this random function. This + /// reduces the ability of a cabal of block producers from conspiring + /// against individuals. + /// + /// WARNING: Hashing the result of this function will remove any + /// low-influnce properties it has and mean that all bits of the resulting + /// value are entirely manipulatable by the author of the parent block, who + /// can determine the value of `parent_hash`. pub fn random(subject: &[u8]) -> T::Hash { let (index, hash_series) = >::get(); if hash_series.len() > 0 { @@ -606,8 +625,9 @@ impl Module { >::insert(who, Self::account_nonce(who) + T::Index::one()); } - /// Note what the extrinsic data of the current extrinsic index is. If this is called, then - /// ensure `derive_extrinsics` is also called before block-building is completed. + /// Note what the extrinsic data of the current extrinsic index is. If this + /// is called, then ensure `derive_extrinsics` is also called before + /// block-building is completed. /// /// NOTE: This function is called only when the block is being constructed locally. /// `execute_block` doesn't note any extrinsics. @@ -722,7 +742,7 @@ mod tests { #[test] fn deposit_event_should_work() { with_externalities(&mut new_test_ext(), || { - System::initialize(&1, &[0u8; 32].into(), &[0u8; 32].into()); + System::initialize(&1, &[0u8; 32].into(), &[0u8; 32].into(), &Default::default()); System::note_finished_extrinsics(); System::deposit_event(1u16); System::finalize(); @@ -737,7 +757,7 @@ mod tests { ] ); - System::initialize(&2, &[0u8; 32].into(), &[0u8; 32].into()); + System::initialize(&2, &[0u8; 32].into(), &[0u8; 32].into(), &Default::default()); System::deposit_event(42u16); System::note_applied_extrinsic(&Ok(()), 0); System::note_applied_extrinsic(&Err(""), 0); @@ -758,7 +778,7 @@ mod tests { with_externalities(&mut new_test_ext(), || { const BLOCK_NUMBER: u64 = 1; - System::initialize(&BLOCK_NUMBER, &[0u8; 32].into(), &[0u8; 32].into()); + System::initialize(&BLOCK_NUMBER, &[0u8; 32].into(), &[0u8; 32].into(), &Default::default()); System::note_finished_extrinsics(); let topics = vec![ diff --git a/substrate/test-utils/transaction-factory/src/lib.rs b/substrate/test-utils/transaction-factory/src/lib.rs index b046cf74c9..8f292f3a02 100644 --- a/substrate/test-utils/transaction-factory/src/lib.rs +++ b/substrate/test-utils/transaction-factory/src/lib.rs @@ -148,7 +148,7 @@ where as ProvideRuntimeApi>::Api: BlockBuilder>, RA: RuntimeAdapter, { - let mut block = client.new_block().expect("Failed to create new block"); + let mut block = client.new_block(Default::default()).expect("Failed to create new block"); block.push( Decode::decode(&mut &transfer.encode()[..]) .expect("Failed to decode transfer extrinsic") diff --git a/substrate/test-utils/transaction-factory/src/modes.rs b/substrate/test-utils/transaction-factory/src/modes.rs index f3d278bbbf..a212d6aed8 100644 --- a/substrate/test-utils/transaction-factory/src/modes.rs +++ b/substrate/test-utils/transaction-factory/src/modes.rs @@ -38,4 +38,3 @@ impl FromStr for Mode { } } } -