Compare commits

..

29 Commits

Author SHA1 Message Date
4c4374c812
downgrade state version
Signed-off-by: Uncle Stretch <uncle.stretch@ghostchain.io>
2026-03-04 17:11:17 +03:00
e7b8cd46e1
add transaction hash to the unique identifier of the bridging tx
Signed-off-by: Uncle Stinky <uncle.stinky@ghostchain.io>
2026-03-03 22:18:32 +03:00
713cbdfdc1
latest benhcmarking setup for casper runtime
Signed-off-by: Uncle Stretch <uncle.stretch@ghostchain.io>
2026-03-01 13:26:26 +03:00
5dcc23c996
update pallets weights based on the real benchmarkings
Signed-off-by: Uncle Stretch <uncle.stretch@ghostchain.io>
2026-03-01 12:39:44 +03:00
562efe5744
apply final changes to casper runtime
Signed-off-by: Uncle Stretch <uncle.stretch@ghostchain.io>
2026-02-26 21:38:34 +03:00
b0a69493cd
fix benchmarking for slow clap
Signed-off-by: Uncle Stretch <uncle.stretch@ghostchain.io>
2026-02-26 21:36:14 +03:00
bd8d7145af
more optimized version for try_offend_validators
Signed-off-by: Uncle Stretch <uncle.stretch@ghostchain.io>
2026-02-26 14:44:36 +03:00
ba7d2a8222
additional function for exposure trait
Signed-off-by: Uncle Stretch <uncle.stretch@ghostchain.io>
2026-02-26 14:42:39 +03:00
cc300fefb0
apply changes to casper runtime; migrations are included
Signed-off-by: Uncle Stinky <uncle.stinky@ghostchain.io>
2026-02-24 22:06:54 +03:00
c8f8ea7130
rustfmt of the chain specs
Signed-off-by: Uncle Stinky <uncle.stinky@ghostchain.io>
2026-02-24 22:03:45 +03:00
93387218ec
make initialise authorities infallable and fix benchmarking
Signed-off-by: Uncle Stinky <uncle.stinky@ghostchain.io>
2026-02-24 22:02:26 +03:00
6a5029017c
use ExternalBlockNumber type everywhere
Signed-off-by: Uncle Stinky <uncle.stinky@ghostchain.io>
2026-02-23 19:13:14 +03:00
4c79048b49
migration to new block commitment data type; tests included
Signed-off-by: Uncle Stinky <uncle.stinky@ghostchain.io>
2026-02-23 18:56:05 +03:00
24b08a87b1
make max commit deviation to be 1/8 of EpochDuration
Signed-off-by: Uncle Stinky <uncle.stinky@ghostchain.io>
2026-02-23 16:55:33 +03:00
06618069e2
avoid commitments check on the beginning of the epoch
Signed-off-by: Uncle Stinky <uncle.stinky@ghostchain.io>
2026-02-23 15:17:13 +03:00
028afc089f
use internal block number as last_update for block commitments
Signed-off-by: Uncle Stinky <uncle.stinky@ghostchain.io>
2026-02-22 21:56:55 +03:00
f082dfc4e0
ability to iterate over network ids only and get networks lenght without storage read
Signed-off-by: Uncle Stinky <uncle.stinky@ghostchain.io>
2026-02-22 21:54:51 +03:00
c963f7816b
slightly optimise try_slow_clap
Signed-off-by: Uncle Stinky <uncle.stinky@ghostchain.io>
2026-02-22 13:25:10 +03:00
63c03ad6ce
extend trait with network existence check
Signed-off-by: Uncle Stinky <uncle.stinky@ghostchain.io>
2026-02-22 13:14:58 +03:00
4e1a3de6de
prepare benchmarks and update default weights
Signed-off-by: Uncle Stinky <uncle.stinky@ghostchain.io>
2026-02-22 11:49:39 +03:00
5dd0c73f7a
move block commitment check to the on_initialize hook
Signed-off-by: Uncle Stinky <uncle.stinky@ghostchain.io>
2026-02-21 17:57:49 +03:00
03262539aa
adapt trait; add extra test; fix benchmarking
Signed-off-by: Uncle Stinky <uncle.stinky@ghostchain.io>
2026-02-21 17:55:26 +03:00
f524b01b03
make function name more obvious
Signed-off-by: Uncle Stinky <uncle.stinky@ghostchain.io>
2026-02-21 17:52:42 +03:00
f99eee2e1a
remove nullification functionality from trait
Signed-off-by: Uncle Stinky <uncle.stinky@ghostchain.io>
2026-02-21 14:17:35 +03:00
d3cc3ac1b3
remove unnecessary storage entry in pallet
Signed-off-by: Uncle Stinky <uncle.stinky@ghostchain.io>
2026-02-21 14:15:51 +03:00
7a7712df0b
replace custom muldiv with multiply_by_rational_with_rounding from substrate
Signed-off-by: Uncle Stinky <uncle.stinky@ghostchain.io>
2026-02-21 12:54:29 +03:00
cce2910cf8
make networks pallet to be indexed storage map; migrations included
Signed-off-by: Uncle Stinky <uncle.stinky@ghostchain.io>
2026-02-20 17:15:53 +03:00
5b5e53e6fd
update traits for the network handler
Signed-off-by: Uncle Stinky <uncle.stinky@ghostchain.io>
2026-02-20 16:09:54 +03:00
2313bc97ec
user agent added to mimic the curl
Signed-off-by: Uncle Stinky <uncle.stinky@ghostchain.io>
2026-02-19 19:23:50 +03:00
35 changed files with 2074 additions and 1226 deletions

10
Cargo.lock generated
View File

@ -1186,7 +1186,7 @@ dependencies = [
[[package]] [[package]]
name = "casper-runtime" name = "casper-runtime"
version = "3.5.37" version = "3.5.41"
dependencies = [ dependencies = [
"casper-runtime-constants", "casper-runtime-constants",
"frame-benchmarking", "frame-benchmarking",
@ -3650,13 +3650,14 @@ dependencies = [
[[package]] [[package]]
name = "ghost-networks" name = "ghost-networks"
version = "0.1.20" version = "0.1.26"
dependencies = [ dependencies = [
"frame-benchmarking", "frame-benchmarking",
"frame-support", "frame-support",
"frame-system", "frame-system",
"ghost-core-primitives", "ghost-core-primitives",
"ghost-traits", "ghost-traits",
"log",
"num-traits", "num-traits",
"pallet-balances", "pallet-balances",
"pallet-staking", "pallet-staking",
@ -3837,7 +3838,7 @@ dependencies = [
[[package]] [[package]]
name = "ghost-slow-clap" name = "ghost-slow-clap"
version = "0.4.14" version = "0.4.28"
dependencies = [ dependencies = [
"frame-benchmarking", "frame-benchmarking",
"frame-support", "frame-support",
@ -3889,10 +3890,11 @@ dependencies = [
[[package]] [[package]]
name = "ghost-traits" name = "ghost-traits"
version = "0.3.26" version = "0.3.32"
dependencies = [ dependencies = [
"frame-support", "frame-support",
"sp-runtime 31.0.1", "sp-runtime 31.0.1",
"sp-std 14.0.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-v1.12.0)",
] ]
[[package]] [[package]]

View File

@ -1,6 +1,6 @@
[package] [package]
name = "ghost-networks" name = "ghost-networks"
version = "0.1.20" version = "0.1.26"
license.workspace = true license.workspace = true
authors.workspace = true authors.workspace = true
edition.workspace = true edition.workspace = true
@ -11,6 +11,7 @@ repository.workspace = true
scale-info = { workspace = true, features = ["derive"] } scale-info = { workspace = true, features = ["derive"] }
codec = { workspace = true, features = ["max-encoded-len"] } codec = { workspace = true, features = ["max-encoded-len"] }
num-traits = { workspace = true } num-traits = { workspace = true }
log = { workspace = true }
frame-benchmarking = { workspace = true, optional = true } frame-benchmarking = { workspace = true, optional = true }
frame-support = { workspace = true } frame-support = { workspace = true }
@ -31,6 +32,7 @@ default = ["std"]
std = [ std = [
"scale-info/std", "scale-info/std",
"codec/std", "codec/std",
"log/std",
"num-traits/std", "num-traits/std",
"frame-support/std", "frame-support/std",
"frame-system/std", "frame-system/std",

View File

@ -85,13 +85,15 @@ benchmarks! {
let (chain_id, network) = prepare_network::<T>(i, j, k); let (chain_id, network) = prepare_network::<T>(i, j, k);
let authority = T::RegisterOrigin::try_successful_origin() let authority = T::RegisterOrigin::try_successful_origin()
.map_err(|_| BenchmarkError::Weightless)?; .map_err(|_| BenchmarkError::Weightless)?;
let prev_network = GhostNetworks::<T>::networks(chain_id.clone()); assert_eq!(GhostNetworks::<T>::networks(chain_id.clone()), None);
assert!(GhostNetworks::<T>::network_indexes().is_empty());
}: _<T::RuntimeOrigin>(authority, chain_id.clone(), network.clone()) }: _<T::RuntimeOrigin>(authority, chain_id.clone(), network.clone())
verify { verify {
assert_last_event::<T>(Event::NetworkRegistered { assert_last_event::<T>(Event::NetworkRegistered {
chain_id: chain_id.clone(), network, chain_id: chain_id.clone(), network: network.clone(),
}.into()); }.into());
assert_ne!(GhostNetworks::<T>::networks(chain_id.clone()), prev_network); assert_eq!(GhostNetworks::<T>::networks(chain_id.clone()), Some(network));
assert_eq!(GhostNetworks::<T>::network_indexes(), vec![chain_id]);
} }
update_network_name { update_network_name {
@ -251,20 +253,23 @@ benchmarks! {
assert_last_event::<T>(Event::NetworkAvgBlockSpeedUpdated { assert_last_event::<T>(Event::NetworkAvgBlockSpeedUpdated {
chain_id: chain_id.clone(), avg_block_speed, chain_id: chain_id.clone(), avg_block_speed,
}.into()); }.into());
assert_ne!(GhostNetworks::<T>::networks(chain_id.clone()), prev_network); assert_ne!(GhostNetworks::<T>::networks(chain_id.clone()), None);
} }
remove_network { remove_network {
let (chain_id, network) = prepare_network::<T>(1, 1, 1); let (chain_id, network) = prepare_network::<T>(1, 1, 1);
let authority = T::RemoveOrigin::try_successful_origin() let authority = T::RemoveOrigin::try_successful_origin()
.map_err(|_| BenchmarkError::Weightless)?; .map_err(|_| BenchmarkError::Weightless)?;
let prev_network = create_network::<T>(chain_id.clone(), network.clone())?; let _ = create_network::<T>(chain_id.clone(), network.clone())?;
assert_eq!(GhostNetworks::<T>::networks(chain_id.clone()), Some(network));
assert_eq!(GhostNetworks::<T>::network_indexes(), vec![chain_id.clone()]);
}: _<T::RuntimeOrigin>(authority, chain_id.clone()) }: _<T::RuntimeOrigin>(authority, chain_id.clone())
verify { verify {
assert_last_event::<T>(Event::NetworkRemoved { assert_last_event::<T>(Event::NetworkRemoved {
chain_id: chain_id.clone(), chain_id: chain_id.clone(),
}.into()); }.into());
assert_ne!(GhostNetworks::<T>::networks(chain_id.clone()), prev_network); assert_eq!(GhostNetworks::<T>::networks(chain_id.clone()), None);
assert!(GhostNetworks::<T>::network_indexes().is_empty());
} }
impl_benchmark_test_suite!(GhostNetworks, crate::mock::ExtBuilder::build(), crate::mock::Test); impl_benchmark_test_suite!(GhostNetworks, crate::mock::ExtBuilder::build(), crate::mock::Test);

View File

@ -12,7 +12,7 @@ use scale_info::TypeInfo;
use sp_runtime::{ use sp_runtime::{
curve::PiecewiseLinear, curve::PiecewiseLinear,
traits::{AtLeast32BitUnsigned, CheckedAdd, CheckedSub, Member}, traits::{AtLeast32BitUnsigned, CheckedAdd, CheckedSub, Member, UniqueSaturatedInto},
DispatchResult, DispatchResult,
}; };
use sp_std::{convert::TryInto, prelude::*}; use sp_std::{convert::TryInto, prelude::*};
@ -21,11 +21,10 @@ pub use ghost_traits::networks::{
NetworkDataBasicHandler, NetworkDataInspectHandler, NetworkDataMutateHandler, NetworkDataBasicHandler, NetworkDataInspectHandler, NetworkDataMutateHandler,
}; };
mod math; pub mod migrations;
mod weights; mod weights;
pub use crate::weights::WeightInfo; pub use crate::weights::WeightInfo;
use math::MulDiv;
pub use module::*; pub use module::*;
#[cfg(any(feature = "runtime-benchmarks", test))] #[cfg(any(feature = "runtime-benchmarks", test))]
@ -35,6 +34,8 @@ mod mock;
#[cfg(all(feature = "std", test))] #[cfg(all(feature = "std", test))]
mod tests; mod tests;
const LOG_TARGET: &str = "runtime::ghost-networks";
pub type BalanceOf<T> = pub type BalanceOf<T> =
<<T as Config>::Currency as Inspect<<T as frame_system::Config>::AccountId>>::Balance; <<T as Config>::Currency as Inspect<<T as frame_system::Config>::AccountId>>::Balance;
@ -96,23 +97,26 @@ where
_era_duration_in_millis: u64, _era_duration_in_millis: u64,
) -> (Balance, Balance) { ) -> (Balance, Balance) {
let reward_curve = RewardCurve::get(); let reward_curve = RewardCurve::get();
let bridged_imbalance = BridgedImbalance::<T>::get(); let bridged_imbalance = BridgedImbalance::<T>::take();
let accumulated_commission = AccumulatedCommission::<T>::get(); let accumulated_commission = AccumulatedCommission::<T>::take();
let accumulated_commission: Balance = accumulated_commission.into(); let accumulated_commission: Balance = accumulated_commission.into();
let adjusted_issuance: Balance = total_issuance let adjusted_issuance: Balance = total_issuance
.saturating_add(bridged_imbalance.bridged_out.into()) .saturating_add(bridged_imbalance.bridged_out.into())
.saturating_sub(bridged_imbalance.bridged_in.into()); .saturating_sub(bridged_imbalance.bridged_in.into());
NullifyNeeded::<T>::set(true);
let estimated_reward = let estimated_reward =
reward_curve.calculate_for_fraction_times_denominator(total_staked, adjusted_issuance); reward_curve.calculate_for_fraction_times_denominator(total_staked, adjusted_issuance);
let payout = MulDiv::<Balance>::calculate(
estimated_reward, let payout: Balance = sp_runtime::helpers_128bit::multiply_by_rational_with_rounding(
accumulated_commission, estimated_reward.unique_saturated_into(),
adjusted_issuance, accumulated_commission.unique_saturated_into(),
); adjusted_issuance.unique_saturated_into(),
sp_runtime::Rounding::NearestPrefUp,
)
.map(|result| result.unique_saturated_into())
.unwrap_or_default();
let rest_payout = accumulated_commission.saturating_sub(payout); let rest_payout = accumulated_commission.saturating_sub(payout);
(payout, rest_payout) (payout, rest_payout)
@ -123,6 +127,8 @@ where
pub mod module { pub mod module {
use super::*; use super::*;
const STORAGE_VERSION: StorageVersion = StorageVersion::new(1);
#[pallet::config] #[pallet::config]
pub trait Config: frame_system::Config { pub trait Config: frame_system::Config {
type RuntimeEvent: From<Event<Self>> + IsType<<Self as frame_system::Config>::RuntimeEvent>; type RuntimeEvent: From<Event<Self>> + IsType<<Self as frame_system::Config>::RuntimeEvent>;
@ -149,6 +155,9 @@ pub mod module {
/// The origin required to remove network. /// The origin required to remove network.
type RemoveOrigin: EnsureOrigin<Self::RuntimeOrigin>; type RemoveOrigin: EnsureOrigin<Self::RuntimeOrigin>;
#[pallet::constant]
type MaxNetworks: Get<u32>;
/// Weight information for extrinsics in this module. /// Weight information for extrinsics in this module.
type WeightInfo: WeightInfo; type WeightInfo: WeightInfo;
} }
@ -163,6 +172,8 @@ pub mod module {
WrongGatekeeperAddress, WrongGatekeeperAddress,
/// Topic name length not 66 or prefix `0x` missed. /// Topic name length not 66 or prefix `0x` missed.
WrongTopicName, WrongTopicName,
/// Could not store networks into bounded vector.
TooManyNetworks,
} }
#[pallet::event] #[pallet::event]
@ -230,10 +241,6 @@ pub mod module {
}, },
} }
#[pallet::storage]
#[pallet::getter(fn nullify_needed)]
pub type NullifyNeeded<T: Config> = StorageValue<_, bool, ValueQuery>;
#[pallet::storage] #[pallet::storage]
#[pallet::getter(fn bridged_imbalance)] #[pallet::getter(fn bridged_imbalance)]
pub type BridgedImbalance<T: Config> = pub type BridgedImbalance<T: Config> =
@ -243,6 +250,11 @@ pub mod module {
#[pallet::getter(fn accumulated_commission)] #[pallet::getter(fn accumulated_commission)]
pub type AccumulatedCommission<T: Config> = StorageValue<_, BalanceOf<T>, ValueQuery>; pub type AccumulatedCommission<T: Config> = StorageValue<_, BalanceOf<T>, ValueQuery>;
#[pallet::storage]
#[pallet::getter(fn network_indexes)]
pub type NetworkIndexes<T: Config> =
StorageValue<_, BoundedVec<T::NetworkId, T::MaxNetworks>, ValueQuery>;
#[pallet::storage] #[pallet::storage]
#[pallet::getter(fn networks)] #[pallet::getter(fn networks)]
pub type Networks<T: Config> = pub type Networks<T: Config> =
@ -282,23 +294,10 @@ pub mod module {
} }
#[pallet::pallet] #[pallet::pallet]
#[pallet::storage_version(STORAGE_VERSION)]
#[pallet::without_storage_info] #[pallet::without_storage_info]
pub struct Pallet<T>(PhantomData<T>); pub struct Pallet<T>(PhantomData<T>);
#[pallet::hooks]
impl<T: Config> Hooks<BlockNumberFor<T>> for Pallet<T> {
fn on_initialize(_: BlockNumberFor<T>) -> Weight {
T::DbWeight::get().reads_writes(1, 1)
}
fn on_finalize(_: BlockNumberFor<T>) {
if Self::nullify_needed() {
Self::nullify_commission();
NullifyNeeded::<T>::put(false);
}
}
}
#[pallet::call] #[pallet::call]
impl<T: Config> Pallet<T> { impl<T: Config> Pallet<T> {
#[pallet::call_index(0)] #[pallet::call_index(0)]
@ -470,12 +469,19 @@ impl<T: Config> Pallet<T> {
Ok(()) Ok(())
})?; })?;
NetworkIndexes::<T>::try_mutate(|ids| -> DispatchResult {
ids.try_push(chain_id)
.map_err(|_| Error::<T>::TooManyNetworks)?;
Ok(())
})?;
Self::deposit_event(Event::<T>::NetworkRegistered { chain_id, network }); Self::deposit_event(Event::<T>::NetworkRegistered { chain_id, network });
Ok(()) Ok(())
} }
/// Remove existent network. /// Remove existent network.
pub fn do_remove_network(chain_id: T::NetworkId) -> DispatchResult { pub fn do_remove_network(chain_id: T::NetworkId) -> DispatchResult {
NetworkIndexes::<T>::mutate(|ids| ids.retain(|id| id != &chain_id));
Networks::<T>::try_mutate(&chain_id, |maybe_network| -> DispatchResult { Networks::<T>::try_mutate(&chain_id, |maybe_network| -> DispatchResult {
ensure!(maybe_network.is_some(), Error::<T>::NetworkDoesNotExist); ensure!(maybe_network.is_some(), Error::<T>::NetworkDoesNotExist);
*maybe_network = None; *maybe_network = None;
@ -723,16 +729,39 @@ impl<T: Config> NetworkDataBasicHandler for Pallet<T> {
} }
impl<T: Config> NetworkDataInspectHandler<NetworkData> for Pallet<T> { impl<T: Config> NetworkDataInspectHandler<NetworkData> for Pallet<T> {
fn count() -> u32 {
NetworkIndexes::<T>::decode_len()
.map(|len| len as u32)
.unwrap_or_default()
}
fn contains_key(n: &Self::NetworkId) -> bool {
Networks::<T>::contains_key(n)
}
fn get(n: &Self::NetworkId) -> Option<NetworkData> { fn get(n: &Self::NetworkId) -> Option<NetworkData> {
Networks::<T>::get(n) Networks::<T>::get(n)
} }
fn network_for_block(block_number: impl Into<usize>) -> Option<(Self::NetworkId, NetworkData)> {
let network_indexes = NetworkIndexes::<T>::get();
block_number
.into()
.checked_rem(network_indexes.len())
.map(|id| {
network_indexes.get(id).copied().and_then(|network_id| {
Self::get(&network_id).map(|network_data| (network_id, network_data))
})
})
.flatten()
}
fn iter() -> PrefixIterator<(Self::NetworkId, NetworkData)> { fn iter() -> PrefixIterator<(Self::NetworkId, NetworkData)> {
Networks::<T>::iter() Networks::<T>::iter()
} }
fn is_nullification_period() -> bool { fn iter_indexes() -> impl Iterator<Item = Self::NetworkId> {
NullifyNeeded::<T>::get() NetworkIndexes::<T>::get().into_iter()
} }
} }
@ -820,18 +849,4 @@ impl<T: Config> NetworkDataMutateHandler<NetworkData, BalanceOf<T>> for Pallet<T
} }
}) })
} }
fn nullify_commission() {
AccumulatedCommission::<T>::set(Default::default());
BridgedImbalance::<T>::set(Default::default());
}
fn trigger_nullification() {
if NullifyNeeded::<T>::get() {
Self::nullify_commission();
NullifyNeeded::<T>::put(false);
} else {
NullifyNeeded::<T>::put(true);
}
}
} }

View File

@ -1,134 +0,0 @@
use crate::AtLeast32BitUnsigned;
pub struct MulDiv<Balance>(core::marker::PhantomData<Balance>);
impl<Balance> MulDiv<Balance>
where
Balance: Copy
+ AtLeast32BitUnsigned
+ num_traits::ops::wrapping::WrappingAdd
+ num_traits::ops::overflowing::OverflowingAdd
+ sp_std::ops::AddAssign
+ sp_std::ops::Not<Output = Balance>
+ sp_std::ops::Shl<Output = Balance>
+ sp_std::ops::Shr<Output = Balance>
+ sp_std::ops::BitAnd<Balance, Output = Balance>,
{
fn zero(&self) -> Balance {
0u32.into()
}
fn one(&self) -> Balance {
1u32.into()
}
fn bit_shift(&self) -> Balance {
let u32_shift: u32 = core::mem::size_of::<Balance>()
.saturating_mul(4)
.try_into()
.unwrap_or_default();
u32_shift.into()
}
fn least_significant_bits(&self, a: Balance) -> Balance {
a & ((self.one() << self.bit_shift()) - self.one())
}
fn most_significant_bits(&self, a: Balance) -> Balance {
a >> self.bit_shift()
}
fn two_complement(&self, a: Balance) -> Balance {
(!a).wrapping_add(&self.one())
}
fn adjusted_ratio(&self, a: Balance) -> Balance {
(self.two_complement(a) / a).wrapping_add(&self.one())
}
fn modulo(&self, a: Balance) -> Balance {
self.two_complement(a) % a
}
fn overflow_resistant_addition(
&self,
a0: Balance,
a1: Balance,
b0: Balance,
b1: Balance,
) -> (Balance, Balance) {
let (r0, overflow) = a0.overflowing_add(&b0);
let overflow: Balance = overflow.then(|| 1u32).unwrap_or_default().into();
let r1 = a1.wrapping_add(&b1).wrapping_add(&overflow);
(r0, r1)
}
fn overflow_resistant_multiplication(&self, a: Balance, b: Balance) -> (Balance, Balance) {
let (a0, a1) = (
self.least_significant_bits(a),
self.most_significant_bits(a),
);
let (b0, b1) = (
self.least_significant_bits(b),
self.most_significant_bits(b),
);
let (x, y) = (a1 * b0, b1 * a0);
let (r0, r1) = (a0 * b0, a1 * b1);
let (r0, r1) = self.overflow_resistant_addition(
r0,
r1,
self.least_significant_bits(x) << self.bit_shift(),
self.most_significant_bits(x),
);
let (r0, r1) = self.overflow_resistant_addition(
r0,
r1,
self.least_significant_bits(y) << self.bit_shift(),
self.most_significant_bits(y),
);
(r0, r1)
}
fn overflow_resistant_division(
&self,
mut a0: Balance,
mut a1: Balance,
b: Balance,
) -> (Balance, Balance) {
if b == self.one() {
return (a0, a1);
}
let zero: Balance = 0u32.into();
let (q, r) = (self.adjusted_ratio(b), self.modulo(b));
let (mut x0, mut x1) = (zero, zero);
while a1 != zero {
let (t0, t1) = self.overflow_resistant_multiplication(a1, q);
let (new_x0, new_x1) = self.overflow_resistant_addition(x0, x1, t0, t1);
x0 = new_x0;
x1 = new_x1;
let (t0, t1) = self.overflow_resistant_multiplication(a1, r);
let (new_a0, new_a1) = self.overflow_resistant_addition(t0, t1, a0, zero);
a0 = new_a0;
a1 = new_a1;
}
self.overflow_resistant_addition(x0, x1, a0 / b, zero)
}
fn mul_div(&self, a: Balance, b: Balance, c: Balance) -> Balance {
let (t0, t1) = self.overflow_resistant_multiplication(a, b);
self.overflow_resistant_division(t0, t1, c).0
}
pub fn calculate(a: Balance, b: Balance, c: Balance) -> Balance {
let inner = MulDiv(core::marker::PhantomData);
if c == inner.zero() {
return c;
}
inner.mul_div(a, b, c)
}
}

View File

@ -0,0 +1,9 @@
pub mod v1;
pub type MigrateV0ToV1<T> = frame_support::migrations::VersionedMigration<
0,
1,
v1::StoreNetworkIdsIntoBoundedVec<T>,
crate::Pallet<T>,
<T as frame_system::Config>::DbWeight,
>;

View File

@ -0,0 +1,59 @@
use frame_support::{
migration::clear_storage_prefix,
traits::{Get, PalletInfoAccess, UncheckedOnRuntimeUpgrade},
weights::Weight,
};
use sp_std::marker::PhantomData;
use crate::{BoundedVec, Config, NetworkIndexes, Networks, Pallet, Vec, LOG_TARGET};
pub struct StoreNetworkIdsIntoBoundedVec<T>(PhantomData<T>);
impl<T: Config> UncheckedOnRuntimeUpgrade for StoreNetworkIdsIntoBoundedVec<T> {
fn on_runtime_upgrade() -> Weight {
let mut weight = T::DbWeight::get().reads(1);
let network_ids: Vec<T::NetworkId> = Networks::<T>::iter_keys().collect();
let networks_count = network_ids.len();
weight = weight.saturating_add(T::DbWeight::get().reads(networks_count as u64));
let clear_results = clear_storage_prefix(
Pallet::<T>::name().as_bytes(),
"NullifyNeeded".as_bytes(),
&[],
Some(1),
None,
);
log::info!(
target: LOG_TARGET,
"⛓️ NullifyNeeded storage succesfully removed: Loops (reads): {}, Unique removed (writes): {}",
clear_results.loops,
clear_results.unique,
);
weight = weight.saturating_add(T::DbWeight::get().reads(clear_results.loops as u64));
weight = weight.saturating_add(T::DbWeight::get().writes(clear_results.unique as u64));
let writes = BoundedVec::<T::NetworkId, T::MaxNetworks>::try_from(network_ids)
.inspect_err(|err| {
log::error!(
target: LOG_TARGET,
"⛓️ Network ids to bounded_vec migration failed: {:?}",
err,
)
})
.ok()
.map(|bounded_networks| {
NetworkIndexes::<T>::put(bounded_networks);
log::info!(
target: LOG_TARGET,
"⛓️ Network ids to bounded_vec migration success: {} networks moved",
networks_count,
);
1u64
})
.unwrap_or_default();
weight.saturating_add(T::DbWeight::get().writes(writes))
}
}

View File

@ -82,6 +82,7 @@ pallet_staking_reward_curve::build! {
parameter_types! { parameter_types! {
pub const RewardCurve: &'static PiecewiseLinear<'static> = &REWARD_CURVE; pub const RewardCurve: &'static PiecewiseLinear<'static> = &REWARD_CURVE;
pub const MaxNetworks: u32 = 3;
} }
ord_parameter_types! { ord_parameter_types! {
@ -98,6 +99,7 @@ impl ghost_networks::Config for Test {
type RegisterOrigin = EnsureSignedBy<RegistererAccount, AccountId>; type RegisterOrigin = EnsureSignedBy<RegistererAccount, AccountId>;
type UpdateOrigin = EnsureSignedBy<UpdaterAccount, AccountId>; type UpdateOrigin = EnsureSignedBy<UpdaterAccount, AccountId>;
type RemoveOrigin = EnsureSignedBy<RemoverAccount, AccountId>; type RemoveOrigin = EnsureSignedBy<RemoverAccount, AccountId>;
type MaxNetworks = MaxNetworks;
type WeightInfo = (); type WeightInfo = ();
} }

View File

@ -1,8 +1,8 @@
use super::*; use super::*;
use frame_support::{assert_err, assert_ok}; use frame_support::{assert_err, assert_ok};
use mock::{ use mock::{
ExtBuilder, GhostNetworks, RandomAccount, RegistererAccount, RemoverAccount, RewardCurve, ExtBuilder, GhostNetworks, MaxNetworks, RandomAccount, RegistererAccount, RemoverAccount,
RuntimeEvent, RuntimeOrigin, System, Test, UpdaterAccount, RewardCurve, RuntimeEvent, RuntimeOrigin, System, Test, UpdaterAccount,
}; };
use pallet_staking::EraPayout; use pallet_staking::EraPayout;
use sp_runtime::DispatchError; use sp_runtime::DispatchError;
@ -36,7 +36,8 @@ fn register_and_check_network(chain_id: u32, network: NetworkData) {
chain_id, chain_id,
network.clone() network.clone()
)); ));
assert_eq!(Networks::<Test>::get(chain_id), Some(network.clone())); assert_eq!(Networks::<Test>::get(chain_id), Some(network));
assert_eq!(NetworkIndexes::<Test>::get(), vec![chain_id]);
} }
#[test] #[test]
@ -44,6 +45,7 @@ fn could_add_network_from_authority() {
ExtBuilder::build().execute_with(|| { ExtBuilder::build().execute_with(|| {
let (chain_id, network) = prepare_network_data(); let (chain_id, network) = prepare_network_data();
assert_eq!(Networks::<Test>::get(chain_id), None); assert_eq!(Networks::<Test>::get(chain_id), None);
assert_eq!(NetworkIndexes::<Test>::get(), vec![]);
assert_ok!(GhostNetworks::register_network( assert_ok!(GhostNetworks::register_network(
RuntimeOrigin::signed(RegistererAccount::get()), RuntimeOrigin::signed(RegistererAccount::get()),
chain_id, chain_id,
@ -56,6 +58,7 @@ fn could_add_network_from_authority() {
}, },
)); ));
assert_eq!(Networks::<Test>::get(chain_id), Some(network)); assert_eq!(Networks::<Test>::get(chain_id), Some(network));
assert_eq!(NetworkIndexes::<Test>::get(), vec![chain_id]);
}); });
} }
@ -64,6 +67,7 @@ fn could_not_add_network_from_random_account() {
ExtBuilder::build().execute_with(|| { ExtBuilder::build().execute_with(|| {
let (chain_id, network) = prepare_network_data(); let (chain_id, network) = prepare_network_data();
assert_eq!(Networks::<Test>::get(chain_id), None); assert_eq!(Networks::<Test>::get(chain_id), None);
assert_eq!(NetworkIndexes::<Test>::get(), vec![]);
assert_err!( assert_err!(
GhostNetworks::register_network( GhostNetworks::register_network(
RuntimeOrigin::signed(RandomAccount::get()), RuntimeOrigin::signed(RandomAccount::get()),
@ -89,6 +93,7 @@ fn could_not_add_network_from_random_account() {
DispatchError::BadOrigin DispatchError::BadOrigin
); );
assert_eq!(Networks::<Test>::get(chain_id), None); assert_eq!(Networks::<Test>::get(chain_id), None);
assert_eq!(NetworkIndexes::<Test>::get(), vec![]);
}); });
} }
@ -1055,6 +1060,7 @@ fn could_remove_network_from_authority_account() {
chain_id, chain_id,
)); ));
assert_eq!(Networks::<Test>::get(chain_id), None); assert_eq!(Networks::<Test>::get(chain_id), None);
assert_eq!(NetworkIndexes::<Test>::get(), vec![]);
}); });
} }
@ -1079,6 +1085,7 @@ fn could_not_remove_network_from_random_account() {
DispatchError::BadOrigin DispatchError::BadOrigin
); );
assert_eq!(Networks::<Test>::get(chain_id), Some(network)); assert_eq!(Networks::<Test>::get(chain_id), Some(network));
assert_eq!(NetworkIndexes::<Test>::get(), vec![chain_id]);
}); });
} }
@ -1092,6 +1099,7 @@ fn could_not_remove_non_existent_network() {
crate::Error::<Test>::NetworkDoesNotExist crate::Error::<Test>::NetworkDoesNotExist
); );
assert_eq!(Networks::<Test>::get(chain_id), None); assert_eq!(Networks::<Test>::get(chain_id), None);
assert_eq!(NetworkIndexes::<Test>::get(), vec![]);
}); });
} }
@ -1270,7 +1278,7 @@ fn bridged_amount_overflow_and_underflow_emits_error() {
} }
#[test] #[test]
fn accumulated_commission_could_be_nullified() { fn accumulated_commission_nullified_after_era_payout() {
ExtBuilder::build().execute_with(|| { ExtBuilder::build().execute_with(|| {
let commission_first: u128 = 420; let commission_first: u128 = 420;
let commission_second: u128 = 69; let commission_second: u128 = 69;
@ -1284,12 +1292,20 @@ fn accumulated_commission_could_be_nullified() {
GhostNetworks::accumulate_commission(&commission_second,), GhostNetworks::accumulate_commission(&commission_second,),
commission_first + commission_second commission_first + commission_second
); );
assert_eq!( assert_eq!(
AccumulatedCommission::<Test>::get(), AccumulatedCommission::<Test>::get(),
commission_first + commission_second commission_first + commission_second
); );
GhostNetworks::nullify_commission(); assert_eq!(
BridgedInflationCurve::<RewardCurve, Test>::era_payout(1, 1, 1),
(0, commission_first + commission_second)
);
assert_eq!(AccumulatedCommission::<Test>::get(), 0); assert_eq!(AccumulatedCommission::<Test>::get(), 0);
assert_eq!(
BridgedInflationCurve::<RewardCurve, Test>::era_payout(1, 1, 1),
(0, 0)
);
}); });
} }
@ -1377,7 +1393,6 @@ fn bridged_inlation_reward_works() {
assert_ok!(GhostNetworks::accumulate_commission(&commission)); assert_ok!(GhostNetworks::accumulate_commission(&commission));
assert_ok!(GhostNetworks::accumulate_incoming_imbalance(&amount)); assert_ok!(GhostNetworks::accumulate_incoming_imbalance(&amount));
assert_eq!( assert_eq!(
BridgedInflationCurve::<RewardCurve, Test>::era_payout( BridgedInflationCurve::<RewardCurve, Test>::era_payout(
total_staked_ideal * 1_000, total_staked_ideal * 1_000,
@ -1386,6 +1401,9 @@ fn bridged_inlation_reward_works() {
), ),
(commission, 0) (commission, 0)
); );
assert_ok!(GhostNetworks::accumulate_commission(&commission));
assert_ok!(GhostNetworks::accumulate_incoming_imbalance(&amount));
assert_eq!( assert_eq!(
BridgedInflationCurve::<RewardCurve, Test>::era_payout( BridgedInflationCurve::<RewardCurve, Test>::era_payout(
total_staked_ideal * 1_000_000_000_000, total_staked_ideal * 1_000_000_000_000,
@ -1394,6 +1412,9 @@ fn bridged_inlation_reward_works() {
), ),
(commission, 0) (commission, 0)
); );
assert_ok!(GhostNetworks::accumulate_commission(&commission));
assert_ok!(GhostNetworks::accumulate_incoming_imbalance(&amount));
assert_eq!( assert_eq!(
BridgedInflationCurve::<RewardCurve, Test>::era_payout( BridgedInflationCurve::<RewardCurve, Test>::era_payout(
total_staked_ideal * 1_000_000_000_000_000_000_000_000, total_staked_ideal * 1_000_000_000_000_000_000_000_000,
@ -1403,6 +1424,8 @@ fn bridged_inlation_reward_works() {
(commission, 0) (commission, 0)
); );
assert_ok!(GhostNetworks::accumulate_commission(&commission));
assert_ok!(GhostNetworks::accumulate_incoming_imbalance(&amount));
assert_eq!( assert_eq!(
BridgedInflationCurve::<RewardCurve, Test>::era_payout( BridgedInflationCurve::<RewardCurve, Test>::era_payout(
total_staked_not_ideal * 1_000, total_staked_not_ideal * 1_000,
@ -1411,6 +1434,9 @@ fn bridged_inlation_reward_works() {
), ),
(13177472000, 192528000) (13177472000, 192528000)
); );
assert_ok!(GhostNetworks::accumulate_commission(&commission));
assert_ok!(GhostNetworks::accumulate_incoming_imbalance(&amount));
assert_eq!(13177472000 + 192528000, commission); assert_eq!(13177472000 + 192528000, commission);
assert_eq!( assert_eq!(
BridgedInflationCurve::<RewardCurve, Test>::era_payout( BridgedInflationCurve::<RewardCurve, Test>::era_payout(
@ -1420,6 +1446,9 @@ fn bridged_inlation_reward_works() {
), ),
(13177568884, 192431116) (13177568884, 192431116)
); );
assert_ok!(GhostNetworks::accumulate_commission(&commission));
assert_ok!(GhostNetworks::accumulate_incoming_imbalance(&amount));
assert_eq!(13177568884 + 192431116, commission); assert_eq!(13177568884 + 192431116, commission);
assert_eq!( assert_eq!(
BridgedInflationCurve::<RewardCurve, Test>::era_payout( BridgedInflationCurve::<RewardCurve, Test>::era_payout(
@ -1429,8 +1458,10 @@ fn bridged_inlation_reward_works() {
), ),
(13177568884, 192431116) (13177568884, 192431116)
); );
assert_eq!(13177568884 + 192431116, commission);
assert_ok!(GhostNetworks::accumulate_commission(&commission));
assert_ok!(GhostNetworks::accumulate_incoming_imbalance(&amount));
assert_eq!(13177568884 + 192431116, commission);
assert_eq!( assert_eq!(
BridgedInflationCurve::<RewardCurve, Test>::era_payout( BridgedInflationCurve::<RewardCurve, Test>::era_payout(
1, 1,
@ -1439,6 +1470,9 @@ fn bridged_inlation_reward_works() {
), ),
(92386700, 13277613300) (92386700, 13277613300)
); );
assert_ok!(GhostNetworks::accumulate_commission(&commission));
assert_ok!(GhostNetworks::accumulate_incoming_imbalance(&amount));
assert_eq!(92386700 + 13277613300, commission); assert_eq!(92386700 + 13277613300, commission);
assert_eq!( assert_eq!(
BridgedInflationCurve::<RewardCurve, Test>::era_payout( BridgedInflationCurve::<RewardCurve, Test>::era_payout(
@ -1448,6 +1482,9 @@ fn bridged_inlation_reward_works() {
), ),
(92253000, 13277747000) (92253000, 13277747000)
); );
assert_ok!(GhostNetworks::accumulate_commission(&commission));
assert_ok!(GhostNetworks::accumulate_incoming_imbalance(&amount));
assert_eq!(92253000 + 13277747000, commission); assert_eq!(92253000 + 13277747000, commission);
assert_eq!( assert_eq!(
BridgedInflationCurve::<RewardCurve, Test>::era_payout( BridgedInflationCurve::<RewardCurve, Test>::era_payout(
@ -1457,10 +1494,8 @@ fn bridged_inlation_reward_works() {
), ),
(92253000, 13277747000) (92253000, 13277747000)
); );
assert_eq!(92253000 + 13277747000, commission); assert_eq!(92253000 + 13277747000, commission);
GhostNetworks::nullify_commission();
assert_eq!( assert_eq!(
BridgedInflationCurve::<RewardCurve, Test>::era_payout( BridgedInflationCurve::<RewardCurve, Test>::era_payout(
total_staked_ideal * 1_000, total_staked_ideal * 1_000,
@ -1539,7 +1574,7 @@ fn bridged_inlation_reward_works() {
} }
#[test] #[test]
fn bridged_inflation_era_payout_triggers_need_of_nullification() { fn bridged_inflation_era_payout_clears_storage() {
ExtBuilder::build().execute_with(|| { ExtBuilder::build().execute_with(|| {
let amount_full: u128 = 1337 * 1_000_000_000; let amount_full: u128 = 1337 * 1_000_000_000;
let commission: u128 = amount_full / 100; // 1% commission let commission: u128 = amount_full / 100; // 1% commission
@ -1550,7 +1585,13 @@ fn bridged_inflation_era_payout_triggers_need_of_nullification() {
assert_ok!(GhostNetworks::accumulate_commission(&commission)); assert_ok!(GhostNetworks::accumulate_commission(&commission));
assert_ok!(GhostNetworks::accumulate_incoming_imbalance(&amount)); assert_ok!(GhostNetworks::accumulate_incoming_imbalance(&amount));
assert_eq!(NullifyNeeded::<Test>::get(), false);
let bridged_adjustment = BridgeAdjustment {
bridged_in: amount,
bridged_out: 0,
};
assert_eq!(BridgedImbalance::<Test>::get(), bridged_adjustment);
assert_eq!(AccumulatedCommission::<Test>::get(), commission);
assert_eq!( assert_eq!(
BridgedInflationCurve::<RewardCurve, Test>::era_payout( BridgedInflationCurve::<RewardCurve, Test>::era_payout(
total_staked_ideal * 1_000, total_staked_ideal * 1_000,
@ -1559,37 +1600,8 @@ fn bridged_inflation_era_payout_triggers_need_of_nullification() {
), ),
(commission, 0) (commission, 0)
); );
assert_eq!(NullifyNeeded::<Test>::get(), true); assert_eq!(BridgedImbalance::<Test>::get(), Default::default());
GhostNetworks::on_finalize(69); assert_eq!(AccumulatedCommission::<Test>::get(), Default::default());
assert_eq!(NullifyNeeded::<Test>::get(), false);
});
}
#[test]
fn trigger_nullification_works_as_expected() {
ExtBuilder::build().execute_with(|| {
let commission: u128 = 69;
let imbalance = BridgeAdjustment {
bridged_in: 1337u128,
bridged_out: 420u128,
};
assert_eq!(AccumulatedCommission::<Test>::get(), 0);
assert_eq!(BridgedImbalance::<Test>::get(), BridgeAdjustment::default());
AccumulatedCommission::<Test>::set(commission);
BridgedImbalance::<Test>::set(imbalance.clone());
assert_eq!(AccumulatedCommission::<Test>::get(), commission);
assert_eq!(BridgedImbalance::<Test>::get(), imbalance);
assert_eq!(NullifyNeeded::<Test>::get(), false);
GhostNetworks::trigger_nullification();
assert_eq!(NullifyNeeded::<Test>::get(), true);
GhostNetworks::trigger_nullification();
assert_eq!(NullifyNeeded::<Test>::get(), false);
assert_eq!(AccumulatedCommission::<Test>::get(), 0);
assert_eq!(BridgedImbalance::<Test>::get(), BridgeAdjustment::default());
}); });
} }
@ -1665,123 +1677,6 @@ fn check_substrate_guarantees_not_to_overflow_u32() {
}); });
} }
#[test]
fn check_muldiv_guarantees_not_to_overflow_for_u128() {
ExtBuilder::build().execute_with(|| {
let mut a: u128 = 2;
let mut b: u128 = 3;
let mut c: u128 = 6;
let mut result: u128 = 1;
loop {
a = match a.checked_mul(1_000) {
Some(value) => value,
None => break,
};
b = match b.checked_mul(1_000) {
Some(value) => value,
None => break,
};
c = match c.checked_mul(1_000) {
Some(value) => value,
None => break,
};
result = match result.checked_mul(1_000) {
Some(value) => value,
None => break,
};
assert_eq!(MulDiv::<u128>::calculate(a, b, c), result);
}
assert_eq!(
MulDiv::<u128>::calculate(u128::MAX, u128::MAX, u128::MAX),
u128::MAX
);
assert_eq!(MulDiv::<u128>::calculate(u128::MAX, 0, 0), 0);
assert_eq!(MulDiv::<u128>::calculate(0, u128::MAX, 0), 0);
assert_eq!(MulDiv::<u128>::calculate(0, 0, u128::MAX), 0);
});
}
#[test]
fn check_muldiv_guarantees_not_to_overflow_for_u64() {
ExtBuilder::build().execute_with(|| {
let mut a: u64 = 2;
let mut b: u64 = 3;
let mut c: u64 = 6;
let mut result: u64 = 1;
loop {
a = match a.checked_mul(1_000) {
Some(value) => value,
None => break,
};
b = match b.checked_mul(1_000) {
Some(value) => value,
None => break,
};
c = match c.checked_mul(1_000) {
Some(value) => value,
None => break,
};
result = match result.checked_mul(1_000) {
Some(value) => value,
None => break,
};
assert_eq!(MulDiv::<u64>::calculate(a, b, c), result);
}
assert_eq!(
MulDiv::<u64>::calculate(u64::MAX, u64::MAX, u64::MAX),
u64::MAX
);
assert_eq!(MulDiv::<u64>::calculate(u64::MAX, 0, 0), 0);
assert_eq!(MulDiv::<u64>::calculate(0, u64::MAX, 0), 0);
assert_eq!(MulDiv::<u64>::calculate(0, 0, u64::MAX), 0);
});
}
#[test]
fn check_muldiv_guarantees_not_to_overflow_for_u32() {
ExtBuilder::build().execute_with(|| {
let mut a: u32 = 2;
let mut b: u32 = 3;
let mut c: u32 = 6;
let mut result: u32 = 1;
loop {
a = match a.checked_mul(1_000) {
Some(value) => value,
None => break,
};
b = match b.checked_mul(1_000) {
Some(value) => value,
None => break,
};
c = match c.checked_mul(1_000) {
Some(value) => value,
None => break,
};
result = match result.checked_mul(1_000) {
Some(value) => value,
None => break,
};
assert_eq!(MulDiv::<u32>::calculate(a, b, c), result);
}
assert_eq!(
MulDiv::<u32>::calculate(u32::MAX, u32::MAX, u32::MAX),
u32::MAX
);
assert_eq!(MulDiv::<u32>::calculate(u32::MAX, 0, 0), 0);
assert_eq!(MulDiv::<u32>::calculate(0, u32::MAX, 0), 0);
assert_eq!(MulDiv::<u32>::calculate(0, 0, u32::MAX), 0);
});
}
#[test] #[test]
fn check_bridged_inflation_curve_for_overflow() { fn check_bridged_inflation_curve_for_overflow() {
ExtBuilder::build().execute_with(|| { ExtBuilder::build().execute_with(|| {
@ -1789,7 +1684,6 @@ fn check_bridged_inflation_curve_for_overflow() {
let commission: u128 = amount_full / 100; // 1% commission let commission: u128 = amount_full / 100; // 1% commission
let amount: u128 = amount_full - commission; let amount: u128 = amount_full - commission;
let tollerance: u128 = commission / 100; // 1% tollerance
let precomputed_payout: u128 = 13177568884; let precomputed_payout: u128 = 13177568884;
let precomputed_rest: u128 = 192431116; let precomputed_rest: u128 = 192431116;
assert_eq!(precomputed_payout + precomputed_rest, commission); assert_eq!(precomputed_payout + precomputed_rest, commission);
@ -1798,10 +1692,10 @@ fn check_bridged_inflation_curve_for_overflow() {
let mut total_staked_not_ideal: u128 = 68_000; let mut total_staked_not_ideal: u128 = 68_000;
let mut total_issuance: u128 = 100_000; let mut total_issuance: u128 = 100_000;
loop {
assert_ok!(GhostNetworks::accumulate_commission(&commission)); assert_ok!(GhostNetworks::accumulate_commission(&commission));
assert_ok!(GhostNetworks::accumulate_incoming_imbalance(&amount)); assert_ok!(GhostNetworks::accumulate_incoming_imbalance(&amount));
loop {
total_staked_ideal = match total_staked_ideal.checked_mul(1_000) { total_staked_ideal = match total_staked_ideal.checked_mul(1_000) {
Some(value) => value, Some(value) => value,
None => break, None => break,
@ -1822,27 +1716,6 @@ fn check_bridged_inflation_curve_for_overflow() {
), ),
(commission, 0) (commission, 0)
); );
let (payout, rest) = BridgedInflationCurve::<RewardCurve, Test>::era_payout(
total_staked_not_ideal,
total_issuance + amount,
0,
);
let payout_deviation = if precomputed_payout > payout {
precomputed_payout - payout
} else {
payout - precomputed_payout
};
let rest_deviation = if precomputed_rest > rest {
precomputed_rest - rest
} else {
rest - precomputed_rest
};
assert!(payout_deviation < tollerance);
assert!(rest_deviation < tollerance);
} }
}); });
} }
@ -1898,3 +1771,106 @@ fn check_bridged_inflation_curve_for_big_commissions() {
} }
}); });
} }
#[test]
fn migration_from_v0_to_v1_works() {
ExtBuilder::build().execute_with(|| {
let (chain_id, network) = prepare_network_data();
let other_chain_id = chain_id.saturating_add(1);
let removed_pallet_name = <Pallet<Test> as PalletInfoAccess>::name();
let removed_storage = "NullifyNeeded";
let key = [
sp_io::hashing::twox_128(removed_pallet_name.as_bytes()).to_vec(),
sp_io::hashing::twox_128(removed_storage.as_bytes()).to_vec(),
]
.concat();
frame_support::storage::unhashed::put_raw(&key, &true.encode());
assert_eq!(Networks::<Test>::get(chain_id), None);
assert_ok!(GhostNetworks::register_network(
RuntimeOrigin::signed(RegistererAccount::get()),
chain_id,
network.clone(),
));
assert_ok!(GhostNetworks::register_network(
RuntimeOrigin::signed(RegistererAccount::get()),
other_chain_id,
network.clone(),
));
NetworkIndexes::<Test>::kill();
assert!(frame_support::storage::unhashed::exists(&key));
assert_eq!(Networks::<Test>::get(chain_id), Some(network.clone()));
assert_eq!(Networks::<Test>::get(other_chain_id), Some(network));
assert_eq!(NetworkIndexes::<Test>::get(), vec![]);
type Migrate = crate::migrations::MigrateV0ToV1<Test>;
<Migrate as frame_support::traits::OnRuntimeUpgrade>::on_runtime_upgrade();
assert!(!frame_support::storage::unhashed::exists(&key));
assert_eq!(
NetworkIndexes::<Test>::get(),
vec![chain_id, other_chain_id]
);
});
}
#[test]
fn error_on_max_networks_overflow() {
ExtBuilder::build().execute_with(|| {
let (chain_id, network) = prepare_network_data();
let max_networks = MaxNetworks::get();
for index in 0..max_networks {
let other_chain_id = chain_id.saturating_add(index);
assert_ok!(GhostNetworks::register_network(
RuntimeOrigin::signed(RegistererAccount::get()),
other_chain_id,
network.clone(),
));
}
assert_err!(
GhostNetworks::register_network(
RuntimeOrigin::signed(RegistererAccount::get()),
chain_id.saturating_add(max_networks),
network.clone(),
),
crate::Error::<Test>::TooManyNetworks,
);
});
}
#[test]
fn migration_from_v0_to_v1_does_not_run_twice() {
ExtBuilder::build().execute_with(|| {
StorageVersion::new(1).put::<GhostNetworks>();
let (chain_id, network) = prepare_network_data();
let other_chain_id = chain_id.saturating_add(1);
assert_eq!(Networks::<Test>::get(chain_id), None);
assert_ok!(GhostNetworks::register_network(
RuntimeOrigin::signed(RegistererAccount::get()),
chain_id,
network.clone(),
));
assert_ok!(GhostNetworks::register_network(
RuntimeOrigin::signed(RegistererAccount::get()),
other_chain_id,
network.clone(),
));
NetworkIndexes::<Test>::kill();
assert_eq!(Networks::<Test>::get(chain_id), Some(network.clone()));
assert_eq!(Networks::<Test>::get(other_chain_id), Some(network));
assert_eq!(NetworkIndexes::<Test>::get(), vec![]);
type Migrate = crate::migrations::MigrateV0ToV1<Test>;
<Migrate as frame_support::traits::OnRuntimeUpgrade>::on_runtime_upgrade();
assert_eq!(NetworkIndexes::<Test>::get(), vec![]);
});
}

View File

@ -16,7 +16,7 @@
//! Autogenerated weights for `ghost_networks` //! Autogenerated weights for `ghost_networks`
//! //!
//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0
//! DATE: 2025-06-19, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! DATE: 2026-02-26, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]`
//! WORST CASE MAP SIZE: `1000000` //! WORST CASE MAP SIZE: `1000000`
//! HOSTNAME: `ghostown`, CPU: `Intel(R) Core(TM) i3-2310M CPU @ 2.10GHz` //! HOSTNAME: `ghostown`, CPU: `Intel(R) Core(TM) i3-2310M CPU @ 2.10GHz`
//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("casper-dev")`, DB CACHE: 1024 //! WASM-EXECUTION: `Compiled`, CHAIN: `Some("casper-dev")`, DB CACHE: 1024
@ -30,7 +30,6 @@
// --repeat=20 // --repeat=20
// --pallet=ghost_networks // --pallet=ghost_networks
// --extrinsic=* // --extrinsic=*
// --wasm-execution=compiled
// --heap-pages=4096 // --heap-pages=4096
// --header=./file_header.txt // --header=./file_header.txt
// --output=./runtime/casper/src/weights/ghost_networks.rs // --output=./runtime/casper/src/weights/ghost_networks.rs
@ -67,33 +66,35 @@ pub trait WeightInfo {
impl WeightInfo for () { impl WeightInfo for () {
/// Storage: `GhostNetworks::Networks` (r:1 w:1) /// Storage: `GhostNetworks::Networks` (r:1 w:1)
/// Proof: `GhostNetworks::Networks` (`max_values`: None, `max_size`: None, mode: `Measured`) /// Proof: `GhostNetworks::Networks` (`max_values`: None, `max_size`: None, mode: `Measured`)
/// Storage: `GhostNetworks::NetworkIndexes` (r:1 w:1)
/// Proof: `GhostNetworks::NetworkIndexes` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
/// The range of component `i` is `[1, 20]`. /// The range of component `i` is `[1, 20]`.
/// The range of component `j` is `[1, 150]`. /// The range of component `j` is `[1, 150]`.
/// The range of component `k` is `[1, 20]`. /// The range of component `k` is `[1, 20]`.
fn register_network(_i: u32, _j: u32, k: u32, ) -> Weight { fn register_network(_i: u32, j: u32, k: u32, ) -> Weight {
// Proof Size summary in bytes: // Proof Size summary in bytes:
// Measured: `109` // Measured: `109`
// Estimated: `3574` // Estimated: `3574`
// Minimum execution time: 46_023_000 picoseconds. // Minimum execution time: 48_419_000 picoseconds.
Weight::from_parts(97_871_287, 0) Weight::from_parts(35_655_823, 0)
.saturating_add(Weight::from_parts(0, 3574)) .saturating_add(Weight::from_parts(0, 3574))
// Standard Error: 94_524 // Standard Error: 1_212
.saturating_add(Weight::from_parts(940_486, 0).saturating_mul(k.into())) .saturating_add(Weight::from_parts(96_762, 0).saturating_mul(j.into()))
.saturating_add(RocksDbWeight::get().reads(1)) // Standard Error: 9_235
.saturating_add(RocksDbWeight::get().writes(1)) .saturating_add(Weight::from_parts(1_460_410, 0).saturating_mul(k.into()))
.saturating_add(RocksDbWeight::get().reads(2))
.saturating_add(RocksDbWeight::get().writes(2))
} }
/// Storage: `GhostNetworks::Networks` (r:1 w:1) /// Storage: `GhostNetworks::Networks` (r:1 w:1)
/// Proof: `GhostNetworks::Networks` (`max_values`: None, `max_size`: None, mode: `Measured`) /// Proof: `GhostNetworks::Networks` (`max_values`: None, `max_size`: None, mode: `Measured`)
/// The range of component `n` is `[1, 20]`. /// The range of component `n` is `[1, 20]`.
fn update_network_name(n: u32, ) -> Weight { fn update_network_name(_n: u32, ) -> Weight {
// Proof Size summary in bytes: // Proof Size summary in bytes:
// Measured: `302` // Measured: `339`
// Estimated: `3767` // Estimated: `3804`
// Minimum execution time: 49_906_000 picoseconds. // Minimum execution time: 48_422_000 picoseconds.
Weight::from_parts(55_537_587, 0) Weight::from_parts(49_987_541, 0)
.saturating_add(Weight::from_parts(0, 3767)) .saturating_add(Weight::from_parts(0, 3804))
// Standard Error: 87_704
.saturating_add(Weight::from_parts(92_366, 0).saturating_mul(n.into()))
.saturating_add(RocksDbWeight::get().reads(1)) .saturating_add(RocksDbWeight::get().reads(1))
.saturating_add(RocksDbWeight::get().writes(1)) .saturating_add(RocksDbWeight::get().writes(1))
} }
@ -102,13 +103,13 @@ impl WeightInfo for () {
/// The range of component `n` is `[1, 150]`. /// The range of component `n` is `[1, 150]`.
fn update_network_endpoint(n: u32, ) -> Weight { fn update_network_endpoint(n: u32, ) -> Weight {
// Proof Size summary in bytes: // Proof Size summary in bytes:
// Measured: `302` // Measured: `339`
// Estimated: `3767` // Estimated: `3804`
// Minimum execution time: 50_556_000 picoseconds. // Minimum execution time: 48_651_000 picoseconds.
Weight::from_parts(57_726_674, 0) Weight::from_parts(50_776_912, 0)
.saturating_add(Weight::from_parts(0, 3767)) .saturating_add(Weight::from_parts(0, 3804))
// Standard Error: 12_261 // Standard Error: 1_062
.saturating_add(Weight::from_parts(274, 0).saturating_mul(n.into())) .saturating_add(Weight::from_parts(838, 0).saturating_mul(n.into()))
.saturating_add(RocksDbWeight::get().reads(1)) .saturating_add(RocksDbWeight::get().reads(1))
.saturating_add(RocksDbWeight::get().writes(1)) .saturating_add(RocksDbWeight::get().writes(1))
} }
@ -116,11 +117,11 @@ impl WeightInfo for () {
/// Proof: `GhostNetworks::Networks` (`max_values`: None, `max_size`: None, mode: `Measured`) /// Proof: `GhostNetworks::Networks` (`max_values`: None, `max_size`: None, mode: `Measured`)
fn update_network_finality_delay() -> Weight { fn update_network_finality_delay() -> Weight {
// Proof Size summary in bytes: // Proof Size summary in bytes:
// Measured: `302` // Measured: `339`
// Estimated: `3767` // Estimated: `3804`
// Minimum execution time: 49_406_000 picoseconds. // Minimum execution time: 48_080_000 picoseconds.
Weight::from_parts(51_256_000, 0) Weight::from_parts(51_781_000, 0)
.saturating_add(Weight::from_parts(0, 3767)) .saturating_add(Weight::from_parts(0, 3804))
.saturating_add(RocksDbWeight::get().reads(1)) .saturating_add(RocksDbWeight::get().reads(1))
.saturating_add(RocksDbWeight::get().writes(1)) .saturating_add(RocksDbWeight::get().writes(1))
} }
@ -128,11 +129,11 @@ impl WeightInfo for () {
/// Proof: `GhostNetworks::Networks` (`max_values`: None, `max_size`: None, mode: `Measured`) /// Proof: `GhostNetworks::Networks` (`max_values`: None, `max_size`: None, mode: `Measured`)
fn update_network_rate_limit_delay() -> Weight { fn update_network_rate_limit_delay() -> Weight {
// Proof Size summary in bytes: // Proof Size summary in bytes:
// Measured: `302` // Measured: `339`
// Estimated: `3767` // Estimated: `3804`
// Minimum execution time: 49_572_000 picoseconds. // Minimum execution time: 47_950_000 picoseconds.
Weight::from_parts(52_584_000, 0) Weight::from_parts(48_925_000, 0)
.saturating_add(Weight::from_parts(0, 3767)) .saturating_add(Weight::from_parts(0, 3804))
.saturating_add(RocksDbWeight::get().reads(1)) .saturating_add(RocksDbWeight::get().reads(1))
.saturating_add(RocksDbWeight::get().writes(1)) .saturating_add(RocksDbWeight::get().writes(1))
} }
@ -140,11 +141,11 @@ impl WeightInfo for () {
/// Proof: `GhostNetworks::Networks` (`max_values`: None, `max_size`: None, mode: `Measured`) /// Proof: `GhostNetworks::Networks` (`max_values`: None, `max_size`: None, mode: `Measured`)
fn update_network_block_distance() -> Weight { fn update_network_block_distance() -> Weight {
// Proof Size summary in bytes: // Proof Size summary in bytes:
// Measured: `302` // Measured: `339`
// Estimated: `3767` // Estimated: `3804`
// Minimum execution time: 48_880_000 picoseconds. // Minimum execution time: 48_324_000 picoseconds.
Weight::from_parts(50_596_000, 0) Weight::from_parts(50_801_000, 0)
.saturating_add(Weight::from_parts(0, 3767)) .saturating_add(Weight::from_parts(0, 3804))
.saturating_add(RocksDbWeight::get().reads(1)) .saturating_add(RocksDbWeight::get().reads(1))
.saturating_add(RocksDbWeight::get().writes(1)) .saturating_add(RocksDbWeight::get().writes(1))
} }
@ -152,11 +153,11 @@ impl WeightInfo for () {
/// Proof: `GhostNetworks::Networks` (`max_values`: None, `max_size`: None, mode: `Measured`) /// Proof: `GhostNetworks::Networks` (`max_values`: None, `max_size`: None, mode: `Measured`)
fn update_network_type() -> Weight { fn update_network_type() -> Weight {
// Proof Size summary in bytes: // Proof Size summary in bytes:
// Measured: `302` // Measured: `339`
// Estimated: `3767` // Estimated: `3804`
// Minimum execution time: 48_282_000 picoseconds. // Minimum execution time: 46_962_000 picoseconds.
Weight::from_parts(49_137_000, 0) Weight::from_parts(47_729_000, 0)
.saturating_add(Weight::from_parts(0, 3767)) .saturating_add(Weight::from_parts(0, 3804))
.saturating_add(RocksDbWeight::get().reads(1)) .saturating_add(RocksDbWeight::get().reads(1))
.saturating_add(RocksDbWeight::get().writes(1)) .saturating_add(RocksDbWeight::get().writes(1))
} }
@ -164,11 +165,11 @@ impl WeightInfo for () {
/// Proof: `GhostNetworks::Networks` (`max_values`: None, `max_size`: None, mode: `Measured`) /// Proof: `GhostNetworks::Networks` (`max_values`: None, `max_size`: None, mode: `Measured`)
fn update_network_gatekeeper() -> Weight { fn update_network_gatekeeper() -> Weight {
// Proof Size summary in bytes: // Proof Size summary in bytes:
// Measured: `302` // Measured: `339`
// Estimated: `3767` // Estimated: `3804`
// Minimum execution time: 50_853_000 picoseconds. // Minimum execution time: 48_728_000 picoseconds.
Weight::from_parts(51_982_000, 0) Weight::from_parts(53_054_000, 0)
.saturating_add(Weight::from_parts(0, 3767)) .saturating_add(Weight::from_parts(0, 3804))
.saturating_add(RocksDbWeight::get().reads(1)) .saturating_add(RocksDbWeight::get().reads(1))
.saturating_add(RocksDbWeight::get().writes(1)) .saturating_add(RocksDbWeight::get().writes(1))
} }
@ -176,11 +177,11 @@ impl WeightInfo for () {
/// Proof: `GhostNetworks::Networks` (`max_values`: None, `max_size`: None, mode: `Measured`) /// Proof: `GhostNetworks::Networks` (`max_values`: None, `max_size`: None, mode: `Measured`)
fn update_network_topic_name() -> Weight { fn update_network_topic_name() -> Weight {
// Proof Size summary in bytes: // Proof Size summary in bytes:
// Measured: `302` // Measured: `339`
// Estimated: `3767` // Estimated: `3804`
// Minimum execution time: 50_343_000 picoseconds. // Minimum execution time: 48_632_000 picoseconds.
Weight::from_parts(52_380_000, 0) Weight::from_parts(49_954_000, 0)
.saturating_add(Weight::from_parts(0, 3767)) .saturating_add(Weight::from_parts(0, 3804))
.saturating_add(RocksDbWeight::get().reads(1)) .saturating_add(RocksDbWeight::get().reads(1))
.saturating_add(RocksDbWeight::get().writes(1)) .saturating_add(RocksDbWeight::get().writes(1))
} }
@ -188,11 +189,11 @@ impl WeightInfo for () {
/// Proof: `GhostNetworks::Networks` (`max_values`: None, `max_size`: None, mode: `Measured`) /// Proof: `GhostNetworks::Networks` (`max_values`: None, `max_size`: None, mode: `Measured`)
fn update_incoming_network_fee() -> Weight { fn update_incoming_network_fee() -> Weight {
// Proof Size summary in bytes: // Proof Size summary in bytes:
// Measured: `302` // Measured: `339`
// Estimated: `3767` // Estimated: `3804`
// Minimum execution time: 49_393_000 picoseconds. // Minimum execution time: 47_660_000 picoseconds.
Weight::from_parts(80_966_000, 0) Weight::from_parts(53_763_000, 0)
.saturating_add(Weight::from_parts(0, 3767)) .saturating_add(Weight::from_parts(0, 3804))
.saturating_add(RocksDbWeight::get().reads(1)) .saturating_add(RocksDbWeight::get().reads(1))
.saturating_add(RocksDbWeight::get().writes(1)) .saturating_add(RocksDbWeight::get().writes(1))
} }
@ -200,11 +201,11 @@ impl WeightInfo for () {
/// Proof: `GhostNetworks::Networks` (`max_values`: None, `max_size`: None, mode: `Measured`) /// Proof: `GhostNetworks::Networks` (`max_values`: None, `max_size`: None, mode: `Measured`)
fn update_outgoing_network_fee() -> Weight { fn update_outgoing_network_fee() -> Weight {
// Proof Size summary in bytes: // Proof Size summary in bytes:
// Measured: `302` // Measured: `339`
// Estimated: `3767` // Estimated: `3804`
// Minimum execution time: 49_579_000 picoseconds. // Minimum execution time: 48_164_000 picoseconds.
Weight::from_parts(51_126_000, 0) Weight::from_parts(48_953_000, 0)
.saturating_add(Weight::from_parts(0, 3767)) .saturating_add(Weight::from_parts(0, 3804))
.saturating_add(RocksDbWeight::get().reads(1)) .saturating_add(RocksDbWeight::get().reads(1))
.saturating_add(RocksDbWeight::get().writes(1)) .saturating_add(RocksDbWeight::get().writes(1))
} }
@ -212,24 +213,26 @@ impl WeightInfo for () {
/// Proof: `GhostNetworks::Networks` (`max_values`: None, `max_size`: None, mode: `Measured`) /// Proof: `GhostNetworks::Networks` (`max_values`: None, `max_size`: None, mode: `Measured`)
fn update_avg_block_speed() -> Weight { fn update_avg_block_speed() -> Weight {
// Proof Size summary in bytes: // Proof Size summary in bytes:
// Measured: `302` // Measured: `339`
// Estimated: `3767` // Estimated: `3804`
// Minimum execution time: 49_579_000 picoseconds. // Minimum execution time: 47_789_000 picoseconds.
Weight::from_parts(51_126_000, 0) Weight::from_parts(52_131_000, 0)
.saturating_add(Weight::from_parts(0, 3767)) .saturating_add(Weight::from_parts(0, 3804))
.saturating_add(RocksDbWeight::get().reads(1)) .saturating_add(RocksDbWeight::get().reads(1))
.saturating_add(RocksDbWeight::get().writes(1)) .saturating_add(RocksDbWeight::get().writes(1))
} }
/// Storage: `GhostNetworks::NetworkIndexes` (r:1 w:1)
/// Proof: `GhostNetworks::NetworkIndexes` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
/// Storage: `GhostNetworks::Networks` (r:1 w:1) /// Storage: `GhostNetworks::Networks` (r:1 w:1)
/// Proof: `GhostNetworks::Networks` (`max_values`: None, `max_size`: None, mode: `Measured`) /// Proof: `GhostNetworks::Networks` (`max_values`: None, `max_size`: None, mode: `Measured`)
fn remove_network() -> Weight { fn remove_network() -> Weight {
// Proof Size summary in bytes: // Proof Size summary in bytes:
// Measured: `302` // Measured: `339`
// Estimated: `3767` // Estimated: `3804`
// Minimum execution time: 44_634_000 picoseconds. // Minimum execution time: 49_720_000 picoseconds.
Weight::from_parts(45_815_000, 0) Weight::from_parts(50_526_000, 0)
.saturating_add(Weight::from_parts(0, 3767)) .saturating_add(Weight::from_parts(0, 3804))
.saturating_add(RocksDbWeight::get().reads(1)) .saturating_add(RocksDbWeight::get().reads(2))
.saturating_add(RocksDbWeight::get().writes(1)) .saturating_add(RocksDbWeight::get().writes(2))
} }
} }

View File

@ -1,6 +1,6 @@
[package] [package]
name = "ghost-slow-clap" name = "ghost-slow-clap"
version = "0.4.14" version = "0.4.28"
description = "Applause protocol for the EVM bridge" description = "Applause protocol for the EVM bridge"
license.workspace = true license.workspace = true
authors.workspace = true authors.workspace = true

View File

@ -90,11 +90,7 @@ benchmarks! {
session_index, session_index,
authority_index, authority_index,
network_id, network_id,
commitment: CommitmentDetails {
last_stored_block: 69, last_stored_block: 69,
commits: 420,
last_updated: 1337,
}
}; };
let authority_id = authorities let authority_id = authorities
@ -102,16 +98,47 @@ benchmarks! {
.expect("first authority should exist"); .expect("first authority should exist");
let signature = authority_id.sign(&block_commitment.encode()) let signature = authority_id.sign(&block_commitment.encode())
.ok_or("couldn't make signature")?; .ok_or("couldn't make signature")?;
}: _(RawOrigin::None, block_commitment, signature) }: _(RawOrigin::None, block_commitment, signature)
verify { verify {
let current_block_number = <Pallet<T> as BlockNumberProvider>::current_block_number();
let stored_commitment = BlockCommitments::<T>::get(&network_id) let stored_commitment = BlockCommitments::<T>::get(&network_id)
.get(&authority_index) .get(&authority_index)
.cloned() .cloned()
.unwrap_or_default(); .unwrap_or_default();
assert_eq!(stored_commitment.last_stored_block, 69); assert_eq!(stored_commitment.last_stored_block, 69);
assert_eq!(stored_commitment.commits, 1); assert_eq!(stored_commitment.commits, 1);
assert_eq!(stored_commitment.last_updated, 1337); assert_eq!(stored_commitment.last_updated, current_block_number);
}
try_offend_validators {
let n in 1 .. T::MaxAuthorities::get();
let d in 0 .. T::MaxAuthorities::get();
let session_index = T::ValidatorSet::session_index();
let mut validators_vec = Vec::new();
for i in 0..T::MaxAuthorities::get() {
let v = account("validator", i, 0);
validators_vec.push(v);
}
let validators = WeakBoundedVec::<ValidatorId<T>, T::MaxAuthorities>::try_from(validators_vec)
.expect("weak bounded vec should be constructed; qed");
let offence_type = OffenceType::CommitmentOffence;
let disabled_bitmap = BitMap::new(T::MaxAuthorities::get());
let mut offence_bitmap = BitMap::new(T::MaxAuthorities::get());
for i in 0..d {
offence_bitmap.set(i);
}
}: {
let _ = Pallet::<T>::try_offend_validators(
&session_index,
&validators,
offence_bitmap,
disabled_bitmap,
offence_type
);
} }
impl_benchmark_test_suite!( impl_benchmark_test_suite!(

View File

@ -8,7 +8,7 @@ where
Ok(Some(s.as_bytes().to_vec())) Ok(Some(s.as_bytes().to_vec()))
} }
pub fn de_string_to_u64<'de, D>(de: D) -> Result<Option<u64>, D::Error> pub fn de_string_to_block_number<'de, D>(de: D) -> Result<Option<u64>, D::Error>
where where
D: Deserializer<'de>, D: Deserializer<'de>,
{ {
@ -17,7 +17,7 @@ where
Ok(u64::from_str_radix(s, 16).ok()) Ok(u64::from_str_radix(s, 16).ok())
} }
pub fn de_string_to_u64_pure<'de, D>(de: D) -> Result<u64, D::Error> pub fn de_string_to_block_number_pure<'de, D>(de: D) -> Result<u64, D::Error>
where where
D: Deserializer<'de>, D: Deserializer<'de>,
{ {

View File

@ -1,14 +1,14 @@
use sp_runtime::SaturatedConversion; use sp_runtime::{traits::UniqueSaturatedInto, SaturatedConversion, Saturating};
use sp_staking::SessionIndex; use sp_staking::SessionIndex;
use crate::{ use crate::{
deserialisations::{ deserialisations::{
de_string_to_bytes, de_string_to_h256, de_string_to_u64, de_string_to_u64_pure, de_string_to_block_number, de_string_to_block_number_pure, de_string_to_bytes,
de_string_to_vec_of_bytes, de_string_to_h256, de_string_to_vec_of_bytes,
}, },
AuthIndex, BalanceOf, BlockCommitment, BlockCommitments, Call, Clap, CommitmentDetails, Config, AuthIndex, BalanceOf, BlockCommitment, BlockCommitments, BlockNumberFor, Call, Clap, Config,
Decode, Deserialize, Encode, NetworkIdOf, RuntimeAppPublic, RuntimeDebug, SubmitTransaction, Decode, Deserialize, Encode, ExternalBlockNumber, NetworkIdOf, RuntimeAppPublic, RuntimeDebug,
Vec, COMMITMENT_DELAY_MILLIS, H256, LOG_TARGET, SubmitTransaction, Vec, BLOCK_COMMITMENT_DELAY, H256, LOG_TARGET,
}; };
const NUMBER_OF_TOPICS: usize = 3; const NUMBER_OF_TOPICS: usize = 3;
@ -28,8 +28,8 @@ pub struct EvmResponse {
#[derive(RuntimeDebug, Clone, PartialEq, Deserialize, Encode, Decode)] #[derive(RuntimeDebug, Clone, PartialEq, Deserialize, Encode, Decode)]
#[serde(untagged)] #[serde(untagged)]
pub enum EvmResponseType { pub enum EvmResponseType {
#[serde(deserialize_with = "de_string_to_u64_pure")] #[serde(deserialize_with = "de_string_to_block_number_pure")]
BlockNumber(u64), BlockNumber(ExternalBlockNumber),
TransactionLogs(Vec<Log>), TransactionLogs(Vec<Log>),
} }
@ -38,34 +38,14 @@ pub enum EvmResponseType {
pub struct Log { pub struct Log {
#[serde(default, deserialize_with = "de_string_to_h256")] #[serde(default, deserialize_with = "de_string_to_h256")]
pub transaction_hash: Option<H256>, pub transaction_hash: Option<H256>,
#[serde(default, deserialize_with = "de_string_to_u64")] #[serde(default, deserialize_with = "de_string_to_block_number")]
pub block_number: Option<u64>, pub block_number: Option<ExternalBlockNumber>,
#[serde(default, deserialize_with = "de_string_to_vec_of_bytes")] #[serde(default, deserialize_with = "de_string_to_vec_of_bytes")]
pub topics: Vec<Vec<u8>>, pub topics: Vec<Vec<u8>>,
pub removed: bool, pub removed: bool,
} }
impl EvmResponseType { impl EvmResponseType {
fn prepare_block_commitment<T: Config>(
&self,
from_block: u64,
authority_index: AuthIndex,
session_index: SessionIndex,
network_id: NetworkIdOf<T>,
) -> BlockCommitment<NetworkIdOf<T>> {
let last_updated = sp_io::offchain::timestamp().unix_millis();
BlockCommitment {
session_index,
authority_index,
network_id,
commitment: CommitmentDetails {
last_stored_block: from_block,
last_updated,
commits: 420,
},
}
}
fn prepare_clap<T: Config>( fn prepare_clap<T: Config>(
&self, &self,
authority_index: AuthIndex, authority_index: AuthIndex,
@ -164,30 +144,30 @@ impl EvmResponseType {
fn sign_and_submit_block_commitment<T: Config>( fn sign_and_submit_block_commitment<T: Config>(
&self, &self,
from_block: u64, block_now: BlockNumberFor<T>,
from_block: ExternalBlockNumber,
authority_index: AuthIndex, authority_index: AuthIndex,
authority_key: T::AuthorityId, authority_key: T::AuthorityId,
session_index: SessionIndex, session_index: SessionIndex,
network_id: NetworkIdOf<T>, network_id: NetworkIdOf<T>,
) { ) {
let block_commitment = self.prepare_block_commitment::<T>( let block_commitment = BlockCommitment {
from_block,
authority_index,
session_index, session_index,
authority_index,
network_id, network_id,
); last_stored_block: from_block,
};
let stored_last_updated = BlockCommitments::<T>::get(&network_id) let stored_last_updated = BlockCommitments::<T>::get(&network_id)
.get(&authority_index) .get(&authority_index)
.map(|details| details.last_updated) .map(|details| {
details
.last_updated
.saturating_add(BLOCK_COMMITMENT_DELAY.unique_saturated_into())
})
.unwrap_or_default(); .unwrap_or_default();
let current_last_updated = block_commitment if block_now < stored_last_updated {
.commitment
.last_updated
.saturating_sub(COMMITMENT_DELAY_MILLIS);
if current_last_updated < stored_last_updated {
return; return;
} }
@ -229,7 +209,8 @@ impl EvmResponseType {
pub fn sign_and_submit<T: Config>( pub fn sign_and_submit<T: Config>(
&self, &self,
from_block: u64, block_now: BlockNumberFor<T>,
from_block: ExternalBlockNumber,
authority_index: AuthIndex, authority_index: AuthIndex,
authority_key: T::AuthorityId, authority_key: T::AuthorityId,
session_index: SessionIndex, session_index: SessionIndex,
@ -243,6 +224,7 @@ impl EvmResponseType {
network_id, network_id,
), ),
EvmResponseType::BlockNumber(_) => self.sign_and_submit_block_commitment::<T>( EvmResponseType::BlockNumber(_) => self.sign_and_submit_block_commitment::<T>(
block_now,
from_block, from_block,
authority_index, authority_index,
authority_key, authority_key,

View File

@ -28,7 +28,7 @@ use sp_runtime::{
storage::StorageValueRef, storage::StorageValueRef,
storage_lock::{StorageLock, Time}, storage_lock::{StorageLock, Time},
}, },
traits::{BlockNumberProvider, Convert, Saturating}, traits::{AtLeast32BitUnsigned, BlockNumberProvider, Convert, Saturating, UniqueSaturatedInto},
Perbill, RuntimeAppPublic, RuntimeDebug, Perbill, RuntimeAppPublic, RuntimeDebug,
}; };
use sp_staking::{ use sp_staking::{
@ -43,6 +43,7 @@ use ghost_networks::{
}; };
use ghost_traits::exposure::ExposureListener; use ghost_traits::exposure::ExposureListener;
pub mod migrations;
pub mod weights; pub mod weights;
pub use crate::weights::WeightInfo; pub use crate::weights::WeightInfo;
mod benchmarking; mod benchmarking;
@ -78,10 +79,12 @@ const MIN_LOCK_GUARD_PERIOD: u64 = 15_000;
const FETCH_TIMEOUT_PERIOD: u64 = 3_000; const FETCH_TIMEOUT_PERIOD: u64 = 3_000;
const LOCK_BLOCK_EXPIRATION: u64 = 20; const LOCK_BLOCK_EXPIRATION: u64 = 20;
const COMMITMENT_DELAY_MILLIS: u64 = 600_000;
const ONE_HOUR_MILLIS: u64 = 3_600_000; const ONE_HOUR_MILLIS: u64 = 3_600_000;
const BLOCK_CHECK_CYCLES: u64 = 8;
const BLOCK_COMMITMENT_DELAY: u64 = 100;
pub type AuthIndex = u32; pub type AuthIndex = u32;
pub type ExternalBlockNumber = u64;
#[derive( #[derive(
RuntimeDebug, RuntimeDebug,
@ -97,10 +100,10 @@ pub type AuthIndex = u32;
TypeInfo, TypeInfo,
MaxEncodedLen, MaxEncodedLen,
)] )]
pub struct CommitmentDetails { pub struct CommitmentDetails<BlockNumberFor> {
pub last_stored_block: u64, pub last_stored_block: ExternalBlockNumber,
pub last_updated: u64, pub last_updated: BlockNumberFor,
pub commits: u64, pub commits: u8,
} }
#[derive( #[derive(
@ -110,7 +113,7 @@ pub struct BlockCommitment<NetworkId> {
pub session_index: SessionIndex, pub session_index: SessionIndex,
pub authority_index: AuthIndex, pub authority_index: AuthIndex,
pub network_id: NetworkId, pub network_id: NetworkId,
pub commitment: CommitmentDetails, pub last_stored_block: ExternalBlockNumber,
} }
#[derive( #[derive(
@ -120,7 +123,7 @@ pub struct Clap<AccountId, NetworkId, Balance> {
pub session_index: SessionIndex, pub session_index: SessionIndex,
pub authority_index: AuthIndex, pub authority_index: AuthIndex,
pub transaction_hash: H256, pub transaction_hash: H256,
pub block_number: u64, pub block_number: ExternalBlockNumber,
pub removed: bool, pub removed: bool,
pub network_id: NetworkId, pub network_id: NetworkId,
pub receiver: AccountId, pub receiver: AccountId,
@ -132,12 +135,16 @@ pub struct ApplauseDetail<NetworkId, Balance> {
pub network_id: NetworkId, pub network_id: NetworkId,
pub authorities: BitMap, pub authorities: BitMap,
pub clapped_amount: Balance, pub clapped_amount: Balance,
pub block_number: u64, pub block_number: ExternalBlockNumber,
pub finalized: bool, pub finalized: bool,
} }
impl<NetworkId, Balance: Default> ApplauseDetail<NetworkId, Balance> { impl<NetworkId, Balance: Default> ApplauseDetail<NetworkId, Balance> {
pub fn new(network_id: NetworkId, block_number: u64, max_authorities: usize) -> Self { pub fn new(
network_id: NetworkId,
block_number: ExternalBlockNumber,
max_authorities: usize,
) -> Self {
ApplauseDetail { ApplauseDetail {
network_id, network_id,
block_number, block_number,
@ -153,7 +160,7 @@ pub struct PreparedApplause<AccountId, NetworkId, Balance> {
pub network_id: NetworkId, pub network_id: NetworkId,
pub receiver: AccountId, pub receiver: AccountId,
pub amount: Balance, pub amount: Balance,
pub block_number: u64, pub block_number: ExternalBlockNumber,
} }
#[cfg_attr(test, derive(PartialEq))] #[cfg_attr(test, derive(PartialEq))]
@ -168,7 +175,11 @@ enum OffchainErr<NetworkId> {
DifferentEvmResponseTypes, DifferentEvmResponseTypes,
MissingBlockNumber(u32, u32), MissingBlockNumber(u32, u32),
ContradictoryTransactionLogs(u32, u32), ContradictoryTransactionLogs(u32, u32),
ContradictoryBlockMedian(u64, u64, u64), ContradictoryBlockMedian(
ExternalBlockNumber,
ExternalBlockNumber,
ExternalBlockNumber,
),
UnparsableRequestBody(Vec<u8>), UnparsableRequestBody(Vec<u8>),
NoEndpointAvailable(NetworkId), NoEndpointAvailable(NetworkId),
StorageRetrievalError(NetworkId), StorageRetrievalError(NetworkId),
@ -268,7 +279,7 @@ type OffchainResult<T, A> = Result<A, OffchainErr<NetworkIdOf<T>>>;
pub mod pallet { pub mod pallet {
use super::*; use super::*;
const STORAGE_VERSION: StorageVersion = StorageVersion::new(2); const STORAGE_VERSION: StorageVersion = StorageVersion::new(3);
#[pallet::pallet] #[pallet::pallet]
#[pallet::storage_version(STORAGE_VERSION)] #[pallet::storage_version(STORAGE_VERSION)]
@ -314,6 +325,9 @@ pub mod pallet {
#[pallet::constant] #[pallet::constant]
type MinAuthoritiesNumber: Get<u32>; type MinAuthoritiesNumber: Get<u32>;
#[pallet::constant]
type EpochDuration: Get<u64>;
type WeightInfo: WeightInfo; type WeightInfo: WeightInfo;
} }
@ -341,12 +355,16 @@ pub mod pallet {
network_id: NetworkIdOf<T>, network_id: NetworkIdOf<T>,
receiver: T::AccountId, receiver: T::AccountId,
received_amount: BalanceOf<T>, received_amount: BalanceOf<T>,
block_number: u64, block_number: ExternalBlockNumber,
}, },
BlockCommited { BlockCommited {
authority_id: AuthIndex, authority_id: AuthIndex,
network_id: NetworkIdOf<T>, network_id: NetworkIdOf<T>,
}, },
BlockCommitmentsCheck {
network_id: NetworkIdOf<T>,
block_number: BlockNumberFor<T>,
},
} }
#[pallet::error] #[pallet::error]
@ -361,6 +379,7 @@ pub mod pallet {
CouldNotIncreaseGatekeeperAmount, CouldNotIncreaseGatekeeperAmount,
NonExistentAuthorityIndex, NonExistentAuthorityIndex,
TimeWentBackwards, TimeWentBackwards,
InnerTimeWentBackwards,
DisabledAuthority, DisabledAuthority,
ExecutedBlockIsHigher, ExecutedBlockIsHigher,
CommitInWrongSession, CommitInWrongSession,
@ -373,7 +392,7 @@ pub mod pallet {
#[pallet::storage] #[pallet::storage]
#[pallet::getter(fn latest_executed_block)] #[pallet::getter(fn latest_executed_block)]
pub(super) type LatestExecutedBlock<T: Config> = pub(super) type LatestExecutedBlock<T: Config> =
StorageMap<_, Twox64Concat, NetworkIdOf<T>, u64, ValueQuery>; StorageMap<_, Twox64Concat, NetworkIdOf<T>, ExternalBlockNumber, ValueQuery>;
#[pallet::storage] #[pallet::storage]
#[pallet::getter(fn block_commitments)] #[pallet::getter(fn block_commitments)]
@ -381,7 +400,7 @@ pub mod pallet {
_, _,
Twox64Concat, Twox64Concat,
NetworkIdOf<T>, NetworkIdOf<T>,
BTreeMap<AuthIndex, CommitmentDetails>, BTreeMap<AuthIndex, CommitmentDetails<BlockNumberFor<T>>>,
ValueQuery, ValueQuery,
>; >;
@ -470,6 +489,98 @@ pub mod pallet {
#[pallet::hooks] #[pallet::hooks]
impl<T: Config> Hooks<BlockNumberFor<T>> for Pallet<T> { impl<T: Config> Hooks<BlockNumberFor<T>> for Pallet<T> {
fn on_initialize(current_block: BlockNumberFor<T>) -> Weight {
let mut weight = T::DbWeight::get().reads(1);
let networks_count = T::NetworkDataHandler::count();
let current_block_number: ExternalBlockNumber = current_block.unique_saturated_into();
let check_block_interval = T::EpochDuration::get().saturating_div(BLOCK_CHECK_CYCLES);
if check_block_interval == 0 {
return weight;
}
let cycle_offset = current_block_number % check_block_interval;
let block_in_epoch = current_block_number % T::EpochDuration::get();
if cycle_offset >= networks_count.into() || block_in_epoch < check_block_interval {
return weight;
}
let converted_block: usize = current_block_number.unique_saturated_into();
if let Some((network_id, network_data)) =
T::NetworkDataHandler::network_for_block(converted_block)
{
weight.saturating_accrue(T::DbWeight::get().reads_writes(3, 1));
let session_index = T::ValidatorSet::session_index();
let block_commitments = BlockCommitments::<T>::get(&network_id);
let validators = Validators::<T>::get(&session_index);
let validators_len = validators.len() as u32;
if validators_len == 0 {
return weight;
}
let disabled_bitmap = DisabledAuthorityIndexes::<T>::get(&session_index)
.unwrap_or(BitMap::new(validators.len() as u32));
let max_external_block_deviation = ONE_HOUR_MILLIS
.saturating_mul(6)
.saturating_div(network_data.avg_block_speed);
let max_internal_block_deviation = check_block_interval.unique_saturated_into();
let mut stored_blocks: Vec<(AuthIndex, ExternalBlockNumber)> = Vec::new();
let mut block_updates: Vec<(AuthIndex, BlockNumberFor<T>)> = Vec::new();
for authority_index in 0..validators_len {
let data = block_commitments
.get(&authority_index)
.copied()
.unwrap_or_default();
stored_blocks.push((authority_index, data.last_stored_block));
block_updates.push((authority_index, data.last_updated));
}
let stored_blocks_offence_bitmap = Self::capture_deviation_in_commitments(
&disabled_bitmap,
&mut stored_blocks,
validators_len,
max_external_block_deviation,
);
let block_updates_offence_bitmap = Self::capture_deviation_in_commitments(
&disabled_bitmap,
&mut block_updates,
validators_len,
max_internal_block_deviation,
);
let offence_bitmap =
stored_blocks_offence_bitmap.bitor(block_updates_offence_bitmap);
let offence_type = OffenceType::CommitmentOffence;
let extra_weight = Self::try_offend_validators(
&session_index,
&validators,
offence_bitmap,
disabled_bitmap,
offence_type,
);
Self::deposit_event(Event::<T>::BlockCommitmentsCheck {
block_number: current_block,
network_id,
});
weight.saturating_accrue(extra_weight);
}
weight
}
fn offchain_worker(now: BlockNumberFor<T>) { fn offchain_worker(now: BlockNumberFor<T>) {
match Self::start_slow_clapping(now) { match Self::start_slow_clapping(now) {
Ok(_) => { Ok(_) => {
@ -505,7 +616,7 @@ pub mod pallet {
ValidTransaction::with_tag_prefix("SlowClap") ValidTransaction::with_tag_prefix("SlowClap")
.priority(T::UnsignedPriority::get()) .priority(T::UnsignedPriority::get())
.and_provides(block_commitment.commitment.encode()) .and_provides(block_commitment.encode())
.longevity(LOCK_BLOCK_EXPIRATION) .longevity(LOCK_BLOCK_EXPIRATION)
.propagate(true) .propagate(true)
.build() .build()
@ -559,12 +670,13 @@ impl<T: Config> Pallet<T> {
let mut clap_args_str = clap.receiver.encode(); let mut clap_args_str = clap.receiver.encode();
clap_args_str.extend(&clap.amount.encode()); clap_args_str.extend(&clap.amount.encode());
clap_args_str.extend(&clap.block_number.encode()); clap_args_str.extend(&clap.block_number.encode());
clap_args_str.extend(&clap.transaction_hash.encode());
clap_args_str.extend(&clap.network_id.encode()); clap_args_str.extend(&clap.network_id.encode());
H256::from_slice(&sp_io::hashing::keccak_256(&clap_args_str)[..]) H256::from_slice(&sp_io::hashing::keccak_256(&clap_args_str)[..])
} }
fn u64_to_hexadecimal_bytes(value: u64) -> Vec<u8> { fn block_number_to_hexadecimal_bytes(value: ExternalBlockNumber) -> Vec<u8> {
let mut hex_str = Vec::new(); let mut hex_str = Vec::new();
hex_str.push(b'0'); hex_str.push(b'0');
hex_str.push(b'x'); hex_str.push(b'x');
@ -595,7 +707,7 @@ impl<T: Config> Pallet<T> {
let clap_unique_hash = Self::generate_unique_hash(&clap); let clap_unique_hash = Self::generate_unique_hash(&clap);
let session_index = let session_index =
if ApplauseDetails::<T>::get(&prev_session_index, &clap_unique_hash).is_some() { if ApplauseDetails::<T>::contains_key(&prev_session_index, &clap_unique_hash) {
prev_session_index prev_session_index
} else { } else {
clap.session_index clap.session_index
@ -607,44 +719,35 @@ impl<T: Config> Pallet<T> {
fn try_slow_clap(clap: &Clap<T::AccountId, NetworkIdOf<T>, BalanceOf<T>>) -> DispatchResult { fn try_slow_clap(clap: &Clap<T::AccountId, NetworkIdOf<T>, BalanceOf<T>>) -> DispatchResult {
let network_id = clap.network_id; let network_id = clap.network_id;
ensure!( ensure!(
T::NetworkDataHandler::get(&network_id).is_some(), T::NetworkDataHandler::contains_key(&network_id),
Error::<T>::UnregistedNetwork Error::<T>::UnregistedNetwork
); );
ensure!(
LatestExecutedBlock::<T>::get(&network_id) <= clap.block_number,
Error::<T>::ExecutedBlockIsHigher,
);
let (session_index, clap_unique_hash) = Self::mended_session_index(&clap); let (session_index, clap_unique_hash) = Self::mended_session_index(&clap);
let authorities = Authorities::<T>::get(&session_index); let authorities = Authorities::<T>::get(&session_index);
let authorities_length = authorities.len(); let authorities_length = authorities.len();
let is_disabled = DisabledAuthorityIndexes::<T>::get(&session_index) let not_disabled = DisabledAuthorityIndexes::<T>::get(&session_index)
.map(|bitmap| bitmap.exists(&clap.authority_index)) .map(|bitmap| !bitmap.exists(&clap.authority_index))
.unwrap_or(true); .unwrap_or_default();
ensure!(!is_disabled, Error::<T>::DisabledAuthority); ensure!(not_disabled, Error::<T>::DisabledAuthority);
let applause_threshold = Perbill::from_parts(T::ApplauseThreshold::get()); let applause_threshold = Perbill::from_parts(T::ApplauseThreshold::get());
let threshold_amount = applause_threshold.mul_floor(TotalExposure::<T>::get()); let threshold_amount = applause_threshold.mul_floor(TotalExposure::<T>::get());
let maybe_account_id = let account_id = T::ExposureListener::get_account_by_index(clap.authority_index as usize)
T::ExposureListener::get_account_by_index(clap.authority_index as usize); .ok_or(Error::<T>::NonExistentAuthorityIndex)?;
ensure!(
maybe_account_id.is_some(),
Error::<T>::NonExistentAuthorityIndex
);
let account_id = maybe_account_id.unwrap();
let new_clapped_amount = T::ExposureListener::get_validator_exposure(&account_id); let new_clapped_amount = T::ExposureListener::get_validator_exposure(&account_id);
let mut applause_details = let mut applause_details =
match ApplauseDetails::<T>::take(&session_index, &clap_unique_hash) { ApplauseDetails::<T>::try_get(&session_index, &clap_unique_hash).unwrap_or(
Some(applause_details) => applause_details, ApplauseDetail::new(network_id, clap.block_number, authorities_length),
None => {
ensure!(
LatestExecutedBlock::<T>::get(&network_id) <= clap.block_number,
Error::<T>::ExecutedBlockIsHigher,
); );
ApplauseDetail::new(network_id, clap.block_number, authorities_length)
}
};
let total_clapped = if clap.removed { let total_clapped = if clap.removed {
ensure!( ensure!(
@ -683,9 +786,9 @@ impl<T: Config> Pallet<T> {
.gt(&(authorities_length as u32 / 2)); .gt(&(authorities_length as u32 / 2));
if total_clapped > threshold_amount && is_enough && !applause_details.finalized { if total_clapped > threshold_amount && is_enough && !applause_details.finalized {
applause_details.finalized = true; match Self::try_applause(&clap) {
if let Err(e) = Self::try_applause(&clap) { Ok(_) => applause_details.finalized = true,
sp_runtime::print(e); Err(e) => sp_runtime::print(e),
} }
} }
@ -695,10 +798,6 @@ impl<T: Config> Pallet<T> {
} }
fn try_applause(clap: &Clap<T::AccountId, NetworkIdOf<T>, BalanceOf<T>>) -> DispatchResult { fn try_applause(clap: &Clap<T::AccountId, NetworkIdOf<T>, BalanceOf<T>>) -> DispatchResult {
if T::NetworkDataHandler::is_nullification_period() {
return Ok(());
}
let commission = T::NetworkDataHandler::get(&clap.network_id) let commission = T::NetworkDataHandler::get(&clap.network_id)
.map(|network_data| Perbill::from_parts(network_data.incoming_fee)) .map(|network_data| Perbill::from_parts(network_data.incoming_fee))
.unwrap_or_default() .unwrap_or_default()
@ -728,10 +827,12 @@ impl<T: Config> Pallet<T> {
fn try_commit_block(new_commitment: &BlockCommitment<NetworkIdOf<T>>) -> DispatchResult { fn try_commit_block(new_commitment: &BlockCommitment<NetworkIdOf<T>>) -> DispatchResult {
let authority_index = new_commitment.authority_index; let authority_index = new_commitment.authority_index;
let network_id = new_commitment.network_id; let network_id = new_commitment.network_id;
let session_index = T::ValidatorSet::session_index(); let session_index = T::ValidatorSet::session_index();
let latest_executed_block = LatestExecutedBlock::<T>::get(&network_id);
ensure!( ensure!(
T::NetworkDataHandler::get(&network_id).is_some(), T::NetworkDataHandler::contains_key(&network_id),
Error::<T>::UnregistedNetwork Error::<T>::UnregistedNetwork
); );
@ -740,88 +841,54 @@ impl<T: Config> Pallet<T> {
Error::<T>::CommitInWrongSession, Error::<T>::CommitInWrongSession,
); );
let block_commitments = BlockCommitments::<T>::try_mutate( BlockCommitments::<T>::try_mutate(&network_id, |current_commitments| -> DispatchResult {
&network_id, let current_block_number = Self::current_block_number();
|current_commitments| -> Result<BTreeMap<AuthIndex, CommitmentDetails>, DispatchError> {
let mut new_commitment_details = new_commitment.commitment;
let (current_commits, current_last_updated) = current_commitments let (current_commits, current_last_updated) = current_commitments
.get(&authority_index) .get(&authority_index)
.map(|details| { .map(|details| {
( (
details.commits.saturating_add(1), details.commits.saturating_add(1),
details.last_updated.saturating_add(COMMITMENT_DELAY_MILLIS), details
.last_updated
.saturating_add(BLOCK_COMMITMENT_DELAY.unique_saturated_into()),
) )
}) })
.unwrap_or((1, 0)); .unwrap_or((1, Default::default()));
ensure!( ensure!(
new_commitment_details.last_updated > current_last_updated, current_block_number >= current_last_updated,
Error::<T>::TimeWentBackwards Error::<T>::TimeWentBackwards,
); );
new_commitment_details.commits = current_commits; ensure!(
new_commitment.last_stored_block > latest_executed_block,
Error::<T>::InnerTimeWentBackwards,
);
let new_commitment_details = CommitmentDetails {
last_stored_block: new_commitment.last_stored_block,
last_updated: Self::current_block_number(),
commits: current_commits,
};
current_commitments.insert(authority_index, new_commitment_details); current_commitments.insert(authority_index, new_commitment_details);
Ok(current_commitments.clone()) Ok(())
}, })?;
)?;
let current_commits = block_commitments
.get(&authority_index)
.map(|details| details.commits)
.unwrap_or(1);
Self::deposit_event(Event::<T>::BlockCommited { Self::deposit_event(Event::<T>::BlockCommited {
network_id, network_id,
authority_id: authority_index, authority_id: authority_index,
}); });
let validators = Validators::<T>::get(&session_index);
let disabled_bitmap = DisabledAuthorityIndexes::<T>::get(&session_index)
.unwrap_or(BitMap::new(validators.len() as u32));
let max_block_deviation = T::NetworkDataHandler::get(&network_id)
.map(|network| {
ONE_HOUR_MILLIS
.saturating_mul(6)
.saturating_div(network.avg_block_speed)
})
.unwrap_or_default();
if current_commits % 3 == 0 && validators.len() > 0 {
let offence_bitmap = Self::capture_deviation_in_commitments_and_remove(
&disabled_bitmap,
&block_commitments,
&validators,
max_block_deviation,
);
let offence_type = OffenceType::CommitmentOffence;
Self::try_offend_validators(
&session_index,
&validators,
offence_bitmap,
disabled_bitmap,
offence_type,
);
}
Ok(()) Ok(())
} }
fn start_slow_clapping(block_number: BlockNumberFor<T>) -> OffchainResult<T, ()> { fn start_slow_clapping(block_number: BlockNumberFor<T>) -> OffchainResult<T, ()> {
let converted_block: usize = block_number.unique_saturated_into();
let session_index = T::ValidatorSet::session_index(); let session_index = T::ValidatorSet::session_index();
let networks = T::NetworkDataHandler::iter().collect::<Vec<_>>(); let network_in_use = T::NetworkDataHandler::network_for_block(converted_block)
let network_index = block_number
.into()
.as_usize()
.checked_rem(networks.len())
.unwrap_or_default();
let network_in_use = networks
.iter()
.nth(network_index)
.ok_or(OffchainErr::NoStoredNetworks)?; .ok_or(OffchainErr::NoStoredNetworks)?;
log::info!( log::info!(
@ -879,7 +946,8 @@ impl<T: Config> Pallet<T> {
return Err(OffchainErr::NoEndpointAvailable(network_id)); return Err(OffchainErr::NoEndpointAvailable(network_id));
} }
let (from_block, to_block): (u64, u64) = StorageValueRef::persistent(&block_number_key) let (from_block, to_block): (ExternalBlockNumber, ExternalBlockNumber) =
StorageValueRef::persistent(&block_number_key)
.get() .get()
.map_err(|_| OffchainErr::StorageRetrievalError(network_id))? .map_err(|_| OffchainErr::StorageRetrievalError(network_id))?
.unwrap_or_default(); .unwrap_or_default();
@ -943,6 +1011,7 @@ impl<T: Config> Pallet<T> {
for (authority_index, authority_key) in Self::local_authorities(&session_index) { for (authority_index, authority_key) in Self::local_authorities(&session_index) {
parsed_evm_response.sign_and_submit::<T>( parsed_evm_response.sign_and_submit::<T>(
block_number,
new_block_range.0, new_block_range.0,
authority_index, authority_index,
authority_key, authority_key,
@ -960,7 +1029,7 @@ impl<T: Config> Pallet<T> {
fn local_authorities( fn local_authorities(
session_index: &SessionIndex, session_index: &SessionIndex,
) -> impl Iterator<Item = (u32, T::AuthorityId)> { ) -> impl Iterator<Item = (AuthIndex, T::AuthorityId)> {
let authorities = Authorities::<T>::get(session_index); let authorities = Authorities::<T>::get(session_index);
let mut local_authorities = T::AuthorityId::all(); let mut local_authorities = T::AuthorityId::all();
local_authorities.sort(); local_authorities.sort();
@ -1003,6 +1072,7 @@ impl<T: Config> Pallet<T> {
match rt_offchain::http::Request::post(&rpc_endpoint_str, vec![request_body_str]) match rt_offchain::http::Request::post(&rpc_endpoint_str, vec![request_body_str])
.add_header("Accept", "application/json") .add_header("Accept", "application/json")
.add_header("Content-Type", "application/json") .add_header("Content-Type", "application/json")
.add_header("User-Agent", "curl/8.9.0") // mimic the curl
.deadline(deadline) .deadline(deadline)
.send() .send()
{ {
@ -1033,7 +1103,7 @@ impl<T: Config> Pallet<T> {
fn get_balanced_evm_response( fn get_balanced_evm_response(
parsed_evm_responses: &Vec<EvmResponseType>, parsed_evm_responses: &Vec<EvmResponseType>,
max_block_distance: u64, max_block_distance: ExternalBlockNumber,
) -> OffchainResult<T, EvmResponseType> { ) -> OffchainResult<T, EvmResponseType> {
let first_evm_response = parsed_evm_responses let first_evm_response = parsed_evm_responses
.first() .first()
@ -1195,8 +1265,8 @@ impl<T: Config> Pallet<T> {
} }
fn prepare_evm_request_body_for_latest_transfers( fn prepare_evm_request_body_for_latest_transfers(
from_block: u64, from_block: ExternalBlockNumber,
to_block: u64, to_block: ExternalBlockNumber,
network_data: &NetworkData, network_data: &NetworkData,
) -> Vec<u8> { ) -> Vec<u8> {
match network_data.network_type { match network_data.network_type {
@ -1205,9 +1275,9 @@ impl<T: Config> Pallet<T> {
b"{\"id\":0,\"jsonrpc\":\"2.0\",\"method\":\"eth_getLogs\",\"params\":[{" b"{\"id\":0,\"jsonrpc\":\"2.0\",\"method\":\"eth_getLogs\",\"params\":[{"
.to_vec(); .to_vec();
body.extend(b"\"fromBlock\":\"".to_vec()); body.extend(b"\"fromBlock\":\"".to_vec());
body.extend(Self::u64_to_hexadecimal_bytes(from_block)); body.extend(Self::block_number_to_hexadecimal_bytes(from_block));
body.extend(b"\",\"toBlock\":\"".to_vec()); body.extend(b"\",\"toBlock\":\"".to_vec());
body.extend(Self::u64_to_hexadecimal_bytes(to_block)); body.extend(Self::block_number_to_hexadecimal_bytes(to_block));
body.extend(b"\",\"address\":\"".to_vec()); body.extend(b"\",\"address\":\"".to_vec());
body.extend(network_data.gatekeeper.to_vec()); body.extend(network_data.gatekeeper.to_vec());
body.extend(b"\",\"topics\":[\"".to_vec()); body.extend(b"\",\"topics\":[\"".to_vec());
@ -1243,12 +1313,16 @@ impl<T: Config> Pallet<T> {
); );
let authorities_len = authorities.len(); let authorities_len = authorities.len();
let bounded_authorities = WeakBoundedVec::<_, T::MaxAuthorities>::try_from(authorities) let bounded_authorities = WeakBoundedVec::<_, T::MaxAuthorities>::force_from(
.expect("more than the maximum number of authorities"); authorities,
Some("slow claps reached maximum number of authorities"),
);
let validators = T::ValidatorSet::validators(); let validators = T::ValidatorSet::validators();
let bounded_validators = WeakBoundedVec::<_, T::MaxAuthorities>::try_from(validators) let bounded_validators = WeakBoundedVec::<_, T::MaxAuthorities>::force_from(
.expect("more than the maximum number of validators"); validators,
Some("slow claps reached maximum number of validators"),
);
if let Some(target_session_index) = session_index.checked_sub(T::HistoryDepth::get()) { if let Some(target_session_index) = session_index.checked_sub(T::HistoryDepth::get()) {
Self::clear_history(&target_session_index); Self::clear_history(&target_session_index);
@ -1273,73 +1347,47 @@ impl<T: Config> Pallet<T> {
debug_assert!(cursor.maybe_cursor.is_none()); debug_assert!(cursor.maybe_cursor.is_none());
} }
fn calculate_median_value(values: &mut Vec<(AuthIndex, u64)>) -> u64 { fn calculate_median_value<InnerValue>(values: &mut Vec<(AuthIndex, InnerValue)>) -> InnerValue
where
InnerValue: AtLeast32BitUnsigned + Copy,
{
values.sort_by_key(|data| data.1); values.sort_by_key(|data| data.1);
let length = values.len(); let length = values.len();
if length % 2 == 0 { if length % 2 == 0 {
let mid_left = values[length / 2 - 1].1; let mid_left = values[length / 2 - 1].1;
let mid_right = values[length / 2].1; let mid_right = values[length / 2].1;
(mid_left + mid_right) / 2 (mid_left + mid_right) / 2u32.into()
} else { } else {
values[length / 2].1 values[length / 2].1
} }
} }
fn apply_median_deviation( fn capture_deviation_in_commitments<InnerValue>(
bitmap: &mut BitMap,
disabled: &BitMap,
values: &Vec<(AuthIndex, u64)>,
median: u64,
max_deviation: u64,
) {
values.iter().for_each(|(authority_index, value)| {
if !disabled.exists(authority_index) && value.abs_diff(median) > max_deviation {
bitmap.set(*authority_index);
}
})
}
fn capture_deviation_in_commitments_and_remove(
disabled_bitmap: &BitMap, disabled_bitmap: &BitMap,
block_commitments: &BTreeMap<AuthIndex, CommitmentDetails>, mut values: &mut Vec<(AuthIndex, InnerValue)>,
validators: &WeakBoundedVec<ValidatorId<T>, T::MaxAuthorities>, validators_len: u32,
max_block_deviation: u64, max_deviation: InnerValue,
) -> BitMap { ) -> BitMap
let validators_len = validators.len() as u32; where
InnerValue: AtLeast32BitUnsigned + Copy,
{
let mut delayed_bitmap = BitMap::new(validators_len);
let median_value = Self::calculate_median_value(&mut values);
let mut delayed = BitMap::new(validators_len); values.iter().for_each(|(authority_index, value)| {
let mut stored_blocks: Vec<(AuthIndex, u64)> = Vec::new(); let abs_diff = if *value > median_value {
let mut time_updates: Vec<(AuthIndex, u64)> = Vec::new(); *value - median_value
} else {
median_value - *value
};
for authority_index in 0..validators_len { if !disabled_bitmap.exists(authority_index) && abs_diff > max_deviation {
let data = block_commitments delayed_bitmap.set(*authority_index);
.get(&authority_index)
.copied()
.unwrap_or_default();
stored_blocks.push((authority_index, data.last_stored_block));
time_updates.push((authority_index, data.last_updated));
} }
});
let stored_block_median = Self::calculate_median_value(&mut stored_blocks); delayed_bitmap
let time_update_median = Self::calculate_median_value(&mut time_updates);
Self::apply_median_deviation(
&mut delayed,
disabled_bitmap,
&stored_blocks,
stored_block_median,
max_block_deviation,
);
Self::apply_median_deviation(
&mut delayed,
disabled_bitmap,
&time_updates,
time_update_median,
ONE_HOUR_MILLIS,
);
delayed
} }
fn get_cumulative_missing_clapped_amount( fn get_cumulative_missing_clapped_amount(
@ -1393,41 +1441,54 @@ impl<T: Config> Pallet<T> {
offence_bitmap: BitMap, offence_bitmap: BitMap,
disabled_bitmap: BitMap, disabled_bitmap: BitMap,
offence_type: OffenceType, offence_type: OffenceType,
) { ) -> Weight {
let validator_set_count = validators.len() as u32; let mut weight = T::DbWeight::get().reads_writes(1, 1);
let validator_set_count = validators.len();
let offenders = validators let mut offenders = Vec::with_capacity(offence_bitmap.count_ones() as usize);
.into_iter() let mut reporter_indexes = Vec::with_capacity(validator_set_count);
.enumerate()
.filter_map(|(index, id)| {
(offence_bitmap.exists(&(index as AuthIndex))).then(|| {
<T::ValidatorSet as ValidatorSetWithIdentification<T::AccountId>>::IdentificationOf::convert(
id.clone(),
).map(|full_id| (id.clone(), full_id))
})
.flatten()
})
.collect::<Vec<IdentificationTuple<T>>>();
let disabled_or_offence_bitmap = disabled_bitmap.bitor(offence_bitmap); let disabled_or_offence_bitmap = disabled_bitmap.bitor(offence_bitmap.clone());
let validator_set_count = validator_set_count as u32;
for (index, id) in validators.iter().enumerate() {
let authority_index = index as AuthIndex;
if offence_bitmap.exists(&authority_index) {
weight.saturating_accrue(T::DbWeight::get().reads(1));
if let Some(full_id) = <T::ValidatorSet as ValidatorSetWithIdentification<
T::AccountId,
>>::IdentificationOf::convert(id.clone())
{
offenders.push((id.clone(), full_id));
}
} else if !disabled_or_offence_bitmap.exists(&authority_index) {
reporter_indexes.push(index);
}
}
let offenders_len = offenders.len() as u32;
let not_enough_validators_left = validator_set_count let not_enough_validators_left = validator_set_count
.saturating_sub(disabled_or_offence_bitmap.count_ones()) .saturating_sub(disabled_or_offence_bitmap.count_ones())
.lt(&T::MinAuthoritiesNumber::get()); .lt(&T::MinAuthoritiesNumber::get());
if not_enough_validators_left && offenders.len() > 0 { if not_enough_validators_left && offenders_len > 0 {
Self::deposit_event(Event::<T>::BlackSwan); Self::deposit_event(Event::<T>::BlackSwan);
return; return weight;
} }
if offenders.len() == 0 { if offenders_len == 0 {
let equilibrium_event = match offence_type { let equilibrium_event = match offence_type {
OffenceType::CommitmentOffence => Event::<T>::AuthoritiesCommitmentEquilibrium, OffenceType::CommitmentOffence => Event::<T>::AuthoritiesCommitmentEquilibrium,
OffenceType::ThrottlingOffence(_) => Event::<T>::AuthoritiesApplauseEquilibrium, OffenceType::ThrottlingOffence(_) => Event::<T>::AuthoritiesApplauseEquilibrium,
}; };
Self::deposit_event(equilibrium_event); Self::deposit_event(equilibrium_event);
return; return weight;
} }
weight.saturating_accrue(T::DbWeight::get().reads(1));
let reporters = T::ExposureListener::get_accounts_by_indexes(reporter_indexes.into_iter());
let offence_event = match offence_type { let offence_event = match offence_type {
OffenceType::CommitmentOffence => Event::<T>::SomeAuthoritiesDelayed { OffenceType::CommitmentOffence => Event::<T>::SomeAuthoritiesDelayed {
delayed: offenders.clone(), delayed: offenders.clone(),
@ -1446,19 +1507,13 @@ impl<T: Config> Pallet<T> {
offence_type, offence_type,
}; };
let reporters = validators
.into_iter()
.enumerate()
.filter_map(|(index, _)| {
(!disabled_or_offence_bitmap.exists(&(index as AuthIndex)))
.then(|| T::ExposureListener::get_account_by_index(index))
.flatten()
})
.collect();
if let Err(e) = T::ReportUnresponsiveness::report_offence(reporters, offence) { if let Err(e) = T::ReportUnresponsiveness::report_offence(reporters, offence) {
sp_runtime::print(e); sp_runtime::print(e);
} }
let extra_weight = T::WeightInfo::try_offend_validators(validator_set_count, offenders_len);
weight.saturating_add(extra_weight)
} }
} }
@ -1488,8 +1543,8 @@ impl<T: Config> OneSessionHandler<T::AccountId> for Pallet<T> {
where where
I: Iterator<Item = (&'a T::AccountId, T::AuthorityId)>, I: Iterator<Item = (&'a T::AccountId, T::AuthorityId)>,
{ {
for (network_id, _) in BlockCommitments::<T>::iter() { for network_id in T::NetworkDataHandler::iter_indexes() {
BlockCommitments::<T>::remove(network_id); BlockCommitments::<T>::remove(&network_id);
} }
let total_exposure = T::ExposureListener::get_total_exposure(); let total_exposure = T::ExposureListener::get_total_exposure();

View File

@ -0,0 +1,9 @@
pub mod v3;
pub type MigrateV2ToV3<T> = frame_support::migrations::VersionedMigration<
2,
3,
v3::CommitmentDetailsTypesChanged<T>,
crate::Pallet<T>,
<T as frame_system::Config>::DbWeight,
>;

View File

@ -0,0 +1,71 @@
use codec::{Decode, Encode, MaxEncodedLen};
use frame_support::{
storage,
traits::{Get, UncheckedOnRuntimeUpgrade},
weights::Weight,
};
use ghost_networks::NetworkDataInspectHandler;
use scale_info::TypeInfo;
use sp_runtime::traits::{BlockNumberProvider, UniqueSaturatedInto};
use sp_runtime::RuntimeDebug;
use sp_std::marker::PhantomData;
use crate::{AuthIndex, BTreeMap, BlockCommitments, CommitmentDetails, Config, Pallet, LOG_TARGET};
#[derive(
RuntimeDebug,
Default,
Copy,
Clone,
Eq,
PartialEq,
Ord,
PartialOrd,
Encode,
Decode,
TypeInfo,
MaxEncodedLen,
)]
pub struct OldCommitmentDetails {
pub last_stored_block: u64,
pub last_updated: u64,
pub commits: u64,
}
pub struct CommitmentDetailsTypesChanged<T>(PhantomData<T>);
impl<T: Config> UncheckedOnRuntimeUpgrade for CommitmentDetailsTypesChanged<T> {
fn on_runtime_upgrade() -> Weight {
let mut weight = T::DbWeight::get().reads(3);
let current_block_number = <Pallet<T> as BlockNumberProvider>::current_block_number();
for network_id in T::NetworkDataHandler::iter_indexes() {
let mut new_btree_map = BTreeMap::new();
let key_hash = BlockCommitments::<T>::hashed_key_for(&network_id);
let old_commitments = storage::unhashed::take_or_default::<
BTreeMap<AuthIndex, OldCommitmentDetails>,
>(&key_hash);
for (authority_index, details) in old_commitments.iter() {
new_btree_map.insert(
authority_index,
CommitmentDetails {
last_stored_block: details.last_stored_block,
last_updated: current_block_number,
commits: details.commits.unique_saturated_into(),
},
);
}
BlockCommitments::<T>::insert(&network_id, new_btree_map);
weight.saturating_accrue(T::DbWeight::get().reads_writes(1, 1));
log::info!(
target: LOG_TARGET,
"👻 Block commitments migrated from unix timestamp to internal block for network {:?}",
network_id,
);
}
weight
}
}

View File

@ -130,6 +130,7 @@ parameter_types! {
parameter_types! { parameter_types! {
pub static MockAverageSessionLength: Option<u64> = None; pub static MockAverageSessionLength: Option<u64> = None;
pub const MaxNetworks: u32 = 5;
} }
impl ghost_networks::Config for Runtime { impl ghost_networks::Config for Runtime {
@ -139,6 +140,7 @@ impl ghost_networks::Config for Runtime {
type RegisterOrigin = EnsureRoot<Self::AccountId>; type RegisterOrigin = EnsureRoot<Self::AccountId>;
type UpdateOrigin = EnsureRoot<Self::AccountId>; type UpdateOrigin = EnsureRoot<Self::AccountId>;
type RemoveOrigin = EnsureRoot<Self::AccountId>; type RemoveOrigin = EnsureRoot<Self::AccountId>;
type MaxNetworks = MaxNetworks;
type WeightInfo = (); type WeightInfo = ();
} }
@ -157,6 +159,7 @@ parameter_types! {
pub static ExistentialDeposit: u64 = 2; pub static ExistentialDeposit: u64 = 2;
pub const RewardCurve: &'static PiecewiseLinear<'static> = &REWARD_CURVE; pub const RewardCurve: &'static PiecewiseLinear<'static> = &REWARD_CURVE;
pub const HistoryDepth: u32 = 10; pub const HistoryDepth: u32 = 10;
pub const EpochDuration: u64 = 80;
} }
#[derive_impl(pallet_balances::config_preludes::TestDefaultConfig)] #[derive_impl(pallet_balances::config_preludes::TestDefaultConfig)]
@ -174,6 +177,15 @@ impl ExposureListener<Balance, u64> for TestExposureListener
where where
Balance: AtLeast32BitUnsigned + From<u64>, Balance: AtLeast32BitUnsigned + From<u64>,
{ {
fn get_accounts_by_indexes(
indexes_iterator: impl Iterator<Item = usize>,
) -> sp_std::prelude::Vec<u64> {
let all_validators = FixedValidators::get();
indexes_iterator
.filter_map(|i| all_validators.get(i).copied())
.collect()
}
fn get_account_by_index(index: usize) -> Option<u64> { fn get_account_by_index(index: usize) -> Option<u64> {
FixedValidators::get().get(index).copied() FixedValidators::get().get(index).copied()
} }
@ -211,6 +223,7 @@ impl Config for Runtime {
type UnsignedPriority = ConstU64<{ 1 << 20 }>; type UnsignedPriority = ConstU64<{ 1 << 20 }>;
type HistoryDepth = HistoryDepth; type HistoryDepth = HistoryDepth;
type MinAuthoritiesNumber = ConstU32<1>; type MinAuthoritiesNumber = ConstU32<1>;
type EpochDuration = EpochDuration;
type WeightInfo = (); type WeightInfo = ();
} }

View File

@ -1,10 +1,10 @@
#![cfg(test)] #![cfg(test)]
use std::time::{SystemTime, UNIX_EPOCH}; use std::collections::HashMap;
use super::*; use super::*;
use crate::evm_types::Log;
use crate::mock::*; use crate::mock::*;
use crate::{evm_types::Log, migrations::v3::OldCommitmentDetails};
use frame_support::{assert_err, assert_ok, dispatch}; use frame_support::{assert_err, assert_ok, dispatch};
use sp_core::offchain::{ use sp_core::offchain::{
@ -822,7 +822,7 @@ fn should_clap_without_applause_on_gatekeeper_amount_overflow() {
let first_receiver: u64 = 1337; let first_receiver: u64 = 1337;
let second_receiver: u64 = 420; let second_receiver: u64 = 420;
let (network_id, block_number, unique_hash) = let (network_id, block_number, _) =
generate_unique_hash(None, None, Some(first_receiver), Some(big_amount), None); generate_unique_hash(None, None, Some(first_receiver), Some(big_amount), None);
new_test_ext().execute_with(|| { new_test_ext().execute_with(|| {
@ -840,13 +840,17 @@ fn should_clap_without_applause_on_gatekeeper_amount_overflow() {
receiver: first_receiver, receiver: first_receiver,
amount: big_amount, amount: big_amount,
}; };
let unique_hash = SlowClap::generate_unique_hash(&clap);
let authority = UintAuthorityId::from(authority_index as u64); let authority = UintAuthorityId::from(authority_index as u64);
let signature = authority.sign(&clap.encode()).unwrap(); let signature = authority.sign(&clap.encode()).unwrap();
assert_ok!(SlowClap::slow_clap(RuntimeOrigin::none(), clap, signature)); assert_ok!(SlowClap::slow_clap(RuntimeOrigin::none(), clap, signature));
assert_clapped(&session_index, &unique_hash, authority_index, true); assert_clapped(&session_index, &unique_hash, authority_index, true);
if authority_index > 2 {
assert_applaused(&session_index, &unique_hash);
}
} }
assert_applaused(&session_index, &unique_hash);
assert_eq!(Balances::total_balance(&first_receiver), big_amount); assert_eq!(Balances::total_balance(&first_receiver), big_amount);
assert_eq!(Balances::total_balance(&second_receiver), 0); assert_eq!(Balances::total_balance(&second_receiver), 0);
@ -892,7 +896,6 @@ fn should_nullify_commission_on_finalize() {
assert_ok!(do_clap_from(session_index, network_id, 1, false)); assert_ok!(do_clap_from(session_index, network_id, 1, false));
assert_ok!(do_clap_from(session_index, network_id, 2, false)); assert_ok!(do_clap_from(session_index, network_id, 2, false));
assert_eq!(Networks::accumulated_commission(), amount); assert_eq!(Networks::accumulated_commission(), amount);
assert_eq!(Networks::is_nullification_period(), false);
assert_applaused(&session_index, &unique_hash); assert_applaused(&session_index, &unique_hash);
assert_eq!( assert_eq!(
@ -903,63 +906,13 @@ fn should_nullify_commission_on_finalize() {
), ),
(amount, 0u64) (amount, 0u64)
); // precomputed values ); // precomputed values
assert_eq!(Networks::is_nullification_period(), true);
Networks::on_finalize(System::block_number());
assert_eq!(Networks::is_nullification_period(), false);
assert_eq!(Networks::accumulated_commission(), 0); assert_eq!(Networks::accumulated_commission(), 0);
assert_ok!(do_clap_from(session_index, network_id, 3, false)); assert_ok!(do_clap_from(session_index, network_id, 3, false));
assert_eq!(Networks::accumulated_commission(), 0); assert_eq!(Networks::accumulated_commission(), 0);
}); });
} }
#[test]
fn should_avoid_applause_during_nullification_period() {
let zero: u64 = 0u64;
let total_staked = 69_000_000;
let total_issuance = 100_000_000;
let (network_id, _, unique_hash) = generate_unique_hash(None, None, None, None, None);
let (_, receiver, amount, _) = get_mocked_metadata();
new_test_ext().execute_with(|| {
let _ = prepare_evm_network(None, None);
let session_index = advance_session_and_get_index();
assert_eq!(Networks::is_nullification_period(), false);
assert_eq!(
BridgedInflationCurve::<RewardCurve, Runtime>::era_payout(
total_staked,
total_issuance,
zero
),
(zero, zero)
);
assert_eq!(Networks::is_nullification_period(), true);
assert_ok!(do_clap_from(session_index, network_id, 0, false));
assert_ok!(do_clap_from(session_index, network_id, 1, false));
assert_eq!(Balances::total_balance(&receiver), 0);
assert_clapped(&session_index, &unique_hash, 0, true);
assert_clapped(&session_index, &unique_hash, 1, true);
assert_clapped(&session_index, &unique_hash, 2, false);
assert_clapped(&session_index, &unique_hash, 3, false);
Networks::on_finalize(System::block_number());
assert_eq!(Networks::is_nullification_period(), false);
assert_ok!(do_clap_from(session_index, network_id, 2, false));
assert_ok!(do_clap_from(session_index, network_id, 3, false));
assert_eq!(Balances::total_balance(&receiver), amount);
assert_applaused(&session_index, &unique_hash);
assert_clapped(&session_index, &unique_hash, 0, true);
assert_clapped(&session_index, &unique_hash, 1, true);
assert_clapped(&session_index, &unique_hash, 2, true);
assert_clapped(&session_index, &unique_hash, 3, true);
});
}
#[test] #[test]
fn should_avoid_session_overlap_on_mended_session_index() { fn should_avoid_session_overlap_on_mended_session_index() {
let (network_id, _, unique_hash) = generate_unique_hash(None, None, None, None, None); let (network_id, _, unique_hash) = generate_unique_hash(None, None, None, None, None);
@ -1112,47 +1065,38 @@ fn should_register_block_commitments() {
let session_index = advance_session_and_get_index(); let session_index = advance_session_and_get_index();
prepare_evm_network(None, None); prepare_evm_network(None, None);
for commitment_details in BlockCommitments::<Runtime>::get(network_id).values() { assert_eq!(BlockCommitments::<Runtime>::get(network_id).len(), 0);
assert_eq!(commitment_details.last_stored_block, 0);
assert_eq!(commitment_details.last_updated, 0); let last_stored_block = 69;
assert_eq!(commitment_details.commits, 0); let current_block = SlowClap::current_block_number();
}
let mut block_commitment = CommitmentDetails {
last_stored_block: 69,
commits: 420,
last_updated: 1337,
};
for i in 0..=3 { for i in 0..=3 {
assert_ok!(do_block_commitment( assert_ok!(do_block_commitment(
session_index, session_index,
network_id, network_id,
i, i,
&block_commitment last_stored_block,
)); ));
} }
block_commitment.last_updated = 1000;
for i in 0..=3 { for i in 0..=3 {
assert_err!( assert_err!(
do_block_commitment(session_index, network_id, i, &block_commitment), do_block_commitment(session_index, network_id, i, last_stored_block),
Error::<Runtime>::TimeWentBackwards, Error::<Runtime>::TimeWentBackwards,
); );
} }
for commitment_details in BlockCommitments::<Runtime>::get(network_id).values() { let block_commitments = BlockCommitments::<Runtime>::get(network_id);
assert_eq!(commitment_details.last_stored_block, 69); assert_eq!(block_commitments.len(), 4);
assert_eq!(commitment_details.last_updated, 1337); block_commitments.values().for_each(|details| {
assert_eq!(commitment_details.commits, 1); assert_eq!(details.last_stored_block, last_stored_block);
} assert_eq!(details.last_updated, current_block);
assert_eq!(details.commits, 1);
});
advance_session(); advance_session();
for commitment_details in BlockCommitments::<Runtime>::get(network_id).values() { assert_eq!(BlockCommitments::<Runtime>::get(network_id).len(), 0);
assert_eq!(commitment_details.last_stored_block, 0);
assert_eq!(commitment_details.last_updated, 0);
assert_eq!(commitment_details.commits, 0);
}
}); });
} }
@ -1164,48 +1108,71 @@ fn should_disable_on_commitment_inactivity() {
let session_index = advance_session_and_get_index(); let session_index = advance_session_and_get_index();
prepare_evm_network(None, None); prepare_evm_network(None, None);
for commitment_details in BlockCommitments::<Runtime>::get(network_id).values() { assert_eq!(BlockCommitments::<Runtime>::get(network_id).len(), 0);
assert_eq!(commitment_details.last_stored_block, 0); System::set_block_number(5 * EpochDuration::get() / 2);
assert_eq!(commitment_details.last_updated, 0); let last_stored_block = 69;
assert_eq!(commitment_details.commits, 0);
}
let timestamp = SystemTime::now()
.duration_since(UNIX_EPOCH)
.expect("Time went backwards")
.as_millis() as u64;
let mut block_commitment = CommitmentDetails {
last_stored_block: 69,
commits: 420,
last_updated: timestamp,
};
// two block commitments
for extra_time in 1..=3 {
block_commitment.last_updated += COMMITMENT_DELAY_MILLIS + extra_time;
for i in 0..3 { for i in 0..3 {
assert_ok!(do_block_commitment( assert_ok!(do_block_commitment(
session_index, session_index,
network_id, network_id,
i, i,
&block_commitment last_stored_block,
)); ));
} }
}
let current_block = System::current_block_number();
SlowClap::on_initialize(current_block);
System::assert_has_event(RuntimeEvent::SlowClap( System::assert_has_event(RuntimeEvent::SlowClap(
crate::Event::SomeAuthoritiesDelayed { crate::Event::SomeAuthoritiesDelayed {
delayed: vec![(3, 3)], delayed: vec![(3, 3)],
}, },
)); ));
for commitment_details in BlockCommitments::<Runtime>::get(network_id) let block_commitments = BlockCommitments::<Runtime>::get(network_id);
.values() assert_eq!(block_commitments.get(&3), None);
.take(2) block_commitments.values().for_each(|details| {
{ assert_eq!(details.commits, 1);
assert_eq!(commitment_details.commits, 3); assert_eq!(details.last_stored_block, last_stored_block);
assert_eq!(details.last_updated, current_block);
})
});
}
#[test]
fn should_ignore_commitments_below_latest_executed_block() {
let (network_id, _, _) = generate_unique_hash(None, None, None, None, None);
let (_, _, _, block_number) = get_mocked_metadata();
new_test_ext().execute_with(|| {
let session_index = advance_session_and_get_index();
prepare_evm_network(None, None);
assert_eq!(LatestExecutedBlock::<Runtime>::get(network_id), 0);
assert_eq!(BlockCommitments::<Runtime>::get(network_id).len(), 0);
assert_ok!(do_clap_from(session_index, network_id, 0, false));
assert_ok!(do_clap_from(session_index, network_id, 1, false));
assert_ok!(do_clap_from(session_index, network_id, 2, false));
assert_ok!(do_clap_from(session_index, network_id, 3, false));
let latest_executed_block = LatestExecutedBlock::<Runtime>::get(&network_id);
assert_eq!(latest_executed_block, block_number);
for low_block in 0..=block_number {
assert_err!(
do_block_commitment(session_index, network_id, 0, low_block),
Error::<Runtime>::InnerTimeWentBackwards,
);
} }
let next_block_number = block_number.saturating_add(1);
assert_ok!(do_block_commitment(
session_index,
network_id,
0,
next_block_number,
));
}); });
} }
@ -1217,53 +1184,51 @@ fn should_disable_on_commitment_block_deviation() {
let session_index = advance_session_and_get_index(); let session_index = advance_session_and_get_index();
prepare_evm_network(None, None); prepare_evm_network(None, None);
for commitment_details in BlockCommitments::<Runtime>::get(network_id).values() { assert_eq!(BlockCommitments::<Runtime>::get(network_id).len(), 0);
assert_eq!(commitment_details.last_stored_block, 0);
assert_eq!(commitment_details.last_updated, 0);
}
let timestamp = SystemTime::now() let good_last_stored_block = 9_500_000;
.duration_since(UNIX_EPOCH) let bad_last_stored_block = 9_100_000;
.expect("Time went backwards")
.as_millis() as u64;
let mut block_commitment = CommitmentDetails { let current_block = SlowClap::current_block_number();
last_stored_block: 9_500_000,
commits: 420,
last_updated: timestamp,
};
let mut bad_block_commitment = CommitmentDetails {
last_stored_block: 9_100_000,
commits: 420,
last_updated: timestamp,
};
// two block commitments
for extra_time in 1..=3 {
block_commitment.last_updated += COMMITMENT_DELAY_MILLIS + extra_time;
bad_block_commitment.last_updated += COMMITMENT_DELAY_MILLIS + extra_time;
for i in 0..3 { for i in 0..3 {
assert_ok!(do_block_commitment( assert_ok!(do_block_commitment(
session_index, session_index,
network_id, network_id,
i, i,
&block_commitment good_last_stored_block,
)); ));
} }
assert_ok!(do_block_commitment( assert_ok!(do_block_commitment(
session_index, session_index,
network_id, network_id,
3, 3,
&bad_block_commitment bad_last_stored_block,
)); ));
}
let to_initialize = EpochDuration::get()
.saturating_div(BLOCK_CHECK_CYCLES)
.saturating_mul(2);
SlowClap::on_initialize(to_initialize);
System::assert_has_event(RuntimeEvent::SlowClap( System::assert_has_event(RuntimeEvent::SlowClap(
crate::Event::SomeAuthoritiesDelayed { crate::Event::SomeAuthoritiesDelayed {
delayed: vec![(3, 3)], delayed: vec![(3, 3)],
}, },
)); ));
BlockCommitments::<Runtime>::get(network_id)
.iter()
.for_each(|(account_id, details)| {
let block_to_be_stored = if *account_id == 3 {
bad_last_stored_block
} else {
good_last_stored_block
};
assert_eq!(details.commits, 1);
assert_eq!(details.last_stored_block, block_to_be_stored);
assert_eq!(details.last_updated, current_block);
})
}); });
} }
@ -1275,106 +1240,50 @@ fn should_throw_error_on_fast_commitments() {
let session_index = advance_session_and_get_index(); let session_index = advance_session_and_get_index();
prepare_evm_network(None, None); prepare_evm_network(None, None);
let timestamp = SystemTime::now() assert_eq!(BlockCommitments::<Runtime>::get(network_id).len(), 0);
.duration_since(UNIX_EPOCH)
.expect("Time went backwards")
.as_millis() as u64;
let mut block_commitment = CommitmentDetails { let last_stored_block = 9_500_000;
last_stored_block: 9_500_000, let next_stored_block = 9_600_000;
commits: 420, let current_block = SlowClap::current_block_number();
last_updated: timestamp,
};
assert_ok!(do_block_commitment( assert_ok!(do_block_commitment(
session_index, session_index,
network_id, network_id,
0, 0,
&block_commitment last_stored_block,
)); ));
assert_err!( assert_err!(
do_block_commitment(session_index, network_id, 0, &block_commitment), do_block_commitment(session_index, network_id, 0, next_stored_block),
Error::<Runtime>::TimeWentBackwards, Error::<Runtime>::TimeWentBackwards,
); );
block_commitment.last_updated += COMMITMENT_DELAY_MILLIS / 2; BlockCommitments::<Runtime>::get(network_id)
assert_err!( .get(&0)
do_block_commitment(session_index, network_id, 0, &block_commitment), .map(|details| {
Error::<Runtime>::TimeWentBackwards, assert_eq!(details.last_stored_block, last_stored_block);
); assert_eq!(details.last_updated, current_block);
assert_eq!(details.commits, 1);
})
.expect("authority_index 0 has voted; qed");
block_commitment.last_updated += COMMITMENT_DELAY_MILLIS / 2; System::set_block_number(current_block + BLOCK_COMMITMENT_DELAY);
assert_err!(
do_block_commitment(session_index, network_id, 0, &block_commitment),
Error::<Runtime>::TimeWentBackwards,
);
block_commitment.last_updated += 1; let new_current_block = SlowClap::current_block_number();
assert_ok!(do_block_commitment( assert_ok!(do_block_commitment(
session_index, session_index,
network_id, network_id,
0, 0,
&block_commitment next_stored_block,
)); ));
block_commitment.last_updated = timestamp; BlockCommitments::<Runtime>::get(network_id)
assert_err!( .get(&0)
do_block_commitment(session_index, network_id, 0, &block_commitment), .map(|details| {
Error::<Runtime>::TimeWentBackwards, assert_eq!(details.last_stored_block, next_stored_block);
); assert_eq!(details.last_updated, new_current_block);
assert_eq!(details.commits, 2);
for commitment_details in BlockCommitments::<Runtime>::get(network_id).values() { })
assert_eq!(commitment_details.last_stored_block, 9_500_000); .expect("authority_index 0 has voted; qed");
assert_eq!(
commitment_details.last_updated,
timestamp + COMMITMENT_DELAY_MILLIS + 1
);
assert_eq!(commitment_details.commits, 2);
}
});
}
#[test]
fn should_not_offend_disabled_authorities() {
let (network_id, _, _) = generate_unique_hash(None, None, None, None, None);
new_test_ext().execute_with(|| {
let session_index = advance_session_and_get_index();
prepare_evm_network(None, None);
assert_ok!(do_clap_from(session_index, network_id, 0, false));
assert_ok!(do_clap_from(session_index, network_id, 1, false));
assert_ok!(do_clap_from(session_index, network_id, 2, false));
let timestamp = SystemTime::now()
.duration_since(UNIX_EPOCH)
.expect("Time went backwards")
.as_millis() as u64;
let mut block_commitment = CommitmentDetails {
last_stored_block: 9_500_000,
commits: 420,
last_updated: timestamp,
};
Session::disable_index(3);
// two block commitments
for extra_time in 1..=3 {
block_commitment.last_updated += COMMITMENT_DELAY_MILLIS + extra_time;
for i in 0..3 {
assert_ok!(do_block_commitment(
session_index,
network_id,
i,
&block_commitment
));
}
}
System::assert_has_event(RuntimeEvent::SlowClap(
crate::Event::AuthoritiesCommitmentEquilibrium,
));
}); });
} }
@ -1386,82 +1295,91 @@ fn should_not_slash_by_applause_if_disabled_by_commitment() {
let session_index = advance_session_and_get_index(); let session_index = advance_session_and_get_index();
prepare_evm_network(None, None); prepare_evm_network(None, None);
for commitment_details in BlockCommitments::<Runtime>::get(network_id).values() { assert_eq!(BlockCommitments::<Runtime>::get(network_id).len(), 0);
assert_eq!(commitment_details.last_stored_block, 0); System::set_block_number(5 * EpochDuration::get() / 2);
assert_eq!(commitment_details.last_updated, 0);
}
let timestamp = SystemTime::now() let last_stored_block = 9_500_000;
.duration_since(UNIX_EPOCH) let current_block = SlowClap::current_block_number();
.expect("Time went backwards") let mut disabled_bitmp = BitMap::new(4);
.as_millis() as u64;
let mut block_commitment = CommitmentDetails {
last_stored_block: 9_500_000,
commits: 420,
last_updated: timestamp,
};
assert_eq!(
DisabledAuthorityIndexes::<Runtime>::get(&session_index),
Some(disabled_bitmp.clone())
);
Session::disable_index(3); Session::disable_index(3);
disabled_bitmp.set(3);
assert_eq!(
DisabledAuthorityIndexes::<Runtime>::get(&session_index),
Some(disabled_bitmp.clone())
);
// two block commitments for i in 0..=3 {
for extra_time in 1..=3 {
block_commitment.last_updated += COMMITMENT_DELAY_MILLIS + extra_time;
for i in 0..3 {
assert_ok!(do_block_commitment( assert_ok!(do_block_commitment(
session_index, session_index,
network_id, network_id,
i, i,
&block_commitment last_stored_block,
)); ));
} }
}
SlowClap::on_initialize(current_block);
System::assert_has_event(RuntimeEvent::SlowClap( System::assert_has_event(RuntimeEvent::SlowClap(
crate::Event::AuthoritiesCommitmentEquilibrium, crate::Event::AuthoritiesCommitmentEquilibrium,
)); ));
let block_commitments = BlockCommitments::<Runtime>::get(network_id);
assert_eq!(
DisabledAuthorityIndexes::<Runtime>::get(&session_index),
Some(disabled_bitmp)
);
assert_eq!(block_commitments.len(), 4);
block_commitments.values().for_each(|details| {
assert_eq!(details.last_stored_block, last_stored_block);
assert_eq!(details.last_updated, current_block);
assert_eq!(details.commits, 1);
});
}); });
} }
#[test] #[test]
fn should_not_nullify_on_incorrect_block_commitment() { fn should_not_register_block_commitment_on_old_blocks() {
let (network_id, _, _) = generate_unique_hash(None, None, None, None, None); let (network_id, _, _) = generate_unique_hash(None, None, None, None, None);
new_test_ext().execute_with(|| { new_test_ext().execute_with(|| {
let session_index = advance_session_and_get_index(); let session_index = advance_session_and_get_index();
prepare_evm_network(None, None); prepare_evm_network(None, None);
let timestamp = SystemTime::now() assert_eq!(BlockCommitments::<Runtime>::get(network_id).len(), 0);
.duration_since(UNIX_EPOCH)
.expect("Time went backwards")
.as_millis() as u64;
let mut block_commitment = CommitmentDetails { let very_old_block = 9_499_999;
last_stored_block: 9_500_000, let last_stored_block = 9_500_000;
commits: 420, let current_block = SlowClap::current_block_number();
last_updated: timestamp,
};
for i in 0..4 { for i in 0..4 {
assert_ok!(do_block_commitment( assert_ok!(do_block_commitment(
session_index, session_index,
network_id, network_id,
i, i,
&block_commitment last_stored_block,
)); ));
} }
block_commitment.last_updated = 0;
assert_err!( assert_err!(
do_block_commitment(session_index, network_id, 3, &block_commitment), do_block_commitment(session_index, network_id, 3, last_stored_block),
Error::<Runtime>::TimeWentBackwards
);
assert_err!(
do_block_commitment(session_index, network_id, 3, very_old_block),
Error::<Runtime>::TimeWentBackwards Error::<Runtime>::TimeWentBackwards
); );
for commitment_details in BlockCommitments::<Runtime>::get(network_id).values() { BlockCommitments::<Runtime>::get(network_id)
assert_eq!(commitment_details.last_stored_block, 9_500_000); .values()
assert_eq!(commitment_details.last_updated, timestamp); .for_each(|details| {
assert_eq!(commitment_details.commits, 1); assert_eq!(details.commits, 1);
} assert_eq!(details.last_stored_block, last_stored_block);
assert_eq!(details.last_updated, current_block);
})
}); });
} }
@ -1473,34 +1391,24 @@ fn should_split_commit_slash_between_active_validators() {
let session_index = advance_session_and_get_index(); let session_index = advance_session_and_get_index();
prepare_evm_network(None, None); prepare_evm_network(None, None);
let timestamp = SystemTime::now() assert_eq!(BlockCommitments::<Runtime>::get(network_id).len(), 0);
.duration_since(UNIX_EPOCH) System::set_block_number(5 * EpochDuration::get() / 2);
.expect("Time went backwards") let last_stored_block = 69;
.as_millis() as u64;
let mut block_commitment = CommitmentDetails {
last_stored_block: 9_500_000,
commits: 420,
last_updated: timestamp,
};
for extra_time in 1..=3 {
if extra_time < 3 {
let offences = Offences::get();
assert_eq!(offences.len(), 0);
}
block_commitment.last_updated += COMMITMENT_DELAY_MILLIS + extra_time;
for i in 0..3 { for i in 0..3 {
assert_ok!(do_block_commitment( assert_ok!(do_block_commitment(
session_index, session_index,
network_id, network_id,
i, i,
&block_commitment last_stored_block,
)); ));
} }
}
let current_block = SlowClap::current_block_number();
let offences = Offences::get();
assert_eq!(offences.len(), 0);
SlowClap::on_initialize(current_block);
System::assert_has_event(RuntimeEvent::SlowClap( System::assert_has_event(RuntimeEvent::SlowClap(
crate::Event::SomeAuthoritiesDelayed { crate::Event::SomeAuthoritiesDelayed {
delayed: vec![(3, 3)], delayed: vec![(3, 3)],
@ -1508,15 +1416,79 @@ fn should_split_commit_slash_between_active_validators() {
)); ));
let offences = Offences::get(); let offences = Offences::get();
assert_eq!(offences.len(), 3); assert_eq!(offences.len(), 1);
for offence in offences { for offence in offences {
assert_eq!(offence.0, vec![0, 1, 2]); assert_eq!(offence.0, vec![0, 1, 2]);
assert_eq!(offence.1.session_index, session_index); assert_eq!(offence.1.session_index, session_index);
assert_eq!(offence.1.validator_set_count, 4); assert_eq!(offence.1.validator_set_count, 4);
assert_eq!(offence.1.offenders, vec![(3, 3)]); assert_eq!(offence.1.offenders, vec![(3, 3)]);
assert_eq!(offence.1.validator_set_count, 4);
assert_eq!(offence.1.offence_type, OffenceType::CommitmentOffence); assert_eq!(offence.1.offence_type, OffenceType::CommitmentOffence);
} }
let block_commitments = BlockCommitments::<Runtime>::get(network_id);
assert_eq!(block_commitments.get(&3), None);
block_commitments.values().for_each(|details| {
assert_eq!(details.last_stored_block, last_stored_block);
assert_eq!(details.last_updated, current_block);
assert_eq!(details.commits, 1);
});
});
}
#[test]
fn should_check_different_networks_during_on_initialize() {
let times = 69;
let networks_count = 3;
let mut check_commitment_events = HashMap::new();
new_test_ext().execute_with(|| {
let _ = advance_session_and_get_index();
for network_id in 0..networks_count {
prepare_evm_network(Some(network_id), None);
}
let expected_events_count: u64 = BLOCK_CHECK_CYCLES
.saturating_sub(1)
.saturating_mul(networks_count as u64)
.saturating_mul(times);
let expected_events_count: usize = expected_events_count.try_into().unwrap();
let epochs_passed = times * EpochDuration::get();
for check_block in 0..epochs_passed {
SlowClap::on_initialize(check_block);
}
let binding = System::events();
let total_number_of_events = binding
.iter()
.filter(|x| {
x.event == RuntimeEvent::SlowClap(crate::Event::AuthoritiesCommitmentEquilibrium)
})
.count();
binding
.iter()
.map(|record| record.event.clone())
.for_each(|event| {
if let RuntimeEvent::SlowClap(crate::Event::BlockCommitmentsCheck {
network_id,
..
}) = event
{
*check_commitment_events.entry(network_id).or_insert(0) += 1;
}
});
assert_eq!(total_number_of_events, expected_events_count);
assert_eq!(check_commitment_events.len() as u32, networks_count);
for network_id in 0..networks_count {
let network_id_count = check_commitment_events.get(&network_id).unwrap();
let expected_events_count =
expected_events_count.saturating_div(networks_count as usize);
assert_eq!(*network_id_count, expected_events_count);
}
}); });
} }
@ -1661,6 +1633,64 @@ fn should_get_balanced_responses_correctly() {
}); });
} }
#[test]
fn migration_from_v2_to_v3_works_fine() {
new_test_ext().execute_with(|| {
let network_ids = vec![1, 57232, 232, 775];
StorageVersion::new(2).put::<SlowClap>();
System::set_block_number(69);
for network_id in network_ids.iter() {
prepare_evm_network(Some(*network_id), None);
let mut fake_old_commits = BTreeMap::new();
fake_old_commits.insert(
0,
OldCommitmentDetails {
last_stored_block: (*network_id).into(),
last_updated: 133742069,
commits: 420,
},
);
fake_old_commits.insert(
2,
OldCommitmentDetails {
last_stored_block: (*network_id).into(),
last_updated: 133742069,
commits: 5,
},
);
let key_hash = BlockCommitments::<Runtime>::hashed_key_for(&network_id);
frame_support::storage::unhashed::put(&key_hash, &fake_old_commits);
}
type Migrate = crate::migrations::MigrateV2ToV3<Runtime>;
<Migrate as frame_support::traits::OnRuntimeUpgrade>::on_runtime_upgrade();
let current_block_number = System::current_block_number();
for network_id in network_ids.iter() {
BlockCommitments::<Runtime>::get(&network_id)
.iter()
.for_each(|(authority_id, details)| match authority_id {
0 => {
assert_eq!(details.last_stored_block, *network_id as u64);
assert_eq!(details.last_updated, current_block_number);
assert_eq!(details.commits, u8::MAX);
}
2 => {
assert_eq!(details.last_stored_block, *network_id as u64);
assert_eq!(details.last_updated, current_block_number);
assert_eq!(details.commits, 5);
}
_ => panic!("non registered block commitment exists after migration"),
});
}
});
}
fn assert_clapped_amount( fn assert_clapped_amount(
session_index: &SessionIndex, session_index: &SessionIndex,
unique_hash: &H256, unique_hash: &H256,
@ -1714,13 +1744,13 @@ fn do_block_commitment(
session_index: u32, session_index: u32,
network_id: u32, network_id: u32,
authority_index: u32, authority_index: u32,
commitment: &CommitmentDetails, last_stored_block: ExternalBlockNumber,
) -> dispatch::DispatchResult { ) -> dispatch::DispatchResult {
let block_commitment = BlockCommitment { let block_commitment = BlockCommitment {
session_index, session_index,
authority_index, authority_index,
network_id, network_id,
commitment: *commitment, last_stored_block,
}; };
let authority = UintAuthorityId::from(authority_index as u64); let authority = UintAuthorityId::from(authority_index as u64);
let signature = authority.sign(&block_commitment.encode()).unwrap(); let signature = authority.sign(&block_commitment.encode()).unwrap();
@ -1884,6 +1914,7 @@ fn evm_block_response(state: &mut testing::OffchainState) {
headers: vec![ headers: vec![
("Accept".to_string(), "application/json".to_string()), ("Accept".to_string(), "application/json".to_string()),
("Content-Type".to_string(), "application/json".to_string()), ("Content-Type".to_string(), "application/json".to_string()),
("User-Agent".to_string(), "curl/8.9.0".to_string()),
], ],
response: Some(b"{\"id\":0,\"jsonrpc\":\"2.0\",\"result\":\"0x1364c81\"}".to_vec()), response: Some(b"{\"id\":0,\"jsonrpc\":\"2.0\",\"result\":\"0x1364c81\"}".to_vec()),
body: expected_body.clone(), body: expected_body.clone(),
@ -1897,6 +1928,7 @@ fn evm_block_response(state: &mut testing::OffchainState) {
headers: vec![ headers: vec![
("Accept".to_string(), "application/json".to_string()), ("Accept".to_string(), "application/json".to_string()),
("Content-Type".to_string(), "application/json".to_string()), ("Content-Type".to_string(), "application/json".to_string()),
("User-Agent".to_string(), "curl/8.9.0".to_string()),
], ],
response: Some(b"{\"id\":0,\"jsonrpc\":\"2.0\",\"result\":\"0x1364c81\"}".to_vec()), response: Some(b"{\"id\":0,\"jsonrpc\":\"2.0\",\"result\":\"0x1364c81\"}".to_vec()),
body: expected_body, body: expected_body,
@ -1951,6 +1983,7 @@ fn evm_logs_response(state: &mut testing::OffchainState) {
headers: vec![ headers: vec![
("Accept".to_string(), "application/json".to_string()), ("Accept".to_string(), "application/json".to_string()),
("Content-Type".to_string(), "application/json".to_string()), ("Content-Type".to_string(), "application/json".to_string()),
("User-Agent".to_string(), "curl/8.9.0".to_string()),
], ],
response_headers: vec![ response_headers: vec![
("Accept".to_string(), "application/json".to_string()), ("Accept".to_string(), "application/json".to_string()),
@ -1968,6 +2001,7 @@ fn evm_logs_response(state: &mut testing::OffchainState) {
headers: vec![ headers: vec![
("Accept".to_string(), "application/json".to_string()), ("Accept".to_string(), "application/json".to_string()),
("Content-Type".to_string(), "application/json".to_string()), ("Content-Type".to_string(), "application/json".to_string()),
("User-Agent".to_string(), "curl/8.9.0".to_string()),
], ],
response_headers: vec![ response_headers: vec![
("Accept".to_string(), "application/json".to_string()), ("Accept".to_string(), "application/json".to_string()),

View File

@ -16,7 +16,7 @@
//! Autogenerated weights for `ghost_slow_clap` //! Autogenerated weights for `ghost_slow_clap`
//! //!
//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0
//! DATE: 2025-11-06, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! DATE: 2026-02-28, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]`
//! WORST CASE MAP SIZE: `1000000` //! WORST CASE MAP SIZE: `1000000`
//! HOSTNAME: `ghostown`, CPU: `Intel(R) Core(TM) i3-2310M CPU @ 2.10GHz` //! HOSTNAME: `ghostown`, CPU: `Intel(R) Core(TM) i3-2310M CPU @ 2.10GHz`
//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("casper-dev")`, DB CACHE: 1024 //! WASM-EXECUTION: `Compiled`, CHAIN: `Some("casper-dev")`, DB CACHE: 1024
@ -49,21 +49,28 @@ use core::marker::PhantomData;
pub trait WeightInfo { pub trait WeightInfo {
fn slow_clap() -> Weight; fn slow_clap() -> Weight;
fn commit_block()-> Weight; fn commit_block()-> Weight;
fn try_offend_validators(validators_len: u32, offenders_len: u32) -> Weight;
} }
impl WeightInfo for () { impl WeightInfo for () {
/// Storage: `GhostSlowClaps::Authorities` (r:1 w:0)
/// Proof: `GhostSlowClaps::Authorities` (`max_values`: None, `max_size`: None, mode: `Measured`)
/// Storage: `GhostSlowClaps::ReceivedClaps` (r:1 w:1)
/// Proof: `GhostSlowClaps::ReceivedClaps` (`max_values`: None, `max_size`: None, mode: `Measured`)
/// Storage: `GhostSlowClaps::ClapsInSession` (r:1 w:1)
/// Proof: `GhostSlowClaps::ClapsInSession` (`max_values`: None, `max_size`: None, mode: `Measured`)
/// Storage: `GhostSlowClaps::ApplausesForTransaction` (r:1 w:1)
/// Proof: `GhostSlowClaps::ApplausesForTransaction` (`max_values`: None, `max_size`: None, mode: `Measured`)
/// Storage: `GhostNetworks::NullifyNeeded` (r:1 w:0)
/// Proof: `GhostNetworks::NullifyNeeded` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
/// Storage: `GhostNetworks::Networks` (r:1 w:0) /// Storage: `GhostNetworks::Networks` (r:1 w:0)
/// Proof: `GhostNetworks::Networks` (`max_values`: None, `max_size`: None, mode: `Measured`) /// Proof: `GhostNetworks::Networks` (`max_values`: None, `max_size`: None, mode: `Measured`)
/// Storage: `GhostSlowClaps::LatestExecutedBlock` (r:1 w:1)
/// Proof: `GhostSlowClaps::LatestExecutedBlock` (`max_values`: None, `max_size`: None, mode: `Measured`)
/// Storage: `GhostSlowClaps::ApplauseDetails` (r:1 w:1)
/// Proof: `GhostSlowClaps::ApplauseDetails` (`max_values`: None, `max_size`: None, mode: `Measured`)
/// Storage: `GhostSlowClaps::Authorities` (r:1 w:0)
/// Proof: `GhostSlowClaps::Authorities` (`max_values`: None, `max_size`: None, mode: `Measured`)
/// Storage: `GhostSlowClaps::DisabledAuthorityIndexes` (r:1 w:0)
/// Proof: `GhostSlowClaps::DisabledAuthorityIndexes` (`max_values`: None, `max_size`: None, mode: `Measured`)
/// Storage: `GhostSlowClaps::TotalExposure` (r:1 w:0)
/// Proof: `GhostSlowClaps::TotalExposure` (`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::CurrentEra` (r:1 w:0)
/// Proof: `Staking::CurrentEra` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`)
/// Storage: `Staking::ErasStakersOverview` (r:1 w:0)
/// Proof: `Staking::ErasStakersOverview` (`max_values`: None, `max_size`: Some(92), added: 2567, mode: `MaxEncodedLen`)
/// Storage: `GhostNetworks::GatekeeperAmount` (r:1 w:1) /// Storage: `GhostNetworks::GatekeeperAmount` (r:1 w:1)
/// Proof: `GhostNetworks::GatekeeperAmount` (`max_values`: None, `max_size`: None, mode: `Measured`) /// Proof: `GhostNetworks::GatekeeperAmount` (`max_values`: None, `max_size`: None, mode: `Measured`)
/// Storage: `GhostNetworks::BridgedImbalance` (r:1 w:1) /// Storage: `GhostNetworks::BridgedImbalance` (r:1 w:1)
@ -74,16 +81,70 @@ impl WeightInfo for () {
/// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`)
fn slow_clap() -> Weight { fn slow_clap() -> Weight {
// Proof Size summary in bytes: // Proof Size summary in bytes:
// Measured: `355` // Measured: `1417`
// Estimated: `3820` // Estimated: `4882`
// Minimum execution time: 213_817_000 picoseconds. // Minimum execution time: 305_397_000 picoseconds.
Weight::from_parts(216_977_000, 0) Weight::from_parts(310_207_000, 0)
.saturating_add(Weight::from_parts(0, 3820)) .saturating_add(Weight::from_parts(0, 4882))
.saturating_add(RocksDbWeight::get().reads(10)) .saturating_add(RocksDbWeight::get().reads(13))
.saturating_add(RocksDbWeight::get().writes(7)) .saturating_add(RocksDbWeight::get().writes(6))
} }
/// Storage: `Session::CurrentIndex` (r:1 w:0)
fn commit_block()-> Weight { /// Proof: `Session::CurrentIndex` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
Default::default() /// Storage: `GhostSlowClaps::LatestExecutedBlock` (r:1 w:0)
/// Proof: `GhostSlowClaps::LatestExecutedBlock` (`max_values`: None, `max_size`: None, mode: `Measured`)
/// Storage: `GhostNetworks::Networks` (r:1 w:0)
/// Proof: `GhostNetworks::Networks` (`max_values`: None, `max_size`: None, mode: `Measured`)
/// Storage: `GhostSlowClaps::BlockCommitments` (r:1 w:1)
/// Proof: `GhostSlowClaps::BlockCommitments` (`max_values`: None, `max_size`: None, mode: `Measured`)
fn commit_block() -> Weight {
// Proof Size summary in bytes:
// Measured: `701`
// Estimated: `4166`
// Minimum execution time: 88_007_000 picoseconds.
Weight::from_parts(89_662_000, 0)
.saturating_add(Weight::from_parts(0, 4166))
.saturating_add(RocksDbWeight::get().reads(4))
.saturating_add(RocksDbWeight::get().writes(1))
}
/// Storage: `Staking::ActiveEra` (r:1 w:0)
/// Proof: `Staking::ActiveEra` (`max_values`: Some(1), `max_size`: Some(13), added: 508, mode: `MaxEncodedLen`)
/// Storage: `Staking::ErasStakersOverview` (r:100000 w:0)
/// Proof: `Staking::ErasStakersOverview` (`max_values`: None, `max_size`: Some(92), added: 2567, mode: `MaxEncodedLen`)
/// Storage: `Staking::ErasStakers` (r:100000 w:0)
/// Proof: `Staking::ErasStakers` (`max_values`: None, `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: `Offences::ConcurrentReportsIndex` (r:1 w:1)
/// Proof: `Offences::ConcurrentReportsIndex` (`max_values`: None, `max_size`: None, mode: `Measured`)
/// Storage: `Offences::Reports` (r:97959 w:97959)
/// Proof: `Offences::Reports` (`max_values`: None, `max_size`: None, mode: `Measured`)
/// Storage: `Staking::SlashRewardFraction` (r:1 w:0)
/// Proof: `Staking::SlashRewardFraction` (`max_values`: Some(1), `max_size`: Some(4), added: 499, 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`: None, mode: `Measured`)
/// Storage: `Staking::SlashingSpans` (r:97959 w:97959)
/// Proof: `Staking::SlashingSpans` (`max_values`: None, `max_size`: None, mode: `Measured`)
/// Storage: `Staking::DisabledValidators` (r:1 w:1)
/// Proof: `Staking::DisabledValidators` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
/// The range of component `n` is `[1, 100000]`.
/// The range of component `d` is `[0, 100000]`.
fn try_offend_validators(n: u32, d: u32, ) -> Weight {
// Proof Size summary in bytes:
// Measured: `674`
// Estimated: `1886 + d * (2567 ±0)`
// Minimum execution time: 13_294_008_000 picoseconds.
Weight::from_parts(13_307_595_000, 0)
.saturating_add(Weight::from_parts(0, 1886))
// Standard Error: 1_146_439
.saturating_add(Weight::from_parts(29_632_292, 0).saturating_mul(n.into()))
// Standard Error: 1_146_441
.saturating_add(Weight::from_parts(14_654_685, 0).saturating_mul(d.into()))
.saturating_add(RocksDbWeight::get().reads((1_u64).saturating_mul(n.into())))
.saturating_add(RocksDbWeight::get().reads((2_u64).saturating_mul(d.into())))
.saturating_add(RocksDbWeight::get().writes((1_u64).saturating_mul(n.into())))
.saturating_add(Weight::from_parts(0, 2567).saturating_mul(d.into()))
} }
} }

View File

@ -1,6 +1,6 @@
[package] [package]
name = "ghost-traits" name = "ghost-traits"
version = "0.3.26" version = "0.3.32"
license.workspace = true license.workspace = true
authors.workspace = true authors.workspace = true
edition.workspace = true edition.workspace = true
@ -10,10 +10,12 @@ repository.workspace = true
[dependencies] [dependencies]
frame-support = { workspace = true } frame-support = { workspace = true }
sp-runtime = { workspace = true } sp-runtime = { workspace = true }
sp-std = { workspace = true }
[features] [features]
default = ["std"] default = ["std"]
std = [ std = [
"frame-support/std", "frame-support/std",
"sp-runtime/std", "sp-runtime/std",
"sp-std/std",
] ]

View File

@ -1,6 +1,9 @@
use sp_runtime::traits::AtLeast32BitUnsigned; use sp_runtime::traits::AtLeast32BitUnsigned;
pub trait ExposureListener<Balance: AtLeast32BitUnsigned, AccountId> { pub trait ExposureListener<Balance: AtLeast32BitUnsigned, AccountId> {
fn get_accounts_by_indexes(
indexes: impl Iterator<Item = usize>,
) -> sp_std::prelude::Vec<AccountId>;
fn get_account_by_index(index: usize) -> Option<AccountId>; fn get_account_by_index(index: usize) -> Option<AccountId>;
fn get_total_exposure() -> Balance; fn get_total_exposure() -> Balance;
fn get_validator_exposure(index: &AccountId) -> Balance; fn get_validator_exposure(index: &AccountId) -> Balance;

View File

@ -16,9 +16,12 @@ pub trait NetworkDataBasicHandler {
} }
pub trait NetworkDataInspectHandler<Network>: NetworkDataBasicHandler { pub trait NetworkDataInspectHandler<Network>: NetworkDataBasicHandler {
fn count() -> u32;
fn contains_key(n: &Self::NetworkId) -> bool;
fn network_for_block(b: impl Into<usize>) -> Option<(Self::NetworkId, Network)>;
fn get(n: &Self::NetworkId) -> Option<Network>; fn get(n: &Self::NetworkId) -> Option<Network>;
fn iter() -> PrefixIterator<(Self::NetworkId, Network)>; fn iter() -> PrefixIterator<(Self::NetworkId, Network)>;
fn is_nullification_period() -> bool; fn iter_indexes() -> impl Iterator<Item = Self::NetworkId>;
} }
pub trait NetworkDataMutateHandler<Network, Balance>: NetworkDataInspectHandler<Network> { pub trait NetworkDataMutateHandler<Network, Balance>: NetworkDataInspectHandler<Network> {
@ -36,8 +39,5 @@ pub trait NetworkDataMutateHandler<Network, Balance>: NetworkDataInspectHandler<
fn accumulate_outgoing_imbalance(amount: &Balance) -> Result<Balance, ()>; fn accumulate_outgoing_imbalance(amount: &Balance) -> Result<Balance, ()>;
fn accumulate_incoming_imbalance(amount: &Balance) -> Result<Balance, ()>; fn accumulate_incoming_imbalance(amount: &Balance) -> Result<Balance, ()>;
fn accumulate_commission(commission: &Balance) -> Result<Balance, ()>; fn accumulate_commission(commission: &Balance) -> Result<Balance, ()>;
fn nullify_commission();
fn trigger_nullification();
} }

View File

@ -1,6 +1,6 @@
[package] [package]
name = "casper-runtime" name = "casper-runtime"
version = "3.5.37" version = "3.5.41"
build = "build.rs" build = "build.rs"
description = "Runtime of the Casper Network" description = "Runtime of the Casper Network"
edition.workspace = true edition.workspace = true

View File

@ -86,6 +86,20 @@ where
u128: From<T::CurrencyBalance>, u128: From<T::CurrencyBalance>,
AccountIdOf<T>: From<<T as pallet_session::Config>::ValidatorId>, AccountIdOf<T>: From<<T as pallet_session::Config>::ValidatorId>,
{ {
fn get_accounts_by_indexes(
indexes_iterator: impl Iterator<Item = usize>,
) -> sp_std::prelude::Vec<AccountIdOf<T>> {
let all_validators = pallet_session::Pallet::<T>::validators();
indexes_iterator
.filter_map(|index| {
all_validators.get(index).map(|validator| {
let account_id: AccountIdOf<T> = validator.clone().into();
account_id
})
})
.collect()
}
fn get_account_by_index(index: usize) -> Option<AccountIdOf<T>> { fn get_account_by_index(index: usize) -> Option<AccountIdOf<T>> {
pallet_session::Pallet::<T>::validators() pallet_session::Pallet::<T>::validators()
.get(index) .get(index)

View File

@ -25,9 +25,10 @@ use runtime_common::{
CurrencyToVote, SlowAdjustingFeeUpdate, CurrencyToVote, SlowAdjustingFeeUpdate,
}; };
#[cfg(not(feature = "runtime-benchmarks"))]
use frame_support::traits::tokens::pay::PayFromAccount; use frame_support::traits::tokens::pay::PayFromAccount;
#[cfg(feature = "runtime-benchmarks")] #[cfg(feature = "runtime-benchmarks")]
use runtime_common::benchmarking::BenchmarkTreasuryHelper; use runtime_common::benchmarking::{BenchmarkTreasuryHelper, BenchmarkTreasuryPaymaster};
use codec::{Decode, Encode, MaxEncodedLen}; use codec::{Decode, Encode, MaxEncodedLen};
use ghost_slow_clap::sr25519::AuthorityId as SlowClapId; use ghost_slow_clap::sr25519::AuthorityId as SlowClapId;
@ -82,9 +83,10 @@ pub use impls::{AllianceProposalProvider, EqualOrGreatestRootCmp, StakingExposur
// Governance configuration. // Governance configuration.
pub mod cult; pub mod cult;
#[cfg(not(feature = "runtime-benchmarks"))]
use cult::CultTreasurySpender;
use cult::{ use cult::{
pallet_cult_origins, CultCollectiveInstance, CultTreasurySpender, Degens, Geniuses, Ghosts, pallet_cult_origins, CultCollectiveInstance, Degens, Geniuses, Ghosts, Skeletons, Zombies,
Skeletons, Zombies,
}; };
pub const LOG_TARGET: &str = "runtime::casper"; pub const LOG_TARGET: &str = "runtime::casper";
@ -117,8 +119,8 @@ pub const VERSION: RuntimeVersion = RuntimeVersion {
spec_name: create_runtime_str!("casper"), spec_name: create_runtime_str!("casper"),
impl_name: create_runtime_str!("casper-svengali"), impl_name: create_runtime_str!("casper-svengali"),
authoring_version: 0, authoring_version: 0,
spec_version: 4, spec_version: 6,
impl_version: 3, impl_version: 4,
apis: RUNTIME_API_VERSIONS, apis: RUNTIME_API_VERSIONS,
transaction_version: 1, transaction_version: 1,
state_version: 1, state_version: 1,
@ -170,7 +172,7 @@ impl frame_system::Config for Runtime {
type SystemWeightInfo = weights::frame_system::WeightInfo<Runtime>; type SystemWeightInfo = weights::frame_system::WeightInfo<Runtime>;
type SS58Prefix = SS58Prefix; type SS58Prefix = SS58Prefix;
type OnSetCode = (); type OnSetCode = ();
type MaxConsumers = frame_support::traits::ConstU32<16>; type MaxConsumers = ConstU32<16>;
type SingleBlockMigrations = (); type SingleBlockMigrations = ();
type MultiBlockMigrator = (); type MultiBlockMigrator = ();
type PreInherents = (); type PreInherents = ();
@ -218,10 +220,7 @@ impl pallet_preimage::Config for Runtime {
} }
parameter_types! { parameter_types! {
pub const EpochDuration: u64 = prod_or_fast!( pub const EpochDuration: u64 = EPOCH_DURATION_IN_SLOTS as u64;
EPOCH_DURATION_IN_SLOTS as u64,
2 * MINUTES as u64
);
pub const ExpectedBlockTime: Moment = MILLISECS_PER_BLOCK; pub const ExpectedBlockTime: Moment = MILLISECS_PER_BLOCK;
pub const ReportLongevity: u64 = pub const ReportLongevity: u64 =
BondingDuration::get() as u64 * BondingDuration::get() as u64 *
@ -237,7 +236,7 @@ impl pallet_babe::Config for Runtime {
type EpochChangeTrigger = pallet_babe::ExternalTrigger; type EpochChangeTrigger = pallet_babe::ExternalTrigger;
type DisabledValidators = Session; type DisabledValidators = Session;
type WeightInfo = (); type WeightInfo = weights::pallet_babe::WeightInfo<Runtime>;
type MaxAuthorities = MaxAuthorities; type MaxAuthorities = MaxAuthorities;
type MaxNominators = MaxNominators; type MaxNominators = MaxNominators;
@ -332,14 +331,8 @@ impl pallet_session::historical::Config for Runtime {
} }
parameter_types! { parameter_types! {
pub SignedPhase: u32 = prod_or_fast!( pub SignedPhase: u32 = EPOCH_DURATION_IN_SLOTS / 4;
EPOCH_DURATION_IN_SLOTS / 4, pub UnsignedPhase: u32 = EPOCH_DURATION_IN_SLOTS / 4;
(1 * MINUTES).min(EpochDuration::get().saturated_into::<u32>() / 2)
);
pub UnsignedPhase: u32 = prod_or_fast!(
EPOCH_DURATION_IN_SLOTS / 4,
(1 * MINUTES).min(EpochDuration::get().saturated_into::<u32>() / 2)
);
// signed config // signed config
pub const SignedMaxSubmissions: u32 = 16; pub const SignedMaxSubmissions: u32 = 16;
@ -567,19 +560,30 @@ impl pallet_identity::Config for Runtime {
parameter_types! { parameter_types! {
pub const ProposalBond: Permill = Permill::from_percent(5); pub const ProposalBond: Permill = Permill::from_percent(5);
pub const ProposalBondMinimum: Balance = 10 * CSPR;
pub const ProposalBondMaximum: Balance = 50 * CSPR;
pub const SpendPeriod: BlockNumber = 24 * DAYS;
pub const Burn: Permill = Permill::from_percent(0); pub const Burn: Permill = Permill::from_percent(0);
pub const MaxBalance: Balance = Balance::MAX; pub const MaxBalance: Balance = Balance::MAX;
pub const PayoutPeriod: BlockNumber = 30 * DAYS; pub const PayoutPeriod: BlockNumber = 30 * DAYS;
pub const TreasuryPalletId: PalletId = PalletId(*b"py/trsry"); pub const TreasuryPalletId: PalletId = PalletId(*b"py/trsry");
pub const DataDepositPerByte: Balance = 1 * STRH; pub const DataDepositPerByte: Balance = 1 * STRH;
pub const MaxApprovals: u32 = 100; pub const MaxApprovals: u32 = 1000;
pub const MaxAuthorities: u32 = 100_000; pub const MaxAuthorities: u32 = 100_000;
} }
#[cfg(not(feature = "runtime-benchmarks"))]
parameter_types! {
pub const ProposalBondMinimum: Balance = 10 * CSPR;
pub const ProposalBondMaximum: Balance = 50 * CSPR;
pub const SpendPeriod: BlockNumber = 6 * DAYS;
}
#[cfg(feature = "runtime-benchmarks")]
parameter_types! {
pub const ProposalBondMinimum: Balance = ExistentialDeposit::get() * 100;
pub const ProposalBondMaximum: Balance = ExistentialDeposit::get() * 500;
pub const SpendPeriod: BlockNumber = 1;
}
impl pallet_treasury::Config for Runtime { impl pallet_treasury::Config for Runtime {
type PalletId = TreasuryPalletId; type PalletId = TreasuryPalletId;
type Currency = Balances; type Currency = Balances;
@ -594,30 +598,29 @@ impl pallet_treasury::Config for Runtime {
type OnSlash = Treasury; type OnSlash = Treasury;
type ProposalBond = ProposalBond; type ProposalBond = ProposalBond;
#[cfg(not(feature = "runtime-benchmarks"))]
type ProposalBondMinimum = ProposalBondMinimum; type ProposalBondMinimum = ProposalBondMinimum;
#[cfg(feature = "runtime-benchmarks")]
type ProposalBondMinimum = ConstU128<{ ExistentialDeposit::get() * 100 }>;
#[cfg(not(feature = "runtime-benchmarks"))]
type ProposalBondMaximum = ProposalBondMaximum; type ProposalBondMaximum = ProposalBondMaximum;
#[cfg(feature = "runtime-benchmarks")]
type ProposalBondMaximum = ConstU128<{ ExistentialDeposit::get() * 500 }>;
type SpendPeriod = SpendPeriod; type SpendPeriod = SpendPeriod;
type Burn = Burn; type Burn = Burn;
type BurnDestination = (); type BurnDestination = ();
type SpendFunds = Bounties; type SpendFunds = Bounties;
type MaxApprovals = MaxApprovals; type MaxApprovals = MaxApprovals;
type WeightInfo = (); type WeightInfo = weights::pallet_treasury::WeightInfo<Runtime>;
#[cfg(not(feature = "runtime-benchmarks"))]
type SpendOrigin = EitherOf<EnsureRootWithSuccess<AccountId, MaxBalance>, CultTreasurySpender>; type SpendOrigin = EitherOf<EnsureRootWithSuccess<AccountId, MaxBalance>, CultTreasurySpender>;
#[cfg(feature = "runtime-benchmarks")]
type SpendOrigin = EnsureRootWithSuccess<AccountId, MaxBalance>;
type AssetKind = (); type AssetKind = ();
type Beneficiary = AccountId; type Beneficiary = AccountId;
type BeneficiaryLookup = IdentityLookup<Self::Beneficiary>; type BeneficiaryLookup = IdentityLookup<Self::Beneficiary>;
#[cfg(not(feature = "runtime-benchmarks"))]
type Paymaster = PayFromAccount<Balances, TreasuryAccount>; type Paymaster = PayFromAccount<Balances, TreasuryAccount>;
#[cfg(feature = "runtime-benchmarks")]
type Paymaster = BenchmarkTreasuryPaymaster;
type BalanceConverter = UnityAssetBalanceConversion; type BalanceConverter = UnityAssetBalanceConversion;
type PayoutPeriod = PayoutPeriod; type PayoutPeriod = PayoutPeriod;
@ -625,30 +628,43 @@ impl pallet_treasury::Config for Runtime {
type BenchmarkHelper = BenchmarkTreasuryHelper; type BenchmarkHelper = BenchmarkTreasuryHelper;
} }
#[cfg(not(feature = "runtime-benchmarks"))]
parameter_types! {
pub const BountyValueMinimum: Balance = 1 * STRH;
pub const CuratorDepositMin: Balance = 10 * CSPR;
}
#[cfg(feature = "runtime-benchmarks")]
parameter_types! {
pub const BountyValueMinimum: Balance = ExistentialDeposit::get() * 10;
pub const CuratorDepositMin: Balance = ExistentialDeposit::get();
}
parameter_types! { parameter_types! {
pub const BountyDepositBase: Balance = 10 * CSPR; pub const BountyDepositBase: Balance = 10 * CSPR;
pub const BountyDepositPayoutDelay: BlockNumber = DAYS; pub const BountyDepositPayoutDelay: BlockNumber = DAYS;
pub const BountyUpdatePeriod: BlockNumber = 2 * WEEKS; pub const BountyUpdatePeriod: BlockNumber = 2 * WEEKS;
pub const MaximumReasonLength: u32 = 16_384; pub const MaximumReasonLength: u32 = 16_384;
pub const CuratorDepositMultiplier: Permill = Permill::from_percent(50); pub const CuratorDepositMultiplier: Permill = Permill::from_percent(50);
pub const CuratorDepositMin: Balance = 10 * CSPR;
pub const CuratorDepositMax: Balance = 200 * CSPR; pub const CuratorDepositMax: Balance = 200 * CSPR;
pub const BountyValueMinimum: Balance = 10 * CSPR;
} }
impl pallet_bounties::Config for Runtime { impl pallet_bounties::Config for Runtime {
type RuntimeEvent = RuntimeEvent; type RuntimeEvent = RuntimeEvent;
type BountyDepositBase = BountyDepositBase; type BountyDepositBase = BountyDepositBase;
type CuratorDepositMin = CuratorDepositMin;
type DataDepositPerByte = DataDepositPerByte;
type BountyValueMinimum = BountyValueMinimum;
type BountyDepositPayoutDelay = BountyDepositPayoutDelay; type BountyDepositPayoutDelay = BountyDepositPayoutDelay;
type BountyUpdatePeriod = BountyUpdatePeriod; type BountyUpdatePeriod = BountyUpdatePeriod;
type CuratorDepositMultiplier = CuratorDepositMultiplier; type CuratorDepositMultiplier = CuratorDepositMultiplier;
type CuratorDepositMin = CuratorDepositMin;
type CuratorDepositMax = CuratorDepositMax; type CuratorDepositMax = CuratorDepositMax;
type BountyValueMinimum = BountyValueMinimum;
type ChildBountyManager = ChildBounties; type ChildBountyManager = ChildBounties;
type DataDepositPerByte = DataDepositPerByte;
type MaximumReasonLength = MaximumReasonLength; type MaximumReasonLength = MaximumReasonLength;
type WeightInfo = ();
type WeightInfo = weights::pallet_bounties::WeightInfo<Runtime>;
} }
parameter_types! { parameter_types! {
@ -660,7 +676,7 @@ impl pallet_child_bounties::Config for Runtime {
type RuntimeEvent = RuntimeEvent; type RuntimeEvent = RuntimeEvent;
type MaxActiveChildBountyCount = MaxActiveChildBountyCount; type MaxActiveChildBountyCount = MaxActiveChildBountyCount;
type ChildBountyValueMinimum = ChildBountyValueMinimum; type ChildBountyValueMinimum = ChildBountyValueMinimum;
type WeightInfo = (); type WeightInfo = weights::pallet_child_bounties::WeightInfo<Runtime>;
} }
impl pallet_offences::Config for Runtime { impl pallet_offences::Config for Runtime {
@ -685,7 +701,7 @@ parameter_types! {
impl pallet_grandpa::Config for Runtime { impl pallet_grandpa::Config for Runtime {
type RuntimeEvent = RuntimeEvent; type RuntimeEvent = RuntimeEvent;
type WeightInfo = (); type WeightInfo = weights::pallet_grandpa::WeightInfo<Runtime>;
type MaxAuthorities = MaxAuthorities; type MaxAuthorities = MaxAuthorities;
type MaxNominators = MaxNominators; type MaxNominators = MaxNominators;
@ -978,7 +994,7 @@ impl pallet_collective::Config<AllianceCollective> for Runtime {
type MaxProposals = ConstU32<ALLIANCE_MAX_PROPOSALS>; type MaxProposals = ConstU32<ALLIANCE_MAX_PROPOSALS>;
type MaxMembers = ConstU32<ALLIANCE_MAX_MEMBERS>; type MaxMembers = ConstU32<ALLIANCE_MAX_MEMBERS>;
type DefaultVote = pallet_collective::MoreThanMajorityThenPrimeDefaultVote; type DefaultVote = pallet_collective::MoreThanMajorityThenPrimeDefaultVote;
type SetMembersOrigin = EnsureRoot<AccountId>; type SetMembersOrigin = EnsureRoot<Self::AccountId>;
type MaxProposalWeight = MaxProposalWeight; type MaxProposalWeight = MaxProposalWeight;
type WeightInfo = weights::pallet_collective::WeightInfo<Runtime>; type WeightInfo = weights::pallet_collective::WeightInfo<Runtime>;
} }
@ -1029,6 +1045,7 @@ impl ghost_networks::Config for Runtime {
type RuntimeEvent = RuntimeEvent; type RuntimeEvent = RuntimeEvent;
type NetworkId = u64; type NetworkId = u64;
type Currency = Balances; type Currency = Balances;
type MaxNetworks = ConstU32<30>;
type RegisterOrigin = EitherOf<EnsureRootWithSuccess<Self::AccountId, ConstU16<65535>>, Ghosts>; type RegisterOrigin = EitherOf<EnsureRootWithSuccess<Self::AccountId, ConstU16<65535>>, Ghosts>;
type UpdateOrigin = EitherOf<EnsureRootWithSuccess<Self::AccountId, ConstU16<65535>>, Zombies>; type UpdateOrigin = EitherOf<EnsureRootWithSuccess<Self::AccountId, ConstU16<65535>>, Zombies>;
@ -1058,14 +1075,22 @@ impl ghost_claims::Config<CultCollectiveInstance> for Runtime {
} }
parameter_types! { parameter_types! {
// will be used in `Perbill::from_parts()`
pub const ApplauseThreshold: u32 = 500_000_000;
pub const MinAuthoritiesNumber: u32 = 5; pub const MinAuthoritiesNumber: u32 = 5;
pub const SlowClapUnsignedPriority: TransactionPriority = TransactionPriority::MAX; pub const SlowClapUnsignedPriority: TransactionPriority = TransactionPriority::MAX;
pub const SlowClapHistoryDepth: sp_staking::SessionIndex = pub const SlowClapHistoryDepth: sp_staking::SessionIndex =
StakingHistoryDepth::get() * SessionsPerEra::get(); StakingHistoryDepth::get() * SessionsPerEra::get();
} }
#[cfg(feature = "runtime-benchmarks")]
parameter_types! {
pub const ApplauseThreshold: u32 = 0;
}
#[cfg(not(feature = "runtime-benchmarks"))]
parameter_types! {
pub const ApplauseThreshold: u32 = 500_000_000;
}
impl ghost_slow_clap::Config for Runtime { impl ghost_slow_clap::Config for Runtime {
type RuntimeEvent = RuntimeEvent; type RuntimeEvent = RuntimeEvent;
type AuthorityId = SlowClapId; type AuthorityId = SlowClapId;
@ -1078,11 +1103,13 @@ impl ghost_slow_clap::Config for Runtime {
type DisabledValidators = Session; type DisabledValidators = Session;
type ExposureListener = StakingExposureListener<Runtime>; type ExposureListener = StakingExposureListener<Runtime>;
type MaxAuthorities = MaxAuthorities;
type ApplauseThreshold = ApplauseThreshold; type ApplauseThreshold = ApplauseThreshold;
type MaxAuthorities = MaxAuthorities;
type UnsignedPriority = SlowClapUnsignedPriority; type UnsignedPriority = SlowClapUnsignedPriority;
type HistoryDepth = SlowClapHistoryDepth; type HistoryDepth = SlowClapHistoryDepth;
type MinAuthoritiesNumber = MinAuthoritiesNumber; type MinAuthoritiesNumber = MinAuthoritiesNumber;
type EpochDuration = EpochDuration;
type WeightInfo = weights::ghost_slow_clap::WeightInfo<Runtime>; type WeightInfo = weights::ghost_slow_clap::WeightInfo<Runtime>;
} }
@ -1185,7 +1212,10 @@ pub type SignedExtra = (
/// All migrations that will run on the next runtime upgrade. /// All migrations that will run on the next runtime upgrade.
/// Should be cleared after release. /// Should be cleared after release.
pub type Migrations = (); pub type Migrations = (
ghost_networks::migrations::MigrateV0ToV1<Runtime>,
ghost_slow_clap::migrations::MigrateV2ToV3<Runtime>,
);
/// Unchecked extrinsic type as expected by this runtime. /// Unchecked extrinsic type as expected by this runtime.
pub type UncheckedExtrinsic = pub type UncheckedExtrinsic =

View File

@ -16,7 +16,7 @@
//! Autogenerated weights for `ghost_networks` //! Autogenerated weights for `ghost_networks`
//! //!
//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0
//! DATE: 2025-11-28, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! DATE: 2026-02-26, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]`
//! WORST CASE MAP SIZE: `1000000` //! WORST CASE MAP SIZE: `1000000`
//! HOSTNAME: `ghostown`, CPU: `Intel(R) Core(TM) i3-2310M CPU @ 2.10GHz` //! HOSTNAME: `ghostown`, CPU: `Intel(R) Core(TM) i3-2310M CPU @ 2.10GHz`
//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("casper-dev")`, DB CACHE: 1024 //! WASM-EXECUTION: `Compiled`, CHAIN: `Some("casper-dev")`, DB CACHE: 1024
@ -30,7 +30,6 @@
// --repeat=20 // --repeat=20
// --pallet=ghost_networks // --pallet=ghost_networks
// --extrinsic=* // --extrinsic=*
// --wasm-execution=compiled
// --heap-pages=4096 // --heap-pages=4096
// --header=./file_header.txt // --header=./file_header.txt
// --output=./runtime/casper/src/weights/ghost_networks.rs // --output=./runtime/casper/src/weights/ghost_networks.rs
@ -48,35 +47,35 @@ pub struct WeightInfo<T>(PhantomData<T>);
impl<T: frame_system::Config> ghost_networks::WeightInfo for WeightInfo<T> { impl<T: frame_system::Config> ghost_networks::WeightInfo for WeightInfo<T> {
/// Storage: `GhostNetworks::Networks` (r:1 w:1) /// Storage: `GhostNetworks::Networks` (r:1 w:1)
/// Proof: `GhostNetworks::Networks` (`max_values`: None, `max_size`: None, mode: `Measured`) /// Proof: `GhostNetworks::Networks` (`max_values`: None, `max_size`: None, mode: `Measured`)
/// Storage: `GhostNetworks::NetworkIndexes` (r:1 w:1)
/// Proof: `GhostNetworks::NetworkIndexes` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
/// The range of component `i` is `[1, 20]`. /// The range of component `i` is `[1, 20]`.
/// The range of component `j` is `[1, 150]`. /// The range of component `j` is `[1, 150]`.
/// The range of component `k` is `[1, 20]`. /// The range of component `k` is `[1, 20]`.
fn register_network(i: u32, j: u32, k: u32, ) -> Weight { fn register_network(_i: u32, j: u32, k: u32, ) -> Weight {
// Proof Size summary in bytes: // Proof Size summary in bytes:
// Measured: `109` // Measured: `109`
// Estimated: `3574` // Estimated: `3574`
// Minimum execution time: 47_308_000 picoseconds. // Minimum execution time: 48_419_000 picoseconds.
Weight::from_parts(32_768_615, 0) Weight::from_parts(35_655_823, 0)
.saturating_add(Weight::from_parts(0, 3574)) .saturating_add(Weight::from_parts(0, 3574))
// Standard Error: 5_701 // Standard Error: 1_212
.saturating_add(Weight::from_parts(31_258, 0).saturating_mul(i.into())) .saturating_add(Weight::from_parts(96_762, 0).saturating_mul(j.into()))
// Standard Error: 748 // Standard Error: 9_235
.saturating_add(Weight::from_parts(102_765, 0).saturating_mul(j.into())) .saturating_add(Weight::from_parts(1_460_410, 0).saturating_mul(k.into()))
// Standard Error: 5_701 .saturating_add(T::DbWeight::get().reads(2))
.saturating_add(Weight::from_parts(1_500_633, 0).saturating_mul(k.into())) .saturating_add(T::DbWeight::get().writes(2))
.saturating_add(T::DbWeight::get().reads(1))
.saturating_add(T::DbWeight::get().writes(1))
} }
/// Storage: `GhostNetworks::Networks` (r:1 w:1) /// Storage: `GhostNetworks::Networks` (r:1 w:1)
/// Proof: `GhostNetworks::Networks` (`max_values`: None, `max_size`: None, mode: `Measured`) /// Proof: `GhostNetworks::Networks` (`max_values`: None, `max_size`: None, mode: `Measured`)
/// The range of component `n` is `[1, 20]`. /// The range of component `n` is `[1, 20]`.
fn update_network_name(_n: u32, ) -> Weight { fn update_network_name(_n: u32, ) -> Weight {
// Proof Size summary in bytes: // Proof Size summary in bytes:
// Measured: `310` // Measured: `339`
// Estimated: `3775` // Estimated: `3804`
// Minimum execution time: 51_079_000 picoseconds. // Minimum execution time: 48_422_000 picoseconds.
Weight::from_parts(52_557_946, 0) Weight::from_parts(49_987_541, 0)
.saturating_add(Weight::from_parts(0, 3775)) .saturating_add(Weight::from_parts(0, 3804))
.saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().reads(1))
.saturating_add(T::DbWeight::get().writes(1)) .saturating_add(T::DbWeight::get().writes(1))
} }
@ -85,13 +84,13 @@ impl<T: frame_system::Config> ghost_networks::WeightInfo for WeightInfo<T> {
/// The range of component `n` is `[1, 150]`. /// The range of component `n` is `[1, 150]`.
fn update_network_endpoint(n: u32, ) -> Weight { fn update_network_endpoint(n: u32, ) -> Weight {
// Proof Size summary in bytes: // Proof Size summary in bytes:
// Measured: `310` // Measured: `339`
// Estimated: `3775` // Estimated: `3804`
// Minimum execution time: 51_709_000 picoseconds. // Minimum execution time: 48_651_000 picoseconds.
Weight::from_parts(53_451_989, 0) Weight::from_parts(50_776_912, 0)
.saturating_add(Weight::from_parts(0, 3775)) .saturating_add(Weight::from_parts(0, 3804))
// Standard Error: 605 // Standard Error: 1_062
.saturating_add(Weight::from_parts(6_984, 0).saturating_mul(n.into())) .saturating_add(Weight::from_parts(838, 0).saturating_mul(n.into()))
.saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().reads(1))
.saturating_add(T::DbWeight::get().writes(1)) .saturating_add(T::DbWeight::get().writes(1))
} }
@ -99,11 +98,11 @@ impl<T: frame_system::Config> ghost_networks::WeightInfo for WeightInfo<T> {
/// Proof: `GhostNetworks::Networks` (`max_values`: None, `max_size`: None, mode: `Measured`) /// Proof: `GhostNetworks::Networks` (`max_values`: None, `max_size`: None, mode: `Measured`)
fn update_network_finality_delay() -> Weight { fn update_network_finality_delay() -> Weight {
// Proof Size summary in bytes: // Proof Size summary in bytes:
// Measured: `310` // Measured: `339`
// Estimated: `3775` // Estimated: `3804`
// Minimum execution time: 50_475_000 picoseconds. // Minimum execution time: 48_080_000 picoseconds.
Weight::from_parts(51_344_000, 0) Weight::from_parts(51_781_000, 0)
.saturating_add(Weight::from_parts(0, 3775)) .saturating_add(Weight::from_parts(0, 3804))
.saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().reads(1))
.saturating_add(T::DbWeight::get().writes(1)) .saturating_add(T::DbWeight::get().writes(1))
} }
@ -111,11 +110,11 @@ impl<T: frame_system::Config> ghost_networks::WeightInfo for WeightInfo<T> {
/// Proof: `GhostNetworks::Networks` (`max_values`: None, `max_size`: None, mode: `Measured`) /// Proof: `GhostNetworks::Networks` (`max_values`: None, `max_size`: None, mode: `Measured`)
fn update_network_rate_limit_delay() -> Weight { fn update_network_rate_limit_delay() -> Weight {
// Proof Size summary in bytes: // Proof Size summary in bytes:
// Measured: `310` // Measured: `339`
// Estimated: `3775` // Estimated: `3804`
// Minimum execution time: 50_467_000 picoseconds. // Minimum execution time: 47_950_000 picoseconds.
Weight::from_parts(51_264_000, 0) Weight::from_parts(48_925_000, 0)
.saturating_add(Weight::from_parts(0, 3775)) .saturating_add(Weight::from_parts(0, 3804))
.saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().reads(1))
.saturating_add(T::DbWeight::get().writes(1)) .saturating_add(T::DbWeight::get().writes(1))
} }
@ -123,11 +122,11 @@ impl<T: frame_system::Config> ghost_networks::WeightInfo for WeightInfo<T> {
/// Proof: `GhostNetworks::Networks` (`max_values`: None, `max_size`: None, mode: `Measured`) /// Proof: `GhostNetworks::Networks` (`max_values`: None, `max_size`: None, mode: `Measured`)
fn update_network_block_distance() -> Weight { fn update_network_block_distance() -> Weight {
// Proof Size summary in bytes: // Proof Size summary in bytes:
// Measured: `310` // Measured: `339`
// Estimated: `3775` // Estimated: `3804`
// Minimum execution time: 50_473_000 picoseconds. // Minimum execution time: 48_324_000 picoseconds.
Weight::from_parts(51_107_000, 0) Weight::from_parts(50_801_000, 0)
.saturating_add(Weight::from_parts(0, 3775)) .saturating_add(Weight::from_parts(0, 3804))
.saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().reads(1))
.saturating_add(T::DbWeight::get().writes(1)) .saturating_add(T::DbWeight::get().writes(1))
} }
@ -135,11 +134,11 @@ impl<T: frame_system::Config> ghost_networks::WeightInfo for WeightInfo<T> {
/// Proof: `GhostNetworks::Networks` (`max_values`: None, `max_size`: None, mode: `Measured`) /// Proof: `GhostNetworks::Networks` (`max_values`: None, `max_size`: None, mode: `Measured`)
fn update_network_type() -> Weight { fn update_network_type() -> Weight {
// Proof Size summary in bytes: // Proof Size summary in bytes:
// Measured: `310` // Measured: `339`
// Estimated: `3775` // Estimated: `3804`
// Minimum execution time: 49_597_000 picoseconds. // Minimum execution time: 46_962_000 picoseconds.
Weight::from_parts(50_283_000, 0) Weight::from_parts(47_729_000, 0)
.saturating_add(Weight::from_parts(0, 3775)) .saturating_add(Weight::from_parts(0, 3804))
.saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().reads(1))
.saturating_add(T::DbWeight::get().writes(1)) .saturating_add(T::DbWeight::get().writes(1))
} }
@ -147,11 +146,11 @@ impl<T: frame_system::Config> ghost_networks::WeightInfo for WeightInfo<T> {
/// Proof: `GhostNetworks::Networks` (`max_values`: None, `max_size`: None, mode: `Measured`) /// Proof: `GhostNetworks::Networks` (`max_values`: None, `max_size`: None, mode: `Measured`)
fn update_network_gatekeeper() -> Weight { fn update_network_gatekeeper() -> Weight {
// Proof Size summary in bytes: // Proof Size summary in bytes:
// Measured: `310` // Measured: `339`
// Estimated: `3775` // Estimated: `3804`
// Minimum execution time: 51_083_000 picoseconds. // Minimum execution time: 48_728_000 picoseconds.
Weight::from_parts(52_464_000, 0) Weight::from_parts(53_054_000, 0)
.saturating_add(Weight::from_parts(0, 3775)) .saturating_add(Weight::from_parts(0, 3804))
.saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().reads(1))
.saturating_add(T::DbWeight::get().writes(1)) .saturating_add(T::DbWeight::get().writes(1))
} }
@ -159,11 +158,11 @@ impl<T: frame_system::Config> ghost_networks::WeightInfo for WeightInfo<T> {
/// Proof: `GhostNetworks::Networks` (`max_values`: None, `max_size`: None, mode: `Measured`) /// Proof: `GhostNetworks::Networks` (`max_values`: None, `max_size`: None, mode: `Measured`)
fn update_network_topic_name() -> Weight { fn update_network_topic_name() -> Weight {
// Proof Size summary in bytes: // Proof Size summary in bytes:
// Measured: `310` // Measured: `339`
// Estimated: `3775` // Estimated: `3804`
// Minimum execution time: 51_270_000 picoseconds. // Minimum execution time: 48_632_000 picoseconds.
Weight::from_parts(52_099_000, 0) Weight::from_parts(49_954_000, 0)
.saturating_add(Weight::from_parts(0, 3775)) .saturating_add(Weight::from_parts(0, 3804))
.saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().reads(1))
.saturating_add(T::DbWeight::get().writes(1)) .saturating_add(T::DbWeight::get().writes(1))
} }
@ -171,11 +170,11 @@ impl<T: frame_system::Config> ghost_networks::WeightInfo for WeightInfo<T> {
/// Proof: `GhostNetworks::Networks` (`max_values`: None, `max_size`: None, mode: `Measured`) /// Proof: `GhostNetworks::Networks` (`max_values`: None, `max_size`: None, mode: `Measured`)
fn update_incoming_network_fee() -> Weight { fn update_incoming_network_fee() -> Weight {
// Proof Size summary in bytes: // Proof Size summary in bytes:
// Measured: `310` // Measured: `339`
// Estimated: `3775` // Estimated: `3804`
// Minimum execution time: 50_289_000 picoseconds. // Minimum execution time: 47_660_000 picoseconds.
Weight::from_parts(50_924_000, 0) Weight::from_parts(53_763_000, 0)
.saturating_add(Weight::from_parts(0, 3775)) .saturating_add(Weight::from_parts(0, 3804))
.saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().reads(1))
.saturating_add(T::DbWeight::get().writes(1)) .saturating_add(T::DbWeight::get().writes(1))
} }
@ -183,11 +182,11 @@ impl<T: frame_system::Config> ghost_networks::WeightInfo for WeightInfo<T> {
/// Proof: `GhostNetworks::Networks` (`max_values`: None, `max_size`: None, mode: `Measured`) /// Proof: `GhostNetworks::Networks` (`max_values`: None, `max_size`: None, mode: `Measured`)
fn update_outgoing_network_fee() -> Weight { fn update_outgoing_network_fee() -> Weight {
// Proof Size summary in bytes: // Proof Size summary in bytes:
// Measured: `310` // Measured: `339`
// Estimated: `3775` // Estimated: `3804`
// Minimum execution time: 49_880_000 picoseconds. // Minimum execution time: 48_164_000 picoseconds.
Weight::from_parts(51_277_000, 0) Weight::from_parts(48_953_000, 0)
.saturating_add(Weight::from_parts(0, 3775)) .saturating_add(Weight::from_parts(0, 3804))
.saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().reads(1))
.saturating_add(T::DbWeight::get().writes(1)) .saturating_add(T::DbWeight::get().writes(1))
} }
@ -195,24 +194,26 @@ impl<T: frame_system::Config> ghost_networks::WeightInfo for WeightInfo<T> {
/// Proof: `GhostNetworks::Networks` (`max_values`: None, `max_size`: None, mode: `Measured`) /// Proof: `GhostNetworks::Networks` (`max_values`: None, `max_size`: None, mode: `Measured`)
fn update_avg_block_speed() -> Weight { fn update_avg_block_speed() -> Weight {
// Proof Size summary in bytes: // Proof Size summary in bytes:
// Measured: `310` // Measured: `339`
// Estimated: `3775` // Estimated: `3804`
// Minimum execution time: 50_612_000 picoseconds. // Minimum execution time: 47_789_000 picoseconds.
Weight::from_parts(51_546_000, 0) Weight::from_parts(52_131_000, 0)
.saturating_add(Weight::from_parts(0, 3775)) .saturating_add(Weight::from_parts(0, 3804))
.saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().reads(1))
.saturating_add(T::DbWeight::get().writes(1)) .saturating_add(T::DbWeight::get().writes(1))
} }
/// Storage: `GhostNetworks::NetworkIndexes` (r:1 w:1)
/// Proof: `GhostNetworks::NetworkIndexes` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
/// Storage: `GhostNetworks::Networks` (r:1 w:1) /// Storage: `GhostNetworks::Networks` (r:1 w:1)
/// Proof: `GhostNetworks::Networks` (`max_values`: None, `max_size`: None, mode: `Measured`) /// Proof: `GhostNetworks::Networks` (`max_values`: None, `max_size`: None, mode: `Measured`)
fn remove_network() -> Weight { fn remove_network() -> Weight {
// Proof Size summary in bytes: // Proof Size summary in bytes:
// Measured: `310` // Measured: `339`
// Estimated: `3775` // Estimated: `3804`
// Minimum execution time: 45_819_000 picoseconds. // Minimum execution time: 49_720_000 picoseconds.
Weight::from_parts(46_590_000, 0) Weight::from_parts(50_526_000, 0)
.saturating_add(Weight::from_parts(0, 3775)) .saturating_add(Weight::from_parts(0, 3804))
.saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().reads(2))
.saturating_add(T::DbWeight::get().writes(1)) .saturating_add(T::DbWeight::get().writes(2))
} }
} }

View File

@ -16,7 +16,7 @@
//! Autogenerated weights for `ghost_slow_clap` //! Autogenerated weights for `ghost_slow_clap`
//! //!
//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0
//! DATE: 2025-11-28, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! DATE: 2026-02-28, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]`
//! WORST CASE MAP SIZE: `1000000` //! WORST CASE MAP SIZE: `1000000`
//! HOSTNAME: `ghostown`, CPU: `Intel(R) Core(TM) i3-2310M CPU @ 2.10GHz` //! HOSTNAME: `ghostown`, CPU: `Intel(R) Core(TM) i3-2310M CPU @ 2.10GHz`
//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("casper-dev")`, DB CACHE: 1024 //! WASM-EXECUTION: `Compiled`, CHAIN: `Some("casper-dev")`, DB CACHE: 1024
@ -48,6 +48,8 @@ pub struct WeightInfo<T>(PhantomData<T>);
impl<T: frame_system::Config> ghost_slow_clap::WeightInfo for WeightInfo<T> { impl<T: frame_system::Config> ghost_slow_clap::WeightInfo for WeightInfo<T> {
/// Storage: `GhostNetworks::Networks` (r:1 w:0) /// Storage: `GhostNetworks::Networks` (r:1 w:0)
/// Proof: `GhostNetworks::Networks` (`max_values`: None, `max_size`: None, mode: `Measured`) /// Proof: `GhostNetworks::Networks` (`max_values`: None, `max_size`: None, mode: `Measured`)
/// Storage: `GhostSlowClaps::LatestExecutedBlock` (r:1 w:1)
/// Proof: `GhostSlowClaps::LatestExecutedBlock` (`max_values`: None, `max_size`: None, mode: `Measured`)
/// Storage: `GhostSlowClaps::ApplauseDetails` (r:1 w:1) /// Storage: `GhostSlowClaps::ApplauseDetails` (r:1 w:1)
/// Proof: `GhostSlowClaps::ApplauseDetails` (`max_values`: None, `max_size`: None, mode: `Measured`) /// Proof: `GhostSlowClaps::ApplauseDetails` (`max_values`: None, `max_size`: None, mode: `Measured`)
/// Storage: `GhostSlowClaps::Authorities` (r:1 w:0) /// Storage: `GhostSlowClaps::Authorities` (r:1 w:0)
@ -62,10 +64,6 @@ impl<T: frame_system::Config> ghost_slow_clap::WeightInfo for WeightInfo<T> {
/// Proof: `Staking::CurrentEra` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) /// Proof: `Staking::CurrentEra` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`)
/// Storage: `Staking::ErasStakersOverview` (r:1 w:0) /// Storage: `Staking::ErasStakersOverview` (r:1 w:0)
/// Proof: `Staking::ErasStakersOverview` (`max_values`: None, `max_size`: Some(92), added: 2567, mode: `MaxEncodedLen`) /// Proof: `Staking::ErasStakersOverview` (`max_values`: None, `max_size`: Some(92), added: 2567, mode: `MaxEncodedLen`)
/// Storage: `GhostSlowClaps::LatestExecutedBlock` (r:1 w:1)
/// Proof: `GhostSlowClaps::LatestExecutedBlock` (`max_values`: None, `max_size`: None, mode: `Measured`)
/// Storage: `GhostNetworks::NullifyNeeded` (r:1 w:0)
/// Proof: `GhostNetworks::NullifyNeeded` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
/// Storage: `GhostNetworks::GatekeeperAmount` (r:1 w:1) /// Storage: `GhostNetworks::GatekeeperAmount` (r:1 w:1)
/// Proof: `GhostNetworks::GatekeeperAmount` (`max_values`: None, `max_size`: None, mode: `Measured`) /// Proof: `GhostNetworks::GatekeeperAmount` (`max_values`: None, `max_size`: None, mode: `Measured`)
/// Storage: `GhostNetworks::BridgedImbalance` (r:1 w:1) /// Storage: `GhostNetworks::BridgedImbalance` (r:1 w:1)
@ -76,32 +74,70 @@ impl<T: frame_system::Config> ghost_slow_clap::WeightInfo for WeightInfo<T> {
/// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`)
fn slow_clap() -> Weight { fn slow_clap() -> Weight {
// Proof Size summary in bytes: // Proof Size summary in bytes:
// Measured: `1388` // Measured: `1417`
// Estimated: `4853` // Estimated: `4882`
// Minimum execution time: 261_978_000 picoseconds. // Minimum execution time: 305_397_000 picoseconds.
Weight::from_parts(266_289_000, 0) Weight::from_parts(310_207_000, 0)
.saturating_add(Weight::from_parts(0, 4853)) .saturating_add(Weight::from_parts(0, 4882))
.saturating_add(T::DbWeight::get().reads(14)) .saturating_add(T::DbWeight::get().reads(13))
.saturating_add(T::DbWeight::get().writes(6)) .saturating_add(T::DbWeight::get().writes(6))
} }
/// Storage: `Session::CurrentIndex` (r:1 w:0)
/// Proof: `Session::CurrentIndex` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
/// Storage: `GhostSlowClaps::LatestExecutedBlock` (r:1 w:0)
/// Proof: `GhostSlowClaps::LatestExecutedBlock` (`max_values`: None, `max_size`: None, mode: `Measured`)
/// Storage: `GhostNetworks::Networks` (r:1 w:0) /// Storage: `GhostNetworks::Networks` (r:1 w:0)
/// Proof: `GhostNetworks::Networks` (`max_values`: None, `max_size`: None, mode: `Measured`) /// Proof: `GhostNetworks::Networks` (`max_values`: None, `max_size`: None, mode: `Measured`)
/// Storage: `GhostSlowClaps::BlockCommitments` (r:1 w:1) /// Storage: `GhostSlowClaps::BlockCommitments` (r:1 w:1)
/// Proof: `GhostSlowClaps::BlockCommitments` (`max_values`: None, `max_size`: None, mode: `Measured`) /// Proof: `GhostSlowClaps::BlockCommitments` (`max_values`: None, `max_size`: None, mode: `Measured`)
/// Storage: `Session::CurrentIndex` (r:1 w:0)
/// Proof: `Session::CurrentIndex` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
/// Storage: `GhostSlowClaps::Validators` (r:1 w:0)
/// Proof: `GhostSlowClaps::Validators` (`max_values`: None, `max_size`: None, mode: `Measured`)
/// Storage: `GhostSlowClaps::DisabledAuthorityIndexes` (r:1 w:0)
/// Proof: `GhostSlowClaps::DisabledAuthorityIndexes` (`max_values`: None, `max_size`: None, mode: `Measured`)
fn commit_block() -> Weight { fn commit_block() -> Weight {
// Proof Size summary in bytes: // Proof Size summary in bytes:
// Measured: `859` // Measured: `701`
// Estimated: `4324` // Estimated: `4166`
// Minimum execution time: 108_966_000 picoseconds. // Minimum execution time: 88_007_000 picoseconds.
Weight::from_parts(110_454_000, 0) Weight::from_parts(89_662_000, 0)
.saturating_add(Weight::from_parts(0, 4324)) .saturating_add(Weight::from_parts(0, 4166))
.saturating_add(T::DbWeight::get().reads(5)) .saturating_add(T::DbWeight::get().reads(4))
.saturating_add(T::DbWeight::get().writes(1)) .saturating_add(T::DbWeight::get().writes(1))
} }
/// Storage: `Staking::ActiveEra` (r:1 w:0)
/// Proof: `Staking::ActiveEra` (`max_values`: Some(1), `max_size`: Some(13), added: 508, mode: `MaxEncodedLen`)
/// Storage: `Staking::ErasStakersOverview` (r:100000 w:0)
/// Proof: `Staking::ErasStakersOverview` (`max_values`: None, `max_size`: Some(92), added: 2567, mode: `MaxEncodedLen`)
/// Storage: `Staking::ErasStakers` (r:100000 w:0)
/// Proof: `Staking::ErasStakers` (`max_values`: None, `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: `Offences::ConcurrentReportsIndex` (r:1 w:1)
/// Proof: `Offences::ConcurrentReportsIndex` (`max_values`: None, `max_size`: None, mode: `Measured`)
/// Storage: `Offences::Reports` (r:97959 w:97959)
/// Proof: `Offences::Reports` (`max_values`: None, `max_size`: None, mode: `Measured`)
/// Storage: `Staking::SlashRewardFraction` (r:1 w:0)
/// Proof: `Staking::SlashRewardFraction` (`max_values`: Some(1), `max_size`: Some(4), added: 499, 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`: None, mode: `Measured`)
/// Storage: `Staking::SlashingSpans` (r:97959 w:97959)
/// Proof: `Staking::SlashingSpans` (`max_values`: None, `max_size`: None, mode: `Measured`)
/// Storage: `Staking::DisabledValidators` (r:1 w:1)
/// Proof: `Staking::DisabledValidators` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
/// The range of component `n` is `[1, 100000]`.
/// The range of component `d` is `[0, 100000]`.
fn try_offend_validators(n: u32, d: u32, ) -> Weight {
// Proof Size summary in bytes:
// Measured: `674`
// Estimated: `1886 + d * (2567 ±0)`
// Minimum execution time: 13_294_008_000 picoseconds.
Weight::from_parts(13_307_595_000, 0)
.saturating_add(Weight::from_parts(0, 1886))
// Standard Error: 1_146_439
.saturating_add(Weight::from_parts(29_632_292, 0).saturating_mul(n.into()))
// Standard Error: 1_146_441
.saturating_add(Weight::from_parts(14_654_685, 0).saturating_mul(d.into()))
.saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(n.into())))
.saturating_add(T::DbWeight::get().reads((2_u64).saturating_mul(d.into())))
.saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(n.into())))
.saturating_add(Weight::from_parts(0, 2567).saturating_mul(d.into()))
}
} }

View File

@ -5,12 +5,16 @@ pub mod ghost_networks;
pub mod ghost_slow_clap; pub mod ghost_slow_clap;
pub mod ghost_sudo; pub mod ghost_sudo;
pub mod pallet_alliance; pub mod pallet_alliance;
pub mod pallet_babe;
pub mod pallet_bags_list; pub mod pallet_bags_list;
pub mod pallet_balances; pub mod pallet_balances;
pub mod pallet_bounties;
pub mod pallet_child_bounties;
pub mod pallet_collective; pub mod pallet_collective;
pub mod pallet_core_fellowship; pub mod pallet_core_fellowship;
pub mod pallet_election_provider_multi_phase; pub mod pallet_election_provider_multi_phase;
pub mod pallet_fast_unstake; pub mod pallet_fast_unstake;
pub mod pallet_grandpa;
pub mod pallet_identity; pub mod pallet_identity;
pub mod pallet_indices; pub mod pallet_indices;
pub mod pallet_multisig; pub mod pallet_multisig;
@ -24,6 +28,7 @@ pub mod pallet_scheduler;
pub mod pallet_session; pub mod pallet_session;
pub mod pallet_staking; pub mod pallet_staking;
pub mod pallet_timestamp; pub mod pallet_timestamp;
pub mod pallet_treasury;
pub mod pallet_utility; pub mod pallet_utility;
pub mod pallet_vesting; pub mod pallet_vesting;
pub mod pallet_whitelist; pub mod pallet_whitelist;

View File

@ -16,7 +16,7 @@
//! Autogenerated weights for `pallet_babe` //! Autogenerated weights for `pallet_babe`
//! //!
//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0
//! DATE: 2025-11-28, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! DATE: 2026-02-27, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]`
//! WORST CASE MAP SIZE: `1000000` //! WORST CASE MAP SIZE: `1000000`
//! HOSTNAME: `ghostown`, CPU: `Intel(R) Core(TM) i3-2310M CPU @ 2.10GHz` //! HOSTNAME: `ghostown`, CPU: `Intel(R) Core(TM) i3-2310M CPU @ 2.10GHz`
//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("casper-dev")`, DB CACHE: 1024 //! WASM-EXECUTION: `Compiled`, CHAIN: `Some("casper-dev")`, DB CACHE: 1024
@ -40,19 +40,52 @@
#![allow(unused_imports)] #![allow(unused_imports)]
#![allow(missing_docs)] #![allow(missing_docs)]
use frame_support::{traits::Get, weights::Weight};
use core::marker::PhantomData; use core::marker::PhantomData;
use frame_support::{
traits::Get,
weights::{
constants::{RocksDbWeight as DbWeight, WEIGHT_REF_TIME_PER_MICROS, WEIGHT_REF_TIME_PER_NANOS},
Weight,
},
};
/// Weight functions for `pallet_babe`. /// Weight functions for `pallet_babe`.
pub struct WeightInfo<T>(PhantomData<T>); pub struct WeightInfo<T>(PhantomData<T>);
impl<T: frame_system::Config> pallet_babe::WeightInfo for WeightInfo<T> { impl<T: frame_system::Config> pallet_babe::WeightInfo for WeightInfo<T> {
/// The range of component `x` is `[0, 1]`. fn plan_config_change() -> Weight {
fn check_equivocation_proof(_x: u32, ) -> Weight { DbWeight::get().writes(1)
}
fn report_equivocation(validator_count: u32, max_nominators_per_validator: u32) -> Weight {
// we take the validator set count from the membership proof to
// calculate the weight but we set a floor of 100 validators.
let validator_count = validator_count.max(100) as u64;
// Proof Size summary in bytes: // Proof Size summary in bytes:
// Measured: `0` // Measured: `0`
// Estimated: `0` // Estimated: `0`
// Minimum execution time: 295_038_000 picoseconds. // Minimum execution time: 305_618_000 picoseconds.
Weight::from_parts(298_100_475, 0) let equivocation_check_weight = Weight::from_parts(308_237_602, 0)
.saturating_add(Weight::from_parts(0, 0)) .saturating_add(Weight::from_parts(0, 0))
// Standard Error: 899_088
.saturating_add(Weight::from_parts(7_097, 0).saturating_mul(validator_count.into()));
// checking membership proof
Weight::from_parts(88u64 * WEIGHT_REF_TIME_PER_MICROS, 0)
.saturating_add(
Weight::from_parts(438u64 * WEIGHT_REF_TIME_PER_NANOS, 0)
.saturating_mul(validator_count),
)
.saturating_add(DbWeight::get().reads(5))
// check equivocation proof
.saturating_add(equivocation_check_weight)
// report offence
.saturating_add(equivocation_check_weight)
.saturating_add(Weight::from_parts(
63u64 * WEIGHT_REF_TIME_PER_MICROS * max_nominators_per_validator as u64,
0,
))
.saturating_add(DbWeight::get().reads(14 + 3 * max_nominators_per_validator as u64))
.saturating_add(DbWeight::get().writes(10 + 3 * max_nominators_per_validator as u64))
} }
} }

View File

@ -16,7 +16,7 @@
//! Autogenerated weights for `pallet_bounties` //! Autogenerated weights for `pallet_bounties`
//! //!
//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0
//! DATE: 2024-08-01, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! DATE: 2026-02-28, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]`
//! WORST CASE MAP SIZE: `1000000` //! WORST CASE MAP SIZE: `1000000`
//! HOSTNAME: `ghostown`, CPU: `Intel(R) Core(TM) i3-2310M CPU @ 2.10GHz` //! HOSTNAME: `ghostown`, CPU: `Intel(R) Core(TM) i3-2310M CPU @ 2.10GHz`
//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("casper-dev")`, DB CACHE: 1024 //! WASM-EXECUTION: `Compiled`, CHAIN: `Some("casper-dev")`, DB CACHE: 1024
@ -29,7 +29,7 @@
// --steps=50 // --steps=50
// --repeat=20 // --repeat=20
// --pallet=pallet_bounties // --pallet=pallet_bounties
// --extrinsic=approve_bounty // --extrinsic=*
// --wasm-execution=compiled // --wasm-execution=compiled
// --heap-pages=4096 // --heap-pages=4096
// --header=./file_header.txt // --header=./file_header.txt
@ -46,18 +46,181 @@ use core::marker::PhantomData;
/// Weight functions for `pallet_bounties`. /// Weight functions for `pallet_bounties`.
pub struct WeightInfo<T>(PhantomData<T>); pub struct WeightInfo<T>(PhantomData<T>);
impl<T: frame_system::Config> pallet_bounties::WeightInfo for WeightInfo<T> { impl<T: frame_system::Config> pallet_bounties::WeightInfo for WeightInfo<T> {
/// Storage: `Bounties::BountyCount` (r:1 w:1)
/// Proof: `Bounties::BountyCount` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`)
/// Storage: `System::Account` (r:1 w:1)
/// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`)
/// Storage: `Bounties::BountyDescriptions` (r:0 w:1)
/// Proof: `Bounties::BountyDescriptions` (`max_values`: None, `max_size`: Some(16400), added: 18875, mode: `MaxEncodedLen`)
/// Storage: `Bounties::Bounties` (r:0 w:1)
/// Proof: `Bounties::Bounties` (`max_values`: None, `max_size`: Some(177), added: 2652, mode: `MaxEncodedLen`)
/// The range of component `d` is `[0, 16384]`.
fn propose_bounty(d: u32, ) -> Weight {
// Proof Size summary in bytes:
// Measured: `210`
// Estimated: `3593`
// Minimum execution time: 125_598_000 picoseconds.
Weight::from_parts(127_962_305, 0)
.saturating_add(Weight::from_parts(0, 3593))
// Standard Error: 21
.saturating_add(Weight::from_parts(1_868, 0).saturating_mul(d.into()))
.saturating_add(T::DbWeight::get().reads(2))
.saturating_add(T::DbWeight::get().writes(4))
}
/// Storage: `Bounties::Bounties` (r:1 w:1) /// Storage: `Bounties::Bounties` (r:1 w:1)
/// Proof: `Bounties::Bounties` (`max_values`: None, `max_size`: Some(177), added: 2652, mode: `MaxEncodedLen`) /// Proof: `Bounties::Bounties` (`max_values`: None, `max_size`: Some(177), added: 2652, mode: `MaxEncodedLen`)
/// Storage: `Bounties::BountyApprovals` (r:1 w:1) /// Storage: `Bounties::BountyApprovals` (r:1 w:1)
/// Proof: `Bounties::BountyApprovals` (`max_values`: Some(1), `max_size`: Some(402), added: 897, mode: `MaxEncodedLen`) /// Proof: `Bounties::BountyApprovals` (`max_values`: Some(1), `max_size`: Some(4002), added: 4497, mode: `MaxEncodedLen`)
fn approve_bounty() -> Weight { fn approve_bounty() -> Weight {
// Proof Size summary in bytes: // Proof Size summary in bytes:
// Measured: `302` // Measured: `302`
// Estimated: `5487`
// Minimum execution time: 57_515_000 picoseconds.
Weight::from_parts(58_519_000, 0)
.saturating_add(Weight::from_parts(0, 5487))
.saturating_add(T::DbWeight::get().reads(2))
.saturating_add(T::DbWeight::get().writes(2))
}
/// Storage: `Bounties::Bounties` (r:1 w:1)
/// Proof: `Bounties::Bounties` (`max_values`: None, `max_size`: Some(177), added: 2652, mode: `MaxEncodedLen`)
fn propose_curator() -> Weight {
// Proof Size summary in bytes:
// Measured: `322`
// Estimated: `3642` // Estimated: `3642`
// Minimum execution time: 52_739_000 picoseconds. // Minimum execution time: 51_036_000 picoseconds.
Weight::from_parts(53_443_000, 0) Weight::from_parts(51_462_000, 0)
.saturating_add(Weight::from_parts(0, 3642))
.saturating_add(T::DbWeight::get().reads(1))
.saturating_add(T::DbWeight::get().writes(1))
}
/// Storage: `Bounties::Bounties` (r:1 w:1)
/// Proof: `Bounties::Bounties` (`max_values`: None, `max_size`: Some(177), added: 2652, mode: `MaxEncodedLen`)
/// Storage: `System::Account` (r:1 w:1)
/// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`)
fn unassign_curator() -> Weight {
// Proof Size summary in bytes:
// Measured: `498`
// Estimated: `3642`
// Minimum execution time: 169_646_000 picoseconds.
Weight::from_parts(172_576_000, 0)
.saturating_add(Weight::from_parts(0, 3642)) .saturating_add(Weight::from_parts(0, 3642))
.saturating_add(T::DbWeight::get().reads(2)) .saturating_add(T::DbWeight::get().reads(2))
.saturating_add(T::DbWeight::get().writes(2)) .saturating_add(T::DbWeight::get().writes(2))
} }
/// Storage: `Bounties::Bounties` (r:1 w:1)
/// Proof: `Bounties::Bounties` (`max_values`: None, `max_size`: Some(177), added: 2652, mode: `MaxEncodedLen`)
/// Storage: `System::Account` (r:1 w:1)
/// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`)
fn accept_curator() -> Weight {
// Proof Size summary in bytes:
// Measured: `494`
// Estimated: `3642`
// Minimum execution time: 125_617_000 picoseconds.
Weight::from_parts(127_448_000, 0)
.saturating_add(Weight::from_parts(0, 3642))
.saturating_add(T::DbWeight::get().reads(2))
.saturating_add(T::DbWeight::get().writes(2))
}
/// Storage: `Bounties::Bounties` (r:1 w:1)
/// Proof: `Bounties::Bounties` (`max_values`: None, `max_size`: Some(177), added: 2652, mode: `MaxEncodedLen`)
/// Storage: `ChildBounties::ParentChildBounties` (r:1 w:0)
/// Proof: `ChildBounties::ParentChildBounties` (`max_values`: None, `max_size`: Some(16), added: 2491, mode: `MaxEncodedLen`)
fn award_bounty() -> Weight {
// Proof Size summary in bytes:
// Measured: `401`
// Estimated: `3642`
// Minimum execution time: 65_865_000 picoseconds.
Weight::from_parts(66_641_000, 0)
.saturating_add(Weight::from_parts(0, 3642))
.saturating_add(T::DbWeight::get().reads(2))
.saturating_add(T::DbWeight::get().writes(1))
}
/// Storage: `Bounties::Bounties` (r:1 w:1)
/// Proof: `Bounties::Bounties` (`max_values`: None, `max_size`: Some(177), added: 2652, mode: `MaxEncodedLen`)
/// Storage: `System::Account` (r:3 w:3)
/// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`)
/// Storage: `ChildBounties::ChildrenCuratorFees` (r:1 w:1)
/// Proof: `ChildBounties::ChildrenCuratorFees` (`max_values`: None, `max_size`: Some(28), added: 2503, mode: `MaxEncodedLen`)
/// Storage: `Bounties::BountyDescriptions` (r:0 w:1)
/// Proof: `Bounties::BountyDescriptions` (`max_values`: None, `max_size`: Some(16400), added: 18875, mode: `MaxEncodedLen`)
fn claim_bounty() -> Weight {
// Proof Size summary in bytes:
// Measured: `713`
// Estimated: `8799`
// Minimum execution time: 516_549_000 picoseconds.
Weight::from_parts(520_792_000, 0)
.saturating_add(Weight::from_parts(0, 8799))
.saturating_add(T::DbWeight::get().reads(5))
.saturating_add(T::DbWeight::get().writes(6))
}
/// Storage: `Bounties::Bounties` (r:1 w:1)
/// Proof: `Bounties::Bounties` (`max_values`: None, `max_size`: Some(177), added: 2652, mode: `MaxEncodedLen`)
/// Storage: `ChildBounties::ParentChildBounties` (r:1 w:0)
/// Proof: `ChildBounties::ParentChildBounties` (`max_values`: None, `max_size`: Some(16), added: 2491, mode: `MaxEncodedLen`)
/// Storage: `System::Account` (r:1 w:1)
/// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`)
/// Storage: `Bounties::BountyDescriptions` (r:0 w:1)
/// Proof: `Bounties::BountyDescriptions` (`max_values`: None, `max_size`: Some(16400), added: 18875, mode: `MaxEncodedLen`)
fn close_bounty_proposed() -> Weight {
// Proof Size summary in bytes:
// Measured: `445`
// Estimated: `3642`
// Minimum execution time: 185_684_000 picoseconds.
Weight::from_parts(187_810_000, 0)
.saturating_add(Weight::from_parts(0, 3642))
.saturating_add(T::DbWeight::get().reads(3))
.saturating_add(T::DbWeight::get().writes(3))
}
/// Storage: `Bounties::Bounties` (r:1 w:1)
/// Proof: `Bounties::Bounties` (`max_values`: None, `max_size`: Some(177), added: 2652, mode: `MaxEncodedLen`)
/// Storage: `ChildBounties::ParentChildBounties` (r:1 w:0)
/// Proof: `ChildBounties::ParentChildBounties` (`max_values`: None, `max_size`: Some(16), added: 2491, mode: `MaxEncodedLen`)
/// Storage: `System::Account` (r:2 w:2)
/// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`)
/// Storage: `Bounties::BountyDescriptions` (r:0 w:1)
/// Proof: `Bounties::BountyDescriptions` (`max_values`: None, `max_size`: Some(16400), added: 18875, mode: `MaxEncodedLen`)
fn close_bounty_active() -> Weight {
// Proof Size summary in bytes:
// Measured: `681`
// Estimated: `6196`
// Minimum execution time: 342_424_000 picoseconds.
Weight::from_parts(349_225_000, 0)
.saturating_add(Weight::from_parts(0, 6196))
.saturating_add(T::DbWeight::get().reads(4))
.saturating_add(T::DbWeight::get().writes(4))
}
/// Storage: `Bounties::Bounties` (r:1 w:1)
/// Proof: `Bounties::Bounties` (`max_values`: None, `max_size`: Some(177), added: 2652, mode: `MaxEncodedLen`)
fn extend_bounty_expiry() -> Weight {
// Proof Size summary in bytes:
// Measured: `358`
// Estimated: `3642`
// Minimum execution time: 52_301_000 picoseconds.
Weight::from_parts(53_018_000, 0)
.saturating_add(Weight::from_parts(0, 3642))
.saturating_add(T::DbWeight::get().reads(1))
.saturating_add(T::DbWeight::get().writes(1))
}
/// Storage: `Bounties::BountyApprovals` (r:1 w:1)
/// Proof: `Bounties::BountyApprovals` (`max_values`: Some(1), `max_size`: Some(4002), added: 4497, mode: `MaxEncodedLen`)
/// Storage: `Bounties::Bounties` (r:100 w:100)
/// Proof: `Bounties::Bounties` (`max_values`: None, `max_size`: Some(177), added: 2652, mode: `MaxEncodedLen`)
/// Storage: `System::Account` (r:200 w:200)
/// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`)
/// The range of component `b` is `[0, 100]`.
fn spend_funds(b: u32, ) -> Weight {
// Proof Size summary in bytes:
// Measured: `0 + b * (297 ±0)`
// Estimated: `5487 + b * (5206 ±0)`
// Minimum execution time: 14_296_000 picoseconds.
Weight::from_parts(14_433_000, 0)
.saturating_add(Weight::from_parts(0, 5487))
// Standard Error: 25_068
.saturating_add(Weight::from_parts(160_411_223, 0).saturating_mul(b.into()))
.saturating_add(T::DbWeight::get().reads(1))
.saturating_add(T::DbWeight::get().reads((3_u64).saturating_mul(b.into())))
.saturating_add(T::DbWeight::get().writes(1))
.saturating_add(T::DbWeight::get().writes((3_u64).saturating_mul(b.into())))
.saturating_add(Weight::from_parts(0, 5206).saturating_mul(b.into()))
}
} }

View File

@ -0,0 +1,198 @@
// This file is part of Ghost Network.
// Ghost Network is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// Ghost Network is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with Ghost Network. If not, see <http://www.gnu.org/licenses/>.
//! Autogenerated weights for `pallet_child_bounties`
//!
//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0
//! DATE: 2026-02-28, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]`
//! WORST CASE MAP SIZE: `1000000`
//! HOSTNAME: `ghostown`, CPU: `Intel(R) Core(TM) i3-2310M CPU @ 2.10GHz`
//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("casper-dev")`, DB CACHE: 1024
// Executed Command:
// ./target/release/ghost
// benchmark
// pallet
// --chain=casper-dev
// --steps=50
// --repeat=20
// --pallet=pallet_child_bounties
// --extrinsic=*
// --wasm-execution=compiled
// --heap-pages=4096
// --header=./file_header.txt
// --output=./runtime/casper/src/weights/pallet_child_bounties.rs
#![cfg_attr(rustfmt, rustfmt_skip)]
#![allow(unused_parens)]
#![allow(unused_imports)]
#![allow(missing_docs)]
use frame_support::{traits::Get, weights::Weight};
use core::marker::PhantomData;
/// Weight functions for `pallet_child_bounties`.
pub struct WeightInfo<T>(PhantomData<T>);
impl<T: frame_system::Config> pallet_child_bounties::WeightInfo for WeightInfo<T> {
/// Storage: `ChildBounties::ParentChildBounties` (r:1 w:1)
/// Proof: `ChildBounties::ParentChildBounties` (`max_values`: None, `max_size`: Some(16), added: 2491, mode: `MaxEncodedLen`)
/// Storage: `Bounties::Bounties` (r:1 w:0)
/// Proof: `Bounties::Bounties` (`max_values`: None, `max_size`: Some(177), added: 2652, mode: `MaxEncodedLen`)
/// Storage: `System::Account` (r:2 w:2)
/// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`)
/// Storage: `ChildBounties::ChildBountyCount` (r:1 w:1)
/// Proof: `ChildBounties::ChildBountyCount` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`)
/// Storage: `ChildBounties::ChildBountyDescriptions` (r:0 w:1)
/// Proof: `ChildBounties::ChildBountyDescriptions` (`max_values`: None, `max_size`: Some(16400), added: 18875, mode: `MaxEncodedLen`)
/// Storage: `ChildBounties::ChildBounties` (r:0 w:1)
/// Proof: `ChildBounties::ChildBounties` (`max_values`: None, `max_size`: Some(145), added: 2620, mode: `MaxEncodedLen`)
/// The range of component `d` is `[0, 16384]`.
fn add_child_bounty(d: u32, ) -> Weight {
// Proof Size summary in bytes:
// Measured: `541`
// Estimated: `6196`
// Minimum execution time: 291_192_000 picoseconds.
Weight::from_parts(296_557_773, 0)
.saturating_add(Weight::from_parts(0, 6196))
// Standard Error: 42
.saturating_add(Weight::from_parts(2_090, 0).saturating_mul(d.into()))
.saturating_add(T::DbWeight::get().reads(5))
.saturating_add(T::DbWeight::get().writes(6))
}
/// Storage: `Bounties::Bounties` (r:1 w:0)
/// Proof: `Bounties::Bounties` (`max_values`: None, `max_size`: Some(177), added: 2652, mode: `MaxEncodedLen`)
/// Storage: `ChildBounties::ChildBounties` (r:1 w:1)
/// Proof: `ChildBounties::ChildBounties` (`max_values`: None, `max_size`: Some(145), added: 2620, mode: `MaxEncodedLen`)
/// Storage: `ChildBounties::ChildrenCuratorFees` (r:1 w:1)
/// Proof: `ChildBounties::ChildrenCuratorFees` (`max_values`: None, `max_size`: Some(28), added: 2503, mode: `MaxEncodedLen`)
fn propose_curator() -> Weight {
// Proof Size summary in bytes:
// Measured: `595`
// Estimated: `3642`
// Minimum execution time: 69_659_000 picoseconds.
Weight::from_parts(70_289_000, 0)
.saturating_add(Weight::from_parts(0, 3642))
.saturating_add(T::DbWeight::get().reads(3))
.saturating_add(T::DbWeight::get().writes(2))
}
/// Storage: `Bounties::Bounties` (r:1 w:0)
/// Proof: `Bounties::Bounties` (`max_values`: None, `max_size`: Some(177), added: 2652, mode: `MaxEncodedLen`)
/// Storage: `ChildBounties::ChildBounties` (r:1 w:1)
/// Proof: `ChildBounties::ChildBounties` (`max_values`: None, `max_size`: Some(145), added: 2620, mode: `MaxEncodedLen`)
/// Storage: `System::Account` (r:1 w:1)
/// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`)
fn accept_curator() -> Weight {
// Proof Size summary in bytes:
// Measured: `741`
// Estimated: `3642`
// Minimum execution time: 135_004_000 picoseconds.
Weight::from_parts(135_738_000, 0)
.saturating_add(Weight::from_parts(0, 3642))
.saturating_add(T::DbWeight::get().reads(3))
.saturating_add(T::DbWeight::get().writes(2))
}
/// Storage: `ChildBounties::ChildBounties` (r:1 w:1)
/// Proof: `ChildBounties::ChildBounties` (`max_values`: None, `max_size`: Some(145), added: 2620, mode: `MaxEncodedLen`)
/// Storage: `Bounties::Bounties` (r:1 w:0)
/// Proof: `Bounties::Bounties` (`max_values`: None, `max_size`: Some(177), added: 2652, mode: `MaxEncodedLen`)
/// Storage: `System::Account` (r:1 w:1)
/// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`)
fn unassign_curator() -> Weight {
// Proof Size summary in bytes:
// Measured: `741`
// Estimated: `3642`
// Minimum execution time: 184_496_000 picoseconds.
Weight::from_parts(186_401_000, 0)
.saturating_add(Weight::from_parts(0, 3642))
.saturating_add(T::DbWeight::get().reads(3))
.saturating_add(T::DbWeight::get().writes(2))
}
/// Storage: `Bounties::Bounties` (r:1 w:0)
/// Proof: `Bounties::Bounties` (`max_values`: None, `max_size`: Some(177), added: 2652, mode: `MaxEncodedLen`)
/// Storage: `ChildBounties::ChildBounties` (r:1 w:1)
/// Proof: `ChildBounties::ChildBounties` (`max_values`: None, `max_size`: Some(145), added: 2620, mode: `MaxEncodedLen`)
fn award_child_bounty() -> Weight {
// Proof Size summary in bytes:
// Measured: `638`
// Estimated: `3642`
// Minimum execution time: 72_603_000 picoseconds.
Weight::from_parts(73_411_000, 0)
.saturating_add(Weight::from_parts(0, 3642))
.saturating_add(T::DbWeight::get().reads(2))
.saturating_add(T::DbWeight::get().writes(1))
}
/// Storage: `ChildBounties::ChildBounties` (r:1 w:1)
/// Proof: `ChildBounties::ChildBounties` (`max_values`: None, `max_size`: Some(145), added: 2620, mode: `MaxEncodedLen`)
/// Storage: `System::Account` (r:3 w:3)
/// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`)
/// Storage: `ChildBounties::ParentChildBounties` (r:1 w:1)
/// Proof: `ChildBounties::ParentChildBounties` (`max_values`: None, `max_size`: Some(16), added: 2491, mode: `MaxEncodedLen`)
/// Storage: `ChildBounties::ChildBountyDescriptions` (r:0 w:1)
/// Proof: `ChildBounties::ChildBountyDescriptions` (`max_values`: None, `max_size`: Some(16400), added: 18875, mode: `MaxEncodedLen`)
fn claim_child_bounty() -> Weight {
// Proof Size summary in bytes:
// Measured: `525`
// Estimated: `8799`
// Minimum execution time: 515_024_000 picoseconds.
Weight::from_parts(527_108_000, 0)
.saturating_add(Weight::from_parts(0, 8799))
.saturating_add(T::DbWeight::get().reads(5))
.saturating_add(T::DbWeight::get().writes(6))
}
/// Storage: `Bounties::Bounties` (r:1 w:0)
/// Proof: `Bounties::Bounties` (`max_values`: None, `max_size`: Some(177), added: 2652, mode: `MaxEncodedLen`)
/// Storage: `ChildBounties::ChildBounties` (r:1 w:1)
/// Proof: `ChildBounties::ChildBounties` (`max_values`: None, `max_size`: Some(145), added: 2620, mode: `MaxEncodedLen`)
/// Storage: `ChildBounties::ChildrenCuratorFees` (r:1 w:1)
/// Proof: `ChildBounties::ChildrenCuratorFees` (`max_values`: None, `max_size`: Some(28), added: 2503, mode: `MaxEncodedLen`)
/// Storage: `ChildBounties::ParentChildBounties` (r:1 w:1)
/// Proof: `ChildBounties::ParentChildBounties` (`max_values`: None, `max_size`: Some(16), added: 2491, mode: `MaxEncodedLen`)
/// Storage: `System::Account` (r:2 w:2)
/// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`)
/// Storage: `ChildBounties::ChildBountyDescriptions` (r:0 w:1)
/// Proof: `ChildBounties::ChildBountyDescriptions` (`max_values`: None, `max_size`: Some(16400), added: 18875, mode: `MaxEncodedLen`)
fn close_child_bounty_added() -> Weight {
// Proof Size summary in bytes:
// Measured: `841`
// Estimated: `6196`
// Minimum execution time: 330_763_000 picoseconds.
Weight::from_parts(334_197_000, 0)
.saturating_add(Weight::from_parts(0, 6196))
.saturating_add(T::DbWeight::get().reads(6))
.saturating_add(T::DbWeight::get().writes(6))
}
/// Storage: `Bounties::Bounties` (r:1 w:0)
/// Proof: `Bounties::Bounties` (`max_values`: None, `max_size`: Some(177), added: 2652, mode: `MaxEncodedLen`)
/// Storage: `ChildBounties::ChildBounties` (r:1 w:1)
/// Proof: `ChildBounties::ChildBounties` (`max_values`: None, `max_size`: Some(145), added: 2620, mode: `MaxEncodedLen`)
/// Storage: `System::Account` (r:3 w:3)
/// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`)
/// Storage: `ChildBounties::ChildrenCuratorFees` (r:1 w:1)
/// Proof: `ChildBounties::ChildrenCuratorFees` (`max_values`: None, `max_size`: Some(28), added: 2503, mode: `MaxEncodedLen`)
/// Storage: `ChildBounties::ParentChildBounties` (r:1 w:1)
/// Proof: `ChildBounties::ParentChildBounties` (`max_values`: None, `max_size`: Some(16), added: 2491, mode: `MaxEncodedLen`)
/// Storage: `ChildBounties::ChildBountyDescriptions` (r:0 w:1)
/// Proof: `ChildBounties::ChildBountyDescriptions` (`max_values`: None, `max_size`: Some(16400), added: 18875, mode: `MaxEncodedLen`)
fn close_child_bounty_active() -> Weight {
// Proof Size summary in bytes:
// Measured: `1028`
// Estimated: `8799`
// Minimum execution time: 405_094_000 picoseconds.
Weight::from_parts(416_868_000, 0)
.saturating_add(Weight::from_parts(0, 8799))
.saturating_add(T::DbWeight::get().reads(7))
.saturating_add(T::DbWeight::get().writes(7))
}
}

View File

@ -16,7 +16,7 @@
//! Autogenerated weights for `pallet_grandpa` //! Autogenerated weights for `pallet_grandpa`
//! //!
//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0
//! DATE: 2025-11-28, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! DATE: 2026-02-27, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]`
//! WORST CASE MAP SIZE: `1000000` //! WORST CASE MAP SIZE: `1000000`
//! HOSTNAME: `ghostown`, CPU: `Intel(R) Core(TM) i3-2310M CPU @ 2.10GHz` //! HOSTNAME: `ghostown`, CPU: `Intel(R) Core(TM) i3-2310M CPU @ 2.10GHz`
//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("casper-dev")`, DB CACHE: 1024 //! WASM-EXECUTION: `Compiled`, CHAIN: `Some("casper-dev")`, DB CACHE: 1024
@ -40,20 +40,51 @@
#![allow(unused_imports)] #![allow(unused_imports)]
#![allow(missing_docs)] #![allow(missing_docs)]
use frame_support::{traits::Get, weights::Weight};
use core::marker::PhantomData; use core::marker::PhantomData;
use frame_support::{
traits::Get,
weights::{
constants::{RocksDbWeight as DbWeight, WEIGHT_REF_TIME_PER_MICROS, WEIGHT_REF_TIME_PER_NANOS},
Weight,
},
};
/// Weight functions for `pallet_grandpa`. /// Weight functions for `pallet_grandpa`.
pub struct WeightInfo<T>(PhantomData<T>); pub struct WeightInfo<T>(PhantomData<T>);
impl<T: frame_system::Config> pallet_grandpa::WeightInfo for WeightInfo<T> { impl<T: frame_system::Config> pallet_grandpa::WeightInfo for WeightInfo<T> {
/// The range of component `x` is `[0, 1]`. fn report_equivocation(validator_count: u32, max_nominators_per_validator: u32) -> Weight {
fn check_equivocation_proof(_x: u32, ) -> Weight { // we take the validator set count from the membership proof to
// calculate the weight but we set a floor of 100 validators.
let validator_count = validator_count.max(100) as u64;
// Proof Size summary in bytes: // Proof Size summary in bytes:
// Measured: `0` // Measured: `0`
// Estimated: `0` // Estimated: `0`
// Minimum execution time: 271_935_000 picoseconds. // Minimum execution time: 272_018_000 picoseconds.
Weight::from_parts(273_848_983, 0) let check_equivocation_proof = Weight::from_parts(275_944_195, 0)
.saturating_add(Weight::from_parts(0, 0)) .saturating_add(Weight::from_parts(0, 0))
// Standard Error: 1_232_802
.saturating_add(Weight::from_parts(1_472_404, 0).saturating_mul(validator_count.into()));
// checking membership proof
Weight::from_parts(88u64 * WEIGHT_REF_TIME_PER_MICROS, 0)
.saturating_add(
Weight::from_parts(438u64 * WEIGHT_REF_TIME_PER_NANOS, 0)
.saturating_mul(validator_count),
)
.saturating_add(DbWeight::get().reads(5))
// check equivocation proof
.saturating_add(check_equivocation_proof)
// report offence
.saturating_add(check_equivocation_proof)
.saturating_add(Weight::from_parts(
63u64 * WEIGHT_REF_TIME_PER_MICROS * max_nominators_per_validator as u64,
0,
))
.saturating_add(DbWeight::get().reads(14 + 3 * max_nominators_per_validator as u64))
.saturating_add(DbWeight::get().writes(10 + 3 * max_nominators_per_validator as u64))
// fetching set id -> session index mappings
.saturating_add(DbWeight::get().reads(2))
} }
/// Storage: `Grandpa::Stalled` (r:0 w:1) /// Storage: `Grandpa::Stalled` (r:0 w:1)
/// Proof: `Grandpa::Stalled` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `MaxEncodedLen`) /// Proof: `Grandpa::Stalled` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `MaxEncodedLen`)
@ -61,8 +92,8 @@ impl<T: frame_system::Config> pallet_grandpa::WeightInfo for WeightInfo<T> {
// Proof Size summary in bytes: // Proof Size summary in bytes:
// Measured: `0` // Measured: `0`
// Estimated: `0` // Estimated: `0`
// Minimum execution time: 11_027_000 picoseconds. // Minimum execution time: 12_930_000 picoseconds.
Weight::from_parts(11_341_000, 0) Weight::from_parts(13_281_000, 0)
.saturating_add(Weight::from_parts(0, 0)) .saturating_add(Weight::from_parts(0, 0))
.saturating_add(T::DbWeight::get().writes(1)) .saturating_add(T::DbWeight::get().writes(1))
} }

View File

@ -16,7 +16,7 @@
//! Autogenerated weights for `pallet_treasury` //! Autogenerated weights for `pallet_treasury`
//! //!
//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0
//! DATE: 2024-08-01, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! DATE: 2026-02-28, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]`
//! WORST CASE MAP SIZE: `1000000` //! WORST CASE MAP SIZE: `1000000`
//! HOSTNAME: `ghostown`, CPU: `Intel(R) Core(TM) i3-2310M CPU @ 2.10GHz` //! HOSTNAME: `ghostown`, CPU: `Intel(R) Core(TM) i3-2310M CPU @ 2.10GHz`
//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("casper-dev")`, DB CACHE: 1024 //! WASM-EXECUTION: `Compiled`, CHAIN: `Some("casper-dev")`, DB CACHE: 1024
@ -29,7 +29,7 @@
// --steps=50 // --steps=50
// --repeat=20 // --repeat=20
// --pallet=pallet_treasury // --pallet=pallet_treasury
// --extrinsic=void_spend // --extrinsic=*
// --wasm-execution=compiled // --wasm-execution=compiled
// --heap-pages=4096 // --heap-pages=4096
// --header=./file_header.txt // --header=./file_header.txt
@ -46,14 +46,151 @@ use core::marker::PhantomData;
/// Weight functions for `pallet_treasury`. /// Weight functions for `pallet_treasury`.
pub struct WeightInfo<T>(PhantomData<T>); pub struct WeightInfo<T>(PhantomData<T>);
impl<T: frame_system::Config> pallet_treasury::WeightInfo for WeightInfo<T> { impl<T: frame_system::Config> pallet_treasury::WeightInfo for WeightInfo<T> {
/// Storage: `Treasury::ProposalCount` (r:1 w:1)
/// Proof: `Treasury::ProposalCount` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`)
/// Storage: `Treasury::Approvals` (r:1 w:1)
/// Proof: `Treasury::Approvals` (`max_values`: Some(1), `max_size`: Some(4002), added: 4497, mode: `MaxEncodedLen`)
/// Storage: `Treasury::Proposals` (r:0 w:1)
/// Proof: `Treasury::Proposals` (`max_values`: None, `max_size`: Some(108), added: 2583, mode: `MaxEncodedLen`)
fn spend_local() -> Weight {
// Proof Size summary in bytes:
// Measured: `6`
// Estimated: `5487`
// Minimum execution time: 52_840_000 picoseconds.
Weight::from_parts(54_220_000, 0)
.saturating_add(Weight::from_parts(0, 5487))
.saturating_add(T::DbWeight::get().reads(2))
.saturating_add(T::DbWeight::get().writes(3))
}
/// Storage: `Treasury::ProposalCount` (r:1 w:1)
/// Proof: `Treasury::ProposalCount` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`)
/// Storage: `Treasury::Proposals` (r:0 w:1)
/// Proof: `Treasury::Proposals` (`max_values`: None, `max_size`: Some(108), added: 2583, mode: `MaxEncodedLen`)
fn propose_spend() -> Weight {
// Proof Size summary in bytes:
// Measured: `107`
// Estimated: `1489`
// Minimum execution time: 119_927_000 picoseconds.
Weight::from_parts(120_611_000, 0)
.saturating_add(Weight::from_parts(0, 1489))
.saturating_add(T::DbWeight::get().reads(1))
.saturating_add(T::DbWeight::get().writes(2))
}
/// Storage: `Treasury::Proposals` (r:1 w:1)
/// Proof: `Treasury::Proposals` (`max_values`: None, `max_size`: Some(108), added: 2583, mode: `MaxEncodedLen`)
/// Storage: `System::Account` (r:1 w:1)
/// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`)
fn reject_proposal() -> Weight {
// Proof Size summary in bytes:
// Measured: `265`
// Estimated: `3593`
// Minimum execution time: 164_605_000 picoseconds.
Weight::from_parts(165_648_000, 0)
.saturating_add(Weight::from_parts(0, 3593))
.saturating_add(T::DbWeight::get().reads(2))
.saturating_add(T::DbWeight::get().writes(2))
}
/// Storage: `Treasury::Proposals` (r:1 w:0)
/// Proof: `Treasury::Proposals` (`max_values`: None, `max_size`: Some(108), added: 2583, mode: `MaxEncodedLen`)
/// Storage: `Treasury::Approvals` (r:1 w:1)
/// Proof: `Treasury::Approvals` (`max_values`: Some(1), `max_size`: Some(4002), added: 4497, mode: `MaxEncodedLen`)
/// The range of component `p` is `[0, 999]`.
fn approve_proposal(p: u32, ) -> Weight {
// Proof Size summary in bytes:
// Measured: `800 + p * (4 ±0)`
// Estimated: `5487`
// Minimum execution time: 38_600_000 picoseconds.
Weight::from_parts(54_379_372, 0)
.saturating_add(Weight::from_parts(0, 5487))
// Standard Error: 669
.saturating_add(Weight::from_parts(34_439, 0).saturating_mul(p.into()))
.saturating_add(T::DbWeight::get().reads(2))
.saturating_add(T::DbWeight::get().writes(1))
}
/// Storage: `Treasury::Approvals` (r:1 w:1)
/// Proof: `Treasury::Approvals` (`max_values`: Some(1), `max_size`: Some(4002), added: 4497, mode: `MaxEncodedLen`)
fn remove_approval() -> Weight {
// Proof Size summary in bytes:
// Measured: `90`
// Estimated: `5487`
// Minimum execution time: 28_269_000 picoseconds.
Weight::from_parts(28_811_000, 0)
.saturating_add(Weight::from_parts(0, 5487))
.saturating_add(T::DbWeight::get().reads(1))
.saturating_add(T::DbWeight::get().writes(1))
}
/// Storage: `Treasury::Deactivated` (r:1 w:1)
/// Proof: `Treasury::Deactivated` (`max_values`: Some(1), `max_size`: Some(16), added: 511, mode: `MaxEncodedLen`)
/// Storage: `Treasury::Approvals` (r:1 w:1)
/// Proof: `Treasury::Approvals` (`max_values`: Some(1), `max_size`: Some(4002), added: 4497, mode: `MaxEncodedLen`)
/// Storage: `Treasury::Proposals` (r:998 w:998)
/// Proof: `Treasury::Proposals` (`max_values`: None, `max_size`: Some(108), added: 2583, mode: `MaxEncodedLen`)
/// Storage: `System::Account` (r:1996 w:1996)
/// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`)
/// Storage: `Bounties::BountyApprovals` (r:1 w:1)
/// Proof: `Bounties::BountyApprovals` (`max_values`: Some(1), `max_size`: Some(4002), added: 4497, mode: `MaxEncodedLen`)
/// The range of component `p` is `[0, 999]`.
fn on_initialize_proposals(p: u32, ) -> Weight {
// Proof Size summary in bytes:
// Measured: `0 + p * (255 ±0)`
// Estimated: `5487 + p * (5206 ±0)`
// Minimum execution time: 93_001_000 picoseconds.
Weight::from_parts(93_875_000, 0)
.saturating_add(Weight::from_parts(0, 5487))
// Standard Error: 106_483
.saturating_add(Weight::from_parts(173_774_586, 0).saturating_mul(p.into()))
.saturating_add(T::DbWeight::get().reads(3))
.saturating_add(T::DbWeight::get().reads((3_u64).saturating_mul(p.into())))
.saturating_add(T::DbWeight::get().writes(3))
.saturating_add(T::DbWeight::get().writes((3_u64).saturating_mul(p.into())))
.saturating_add(Weight::from_parts(0, 5206).saturating_mul(p.into()))
}
/// Storage: `Treasury::SpendCount` (r:1 w:1)
/// Proof: `Treasury::SpendCount` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`)
/// Storage: `Treasury::Spends` (r:0 w:1)
/// Proof: `Treasury::Spends` (`max_values`: None, `max_size`: Some(69), added: 2544, mode: `MaxEncodedLen`)
fn spend() -> Weight {
// Proof Size summary in bytes:
// Measured: `6`
// Estimated: `1489`
// Minimum execution time: 47_856_000 picoseconds.
Weight::from_parts(49_457_000, 0)
.saturating_add(Weight::from_parts(0, 1489))
.saturating_add(T::DbWeight::get().reads(1))
.saturating_add(T::DbWeight::get().writes(2))
}
/// Storage: `Treasury::Spends` (r:1 w:1)
/// Proof: `Treasury::Spends` (`max_values`: None, `max_size`: Some(69), added: 2544, mode: `MaxEncodedLen`)
fn payout() -> Weight {
// Proof Size summary in bytes:
// Measured: `124`
// Estimated: `3534`
// Minimum execution time: 54_017_000 picoseconds.
Weight::from_parts(54_712_000, 0)
.saturating_add(Weight::from_parts(0, 3534))
.saturating_add(T::DbWeight::get().reads(1))
.saturating_add(T::DbWeight::get().writes(1))
}
/// Storage: `Treasury::Spends` (r:1 w:1)
/// Proof: `Treasury::Spends` (`max_values`: None, `max_size`: Some(69), added: 2544, mode: `MaxEncodedLen`)
fn check_status() -> Weight {
// Proof Size summary in bytes:
// Measured: `124`
// Estimated: `3534`
// Minimum execution time: 53_415_000 picoseconds.
Weight::from_parts(57_185_000, 0)
.saturating_add(Weight::from_parts(0, 3534))
.saturating_add(T::DbWeight::get().reads(1))
.saturating_add(T::DbWeight::get().writes(1))
}
/// Storage: `Treasury::Spends` (r:1 w:1) /// Storage: `Treasury::Spends` (r:1 w:1)
/// Proof: `Treasury::Spends` (`max_values`: None, `max_size`: Some(69), added: 2544, mode: `MaxEncodedLen`) /// Proof: `Treasury::Spends` (`max_values`: None, `max_size`: Some(69), added: 2544, mode: `MaxEncodedLen`)
fn void_spend() -> Weight { fn void_spend() -> Weight {
// Proof Size summary in bytes: // Proof Size summary in bytes:
// Measured: `124` // Measured: `124`
// Estimated: `3534` // Estimated: `3534`
// Minimum execution time: 77_449_000 picoseconds. // Minimum execution time: 50_317_000 picoseconds.
Weight::from_parts(88_782_000, 0) Weight::from_parts(51_617_000, 0)
.saturating_add(Weight::from_parts(0, 3534)) .saturating_add(Weight::from_parts(0, 3534))
.saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().reads(1))
.saturating_add(T::DbWeight::get().writes(1)) .saturating_add(T::DbWeight::get().writes(1))

View File

@ -211,10 +211,12 @@ fn casper_testnet_evm_networks() -> Vec<(u32, Vec<u8>, u128)> {
avg_block_speed: 12_000, avg_block_speed: 12_000,
network_type: ghost_networks::NetworkType::Evm, network_type: ghost_networks::NetworkType::Evm,
gatekeeper: "0xc85129A097773B7F8970a7364c928C05f265E6A1".into(), gatekeeper: "0xc85129A097773B7F8970a7364c928C05f265E6A1".into(),
topic_name: "0x7ab52ec05c331e6257a3d705d6bea6e4c27277351764ad139209e06b203811a6".into(), topic_name: "0x7ab52ec05c331e6257a3d705d6bea6e4c27277351764ad139209e06b203811a6"
.into(),
incoming_fee: 69_000_000u32, incoming_fee: 69_000_000u32,
outgoing_fee: 0u32, outgoing_fee: 0u32,
}.encode(), }
.encode(),
2048861035254140036511u128, 2048861035254140036511u128,
), ),
( (
@ -232,10 +234,12 @@ fn casper_testnet_evm_networks() -> Vec<(u32, Vec<u8>, u128)> {
avg_block_speed: 13_000, avg_block_speed: 13_000,
network_type: ghost_networks::NetworkType::Evm, network_type: ghost_networks::NetworkType::Evm,
gatekeeper: "0xA59cB4ff90bE2206121aE61eEB68d0AeC7BA095f".into(), gatekeeper: "0xA59cB4ff90bE2206121aE61eEB68d0AeC7BA095f".into(),
topic_name: "0x7ab52ec05c331e6257a3d705d6bea6e4c27277351764ad139209e06b203811a6".into(), topic_name: "0x7ab52ec05c331e6257a3d705d6bea6e4c27277351764ad139209e06b203811a6"
.into(),
incoming_fee: 69_000_000u32, incoming_fee: 69_000_000u32,
outgoing_fee: 0u32, outgoing_fee: 0u32,
}.encode(), }
.encode(),
5100000000000000000u128, 5100000000000000000u128,
), ),
] ]