use super::{
AllowedSlots, AuthorityId, AuthorityIndex, AuthoritySignature, BabeAuthorityWeight,
BabeEpochConfiguration, Slot, BABE_ENGINE_ID,
};
use codec::{Decode, Encode, MaxEncodedLen};
use scale_info::TypeInfo;
use sp_runtime::{DigestItem, RuntimeDebug};
use sp_std::vec::Vec;
use sp_consensus_vrf::schnorrkel::{Randomness, VRFOutput, VRFProof};
#[derive(Clone, RuntimeDebug, Encode, Decode, MaxEncodedLen, TypeInfo)]
pub struct PrimaryPreDigest {
pub authority_index: super::AuthorityIndex,
pub slot: Slot,
pub vrf_output: VRFOutput,
pub vrf_proof: VRFProof,
}
#[derive(Clone, RuntimeDebug, Encode, Decode, MaxEncodedLen, TypeInfo)]
pub struct SecondaryPlainPreDigest {
pub authority_index: super::AuthorityIndex,
pub slot: Slot,
}
#[derive(Clone, RuntimeDebug, Encode, Decode, MaxEncodedLen, TypeInfo)]
pub struct SecondaryVRFPreDigest {
pub authority_index: super::AuthorityIndex,
pub slot: Slot,
pub vrf_output: VRFOutput,
pub vrf_proof: VRFProof,
}
#[derive(Clone, RuntimeDebug, Encode, Decode, MaxEncodedLen, TypeInfo)]
pub enum PreDigest {
#[codec(index = 1)]
Primary(PrimaryPreDigest),
#[codec(index = 2)]
SecondaryPlain(SecondaryPlainPreDigest),
#[codec(index = 3)]
SecondaryVRF(SecondaryVRFPreDigest),
}
impl PreDigest {
pub fn authority_index(&self) -> AuthorityIndex {
match self {
PreDigest::Primary(primary) => primary.authority_index,
PreDigest::SecondaryPlain(secondary) => secondary.authority_index,
PreDigest::SecondaryVRF(secondary) => secondary.authority_index,
}
}
pub fn slot(&self) -> Slot {
match self {
PreDigest::Primary(primary) => primary.slot,
PreDigest::SecondaryPlain(secondary) => secondary.slot,
PreDigest::SecondaryVRF(secondary) => secondary.slot,
}
}
pub fn is_primary(&self) -> bool {
matches!(self, PreDigest::Primary(..))
}
pub fn added_weight(&self) -> crate::BabeBlockWeight {
match self {
PreDigest::Primary(_) => 1,
PreDigest::SecondaryPlain(_) | PreDigest::SecondaryVRF(_) => 0,
}
}
pub fn vrf(&self) -> Option<(&VRFOutput, &VRFProof)> {
match self {
PreDigest::Primary(primary) => Some((&primary.vrf_output, &primary.vrf_proof)),
PreDigest::SecondaryVRF(secondary) =>
Some((&secondary.vrf_output, &secondary.vrf_proof)),
PreDigest::SecondaryPlain(_) => None,
}
}
}
#[derive(Decode, Encode, PartialEq, Eq, Clone, RuntimeDebug)]
pub struct NextEpochDescriptor {
pub authorities: Vec<(AuthorityId, BabeAuthorityWeight)>,
pub randomness: Randomness,
}
#[derive(
Decode, Encode, PartialEq, Eq, Clone, RuntimeDebug, MaxEncodedLen, scale_info::TypeInfo,
)]
pub enum NextConfigDescriptor {
#[codec(index = 1)]
V1 {
c: (u64, u64),
allowed_slots: AllowedSlots,
},
}
impl From<NextConfigDescriptor> for BabeEpochConfiguration {
fn from(desc: NextConfigDescriptor) -> Self {
match desc {
NextConfigDescriptor::V1 { c, allowed_slots } => Self { c, allowed_slots },
}
}
}
pub trait CompatibleDigestItem: Sized {
fn babe_pre_digest(seal: PreDigest) -> Self;
fn as_babe_pre_digest(&self) -> Option<PreDigest>;
fn babe_seal(signature: AuthoritySignature) -> Self;
fn as_babe_seal(&self) -> Option<AuthoritySignature>;
fn as_next_epoch_descriptor(&self) -> Option<NextEpochDescriptor>;
fn as_next_config_descriptor(&self) -> Option<NextConfigDescriptor>;
}
impl CompatibleDigestItem for DigestItem {
fn babe_pre_digest(digest: PreDigest) -> Self {
DigestItem::PreRuntime(BABE_ENGINE_ID, digest.encode())
}
fn as_babe_pre_digest(&self) -> Option<PreDigest> {
self.pre_runtime_try_to(&BABE_ENGINE_ID)
}
fn babe_seal(signature: AuthoritySignature) -> Self {
DigestItem::Seal(BABE_ENGINE_ID, signature.encode())
}
fn as_babe_seal(&self) -> Option<AuthoritySignature> {
self.seal_try_to(&BABE_ENGINE_ID)
}
fn as_next_epoch_descriptor(&self) -> Option<NextEpochDescriptor> {
self.consensus_try_to(&BABE_ENGINE_ID)
.and_then(|x: super::ConsensusLog| match x {
super::ConsensusLog::NextEpochData(n) => Some(n),
_ => None,
})
}
fn as_next_config_descriptor(&self) -> Option<NextConfigDescriptor> {
self.consensus_try_to(&BABE_ENGINE_ID)
.and_then(|x: super::ConsensusLog| match x {
super::ConsensusLog::NextConfigData(n) => Some(n),
_ => None,
})
}
}