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:
DemiMarie-parity
2019-05-29 08:13:38 -04:00
committed by Gavin Wood
parent e9a4c80c40
commit c7d1204ce5
55 changed files with 1031 additions and 871 deletions
+2 -2
View File
@@ -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
+17 -8
View File
@@ -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"
+2 -2
View File
@@ -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);
+1 -1
View File
@@ -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 {
+48 -42
View File
@@ -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();
}
+1 -1
View File
@@ -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,
}
}
}
+166 -281
View File
@@ -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;
+149
View File
@@ -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,
}
}
}
+234 -295
View File
@@ -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 wasnt 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();
+7 -2
View File
@@ -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,
+1 -2
View File
@@ -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]) {
+3 -3
View File
@@ -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)
);
+6 -6
View File
@@ -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()))?
+3 -3
View File
@@ -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 },
+2 -2
View File
@@ -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);
+2 -1
View File
@@ -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!(
+1 -1
View File
@@ -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 }
+5 -5
View File
@@ -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();
}
+3 -3
View File
@@ -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(),
+1 -1
View File
@@ -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,
}
}
}
+4
View File
@@ -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 {
+3 -4
View File
@@ -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,
}
}
}
+5 -4
View File
@@ -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.
+30 -30
View File
@@ -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(),
+12 -9
View File
@@ -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
View File
@@ -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
View File
@@ -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"
+2 -2
View File
@@ -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;
+2 -2
View File
@@ -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,
};
+19 -7
View File
@@ -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"
+3 -3
View File
@@ -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
+2 -2
View File
@@ -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();
+6 -6
View File
@@ -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]);
+12 -12
View File
@@ -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(
+8 -5
View File
@@ -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);
}
+2 -2
View File
@@ -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,
+12 -12
View File
@@ -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));
+48 -28
View File
@@ -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 {
}
}
}