mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-06-13 02:21:14 +00:00
babe: Introduce secondary slots (Aurababeous) (#3380)
* babe: initial implementation of secondary slots * babe: validate secondary slot author * babe: implement weight based fork choice * babe: remove unused * aura: cleanup unused imports * babe: pass in parent weight when authoring and verifying * babe: use epoch randomness for picking secondary slot authors * babe: fix tests * babe: fix wasm build * babe: node-side code for disabling secondary slots * babe: allow enabling/disabling secondary slots from runtime * babe: fix test * babe: use blake2_256 for secondary slot assignment * babe: run block initialization in should_end_session * node: increase slot duration to 6s * babe: add docs * node: bump spec_version * Apply suggestions from code review Co-Authored-By: joe petrowski <25483142+joepetrowski@users.noreply.github.com> * babe: simplify secondary slot assignment calculation * babe: remove unnecessary comment * node: bump spec_version * babe: fix bad merge
This commit is contained in:
@@ -22,7 +22,7 @@ use super::AuthoritySignature;
|
||||
use super::{BABE_ENGINE_ID, Epoch};
|
||||
#[cfg(not(feature = "std"))]
|
||||
use super::{VRF_OUTPUT_LENGTH, VRF_PROOF_LENGTH};
|
||||
use super::SlotNumber;
|
||||
use super::{AuthorityIndex, BabeBlockWeight, SlotNumber};
|
||||
#[cfg(feature = "std")]
|
||||
use sr_primitives::{DigestItem, generic::OpaqueDigestItemId};
|
||||
#[cfg(feature = "std")]
|
||||
@@ -36,18 +36,61 @@ use schnorrkel::{
|
||||
vrf::{VRFProof, VRFOutput, VRF_OUTPUT_LENGTH, VRF_PROOF_LENGTH}
|
||||
};
|
||||
|
||||
/// A BABE pre-digest
|
||||
/// 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).
|
||||
#[cfg(feature = "std")]
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct BabePreDigest {
|
||||
/// VRF output
|
||||
pub vrf_output: VRFOutput,
|
||||
/// VRF proof
|
||||
pub vrf_proof: VRFProof,
|
||||
/// Authority index
|
||||
pub authority_index: super::AuthorityIndex,
|
||||
/// Slot number
|
||||
pub slot_number: SlotNumber,
|
||||
pub enum BabePreDigest {
|
||||
/// A primary VRF-based slot assignment.
|
||||
Primary {
|
||||
/// VRF output
|
||||
vrf_output: VRFOutput,
|
||||
/// VRF proof
|
||||
vrf_proof: VRFProof,
|
||||
/// Authority index
|
||||
authority_index: super::AuthorityIndex,
|
||||
/// Slot number
|
||||
slot_number: SlotNumber,
|
||||
/// Chain weight (measured in number of Primary blocks)
|
||||
weight: BabeBlockWeight,
|
||||
},
|
||||
/// A secondary deterministic slot assignment.
|
||||
Secondary {
|
||||
/// Authority index
|
||||
authority_index: super::AuthorityIndex,
|
||||
/// Slot number
|
||||
slot_number: SlotNumber,
|
||||
/// Chain weight (measured in number of Primary blocks)
|
||||
weight: BabeBlockWeight,
|
||||
},
|
||||
}
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
impl BabePreDigest {
|
||||
/// Returns the slot number of the pre digest.
|
||||
pub fn authority_index(&self) -> AuthorityIndex {
|
||||
match self {
|
||||
BabePreDigest::Primary { authority_index, .. } => *authority_index,
|
||||
BabePreDigest::Secondary { authority_index, .. } => *authority_index,
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the slot number of the pre digest.
|
||||
pub fn slot_number(&self) -> SlotNumber {
|
||||
match self {
|
||||
BabePreDigest::Primary { slot_number, .. } => *slot_number,
|
||||
BabePreDigest::Secondary { slot_number, .. } => *slot_number,
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the weight of the pre digest.
|
||||
pub fn weight(&self) -> BabeBlockWeight {
|
||||
match self {
|
||||
BabePreDigest::Primary { weight, .. } => *weight,
|
||||
BabePreDigest::Secondary { weight, .. } => *weight,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// The prefix used by BABE for its VRF keys.
|
||||
@@ -55,27 +98,74 @@ pub const BABE_VRF_PREFIX: &'static [u8] = b"substrate-babe-vrf";
|
||||
|
||||
/// A raw version of `BabePreDigest`, usable on `no_std`.
|
||||
#[derive(Copy, Clone, Encode, Decode)]
|
||||
pub struct RawBabePreDigest {
|
||||
/// Slot number
|
||||
pub slot_number: SlotNumber,
|
||||
/// Authority index
|
||||
pub authority_index: super::AuthorityIndex,
|
||||
/// VRF output
|
||||
pub vrf_output: [u8; VRF_OUTPUT_LENGTH],
|
||||
/// VRF proof
|
||||
pub vrf_proof: [u8; VRF_PROOF_LENGTH],
|
||||
pub enum RawBabePreDigest {
|
||||
/// A primary VRF-based slot assignment.
|
||||
Primary {
|
||||
/// Authority index
|
||||
authority_index: AuthorityIndex,
|
||||
/// Slot number
|
||||
slot_number: SlotNumber,
|
||||
/// Chain weight (measured in number of Primary blocks)
|
||||
weight: BabeBlockWeight,
|
||||
/// VRF output
|
||||
vrf_output: [u8; VRF_OUTPUT_LENGTH],
|
||||
/// VRF proof
|
||||
vrf_proof: [u8; VRF_PROOF_LENGTH],
|
||||
},
|
||||
/// A secondary deterministic slot assignment.
|
||||
Secondary {
|
||||
/// Authority index
|
||||
authority_index: AuthorityIndex,
|
||||
/// Slot number
|
||||
slot_number: SlotNumber,
|
||||
/// Chain weight (measured in number of Primary blocks)
|
||||
weight: BabeBlockWeight,
|
||||
},
|
||||
}
|
||||
|
||||
impl RawBabePreDigest {
|
||||
/// Returns the slot number of the pre digest.
|
||||
pub fn slot_number(&self) -> SlotNumber {
|
||||
match self {
|
||||
RawBabePreDigest::Primary { slot_number, .. } => *slot_number,
|
||||
RawBabePreDigest::Secondary { slot_number, .. } => *slot_number,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
impl Encode for BabePreDigest {
|
||||
fn encode(&self) -> Vec<u8> {
|
||||
let tmp = RawBabePreDigest {
|
||||
vrf_output: *self.vrf_output.as_bytes(),
|
||||
vrf_proof: self.vrf_proof.to_bytes(),
|
||||
authority_index: self.authority_index,
|
||||
slot_number: self.slot_number,
|
||||
let raw = match self {
|
||||
BabePreDigest::Primary {
|
||||
vrf_output,
|
||||
vrf_proof,
|
||||
authority_index,
|
||||
slot_number,
|
||||
weight,
|
||||
} => {
|
||||
RawBabePreDigest::Primary {
|
||||
vrf_output: *vrf_output.as_bytes(),
|
||||
vrf_proof: vrf_proof.to_bytes(),
|
||||
authority_index: *authority_index,
|
||||
slot_number: *slot_number,
|
||||
weight: *weight,
|
||||
}
|
||||
},
|
||||
BabePreDigest::Secondary {
|
||||
authority_index,
|
||||
slot_number,
|
||||
weight,
|
||||
} => {
|
||||
RawBabePreDigest::Secondary {
|
||||
authority_index: *authority_index,
|
||||
slot_number: *slot_number,
|
||||
weight: *weight,
|
||||
}
|
||||
},
|
||||
};
|
||||
codec::Encode::encode(&tmp)
|
||||
|
||||
codec::Encode::encode(&raw)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -85,19 +175,26 @@ impl codec::EncodeLike for BabePreDigest {}
|
||||
#[cfg(feature = "std")]
|
||||
impl Decode for BabePreDigest {
|
||||
fn decode<R: Input>(i: &mut R) -> Result<Self, Error> {
|
||||
let RawBabePreDigest { vrf_output, vrf_proof, authority_index, slot_number } = Decode::decode(i)?;
|
||||
let pre_digest = match Decode::decode(i)? {
|
||||
RawBabePreDigest::Primary { vrf_output, vrf_proof, authority_index, slot_number, weight } => {
|
||||
// Verify (at compile time) that the sizes in babe_primitives are correct
|
||||
let _: [u8; super::VRF_OUTPUT_LENGTH] = vrf_output;
|
||||
let _: [u8; super::VRF_PROOF_LENGTH] = vrf_proof;
|
||||
|
||||
// Verify (at compile time) that the sizes in babe_primitives are correct
|
||||
let _: [u8; super::VRF_OUTPUT_LENGTH] = vrf_output;
|
||||
let _: [u8; super::VRF_PROOF_LENGTH] = vrf_proof;
|
||||
Ok(BabePreDigest {
|
||||
vrf_proof: VRFProof::from_bytes(&vrf_proof)
|
||||
.map_err(convert_error)?,
|
||||
vrf_output: VRFOutput::from_bytes(&vrf_output)
|
||||
.map_err(convert_error)?,
|
||||
authority_index,
|
||||
slot_number,
|
||||
})
|
||||
BabePreDigest::Primary {
|
||||
vrf_proof: VRFProof::from_bytes(&vrf_proof).map_err(convert_error)?,
|
||||
vrf_output: VRFOutput::from_bytes(&vrf_output).map_err(convert_error)?,
|
||||
authority_index,
|
||||
slot_number,
|
||||
weight,
|
||||
}
|
||||
},
|
||||
RawBabePreDigest::Secondary { authority_index, slot_number, weight } => {
|
||||
BabePreDigest::Secondary { authority_index, slot_number, weight }
|
||||
},
|
||||
};
|
||||
|
||||
Ok(pre_digest)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -68,7 +68,10 @@ pub type SlotNumber = u64;
|
||||
/// The weight of an authority.
|
||||
// NOTE: we use a unique name for the weight to avoid conflicts with other
|
||||
// `Weight` types, since the metadata isn't able to disambiguate.
|
||||
pub type BabeWeight = u64;
|
||||
pub type BabeAuthorityWeight = u64;
|
||||
|
||||
/// The weight of a BABE block.
|
||||
pub type BabeBlockWeight = u32;
|
||||
|
||||
/// BABE epoch information
|
||||
#[derive(Decode, Encode, Default, PartialEq, Eq, Clone)]
|
||||
@@ -81,9 +84,11 @@ pub struct Epoch {
|
||||
/// The duration of this epoch
|
||||
pub duration: SlotNumber,
|
||||
/// The authorities and their weights
|
||||
pub authorities: Vec<(AuthorityId, BabeWeight)>,
|
||||
pub authorities: Vec<(AuthorityId, BabeAuthorityWeight)>,
|
||||
/// Randomness for this epoch
|
||||
pub randomness: [u8; VRF_OUTPUT_LENGTH],
|
||||
/// Whether secondary slot assignments should be used during the epoch.
|
||||
pub secondary_slots: bool,
|
||||
}
|
||||
|
||||
/// An consensus log item for BABE.
|
||||
|
||||
Reference in New Issue
Block a user