Refactoring Checkpoint: (WIP)
This commit is contained in:
@@ -0,0 +1,142 @@
|
||||
//! Benchmarking setup for pezpallet-validator-pool
|
||||
|
||||
use super::*;
|
||||
use pezframe_benchmarking::v2::*;
|
||||
use pezframe_system::{pezpallet_prelude::BlockNumberFor, RawOrigin};
|
||||
use pezsp_std::vec;
|
||||
|
||||
#[benchmarks]
|
||||
mod benchmarks {
|
||||
use super::*;
|
||||
|
||||
#[benchmark]
|
||||
fn join_validator_pool() {
|
||||
let caller: T::AccountId = whitelisted_caller();
|
||||
|
||||
let category = ValidatorPoolCategory::StakeValidator {
|
||||
min_stake: T::MinStakeAmount::get(),
|
||||
trust_threshold: 100u128, // Low threshold for benchmarking
|
||||
};
|
||||
|
||||
#[extrinsic_call]
|
||||
_(RawOrigin::Signed(caller.clone()), category.clone());
|
||||
|
||||
// Verify the validator was added
|
||||
assert!(PoolMembers::<T>::contains_key(&caller));
|
||||
assert!(PerformanceMetrics::<T>::contains_key(&caller));
|
||||
}
|
||||
|
||||
#[benchmark]
|
||||
fn leave_validator_pool() {
|
||||
let caller: T::AccountId = whitelisted_caller();
|
||||
|
||||
let category = ValidatorPoolCategory::StakeValidator {
|
||||
min_stake: T::MinStakeAmount::get(),
|
||||
trust_threshold: 100u128,
|
||||
};
|
||||
|
||||
PoolMembers::<T>::insert(&caller, &category);
|
||||
PoolSize::<T>::put(1u32);
|
||||
PerformanceMetrics::<T>::insert(&caller, ValidatorPerformance::default());
|
||||
|
||||
#[extrinsic_call]
|
||||
_(RawOrigin::Signed(caller.clone()));
|
||||
|
||||
// Verify the validator was removed
|
||||
assert!(!PoolMembers::<T>::contains_key(&caller));
|
||||
assert!(!PerformanceMetrics::<T>::contains_key(&caller));
|
||||
}
|
||||
|
||||
#[benchmark]
|
||||
fn update_performance_metrics() {
|
||||
let validator: T::AccountId = whitelisted_caller();
|
||||
|
||||
PerformanceMetrics::<T>::insert(&validator, ValidatorPerformance::default());
|
||||
|
||||
#[extrinsic_call]
|
||||
_(
|
||||
RawOrigin::Root,
|
||||
validator.clone(),
|
||||
100u32, // blocks_produced
|
||||
10u32, // blocks_missed
|
||||
500u32, // era_points
|
||||
);
|
||||
|
||||
// Verify metrics were updated
|
||||
let metrics = PerformanceMetrics::<T>::get(&validator);
|
||||
assert_eq!(metrics.blocks_produced, 100);
|
||||
}
|
||||
|
||||
#[benchmark]
|
||||
fn force_new_era(p: Linear<4, 100>, // Pool size
|
||||
) {
|
||||
// Add validators to pool
|
||||
for i in 0..p {
|
||||
let validator: T::AccountId = account("validator", i, 0);
|
||||
let category = match i % 3 {
|
||||
0 => ValidatorPoolCategory::StakeValidator {
|
||||
min_stake: T::MinStakeAmount::get(),
|
||||
trust_threshold: 100u128,
|
||||
},
|
||||
1 => ValidatorPoolCategory::ParliamentaryValidator,
|
||||
_ => ValidatorPoolCategory::MeritValidator {
|
||||
special_tikis: vec![1u8].try_into().unwrap(),
|
||||
community_threshold: 100u32,
|
||||
},
|
||||
};
|
||||
|
||||
PoolMembers::<T>::insert(&validator, &category);
|
||||
|
||||
let performance = ValidatorPerformance {
|
||||
blocks_produced: 90,
|
||||
blocks_missed: 10,
|
||||
era_points: 500,
|
||||
last_active_era: 0,
|
||||
reputation_score: 90,
|
||||
};
|
||||
PerformanceMetrics::<T>::insert(&validator, performance);
|
||||
}
|
||||
|
||||
PoolSize::<T>::put(p);
|
||||
EraLength::<T>::put(BlockNumberFor::<T>::from(100u32));
|
||||
|
||||
#[extrinsic_call]
|
||||
_(RawOrigin::Root);
|
||||
|
||||
// Verify new era was created
|
||||
assert_eq!(CurrentEra::<T>::get(), 1);
|
||||
assert!(CurrentValidatorSet::<T>::get().is_some());
|
||||
}
|
||||
|
||||
#[benchmark]
|
||||
fn update_category() {
|
||||
let caller: T::AccountId = whitelisted_caller();
|
||||
|
||||
let initial_category = ValidatorPoolCategory::StakeValidator {
|
||||
min_stake: T::MinStakeAmount::get(),
|
||||
trust_threshold: 100u128,
|
||||
};
|
||||
PoolMembers::<T>::insert(&caller, &initial_category);
|
||||
|
||||
let new_category = ValidatorPoolCategory::ParliamentaryValidator;
|
||||
|
||||
#[extrinsic_call]
|
||||
_(RawOrigin::Signed(caller.clone()), new_category.clone());
|
||||
|
||||
// Verify category was updated
|
||||
assert_eq!(PoolMembers::<T>::get(&caller).unwrap(), new_category);
|
||||
}
|
||||
|
||||
#[benchmark]
|
||||
fn set_pool_parameters() {
|
||||
let new_era_length = BlockNumberFor::<T>::from(200u32);
|
||||
|
||||
#[extrinsic_call]
|
||||
_(RawOrigin::Root, new_era_length);
|
||||
|
||||
// Verify parameters were updated
|
||||
assert_eq!(EraLength::<T>::get(), new_era_length);
|
||||
}
|
||||
|
||||
impl_benchmark_test_suite!(ValidatorPool, crate::mock::new_test_ext(), crate::mock::Test);
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,274 @@
|
||||
use super::*;
|
||||
use crate::{self as pezpallet_validator_pool, types::*};
|
||||
use pezframe_support::{
|
||||
construct_runtime, parameter_types,
|
||||
traits::{ConstU32, Everything},
|
||||
};
|
||||
use pezframe_system as system;
|
||||
use pezsp_core::H256;
|
||||
use pezsp_runtime::{
|
||||
traits::{BlakeTwo256, IdentityLookup},
|
||||
BuildStorage,
|
||||
};
|
||||
|
||||
pub type AccountId = u64;
|
||||
pub type Balance = u128;
|
||||
pub type BlockNumber = u64;
|
||||
|
||||
// Configure a mock runtime to test the pallet.
|
||||
// Note: We don't include pezpallet_session here because it requires complex Currency setup.
|
||||
// We can test SessionManager trait implementation directly.
|
||||
construct_runtime!(
|
||||
pub enum Test {
|
||||
System: pezframe_system,
|
||||
Balances: pezpallet_balances,
|
||||
ValidatorPool: pezpallet_validator_pool,
|
||||
}
|
||||
);
|
||||
|
||||
parameter_types! {
|
||||
pub const BlockHashCount: u64 = 250;
|
||||
pub const SS58Prefix: u8 = 42;
|
||||
}
|
||||
|
||||
impl system::Config for Test {
|
||||
type BaseCallFilter = Everything;
|
||||
type BlockWeights = ();
|
||||
type BlockLength = ();
|
||||
type DbWeight = ();
|
||||
type RuntimeOrigin = RuntimeOrigin;
|
||||
type RuntimeCall = RuntimeCall;
|
||||
type RuntimeTask = ();
|
||||
type Nonce = u64;
|
||||
type Hash = H256;
|
||||
type Hashing = BlakeTwo256;
|
||||
type AccountId = AccountId;
|
||||
type Lookup = IdentityLookup<Self::AccountId>;
|
||||
type Block = pezframe_system::mocking::MockBlock<Test>;
|
||||
type RuntimeEvent = RuntimeEvent;
|
||||
type BlockHashCount = BlockHashCount;
|
||||
type Version = ();
|
||||
type PalletInfo = PalletInfo;
|
||||
type AccountData = pezpallet_balances::AccountData<Balance>;
|
||||
type OnNewAccount = ();
|
||||
type OnKilledAccount = ();
|
||||
type SystemWeightInfo = ();
|
||||
type SS58Prefix = SS58Prefix;
|
||||
type OnSetCode = ();
|
||||
type MaxConsumers = ConstU32<16>;
|
||||
type ExtensionsWeightInfo = ();
|
||||
type SingleBlockMigrations = ();
|
||||
type MultiBlockMigrator = ();
|
||||
type PreInherents = ();
|
||||
type PostInherents = ();
|
||||
type PostTransactions = ();
|
||||
}
|
||||
|
||||
parameter_types! {
|
||||
pub const ExistentialDeposit: Balance = 1;
|
||||
pub const MaxLocks: u32 = 50;
|
||||
pub const MaxReserves: u32 = 50;
|
||||
}
|
||||
|
||||
impl pezpallet_balances::Config for Test {
|
||||
type MaxLocks = MaxLocks;
|
||||
type MaxReserves = MaxReserves;
|
||||
type ReserveIdentifier = [u8; 8];
|
||||
type Balance = Balance;
|
||||
type RuntimeEvent = RuntimeEvent;
|
||||
type DustRemoval = ();
|
||||
type ExistentialDeposit = ExistentialDeposit;
|
||||
type AccountStore = System;
|
||||
type WeightInfo = ();
|
||||
type FreezeIdentifier = ();
|
||||
type MaxFreezes = ();
|
||||
type RuntimeHoldReason = ();
|
||||
type RuntimeFreezeReason = ();
|
||||
type DoneSlashHandler = ();
|
||||
}
|
||||
|
||||
// Mock Randomness
|
||||
pub struct MockRandomness;
|
||||
impl Randomness<H256, BlockNumber> for MockRandomness {
|
||||
fn random(subject: &[u8]) -> (H256, BlockNumber) {
|
||||
let mut hash = H256::zero();
|
||||
// Simple deterministic randomness for testing
|
||||
if !subject.is_empty() {
|
||||
hash.as_mut()[0] = subject[0];
|
||||
}
|
||||
(hash, 1)
|
||||
}
|
||||
}
|
||||
|
||||
// Test implementations for trait dependencies
|
||||
pub struct TestTrustProvider;
|
||||
impl TrustScoreProvider<AccountId> for TestTrustProvider {
|
||||
fn trust_score_of(who: &AccountId) -> u128 {
|
||||
match who {
|
||||
1..=15 => 1000, // Test users with high trust (threshold: 450)
|
||||
_ => 100, // Others have insufficient trust
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct TestTikiProvider;
|
||||
impl TikiScoreProvider<AccountId> for TestTikiProvider {
|
||||
fn get_tiki_score(who: &AccountId) -> u32 {
|
||||
match who {
|
||||
1..=15 => 1, // Tüm test user'ları için tiki var
|
||||
_ => 0,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct TestReferralProvider;
|
||||
impl ReferralProvider<AccountId> for TestReferralProvider {
|
||||
fn get_referral_count(who: &AccountId) -> u32 {
|
||||
match who {
|
||||
1..=15 => 1000, // Tüm test user'ları için yüksek community support (threshold: 500)
|
||||
_ => 600, // Diğerleri için de yeterli
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct TestPerwerdeProvider;
|
||||
impl PerwerdeProvider<AccountId> for TestPerwerdeProvider {
|
||||
fn get_perwerde_score(who: &AccountId) -> u32 {
|
||||
match who {
|
||||
1..=15 => 100, // Tüm test user'ları için perwerde var
|
||||
_ => 50,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
parameter_types! {
|
||||
pub const MaxValidators: u32 = 21;
|
||||
pub const MaxPoolSize: u32 = 500;
|
||||
pub const MinStakeAmount: u128 = 1000;
|
||||
}
|
||||
|
||||
// Mock WeightInfo implementation
|
||||
pub struct MockWeightInfo;
|
||||
impl crate::WeightInfo for MockWeightInfo {
|
||||
fn join_validator_pool() -> pezframe_support::weights::Weight {
|
||||
pezframe_support::weights::Weight::from_parts(10_000, 0)
|
||||
}
|
||||
|
||||
fn leave_validator_pool() -> pezframe_support::weights::Weight {
|
||||
pezframe_support::weights::Weight::from_parts(10_000, 0)
|
||||
}
|
||||
|
||||
fn update_performance_metrics() -> pezframe_support::weights::Weight {
|
||||
pezframe_support::weights::Weight::from_parts(10_000, 0)
|
||||
}
|
||||
|
||||
fn force_new_era() -> pezframe_support::weights::Weight {
|
||||
pezframe_support::weights::Weight::from_parts(50_000, 0)
|
||||
}
|
||||
|
||||
fn update_category() -> pezframe_support::weights::Weight {
|
||||
pezframe_support::weights::Weight::from_parts(10_000, 0)
|
||||
}
|
||||
|
||||
fn set_pool_parameters() -> pezframe_support::weights::Weight {
|
||||
pezframe_support::weights::Weight::from_parts(10_000, 0)
|
||||
}
|
||||
}
|
||||
|
||||
impl Config for Test {
|
||||
type RuntimeEvent = RuntimeEvent;
|
||||
type WeightInfo = MockWeightInfo;
|
||||
type Randomness = MockRandomness;
|
||||
type TrustSource = TestTrustProvider;
|
||||
type TikiSource = TestTikiProvider;
|
||||
type ReferralSource = TestReferralProvider;
|
||||
type PerwerdeSource = TestPerwerdeProvider;
|
||||
type PoolManagerOrigin = pezframe_system::EnsureRoot<AccountId>;
|
||||
type MaxValidators = MaxValidators;
|
||||
type MaxPoolSize = MaxPoolSize;
|
||||
type MinStakeAmount = MinStakeAmount;
|
||||
}
|
||||
|
||||
// Build genesis storage according to the mock runtime.
|
||||
pub fn new_test_ext() -> pezsp_io::TestExternalities {
|
||||
new_test_ext_with_mode(OperationMode::Active)
|
||||
}
|
||||
|
||||
// Build genesis storage with specific operation mode
|
||||
pub fn new_test_ext_with_mode(mode: OperationMode) -> pezsp_io::TestExternalities {
|
||||
let mut storage = system::GenesisConfig::<Test>::default().build_storage().unwrap();
|
||||
|
||||
// Initialize balances - Fixed genesis config with correct type
|
||||
pezpallet_balances::GenesisConfig::<Test> {
|
||||
balances: vec![
|
||||
(1, 10000),
|
||||
(2, 8000),
|
||||
(3, 6000),
|
||||
(4, 4000),
|
||||
(5, 2000),
|
||||
(6, 5000),
|
||||
(7, 5000),
|
||||
(8, 5000),
|
||||
(9, 5000),
|
||||
(10, 5000),
|
||||
],
|
||||
dev_accounts: None,
|
||||
}
|
||||
.assimilate_storage(&mut storage)
|
||||
.unwrap();
|
||||
|
||||
// Initialize validator pool with genesis config
|
||||
pezpallet_validator_pool::GenesisConfig::<Test> {
|
||||
operation_mode: mode,
|
||||
era_length: 100,
|
||||
initial_pool_members: vec![],
|
||||
}
|
||||
.assimilate_storage(&mut storage)
|
||||
.unwrap();
|
||||
|
||||
let mut ext = pezsp_io::TestExternalities::new(storage);
|
||||
ext.execute_with(|| {
|
||||
System::set_block_number(1);
|
||||
});
|
||||
ext
|
||||
}
|
||||
|
||||
// Build genesis storage for shadow mode testing
|
||||
pub fn new_test_ext_shadow_mode() -> pezsp_io::TestExternalities {
|
||||
new_test_ext_with_mode(OperationMode::Shadow)
|
||||
}
|
||||
|
||||
// Helper functions for tests
|
||||
pub fn run_to_block(n: u64) {
|
||||
while System::block_number() < n {
|
||||
if System::block_number() > 1 {
|
||||
ValidatorPool::on_finalize(System::block_number());
|
||||
System::on_finalize(System::block_number());
|
||||
}
|
||||
System::set_block_number(System::block_number() + 1);
|
||||
System::on_initialize(System::block_number());
|
||||
ValidatorPool::on_initialize(System::block_number());
|
||||
}
|
||||
}
|
||||
|
||||
pub fn advance_era() {
|
||||
let current_era_start = ValidatorPool::era_start();
|
||||
let era_length = ValidatorPool::era_length();
|
||||
run_to_block(current_era_start + era_length + 1);
|
||||
}
|
||||
|
||||
// Create test categories
|
||||
pub fn stake_validator_category() -> ValidatorPoolCategory {
|
||||
ValidatorPoolCategory::StakeValidator { min_stake: 1000, trust_threshold: 450 }
|
||||
}
|
||||
|
||||
pub fn parliamentary_validator_category() -> ValidatorPoolCategory {
|
||||
ValidatorPoolCategory::ParliamentaryValidator
|
||||
}
|
||||
|
||||
pub fn merit_validator_category() -> ValidatorPoolCategory {
|
||||
ValidatorPoolCategory::MeritValidator {
|
||||
special_tikis: vec![1u8].try_into().unwrap(), // Mock tiki type
|
||||
community_threshold: 500,
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,799 @@
|
||||
use super::*;
|
||||
use crate::{mock::*, types::OperationMode};
|
||||
use pezframe_support::{assert_noop, assert_ok};
|
||||
// Import SessionManager trait for testing
|
||||
use pezpallet_session::SessionManager;
|
||||
|
||||
#[test]
|
||||
fn join_validator_pool_works() {
|
||||
new_test_ext().execute_with(|| {
|
||||
// User 1 has high trust (800) and tiki score (1)
|
||||
assert_ok!(ValidatorPool::join_validator_pool(
|
||||
RuntimeOrigin::signed(1),
|
||||
stake_validator_category()
|
||||
));
|
||||
|
||||
// Check storage
|
||||
assert!(ValidatorPool::pool_members(1).is_some());
|
||||
assert_eq!(ValidatorPool::pool_size(), 1);
|
||||
|
||||
// Check performance metrics initialized
|
||||
let metrics = ValidatorPool::performance_metrics(1);
|
||||
assert_eq!(metrics.reputation_score, 100);
|
||||
assert_eq!(metrics.blocks_produced, 0);
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn join_validator_pool_fails_insufficient_trust() {
|
||||
new_test_ext().execute_with(|| {
|
||||
assert_noop!(
|
||||
ValidatorPool::join_validator_pool(
|
||||
RuntimeOrigin::signed(99),
|
||||
stake_validator_category()
|
||||
),
|
||||
Error::<Test>::InsufficientTrustScore
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn join_validator_pool_fails_already_in_pool() {
|
||||
new_test_ext().execute_with(|| {
|
||||
// First join succeeds
|
||||
assert_ok!(ValidatorPool::join_validator_pool(
|
||||
RuntimeOrigin::signed(1),
|
||||
stake_validator_category()
|
||||
));
|
||||
|
||||
// Second join fails
|
||||
assert_noop!(
|
||||
ValidatorPool::join_validator_pool(
|
||||
RuntimeOrigin::signed(1),
|
||||
stake_validator_category()
|
||||
),
|
||||
Error::<Test>::AlreadyInPool
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn leave_validator_pool_works() {
|
||||
new_test_ext().execute_with(|| {
|
||||
// Join first
|
||||
assert_ok!(ValidatorPool::join_validator_pool(
|
||||
RuntimeOrigin::signed(1),
|
||||
stake_validator_category()
|
||||
));
|
||||
assert_eq!(ValidatorPool::pool_size(), 1);
|
||||
|
||||
// Leave pool
|
||||
assert_ok!(ValidatorPool::leave_validator_pool(RuntimeOrigin::signed(1)));
|
||||
|
||||
// Check storage cleaned up
|
||||
assert!(ValidatorPool::pool_members(1).is_none());
|
||||
assert_eq!(ValidatorPool::pool_size(), 0);
|
||||
|
||||
// Performance metrics should be removed
|
||||
let metrics = ValidatorPool::performance_metrics(1);
|
||||
assert_eq!(metrics.reputation_score, 0); // Default value
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn leave_validator_pool_fails_not_in_pool() {
|
||||
new_test_ext().execute_with(|| {
|
||||
assert_noop!(
|
||||
ValidatorPool::leave_validator_pool(RuntimeOrigin::signed(1)),
|
||||
Error::<Test>::NotInPool
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parliamentary_validator_category_validation() {
|
||||
new_test_ext().execute_with(|| {
|
||||
// User 1 has tiki score, should succeed
|
||||
assert_ok!(ValidatorPool::join_validator_pool(
|
||||
RuntimeOrigin::signed(1),
|
||||
parliamentary_validator_category()
|
||||
));
|
||||
|
||||
// User 16 has no tiki score, should fail
|
||||
assert_noop!(
|
||||
ValidatorPool::join_validator_pool(
|
||||
RuntimeOrigin::signed(16),
|
||||
parliamentary_validator_category()
|
||||
),
|
||||
Error::<Test>::MissingRequiredTiki
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn merit_validator_category_validation() {
|
||||
new_test_ext().execute_with(|| {
|
||||
// User 1 has both tiki score (1) and high community support (1000)
|
||||
assert_ok!(ValidatorPool::join_validator_pool(
|
||||
RuntimeOrigin::signed(1),
|
||||
merit_validator_category()
|
||||
));
|
||||
|
||||
// User 16 has no tiki score
|
||||
assert_noop!(
|
||||
ValidatorPool::join_validator_pool(
|
||||
RuntimeOrigin::signed(16),
|
||||
merit_validator_category()
|
||||
),
|
||||
Error::<Test>::MissingRequiredTiki
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn update_category_works() {
|
||||
new_test_ext().execute_with(|| {
|
||||
// Join as stake validator
|
||||
assert_ok!(ValidatorPool::join_validator_pool(
|
||||
RuntimeOrigin::signed(1),
|
||||
stake_validator_category()
|
||||
));
|
||||
|
||||
// Update to parliamentary validator
|
||||
assert_ok!(ValidatorPool::update_category(
|
||||
RuntimeOrigin::signed(1),
|
||||
parliamentary_validator_category()
|
||||
));
|
||||
|
||||
// Check category updated
|
||||
let category = ValidatorPool::pool_members(1).unwrap();
|
||||
assert!(matches!(category, ValidatorPoolCategory::ParliamentaryValidator));
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn force_new_era_works() {
|
||||
new_test_ext().execute_with(|| {
|
||||
// Add validators to pool (at least 4 for BFT)
|
||||
assert_ok!(ValidatorPool::join_validator_pool(
|
||||
RuntimeOrigin::signed(1),
|
||||
stake_validator_category()
|
||||
));
|
||||
assert_ok!(ValidatorPool::join_validator_pool(
|
||||
RuntimeOrigin::signed(2),
|
||||
parliamentary_validator_category()
|
||||
));
|
||||
assert_ok!(ValidatorPool::join_validator_pool(
|
||||
RuntimeOrigin::signed(3),
|
||||
merit_validator_category()
|
||||
));
|
||||
assert_ok!(ValidatorPool::join_validator_pool(
|
||||
RuntimeOrigin::signed(4),
|
||||
stake_validator_category()
|
||||
));
|
||||
|
||||
let initial_era = ValidatorPool::current_era();
|
||||
|
||||
// Force new era
|
||||
assert_ok!(ValidatorPool::force_new_era(RuntimeOrigin::root()));
|
||||
|
||||
// Check era incremented
|
||||
assert_eq!(ValidatorPool::current_era(), initial_era + 1);
|
||||
|
||||
// Check validator set exists
|
||||
assert!(ValidatorPool::current_validator_set().is_some());
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn automatic_era_transition_works() {
|
||||
new_test_ext().execute_with(|| {
|
||||
// Add validators
|
||||
assert_ok!(ValidatorPool::join_validator_pool(
|
||||
RuntimeOrigin::signed(1),
|
||||
stake_validator_category()
|
||||
));
|
||||
assert_ok!(ValidatorPool::join_validator_pool(
|
||||
RuntimeOrigin::signed(2),
|
||||
parliamentary_validator_category()
|
||||
));
|
||||
assert_ok!(ValidatorPool::join_validator_pool(
|
||||
RuntimeOrigin::signed(3),
|
||||
stake_validator_category()
|
||||
));
|
||||
assert_ok!(ValidatorPool::join_validator_pool(
|
||||
RuntimeOrigin::signed(4),
|
||||
stake_validator_category()
|
||||
));
|
||||
|
||||
let initial_era = ValidatorPool::current_era();
|
||||
let era_start = ValidatorPool::era_start();
|
||||
let era_length = ValidatorPool::era_length();
|
||||
|
||||
// Advance to trigger era transition
|
||||
run_to_block(era_start + era_length);
|
||||
|
||||
// Era should have automatically transitioned
|
||||
assert_eq!(ValidatorPool::current_era(), initial_era + 1);
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn validator_selection_respects_constraints() {
|
||||
new_test_ext().execute_with(|| {
|
||||
// Add different types of validators
|
||||
for i in 1..=10 {
|
||||
assert_ok!(ValidatorPool::join_validator_pool(
|
||||
RuntimeOrigin::signed(i),
|
||||
stake_validator_category()
|
||||
));
|
||||
}
|
||||
|
||||
// Force era to trigger selection
|
||||
assert_ok!(ValidatorPool::force_new_era(RuntimeOrigin::root()));
|
||||
|
||||
let validator_set = ValidatorPool::current_validator_set().unwrap();
|
||||
|
||||
assert!(!validator_set.stake_validators.is_empty());
|
||||
assert!(validator_set.total_count() <= 21);
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn performance_metrics_update_works() {
|
||||
new_test_ext().execute_with(|| {
|
||||
assert_ok!(ValidatorPool::join_validator_pool(
|
||||
RuntimeOrigin::signed(1),
|
||||
stake_validator_category()
|
||||
));
|
||||
|
||||
assert_ok!(ValidatorPool::update_performance_metrics(
|
||||
RuntimeOrigin::root(),
|
||||
1,
|
||||
100,
|
||||
10,
|
||||
500
|
||||
));
|
||||
|
||||
let metrics = ValidatorPool::performance_metrics(1);
|
||||
assert_eq!(metrics.blocks_produced, 100);
|
||||
assert_eq!(metrics.blocks_missed, 10);
|
||||
assert_eq!(metrics.era_points, 500);
|
||||
assert_eq!(metrics.reputation_score, 90);
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn poor_performance_excludes_from_selection() {
|
||||
new_test_ext().execute_with(|| {
|
||||
assert_ok!(ValidatorPool::join_validator_pool(
|
||||
RuntimeOrigin::signed(1),
|
||||
stake_validator_category()
|
||||
));
|
||||
assert_ok!(ValidatorPool::update_performance_metrics(
|
||||
RuntimeOrigin::root(),
|
||||
1,
|
||||
30,
|
||||
70,
|
||||
100
|
||||
));
|
||||
let metrics = ValidatorPool::performance_metrics(1);
|
||||
assert_eq!(metrics.reputation_score, 30);
|
||||
|
||||
// Add other good performers
|
||||
for i in 2..=5 {
|
||||
assert_ok!(ValidatorPool::join_validator_pool(
|
||||
RuntimeOrigin::signed(i),
|
||||
stake_validator_category()
|
||||
));
|
||||
}
|
||||
|
||||
assert_ok!(ValidatorPool::force_new_era(RuntimeOrigin::root()));
|
||||
let validator_set = ValidatorPool::current_validator_set().unwrap();
|
||||
assert!(!validator_set.all_validators().contains(&1));
|
||||
assert!(validator_set.all_validators().contains(&2));
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn rotation_rule_works() {
|
||||
new_test_ext().execute_with(|| {
|
||||
// Simply test that multiple validators can be added and pool works
|
||||
for i in 1..=5 {
|
||||
assert_ok!(ValidatorPool::join_validator_pool(
|
||||
RuntimeOrigin::signed(i),
|
||||
stake_validator_category()
|
||||
));
|
||||
}
|
||||
|
||||
// Test that pool size is correct
|
||||
assert_eq!(ValidatorPool::pool_size(), 5);
|
||||
|
||||
// Test that we can remove validators
|
||||
assert_ok!(ValidatorPool::leave_validator_pool(RuntimeOrigin::signed(1)));
|
||||
assert_eq!(ValidatorPool::pool_size(), 4);
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn pool_size_limit_enforced() {
|
||||
new_test_ext().execute_with(|| {
|
||||
assert_ok!(ValidatorPool::join_validator_pool(
|
||||
RuntimeOrigin::signed(1),
|
||||
stake_validator_category()
|
||||
));
|
||||
assert_eq!(ValidatorPool::pool_size(), 1);
|
||||
|
||||
assert_ok!(ValidatorPool::join_validator_pool(
|
||||
RuntimeOrigin::signed(2),
|
||||
parliamentary_validator_category()
|
||||
));
|
||||
assert_eq!(ValidatorPool::pool_size(), 2);
|
||||
|
||||
assert_ok!(ValidatorPool::leave_validator_pool(RuntimeOrigin::signed(1)));
|
||||
assert_eq!(ValidatorPool::pool_size(), 1);
|
||||
|
||||
assert_ok!(ValidatorPool::join_validator_pool(
|
||||
RuntimeOrigin::signed(3),
|
||||
merit_validator_category()
|
||||
));
|
||||
assert_eq!(ValidatorPool::pool_size(), 2);
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn set_pool_parameters_works() {
|
||||
new_test_ext().execute_with(|| {
|
||||
assert_noop!(
|
||||
ValidatorPool::set_pool_parameters(RuntimeOrigin::signed(1), 200),
|
||||
pezsp_runtime::DispatchError::BadOrigin
|
||||
);
|
||||
assert_ok!(ValidatorPool::set_pool_parameters(RuntimeOrigin::root(), 200));
|
||||
assert_eq!(ValidatorPool::era_length(), 200);
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn session_manager_integration_works() {
|
||||
new_test_ext().execute_with(|| {
|
||||
for i in 1..=5 {
|
||||
assert_ok!(ValidatorPool::join_validator_pool(
|
||||
RuntimeOrigin::signed(i),
|
||||
stake_validator_category()
|
||||
));
|
||||
}
|
||||
assert_ok!(ValidatorPool::force_new_era(RuntimeOrigin::root()));
|
||||
let validators = <ValidatorPool as SessionManager<u64>>::new_session(1);
|
||||
assert!(validators.is_some());
|
||||
let validator_list = validators.unwrap();
|
||||
assert!(!validator_list.is_empty());
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn validator_set_distribution_works() {
|
||||
new_test_ext().execute_with(|| {
|
||||
for i in 1..=15 {
|
||||
let category = match i {
|
||||
1..=10 => stake_validator_category(),
|
||||
11..=13 => parliamentary_validator_category(),
|
||||
_ => merit_validator_category(),
|
||||
};
|
||||
assert_ok!(ValidatorPool::join_validator_pool(RuntimeOrigin::signed(i), category));
|
||||
}
|
||||
assert_ok!(ValidatorPool::force_new_era(RuntimeOrigin::root()));
|
||||
let validator_set = ValidatorPool::current_validator_set().unwrap();
|
||||
assert!(validator_set.total_count() > 0);
|
||||
assert!(validator_set.total_count() <= 21);
|
||||
assert!(!validator_set.stake_validators.is_empty());
|
||||
assert!(!validator_set.parliamentary_validators.is_empty());
|
||||
assert!(!validator_set.merit_validators.is_empty());
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn events_are_emitted() {
|
||||
new_test_ext().execute_with(|| {
|
||||
System::set_block_number(1);
|
||||
assert_ok!(ValidatorPool::join_validator_pool(
|
||||
RuntimeOrigin::signed(1),
|
||||
stake_validator_category()
|
||||
));
|
||||
let events = System::events();
|
||||
assert!(events.iter().any(|event| matches!(
|
||||
event.event,
|
||||
RuntimeEvent::ValidatorPool(crate::Event::ValidatorJoinedPool { .. })
|
||||
)));
|
||||
|
||||
System::reset_events();
|
||||
assert_ok!(ValidatorPool::leave_validator_pool(RuntimeOrigin::signed(1)));
|
||||
let events = System::events();
|
||||
assert!(events.iter().any(|event| matches!(
|
||||
event.event,
|
||||
RuntimeEvent::ValidatorPool(crate::Event::ValidatorLeftPool { .. })
|
||||
)));
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn minimum_validator_count_enforced() {
|
||||
new_test_ext().execute_with(|| {
|
||||
assert_ok!(ValidatorPool::join_validator_pool(
|
||||
RuntimeOrigin::signed(1),
|
||||
stake_validator_category()
|
||||
));
|
||||
assert_ok!(ValidatorPool::join_validator_pool(
|
||||
RuntimeOrigin::signed(2),
|
||||
parliamentary_validator_category()
|
||||
));
|
||||
assert_noop!(
|
||||
ValidatorPool::force_new_era(RuntimeOrigin::root()),
|
||||
Error::<Test>::NotEnoughValidators
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn complex_era_transition_scenario() {
|
||||
new_test_ext().execute_with(|| {
|
||||
// Test validator addition with different categories
|
||||
assert_ok!(ValidatorPool::join_validator_pool(
|
||||
RuntimeOrigin::signed(1),
|
||||
stake_validator_category()
|
||||
));
|
||||
assert_ok!(ValidatorPool::join_validator_pool(
|
||||
RuntimeOrigin::signed(2),
|
||||
parliamentary_validator_category()
|
||||
));
|
||||
assert_ok!(ValidatorPool::join_validator_pool(
|
||||
RuntimeOrigin::signed(3),
|
||||
merit_validator_category()
|
||||
));
|
||||
|
||||
// Test performance metrics update
|
||||
assert_ok!(ValidatorPool::update_performance_metrics(
|
||||
RuntimeOrigin::root(),
|
||||
1,
|
||||
90,
|
||||
10,
|
||||
500
|
||||
));
|
||||
let metrics = ValidatorPool::performance_metrics(1);
|
||||
assert_eq!(metrics.reputation_score, 90);
|
||||
|
||||
// Test category update
|
||||
assert_ok!(ValidatorPool::update_category(
|
||||
RuntimeOrigin::signed(1),
|
||||
parliamentary_validator_category()
|
||||
));
|
||||
|
||||
// Test pool size
|
||||
assert_eq!(ValidatorPool::pool_size(), 3);
|
||||
});
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// SHADOW MODE TESTS
|
||||
// ============================================================================
|
||||
|
||||
#[test]
|
||||
fn genesis_sets_operation_mode() {
|
||||
// Test Active mode genesis
|
||||
new_test_ext().execute_with(|| {
|
||||
assert_eq!(ValidatorPool::operation_mode(), OperationMode::Active);
|
||||
});
|
||||
|
||||
// Test Shadow mode genesis
|
||||
new_test_ext_shadow_mode().execute_with(|| {
|
||||
assert_eq!(ValidatorPool::operation_mode(), OperationMode::Shadow);
|
||||
// Shadow mode should track activation block
|
||||
assert!(ValidatorPool::shadow_mode_since().is_some());
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn set_operation_mode_works() {
|
||||
new_test_ext().execute_with(|| {
|
||||
// Start in Active mode
|
||||
assert_eq!(ValidatorPool::operation_mode(), OperationMode::Active);
|
||||
|
||||
// Switch to Shadow mode
|
||||
assert_ok!(ValidatorPool::set_operation_mode(RuntimeOrigin::root(), OperationMode::Shadow));
|
||||
assert_eq!(ValidatorPool::operation_mode(), OperationMode::Shadow);
|
||||
|
||||
// Switch back to Active mode
|
||||
assert_ok!(ValidatorPool::set_operation_mode(RuntimeOrigin::root(), OperationMode::Active));
|
||||
assert_eq!(ValidatorPool::operation_mode(), OperationMode::Active);
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn set_operation_mode_fails_same_mode() {
|
||||
new_test_ext().execute_with(|| {
|
||||
// Already in Active mode
|
||||
assert_noop!(
|
||||
ValidatorPool::set_operation_mode(RuntimeOrigin::root(), OperationMode::Active),
|
||||
Error::<Test>::AlreadyInActiveMode
|
||||
);
|
||||
});
|
||||
|
||||
new_test_ext_shadow_mode().execute_with(|| {
|
||||
// Already in Shadow mode
|
||||
assert_noop!(
|
||||
ValidatorPool::set_operation_mode(RuntimeOrigin::root(), OperationMode::Shadow),
|
||||
Error::<Test>::AlreadyInShadowMode
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn set_operation_mode_requires_root() {
|
||||
new_test_ext().execute_with(|| {
|
||||
assert_noop!(
|
||||
ValidatorPool::set_operation_mode(RuntimeOrigin::signed(1), OperationMode::Shadow),
|
||||
pezsp_runtime::DispatchError::BadOrigin
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn shadow_mode_session_manager_returns_none() {
|
||||
new_test_ext_shadow_mode().execute_with(|| {
|
||||
// Add validators
|
||||
for i in 1..=5 {
|
||||
assert_ok!(ValidatorPool::join_validator_pool(
|
||||
RuntimeOrigin::signed(i),
|
||||
stake_validator_category()
|
||||
));
|
||||
}
|
||||
|
||||
// In shadow mode, new_session should return None
|
||||
let validators = <ValidatorPool as SessionManager<u64>>::new_session(1);
|
||||
assert!(validators.is_none());
|
||||
|
||||
// But shadow validator set should be stored
|
||||
assert!(ValidatorPool::shadow_validator_set().is_some());
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn active_mode_session_manager_returns_validators() {
|
||||
new_test_ext().execute_with(|| {
|
||||
// Add validators
|
||||
for i in 1..=5 {
|
||||
assert_ok!(ValidatorPool::join_validator_pool(
|
||||
RuntimeOrigin::signed(i),
|
||||
stake_validator_category()
|
||||
));
|
||||
}
|
||||
|
||||
// Force first era to get a validator set
|
||||
assert_ok!(ValidatorPool::force_new_era(RuntimeOrigin::root()));
|
||||
|
||||
// In active mode, new_session should return validators
|
||||
let validators = <ValidatorPool as SessionManager<u64>>::new_session(2);
|
||||
assert!(validators.is_some());
|
||||
assert!(!validators.unwrap().is_empty());
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn record_npos_validators_works() {
|
||||
new_test_ext_shadow_mode().execute_with(|| {
|
||||
// Add validators to pool
|
||||
for i in 1..=5 {
|
||||
assert_ok!(ValidatorPool::join_validator_pool(
|
||||
RuntimeOrigin::signed(i),
|
||||
stake_validator_category()
|
||||
));
|
||||
}
|
||||
|
||||
// Trigger shadow selection
|
||||
let _ = <ValidatorPool as SessionManager<u64>>::new_session(1);
|
||||
|
||||
// Record NPoS validators
|
||||
let npos_validators = vec![1u64, 2, 3, 6, 7];
|
||||
assert_ok!(ValidatorPool::record_npos_validators(RuntimeOrigin::root(), npos_validators));
|
||||
|
||||
// Check NPoS set is stored
|
||||
assert!(!ValidatorPool::npos_validator_set().is_empty());
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn record_npos_validators_fails_in_active_mode() {
|
||||
new_test_ext().execute_with(|| {
|
||||
let npos_validators = vec![1u64, 2, 3];
|
||||
assert_noop!(
|
||||
ValidatorPool::record_npos_validators(RuntimeOrigin::root(), npos_validators),
|
||||
Error::<Test>::ShadowModeNotEnabled
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn shadow_comparison_recorded() {
|
||||
new_test_ext_shadow_mode().execute_with(|| {
|
||||
// Add validators to pool
|
||||
for i in 1..=10 {
|
||||
let category = if i <= 5 {
|
||||
stake_validator_category()
|
||||
} else if i <= 7 {
|
||||
parliamentary_validator_category()
|
||||
} else {
|
||||
merit_validator_category()
|
||||
};
|
||||
assert_ok!(ValidatorPool::join_validator_pool(RuntimeOrigin::signed(i), category));
|
||||
}
|
||||
|
||||
// Trigger shadow selection
|
||||
let _ = <ValidatorPool as SessionManager<u64>>::new_session(1);
|
||||
|
||||
// Record NPoS validators (some overlap, some different)
|
||||
let npos_validators = vec![1u64, 2, 3, 11, 12];
|
||||
assert_ok!(ValidatorPool::record_npos_validators(RuntimeOrigin::root(), npos_validators));
|
||||
|
||||
// Check comparison was recorded
|
||||
let comparison = ValidatorPool::shadow_comparison();
|
||||
assert!(comparison.is_some());
|
||||
let comp = comparison.unwrap();
|
||||
assert!(comp.overlap_count > 0 || comp.tnpos_only.len() > 0 || comp.npos_only.len() > 0);
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn cumulative_statistics_updated() {
|
||||
new_test_ext_shadow_mode().execute_with(|| {
|
||||
// Add validators
|
||||
for i in 1..=5 {
|
||||
assert_ok!(ValidatorPool::join_validator_pool(
|
||||
RuntimeOrigin::signed(i),
|
||||
stake_validator_category()
|
||||
));
|
||||
}
|
||||
|
||||
// Trigger shadow selection
|
||||
let _ = <ValidatorPool as SessionManager<u64>>::new_session(1);
|
||||
|
||||
// Record NPoS validators
|
||||
let npos_validators = vec![1u64, 2, 6, 7, 8];
|
||||
assert_ok!(ValidatorPool::record_npos_validators(RuntimeOrigin::root(), npos_validators));
|
||||
|
||||
// Check cumulative stats were updated
|
||||
let stats = ValidatorPool::shadow_statistics();
|
||||
assert_eq!(stats.eras_analyzed, 1);
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn era_analysis_data_stored() {
|
||||
new_test_ext_shadow_mode().execute_with(|| {
|
||||
// Add validators
|
||||
for i in 1..=5 {
|
||||
assert_ok!(ValidatorPool::join_validator_pool(
|
||||
RuntimeOrigin::signed(i),
|
||||
stake_validator_category()
|
||||
));
|
||||
}
|
||||
|
||||
// Trigger shadow selection
|
||||
let _ = <ValidatorPool as SessionManager<u64>>::new_session(1);
|
||||
|
||||
// Record NPoS validators
|
||||
let npos_validators = vec![1u64, 2, 3, 4, 5];
|
||||
assert_ok!(ValidatorPool::record_npos_validators(RuntimeOrigin::root(), npos_validators));
|
||||
|
||||
// Check era analysis was stored
|
||||
let era = ValidatorPool::current_era();
|
||||
let analysis = ValidatorPool::era_analysis(era);
|
||||
assert!(analysis.is_some());
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn category_distribution_tracked() {
|
||||
new_test_ext_shadow_mode().execute_with(|| {
|
||||
// Add different category validators
|
||||
assert_ok!(ValidatorPool::join_validator_pool(
|
||||
RuntimeOrigin::signed(1),
|
||||
stake_validator_category()
|
||||
));
|
||||
assert_ok!(ValidatorPool::join_validator_pool(
|
||||
RuntimeOrigin::signed(2),
|
||||
stake_validator_category()
|
||||
));
|
||||
assert_ok!(ValidatorPool::join_validator_pool(
|
||||
RuntimeOrigin::signed(3),
|
||||
parliamentary_validator_category()
|
||||
));
|
||||
assert_ok!(ValidatorPool::join_validator_pool(
|
||||
RuntimeOrigin::signed(4),
|
||||
merit_validator_category()
|
||||
));
|
||||
assert_ok!(ValidatorPool::join_validator_pool(
|
||||
RuntimeOrigin::signed(5),
|
||||
stake_validator_category()
|
||||
));
|
||||
|
||||
// Trigger shadow selection
|
||||
let _ = <ValidatorPool as SessionManager<u64>>::new_session(1);
|
||||
|
||||
// Record NPoS validators
|
||||
assert_ok!(ValidatorPool::record_npos_validators(
|
||||
RuntimeOrigin::root(),
|
||||
vec![1u64, 2, 3, 4, 5]
|
||||
));
|
||||
|
||||
// Check category distribution was recorded
|
||||
let era = ValidatorPool::current_era();
|
||||
let distribution = ValidatorPool::category_distribution(era);
|
||||
assert!(distribution.is_some());
|
||||
let dist = distribution.unwrap();
|
||||
assert!(dist.target_stake > 0);
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn record_era_end_stats_works() {
|
||||
new_test_ext_shadow_mode().execute_with(|| {
|
||||
// Setup validators and trigger comparison
|
||||
for i in 1..=5 {
|
||||
assert_ok!(ValidatorPool::join_validator_pool(
|
||||
RuntimeOrigin::signed(i),
|
||||
stake_validator_category()
|
||||
));
|
||||
}
|
||||
let _ = <ValidatorPool as SessionManager<u64>>::new_session(1);
|
||||
assert_ok!(ValidatorPool::record_npos_validators(
|
||||
RuntimeOrigin::root(),
|
||||
vec![1u64, 2, 3, 4, 5]
|
||||
));
|
||||
|
||||
// Record era end stats
|
||||
let era = ValidatorPool::current_era();
|
||||
assert_ok!(ValidatorPool::record_era_end_stats(
|
||||
RuntimeOrigin::root(),
|
||||
era,
|
||||
950, // blocks produced
|
||||
50 // blocks missed
|
||||
));
|
||||
|
||||
// Check era analysis was updated
|
||||
let analysis = ValidatorPool::era_analysis(era);
|
||||
assert!(analysis.is_some());
|
||||
let a = analysis.unwrap();
|
||||
assert_eq!(a.blocks_produced, 950);
|
||||
assert_eq!(a.blocks_missed, 50);
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn operation_mode_change_emits_event() {
|
||||
new_test_ext().execute_with(|| {
|
||||
System::set_block_number(1);
|
||||
System::reset_events();
|
||||
|
||||
assert_ok!(ValidatorPool::set_operation_mode(RuntimeOrigin::root(), OperationMode::Shadow));
|
||||
|
||||
let events = System::events();
|
||||
assert!(events.iter().any(|event| matches!(
|
||||
event.event,
|
||||
RuntimeEvent::ValidatorPool(crate::Event::OperationModeChanged { .. })
|
||||
)));
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn shadow_mode_tracks_activation_block() {
|
||||
new_test_ext().execute_with(|| {
|
||||
System::set_block_number(100);
|
||||
|
||||
// Switch to shadow mode
|
||||
assert_ok!(ValidatorPool::set_operation_mode(RuntimeOrigin::root(), OperationMode::Shadow));
|
||||
|
||||
// Check activation block is tracked
|
||||
let since = ValidatorPool::shadow_mode_since();
|
||||
assert!(since.is_some());
|
||||
assert_eq!(since.unwrap(), 100);
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,305 @@
|
||||
extern crate alloc;
|
||||
|
||||
use alloc::vec::Vec;
|
||||
use codec::{Decode, DecodeWithMemTracking, Encode, MaxEncodedLen};
|
||||
use pezframe_support::{traits::ConstU32, BoundedVec};
|
||||
use scale_info::TypeInfo;
|
||||
use pezsp_runtime::RuntimeDebug;
|
||||
|
||||
/// Types of validators in the pool
|
||||
#[derive(
|
||||
Encode,
|
||||
Decode,
|
||||
DecodeWithMemTracking,
|
||||
Clone,
|
||||
PartialEq,
|
||||
Eq,
|
||||
RuntimeDebug,
|
||||
TypeInfo,
|
||||
MaxEncodedLen,
|
||||
serde::Serialize,
|
||||
serde::Deserialize,
|
||||
)]
|
||||
#[codec(mel_bound())]
|
||||
pub enum ValidatorPoolCategory {
|
||||
/// Stake-based validators (high stake + trust score)
|
||||
StakeValidator { min_stake: u128, trust_threshold: u128 },
|
||||
/// Parliamentary validators (elected parliament members)
|
||||
ParliamentaryValidator,
|
||||
/// Merit-based validators (special Tikis + community support)
|
||||
MeritValidator {
|
||||
special_tikis: BoundedVec<u8, ConstU32<5>>, // Tiki types they hold
|
||||
community_threshold: u32, // Minimum referral count
|
||||
},
|
||||
}
|
||||
|
||||
/// Performance metrics for a validator
|
||||
#[derive(
|
||||
Encode,
|
||||
Decode,
|
||||
DecodeWithMemTracking,
|
||||
Clone,
|
||||
PartialEq,
|
||||
Eq,
|
||||
RuntimeDebug,
|
||||
TypeInfo,
|
||||
MaxEncodedLen,
|
||||
Default,
|
||||
)]
|
||||
#[codec(mel_bound())]
|
||||
pub struct ValidatorPerformance {
|
||||
/// Total blocks produced
|
||||
pub blocks_produced: u32,
|
||||
/// Total blocks missed
|
||||
pub blocks_missed: u32,
|
||||
/// Era points earned
|
||||
pub era_points: u32,
|
||||
/// Last era when this validator was active
|
||||
pub last_active_era: u32,
|
||||
/// Reputation score (0-100)
|
||||
pub reputation_score: u8,
|
||||
}
|
||||
|
||||
/// Current validator set for an era
|
||||
#[derive(
|
||||
Encode,
|
||||
Decode,
|
||||
DecodeWithMemTracking,
|
||||
Clone,
|
||||
PartialEq,
|
||||
Eq,
|
||||
RuntimeDebug,
|
||||
TypeInfo,
|
||||
MaxEncodedLen,
|
||||
)]
|
||||
#[codec(mel_bound())]
|
||||
pub struct ValidatorSet<AccountId>
|
||||
where
|
||||
AccountId: Encode + Decode + DecodeWithMemTracking + Clone + PartialEq + Eq + MaxEncodedLen,
|
||||
{
|
||||
/// Era index
|
||||
pub era_index: u32,
|
||||
/// Stake-based validators (target: 10)
|
||||
pub stake_validators: BoundedVec<AccountId, ConstU32<10>>,
|
||||
/// Parliamentary validators (target: 6)
|
||||
pub parliamentary_validators: BoundedVec<AccountId, ConstU32<6>>,
|
||||
/// Merit-based validators (target: 5)
|
||||
pub merit_validators: BoundedVec<AccountId, ConstU32<5>>,
|
||||
}
|
||||
|
||||
impl<AccountId> ValidatorSet<AccountId>
|
||||
where
|
||||
AccountId: Encode + Decode + DecodeWithMemTracking + Clone + PartialEq + Eq + MaxEncodedLen,
|
||||
{
|
||||
/// Get all validators in the set
|
||||
pub fn all_validators(&self) -> Vec<AccountId> {
|
||||
let mut all = Vec::new();
|
||||
all.extend(self.stake_validators.iter().cloned());
|
||||
all.extend(self.parliamentary_validators.iter().cloned());
|
||||
all.extend(self.merit_validators.iter().cloned());
|
||||
all
|
||||
}
|
||||
|
||||
/// Get total validator count
|
||||
pub fn total_count(&self) -> u32 {
|
||||
self.stake_validators.len() as u32 +
|
||||
self.parliamentary_validators.len() as u32 +
|
||||
self.merit_validators.len() as u32
|
||||
}
|
||||
}
|
||||
|
||||
/// Trait for referral system integration
|
||||
pub trait ReferralProvider<AccountId> {
|
||||
/// Get referral count for an account
|
||||
fn get_referral_count(who: &AccountId) -> u32;
|
||||
}
|
||||
|
||||
/// Trait for Perwerde system integration
|
||||
pub trait PerwerdeProvider<AccountId> {
|
||||
/// Get Perwerde score for an account
|
||||
fn get_perwerde_score(who: &AccountId) -> u32;
|
||||
}
|
||||
|
||||
/// Default implementation for tests
|
||||
impl<AccountId> ReferralProvider<AccountId> for () {
|
||||
fn get_referral_count(_who: &AccountId) -> u32 {
|
||||
0
|
||||
}
|
||||
}
|
||||
|
||||
impl<AccountId> PerwerdeProvider<AccountId> for () {
|
||||
fn get_perwerde_score(_who: &AccountId) -> u32 {
|
||||
0
|
||||
}
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// SHADOW MODE TYPES
|
||||
// ============================================================================
|
||||
|
||||
/// Operation mode for the validator pool
|
||||
#[derive(
|
||||
Encode,
|
||||
Decode,
|
||||
DecodeWithMemTracking,
|
||||
Clone,
|
||||
Copy,
|
||||
PartialEq,
|
||||
Eq,
|
||||
RuntimeDebug,
|
||||
TypeInfo,
|
||||
MaxEncodedLen,
|
||||
Default,
|
||||
serde::Serialize,
|
||||
serde::Deserialize,
|
||||
)]
|
||||
pub enum OperationMode {
|
||||
/// Shadow mode: TNPoS runs in parallel but doesn't control consensus
|
||||
/// NPoS remains the authority, TNPoS results are recorded for comparison
|
||||
#[default]
|
||||
Shadow,
|
||||
/// Active mode: TNPoS directly controls validator selection
|
||||
/// Used on Zagros testnet and after full transition
|
||||
Active,
|
||||
}
|
||||
|
||||
/// Shadow mode comparison result for a single era
|
||||
#[derive(
|
||||
Encode,
|
||||
Decode,
|
||||
DecodeWithMemTracking,
|
||||
Clone,
|
||||
PartialEq,
|
||||
Eq,
|
||||
RuntimeDebug,
|
||||
TypeInfo,
|
||||
MaxEncodedLen,
|
||||
Default,
|
||||
)]
|
||||
#[codec(mel_bound())]
|
||||
pub struct ShadowComparison<AccountId>
|
||||
where
|
||||
AccountId: Encode + Decode + DecodeWithMemTracking + Clone + PartialEq + Eq + MaxEncodedLen,
|
||||
{
|
||||
/// Era when this comparison was made
|
||||
pub era_index: u32,
|
||||
/// Number of validators that appear in both NPoS and TNPoS selections
|
||||
pub overlap_count: u32,
|
||||
/// Validators selected by TNPoS but not by NPoS
|
||||
pub tnpos_only: BoundedVec<AccountId, ConstU32<21>>,
|
||||
/// Validators selected by NPoS but not by TNPoS
|
||||
pub npos_only: BoundedVec<AccountId, ConstU32<21>>,
|
||||
/// TNPoS selection would have included more stake validators
|
||||
pub stake_diff: i32,
|
||||
/// TNPoS selection would have included more parliamentary validators
|
||||
pub parliamentary_diff: i32,
|
||||
/// TNPoS selection would have included more merit validators
|
||||
pub merit_diff: i32,
|
||||
}
|
||||
|
||||
/// Cumulative shadow mode statistics across multiple eras
|
||||
#[derive(
|
||||
Encode,
|
||||
Decode,
|
||||
DecodeWithMemTracking,
|
||||
Clone,
|
||||
PartialEq,
|
||||
Eq,
|
||||
RuntimeDebug,
|
||||
TypeInfo,
|
||||
MaxEncodedLen,
|
||||
Default,
|
||||
)]
|
||||
#[codec(mel_bound())]
|
||||
pub struct ShadowStatistics {
|
||||
/// Total number of eras analyzed
|
||||
pub eras_analyzed: u32,
|
||||
/// Total overlapping validators across all eras
|
||||
pub total_overlap: u32,
|
||||
/// Total TNPoS-only selections across all eras
|
||||
pub total_tnpos_only: u32,
|
||||
/// Total NPoS-only selections across all eras
|
||||
pub total_npos_only: u32,
|
||||
/// Average overlap percentage (stored as basis points, e.g., 5000 = 50%)
|
||||
pub avg_overlap_bps: u32,
|
||||
/// Number of eras where TNPoS would have performed better (based on block production)
|
||||
pub tnpos_better_eras: u32,
|
||||
/// Number of eras where NPoS performed better
|
||||
pub npos_better_eras: u32,
|
||||
/// Total blocks that would have been produced by TNPoS selections
|
||||
pub tnpos_projected_blocks: u64,
|
||||
/// Total blocks actually produced by NPoS selections
|
||||
pub npos_actual_blocks: u64,
|
||||
/// Eras where TNPoS had higher stake representation
|
||||
pub higher_stake_eras: u32,
|
||||
/// Eras where TNPoS had higher trust representation
|
||||
pub higher_trust_eras: u32,
|
||||
}
|
||||
|
||||
/// Detailed per-era shadow analysis data
|
||||
#[derive(
|
||||
Encode,
|
||||
Decode,
|
||||
DecodeWithMemTracking,
|
||||
Clone,
|
||||
PartialEq,
|
||||
Eq,
|
||||
RuntimeDebug,
|
||||
TypeInfo,
|
||||
MaxEncodedLen,
|
||||
Default,
|
||||
)]
|
||||
#[codec(mel_bound())]
|
||||
pub struct EraAnalysis {
|
||||
/// Era index
|
||||
pub era_index: u32,
|
||||
/// Block number when analysis was recorded
|
||||
pub recorded_at_block: u32,
|
||||
/// Total stake of TNPoS selected validators
|
||||
pub tnpos_total_stake: u128,
|
||||
/// Total stake of NPoS selected validators
|
||||
pub npos_total_stake: u128,
|
||||
/// Average trust score of TNPoS selected validators
|
||||
pub tnpos_avg_trust: u32,
|
||||
/// Average trust score of NPoS selected validators
|
||||
pub npos_avg_trust: u32,
|
||||
/// Number of stake validators in TNPoS selection
|
||||
pub tnpos_stake_count: u8,
|
||||
/// Number of parliamentary validators in TNPoS selection
|
||||
pub tnpos_parliamentary_count: u8,
|
||||
/// Number of merit validators in TNPoS selection
|
||||
pub tnpos_merit_count: u8,
|
||||
/// Blocks produced this era (filled at era end)
|
||||
pub blocks_produced: u32,
|
||||
/// Blocks missed this era (filled at era end)
|
||||
pub blocks_missed: u32,
|
||||
}
|
||||
|
||||
/// Category distribution snapshot
|
||||
#[derive(
|
||||
Encode,
|
||||
Decode,
|
||||
DecodeWithMemTracking,
|
||||
Clone,
|
||||
PartialEq,
|
||||
Eq,
|
||||
RuntimeDebug,
|
||||
TypeInfo,
|
||||
MaxEncodedLen,
|
||||
Default,
|
||||
)]
|
||||
#[codec(mel_bound())]
|
||||
pub struct CategoryDistribution {
|
||||
/// Stake validators count
|
||||
pub stake: u8,
|
||||
/// Parliamentary validators count
|
||||
pub parliamentary: u8,
|
||||
/// Merit validators count
|
||||
pub merit: u8,
|
||||
/// Target stake count
|
||||
pub target_stake: u8,
|
||||
/// Target parliamentary count
|
||||
pub target_parliamentary: u8,
|
||||
/// Target merit count
|
||||
pub target_merit: u8,
|
||||
}
|
||||
@@ -0,0 +1,252 @@
|
||||
// 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.
|
||||
|
||||
|
||||
//! Autogenerated weights for `pezpallet_validator_pool`
|
||||
//!
|
||||
//! THIS FILE WAS AUTO-GENERATED USING THE BIZINIKIWI BENCHMARK CLI VERSION 32.0.0
|
||||
//! DATE: 2025-11-30, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]`
|
||||
//! WORST CASE MAP SIZE: `1000000`
|
||||
//! HOSTNAME: `MamostePC`, CPU: `11th Gen Intel(R) Core(TM) i9-11950H @ 2.60GHz`
|
||||
//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("dev")`, DB CACHE: `1024`
|
||||
|
||||
// Executed Command:
|
||||
// /home/mamostehp/Pezkuwi-SDK/target/release/pezkuwi
|
||||
// benchmark
|
||||
// pallet
|
||||
// --chain=dev
|
||||
// --pallet=pezpallet_validator_pool
|
||||
// --extrinsic=*
|
||||
// --steps=50
|
||||
// --repeat=20
|
||||
// --output=/home/mamostehp/Pezkuwi-SDK/pezkuwi/pallets/validator-pool/src/weights.rs
|
||||
// --template=/home/mamostehp/Pezkuwi-SDK/bizinikiwi/.maintain/frame-weight-template.hbs
|
||||
|
||||
#![cfg_attr(rustfmt, rustfmt_skip)]
|
||||
#![allow(unused_parens)]
|
||||
#![allow(unused_imports)]
|
||||
#![allow(missing_docs)]
|
||||
#![allow(dead_code)]
|
||||
|
||||
use pezframe_support::{traits::Get, weights::{Weight, constants::RocksDbWeight}};
|
||||
use core::marker::PhantomData;
|
||||
use crate::WeightInfo;
|
||||
|
||||
/// Weights for `pezpallet_validator_pool` using the Bizinikiwi node and recommended hardware.
|
||||
pub struct BizinikiwiWeight<T>(PhantomData<T>);
|
||||
impl<T: pezframe_system::Config> WeightInfo for BizinikiwiWeight<T> {
|
||||
/// Storage: `ValidatorPool::PoolMembers` (r:1 w:1)
|
||||
/// Proof: `ValidatorPool::PoolMembers` (`max_values`: None, `max_size`: Some(81), added: 2556, mode: `MaxEncodedLen`)
|
||||
/// Storage: `ValidatorPool::PoolSize` (r:1 w:1)
|
||||
/// Proof: `ValidatorPool::PoolSize` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`)
|
||||
/// Storage: `ValidatorPool::CurrentEra` (r:1 w:0)
|
||||
/// Proof: `ValidatorPool::CurrentEra` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`)
|
||||
/// Storage: `ValidatorPool::PerformanceMetrics` (r:0 w:1)
|
||||
/// Proof: `ValidatorPool::PerformanceMetrics` (`max_values`: None, `max_size`: Some(65), added: 2540, mode: `MaxEncodedLen`)
|
||||
fn join_validator_pool() -> Weight {
|
||||
// Proof Size summary in bytes:
|
||||
// Measured: `110`
|
||||
// Estimated: `3546`
|
||||
// Minimum execution time: 16_865_000 picoseconds.
|
||||
Weight::from_parts(18_041_000, 3546)
|
||||
.saturating_add(T::DbWeight::get().reads(3_u64))
|
||||
.saturating_add(T::DbWeight::get().writes(3_u64))
|
||||
}
|
||||
/// Storage: `ValidatorPool::PoolMembers` (r:1 w:1)
|
||||
/// Proof: `ValidatorPool::PoolMembers` (`max_values`: None, `max_size`: Some(81), added: 2556, mode: `MaxEncodedLen`)
|
||||
/// Storage: `ValidatorPool::PoolSize` (r:1 w:1)
|
||||
/// Proof: `ValidatorPool::PoolSize` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`)
|
||||
/// Storage: `ValidatorPool::PerformanceMetrics` (r:0 w:1)
|
||||
/// Proof: `ValidatorPool::PerformanceMetrics` (`max_values`: None, `max_size`: Some(65), added: 2540, mode: `MaxEncodedLen`)
|
||||
/// Storage: `ValidatorPool::SelectionHistory` (r:0 w:1)
|
||||
/// Proof: `ValidatorPool::SelectionHistory` (`max_values`: None, `max_size`: Some(69), added: 2544, mode: `MaxEncodedLen`)
|
||||
fn leave_validator_pool() -> Weight {
|
||||
// Proof Size summary in bytes:
|
||||
// Measured: `267`
|
||||
// Estimated: `3546`
|
||||
// Minimum execution time: 18_228_000 picoseconds.
|
||||
Weight::from_parts(18_832_000, 3546)
|
||||
.saturating_add(T::DbWeight::get().reads(2_u64))
|
||||
.saturating_add(T::DbWeight::get().writes(4_u64))
|
||||
}
|
||||
/// Storage: `ValidatorPool::PerformanceMetrics` (r:1 w:1)
|
||||
/// Proof: `ValidatorPool::PerformanceMetrics` (`max_values`: None, `max_size`: Some(65), added: 2540, mode: `MaxEncodedLen`)
|
||||
/// Storage: `ValidatorPool::CurrentEra` (r:1 w:0)
|
||||
/// Proof: `ValidatorPool::CurrentEra` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`)
|
||||
fn update_performance_metrics() -> Weight {
|
||||
// Proof Size summary in bytes:
|
||||
// Measured: `197`
|
||||
// Estimated: `3530`
|
||||
// Minimum execution time: 15_814_000 picoseconds.
|
||||
Weight::from_parts(16_553_000, 3530)
|
||||
.saturating_add(T::DbWeight::get().reads(2_u64))
|
||||
.saturating_add(T::DbWeight::get().writes(1_u64))
|
||||
}
|
||||
/// Storage: `ValidatorPool::CurrentEra` (r:1 w:1)
|
||||
/// Proof: `ValidatorPool::CurrentEra` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`)
|
||||
/// Storage: `Babe::NextRandomness` (r:1 w:0)
|
||||
/// Proof: `Babe::NextRandomness` (`max_values`: Some(1), `max_size`: Some(32), added: 527, mode: `MaxEncodedLen`)
|
||||
/// Storage: `Babe::EpochStart` (r:1 w:0)
|
||||
/// Proof: `Babe::EpochStart` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `MaxEncodedLen`)
|
||||
/// Storage: `ValidatorPool::PoolMembers` (r:101 w:0)
|
||||
/// Proof: `ValidatorPool::PoolMembers` (`max_values`: None, `max_size`: Some(81), added: 2556, mode: `MaxEncodedLen`)
|
||||
/// Storage: `ValidatorPool::SelectionHistory` (r:100 w:21)
|
||||
/// Proof: `ValidatorPool::SelectionHistory` (`max_values`: None, `max_size`: Some(69), added: 2544, mode: `MaxEncodedLen`)
|
||||
/// Storage: `ValidatorPool::PerformanceMetrics` (r:100 w:0)
|
||||
/// Proof: `ValidatorPool::PerformanceMetrics` (`max_values`: None, `max_size`: Some(65), added: 2540, mode: `MaxEncodedLen`)
|
||||
/// Storage: `ValidatorPool::CurrentValidatorSet` (r:0 w:1)
|
||||
/// Proof: `ValidatorPool::CurrentValidatorSet` (`max_values`: Some(1), `max_size`: Some(679), added: 1174, mode: `MaxEncodedLen`)
|
||||
/// Storage: `ValidatorPool::EraStart` (r:0 w:1)
|
||||
/// Proof: `ValidatorPool::EraStart` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`)
|
||||
/// The range of component `p` is `[4, 100]`.
|
||||
fn force_new_era(p: u32, ) -> Weight {
|
||||
// Proof Size summary in bytes:
|
||||
// Measured: `354 + p * (139 ±0)`
|
||||
// Estimated: `3546 + p * (2556 ±0)`
|
||||
// Minimum execution time: 68_990_000 picoseconds.
|
||||
Weight::from_parts(55_692_892, 3546)
|
||||
// Standard Error: 19_014
|
||||
.saturating_add(Weight::from_parts(9_817_847, 0).saturating_mul(p.into()))
|
||||
.saturating_add(T::DbWeight::get().reads(4_u64))
|
||||
.saturating_add(T::DbWeight::get().reads((3_u64).saturating_mul(p.into())))
|
||||
.saturating_add(T::DbWeight::get().writes(17_u64))
|
||||
.saturating_add(Weight::from_parts(0, 2556).saturating_mul(p.into()))
|
||||
}
|
||||
/// Storage: `ValidatorPool::PoolMembers` (r:1 w:1)
|
||||
/// Proof: `ValidatorPool::PoolMembers` (`max_values`: None, `max_size`: Some(81), added: 2556, mode: `MaxEncodedLen`)
|
||||
fn update_category() -> Weight {
|
||||
// Proof Size summary in bytes:
|
||||
// Measured: `215`
|
||||
// Estimated: `3546`
|
||||
// Minimum execution time: 15_344_000 picoseconds.
|
||||
Weight::from_parts(16_181_000, 3546)
|
||||
.saturating_add(T::DbWeight::get().reads(1_u64))
|
||||
.saturating_add(T::DbWeight::get().writes(1_u64))
|
||||
}
|
||||
/// Storage: `ValidatorPool::EraLength` (r:0 w:1)
|
||||
/// Proof: `ValidatorPool::EraLength` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`)
|
||||
fn set_pool_parameters() -> Weight {
|
||||
// Proof Size summary in bytes:
|
||||
// Measured: `0`
|
||||
// Estimated: `0`
|
||||
// Minimum execution time: 6_159_000 picoseconds.
|
||||
Weight::from_parts(6_422_000, 0)
|
||||
.saturating_add(T::DbWeight::get().writes(1_u64))
|
||||
}
|
||||
}
|
||||
|
||||
// For backwards compatibility and tests.
|
||||
impl WeightInfo for () {
|
||||
/// Storage: `ValidatorPool::PoolMembers` (r:1 w:1)
|
||||
/// Proof: `ValidatorPool::PoolMembers` (`max_values`: None, `max_size`: Some(81), added: 2556, mode: `MaxEncodedLen`)
|
||||
/// Storage: `ValidatorPool::PoolSize` (r:1 w:1)
|
||||
/// Proof: `ValidatorPool::PoolSize` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`)
|
||||
/// Storage: `ValidatorPool::CurrentEra` (r:1 w:0)
|
||||
/// Proof: `ValidatorPool::CurrentEra` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`)
|
||||
/// Storage: `ValidatorPool::PerformanceMetrics` (r:0 w:1)
|
||||
/// Proof: `ValidatorPool::PerformanceMetrics` (`max_values`: None, `max_size`: Some(65), added: 2540, mode: `MaxEncodedLen`)
|
||||
fn join_validator_pool() -> Weight {
|
||||
// Proof Size summary in bytes:
|
||||
// Measured: `110`
|
||||
// Estimated: `3546`
|
||||
// Minimum execution time: 16_865_000 picoseconds.
|
||||
Weight::from_parts(18_041_000, 3546)
|
||||
.saturating_add(RocksDbWeight::get().reads(3_u64))
|
||||
.saturating_add(RocksDbWeight::get().writes(3_u64))
|
||||
}
|
||||
/// Storage: `ValidatorPool::PoolMembers` (r:1 w:1)
|
||||
/// Proof: `ValidatorPool::PoolMembers` (`max_values`: None, `max_size`: Some(81), added: 2556, mode: `MaxEncodedLen`)
|
||||
/// Storage: `ValidatorPool::PoolSize` (r:1 w:1)
|
||||
/// Proof: `ValidatorPool::PoolSize` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`)
|
||||
/// Storage: `ValidatorPool::PerformanceMetrics` (r:0 w:1)
|
||||
/// Proof: `ValidatorPool::PerformanceMetrics` (`max_values`: None, `max_size`: Some(65), added: 2540, mode: `MaxEncodedLen`)
|
||||
/// Storage: `ValidatorPool::SelectionHistory` (r:0 w:1)
|
||||
/// Proof: `ValidatorPool::SelectionHistory` (`max_values`: None, `max_size`: Some(69), added: 2544, mode: `MaxEncodedLen`)
|
||||
fn leave_validator_pool() -> Weight {
|
||||
// Proof Size summary in bytes:
|
||||
// Measured: `267`
|
||||
// Estimated: `3546`
|
||||
// Minimum execution time: 18_228_000 picoseconds.
|
||||
Weight::from_parts(18_832_000, 3546)
|
||||
.saturating_add(RocksDbWeight::get().reads(2_u64))
|
||||
.saturating_add(RocksDbWeight::get().writes(4_u64))
|
||||
}
|
||||
/// Storage: `ValidatorPool::PerformanceMetrics` (r:1 w:1)
|
||||
/// Proof: `ValidatorPool::PerformanceMetrics` (`max_values`: None, `max_size`: Some(65), added: 2540, mode: `MaxEncodedLen`)
|
||||
/// Storage: `ValidatorPool::CurrentEra` (r:1 w:0)
|
||||
/// Proof: `ValidatorPool::CurrentEra` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`)
|
||||
fn update_performance_metrics() -> Weight {
|
||||
// Proof Size summary in bytes:
|
||||
// Measured: `197`
|
||||
// Estimated: `3530`
|
||||
// Minimum execution time: 15_814_000 picoseconds.
|
||||
Weight::from_parts(16_553_000, 3530)
|
||||
.saturating_add(RocksDbWeight::get().reads(2_u64))
|
||||
.saturating_add(RocksDbWeight::get().writes(1_u64))
|
||||
}
|
||||
/// Storage: `ValidatorPool::CurrentEra` (r:1 w:1)
|
||||
/// Proof: `ValidatorPool::CurrentEra` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`)
|
||||
/// Storage: `Babe::NextRandomness` (r:1 w:0)
|
||||
/// Proof: `Babe::NextRandomness` (`max_values`: Some(1), `max_size`: Some(32), added: 527, mode: `MaxEncodedLen`)
|
||||
/// Storage: `Babe::EpochStart` (r:1 w:0)
|
||||
/// Proof: `Babe::EpochStart` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `MaxEncodedLen`)
|
||||
/// Storage: `ValidatorPool::PoolMembers` (r:101 w:0)
|
||||
/// Proof: `ValidatorPool::PoolMembers` (`max_values`: None, `max_size`: Some(81), added: 2556, mode: `MaxEncodedLen`)
|
||||
/// Storage: `ValidatorPool::SelectionHistory` (r:100 w:21)
|
||||
/// Proof: `ValidatorPool::SelectionHistory` (`max_values`: None, `max_size`: Some(69), added: 2544, mode: `MaxEncodedLen`)
|
||||
/// Storage: `ValidatorPool::PerformanceMetrics` (r:100 w:0)
|
||||
/// Proof: `ValidatorPool::PerformanceMetrics` (`max_values`: None, `max_size`: Some(65), added: 2540, mode: `MaxEncodedLen`)
|
||||
/// Storage: `ValidatorPool::CurrentValidatorSet` (r:0 w:1)
|
||||
/// Proof: `ValidatorPool::CurrentValidatorSet` (`max_values`: Some(1), `max_size`: Some(679), added: 1174, mode: `MaxEncodedLen`)
|
||||
/// Storage: `ValidatorPool::EraStart` (r:0 w:1)
|
||||
/// Proof: `ValidatorPool::EraStart` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`)
|
||||
/// The range of component `p` is `[4, 100]`.
|
||||
fn force_new_era(p: u32, ) -> Weight {
|
||||
// Proof Size summary in bytes:
|
||||
// Measured: `354 + p * (139 ±0)`
|
||||
// Estimated: `3546 + p * (2556 ±0)`
|
||||
// Minimum execution time: 68_990_000 picoseconds.
|
||||
Weight::from_parts(55_692_892, 3546)
|
||||
// Standard Error: 19_014
|
||||
.saturating_add(Weight::from_parts(9_817_847, 0).saturating_mul(p.into()))
|
||||
.saturating_add(RocksDbWeight::get().reads(4_u64))
|
||||
.saturating_add(RocksDbWeight::get().reads((3_u64).saturating_mul(p.into())))
|
||||
.saturating_add(RocksDbWeight::get().writes(17_u64))
|
||||
.saturating_add(Weight::from_parts(0, 2556).saturating_mul(p.into()))
|
||||
}
|
||||
/// Storage: `ValidatorPool::PoolMembers` (r:1 w:1)
|
||||
/// Proof: `ValidatorPool::PoolMembers` (`max_values`: None, `max_size`: Some(81), added: 2556, mode: `MaxEncodedLen`)
|
||||
fn update_category() -> Weight {
|
||||
// Proof Size summary in bytes:
|
||||
// Measured: `215`
|
||||
// Estimated: `3546`
|
||||
// Minimum execution time: 15_344_000 picoseconds.
|
||||
Weight::from_parts(16_181_000, 3546)
|
||||
.saturating_add(RocksDbWeight::get().reads(1_u64))
|
||||
.saturating_add(RocksDbWeight::get().writes(1_u64))
|
||||
}
|
||||
/// Storage: `ValidatorPool::EraLength` (r:0 w:1)
|
||||
/// Proof: `ValidatorPool::EraLength` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`)
|
||||
fn set_pool_parameters() -> Weight {
|
||||
// Proof Size summary in bytes:
|
||||
// Measured: `0`
|
||||
// Estimated: `0`
|
||||
// Minimum execution time: 6_159_000 picoseconds.
|
||||
Weight::from_parts(6_422_000, 0)
|
||||
.saturating_add(RocksDbWeight::get().writes(1_u64))
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user