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,408 @@
|
||||
// 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.
|
||||
|
||||
//! # Aura Module
|
||||
//!
|
||||
//! - [`Config`]
|
||||
//! - [`Pallet`]
|
||||
//!
|
||||
//! ## Overview
|
||||
//!
|
||||
//! The Aura module extends Aura consensus by managing offline reporting.
|
||||
//!
|
||||
//! ## Interface
|
||||
//!
|
||||
//! ### Public Functions
|
||||
//!
|
||||
//! - `slot_duration` - Determine the Aura slot-duration based on the Timestamp module
|
||||
//! configuration.
|
||||
//!
|
||||
//! ## Related Modules
|
||||
//!
|
||||
//! - [Timestamp](../pezpallet_timestamp/index.html): The Timestamp module is used in Aura to track
|
||||
//! consensus rounds (via `slots`).
|
||||
|
||||
#![cfg_attr(not(feature = "std"), no_std)]
|
||||
|
||||
extern crate alloc;
|
||||
|
||||
use alloc::vec::Vec;
|
||||
use codec::{Decode, Encode, MaxEncodedLen};
|
||||
use pezframe_support::{
|
||||
traits::{DisabledValidators, FindAuthor, Get, OnTimestampSet, OneSessionHandler},
|
||||
BoundedSlice, BoundedVec, ConsensusEngineId, Parameter,
|
||||
};
|
||||
use log;
|
||||
use pezsp_consensus_aura::{AuthorityIndex, ConsensusLog, Slot, AURA_ENGINE_ID};
|
||||
use pezsp_runtime::{
|
||||
generic::DigestItem,
|
||||
traits::{IsMember, Member, SaturatedConversion, Saturating, Zero},
|
||||
RuntimeAppPublic,
|
||||
};
|
||||
|
||||
pub mod migrations;
|
||||
mod mock;
|
||||
mod tests;
|
||||
|
||||
pub use pallet::*;
|
||||
|
||||
const LOG_TARGET: &str = "runtime::aura";
|
||||
|
||||
/// A slot duration provider which infers the slot duration from the
|
||||
/// [`pezpallet_timestamp::Config::MinimumPeriod`] by multiplying it by two, to ensure
|
||||
/// that authors have the majority of their slot to author within.
|
||||
///
|
||||
/// This was the default behavior of the Aura pallet and may be used for
|
||||
/// backwards compatibility.
|
||||
pub struct MinimumPeriodTimesTwo<T>(core::marker::PhantomData<T>);
|
||||
|
||||
impl<T: pezpallet_timestamp::Config> Get<T::Moment> for MinimumPeriodTimesTwo<T> {
|
||||
fn get() -> T::Moment {
|
||||
<T as pezpallet_timestamp::Config>::MinimumPeriod::get().saturating_mul(2u32.into())
|
||||
}
|
||||
}
|
||||
|
||||
#[pezframe_support::pallet]
|
||||
pub mod pallet {
|
||||
use super::*;
|
||||
use pezframe_support::pezpallet_prelude::*;
|
||||
use pezframe_system::pezpallet_prelude::*;
|
||||
|
||||
#[pallet::config]
|
||||
pub trait Config: pezpallet_timestamp::Config + pezframe_system::Config {
|
||||
/// The identifier type for an authority.
|
||||
type AuthorityId: Member
|
||||
+ Parameter
|
||||
+ RuntimeAppPublic
|
||||
+ MaybeSerializeDeserialize
|
||||
+ MaxEncodedLen;
|
||||
/// The maximum number of authorities that the pallet can hold.
|
||||
type MaxAuthorities: Get<u32>;
|
||||
|
||||
/// A way to check whether a given validator is disabled and should not be authoring blocks.
|
||||
/// Blocks authored by a disabled validator will lead to a panic as part of this module's
|
||||
/// initialization.
|
||||
type DisabledValidators: DisabledValidators;
|
||||
|
||||
/// Whether to allow block authors to create multiple blocks per slot.
|
||||
///
|
||||
/// If this is `true`, the pallet will allow slots to stay the same across sequential
|
||||
/// blocks. If this is `false`, the pallet will require that subsequent blocks always have
|
||||
/// higher slots than previous ones.
|
||||
///
|
||||
/// Regardless of the setting of this storage value, the pallet will always enforce the
|
||||
/// invariant that slots don't move backwards as the chain progresses.
|
||||
///
|
||||
/// The typical value for this should be 'false' unless this pallet is being augmented by
|
||||
/// another pallet which enforces some limitation on the number of blocks authors can create
|
||||
/// using the same slot.
|
||||
type AllowMultipleBlocksPerSlot: Get<bool>;
|
||||
|
||||
/// The slot duration Aura should run with, expressed in milliseconds.
|
||||
/// The effective value of this type should not change while the chain is running.
|
||||
///
|
||||
/// For backwards compatibility either use [`MinimumPeriodTimesTwo`] or a const.
|
||||
#[pallet::constant]
|
||||
type SlotDuration: Get<<Self as pezpallet_timestamp::Config>::Moment>;
|
||||
}
|
||||
|
||||
#[pallet::pallet]
|
||||
pub struct Pallet<T>(core::marker::PhantomData<T>);
|
||||
|
||||
#[pallet::hooks]
|
||||
impl<T: Config> Hooks<BlockNumberFor<T>> for Pallet<T> {
|
||||
fn on_initialize(_: BlockNumberFor<T>) -> Weight {
|
||||
if let Some(new_slot) = Self::current_slot_from_digests() {
|
||||
let current_slot = CurrentSlot::<T>::get();
|
||||
|
||||
if T::AllowMultipleBlocksPerSlot::get() {
|
||||
assert!(current_slot <= new_slot, "Slot must not decrease");
|
||||
} else {
|
||||
assert!(current_slot < new_slot, "Slot must increase");
|
||||
}
|
||||
|
||||
CurrentSlot::<T>::put(new_slot);
|
||||
|
||||
if let Some(n_authorities) = <Authorities<T>>::decode_len() {
|
||||
let authority_index = *new_slot % n_authorities as u64;
|
||||
if T::DisabledValidators::is_disabled(authority_index as u32) {
|
||||
panic!(
|
||||
"Validator with index {:?} is disabled and should not be attempting to author blocks.",
|
||||
authority_index,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// TODO [#3398] Generate offence report for all authorities that skipped their
|
||||
// slots.
|
||||
|
||||
T::DbWeight::get().reads_writes(2, 1)
|
||||
} else {
|
||||
T::DbWeight::get().reads(1)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "try-runtime")]
|
||||
fn try_state(_: BlockNumberFor<T>) -> Result<(), pezsp_runtime::TryRuntimeError> {
|
||||
Self::do_try_state()
|
||||
}
|
||||
}
|
||||
|
||||
/// The current authority set.
|
||||
#[pallet::storage]
|
||||
pub type Authorities<T: Config> =
|
||||
StorageValue<_, BoundedVec<T::AuthorityId, T::MaxAuthorities>, ValueQuery>;
|
||||
|
||||
/// The current slot of this block.
|
||||
///
|
||||
/// This will be set in `on_initialize`.
|
||||
#[pallet::storage]
|
||||
pub type CurrentSlot<T: Config> = StorageValue<_, Slot, ValueQuery>;
|
||||
|
||||
#[pallet::genesis_config]
|
||||
#[derive(pezframe_support::DefaultNoBound)]
|
||||
pub struct GenesisConfig<T: Config> {
|
||||
pub authorities: Vec<T::AuthorityId>,
|
||||
}
|
||||
|
||||
#[pallet::genesis_build]
|
||||
impl<T: Config> BuildGenesisConfig for GenesisConfig<T> {
|
||||
fn build(&self) {
|
||||
Pallet::<T>::initialize_authorities(&self.authorities);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Config> Pallet<T> {
|
||||
/// Change authorities.
|
||||
///
|
||||
/// The storage will be applied immediately.
|
||||
/// And aura consensus log will be appended to block's log.
|
||||
///
|
||||
/// This is a no-op if `new` is empty.
|
||||
pub fn change_authorities(new: BoundedVec<T::AuthorityId, T::MaxAuthorities>) {
|
||||
if new.is_empty() {
|
||||
log::warn!(target: LOG_TARGET, "Ignoring empty authority change.");
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
<Authorities<T>>::put(&new);
|
||||
|
||||
let log = DigestItem::Consensus(
|
||||
AURA_ENGINE_ID,
|
||||
ConsensusLog::AuthoritiesChange(new.into_inner()).encode(),
|
||||
);
|
||||
<pezframe_system::Pallet<T>>::deposit_log(log);
|
||||
}
|
||||
|
||||
/// Initial authorities.
|
||||
///
|
||||
/// The storage will be applied immediately.
|
||||
///
|
||||
/// The authorities length must be equal or less than T::MaxAuthorities.
|
||||
pub fn initialize_authorities(authorities: &[T::AuthorityId]) {
|
||||
if !authorities.is_empty() {
|
||||
assert!(<Authorities<T>>::get().is_empty(), "Authorities are already initialized!");
|
||||
let bounded = <BoundedSlice<'_, _, T::MaxAuthorities>>::try_from(authorities)
|
||||
.expect("Initial authority set must be less than T::MaxAuthorities");
|
||||
<Authorities<T>>::put(bounded);
|
||||
}
|
||||
}
|
||||
|
||||
/// Return current authorities length.
|
||||
pub fn authorities_len() -> usize {
|
||||
Authorities::<T>::decode_len().unwrap_or(0)
|
||||
}
|
||||
|
||||
/// Get the current slot from the pre-runtime digests.
|
||||
fn current_slot_from_digests() -> Option<Slot> {
|
||||
let digest = pezframe_system::Pallet::<T>::digest();
|
||||
let pre_runtime_digests = digest.logs.iter().filter_map(|d| d.as_pre_runtime());
|
||||
for (id, mut data) in pre_runtime_digests {
|
||||
if id == AURA_ENGINE_ID {
|
||||
return Slot::decode(&mut data).ok();
|
||||
}
|
||||
}
|
||||
|
||||
None
|
||||
}
|
||||
|
||||
/// Determine the Aura slot-duration based on the Timestamp module configuration.
|
||||
pub fn slot_duration() -> T::Moment {
|
||||
T::SlotDuration::get()
|
||||
}
|
||||
|
||||
/// Ensure the correctness of the state of this pallet.
|
||||
///
|
||||
/// This should be valid before or after each state transition of this pallet.
|
||||
///
|
||||
/// # Invariants
|
||||
///
|
||||
/// ## `CurrentSlot`
|
||||
///
|
||||
/// If we don't allow for multiple blocks per slot, then the current slot must be less than the
|
||||
/// maximal slot number. Otherwise, it can be arbitrary.
|
||||
///
|
||||
/// ## `Authorities`
|
||||
///
|
||||
/// * The authorities must be non-empty.
|
||||
/// * The current authority cannot be disabled.
|
||||
/// * The number of authorities must be less than or equal to `T::MaxAuthorities`. This however,
|
||||
/// is guarded by the type system.
|
||||
#[cfg(any(test, feature = "try-runtime"))]
|
||||
pub fn do_try_state() -> Result<(), pezsp_runtime::TryRuntimeError> {
|
||||
// We don't have any guarantee that we are already after `on_initialize` and thus we have to
|
||||
// check the current slot from the digest or take the last known slot.
|
||||
let current_slot =
|
||||
Self::current_slot_from_digests().unwrap_or_else(|| CurrentSlot::<T>::get());
|
||||
|
||||
// Check that the current slot is less than the maximal slot number, unless we allow for
|
||||
// multiple blocks per slot.
|
||||
if !T::AllowMultipleBlocksPerSlot::get() {
|
||||
pezframe_support::ensure!(
|
||||
current_slot < u64::MAX,
|
||||
"Current slot has reached maximum value and cannot be incremented further.",
|
||||
);
|
||||
}
|
||||
|
||||
let authorities_len =
|
||||
<Authorities<T>>::decode_len().ok_or("Failed to decode authorities length")?;
|
||||
|
||||
// Check that the authorities are non-empty.
|
||||
pezframe_support::ensure!(!authorities_len.is_zero(), "Authorities must be non-empty.");
|
||||
|
||||
// Check that the current authority is not disabled.
|
||||
let authority_index = *current_slot % authorities_len as u64;
|
||||
pezframe_support::ensure!(
|
||||
!T::DisabledValidators::is_disabled(authority_index as u32),
|
||||
"Current validator is disabled and should not be attempting to author blocks.",
|
||||
);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Config> pezsp_runtime::BoundToRuntimeAppPublic for Pallet<T> {
|
||||
type Public = T::AuthorityId;
|
||||
}
|
||||
|
||||
impl<T: Config> OneSessionHandler<T::AccountId> for Pallet<T> {
|
||||
type Key = T::AuthorityId;
|
||||
|
||||
fn on_genesis_session<'a, I: 'a>(validators: I)
|
||||
where
|
||||
I: Iterator<Item = (&'a T::AccountId, T::AuthorityId)>,
|
||||
{
|
||||
let authorities = validators.map(|(_, k)| k).collect::<Vec<_>>();
|
||||
Self::initialize_authorities(&authorities);
|
||||
}
|
||||
|
||||
fn on_new_session<'a, I: 'a>(changed: bool, validators: I, _queued_validators: I)
|
||||
where
|
||||
I: Iterator<Item = (&'a T::AccountId, T::AuthorityId)>,
|
||||
{
|
||||
// instant changes
|
||||
if changed {
|
||||
let next_authorities = validators.map(|(_, k)| k).collect::<Vec<_>>();
|
||||
let last_authorities = Authorities::<T>::get();
|
||||
if last_authorities != next_authorities {
|
||||
if next_authorities.len() as u32 > T::MaxAuthorities::get() {
|
||||
log::warn!(
|
||||
target: LOG_TARGET,
|
||||
"next authorities list larger than {}, truncating",
|
||||
T::MaxAuthorities::get(),
|
||||
);
|
||||
}
|
||||
let bounded = <BoundedVec<_, T::MaxAuthorities>>::truncate_from(next_authorities);
|
||||
Self::change_authorities(bounded);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn on_disabled(i: u32) {
|
||||
let log = DigestItem::Consensus(
|
||||
AURA_ENGINE_ID,
|
||||
ConsensusLog::<T::AuthorityId>::OnDisabled(i as AuthorityIndex).encode(),
|
||||
);
|
||||
|
||||
<pezframe_system::Pallet<T>>::deposit_log(log);
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Config> FindAuthor<u32> for Pallet<T> {
|
||||
fn find_author<'a, I>(digests: I) -> Option<u32>
|
||||
where
|
||||
I: 'a + IntoIterator<Item = (ConsensusEngineId, &'a [u8])>,
|
||||
{
|
||||
for (id, mut data) in digests.into_iter() {
|
||||
if id == AURA_ENGINE_ID {
|
||||
let slot = Slot::decode(&mut data).ok()?;
|
||||
let author_index = *slot % Self::authorities_len() as u64;
|
||||
return Some(author_index as u32);
|
||||
}
|
||||
}
|
||||
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
/// We can not implement `FindAuthor` twice, because the compiler does not know if
|
||||
/// `u32 == T::AuthorityId` and thus, prevents us to implement the trait twice.
|
||||
#[doc(hidden)]
|
||||
pub struct FindAccountFromAuthorIndex<T, Inner>(core::marker::PhantomData<(T, Inner)>);
|
||||
|
||||
impl<T: Config, Inner: FindAuthor<u32>> FindAuthor<T::AuthorityId>
|
||||
for FindAccountFromAuthorIndex<T, Inner>
|
||||
{
|
||||
fn find_author<'a, I>(digests: I) -> Option<T::AuthorityId>
|
||||
where
|
||||
I: 'a + IntoIterator<Item = (ConsensusEngineId, &'a [u8])>,
|
||||
{
|
||||
let i = Inner::find_author(digests)?;
|
||||
|
||||
let validators = Authorities::<T>::get();
|
||||
validators.get(i as usize).cloned()
|
||||
}
|
||||
}
|
||||
|
||||
/// Find the authority ID of the Aura authority who authored the current block.
|
||||
pub type AuraAuthorId<T> = FindAccountFromAuthorIndex<T, Pallet<T>>;
|
||||
|
||||
impl<T: Config> IsMember<T::AuthorityId> for Pallet<T> {
|
||||
fn is_member(authority_id: &T::AuthorityId) -> bool {
|
||||
Authorities::<T>::get().iter().any(|id| id == authority_id)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Config> OnTimestampSet<T::Moment> for Pallet<T> {
|
||||
fn on_timestamp_set(moment: T::Moment) {
|
||||
let slot_duration = Self::slot_duration();
|
||||
assert!(!slot_duration.is_zero(), "Aura slot duration cannot be zero.");
|
||||
|
||||
let timestamp_slot = moment / slot_duration;
|
||||
let timestamp_slot = Slot::from(timestamp_slot.saturated_into::<u64>());
|
||||
|
||||
assert_eq!(
|
||||
CurrentSlot::<T>::get(),
|
||||
timestamp_slot,
|
||||
"Timestamp slot must match `CurrentSlot`. This likely means that the configured block \
|
||||
time in the node and/or rest of the runtime is not compatible with Aura's \
|
||||
`SlotDuration`",
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
// 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.
|
||||
|
||||
//! Migrations for the AURA pallet.
|
||||
|
||||
use pezframe_support::{pezpallet_prelude::*, traits::Get, weights::Weight};
|
||||
|
||||
struct __LastTimestamp<T>(core::marker::PhantomData<T>);
|
||||
impl<T: RemoveLastTimestamp> pezframe_support::traits::StorageInstance for __LastTimestamp<T> {
|
||||
fn pezpallet_prefix() -> &'static str {
|
||||
T::PalletPrefix::get()
|
||||
}
|
||||
const STORAGE_PREFIX: &'static str = "LastTimestamp";
|
||||
}
|
||||
|
||||
type LastTimestamp<T> = StorageValue<__LastTimestamp<T>, (), ValueQuery>;
|
||||
|
||||
pub trait RemoveLastTimestamp: super::Config {
|
||||
type PalletPrefix: Get<&'static str>;
|
||||
}
|
||||
|
||||
/// Remove the `LastTimestamp` storage value.
|
||||
///
|
||||
/// This storage value was removed and replaced by `CurrentSlot`. As we only remove this storage
|
||||
/// value, it is safe to call this method multiple times.
|
||||
///
|
||||
/// This migration requires a type `T` that implements [`RemoveLastTimestamp`].
|
||||
pub fn remove_last_timestamp<T: RemoveLastTimestamp>() -> Weight {
|
||||
LastTimestamp::<T>::kill();
|
||||
T::DbWeight::get().writes(1)
|
||||
}
|
||||
@@ -0,0 +1,106 @@
|
||||
// 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.
|
||||
|
||||
//! Test utilities
|
||||
|
||||
#![cfg(test)]
|
||||
|
||||
use crate as pezpallet_aura;
|
||||
use pezframe_support::{
|
||||
derive_impl, parameter_types,
|
||||
traits::{ConstU32, ConstU64, DisabledValidators},
|
||||
};
|
||||
use pezsp_consensus_aura::{ed25519::AuthorityId, AuthorityIndex};
|
||||
use pezsp_runtime::{testing::UintAuthorityId, BuildStorage};
|
||||
|
||||
type Block = pezframe_system::mocking::MockBlock<Test>;
|
||||
|
||||
const SLOT_DURATION: u64 = 2;
|
||||
|
||||
pezframe_support::construct_runtime!(
|
||||
pub enum Test
|
||||
{
|
||||
System: pezframe_system,
|
||||
Timestamp: pezpallet_timestamp,
|
||||
Aura: pezpallet_aura,
|
||||
}
|
||||
);
|
||||
|
||||
#[derive_impl(pezframe_system::config_preludes::TestDefaultConfig)]
|
||||
impl pezframe_system::Config for Test {
|
||||
type Block = Block;
|
||||
}
|
||||
|
||||
impl pezpallet_timestamp::Config for Test {
|
||||
type Moment = u64;
|
||||
type OnTimestampSet = Aura;
|
||||
type MinimumPeriod = ConstU64<{ SLOT_DURATION / 2 }>;
|
||||
type WeightInfo = ();
|
||||
}
|
||||
|
||||
parameter_types! {
|
||||
static DisabledValidatorTestValue: Vec<AuthorityIndex> = Default::default();
|
||||
pub static AllowMultipleBlocksPerSlot: bool = false;
|
||||
}
|
||||
|
||||
pub struct MockDisabledValidators;
|
||||
|
||||
impl MockDisabledValidators {
|
||||
pub fn disable_validator(index: AuthorityIndex) {
|
||||
DisabledValidatorTestValue::mutate(|v| {
|
||||
if let Err(i) = v.binary_search(&index) {
|
||||
v.insert(i, index);
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl DisabledValidators for MockDisabledValidators {
|
||||
fn is_disabled(index: AuthorityIndex) -> bool {
|
||||
DisabledValidatorTestValue::get().binary_search(&index).is_ok()
|
||||
}
|
||||
|
||||
fn disabled_validators() -> Vec<u32> {
|
||||
DisabledValidatorTestValue::get()
|
||||
}
|
||||
}
|
||||
|
||||
impl pezpallet_aura::Config for Test {
|
||||
type AuthorityId = AuthorityId;
|
||||
type DisabledValidators = MockDisabledValidators;
|
||||
type MaxAuthorities = ConstU32<10>;
|
||||
type AllowMultipleBlocksPerSlot = AllowMultipleBlocksPerSlot;
|
||||
type SlotDuration = ConstU64<SLOT_DURATION>;
|
||||
}
|
||||
|
||||
fn build_ext(authorities: Vec<u64>) -> pezsp_io::TestExternalities {
|
||||
let mut storage = pezframe_system::GenesisConfig::<Test>::default().build_storage().unwrap();
|
||||
pezpallet_aura::GenesisConfig::<Test> {
|
||||
authorities: authorities.into_iter().map(|a| UintAuthorityId(a).to_public_key()).collect(),
|
||||
}
|
||||
.assimilate_storage(&mut storage)
|
||||
.unwrap();
|
||||
storage.into()
|
||||
}
|
||||
|
||||
pub fn build_ext_and_execute_test(authorities: Vec<u64>, test: impl FnOnce() -> ()) {
|
||||
let mut ext = build_ext(authorities);
|
||||
ext.execute_with(|| {
|
||||
test();
|
||||
Aura::do_try_state().expect("Storage invariants should hold")
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,119 @@
|
||||
// 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.
|
||||
|
||||
//! Tests for the module.
|
||||
|
||||
#![cfg(test)]
|
||||
|
||||
use super::pallet;
|
||||
use crate::mock::{build_ext_and_execute_test, Aura, MockDisabledValidators, System, Test};
|
||||
use codec::Encode;
|
||||
use pezframe_support::traits::OnInitialize;
|
||||
use pezsp_consensus_aura::{Slot, AURA_ENGINE_ID};
|
||||
use pezsp_runtime::{Digest, DigestItem};
|
||||
|
||||
#[test]
|
||||
fn initial_values() {
|
||||
build_ext_and_execute_test(vec![0, 1, 2, 3], || {
|
||||
assert_eq!(pallet::CurrentSlot::<Test>::get(), 0u64);
|
||||
assert_eq!(pallet::Authorities::<Test>::get().len(), Aura::authorities_len());
|
||||
assert_eq!(Aura::authorities_len(), 4);
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[should_panic(
|
||||
expected = "Validator with index 1 is disabled and should not be attempting to author blocks."
|
||||
)]
|
||||
fn disabled_validators_cannot_author_blocks() {
|
||||
build_ext_and_execute_test(vec![0, 1, 2, 3], || {
|
||||
// slot 1 should be authored by validator at index 1
|
||||
let slot = Slot::from(1);
|
||||
let pre_digest =
|
||||
Digest { logs: vec![DigestItem::PreRuntime(AURA_ENGINE_ID, slot.encode())] };
|
||||
|
||||
System::reset_events();
|
||||
System::initialize(&1, &System::parent_hash(), &pre_digest);
|
||||
|
||||
// let's disable the validator
|
||||
MockDisabledValidators::disable_validator(1);
|
||||
|
||||
// and we should not be able to initialize the block
|
||||
Aura::on_initialize(1);
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[should_panic(expected = "Slot must increase")]
|
||||
fn pezpallet_requires_slot_to_increase_unless_allowed() {
|
||||
build_ext_and_execute_test(vec![0, 1, 2, 3], || {
|
||||
crate::mock::AllowMultipleBlocksPerSlot::set(false);
|
||||
|
||||
let slot = Slot::from(1);
|
||||
let pre_digest =
|
||||
Digest { logs: vec![DigestItem::PreRuntime(AURA_ENGINE_ID, slot.encode())] };
|
||||
|
||||
System::reset_events();
|
||||
System::initialize(&1, &System::parent_hash(), &pre_digest);
|
||||
|
||||
// and we should not be able to initialize the block with the same slot a second time.
|
||||
Aura::on_initialize(1);
|
||||
Aura::on_initialize(1);
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn pezpallet_can_allow_unchanged_slot() {
|
||||
build_ext_and_execute_test(vec![0, 1, 2, 3], || {
|
||||
let slot = Slot::from(1);
|
||||
let pre_digest =
|
||||
Digest { logs: vec![DigestItem::PreRuntime(AURA_ENGINE_ID, slot.encode())] };
|
||||
|
||||
System::reset_events();
|
||||
System::initialize(&1, &System::parent_hash(), &pre_digest);
|
||||
|
||||
crate::mock::AllowMultipleBlocksPerSlot::set(true);
|
||||
|
||||
// and we should be able to initialize the block with the same slot a second time.
|
||||
Aura::on_initialize(1);
|
||||
Aura::on_initialize(1);
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[should_panic(expected = "Slot must not decrease")]
|
||||
fn pezpallet_always_rejects_decreasing_slot() {
|
||||
build_ext_and_execute_test(vec![0, 1, 2, 3], || {
|
||||
let slot = Slot::from(2);
|
||||
let pre_digest =
|
||||
Digest { logs: vec![DigestItem::PreRuntime(AURA_ENGINE_ID, slot.encode())] };
|
||||
|
||||
System::reset_events();
|
||||
System::initialize(&1, &System::parent_hash(), &pre_digest);
|
||||
|
||||
crate::mock::AllowMultipleBlocksPerSlot::set(true);
|
||||
|
||||
Aura::on_initialize(1);
|
||||
System::finalize();
|
||||
|
||||
let earlier_slot = Slot::from(1);
|
||||
let pre_digest =
|
||||
Digest { logs: vec![DigestItem::PreRuntime(AURA_ENGINE_ID, earlier_slot.encode())] };
|
||||
System::initialize(&2, &System::parent_hash(), &pre_digest);
|
||||
Aura::on_initialize(2);
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user