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,57 @@
|
||||
[package]
|
||||
name = "pezpallet-offences"
|
||||
version = "27.0.0"
|
||||
authors.workspace = true
|
||||
edition.workspace = true
|
||||
license = "Apache-2.0"
|
||||
homepage.workspace = true
|
||||
repository.workspace = true
|
||||
description = "FRAME offences pallet"
|
||||
readme = "README.md"
|
||||
|
||||
[lints]
|
||||
workspace = true
|
||||
|
||||
[package.metadata.docs.rs]
|
||||
targets = ["x86_64-unknown-linux-gnu"]
|
||||
|
||||
[dependencies]
|
||||
codec = { features = ["derive"], workspace = true }
|
||||
pezframe-support = { workspace = true }
|
||||
pezframe-system = { workspace = true }
|
||||
log = { workspace = true }
|
||||
scale-info = { features = ["derive"], workspace = true }
|
||||
serde = { optional = true, workspace = true, default-features = true }
|
||||
pezsp-runtime = { workspace = true }
|
||||
pezsp-staking = { workspace = true }
|
||||
|
||||
[dev-dependencies]
|
||||
pezsp-core = { workspace = true, default-features = true }
|
||||
pezsp-io = { workspace = true, default-features = true }
|
||||
|
||||
[features]
|
||||
default = ["std"]
|
||||
std = [
|
||||
"codec/std",
|
||||
"pezframe-support/std",
|
||||
"pezframe-system/std",
|
||||
"log/std",
|
||||
"scale-info/std",
|
||||
"serde",
|
||||
"pezsp-core/std",
|
||||
"pezsp-io/std",
|
||||
"pezsp-runtime/std",
|
||||
"pezsp-staking/std",
|
||||
]
|
||||
runtime-benchmarks = [
|
||||
"pezframe-support/runtime-benchmarks",
|
||||
"pezframe-system/runtime-benchmarks",
|
||||
"pezsp-io/runtime-benchmarks",
|
||||
"pezsp-runtime/runtime-benchmarks",
|
||||
"pezsp-staking/runtime-benchmarks",
|
||||
]
|
||||
try-runtime = [
|
||||
"pezframe-support/try-runtime",
|
||||
"pezframe-system/try-runtime",
|
||||
"pezsp-runtime/try-runtime",
|
||||
]
|
||||
@@ -0,0 +1,5 @@
|
||||
# Offences Module
|
||||
|
||||
Tracks reported offences
|
||||
|
||||
License: Apache-2.0
|
||||
@@ -0,0 +1,83 @@
|
||||
[package]
|
||||
name = "pezpallet-offences-benchmarking"
|
||||
version = "28.0.0"
|
||||
authors.workspace = true
|
||||
edition.workspace = true
|
||||
license = "Apache-2.0"
|
||||
homepage.workspace = true
|
||||
repository.workspace = true
|
||||
description = "FRAME offences pallet benchmarking"
|
||||
readme = "README.md"
|
||||
|
||||
[lints]
|
||||
workspace = true
|
||||
|
||||
[package.metadata.docs.rs]
|
||||
targets = ["x86_64-unknown-linux-gnu"]
|
||||
|
||||
[dependencies]
|
||||
codec = { workspace = true }
|
||||
pezframe-benchmarking = { workspace = true }
|
||||
pezframe-election-provider-support = { workspace = true }
|
||||
pezframe-support = { workspace = true }
|
||||
pezframe-system = { workspace = true }
|
||||
log = { workspace = true }
|
||||
pezpallet-babe = { workspace = true }
|
||||
pezpallet-balances = { workspace = true }
|
||||
pezpallet-grandpa = { workspace = true }
|
||||
pezpallet-im-online = { workspace = true }
|
||||
pezpallet-offences = { workspace = true }
|
||||
pezpallet-session = { workspace = true }
|
||||
pezpallet-staking = { workspace = true }
|
||||
scale-info = { features = ["derive"], workspace = true }
|
||||
pezsp-runtime = { workspace = true }
|
||||
pezsp-staking = { workspace = true }
|
||||
|
||||
[dev-dependencies]
|
||||
pezpallet-staking-reward-curve = { workspace = true, default-features = true }
|
||||
pezpallet-timestamp = { workspace = true, default-features = true }
|
||||
pezsp-core = { workspace = true, default-features = true }
|
||||
pezsp-io = { workspace = true, default-features = true }
|
||||
pezsp-tracing = { workspace = true, default-features = true }
|
||||
|
||||
[features]
|
||||
default = ["std"]
|
||||
std = [
|
||||
"codec/std",
|
||||
"pezframe-benchmarking/std",
|
||||
"pezframe-election-provider-support/std",
|
||||
"pezframe-support/std",
|
||||
"pezframe-system/std",
|
||||
"log/std",
|
||||
"pezpallet-babe/std",
|
||||
"pezpallet-balances/std",
|
||||
"pezpallet-grandpa/std",
|
||||
"pezpallet-im-online/std",
|
||||
"pezpallet-offences/std",
|
||||
"pezpallet-session/std",
|
||||
"pezpallet-staking/std",
|
||||
"pezpallet-timestamp/std",
|
||||
"scale-info/std",
|
||||
"pezsp-core/std",
|
||||
"pezsp-io/std",
|
||||
"pezsp-runtime/std",
|
||||
"pezsp-staking/std",
|
||||
]
|
||||
runtime-benchmarks = [
|
||||
"pezframe-benchmarking/runtime-benchmarks",
|
||||
"pezframe-election-provider-support/runtime-benchmarks",
|
||||
"pezframe-support/runtime-benchmarks",
|
||||
"pezframe-system/runtime-benchmarks",
|
||||
"pezpallet-babe/runtime-benchmarks",
|
||||
"pezpallet-balances/runtime-benchmarks",
|
||||
"pezpallet-grandpa/runtime-benchmarks",
|
||||
"pezpallet-im-online/runtime-benchmarks",
|
||||
"pezpallet-offences/runtime-benchmarks",
|
||||
"pezpallet-session/runtime-benchmarks",
|
||||
"pezpallet-staking-reward-curve/runtime-benchmarks",
|
||||
"pezpallet-staking/runtime-benchmarks",
|
||||
"pezpallet-timestamp/runtime-benchmarks",
|
||||
"pezsp-io/runtime-benchmarks",
|
||||
"pezsp-runtime/runtime-benchmarks",
|
||||
"pezsp-staking/runtime-benchmarks",
|
||||
]
|
||||
@@ -0,0 +1,3 @@
|
||||
Offences pallet benchmarking.
|
||||
|
||||
License: Apache-2.0
|
||||
@@ -0,0 +1,289 @@
|
||||
// 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.
|
||||
|
||||
//! Offences pallet benchmarking.
|
||||
|
||||
use alloc::{vec, vec::Vec};
|
||||
use codec::Decode;
|
||||
use pezframe_benchmarking::v2::*;
|
||||
use pezframe_support::traits::Get;
|
||||
use pezframe_system::{Config as SystemConfig, Pallet as System, RawOrigin};
|
||||
use pezpallet_babe::EquivocationOffence as BabeEquivocationOffence;
|
||||
use pezpallet_balances::Config as BalancesConfig;
|
||||
use pezpallet_grandpa::{
|
||||
EquivocationOffence as GrandpaEquivocationOffence, TimeSlot as GrandpaTimeSlot,
|
||||
};
|
||||
use pezpallet_offences::{Config as OffencesConfig, Pallet as Offences};
|
||||
use pezpallet_session::{
|
||||
historical::{Config as HistoricalConfig, IdentificationTuple},
|
||||
Config as SessionConfig, Pallet as Session,
|
||||
};
|
||||
use pezpallet_staking::{
|
||||
Config as StakingConfig, Exposure, IndividualExposure, MaxNominationsOf, Pallet as Staking,
|
||||
RewardDestination, ValidatorPrefs,
|
||||
};
|
||||
use pezsp_runtime::{
|
||||
traits::{Convert, Saturating, StaticLookup},
|
||||
Perbill,
|
||||
};
|
||||
use pezsp_staking::offence::ReportOffence;
|
||||
|
||||
const SEED: u32 = 0;
|
||||
|
||||
const MAX_NOMINATORS: u32 = 100;
|
||||
|
||||
pub struct Pallet<T: Config>(Offences<T>);
|
||||
|
||||
pub trait Config:
|
||||
SessionConfig<ValidatorId = <Self as pezframe_system::Config>::AccountId>
|
||||
+ StakingConfig
|
||||
+ OffencesConfig
|
||||
+ HistoricalConfig
|
||||
+ BalancesConfig
|
||||
+ IdTupleConvert<Self>
|
||||
{
|
||||
}
|
||||
|
||||
/// A helper trait to make sure we can convert `IdentificationTuple` coming from historical
|
||||
/// and the one required by offences.
|
||||
pub trait IdTupleConvert<T: HistoricalConfig + OffencesConfig> {
|
||||
/// Convert identification tuple from `historical` trait to the one expected by `offences`.
|
||||
fn convert(id: IdentificationTuple<T>) -> <T as OffencesConfig>::IdentificationTuple;
|
||||
}
|
||||
|
||||
impl<T: HistoricalConfig + OffencesConfig> IdTupleConvert<T> for T
|
||||
where
|
||||
<T as OffencesConfig>::IdentificationTuple: From<IdentificationTuple<T>>,
|
||||
{
|
||||
fn convert(id: IdentificationTuple<T>) -> <T as OffencesConfig>::IdentificationTuple {
|
||||
id.into()
|
||||
}
|
||||
}
|
||||
|
||||
type LookupSourceOf<T> = <<T as SystemConfig>::Lookup as StaticLookup>::Source;
|
||||
type BalanceOf<T> = <T as StakingConfig>::CurrencyBalance;
|
||||
|
||||
struct Offender<T: Config> {
|
||||
pub controller: T::AccountId,
|
||||
#[allow(dead_code)]
|
||||
pub stash: T::AccountId,
|
||||
#[allow(dead_code)]
|
||||
pub nominator_stashes: Vec<T::AccountId>,
|
||||
}
|
||||
|
||||
fn bond_amount<T: Config>() -> BalanceOf<T> {
|
||||
pezpallet_staking::asset::existential_deposit::<T>().saturating_mul(10_000u32.into())
|
||||
}
|
||||
|
||||
fn create_offender<T: Config>(n: u32, nominators: u32) -> Result<Offender<T>, &'static str> {
|
||||
let stash: T::AccountId = account("stash", n, SEED);
|
||||
let stash_lookup: LookupSourceOf<T> = T::Lookup::unlookup(stash.clone());
|
||||
let reward_destination = RewardDestination::Staked;
|
||||
let amount = bond_amount::<T>();
|
||||
// add twice as much balance to prevent the account from being killed.
|
||||
let free_amount = amount.saturating_mul(2u32.into());
|
||||
pezpallet_staking::asset::set_stakeable_balance::<T>(&stash, free_amount);
|
||||
Staking::<T>::bond(
|
||||
RawOrigin::Signed(stash.clone()).into(),
|
||||
amount,
|
||||
reward_destination.clone(),
|
||||
)?;
|
||||
|
||||
let validator_prefs =
|
||||
ValidatorPrefs { commission: Perbill::from_percent(50), ..Default::default() };
|
||||
Staking::<T>::validate(RawOrigin::Signed(stash.clone()).into(), validator_prefs)?;
|
||||
|
||||
// set some fake keys for the validators.
|
||||
let keys =
|
||||
<T as SessionConfig>::Keys::decode(&mut pezsp_runtime::traits::TrailingZeroInput::zeroes())
|
||||
.unwrap();
|
||||
let proof: Vec<u8> = vec![0, 1, 2, 3];
|
||||
Session::<T>::ensure_can_pay_key_deposit(&stash)?;
|
||||
Session::<T>::set_keys(RawOrigin::Signed(stash.clone()).into(), keys, proof)?;
|
||||
|
||||
let mut individual_exposures = vec![];
|
||||
let mut nominator_stashes = vec![];
|
||||
// Create n nominators
|
||||
for i in 0..nominators {
|
||||
let nominator_stash: T::AccountId =
|
||||
account("nominator stash", n * MAX_NOMINATORS + i, SEED);
|
||||
pezpallet_staking::asset::set_stakeable_balance::<T>(&nominator_stash, free_amount);
|
||||
|
||||
Staking::<T>::bond(
|
||||
RawOrigin::Signed(nominator_stash.clone()).into(),
|
||||
amount,
|
||||
reward_destination.clone(),
|
||||
)?;
|
||||
|
||||
let selected_validators: Vec<LookupSourceOf<T>> = vec![stash_lookup.clone()];
|
||||
Staking::<T>::nominate(
|
||||
RawOrigin::Signed(nominator_stash.clone()).into(),
|
||||
selected_validators,
|
||||
)?;
|
||||
|
||||
individual_exposures
|
||||
.push(IndividualExposure { who: nominator_stash.clone(), value: amount });
|
||||
nominator_stashes.push(nominator_stash.clone());
|
||||
}
|
||||
|
||||
let exposure = Exposure { total: amount * n.into(), own: amount, others: individual_exposures };
|
||||
let current_era = 0u32;
|
||||
Staking::<T>::add_era_stakers(current_era, stash.clone(), exposure);
|
||||
|
||||
Ok(Offender { controller: stash.clone(), stash, nominator_stashes })
|
||||
}
|
||||
|
||||
fn make_offenders<T: Config>(
|
||||
num_offenders: u32,
|
||||
num_nominators: u32,
|
||||
) -> Result<Vec<IdentificationTuple<T>>, &'static str> {
|
||||
let mut offenders = vec![];
|
||||
for i in 0..num_offenders {
|
||||
let offender = create_offender::<T>(i + 1, num_nominators)?;
|
||||
// add them to the session validators -- this is needed since `FullIdentificationOf` usually
|
||||
// checks this.
|
||||
pezpallet_session::Validators::<T>::mutate(|v| v.push(offender.controller.clone()));
|
||||
offenders.push(offender);
|
||||
}
|
||||
|
||||
let id_tuples = offenders
|
||||
.iter()
|
||||
.map(|offender| {
|
||||
<T as SessionConfig>::ValidatorIdOf::convert(offender.controller.clone())
|
||||
.expect("failed to get validator id from account id")
|
||||
})
|
||||
.map(|validator_id| {
|
||||
<T as HistoricalConfig>::FullIdentificationOf::convert(validator_id.clone())
|
||||
.map(|full_id| (validator_id, full_id))
|
||||
.unwrap()
|
||||
})
|
||||
.collect::<Vec<IdentificationTuple<T>>>();
|
||||
|
||||
if pezpallet_staking::ActiveEra::<T>::get().is_none() {
|
||||
pezpallet_staking::ActiveEra::<T>::put(pezpallet_staking::ActiveEraInfo {
|
||||
index: 0,
|
||||
start: Some(0),
|
||||
});
|
||||
}
|
||||
|
||||
Ok(id_tuples)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
fn assert_all_slashes_applied<T>(offender_count: usize)
|
||||
where
|
||||
T: Config,
|
||||
<T as pezframe_system::Config>::RuntimeEvent: TryInto<pezpallet_staking::Event<T>>,
|
||||
<T as pezframe_system::Config>::RuntimeEvent: TryInto<pezpallet_balances::Event<T>>,
|
||||
<T as pezframe_system::Config>::RuntimeEvent: TryInto<pezpallet_offences::Event>,
|
||||
<T as pezframe_system::Config>::RuntimeEvent: TryInto<pezframe_system::Event<T>>,
|
||||
{
|
||||
// make sure that all slashes have been applied and TotalIssuance adjusted(BurnedDebt).
|
||||
// deposit to reporter + reporter account endowed.
|
||||
assert_eq!(System::<T>::read_events_for_pallet::<pezpallet_balances::Event<T>>().len(), 3);
|
||||
// (n nominators + one validator) * slashed + Slash Reported + Slash Computed
|
||||
assert_eq!(
|
||||
System::<T>::read_events_for_pallet::<pezpallet_staking::Event<T>>().len(),
|
||||
1 * (offender_count + 1) as usize + 1
|
||||
);
|
||||
// offence
|
||||
assert_eq!(System::<T>::read_events_for_pallet::<pezpallet_offences::Event>().len(), 1);
|
||||
// reporter new account
|
||||
assert_eq!(System::<T>::read_events_for_pallet::<pezframe_system::Event<T>>().len(), 1);
|
||||
}
|
||||
|
||||
#[benchmarks(
|
||||
where
|
||||
<T as pezframe_system::Config>::RuntimeEvent: TryInto<pezpallet_staking::Event<T>>,
|
||||
<T as pezframe_system::Config>::RuntimeEvent: TryInto<pezpallet_balances::Event<T>>,
|
||||
<T as pezframe_system::Config>::RuntimeEvent: TryInto<pezpallet_offences::Event>,
|
||||
<T as pezframe_system::Config>::RuntimeEvent: TryInto<pezframe_system::Event<T>>,
|
||||
)]
|
||||
mod benchmarks {
|
||||
use super::*;
|
||||
|
||||
#[benchmark]
|
||||
pub fn report_offence_grandpa(
|
||||
n: Linear<0, { MAX_NOMINATORS.min(MaxNominationsOf::<T>::get()) }>,
|
||||
) -> Result<(), BenchmarkError> {
|
||||
// for grandpa equivocation reports the number of reporters
|
||||
// and offenders is always 1
|
||||
let reporters = vec![account("reporter", 1, SEED)];
|
||||
|
||||
// make sure reporters actually get rewarded
|
||||
Staking::<T>::set_slash_reward_fraction(Perbill::one());
|
||||
|
||||
let mut offenders = make_offenders::<T>(1, n)?;
|
||||
let validator_set_count = Session::<T>::validators().len() as u32;
|
||||
|
||||
let offence = GrandpaEquivocationOffence {
|
||||
time_slot: GrandpaTimeSlot { set_id: 0, round: 0 },
|
||||
session_index: 0,
|
||||
validator_set_count,
|
||||
offender: T::convert(offenders.pop().unwrap()),
|
||||
};
|
||||
assert_eq!(System::<T>::event_count(), 0);
|
||||
|
||||
#[block]
|
||||
{
|
||||
let _ = Offences::<T>::report_offence(reporters, offence);
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
{
|
||||
assert_all_slashes_applied::<T>(n as usize);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[benchmark]
|
||||
fn report_offence_babe(
|
||||
n: Linear<0, { MAX_NOMINATORS.min(MaxNominationsOf::<T>::get()) }>,
|
||||
) -> Result<(), BenchmarkError> {
|
||||
// for babe equivocation reports the number of reporters
|
||||
// and offenders is always 1
|
||||
let reporters = vec![account("reporter", 1, SEED)];
|
||||
|
||||
// make sure reporters actually get rewarded
|
||||
Staking::<T>::set_slash_reward_fraction(Perbill::one());
|
||||
|
||||
let mut offenders = make_offenders::<T>(1, n)?;
|
||||
let validator_set_count = Session::<T>::validators().len() as u32;
|
||||
|
||||
let offence = BabeEquivocationOffence {
|
||||
slot: 0u64.into(),
|
||||
session_index: 0,
|
||||
validator_set_count,
|
||||
offender: T::convert(offenders.pop().unwrap()),
|
||||
};
|
||||
assert_eq!(System::<T>::event_count(), 0);
|
||||
|
||||
#[block]
|
||||
{
|
||||
let _ = Offences::<T>::report_offence(reporters, offence);
|
||||
}
|
||||
#[cfg(test)]
|
||||
{
|
||||
assert_all_slashes_applied::<T>(n as usize);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
impl_benchmark_test_suite!(Pallet, crate::mock::new_test_ext(), crate::mock::Test);
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
// 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.
|
||||
|
||||
//! Offences pallet benchmarking.
|
||||
|
||||
#![cfg_attr(not(feature = "std"), no_std)]
|
||||
|
||||
extern crate alloc;
|
||||
|
||||
#[cfg(feature = "runtime-benchmarks")]
|
||||
pub mod inner;
|
||||
|
||||
#[cfg(feature = "runtime-benchmarks")]
|
||||
pub use inner::*;
|
||||
|
||||
#[cfg(all(feature = "runtime-benchmarks", test))]
|
||||
pub(crate) mod mock;
|
||||
@@ -0,0 +1,205 @@
|
||||
// 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.
|
||||
|
||||
//! Mock file for offences benchmarking.
|
||||
|
||||
use pezframe_election_provider_support::{
|
||||
bounds::{ElectionBounds, ElectionBoundsBuilder},
|
||||
onchain, SequentialPhragmen,
|
||||
};
|
||||
use pezframe_support::{
|
||||
derive_impl, parameter_types,
|
||||
traits::{ConstU32, ConstU64},
|
||||
};
|
||||
use pezframe_system as system;
|
||||
use pezpallet_session::historical as pezpallet_session_historical;
|
||||
use pezsp_runtime::{
|
||||
testing::{Header, UintAuthorityId},
|
||||
BuildStorage, KeyTypeId, Perbill,
|
||||
};
|
||||
|
||||
type AccountId = u64;
|
||||
|
||||
#[derive_impl(pezframe_system::config_preludes::TestDefaultConfig)]
|
||||
impl pezframe_system::Config for Test {
|
||||
type Block = Block;
|
||||
type AccountData = pezpallet_balances::AccountData<u64>;
|
||||
}
|
||||
|
||||
#[derive_impl(pezpallet_balances::config_preludes::TestDefaultConfig)]
|
||||
impl pezpallet_balances::Config for Test {
|
||||
type ExistentialDeposit = ConstU64<10>;
|
||||
type AccountStore = System;
|
||||
}
|
||||
|
||||
impl pezpallet_timestamp::Config for Test {
|
||||
type Moment = u64;
|
||||
type OnTimestampSet = ();
|
||||
type MinimumPeriod = ConstU64<5>;
|
||||
type WeightInfo = ();
|
||||
}
|
||||
impl pezpallet_session::historical::Config for Test {
|
||||
type RuntimeEvent = RuntimeEvent;
|
||||
type FullIdentification = ();
|
||||
type FullIdentificationOf = pezpallet_staking::UnitIdentificationOf<Self>;
|
||||
}
|
||||
|
||||
pezsp_runtime::impl_opaque_keys! {
|
||||
pub struct SessionKeys {
|
||||
pub foo: pezsp_runtime::testing::UintAuthorityId,
|
||||
}
|
||||
}
|
||||
|
||||
pub struct TestSessionHandler;
|
||||
impl pezpallet_session::SessionHandler<AccountId> for TestSessionHandler {
|
||||
// corresponds to the opaque key id above
|
||||
const KEY_TYPE_IDS: &'static [KeyTypeId] = &[KeyTypeId([100u8, 117u8, 109u8, 121u8])];
|
||||
|
||||
fn on_genesis_session<Ks: pezsp_runtime::traits::OpaqueKeys>(_validators: &[(AccountId, Ks)]) {}
|
||||
|
||||
fn on_new_session<Ks: pezsp_runtime::traits::OpaqueKeys>(
|
||||
_: bool,
|
||||
_: &[(AccountId, Ks)],
|
||||
_: &[(AccountId, Ks)],
|
||||
) {
|
||||
}
|
||||
|
||||
fn on_disabled(_: u32) {}
|
||||
}
|
||||
|
||||
parameter_types! {
|
||||
pub const Period: u64 = 1;
|
||||
pub const Offset: u64 = 0;
|
||||
}
|
||||
|
||||
impl pezpallet_session::Config for Test {
|
||||
type SessionManager = pezpallet_session::historical::NoteHistoricalRoot<Test, Staking>;
|
||||
type Keys = SessionKeys;
|
||||
type ShouldEndSession = pezpallet_session::PeriodicSessions<Period, Offset>;
|
||||
type NextSessionRotation = pezpallet_session::PeriodicSessions<Period, Offset>;
|
||||
type SessionHandler = TestSessionHandler;
|
||||
type RuntimeEvent = RuntimeEvent;
|
||||
type ValidatorId = AccountId;
|
||||
type ValidatorIdOf = pezsp_runtime::traits::ConvertInto;
|
||||
type DisablingStrategy = ();
|
||||
type WeightInfo = ();
|
||||
type Currency = Balances;
|
||||
type KeyDeposit = ();
|
||||
}
|
||||
|
||||
pezpallet_staking_reward_curve::build! {
|
||||
const I_NPOS: pezsp_runtime::curve::PiecewiseLinear<'static> = curve!(
|
||||
min_inflation: 0_025_000,
|
||||
max_inflation: 0_100_000,
|
||||
ideal_stake: 0_500_000,
|
||||
falloff: 0_050_000,
|
||||
max_piece_count: 40,
|
||||
test_precision: 0_005_000,
|
||||
);
|
||||
}
|
||||
parameter_types! {
|
||||
pub const RewardCurve: &'static pezsp_runtime::curve::PiecewiseLinear<'static> = &I_NPOS;
|
||||
pub static ElectionsBounds: ElectionBounds = ElectionBoundsBuilder::default().build();
|
||||
pub const Sort: bool = true;
|
||||
}
|
||||
|
||||
pub struct OnChainSeqPhragmen;
|
||||
impl onchain::Config for OnChainSeqPhragmen {
|
||||
type System = Test;
|
||||
type Solver = SequentialPhragmen<AccountId, Perbill>;
|
||||
type DataProvider = Staking;
|
||||
type WeightInfo = ();
|
||||
type MaxWinnersPerPage = ConstU32<100>;
|
||||
type MaxBackersPerWinner = ConstU32<100>;
|
||||
type Sort = Sort;
|
||||
type Bounds = ElectionsBounds;
|
||||
}
|
||||
|
||||
#[derive_impl(pezpallet_staking::config_preludes::TestDefaultConfig)]
|
||||
impl pezpallet_staking::Config for Test {
|
||||
type OldCurrency = Balances;
|
||||
type Currency = Balances;
|
||||
type CurrencyBalance = <Self as pezpallet_balances::Config>::Balance;
|
||||
type UnixTime = pezpallet_timestamp::Pallet<Self>;
|
||||
type AdminOrigin = pezframe_system::EnsureRoot<Self::AccountId>;
|
||||
type SessionInterface = Self;
|
||||
type EraPayout = pezpallet_staking::ConvertCurve<RewardCurve>;
|
||||
type NextNewSession = Session;
|
||||
type ElectionProvider = onchain::OnChainExecution<OnChainSeqPhragmen>;
|
||||
type GenesisElectionProvider = Self::ElectionProvider;
|
||||
type VoterList = pezpallet_staking::UseNominatorsAndValidatorsMap<Self>;
|
||||
type TargetList = pezpallet_staking::UseValidatorsMap<Self>;
|
||||
}
|
||||
|
||||
impl pezpallet_im_online::Config for Test {
|
||||
type AuthorityId = UintAuthorityId;
|
||||
type RuntimeEvent = RuntimeEvent;
|
||||
type ValidatorSet = Historical;
|
||||
type NextSessionRotation = pezpallet_session::PeriodicSessions<Period, Offset>;
|
||||
type ReportUnresponsiveness = Offences;
|
||||
type UnsignedPriority = ();
|
||||
type WeightInfo = ();
|
||||
type MaxKeys = ConstU32<10_000>;
|
||||
type MaxPeerInHeartbeats = ConstU32<10_000>;
|
||||
}
|
||||
|
||||
impl pezpallet_offences::Config for Test {
|
||||
type RuntimeEvent = RuntimeEvent;
|
||||
type IdentificationTuple = pezpallet_session::historical::IdentificationTuple<Self>;
|
||||
type OnOffenceHandler = Staking;
|
||||
}
|
||||
|
||||
impl<T> pezframe_system::offchain::CreateTransactionBase<T> for Test
|
||||
where
|
||||
RuntimeCall: From<T>,
|
||||
{
|
||||
type Extrinsic = UncheckedExtrinsic;
|
||||
type RuntimeCall = RuntimeCall;
|
||||
}
|
||||
|
||||
impl<T> pezframe_system::offchain::CreateBare<T> for Test
|
||||
where
|
||||
RuntimeCall: From<T>,
|
||||
{
|
||||
fn create_bare(call: Self::RuntimeCall) -> Self::Extrinsic {
|
||||
UncheckedExtrinsic::new_bare(call)
|
||||
}
|
||||
}
|
||||
|
||||
impl crate::Config for Test {}
|
||||
|
||||
pub type Block = pezsp_runtime::generic::Block<Header, UncheckedExtrinsic>;
|
||||
pub type UncheckedExtrinsic = pezsp_runtime::generic::UncheckedExtrinsic<u32, RuntimeCall, u64, ()>;
|
||||
|
||||
pezframe_support::construct_runtime!(
|
||||
pub enum Test
|
||||
{
|
||||
System: system::{Pallet, Call, Event<T>},
|
||||
Balances: pezpallet_balances,
|
||||
Staking: pezpallet_staking,
|
||||
Session: pezpallet_session,
|
||||
ImOnline: pezpallet_im_online::{Pallet, Call, Storage, Event<T>, ValidateUnsigned, Config<T>},
|
||||
Offences: pezpallet_offences::{Pallet, Storage, Event},
|
||||
Historical: pezpallet_session_historical::{Pallet, Event<T>},
|
||||
}
|
||||
);
|
||||
|
||||
pub fn new_test_ext() -> pezsp_io::TestExternalities {
|
||||
pezsp_tracing::try_init_simple();
|
||||
let t = pezframe_system::GenesisConfig::<Test>::default().build_storage().unwrap();
|
||||
pezsp_io::TestExternalities::new(t)
|
||||
}
|
||||
@@ -0,0 +1,254 @@
|
||||
// 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.
|
||||
|
||||
//! # Offences Pallet
|
||||
//!
|
||||
//! Tracks reported offences
|
||||
|
||||
// Ensure we're `no_std` when compiling for Wasm.
|
||||
#![cfg_attr(not(feature = "std"), no_std)]
|
||||
|
||||
pub mod migration;
|
||||
mod mock;
|
||||
mod tests;
|
||||
|
||||
extern crate alloc;
|
||||
|
||||
use alloc::vec::Vec;
|
||||
use codec::Encode;
|
||||
use core::marker::PhantomData;
|
||||
use pezframe_support::weights::Weight;
|
||||
use pezsp_runtime::{traits::Hash, Perbill};
|
||||
use pezsp_staking::{
|
||||
offence::{Kind, Offence, OffenceDetails, OffenceError, OnOffenceHandler, ReportOffence},
|
||||
SessionIndex,
|
||||
};
|
||||
|
||||
pub use pallet::*;
|
||||
|
||||
/// A binary blob which represents a SCALE codec-encoded `O::TimeSlot`.
|
||||
type OpaqueTimeSlot = Vec<u8>;
|
||||
|
||||
/// A type alias for a report identifier.
|
||||
type ReportIdOf<T> = <T as pezframe_system::Config>::Hash;
|
||||
|
||||
const LOG_TARGET: &str = "runtime::offences";
|
||||
|
||||
#[pezframe_support::pallet]
|
||||
pub mod pallet {
|
||||
use super::*;
|
||||
use pezframe_support::pezpallet_prelude::*;
|
||||
|
||||
const STORAGE_VERSION: StorageVersion = StorageVersion::new(1);
|
||||
|
||||
#[pallet::pallet]
|
||||
#[pallet::storage_version(STORAGE_VERSION)]
|
||||
#[pallet::without_storage_info]
|
||||
pub struct Pallet<T>(_);
|
||||
|
||||
/// The pallet's config trait.
|
||||
#[pallet::config]
|
||||
pub trait Config: pezframe_system::Config {
|
||||
/// The overarching event type.
|
||||
#[allow(deprecated)]
|
||||
type RuntimeEvent: From<Event> + IsType<<Self as pezframe_system::Config>::RuntimeEvent>;
|
||||
/// Full identification of the validator.
|
||||
type IdentificationTuple: Parameter;
|
||||
/// A handler called for every offence report.
|
||||
type OnOffenceHandler: OnOffenceHandler<Self::AccountId, Self::IdentificationTuple, Weight>;
|
||||
}
|
||||
|
||||
/// The primary structure that holds all offence records keyed by report identifiers.
|
||||
#[pallet::storage]
|
||||
pub type Reports<T: Config> = StorageMap<
|
||||
_,
|
||||
Twox64Concat,
|
||||
ReportIdOf<T>,
|
||||
OffenceDetails<T::AccountId, T::IdentificationTuple>,
|
||||
>;
|
||||
|
||||
/// A vector of reports of the same kind that happened at the same time slot.
|
||||
#[pallet::storage]
|
||||
pub type ConcurrentReportsIndex<T: Config> = StorageDoubleMap<
|
||||
_,
|
||||
Twox64Concat,
|
||||
Kind,
|
||||
Twox64Concat,
|
||||
OpaqueTimeSlot,
|
||||
Vec<ReportIdOf<T>>,
|
||||
ValueQuery,
|
||||
>;
|
||||
|
||||
/// Events type.
|
||||
#[pallet::event]
|
||||
#[pallet::generate_deposit(pub(super) fn deposit_event)]
|
||||
pub enum Event {
|
||||
/// There is an offence reported of the given `kind` happened at the `session_index` and
|
||||
/// (kind-specific) time slot. This event is not deposited for duplicate slashes.
|
||||
/// \[kind, timeslot\].
|
||||
Offence { kind: Kind, timeslot: OpaqueTimeSlot },
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, O> ReportOffence<T::AccountId, T::IdentificationTuple, O> for Pallet<T>
|
||||
where
|
||||
T: Config,
|
||||
O: Offence<T::IdentificationTuple>,
|
||||
{
|
||||
fn report_offence(reporters: Vec<T::AccountId>, offence: O) -> Result<(), OffenceError> {
|
||||
let offenders = offence.offenders();
|
||||
let time_slot = offence.time_slot();
|
||||
|
||||
// Go through all offenders in the offence report and find all offenders that were spotted
|
||||
// in unique reports.
|
||||
let TriageOutcome { concurrent_offenders } =
|
||||
match Self::triage_offence_report::<O>(reporters, &time_slot, offenders) {
|
||||
Some(triage) => triage,
|
||||
// The report contained only duplicates, so there is no need to slash again.
|
||||
None => return Err(OffenceError::DuplicateReport),
|
||||
};
|
||||
|
||||
let offenders_count = concurrent_offenders.len() as u32;
|
||||
|
||||
// The amount new offenders are slashed
|
||||
let new_fraction = offence.slash_fraction(offenders_count);
|
||||
|
||||
let slash_perbill: Vec<_> = (0..concurrent_offenders.len()).map(|_| new_fraction).collect();
|
||||
|
||||
T::OnOffenceHandler::on_offence(
|
||||
&concurrent_offenders,
|
||||
&slash_perbill,
|
||||
offence.session_index(),
|
||||
);
|
||||
|
||||
// Deposit the event.
|
||||
Self::deposit_event(Event::Offence { kind: O::ID, timeslot: time_slot.encode() });
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn is_known_offence(offenders: &[T::IdentificationTuple], time_slot: &O::TimeSlot) -> bool {
|
||||
let any_unknown = offenders.iter().any(|offender| {
|
||||
let report_id = Self::report_id::<O>(time_slot, offender);
|
||||
!<Reports<T>>::contains_key(&report_id)
|
||||
});
|
||||
|
||||
!any_unknown
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Config> Pallet<T> {
|
||||
/// Get the offence details from reports of given ID.
|
||||
pub fn reports(
|
||||
report_id: ReportIdOf<T>,
|
||||
) -> Option<OffenceDetails<T::AccountId, T::IdentificationTuple>> {
|
||||
Reports::<T>::get(report_id)
|
||||
}
|
||||
|
||||
/// Compute the ID for the given report properties.
|
||||
///
|
||||
/// The report id depends on the offence kind, time slot and the id of offender.
|
||||
fn report_id<O: Offence<T::IdentificationTuple>>(
|
||||
time_slot: &O::TimeSlot,
|
||||
offender: &T::IdentificationTuple,
|
||||
) -> ReportIdOf<T> {
|
||||
(O::ID, time_slot.encode(), offender).using_encoded(T::Hashing::hash)
|
||||
}
|
||||
|
||||
/// Triages the offence report and returns the set of offenders that was involved in unique
|
||||
/// reports along with the list of the concurrent offences.
|
||||
fn triage_offence_report<O: Offence<T::IdentificationTuple>>(
|
||||
reporters: Vec<T::AccountId>,
|
||||
time_slot: &O::TimeSlot,
|
||||
offenders: Vec<T::IdentificationTuple>,
|
||||
) -> Option<TriageOutcome<T>> {
|
||||
let mut storage = ReportIndexStorage::<T, O>::load(time_slot);
|
||||
|
||||
let mut any_new = false;
|
||||
for offender in offenders {
|
||||
let report_id = Self::report_id::<O>(time_slot, &offender);
|
||||
|
||||
if !<Reports<T>>::contains_key(&report_id) {
|
||||
any_new = true;
|
||||
<Reports<T>>::insert(
|
||||
&report_id,
|
||||
OffenceDetails { offender, reporters: reporters.clone() },
|
||||
);
|
||||
|
||||
storage.insert(report_id);
|
||||
}
|
||||
}
|
||||
|
||||
if any_new {
|
||||
// Load report details for the all reports happened at the same time.
|
||||
let concurrent_offenders = storage
|
||||
.concurrent_reports
|
||||
.iter()
|
||||
.filter_map(<Reports<T>>::get)
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
storage.save();
|
||||
|
||||
Some(TriageOutcome { concurrent_offenders })
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct TriageOutcome<T: Config> {
|
||||
/// Other reports for the same report kinds.
|
||||
concurrent_offenders: Vec<OffenceDetails<T::AccountId, T::IdentificationTuple>>,
|
||||
}
|
||||
|
||||
/// An auxiliary struct for working with storage of indexes localized for a specific offence
|
||||
/// kind (specified by the `O` type parameter).
|
||||
///
|
||||
/// This struct is responsible for aggregating storage writes and the underlying storage should not
|
||||
/// accessed directly meanwhile.
|
||||
#[must_use = "The changes are not saved without called `save`"]
|
||||
struct ReportIndexStorage<T: Config, O: Offence<T::IdentificationTuple>> {
|
||||
opaque_time_slot: OpaqueTimeSlot,
|
||||
concurrent_reports: Vec<ReportIdOf<T>>,
|
||||
_phantom: PhantomData<O>,
|
||||
}
|
||||
|
||||
impl<T: Config, O: Offence<T::IdentificationTuple>> ReportIndexStorage<T, O> {
|
||||
/// Preload indexes from the storage for the specific `time_slot` and the kind of the offence.
|
||||
fn load(time_slot: &O::TimeSlot) -> Self {
|
||||
let opaque_time_slot = time_slot.encode();
|
||||
|
||||
let concurrent_reports = <ConcurrentReportsIndex<T>>::get(&O::ID, &opaque_time_slot);
|
||||
|
||||
Self { opaque_time_slot, concurrent_reports, _phantom: Default::default() }
|
||||
}
|
||||
|
||||
/// Insert a new report to the index.
|
||||
fn insert(&mut self, report_id: ReportIdOf<T>) {
|
||||
// Update the list of concurrent reports.
|
||||
self.concurrent_reports.push(report_id);
|
||||
}
|
||||
|
||||
/// Dump the indexes to the storage.
|
||||
fn save(self) {
|
||||
<ConcurrentReportsIndex<T>>::insert(
|
||||
&O::ID,
|
||||
&self.opaque_time_slot,
|
||||
&self.concurrent_reports,
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,182 @@
|
||||
// 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.
|
||||
|
||||
use super::{Config, Kind, OffenceDetails, Pallet, Perbill, SessionIndex, LOG_TARGET};
|
||||
use alloc::vec::Vec;
|
||||
use pezframe_support::{
|
||||
pezpallet_prelude::ValueQuery,
|
||||
storage_alias,
|
||||
traits::{Get, GetStorageVersion, OnRuntimeUpgrade},
|
||||
weights::Weight,
|
||||
Twox64Concat,
|
||||
};
|
||||
use pezsp_staking::offence::OnOffenceHandler;
|
||||
|
||||
#[cfg(feature = "try-runtime")]
|
||||
use pezframe_support::ensure;
|
||||
#[cfg(feature = "try-runtime")]
|
||||
use pezsp_runtime::TryRuntimeError;
|
||||
|
||||
mod v0 {
|
||||
use super::*;
|
||||
|
||||
#[storage_alias]
|
||||
pub type ReportsByKindIndex<T: Config> = StorageMap<
|
||||
Pallet<T>,
|
||||
Twox64Concat,
|
||||
Kind,
|
||||
Vec<u8>, // (O::TimeSlot, ReportIdOf<T>)
|
||||
ValueQuery,
|
||||
>;
|
||||
}
|
||||
|
||||
pub mod v1 {
|
||||
use pezframe_support::traits::StorageVersion;
|
||||
|
||||
use super::*;
|
||||
|
||||
pub struct MigrateToV1<T>(core::marker::PhantomData<T>);
|
||||
impl<T: Config> OnRuntimeUpgrade for MigrateToV1<T> {
|
||||
#[cfg(feature = "try-runtime")]
|
||||
fn pre_upgrade() -> Result<Vec<u8>, TryRuntimeError> {
|
||||
log::info!(
|
||||
target: LOG_TARGET,
|
||||
"Number of reports to refund and delete: {}",
|
||||
v0::ReportsByKindIndex::<T>::iter_keys().count()
|
||||
);
|
||||
|
||||
Ok(Vec::new())
|
||||
}
|
||||
|
||||
fn on_runtime_upgrade() -> Weight {
|
||||
if Pallet::<T>::on_chain_storage_version() > 0 {
|
||||
log::info!(target: LOG_TARGET, "pezpallet_offences::MigrateToV1 should be removed");
|
||||
return T::DbWeight::get().reads(1);
|
||||
}
|
||||
|
||||
let keys_removed = v0::ReportsByKindIndex::<T>::clear(u32::MAX, None).unique as u64;
|
||||
StorageVersion::new(1).put::<Pallet<T>>();
|
||||
|
||||
// + 1 for reading/writing the new storage version
|
||||
T::DbWeight::get().reads_writes(keys_removed + 1, keys_removed + 1)
|
||||
}
|
||||
|
||||
#[cfg(feature = "try-runtime")]
|
||||
fn post_upgrade(_state: Vec<u8>) -> Result<(), TryRuntimeError> {
|
||||
let onchain = Pallet::<T>::on_chain_storage_version();
|
||||
ensure!(onchain == 1, "pezpallet_offences::MigrateToV1 needs to be run");
|
||||
ensure!(
|
||||
v0::ReportsByKindIndex::<T>::iter_keys().count() == 0,
|
||||
"there are some dangling reports that need to be destroyed and refunded"
|
||||
);
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Type of data stored as a deferred offence
|
||||
type DeferredOffenceOf<T> = (
|
||||
Vec<OffenceDetails<<T as pezframe_system::Config>::AccountId, <T as Config>::IdentificationTuple>>,
|
||||
Vec<Perbill>,
|
||||
SessionIndex,
|
||||
);
|
||||
|
||||
// Deferred reports that have been rejected by the offence handler and need to be submitted
|
||||
// at a later time.
|
||||
#[storage_alias]
|
||||
type DeferredOffences<T: Config> =
|
||||
StorageValue<crate::Pallet<T>, Vec<DeferredOffenceOf<T>>, ValueQuery>;
|
||||
|
||||
pub fn remove_deferred_storage<T: Config>() -> Weight {
|
||||
let mut weight = T::DbWeight::get().reads_writes(1, 1);
|
||||
let deferred = <DeferredOffences<T>>::take();
|
||||
log::info!(target: LOG_TARGET, "have {} deferred offences, applying.", deferred.len());
|
||||
for (offences, perbill, session) in deferred.iter() {
|
||||
let consumed = T::OnOffenceHandler::on_offence(offences, perbill, *session);
|
||||
weight = weight.saturating_add(consumed);
|
||||
}
|
||||
|
||||
weight
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
use crate::mock::{new_test_ext, with_on_offence_fractions, Runtime as T, KIND};
|
||||
use codec::Encode;
|
||||
use pezsp_runtime::Perbill;
|
||||
use pezsp_staking::offence::OffenceDetails;
|
||||
|
||||
#[test]
|
||||
fn migration_to_v1_works() {
|
||||
let mut ext = new_test_ext();
|
||||
|
||||
ext.execute_with(|| {
|
||||
<v0::ReportsByKindIndex<T>>::insert(KIND, 2u32.encode());
|
||||
assert!(<v0::ReportsByKindIndex<T>>::iter_values().count() > 0);
|
||||
});
|
||||
|
||||
ext.commit_all().unwrap();
|
||||
|
||||
ext.execute_with(|| {
|
||||
assert_eq!(
|
||||
v1::MigrateToV1::<T>::on_runtime_upgrade(),
|
||||
<T as pezframe_system::Config>::DbWeight::get().reads_writes(2, 2),
|
||||
);
|
||||
|
||||
assert!(<v0::ReportsByKindIndex<T>>::iter_values().count() == 0);
|
||||
})
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn should_resubmit_deferred_offences() {
|
||||
new_test_ext().execute_with(|| {
|
||||
// given
|
||||
assert_eq!(<DeferredOffences<T>>::get().len(), 0);
|
||||
with_on_offence_fractions(|f| {
|
||||
assert_eq!(f.clone(), vec![]);
|
||||
});
|
||||
|
||||
let offence_details = OffenceDetails::<
|
||||
<T as pezframe_system::Config>::AccountId,
|
||||
<T as Config>::IdentificationTuple,
|
||||
> {
|
||||
offender: 5,
|
||||
reporters: vec![],
|
||||
};
|
||||
|
||||
// push deferred offence
|
||||
<DeferredOffences<T>>::append((
|
||||
vec![offence_details],
|
||||
vec![Perbill::from_percent(5 + 1 * 100 / 5)],
|
||||
1,
|
||||
));
|
||||
|
||||
// when
|
||||
assert_eq!(
|
||||
remove_deferred_storage::<T>(),
|
||||
<T as pezframe_system::Config>::DbWeight::get().reads_writes(1, 1),
|
||||
);
|
||||
|
||||
// then
|
||||
assert!(!<DeferredOffences<T>>::exists());
|
||||
with_on_offence_fractions(|f| {
|
||||
assert_eq!(f.clone(), vec![Perbill::from_percent(5 + 1 * 100 / 5)]);
|
||||
});
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,138 @@
|
||||
// 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 offences;
|
||||
use crate::Config;
|
||||
use codec::Encode;
|
||||
use pezframe_support::{
|
||||
derive_impl, parameter_types,
|
||||
traits::ConstU32,
|
||||
weights::{constants::RocksDbWeight, Weight},
|
||||
};
|
||||
use pezsp_runtime::{traits::IdentityLookup, BuildStorage, Perbill};
|
||||
use pezsp_staking::{
|
||||
offence::{self, Kind, OffenceDetails},
|
||||
SessionIndex,
|
||||
};
|
||||
|
||||
pub struct OnOffenceHandler;
|
||||
|
||||
parameter_types! {
|
||||
pub static OnOffencePerbill: Vec<Perbill> = Default::default();
|
||||
pub static OffenceWeight: Weight = Default::default();
|
||||
}
|
||||
|
||||
impl<Reporter, Offender> offence::OnOffenceHandler<Reporter, Offender, Weight>
|
||||
for OnOffenceHandler
|
||||
{
|
||||
fn on_offence(
|
||||
_offenders: &[OffenceDetails<Reporter, Offender>],
|
||||
slash_fraction: &[Perbill],
|
||||
_offence_session: SessionIndex,
|
||||
) -> Weight {
|
||||
OnOffencePerbill::mutate(|f| {
|
||||
*f = slash_fraction.to_vec();
|
||||
});
|
||||
|
||||
OffenceWeight::get()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn with_on_offence_fractions<R, F: FnOnce(&mut Vec<Perbill>) -> R>(f: F) -> R {
|
||||
OnOffencePerbill::mutate(|fractions| f(fractions))
|
||||
}
|
||||
|
||||
type Block = pezframe_system::mocking::MockBlock<Runtime>;
|
||||
|
||||
pezframe_support::construct_runtime!(
|
||||
pub enum Runtime {
|
||||
System: pezframe_system,
|
||||
Offences: offences,
|
||||
}
|
||||
);
|
||||
|
||||
#[derive_impl(pezframe_system::config_preludes::TestDefaultConfig)]
|
||||
impl pezframe_system::Config for Runtime {
|
||||
type Nonce = u64;
|
||||
type Lookup = IdentityLookup<Self::AccountId>;
|
||||
type Block = Block;
|
||||
type RuntimeEvent = RuntimeEvent;
|
||||
type DbWeight = RocksDbWeight;
|
||||
type MaxConsumers = ConstU32<16>;
|
||||
}
|
||||
|
||||
impl Config for Runtime {
|
||||
type RuntimeEvent = RuntimeEvent;
|
||||
type IdentificationTuple = u64;
|
||||
type OnOffenceHandler = OnOffenceHandler;
|
||||
}
|
||||
|
||||
pub fn new_test_ext() -> pezsp_io::TestExternalities {
|
||||
let t = pezframe_system::GenesisConfig::<Runtime>::default().build_storage().unwrap();
|
||||
let mut ext = pezsp_io::TestExternalities::new(t);
|
||||
ext.execute_with(|| System::set_block_number(1));
|
||||
ext
|
||||
}
|
||||
|
||||
pub const KIND: [u8; 16] = *b"test_report_1234";
|
||||
|
||||
/// Returns all offence details for the specific `kind` happened at the specific time slot.
|
||||
pub fn offence_reports(kind: Kind, time_slot: u128) -> Vec<OffenceDetails<u64, u64>> {
|
||||
<crate::ConcurrentReportsIndex<Runtime>>::get(&kind, &time_slot.encode())
|
||||
.into_iter()
|
||||
.map(|report_id| {
|
||||
<crate::Reports<Runtime>>::get(&report_id)
|
||||
.expect("dangling report id is found in ConcurrentReportsIndex")
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct Offence {
|
||||
pub validator_set_count: u32,
|
||||
pub offenders: Vec<u64>,
|
||||
pub time_slot: u128,
|
||||
}
|
||||
|
||||
impl offence::Offence<u64> for Offence {
|
||||
const ID: offence::Kind = KIND;
|
||||
type TimeSlot = u128;
|
||||
|
||||
fn offenders(&self) -> Vec<u64> {
|
||||
self.offenders.clone()
|
||||
}
|
||||
|
||||
fn validator_set_count(&self) -> u32 {
|
||||
self.validator_set_count
|
||||
}
|
||||
|
||||
fn time_slot(&self) -> u128 {
|
||||
self.time_slot
|
||||
}
|
||||
|
||||
fn session_index(&self) -> SessionIndex {
|
||||
1
|
||||
}
|
||||
|
||||
fn slash_fraction(&self, offenders_count: u32) -> Perbill {
|
||||
Perbill::from_percent(5 + offenders_count * 100 / self.validator_set_count)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,269 @@
|
||||
// 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 offences module.
|
||||
|
||||
#![cfg(test)]
|
||||
|
||||
use super::*;
|
||||
use crate::mock::{
|
||||
new_test_ext, offence_reports, with_on_offence_fractions, Offence, Offences, Runtime,
|
||||
RuntimeEvent, System, KIND,
|
||||
};
|
||||
use pezframe_system::{EventRecord, Phase};
|
||||
use pezsp_core::H256;
|
||||
use pezsp_runtime::Perbill;
|
||||
|
||||
#[test]
|
||||
fn should_get_reports_with_storagemap_getter_and_function_getter() {
|
||||
new_test_ext().execute_with(|| {
|
||||
// given
|
||||
let report_id: ReportIdOf<Runtime> = H256::from_low_u64_be(1);
|
||||
let offence_details = OffenceDetails { offender: 1, reporters: vec![2, 3] };
|
||||
|
||||
Reports::<Runtime>::insert(report_id, offence_details.clone());
|
||||
|
||||
// when
|
||||
let stored_offence_details = Offences::reports(report_id);
|
||||
// then
|
||||
assert_eq!(stored_offence_details, Some(offence_details.clone()));
|
||||
|
||||
// when
|
||||
let stored_offence_details = Reports::<Runtime>::get(report_id);
|
||||
// then
|
||||
assert_eq!(stored_offence_details, Some(offence_details.clone()));
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn should_report_an_authority_and_trigger_on_offence() {
|
||||
new_test_ext().execute_with(|| {
|
||||
// given
|
||||
let time_slot = 42;
|
||||
assert_eq!(offence_reports(KIND, time_slot), vec![]);
|
||||
|
||||
let offence = Offence { validator_set_count: 5, time_slot, offenders: vec![5] };
|
||||
|
||||
// when
|
||||
Offences::report_offence(vec![], offence).unwrap();
|
||||
|
||||
// then
|
||||
with_on_offence_fractions(|f| {
|
||||
assert_eq!(f.clone(), vec![Perbill::from_percent(25)]);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn should_not_report_the_same_authority_twice_in_the_same_slot() {
|
||||
new_test_ext().execute_with(|| {
|
||||
// given
|
||||
let time_slot = 42;
|
||||
assert_eq!(offence_reports(KIND, time_slot), vec![]);
|
||||
|
||||
let offence = Offence { validator_set_count: 5, time_slot, offenders: vec![5] };
|
||||
Offences::report_offence(vec![], offence.clone()).unwrap();
|
||||
with_on_offence_fractions(|f| {
|
||||
assert_eq!(f.clone(), vec![Perbill::from_percent(25)]);
|
||||
f.clear();
|
||||
});
|
||||
|
||||
// when
|
||||
// report for the second time
|
||||
assert_eq!(Offences::report_offence(vec![], offence), Err(OffenceError::DuplicateReport));
|
||||
|
||||
// then
|
||||
with_on_offence_fractions(|f| {
|
||||
assert_eq!(f.clone(), vec![]);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn should_report_in_different_time_slot() {
|
||||
new_test_ext().execute_with(|| {
|
||||
// given
|
||||
let time_slot = 42;
|
||||
assert_eq!(offence_reports(KIND, time_slot), vec![]);
|
||||
|
||||
let mut offence = Offence { validator_set_count: 5, time_slot, offenders: vec![5] };
|
||||
Offences::report_offence(vec![], offence.clone()).unwrap();
|
||||
with_on_offence_fractions(|f| {
|
||||
assert_eq!(f.clone(), vec![Perbill::from_percent(25)]);
|
||||
f.clear();
|
||||
});
|
||||
|
||||
// when
|
||||
// report for the second time
|
||||
offence.time_slot += 1;
|
||||
Offences::report_offence(vec![], offence).unwrap();
|
||||
|
||||
// then
|
||||
with_on_offence_fractions(|f| {
|
||||
assert_eq!(f.clone(), vec![Perbill::from_percent(25)]);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn should_deposit_event() {
|
||||
new_test_ext().execute_with(|| {
|
||||
// given
|
||||
let time_slot = 42;
|
||||
assert_eq!(offence_reports(KIND, time_slot), vec![]);
|
||||
|
||||
let offence = Offence { validator_set_count: 5, time_slot, offenders: vec![5] };
|
||||
|
||||
// when
|
||||
Offences::report_offence(vec![], offence).unwrap();
|
||||
|
||||
// then
|
||||
assert_eq!(
|
||||
System::events(),
|
||||
vec![EventRecord {
|
||||
phase: Phase::Initialization,
|
||||
event: RuntimeEvent::Offences(crate::Event::Offence {
|
||||
kind: KIND,
|
||||
timeslot: time_slot.encode()
|
||||
}),
|
||||
topics: vec![],
|
||||
}]
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn doesnt_deposit_event_for_dups() {
|
||||
new_test_ext().execute_with(|| {
|
||||
// given
|
||||
let time_slot = 42;
|
||||
assert_eq!(offence_reports(KIND, time_slot), vec![]);
|
||||
|
||||
let offence = Offence { validator_set_count: 5, time_slot, offenders: vec![5] };
|
||||
Offences::report_offence(vec![], offence.clone()).unwrap();
|
||||
with_on_offence_fractions(|f| {
|
||||
assert_eq!(f.clone(), vec![Perbill::from_percent(25)]);
|
||||
f.clear();
|
||||
});
|
||||
|
||||
// when
|
||||
// report for the second time
|
||||
assert_eq!(Offences::report_offence(vec![], offence), Err(OffenceError::DuplicateReport));
|
||||
|
||||
// then
|
||||
// there is only one event.
|
||||
assert_eq!(
|
||||
System::events(),
|
||||
vec![EventRecord {
|
||||
phase: Phase::Initialization,
|
||||
event: RuntimeEvent::Offences(crate::Event::Offence {
|
||||
kind: KIND,
|
||||
timeslot: time_slot.encode()
|
||||
}),
|
||||
topics: vec![],
|
||||
}]
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn reports_if_an_offence_is_dup() {
|
||||
new_test_ext().execute_with(|| {
|
||||
let time_slot = 42;
|
||||
assert_eq!(offence_reports(KIND, time_slot), vec![]);
|
||||
|
||||
let offence =
|
||||
|time_slot, offenders| Offence { validator_set_count: 5, time_slot, offenders };
|
||||
|
||||
let mut test_offence = offence(time_slot, vec![0]);
|
||||
|
||||
// the report for authority 0 at time slot 42 should not be a known
|
||||
// offence
|
||||
assert!(!<Offences as ReportOffence<_, _, Offence>>::is_known_offence(
|
||||
&test_offence.offenders,
|
||||
&test_offence.time_slot
|
||||
));
|
||||
|
||||
// we report an offence for authority 0 at time slot 42
|
||||
Offences::report_offence(vec![], test_offence.clone()).unwrap();
|
||||
|
||||
// the same report should be a known offence now
|
||||
assert!(<Offences as ReportOffence<_, _, Offence>>::is_known_offence(
|
||||
&test_offence.offenders,
|
||||
&test_offence.time_slot
|
||||
));
|
||||
|
||||
// and reporting it again should yield a duplicate report error
|
||||
assert_eq!(
|
||||
Offences::report_offence(vec![], test_offence.clone()),
|
||||
Err(OffenceError::DuplicateReport)
|
||||
);
|
||||
|
||||
// after adding a new offender to the offence report
|
||||
test_offence.offenders.push(1);
|
||||
|
||||
// it should not be a known offence anymore
|
||||
assert!(!<Offences as ReportOffence<_, _, Offence>>::is_known_offence(
|
||||
&test_offence.offenders,
|
||||
&test_offence.time_slot
|
||||
));
|
||||
|
||||
// and reporting it again should work without any error
|
||||
assert_eq!(Offences::report_offence(vec![], test_offence.clone()), Ok(()));
|
||||
|
||||
// creating a new offence for the same authorities on the next slot
|
||||
// should be considered a new offence and therefore not known
|
||||
let test_offence_next_slot = offence(time_slot + 1, vec![0, 1]);
|
||||
assert!(!<Offences as ReportOffence<_, _, Offence>>::is_known_offence(
|
||||
&test_offence_next_slot.offenders,
|
||||
&test_offence_next_slot.time_slot
|
||||
));
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn should_properly_count_offences() {
|
||||
// We report two different authorities for the same issue. Ultimately, the 1st authority
|
||||
// should have `count` equal 2 and the count of the 2nd one should be equal to 1.
|
||||
new_test_ext().execute_with(|| {
|
||||
// given
|
||||
let time_slot = 42;
|
||||
assert_eq!(offence_reports(KIND, time_slot), vec![]);
|
||||
|
||||
let offence1 = Offence { validator_set_count: 5, time_slot, offenders: vec![5] };
|
||||
let offence2 = Offence { validator_set_count: 5, time_slot, offenders: vec![4] };
|
||||
Offences::report_offence(vec![], offence1).unwrap();
|
||||
with_on_offence_fractions(|f| {
|
||||
assert_eq!(f.clone(), vec![Perbill::from_percent(25)]);
|
||||
f.clear();
|
||||
});
|
||||
|
||||
// when
|
||||
// report for the second time
|
||||
Offences::report_offence(vec![], offence2).unwrap();
|
||||
|
||||
// then
|
||||
// the 1st authority should have count 2 and the 2nd one should be reported only once.
|
||||
assert_eq!(
|
||||
offence_reports(KIND, time_slot),
|
||||
vec![
|
||||
OffenceDetails { offender: 5, reporters: vec![] },
|
||||
OffenceDetails { offender: 4, reporters: vec![] },
|
||||
]
|
||||
);
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,226 @@
|
||||
// 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.
|
||||
|
||||
// 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_offences`
|
||||
//!
|
||||
//! THIS FILE WAS AUTO-GENERATED USING THE BIZINIKIWI BENCHMARK CLI VERSION 32.0.0
|
||||
//! DATE: 2025-02-21, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]`
|
||||
//! WORST CASE MAP SIZE: `1000000`
|
||||
//! HOSTNAME: `4563561839a5`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz`
|
||||
//! WASM-EXECUTION: `Compiled`, CHAIN: `None`, DB CACHE: `1024`
|
||||
|
||||
// Executed Command:
|
||||
// frame-omni-bencher
|
||||
// v1
|
||||
// benchmark
|
||||
// pallet
|
||||
// --extrinsic=*
|
||||
// --runtime=target/production/wbuild/kitchensink-runtime/kitchensink_runtime.wasm
|
||||
// --pallet=pezpallet_offences
|
||||
// --header=/__w/pezkuwi-sdk/pezkuwi-sdk/bizinikiwi/HEADER-APACHE2
|
||||
// --output=/__w/pezkuwi-sdk/pezkuwi-sdk/bizinikiwi/pezframe/offences/src/weights.rs
|
||||
// --wasm-execution=compiled
|
||||
// --steps=50
|
||||
// --repeat=20
|
||||
// --heap-pages=4096
|
||||
// --template=bizinikiwi/.maintain/frame-weight-template.hbs
|
||||
// --no-storage-info
|
||||
// --no-min-squares
|
||||
// --no-median-slopes
|
||||
// --genesis-builder-policy=none
|
||||
// --exclude-pallets=pezpallet_xcm,pezpallet_xcm_benchmarks::fungible,pezpallet_xcm_benchmarks::generic,pezpallet_nomination_pools,pezpallet_remark,pezpallet_transaction_storage,pezpallet_election_provider_multi_block,pezpallet_election_provider_multi_block::signed,pezpallet_election_provider_multi_block::unsigned,pezpallet_election_provider_multi_block::verifier
|
||||
|
||||
#![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;
|
||||
|
||||
/// Weight functions needed for `pezpallet_offences`.
|
||||
pub trait WeightInfo {
|
||||
fn report_offence_grandpa(n: u32, ) -> Weight;
|
||||
fn report_offence_babe(n: u32, ) -> Weight;
|
||||
}
|
||||
|
||||
/// Weights for `pezpallet_offences` using the Bizinikiwi node and recommended hardware.
|
||||
pub struct BizinikiwiWeight<T>(PhantomData<T>);
|
||||
impl<T: pezframe_system::Config> WeightInfo for BizinikiwiWeight<T> {
|
||||
/// Storage: `Offences::ConcurrentReportsIndex` (r:1 w:1)
|
||||
/// Proof: `Offences::ConcurrentReportsIndex` (`max_values`: None, `max_size`: None, mode: `Measured`)
|
||||
/// Storage: `Offences::Reports` (r:1 w:1)
|
||||
/// Proof: `Offences::Reports` (`max_values`: None, `max_size`: None, mode: `Measured`)
|
||||
/// Storage: `Staking::ActiveEra` (r:1 w:0)
|
||||
/// Proof: `Staking::ActiveEra` (`max_values`: Some(1), `max_size`: Some(13), added: 508, mode: `MaxEncodedLen`)
|
||||
/// Storage: `Staking::ErasStartSessionIndex` (r:1 w:0)
|
||||
/// Proof: `Staking::ErasStartSessionIndex` (`max_values`: None, `max_size`: Some(16), added: 2491, mode: `MaxEncodedLen`)
|
||||
/// Storage: `Staking::Invulnerables` (r:1 w:0)
|
||||
/// Proof: `Staking::Invulnerables` (`max_values`: Some(1), `max_size`: Some(641), added: 1136, mode: `MaxEncodedLen`)
|
||||
/// Storage: `Staking::ErasStakersOverview` (r:1 w:0)
|
||||
/// Proof: `Staking::ErasStakersOverview` (`max_values`: None, `max_size`: Some(92), added: 2567, mode: `MaxEncodedLen`)
|
||||
/// Storage: `Session::DisabledValidators` (r:1 w:1)
|
||||
/// Proof: `Session::DisabledValidators` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
|
||||
/// Storage: `Session::Validators` (r:1 w:0)
|
||||
/// Proof: `Session::Validators` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
|
||||
/// Storage: `Staking::ValidatorSlashInEra` (r:1 w:1)
|
||||
/// Proof: `Staking::ValidatorSlashInEra` (`max_values`: None, `max_size`: Some(72), added: 2547, mode: `MaxEncodedLen`)
|
||||
/// Storage: `Staking::OffenceQueue` (r:1 w:1)
|
||||
/// Proof: `Staking::OffenceQueue` (`max_values`: None, `max_size`: Some(101), added: 2576, mode: `MaxEncodedLen`)
|
||||
/// Storage: `Staking::OffenceQueueEras` (r:1 w:1)
|
||||
/// Proof: `Staking::OffenceQueueEras` (`max_values`: Some(1), `max_size`: Some(2690), added: 3185, mode: `MaxEncodedLen`)
|
||||
/// The range of component `n` is `[0, 16]`.
|
||||
fn report_offence_grandpa(n: u32, ) -> Weight {
|
||||
// Proof Size summary in bytes:
|
||||
// Measured: `424`
|
||||
// Estimated: `4175 + n * (1 ±0)`
|
||||
// Minimum execution time: 39_455_000 picoseconds.
|
||||
Weight::from_parts(41_709_372, 4175)
|
||||
// Standard Error: 5_442
|
||||
.saturating_add(Weight::from_parts(438_959, 0).saturating_mul(n.into()))
|
||||
.saturating_add(T::DbWeight::get().reads(11_u64))
|
||||
.saturating_add(T::DbWeight::get().writes(6_u64))
|
||||
.saturating_add(Weight::from_parts(0, 1).saturating_mul(n.into()))
|
||||
}
|
||||
/// Storage: `Offences::ConcurrentReportsIndex` (r:1 w:1)
|
||||
/// Proof: `Offences::ConcurrentReportsIndex` (`max_values`: None, `max_size`: None, mode: `Measured`)
|
||||
/// Storage: `Offences::Reports` (r:1 w:1)
|
||||
/// Proof: `Offences::Reports` (`max_values`: None, `max_size`: None, mode: `Measured`)
|
||||
/// Storage: `Staking::ActiveEra` (r:1 w:0)
|
||||
/// Proof: `Staking::ActiveEra` (`max_values`: Some(1), `max_size`: Some(13), added: 508, mode: `MaxEncodedLen`)
|
||||
/// Storage: `Staking::ErasStartSessionIndex` (r:1 w:0)
|
||||
/// Proof: `Staking::ErasStartSessionIndex` (`max_values`: None, `max_size`: Some(16), added: 2491, mode: `MaxEncodedLen`)
|
||||
/// Storage: `Staking::Invulnerables` (r:1 w:0)
|
||||
/// Proof: `Staking::Invulnerables` (`max_values`: Some(1), `max_size`: Some(641), added: 1136, mode: `MaxEncodedLen`)
|
||||
/// Storage: `Staking::ErasStakersOverview` (r:1 w:0)
|
||||
/// Proof: `Staking::ErasStakersOverview` (`max_values`: None, `max_size`: Some(92), added: 2567, mode: `MaxEncodedLen`)
|
||||
/// Storage: `Session::DisabledValidators` (r:1 w:1)
|
||||
/// Proof: `Session::DisabledValidators` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
|
||||
/// Storage: `Session::Validators` (r:1 w:0)
|
||||
/// Proof: `Session::Validators` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
|
||||
/// Storage: `Staking::ValidatorSlashInEra` (r:1 w:1)
|
||||
/// Proof: `Staking::ValidatorSlashInEra` (`max_values`: None, `max_size`: Some(72), added: 2547, mode: `MaxEncodedLen`)
|
||||
/// Storage: `Staking::OffenceQueue` (r:1 w:1)
|
||||
/// Proof: `Staking::OffenceQueue` (`max_values`: None, `max_size`: Some(101), added: 2576, mode: `MaxEncodedLen`)
|
||||
/// Storage: `Staking::OffenceQueueEras` (r:1 w:1)
|
||||
/// Proof: `Staking::OffenceQueueEras` (`max_values`: Some(1), `max_size`: Some(2690), added: 3185, mode: `MaxEncodedLen`)
|
||||
/// The range of component `n` is `[0, 16]`.
|
||||
fn report_offence_babe(n: u32, ) -> Weight {
|
||||
// Proof Size summary in bytes:
|
||||
// Measured: `424`
|
||||
// Estimated: `4175 + n * (1 ±0)`
|
||||
// Minimum execution time: 39_396_000 picoseconds.
|
||||
Weight::from_parts(41_490_043, 4175)
|
||||
// Standard Error: 4_716
|
||||
.saturating_add(Weight::from_parts(433_178, 0).saturating_mul(n.into()))
|
||||
.saturating_add(T::DbWeight::get().reads(11_u64))
|
||||
.saturating_add(T::DbWeight::get().writes(6_u64))
|
||||
.saturating_add(Weight::from_parts(0, 1).saturating_mul(n.into()))
|
||||
}
|
||||
}
|
||||
|
||||
// For backwards compatibility and tests.
|
||||
impl WeightInfo for () {
|
||||
/// Storage: `Offences::ConcurrentReportsIndex` (r:1 w:1)
|
||||
/// Proof: `Offences::ConcurrentReportsIndex` (`max_values`: None, `max_size`: None, mode: `Measured`)
|
||||
/// Storage: `Offences::Reports` (r:1 w:1)
|
||||
/// Proof: `Offences::Reports` (`max_values`: None, `max_size`: None, mode: `Measured`)
|
||||
/// Storage: `Staking::ActiveEra` (r:1 w:0)
|
||||
/// Proof: `Staking::ActiveEra` (`max_values`: Some(1), `max_size`: Some(13), added: 508, mode: `MaxEncodedLen`)
|
||||
/// Storage: `Staking::ErasStartSessionIndex` (r:1 w:0)
|
||||
/// Proof: `Staking::ErasStartSessionIndex` (`max_values`: None, `max_size`: Some(16), added: 2491, mode: `MaxEncodedLen`)
|
||||
/// Storage: `Staking::Invulnerables` (r:1 w:0)
|
||||
/// Proof: `Staking::Invulnerables` (`max_values`: Some(1), `max_size`: Some(641), added: 1136, mode: `MaxEncodedLen`)
|
||||
/// Storage: `Staking::ErasStakersOverview` (r:1 w:0)
|
||||
/// Proof: `Staking::ErasStakersOverview` (`max_values`: None, `max_size`: Some(92), added: 2567, mode: `MaxEncodedLen`)
|
||||
/// Storage: `Session::DisabledValidators` (r:1 w:1)
|
||||
/// Proof: `Session::DisabledValidators` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
|
||||
/// Storage: `Session::Validators` (r:1 w:0)
|
||||
/// Proof: `Session::Validators` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
|
||||
/// Storage: `Staking::ValidatorSlashInEra` (r:1 w:1)
|
||||
/// Proof: `Staking::ValidatorSlashInEra` (`max_values`: None, `max_size`: Some(72), added: 2547, mode: `MaxEncodedLen`)
|
||||
/// Storage: `Staking::OffenceQueue` (r:1 w:1)
|
||||
/// Proof: `Staking::OffenceQueue` (`max_values`: None, `max_size`: Some(101), added: 2576, mode: `MaxEncodedLen`)
|
||||
/// Storage: `Staking::OffenceQueueEras` (r:1 w:1)
|
||||
/// Proof: `Staking::OffenceQueueEras` (`max_values`: Some(1), `max_size`: Some(2690), added: 3185, mode: `MaxEncodedLen`)
|
||||
/// The range of component `n` is `[0, 16]`.
|
||||
fn report_offence_grandpa(n: u32, ) -> Weight {
|
||||
// Proof Size summary in bytes:
|
||||
// Measured: `424`
|
||||
// Estimated: `4175 + n * (1 ±0)`
|
||||
// Minimum execution time: 39_455_000 picoseconds.
|
||||
Weight::from_parts(41_709_372, 4175)
|
||||
// Standard Error: 5_442
|
||||
.saturating_add(Weight::from_parts(438_959, 0).saturating_mul(n.into()))
|
||||
.saturating_add(RocksDbWeight::get().reads(11_u64))
|
||||
.saturating_add(RocksDbWeight::get().writes(6_u64))
|
||||
.saturating_add(Weight::from_parts(0, 1).saturating_mul(n.into()))
|
||||
}
|
||||
/// Storage: `Offences::ConcurrentReportsIndex` (r:1 w:1)
|
||||
/// Proof: `Offences::ConcurrentReportsIndex` (`max_values`: None, `max_size`: None, mode: `Measured`)
|
||||
/// Storage: `Offences::Reports` (r:1 w:1)
|
||||
/// Proof: `Offences::Reports` (`max_values`: None, `max_size`: None, mode: `Measured`)
|
||||
/// Storage: `Staking::ActiveEra` (r:1 w:0)
|
||||
/// Proof: `Staking::ActiveEra` (`max_values`: Some(1), `max_size`: Some(13), added: 508, mode: `MaxEncodedLen`)
|
||||
/// Storage: `Staking::ErasStartSessionIndex` (r:1 w:0)
|
||||
/// Proof: `Staking::ErasStartSessionIndex` (`max_values`: None, `max_size`: Some(16), added: 2491, mode: `MaxEncodedLen`)
|
||||
/// Storage: `Staking::Invulnerables` (r:1 w:0)
|
||||
/// Proof: `Staking::Invulnerables` (`max_values`: Some(1), `max_size`: Some(641), added: 1136, mode: `MaxEncodedLen`)
|
||||
/// Storage: `Staking::ErasStakersOverview` (r:1 w:0)
|
||||
/// Proof: `Staking::ErasStakersOverview` (`max_values`: None, `max_size`: Some(92), added: 2567, mode: `MaxEncodedLen`)
|
||||
/// Storage: `Session::DisabledValidators` (r:1 w:1)
|
||||
/// Proof: `Session::DisabledValidators` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
|
||||
/// Storage: `Session::Validators` (r:1 w:0)
|
||||
/// Proof: `Session::Validators` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
|
||||
/// Storage: `Staking::ValidatorSlashInEra` (r:1 w:1)
|
||||
/// Proof: `Staking::ValidatorSlashInEra` (`max_values`: None, `max_size`: Some(72), added: 2547, mode: `MaxEncodedLen`)
|
||||
/// Storage: `Staking::OffenceQueue` (r:1 w:1)
|
||||
/// Proof: `Staking::OffenceQueue` (`max_values`: None, `max_size`: Some(101), added: 2576, mode: `MaxEncodedLen`)
|
||||
/// Storage: `Staking::OffenceQueueEras` (r:1 w:1)
|
||||
/// Proof: `Staking::OffenceQueueEras` (`max_values`: Some(1), `max_size`: Some(2690), added: 3185, mode: `MaxEncodedLen`)
|
||||
/// The range of component `n` is `[0, 16]`.
|
||||
fn report_offence_babe(n: u32, ) -> Weight {
|
||||
// Proof Size summary in bytes:
|
||||
// Measured: `424`
|
||||
// Estimated: `4175 + n * (1 ±0)`
|
||||
// Minimum execution time: 39_396_000 picoseconds.
|
||||
Weight::from_parts(41_490_043, 4175)
|
||||
// Standard Error: 4_716
|
||||
.saturating_add(Weight::from_parts(433_178, 0).saturating_mul(n.into()))
|
||||
.saturating_add(RocksDbWeight::get().reads(11_u64))
|
||||
.saturating_add(RocksDbWeight::get().writes(6_u64))
|
||||
.saturating_add(Weight::from_parts(0, 1).saturating_mul(n.into()))
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user