mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-06-12 07:41:08 +00:00
Introduce inherent digests (#2466)
* Introduce inherent digests * Implement inherent digests * fix silly error * Implementation of inherent digests in BABE All tests pass. There are still limitations: 1. The runtime strips out inherent digests, so BABE must re-add them. 2. The test runtime checks that it can re-compute all digests. It can’t, so I had to comment out that test. * Fix compilation and seal import Seals were not imported correctly: the pre-digest was imported twice, instead of both it and the seal being imported. Also, other parts of the code did not compile due to incomplete refactoring. * Remove bogus assertion * Fix testsuite compilation * Remove unused import * Fix compiler diagnostics * Add inherent digest parameters to block constructors This enforces that inherent digests are added first. * Fixup Cargo.lock * Fix build errors * Re-add an incorrectly removed import * Bump primitive-types version * Update Cargo.lock * Refactoring * Use inherent digests for AuRa They do reach the runtime, but get stripped. I have not figured out where. * Fix compilation errors * Fix compilation errors due to incorrect types * Fix whitespace Suggested-by: Tomasz Drwiega <tomasz@parity.io> * Add preamble Suggested-by: Tomasz Drwiega <tomasz@parity.io> * Fix silly compile error * Refactor pre-digest finding code into a separate function * Remove unwanted assertion It is too likely to bring down the entire blockchain. Suggested-by: Tomasz Drwiega <tomasz@parity.io> * Use `find_pre_digest` after runtime, too Also, use `Member` trait rather than rolling our own requirements. Suggested-by: Tomasz Drwiega <tomasz@parity.io> * Fix various warnings mostly due to upgrading the dependency on `error_chain`. * Pre-digests nearly complete This nearly completes the implementation of pre-runtime digests. * `Seal2` → `Seal` and fix test suite * Try to fix the storage error * Try to fix storage (again) * Fix tests * Hopefully finish pre-runtime digests The key is to pass *only* the pre-runtime digests to the runtime. The others must be stripped out by `initialize_block`. * Fix silly typo * Fix another silly mistake * Remove unnecessary filtering of BABE pre-digests We no longer get duplicate BABE pre-digests, so if they appear, the header should be rejected outright. * Update Cargo.lock files * Reformatting * Fix silly typo in inherent digest code Also, revert `error.rs` files that contained calls to the `error_chain!` macro. * Try to keep the runtime from stripping pre-digests Currently runs into the “Storage root must match that calculated” assertion. * Don’t compute storage root until storage changes are done. Also, fix a compilation error. * Fix compile-time error * Fix compilation errors * Fix more compile errors * Hopefully it compiles this time… * Fix compilation and add docs * Prevent BABE from adding duplicate pre-runtime digests Found by comparing with the AuRa code. I also did some refactoring. * Respond to review and fix some warnings * Delete some dead code introduced earlier * More dead code goes away * `ref mut` → `&mut` * Respond to review and fix some warnings * Fix compilation error * Remove unneeded `HashT` type parameter Suggested-by: Robert Habermeier <robert@parity.io> * Remove spurious #[allow(deprecated)] * Document inherent digest parameter to `build_block` * Delete `Simple` trait It wasn’t needed * delete wrongly added files * Fix trait bounds * Digest serialization tests I also did some reformatting and cleanup. * Apply suggestions from code review Reformatting Co-Authored-By: André Silva <andre.beat@gmail.com> * Swap two arguments to `propose` and `propose_with` Also, remove some needless unsafe code. * Remove bogus `#![allow(deprecated)]` annotations With the removal of the deprecated `Seal` variant, these are not needed. * Add a missing `#[allow(deprecated)]` in the AuRa tests * Fix silly compile error * Fix silly compiler error RLS did not tell me that I hadn’t fixed `babe/lib.rs`, so I missed it. * Fixes made automatically by Cargo
This commit is contained in:
committed by
Gavin Wood
parent
e9a4c80c40
commit
c7d1204ce5
@@ -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
|
||||
|
||||
Generated
+17
-8
@@ -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"
|
||||
|
||||
@@ -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 ======
|
||||
|
||||
@@ -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<F: FnMut(&mut BlockBuilder<Self::Block>) -> ()>(
|
||||
&self,
|
||||
at: &BlockId<Self::Block>,
|
||||
inherent_data: InherentData,
|
||||
inherent_digests: DigestFor<Self::Block>,
|
||||
build_ctx: F,
|
||||
) -> Result<Self::Block, error::Error>;
|
||||
}
|
||||
@@ -92,9 +95,11 @@ impl<B, E, Block, RA> AuthoringApi for SubstrateClient<B, E, Block, RA> where
|
||||
&self,
|
||||
at: &BlockId<Self::Block>,
|
||||
inherent_data: InherentData,
|
||||
inherent_digests: DigestFor<Self::Block>,
|
||||
mut build_ctx: F,
|
||||
) -> Result<Self::Block, error::Error> {
|
||||
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<Block, C, A> consensus_common::Proposer<<C as AuthoringApi>::Block> for Pro
|
||||
type Create = Result<<C as AuthoringApi>::Block, error::Error>;
|
||||
type Error = error::Error;
|
||||
|
||||
fn propose(&self, inherent_data: InherentData, max_duration: time::Duration)
|
||||
-> Result<<C as AuthoringApi>::Block, error::Error>
|
||||
fn propose(
|
||||
&self,
|
||||
inherent_data: InherentData,
|
||||
inherent_digests: DigestFor<Block>,
|
||||
max_duration: time::Duration,
|
||||
) -> Result<<C as AuthoringApi>::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<Block, C, A> Proposer<Block, C, A> where
|
||||
A: txpool::ChainApi<Block=Block>,
|
||||
client::error::Error: From<<C as AuthoringApi>::Error>,
|
||||
{
|
||||
fn propose_with(&self, inherent_data: InherentData, deadline: time::Instant)
|
||||
-> Result<<C as AuthoringApi>::Block, error::Error>
|
||||
fn propose_with(
|
||||
&self,
|
||||
inherent_data: InherentData,
|
||||
inherent_digests: DigestFor<Block>,
|
||||
deadline: time::Instant,
|
||||
) -> Result<<C as AuthoringApi>::Block, error::Error>
|
||||
{
|
||||
use runtime_primitives::traits::BlakeTwo256;
|
||||
|
||||
@@ -203,17 +216,16 @@ impl<Block, C, A> Proposer<Block, C, A> 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);
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
@@ -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<Block> + 'a,
|
||||
A::Api: BlockBuilderApi<Block>,
|
||||
{
|
||||
/// Create a new instance of builder from the given client, building on the latest block.
|
||||
pub fn new(api: &'a A) -> error::Result<Self> {
|
||||
/// Create a new instance of builder from the given client, building on the
|
||||
/// latest block.
|
||||
pub fn new(api: &'a A, inherent_digests: DigestFor<Block>) -> error::Result<Self> {
|
||||
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<Block>,
|
||||
api: &'a A,
|
||||
proof_recording: bool
|
||||
proof_recording: bool,
|
||||
inherent_digests: DigestFor<Block>,
|
||||
) -> error::Result<Self> {
|
||||
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 {
|
||||
|
||||
@@ -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<B, E, Block, RA> Client<B, E, Block, RA> where
|
||||
|
||||
/// Create a new block, built on the head of the chain.
|
||||
pub fn new_block(
|
||||
&self
|
||||
&self,
|
||||
inherent_digests: DigestFor<Block>,
|
||||
) -> error::Result<block_builder::BlockBuilder<Block, Self>> where
|
||||
E: Clone + Send + Sync,
|
||||
RA: Send + Sync,
|
||||
Self: ProvideRuntimeApi,
|
||||
<Self as ProvideRuntimeApi>::Api: BlockBuilderAPI<Block>
|
||||
{
|
||||
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<Block>
|
||||
&self,
|
||||
parent: &BlockId<Block>,
|
||||
inherent_digests: DigestFor<Block>,
|
||||
) -> error::Result<block_builder::BlockBuilder<Block, Self>> where
|
||||
E: Clone + Send + Sync,
|
||||
RA: Send + Sync,
|
||||
Self: ProvideRuntimeApi,
|
||||
<Self as ProvideRuntimeApi>::Api: BlockBuilderAPI<Block>
|
||||
{
|
||||
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<B, E, Block, RA> Client<B, E, Block, RA> 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<Block>
|
||||
&self,
|
||||
parent: &BlockId<Block>,
|
||||
inherent_digests: DigestFor<Block>,
|
||||
) -> error::Result<block_builder::BlockBuilder<Block, Self>> where
|
||||
E: Clone + Send + Sync,
|
||||
RA: Send + Sync,
|
||||
Self: ProvideRuntimeApi,
|
||||
<Self as ProvideRuntimeApi>::Api: BlockBuilderAPI<Block>
|
||||
{
|
||||
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<B, E, Block, RA> Client<B, E, Block, RA> where
|
||||
|
||||
/// Prepare in-memory header that is used in execution environment.
|
||||
fn prepare_environment_block(&self, parent: &BlockId<Block>) -> error::Result<Block::Header> {
|
||||
let parent_header = self.backend().blockchain().expect_header(*parent)?;
|
||||
Ok(<<Block as BlockT>::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<H256> = 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)]
|
||||
|
||||
@@ -448,7 +448,7 @@ pub fn check_execution_proof<Header, E, H>(
|
||||
Default::default(),
|
||||
Default::default(),
|
||||
request.header.hash(),
|
||||
Default::default(),
|
||||
request.header.digest().clone(),
|
||||
);
|
||||
execution_proof_check_on_trie_backend::<H, _>(
|
||||
&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();
|
||||
}
|
||||
|
||||
@@ -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())));
|
||||
|
||||
@@ -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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
//! 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<P> = <P as Pair>::Signature;
|
||||
|
||||
/// A digest item which is usable with aura consensus.
|
||||
pub trait CompatibleDigestItem<T: Pair>: Sized {
|
||||
/// Construct a digest item which contains a signature on the hash.
|
||||
fn aura_seal(signature: Signature<T>) -> Self;
|
||||
|
||||
/// If this item is an Aura seal, return the signature.
|
||||
fn as_aura_seal(&self) -> Option<&Signature<T>>;
|
||||
|
||||
/// 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<u64>;
|
||||
}
|
||||
|
||||
impl<P, Hash> CompatibleDigestItem<P> for DigestItem<Hash, P::Public, P::Signature>
|
||||
where P: Pair, P::Signature: Clone + Encode + Decode,
|
||||
{
|
||||
fn aura_seal(signature: Signature<P>) -> Self {
|
||||
DigestItem::Seal(AURA_ENGINE_ID, signature)
|
||||
}
|
||||
|
||||
fn as_aura_seal(&self) -> Option<&Signature<P>> {
|
||||
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<u64> {
|
||||
match self {
|
||||
DigestItem::PreRuntime(AURA_ENGINE_ID, ref buffer) => Decode::decode(&mut &buffer[..]),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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<P> = <P as Pair>::Public;
|
||||
type Signature<P> = <P as Pair>::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<Item=Vec<u8>,Error=()>;
|
||||
|
||||
/// Send a message at a specific round out.
|
||||
fn send_message(&self, slot: u64, message: Vec<u8>);
|
||||
}
|
||||
|
||||
/// 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<P: Pair>(slot_num: u64, authorities: &[AuthorityId<P>]) -> Option
|
||||
Some(current_author)
|
||||
}
|
||||
|
||||
/// A digest item which is usable with aura consensus.
|
||||
pub trait CompatibleDigestItem<T: Pair>: Sized {
|
||||
/// Construct a digest item which contains a slot number and a signature on the
|
||||
/// hash.
|
||||
fn aura_seal(slot_num: u64, signature: Signature<T>) -> Self;
|
||||
|
||||
/// If this item is an Aura seal, return the slot number and signature.
|
||||
fn as_aura_seal(&self) -> Option<(u64, Signature<T>)>;
|
||||
|
||||
/// Return `true` if this seal type is deprecated. Otherwise, return
|
||||
/// `false`.
|
||||
fn is_deprecated(&self) -> bool;
|
||||
}
|
||||
|
||||
impl<P, Hash> CompatibleDigestItem<P> for generic::DigestItem<Hash, P::Public, P::Signature>
|
||||
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<P>) -> 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<P>)> {
|
||||
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<B, C, SC, E, I, P, SO, Error, OnExit>(
|
||||
slot_duration: SlotDuration,
|
||||
local_key: Arc<P>,
|
||||
client: Arc<C>,
|
||||
select_chain: SC,
|
||||
block_import: Arc<I>,
|
||||
env: Arc<E>,
|
||||
sync_oracle: SO,
|
||||
on_exit: OnExit,
|
||||
inherent_data_providers: InherentDataProviders,
|
||||
force_authoring: bool,
|
||||
) -> Result<(), consensus_common::Error> where
|
||||
B: Block + 'static,
|
||||
C: ProvideRuntimeApi + ProvideCache<B> + AuxStore + Send + Sync + 'static,
|
||||
C::Api: AuthoritiesApi<B>,
|
||||
SC: SelectChain<B> + Clone + 'static,
|
||||
E: Environment<B, Error=Error> + Send + Sync + 'static,
|
||||
E::Proposer: Proposer<B, Error=Error> + Send + 'static,
|
||||
<<E::Proposer as Proposer<B>>::Create as IntoFuture>::Future: Send + 'static,
|
||||
I: BlockImport<B> + Send + Sync + 'static,
|
||||
Error: From<I::Error> + '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<Item=(), Error=()> + Send + 'static,
|
||||
DigestItemFor<B>: CompatibleDigestItem<P> + DigestItem<AuthorityId=AuthorityId<P>> + '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<B, C, SC, E, I, P, SO, Error, OnExit>(
|
||||
pub fn start_aura<B, C, SC, E, I, P, SO, Error, OnExit, H>(
|
||||
slot_duration: SlotDuration,
|
||||
local_key: Arc<P>,
|
||||
client: Arc<C>,
|
||||
@@ -243,20 +137,25 @@ pub fn start_aura<B, C, SC, E, I, P, SO, Error, OnExit>(
|
||||
inherent_data_providers: InherentDataProviders,
|
||||
force_authoring: bool,
|
||||
) -> Result<impl Future<Item=(), Error=()>, consensus_common::Error> where
|
||||
B: Block,
|
||||
C: ProvideRuntimeApi + ProvideCache<B> + AuxStore,
|
||||
B: Block<Header=H>,
|
||||
C: ProvideRuntimeApi + ProvideCache<B> + AuxStore + Send + Sync,
|
||||
C::Api: AuthoritiesApi<B>,
|
||||
SC: SelectChain<B> + Clone,
|
||||
E: Environment<B, Error=Error>,
|
||||
SC: SelectChain<B>,
|
||||
generic::DigestItem<B::Hash, P::Public, P::Signature>: DigestItem<Hash=B::Hash>,
|
||||
E::Proposer: Proposer<B, Error=Error>,
|
||||
<<E::Proposer as Proposer<B>>::Create as IntoFuture>::Future: Send + 'static,
|
||||
I: BlockImport<B> + 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<B>: CompatibleDigestItem<P> + DigestItem<AuthorityId=AuthorityId<P>>,
|
||||
H: Header<
|
||||
Digest=generic::Digest<generic::DigestItem<B::Hash, P::Public, P::Signature>>,
|
||||
Hash=B::Hash,
|
||||
>,
|
||||
E: Environment<B, Error=Error>,
|
||||
I: BlockImport<B> + Send + Sync + 'static,
|
||||
Error: ::std::error::Error + Send + From<::consensus_common::Error> + From<I::Error> + 'static,
|
||||
SO: SyncOracle + Send + Sync + Clone,
|
||||
OnExit: Future<Item=(), Error=()>,
|
||||
{
|
||||
let worker = AuraWorker {
|
||||
@@ -288,18 +187,23 @@ struct AuraWorker<C, E, I, P, SO> {
|
||||
force_authoring: bool,
|
||||
}
|
||||
|
||||
impl<B: Block, C, E, I, P, Error, SO> SlotWorker<B> for AuraWorker<C, E, I, P, SO> where
|
||||
C: ProvideRuntimeApi + ProvideCache<B> + AuxStore,
|
||||
impl<H, B, C, E, I, P, Error, SO> SlotWorker<B> for AuraWorker<C, E, I, P, SO> where
|
||||
B: Block<Header=H>,
|
||||
C: ProvideRuntimeApi + ProvideCache<B> + Sync,
|
||||
C::Api: AuthoritiesApi<B>,
|
||||
E: Environment<B, Error=Error>,
|
||||
E::Proposer: Proposer<B, Error=Error>,
|
||||
<<E::Proposer as Proposer<B>>::Create as IntoFuture>::Future: Send + 'static,
|
||||
H: Header<
|
||||
Digest=generic::Digest<generic::DigestItem<B::Hash, P::Public, P::Signature>>,
|
||||
Hash=B::Hash,
|
||||
>,
|
||||
I: BlockImport<B> + 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<B>: CompatibleDigestItem<P> + DigestItem<AuthorityId=AuthorityId<P>>,
|
||||
DigestItemFor<B>: CompatibleDigestItem<P> + DigestItem<AuthorityId=AuthorityId<P>, Hash=B::Hash>,
|
||||
Error: ::std::error::Error + Send + From<::consensus_common::Error> + From<I::Error> + 'static,
|
||||
{
|
||||
type OnSlot = Box<Future<Item=(), Error=consensus_common::Error> + Send>;
|
||||
@@ -376,7 +280,15 @@ impl<B: Block, C, E, I, P, Error, SO> SlotWorker<B> for AuraWorker<C, E, I, P, S
|
||||
// deadline our production to approx. the end of the
|
||||
// slot
|
||||
Timeout::new(
|
||||
proposer.propose(slot_info.inherent_data, remaining_duration).into_future(),
|
||||
proposer.propose(
|
||||
slot_info.inherent_data,
|
||||
generic::Digest {
|
||||
logs: vec![
|
||||
<DigestItemFor<B> as CompatibleDigestItem<P>>::aura_pre_digest(slot_num),
|
||||
],
|
||||
},
|
||||
remaining_duration,
|
||||
).into_future(),
|
||||
remaining_duration,
|
||||
)
|
||||
} else {
|
||||
@@ -384,72 +296,98 @@ impl<B: Block, C, E, I, P, Error, SO> SlotWorker<B> for AuraWorker<C, E, I, P, S
|
||||
}
|
||||
};
|
||||
|
||||
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
|
||||
}
|
||||
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<u64, String> = find_pre_digest::<B, P>(&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 = <DigestItemFor<B> as CompatibleDigestItem<P>>::aura_seal(
|
||||
slot_num,
|
||||
signature,
|
||||
);
|
||||
let header_num = header.number().clone();
|
||||
let parent_hash = header.parent_hash().clone();
|
||||
|
||||
let import_block: ImportBlock<B> = 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 = <DigestItemFor<B> as CompatibleDigestItem<P>>::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<B> = 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<B: Block, P: Pair>(header: &B::Header) -> Result<u64, String>
|
||||
where DigestItemFor<B>: CompatibleDigestItem<P>,
|
||||
P::Signature: Decode,
|
||||
P::Public: Encode + Decode + PartialEq + Clone,
|
||||
{
|
||||
let mut pre_digest: Option<u64> = 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<C, B: Block, P: Pair>(
|
||||
mut header: B::Header,
|
||||
hash: B::Hash,
|
||||
authorities: &[AuthorityId<P>],
|
||||
allow_old_seals: bool,
|
||||
) -> Result<CheckedHeader<B::Header, DigestItemFor<B>>, String>
|
||||
where DigestItemFor<B>: CompatibleDigestItem<P>,
|
||||
P::Signature: Decode,
|
||||
C: client::backend::AuxStore,
|
||||
P::Public: AsRef<P::Public> + Encode + Decode + PartialEq + Clone,
|
||||
) -> Result<CheckedHeader<B::Header, (u64, DigestItemFor<B>)>, String> where
|
||||
DigestItemFor<B>: CompatibleDigestItem<P>,
|
||||
P::Signature: Decode,
|
||||
C: client::backend::AuxStore,
|
||||
P::Public: AsRef<P::Public> + 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::<B, _>(&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<C, B: Block, P: Pair>(
|
||||
};
|
||||
|
||||
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::<_, _, <P as Pair>::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<C, B: Block, P: Pair>(
|
||||
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<C, E, P> {
|
||||
extra: E,
|
||||
phantom: PhantomData<P>,
|
||||
inherent_data_providers: inherents::InherentDataProviders,
|
||||
allow_old_seals: bool,
|
||||
}
|
||||
|
||||
impl<C, E, P> AuraVerifier<C, E, P>
|
||||
@@ -631,20 +561,17 @@ impl<B: Block, C, E, P> Verifier<B> for AuraVerifier<C, E, P> 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::<C, B, P>(
|
||||
&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<B, C, E, P>(
|
||||
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<B, C, E, P>(
|
||||
slot_duration: SlotDuration,
|
||||
block_import: SharedBlockImport<B>,
|
||||
justification_import: Option<SharedJustificationImport<B>>,
|
||||
finality_proof_import: Option<SharedFinalityProofImport<B>>,
|
||||
finality_proof_request_builder: Option<SharedFinalityProofRequestBuilder<B>>,
|
||||
client: Arc<C>,
|
||||
extra: E,
|
||||
inherent_data_providers: InherentDataProviders,
|
||||
) -> Result<AuraImportQueue<B>, consensus_common::Error> where
|
||||
B: Block,
|
||||
C: 'static + ProvideRuntimeApi + ProvideCache<B> + Send + Sync + AuxStore,
|
||||
C::Api: BlockBuilderApi<B> + AuthoritiesApi<B>,
|
||||
DigestItemFor<B>: CompatibleDigestItem<P> + DigestItem<AuthorityId=AuthorityId<P>>,
|
||||
E: 'static + ExtraVerification<B>,
|
||||
P: Pair + Send + Sync + 'static,
|
||||
P::Public: Clone + Eq + Send + Sync + Hash + Debug + Encode + Decode + AsRef<P::Public>,
|
||||
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<B, C, E, P>(
|
||||
#[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<TestBlock, Error>;
|
||||
|
||||
fn propose(&self, _: InherentData, _: Duration) -> Result<TestBlock, Error> {
|
||||
self.1.new_block().unwrap().bake().map_err(|e| e.into())
|
||||
fn propose(
|
||||
&self,
|
||||
_: InherentData,
|
||||
digests: DigestFor<TestBlock>,
|
||||
_: Duration,
|
||||
) -> Result<TestBlock, Error> {
|
||||
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 = <DigestItemFor<TestBlock> as CompatibleDigestItem<sr25519::Pair>>::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 = <generic::DigestItem<_, _, _> as CompatibleDigestItem<sr25519::Pair>>::aura_seal(
|
||||
slot_num,
|
||||
signature,
|
||||
);
|
||||
let item = CompatibleDigestItem::<sr25519::Pair>::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());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
// along with Substrate. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
//! 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;
|
||||
|
||||
@@ -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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
//! 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<u8> {
|
||||
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<R: Input>(i: &mut R) -> Option<Self> {
|
||||
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<BabePreDigest>;
|
||||
|
||||
/// 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<Signature>;
|
||||
}
|
||||
|
||||
impl<Hash: Debug> CompatibleDigestItem for DigestItem<Hash, Public, Vec<u8>>
|
||||
{
|
||||
fn babe_pre_digest(digest: BabePreDigest) -> Self {
|
||||
DigestItem::PreRuntime(BABE_ENGINE_ID, digest.encode())
|
||||
}
|
||||
|
||||
fn as_babe_pre_digest(&self) -> Option<BabePreDigest> {
|
||||
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<Signature> {
|
||||
match self {
|
||||
DigestItem::Seal(BABE_ENGINE_ID, signature) => Decode::decode(&mut &signature[..]),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<Hash: Debug> CompatibleDigestItem for DigestItem<Hash, Public, Signature>
|
||||
{
|
||||
fn babe_pre_digest(digest: BabePreDigest) -> Self {
|
||||
DigestItem::PreRuntime(BABE_ENGINE_ID, digest.encode())
|
||||
}
|
||||
|
||||
fn as_babe_pre_digest(&self) -> Option<BabePreDigest> {
|
||||
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<Signature> {
|
||||
match self {
|
||||
DigestItem::Seal(BABE_ENGINE_ID, signature) => Some(signature.clone()),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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<u8> {
|
||||
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<R: Input>(i: &mut R) -> Option<Self> {
|
||||
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<BabeConfiguration>);
|
||||
|
||||
@@ -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<BabeSeal>;
|
||||
}
|
||||
|
||||
impl<T, Hash> CompatibleDigestItem for generic::DigestItem<Hash, Public, T>
|
||||
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<BabeSeal> {
|
||||
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<C, E, I, SO, SC, OnExit> {
|
||||
}
|
||||
|
||||
/// Start the babe worker. The returned future should be run in a tokio runtime.
|
||||
pub fn start_babe<B, C, E, I, SO, SC, Error, OnExit>(BabeParams {
|
||||
pub fn start_babe<B, C, SC, E, I, SO, Error, OnExit, H>(BabeParams {
|
||||
config,
|
||||
local_key,
|
||||
client,
|
||||
@@ -295,17 +184,22 @@ pub fn start_babe<B, C, E, I, SO, SC, Error, OnExit>(BabeParams {
|
||||
impl Future<Item=(), Error=()>,
|
||||
consensus_common::Error,
|
||||
> where
|
||||
B: Block,
|
||||
B: Block<Header=H>,
|
||||
C: ProvideRuntimeApi + ProvideCache<B>,
|
||||
C::Api: AuthoritiesApi<B>,
|
||||
E: Environment<B, Error=Error>,
|
||||
SC: SelectChain<B>,
|
||||
generic::DigestItem<B::Hash, Public, Signature>: DigestItem<Hash=B::Hash>,
|
||||
E::Proposer: Proposer<B, Error=Error>,
|
||||
<<E::Proposer as Proposer<B>>::Create as IntoFuture>::Future: Send + 'static,
|
||||
I: BlockImport<B> + Send + Sync + 'static,
|
||||
SO: SyncOracle + Send + Sync + Clone,
|
||||
SC: SelectChain<B>,
|
||||
DigestItemFor<B>: CompatibleDigestItem + DigestItem<AuthorityId=Public>,
|
||||
Error: ::std::error::Error + Send + From<::consensus_common::Error> + From<I::Error> + 'static,
|
||||
H: Header<
|
||||
Digest=generic::Digest<generic::DigestItem<B::Hash, Public, Signature>>,
|
||||
Hash=B::Hash,
|
||||
>,
|
||||
E: Environment<B, Error=Error>,
|
||||
I: BlockImport<B> + Send + Sync + 'static,
|
||||
Error: std::error::Error + Send + From<::consensus_common::Error> + From<I::Error> + 'static,
|
||||
SO: SyncOracle + Send + Sync + Clone,
|
||||
OnExit: Future<Item=(), Error=()>,
|
||||
{
|
||||
let worker = BabeWorker {
|
||||
@@ -339,15 +233,22 @@ struct BabeWorker<C, E, I, SO> {
|
||||
threshold: u64,
|
||||
}
|
||||
|
||||
impl<B: Block, C, E, I, Error, SO> SlotWorker<B> for BabeWorker<C, E, I, SO> where
|
||||
impl<Hash, H, B, C, E, I, Error, SO> SlotWorker<B> for BabeWorker<C, E, I, SO> where
|
||||
B: Block<Header=H, Hash=Hash>,
|
||||
C: ProvideRuntimeApi + ProvideCache<B>,
|
||||
C::Api: AuthoritiesApi<B>,
|
||||
E: Environment<B, Error=Error>,
|
||||
E::Proposer: Proposer<B, Error=Error>,
|
||||
<<E::Proposer as Proposer<B>>::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<generic::DigestItem<B::Hash, Public, Signature>>,
|
||||
Hash=B::Hash,
|
||||
>,
|
||||
I: BlockImport<B> + Send + Sync + 'static,
|
||||
SO: SyncOracle + Send + Clone,
|
||||
DigestItemFor<B>: CompatibleDigestItem + DigestItem<AuthorityId=Public>,
|
||||
Error: std::error::Error + Send + From<::consensus_common::Error> + From<I::Error> + 'static,
|
||||
{
|
||||
type OnSlot = Box<Future<Item=(), Error=consensus_common::Error> + Send>;
|
||||
@@ -399,7 +300,7 @@ impl<B: Block, C, E, I, Error, SO> SlotWorker<B> for BabeWorker<C, E, I, SO> 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<B: Block, C, E, I, Error, SO> SlotWorker<B> for BabeWorker<C, E, I, SO> 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<BabePreDigest, String> = find_pre_digest::<B>(&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 = <DigestItemFor<B> 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::<B>::babe_seal(signature);
|
||||
|
||||
let import_block: ImportBlock<B> = 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<B> = 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<B: Block>(header: &B::Header) -> Result<BabePreDigest, String>
|
||||
where DigestItemFor<B>: 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<B: Block + Sized, C: AuxStore>(
|
||||
hash: B::Hash,
|
||||
authorities: &[Public],
|
||||
threshold: u64,
|
||||
) -> Result<CheckedHeader<B::Header, DigestItemFor<B>>, String>
|
||||
) -> Result<CheckedHeader<B::Header, (DigestItemFor<B>, DigestItemFor<B>)>, String>
|
||||
where DigestItemFor<B>: 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::<B>(&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<B: Block + Sized, C: AuxStore>(
|
||||
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<B: Block, C, E> Verifier<B> for BabeVerifier<C, E> 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<B: Block, C, E> Verifier<B> for BabeVerifier<C, E> 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<B: Block, C, E> Verifier<B> for BabeVerifier<C, E> 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<B: Block, C, E> Verifier<B> for BabeVerifier<C, E> 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<Hash, Public, Signature>;
|
||||
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<TestBlock, Error>;
|
||||
|
||||
fn propose(&self, _: InherentData, _: Duration) -> Result<TestBlock, Error> {
|
||||
self.1.new_block().unwrap().bake().map_err(|e| e.into())
|
||||
fn propose(&self, _: InherentData, digests: DigestFor<TestBlock>, _: Duration) -> Result<TestBlock, Error> {
|
||||
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 = <generic::DigestItem<_, _, _> 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::<network::test::Hash, Public, primitives::sr25519::Signature>::Seal(0, Signature([0; 64])).as_babe_seal().unwrap();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn wrong_number_rejected() {
|
||||
drop(env_logger::try_init());
|
||||
let bad_seal = generic::DigestItem::<network::test::Hash, Public, primitives::sr25519::Signature>::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::<network::test::Hash, Public, primitives::sr25519::Signature>::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();
|
||||
|
||||
@@ -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<B: BlockT, V: Verifier<B>>(
|
||||
},
|
||||
};
|
||||
|
||||
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();
|
||||
|
||||
@@ -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<B: Block> {
|
||||
/// Future that resolves to a committed proposal.
|
||||
type Create: IntoFuture<Item=B, Error=Self::Error>;
|
||||
/// Create a proposal.
|
||||
fn propose(&self, inherent_data: InherentData, max_duration: Duration) -> Self::Create;
|
||||
fn propose(
|
||||
&self,
|
||||
inherent_data: InherentData,
|
||||
inherent_digests: DigestFor<B>,
|
||||
max_duration: Duration,
|
||||
) -> Self::Create;
|
||||
}
|
||||
|
||||
/// An oracle for when major synchronization work is being undertaken.
|
||||
|
||||
@@ -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<Block: BlockT>: Sync + Send + Clone {
|
||||
) -> Result<Option<<Block as BlockT>::Hash>, Error> {
|
||||
Ok(Some(target_hash))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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<C, T>(backend: Arc<C>, key: &[u8]) -> ClientResult<Option<T>>
|
||||
fn load_decode<C, T>(backend: Arc<C>, key: &[u8]) -> ClientResult<Option<T>>
|
||||
where
|
||||
C: AuxStore,
|
||||
T: Decode,
|
||||
|
||||
@@ -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]) {
|
||||
|
||||
@@ -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)
|
||||
);
|
||||
|
||||
Generated
+6
-6
@@ -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"
|
||||
|
||||
@@ -117,7 +117,7 @@ impl<Block: BlockT> AuthoritySetForFinalityChecker<Block> for Arc<FetchChecker<B
|
||||
call_data: vec![],
|
||||
retry_count: None,
|
||||
};
|
||||
|
||||
|
||||
self.check_execution_proof(&request, proof)
|
||||
.and_then(|authorities| {
|
||||
let authorities: Vec<(AuthorityId, u64)> = Decode::decode(&mut &authorities[..])
|
||||
|
||||
@@ -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()))?
|
||||
|
||||
@@ -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 },
|
||||
|
||||
@@ -297,7 +297,7 @@ impl<B: BlockT> OnDemandCore<B> 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]],
|
||||
|
||||
@@ -26,9 +26,14 @@ struct TestLink {}
|
||||
|
||||
impl Link<Block> for TestLink {}
|
||||
|
||||
fn prepare_good_block() -> (client::Client<test_client::Backend, test_client::Executor, Block, test_client::runtime::RuntimeApi>, Hash, u64, PeerId, IncomingBlock<Block>) {
|
||||
fn prepare_good_block() -> (client::Client<
|
||||
test_client::Backend,
|
||||
test_client::Executor,
|
||||
Block,
|
||||
test_client::runtime::RuntimeApi,
|
||||
>, Hash, u64, PeerId, IncomingBlock<Block>) {
|
||||
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);
|
||||
|
||||
@@ -636,7 +636,8 @@ impl<D, S: NetworkSpecialization<Block>> Peer<D, S> {
|
||||
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!(
|
||||
|
||||
@@ -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 }
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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(),
|
||||
|
||||
@@ -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());
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -8,4 +8,3 @@ decl_runtime_apis! {
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
|
||||
|
||||
@@ -62,7 +62,6 @@ impl<Item> traits::Digest for Digest<Item> where
|
||||
/// provide opaque access to other items.
|
||||
#[derive(PartialEq, Eq, Clone)]
|
||||
#[cfg_attr(feature = "std", derive(Debug))]
|
||||
#[allow(deprecated)]
|
||||
pub enum DigestItem<Hash, AuthorityId, SealSignature> {
|
||||
/// 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<Hash, AuthorityId, SealSignature> {
|
||||
/// 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<u8>),
|
||||
/// 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<u8>),
|
||||
/// Any 'non-system' digest item, opaque to the native code.
|
||||
Other(Vec<u8>),
|
||||
}
|
||||
@@ -97,20 +101,26 @@ impl<Hash: Encode, AuthorityId: Encode, SealSignature: Encode> ::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<u8>),
|
||||
/// 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<u8>),
|
||||
/// Any 'non-system' digest item, opaque to the native code.
|
||||
/// Reference to `DigestItem::Other`.
|
||||
Other(&'a [u8]),
|
||||
Other(&'a Vec<u8>),
|
||||
}
|
||||
|
||||
/// 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<Hash, AuthorityId, SealSignature> DigestItem<Hash, AuthorityId, SealSignature> {
|
||||
@@ -137,13 +148,13 @@ impl<Hash, AuthorityId, SealSignature> DigestItem<Hash, AuthorityId, SealSignatu
|
||||
}
|
||||
|
||||
/// Returns a 'referencing view' for this digest item.
|
||||
#[allow(deprecated)]
|
||||
fn dref<'a>(&'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<Hash: Encode, AuthorityId: Encode, SealSignature: Encode> Encode for DigestItem<Hash, AuthorityId, SealSignature> {
|
||||
@@ -183,14 +198,18 @@ impl<Hash: Decode, AuthorityId: Decode, SealSignature: Decode> 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<u8>) = 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<u8>) = 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<u8> {
|
||||
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\"]}",
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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<Number, Hash, DigestItem> traits::Header for Header<Number, Hash, DigestIte
|
||||
fn set_parent_hash(&mut self, hash: Self::Hash) { self.parent_hash = hash }
|
||||
|
||||
fn digest(&self) -> &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,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -50,14 +50,14 @@ pub fn test_leaves_for_backend<B: 'static>(backend: Arc<B>) 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<B: 'static>(backend: Arc<B>) 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<B: 'static>(backend: Arc<B>) 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<B: 'static>(backend: Arc<B>) 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<B: 'static>(backend: Arc<B>) 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<B: 'static>(backend: Arc<B>) 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<B: 'static>(backend: Arc<B>) 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<B: 'static>(backend: Arc<B
|
||||
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(),
|
||||
@@ -282,15 +282,15 @@ pub fn test_blockchain_query_by_number_gets_canonical<B: 'static>(backend: Arc<B
|
||||
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(),
|
||||
@@ -302,7 +302,7 @@ pub fn test_blockchain_query_by_number_gets_canonical<B: 'static>(backend: Arc<B
|
||||
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(),
|
||||
|
||||
@@ -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<AuthorityId>;
|
||||
StorageDigest: b"sys:digest" => Digest;
|
||||
}
|
||||
|
||||
pub fn balance_of_key(who: AccountId) -> Vec<u8> {
|
||||
@@ -67,6 +68,7 @@ pub fn initialize_block(header: &Header) {
|
||||
// populate environment.
|
||||
<Number>::put(&header.number);
|
||||
<ParentHash>::put(&header.parent_hash);
|
||||
<StorageDigest>::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) = <NewAuthorities>::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::<Vec<_>>();
|
||||
@@ -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) = <NewAuthorities>::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::<Vec<_>>();
|
||||
let extrinsics_root = enumerated_trie_root::<Blake2Hasher>(&txs).into();
|
||||
|
||||
// let mut digest = Digest::default();
|
||||
let number = <Number>::take().expect("Number is set by `initialize_block`");
|
||||
let parent_hash = <ParentHash>::take();
|
||||
let mut digest = <StorageDigest>::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));
|
||||
}
|
||||
|
||||
+6
-6
@@ -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"
|
||||
|
||||
+6
-6
@@ -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"
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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,
|
||||
};
|
||||
|
||||
|
||||
Generated
+19
-7
@@ -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"
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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::<HandleTestReport>(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::<HandleTestReport>(8 * slot_duration, slot_duration);
|
||||
let _header = System::finalize();
|
||||
|
||||
|
||||
@@ -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<u32> = 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]);
|
||||
|
||||
|
||||
@@ -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::<Test>::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::<Test>::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::<Test>::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::<Test>::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::<Test>::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::<Test>::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, <BalanceOf<Test>>::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(
|
||||
|
||||
@@ -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) {
|
||||
<system::Module<System>>::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) {
|
||||
<system::Module<System>>::initialize(block_number, parent_hash, extrinsics_root, digest);
|
||||
<AllModules as OnInitialize<System::BlockNumber>>::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
|
||||
<system::Module<System>>::inc_account_nonce(sender);
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -465,10 +465,16 @@ impl<T: Trait> Module<T> {
|
||||
}
|
||||
|
||||
/// 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);
|
||||
<Number<T>>::put(number);
|
||||
<Digest<T>>::put(digest);
|
||||
<ParentHash<T>>::put(parent_hash);
|
||||
<BlockHash<T>>::insert(*number - One::one(), parent_hash);
|
||||
<ExtrinsicsRoot<T>>::put(txs_root);
|
||||
@@ -553,38 +559,51 @@ impl<T: Trait> Module<T> {
|
||||
|
||||
/// 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) = <RandomMaterial<T>>::get();
|
||||
if hash_series.len() > 0 {
|
||||
@@ -606,8 +625,9 @@ impl<T: Trait> Module<T> {
|
||||
<AccountNonce<T>>::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![
|
||||
|
||||
@@ -148,7 +148,7 @@ where
|
||||
<FullClient<F> as ProvideRuntimeApi>::Api: BlockBuilder<FactoryBlock<F>>,
|
||||
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")
|
||||
|
||||
@@ -38,4 +38,3 @@ impl FromStr for Mode {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user