Skip to content

Commit

Permalink
clean-outdated-vbl (#1218)
Browse files Browse the repository at this point in the history
  • Loading branch information
herryho authored Apr 1, 2024
1 parent a99333a commit 63f81c3
Show file tree
Hide file tree
Showing 7 changed files with 216 additions and 1 deletion.
22 changes: 22 additions & 0 deletions pallets/slp/src/benchmarking.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1083,6 +1083,28 @@ mod benchmarks {
Ok(())
}

#[benchmark]
fn clean_outdated_validator_boost_list() -> Result<(), BenchmarkError> {
let origin = <T as Config>::ControlOrigin::try_successful_origin()
.map_err(|_| BenchmarkError::Weightless)?;
set_mins_and_maxs::<T>(origin.clone());

frame_system::Pallet::<T>::set_block_number(1u32.into());

assert_ok!(Pallet::<T>::add_to_validator_boost_list(
origin.clone() as <T as frame_system::Config>::RuntimeOrigin,
KSM,
Box::new(DELEGATOR1)
));

frame_system::Pallet::<T>::set_block_number((1 + SIX_MONTHS).into());

#[extrinsic_call]
_(origin as <T as frame_system::Config>::RuntimeOrigin, KSM, 1u8);

Ok(())
}

// `cargo test -p bifrost-slp --all-features`
impl_benchmark_test_suite!(
Pallet,
Expand Down
77 changes: 77 additions & 0 deletions pallets/slp/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ use bifrost_stable_pool::traits::StablePoolHandler;
use cumulus_primitives_core::{relay_chain::HashT, ParaId};
use frame_support::{pallet_prelude::*, traits::Contains, weights::Weight};
use frame_system::{
ensure_signed,
pallet_prelude::{BlockNumberFor, OriginFor},
RawOrigin,
};
Expand Down Expand Up @@ -90,6 +91,7 @@ pub type CurrencyIdOf<T> = <<T as Config>::MultiCurrency as MultiCurrency<
<T as frame_system::Config>::AccountId,
>>::CurrencyId;
const SIX_MONTHS: u32 = 5 * 60 * 24 * 180;
const ITERATE_LENGTH: usize = 100;

#[frame_support::pallet]
pub mod pallet {
Expand Down Expand Up @@ -268,6 +270,8 @@ pub mod pallet {
StablePoolNotFound,
StablePoolTokenIndexNotFound,
ExceedLimit,
InvalidPageNumber,
NoMoreValidatorBoostListForCurrency,
}

#[pallet::event]
Expand Down Expand Up @@ -522,6 +526,14 @@ pub mod pallet {
currency_id: CurrencyId,
who: MultiLocation,
},
OutdatedValidatorBoostListCleaned {
currency_id: CurrencyId,
page: u8,
// already removed num
remove_num: u32,
// still to iterate num
num_left: u32,
},
}

/// The current storage version, we set to 3 our new version(after migrate stroage from vec t
Expand Down Expand Up @@ -2421,6 +2433,71 @@ pub mod pallet {
Zero::zero(),
)
}

#[pallet::call_index(48)]
#[pallet::weight(<T as Config>::WeightInfo::clean_outdated_validator_boost_list())]
pub fn clean_outdated_validator_boost_list(
origin: OriginFor<T>,
token: CurrencyId,
// start from 1
page: u8,
) -> DispatchResult {
ensure_signed(origin)?;
let page = page as usize;
ensure!(page > 0, Error::<T>::InvalidPageNumber);

let validator_boost_list_len = ValidatorBoostList::<T>::decode_len(token)
.ok_or(Error::<T>::NoMoreValidatorBoostListForCurrency)?;

let previous_count = (page - 1) * ITERATE_LENGTH;
ensure!(
validator_boost_list_len > previous_count,
Error::<T>::NoMoreValidatorBoostListForCurrency
);

// calculate next page number left
let num_left = if validator_boost_list_len > (previous_count + ITERATE_LENGTH) {
validator_boost_list_len - previous_count - ITERATE_LENGTH
} else {
0
};

let current_block_number = <frame_system::Pallet<T>>::block_number();
let mut remove_num = 0;
// for each validator in the validator boost list, if the due block number is less than
// or equal to the current block number, remove it
ValidatorBoostList::<T>::mutate(token, |validator_boost_list_op| {
if let Some(ref mut validator_boost_list) = validator_boost_list_op {
let mut remove_index = vec![];
for (index, (_validator, due_block_number)) in validator_boost_list
.iter()
.skip(previous_count)
.take(ITERATE_LENGTH)
.enumerate()
{
if *due_block_number <= current_block_number {
remove_index.push(index + previous_count);
}
}

// remove from the end to the start
for index in remove_index.iter().rev() {
validator_boost_list.remove(*index);
remove_num += 1;
}
}
});

// Deposit event.
Pallet::<T>::deposit_event(Event::OutdatedValidatorBoostListCleaned {
currency_id: token,
page: page as u8,
remove_num,
num_left: num_left as u32,
});

Ok(())
}
}

impl<T: Config> Pallet<T> {
Expand Down
101 changes: 101 additions & 0 deletions pallets/slp/src/tests/manta_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1918,3 +1918,104 @@ fn remove_from_validator_boost_list_should_work() {
assert_eq!(Slp::get_validator_boost_list(MANTA), None);
});
}

#[test]
fn clean_outdated_validator_boost_list_work() {
ExtBuilder::default().build().execute_with(|| {
manta_setup();

// no validator boost list exists for this currency
assert_noop!(
Slp::clean_outdated_validator_boost_list(RuntimeOrigin::signed(ALICE), MANTA, 1),
Error::<Runtime>::NoMoreValidatorBoostListForCurrency
);

let validator_list_output_1 =
BoundedVec::try_from(vec![(VALIDATOR_0_LOCATION, SIX_MONTHS as u64 + 300)]).unwrap();
let validator_list_output_2 = BoundedVec::try_from(vec![(
VALIDATOR_0_LOCATION,
SIX_MONTHS as u64 + 300 + SIX_MONTHS as u64,
)])
.unwrap();
let validator_list_output_3 = BoundedVec::try_from(vec![
(VALIDATOR_0_LOCATION, SIX_MONTHS as u64 + 300 + SIX_MONTHS as u64),
(VALIDATOR_1_LOCATION, SIX_MONTHS as u64 + 400),
])
.unwrap();

assert_ok!(Slp::add_to_validator_boost_list(
RuntimeOrigin::signed(ALICE),
MANTA,
Box::new(VALIDATOR_0_LOCATION)
));

assert_eq!(Slp::get_validator_boost_list(MANTA), Some(validator_list_output_1));

let bounded_validator_0 = BoundedVec::try_from(vec![VALIDATOR_0_LOCATION]).unwrap();
assert_eq!(Slp::get_validators(MANTA), Some(bounded_validator_0.clone()));

System::set_block_number(400);

assert_ok!(Slp::add_to_validator_boost_list(
RuntimeOrigin::signed(ALICE),
MANTA,
Box::new(VALIDATOR_0_LOCATION)
));

assert_eq!(Slp::get_validators(MANTA), Some(bounded_validator_0));

assert_eq!(Slp::get_validator_boost_list(MANTA), Some(validator_list_output_2.clone()));

assert_ok!(Slp::add_to_validator_boost_list(
RuntimeOrigin::signed(ALICE),
MANTA,
Box::new(VALIDATOR_1_LOCATION)
));

assert_eq!(Slp::get_validator_boost_list(MANTA), Some(validator_list_output_3.clone()));
let bounded_validator_0_1 =
BoundedVec::try_from(vec![VALIDATOR_0_LOCATION, VALIDATOR_1_LOCATION]).unwrap();
assert_eq!(Slp::get_validators(MANTA), Some(bounded_validator_0_1),);

// no validator due yet. Everything should be kept after calling
// clean_outdated_validator_boost_list
System::set_block_number(399 + SIX_MONTHS as u64);

assert_ok!(Slp::clean_outdated_validator_boost_list(
RuntimeOrigin::signed(ALICE),
MANTA,
1
));
assert_eq!(Slp::get_validator_boost_list(MANTA), Some(validator_list_output_3));

// move to block SIX_MONTHS + 400, validator 1 should be removable
System::set_block_number(400 + SIX_MONTHS as u64);

// page at least 1
assert_noop!(
Slp::clean_outdated_validator_boost_list(RuntimeOrigin::signed(ALICE), MANTA, 0),
Error::<Runtime>::InvalidPageNumber
);

// successfully clean outdated validator boost list
assert_ok!(Slp::clean_outdated_validator_boost_list(
RuntimeOrigin::signed(ALICE),
MANTA,
1
));
assert_eq!(Slp::get_validator_boost_list(MANTA), Some(validator_list_output_2.clone()));

// do it again
assert_ok!(Slp::clean_outdated_validator_boost_list(
RuntimeOrigin::signed(ALICE),
MANTA,
1
));
assert_eq!(Slp::get_validator_boost_list(MANTA), Some(validator_list_output_2));

assert_noop!(
Slp::clean_outdated_validator_boost_list(RuntimeOrigin::signed(ALICE), MANTA, 2),
Error::<Runtime>::NoMoreValidatorBoostListForCurrency
);
});
}
6 changes: 6 additions & 0 deletions pallets/slp/src/weights.rs
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ pub trait WeightInfo {
fn add_to_validator_boost_list() -> Weight;
fn remove_from_validator_boot_list() -> Weight;
fn convert_treasury_vtoken() -> Weight;
fn clean_outdated_validator_boost_list() -> Weight;
}

// For backwards compatibility and tests
Expand Down Expand Up @@ -841,4 +842,9 @@ impl WeightInfo for () {
.saturating_add(RocksDbWeight::get().reads(1_u64))
.saturating_add(RocksDbWeight::get().writes(1_u64))
}
fn clean_outdated_validator_boost_list() -> Weight {
Weight::from_parts(42_190_000, 3911)
.saturating_add(RocksDbWeight::get().reads(1_u64))
.saturating_add(RocksDbWeight::get().writes(1_u64))
}
}
1 change: 0 additions & 1 deletion pallets/slpx/src/benchmarking.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,6 @@ fn init_whitelist<T: Config + bifrost_asset_registry::Config>() -> (T::AccountId
#[benchmarks(where T: Config + bifrost_asset_registry::Config + bifrost_stable_pool::Config + bifrost_stable_asset::Config + orml_tokens::Config<CurrencyId = CurrencyId>)]
mod benchmarks {
use super::*;
use bifrost_stable_pool::AtLeast64BitUnsignedOf;
use frame_benchmarking::impl_benchmark_test_suite;

#[benchmark]
Expand Down
5 changes: 5 additions & 0 deletions runtime/bifrost-kusama/src/weights/bifrost_slp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -793,4 +793,9 @@ impl<T: frame_system::Config> bifrost_slp::WeightInfo for BifrostWeight<T> {
.saturating_add(RocksDbWeight::get().reads(1_u64))
.saturating_add(RocksDbWeight::get().writes(1_u64))
}
fn clean_outdated_validator_boost_list() -> Weight {
Weight::from_parts(42_190_000, 3911)
.saturating_add(RocksDbWeight::get().reads(1_u64))
.saturating_add(RocksDbWeight::get().writes(1_u64))
}
}
5 changes: 5 additions & 0 deletions runtime/bifrost-polkadot/src/weights/bifrost_slp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -793,4 +793,9 @@ impl<T: frame_system::Config> bifrost_slp::WeightInfo for BifrostWeight<T> {
.saturating_add(RocksDbWeight::get().reads(1_u64))
.saturating_add(RocksDbWeight::get().writes(1_u64))
}
fn clean_outdated_validator_boost_list() -> Weight {
Weight::from_parts(42_190_000, 3911)
.saturating_add(RocksDbWeight::get().reads(1_u64))
.saturating_add(RocksDbWeight::get().writes(1_u64))
}
}

0 comments on commit 63f81c3

Please sign in to comment.