Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Finishing "Additional priority boost for relayers that have explicitly registered at lane" #2605

Open
wants to merge 66 commits into
base: bridges-v2
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
66 commits
Select commit Hold shift + click to select a range
663c4c3
per-lane priority boost: prototype
svyatonik Oct 2, 2023
cb2e045
compute_per_lane_priority_boost to discuss new approach
svyatonik Oct 2, 2023
d310fe0
clippy
svyatonik Oct 2, 2023
57cd105
change approach a bit
svyatonik Oct 4, 2023
c1f9d8a
continue
svyatonik Oct 4, 2023
ebd6c61
continue
svyatonik Oct 6, 2023
facf6a5
flush
svyatonik Oct 6, 2023
e208524
continue prototyping
svyatonik Oct 6, 2023
73ea54e
Merge branch 'per-lane-priority-boost-for-discussing' into lane-prior…
svyatonik Oct 6, 2023
16aba6c
lanes now affect valid_till
svyatonik Oct 6, 2023
f473051
fmt
svyatonik Oct 6, 2023
ec87fbb
flush
svyatonik Oct 6, 2023
da47b6b
removed couple of obsolete TODOs
svyatonik Oct 6, 2023
6d52f11
added lost TODO
svyatonik Oct 6, 2023
2a0bae9
relayers are readded to the next set only if they are delivering at l…
svyatonik Oct 9, 2023
104754a
use expected reward from LaneRelayersSet to compute relayer reward
svyatonik Oct 9, 2023
034b38f
added comment to wrong code
svyatonik Oct 9, 2023
5df0872
reward is now a part of unrewarded relayers vector
svyatonik Oct 9, 2023
1a3efe7
remove unneeded constratind
svyatonik Oct 10, 2023
9c134da
set RewardAtSource to be u64
svyatonik Oct 10, 2023
5a86ed4
removed fixed TODO
svyatonik Oct 10, 2023
9b174cd
fmt
svyatonik Oct 10, 2023
579b90b
MaxRewardPerMessage + fixed TODO
svyatonik Oct 10, 2023
60b55af
fixed couple of TODOs + added comments + added new TODO
svyatonik Oct 10, 2023
72d5bbe
more TODO fixes
svyatonik Oct 10, 2023
e225164
fixed another TODO
svyatonik Oct 10, 2023
081523c
make next relayers set larger than the actual set
svyatonik Oct 11, 2023
e0e16cd
fmt
svyatonik Oct 11, 2023
926644d
Merge branch 'master' into lane-priority-prototype
svyatonik Oct 11, 2023
730e368
fix compilation
svyatonik Oct 11, 2023
f926504
added TODO
svyatonik Oct 12, 2023
043908f
tests + more TODOs
svyatonik Oct 12, 2023
2c425de
more tests
svyatonik Oct 12, 2023
2c3fed8
more tests
svyatonik Oct 12, 2023
4ad58da
tests for deregister_at_lane
svyatonik Oct 12, 2023
27e2669
tests for advance_lane_epoch
svyatonik Oct 12, 2023
1f04623
separate calls to manage relayers stake
svyatonik Oct 13, 2023
0638bcc
split active and next relayer sets
svyatonik Oct 13, 2023
38fac9f
Merge branch 'master' into lane-priority-prototype
svyatonik Oct 17, 2023
ce46ebc
removed TODO + added comment
svyatonik Oct 17, 2023
187fc19
intreoduce ActiveLaneRelayersSet and NextLaneRelayersSet
svyatonik Oct 17, 2023
392f93a
more tests
svyatonik Oct 17, 2023
b48a218
fix runtimes
svyatonik Oct 17, 2023
9f4e5cc
CI
svyatonik Oct 17, 2023
6957d6d
CI 2
svyatonik Oct 17, 2023
21f8caa
CI 3
svyatonik Oct 17, 2023
6ef384e
Merge branch 'next-and-active-lane-relayers' into lane-priority-proto…
svyatonik Oct 17, 2023
7e94f24
successful advance_lane_epoch is free for submitter
svyatonik Oct 17, 2023
03bc705
small optimization
svyatonik Oct 17, 2023
772837f
remove lane registrations when slashing relayer
svyatonik Oct 17, 2023
78a56ed
remove obsolete TODO and dev comment
svyatonik Oct 17, 2023
1f70ac7
added benchmarks for increase_stake, decrease_stake and register_at_lane
svyatonik Oct 17, 2023
94018e2
deregister_at_lane benchmark
svyatonik Oct 18, 2023
48504d9
advance_lane_epoch benchmark
svyatonik Oct 18, 2023
e235574
fixed slash_and_deregister benchmark
svyatonik Oct 18, 2023
3218672
added small comment regarding MaxLanesPerRelayer
svyatonik Oct 18, 2023
00dc6b8
removed already fixed TODO
svyatonik Oct 18, 2023
0d6d8a8
relayer_reward_per_message is now Option<RelayerRewardAtSource>
svyatonik Oct 18, 2023
113251e
properly implement relayer_reward_per_message in DeliveryConfirmation…
svyatonik Oct 18, 2023
325a99a
clippy
svyatonik Oct 18, 2023
17b678b
spelling
svyatonik Oct 18, 2023
bd000e2
fmt
svyatonik Oct 18, 2023
b5146bb
fixed benchmarks compilation
svyatonik Oct 18, 2023
cc98138
Merge branch 'master' into lane-priority-prototype
svyatonik Oct 30, 2023
c6b4f45
fix benchmarks
svyatonik Oct 30, 2023
0d761ed
Merge branch 'master' into lane-priority-prototype
svyatonik Feb 5, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

221 changes: 204 additions & 17 deletions modules/relayers/src/benchmarking.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,10 @@ use crate::*;
use bp_messages::LaneId;
use bp_relayers::RewardsAccountOwner;
use frame_benchmarking::v2::*;
use frame_system::RawOrigin;
use frame_support::traits::Get;
use frame_system::{pallet_prelude::BlockNumberFor, RawOrigin};
use sp_runtime::traits::One;
use sp_std::vec::Vec;

/// Reward amount that is (hopefully) is larger than existential deposit across all chains.
const REWARD_AMOUNT: u32 = u32::MAX;
Expand All @@ -40,6 +42,47 @@ pub trait Config: crate::Config {
fn deposit_account(account: Self::AccountId, balance: Self::Reward);
}

/// Return lane id that we use in tests.
fn lane_id(i: u32) -> LaneId {
LaneId::new(i, i)
}

/// Return block number until which our test registration is considered valid.
fn valid_till<T: Config>() -> BlockNumberFor<T> {
frame_system::Pallet::<T>::block_number()
.saturating_add(crate::Pallet::<T>::required_registration_lease())
.saturating_add(One::one())
.saturating_add(One::one())
}

/// Add basic relayer registration and optionally lane registrations.
fn register_relayer<T: Config>(
relayer: &T::AccountId,
lanes_reg_count: u32,
expected_reward: RelayerRewardAtSource,
) {
let stake = crate::Pallet::<T>::base_stake().saturating_add(
crate::Pallet::<T>::stake_per_lane().saturating_mul((lanes_reg_count + 1).into()),
);
T::deposit_account(relayer.clone(), stake);
crate::Pallet::<T>::increase_stake(RawOrigin::Signed(relayer.clone()).into(), stake).unwrap();
crate::Pallet::<T>::register(RawOrigin::Signed(relayer.clone()).into(), valid_till::<T>())
.unwrap();

for i in 0..lanes_reg_count {
crate::Pallet::<T>::register_at_lane(
RawOrigin::Signed(relayer.clone()).into(),
lane_id(i),
expected_reward,
)
.unwrap();
}
assert_eq!(
crate::Pallet::<T>::registered_relayer(&relayer).map(|reg| reg.lanes().len() as u32),
Some(lanes_reg_count),
);
}

#[benchmarks]
mod benchmarks {
use super::*;
Expand All @@ -64,16 +107,54 @@ mod benchmarks {
// also completed successfully
}

/// Benchmark `increase_stake` call.
#[benchmark]
fn increase_stake() {
let relayer: T::AccountId = whitelisted_caller();
let stake = crate::Pallet::<T>::base_stake();
T::deposit_account(relayer.clone(), stake);

#[extrinsic_call]
_(RawOrigin::Signed(relayer.clone()), stake);

assert_eq!(
crate::Pallet::<T>::registered_relayer(&relayer).map(|reg| reg.current_stake()),
Some(stake),
);
}

/// Benchmark `decrease_stake` call.
#[benchmark]
fn decrease_stake() {
let relayer: T::AccountId = whitelisted_caller();
let base_stake = crate::Pallet::<T>::base_stake();
let stake = base_stake.saturating_add(100u32.into());
T::deposit_account(relayer.clone(), stake);
crate::Pallet::<T>::increase_stake(RawOrigin::Signed(relayer.clone()).into(), stake)
.unwrap();

#[extrinsic_call]
_(RawOrigin::Signed(relayer.clone()), 100u32.into());

assert_eq!(
crate::Pallet::<T>::registered_relayer(&relayer).map(|reg| reg.current_stake()),
Some(base_stake),
);
}

/// Benchmark `register` call.
#[benchmark]
fn register() {
let relayer: T::AccountId = whitelisted_caller();
let base_stake = crate::Pallet::<T>::base_stake();
let valid_till = frame_system::Pallet::<T>::block_number()
.saturating_add(crate::Pallet::<T>::required_registration_lease())
.saturating_add(One::one())
.saturating_add(One::one());

T::deposit_account(relayer.clone(), crate::Pallet::<T>::required_stake());
T::deposit_account(relayer.clone(), base_stake);
crate::Pallet::<T>::increase_stake(RawOrigin::Signed(relayer.clone()).into(), base_stake)
.unwrap();

#[extrinsic_call]
_(RawOrigin::Signed(relayer.clone()), valid_till);
Expand All @@ -85,36 +166,133 @@ mod benchmarks {
#[benchmark]
fn deregister() {
let relayer: T::AccountId = whitelisted_caller();
let valid_till = frame_system::Pallet::<T>::block_number()
.saturating_add(crate::Pallet::<T>::required_registration_lease())
.saturating_add(One::one())
.saturating_add(One::one());
T::deposit_account(relayer.clone(), crate::Pallet::<T>::required_stake());
crate::Pallet::<T>::register(RawOrigin::Signed(relayer.clone()).into(), valid_till)
.unwrap();

frame_system::Pallet::<T>::set_block_number(valid_till.saturating_add(One::one()));
register_relayer::<T>(&relayer, 0, 0);
frame_system::Pallet::<T>::set_block_number(valid_till::<T>().saturating_add(One::one()));

#[extrinsic_call]
_(RawOrigin::Signed(relayer.clone()));

assert!(!crate::Pallet::<T>::is_registration_active(&relayer));
}

/// Benchmark `register_at_lane` call. The worst case for this call is when:
///
/// - relayer has `T::MaxLanesPerRelayer::get() - 1` lane registrations;
///
/// - there are no other relayers registered at that lane yet;
#[benchmark]
fn register_at_lane() {
let relayer: T::AccountId = whitelisted_caller();
let max_lanes_per_relayer = T::MaxLanesPerRelayer::get();
register_relayer::<T>(&relayer, max_lanes_per_relayer - 1, 0);

#[extrinsic_call]
_(RawOrigin::Signed(relayer.clone()), lane_id(max_lanes_per_relayer), 0);

assert_eq!(
crate::Pallet::<T>::registered_relayer(&relayer).map(|reg| reg.lanes().len() as u32),
Some(max_lanes_per_relayer),
);
}

/// Benchmark `deregister_at_lane` call. The worst case for this call is when relayer is not in
/// the active relayers set.
#[benchmark]
fn deregister_at_lane() {
let relayer: T::AccountId = whitelisted_caller();
let max_lanes_per_relayer = T::MaxLanesPerRelayer::get();
register_relayer::<T>(&relayer, max_lanes_per_relayer, 0);

#[extrinsic_call]
_(RawOrigin::Signed(relayer.clone()), lane_id(0));

assert_eq!(
crate::Pallet::<T>::registered_relayer(&relayer).map(|reg| reg.lanes().len() as u32),
Some(max_lanes_per_relayer - 1),
);
}

// Benchmark `advance_lane_epoch` call. The worst case for this call is when active set is
// completely replaced with a next set.
#[benchmark]
fn advance_lane_epoch() {
let current_block_number = frame_system::Pallet::<T>::block_number();

// prepare active relayers set with max possible relayers count
let max_active_relayers_per_lane = T::MaxActiveRelayersPerLane::get();
let active_relayers = (0..max_active_relayers_per_lane)
.map(|i| account("relayer", i, 0))
.collect::<Vec<_>>();
let mut active_relayers_set =
ActiveLaneRelayersSet::<_, BlockNumberFor<T>, T::MaxActiveRelayersPerLane>::default();
let mut next_relayers_set =
NextLaneRelayersSet::<_, BlockNumberFor<T>, T::MaxNextRelayersPerLane>::empty(
current_block_number,
);
for active_relayer in &active_relayers {
register_relayer::<T>(active_relayer, 1, 1);
assert!(next_relayers_set.try_insert(active_relayer.clone(), 0));
}
active_relayers_set.activate_next_set(current_block_number, next_relayers_set, |_| true);
ActiveLaneRelayers::<T>::insert(lane_id(0), active_relayers_set);

// prepare next relayers set with max possible relayers count
let max_next_relayers_per_lane = T::MaxNextRelayersPerLane::get();
let next_relayers = (0..max_next_relayers_per_lane)
.map(|i| account::<T::AccountId>("relayer", max_active_relayers_per_lane + i, 0))
.collect::<Vec<_>>();
for next_relayer in &next_relayers {
register_relayer::<T>(next_relayer, 1, 0);
}

// set next block to block where next set can be activated
frame_system::Pallet::<T>::set_block_number(
NextLaneRelayers::<T>::get(lane_id(0)).unwrap().may_enact_at(),
);

#[extrinsic_call]
_(RawOrigin::Signed(whitelisted_caller()), lane_id(0));

// active relayers are replaced with next relayers
assert_eq!(
crate::Pallet::<T>::active_lane_relayers(&lane_id(0))
.relayers()
.iter()
.map(|r| r.relayer())
.collect::<Vec<_>>(),
next_relayers.iter().take(max_active_relayers_per_lane as _).collect::<Vec<_>>(),
);

// all (previous) active relayers have no lane registration
active_relayers
.into_iter()
.all(|r| crate::Pallet::<T>::registered_relayer(&r).unwrap().lanes().len() == 0);

// all (previous) next relayers have no lane registration
next_relayers
.into_iter()
.all(|r| crate::Pallet::<T>::registered_relayer(&r).unwrap().lanes().len() == 1);
}

/// Benchmark `slash_and_deregister` method of the pallet. We are adding this weight to
/// the weight of message delivery call if `RefundBridgedParachainMessages` signed extension
/// is deployed at runtime level.
#[benchmark]
fn slash_and_deregister() {
// prepare and register relayer account
let relayer: T::AccountId = whitelisted_caller();
let valid_till = frame_system::Pallet::<T>::block_number()
.saturating_add(crate::Pallet::<T>::required_registration_lease())
.saturating_add(One::one())
.saturating_add(One::one());
T::deposit_account(relayer.clone(), crate::Pallet::<T>::required_stake());
crate::Pallet::<T>::register(RawOrigin::Signed(relayer.clone()).into(), valid_till)
let max_lanes_per_relayer = T::MaxLanesPerRelayer::get();
register_relayer::<T>(&relayer, max_lanes_per_relayer, 1);

// also register relayer in next lane relayers set (with better bid)
for i in 0..max_lanes_per_relayer {
crate::Pallet::<T>::register_at_lane(
RawOrigin::Signed(relayer.clone()).into(),
lane_id(i),
0,
)
.unwrap();
}

// create slash destination account
let lane = LaneId::new(1, 2);
Expand All @@ -128,6 +306,15 @@ mod benchmarks {
}

assert!(!crate::Pallet::<T>::is_registration_active(&relayer));
for i in 0..max_lanes_per_relayer {
assert!(crate::Pallet::<T>::active_lane_relayers(lane_id(i))
.relayer(&relayer)
.is_none(),);
assert!(crate::Pallet::<T>::next_lane_relayers(lane_id(i))
.unwrap_or_else(|| NextLaneRelayersSet::empty(Zero::zero()))
.relayer(&relayer)
.is_none(),);
}
}

// Benchmark `register_relayer_reward` method of the pallet. We are adding this weight to
Expand Down
30 changes: 30 additions & 0 deletions modules/relayers/src/extension/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1013,6 +1013,11 @@ mod tests {
run_test(|| {
initialize_environment(100, 100, 100);

BridgeRelayers::increase_stake(
RuntimeOrigin::signed(relayer_account_at_this_chain()),
Stake::get(),
)
.unwrap();
BridgeRelayers::register(RuntimeOrigin::signed(relayer_account_at_this_chain()), 1000)
.unwrap();

Expand Down Expand Up @@ -1043,6 +1048,11 @@ mod tests {
run_test(|| {
initialize_environment(100, 100, 100);

BridgeRelayers::increase_stake(
RuntimeOrigin::signed(relayer_account_at_this_chain()),
Stake::get(),
)
.unwrap();
BridgeRelayers::register(RuntimeOrigin::signed(relayer_account_at_this_chain()), 1000)
.unwrap();

Expand Down Expand Up @@ -1579,6 +1589,11 @@ mod tests {
);

// slashing works for message delivery calls
BridgeRelayers::increase_stake(
RuntimeOrigin::signed(relayer_account_at_this_chain()),
test_stake,
)
.unwrap();
BridgeRelayers::register(RuntimeOrigin::signed(relayer_account_at_this_chain()), 1000)
.unwrap();
assert_eq!(Balances::reserved_balance(relayer_account_at_this_chain()), test_stake);
Expand All @@ -1589,6 +1604,11 @@ mod tests {
Balances::free_balance(delivery_rewards_account())
);

BridgeRelayers::increase_stake(
RuntimeOrigin::signed(relayer_account_at_this_chain()),
test_stake,
)
.unwrap();
BridgeRelayers::register(RuntimeOrigin::signed(relayer_account_at_this_chain()), 1000)
.unwrap();
assert_eq!(Balances::reserved_balance(relayer_account_at_this_chain()), test_stake);
Expand All @@ -1599,6 +1619,11 @@ mod tests {
Balances::free_balance(delivery_rewards_account())
);

BridgeRelayers::increase_stake(
RuntimeOrigin::signed(relayer_account_at_this_chain()),
test_stake,
)
.unwrap();
BridgeRelayers::register(RuntimeOrigin::signed(relayer_account_at_this_chain()), 1000)
.unwrap();
assert_eq!(Balances::reserved_balance(relayer_account_at_this_chain()), test_stake);
Expand Down Expand Up @@ -1888,6 +1913,11 @@ mod tests {
initialize_environment(100, 100, best_delivered_message);

// register relayer so it gets priority boost
BridgeRelayers::increase_stake(
RuntimeOrigin::signed(relayer_account_at_this_chain()),
Stake::get(),
)
.unwrap();
BridgeRelayers::register(RuntimeOrigin::signed(relayer_account_at_this_chain()), 1000)
.unwrap();

Expand Down
Loading