mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-05-31 01:41:03 +00:00
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:
Generated
+28
-19
@@ -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",
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -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(),
|
||||||
|
|||||||
@@ -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,31 +29,28 @@ 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")]
|
||||||
impl slots::SlotData for BabeConfiguration {
|
impl slots::SlotData for BabeConfiguration {
|
||||||
/// Return the slot duration in milliseconds for BABE. Currently, only
|
/// 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.
|
||||||
@@ -67,7 +64,7 @@ impl slots::SlotData for BabeConfiguration {
|
|||||||
decl_runtime_apis! {
|
decl_runtime_apis! {
|
||||||
/// API necessary for block authorship with BABE.
|
/// API necessary for block authorship with BABE.
|
||||||
pub trait BabeApi {
|
pub trait BabeApi {
|
||||||
/// Return the configuration for BABE. Currently,
|
/// Return the configuration for BABE. Currently,
|
||||||
/// only the value provided by this type at genesis will be used.
|
/// only the value provided by this type at genesis will be used.
|
||||||
///
|
///
|
||||||
/// Dynamic configuration may be supported in the future.
|
/// Dynamic configuration may be supported in the future.
|
||||||
|
|||||||
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.
|
||||||
|
|||||||
@@ -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())?;
|
||||||
@@ -174,15 +177,14 @@ pub fn start_slot_worker<B, C, W, T, SO, SC, OnExit>(
|
|||||||
Ok(x) => x,
|
Ok(x) => x,
|
||||||
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()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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(
|
number: slot_num,
|
||||||
Some(SlotInfo {
|
duration: self.slot_duration,
|
||||||
number: slot_num,
|
timestamp,
|
||||||
duration: self.slot_duration,
|
ends_at,
|
||||||
timestamp,
|
inherent_data,
|
||||||
ends_at,
|
})))
|
||||||
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>,
|
||||||
|
|||||||
@@ -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 {
|
||||||
|
|||||||
@@ -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));
|
||||||
|
|||||||
@@ -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)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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"]
|
||||||
|
|||||||
@@ -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),
|
||||||
|
|||||||
@@ -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()
|
||||||
|
|||||||
@@ -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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|
||||||
|
|||||||
@@ -18,16 +18,21 @@ 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)]
|
||||||
foreign_links {
|
mod internal_errors {
|
||||||
Client(client::error::Error) #[doc = "Client error"];
|
use super::*;
|
||||||
}
|
error_chain! {
|
||||||
errors {
|
foreign_links {
|
||||||
/// Not implemented yet
|
Client(client::error::Error) #[doc = "Client error"];
|
||||||
Unimplemented {
|
}
|
||||||
description("not yet implemented"),
|
errors {
|
||||||
display("Method Not Implemented"),
|
/// Not implemented yet
|
||||||
|
Unimplemented {
|
||||||
|
description("not yet implemented"),
|
||||||
|
display("Method Not Implemented"),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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 }
|
||||||
|
|||||||
@@ -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)]
|
||||||
|
|||||||
@@ -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"]
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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 {
|
||||||
|
|||||||
@@ -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()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
@@ -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",
|
||||||
|
|||||||
@@ -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" }
|
||||||
|
|||||||
@@ -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,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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",
|
||||||
|
]
|
||||||
@@ -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(×tamp::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 doesn’t match slot in seal").into())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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;
|
||||||
|
|||||||
Reference in New Issue
Block a user