babe: secondary blocks with VRF (#5501)

* babe: secondary blocks with VRF

* Fix node runtime compile

* Fix test-utils runtime interface

* Fix babe tests

* typo: v == 2

* babe: support online configuration upgrades

* Fix rpc tests

* Fix runtime version tests

* Switch to use NextConfigDescriptor instead of changing runtime interface

* Fix tests

* epoch-changes: map function that allows converting with different epoch types

* Add migration script for the epoch config change

* Fix docs for PrimaryAndSecondaryVRFSlots

* Add docs of `SecondaryVRF` in babe crate

* babe-primitives: Secondary -> SecondaryPlain

* babe-client: Secondary -> SecondaryPlain

* Fix migration tests

* test-utils-runtime: Secondary -> SecondaryPlain

* Fix missing name change in test-utils-runtime

* Fix migration: Epoch should be EpochV0

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

Co-Authored-By: André Silva <123550+andresilva@users.noreply.github.com>

* Fix new epochChanges version

* Fix babe-primitives naming changes

* Fix merge issues in babe-client

Co-authored-by: André Silva <123550+andresilva@users.noreply.github.com>
Co-authored-by: André Silva <andre.beat@gmail.com>
This commit is contained in:
Wei Tang
2020-04-24 17:03:03 +02:00
committed by GitHub
parent 8a3dcd6862
commit 969720c2ad
12 changed files with 265 additions and 52 deletions
@@ -65,7 +65,7 @@ impl TryFrom<RawPrimaryPreDigest> 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
@@ -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<VRFOutput=schnorrkel::RawVRFOutput, VRFProof=schnorrkel::RawVRFProof> {
/// 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<schnorrkel::VRFOutput, schnorrkel::VRFProof>;
#[cfg(feature = "std")]
impl TryFrom<RawSecondaryVRFPreDigest> for SecondaryVRFPreDigest {
type Error = SignatureError;
fn try_from(raw: RawSecondaryVRFPreDigest) -> Result<SecondaryVRFPreDigest, SignatureError> {
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).
@@ -87,7 +118,10 @@ pub enum RawPreDigest<VRFOutput=schnorrkel::RawVRFOutput, VRFProof=schnorrkel::R
Primary(RawPrimaryPreDigest<VRFOutput, VRFProof>),
/// 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<VRFOutput, VRFProof>),
}
#[cfg(feature = "std")]
@@ -99,7 +133,8 @@ impl<VRFOutput, VRFProof> RawPreDigest<VRFOutput, VRFProof> {
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,
}
}
@@ -107,7 +142,8 @@ impl<VRFOutput, VRFProof> RawPreDigest<VRFOutput, VRFProof> {
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,
}
}
@@ -116,7 +152,7 @@ impl<VRFOutput, VRFProof> RawPreDigest<VRFOutput, VRFProof> {
pub fn added_weight(&self) -> crate::BabeBlockWeight {
match self {
RawPreDigest::Primary(_) => 1,
RawPreDigest::Secondary(_) => 0,
RawPreDigest::SecondaryPlain(_) | RawPreDigest::SecondaryVRF(_) => 0,
}
}
}
@@ -128,7 +164,8 @@ impl TryFrom<RawPreDigest> for PreDigest {
fn try_from(raw: RawPreDigest) -> Result<PreDigest, SignatureError> {
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()?),
})
}
}
+77 -2
View File
@@ -95,7 +95,7 @@ pub enum ConsensusLog {
/// Configuration data used by the BABE consensus engine.
#[derive(Clone, PartialEq, Eq, Encode, Decode, RuntimeDebug)]
pub struct BabeGenesisConfiguration {
pub struct BabeGenesisConfigurationV1 {
/// The slot duration in milliseconds for BABE. Currently, only
/// the value provided by this type at genesis will be used.
///
@@ -124,6 +124,76 @@ pub struct BabeGenesisConfiguration {
pub secondary_slots: bool,
}
impl From<BabeGenesisConfigurationV1> for BabeGenesisConfiguration {
fn from(v1: BabeGenesisConfigurationV1) -> 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::PrimaryAndSecondaryPlainSlots
} else {
AllowedSlots::PrimarySlots
},
}
}
}
/// 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,
/// 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 plain slots.
PrimaryAndSecondaryPlainSlots,
/// Allow primary and secondary VRF slots.
PrimaryAndSecondaryVRFSlots,
}
impl AllowedSlots {
/// Whether plain secondary slots are allowed.
pub fn is_secondary_plain_slots_allowed(&self) -> bool {
*self == Self::PrimaryAndSecondaryPlainSlots
}
/// 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 BabeGenesisConfiguration {
fn slot_duration(&self) -> u64 {
@@ -146,15 +216,20 @@ pub struct BabeEpochConfiguration {
/// Whether this chain should run with secondary slots, which are assigned
/// in round-robin manner.
pub secondary_slots: bool,
pub allowed_slots: AllowedSlots,
}
sp_api::decl_runtime_apis! {
/// API necessary for block authorship with BABE.
#[api_version(2)]
pub trait BabeApi {
/// Return the genesis configuration for BABE. The configuration is only read on genesis.
fn configuration() -> BabeGenesisConfiguration;
/// Return the configuration for BABE. Version 1.
#[changed_in(2)]
fn configuration() -> BabeGenesisConfigurationV1;
/// Returns the slot number that started the current epoch.
fn current_epoch_start() -> SlotNumber;
}