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:
2025-12-14 00:04:10 +03:00
parent 286de54384
commit 1c0e57d984
9084 changed files with 997839 additions and 997557 deletions
@@ -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<()>;
}
}