From 3517a80145ebab66f4d6fb35ff4e5dc19f030480 Mon Sep 17 00:00:00 2001 From: Wei Tang Date: Thu, 2 Apr 2020 13:36:59 +0200 Subject: [PATCH 01/24] babe: secondary blocks with VRF --- client/consensus/babe/rpc/src/lib.rs | 5 ++ client/consensus/babe/src/authorship.rs | 45 +++++++++---- client/consensus/babe/src/lib.rs | 21 ++++++- client/consensus/babe/src/verification.rs | 65 ++++++++++++++++--- primitives/consensus/babe/src/digests.rs | 39 +++++++++++- primitives/consensus/babe/src/lib.rs | 77 ++++++++++++++++++++++- 6 files changed, 231 insertions(+), 21 deletions(-) diff --git a/client/consensus/babe/rpc/src/lib.rs b/client/consensus/babe/rpc/src/lib.rs index cb78504b1f788..5efa1ddb2dabd 100644 --- a/client/consensus/babe/rpc/src/lib.rs +++ b/client/consensus/babe/rpc/src/lib.rs @@ -126,6 +126,9 @@ impl BabeApi for BabeRPCHandler PreDigest::Secondary { .. } => { claims.entry(key.public()).or_default().secondary.push(slot_number); } + PreDigest::SecondaryVRF { .. } => { + claims.entry(key.public()).or_default().secondary_vrf.push(slot_number); + }, }; } } @@ -144,6 +147,8 @@ pub struct EpochAuthorship { primary: Vec, /// the array of secondary slots that can be claimed secondary: Vec, + /// The array of secondary VRF slots that can be claimed. + secondary_vrf: Vec, } /// Errors encountered by the RPC diff --git a/client/consensus/babe/src/authorship.rs b/client/consensus/babe/src/authorship.rs index 074e582bff252..98e57bc27aac5 100644 --- a/client/consensus/babe/src/authorship.rs +++ b/client/consensus/babe/src/authorship.rs @@ -21,7 +21,9 @@ use sp_consensus_babe::{ AuthorityId, BabeAuthorityWeight, BABE_ENGINE_ID, BABE_VRF_PREFIX, SlotNumber, AuthorityPair, BabeConfiguration }; -use sp_consensus_babe::digests::{PreDigest, PrimaryPreDigest, SecondaryPreDigest}; +use sp_consensus_babe::digests::{ + PreDigest, PrimaryPreDigest, SecondaryPreDigest, SecondaryVRFPreDigest, +}; use sp_consensus_vrf::schnorrkel::{VRFOutput, VRFProof}; use sp_core::{U256, blake2_256}; use codec::Encode; @@ -105,10 +107,12 @@ pub(super) fn make_transcript( /// to propose. fn claim_secondary_slot( slot_number: SlotNumber, - authorities: &[(AuthorityId, BabeAuthorityWeight)], + epoch: &Epoch, keystore: &KeyStorePtr, - randomness: [u8; 32], + author_secondary_vrf: bool, ) -> Option<(PreDigest, AuthorityPair)> { + let Epoch { authorities, randomness, epoch_index, .. } = epoch; + if authorities.is_empty() { return None; } @@ -116,7 +120,7 @@ fn claim_secondary_slot( let expected_author = super::authorship::secondary_slot_author( slot_number, authorities, - randomness, + *randomness, )?; let keystore = keystore.read(); @@ -128,10 +132,27 @@ fn claim_secondary_slot( }) { if pair.public() == *expected_author { - let pre_digest = PreDigest::Secondary(SecondaryPreDigest { - slot_number, - authority_index: authority_index as u32, - }); + let pre_digest = if author_secondary_vrf { + let transcript = super::authorship::make_transcript( + randomness, + slot_number, + *epoch_index, + ); + + let s = get_keypair(&pair).vrf_sign(transcript); + + PreDigest::SecondaryVRF(SecondaryVRFPreDigest { + slot_number, + vrf_output: VRFOutput(s.0.to_output()), + vrf_proof: VRFProof(s.1), + authority_index: authority_index as u32, + }) + } else { + PreDigest::Secondary(SecondaryPreDigest { + slot_number, + authority_index: authority_index as u32, + }) + }; return Some((pre_digest, pair)); } @@ -152,12 +173,14 @@ pub fn claim_slot( ) -> Option<(PreDigest, AuthorityPair)> { claim_primary_slot(slot_number, epoch, config.c, keystore) .or_else(|| { - if config.secondary_slots { + if config.allowed_slots.is_secondary_slots_allowed() || + config.allowed_slots.is_secondary_vrf_slots_allowed() + { claim_secondary_slot( slot_number, - &epoch.authorities, + &epoch, keystore, - epoch.randomness, + config.allowed_slots.is_secondary_vrf_slots_allowed(), ) } else { None diff --git a/client/consensus/babe/src/lib.rs b/client/consensus/babe/src/lib.rs index 5365aae2aa6cb..29094fc15b84b 100644 --- a/client/consensus/babe/src/lib.rs +++ b/client/consensus/babe/src/lib.rs @@ -255,7 +255,26 @@ impl Config { C: AuxStore + ProvideRuntimeApi, C::Api: BabeApi, { trace!(target: "babe", "Getting slot duration"); - match sc_consensus_slots::SlotDuration::get_or_compute(client, |a, b| a.configuration(b)).map(Self) { + match sc_consensus_slots::SlotDuration::get_or_compute(client, |a, b| { + let has_api_v1 = a.has_api_with::, _>( + &b, |v| v == 1, + )?; + let has_api_v2 = a.has_api_with::, _>( + &b, |v| v == 1, + )?; + + if has_api_v1 { + #[allow(deprecated)] { + Ok(a.configuration_before_version_2(b)?.into()) + } + } else if has_api_v2 { + a.configuration(b) + } else { + Err(sp_blockchain::Error::VersionInvalid( + "Unsupported or invalid BabeApi version".to_string() + )) + } + }).map(Self) { Ok(s) => Ok(s), Err(s) => { warn!(target: "babe", "Failed to get slot duration"); diff --git a/client/consensus/babe/src/verification.rs b/client/consensus/babe/src/verification.rs index 2fd37280b3b36..f82c1894df925 100644 --- a/client/consensus/babe/src/verification.rs +++ b/client/consensus/babe/src/verification.rs @@ -19,7 +19,8 @@ use sp_runtime::{traits::Header, traits::DigestItemFor}; use sp_core::{Pair, Public}; use sp_consensus_babe::{AuthoritySignature, SlotNumber, AuthorityPair, AuthorityId}; use sp_consensus_babe::digests::{ - PreDigest, PrimaryPreDigest, SecondaryPreDigest, CompatibleDigestItem + PreDigest, PrimaryPreDigest, SecondaryPreDigest, SecondaryVRFPreDigest, + CompatibleDigestItem }; use sc_consensus_slots::CheckedHeader; use log::{debug, trace}; @@ -28,17 +29,17 @@ use super::authorship::{make_transcript, calculate_primary_threshold, check_prim /// BABE verification parameters pub(super) struct VerificationParams<'a, B: 'a + BlockT> { - /// the header being verified. + /// The header being verified. pub(super) header: B::Header, - /// the pre-digest of the header being verified. this is optional - if prior + /// The pre-digest of the header being verified. this is optional - if prior /// verification code had to read it, it can be included here to avoid duplicate /// work. pub(super) pre_digest: Option, - /// the slot number of the current time. + /// The slot number of the current time. pub(super) slot_now: SlotNumber, - /// epoch descriptor of the epoch this block _should_ be under, if it's valid. + /// Epoch descriptor of the epoch this block _should_ be under, if it's valid. pub(super) epoch: &'a Epoch, - /// genesis config of this BABE chain. + /// Genesis config of this BABE chain. pub(super) config: &'a super::Config, } @@ -105,7 +106,7 @@ pub(super) fn check_header( config.c, )?; }, - PreDigest::Secondary(secondary) if config.secondary_slots => { + PreDigest::Secondary(secondary) if config.allowed_slots.is_secondary_slots_allowed() => { debug!(target: "babe", "Verifying Secondary block"); check_secondary_header::( @@ -115,6 +116,16 @@ pub(super) fn check_header( &epoch, )?; }, + PreDigest::SecondaryVRF(secondary) if config.allowed_slots.is_secondary_vrf_slots_allowed() => { + debug!(target: "babe", "Verifying Secondary VRF block"); + + check_secondary_vrf_header::( + pre_hash, + secondary, + sig, + &epoch, + )?; + }, _ => { return Err(babe_err(Error::SecondarySlotAssignmentsDisabled)); } @@ -208,3 +219,43 @@ fn check_secondary_header( Err(Error::BadSignature(pre_hash)) } } + +/// Check a secondary VRF slot proposal header. +fn check_secondary_vrf_header( + pre_hash: B::Hash, + pre_digest: &SecondaryVRFPreDigest, + signature: AuthoritySignature, + epoch: &Epoch, +) -> Result<(), Error> { + // check the signature is valid under the expected authority and + // chain state. + let expected_author = secondary_slot_author( + pre_digest.slot_number, + &epoch.authorities, + epoch.randomness, + ).ok_or_else(|| Error::NoSecondaryAuthorExpected)?; + + let author = &epoch.authorities[pre_digest.authority_index as usize].0; + + if expected_author != author { + return Err(Error::InvalidAuthor(expected_author.clone(), author.clone())); + } + + if AuthorityPair::verify(&signature, pre_hash.as_ref(), author) { + let transcript = make_transcript( + &epoch.randomness, + pre_digest.slot_number, + epoch.epoch_index, + ); + + schnorrkel::PublicKey::from_bytes(author.as_slice()).and_then(|p| { + p.vrf_verify(transcript, &pre_digest.vrf_output, &pre_digest.vrf_proof) + }).map_err(|s| { + babe_err(Error::VRFVerificationFailed(s)) + })?; + + Ok(()) + } else { + Err(Error::BadSignature(pre_hash)) + } +} diff --git a/primitives/consensus/babe/src/digests.rs b/primitives/consensus/babe/src/digests.rs index 6079aa88c8749..05e7a22a195f8 100644 --- a/primitives/consensus/babe/src/digests.rs +++ b/primitives/consensus/babe/src/digests.rs @@ -77,6 +77,37 @@ pub struct SecondaryPreDigest { pub slot_number: SlotNumber, } +/// BABE secondary deterministic slot assignment with VRF outputs. +#[derive(Clone, RuntimeDebug, Encode, Decode)] +pub struct RawSecondaryVRFPreDigest { + /// Authority index + pub authority_index: super::AuthorityIndex, + /// Slot number + pub slot_number: SlotNumber, + /// VRF output + pub vrf_output: VRFOutput, + /// VRF proof + pub vrf_proof: VRFProof, +} + +#[cfg(feature = "std")] +/// BABE secondary slot assignment with VRF outputs pre-digest, for std environment. +pub type SecondaryVRFPreDigest = RawSecondaryVRFPreDigest; + +#[cfg(feature = "std")] +impl TryFrom for SecondaryVRFPreDigest { + type Error = SignatureError; + + fn try_from(raw: RawSecondaryVRFPreDigest) -> Result { + Ok(SecondaryVRFPreDigest { + authority_index: raw.authority_index, + slot_number: raw.slot_number, + vrf_output: raw.vrf_output.try_into()?, + vrf_proof: raw.vrf_proof.try_into()?, + }) + } +} + /// A BABE pre-runtime digest. This contains all data required to validate a /// block and for the BABE runtime module. Slots can be assigned to a primary /// (VRF based) and to a secondary (slot number based). @@ -88,6 +119,9 @@ pub enum RawPreDigest), } #[cfg(feature = "std")] @@ -100,6 +134,7 @@ impl RawPreDigest { match self { RawPreDigest::Primary(primary) => primary.authority_index, RawPreDigest::Secondary(secondary) => secondary.authority_index, + RawPreDigest::SecondaryVRF(secondary) => secondary.authority_index, } } @@ -108,6 +143,7 @@ impl RawPreDigest { match self { RawPreDigest::Primary(primary) => primary.slot_number, RawPreDigest::Secondary(secondary) => secondary.slot_number, + RawPreDigest::SecondaryVRF(secondary) => secondary.slot_number, } } @@ -116,7 +152,7 @@ impl RawPreDigest { pub fn added_weight(&self) -> crate::BabeBlockWeight { match self { RawPreDigest::Primary(_) => 1, - RawPreDigest::Secondary(_) => 0, + RawPreDigest::Secondary(_) | RawPreDigest::SecondaryVRF(_) => 0, } } } @@ -129,6 +165,7 @@ impl TryFrom for PreDigest { Ok(match raw { RawPreDigest::Primary(primary) => PreDigest::Primary(primary.try_into()?), RawPreDigest::Secondary(secondary) => PreDigest::Secondary(secondary), + RawPreDigest::SecondaryVRF(secondary) => PreDigest::SecondaryVRF(secondary.try_into()?), }) } } diff --git a/primitives/consensus/babe/src/lib.rs b/primitives/consensus/babe/src/lib.rs index 33701860d1f10..c07abc41765a0 100644 --- a/primitives/consensus/babe/src/lib.rs +++ b/primitives/consensus/babe/src/lib.rs @@ -91,7 +91,7 @@ pub enum ConsensusLog { /// Configuration data used by the BABE consensus engine. #[derive(Clone, PartialEq, Eq, Encode, Decode, RuntimeDebug)] -pub struct BabeConfiguration { +pub struct BabeConfigurationV1 { /// The slot duration in milliseconds for BABE. Currently, only /// the value provided by this type at genesis will be used. /// @@ -120,6 +120,76 @@ pub struct BabeConfiguration { pub secondary_slots: bool, } +impl From for BabeConfiguration { + fn from(v1: BabeConfigurationV1) -> Self { + Self { + slot_duration: v1.slot_duration, + epoch_length: v1.epoch_length, + c: v1.c, + genesis_authorities: v1.genesis_authorities, + randomness: v1.randomness, + allowed_slots: if v1.secondary_slots { + AllowedSlots::PrimaryAndSecondarySlots + } else { + AllowedSlots::PrimarySlots + }, + } + } +} + +/// Configuration data used by the BABE consensus engine. +#[derive(Clone, PartialEq, Eq, Encode, Decode, RuntimeDebug)] +pub struct BabeConfiguration { + /// The slot duration in milliseconds for BABE. Currently, only + /// the value provided by this type at genesis will be used. + /// + /// Dynamic slot duration may be supported in the future. + pub slot_duration: u64, + + /// The duration of epochs in slots. + pub epoch_length: SlotNumber, + + /// A constant value that is used in the threshold calculation formula. + /// Expressed as a rational where the first member of the tuple is the + /// numerator and the second is the denominator. The rational should + /// represent a value between 0 and 1. + /// In the threshold formula calculation, `1 - c` represents the probability + /// of a slot being empty. + pub c: (u64, u64), + + /// The authorities for the genesis epoch. + pub genesis_authorities: Vec<(AuthorityId, BabeAuthorityWeight)>, + + /// The randomness for the genesis epoch. + pub randomness: Randomness, + + /// Type of allowed slots. + pub allowed_slots: AllowedSlots, +} + +/// Types of allowed slots. +#[derive(Clone, Copy, PartialEq, Eq, Encode, Decode, RuntimeDebug)] +pub enum AllowedSlots { + /// Only allow primary slots. + PrimarySlots, + /// Allow primary and secondary slots, but disallow secondary VRF slots. + PrimaryAndSecondarySlots, + /// Allow primary and secondary slots. Enable secondary VRF slots after slot number. + PrimaryAndSecondaryVRFSlots, +} + +impl AllowedSlots { + /// Whether plain secondary slots are allowed. + pub fn is_secondary_slots_allowed(&self) -> bool { + *self == Self::PrimaryAndSecondarySlots + } + + /// Whether VRF secondary slots are allowed. + pub fn is_secondary_vrf_slots_allowed(&self) -> bool { + *self == Self::PrimaryAndSecondaryVRFSlots + } +} + #[cfg(feature = "std")] impl sp_consensus::SlotData for BabeConfiguration { fn slot_duration(&self) -> u64 { @@ -131,6 +201,7 @@ impl sp_consensus::SlotData for BabeConfiguration { sp_api::decl_runtime_apis! { /// API necessary for block authorship with BABE. + #[api_version(2)] pub trait BabeApi { /// Return the configuration for BABE. Currently, /// only the value provided by this type at genesis will be used. @@ -138,6 +209,10 @@ sp_api::decl_runtime_apis! { /// Dynamic configuration may be supported in the future. fn configuration() -> BabeConfiguration; + /// Return the configuration for BABE. Version 1. + #[changed_in(2)] + fn configuration() -> BabeConfigurationV1; + /// Returns the slot number that started the current epoch. fn current_epoch_start() -> SlotNumber; } From ae38673b5fd6047bd2a4735263c195b1913e5ad6 Mon Sep 17 00:00:00 2001 From: Wei Tang Date: Thu, 2 Apr 2020 13:53:37 +0200 Subject: [PATCH 02/24] Fix node runtime compile --- bin/node/runtime/src/lib.rs | 6 +++--- test-utils/runtime/src/lib.rs | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/bin/node/runtime/src/lib.rs b/bin/node/runtime/src/lib.rs index 309f4ed0245e4..a4c7b894a6fce 100644 --- a/bin/node/runtime/src/lib.rs +++ b/bin/node/runtime/src/lib.rs @@ -128,8 +128,8 @@ pub const VERSION: RuntimeVersion = RuntimeVersion { // and set impl_version to 0. If only runtime // implementation changes and behavior does not, then leave spec_version as // is and increment impl_version. - spec_version: 240, - impl_version: 1, + spec_version: 241, + impl_version: 0, apis: RUNTIME_API_VERSIONS, }; @@ -794,7 +794,7 @@ impl_runtime_apis! { c: PRIMARY_PROBABILITY, genesis_authorities: Babe::authorities(), randomness: Babe::randomness(), - secondary_slots: true, + allowed_slots: sp_consensus_babe::AllowedSlots::PrimaryAndSecondarySlots, } } diff --git a/test-utils/runtime/src/lib.rs b/test-utils/runtime/src/lib.rs index f3efb4bea7c76..24149c81fbc6f 100644 --- a/test-utils/runtime/src/lib.rs +++ b/test-utils/runtime/src/lib.rs @@ -53,7 +53,7 @@ use cfg_if::cfg_if; use sp_core::storage::ChildType; // Ensure Babe and Aura use the same crypto to simplify things a bit. -pub use sp_consensus_babe::{AuthorityId, SlotNumber}; +pub use sp_consensus_babe::{AuthorityId, SlotNumber, AllowedSlots}; pub type AuraId = sp_consensus_aura::sr25519::AuthorityId; // Include the WASM binary @@ -820,7 +820,7 @@ cfg_if! { genesis_authorities: system::authorities() .into_iter().map(|x|(x, 1)).collect(), randomness: >::randomness(), - secondary_slots: true, + allowed_slots: AllowedSlots::PrimaryAndSecondarySlots, } } From 13aa4953a6f877c24d66eed1fcff0b914ba5a760 Mon Sep 17 00:00:00 2001 From: Wei Tang Date: Thu, 2 Apr 2020 13:56:15 +0200 Subject: [PATCH 03/24] Fix test-utils runtime interface --- test-utils/runtime/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test-utils/runtime/src/lib.rs b/test-utils/runtime/src/lib.rs index 24149c81fbc6f..37ae79ef3dbd7 100644 --- a/test-utils/runtime/src/lib.rs +++ b/test-utils/runtime/src/lib.rs @@ -626,7 +626,7 @@ cfg_if! { genesis_authorities: system::authorities() .into_iter().map(|x|(x, 1)).collect(), randomness: >::randomness(), - secondary_slots: true, + allowed_slots: AllowedSlots::PrimaryAndSecondarySlots, } } From c264025ca854d41defed37cf629d10f1c14353a3 Mon Sep 17 00:00:00 2001 From: Wei Tang Date: Thu, 2 Apr 2020 14:03:31 +0200 Subject: [PATCH 04/24] Fix babe tests --- client/consensus/babe/src/tests.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/client/consensus/babe/src/tests.rs b/client/consensus/babe/src/tests.rs index 20b924669d614..4912c13cfe45d 100644 --- a/client/consensus/babe/src/tests.rs +++ b/client/consensus/babe/src/tests.rs @@ -22,7 +22,7 @@ use super::*; use authorship::claim_slot; -use sp_consensus_babe::{AuthorityPair, SlotNumber}; +use sp_consensus_babe::{AuthorityPair, SlotNumber, AllowedSlots}; use sc_block_builder::{BlockBuilder, BlockBuilderProvider}; use sp_consensus::{ NoNetwork as DummyOracle, Proposal, RecordProof, @@ -513,7 +513,7 @@ fn can_author_block() { c: (3, 10), genesis_authorities: Vec::new(), randomness: [0; 32], - secondary_slots: true, + allowed_slots: AllowedSlots::PrimaryAndSecondarySlots, }; // with secondary slots enabled it should never be empty @@ -524,7 +524,7 @@ fn can_author_block() { // otherwise with only vrf-based primary slots we might need to try a couple // of times. - config.secondary_slots = false; + config.allowed_slots = AllowedSlots::PrimarySlots; loop { match claim_slot(i, &epoch, &config, &keystore) { None => i += 1, From 936253c9a07f4ac1eae4faf1641a636b0db720d9 Mon Sep 17 00:00:00 2001 From: Wei Tang Date: Fri, 3 Apr 2020 11:38:33 +0200 Subject: [PATCH 05/24] typo: v == 2 --- client/consensus/babe/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/consensus/babe/src/lib.rs b/client/consensus/babe/src/lib.rs index 29094fc15b84b..100b72cec592d 100644 --- a/client/consensus/babe/src/lib.rs +++ b/client/consensus/babe/src/lib.rs @@ -260,7 +260,7 @@ impl Config { &b, |v| v == 1, )?; let has_api_v2 = a.has_api_with::, _>( - &b, |v| v == 1, + &b, |v| v == 2, )?; if has_api_v1 { From 5383f4d9440e9f39fee2afaa50fee6072d3d5350 Mon Sep 17 00:00:00 2001 From: Wei Tang Date: Fri, 3 Apr 2020 12:33:47 +0200 Subject: [PATCH 06/24] babe: support online configuration upgrades --- client/consensus/babe/src/authorship.rs | 7 +- client/consensus/babe/src/lib.rs | 106 +++++++++++++++------- client/consensus/babe/src/verification.rs | 7 +- client/consensus/epochs/src/lib.rs | 4 +- primitives/consensus/babe/src/lib.rs | 50 +++++----- 5 files changed, 107 insertions(+), 67 deletions(-) diff --git a/client/consensus/babe/src/authorship.rs b/client/consensus/babe/src/authorship.rs index 074e582bff252..165ff0ca4fef0 100644 --- a/client/consensus/babe/src/authorship.rs +++ b/client/consensus/babe/src/authorship.rs @@ -19,7 +19,7 @@ use merlin::Transcript; use sp_consensus_babe::{ AuthorityId, BabeAuthorityWeight, BABE_ENGINE_ID, BABE_VRF_PREFIX, - SlotNumber, AuthorityPair, BabeConfiguration + SlotNumber, AuthorityPair, }; use sp_consensus_babe::digests::{PreDigest, PrimaryPreDigest, SecondaryPreDigest}; use sp_consensus_vrf::schnorrkel::{VRFOutput, VRFProof}; @@ -147,12 +147,11 @@ fn claim_secondary_slot( pub fn claim_slot( slot_number: SlotNumber, epoch: &Epoch, - config: &BabeConfiguration, keystore: &KeyStorePtr, ) -> Option<(PreDigest, AuthorityPair)> { - claim_primary_slot(slot_number, epoch, config.c, keystore) + claim_primary_slot(slot_number, epoch, epoch.config.c, keystore) .or_else(|| { - if config.secondary_slots { + if epoch.config.secondary_slots { claim_secondary_slot( slot_number, &epoch.authorities, diff --git a/client/consensus/babe/src/lib.rs b/client/consensus/babe/src/lib.rs index 5365aae2aa6cb..04883665abf2c 100644 --- a/client/consensus/babe/src/lib.rs +++ b/client/consensus/babe/src/lib.rs @@ -59,7 +59,8 @@ #![forbid(unsafe_code)] #![warn(missing_docs)] pub use sp_consensus_babe::{ - BabeApi, ConsensusLog, BABE_ENGINE_ID, SlotNumber, BabeConfiguration, + BabeApi, ConsensusLog, BABE_ENGINE_ID, SlotNumber, + BabeEpochConfiguration, BabeGenesisConfiguration, AuthorityId, AuthorityPair, AuthoritySignature, BabeAuthorityWeight, VRF_OUTPUT_LENGTH, digests::{ @@ -123,31 +124,37 @@ pub mod authorship; mod tests; /// BABE epoch information -#[derive(Decode, Encode, Default, PartialEq, Eq, Clone, Debug)] +#[derive(Decode, Encode, PartialEq, Eq, Clone, Debug)] pub struct Epoch { - /// The epoch index + /// The epoch index. pub epoch_index: u64, - /// The starting slot of the epoch, + /// The starting slot of the epoch. pub start_slot: SlotNumber, - /// The duration of this epoch + /// The duration of this epoch. pub duration: SlotNumber, - /// The authorities and their weights + /// The authorities and their weights. pub authorities: Vec<(AuthorityId, BabeAuthorityWeight)>, - /// Randomness for this epoch + /// Randomness for this epoch. pub randomness: [u8; VRF_OUTPUT_LENGTH], + /// Configuration of the epoch. + pub config: BabeEpochConfiguration, } impl EpochT for Epoch { - type NextEpochDescriptor = NextEpochDescriptor; + type NextEpochDescriptor = (NextEpochDescriptor, BabeEpochConfiguration); type SlotNumber = SlotNumber; - fn increment(&self, descriptor: NextEpochDescriptor) -> Epoch { + fn increment( + &self, + (descriptor, config): (NextEpochDescriptor, BabeEpochConfiguration) + ) -> Epoch { Epoch { epoch_index: self.epoch_index + 1, start_slot: self.start_slot + self.duration, duration: self.duration, authorities: descriptor.authorities, randomness: descriptor.randomness, + config, } } @@ -160,6 +167,25 @@ impl EpochT for Epoch { } } +impl Epoch { + /// Create the genesis epoch (epoch #0). This is defined to start at the slot of + /// the first block, so that has to be provided. + pub fn genesis( + genesis_config: &BabeGenesisConfiguration, + epoch_config: &BabeEpochConfiguration, + slot_number: SlotNumber + ) -> Epoch { + Epoch { + epoch_index: 0, + start_slot: slot_number, + duration: epoch_config.epoch_length, + authorities: genesis_config.genesis_authorities.clone(), + randomness: genesis_config.randomness.clone(), + config: epoch_config.clone(), + } + } +} + #[derive(derive_more::Display, Debug)] enum Error { #[display(fmt = "Multiple BABE pre-runtime digests, rejecting!")] @@ -168,6 +194,8 @@ enum Error { NoPreRuntimeDigest, #[display(fmt = "Multiple BABE epoch change digests, rejecting!")] MultipleEpochChangeDigests, + #[display(fmt = "Fetch new epoch configuration failed")] + FetchEpochConfig(B::Hash), #[display(fmt = "Could not extract timestamp and slot: {:?}", _0)] Extraction(sp_consensus::Error), #[display(fmt = "Could not fetch epoch at {:?}", _0)] @@ -246,7 +274,7 @@ pub static INTERMEDIATE_KEY: &[u8] = b"babe1"; // and `super::babe::Config` can be eliminated. // https://github.com/paritytech/substrate/issues/2434 #[derive(Clone)] -pub struct Config(sc_consensus_slots::SlotDuration); +pub struct Config(sc_consensus_slots::SlotDuration); impl Config { /// Either fetch the slot duration from disk or compute it from the genesis @@ -255,7 +283,9 @@ impl Config { C: AuxStore + ProvideRuntimeApi, C::Api: BabeApi, { trace!(target: "babe", "Getting slot duration"); - match sc_consensus_slots::SlotDuration::get_or_compute(client, |a, b| a.configuration(b)).map(Self) { + match sc_consensus_slots::SlotDuration::get_or_compute(client, |a, b| { + a.genesis_configuration(b) + }).map(Self) { Ok(s) => Ok(s), Err(s) => { warn!(target: "babe", "Failed to get slot duration"); @@ -263,24 +293,12 @@ impl Config { } } } - - /// Create the genesis epoch (epoch #0). This is defined to start at the slot of - /// the first block, so that has to be provided. - pub fn genesis_epoch(&self, slot_number: SlotNumber) -> Epoch { - Epoch { - epoch_index: 0, - start_slot: slot_number, - duration: self.epoch_length, - authorities: self.genesis_authorities.clone(), - randomness: self.randomness.clone(), - } - } } impl std::ops::Deref for Config { - type Target = BabeConfiguration; + type Target = BabeGenesisConfiguration; - fn deref(&self) -> &BabeConfiguration { + fn deref(&self) -> &BabeGenesisConfiguration { &*self.0 } } @@ -438,7 +456,12 @@ impl sc_consensus_slots::SimpleSlotWorker for BabeWork fn authorities_len(&self, epoch_descriptor: &Self::EpochData) -> Option { self.epoch_changes.lock() - .viable_epoch(&epoch_descriptor, |slot| self.config.genesis_epoch(slot)) + .viable_epoch(&epoch_descriptor, |slot| { + let epoch_config = self.client.runtime_api() + .epoch_configuration(&BlockId::number(Zero::zero())) + .ok()?; + Some(Epoch::genesis(&self.config, &epoch_config, slot)) + }) .map(|epoch| epoch.as_ref().authorities.len()) } @@ -453,9 +476,13 @@ impl sc_consensus_slots::SimpleSlotWorker for BabeWork slot_number, self.epoch_changes.lock().viable_epoch( &epoch_descriptor, - |slot| self.config.genesis_epoch(slot) + |slot| { + let epoch_config = self.client.runtime_api() + .epoch_configuration(&BlockId::number(Zero::zero())) + .ok()?; + Some(Epoch::genesis(&self.config, &epoch_config, slot)) + } )?.as_ref(), - &*self.config, &self.keystore, ); @@ -746,7 +773,12 @@ impl Verifier for BabeVerifier where .ok_or_else(|| Error::::FetchEpoch(parent_hash))?; let viable_epoch = epoch_changes.viable_epoch( &epoch_descriptor, - |slot| self.config.genesis_epoch(slot) + |slot| { + let epoch_config = self.client.runtime_api() + .epoch_configuration(&BlockId::number(Zero::zero())) + .ok()?; + Some(Epoch::genesis(&self.config, &epoch_config, slot)) + } ).ok_or_else(|| Error::::FetchEpoch(parent_hash))?; // We add one to the current slot to allow for some small drift. @@ -756,7 +788,6 @@ impl Verifier for BabeVerifier where pre_digest: Some(pre_digest.clone()), slot_now: slot_now + 1, epoch: viable_epoch.as_ref(), - config: &self.config, }; match verification::check_header::(v_params)? { @@ -1005,18 +1036,29 @@ impl BlockImport for BabeBlockImport::FetchEpoch(parent_hash).into()) })?; + let epoch_config = self.client.runtime_api() + .epoch_configuration(&BlockId::hash(parent_hash)) + .map_err(|_| ConsensusError::ClientImport( + Error::::FetchEpochConfig(parent_hash).into() + ))?; + babe_info!("👶 New epoch {} launching at block {} (block slot {} >= start slot {}).", viable_epoch.as_ref().epoch_index, hash, slot_number, viable_epoch.as_ref().start_slot); - let next_epoch = viable_epoch.increment(next_epoch_descriptor); + let next_epoch = viable_epoch.increment((next_epoch_descriptor, epoch_config)); babe_info!("👶 Next epoch starts at slot {}", next_epoch.as_ref().start_slot); diff --git a/client/consensus/babe/src/verification.rs b/client/consensus/babe/src/verification.rs index 2fd37280b3b36..1a3eba458430a 100644 --- a/client/consensus/babe/src/verification.rs +++ b/client/consensus/babe/src/verification.rs @@ -38,8 +38,6 @@ pub(super) struct VerificationParams<'a, B: 'a + BlockT> { pub(super) slot_now: SlotNumber, /// epoch descriptor of the epoch this block _should_ be under, if it's valid. pub(super) epoch: &'a Epoch, - /// genesis config of this BABE chain. - pub(super) config: &'a super::Config, } /// Check a header has been signed by the right key. If the slot is too far in @@ -63,7 +61,6 @@ pub(super) fn check_header( pre_digest, slot_now, epoch, - config, } = params; let authorities = &epoch.authorities; @@ -102,10 +99,10 @@ pub(super) fn check_header( primary, sig, &epoch, - config.c, + epoch.config.c, )?; }, - PreDigest::Secondary(secondary) if config.secondary_slots => { + PreDigest::Secondary(secondary) if epoch.config.secondary_slots => { debug!(target: "babe", "Verifying Secondary block"); check_secondary_header::( diff --git a/client/consensus/epochs/src/lib.rs b/client/consensus/epochs/src/lib.rs index 001c172b34905..9714dc1a198c0 100644 --- a/client/consensus/epochs/src/lib.rs +++ b/client/consensus/epochs/src/lib.rs @@ -394,11 +394,11 @@ impl EpochChanges where descriptor: &ViableEpochDescriptor, make_genesis: G, ) -> Option> where - G: FnOnce(E::SlotNumber) -> E + G: FnOnce(E::SlotNumber) -> Option { match descriptor { ViableEpochDescriptor::UnimportedGenesis(slot_number) => { - Some(ViableEpoch::UnimportedGenesis(make_genesis(*slot_number))) + make_genesis(*slot_number).map(ViableEpoch::UnimportedGenesis) }, ViableEpochDescriptor::Signaled(identifier, _) => { self.epoch(&identifier).map(ViableEpoch::Signaled) diff --git a/primitives/consensus/babe/src/lib.rs b/primitives/consensus/babe/src/lib.rs index 33701860d1f10..9e7f9cad9d153 100644 --- a/primitives/consensus/babe/src/lib.rs +++ b/primitives/consensus/babe/src/lib.rs @@ -89,15 +89,32 @@ pub enum ConsensusLog { OnDisabled(AuthorityIndex), } -/// Configuration data used by the BABE consensus engine. +/// Genesis configuration data used by the BABE consensus engine. #[derive(Clone, PartialEq, Eq, Encode, Decode, RuntimeDebug)] -pub struct BabeConfiguration { +pub struct BabeGenesisConfiguration { /// The slot duration in milliseconds for BABE. Currently, only /// the value provided by this type at genesis will be used. - /// - /// Dynamic slot duration may be supported in the future. pub slot_duration: u64, + /// The authorities for the genesis epoch. + pub genesis_authorities: Vec<(AuthorityId, BabeAuthorityWeight)>, + + /// The randomness for the genesis epoch. + pub randomness: Randomness, +} + +#[cfg(feature = "std")] +impl sp_consensus::SlotData for BabeGenesisConfiguration { + fn slot_duration(&self) -> u64 { + self.slot_duration + } + + const SLOT_KEY: &'static [u8] = b"babe_configuration"; +} + +/// Configuration data used by the BABE consensus engine. +#[derive(Clone, PartialEq, Eq, Encode, Decode, RuntimeDebug)] +pub struct BabeEpochConfiguration { /// The duration of epochs in slots. pub epoch_length: SlotNumber, @@ -109,34 +126,19 @@ pub struct BabeConfiguration { /// of a slot being empty. pub c: (u64, u64), - /// The authorities for the genesis epoch. - pub genesis_authorities: Vec<(AuthorityId, BabeAuthorityWeight)>, - - /// The randomness for the genesis epoch. - pub randomness: Randomness, - /// Whether this chain should run with secondary slots, which are assigned /// in round-robin manner. pub secondary_slots: bool, } -#[cfg(feature = "std")] -impl sp_consensus::SlotData for BabeConfiguration { - fn slot_duration(&self) -> u64 { - self.slot_duration - } - - const SLOT_KEY: &'static [u8] = b"babe_configuration"; -} - sp_api::decl_runtime_apis! { /// API necessary for block authorship with BABE. pub trait BabeApi { - /// Return the configuration for BABE. Currently, - /// only the value provided by this type at genesis will be used. - /// - /// Dynamic configuration may be supported in the future. - fn configuration() -> BabeConfiguration; + /// Return the epoch configuration for BABE. The configuration is read once every epoch. + fn epoch_configuration() -> BabeEpochConfiguration; + + /// Return the genesis configuration for BABE. The configuration is only read on genesis. + fn genesis_configuration() -> BabeGenesisConfiguration; /// Returns the slot number that started the current epoch. fn current_epoch_start() -> SlotNumber; From 2c91a14890f492e3964f0a8c967b0dc0d543555c Mon Sep 17 00:00:00 2001 From: Wei Tang Date: Fri, 3 Apr 2020 12:43:09 +0200 Subject: [PATCH 07/24] Fix rpc tests --- client/consensus/babe/rpc/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/consensus/babe/rpc/src/lib.rs b/client/consensus/babe/rpc/src/lib.rs index 5efa1ddb2dabd..b334ce6280133 100644 --- a/client/consensus/babe/rpc/src/lib.rs +++ b/client/consensus/babe/rpc/src/lib.rs @@ -241,7 +241,7 @@ mod tests { io.extend_with(BabeApi::to_delegate(handler)); let request = r#"{"jsonrpc":"2.0","method":"babe_epochAuthorship","params": [],"id":1}"#; - let response = r#"{"jsonrpc":"2.0","result":{"5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY":{"primary":[0],"secondary":[1,2,4]}},"id":1}"#; + let response = r#"{"jsonrpc":"2.0","result":{"5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY":{"primary":[0],"secondary":[1,2,4],"secondary_vrf":[]}},"id":1}"#; assert_eq!(Some(response.into()), io.handle_request_sync(request)); } From 06adbb9ed71c33bb9217cb1d4d62682ef55421a1 Mon Sep 17 00:00:00 2001 From: Wei Tang Date: Fri, 3 Apr 2020 14:05:26 +0200 Subject: [PATCH 08/24] Fix runtime version tests --- client/rpc/src/state/tests.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/rpc/src/state/tests.rs b/client/rpc/src/state/tests.rs index 4a9b701959c8c..c8d4952d8f3fe 100644 --- a/client/rpc/src/state/tests.rs +++ b/client/rpc/src/state/tests.rs @@ -439,7 +439,7 @@ fn should_return_runtime_version() { let result = "{\"specName\":\"test\",\"implName\":\"parity-test\",\"authoringVersion\":1,\ \"specVersion\":2,\"implVersion\":2,\"apis\":[[\"0xdf6acb689907609b\",2],\ [\"0x37e397fc7c91f5e4\",1],[\"0xd2bc9897eed08f15\",2],[\"0x40fe3ad401f8959a\",4],\ - [\"0xc6e9a76309f39b09\",1],[\"0xdd718d5cc53262d4\",1],[\"0xcbca25e39f142387\",1],\ + [\"0xc6e9a76309f39b09\",1],[\"0xdd718d5cc53262d4\",1],[\"0xcbca25e39f142387\",2],\ [\"0xf78b278be53f454c\",2],[\"0xab3c0572291feb8b\",1],[\"0xbc9d89904f5b923f\",1]]}"; let runtime_version = api.runtime_version(None.into()).wait().unwrap(); From 8185b917e8f9acc0f4f869482adf471ada7f6b1d Mon Sep 17 00:00:00 2001 From: Wei Tang Date: Tue, 7 Apr 2020 17:07:06 +0200 Subject: [PATCH 09/24] Switch to use NextConfigDescriptor instead of changing runtime interface --- client/consensus/babe/src/lib.rs | 102 +++++++++++++---------- client/consensus/epochs/src/lib.rs | 4 +- primitives/consensus/babe/src/digests.rs | 21 ++++- primitives/consensus/babe/src/lib.rs | 33 ++++++-- 4 files changed, 101 insertions(+), 59 deletions(-) diff --git a/client/consensus/babe/src/lib.rs b/client/consensus/babe/src/lib.rs index 04883665abf2c..25324c1d9122c 100644 --- a/client/consensus/babe/src/lib.rs +++ b/client/consensus/babe/src/lib.rs @@ -64,7 +64,8 @@ pub use sp_consensus_babe::{ AuthorityId, AuthorityPair, AuthoritySignature, BabeAuthorityWeight, VRF_OUTPUT_LENGTH, digests::{ - CompatibleDigestItem, NextEpochDescriptor, PreDigest, PrimaryPreDigest, SecondaryPreDigest, + CompatibleDigestItem, NextEpochDescriptor, NextConfigDescriptor, + PreDigest, PrimaryPreDigest, SecondaryPreDigest, }, }; pub use sp_consensus::SyncOracle; @@ -172,16 +173,18 @@ impl Epoch { /// the first block, so that has to be provided. pub fn genesis( genesis_config: &BabeGenesisConfiguration, - epoch_config: &BabeEpochConfiguration, slot_number: SlotNumber ) -> Epoch { Epoch { epoch_index: 0, start_slot: slot_number, - duration: epoch_config.epoch_length, + duration: genesis_config.epoch_length, authorities: genesis_config.genesis_authorities.clone(), randomness: genesis_config.randomness.clone(), - config: epoch_config.clone(), + config: BabeEpochConfiguration { + c: genesis_config.c, + secondary_slots: genesis_config.secondary_slots, + }, } } } @@ -194,8 +197,8 @@ enum Error { NoPreRuntimeDigest, #[display(fmt = "Multiple BABE epoch change digests, rejecting!")] MultipleEpochChangeDigests, - #[display(fmt = "Fetch new epoch configuration failed")] - FetchEpochConfig(B::Hash), + #[display(fmt = "Multiple BABE config change digests, rejecting!")] + MultipleConfigChangeDigests, #[display(fmt = "Could not extract timestamp and slot: {:?}", _0)] Extraction(sp_consensus::Error), #[display(fmt = "Could not fetch epoch at {:?}", _0)] @@ -228,6 +231,8 @@ enum Error { FetchParentHeader(sp_blockchain::Error), #[display(fmt = "Expected epoch change to happen at {:?}, s{}", _0, _1)] ExpectedEpochChange(B::Hash, u64), + #[display(fmt = "Unexpected config change")] + UnexpectedConfigChange, #[display(fmt = "Unexpected epoch change")] UnexpectedEpochChange, #[display(fmt = "Parent block of {} has no associated weight", _0)] @@ -283,9 +288,7 @@ impl Config { C: AuxStore + ProvideRuntimeApi, C::Api: BabeApi, { trace!(target: "babe", "Getting slot duration"); - match sc_consensus_slots::SlotDuration::get_or_compute(client, |a, b| { - a.genesis_configuration(b) - }).map(Self) { + match sc_consensus_slots::SlotDuration::get_or_compute(client, |a, b| a.configuration(b)).map(Self) { Ok(s) => Ok(s), Err(s) => { warn!(target: "babe", "Failed to get slot duration"); @@ -456,12 +459,7 @@ impl sc_consensus_slots::SimpleSlotWorker for BabeWork fn authorities_len(&self, epoch_descriptor: &Self::EpochData) -> Option { self.epoch_changes.lock() - .viable_epoch(&epoch_descriptor, |slot| { - let epoch_config = self.client.runtime_api() - .epoch_configuration(&BlockId::number(Zero::zero())) - .ok()?; - Some(Epoch::genesis(&self.config, &epoch_config, slot)) - }) + .viable_epoch(&epoch_descriptor, |slot| Epoch::genesis(&self.config, slot)) .map(|epoch| epoch.as_ref().authorities.len()) } @@ -476,12 +474,7 @@ impl sc_consensus_slots::SimpleSlotWorker for BabeWork slot_number, self.epoch_changes.lock().viable_epoch( &epoch_descriptor, - |slot| { - let epoch_config = self.client.runtime_api() - .epoch_configuration(&BlockId::number(Zero::zero())) - .ok()?; - Some(Epoch::genesis(&self.config, &epoch_config, slot)) - } + |slot| Epoch::genesis(&self.config, slot) )?.as_ref(), &self.keystore, ); @@ -646,6 +639,24 @@ fn find_next_epoch_digest(header: &B::Header) Ok(epoch_digest) } +/// Extract the BABE config change digest from the given header, if it exists. +fn find_next_config_digest(header: &B::Header) + -> Result, Error> + where DigestItemFor: CompatibleDigestItem, +{ + let mut config_digest: Option<_> = None; + for log in header.digest().logs() { + trace!(target: "babe", "Checking log {:?}, looking for epoch change digest.", log); + let log = log.try_to::(OpaqueDigestItemId::Consensus(&BABE_ENGINE_ID)); + match (log, config_digest.is_some()) { + (Some(ConsensusLog::NextConfigData(_)), true) => return Err(babe_err(Error::MultipleConfigChangeDigests)), + (Some(ConsensusLog::NextConfigData(config)), false) => config_digest = Some(config), + _ => trace!(target: "babe", "Ignoring digest not meant for us"), + } + } + + Ok(config_digest) +} #[derive(Default, Clone)] struct TimeSource(Arc, Vec<(Instant, u64)>)>>); @@ -773,12 +784,7 @@ impl Verifier for BabeVerifier where .ok_or_else(|| Error::::FetchEpoch(parent_hash))?; let viable_epoch = epoch_changes.viable_epoch( &epoch_descriptor, - |slot| { - let epoch_config = self.client.runtime_api() - .epoch_configuration(&BlockId::number(Zero::zero())) - .ok()?; - Some(Epoch::genesis(&self.config, &epoch_config, slot)) - } + |slot| Epoch::genesis(&self.config, slot) ).ok_or_else(|| Error::::FetchEpoch(parent_hash))?; // We add one to the current slot to allow for some small drift. @@ -1009,19 +1015,32 @@ impl BlockImport for BabeBlockImport(&block.header) .map_err(|e| ConsensusError::ClientImport(e.to_string()))?; + let next_config_digest = find_next_config_digest::(&block.header) + .map_err(|e| ConsensusError::ClientImport(e.to_string()))?; - match (first_in_epoch, next_epoch_digest.is_some()) { - (true, true) => {}, - (false, false) => {}, - (true, false) => { + match (first_in_epoch, next_epoch_digest.is_some(), next_config_digest.is_some()) { + (true, true, _) => {}, + (false, false, false) => {}, + (false, false, true) => { + return Err( + ConsensusError::ClientImport( + babe_err(Error::::UnexpectedConfigChange).into(), + ) + ) + }, + (true, false, _) => { return Err( ConsensusError::ClientImport( babe_err(Error::::ExpectedEpochChange(hash, slot_number)).into(), ) - ); + ) }, - (false, true) => { - return Err(ConsensusError::ClientImport(Error::::UnexpectedEpochChange.into())); + (false, true, _) => { + return Err( + ConsensusError::ClientImport( + babe_err(Error::::UnexpectedEpochChange).into(), + ) + ) }, } @@ -1036,21 +1055,14 @@ impl BlockImport for BabeBlockImport::FetchEpoch(parent_hash).into()) })?; - let epoch_config = self.client.runtime_api() - .epoch_configuration(&BlockId::hash(parent_hash)) - .map_err(|_| ConsensusError::ClientImport( - Error::::FetchEpochConfig(parent_hash).into() - ))?; + let epoch_config = next_config_digest.unwrap_or_else( + || viable_epoch.as_ref().config.clone() + ); babe_info!("👶 New epoch {} launching at block {} (block slot {} >= start slot {}).", viable_epoch.as_ref().epoch_index, diff --git a/client/consensus/epochs/src/lib.rs b/client/consensus/epochs/src/lib.rs index 9714dc1a198c0..001c172b34905 100644 --- a/client/consensus/epochs/src/lib.rs +++ b/client/consensus/epochs/src/lib.rs @@ -394,11 +394,11 @@ impl EpochChanges where descriptor: &ViableEpochDescriptor, make_genesis: G, ) -> Option> where - G: FnOnce(E::SlotNumber) -> Option + G: FnOnce(E::SlotNumber) -> E { match descriptor { ViableEpochDescriptor::UnimportedGenesis(slot_number) => { - make_genesis(*slot_number).map(ViableEpoch::UnimportedGenesis) + Some(ViableEpoch::UnimportedGenesis(make_genesis(*slot_number))) }, ViableEpochDescriptor::Signaled(identifier, _) => { self.epoch(&identifier).map(ViableEpoch::Signaled) diff --git a/primitives/consensus/babe/src/digests.rs b/primitives/consensus/babe/src/digests.rs index 6079aa88c8749..50eca40a5e578 100644 --- a/primitives/consensus/babe/src/digests.rs +++ b/primitives/consensus/babe/src/digests.rs @@ -17,7 +17,7 @@ //! Private implementation details of BABE digests. #[cfg(feature = "std")] -use super::{BABE_ENGINE_ID, AuthoritySignature}; +use super::{BABE_ENGINE_ID, AuthoritySignature, BabeEpochConfiguration}; use super::{AuthorityId, AuthorityIndex, SlotNumber, BabeAuthorityWeight}; #[cfg(feature = "std")] use sp_runtime::{DigestItem, generic::OpaqueDigestItemId}; @@ -135,7 +135,7 @@ impl TryFrom for PreDigest { /// Information about the next epoch. This is broadcast in the first block /// of the epoch. -#[derive(Decode, Encode, Default, PartialEq, Eq, Clone, RuntimeDebug)] +#[derive(Decode, Encode, PartialEq, Eq, Clone, RuntimeDebug)] pub struct NextEpochDescriptor { /// The authorities. pub authorities: Vec<(AuthorityId, BabeAuthorityWeight)>, @@ -144,6 +144,10 @@ pub struct NextEpochDescriptor { pub randomness: Randomness, } +/// Information about the next epoch config, if changed. This is broadcast in the first +/// block of the epoch, and applies using the same rules as `NextEpochDescriptor`. +pub type NextConfigDescriptor = BabeEpochConfiguration; + /// A digest item which is usable with BABE consensus. #[cfg(feature = "std")] pub trait CompatibleDigestItem: Sized { @@ -159,8 +163,11 @@ pub trait CompatibleDigestItem: Sized { /// If this item is a BABE signature, return the signature. fn as_babe_seal(&self) -> Option; - /// If this item is a BABE epoch, return it. + /// If this item is a BABE epoch descriptor, return it. fn as_next_epoch_descriptor(&self) -> Option; + + /// If this item is a BABE config descriptor, return it. + fn as_next_config_descriptor(&self) -> Option; } #[cfg(feature = "std")] @@ -190,4 +197,12 @@ impl CompatibleDigestItem for DigestItem where _ => None, }) } + + fn as_next_config_descriptor(&self) -> Option { + self.try_to(OpaqueDigestItemId::Consensus(&BABE_ENGINE_ID)) + .and_then(|x: super::ConsensusLog| match x { + super::ConsensusLog::NextConfigData(n) => Some(n), + _ => None, + }) + } } diff --git a/primitives/consensus/babe/src/lib.rs b/primitives/consensus/babe/src/lib.rs index 9e7f9cad9d153..37109b69be791 100644 --- a/primitives/consensus/babe/src/lib.rs +++ b/primitives/consensus/babe/src/lib.rs @@ -29,7 +29,7 @@ pub use sp_consensus_vrf::schnorrkel::{ use codec::{Encode, Decode}; use sp_std::vec::Vec; use sp_runtime::{ConsensusEngineId, RuntimeDebug}; -use crate::digests::NextEpochDescriptor; +use crate::digests::{NextEpochDescriptor, NextConfigDescriptor}; mod app { use sp_application_crypto::{app_crypto, key_types::BABE, sr25519}; @@ -87,20 +87,41 @@ pub enum ConsensusLog { /// Disable the authority with given index. #[codec(index = "2")] OnDisabled(AuthorityIndex), + /// The epoch has changed, and the epoch after the current one will + /// enact different epoch configurations. + #[codec(index = "3")] + NextConfigData(NextConfigDescriptor), } -/// Genesis configuration data used by the BABE consensus engine. +/// Configuration data used by the BABE consensus engine. #[derive(Clone, PartialEq, Eq, Encode, Decode, RuntimeDebug)] pub struct BabeGenesisConfiguration { /// The slot duration in milliseconds for BABE. Currently, only /// the value provided by this type at genesis will be used. + /// + /// Dynamic slot duration may be supported in the future. pub slot_duration: u64, + /// The duration of epochs in slots. + pub epoch_length: SlotNumber, + + /// A constant value that is used in the threshold calculation formula. + /// Expressed as a rational where the first member of the tuple is the + /// numerator and the second is the denominator. The rational should + /// represent a value between 0 and 1. + /// In the threshold formula calculation, `1 - c` represents the probability + /// of a slot being empty. + pub c: (u64, u64), + /// The authorities for the genesis epoch. pub genesis_authorities: Vec<(AuthorityId, BabeAuthorityWeight)>, /// The randomness for the genesis epoch. pub randomness: Randomness, + + /// Whether this chain should run with secondary slots, which are assigned + /// in round-robin manner. + pub secondary_slots: bool, } #[cfg(feature = "std")] @@ -115,9 +136,6 @@ impl sp_consensus::SlotData for BabeGenesisConfiguration { /// Configuration data used by the BABE consensus engine. #[derive(Clone, PartialEq, Eq, Encode, Decode, RuntimeDebug)] pub struct BabeEpochConfiguration { - /// The duration of epochs in slots. - pub epoch_length: SlotNumber, - /// A constant value that is used in the threshold calculation formula. /// Expressed as a rational where the first member of the tuple is the /// numerator and the second is the denominator. The rational should @@ -134,11 +152,8 @@ pub struct BabeEpochConfiguration { sp_api::decl_runtime_apis! { /// API necessary for block authorship with BABE. pub trait BabeApi { - /// Return the epoch configuration for BABE. The configuration is read once every epoch. - fn epoch_configuration() -> BabeEpochConfiguration; - /// Return the genesis configuration for BABE. The configuration is only read on genesis. - fn genesis_configuration() -> BabeGenesisConfiguration; + fn configuration() -> BabeGenesisConfiguration; /// Returns the slot number that started the current epoch. fn current_epoch_start() -> SlotNumber; From 559b8959b880a6be3c36594ffde76198e739a4e6 Mon Sep 17 00:00:00 2001 From: Wei Tang Date: Tue, 7 Apr 2020 18:10:01 +0200 Subject: [PATCH 10/24] Fix tests --- bin/node/runtime/src/lib.rs | 6 +++--- client/consensus/babe/rpc/src/lib.rs | 4 ++-- client/consensus/babe/src/aux_schema.rs | 5 +++++ client/consensus/babe/src/lib.rs | 3 +-- client/consensus/babe/src/tests.rs | 16 ++++++++++------ primitives/consensus/babe/src/digests.rs | 4 ++-- test-utils/runtime/src/lib.rs | 8 ++++---- 7 files changed, 27 insertions(+), 19 deletions(-) diff --git a/bin/node/runtime/src/lib.rs b/bin/node/runtime/src/lib.rs index 483c8c6c97e47..ee67a2e32614f 100644 --- a/bin/node/runtime/src/lib.rs +++ b/bin/node/runtime/src/lib.rs @@ -129,7 +129,7 @@ pub const VERSION: RuntimeVersion = RuntimeVersion { // implementation changes and behavior does not, then leave spec_version as // is and increment impl_version. spec_version: 240, - impl_version: 1, + impl_version: 2, apis: RUNTIME_API_VERSIONS, }; @@ -782,13 +782,13 @@ impl_runtime_apis! { } impl sp_consensus_babe::BabeApi for Runtime { - fn configuration() -> sp_consensus_babe::BabeConfiguration { + fn configuration() -> sp_consensus_babe::BabeGenesisConfiguration { // The choice of `c` parameter (where `1 - c` represents the // probability of a slot being empty), is done in accordance to the // slot duration and expected target block time, for safely // resisting network delays of maximum two seconds. // - sp_consensus_babe::BabeConfiguration { + sp_consensus_babe::BabeGenesisConfiguration { slot_duration: Babe::slot_duration(), epoch_length: EpochDuration::get(), c: PRIMARY_PROBABILITY, diff --git a/client/consensus/babe/rpc/src/lib.rs b/client/consensus/babe/rpc/src/lib.rs index cb78504b1f788..296b5cf237869 100644 --- a/client/consensus/babe/rpc/src/lib.rs +++ b/client/consensus/babe/rpc/src/lib.rs @@ -118,7 +118,7 @@ impl BabeApi for BabeRPCHandler for slot_number in epoch_start..epoch_end { let epoch = epoch_data(&shared_epoch, &client, &babe_config, slot_number, &select_chain)?; - if let Some((claim, key)) = authorship::claim_slot(slot_number, &epoch, &babe_config, &keystore) { + if let Some((claim, key)) = authorship::claim_slot(slot_number, &epoch, &keystore) { match claim { PreDigest::Primary { .. } => { claims.entry(key.public()).or_default().primary.push(slot_number); @@ -184,7 +184,7 @@ fn epoch_data( &parent.hash(), parent.number().clone(), slot_number, - |slot| babe_config.genesis_epoch(slot), + |slot| Epoch::genesis(&babe_config, slot), ) .map_err(|e| Error::Consensus(ConsensusError::ChainLookup(format!("{:?}", e))))? .ok_or(Error::Consensus(ConsensusError::InvalidAuthoritiesSet)) diff --git a/client/consensus/babe/src/aux_schema.rs b/client/consensus/babe/src/aux_schema.rs index e014c8975acee..e7e858994ce68 100644 --- a/client/consensus/babe/src/aux_schema.rs +++ b/client/consensus/babe/src/aux_schema.rs @@ -136,6 +136,7 @@ mod test { use substrate_test_runtime_client; use sp_core::H256; use sp_runtime::traits::NumberFor; + use sp_consensus_babe::BabeEpochConfiguration; use sc_consensus_epochs::{PersistedEpoch, PersistedEpochHeader, EpochHeader}; use sp_consensus::Error as ConsensusError; use sc_network_test::Block as TestBlock; @@ -148,6 +149,10 @@ mod test { randomness: [0; 32], epoch_index: 1, duration: 100, + config: BabeEpochConfiguration { + c: (3, 10), + secondary_slots: true, + }, }; let client = substrate_test_runtime_client::new(); let mut v0_tree = ForkTree::, _>::new(); diff --git a/client/consensus/babe/src/lib.rs b/client/consensus/babe/src/lib.rs index 25324c1d9122c..544c874bcb796 100644 --- a/client/consensus/babe/src/lib.rs +++ b/client/consensus/babe/src/lib.rs @@ -1305,13 +1305,12 @@ pub mod test_helpers { &parent.hash(), parent.number().clone(), slot_number, - |slot| link.config.genesis_epoch(slot), + |slot| Epoch::genesis(&link.config, slot), ).unwrap().unwrap(); authorship::claim_slot( slot_number, &epoch, - &link.config, keystore, ).map(|(digest, _)| digest) } diff --git a/client/consensus/babe/src/tests.rs b/client/consensus/babe/src/tests.rs index 20b924669d614..3c433b4030586 100644 --- a/client/consensus/babe/src/tests.rs +++ b/client/consensus/babe/src/tests.rs @@ -127,7 +127,7 @@ impl DummyProposer { &self.parent_hash, self.parent_number, this_slot, - |slot| self.factory.config.genesis_epoch(slot), + |slot| Epoch::genesis(&self.factory.config, slot), ) .expect("client has data to find epoch") .expect("can compute epoch for baked block"); @@ -505,9 +505,13 @@ fn can_author_block() { randomness: [0; 32], epoch_index: 1, duration: 100, + config: BabeEpochConfiguration { + c: (3, 10), + secondary_slots: true, + }, }; - let mut config = crate::BabeConfiguration { + let mut config = crate::BabeGenesisConfiguration { slot_duration: 1000, epoch_length: 100, c: (3, 10), @@ -517,7 +521,7 @@ fn can_author_block() { }; // with secondary slots enabled it should never be empty - match claim_slot(i, &epoch, &config, &keystore) { + match claim_slot(i, &epoch, &keystore) { None => i += 1, Some(s) => debug!(target: "babe", "Authored block {:?}", s.0), } @@ -526,7 +530,7 @@ fn can_author_block() { // of times. config.secondary_slots = false; loop { - match claim_slot(i, &epoch, &config, &keystore) { + match claim_slot(i, &epoch, &keystore) { None => i += 1, Some(s) => { debug!(target: "babe", "Authored block {:?}", s.0); @@ -632,7 +636,7 @@ fn importing_block_one_sets_genesis_epoch() { &mut block_import, ); - let genesis_epoch = data.link.config.genesis_epoch(999); + let genesis_epoch = Epoch::genesis(&data.link.config, 999); let epoch_changes = data.link.epoch_changes.lock(); let epoch_for_second_block = epoch_changes.epoch_data_for_child_of( @@ -640,7 +644,7 @@ fn importing_block_one_sets_genesis_epoch() { &block_hash, 1, 1000, - |slot| data.link.config.genesis_epoch(slot), + |slot| Epoch::genesis(&data.link.config, slot), ).unwrap().unwrap(); assert_eq!(epoch_for_second_block, genesis_epoch); diff --git a/primitives/consensus/babe/src/digests.rs b/primitives/consensus/babe/src/digests.rs index 50eca40a5e578..291b32cf49948 100644 --- a/primitives/consensus/babe/src/digests.rs +++ b/primitives/consensus/babe/src/digests.rs @@ -17,8 +17,8 @@ //! Private implementation details of BABE digests. #[cfg(feature = "std")] -use super::{BABE_ENGINE_ID, AuthoritySignature, BabeEpochConfiguration}; -use super::{AuthorityId, AuthorityIndex, SlotNumber, BabeAuthorityWeight}; +use super::{BABE_ENGINE_ID, AuthoritySignature}; +use super::{AuthorityId, AuthorityIndex, SlotNumber, BabeAuthorityWeight, BabeEpochConfiguration}; #[cfg(feature = "std")] use sp_runtime::{DigestItem, generic::OpaqueDigestItemId}; #[cfg(feature = "std")] diff --git a/test-utils/runtime/src/lib.rs b/test-utils/runtime/src/lib.rs index f3efb4bea7c76..815695a6ee7bd 100644 --- a/test-utils/runtime/src/lib.rs +++ b/test-utils/runtime/src/lib.rs @@ -618,8 +618,8 @@ cfg_if! { } impl sp_consensus_babe::BabeApi for Runtime { - fn configuration() -> sp_consensus_babe::BabeConfiguration { - sp_consensus_babe::BabeConfiguration { + fn configuration() -> sp_consensus_babe::BabeGenesisConfiguration { + sp_consensus_babe::BabeGenesisConfiguration { slot_duration: 1000, epoch_length: EpochDuration::get(), c: (3, 10), @@ -812,8 +812,8 @@ cfg_if! { } impl sp_consensus_babe::BabeApi for Runtime { - fn configuration() -> sp_consensus_babe::BabeConfiguration { - sp_consensus_babe::BabeConfiguration { + fn configuration() -> sp_consensus_babe::BabeGenesisConfiguration { + sp_consensus_babe::BabeGenesisConfiguration { slot_duration: 1000, epoch_length: EpochDuration::get(), c: (3, 10), From 682e3b71296e17838f8608664002c600f245c0ea Mon Sep 17 00:00:00 2001 From: Wei Tang Date: Wed, 8 Apr 2020 16:17:01 +0200 Subject: [PATCH 11/24] epoch-changes: map function that allows converting with different epoch types --- client/consensus/epochs/src/lib.rs | 49 ++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) diff --git a/client/consensus/epochs/src/lib.rs b/client/consensus/epochs/src/lib.rs index 001c172b34905..acb07dd668a3c 100644 --- a/client/consensus/epochs/src/lib.rs +++ b/client/consensus/epochs/src/lib.rs @@ -335,6 +335,55 @@ impl EpochChanges where self.inner.rebalance() } + /// Map the epoch changes from one storing data to a different one. + pub fn map(self, mut f: F) -> EpochChanges where + B: Epoch, + F: FnMut(&Hash, &Number, E) -> B, + { + EpochChanges { + inner: self.inner.map(&mut |_, _, header| { + match header { + PersistedEpochHeader::Genesis(epoch_0, epoch_1) => { + PersistedEpochHeader::Genesis( + EpochHeader { + start_slot: epoch_0.start_slot, + end_slot: epoch_0.end_slot, + }, + EpochHeader { + start_slot: epoch_1.start_slot, + end_slot: epoch_1.end_slot, + }, + ) + }, + PersistedEpochHeader::Regular(epoch_n) => { + PersistedEpochHeader::Regular( + EpochHeader { + start_slot: epoch_n.start_slot, + end_slot: epoch_n.end_slot, + }, + ) + }, + } + }), + epochs: self.epochs.into_iter().map(|((hash, number), epoch)| { + let bepoch = match epoch { + PersistedEpoch::Genesis(epoch_0, epoch_1) => { + PersistedEpoch::Genesis( + f(&hash, &number, epoch_0), + f(&hash, &number, epoch_1), + ) + }, + PersistedEpoch::Regular(epoch_n) => { + PersistedEpoch::Regular( + f(&hash, &number, epoch_n) + ) + }, + }; + ((hash, number), bepoch) + }).collect(), + } + } + /// Prune out finalized epochs, except for the ancestor of the finalized /// block. The given slot should be the slot number at which the finalized /// block was authored. From fc8d9fe56b187de0865344ead360e0603721d6df Mon Sep 17 00:00:00 2001 From: Wei Tang Date: Wed, 8 Apr 2020 16:29:05 +0200 Subject: [PATCH 12/24] Add migration script for the epoch config change --- client/consensus/babe/src/aux_schema.rs | 15 ++++-- client/consensus/babe/src/lib.rs | 3 +- client/consensus/babe/src/migration.rs | 64 +++++++++++++++++++++++++ 3 files changed, 76 insertions(+), 6 deletions(-) create mode 100644 client/consensus/babe/src/migration.rs diff --git a/client/consensus/babe/src/aux_schema.rs b/client/consensus/babe/src/aux_schema.rs index e7e858994ce68..ab34ccea1d517 100644 --- a/client/consensus/babe/src/aux_schema.rs +++ b/client/consensus/babe/src/aux_schema.rs @@ -24,13 +24,13 @@ use codec::{Decode, Encode}; use sc_client_api::backend::AuxStore; use sp_blockchain::{Result as ClientResult, Error as ClientError}; use sp_runtime::traits::Block as BlockT; -use sp_consensus_babe::BabeBlockWeight; +use sp_consensus_babe::{BabeBlockWeight, BabeGenesisConfiguration}; use sc_consensus_epochs::{EpochChangesFor, SharedEpochChanges, migration::EpochChangesForV0}; -use crate::Epoch; +use crate::{Epoch, migration::EpochV0}; const BABE_EPOCH_CHANGES_VERSION: &[u8] = b"babe_epoch_changes_version"; const BABE_EPOCH_CHANGES_KEY: &[u8] = b"babe_epoch_changes"; -const BABE_EPOCH_CHANGES_CURRENT_VERSION: u32 = 1; +const BABE_EPOCH_CHANGES_CURRENT_VERSION: u32 = 2; fn block_weight_key(block_hash: H) -> Vec { (b"block_weight", block_hash).encode() @@ -53,14 +53,19 @@ fn load_decode(backend: &B, key: &[u8]) -> ClientResult> /// Load or initialize persistent epoch change data from backend. pub(crate) fn load_epoch_changes( backend: &B, + config: &BabeGenesisConfiguration, ) -> ClientResult> { let version = load_decode::<_, u32>(backend, BABE_EPOCH_CHANGES_VERSION)?; let maybe_epoch_changes = match version { - None => load_decode::<_, EpochChangesForV0>( + None => load_decode::<_, EpochChangesForV0>( backend, BABE_EPOCH_CHANGES_KEY, - )?.map(|v0| v0.migrate()), + )?.map(|v0| v0.migrate().map(|_, _, epoch| epoch.migrate(config))), + Some(1) => load_decode::<_, EpochChangesFor>( + backend, + BABE_EPOCH_CHANGES_KEY, + )?.map(|v1| v1.map(|_, _, epoch| epoch.migrate(config))), Some(BABE_EPOCH_CHANGES_CURRENT_VERSION) => load_decode::<_, EpochChangesFor>( backend, BABE_EPOCH_CHANGES_KEY, diff --git a/client/consensus/babe/src/lib.rs b/client/consensus/babe/src/lib.rs index 544c874bcb796..e32fdd31770b6 100644 --- a/client/consensus/babe/src/lib.rs +++ b/client/consensus/babe/src/lib.rs @@ -120,6 +120,7 @@ use sp_api::ApiExt; mod aux_schema; mod verification; +mod migration; pub mod authorship; #[cfg(test)] mod tests; @@ -1212,7 +1213,7 @@ pub fn block_import( ) -> ClientResult<(BabeBlockImport, BabeLink)> where Client: AuxStore + HeaderBackend + HeaderMetadata, { - let epoch_changes = aux_schema::load_epoch_changes::(&*client)?; + let epoch_changes = aux_schema::load_epoch_changes::(&*client, &config)?; let link = BabeLink { epoch_changes: epoch_changes.clone(), time_source: Default::default(), diff --git a/client/consensus/babe/src/migration.rs b/client/consensus/babe/src/migration.rs new file mode 100644 index 0000000000000..837704abb1b5a --- /dev/null +++ b/client/consensus/babe/src/migration.rs @@ -0,0 +1,64 @@ +use codec::{Encode, Decode}; +use sc_consensus_epochs::Epoch as EpochT; +use crate::{ + Epoch, SlotNumber, AuthorityId, BabeAuthorityWeight, BabeGenesisConfiguration, + BabeEpochConfiguration, VRF_OUTPUT_LENGTH, NextEpochDescriptor, +}; + +/// BABE epoch information, version 0. +#[derive(Decode, Encode, PartialEq, Eq, Clone, Debug)] +pub struct EpochV0 { + /// The epoch index. + pub epoch_index: u64, + /// The starting slot of the epoch. + pub start_slot: SlotNumber, + /// The duration of this epoch. + pub duration: SlotNumber, + /// The authorities and their weights. + pub authorities: Vec<(AuthorityId, BabeAuthorityWeight)>, + /// Randomness for this epoch. + pub randomness: [u8; VRF_OUTPUT_LENGTH], +} + +impl EpochT for EpochV0 { + type NextEpochDescriptor = NextEpochDescriptor; + type SlotNumber = SlotNumber; + + fn increment( + &self, + descriptor: NextEpochDescriptor + ) -> EpochV0 { + EpochV0 { + epoch_index: self.epoch_index + 1, + start_slot: self.start_slot + self.duration, + duration: self.duration, + authorities: descriptor.authorities, + randomness: descriptor.randomness, + } + } + + fn start_slot(&self) -> SlotNumber { + self.start_slot + } + + fn end_slot(&self) -> SlotNumber { + self.start_slot + self.duration + } +} + +impl EpochV0 { + /// Migrate the sturct to current epoch version. + pub fn migrate(self, config: &BabeGenesisConfiguration) -> Epoch { + Epoch { + epoch_index: self.epoch_index, + start_slot: self.start_slot, + duration: self.duration, + authorities: self.authorities, + randomness: self.randomness, + config: BabeEpochConfiguration { + c: config.c, + secondary_slots: config.secondary_slots, + }, + } + } +} From 0c52d85010fe7a40b5cc80e28e2f09556cb01452 Mon Sep 17 00:00:00 2001 From: Wei Tang Date: Mon, 20 Apr 2020 00:46:29 +0200 Subject: [PATCH 13/24] Fix docs for PrimaryAndSecondaryVRFSlots --- primitives/consensus/babe/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/primitives/consensus/babe/src/lib.rs b/primitives/consensus/babe/src/lib.rs index c07abc41765a0..33270a0a8c970 100644 --- a/primitives/consensus/babe/src/lib.rs +++ b/primitives/consensus/babe/src/lib.rs @@ -174,7 +174,7 @@ pub enum AllowedSlots { PrimarySlots, /// Allow primary and secondary slots, but disallow secondary VRF slots. PrimaryAndSecondarySlots, - /// Allow primary and secondary slots. Enable secondary VRF slots after slot number. + /// Allow primary and secondary VRF slots. PrimaryAndSecondaryVRFSlots, } From d825d457442ab750348e3ae2232ab8646a891ffc Mon Sep 17 00:00:00 2001 From: Wei Tang Date: Mon, 20 Apr 2020 15:19:12 +0200 Subject: [PATCH 14/24] Add docs of `SecondaryVRF` in babe crate --- client/consensus/babe/src/lib.rs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/client/consensus/babe/src/lib.rs b/client/consensus/babe/src/lib.rs index b9e197ece76cd..809744c04f374 100644 --- a/client/consensus/babe/src/lib.rs +++ b/client/consensus/babe/src/lib.rs @@ -49,6 +49,11 @@ //! //! `blake2_256(epoch_randomness ++ slot_number) % authorities_len`. //! +//! The secondary slots supports either a `SecondaryPlain` or `SecondaryVRF` +//! variant. Comparing with `SecondaryPlain` variant, the `SecondaryVRF` variant +//! generates an additional VRF output. The output is not included in beacon +//! randomness, but can be consumed by parachains. +//! //! The fork choice rule is weight-based, where weight equals the number of //! primary blocks in the chain. We will pick the heaviest chain (more primary //! blocks) and will go with the longest one in case of a tie. @@ -1027,7 +1032,7 @@ impl BlockImport for BabeBlockImport= start slot {}).", viable_epoch.as_ref().epoch_index, hash, From df540a4994e3550c4d35efe1b8efa0101a874372 Mon Sep 17 00:00:00 2001 From: Wei Tang Date: Mon, 20 Apr 2020 15:28:11 +0200 Subject: [PATCH 15/24] babe-primitives: Secondary -> SecondaryPlain --- primitives/consensus/babe/src/digests.rs | 12 ++++++------ primitives/consensus/babe/src/lib.rs | 8 ++++---- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/primitives/consensus/babe/src/digests.rs b/primitives/consensus/babe/src/digests.rs index 05e7a22a195f8..1df987e7c0307 100644 --- a/primitives/consensus/babe/src/digests.rs +++ b/primitives/consensus/babe/src/digests.rs @@ -65,7 +65,7 @@ impl TryFrom for PrimaryPreDigest { /// BABE secondary slot assignment pre-digest. #[derive(Clone, RuntimeDebug, Encode, Decode)] -pub struct SecondaryPreDigest { +pub struct SecondaryPlainPreDigest { /// Authority index /// /// This is not strictly-speaking necessary, since the secondary slots @@ -118,7 +118,7 @@ pub enum RawPreDigest), /// A secondary deterministic slot assignment. #[codec(index = "2")] - Secondary(SecondaryPreDigest), + SecondaryPlain(SecondaryPlainPreDigest), /// A secondary deterministic slot assignment with VRF outputs. #[codec(index = "3")] SecondaryVRF(RawSecondaryVRFPreDigest), @@ -133,7 +133,7 @@ impl RawPreDigest { pub fn authority_index(&self) -> AuthorityIndex { match self { RawPreDigest::Primary(primary) => primary.authority_index, - RawPreDigest::Secondary(secondary) => secondary.authority_index, + RawPreDigest::SecondaryPlain(secondary) => secondary.authority_index, RawPreDigest::SecondaryVRF(secondary) => secondary.authority_index, } } @@ -142,7 +142,7 @@ impl RawPreDigest { pub fn slot_number(&self) -> SlotNumber { match self { RawPreDigest::Primary(primary) => primary.slot_number, - RawPreDigest::Secondary(secondary) => secondary.slot_number, + RawPreDigest::SecondaryPlain(secondary) => secondary.slot_number, RawPreDigest::SecondaryVRF(secondary) => secondary.slot_number, } } @@ -152,7 +152,7 @@ impl RawPreDigest { pub fn added_weight(&self) -> crate::BabeBlockWeight { match self { RawPreDigest::Primary(_) => 1, - RawPreDigest::Secondary(_) | RawPreDigest::SecondaryVRF(_) => 0, + RawPreDigest::SecondaryPlain(_) | RawPreDigest::SecondaryVRF(_) => 0, } } } @@ -164,7 +164,7 @@ impl TryFrom for PreDigest { fn try_from(raw: RawPreDigest) -> Result { Ok(match raw { RawPreDigest::Primary(primary) => PreDigest::Primary(primary.try_into()?), - RawPreDigest::Secondary(secondary) => PreDigest::Secondary(secondary), + RawPreDigest::SecondaryPlain(secondary) => PreDigest::SecondaryPlain(secondary), RawPreDigest::SecondaryVRF(secondary) => PreDigest::SecondaryVRF(secondary.try_into()?), }) } diff --git a/primitives/consensus/babe/src/lib.rs b/primitives/consensus/babe/src/lib.rs index 33270a0a8c970..3f3d973a9b42f 100644 --- a/primitives/consensus/babe/src/lib.rs +++ b/primitives/consensus/babe/src/lib.rs @@ -129,7 +129,7 @@ impl From for BabeConfiguration { genesis_authorities: v1.genesis_authorities, randomness: v1.randomness, allowed_slots: if v1.secondary_slots { - AllowedSlots::PrimaryAndSecondarySlots + AllowedSlots::PrimaryAndSecondaryPlainSlots } else { AllowedSlots::PrimarySlots }, @@ -172,8 +172,8 @@ pub struct BabeConfiguration { pub enum AllowedSlots { /// Only allow primary slots. PrimarySlots, - /// Allow primary and secondary slots, but disallow secondary VRF slots. - PrimaryAndSecondarySlots, + /// Allow primary and secondary plain slots. + PrimaryAndSecondaryPlainSlots, /// Allow primary and secondary VRF slots. PrimaryAndSecondaryVRFSlots, } @@ -181,7 +181,7 @@ pub enum AllowedSlots { impl AllowedSlots { /// Whether plain secondary slots are allowed. pub fn is_secondary_slots_allowed(&self) -> bool { - *self == Self::PrimaryAndSecondarySlots + *self == Self::PrimaryAndSecondaryPlainSlots } /// Whether VRF secondary slots are allowed. From 42360ec096e93e3a388ce92f8e65cc0ea3bd86a4 Mon Sep 17 00:00:00 2001 From: Wei Tang Date: Mon, 20 Apr 2020 15:35:43 +0200 Subject: [PATCH 16/24] babe-client: Secondary -> SecondaryPlain --- bin/node/runtime/src/lib.rs | 2 +- client/consensus/babe/rpc/src/lib.rs | 2 +- client/consensus/babe/src/authorship.rs | 4 ++-- client/consensus/babe/src/lib.rs | 5 +++-- client/consensus/babe/src/tests.rs | 4 ++-- client/consensus/babe/src/verification.rs | 12 ++++++------ 6 files changed, 15 insertions(+), 14 deletions(-) diff --git a/bin/node/runtime/src/lib.rs b/bin/node/runtime/src/lib.rs index 16451e3ddeea2..c61ffcebe465f 100644 --- a/bin/node/runtime/src/lib.rs +++ b/bin/node/runtime/src/lib.rs @@ -801,7 +801,7 @@ impl_runtime_apis! { c: PRIMARY_PROBABILITY, genesis_authorities: Babe::authorities(), randomness: Babe::randomness(), - allowed_slots: sp_consensus_babe::AllowedSlots::PrimaryAndSecondarySlots, + allowed_slots: sp_consensus_babe::AllowedSlots::PrimaryAndSecondaryPlainSlots, } } diff --git a/client/consensus/babe/rpc/src/lib.rs b/client/consensus/babe/rpc/src/lib.rs index b334ce6280133..b7507dc39c291 100644 --- a/client/consensus/babe/rpc/src/lib.rs +++ b/client/consensus/babe/rpc/src/lib.rs @@ -123,7 +123,7 @@ impl BabeApi for BabeRPCHandler PreDigest::Primary { .. } => { claims.entry(key.public()).or_default().primary.push(slot_number); } - PreDigest::Secondary { .. } => { + PreDigest::SecondaryPlain { .. } => { claims.entry(key.public()).or_default().secondary.push(slot_number); } PreDigest::SecondaryVRF { .. } => { diff --git a/client/consensus/babe/src/authorship.rs b/client/consensus/babe/src/authorship.rs index 98e57bc27aac5..4758a56404341 100644 --- a/client/consensus/babe/src/authorship.rs +++ b/client/consensus/babe/src/authorship.rs @@ -22,7 +22,7 @@ use sp_consensus_babe::{ SlotNumber, AuthorityPair, BabeConfiguration }; use sp_consensus_babe::digests::{ - PreDigest, PrimaryPreDigest, SecondaryPreDigest, SecondaryVRFPreDigest, + PreDigest, PrimaryPreDigest, SecondaryPlainPreDigest, SecondaryVRFPreDigest, }; use sp_consensus_vrf::schnorrkel::{VRFOutput, VRFProof}; use sp_core::{U256, blake2_256}; @@ -148,7 +148,7 @@ fn claim_secondary_slot( authority_index: authority_index as u32, }) } else { - PreDigest::Secondary(SecondaryPreDigest { + PreDigest::SecondaryPlain(SecondaryPlainPreDigest { slot_number, authority_index: authority_index as u32, }) diff --git a/client/consensus/babe/src/lib.rs b/client/consensus/babe/src/lib.rs index 809744c04f374..d93c9ecdd379b 100644 --- a/client/consensus/babe/src/lib.rs +++ b/client/consensus/babe/src/lib.rs @@ -68,7 +68,8 @@ pub use sp_consensus_babe::{ AuthorityId, AuthorityPair, AuthoritySignature, BabeAuthorityWeight, VRF_OUTPUT_LENGTH, digests::{ - CompatibleDigestItem, NextEpochDescriptor, PreDigest, PrimaryPreDigest, SecondaryPreDigest, + CompatibleDigestItem, NextEpochDescriptor, PreDigest, PrimaryPreDigest, + SecondaryPlainPreDigest, }, }; pub use sp_consensus::SyncOracle; @@ -596,7 +597,7 @@ fn find_pre_digest(header: &B::Header) -> Result> // genesis block doesn't contain a pre digest so let's generate a // dummy one to not break any invariants in the rest of the code if header.number().is_zero() { - return Ok(PreDigest::Secondary(SecondaryPreDigest { + return Ok(PreDigest::SecondaryPlain(SecondaryPlainPreDigest { slot_number: 0, authority_index: 0, })); diff --git a/client/consensus/babe/src/tests.rs b/client/consensus/babe/src/tests.rs index 4912c13cfe45d..230629e1c3383 100644 --- a/client/consensus/babe/src/tests.rs +++ b/client/consensus/babe/src/tests.rs @@ -513,7 +513,7 @@ fn can_author_block() { c: (3, 10), genesis_authorities: Vec::new(), randomness: [0; 32], - allowed_slots: AllowedSlots::PrimaryAndSecondarySlots, + allowed_slots: AllowedSlots::PrimaryAndSecondaryPlainSlots, }; // with secondary slots enabled it should never be empty @@ -553,7 +553,7 @@ fn propose_and_import_block( let pre_digest = sp_runtime::generic::Digest { logs: vec![ Item::babe_pre_digest( - PreDigest::Secondary(SecondaryPreDigest { + PreDigest::SecondaryPlain(SecondaryPlainPreDigest { authority_index: 0, slot_number, }), diff --git a/client/consensus/babe/src/verification.rs b/client/consensus/babe/src/verification.rs index f82c1894df925..432cc160fa5e9 100644 --- a/client/consensus/babe/src/verification.rs +++ b/client/consensus/babe/src/verification.rs @@ -19,7 +19,7 @@ use sp_runtime::{traits::Header, traits::DigestItemFor}; use sp_core::{Pair, Public}; use sp_consensus_babe::{AuthoritySignature, SlotNumber, AuthorityPair, AuthorityId}; use sp_consensus_babe::digests::{ - PreDigest, PrimaryPreDigest, SecondaryPreDigest, SecondaryVRFPreDigest, + PreDigest, PrimaryPreDigest, SecondaryPlainPreDigest, SecondaryVRFPreDigest, CompatibleDigestItem }; use sc_consensus_slots::CheckedHeader; @@ -106,10 +106,10 @@ pub(super) fn check_header( config.c, )?; }, - PreDigest::Secondary(secondary) if config.allowed_slots.is_secondary_slots_allowed() => { - debug!(target: "babe", "Verifying Secondary block"); + PreDigest::SecondaryPlain(secondary) if config.allowed_slots.is_secondary_slots_allowed() => { + debug!(target: "babe", "Verifying Secondary plain block"); - check_secondary_header::( + check_secondary_plain_header::( pre_hash, secondary, sig, @@ -193,9 +193,9 @@ fn check_primary_header( /// properly signed by the expected authority, which we have a deterministic way /// of computing. Additionally, the weight of this block must stay the same /// compared to its parent since it is a secondary block. -fn check_secondary_header( +fn check_secondary_plain_header( pre_hash: B::Hash, - pre_digest: &SecondaryPreDigest, + pre_digest: &SecondaryPlainPreDigest, signature: AuthoritySignature, epoch: &Epoch, ) -> Result<(), Error> { From 5144e80c8c76da1a2a5f452795e75d897b034f1c Mon Sep 17 00:00:00 2001 From: Wei Tang Date: Mon, 20 Apr 2020 15:40:11 +0200 Subject: [PATCH 17/24] Fix migration tests --- client/consensus/babe/src/aux_schema.rs | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/client/consensus/babe/src/aux_schema.rs b/client/consensus/babe/src/aux_schema.rs index ab34ccea1d517..3ad877c465c03 100644 --- a/client/consensus/babe/src/aux_schema.rs +++ b/client/consensus/babe/src/aux_schema.rs @@ -141,7 +141,7 @@ mod test { use substrate_test_runtime_client; use sp_core::H256; use sp_runtime::traits::NumberFor; - use sp_consensus_babe::BabeEpochConfiguration; + use sp_consensus_babe::{BabeEpochConfiguration, BabeGenesisConfiguration}; use sc_consensus_epochs::{PersistedEpoch, PersistedEpochHeader, EpochHeader}; use sp_consensus::Error as ConsensusError; use sc_network_test::Block as TestBlock; @@ -179,7 +179,16 @@ mod test { None, ); - let epoch_changes = load_epoch_changes::(&client).unwrap(); + let epoch_changes = load_epoch_changes::( + &client, &BabeGenesisConfiguration { + slot_duration: 10, + epoch_length: 4, + c: (3, 10), + genesis_authorities: Vec::new(), + randomness: Default::default(), + secondary_slots: true, + }, + ).unwrap(); assert!( epoch_changes.lock() From e049b81b9a9b1bad3f0c7dfe4208895d242c7925 Mon Sep 17 00:00:00 2001 From: Wei Tang Date: Mon, 20 Apr 2020 15:45:18 +0200 Subject: [PATCH 18/24] test-utils-runtime: Secondary -> SecondaryPlain --- test-utils/runtime/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test-utils/runtime/src/lib.rs b/test-utils/runtime/src/lib.rs index 44877fc6c7003..a850e93deb23b 100644 --- a/test-utils/runtime/src/lib.rs +++ b/test-utils/runtime/src/lib.rs @@ -836,7 +836,7 @@ cfg_if! { genesis_authorities: system::authorities() .into_iter().map(|x|(x, 1)).collect(), randomness: >::randomness(), - allowed_slots: AllowedSlots::PrimaryAndSecondarySlots, + allowed_slots: AllowedSlots::PrimaryAndSecondaryPlainSlots, } } From 904df0422f1cbade7bc585d4605a072022691ee9 Mon Sep 17 00:00:00 2001 From: Wei Tang Date: Mon, 20 Apr 2020 15:56:30 +0200 Subject: [PATCH 19/24] Fix missing name change in test-utils-runtime --- test-utils/runtime/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test-utils/runtime/src/lib.rs b/test-utils/runtime/src/lib.rs index a850e93deb23b..d3afd6a98b011 100644 --- a/test-utils/runtime/src/lib.rs +++ b/test-utils/runtime/src/lib.rs @@ -642,7 +642,7 @@ cfg_if! { genesis_authorities: system::authorities() .into_iter().map(|x|(x, 1)).collect(), randomness: >::randomness(), - allowed_slots: AllowedSlots::PrimaryAndSecondarySlots, + allowed_slots: AllowedSlots::PrimaryAndSecondaryPlainSlots, } } From abba6a50ac49353a3695fc62ee0d04afcd761ea6 Mon Sep 17 00:00:00 2001 From: Wei Tang Date: Mon, 20 Apr 2020 16:24:03 +0200 Subject: [PATCH 20/24] Fix migration: Epoch should be EpochV0 --- client/consensus/babe/src/aux_schema.rs | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/client/consensus/babe/src/aux_schema.rs b/client/consensus/babe/src/aux_schema.rs index 3ad877c465c03..990f797857dfa 100644 --- a/client/consensus/babe/src/aux_schema.rs +++ b/client/consensus/babe/src/aux_schema.rs @@ -136,7 +136,7 @@ pub(crate) fn load_block_weight( #[cfg(test)] mod test { use super::*; - use crate::Epoch; + use crate::{Epoch, migration::EpochV0}; use fork_tree::ForkTree; use substrate_test_runtime_client; use sp_core::H256; @@ -148,16 +148,12 @@ mod test { #[test] fn load_decode_from_v0_epoch_changes() { - let epoch = Epoch { + let epoch = EpochV0 { start_slot: 0, authorities: vec![], randomness: [0; 32], epoch_index: 1, duration: 100, - config: BabeEpochConfiguration { - c: (3, 10), - secondary_slots: true, - }, }; let client = substrate_test_runtime_client::new(); let mut v0_tree = ForkTree::, _>::new(); @@ -170,7 +166,7 @@ mod test { client.insert_aux( &[(BABE_EPOCH_CHANGES_KEY, - &EpochChangesForV0::::from_raw(v0_tree).encode()[..])], + &EpochChangesForV0::::from_raw(v0_tree).encode()[..])], &[], ).unwrap(); From ee72297c94514610723de9d0a29b20ff38cc72ef Mon Sep 17 00:00:00 2001 From: Wei Tang Date: Tue, 21 Apr 2020 00:02:47 +0200 Subject: [PATCH 21/24] Update client/consensus/babe/src/lib.rs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: André Silva <123550+andresilva@users.noreply.github.com> --- client/consensus/babe/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/consensus/babe/src/lib.rs b/client/consensus/babe/src/lib.rs index 21fc1436d9b93..1dcb5c92b012a 100644 --- a/client/consensus/babe/src/lib.rs +++ b/client/consensus/babe/src/lib.rs @@ -1051,7 +1051,7 @@ impl BlockImport for BabeBlockImport::FetchEpoch(parent_hash).into()) })?; - let epoch_config = next_config_digest.unwrap_or_else( + let epoch_config = next_config_digest.unwrap_or_else( || viable_epoch.as_ref().config.clone() ); From 52bc6f9481c6f64bb96def3c75c1b2708c1e2d23 Mon Sep 17 00:00:00 2001 From: Wei Tang Date: Tue, 21 Apr 2020 00:03:23 +0200 Subject: [PATCH 22/24] Fix new epochChanges version --- client/consensus/babe/src/aux_schema.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/consensus/babe/src/aux_schema.rs b/client/consensus/babe/src/aux_schema.rs index 990f797857dfa..5adcb35ccfe58 100644 --- a/client/consensus/babe/src/aux_schema.rs +++ b/client/consensus/babe/src/aux_schema.rs @@ -207,7 +207,7 @@ mod test { assert_eq!( load_decode::<_, u32>(&client, BABE_EPOCH_CHANGES_VERSION).unwrap(), - Some(1), + Some(2), ); } } From 3b889a310b1ef5795a3835e54b1f442556e96c1f Mon Sep 17 00:00:00 2001 From: Wei Tang Date: Tue, 21 Apr 2020 00:13:56 +0200 Subject: [PATCH 23/24] Fix babe-primitives naming changes --- primitives/consensus/babe/src/lib.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/primitives/consensus/babe/src/lib.rs b/primitives/consensus/babe/src/lib.rs index bf473088c1ad7..2eb312acd1e48 100644 --- a/primitives/consensus/babe/src/lib.rs +++ b/primitives/consensus/babe/src/lib.rs @@ -124,8 +124,8 @@ pub struct BabeGenesisConfigurationV1 { pub secondary_slots: bool, } -impl From for BabeGenesisConfiguration { - fn from(v1: BabeConfigurationV1) -> Self { +impl From for BabeGenesisConfiguration { + fn from(v1: BabeGenesisConfigurationV1) -> Self { Self { slot_duration: v1.slot_duration, epoch_length: v1.epoch_length, @@ -228,7 +228,7 @@ sp_api::decl_runtime_apis! { /// Return the configuration for BABE. Version 1. #[changed_in(2)] - fn configuration() -> BabeConfigurationV1; + fn configuration() -> BabeGenesisConfigurationV1; /// Returns the slot number that started the current epoch. fn current_epoch_start() -> SlotNumber; From 6cf220ae8310abbf4dc013fa96503a2cb03786b8 Mon Sep 17 00:00:00 2001 From: Wei Tang Date: Tue, 21 Apr 2020 00:25:22 +0200 Subject: [PATCH 24/24] Fix merge issues in babe-client --- client/consensus/babe/src/authorship.rs | 6 +++--- client/consensus/babe/src/aux_schema.rs | 6 +++--- client/consensus/babe/src/lib.rs | 2 +- client/consensus/babe/src/migration.rs | 2 +- client/consensus/babe/src/tests.rs | 2 +- client/consensus/babe/src/verification.rs | 4 ++-- primitives/consensus/babe/src/lib.rs | 2 +- 7 files changed, 12 insertions(+), 12 deletions(-) diff --git a/client/consensus/babe/src/authorship.rs b/client/consensus/babe/src/authorship.rs index 722b4eee33bd5..1b4bf5683ec5f 100644 --- a/client/consensus/babe/src/authorship.rs +++ b/client/consensus/babe/src/authorship.rs @@ -172,14 +172,14 @@ pub fn claim_slot( ) -> Option<(PreDigest, AuthorityPair)> { claim_primary_slot(slot_number, epoch, epoch.config.c, keystore) .or_else(|| { - if config.allowed_slots.is_secondary_plain_slots_allowed() || - config.allowed_slots.is_secondary_vrf_slots_allowed() + if epoch.config.allowed_slots.is_secondary_plain_slots_allowed() || + epoch.config.allowed_slots.is_secondary_vrf_slots_allowed() { claim_secondary_slot( slot_number, &epoch, keystore, - config.allowed_slots.is_secondary_vrf_slots_allowed(), + epoch.config.allowed_slots.is_secondary_vrf_slots_allowed(), ) } else { None diff --git a/client/consensus/babe/src/aux_schema.rs b/client/consensus/babe/src/aux_schema.rs index 5adcb35ccfe58..2a3f23981dc30 100644 --- a/client/consensus/babe/src/aux_schema.rs +++ b/client/consensus/babe/src/aux_schema.rs @@ -136,12 +136,12 @@ pub(crate) fn load_block_weight( #[cfg(test)] mod test { use super::*; - use crate::{Epoch, migration::EpochV0}; + use crate::migration::EpochV0; use fork_tree::ForkTree; use substrate_test_runtime_client; use sp_core::H256; use sp_runtime::traits::NumberFor; - use sp_consensus_babe::{BabeEpochConfiguration, BabeGenesisConfiguration}; + use sp_consensus_babe::{AllowedSlots, BabeGenesisConfiguration}; use sc_consensus_epochs::{PersistedEpoch, PersistedEpochHeader, EpochHeader}; use sp_consensus::Error as ConsensusError; use sc_network_test::Block as TestBlock; @@ -182,7 +182,7 @@ mod test { c: (3, 10), genesis_authorities: Vec::new(), randomness: Default::default(), - secondary_slots: true, + allowed_slots: AllowedSlots::PrimaryAndSecondaryPlainSlots, }, ).unwrap(); diff --git a/client/consensus/babe/src/lib.rs b/client/consensus/babe/src/lib.rs index 5b8441d34a358..8813501eb0ee3 100644 --- a/client/consensus/babe/src/lib.rs +++ b/client/consensus/babe/src/lib.rs @@ -189,7 +189,7 @@ impl Epoch { randomness: genesis_config.randomness.clone(), config: BabeEpochConfiguration { c: genesis_config.c, - secondary_slots: genesis_config.secondary_slots, + allowed_slots: genesis_config.allowed_slots, }, } } diff --git a/client/consensus/babe/src/migration.rs b/client/consensus/babe/src/migration.rs index 837704abb1b5a..2a5a8749cc3c1 100644 --- a/client/consensus/babe/src/migration.rs +++ b/client/consensus/babe/src/migration.rs @@ -57,7 +57,7 @@ impl EpochV0 { randomness: self.randomness, config: BabeEpochConfiguration { c: config.c, - secondary_slots: config.secondary_slots, + allowed_slots: config.allowed_slots, }, } } diff --git a/client/consensus/babe/src/tests.rs b/client/consensus/babe/src/tests.rs index 2f32e58582c43..5e20c8b5e99f6 100644 --- a/client/consensus/babe/src/tests.rs +++ b/client/consensus/babe/src/tests.rs @@ -507,7 +507,7 @@ fn can_author_block() { duration: 100, config: BabeEpochConfiguration { c: (3, 10), - secondary_slots: true, + allowed_slots: AllowedSlots::PrimaryAndSecondaryPlainSlots, }, }; diff --git a/client/consensus/babe/src/verification.rs b/client/consensus/babe/src/verification.rs index 1a1076a398c04..1b89bbc643fc1 100644 --- a/client/consensus/babe/src/verification.rs +++ b/client/consensus/babe/src/verification.rs @@ -103,7 +103,7 @@ pub(super) fn check_header( epoch.config.c, )?; }, - PreDigest::SecondaryPlain(secondary) if config.allowed_slots.is_secondary_plain_slots_allowed() => { + PreDigest::SecondaryPlain(secondary) if epoch.config.allowed_slots.is_secondary_plain_slots_allowed() => { debug!(target: "babe", "Verifying Secondary plain block"); check_secondary_plain_header::( pre_hash, @@ -112,7 +112,7 @@ pub(super) fn check_header( &epoch, )?; }, - PreDigest::SecondaryVRF(secondary) if config.allowed_slots.is_secondary_vrf_slots_allowed() => { + PreDigest::SecondaryVRF(secondary) if epoch.config.allowed_slots.is_secondary_vrf_slots_allowed() => { debug!(target: "babe", "Verifying Secondary VRF block"); check_secondary_vrf_header::( pre_hash, diff --git a/primitives/consensus/babe/src/lib.rs b/primitives/consensus/babe/src/lib.rs index 2eb312acd1e48..7cf9483e6f6b7 100644 --- a/primitives/consensus/babe/src/lib.rs +++ b/primitives/consensus/babe/src/lib.rs @@ -184,7 +184,7 @@ pub enum AllowedSlots { impl AllowedSlots { /// Whether plain secondary slots are allowed. - pub fn is_secondary_slots_allowed(&self) -> bool { + pub fn is_secondary_plain_slots_allowed(&self) -> bool { *self == Self::PrimaryAndSecondaryPlainSlots }