Compare commits
No commits in common. "5dd0c73f7a56a54b82cc69206a6e364a25b10ee0" and "cce2910cf860c6537bedaa54661aaba15d43f203" have entirely different histories.
5dd0c73f7a
...
cce2910cf8
@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "ghost-networks"
|
name = "ghost-networks"
|
||||||
version = "0.1.23"
|
version = "0.1.20"
|
||||||
license.workspace = true
|
license.workspace = true
|
||||||
authors.workspace = true
|
authors.workspace = true
|
||||||
edition.workspace = true
|
edition.workspace = true
|
||||||
|
|||||||
@ -85,15 +85,13 @@ 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)?;
|
||||||
assert_eq!(GhostNetworks::<T>::networks(chain_id.clone()), None);
|
let prev_network = GhostNetworks::<T>::networks(chain_id.clone());
|
||||||
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: network.clone(),
|
chain_id: chain_id.clone(), network,
|
||||||
}.into());
|
}.into());
|
||||||
assert_eq!(GhostNetworks::<T>::networks(chain_id.clone()), Some(network));
|
assert_ne!(GhostNetworks::<T>::networks(chain_id.clone()), prev_network);
|
||||||
assert_eq!(GhostNetworks::<T>::network_indexes(), vec![chain_id]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
update_network_name {
|
update_network_name {
|
||||||
@ -253,23 +251,20 @@ 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()), None);
|
assert_ne!(GhostNetworks::<T>::networks(chain_id.clone()), prev_network);
|
||||||
}
|
}
|
||||||
|
|
||||||
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 _ = create_network::<T>(chain_id.clone(), network.clone())?;
|
let prev_network = 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_eq!(GhostNetworks::<T>::networks(chain_id.clone()), None);
|
assert_ne!(GhostNetworks::<T>::networks(chain_id.clone()), prev_network);
|
||||||
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);
|
||||||
|
|||||||
@ -12,7 +12,7 @@ use scale_info::TypeInfo;
|
|||||||
|
|
||||||
use sp_runtime::{
|
use sp_runtime::{
|
||||||
curve::PiecewiseLinear,
|
curve::PiecewiseLinear,
|
||||||
traits::{AtLeast32BitUnsigned, CheckedAdd, CheckedSub, Member, UniqueSaturatedInto},
|
traits::{AtLeast32BitUnsigned, CheckedAdd, CheckedSub, Member},
|
||||||
DispatchResult,
|
DispatchResult,
|
||||||
};
|
};
|
||||||
use sp_std::{convert::TryInto, prelude::*};
|
use sp_std::{convert::TryInto, prelude::*};
|
||||||
@ -21,10 +21,12 @@ pub use ghost_traits::networks::{
|
|||||||
NetworkDataBasicHandler, NetworkDataInspectHandler, NetworkDataMutateHandler,
|
NetworkDataBasicHandler, NetworkDataInspectHandler, NetworkDataMutateHandler,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
mod math;
|
||||||
pub mod migrations;
|
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))]
|
||||||
@ -97,26 +99,23 @@ 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>::take();
|
let bridged_imbalance = BridgedImbalance::<T>::get();
|
||||||
let accumulated_commission = AccumulatedCommission::<T>::take();
|
let accumulated_commission = AccumulatedCommission::<T>::get();
|
||||||
|
|
||||||
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(
|
||||||
let payout: Balance = sp_runtime::helpers_128bit::multiply_by_rational_with_rounding(
|
estimated_reward,
|
||||||
estimated_reward.unique_saturated_into(),
|
accumulated_commission,
|
||||||
accumulated_commission.unique_saturated_into(),
|
adjusted_issuance,
|
||||||
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)
|
||||||
@ -241,6 +240,10 @@ 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> =
|
||||||
@ -298,6 +301,20 @@ pub mod module {
|
|||||||
#[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)]
|
||||||
@ -737,7 +754,9 @@ impl<T: Config> NetworkDataInspectHandler<NetworkData> for Pallet<T> {
|
|||||||
Networks::<T>::get(n)
|
Networks::<T>::get(n)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn network_for_block(block_number: impl Into<usize>) -> Option<(Self::NetworkId, NetworkData)> {
|
fn next_network_for_block(
|
||||||
|
block_number: impl Into<usize>,
|
||||||
|
) -> Option<(Self::NetworkId, NetworkData)> {
|
||||||
let network_indexes = NetworkIndexes::<T>::get();
|
let network_indexes = NetworkIndexes::<T>::get();
|
||||||
block_number
|
block_number
|
||||||
.into()
|
.into()
|
||||||
@ -753,6 +772,10 @@ impl<T: Config> NetworkDataInspectHandler<NetworkData> for Pallet<T> {
|
|||||||
fn iter() -> PrefixIterator<(Self::NetworkId, NetworkData)> {
|
fn iter() -> PrefixIterator<(Self::NetworkId, NetworkData)> {
|
||||||
Networks::<T>::iter()
|
Networks::<T>::iter()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn is_nullification_period() -> bool {
|
||||||
|
NullifyNeeded::<T>::get()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: Config> NetworkDataMutateHandler<NetworkData, BalanceOf<T>> for Pallet<T> {
|
impl<T: Config> NetworkDataMutateHandler<NetworkData, BalanceOf<T>> for Pallet<T> {
|
||||||
@ -839,4 +862,18 @@ 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
134
pallets/networks/src/math.rs
Normal file
134
pallets/networks/src/math.rs
Normal file
@ -0,0 +1,134 @@
|
|||||||
|
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)
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,11 +1,10 @@
|
|||||||
use frame_support::{
|
use frame_support::{
|
||||||
migration::clear_storage_prefix,
|
traits::{Get, UncheckedOnRuntimeUpgrade},
|
||||||
traits::{Get, PalletInfoAccess, UncheckedOnRuntimeUpgrade},
|
|
||||||
weights::Weight,
|
weights::Weight,
|
||||||
};
|
};
|
||||||
use sp_std::marker::PhantomData;
|
use sp_std::marker::PhantomData;
|
||||||
|
|
||||||
use crate::{BoundedVec, Config, NetworkIndexes, Networks, Pallet, Vec, LOG_TARGET};
|
use crate::{BoundedVec, Config, NetworkIndexes, Networks, Vec, LOG_TARGET};
|
||||||
|
|
||||||
pub struct StoreNetworkIdsIntoBoundedVec<T>(PhantomData<T>);
|
pub struct StoreNetworkIdsIntoBoundedVec<T>(PhantomData<T>);
|
||||||
impl<T: Config> UncheckedOnRuntimeUpgrade for StoreNetworkIdsIntoBoundedVec<T> {
|
impl<T: Config> UncheckedOnRuntimeUpgrade for StoreNetworkIdsIntoBoundedVec<T> {
|
||||||
@ -17,28 +16,11 @@ impl<T: Config> UncheckedOnRuntimeUpgrade for StoreNetworkIdsIntoBoundedVec<T> {
|
|||||||
|
|
||||||
weight = weight.saturating_add(T::DbWeight::get().reads(networks_count as u64));
|
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)
|
let writes = BoundedVec::<T::NetworkId, T::MaxNetworks>::try_from(network_ids)
|
||||||
.inspect_err(|err| {
|
.inspect_err(|err| {
|
||||||
log::error!(
|
log::error!(
|
||||||
target: LOG_TARGET,
|
target: LOG_TARGET,
|
||||||
"⛓️ Network ids to bounded_vec migration failed: {:?}",
|
"⛓️ Network ids to bounded_vec migration failed: {:?}",
|
||||||
err,
|
err,
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
@ -47,7 +29,7 @@ impl<T: Config> UncheckedOnRuntimeUpgrade for StoreNetworkIdsIntoBoundedVec<T> {
|
|||||||
NetworkIndexes::<T>::put(bounded_networks);
|
NetworkIndexes::<T>::put(bounded_networks);
|
||||||
log::info!(
|
log::info!(
|
||||||
target: LOG_TARGET,
|
target: LOG_TARGET,
|
||||||
"⛓️ Network ids to bounded_vec migration success: {} networks moved",
|
"⛓️ Network ids to bounded_vec migration success: {} networks moved",
|
||||||
networks_count,
|
networks_count,
|
||||||
);
|
);
|
||||||
1u64
|
1u64
|
||||||
|
|||||||
@ -82,7 +82,6 @@ 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! {
|
||||||
@ -99,7 +98,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 MaxNetworks = ConstU32<3>;
|
||||||
type WeightInfo = ();
|
type WeightInfo = ();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -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, MaxNetworks, RandomAccount, RegistererAccount, RemoverAccount,
|
ExtBuilder, GhostNetworks, RandomAccount, RegistererAccount, RemoverAccount, RewardCurve,
|
||||||
RewardCurve, RuntimeEvent, RuntimeOrigin, System, Test, UpdaterAccount,
|
RuntimeEvent, RuntimeOrigin, System, Test, UpdaterAccount,
|
||||||
};
|
};
|
||||||
use pallet_staking::EraPayout;
|
use pallet_staking::EraPayout;
|
||||||
use sp_runtime::DispatchError;
|
use sp_runtime::DispatchError;
|
||||||
@ -1278,7 +1278,7 @@ fn bridged_amount_overflow_and_underflow_emits_error() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn accumulated_commission_nullified_after_era_payout() {
|
fn accumulated_commission_could_be_nullified() {
|
||||||
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;
|
||||||
@ -1292,20 +1292,12 @@ fn accumulated_commission_nullified_after_era_payout() {
|
|||||||
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
|
||||||
);
|
);
|
||||||
assert_eq!(
|
GhostNetworks::nullify_commission();
|
||||||
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)
|
|
||||||
);
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1393,6 +1385,7 @@ 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,
|
||||||
@ -1401,9 +1394,6 @@ 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,
|
||||||
@ -1412,9 +1402,6 @@ 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,
|
||||||
@ -1424,8 +1411,6 @@ 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,
|
||||||
@ -1434,9 +1419,6 @@ 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(
|
||||||
@ -1446,9 +1428,6 @@ 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(
|
||||||
@ -1458,10 +1437,8 @@ 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(
|
||||||
1,
|
1,
|
||||||
@ -1470,9 +1447,6 @@ 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(
|
||||||
@ -1482,9 +1456,6 @@ 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(
|
||||||
@ -1494,8 +1465,10 @@ 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,
|
||||||
@ -1574,7 +1547,7 @@ fn bridged_inlation_reward_works() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn bridged_inflation_era_payout_clears_storage() {
|
fn bridged_inflation_era_payout_triggers_need_of_nullification() {
|
||||||
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
|
||||||
@ -1585,13 +1558,7 @@ fn bridged_inflation_era_payout_clears_storage() {
|
|||||||
|
|
||||||
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,
|
||||||
@ -1600,8 +1567,37 @@ fn bridged_inflation_era_payout_clears_storage() {
|
|||||||
),
|
),
|
||||||
(commission, 0)
|
(commission, 0)
|
||||||
);
|
);
|
||||||
assert_eq!(BridgedImbalance::<Test>::get(), Default::default());
|
assert_eq!(NullifyNeeded::<Test>::get(), true);
|
||||||
assert_eq!(AccumulatedCommission::<Test>::get(), Default::default());
|
GhostNetworks::on_finalize(69);
|
||||||
|
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());
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1677,6 +1673,123 @@ 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(|| {
|
||||||
@ -1684,6 +1797,7 @@ 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);
|
||||||
@ -1692,10 +1806,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,
|
||||||
@ -1716,6 +1830,27 @@ 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);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -1778,17 +1913,6 @@ fn migration_from_v0_to_v1_works() {
|
|||||||
let (chain_id, network) = prepare_network_data();
|
let (chain_id, network) = prepare_network_data();
|
||||||
let other_chain_id = chain_id.saturating_add(1);
|
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_eq!(Networks::<Test>::get(chain_id), None);
|
||||||
assert_ok!(GhostNetworks::register_network(
|
assert_ok!(GhostNetworks::register_network(
|
||||||
RuntimeOrigin::signed(RegistererAccount::get()),
|
RuntimeOrigin::signed(RegistererAccount::get()),
|
||||||
@ -1802,15 +1926,12 @@ fn migration_from_v0_to_v1_works() {
|
|||||||
));
|
));
|
||||||
NetworkIndexes::<Test>::kill();
|
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(chain_id), Some(network.clone()));
|
||||||
assert_eq!(Networks::<Test>::get(other_chain_id), Some(network));
|
assert_eq!(Networks::<Test>::get(other_chain_id), Some(network));
|
||||||
assert_eq!(NetworkIndexes::<Test>::get(), vec![]);
|
assert_eq!(NetworkIndexes::<Test>::get(), vec![]);
|
||||||
|
|
||||||
type Migrate = crate::migrations::MigrateV0ToV1<Test>;
|
type Migrate = crate::migrations::MigrateV0ToV1<Test>;
|
||||||
<Migrate as frame_support::traits::OnRuntimeUpgrade>::on_runtime_upgrade();
|
<Migrate as frame_support::traits::OnRuntimeUpgrade>::on_runtime_upgrade();
|
||||||
|
|
||||||
assert!(!frame_support::storage::unhashed::exists(&key));
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
NetworkIndexes::<Test>::get(),
|
NetworkIndexes::<Test>::get(),
|
||||||
vec![chain_id, other_chain_id]
|
vec![chain_id, other_chain_id]
|
||||||
@ -1818,32 +1939,6 @@ fn migration_from_v0_to_v1_works() {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
#[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]
|
#[test]
|
||||||
fn migration_from_v0_to_v1_does_not_run_twice() {
|
fn migration_from_v0_to_v1_does_not_run_twice() {
|
||||||
ExtBuilder::build().execute_with(|| {
|
ExtBuilder::build().execute_with(|| {
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "ghost-slow-clap"
|
name = "ghost-slow-clap"
|
||||||
version = "0.4.16"
|
version = "0.4.15"
|
||||||
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
|
||||||
|
|||||||
@ -28,7 +28,7 @@ use sp_runtime::{
|
|||||||
storage::StorageValueRef,
|
storage::StorageValueRef,
|
||||||
storage_lock::{StorageLock, Time},
|
storage_lock::{StorageLock, Time},
|
||||||
},
|
},
|
||||||
traits::{BlockNumberProvider, Convert, Saturating, UniqueSaturatedInto},
|
traits::{BlockNumberProvider, Convert, Saturating},
|
||||||
Perbill, RuntimeAppPublic, RuntimeDebug,
|
Perbill, RuntimeAppPublic, RuntimeDebug,
|
||||||
};
|
};
|
||||||
use sp_staking::{
|
use sp_staking::{
|
||||||
@ -80,7 +80,6 @@ const LOCK_BLOCK_EXPIRATION: u64 = 20;
|
|||||||
|
|
||||||
const COMMITMENT_DELAY_MILLIS: u64 = 600_000;
|
const COMMITMENT_DELAY_MILLIS: u64 = 600_000;
|
||||||
const ONE_HOUR_MILLIS: u64 = 3_600_000;
|
const ONE_HOUR_MILLIS: u64 = 3_600_000;
|
||||||
const CHECK_BLOCK_INTERVAL: u64 = 300;
|
|
||||||
|
|
||||||
pub type AuthIndex = u32;
|
pub type AuthIndex = u32;
|
||||||
|
|
||||||
@ -348,10 +347,6 @@ pub mod pallet {
|
|||||||
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]
|
||||||
@ -475,68 +470,6 @@ 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 {
|
|
||||||
// TODO: what about start of the session???
|
|
||||||
let mut weight = T::DbWeight::get().reads(1);
|
|
||||||
|
|
||||||
let networks_count = T::NetworkDataHandler::count();
|
|
||||||
let current_block_number: u64 = current_block.unique_saturated_into();
|
|
||||||
//let cycle_start = (current_block_number / CHECK_BLOCK_INTERVAL) * CHECK_BLOCK_INTERVAL;
|
|
||||||
let cycle_offset = current_block_number % CHECK_BLOCK_INTERVAL;
|
|
||||||
|
|
||||||
if cycle_offset >= networks_count.into() {
|
|
||||||
return Default::default();
|
|
||||||
}
|
|
||||||
|
|
||||||
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 = weight.saturating_add(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);
|
|
||||||
|
|
||||||
if validators.len() == 0 {
|
|
||||||
return weight;
|
|
||||||
}
|
|
||||||
|
|
||||||
let disabled_bitmap = DisabledAuthorityIndexes::<T>::get(&session_index)
|
|
||||||
.unwrap_or(BitMap::new(validators.len() as u32));
|
|
||||||
|
|
||||||
let max_block_deviation = ONE_HOUR_MILLIS
|
|
||||||
.saturating_mul(6) // TODO: make it constant or calculate
|
|
||||||
.saturating_div(network_data.avg_block_speed);
|
|
||||||
|
|
||||||
let offence_bitmap = Self::capture_deviation_in_commitments_and_remove(
|
|
||||||
&disabled_bitmap,
|
|
||||||
&block_commitments,
|
|
||||||
&validators,
|
|
||||||
max_block_deviation,
|
|
||||||
);
|
|
||||||
|
|
||||||
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 = weight.saturating_add(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(_) => {
|
||||||
@ -762,6 +695,10 @@ 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()
|
||||||
@ -803,35 +740,73 @@ impl<T: Config> Pallet<T> {
|
|||||||
Error::<T>::CommitInWrongSession,
|
Error::<T>::CommitInWrongSession,
|
||||||
);
|
);
|
||||||
|
|
||||||
BlockCommitments::<T>::try_mutate(&network_id, |current_commitments| -> DispatchResult {
|
let block_commitments = BlockCommitments::<T>::try_mutate(
|
||||||
let mut new_commitment_details = new_commitment.commitment;
|
&network_id,
|
||||||
|
|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(COMMITMENT_DELAY_MILLIS),
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
.unwrap_or((1, 0));
|
.unwrap_or((1, 0));
|
||||||
|
|
||||||
ensure!(
|
ensure!(
|
||||||
new_commitment_details.last_updated > current_last_updated,
|
new_commitment_details.last_updated > current_last_updated,
|
||||||
Error::<T>::TimeWentBackwards
|
Error::<T>::TimeWentBackwards
|
||||||
);
|
);
|
||||||
|
|
||||||
new_commitment_details.commits = current_commits;
|
new_commitment_details.commits = current_commits;
|
||||||
current_commitments.insert(authority_index, new_commitment_details);
|
current_commitments.insert(authority_index, new_commitment_details);
|
||||||
|
|
||||||
Ok(())
|
Ok(current_commitments.clone())
|
||||||
})?;
|
},
|
||||||
|
)?;
|
||||||
|
|
||||||
|
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(())
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1419,7 +1394,7 @@ 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 validator_set_count = validators.len() as u32;
|
||||||
|
|
||||||
let offenders = validators
|
let offenders = validators
|
||||||
@ -1442,17 +1417,16 @@ impl<T: Config> Pallet<T> {
|
|||||||
|
|
||||||
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 T::DbWeight::get().writes(1);
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let offenders_len = offenders.len() as u32;
|
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 T::DbWeight::get().writes(1);
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let offence_event = match offence_type {
|
let offence_event = match offence_type {
|
||||||
@ -1486,8 +1460,6 @@ impl<T: Config> Pallet<T> {
|
|||||||
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
T::WeightInfo::try_offend_validators(offenders_len)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -130,7 +130,6 @@ 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 {
|
||||||
@ -140,7 +139,6 @@ 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 = ();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,9 +1,6 @@
|
|||||||
#![cfg(test)]
|
#![cfg(test)]
|
||||||
|
|
||||||
use std::{
|
use std::time::{SystemTime, UNIX_EPOCH};
|
||||||
collections::HashMap,
|
|
||||||
time::{SystemTime, UNIX_EPOCH},
|
|
||||||
};
|
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::evm_types::Log;
|
use crate::evm_types::Log;
|
||||||
@ -895,6 +892,7 @@ 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!(
|
||||||
@ -905,13 +903,63 @@ 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);
|
||||||
@ -1146,7 +1194,6 @@ fn should_disable_on_commitment_inactivity() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SlowClap::on_initialize(CHECK_BLOCK_INTERVAL);
|
|
||||||
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)],
|
||||||
@ -1212,7 +1259,6 @@ fn should_disable_on_commitment_block_deviation() {
|
|||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
SlowClap::on_initialize(CHECK_BLOCK_INTERVAL);
|
|
||||||
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)],
|
||||||
@ -1326,7 +1372,6 @@ fn should_not_offend_disabled_authorities() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SlowClap::on_initialize(CHECK_BLOCK_INTERVAL);
|
|
||||||
System::assert_has_event(RuntimeEvent::SlowClap(
|
System::assert_has_event(RuntimeEvent::SlowClap(
|
||||||
crate::Event::AuthoritiesCommitmentEquilibrium,
|
crate::Event::AuthoritiesCommitmentEquilibrium,
|
||||||
));
|
));
|
||||||
@ -1372,7 +1417,6 @@ fn should_not_slash_by_applause_if_disabled_by_commitment() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SlowClap::on_initialize(CHECK_BLOCK_INTERVAL);
|
|
||||||
System::assert_has_event(RuntimeEvent::SlowClap(
|
System::assert_has_event(RuntimeEvent::SlowClap(
|
||||||
crate::Event::AuthoritiesCommitmentEquilibrium,
|
crate::Event::AuthoritiesCommitmentEquilibrium,
|
||||||
));
|
));
|
||||||
@ -1457,7 +1501,6 @@ fn should_split_commit_slash_between_active_validators() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SlowClap::on_initialize(CHECK_BLOCK_INTERVAL);
|
|
||||||
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)],
|
||||||
@ -1465,7 +1508,7 @@ fn should_split_commit_slash_between_active_validators() {
|
|||||||
));
|
));
|
||||||
|
|
||||||
let offences = Offences::get();
|
let offences = Offences::get();
|
||||||
assert_eq!(offences.len(), 1);
|
assert_eq!(offences.len(), 3);
|
||||||
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);
|
||||||
@ -1477,55 +1520,6 @@ fn should_split_commit_slash_between_active_validators() {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
#[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 check_interval = times * CHECK_BLOCK_INTERVAL;
|
|
||||||
for check_block in 0..check_interval {
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
let expected_events = networks_count * (times as u32);
|
|
||||||
assert_eq!(total_number_of_events, expected_events as usize);
|
|
||||||
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();
|
|
||||||
assert_eq!(*network_id_count, times);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn should_check_responses_correctly() {
|
fn should_check_responses_correctly() {
|
||||||
new_test_ext().execute_with(|| {
|
new_test_ext().execute_with(|| {
|
||||||
@ -1890,7 +1884,6 @@ 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(),
|
||||||
@ -1904,7 +1897,6 @@ 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,
|
||||||
@ -1959,7 +1951,6 @@ 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()),
|
||||||
@ -1977,7 +1968,6 @@ 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()),
|
||||||
|
|||||||
@ -49,7 +49,6 @@ 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(offenders_len: u32) -> Weight;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl WeightInfo for () {
|
impl WeightInfo for () {
|
||||||
@ -87,8 +86,4 @@ impl WeightInfo for () {
|
|||||||
fn commit_block()-> Weight {
|
fn commit_block()-> Weight {
|
||||||
Default::default()
|
Default::default()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn try_offend_validators(offenders_len: u32) -> Weight {
|
|
||||||
Default::default()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "ghost-traits"
|
name = "ghost-traits"
|
||||||
version = "0.3.29"
|
version = "0.3.27"
|
||||||
license.workspace = true
|
license.workspace = true
|
||||||
authors.workspace = true
|
authors.workspace = true
|
||||||
edition.workspace = true
|
edition.workspace = true
|
||||||
|
|||||||
@ -17,9 +17,10 @@ pub trait NetworkDataBasicHandler {
|
|||||||
|
|
||||||
pub trait NetworkDataInspectHandler<Network>: NetworkDataBasicHandler {
|
pub trait NetworkDataInspectHandler<Network>: NetworkDataBasicHandler {
|
||||||
fn count() -> u32;
|
fn count() -> u32;
|
||||||
fn network_for_block(b: impl Into<usize>) -> Option<(Self::NetworkId, Network)>;
|
fn next_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;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait NetworkDataMutateHandler<Network, Balance>: NetworkDataInspectHandler<Network> {
|
pub trait NetworkDataMutateHandler<Network, Balance>: NetworkDataInspectHandler<Network> {
|
||||||
@ -37,5 +38,8 @@ 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();
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user