BABE signing and verification (#2270)

* Add basic BABE consensus type

* Update core/consensus/babe/slots/Cargo.toml

Co-Authored-By: DemiMarie-parity <48690212+DemiMarie-parity@users.noreply.github.com>

* Fix parameterization and run `rustfmt`

* Respond to review comments

* Update various Cargo.lock files

* Revert "Update various Cargo.lock files"

This reverts commit af53d7624752a744320e9cbb25749fdd8e6f46d2.

* `BabeSealSignature` → `BabeSeal`

* Move slot code to its own crate

This was highly non-trivial, due to cyclic dependencies.

* Remove redundancy between AuRa and BABE

Some of the code duplication was removed using a macro.

* Fix build error

* Avoid non-`#[doc(hidden)]` re-exports

Also, bump some library versions in `Cargo.toml`.

* Remove dead code in AuRa

* Remove impl_slot macro

It was more trouble than it was worth.

Also, delete useless dependencies on Serde.

* AuRa and BABE need different DB keys

* Bring back `aura::Network`, but deprecate it.

* Improve docs and add `slot_duration` inherent method

* Add docs to `substrate_consensus_aura::SlotDuration`

* Add missing documentation and #![forbid(missing_docs, unsafe_code)]

* Add a #![forbid(missing_docs)]

* Remove dependency of `test-runtime` on `slots`

* Update core/consensus/babe/src/lib.rs

Co-Authored-By: DemiMarie-parity <48690212+DemiMarie-parity@users.noreply.github.com>

* Remove wrongly added file

* Fix copyright notice

Co-Authored-By: DemiMarie-parity <48690212+DemiMarie-parity@users.noreply.github.com>

* Bump `impl_version` and `spec_version`

* Add more code to BABE

Most of it is copied from AuRa code, but at least the initial core is
there.

* Stuck on horrible compiler error message

* add missing files

* Spaces → tabs

* Simplify code

* Fix compilation

This involved fixing dependencies and adding a `Mutex`.

* More work on BABE

* Fix deprecation version

* Fix deprecation version; remove spurious carets

* Fix Cargo.toml

* Implement VRF signing logic

* The import queue code compiles, though it probably doesn’t work.

* Add VRF verification

* Update Cargo.lock

* Update dependencies

* Move test network to sr25519 authority keys

* Fix accidental build bustage

* Trying to get the tests to work

* Add logging messages and remove dead code

There seems to be a problem with the test network.  Since AuRa and BABE
are both affected, this is most likely due to the switch from ed25519 to
sr25519.

* Trying to get the tests to work

* Add logging messages and remove dead code

There seems to be a problem with the test network.  Since AuRa and BABE
are both affected, this is most likely due to the switch from ed25519 to
sr25519.

* Working testsuite at last!

The problem was with serialization and deserialization.  Normally,
those functions are generated automatically, but those for `BabeSeal`
had to be written manually.  The hand-written versions were not
correct, however, as shown by the decoder not being able to decode the
output of the encoder.

* Enable BabeSeal::Encode asserts in --release tests

* Bump runtime and dependency versions

* Fix wasm compilation

The wasm build was broken because of a typo in
`core/test-runtime/src/lib.rs`, and missing gates on the `std` feature
in `core/consensus/{aura,babe}/primitives/Cargo.toml`.  Additionally,
improve the quotation in the build scripts.

* Merge Cargo.lock

* Change expected JSON string

The test was also broken on `master`, so I suspect that the test was
incorrect.

* Responded to review

* Remove hard-coded threshold from production code

A hard-coded threshold is now only used in tests.

* Fix swapped doc comments

* Fix unused import warnings

* fix ci error

* fix typo

* Fix spacing in docs

* Minor changes suggested by @joepetrowski

on https://github.com/paritytech/substrate/pull/2372

* Remove unnecessary getters

* fix compile error

* Fix silly unused-variable error

* Improve documentation formatting

Co-Authored-By: DemiMarie-parity <48690212+DemiMarie-parity@users.noreply.github.com>

* Add issue links

* Revert excess verbosity and #![forbid(warnings)]

* Apply suggestions from code review

Co-Authored-By: DemiMarie-parity <48690212+DemiMarie-parity@users.noreply.github.com>

* Reformat some comments

* Threshold should depend on number of validators

Also, respond to code review

* Fix silly compilation errors

* Reduce logging verbosity

* Fix missing import
This commit is contained in:
DemiMarie-parity
2019-05-02 11:16:54 -04:00
committed by GitHub
parent d3f59a0712
commit fb19684358
40 changed files with 1570 additions and 263 deletions
+28 -19
View File
@@ -2892,23 +2892,6 @@ dependencies = [
"winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
[[package]]
name = "schnorrkel"
version = "0.1.1"
source = "git+https://github.com/paritytech/schnorrkel#1762df02ac48ba5c3fa8c162e19a393247079f88"
dependencies = [
"clear_on_drop 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
"curve25519-dalek 1.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
"ed25519-dalek 1.0.0-pre.1 (registry+https://github.com/rust-lang/crates.io-index)",
"failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
"merlin 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
"rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)",
"rand_chacha 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
"sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
"sha3 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)",
"subtle 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]] [[package]]
name = "schnorrkel" name = "schnorrkel"
version = "0.1.1" version = "0.1.1"
@@ -3271,6 +3254,29 @@ dependencies = [
"substrate-primitives 1.0.0", "substrate-primitives 1.0.0",
] ]
[[package]]
name = "srml-babe"
version = "0.1.0"
dependencies = [
"hex-literal 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
"lazy_static 1.3.0 (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)",
"serde 1.0.90 (registry+https://github.com/rust-lang/crates.io-index)",
"sr-io 1.0.0",
"sr-primitives 1.0.0",
"sr-std 1.0.0",
"srml-consensus 1.0.0",
"srml-session 1.0.0",
"srml-staking 1.0.0",
"srml-support 1.0.0",
"srml-system 1.0.0",
"srml-timestamp 1.0.0",
"substrate-consensus-babe-primitives 1.0.0",
"substrate-inherents 1.0.0",
"substrate-primitives 1.0.0",
]
[[package]] [[package]]
name = "srml-balances" name = "srml-balances"
version = "1.0.0" version = "1.0.0"
@@ -3936,13 +3942,16 @@ dependencies = [
"error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", "error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)",
"futures 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
"merlin 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
"parity-codec 3.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "parity-codec 3.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
"parity-codec-derive 3.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "parity-codec-derive 3.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
"parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
"schnorrkel 0.1.1 (git+https://github.com/paritytech/schnorrkel)", "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)",
"schnorrkel 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
"sr-io 1.0.0", "sr-io 1.0.0",
"sr-primitives 1.0.0", "sr-primitives 1.0.0",
"sr-version 1.0.0", "sr-version 1.0.0",
"srml-babe 0.1.0",
"srml-consensus 1.0.0", "srml-consensus 1.0.0",
"srml-support 1.0.0", "srml-support 1.0.0",
"substrate-client 1.0.0", "substrate-client 1.0.0",
@@ -4450,6 +4459,7 @@ dependencies = [
"substrate-client 1.0.0", "substrate-client 1.0.0",
"substrate-consensus-aura-primitives 1.0.0", "substrate-consensus-aura-primitives 1.0.0",
"substrate-consensus-authorities 1.0.0", "substrate-consensus-authorities 1.0.0",
"substrate-consensus-babe-primitives 1.0.0",
"substrate-executor 1.0.0", "substrate-executor 1.0.0",
"substrate-inherents 1.0.0", "substrate-inherents 1.0.0",
"substrate-keyring 1.0.0", "substrate-keyring 1.0.0",
@@ -5671,7 +5681,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
"checksum safemem 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8dca453248a96cb0749e36ccdfe2b0b4e54a61bfef89fb97ec621eb8e0a93dd9" "checksum safemem 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8dca453248a96cb0749e36ccdfe2b0b4e54a61bfef89fb97ec621eb8e0a93dd9"
"checksum same-file 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8f20c4be53a8a1ff4c1f1b2bd14570d2f634628709752f0702ecdd2b3f9a5267" "checksum same-file 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8f20c4be53a8a1ff4c1f1b2bd14570d2f634628709752f0702ecdd2b3f9a5267"
"checksum schannel 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)" = "f2f6abf258d99c3c1c5c2131d99d064e94b7b3dd5f416483057f308fea253339" "checksum schannel 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)" = "f2f6abf258d99c3c1c5c2131d99d064e94b7b3dd5f416483057f308fea253339"
"checksum schnorrkel 0.1.1 (git+https://github.com/paritytech/schnorrkel)" = "<none>"
"checksum schnorrkel 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b5eff518f9bed3d803a0d002af0ab96339b0ebbedde3bec98a684986134b7a39" "checksum schnorrkel 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b5eff518f9bed3d803a0d002af0ab96339b0ebbedde3bec98a684986134b7a39"
"checksum scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "94258f53601af11e6a49f722422f6e3425c52b06245a5cf9bc09908b174f5e27" "checksum scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "94258f53601af11e6a49f722422f6e3425c52b06245a5cf9bc09908b174f5e27"
"checksum secp256k1 0.12.2 (registry+https://github.com/rust-lang/crates.io-index)" = "bfaccd3a23619349e0878d9a241f34b1982343cdf67367058cd7d078d326b63e" "checksum secp256k1 0.12.2 (registry+https://github.com/rust-lang/crates.io-index)" = "bfaccd3a23619349e0878d9a241f34b1982343cdf67367058cd7d078d326b63e"
@@ -12,5 +12,6 @@ runtime_primitives = { package = "sr-primitives", path = "../../../sr-primitives
[features] [features]
default = ["std"] default = ["std"]
std = [ std = [
"runtime_primitives/std",
"substrate-client/std", "substrate-client/std",
] ]
+9 -36
View File
@@ -62,10 +62,10 @@ use srml_aura::{
}; };
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 slots::{CheckedHeader, SlotWorker, SlotInfo, SlotCompatible}; use slots::{CheckedHeader, SlotWorker, SlotInfo, SlotCompatible, slot_now};
pub use aura_primitives::*; pub use aura_primitives::*;
pub use consensus_common::SyncOracle; pub use consensus_common::{SyncOracle, ExtraVerification};
type AuthorityId<P> = <P as Pair>::Public; type AuthorityId<P> = <P as Pair>::Public;
type Signature<P> = <P as Pair>::Signature; type Signature<P> = <P as Pair>::Signature;
@@ -120,20 +120,6 @@ fn slot_author<P: Pair>(slot_num: u64, authorities: &[AuthorityId<P>]) -> Option
Some(current_author) Some(current_author)
} }
fn duration_now() -> Option<Duration> {
use std::time::SystemTime;
let now = SystemTime::now();
now.duration_since(SystemTime::UNIX_EPOCH).map_err(|e| {
warn!("Current time {:?} is before unix epoch. Something is wrong: {:?}", now, e);
}).ok()
}
/// Get the slot for now.
fn slot_now(slot_duration: u64) -> Option<u64> {
duration_now().map(|s| s.as_secs() / slot_duration)
}
fn inherent_to_common_error(err: RuntimeString) -> consensus_common::Error { fn inherent_to_common_error(err: RuntimeString) -> consensus_common::Error {
consensus_common::ErrorKind::InherentData(err.into()).into() consensus_common::ErrorKind::InherentData(err.into()).into()
} }
@@ -467,7 +453,6 @@ impl<B: Block, C, E, I, P, Error, SO> SlotWorker<B> for AuraWorker<C, E, I, P, S
/// This digest item will always return `Some` when used with `as_aura_seal`. /// This digest item will always return `Some` when used with `as_aura_seal`.
// //
// FIXME #1018 needs misbehavior types // FIXME #1018 needs misbehavior types
#[forbid(deprecated)]
fn check_header<B: Block, P: Pair>( fn check_header<B: Block, P: Pair>(
slot_now: u64, slot_now: u64,
mut header: B::Header, mut header: B::Header,
@@ -517,19 +502,6 @@ fn check_header<B: Block, P: Pair>(
} }
} }
/// Extra verification for Aura blocks.
pub trait ExtraVerification<B: Block>: Send + Sync {
/// Future that resolves when the block is verified or fails with error if not.
type Verified: IntoFuture<Item=(),Error=String>;
/// Do additional verification for this block.
fn verify(
&self,
header: &B::Header,
body: Option<&[B::Extrinsic]>,
) -> Self::Verified;
}
/// A verifier for Aura blocks. /// A verifier for Aura blocks.
pub struct AuraVerifier<C, E, P> { pub struct AuraVerifier<C, E, P> {
client: Arc<C>, client: Arc<C>,
@@ -785,7 +757,8 @@ pub fn import_queue<B, C, E, P>(
/// Start an import queue for the Aura consensus algorithm with backwards compatibility. /// Start an import queue for the Aura consensus algorithm with backwards compatibility.
#[deprecated( #[deprecated(
note = "should not be used unless backwards compatibility with an older chain is needed." 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>( pub fn import_queue_accept_old_seals<B, C, E, P>(
slot_duration: SlotDuration, slot_duration: SlotDuration,
@@ -828,8 +801,8 @@ mod tests {
use network::config::ProtocolConfig; use network::config::ProtocolConfig;
use parking_lot::Mutex; use parking_lot::Mutex;
use tokio::runtime::current_thread; use tokio::runtime::current_thread;
use keyring::ed25519::Keyring; use keyring::sr25519::Keyring;
use primitives::ed25519; use primitives::sr25519;
use client::BlockchainEvents; use client::BlockchainEvents;
use test_client; use test_client;
@@ -844,7 +817,7 @@ mod tests {
type Proposer = DummyProposer; type Proposer = DummyProposer;
type Error = Error; type Error = Error;
fn init(&self, parent_header: &<TestBlock as BlockT>::Header, _authorities: &[AuthorityId<ed25519::Pair>]) fn init(&self, parent_header: &<TestBlock as BlockT>::Header, _authorities: &[AuthorityId<sr25519::Pair>])
-> Result<DummyProposer, Error> -> Result<DummyProposer, Error>
{ {
Ok(DummyProposer(parent_header.number + 1, self.0.clone())) Ok(DummyProposer(parent_header.number + 1, self.0.clone()))
@@ -870,7 +843,7 @@ mod tests {
impl TestNetFactory for AuraTestNet { impl TestNetFactory for AuraTestNet {
type Specialization = DummySpecialization; type Specialization = DummySpecialization;
type Verifier = AuraVerifier<PeersClient, NothingExtra, ed25519::Pair>; type Verifier = AuraVerifier<PeersClient, NothingExtra, sr25519::Pair>;
type PeerData = (); type PeerData = ();
/// Create new test network with peers and given config. /// Create new test network with peers and given config.
@@ -957,7 +930,7 @@ mod tests {
&inherent_data_providers, slot_duration.get() &inherent_data_providers, slot_duration.get()
).expect("Registers aura inherent data provider"); ).expect("Registers aura inherent data provider");
let aura = start_aura::<_, _, _, _, ed25519::Pair, _, _, _>( let aura = start_aura::<_, _, _, _, sr25519::Pair, _, _, _>(
slot_duration, slot_duration,
Arc::new(key.clone().into()), Arc::new(key.clone().into()),
client.clone(), client.clone(),
+4 -4
View File
@@ -16,6 +16,7 @@ runtime_io = { package = "sr-io", path = "../../sr-io" }
inherents = { package = "substrate-inherents", path = "../../inherents" } inherents = { package = "substrate-inherents", path = "../../inherents" }
srml-consensus = { path = "../../../srml/consensus" } srml-consensus = { path = "../../../srml/consensus" }
substrate-telemetry = { path = "../../telemetry" } substrate-telemetry = { path = "../../telemetry" }
srml-babe = { path = "../../../srml/babe" }
client = { package = "substrate-client", path = "../../client" } client = { package = "substrate-client", path = "../../client" }
consensus_common = { package = "substrate-consensus-common", path = "../common" } consensus_common = { package = "substrate-consensus-common", path = "../common" }
authorities = { package = "substrate-consensus-authorities", path = "../authorities" } authorities = { package = "substrate-consensus-authorities", path = "../authorities" }
@@ -26,10 +27,9 @@ tokio = "0.1.18"
parking_lot = "0.7.1" parking_lot = "0.7.1"
error-chain = "0.12.0" error-chain = "0.12.0"
log = "0.4.6" log = "0.4.6"
schnorrkel = "0.1.1"
[dependencies.schnorrkel] rand = "0.6.5"
git = "https://github.com/paritytech/schnorrkel" merlin = "1.0.3"
branch = "master"
[dev-dependencies] [dev-dependencies]
keyring = { package = "substrate-keyring", path = "../../keyring" } keyring = { package = "substrate-keyring", path = "../../keyring" }
@@ -9,11 +9,13 @@ edition = "2018"
substrate-client = { path = "../../../client", default-features = false } substrate-client = { path = "../../../client", default-features = false }
runtime_primitives = { package = "sr-primitives", path = "../../../sr-primitives", default-features = false } runtime_primitives = { package = "sr-primitives", path = "../../../sr-primitives", default-features = false }
slots = { package = "substrate-consensus-slots", path = "../../slots", optional = true } slots = { package = "substrate-consensus-slots", path = "../../slots", optional = true }
parity-codec = "^3.4.0" parity-codec = { version = "3.5.1", default-features = false }
[features] [features]
default = ["std"] default = ["std"]
std = [ std = [
"runtime_primitives/std",
"substrate-client/std", "substrate-client/std",
"parity-codec/std",
"slots", "slots",
] ]
@@ -29,26 +29,23 @@ pub const BABE_ENGINE_ID: ConsensusEngineId = [b'b', b'a', b'b', b'e'];
/// Configuration data used by the BABE consensus engine. /// Configuration data used by the BABE consensus engine.
#[derive(Copy, Clone, Hash, PartialEq, Eq, Debug, Encode, Decode)] #[derive(Copy, Clone, Hash, PartialEq, Eq, Debug, Encode, Decode)]
pub struct BabeConfiguration { pub struct BabeConfiguration {
slot_duration: u64, /// The slot duration in milliseconds for BABE. Currently, only
expected_block_time: u64,
}
impl BabeConfiguration {
/// Return the expected block time in milliseconds for BABE. Currently,
/// only the value provided by this type at genesis will be used.
///
/// Dynamic expected block time may be supported in the future.
pub fn expected_block_time(&self) -> u64 {
self.expected_block_time
}
/// Return the slot duration in milliseconds for BABE. Currently, only
/// the value provided by this type at genesis will be used. /// the value provided by this type at genesis will be used.
/// ///
/// Dynamic slot duration may be supported in the future. /// Dynamic slot duration may be supported in the future.
pub fn slot_duration(&self) -> u64 { pub slot_duration: u64,
self.slot_duration
} /// The expected block time in milliseconds for BABE. Currently,
/// only the value provided by this type at genesis will be used.
///
/// Dynamic expected block time may be supported in the future.
pub expected_block_time: u64,
/// The maximum permitted VRF output, or *threshold*, for BABE. Currently,
/// only the value provided by this type at genesis will be used.
///
/// Dynamic thresholds may be supported in the future.
pub threshold: u64,
} }
#[cfg(feature = "std")] #[cfg(feature = "std")]
File diff suppressed because it is too large Load Diff
@@ -17,12 +17,13 @@
//! Import Queue primitive: something which can verify and import blocks. //! Import Queue primitive: something which can verify and import blocks.
//! //!
//! This serves as an intermediate and abstracted step between synchronization //! This serves as an intermediate and abstracted step between synchronization
//! and import. Each mode of consensus will have its own requirements for block verification. //! and import. Each mode of consensus will have its own requirements for block
//! Some algorithms can verify in parallel, while others only sequentially. //! verification. Some algorithms can verify in parallel, while others only
//! sequentially.
//! //!
//! The `ImportQueue` trait allows such verification strategies to be instantiated. //! The `ImportQueue` trait allows such verification strategies to be
//! The `BasicQueue` and `BasicVerifier` traits allow serial queues to be //! instantiated. The `BasicQueue` and `BasicVerifier` traits allow serial
//! instantiated simply. //! queues to be instantiated simply.
use crate::block_import::{ use crate::block_import::{
BlockImport, BlockOrigin, ImportBlock, ImportedAux, ImportResult, JustificationImport, BlockImport, BlockOrigin, ImportBlock, ImportedAux, ImportResult, JustificationImport,
@@ -106,8 +107,8 @@ impl<B: BlockT> Clone for Box<ImportQueue<B>> {
} }
} }
/// Interface to a basic block import queue that is importing blocks sequentially in a separate thread, /// Interface to a basic block import queue that is importing blocks
/// with pluggable verification. /// sequentially in a separate thread, with pluggable verification.
#[derive(Clone)] #[derive(Clone)]
pub struct BasicQueue<B: BlockT> { pub struct BasicQueue<B: BlockT> {
sender: Sender<BlockImportMsg<B>>, sender: Sender<BlockImportMsg<B>>,
@@ -120,20 +121,24 @@ impl<B: BlockT> ImportQueueClone<B> for BasicQueue<B> {
} }
/// "BasicQueue" is a wrapper around a channel sender to the "BlockImporter". /// "BasicQueue" is a wrapper around a channel sender to the "BlockImporter".
/// "BasicQueue" itself does not keep any state or do any importing work, and can therefore be send to other threads. /// "BasicQueue" itself does not keep any state or do any importing work, and
/// can therefore be send to other threads.
/// ///
/// "BasicQueue" implements "ImportQueue" by sending messages to the "BlockImporter", which runs in it's own thread. /// "BasicQueue" implements "ImportQueue" by sending messages to the
/// "BlockImporter", which runs in it's own thread.
/// ///
/// The "BlockImporter" is responsible for handling incoming requests from the "BasicQueue", /// The "BlockImporter" is responsible for handling incoming requests from the
/// some of these requests are handled by the "BlockImporter" itself, such as "is_importing" or "status", /// "BasicQueue". Some of these requests are handled by the "BlockImporter"
/// and justifications are also imported by the "BlockImporter". /// itself, such as "is_importing", "status", and justifications.
/// ///
/// The "import block" work will be offloaded to a single "BlockImportWorker", running in another thread. /// The "import block" work will be offloaded to a single "BlockImportWorker",
/// Offloading the work is done via a channel, /// running in another thread. Offloading the work is done via a channel,
/// ensuring blocks in this implementation are imported sequentially and in order(as received by the "BlockImporter") /// ensuring blocks in this implementation are imported sequentially and in
/// order (as received by the "BlockImporter").
/// ///
/// As long as the "BasicQueue" is not dropped, the "BlockImporter" will keep running. /// As long as the "BasicQueue" is not dropped, the "BlockImporter" will keep
/// The "BlockImporter" owns a sender to the "BlockImportWorker", ensuring that the worker is kept alive until that sender is dropped. /// running. The "BlockImporter" owns a sender to the "BlockImportWorker",
/// ensuring that the worker is kept alive until that sender is dropped.
impl<B: BlockT> BasicQueue<B> { impl<B: BlockT> BasicQueue<B> {
/// Instantiate a new basic queue, with given verifier. /// Instantiate a new basic queue, with given verifier.
pub fn new<V: 'static + Verifier<B>>( pub fn new<V: 'static + Verifier<B>>(
@@ -152,8 +157,8 @@ impl<B: BlockT> BasicQueue<B> {
/// Send synchronization request to the block import channel. /// Send synchronization request to the block import channel.
/// ///
/// The caller should wait for Link::synchronized() call to ensure that it has synchronized /// The caller should wait for Link::synchronized() call to ensure that it
/// with ImportQueue. /// has synchronized with ImportQueue.
#[cfg(any(test, feature = "test-helpers"))] #[cfg(any(test, feature = "test-helpers"))]
pub fn synchronize(&self) { pub fn synchronize(&self) {
self self
@@ -238,6 +243,7 @@ impl<B: BlockT> BlockImporter<B> {
worker_sender: Sender<BlockImportWorkerMsg<B>>, worker_sender: Sender<BlockImportWorkerMsg<B>>,
justification_import: Option<SharedJustificationImport<B>>, justification_import: Option<SharedJustificationImport<B>>,
) -> Sender<BlockImportMsg<B>> { ) -> Sender<BlockImportMsg<B>> {
trace!(target: "block_import", "Creating new Block Importer!");
let (sender, port) = channel::bounded(4); let (sender, port) = channel::bounded(4);
let _ = thread::Builder::new() let _ = thread::Builder::new()
.name("ImportQueue".into()) .name("ImportQueue".into())
@@ -258,6 +264,7 @@ impl<B: BlockT> BlockImporter<B> {
} }
fn run(&mut self) -> bool { fn run(&mut self) -> bool {
trace!(target: "import_queue", "Running import queue");
let msg = select! { let msg = select! {
recv(self.port) -> msg => { recv(self.port) -> msg => {
match msg { match msg {
@@ -297,6 +304,7 @@ impl<B: BlockT> BlockImporter<B> {
BlockImportMsg::Stop => return false, BlockImportMsg::Stop => return false,
#[cfg(any(test, feature = "test-helpers"))] #[cfg(any(test, feature = "test-helpers"))]
BlockImportMsg::Synchronize => { BlockImportMsg::Synchronize => {
trace!(target: "sync", "Received synchronization message");
self.worker_sender self.worker_sender
.send(BlockImportWorkerMsg::Synchronize) .send(BlockImportWorkerMsg::Synchronize)
.expect("1. This is holding a sender to the worker, 2. the worker should not quit while a sender is still held; qed"); .expect("1. This is holding a sender to the worker, 2. the worker should not quit while a sender is still held; qed");
@@ -318,6 +326,7 @@ impl<B: BlockT> BlockImporter<B> {
BlockImportWorkerMsg::Imported(results) => (results), BlockImportWorkerMsg::Imported(results) => (results),
#[cfg(any(test, feature = "test-helpers"))] #[cfg(any(test, feature = "test-helpers"))]
BlockImportWorkerMsg::Synchronize => { BlockImportWorkerMsg::Synchronize => {
trace!(target: "sync", "Synchronizing link");
link.synchronized(); link.synchronized();
return true; return true;
}, },
@@ -434,6 +443,7 @@ impl<B: BlockT, V: 'static + Verifier<B>> BlockImportWorker<B, V> {
}, },
#[cfg(any(test, feature = "test-helpers"))] #[cfg(any(test, feature = "test-helpers"))]
BlockImportWorkerMsg::Synchronize => { BlockImportWorkerMsg::Synchronize => {
trace!(target: "sync", "Sending sync message");
let _ = worker.result_sender.send(BlockImportWorkerMsg::Synchronize); let _ = worker.result_sender.send(BlockImportWorkerMsg::Synchronize);
}, },
_ => unreachable!("Import Worker does not receive the Imported message; qed"), _ => unreachable!("Import Worker does not receive the Imported message; qed"),
@@ -118,6 +118,20 @@ impl<T: SyncOracle> SyncOracle for Arc<T> {
} }
} }
/// Extra verification for blocks.
pub trait ExtraVerification<B: Block>: Send + Sync {
/// Future that resolves when the block is verified, or fails with error if
/// not.
type Verified: IntoFuture<Item=(),Error=String>;
/// Do additional verification for this block.
fn verify(
&self,
header: &B::Header,
body: Option<&[B::Extrinsic]>,
) -> Self::Verified;
}
/// A list of all well known keys in the cache. /// A list of all well known keys in the cache.
pub mod well_known_cache_keys { pub mod well_known_cache_keys {
/// The type representing cache keys. /// The type representing cache keys.
+69 -52
View File
@@ -24,45 +24,44 @@
mod slots; mod slots;
pub use slots::{Slots, SlotInfo}; pub use slots::{slot_now, SlotInfo, Slots};
use client::ChainHead;
use codec::{Decode, Encode};
use consensus_common::SyncOracle;
use futures::prelude::*;
use futures::{
future::{self, Either},
Future, IntoFuture,
};
use inherents::{InherentData, InherentDataProviders};
use log::{debug, error, info, warn};
use runtime_primitives::generic::BlockId;
use runtime_primitives::traits::{ApiRef, Block, ProvideRuntimeApi};
use std::fmt::Debug;
use std::ops::Deref;
use std::sync::{mpsc, Arc}; use std::sync::{mpsc, Arc};
use std::thread; use std::thread;
use std::fmt::Debug;
use futures::prelude::*;
use futures::{Future, IntoFuture, future::{self, Either}};
use log::{warn, debug, info};
use runtime_primitives::generic::BlockId;
use runtime_primitives::traits::{ProvideRuntimeApi, Block, ApiRef};
use consensus_common::SyncOracle;
use inherents::{InherentData, InherentDataProviders};
use client::ChainHead;
use codec::{Encode, Decode};
/// A worker that should be invoked at every new slot. /// A worker that should be invoked at every new slot.
pub trait SlotWorker<B: Block> { pub trait SlotWorker<B: Block> {
/// The type of the future that will be returned when a new slot is /// The type of the future that will be returned when a new slot is
/// triggered. /// triggered.
type OnSlot: IntoFuture<Item=(), Error=consensus_common::Error>; type OnSlot: IntoFuture<Item = (), Error = consensus_common::Error>;
/// Called when the proposer starts. /// Called when the proposer starts.
fn on_start( fn on_start(&self, slot_duration: u64) -> Result<(), consensus_common::Error>;
&self,
slot_duration: u64
) -> Result<(), consensus_common::Error>;
/// Called when a new slot is triggered. /// Called when a new slot is triggered.
fn on_slot( fn on_slot(&self, chain_head: B::Header, slot_info: SlotInfo) -> Self::OnSlot;
&self,
chain_head: B::Header,
slot_info: SlotInfo,
) -> Self::OnSlot;
} }
/// Slot compatible inherent data. /// Slot compatible inherent data.
pub trait SlotCompatible { pub trait SlotCompatible {
/// Extract timestamp and slot from inherent data. /// Extract timestamp and slot from inherent data.
fn extract_timestamp_and_slot(inherent: &InherentData) -> Result<(u64, u64), consensus_common::Error>; fn extract_timestamp_and_slot(
inherent: &InherentData,
) -> Result<(u64, u64), consensus_common::Error>;
} }
/// Convert an inherent error to common error. /// Convert an inherent error to common error.
@@ -79,13 +78,14 @@ pub fn start_slot_worker_thread<B, C, W, SO, SC, T, OnExit>(
sync_oracle: SO, sync_oracle: SO,
on_exit: OnExit, on_exit: OnExit,
inherent_data_providers: InherentDataProviders, inherent_data_providers: InherentDataProviders,
) -> Result<(), consensus_common::Error> where ) -> Result<(), consensus_common::Error>
where
B: Block + 'static, B: Block + 'static,
C: ChainHead<B> + Send + Sync + 'static, C: ChainHead<B> + Send + Sync + 'static,
W: SlotWorker<B> + Send + Sync + 'static, W: SlotWorker<B> + Send + Sync + 'static,
SO: SyncOracle + Send + Clone + 'static, SO: SyncOracle + Send + Clone + 'static,
SC: SlotCompatible + 'static, SC: SlotCompatible + 'static,
OnExit: Future<Item=(), Error=()> + Send + 'static, OnExit: Future<Item = (), Error = ()> + Send + 'static,
T: SlotData + Send + Clone + 'static, T: SlotData + Send + Clone + 'static,
{ {
use tokio::runtime::current_thread::Runtime; use tokio::runtime::current_thread::Runtime;
@@ -96,7 +96,7 @@ pub fn start_slot_worker_thread<B, C, W, SO, SC, T, OnExit>(
let mut runtime = match Runtime::new() { let mut runtime = match Runtime::new() {
Ok(r) => r, Ok(r) => r,
Err(e) => { Err(e) => {
warn!("Unable to start authorship: {:?}", e); warn!(target: "slots", "Unable to start authorship: {:?}", e);
return; return;
} }
}; };
@@ -114,7 +114,7 @@ pub fn start_slot_worker_thread<B, C, W, SO, SC, T, OnExit>(
.send(Ok(())) .send(Ok(()))
.expect("Receive is not dropped before receiving a result; qed"); .expect("Receive is not dropped before receiving a result; qed");
slot_worker_future slot_worker_future
}, }
Err(e) => { Err(e) => {
result_sender result_sender
.send(Err(e)) .send(Err(e))
@@ -126,7 +126,9 @@ pub fn start_slot_worker_thread<B, C, W, SO, SC, T, OnExit>(
let _ = runtime.block_on(slot_worker_future); let _ = runtime.block_on(slot_worker_future);
}); });
result_recv.recv().expect("Slots start thread result sender dropped") result_recv
.recv()
.expect("Slots start thread result sender dropped")
} }
/// Start a new slot worker. /// Start a new slot worker.
@@ -137,13 +139,14 @@ pub fn start_slot_worker<B, C, W, T, SO, SC, OnExit>(
sync_oracle: SO, sync_oracle: SO,
on_exit: OnExit, on_exit: OnExit,
inherent_data_providers: InherentDataProviders, inherent_data_providers: InherentDataProviders,
) -> Result<impl Future<Item=(), Error=()>, consensus_common::Error> where ) -> Result<impl Future<Item = (), Error = ()>, consensus_common::Error>
where
B: Block, B: Block,
C: ChainHead<B>, C: ChainHead<B>,
W: SlotWorker<B>, W: SlotWorker<B>,
SO: SyncOracle + Send + Clone, SO: SyncOracle + Send + Clone,
SC: SlotCompatible, SC: SlotCompatible,
OnExit: Future<Item=(), Error=()>, OnExit: Future<Item = (), Error = ()>,
T: SlotData + Clone, T: SlotData + Clone,
{ {
worker.on_start(slot_duration.slot_duration())?; worker.on_start(slot_duration.slot_duration())?;
@@ -175,14 +178,13 @@ pub fn start_slot_worker<B, C, W, T, SO, SC, OnExit>(
Err(e) => { Err(e) => {
warn!(target: "slots", "Unable to author block in slot {}. \ warn!(target: "slots", "Unable to author block in slot {}. \
no best block header: {:?}", slot_num, e); no best block header: {:?}", slot_num, e);
return Either::B(future::ok(())) return Either::B(future::ok(()));
} }
}; };
Either::A( Either::A(worker.on_slot(chain_head, slot_info).into_future().map_err(
worker.on_slot(chain_head, slot_info).into_future() |e| warn!(target: "slots", "Encountered consensus error: {:?}", e),
.map_err(|e| debug!(target: "slots", "Encountered consensus error: {:?}", e)) ))
)
}) })
}; };
@@ -230,7 +232,9 @@ pub trait SlotData {
} }
impl SlotData for u64 { impl SlotData for u64 {
fn slot_duration(&self) -> u64 { *self } fn slot_duration(&self) -> u64 {
*self
}
const SLOT_KEY: &'static [u8] = b"aura_slot_duration"; const SLOT_KEY: &'static [u8] = b"aura_slot_duration";
} }
@@ -238,7 +242,25 @@ impl SlotData for u64 {
/// A slot duration. Create with `get_or_compute`. /// A slot duration. Create with `get_or_compute`.
// The internal member should stay private here. // The internal member should stay private here.
#[derive(Clone, Copy, Debug, Encode, Decode, Hash, PartialOrd, Ord, PartialEq, Eq)] #[derive(Clone, Copy, Debug, Encode, Decode, Hash, PartialOrd, Ord, PartialEq, Eq)]
pub struct SlotDuration<T: Clone>(T); pub struct SlotDuration<T>(T);
impl<T> Deref for SlotDuration<T> {
type Target = T;
fn deref(&self) -> &T {
&self.0
}
}
impl<T: SlotData + Clone> SlotData for SlotDuration<T> {
/// Get the slot duration in milliseconds.
fn slot_duration(&self) -> u64
where T: SlotData,
{
self.0.slot_duration()
}
const SLOT_KEY: &'static [u8] = T::SLOT_KEY;
}
impl<T: Clone> SlotDuration<T> { impl<T: Clone> SlotDuration<T> {
/// Either fetch the slot duration from disk or compute it from the /// Either fetch the slot duration from disk or compute it from the
@@ -255,23 +277,25 @@ impl<T: Clone> SlotDuration<T> {
match client.get_aux(T::SLOT_KEY)? { match client.get_aux(T::SLOT_KEY)? {
Some(v) => <T as codec::Decode>::decode(&mut &v[..]) Some(v) => <T as codec::Decode>::decode(&mut &v[..])
.map(SlotDuration) .map(SlotDuration)
.ok_or_else(|| ::client::error::Error::Backend( .ok_or_else(|| {
format!("slot duration kept in invalid format"), ::client::error::Error::Backend({
).into()), error!(target: "slots", "slot duration kept in invalid format");
format!("slot duration kept in invalid format")
})
.into()
}),
None => { None => {
use runtime_primitives::traits::Zero; use runtime_primitives::traits::Zero;
let genesis_slot_duration = cb( let genesis_slot_duration =
client.runtime_api(), cb(client.runtime_api(), &BlockId::number(Zero::zero()))?;
&BlockId::number(Zero::zero()))?;
info!( info!(
"Loaded block-time = {:?} seconds from genesis on first-launch", "Loaded block-time = {:?} seconds from genesis on first-launch",
genesis_slot_duration genesis_slot_duration
); );
genesis_slot_duration.using_encoded(|s| { genesis_slot_duration
client.insert_aux(&[(T::SLOT_KEY, &s[..])], &[]) .using_encoded(|s| client.insert_aux(&[(T::SLOT_KEY, &s[..])], &[]))?;
})?;
Ok(SlotDuration(genesis_slot_duration)) Ok(SlotDuration(genesis_slot_duration))
} }
@@ -282,11 +306,4 @@ impl<T: Clone> SlotDuration<T> {
pub fn get(&self) -> T { pub fn get(&self) -> T {
self.0.clone() self.0.clone()
} }
/// Get the slot duration in milliseconds
pub fn slot_duration(&self) -> u64
where T: SlotData
{
self.0.slot_duration()
}
} }
+29 -18
View File
@@ -18,24 +18,34 @@
//! //!
//! This is used instead of `tokio_timer::Interval` because it was unreliable. //! This is used instead of `tokio_timer::Interval` because it was unreliable.
use std::time::{Instant, Duration}; use super::SlotCompatible;
use std::marker::PhantomData; use consensus_common::{Error, ErrorKind};
use tokio::timer::Delay;
use futures::prelude::*; use futures::prelude::*;
use futures::try_ready; use futures::try_ready;
use inherents::{InherentData, InherentDataProviders};
use log::warn; use log::warn;
use inherents::{InherentDataProviders, InherentData}; use std::marker::PhantomData;
use consensus_common::{Error, ErrorKind}; use std::time::{Duration, Instant};
use crate::SlotCompatible; use tokio::timer::Delay;
/// Returns current duration since unix epoch. /// Returns current duration since unix epoch.
pub fn duration_now() -> Option<Duration> { pub fn duration_now() -> Option<Duration> {
use std::time::SystemTime; use std::time::SystemTime;
let now = SystemTime::now(); let now = SystemTime::now();
now.duration_since(SystemTime::UNIX_EPOCH).map_err(|e| { now.duration_since(SystemTime::UNIX_EPOCH)
warn!("Current time {:?} is before unix epoch. Something is wrong: {:?}", now, e); .map_err(|e| {
}).ok() warn!(
"Current time {:?} is before unix epoch. Something is wrong: {:?}",
now, e
);
})
.ok()
}
/// Get the slot for now.
pub fn slot_now(slot_duration: u64) -> Option<u64> {
duration_now().map(|s| s.as_secs() / slot_duration)
} }
/// Returns the duration until the next slot, based on current duration since /// Returns the duration until the next slot, based on current duration since
@@ -113,34 +123,35 @@ impl<SC: SlotCompatible> Stream for Slots<SC> {
}; };
if let Some(ref mut inner_delay) = self.inner_delay { if let Some(ref mut inner_delay) = self.inner_delay {
try_ready!(inner_delay.poll().map_err(|e| Error::from(ErrorKind::FaultyTimer(e)))); try_ready!(inner_delay
.poll()
.map_err(|e| Error::from(ErrorKind::FaultyTimer(e))));
} }
// timeout has fired. // timeout has fired.
let inherent_data = self.inherent_data_providers.create_inherent_data() let inherent_data = self
.inherent_data_providers
.create_inherent_data()
.map_err(crate::inherent_to_common_error)?; .map_err(crate::inherent_to_common_error)?;
let (timestamp, slot_num) = SC::extract_timestamp_and_slot(&inherent_data)?; let (timestamp, slot_num) = SC::extract_timestamp_and_slot(&inherent_data)?;
// reschedule delay for next slot. // reschedule delay for next slot.
let ends_at = Instant::now() + time_until_next(Duration::from_secs(timestamp), slot_duration); let ends_at =
Instant::now() + time_until_next(Duration::from_secs(timestamp), slot_duration);
self.inner_delay = Some(Delay::new(ends_at)); self.inner_delay = Some(Delay::new(ends_at));
// never yield the same slot twice. // never yield the same slot twice.
if slot_num > self.last_slot { if slot_num > self.last_slot {
self.last_slot = slot_num; self.last_slot = slot_num;
Ok( Ok(Async::Ready(Some(SlotInfo {
Async::Ready(
Some(SlotInfo {
number: slot_num, number: slot_num,
duration: self.slot_duration, duration: self.slot_duration,
timestamp, timestamp,
ends_at, ends_at,
inherent_data, inherent_data,
}) })))
)
)
} else { } else {
// re-poll until we get a new slot. // re-poll until we get a new slot.
self.poll() self.poll()
@@ -33,10 +33,10 @@ use fg_primitives::GrandpaApi;
use runtime_primitives::Justification; use runtime_primitives::Justification;
use runtime_primitives::generic::BlockId; use runtime_primitives::generic::BlockId;
use runtime_primitives::traits::{ use runtime_primitives::traits::{
Block as BlockT, DigestFor, DigestItemFor, DigestItem, Block as BlockT, DigestFor,
Header as HeaderT, NumberFor, ProvideRuntimeApi, Header as HeaderT, NumberFor, ProvideRuntimeApi,
}; };
use substrate_primitives::{H256, ed25519, Blake2Hasher}; use substrate_primitives::{H256, Blake2Hasher};
use crate::{Error, CommandOrError, NewAuthoritySet, VoterCommand}; use crate::{Error, CommandOrError, NewAuthoritySet, VoterCommand};
use crate::authorities::{AuthoritySet, SharedAuthoritySet, DelayKind, PendingChange}; use crate::authorities::{AuthoritySet, SharedAuthoritySet, DelayKind, PendingChange};
@@ -44,8 +44,6 @@ use crate::consensus_changes::SharedConsensusChanges;
use crate::environment::{finalize_block, is_descendent_of}; use crate::environment::{finalize_block, is_descendent_of};
use crate::justification::GrandpaJustification; use crate::justification::GrandpaJustification;
use ed25519::Public as AuthorityId;
/// A block-import handler for GRANDPA. /// A block-import handler for GRANDPA.
/// ///
/// This scans each imported block for signals of changing authority set. /// This scans each imported block for signals of changing authority set.
@@ -69,7 +67,6 @@ impl<B, E, Block: BlockT<Hash=H256>, RA, PRA> JustificationImport<Block>
B: Backend<Block, Blake2Hasher> + 'static, B: Backend<Block, Blake2Hasher> + 'static,
E: CallExecutor<Block, Blake2Hasher> + 'static + Clone + Send + Sync, E: CallExecutor<Block, Blake2Hasher> + 'static + Clone + Send + Sync,
DigestFor<Block>: Encode, DigestFor<Block>: Encode,
DigestItemFor<Block>: DigestItem<AuthorityId=AuthorityId>,
RA: Send + Sync, RA: Send + Sync,
PRA: ProvideRuntimeApi, PRA: ProvideRuntimeApi,
PRA::Api: GrandpaApi<Block>, PRA::Api: GrandpaApi<Block>,
@@ -163,7 +160,6 @@ impl<B, E, Block: BlockT<Hash=H256>, RA, PRA> GrandpaBlockImport<B, E, Block, RA
B: Backend<Block, Blake2Hasher> + 'static, B: Backend<Block, Blake2Hasher> + 'static,
E: CallExecutor<Block, Blake2Hasher> + 'static + Clone + Send + Sync, E: CallExecutor<Block, Blake2Hasher> + 'static + Clone + Send + Sync,
DigestFor<Block>: Encode, DigestFor<Block>: Encode,
DigestItemFor<Block>: DigestItem<AuthorityId=AuthorityId>,
RA: Send + Sync, RA: Send + Sync,
PRA: ProvideRuntimeApi, PRA: ProvideRuntimeApi,
PRA::Api: GrandpaApi<Block>, PRA::Api: GrandpaApi<Block>,
@@ -381,7 +377,6 @@ impl<B, E, Block: BlockT<Hash=H256>, RA, PRA> BlockImport<Block>
B: Backend<Block, Blake2Hasher> + 'static, B: Backend<Block, Blake2Hasher> + 'static,
E: CallExecutor<Block, Blake2Hasher> + 'static + Clone + Send + Sync, E: CallExecutor<Block, Blake2Hasher> + 'static + Clone + Send + Sync,
DigestFor<Block>: Encode, DigestFor<Block>: Encode,
DigestItemFor<Block>: DigestItem<AuthorityId=AuthorityId>,
RA: Send + Sync, RA: Send + Sync,
PRA: ProvideRuntimeApi, PRA: ProvideRuntimeApi,
PRA::Api: GrandpaApi<Block>, PRA::Api: GrandpaApi<Block>,
+2 -5
View File
@@ -51,7 +51,7 @@
//! number (this is num(signal) + N). When finalizing a block, we either apply //! number (this is num(signal) + N). When finalizing a block, we either apply
//! or prune any signaled changes based on whether the signaling block is //! or prune any signaled changes based on whether the signaling block is
//! included in the newly-finalized chain. //! included in the newly-finalized chain.
#![forbid(warnings)]
use futures::prelude::*; use futures::prelude::*;
use log::{debug, info, warn}; use log::{debug, info, warn};
use futures::sync::mpsc; use futures::sync::mpsc;
@@ -62,7 +62,7 @@ use client::{
use client::blockchain::HeaderBackend; use client::blockchain::HeaderBackend;
use parity_codec::Encode; use parity_codec::Encode;
use runtime_primitives::traits::{ use runtime_primitives::traits::{
NumberFor, Block as BlockT, DigestFor, ProvideRuntimeApi, DigestItemFor, DigestItem, NumberFor, Block as BlockT, DigestFor, ProvideRuntimeApi,
}; };
use fg_primitives::GrandpaApi; use fg_primitives::GrandpaApi;
use inherents::InherentDataProviders; use inherents::InherentDataProviders;
@@ -362,7 +362,6 @@ fn global_communication<Block: BlockT<Hash=H256>, B, E, N, RA>(
N: Network<Block>, N: Network<Block>,
RA: Send + Sync, RA: Send + Sync,
NumberFor<Block>: BlockNumberOps, NumberFor<Block>: BlockNumberOps,
DigestItemFor<Block>: DigestItem<AuthorityId=AuthorityId>,
{ {
let is_voter = local_key let is_voter = local_key
@@ -463,7 +462,6 @@ pub fn run_grandpa_voter<B, E, Block: BlockT<Hash=H256>, N, RA, X>(
N::In: Send + 'static, N::In: Send + 'static,
NumberFor<Block>: BlockNumberOps, NumberFor<Block>: BlockNumberOps,
DigestFor<Block>: Encode, DigestFor<Block>: Encode,
DigestItemFor<Block>: DigestItem<AuthorityId=AuthorityId>,
RA: Send + Sync + 'static, RA: Send + Sync + 'static,
X: Future<Item=(),Error=()> + Clone + Send + 'static, X: Future<Item=(),Error=()> + Clone + Send + 'static,
{ {
@@ -716,7 +714,6 @@ pub fn run_grandpa<B, E, Block: BlockT<Hash=H256>, N, RA, X>(
N::In: Send + 'static, N::In: Send + 'static,
NumberFor<Block>: BlockNumberOps, NumberFor<Block>: BlockNumberOps,
DigestFor<Block>: Encode, DigestFor<Block>: Encode,
DigestItemFor<Block>: DigestItem<AuthorityId=AuthorityId>,
RA: Send + Sync + 'static, RA: Send + Sync + 'static,
X: Future<Item=(),Error=()> + Clone + Send + 'static, X: Future<Item=(),Error=()> + Clone + Send + 'static,
{ {
@@ -25,9 +25,8 @@ use grandpa::{
use log::{debug, info, warn}; use log::{debug, info, warn};
use client::{CallExecutor, Client, backend::Backend}; use client::{CallExecutor, Client, backend::Backend};
use ed25519::Public as AuthorityId; use runtime_primitives::traits::{NumberFor, Block as BlockT};
use runtime_primitives::traits::{NumberFor, Block as BlockT, DigestItemFor, DigestItem}; use substrate_primitives::{ed25519::Public as AuthorityId, H256, Blake2Hasher};
use substrate_primitives::{ed25519, H256, Blake2Hasher};
use crate::{ use crate::{
AuthoritySignature, global_communication, CommandOrError, Config, environment, AuthoritySignature, global_communication, CommandOrError, Config, environment,
@@ -155,7 +154,6 @@ pub fn run_grandpa_observer<B, E, Block: BlockT<Hash=H256>, N, RA>(
N: Network<Block> + Send + Sync + 'static, N: Network<Block> + Send + Sync + 'static,
N::In: Send + 'static, N::In: Send + 'static,
NumberFor<Block>: BlockNumberOps, NumberFor<Block>: BlockNumberOps,
DigestItemFor<Block>: DigestItem<AuthorityId=AuthorityId>,
RA: Send + Sync + 'static, RA: Send + Sync + 'static,
{ {
let LinkHalf { let LinkHalf {
+6 -6
View File
@@ -23,7 +23,7 @@ use network::config::{ProtocolConfig, Roles};
use network::consensus_gossip as network_gossip; use network::consensus_gossip as network_gossip;
use parking_lot::Mutex; use parking_lot::Mutex;
use tokio::runtime::current_thread; use tokio::runtime::current_thread;
use keyring::AuthorityKeyring; use keyring::ed25519::{Keyring as AuthorityKeyring};
use client::{ use client::{
BlockchainEvents, error::Result, BlockchainEvents, error::Result,
blockchain::Backend as BlockchainBackend, blockchain::Backend as BlockchainBackend,
@@ -36,7 +36,7 @@ use std::collections::{HashMap, HashSet};
use std::result; use std::result;
use runtime_primitives::traits::{ApiRef, ProvideRuntimeApi, Header as HeaderT}; use runtime_primitives::traits::{ApiRef, ProvideRuntimeApi, Header as HeaderT};
use runtime_primitives::generic::BlockId; use runtime_primitives::generic::BlockId;
use substrate_primitives::{NativeOrEncoded, ExecutionContext}; use substrate_primitives::{NativeOrEncoded, ExecutionContext, ed25519::Public as AuthorityId};
use authorities::AuthoritySet; use authorities::AuthoritySet;
use communication::GRANDPA_ENGINE_ID; use communication::GRANDPA_ENGINE_ID;
@@ -290,7 +290,7 @@ impl Core<Block> for RuntimeApi {
_: ExecutionContext, _: ExecutionContext,
_: Option<()>, _: Option<()>,
_: Vec<u8>, _: Vec<u8>,
) -> Result<NativeOrEncoded<Vec<AuthorityId>>> { ) -> Result<NativeOrEncoded<Vec<substrate_primitives::sr25519::Public>>> {
unimplemented!("Not required for testing!") unimplemented!("Not required for testing!")
} }
} }
@@ -323,7 +323,7 @@ impl GrandpaApi<Block> for RuntimeApi {
_: ExecutionContext, _: ExecutionContext,
_: Option<()>, _: Option<()>,
_: Vec<u8>, _: Vec<u8>,
) -> Result<NativeOrEncoded<Vec<(AuthorityId, u64)>>> { ) -> Result<NativeOrEncoded<Vec<(substrate_primitives::ed25519::Public, u64)>>> {
if at == &BlockId::Number(0) { if at == &BlockId::Number(0) {
Ok(self.inner.genesis_authorities.clone()).map(NativeOrEncoded::Native) Ok(self.inner.genesis_authorities.clone()).map(NativeOrEncoded::Native)
} else { } else {
@@ -370,7 +370,7 @@ impl GrandpaApi<Block> for RuntimeApi {
const TEST_GOSSIP_DURATION: Duration = Duration::from_millis(500); const TEST_GOSSIP_DURATION: Duration = Duration::from_millis(500);
const TEST_ROUTING_INTERVAL: Duration = Duration::from_millis(50); const TEST_ROUTING_INTERVAL: Duration = Duration::from_millis(50);
fn make_ids(keys: &[AuthorityKeyring]) -> Vec<(AuthorityId, u64)> { fn make_ids(keys: &[AuthorityKeyring]) -> Vec<(substrate_primitives::ed25519::Public, u64)> {
keys.iter() keys.iter()
.map(|key| AuthorityId(key.to_raw_public())) .map(|key| AuthorityId(key.to_raw_public()))
.map(|id| (id, 1)) .map(|id| (id, 1))
@@ -734,7 +734,7 @@ fn justification_is_emitted_when_consensus_data_changes() {
let mut net = GrandpaTestNet::new(TestApi::new(make_ids(peers)), 3); let mut net = GrandpaTestNet::new(TestApi::new(make_ids(peers)), 3);
// import block#1 WITH consensus data change // import block#1 WITH consensus data change
let new_authorities = vec![AuthorityId::from_raw([42; 32])]; let new_authorities = vec![substrate_primitives::sr25519::Public::from_raw([42; 32])];
net.peer(0).push_authorities_change_block(new_authorities); net.peer(0).push_authorities_change_block(new_authorities);
net.sync(); net.sync();
let net = Arc::new(Mutex::new(net)); let net = Arc::new(Mutex::new(net));
+3 -1
View File
@@ -114,7 +114,9 @@ impl InherentData {
match self.data.get(identifier) { match self.data.get(identifier) {
Some(inherent) => Some(inherent) =>
I::decode(&mut &inherent[..]) I::decode(&mut &inherent[..])
.ok_or_else(|| "Could not decode requested inherent type!".into()) .ok_or_else(|| {
"Could not decode requested inherent type!".into()
})
.map(Some), .map(Some),
None => Ok(None) None => Ok(None)
} }
+1 -1
View File
@@ -40,4 +40,4 @@ consensus = { package = "substrate-consensus-common", path = "../../core/consens
[features] [features]
default = [] default = []
test-helpers = ["keyring", "test_client"] test-helpers = ["keyring", "test_client", "consensus/test-helpers"]
+10 -1
View File
@@ -435,7 +435,10 @@ impl<B: BlockT, S: NetworkSpecialization<B>, H: ExHashT> Protocol<B, S, H> {
return false; return false;
}, },
#[cfg(any(test, feature = "test-helpers"))] #[cfg(any(test, feature = "test-helpers"))]
ProtocolMsg::Synchronize => self.network_chan.send(NetworkMsg::Synchronized), ProtocolMsg::Synchronize => {
trace!(target: "sync", "handle_client_msg: received Synchronize msg");
self.network_chan.send(NetworkMsg::Synchronized)
}
} }
true true
} }
@@ -755,6 +758,11 @@ impl<B: BlockT, S: NetworkSpecialization<B>, H: ExHashT> Protocol<B, S, H> {
"Peer is on different chain (our genesis: {} theirs: {})", "Peer is on different chain (our genesis: {} theirs: {})",
self.genesis_hash, status.genesis_hash self.genesis_hash, status.genesis_hash
); );
trace!(
target: "protocol",
"Peer is on different chain (our genesis: {} theirs: {})",
self.genesis_hash, status.genesis_hash
);
self.network_chan.send(NetworkMsg::ReportPeer( self.network_chan.send(NetworkMsg::ReportPeer(
who, who,
Severity::Bad(reason), Severity::Bad(reason),
@@ -763,6 +771,7 @@ impl<B: BlockT, S: NetworkSpecialization<B>, H: ExHashT> Protocol<B, S, H> {
} }
if status.version < MIN_VERSION && CURRENT_VERSION < status.min_supported_version { if status.version < MIN_VERSION && CURRENT_VERSION < status.min_supported_version {
let reason = format!("Peer using unsupported protocol version {}", status.version); let reason = format!("Peer using unsupported protocol version {}", status.version);
trace!(target: "protocol", "Peer {:?} using unsupported protocol version {}", who, status.version);
self.network_chan.send(NetworkMsg::ReportPeer( self.network_chan.send(NetworkMsg::ReportPeer(
who, who,
Severity::Bad(reason), Severity::Bad(reason),
+2 -1
View File
@@ -848,8 +848,9 @@ impl<B: BlockT> ChainSync<B> {
/// Handle new block announcement. /// Handle new block announcement.
pub(crate) fn on_block_announce(&mut self, protocol: &mut Context<B>, who: PeerId, hash: B::Hash, header: &B::Header) { pub(crate) fn on_block_announce(&mut self, protocol: &mut Context<B>, who: PeerId, hash: B::Hash, header: &B::Header) {
let number = *header.number(); let number = *header.number();
debug!(target: "sync", "Received block announcement with number {:?}", number);
if number <= As::sa(0) { if number <= As::sa(0) {
trace!(target: "sync", "Ignored invalid block announcement from {}: {}", who, hash); warn!(target: "sync", "Ignored invalid block announcement from {}: {}", who, hash);
return; return;
} }
let parent_status = block_status(&*protocol.client(), &self.queue_blocks, header.parent_hash().clone()).ok() let parent_status = block_status(&*protocol.client(), &self.queue_blocks, header.parent_hash().clone()).ok()
+28 -5
View File
@@ -40,7 +40,7 @@ use futures::sync::{mpsc, oneshot};
use crate::message::Message; use crate::message::Message;
use network_libp2p::PeerId; use network_libp2p::PeerId;
use parking_lot::{Mutex, RwLock}; use parking_lot::{Mutex, RwLock};
use primitives::{H256, ed25519::Public as AuthorityId}; use primitives::{H256, sr25519::Public as AuthorityId};
use crate::protocol::{ConnectedPeer, Context, FromNetworkMsg, Protocol, ProtocolMsg}; use crate::protocol::{ConnectedPeer, Context, FromNetworkMsg, Protocol, ProtocolMsg};
use runtime_primitives::generic::BlockId; use runtime_primitives::generic::BlockId;
use runtime_primitives::traits::{AuthorityIdFor, Block as BlockT, Digest, DigestItem, Header, NumberFor}; use runtime_primitives::traits::{AuthorityIdFor, Block as BlockT, Digest, DigestItem, Header, NumberFor};
@@ -48,6 +48,7 @@ use runtime_primitives::{Justification, ConsensusEngineId};
use crate::service::{network_channel, NetworkChan, NetworkLink, NetworkMsg, NetworkPort, TransactionPool}; use crate::service::{network_channel, NetworkChan, NetworkLink, NetworkMsg, NetworkPort, TransactionPool};
use crate::specialization::NetworkSpecialization; use crate::specialization::NetworkSpecialization;
use test_client::{self, AccountKeyring}; use test_client::{self, AccountKeyring};
use log::debug;
pub use test_client::runtime::{Block, Extrinsic, Hash, Transfer}; pub use test_client::runtime::{Block, Extrinsic, Hash, Transfer};
pub use test_client::TestClient; pub use test_client::TestClient;
@@ -117,17 +118,20 @@ pub type PeersClient = client::Client<test_client::Backend, test_client::Executo
/// A Link that can wait for a block to have been imported. /// A Link that can wait for a block to have been imported.
pub struct TestLink<S: NetworkSpecialization<Block>> { pub struct TestLink<S: NetworkSpecialization<Block>> {
link: NetworkLink<Block, S>, link: NetworkLink<Block, S>,
#[cfg(any(test, feature = "test-helpers"))]
network_to_protocol_sender: Sender<FromNetworkMsg<Block>>, network_to_protocol_sender: Sender<FromNetworkMsg<Block>>,
} }
impl<S: NetworkSpecialization<Block>> TestLink<S> { impl<S: NetworkSpecialization<Block>> TestLink<S> {
fn new( fn new(
protocol_sender: Sender<ProtocolMsg<Block, S>>, protocol_sender: Sender<ProtocolMsg<Block, S>>,
network_to_protocol_sender: Sender<FromNetworkMsg<Block>>, _network_to_protocol_sender: Sender<FromNetworkMsg<Block>>,
network_sender: NetworkChan<Block> network_sender: NetworkChan<Block>
) -> TestLink<S> { ) -> TestLink<S> {
TestLink { TestLink {
network_to_protocol_sender, #[cfg(any(test, feature = "test-helpers"))]
network_to_protocol_sender: _network_to_protocol_sender,
link: NetworkLink { link: NetworkLink {
protocol_sender, protocol_sender,
network_sender, network_sender,
@@ -165,8 +169,14 @@ impl<S: NetworkSpecialization<Block>> Link<Block> for TestLink<S> {
self.link.restart(); self.link.restart();
} }
/// Send synchronization request to the block import channel.
///
/// The caller should wait for the `Link::synchronized` call to ensure that it has synchronized
/// with `ImportQueue`.
#[cfg(any(test, feature = "test-helpers"))]
fn synchronized(&self) { fn synchronized(&self) {
let _ = self.network_to_protocol_sender.send(FromNetworkMsg::Synchronize); trace!(target: "test_network", "Synchronizing");
drop(self.network_to_protocol_sender.send(FromNetworkMsg::Synchronize))
} }
} }
@@ -225,12 +235,14 @@ impl<S: NetworkSpecialization<Block>> ProtocolChannel<S> {
/// Wait until synchronization response is generated by the protocol. /// Wait until synchronization response is generated by the protocol.
pub fn wait_sync(&self) -> Result<(), RecvError> { pub fn wait_sync(&self) -> Result<(), RecvError> {
trace!(target: "test_network", "Waiting for sync");
loop { loop {
match self.protocol_to_network_receiver.receiver().recv() { match self.protocol_to_network_receiver.receiver().recv() {
Ok(NetworkMsg::Synchronized) => return Ok(()), Ok(NetworkMsg::Synchronized) => return Ok(()),
Err(error) => return Err(error), Err(error) => return Err(error),
Ok(msg) => self.buffered_messages.lock().push_back(msg), Ok(msg) => self.buffered_messages.lock().push_back(msg),
} }
trace!(target: "test_network", "Retrying sync");
} }
} }
@@ -370,8 +382,11 @@ impl<D, S: NetworkSpecialization<Block>> Peer<D, S> {
} }
/// Synchronize with import queue. /// Synchronize with import queue.
#[cfg(any(test, feature = "test-helpers"))]
fn import_queue_sync(&self) { fn import_queue_sync(&self) {
trace!(target: "test_network", "syncing this queue");
self.import_queue.synchronize(); self.import_queue.synchronize();
trace!(target: "test_network", "wating for sync to finish");
let _ = self.net_proto_channel.wait_sync(); let _ = self.net_proto_channel.wait_sync();
} }
@@ -491,6 +506,7 @@ impl<D, S: NetworkSpecialization<Block>> Peer<D, S> {
let block = edit_block(builder); let block = edit_block(builder);
let hash = block.header.hash(); let hash = block.header.hash();
trace!( trace!(
target: "test_network",
"Generating {}, (#{}, parent={})", "Generating {}, (#{}, parent={})",
hash, hash,
block.header.number, block.header.number,
@@ -610,10 +626,12 @@ pub trait TestNetFactory: Sized {
/// Create new test network with this many peers. /// Create new test network with this many peers.
fn new(n: usize) -> Self { fn new(n: usize) -> Self {
trace!(target: "test_network", "Creating test network");
let config = Self::default_config(); let config = Self::default_config();
let mut net = Self::from_config(&config); let mut net = Self::from_config(&config);
for _ in 0..n { for i in 0..n {
trace!(target: "test_network", "Adding peer {}", i);
net.add_peer(&config); net.add_peer(&config);
} }
net net
@@ -681,6 +699,7 @@ pub trait TestNetFactory: Sized {
} }
loop { loop {
debug!(target: "test_network", "loop iteration");
// we only deliver Status messages during start // we only deliver Status messages during start
let need_continue = self.route_single(true, None, &|msg| match *msg { let need_continue = self.route_single(true, None, &|msg| match *msg {
NetworkMsg::Outgoing(_, crate::message::generic::Message::Status(_)) => true, NetworkMsg::Outgoing(_, crate::message::generic::Message::Status(_)) => true,
@@ -706,6 +725,7 @@ pub trait TestNetFactory: Sized {
let mut to_disconnect = HashSet::new(); let mut to_disconnect = HashSet::new();
let peers = self.peers(); let peers = self.peers();
for peer in peers { for peer in peers {
debug!(target: "test_network", "checking peer");
if let Some(message) = peer.pending_message(message_filter) { if let Some(message) = peer.pending_message(message_filter) {
match message { match message {
NetworkMsg::Outgoing(recipient_id, packet) => { NetworkMsg::Outgoing(recipient_id, packet) => {
@@ -744,10 +764,13 @@ pub trait TestNetFactory: Sized {
} }
} }
} }
debug!(target: "test_network", "syncing queues");
// make sure that the protocol(s) has processed all messages that have been queued // make sure that the protocol(s) has processed all messages that have been queued
self.peers().iter().for_each(|peer| peer.import_queue_sync()); self.peers().iter().for_each(|peer| peer.import_queue_sync());
debug!(target: "test_network", "queues synced");
had_messages had_messages
} }
+1 -1
View File
@@ -288,7 +288,7 @@ impl<T: AsMut<[u8]> + AsRef<[u8]> + Default + Derive> Ss58Codec for T {
/// ///
/// For now it just specifies how to create a key from a phrase and derivation path. /// For now it just specifies how to create a key from a phrase and derivation path.
#[cfg(feature = "std")] #[cfg(feature = "std")]
pub trait Pair: Sized { pub trait Pair: Sized + 'static {
/// TThe type which is used to encode a public key. /// TThe type which is used to encode a public key.
type Public; type Public;
+6 -1
View File
@@ -18,8 +18,12 @@ use error_chain::*;
use client; use client;
use crate::rpc; use crate::rpc;
use crate::errors; use crate::errors;
pub use internal_errors::*;
error_chain! { #[allow(deprecated)]
mod internal_errors {
use super::*;
error_chain! {
foreign_links { foreign_links {
Client(client::error::Error) #[doc = "Client error"]; Client(client::error::Error) #[doc = "Client error"];
} }
@@ -30,6 +34,7 @@ error_chain! {
display("Method Not Implemented"), display("Method Not Implemented"),
} }
} }
}
} }
impl From<Error> for rpc::Error { impl From<Error> for rpc::Error {
+2 -1
View File
@@ -221,7 +221,7 @@ fn should_return_runtime_version() {
assert_eq!( assert_eq!(
::serde_json::to_string(&api.runtime_version(None.into()).unwrap()).unwrap(), ::serde_json::to_string(&api.runtime_version(None.into()).unwrap()).unwrap(),
r#"{"specName":"test","implName":"parity-test","authoringVersion":1,"specVersion":1,"implVersion":1,"apis":[["0xdf6acb689907609b",2],["0x37e397fc7c91f5e4",1],["0xd2bc9897eed08f15",1],["0x40fe3ad401f8959a",3],["0xc6e9a76309f39b09",1],["0xdd718d5cc53262d4",1],["0xf78b278be53f454c",1],["0x7801759919ee83e5",1]]}"# r#"{"specName":"test","implName":"parity-test","authoringVersion":1,"specVersion":1,"implVersion":1,"apis":[["0xdf6acb689907609b",2],["0x37e397fc7c91f5e4",1],["0xd2bc9897eed08f15",1],["0x40fe3ad401f8959a",3],["0xc6e9a76309f39b09",1],["0xdd718d5cc53262d4",1],["0xcbca25e39f142387",1],["0xf78b278be53f454c",1],["0x7801759919ee83e5",1]]}"#
); );
} }
@@ -246,3 +246,4 @@ fn should_notify_on_runtime_version_initially() {
// no more notifications on this channel // no more notifications on this channel
assert_eq!(core.block_on(next.into_future()).unwrap().0, None); assert_eq!(core.block_on(next.into_future()).unwrap().0, None);
} }
+1 -1
View File
@@ -11,7 +11,7 @@ rustc_version = "0.2"
[dependencies] [dependencies]
rstd = { package = "sr-std", path = "../sr-std", default-features = false } rstd = { package = "sr-std", path = "../sr-std", default-features = false }
primitives = { package = "substrate-primitives", path = "../primitives", default-features = false } primitives = { package = "substrate-primitives", path = "../primitives", default-features = false }
codec = { package="parity-codec", version = "3.3", default-features = false } codec = { package = "parity-codec", version = "3.5.1", default-features = false }
hash-db = { version = "0.12", default-features = false } hash-db = { version = "0.12", default-features = false }
libsecp256k1 = { version = "0.2.1", optional = true } libsecp256k1 = { version = "0.2.1", optional = true }
tiny-keccak = { version = "1.4.2", optional = true } tiny-keccak = { version = "1.4.2", optional = true }
+1 -1
View File
@@ -23,7 +23,7 @@ use crate::traits::{self, Checkable, Applyable, BlakeTwo256, Convert};
use crate::generic::DigestItem as GenDigestItem; use crate::generic::DigestItem as GenDigestItem;
pub use substrate_primitives::H256; pub use substrate_primitives::H256;
use substrate_primitives::U256; use substrate_primitives::U256;
use substrate_primitives::ed25519::{Public as AuthorityId, Signature as AuthoritySignature}; use substrate_primitives::sr25519::{Public as AuthorityId, Signature as AuthoritySignature};
/// Authority Id /// Authority Id
#[derive(Default, PartialEq, Eq, Clone, Encode, Decode, Debug)] #[derive(Default, PartialEq, Eq, Clone, Encode, Decode, Debug)]
+1 -1
View File
@@ -6,7 +6,7 @@ build = "build.rs"
edition = "2018" edition = "2018"
[build-dependencies] [build-dependencies]
rustc_version = "0.2" rustc_version = "0.2.3"
[features] [features]
default = ["std"] default = ["std"]
+1 -1
View File
@@ -29,7 +29,7 @@ pub use client::{ExecutionStrategies, blockchain, backend, self};
pub use executor::{NativeExecutor, self}; pub use executor::{NativeExecutor, self};
pub use runtime; pub use runtime;
pub use consensus; pub use consensus;
pub use keyring::{AuthorityKeyring, AccountKeyring}; pub use keyring::{sr25519::Keyring as AuthorityKeyring, AccountKeyring};
use std::{sync::Arc, collections::HashMap}; use std::{sync::Arc, collections::HashMap};
use futures::future::FutureResult; use futures::future::FutureResult;
+2
View File
@@ -13,6 +13,7 @@ substrate-client = { path = "../client", default-features = false }
primitives = { package = "substrate-primitives", path = "../primitives", default-features = false } primitives = { package = "substrate-primitives", path = "../primitives", default-features = false }
inherents = { package = "substrate-inherents", path = "../inherents", default-features = false } inherents = { package = "substrate-inherents", path = "../inherents", default-features = false }
consensus_aura = { package = "substrate-consensus-aura-primitives", path = "../consensus/aura/primitives", default-features = false } consensus_aura = { package = "substrate-consensus-aura-primitives", path = "../consensus/aura/primitives", default-features = false }
consensus_babe = { package = "substrate-consensus-babe-primitives", path = "../consensus/babe/primitives", default-features = false }
rstd = { package = "sr-std", path = "../sr-std", default-features = false } rstd = { package = "sr-std", path = "../sr-std", default-features = false }
runtime_io = { package = "sr-io", path = "../sr-io", default-features = false } runtime_io = { package = "sr-io", path = "../sr-io", default-features = false }
runtime_primitives = { package = "sr-primitives", path = "../sr-primitives", default-features = false } runtime_primitives = { package = "sr-primitives", path = "../sr-primitives", default-features = false }
@@ -49,6 +50,7 @@ std = [
"runtime_primitives/std", "runtime_primitives/std",
"runtime_version/std", "runtime_version/std",
"consensus_aura/std", "consensus_aura/std",
"consensus_babe/std",
"primitives/std", "primitives/std",
"substrate-trie/std", "substrate-trie/std",
"trie-db/std", "trie-db/std",
@@ -22,7 +22,7 @@ use super::AccountId;
use parity_codec::{Encode, KeyedVec, Joiner}; use parity_codec::{Encode, KeyedVec, Joiner};
use primitives::{ChangesTrieConfiguration, map, storage::well_known_keys}; use primitives::{ChangesTrieConfiguration, map, storage::well_known_keys};
use runtime_primitives::traits::Block; use runtime_primitives::traits::Block;
use primitives::ed25519::Public as AuthorityId; use primitives::sr25519::Public as AuthorityId;
/// Configuration of a general Substrate test genesis block. /// Configuration of a general Substrate test genesis block.
pub struct GenesisConfig { pub struct GenesisConfig {
+24 -4
View File
@@ -43,7 +43,7 @@ use runtime_primitives::{
}; };
use runtime_version::RuntimeVersion; use runtime_version::RuntimeVersion;
pub use primitives::hash::H256; pub use primitives::hash::H256;
use primitives::{ed25519, sr25519, OpaqueMetadata}; use primitives::{sr25519, OpaqueMetadata};
#[cfg(any(feature = "std", test))] #[cfg(any(feature = "std", test))]
use runtime_version::NativeVersion; use runtime_version::NativeVersion;
use inherents::{CheckInherentsResult, InherentData}; use inherents::{CheckInherentsResult, InherentData};
@@ -142,7 +142,7 @@ impl Extrinsic {
} }
/// The signature type used by authorities. /// The signature type used by authorities.
pub type AuthoritySignature = ed25519::Signature; pub type AuthoritySignature = sr25519::Signature;
/// The identity type used by authorities. /// The identity type used by authorities.
pub type AuthorityId = <AuthoritySignature as Verify>::Signer; pub type AuthorityId = <AuthoritySignature as Verify>::Signer;
/// The signature type used by accounts/transactions. /// The signature type used by accounts/transactions.
@@ -448,6 +448,16 @@ cfg_if! {
fn slot_duration() -> u64 { 1 } fn slot_duration() -> u64 { 1 }
} }
impl consensus_babe::BabeApi<Block> for Runtime {
fn startup_data() -> consensus_babe::BabeConfiguration {
consensus_babe::BabeConfiguration {
slot_duration: 1,
expected_block_time: 1,
threshold: std::u64::MAX,
}
}
}
impl offchain_primitives::OffchainWorkerApi<Block> for Runtime { impl offchain_primitives::OffchainWorkerApi<Block> for Runtime {
fn offchain_worker(block: u64) { fn offchain_worker(block: u64) {
let ex = Extrinsic::IncludeData(block.encode()); let ex = Extrinsic::IncludeData(block.encode());
@@ -457,7 +467,7 @@ cfg_if! {
impl consensus_authorities::AuthoritiesApi<Block> for Runtime { impl consensus_authorities::AuthoritiesApi<Block> for Runtime {
fn authorities() -> Vec<AuthorityIdFor<Block>> { fn authorities() -> Vec<AuthorityIdFor<Block>> {
crate::system::authorities() system::authorities()
} }
} }
} }
@@ -580,6 +590,16 @@ cfg_if! {
fn slot_duration() -> u64 { 1 } fn slot_duration() -> u64 { 1 }
} }
impl consensus_babe::BabeApi<Block> for Runtime {
fn startup_data() -> consensus_babe::BabeConfiguration {
consensus_babe::BabeConfiguration {
slot_duration: 1,
expected_block_time: 1,
threshold: core::u64::MAX,
}
}
}
impl offchain_primitives::OffchainWorkerApi<Block> for Runtime { impl offchain_primitives::OffchainWorkerApi<Block> for Runtime {
fn offchain_worker(block: u64) { fn offchain_worker(block: u64) {
let ex = Extrinsic::IncludeData(block.encode()); let ex = Extrinsic::IncludeData(block.encode());
@@ -589,7 +609,7 @@ cfg_if! {
impl consensus_authorities::AuthoritiesApi<Block> for Runtime { impl consensus_authorities::AuthoritiesApi<Block> for Runtime {
fn authorities() -> Vec<AuthorityIdFor<Block>> { fn authorities() -> Vec<AuthorityIdFor<Block>> {
crate::system::authorities() system::authorities()
} }
} }
} }
+1 -1
View File
@@ -27,7 +27,7 @@ use runtime_primitives::{ApplyError, ApplyOutcome, ApplyResult, transaction_vali
use parity_codec::{KeyedVec, Encode}; use parity_codec::{KeyedVec, Encode};
use super::{AccountId, BlockNumber, Extrinsic, Transfer, H256 as Hash, Block, Header, Digest}; use super::{AccountId, BlockNumber, Extrinsic, Transfer, H256 as Hash, Block, Header, Digest};
use primitives::{Blake2Hasher, storage::well_known_keys}; use primitives::{Blake2Hasher, storage::well_known_keys};
use primitives::ed25519::Public as AuthorityId; use primitives::sr25519::Public as AuthorityId;
const NONCE_OF: &[u8] = b"nonce:"; const NONCE_OF: &[u8] = b"nonce:";
const BALANCE_OF: &[u8] = b"balance:"; const BALANCE_OF: &[u8] = b"balance:";
+28
View File
@@ -2433,6 +2433,16 @@ dependencies = [
"substrate-primitives 1.0.0", "substrate-primitives 1.0.0",
] ]
[[package]]
name = "substrate-consensus-babe-primitives"
version = "1.0.0"
dependencies = [
"parity-codec 3.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
"sr-primitives 1.0.0",
"substrate-client 1.0.0",
"substrate-consensus-slots 1.1.0",
]
[[package]] [[package]]
name = "substrate-consensus-common" name = "substrate-consensus-common"
version = "1.0.0" version = "1.0.0"
@@ -2450,6 +2460,23 @@ dependencies = [
"tokio 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", "tokio 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
[[package]]
name = "substrate-consensus-slots"
version = "1.1.0"
dependencies = [
"error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)",
"futures 0.1.25 (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 1.0.0",
"substrate-client 1.0.0",
"substrate-consensus-common 1.0.0",
"substrate-inherents 1.0.0",
"substrate-primitives 1.0.0",
"tokio 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]] [[package]]
name = "substrate-executor" name = "substrate-executor"
version = "1.0.0" version = "1.0.0"
@@ -2596,6 +2623,7 @@ dependencies = [
"substrate-client 1.0.0", "substrate-client 1.0.0",
"substrate-consensus-aura-primitives 1.0.0", "substrate-consensus-aura-primitives 1.0.0",
"substrate-consensus-authorities 1.0.0", "substrate-consensus-authorities 1.0.0",
"substrate-consensus-babe-primitives 1.0.0",
"substrate-inherents 1.0.0", "substrate-inherents 1.0.0",
"substrate-keyring 1.0.0", "substrate-keyring 1.0.0",
"substrate-offchain-primitives 0.1.0", "substrate-offchain-primitives 0.1.0",
+1 -1
View File
@@ -9,5 +9,5 @@ fi
CARGO_INCREMENTAL=0 RUSTFLAGS="-C link-arg=--export-table" $CARGO_CMD build --target=wasm32-unknown-unknown --release CARGO_INCREMENTAL=0 RUSTFLAGS="-C link-arg=--export-table" $CARGO_CMD build --target=wasm32-unknown-unknown --release
for i in substrate_test_runtime for i in substrate_test_runtime
do do
wasm-gc target/wasm32-unknown-unknown/release/$i.wasm target/wasm32-unknown-unknown/release/$i.compact.wasm wasm-gc "target/wasm32-unknown-unknown/release/$i.wasm" "target/wasm32-unknown-unknown/release/$i.compact.wasm"
done done
@@ -14,7 +14,7 @@ substrate-primitives = { path = "../../primitives" }
sr-primitives = { path = "../../sr-primitives" } sr-primitives = { path = "../../sr-primitives" }
[dev-dependencies] [dev-dependencies]
assert_matches = "1.1" assert_matches = "1.3.0"
env_logger = "0.6" env_logger = "0.6.1"
parity-codec = "3.3" parity-codec = "3.5.1"
test_runtime = { package = "substrate-test-runtime", path = "../../test-runtime" } test_runtime = { package = "substrate-test-runtime", path = "../../test-runtime" }
+2 -2
View File
@@ -58,8 +58,8 @@ pub const VERSION: RuntimeVersion = RuntimeVersion {
spec_name: create_runtime_str!("node"), spec_name: create_runtime_str!("node"),
impl_name: create_runtime_str!("substrate-node"), impl_name: create_runtime_str!("substrate-node"),
authoring_version: 10, authoring_version: 10,
spec_version: 67, spec_version: 69,
impl_version: 68, impl_version: 70,
apis: RUNTIME_API_VERSIONS, apis: RUNTIME_API_VERSIONS,
}; };
+2 -2
View File
@@ -5,14 +5,14 @@
set -e set -e
PROJECT_ROOT=`git rev-parse --show-toplevel` PROJECT_ROOT=`git rev-parse --show-toplevel`
source `dirname "$0"`/common.sh source "`dirname \"$0\"`/common.sh"
export CARGO_INCREMENTAL=0 export CARGO_INCREMENTAL=0
# Save current directory. # Save current directory.
pushd . pushd .
cd $ROOT cd -- "$ROOT"
for SRC in "${SRCS[@]}" for SRC in "${SRCS[@]}"
do do
+41
View File
@@ -0,0 +1,41 @@
[package]
name = "srml-babe"
version = "0.1.0"
authors = ["Parity Technologies <admin@parity.io>"]
edition = "2018"
[dependencies]
hex-literal = "0.1.4"
parity-codec = { version = "3.5.1", default-features = false, features = ["derive"] }
serde = { version = "1.0.90", optional = true }
inherents = { package = "substrate-inherents", path = "../../core/inherents", default-features = false }
rstd = { package = "sr-std", path = "../../core/sr-std", default-features = false }
primitives = { package = "sr-primitives", path = "../../core/sr-primitives", default-features = false }
srml-support = { path = "../support", default-features = false }
system = { package = "srml-system", path = "../system", default-features = false }
timestamp = { package = "srml-timestamp", path = "../timestamp", default-features = false }
staking = { package = "srml-staking", path = "../staking", default-features = false }
session = { package = "srml-session", path = "../session", default-features = false }
babe-primitives = { package = "substrate-consensus-babe-primitives", path = "../../core/consensus/babe/primitives", default-features = false }
[dev-dependencies]
lazy_static = "1.3.0"
parking_lot = "0.7.1"
substrate-primitives = { path = "../../core/primitives" }
runtime_io = { package = "sr-io", path = "../../core/sr-io" }
consensus = { package = "srml-consensus", path = "../consensus" }
[features]
default = ["std"]
std = [
"serde",
"parity-codec/std",
"rstd/std",
"srml-support/std",
"primitives/std",
"system/std",
"timestamp/std",
"staking/std",
"inherents/std",
"babe-primitives/std",
]
+155
View File
@@ -0,0 +1,155 @@
// 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/>.
//! Consensus extension module for BABE consensus.
#![cfg_attr(not(feature = "std"), no_std)]
#![forbid(unsafe_code, warnings)]
pub use timestamp;
use rstd::{result, prelude::*};
use srml_support::{decl_storage, decl_module};
use primitives::traits::As;
use timestamp::{OnTimestampSet, Trait};
#[cfg(feature = "std")]
use timestamp::TimestampInherentData;
use parity_codec::Decode;
use inherents::{RuntimeString, InherentIdentifier, InherentData, ProvideInherent, MakeFatalError};
#[cfg(feature = "std")]
use inherents::{InherentDataProviders, ProvideInherentData};
/// The BABE inherent identifier.
pub const INHERENT_IDENTIFIER: InherentIdentifier = *b"babeslot";
/// The type of the BABE inherent.
pub type InherentType = u64;
/// Auxiliary trait to extract BABE inherent data.
pub trait BabeInherentData {
/// Get BABE inherent data.
fn babe_inherent_data(&self) -> result::Result<InherentType, RuntimeString>;
/// Replace BABE inherent data.
fn babe_replace_inherent_data(&mut self, new: InherentType);
}
impl BabeInherentData for InherentData {
fn babe_inherent_data(&self) -> result::Result<InherentType, RuntimeString> {
self.get_data(&INHERENT_IDENTIFIER)
.and_then(|r| r.ok_or_else(|| "BABE inherent data not found".into()))
}
fn babe_replace_inherent_data(&mut self, new: InherentType) {
self.replace_data(INHERENT_IDENTIFIER, &new);
}
}
/// Provides the slot duration inherent data for BABE.
#[cfg(feature = "std")]
pub struct InherentDataProvider {
slot_duration: u64,
}
#[cfg(feature = "std")]
impl InherentDataProvider {
pub fn new(slot_duration: u64) -> Self {
Self {
slot_duration
}
}
}
#[cfg(feature = "std")]
impl ProvideInherentData for InherentDataProvider {
fn on_register(
&self,
providers: &InherentDataProviders,
) -> result::Result<(), RuntimeString> {
if !providers.has_provider(&timestamp::INHERENT_IDENTIFIER) {
// Add the timestamp inherent data provider, as we require it.
providers.register_provider(timestamp::InherentDataProvider)
} else {
Ok(())
}
}
fn inherent_identifier(&self) -> &'static inherents::InherentIdentifier {
&INHERENT_IDENTIFIER
}
fn provide_inherent_data(
&self,
inherent_data: &mut InherentData,
) -> result::Result<(), RuntimeString> {
let timestamp = inherent_data.timestamp_inherent_data()?;
let slot_num = timestamp / self.slot_duration;
inherent_data.put_data(INHERENT_IDENTIFIER, &slot_num)
}
fn error_to_string(&self, error: &[u8]) -> Option<String> {
RuntimeString::decode(&mut &error[..]).map(Into::into)
}
}
decl_storage! {
trait Store for Module<T: Trait> as Babe {
// The last timestamp.
LastTimestamp get(last): T::Moment;
}
}
decl_module! {
pub struct Module<T: Trait> for enum Call where origin: T::Origin { }
}
impl<T: Trait> Module<T> {
/// Determine the BABE slot duration based on the Timestamp module configuration.
pub fn slot_duration() -> u64 {
// we double the minimum block-period so each author can always propose within
// the majority of their slot.
<timestamp::Module<T>>::minimum_period().as_().saturating_mul(2)
}
}
impl<T: Trait> OnTimestampSet<T::Moment> for Module<T> {
fn on_timestamp_set(_moment: T::Moment) { }
}
impl<T: Trait> ProvideInherent for Module<T> {
type Call = timestamp::Call<T>;
type Error = MakeFatalError<RuntimeString>;
const INHERENT_IDENTIFIER: InherentIdentifier = INHERENT_IDENTIFIER;
fn create_inherent(_: &InherentData) -> Option<Self::Call> {
None
}
fn check_inherent(call: &Self::Call, data: &InherentData) -> result::Result<(), Self::Error> {
let timestamp = match call {
timestamp::Call::set(ref timestamp) => timestamp.clone(),
_ => return Ok(()),
};
let timestamp_based_slot = timestamp.as_() / Self::slot_duration();
let seal_slot = data.babe_inherent_data()?;
if timestamp_based_slot == seal_slot {
Ok(())
} else {
Err(RuntimeString::from("timestamp set in block doesnt match slot in seal").into())
}
}
}
+1 -1
View File
@@ -142,7 +142,7 @@ use inherents::{
}; };
#[cfg(any(feature = "std", test))] #[cfg(any(feature = "std", test))]
use substrate_primitives::ed25519::Public as AuthorityId; use substrate_primitives::sr25519::Public as AuthorityId;
mod mock; mod mock;
mod tests; mod tests;