feat: Rebrand Polkadot/Substrate references to PezkuwiChain
This commit systematically rebrands various references from Parity Technologies' Polkadot/Substrate ecosystem to PezkuwiChain within the kurdistan-sdk. Key changes include: - Updated external repository URLs (zombienet-sdk, parity-db, parity-scale-codec, wasm-instrument) to point to pezkuwichain forks. - Modified internal documentation and code comments to reflect PezkuwiChain naming and structure. - Replaced direct references to with or specific paths within the for XCM, Pezkuwi, and other modules. - Cleaned up deprecated issue and PR references in various and files, particularly in and modules. - Adjusted image and logo URLs in documentation to point to PezkuwiChain assets. - Removed or rephrased comments related to external Polkadot/Substrate PRs and issues. This is a significant step towards fully customizing the SDK for the PezkuwiChain ecosystem.
This commit is contained in:
@@ -0,0 +1,62 @@
|
||||
[package]
|
||||
name = "pezsp-consensus-babe"
|
||||
version = "0.32.0"
|
||||
authors.workspace = true
|
||||
description = "Primitives for BABE consensus"
|
||||
edition.workspace = true
|
||||
license = "Apache-2.0"
|
||||
homepage.workspace = true
|
||||
repository.workspace = true
|
||||
readme = "README.md"
|
||||
|
||||
[lints]
|
||||
workspace = true
|
||||
|
||||
[package.metadata.docs.rs]
|
||||
targets = ["x86_64-unknown-linux-gnu"]
|
||||
|
||||
[dependencies]
|
||||
async-trait = { optional = true, workspace = true }
|
||||
codec = { workspace = true }
|
||||
scale-info = { features = ["derive"], workspace = true }
|
||||
serde = { features = ["alloc", "derive"], optional = true, workspace = true }
|
||||
pezsp-api = { workspace = true }
|
||||
pezsp-application-crypto = { workspace = true }
|
||||
pezsp-consensus-slots = { workspace = true }
|
||||
pezsp-core = { workspace = true }
|
||||
pezsp-inherents = { workspace = true }
|
||||
pezsp-runtime = { workspace = true }
|
||||
pezsp-timestamp = { optional = true, workspace = true }
|
||||
|
||||
[features]
|
||||
default = ["std"]
|
||||
std = [
|
||||
"async-trait",
|
||||
"codec/std",
|
||||
"scale-info/std",
|
||||
"serde/std",
|
||||
"pezsp-api/std",
|
||||
"pezsp-application-crypto/std",
|
||||
"pezsp-consensus-slots/std",
|
||||
"pezsp-core/std",
|
||||
"pezsp-inherents/std",
|
||||
"pezsp-runtime/std",
|
||||
"pezsp-timestamp/std",
|
||||
]
|
||||
|
||||
# Serde support without relying on std features.
|
||||
serde = [
|
||||
"dep:serde",
|
||||
"scale-info/serde",
|
||||
"pezsp-application-crypto/serde",
|
||||
"pezsp-consensus-slots/serde",
|
||||
"pezsp-core/serde",
|
||||
"pezsp-runtime/serde",
|
||||
]
|
||||
runtime-benchmarks = [
|
||||
"pezsp-api/runtime-benchmarks",
|
||||
"pezsp-consensus-slots/runtime-benchmarks",
|
||||
"pezsp-inherents/runtime-benchmarks",
|
||||
"pezsp-runtime/runtime-benchmarks",
|
||||
"pezsp-timestamp?/runtime-benchmarks",
|
||||
]
|
||||
@@ -0,0 +1,3 @@
|
||||
Primitives for BABE.
|
||||
|
||||
License: Apache-2.0
|
||||
@@ -0,0 +1,224 @@
|
||||
// This file is part of Bizinikiwi.
|
||||
|
||||
// Copyright (C) Parity Technologies (UK) Ltd.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
//! Private implementation details of BABE digests.
|
||||
|
||||
use super::{
|
||||
AllowedSlots, AuthorityId, AuthorityIndex, AuthoritySignature, BabeAuthorityWeight,
|
||||
BabeEpochConfiguration, Randomness, Slot, BABE_ENGINE_ID,
|
||||
};
|
||||
|
||||
#[cfg(not(feature = "std"))]
|
||||
use alloc::vec::Vec;
|
||||
use pezsp_core::sr25519::vrf::VrfSignature;
|
||||
use pezsp_runtime::{DigestItem, RuntimeDebug};
|
||||
|
||||
use codec::{Decode, DecodeWithMemTracking, Encode, MaxEncodedLen};
|
||||
use scale_info::TypeInfo;
|
||||
|
||||
/// Raw BABE primary slot assignment pre-digest.
|
||||
#[derive(Clone, RuntimeDebug, Encode, Decode, MaxEncodedLen, TypeInfo)]
|
||||
pub struct PrimaryPreDigest {
|
||||
/// Authority index
|
||||
pub authority_index: super::AuthorityIndex,
|
||||
/// Slot
|
||||
pub slot: Slot,
|
||||
/// VRF signature
|
||||
pub vrf_signature: VrfSignature,
|
||||
}
|
||||
|
||||
/// BABE secondary slot assignment pre-digest.
|
||||
#[derive(Clone, RuntimeDebug, Encode, Decode, MaxEncodedLen, TypeInfo)]
|
||||
pub struct SecondaryPlainPreDigest {
|
||||
/// Authority index
|
||||
///
|
||||
/// This is not strictly-speaking necessary, since the secondary slots
|
||||
/// are assigned based on slot number and epoch randomness. But including
|
||||
/// it makes things easier for higher-level users of the chain data to
|
||||
/// be aware of the author of a secondary-slot block.
|
||||
pub authority_index: super::AuthorityIndex,
|
||||
/// Slot
|
||||
pub slot: Slot,
|
||||
}
|
||||
|
||||
/// BABE secondary deterministic slot assignment with VRF outputs.
|
||||
#[derive(Clone, RuntimeDebug, Encode, Decode, MaxEncodedLen, TypeInfo)]
|
||||
pub struct SecondaryVRFPreDigest {
|
||||
/// Authority index
|
||||
pub authority_index: super::AuthorityIndex,
|
||||
/// Slot
|
||||
pub slot: Slot,
|
||||
/// VRF signature
|
||||
pub vrf_signature: VrfSignature,
|
||||
}
|
||||
|
||||
/// 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).
|
||||
#[derive(Clone, RuntimeDebug, Encode, Decode, MaxEncodedLen, TypeInfo)]
|
||||
pub enum PreDigest {
|
||||
/// A primary VRF-based slot assignment.
|
||||
#[codec(index = 1)]
|
||||
Primary(PrimaryPreDigest),
|
||||
/// A secondary deterministic slot assignment.
|
||||
#[codec(index = 2)]
|
||||
SecondaryPlain(SecondaryPlainPreDigest),
|
||||
/// A secondary deterministic slot assignment with VRF outputs.
|
||||
#[codec(index = 3)]
|
||||
SecondaryVRF(SecondaryVRFPreDigest),
|
||||
}
|
||||
|
||||
impl PreDigest {
|
||||
/// Returns the slot number of the pre digest.
|
||||
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,
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the slot of the pre digest.
|
||||
pub fn slot(&self) -> Slot {
|
||||
match self {
|
||||
PreDigest::Primary(primary) => primary.slot,
|
||||
PreDigest::SecondaryPlain(secondary) => secondary.slot,
|
||||
PreDigest::SecondaryVRF(secondary) => secondary.slot,
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns true if this pre-digest is for a primary slot assignment.
|
||||
pub fn is_primary(&self) -> bool {
|
||||
matches!(self, PreDigest::Primary(..))
|
||||
}
|
||||
|
||||
/// Returns the weight _added_ by this digest, not the cumulative weight
|
||||
/// of the chain.
|
||||
pub fn added_weight(&self) -> crate::BabeBlockWeight {
|
||||
match self {
|
||||
PreDigest::Primary(_) => 1,
|
||||
PreDigest::SecondaryPlain(_) | PreDigest::SecondaryVRF(_) => 0,
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the VRF output and proof, if they exist.
|
||||
pub fn vrf_signature(&self) -> Option<&VrfSignature> {
|
||||
match self {
|
||||
PreDigest::Primary(primary) => Some(&primary.vrf_signature),
|
||||
PreDigest::SecondaryVRF(secondary) => Some(&secondary.vrf_signature),
|
||||
PreDigest::SecondaryPlain(_) => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Information about the next epoch. This is broadcast in the first block
|
||||
/// of the epoch.
|
||||
#[derive(Decode, Encode, PartialEq, Eq, Clone, RuntimeDebug)]
|
||||
pub struct NextEpochDescriptor {
|
||||
/// The authorities.
|
||||
pub authorities: Vec<(AuthorityId, BabeAuthorityWeight)>,
|
||||
|
||||
/// The value of randomness to use for the slot-assignment.
|
||||
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`.
|
||||
#[derive(
|
||||
Decode,
|
||||
DecodeWithMemTracking,
|
||||
Encode,
|
||||
PartialEq,
|
||||
Eq,
|
||||
Clone,
|
||||
RuntimeDebug,
|
||||
MaxEncodedLen,
|
||||
scale_info::TypeInfo,
|
||||
)]
|
||||
pub enum NextConfigDescriptor {
|
||||
/// Version 1.
|
||||
#[codec(index = 1)]
|
||||
V1 {
|
||||
/// Value of `c` in `BabeEpochConfiguration`.
|
||||
c: (u64, u64),
|
||||
/// Value of `allowed_slots` in `BabeEpochConfiguration`.
|
||||
allowed_slots: AllowedSlots,
|
||||
},
|
||||
}
|
||||
|
||||
impl From<NextConfigDescriptor> for BabeEpochConfiguration {
|
||||
fn from(desc: NextConfigDescriptor) -> Self {
|
||||
match desc {
|
||||
NextConfigDescriptor::V1 { c, allowed_slots } => Self { c, allowed_slots },
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// A digest item which is usable with BABE consensus.
|
||||
pub trait CompatibleDigestItem: Sized {
|
||||
/// Construct a digest item which contains a BABE pre-digest.
|
||||
fn babe_pre_digest(seal: PreDigest) -> Self;
|
||||
|
||||
/// If this item is an BABE pre-digest, return it.
|
||||
fn as_babe_pre_digest(&self) -> Option<PreDigest>;
|
||||
|
||||
/// Construct a digest item which contains a BABE seal.
|
||||
fn babe_seal(signature: AuthoritySignature) -> Self;
|
||||
|
||||
/// If this item is a BABE signature, return the signature.
|
||||
fn as_babe_seal(&self) -> Option<AuthoritySignature>;
|
||||
|
||||
/// If this item is a BABE epoch descriptor, return it.
|
||||
fn as_next_epoch_descriptor(&self) -> Option<NextEpochDescriptor>;
|
||||
|
||||
/// If this item is a BABE config descriptor, return it.
|
||||
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,
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,111 @@
|
||||
// This file is part of Bizinikiwi.
|
||||
|
||||
// Copyright (C) Parity Technologies (UK) Ltd.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
//! Inherents for BABE
|
||||
|
||||
use pezsp_inherents::{Error, InherentData, InherentIdentifier};
|
||||
|
||||
/// The BABE inherent identifier.
|
||||
pub const INHERENT_IDENTIFIER: InherentIdentifier = *b"babeslot";
|
||||
|
||||
/// The type of the BABE inherent.
|
||||
pub type InherentType = pezsp_consensus_slots::Slot;
|
||||
|
||||
/// Create inherent data providers for BABE with timestamp.
|
||||
#[cfg(feature = "std")]
|
||||
pub type BabeCreateInherentDataProviders<Block> = std::sync::Arc<
|
||||
dyn pezsp_inherents::CreateInherentDataProviders<
|
||||
Block,
|
||||
(),
|
||||
InherentDataProviders = (InherentDataProvider, pezsp_timestamp::InherentDataProvider),
|
||||
>,
|
||||
>;
|
||||
|
||||
/// Auxiliary trait to extract BABE inherent data.
|
||||
pub trait BabeInherentData {
|
||||
/// Get BABE inherent data.
|
||||
fn babe_inherent_data(&self) -> Result<Option<InherentType>, Error>;
|
||||
/// Replace BABE inherent data.
|
||||
fn babe_replace_inherent_data(&mut self, new: InherentType);
|
||||
}
|
||||
|
||||
impl BabeInherentData for InherentData {
|
||||
fn babe_inherent_data(&self) -> Result<Option<InherentType>, Error> {
|
||||
self.get_data(&INHERENT_IDENTIFIER)
|
||||
}
|
||||
|
||||
fn babe_replace_inherent_data(&mut self, new: InherentType) {
|
||||
self.replace_data(INHERENT_IDENTIFIER, &new);
|
||||
}
|
||||
}
|
||||
|
||||
/// Provides the slot duration inherent data for BABE.
|
||||
// TODO: Remove in the future. https://github.com/pezkuwichain/kurdistan-sdk/issues/31
|
||||
#[cfg(feature = "std")]
|
||||
pub struct InherentDataProvider {
|
||||
slot: InherentType,
|
||||
}
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
impl InherentDataProvider {
|
||||
/// Create new inherent data provider from the given `slot`.
|
||||
pub fn new(slot: InherentType) -> Self {
|
||||
Self { slot }
|
||||
}
|
||||
|
||||
/// Creates the inherent data provider by calculating the slot from the given
|
||||
/// `timestamp` and `duration`.
|
||||
pub fn from_timestamp_and_slot_duration(
|
||||
timestamp: pezsp_timestamp::Timestamp,
|
||||
slot_duration: pezsp_consensus_slots::SlotDuration,
|
||||
) -> Self {
|
||||
let slot = InherentType::from_timestamp(timestamp, slot_duration);
|
||||
|
||||
Self { slot }
|
||||
}
|
||||
|
||||
/// Returns the `slot` of this inherent data provider.
|
||||
pub fn slot(&self) -> InherentType {
|
||||
self.slot
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
impl core::ops::Deref for InherentDataProvider {
|
||||
type Target = InherentType;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.slot
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
#[async_trait::async_trait]
|
||||
impl pezsp_inherents::InherentDataProvider for InherentDataProvider {
|
||||
async fn provide_inherent_data(&self, inherent_data: &mut InherentData) -> Result<(), Error> {
|
||||
inherent_data.put_data(INHERENT_IDENTIFIER, &self.slot)
|
||||
}
|
||||
|
||||
async fn try_handle_error(
|
||||
&self,
|
||||
_: &InherentIdentifier,
|
||||
_: &[u8],
|
||||
) -> Option<Result<(), Error>> {
|
||||
// There is no error anymore
|
||||
None
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,447 @@
|
||||
// This file is part of Bizinikiwi.
|
||||
|
||||
// Copyright (C) Parity Technologies (UK) Ltd.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
//! Primitives for BABE.
|
||||
#![deny(warnings)]
|
||||
#![forbid(unsafe_code, missing_docs, unused_variables, unused_imports)]
|
||||
#![cfg_attr(not(feature = "std"), no_std)]
|
||||
|
||||
extern crate alloc;
|
||||
|
||||
pub mod digests;
|
||||
pub mod inherents;
|
||||
|
||||
#[cfg(not(feature = "std"))]
|
||||
use alloc::vec::Vec;
|
||||
use codec::{Decode, DecodeWithMemTracking, Encode, MaxEncodedLen};
|
||||
use scale_info::TypeInfo;
|
||||
#[cfg(feature = "serde")]
|
||||
use serde::{Deserialize, Serialize};
|
||||
use pezsp_runtime::{traits::Header, ConsensusEngineId, RuntimeDebug};
|
||||
|
||||
use crate::digests::{NextConfigDescriptor, NextEpochDescriptor};
|
||||
|
||||
pub use pezsp_core::sr25519::vrf::{
|
||||
VrfInput, VrfPreOutput, VrfProof, VrfSignData, VrfSignature, VrfTranscript,
|
||||
};
|
||||
|
||||
/// Key type for BABE module.
|
||||
pub const KEY_TYPE: pezsp_core::crypto::KeyTypeId = pezsp_application_crypto::key_types::BABE;
|
||||
|
||||
mod app {
|
||||
use pezsp_application_crypto::{app_crypto, key_types::BABE, sr25519};
|
||||
app_crypto!(sr25519, BABE);
|
||||
}
|
||||
|
||||
/// VRF context used for per-slot randomness generation.
|
||||
pub const RANDOMNESS_VRF_CONTEXT: &[u8] = b"BabeVRFInOutContext";
|
||||
|
||||
/// VRF output length for per-slot randomness.
|
||||
pub const RANDOMNESS_LENGTH: usize = 32;
|
||||
|
||||
/// Randomness type required by BABE operations.
|
||||
pub type Randomness = [u8; RANDOMNESS_LENGTH];
|
||||
|
||||
/// A Babe authority keypair. Necessarily equivalent to the schnorrkel public key used in
|
||||
/// the main Babe module. If that ever changes, then this must, too.
|
||||
#[cfg(feature = "std")]
|
||||
pub type AuthorityPair = app::Pair;
|
||||
|
||||
/// A Babe authority signature.
|
||||
pub type AuthoritySignature = app::Signature;
|
||||
|
||||
/// A Babe authority identifier. Necessarily equivalent to the schnorrkel public key used in
|
||||
/// the main Babe module. If that ever changes, then this must, too.
|
||||
pub type AuthorityId = app::Public;
|
||||
|
||||
/// The `ConsensusEngineId` of BABE.
|
||||
pub const BABE_ENGINE_ID: ConsensusEngineId = *b"BABE";
|
||||
|
||||
/// The length of the public key
|
||||
pub const PUBLIC_KEY_LENGTH: usize = 32;
|
||||
|
||||
/// How many blocks to wait before running the median algorithm for relative time
|
||||
/// This will not vary from chain to chain as it is not dependent on slot duration
|
||||
/// or epoch length.
|
||||
pub const MEDIAN_ALGORITHM_CARDINALITY: usize = 1200; // arbitrary suggestion by w3f-research.
|
||||
|
||||
/// The index of an authority.
|
||||
pub type AuthorityIndex = u32;
|
||||
|
||||
pub use pezsp_consensus_slots::{Slot, SlotDuration};
|
||||
|
||||
/// An equivocation proof for multiple block authorships on the same slot (i.e. double vote).
|
||||
pub type EquivocationProof<H> = pezsp_consensus_slots::EquivocationProof<H, AuthorityId>;
|
||||
|
||||
/// 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 BabeAuthorityWeight = u64;
|
||||
|
||||
/// The cumulative weight of a BABE block, i.e. sum of block weights starting
|
||||
/// at this block until the genesis block.
|
||||
///
|
||||
/// Primary blocks have a weight of 1 whereas secondary blocks have a weight
|
||||
/// of 0 (regardless of whether they are plain or vrf secondary blocks).
|
||||
pub type BabeBlockWeight = u32;
|
||||
|
||||
/// Make VRF input suitable for BABE's randomness generation.
|
||||
pub fn make_vrf_transcript(randomness: &Randomness, slot: Slot, epoch: u64) -> VrfInput {
|
||||
VrfInput::new(
|
||||
&BABE_ENGINE_ID,
|
||||
&[
|
||||
(b"slot number", &slot.to_le_bytes()),
|
||||
(b"current epoch", &epoch.to_le_bytes()),
|
||||
(b"chain randomness", randomness),
|
||||
],
|
||||
)
|
||||
}
|
||||
|
||||
/// Make VRF signing data suitable for BABE's protocol.
|
||||
pub fn make_vrf_sign_data(randomness: &Randomness, slot: Slot, epoch: u64) -> VrfSignData {
|
||||
make_vrf_transcript(randomness, slot, epoch).into()
|
||||
}
|
||||
|
||||
/// An consensus log item for BABE.
|
||||
#[derive(Decode, Encode, Clone, PartialEq, Eq)]
|
||||
pub enum ConsensusLog {
|
||||
/// The epoch has changed. This provides information about the _next_
|
||||
/// epoch - information about the _current_ epoch (i.e. the one we've just
|
||||
/// entered) should already be available earlier in the chain.
|
||||
#[codec(index = 1)]
|
||||
NextEpochData(NextEpochDescriptor),
|
||||
/// 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),
|
||||
}
|
||||
|
||||
/// Configuration data used by the BABE consensus engine.
|
||||
#[derive(Clone, PartialEq, Eq, Encode, Decode, RuntimeDebug, TypeInfo)]
|
||||
pub struct BabeConfigurationV1 {
|
||||
/// 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: u64,
|
||||
|
||||
/// 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 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,
|
||||
}
|
||||
|
||||
impl From<BabeConfigurationV1> for BabeConfiguration {
|
||||
fn from(v1: BabeConfigurationV1) -> Self {
|
||||
Self {
|
||||
slot_duration: v1.slot_duration,
|
||||
epoch_length: v1.epoch_length,
|
||||
c: v1.c,
|
||||
authorities: v1.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, TypeInfo)]
|
||||
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: u64,
|
||||
|
||||
/// 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
|
||||
pub authorities: Vec<(AuthorityId, BabeAuthorityWeight)>,
|
||||
|
||||
/// The randomness
|
||||
pub randomness: Randomness,
|
||||
|
||||
/// Type of allowed slots.
|
||||
pub allowed_slots: AllowedSlots,
|
||||
}
|
||||
|
||||
impl BabeConfiguration {
|
||||
/// Convenience method to get the slot duration as a `SlotDuration` value.
|
||||
pub fn slot_duration(&self) -> SlotDuration {
|
||||
SlotDuration::from_millis(self.slot_duration)
|
||||
}
|
||||
}
|
||||
|
||||
/// Types of allowed slots.
|
||||
#[derive(
|
||||
Clone,
|
||||
Copy,
|
||||
PartialEq,
|
||||
Eq,
|
||||
Encode,
|
||||
Decode,
|
||||
DecodeWithMemTracking,
|
||||
RuntimeDebug,
|
||||
MaxEncodedLen,
|
||||
TypeInfo,
|
||||
)]
|
||||
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
/// Configuration data used by the BABE consensus engine that may change with epochs.
|
||||
#[derive(Clone, PartialEq, Eq, Encode, Decode, RuntimeDebug, MaxEncodedLen, TypeInfo)]
|
||||
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
|
||||
pub struct BabeEpochConfiguration {
|
||||
/// 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),
|
||||
|
||||
/// Whether this chain should run with secondary slots, which are assigned
|
||||
/// in round-robin manner.
|
||||
pub allowed_slots: AllowedSlots,
|
||||
}
|
||||
|
||||
impl Default for BabeEpochConfiguration {
|
||||
fn default() -> Self {
|
||||
Self { c: (1, 4), allowed_slots: AllowedSlots::PrimaryAndSecondaryVRFSlots }
|
||||
}
|
||||
}
|
||||
|
||||
/// Verifies the equivocation proof by making sure that: both headers have
|
||||
/// different hashes, are targeting the same slot, and have valid signatures by
|
||||
/// the same authority.
|
||||
pub fn check_equivocation_proof<H>(proof: EquivocationProof<H>) -> bool
|
||||
where
|
||||
H: Header,
|
||||
{
|
||||
use digests::*;
|
||||
use pezsp_application_crypto::RuntimeAppPublic;
|
||||
|
||||
let find_pre_digest =
|
||||
|header: &H| header.digest().logs().iter().find_map(|log| log.as_babe_pre_digest());
|
||||
|
||||
let verify_seal_signature = |mut header: H, offender: &AuthorityId| {
|
||||
let seal = header.digest_mut().pop()?.as_babe_seal()?;
|
||||
let pre_hash = header.hash();
|
||||
|
||||
if !offender.verify(&pre_hash.as_ref(), &seal) {
|
||||
return None;
|
||||
}
|
||||
|
||||
Some(())
|
||||
};
|
||||
|
||||
let verify_proof = || {
|
||||
// we must have different headers for the equivocation to be valid
|
||||
if proof.first_header.hash() == proof.second_header.hash() {
|
||||
return None;
|
||||
}
|
||||
|
||||
let first_pre_digest = find_pre_digest(&proof.first_header)?;
|
||||
let second_pre_digest = find_pre_digest(&proof.second_header)?;
|
||||
|
||||
// both headers must be targeting the same slot and it must
|
||||
// be the same as the one in the proof.
|
||||
if proof.slot != first_pre_digest.slot() ||
|
||||
first_pre_digest.slot() != second_pre_digest.slot()
|
||||
{
|
||||
return None;
|
||||
}
|
||||
|
||||
// both headers must have been authored by the same authority
|
||||
if first_pre_digest.authority_index() != second_pre_digest.authority_index() {
|
||||
return None;
|
||||
}
|
||||
|
||||
// we finally verify that the expected authority has signed both headers and
|
||||
// that the signature is valid.
|
||||
verify_seal_signature(proof.first_header, &proof.offender)?;
|
||||
verify_seal_signature(proof.second_header, &proof.offender)?;
|
||||
|
||||
Some(())
|
||||
};
|
||||
|
||||
// NOTE: we isolate the verification code into an helper function that
|
||||
// returns `Option<()>` so that we can use `?` to deal with any intermediate
|
||||
// errors and discard the proof as invalid.
|
||||
verify_proof().is_some()
|
||||
}
|
||||
|
||||
/// An opaque type used to represent the key ownership proof at the runtime API
|
||||
/// boundary. The inner value is an encoded representation of the actual key
|
||||
/// ownership proof which will be parameterized when defining the runtime. At
|
||||
/// the runtime API boundary this type is unknown and as such we keep this
|
||||
/// opaque representation, implementors of the runtime API will have to make
|
||||
/// sure that all usages of `OpaqueKeyOwnershipProof` refer to the same type.
|
||||
#[derive(Decode, Encode, PartialEq, TypeInfo)]
|
||||
pub struct OpaqueKeyOwnershipProof(Vec<u8>);
|
||||
impl OpaqueKeyOwnershipProof {
|
||||
/// Create a new `OpaqueKeyOwnershipProof` using the given encoded
|
||||
/// representation.
|
||||
pub fn new(inner: Vec<u8>) -> OpaqueKeyOwnershipProof {
|
||||
OpaqueKeyOwnershipProof(inner)
|
||||
}
|
||||
|
||||
/// Try to decode this `OpaqueKeyOwnershipProof` into the given concrete key
|
||||
/// ownership proof type.
|
||||
pub fn decode<T: Decode>(self) -> Option<T> {
|
||||
Decode::decode(&mut &self.0[..]).ok()
|
||||
}
|
||||
}
|
||||
|
||||
/// BABE epoch information
|
||||
#[derive(Decode, Encode, PartialEq, Eq, Clone, Debug, TypeInfo)]
|
||||
pub struct Epoch {
|
||||
/// The epoch index.
|
||||
pub epoch_index: u64,
|
||||
/// The starting slot of the epoch.
|
||||
pub start_slot: Slot,
|
||||
/// The duration of this epoch.
|
||||
pub duration: u64,
|
||||
/// The authorities and their weights.
|
||||
pub authorities: Vec<(AuthorityId, BabeAuthorityWeight)>,
|
||||
/// Randomness for this epoch.
|
||||
pub randomness: Randomness,
|
||||
/// Configuration of the epoch.
|
||||
pub config: BabeEpochConfiguration,
|
||||
}
|
||||
|
||||
/// Returns the epoch index the given slot belongs to.
|
||||
pub fn epoch_index(slot: Slot, genesis_slot: Slot, epoch_duration: u64) -> u64 {
|
||||
*slot.saturating_sub(genesis_slot) / epoch_duration
|
||||
}
|
||||
|
||||
/// Returns the first slot at the given epoch index.
|
||||
pub fn epoch_start_slot(epoch_index: u64, genesis_slot: Slot, epoch_duration: u64) -> Slot {
|
||||
// (epoch_index * epoch_duration) + genesis_slot
|
||||
|
||||
const PROOF: &str = "slot number is u64; it should relate in some way to wall clock time; \
|
||||
if u64 is not enough we should crash for safety; qed.";
|
||||
|
||||
epoch_index
|
||||
.checked_mul(epoch_duration)
|
||||
.and_then(|slot| slot.checked_add(*genesis_slot))
|
||||
.expect(PROOF)
|
||||
.into()
|
||||
}
|
||||
|
||||
pezsp_api::decl_runtime_apis! {
|
||||
/// API necessary for block authorship with BABE.
|
||||
#[api_version(2)]
|
||||
pub trait BabeApi {
|
||||
/// Return the configuration for BABE.
|
||||
fn configuration() -> BabeConfiguration;
|
||||
|
||||
/// Return the configuration for BABE. Version 1.
|
||||
#[changed_in(2)]
|
||||
fn configuration() -> BabeConfigurationV1;
|
||||
|
||||
/// Returns the slot that started the current epoch.
|
||||
fn current_epoch_start() -> Slot;
|
||||
|
||||
/// Returns information regarding the current epoch.
|
||||
fn current_epoch() -> Epoch;
|
||||
|
||||
/// Returns information regarding the next epoch (which was already
|
||||
/// previously announced).
|
||||
fn next_epoch() -> Epoch;
|
||||
|
||||
/// Generates a proof of key ownership for the given authority in the
|
||||
/// current epoch. An example usage of this module is coupled with the
|
||||
/// session historical module to prove that a given authority key is
|
||||
/// tied to a given staking identity during a specific session. Proofs
|
||||
/// of key ownership are necessary for submitting equivocation reports.
|
||||
/// NOTE: even though the API takes a `slot` as parameter the current
|
||||
/// implementations ignores this parameter and instead relies on this
|
||||
/// method being called at the correct block height, i.e. any point at
|
||||
/// which the epoch for the given slot is live on-chain. Future
|
||||
/// implementations will instead use indexed data through an offchain
|
||||
/// worker, not requiring older states to be available.
|
||||
fn generate_key_ownership_proof(
|
||||
slot: Slot,
|
||||
authority_id: AuthorityId,
|
||||
) -> Option<OpaqueKeyOwnershipProof>;
|
||||
|
||||
/// Submits an unsigned extrinsic to report an equivocation. The caller
|
||||
/// must provide the equivocation proof and a key ownership proof
|
||||
/// (should be obtained using `generate_key_ownership_proof`). The
|
||||
/// extrinsic will be unsigned and should only be accepted for local
|
||||
/// authorship (not to be broadcast to the network). This method returns
|
||||
/// `None` when creation of the extrinsic fails, e.g. if equivocation
|
||||
/// reporting is disabled for the given runtime (i.e. this method is
|
||||
/// hardcoded to return `None`). Only useful in an offchain context.
|
||||
fn submit_report_equivocation_unsigned_extrinsic(
|
||||
equivocation_proof: EquivocationProof<Block::Header>,
|
||||
key_owner_proof: OpaqueKeyOwnershipProof,
|
||||
) -> Option<()>;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user