From 2c9c3a091d28b2bba01175d8bfd3bfd3e9ed9b3b Mon Sep 17 00:00:00 2001 From: ouwenkg <2630582710@qq.com> Date: Fri, 5 Nov 2021 14:44:53 +0800 Subject: [PATCH 01/46] Update some renames --- frame/fee-market/src/lib.rs | 13 ++++++++----- frame/fee-market/src/s2s/callbacks.rs | 7 ++++++- 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/frame/fee-market/src/lib.rs b/frame/fee-market/src/lib.rs index f4a989848f..2a9f671541 100644 --- a/frame/fee-market/src/lib.rs +++ b/frame/fee-market/src/lib.rs @@ -132,6 +132,8 @@ pub mod pallet { TooFewEnrolledRelayers, /// The relayer is occupied, and can't cancel enrollment now. OccupiedRelayer, + /// Extend lock failed. + ExtendLockFailed, } // Enrolled relayers storage @@ -306,12 +308,12 @@ impl Pallet { .iter() .map(RelayersMap::::get) .collect(); - relayers.sort(); // Select the first `AssignedRelayersNumber` relayers as AssignedRelayer. // Only when total relayer's number greater than `AssignedRelayersNumber`, selection happens. let assigned_relayers_len = T::AssignedRelayersNumber::get() as usize; if relayers.len() >= assigned_relayers_len { + relayers.sort(); let mut assigned_relayers = Vec::with_capacity(assigned_relayers_len); for i in 0..assigned_relayers_len { if let Some(r) = relayers.get(i) { @@ -337,7 +339,8 @@ impl Pallet { who, new_collateral, WithdrawReasons::all(), - ); + ) + .map_err(|_| >::ExtendLockFailed); >::mutate(who.clone(), |relayer| { relayer.collateral = new_collateral; }); @@ -392,14 +395,14 @@ impl Pallet { } pub trait Slasher { - fn slash(base: RingBalance, _timeout: T::BlockNumber) -> RingBalance; + fn slash(base_fee: RingBalance, timeout: T::BlockNumber) -> RingBalance; } impl Slasher for () { - // The slash result = base(p3 fee) + slash_each_block * timeout + // The slash result = base_fee + slash_each_block * timeout // Note: The maximum slash result is the MiniumLockCollateral. We mush ensures that all enrolled // relayers have ability to pay this slash result. - fn slash(base: Fee, timeout: T::BlockNumber) -> RingBalance { + fn slash(base_fee: Fee, timeout: T::BlockNumber) -> RingBalance { // Slash 20 RING for each delay block until the maximum slash value let slash_each_block = 20_000_000_000u128; let timeout_u128: u128 = timeout.unique_saturated_into(); diff --git a/frame/fee-market/src/s2s/callbacks.rs b/frame/fee-market/src/s2s/callbacks.rs index 4af504c408..fde6c4b4bb 100644 --- a/frame/fee-market/src/s2s/callbacks.rs +++ b/frame/fee-market/src/s2s/callbacks.rs @@ -49,19 +49,24 @@ pub struct FeeMarketMessageConfirmedHandler(PhantomData); impl OnDeliveryConfirmed for FeeMarketMessageConfirmedHandler { fn on_messages_delivered(lane: &LaneId, delivered_messages: &DeliveredMessages) -> Weight { + let mut reads = 0; + let mut writes = 0; + let now = frame_system::Pallet::::block_number(); for message_nonce in delivered_messages.begin..=delivered_messages.end { if let Some(order) = >::get((lane, message_nonce)) { + reads += 1; if !order.is_confirmed() { >::mutate((lane, message_nonce), |order| match order { Some(order) => order.set_confirm_time(Some(now)), None => {} }); >::append((lane, message_nonce)); + writes += 2; } } } - ::DbWeight::get().reads_writes(1, 1) + ::DbWeight::get().reads_writes(reads, writes) } } From 3a54d3486ee4527ba6855ade8c173b7f638a9273 Mon Sep 17 00:00:00 2001 From: ouwenkg <2630582710@qq.com> Date: Fri, 5 Nov 2021 14:55:41 +0800 Subject: [PATCH 02/46] Rename --- frame/fee-market/src/lib.rs | 2 +- frame/fee-market/src/s2s/payment.rs | 23 +++++++++-------------- primitives/fee-market/src/lib.rs | 10 +++++----- 3 files changed, 15 insertions(+), 20 deletions(-) diff --git a/frame/fee-market/src/lib.rs b/frame/fee-market/src/lib.rs index 2a9f671541..deda2d8cd9 100644 --- a/frame/fee-market/src/lib.rs +++ b/frame/fee-market/src/lib.rs @@ -406,7 +406,7 @@ impl Slasher for () { // Slash 20 RING for each delay block until the maximum slash value let slash_each_block = 20_000_000_000u128; let timeout_u128: u128 = timeout.unique_saturated_into(); - let mut slash = base.saturating_add( + let mut slash = base_fee.saturating_add( timeout_u128 .saturating_mul(slash_each_block) .unique_saturated_into(), diff --git a/frame/fee-market/src/s2s/payment.rs b/frame/fee-market/src/s2s/payment.rs index f436a7def1..8ff4b462d5 100644 --- a/frame/fee-market/src/s2s/payment.rs +++ b/frame/fee-market/src/s2s/payment.rs @@ -139,8 +139,8 @@ where break; } } - let lowest_fee = order.first_and_last_fee().0.unwrap_or_default(); - let message_fee = order.first_and_last_fee().1.unwrap_or_default(); + let lowest_fee = order.lowest_and_highest_fee().0.unwrap_or_default(); + let message_fee = order.lowest_and_highest_fee().1.unwrap_or_default(); let message_reward; let confirm_reward; @@ -197,7 +197,7 @@ pub fn slash_assigned_relayers( match (order.confirm_time, order.range_end()) { (Some(confirm_time), Some(end_time)) if confirm_time >= end_time => { let timeout = confirm_time - end_time; - let message_fee = order.first_and_last_fee().1.unwrap_or_default(); + let message_fee = order.lowest_and_highest_fee().1.unwrap_or_default(); let slash_max = T::Slasher::slash(message_fee, timeout); debug_assert!( slash_max <= T::MiniumLockCollateral::get(), @@ -241,33 +241,28 @@ pub fn do_slash( fn transfer_and_print_logs_on_error( from: &T::AccountId, to: &T::AccountId, - reward: RingBalance, + amount: RingBalance, ) { - if reward.is_zero() { + if amount.is_zero() { return; } let pay_result = ::RingCurrency::transfer( from, to, - reward, + amount, // the relayer fund account must stay above ED (needs to be pre-funded) ExistenceRequirement::KeepAlive, ); match pay_result { - Ok(_) => log::trace!( - "Pay reward, from {:?} to {:?} reward: {:?}", - from, - to, - reward, - ), + Ok(_) => log::trace!("Transfer, from {:?} to {:?} amount: {:?}", from, to, amount,), Err(error) => log::error!( - "Failed to pay reward, from {:?} to {:?} reward {:?}: {:?}", + "Transfer, from {:?} to {:?} amount {:?}: {:?}", from, to, - reward, + amount, error, ), } diff --git a/primitives/fee-market/src/lib.rs b/primitives/fee-market/src/lib.rs index 16c1e9438a..cfcc0be5df 100644 --- a/primitives/fee-market/src/lib.rs +++ b/primitives/fee-market/src/lib.rs @@ -131,10 +131,10 @@ where self.relayers.as_ref() } - pub fn first_and_last_fee(&self) -> (Option, Option) { - let first = self.relayers.iter().nth(0).map(|r| r.fee); - let last = self.relayers.iter().last().map(|r| r.fee); - (first, last) + pub fn lowest_and_highest_fee(&self) -> (Option, Option) { + let lowest = self.relayers.iter().nth(0).map(|r| r.fee); + let highest = self.relayers.iter().last().map(|r| r.fee); + (lowest, highest) } pub fn is_confirmed(&self) -> bool { @@ -247,7 +247,7 @@ mod test { assert_eq!(order.relayer_valid_range(2).unwrap(), (150..200)); assert_eq!(order.relayer_valid_range(3).unwrap(), (200..250)); assert_eq!(order.range_end(), Some(250)); - assert_eq!(order.first_and_last_fee(), (Some(30), Some(80))); + assert_eq!(order.lowest_and_highest_fee(), (Some(30), Some(80))); } #[test] From 88396b2ca587ad6983d208799d42052c8c8885f6 Mon Sep 17 00:00:00 2001 From: ouwenkg <2630582710@qq.com> Date: Fri, 5 Nov 2021 14:58:57 +0800 Subject: [PATCH 03/46] Code clean --- frame/fee-market/src/s2s/payment.rs | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/frame/fee-market/src/s2s/payment.rs b/frame/fee-market/src/s2s/payment.rs index 8ff4b462d5..d0a1395425 100644 --- a/frame/fee-market/src/s2s/payment.rs +++ b/frame/fee-market/src/s2s/payment.rs @@ -256,14 +256,13 @@ fn transfer_and_print_logs_on_error( ); match pay_result { - Ok(_) => log::trace!("Transfer, from {:?} to {:?} amount: {:?}", from, to, amount,), - - Err(error) => log::error!( + Ok(_) => log::trace!("Transfer, from {:?} to {:?} amount: {:?}", from, to, amount), + Err(e) => log::error!( "Transfer, from {:?} to {:?} amount {:?}: {:?}", from, to, amount, - error, + e, ), } } From e57efd2a1f84612e1edfd71a4745655950affcfa Mon Sep 17 00:00:00 2001 From: ouwenkg <2630582710@qq.com> Date: Fri, 5 Nov 2021 16:07:44 +0800 Subject: [PATCH 04/46] Revert reads and writes weight changes --- frame/fee-market/src/s2s/callbacks.rs | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/frame/fee-market/src/s2s/callbacks.rs b/frame/fee-market/src/s2s/callbacks.rs index fde6c4b4bb..4af504c408 100644 --- a/frame/fee-market/src/s2s/callbacks.rs +++ b/frame/fee-market/src/s2s/callbacks.rs @@ -49,24 +49,19 @@ pub struct FeeMarketMessageConfirmedHandler(PhantomData); impl OnDeliveryConfirmed for FeeMarketMessageConfirmedHandler { fn on_messages_delivered(lane: &LaneId, delivered_messages: &DeliveredMessages) -> Weight { - let mut reads = 0; - let mut writes = 0; - let now = frame_system::Pallet::::block_number(); for message_nonce in delivered_messages.begin..=delivered_messages.end { if let Some(order) = >::get((lane, message_nonce)) { - reads += 1; if !order.is_confirmed() { >::mutate((lane, message_nonce), |order| match order { Some(order) => order.set_confirm_time(Some(now)), None => {} }); >::append((lane, message_nonce)); - writes += 2; } } } - ::DbWeight::get().reads_writes(reads, writes) + ::DbWeight::get().reads_writes(1, 1) } } From 37d92b76a22a44f92adee1d1b9d201ea0627920a Mon Sep 17 00:00:00 2001 From: ouwenkg <2630582710@qq.com> Date: Fri, 5 Nov 2021 16:35:22 +0800 Subject: [PATCH 05/46] Update review issues --- frame/fee-market/src/lib.rs | 24 ++------- frame/fee-market/src/s2s/callbacks.rs | 1 + frame/fee-market/src/s2s/payment.rs | 78 +++++++++++++++------------ 3 files changed, 49 insertions(+), 54 deletions(-) diff --git a/frame/fee-market/src/lib.rs b/frame/fee-market/src/lib.rs index deda2d8cd9..4b44d993a9 100644 --- a/frame/fee-market/src/lib.rs +++ b/frame/fee-market/src/lib.rs @@ -128,8 +128,6 @@ pub mod pallet { OnlyIncreaseLockedCollateralAllowed, /// The fee is lower than MinimumRelayFee RelayFeeTooLow, - /// The enrolled relayers less than MIN_RELAYERS_NUMBER - TooFewEnrolledRelayers, /// The relayer is occupied, and can't cancel enrollment now. OccupiedRelayer, /// Extend lock failed. @@ -153,7 +151,7 @@ pub mod pallet { // Priority relayers storage #[pallet::storage] #[pallet::getter(fn assigned_relayers)] - pub type AssignedRelayersStorage = + pub type AssignedRelayers = StorageValue<_, Vec>>, OptionQuery>; // Order storage @@ -259,10 +257,6 @@ pub mod pallet { pub fn cancel_enrollment(origin: OriginFor) -> DispatchResultWithPostInfo { let who = ensure_signed(origin)?; ensure!(Self::is_enrolled(&who), >::NotEnrolled); - ensure!( - >::get().len() > T::AssignedRelayersNumber::get() as usize, - >::TooFewEnrolledRelayers - ); ensure!(!Self::is_occupied(&who), >::OccupiedRelayer); Self::remove_enrolled_relayer(&who); @@ -320,16 +314,14 @@ impl Pallet { assigned_relayers.push(r); } } - >::put(assigned_relayers); + >::put(assigned_relayers); } } /// Update relayer locked collateral, then update market fee, this will changes RelayersMap storage. pub fn update_collateral(who: &T::AccountId, new_collateral: RingBalance) { - // Ensure always at least `AssignedRelayersNumber` relayers are able to provide market fee. - if new_collateral < T::MiniumLockCollateral::get() - && >::get().len() > T::AssignedRelayersNumber::get() as usize - { + // If the slashed collateral lower than MiniumLockCollateral, kick it out. + if new_collateral < T::MiniumLockCollateral::get() { Self::remove_enrolled_relayer(who); return; } @@ -375,14 +367,6 @@ impl Pallet { Self::assigned_relayers().and_then(|relayers| relayers.last().map(|r| r.fee)) } - /// Get order info - pub fn order( - lane_id: &LaneId, - message: &MessageNonce, - ) -> Option>> { - >::get((lane_id, message)) - } - /// Whether the enrolled relayer is occupied(Responsible for order relaying) pub fn is_occupied(who: &T::AccountId) -> bool { for (_, order) in >::iter() { diff --git a/frame/fee-market/src/s2s/callbacks.rs b/frame/fee-market/src/s2s/callbacks.rs index 4af504c408..ee224a71b3 100644 --- a/frame/fee-market/src/s2s/callbacks.rs +++ b/frame/fee-market/src/s2s/callbacks.rs @@ -62,6 +62,7 @@ impl OnDeliveryConfirmed for FeeMarketMessageConfirmedHandler { } } + // TODO: The returned weight should be more accurately. See: https://github.com/darwinia-network/darwinia-common/issues/911 ::DbWeight::get().reads_writes(1, 1) } } diff --git a/frame/fee-market/src/s2s/payment.rs b/frame/fee-market/src/s2s/payment.rs index d0a1395425..7ed7122057 100644 --- a/frame/fee-market/src/s2s/payment.rs +++ b/frame/fee-market/src/s2s/payment.rs @@ -139,45 +139,55 @@ where break; } } - let lowest_fee = order.lowest_and_highest_fee().0.unwrap_or_default(); - let message_fee = order.lowest_and_highest_fee().1.unwrap_or_default(); + match order.lowest_and_highest_fee() { + (Some(lowest_fee), Some(message_fee)) => { + let message_reward; + let confirm_reward; - let message_reward; - let confirm_reward; - if let Some(who) = order.required_delivery_relayer_for_time(order_confirm_time) { - // message fee - lowest fee => treasury - let treasury_reward = message_fee.saturating_sub(lowest_fee); - treasury_total_rewards = treasury_total_rewards.saturating_add(treasury_reward); + if let Some(who) = order.required_delivery_relayer_for_time(order_confirm_time) + { + // message fee - lowest fee => treasury + let treasury_reward = message_fee.saturating_sub(lowest_fee); + treasury_total_rewards = + treasury_total_rewards.saturating_add(treasury_reward); - // 60% * lowest fee => assigned_relayers_rewards - let assigned_relayers_reward = T::AssignedRelayersRewardRatio::get() * lowest_fee; - assigned_relayers_rewards - .entry(who) - .and_modify(|r| *r = r.saturating_add(assigned_relayers_reward)) - .or_insert(assigned_relayers_reward); + // 60% * lowest fee => assigned_relayers_rewards + let assigned_relayers_reward = + T::AssignedRelayersRewardRatio::get() * lowest_fee; + assigned_relayers_rewards + .entry(who) + .and_modify(|r| *r = r.saturating_add(assigned_relayers_reward)) + .or_insert(assigned_relayers_reward); - let bridger_relayers_reward = lowest_fee.saturating_sub(assigned_relayers_reward); - // 80% * (1 - 60%) * lowest_fee => message relayer - message_reward = T::MessageRelayersRewardRatio::get() * bridger_relayers_reward; - // 20% * (1 - 60%) * lowest_fee => confirm relayer - confirm_reward = T::ConfirmRelayersRewardRatio::get() * bridger_relayers_reward; - } else { - // The message is delivered by common relayer instead of order assigned relayers, all assigned relayers of this order should be punished. - let slashed_reward = slash_assigned_relayers::(order, relayer_fund_account); + let bridger_relayers_reward = + lowest_fee.saturating_sub(assigned_relayers_reward); + // 80% * (1 - 60%) * lowest_fee => message relayer + message_reward = + T::MessageRelayersRewardRatio::get() * bridger_relayers_reward; + // 20% * (1 - 60%) * lowest_fee => confirm relayer + confirm_reward = + T::ConfirmRelayersRewardRatio::get() * bridger_relayers_reward; + } else { + // The message is delivered by common relayer instead of order assigned relayers, all assigned relayers of this order should be punished. + let slashed_reward = + slash_assigned_relayers::(order, relayer_fund_account); - // 80% total slash => confirm relayer - message_reward = T::MessageRelayersRewardRatio::get() * slashed_reward; - // 20% total slash => confirm relayer - confirm_reward = T::ConfirmRelayersRewardRatio::get() * slashed_reward; - } + // 80% total slash => confirm relayer + message_reward = T::MessageRelayersRewardRatio::get() * slashed_reward; + // 20% total slash => confirm relayer + confirm_reward = T::ConfirmRelayersRewardRatio::get() * slashed_reward; + } - // Update confirmation relayer total rewards - confirmation_rewards = confirmation_rewards.saturating_add(confirm_reward); - // Update message relayers total rewards - messages_rewards - .entry(message_relayer) - .and_modify(|r| *r = r.saturating_add(message_reward)) - .or_insert(message_reward); + // Update confirmation relayer total rewards + confirmation_rewards = confirmation_rewards.saturating_add(confirm_reward); + // Update message relayers total rewards + messages_rewards + .entry(message_relayer) + .and_modify(|r| *r = r.saturating_add(message_reward)) + .or_insert(message_reward); + } + _ => {} + } } } RewardsBook { From 1f790a55bc798d9021dd40eb41f5ec2fba2a8064 Mon Sep 17 00:00:00 2001 From: ouwenkg <2630582710@qq.com> Date: Fri, 5 Nov 2021 16:54:08 +0800 Subject: [PATCH 06/46] Update review issues 2 --- frame/fee-market/src/s2s/payment.rs | 40 +++++++++++++++++------------ 1 file changed, 23 insertions(+), 17 deletions(-) diff --git a/frame/fee-market/src/s2s/payment.rs b/frame/fee-market/src/s2s/payment.rs index 7ed7122057..1692794eff 100644 --- a/frame/fee-market/src/s2s/payment.rs +++ b/frame/fee-market/src/s2s/payment.rs @@ -87,21 +87,21 @@ where } = slash_and_calculate_rewards::(messages_relayers, relayer_fund_account); // Pay confirmation relayer rewards - transfer_and_print_logs_on_error::( + do_reward::( relayer_fund_account, confirmation_relayer, confirmation_relayer_rewards, ); // Pay messages relayers rewards for (relayer, reward) in messages_relayers_rewards { - transfer_and_print_logs_on_error::(relayer_fund_account, &relayer, reward); + do_reward::(relayer_fund_account, &relayer, reward); } // Pay assign relayer reward for (relayer, reward) in assigned_relayers_rewards { - transfer_and_print_logs_on_error::(relayer_fund_account, &relayer, reward); + do_reward::(relayer_fund_account, &relayer, reward); } // Pay treasury reward - transfer_and_print_logs_on_error::( + do_reward::( relayer_fund_account, &T::TreasuryPalletId::get().into_account(), treasury_total_rewards, @@ -237,41 +237,47 @@ pub fn do_slash( if locked_collateral >= slash_max { slashed = slash_max; let locked_reserved = locked_collateral.saturating_sub(slashed); - transfer_and_print_logs_on_error::(slash_account, fund_account, slashed); + let _ = ::RingCurrency::transfer( + slash_account, + fund_account, + slashed, + ExistenceRequirement::AllowDeath, + ); crate::Pallet::::update_collateral(&slash_account, locked_reserved); } else { slashed = locked_collateral; - transfer_and_print_logs_on_error::(slash_account, fund_account, slashed); + let _ = ::RingCurrency::transfer( + slash_account, + fund_account, + slashed, + ExistenceRequirement::AllowDeath, + ); crate::Pallet::::update_collateral(&slash_account, RingBalance::::zero()); } slashed } -/// Do transfer -fn transfer_and_print_logs_on_error( - from: &T::AccountId, - to: &T::AccountId, - amount: RingBalance, -) { - if amount.is_zero() { +/// Do reward +fn do_reward(from: &T::AccountId, to: &T::AccountId, reward: RingBalance) { + if reward.is_zero() { return; } let pay_result = ::RingCurrency::transfer( from, to, - amount, + reward, // the relayer fund account must stay above ED (needs to be pre-funded) ExistenceRequirement::KeepAlive, ); match pay_result { - Ok(_) => log::trace!("Transfer, from {:?} to {:?} amount: {:?}", from, to, amount), + Ok(_) => log::trace!("Reward, from {:?} to {:?} reward: {:?}", from, to, reward), Err(e) => log::error!( - "Transfer, from {:?} to {:?} amount {:?}: {:?}", + "Reward, from {:?} to {:?} reward {:?}: {:?}", from, to, - amount, + reward, e, ), } From d3469e7ce0fbb617486d34a4a3a78f836049d571 Mon Sep 17 00:00:00 2001 From: ouwenkg <2630582710@qq.com> Date: Fri, 5 Nov 2021 19:04:17 +0800 Subject: [PATCH 07/46] Fix unit tests --- frame/fee-market/src/lib.rs | 10 ++ frame/fee-market/src/s2s/payment.rs | 12 ++ frame/fee-market/src/tests.rs | 172 +++++++++++++++++++--------- 3 files changed, 138 insertions(+), 56 deletions(-) diff --git a/frame/fee-market/src/lib.rs b/frame/fee-market/src/lib.rs index 4b44d993a9..4ee94f99ce 100644 --- a/frame/fee-market/src/lib.rs +++ b/frame/fee-market/src/lib.rs @@ -156,6 +156,7 @@ pub mod pallet { // Order storage #[pallet::storage] + #[pallet::getter(fn order)] pub type Orders = StorageMap< _, Blake2_128Concat, @@ -315,6 +316,9 @@ impl Pallet { } } >::put(assigned_relayers); + } else { + // The enrolled relayers not enough, pallet can't provide any fee advice. + >::kill(); } } @@ -342,8 +346,14 @@ impl Pallet { /// Remove enrolled relayer, then update market fee. pub fn remove_enrolled_relayer(who: &T::AccountId) { T::RingCurrency::remove_lock(T::LockId::get(), who); + >::remove(who.clone()); >::mutate(|relayers| relayers.retain(|x| x != who)); + >::mutate(|assigned_relayers| { + if let Some(relayers) = assigned_relayers { + relayers.retain(|x| x.id != *who); + } + }); Self::update_market(); } diff --git a/frame/fee-market/src/s2s/payment.rs b/frame/fee-market/src/s2s/payment.rs index 1692794eff..b876d8a77e 100644 --- a/frame/fee-market/src/s2s/payment.rs +++ b/frame/fee-market/src/s2s/payment.rs @@ -139,6 +139,8 @@ where break; } } + println!("the message relayer is {:?}", message_relayer); + match order.lowest_and_highest_fee() { (Some(lowest_fee), Some(message_fee)) => { let message_reward; @@ -190,6 +192,15 @@ where } } } + + println!("messages_relayers_rewards {:?}", messages_rewards); + println!( + "confirmation_relayer_rewards {:?}", + confirmation_rewards + ); + println!("assigned_relayers_rewards {:?}", assigned_relayers_rewards); + println!("treasury_total_rewards {:?}", treasury_total_rewards); + RewardsBook { messages_relayers_rewards: messages_rewards, confirmation_relayer_rewards: confirmation_rewards, @@ -217,6 +228,7 @@ pub fn slash_assigned_relayers( for assigned_relayer in order.relayers_slice() { let slashed_asset = do_slash::(&assigned_relayer.id, relayer_fund_account, slash_max); + println!("slash {:?}, {:?}", assigned_relayer.id, slashed_asset.clone()); total_slash += slashed_asset; } } diff --git a/frame/fee-market/src/tests.rs b/frame/fee-market/src/tests.rs index bc5501ce33..7b6e7227bd 100644 --- a/frame/fee-market/src/tests.rs +++ b/frame/fee-market/src/tests.rs @@ -485,7 +485,16 @@ pub fn new_test_ext() -> sp_io::TestExternalities { .build_storage::() .unwrap(); darwinia_balances::GenesisConfig:: { - balances: vec![(1, 150), (2, 200), (3, 350), (4, 220), (5, 350), (12, 400)], + balances: vec![ + (1, 150), + (2, 200), + (3, 350), + (4, 220), + (5, 350), + (6, 500), + (7, 500), + (12, 400), + ], } .assimilate_storage(&mut t) .unwrap(); @@ -594,11 +603,8 @@ fn test_single_relayer_cancel_registration() { None )); assert!(FeeMarket::is_enrolled(&1)); - assert_err!( - FeeMarket::cancel_enrollment(Origin::signed(1)), - >::TooFewEnrolledRelayers - ); - assert!(FeeMarket::is_enrolled(&1)); + assert_ok!(FeeMarket::cancel_enrollment(Origin::signed(1))); + assert!(!FeeMarket::is_enrolled(&1)); }); } @@ -641,6 +647,7 @@ fn test_multiple_relayers_registration_with_same_lock_value_and_default_fee() { #[test] fn test_multiple_relayers_cancel_registration() { new_test_ext().execute_with(|| { + System::set_block_number(2); let _ = FeeMarket::enroll_and_lock_collateral(Origin::signed(1), 100, None); let _ = FeeMarket::enroll_and_lock_collateral(Origin::signed(2), 100, None); let _ = FeeMarket::enroll_and_lock_collateral(Origin::signed(3), 100, None); @@ -681,11 +688,27 @@ fn test_multiple_relayers_cancel_registration() { assert_eq!(FeeMarket::relayers(), vec![1, 2, 3, 4]); assert_eq!(FeeMarket::market_fee().unwrap(), 30); - assert_ok!(FeeMarket::cancel_enrollment(Origin::signed(4))); - assert_err!( - FeeMarket::cancel_enrollment(Origin::signed(2)), - >::TooFewEnrolledRelayers - ); + // clean order info, then 3 is able to cancel enrollment. + System::set_block_number(3); + assert_ok!(Messages::receive_messages_delivery_proof( + Origin::signed(5), + TestMessagesDeliveryProof(Ok(( + TEST_LANE_ID, + InboundLaneData { + relayers: vec![unrewarded_relayer(1, 1, TEST_RELAYER_A)] + .into_iter() + .collect(), + ..Default::default() + } + ))), + UnrewardedRelayersState { + unrewarded_relayer_entries: 1, + total_messages: 1, + ..Default::default() + }, + )); + assert_ok!(FeeMarket::cancel_enrollment(Origin::signed(3))); + assert!(!FeeMarket::market_fee().is_none()); }); } @@ -801,7 +824,7 @@ fn test_order_creation_when_bridged_pallet_accept_message() { let assigned_relayers = FeeMarket::assigned_relayers().unwrap(); let market_fee = FeeMarket::market_fee().unwrap(); let (lane, message_nonce) = send_regular_message(market_fee); - let order = FeeMarket::order(&lane, &message_nonce).unwrap(); + let order = FeeMarket::order((&lane, &message_nonce)).unwrap(); let relayers = order.relayers_slice(); assert_eq!(relayers[0].id, assigned_relayers.get(0).unwrap().id); assert_eq!(relayers[1].id, assigned_relayers.get(1).unwrap().id); @@ -838,12 +861,12 @@ fn test_order_confirm_time_set_when_bridged_pallet_confirmed_message() { let _ = FeeMarket::enroll_and_lock_collateral(Origin::signed(3), 120, Some(100)); let market_fee = FeeMarket::market_fee().unwrap(); let (lane, message_nonce) = send_regular_message(market_fee); - let order = FeeMarket::order(&lane, &message_nonce).unwrap(); + let order = FeeMarket::order((&lane, &message_nonce)).unwrap(); assert_eq!(order.confirm_time, None); System::set_block_number(4); receive_messages_delivery_proof(); - let order = FeeMarket::order(&lane, &message_nonce).unwrap(); + let order = FeeMarket::order((&lane, &message_nonce)).unwrap(); assert_eq!(order.confirm_time, Some(4)); assert_eq!(>::get().len(), 1); }); @@ -1019,40 +1042,41 @@ fn test_payment_reward_calculation_assigned_relayer_single_message_with_multiple fn test_assigned_relayers_slash_calculation() { new_test_ext().execute_with(|| { System::set_block_number(2); - let _ = FeeMarket::enroll_and_lock_collateral(Origin::signed(1), 100, Some(30)); - let _ = FeeMarket::enroll_and_lock_collateral(Origin::signed(2), 110, Some(50)); - let _ = FeeMarket::enroll_and_lock_collateral(Origin::signed(3), 120, Some(70)); + let _ = FeeMarket::enroll_and_lock_collateral(Origin::signed(5), 200, Some(30)); + let _ = FeeMarket::enroll_and_lock_collateral(Origin::signed(6), 200, Some(50)); + let _ = FeeMarket::enroll_and_lock_collateral(Origin::signed(7), 200, Some(70)); let market_fee = FeeMarket::market_fee().unwrap(); let (lane, message_nonce) = send_regular_message(market_fee); - let mut order = FeeMarket::order(&lane, &message_nonce).unwrap(); - assert_eq!(Ring::usable_balance(&1), 50); - assert_eq!(Ring::usable_balance(&2), 90); - assert_eq!(Ring::usable_balance(&3), 230); + let mut order = FeeMarket::order((&lane, &message_nonce)).unwrap(); + assert_eq!(Ring::usable_balance(&5), 150); + assert_eq!(Ring::usable_balance(&6), 300); + assert_eq!(Ring::usable_balance(&7), 300); order.confirm_time = order.range_end(); assert_eq!(slash_assigned_relayers::(order.clone(), &0), 210); - assert_eq!(Ring::usable_balance(&1), 50); - assert_eq!(Ring::usable_balance(&2), 90); - assert_eq!(Ring::usable_balance(&3), 230); - assert_eq!(FeeMarket::relayer_locked_collateral(&1), 30); - assert_eq!(FeeMarket::relayer_locked_collateral(&2), 40); - assert_eq!(FeeMarket::relayer_locked_collateral(&3), 50); + assert_eq!(Ring::usable_balance(&5), 150); + assert_eq!(Ring::usable_balance(&6), 300); + assert_eq!(Ring::usable_balance(&7), 300); + assert_eq!(FeeMarket::relayer_locked_collateral(&5), 130); + assert_eq!(FeeMarket::relayer_locked_collateral(&6), 130); + assert_eq!(FeeMarket::relayer_locked_collateral(&7), 130); assert_eq!(FeeMarket::assigned_relayers().unwrap().len(), 3); - order.confirm_time = Some(order.range_end().unwrap() + 5); - assert_eq!(slash_assigned_relayers::(order, &0), 120); - assert_eq!(Ring::usable_balance(&1), 50); - assert_eq!(Ring::usable_balance(&2), 90); - assert_eq!(Ring::usable_balance(&3), 230); - assert_eq!(FeeMarket::relayer_locked_collateral(&1), 0); - assert_eq!(FeeMarket::relayer_locked_collateral(&2), 0); - assert_eq!(FeeMarket::relayer_locked_collateral(&3), 0); - assert_eq!(FeeMarket::assigned_relayers().unwrap().len(), 3); + // slash value = 70 + 30 * 2 = 130 > 100 + order.confirm_time = Some(order.range_end().unwrap() + 30); + assert_eq!(slash_assigned_relayers::(order, &10), 300); + assert_eq!(Ring::usable_balance(&5), 180); + assert_eq!(Ring::usable_balance(&6), 330); + assert_eq!(Ring::usable_balance(&7), 330); + assert_eq!(FeeMarket::relayer_locked_collateral(&5), 0); + assert_eq!(FeeMarket::relayer_locked_collateral(&6), 0); + assert_eq!(FeeMarket::relayer_locked_collateral(&7), 0); + assert!(FeeMarket::assigned_relayers().is_none()); }); } #[test] -fn test_assigned_relayers_slash_kick_out() { +fn test_assigned_relayers_slash_kick_out_market_fee_hung() { new_test_ext().execute_with(|| { System::set_block_number(2); let _ = FeeMarket::enroll_and_lock_collateral(Origin::signed(1), 100, Some(30)); @@ -1061,7 +1085,7 @@ fn test_assigned_relayers_slash_kick_out() { let _ = FeeMarket::enroll_and_lock_collateral(Origin::signed(4), 120, Some(80)); let market_fee = FeeMarket::market_fee().unwrap(); let (lane, message_nonce) = send_regular_message(market_fee); - let mut order = FeeMarket::order(&lane, &message_nonce).unwrap(); + let mut order = FeeMarket::order((&lane, &message_nonce)).unwrap(); assert_eq!(Ring::usable_balance(&1), 50); assert_eq!(Ring::usable_balance(&2), 90); assert_eq!(Ring::usable_balance(&3), 230); @@ -1077,20 +1101,56 @@ fn test_assigned_relayers_slash_kick_out() { order.confirm_time = Some(order.range_end().unwrap() + 50); assert_eq!(slash_assigned_relayers::(order.clone(), &0), 300); assert_eq!(Ring::usable_balance(&1), 50); - assert_eq!(Ring::usable_balance(&2), 90); - assert_eq!(Ring::usable_balance(&3), 230); - assert_eq!(FeeMarket::relayer_locked_collateral(&1), 0); - assert_eq!(FeeMarket::relayer_locked_collateral(&2), 10); - assert_eq!(FeeMarket::relayer_locked_collateral(&3), 20); + assert!(!FeeMarket::is_enrolled(&1)); + assert_eq!(Ring::usable_balance(&2), 100); + assert!(!FeeMarket::is_enrolled(&2)); + assert_eq!(Ring::usable_balance(&3), 250); + assert!(!FeeMarket::is_enrolled(&3)); + assert!(FeeMarket::assigned_relayers().is_none()); + assert!(FeeMarket::market_fee().is_none()); + }); +} + +#[test] +fn test_assigned_relayers_slash_kick_out_market_fee_works() { + new_test_ext().execute_with(|| { + System::set_block_number(2); + let _ = FeeMarket::enroll_and_lock_collateral(Origin::signed(1), 100, Some(30)); + let _ = FeeMarket::enroll_and_lock_collateral(Origin::signed(3), 250, Some(50)); + let _ = FeeMarket::enroll_and_lock_collateral(Origin::signed(6), 300, Some(70)); + let _ = FeeMarket::enroll_and_lock_collateral(Origin::signed(7), 300, Some(80)); + let market_fee = FeeMarket::market_fee().unwrap(); + let (lane, message_nonce) = send_regular_message(market_fee); + let mut order = FeeMarket::order((&lane, &message_nonce)).unwrap(); + assert_eq!(Ring::usable_balance(&1), 50); + assert_eq!(Ring::usable_balance(&3), 100); + assert_eq!(Ring::usable_balance(&6), 200); assert_eq!( FeeMarket::assigned_relayers().unwrap(), vec![ - Relayer::::new(2, 10, 50), - Relayer::::new(3, 20, 70), - Relayer::::new(4, 120, 80), + Relayer::::new(1, 100, 30), + Relayer::::new(3, 250, 50), + Relayer::::new(6, 300, 70), ] ); + + order.confirm_time = Some(order.range_end().unwrap() + 50); + assert_eq!(slash_assigned_relayers::(order.clone(), &0), 300); + assert_eq!(Ring::usable_balance(&1), 50); assert!(!FeeMarket::is_enrolled(&1)); + assert_eq!(Ring::usable_balance(&3), 100); + assert!(FeeMarket::is_enrolled(&3)); + assert_eq!(Ring::usable_balance(&6), 200); + assert!(FeeMarket::is_enrolled(&6)); + assert_eq!( + FeeMarket::assigned_relayers().unwrap(), + vec![ + Relayer::::new(3, 150, 50), + Relayer::::new(6, 200, 70), + Relayer::::new(7, 300, 80), + ] + ); + assert_eq!(FeeMarket::market_fee().unwrap(), 80); }); } @@ -1168,14 +1228,14 @@ fn test_payment_reward_calculation_assigned_relayers_absent_with_multiple_messag ..Default::default() }, )); - assert!(TestMessageDeliveryAndDispatchPayment::is_reward_paid(5, 66)); + assert!(TestMessageDeliveryAndDispatchPayment::is_reward_paid(5, 60)); assert!(TestMessageDeliveryAndDispatchPayment::is_reward_paid( TEST_RELAYER_A, 240 )); assert!(TestMessageDeliveryAndDispatchPayment::is_reward_paid( TEST_RELAYER_B, - 24 + 0 )); }); } @@ -1216,19 +1276,19 @@ fn test_clean_order_state_at_the_end_of_block() { }, )); assert_eq!(ConfirmedMessagesThisBlock::::get().len(), 4); - assert!(FeeMarket::order(&lane1, &nonce1).is_some()); - assert!(FeeMarket::order(&lane2, &nonce2).is_some()); - assert!(FeeMarket::order(&lane3, &nonce3).is_some()); - assert!(FeeMarket::order(&lane4, &nonce4).is_some()); + assert!(FeeMarket::order((&lane1, &nonce1)).is_some()); + assert!(FeeMarket::order((&lane2, &nonce2)).is_some()); + assert!(FeeMarket::order((&lane3, &nonce3)).is_some()); + assert!(FeeMarket::order((&lane4, &nonce4)).is_some()); // Check in next block FeeMarket::on_finalize(10); System::set_block_number(1); assert_eq!(ConfirmedMessagesThisBlock::::get().len(), 0); - assert!(FeeMarket::order(&lane1, &nonce1).is_none()); - assert!(FeeMarket::order(&lane2, &nonce2).is_none()); - assert!(FeeMarket::order(&lane3, &nonce3).is_none()); - assert!(FeeMarket::order(&lane4, &nonce4).is_none()); + assert!(FeeMarket::order((&lane1, &nonce1)).is_none()); + assert!(FeeMarket::order((&lane2, &nonce2)).is_none()); + assert!(FeeMarket::order((&lane3, &nonce3)).is_none()); + assert!(FeeMarket::order((&lane4, &nonce4)).is_none()); }); } From 86c0752bb431f599da48dcae5dc905b4ad8b3cc7 Mon Sep 17 00:00:00 2001 From: ouwenkg <2630582710@qq.com> Date: Mon, 8 Nov 2021 15:02:40 +0800 Subject: [PATCH 08/46] Add order_capacity support --- frame/fee-market/src/lib.rs | 25 ++++++++++----- frame/fee-market/src/s2s/payment.rs | 11 ++++--- primitives/fee-market/src/lib.rs | 47 ++++++++++++++++++----------- 3 files changed, 53 insertions(+), 30 deletions(-) diff --git a/frame/fee-market/src/lib.rs b/frame/fee-market/src/lib.rs index 4ee94f99ce..c3b4a0cdda 100644 --- a/frame/fee-market/src/lib.rs +++ b/frame/fee-market/src/lib.rs @@ -68,6 +68,7 @@ pub mod pallet { type TreasuryPalletId: Get; #[pallet::constant] type LockId: Get; + /// The minimum locked collateral for a fee market relayer, also represented as the maximum value for slash. #[pallet::constant] type MiniumLockCollateral: Get>; @@ -90,6 +91,10 @@ pub mod pallet { /// The slash rule type Slasher: Slasher; + /// TODO: ADD more comment + #[pallet::constant] + type CollateralForEachOrder: Get>; + type RingCurrency: LockableCurrency + Currency; type Event: From> + IsType<::Event>; @@ -105,7 +110,7 @@ pub mod pallet { )] pub enum Event { /// Relayer enrollment - EnrollAndLockCollateral(T::AccountId, RingBalance, Fee), + EnrollAndLockCollateral(T::AccountId, RingBalance, Fee, u32), /// Update relayer locked collateral UpdateLockedCollateral(T::AccountId, RingBalance), /// Update relayer fee @@ -190,14 +195,14 @@ pub mod pallet { #[transactional] pub fn enroll_and_lock_collateral( origin: OriginFor, - lock_collateral: RingBalance, + order_capacity: u32, relay_fee: Option>, ) -> DispatchResultWithPostInfo { let who = ensure_signed(origin)?; - ensure!( - lock_collateral >= T::MiniumLockCollateral::get(), - >::LockCollateralTooLow - ); + // Calculate how many collateral needs for this order capacity. + let lock_collateral = + T::CollateralForEachOrder::get().saturating_mul(order_capacity.into()); + ensure!( T::RingCurrency::free_balance(&who) >= lock_collateral, >::InsufficientBalance @@ -217,14 +222,20 @@ pub mod pallet { WithdrawReasons::all(), ); - >::insert(&who, Relayer::new(who.clone(), lock_collateral, fee)); + // Store enrollment detail information. + >::insert( + &who, + Relayer::new(who.clone(), lock_collateral, fee, order_capacity), + ); >::append(who.clone()); Self::update_market(); + // TODO: let application knows about this changes. Self::deposit_event(Event::::EnrollAndLockCollateral( who, lock_collateral, fee, + order_capacity, )); Ok(().into()) } diff --git a/frame/fee-market/src/s2s/payment.rs b/frame/fee-market/src/s2s/payment.rs index b876d8a77e..6eb70ca25a 100644 --- a/frame/fee-market/src/s2s/payment.rs +++ b/frame/fee-market/src/s2s/payment.rs @@ -194,10 +194,7 @@ where } println!("messages_relayers_rewards {:?}", messages_rewards); - println!( - "confirmation_relayer_rewards {:?}", - confirmation_rewards - ); + println!("confirmation_relayer_rewards {:?}", confirmation_rewards); println!("assigned_relayers_rewards {:?}", assigned_relayers_rewards); println!("treasury_total_rewards {:?}", treasury_total_rewards); @@ -228,7 +225,11 @@ pub fn slash_assigned_relayers( for assigned_relayer in order.relayers_slice() { let slashed_asset = do_slash::(&assigned_relayer.id, relayer_fund_account, slash_max); - println!("slash {:?}, {:?}", assigned_relayer.id, slashed_asset.clone()); + println!( + "slash {:?}, {:?}", + assigned_relayer.id, + slashed_asset.clone() + ); total_slash += slashed_asset; } } diff --git a/primitives/fee-market/src/lib.rs b/primitives/fee-market/src/lib.rs index cfcc0be5df..5240385ade 100644 --- a/primitives/fee-market/src/lib.rs +++ b/primitives/fee-market/src/lib.rs @@ -31,14 +31,21 @@ pub struct Relayer { pub id: AccountId, pub collateral: Balance, pub fee: Balance, + pub order_capacity: u32, } impl Relayer { - pub fn new(id: AccountId, collateral: Balance, fee: Balance) -> Relayer { + pub fn new( + id: AccountId, + collateral: Balance, + fee: Balance, + order_capacity: u32, + ) -> Relayer { Relayer { id, collateral, fee, + order_capacity, } } } @@ -46,7 +53,7 @@ impl Relayer { impl PartialOrd for Relayer { fn partial_cmp(&self, other: &Self) -> Option { if self.fee == other.fee { - return other.collateral.partial_cmp(&self.collateral); + return other.order_capacity.partial_cmp(&self.order_capacity); } self.fee.partial_cmp(&other.fee) } @@ -55,7 +62,7 @@ impl PartialOrd for Relayer Ord for Relayer { fn cmp(&self, other: &Self) -> Ordering { if self.fee == other.fee { - return self.collateral.cmp(&other.collateral); + return self.order_capacity.cmp(&other.order_capacity); } self.fee.cmp(&other.fee) } @@ -63,7 +70,10 @@ impl Ord for Relayer { impl PartialEq for Relayer { fn eq(&self, other: &Self) -> bool { - self.fee == other.fee && self.id == other.id && self.collateral == other.collateral + self.fee == other.fee + && self.id == other.id + && self.collateral == other.collateral + && self.order_capacity == other.order_capacity } } @@ -73,6 +83,7 @@ impl Default for Relayer::new(1, 100, 30); - let r2 = Relayer::::new(2, 100, 40); + let r1 = Relayer::::new(1, 100, 30, 0); + let r2 = Relayer::::new(2, 100, 40, 0); assert!(r1 < r2); - let r3 = Relayer::::new(3, 150, 30); - let r4 = Relayer::::new(4, 100, 30); + let r3 = Relayer::::new(3, 150, 30, 30); + let r4 = Relayer::::new(4, 100, 30, 20); assert!(r3 < r4); } #[test] fn test_assign_order_relayers_one() { let mut assigned_relayers = Vec::new(); - assigned_relayers.push(Relayer::::new(1, 100, 30)); + assigned_relayers.push(Relayer::::new(1, 100, 30, 0)); let order = Order::new(TEST_LANE_ID, TEST_MESSAGE_NONCE, 100, assigned_relayers, 50); assert_eq!(order.relayer_valid_range(1).unwrap(), (100..150)); } @@ -229,8 +240,8 @@ mod test { #[test] fn test_assign_order_relayers_two() { let mut assigned_relayers = Vec::new(); - assigned_relayers.push(Relayer::::new(1, 100, 30)); - assigned_relayers.push(Relayer::::new(2, 100, 30)); + assigned_relayers.push(Relayer::::new(1, 100, 30, 0)); + assigned_relayers.push(Relayer::::new(2, 100, 30, 0)); let order = Order::new(TEST_LANE_ID, TEST_MESSAGE_NONCE, 100, assigned_relayers, 50); assert_eq!(order.relayer_valid_range(1).unwrap(), (100..150)); assert_eq!(order.relayer_valid_range(2).unwrap(), (150..200)); @@ -239,9 +250,9 @@ mod test { #[test] fn test_assign_order_relayers_three() { let mut assigned_relayers = Vec::new(); - assigned_relayers.push(Relayer::::new(1, 100, 30)); - assigned_relayers.push(Relayer::::new(2, 100, 40)); - assigned_relayers.push(Relayer::::new(3, 100, 80)); + assigned_relayers.push(Relayer::::new(1, 100, 30, 0)); + assigned_relayers.push(Relayer::::new(2, 100, 40, 0)); + assigned_relayers.push(Relayer::::new(3, 100, 80, 0)); let order = Order::new(TEST_LANE_ID, TEST_MESSAGE_NONCE, 100, assigned_relayers, 50); assert_eq!(order.relayer_valid_range(1).unwrap(), (100..150)); assert_eq!(order.relayer_valid_range(2).unwrap(), (150..200)); @@ -253,10 +264,10 @@ mod test { #[test] fn test_assign_order_relayers_four() { let mut assigned_relayers = Vec::new(); - assigned_relayers.push(Relayer::::new(1, 100, 30)); - assigned_relayers.push(Relayer::::new(2, 100, 30)); - assigned_relayers.push(Relayer::::new(3, 100, 30)); - assigned_relayers.push(Relayer::::new(4, 100, 30)); + assigned_relayers.push(Relayer::::new(1, 100, 30, 0)); + assigned_relayers.push(Relayer::::new(2, 100, 30, 0)); + assigned_relayers.push(Relayer::::new(3, 100, 30, 0)); + assigned_relayers.push(Relayer::::new(4, 100, 30, 0)); let order = Order::new(TEST_LANE_ID, TEST_MESSAGE_NONCE, 100, assigned_relayers, 50); assert_eq!(order.relayer_valid_range(1).unwrap(), (100..150)); assert_eq!(order.relayer_valid_range(2).unwrap(), (150..200)); From 4675beec3d33efd54518787967f198f43d6fb65b Mon Sep 17 00:00:00 2001 From: ouwenkg <2630582710@qq.com> Date: Mon, 8 Nov 2021 16:06:25 +0800 Subject: [PATCH 09/46] Add inc,dec relayer_order_capacity --- frame/fee-market/src/lib.rs | 79 +++++++++++++++++++-------- frame/fee-market/src/s2s/callbacks.rs | 18 +++--- 2 files changed, 68 insertions(+), 29 deletions(-) diff --git a/frame/fee-market/src/lib.rs b/frame/fee-market/src/lib.rs index c3b4a0cdda..2421ac4cfd 100644 --- a/frame/fee-market/src/lib.rs +++ b/frame/fee-market/src/lib.rs @@ -240,25 +240,31 @@ pub mod pallet { Ok(().into()) } - /// Update locked collateral for enrolled relayer, only supporting lock more. + /// Increase the order capacity for the enrolled relayer. + // todo: update the weight function #[pallet::weight(::WeightInfo::update_locked_collateral())] #[transactional] - pub fn update_locked_collateral( + pub fn increase_order_capacity( origin: OriginFor, - new_collateral: RingBalance, + new_order_capacity: u32, ) -> DispatchResultWithPostInfo { let who = ensure_signed(origin)?; ensure!(Self::is_enrolled(&who), >::NotEnrolled); ensure!( - T::RingCurrency::free_balance(&who) >= new_collateral, - >::InsufficientBalance + new_order_capacity > Self::get_relayer(&who).order_capacity, + // todo: update the error type + >::OnlyIncreaseLockedCollateralAllowed ); + + // Calculate how many collateral needs for this order capacity. + let new_collateral = + T::CollateralForEachOrder::get().saturating_mul(new_order_capacity.into()); ensure!( - new_collateral > Self::get_relayer(&who).collateral, - >::OnlyIncreaseLockedCollateralAllowed + T::RingCurrency::free_balance(&who) >= new_collateral, + >::InsufficientBalance ); - Self::update_collateral(&who, new_collateral); + Self::update_order_capacity(&who, new_collateral, Some(new_order_capacity)); Self::deposit_event(Event::::UpdateLockedCollateral(who, new_collateral)); Ok(().into()) } @@ -320,6 +326,7 @@ impl Pallet { let assigned_relayers_len = T::AssignedRelayersNumber::get() as usize; if relayers.len() >= assigned_relayers_len { relayers.sort(); + let mut assigned_relayers = Vec::with_capacity(assigned_relayers_len); for i in 0..assigned_relayers_len { if let Some(r) = relayers.get(i) { @@ -334,23 +341,32 @@ impl Pallet { } /// Update relayer locked collateral, then update market fee, this will changes RelayersMap storage. - pub fn update_collateral(who: &T::AccountId, new_collateral: RingBalance) { + pub fn update_order_capacity( + who: &T::AccountId, + new_collateral: RingBalance, + new_order_capacity: Option, + ) { + // todo: how to kick out slashed relayers // If the slashed collateral lower than MiniumLockCollateral, kick it out. - if new_collateral < T::MiniumLockCollateral::get() { - Self::remove_enrolled_relayer(who); - return; + // if new_collateral < T::MiniumLockCollateral::get() { + // Self::remove_enrolled_relayer(who); + // return; + // } + if let Some(new_capacity) = new_order_capacity { + let _ = T::RingCurrency::extend_lock( + T::LockId::get(), + who, + new_collateral, + WithdrawReasons::all(), + ) + .map_err(|_| >::ExtendLockFailed); + + >::mutate(who.clone(), |relayer| { + relayer.collateral = new_collateral; + relayer.order_capacity += new_capacity - relayer.order_capacity; + }); } - let _ = T::RingCurrency::extend_lock( - T::LockId::get(), - who, - new_collateral, - WithdrawReasons::all(), - ) - .map_err(|_| >::ExtendLockFailed); - >::mutate(who.clone(), |relayer| { - relayer.collateral = new_collateral; - }); Self::update_market(); } @@ -368,6 +384,25 @@ impl Pallet { Self::update_market(); } + pub fn inc_relayer_order_capacity(relayers: &[T::AccountId]) { + for who in relayers { + >::mutate(who.clone(), |r| { + r.order_capacity += 1; + }); + } + Self::update_market(); + } + + pub fn dec_relayer_order_capacity(relayers: &[T::AccountId]) { + // todo: need to check 0-1 case. + for who in relayers { + >::mutate(who.clone(), |r| { + r.order_capacity -= 1; + }); + } + Self::update_market(); + } + /// Whether the relayer has enrolled pub fn is_enrolled(who: &T::AccountId) -> bool { >::get().iter().any(|r| *r == *who) diff --git a/frame/fee-market/src/s2s/callbacks.rs b/frame/fee-market/src/s2s/callbacks.rs index ee224a71b3..4f6a00234e 100644 --- a/frame/fee-market/src/s2s/callbacks.rs +++ b/frame/fee-market/src/s2s/callbacks.rs @@ -27,21 +27,20 @@ pub struct FeeMarketMessageAcceptedHandler(PhantomData); impl OnMessageAccepted for FeeMarketMessageAcceptedHandler { // Called when the message is accepted by message pallet fn on_messages_accepted(lane: &LaneId, message: &MessageNonce) -> Weight { - let mut reads = 0; - let mut writes = 0; - // Create a new order based on the latest block, assign relayers which have priority to relaying let now = frame_system::Pallet::::block_number(); if let Some(assigned_relayers) = >::assigned_relayers() { - reads += 1; let order = Order::new(*lane, *message, now, assigned_relayers, T::Slot::get()); - // Store the create order >::insert((order.lane, order.message), order); - writes += 1; + + let assigned_relayers_ids: Vec = + assigned_relayers.iter().map(|relayer| relayer.id).collect(); + Pallet::::dec_relayer_order_capacity(&assigned_relayers_ids); } - ::DbWeight::get().reads_writes(reads, writes) + // TODO: The returned weight should be more accurately. See: https://github.com/darwinia-network/darwinia-common/issues/911 + ::DbWeight::get().reads_writes(1, 1) } } @@ -58,6 +57,11 @@ impl OnDeliveryConfirmed for FeeMarketMessageConfirmedHandler { None => {} }); >::append((lane, message_nonce)); + + let assigned_relayers_ids: Vec = + order.relayers_slice().iter().map(|r| r.id).collect(); + // todo: should we move this part after the reward? + Pallet::::inc_relayer_order_capacity(&assigned_relayers_ids); } } } From c94e86f9740416e58bc7a06ab0edaf684238806c Mon Sep 17 00:00:00 2001 From: ouwenkg <2630582710@qq.com> Date: Mon, 8 Nov 2021 17:23:21 +0800 Subject: [PATCH 10/46] Update slash logic to new design --- frame/fee-market/src/lib.rs | 188 ++++++++++++++------------ frame/fee-market/src/s2s/callbacks.rs | 21 ++- frame/fee-market/src/s2s/payment.rs | 23 +--- 3 files changed, 124 insertions(+), 108 deletions(-) diff --git a/frame/fee-market/src/lib.rs b/frame/fee-market/src/lib.rs index 2421ac4cfd..330e11a3ad 100644 --- a/frame/fee-market/src/lib.rs +++ b/frame/fee-market/src/lib.rs @@ -39,6 +39,7 @@ use frame_support::{ transactional, PalletId, }; use frame_system::{ensure_signed, pallet_prelude::*}; +use num_traits::Zero; use sp_runtime::{ traits::{Saturating, UniqueSaturatedInto}, Permill, @@ -69,9 +70,6 @@ pub mod pallet { #[pallet::constant] type LockId: Get; - /// The minimum locked collateral for a fee market relayer, also represented as the maximum value for slash. - #[pallet::constant] - type MiniumLockCollateral: Get>; /// The minimum fee for relaying. #[pallet::constant] type MinimumRelayFee: Get>; @@ -93,7 +91,7 @@ pub mod pallet { type Slasher: Slasher; /// TODO: ADD more comment #[pallet::constant] - type CollateralForEachOrder: Get>; + type CollateralEachOrder: Get>; type RingCurrency: LockableCurrency + Currency; @@ -110,28 +108,31 @@ pub mod pallet { )] pub enum Event { /// Relayer enrollment - EnrollAndLockCollateral(T::AccountId, RingBalance, Fee, u32), - /// Update relayer locked collateral - UpdateLockedCollateral(T::AccountId, RingBalance), - /// Update relayer fee - UpdateRelayFee(T::AccountId, Fee), + Enroll(T::AccountId, RingBalance, Fee, u32), + /// Update relayer + UpdateRelayer( + T::AccountId, + Option>, + Option, + Option>, + ), /// Relayer cancel enrollment CancelEnrollment(T::AccountId), } #[pallet::error] pub enum Error { - /// Insufficient balance + /// Insufficient balance. InsufficientBalance, - /// The locked collateral is lower than MiniumLockLimit + /// The locked collateral is lower than MiniumLockLimit. LockCollateralTooLow, - /// The relayer has been enrolled + /// The relayer has been enrolled. AlreadyEnrolled, - /// This relayer doesn't enroll ever + /// This relayer doesn't enroll ever. NotEnrolled, - /// Only increase lock collateral is allowed when update_locked_balance - OnlyIncreaseLockedCollateralAllowed, - /// The fee is lower than MinimumRelayFee + /// Only increase order capacity is allowed. + OnlyIncreaseOrderCapacityAllowed, + /// The fee is lower than MinimumRelayFee. RelayFeeTooLow, /// The relayer is occupied, and can't cancel enrollment now. OccupiedRelayer, @@ -191,28 +192,30 @@ pub mod pallet { /// Any accounts can enroll to be a relayer by lock collateral. The relay fee is optional, /// the default value is MinimumRelayFee in runtime. /// Note: One account can enroll only once. + /// todo: update the weight function #[pallet::weight(::WeightInfo::enroll_and_lock_collateral())] #[transactional] - pub fn enroll_and_lock_collateral( + pub fn enroll( origin: OriginFor, order_capacity: u32, relay_fee: Option>, ) -> DispatchResultWithPostInfo { let who = ensure_signed(origin)?; + ensure!(!Self::is_enrolled(&who), >::AlreadyEnrolled); + // Calculate how many collateral needs for this order capacity. let lock_collateral = - T::CollateralForEachOrder::get().saturating_mul(order_capacity.into()); - + T::CollateralEachOrder::get().saturating_mul(order_capacity.into()); ensure!( T::RingCurrency::free_balance(&who) >= lock_collateral, >::InsufficientBalance ); - ensure!(!Self::is_enrolled(&who), >::AlreadyEnrolled); + if let Some(fee) = relay_fee { ensure!(fee >= T::MinimumRelayFee::get(), >::RelayFeeTooLow); } - let fee = relay_fee.unwrap_or_else(T::MinimumRelayFee::get); + T::RingCurrency::set_lock( T::LockId::get(), &who, @@ -221,7 +224,6 @@ pub mod pallet { }, WithdrawReasons::all(), ); - // Store enrollment detail information. >::insert( &who, @@ -230,8 +232,7 @@ pub mod pallet { >::append(who.clone()); Self::update_market(); - // TODO: let application knows about this changes. - Self::deposit_event(Event::::EnrollAndLockCollateral( + Self::deposit_event(Event::::Enroll( who, lock_collateral, fee, @@ -252,33 +253,36 @@ pub mod pallet { ensure!(Self::is_enrolled(&who), >::NotEnrolled); ensure!( new_order_capacity > Self::get_relayer(&who).order_capacity, - // todo: update the error type - >::OnlyIncreaseLockedCollateralAllowed + >::OnlyIncreaseOrderCapacityAllowed ); // Calculate how many collateral needs for this order capacity. let new_collateral = - T::CollateralForEachOrder::get().saturating_mul(new_order_capacity.into()); + T::CollateralEachOrder::get().saturating_mul(new_order_capacity.into()); ensure!( T::RingCurrency::free_balance(&who) >= new_collateral, >::InsufficientBalance ); - Self::update_order_capacity(&who, new_collateral, Some(new_order_capacity)); - Self::deposit_event(Event::::UpdateLockedCollateral(who, new_collateral)); - Ok(().into()) - } - - /// Cancel enrolled relayer - #[pallet::weight(::WeightInfo::cancel_enrollment())] - #[transactional] - pub fn cancel_enrollment(origin: OriginFor) -> DispatchResultWithPostInfo { - let who = ensure_signed(origin)?; - ensure!(Self::is_enrolled(&who), >::NotEnrolled); - ensure!(!Self::is_occupied(&who), >::OccupiedRelayer); + let _ = T::RingCurrency::extend_lock( + T::LockId::get(), + &who, + new_collateral, + WithdrawReasons::all(), + ) + .map_err(|_| >::ExtendLockFailed); + >::mutate(who.clone(), |relayer| { + relayer.collateral = new_collateral; + relayer.order_capacity += new_order_capacity - relayer.order_capacity; + }); - Self::remove_enrolled_relayer(&who); - Self::deposit_event(Event::::CancelEnrollment(who)); + Self::update_market(); + Self::deposit_event(Event::::UpdateRelayer( + who, + Some(new_collateral), + Some(new_order_capacity), + None, + )); Ok(().into()) } @@ -287,21 +291,34 @@ pub mod pallet { #[transactional] pub fn update_relay_fee( origin: OriginFor, - relay_fee: Fee, + new_fee: Fee, ) -> DispatchResultWithPostInfo { let who = ensure_signed(origin)?; ensure!(Self::is_enrolled(&who), >::NotEnrolled); ensure!( - relay_fee >= T::MinimumRelayFee::get(), + new_fee >= T::MinimumRelayFee::get(), >::RelayFeeTooLow ); >::mutate(who.clone(), |relayer| { - relayer.fee = relay_fee; + relayer.fee = new_fee; }); Self::update_market(); - Self::deposit_event(Event::::UpdateRelayFee(who, relay_fee)); + Self::deposit_event(Event::::UpdateRelayer(who, None, None, Some(new_fee))); + Ok(().into()) + } + + /// Cancel enrolled relayer + #[pallet::weight(::WeightInfo::cancel_enrollment())] + #[transactional] + pub fn cancel_enrollment(origin: OriginFor) -> DispatchResultWithPostInfo { + let who = ensure_signed(origin)?; + ensure!(Self::is_enrolled(&who), >::NotEnrolled); + ensure!(!Self::is_occupied(&who), >::OccupiedRelayer); + + Self::remove_enrolled_relayer(&who); + Self::deposit_event(Event::::CancelEnrollment(who)); Ok(().into()) } } @@ -310,10 +327,9 @@ pub mod pallet { impl Pallet { /// An important update in this pallet, need to update market information in the following cases: /// - /// - When new relayer enroll - /// - When enrolled relayer wants to update relaying fee - /// - When enrolled relayer wants to cancel enrollment - /// - When some enrolled relayer's collateral below MiniumLockCollateral, might trigger market update + /// - When new relayer enroll. + /// - When enrolled relayer wants to update fee or order capacity. + /// - When enrolled relayer wants to cancel enrollment. pub fn update_market() { // Sort all enrolled relayers firstly. let mut relayers: Vec>> = >::get() @@ -328,8 +344,13 @@ impl Pallet { relayers.sort(); let mut assigned_relayers = Vec::with_capacity(assigned_relayers_len); - for i in 0..assigned_relayers_len { - if let Some(r) = relayers.get(i) { + // todo: need more tests. + while let Some(r) = relayers.iter().next() { + if assigned_relayers.len() == assigned_relayers_len { + break; + } + + if r.order_capacity >= 1 { assigned_relayers.push(r); } } @@ -340,33 +361,28 @@ impl Pallet { } } - /// Update relayer locked collateral, then update market fee, this will changes RelayersMap storage. - pub fn update_order_capacity( - who: &T::AccountId, - new_collateral: RingBalance, - new_order_capacity: Option, - ) { - // todo: how to kick out slashed relayers - // If the slashed collateral lower than MiniumLockCollateral, kick it out. - // if new_collateral < T::MiniumLockCollateral::get() { - // Self::remove_enrolled_relayer(who); - // return; - // } - if let Some(new_capacity) = new_order_capacity { - let _ = T::RingCurrency::extend_lock( - T::LockId::get(), - who, - new_collateral, - WithdrawReasons::all(), - ) - .map_err(|_| >::ExtendLockFailed); - - >::mutate(who.clone(), |relayer| { - relayer.collateral = new_collateral; - relayer.order_capacity += new_capacity - relayer.order_capacity; - }); + /// Update relayer after slash occurred, this will changes RelayersMap storage. + pub fn update_relayer_after_slash(who: &T::AccountId, new_collateral: RingBalance) { + if new_collateral == RingBalance::::zero() { + Self::remove_enrolled_relayer(who); + return; } + // Update locked collateral + let _ = T::RingCurrency::extend_lock( + T::LockId::get(), + who, + new_collateral, + WithdrawReasons::all(), + ) + .map_err(|_| >::ExtendLockFailed); + // Update order capacity + let new_capacity = new_collateral.saturating_div(T::CollateralEachOrder::get()); + >::mutate(who.clone(), |relayer| { + relayer.collateral = new_collateral; + relayer.order_capacity += new_capacity - relayer.order_capacity; + }); + Self::update_market(); } @@ -384,20 +400,22 @@ impl Pallet { Self::update_market(); } - pub fn inc_relayer_order_capacity(relayers: &[T::AccountId]) { + /// Decrease relayer order capacity by 1 after message order created. + pub fn dec_relayer_order_capacity(relayers: &[T::AccountId]) { + // todo: need to check 0-1 case. for who in relayers { >::mutate(who.clone(), |r| { - r.order_capacity += 1; + r.order_capacity -= 1; }); } Self::update_market(); } - pub fn dec_relayer_order_capacity(relayers: &[T::AccountId]) { - // todo: need to check 0-1 case. + /// Increase relayer order capacity by 1 after message order confirmed. + pub fn inc_relayer_order_capacity(relayers: &[T::AccountId]) { for who in relayers { >::mutate(who.clone(), |r| { - r.order_capacity -= 1; + r.order_capacity += 1; }); } Self::update_market(); @@ -443,8 +461,7 @@ impl Slasher for () { // Note: The maximum slash result is the MiniumLockCollateral. We mush ensures that all enrolled // relayers have ability to pay this slash result. fn slash(base_fee: Fee, timeout: T::BlockNumber) -> RingBalance { - // Slash 20 RING for each delay block until the maximum slash value - let slash_each_block = 20_000_000_000u128; + let slash_each_block = 2_000_000_000u128; let timeout_u128: u128 = timeout.unique_saturated_into(); let mut slash = base_fee.saturating_add( timeout_u128 @@ -452,8 +469,9 @@ impl Slasher for () { .unique_saturated_into(), ); - if slash >= T::MiniumLockCollateral::get() { - slash = T::MiniumLockCollateral::get(); + // todo: need more tests. + if slash >= T::CollateralEachOrder::get() { + slash = T::CollateralEachOrder::get(); } slash } diff --git a/frame/fee-market/src/s2s/callbacks.rs b/frame/fee-market/src/s2s/callbacks.rs index 4f6a00234e..3aed65244b 100644 --- a/frame/fee-market/src/s2s/callbacks.rs +++ b/frame/fee-market/src/s2s/callbacks.rs @@ -30,12 +30,20 @@ impl OnMessageAccepted for FeeMarketMessageAcceptedHandler { // Create a new order based on the latest block, assign relayers which have priority to relaying let now = frame_system::Pallet::::block_number(); if let Some(assigned_relayers) = >::assigned_relayers() { - let order = Order::new(*lane, *message, now, assigned_relayers, T::Slot::get()); + let order = Order::new( + *lane, + *message, + now, + assigned_relayers.clone(), + T::Slot::get(), + ); // Store the create order >::insert((order.lane, order.message), order); - let assigned_relayers_ids: Vec = - assigned_relayers.iter().map(|relayer| relayer.id).collect(); + let assigned_relayers_ids: Vec = assigned_relayers + .iter() + .map(|relayer| relayer.id.clone()) + .collect(); Pallet::::dec_relayer_order_capacity(&assigned_relayers_ids); } @@ -58,8 +66,11 @@ impl OnDeliveryConfirmed for FeeMarketMessageConfirmedHandler { }); >::append((lane, message_nonce)); - let assigned_relayers_ids: Vec = - order.relayers_slice().iter().map(|r| r.id).collect(); + let assigned_relayers_ids: Vec = order + .relayers_slice() + .iter() + .map(|r| r.id.clone()) + .collect(); // todo: should we move this part after the reward? Pallet::::inc_relayer_order_capacity(&assigned_relayers_ids); } diff --git a/frame/fee-market/src/s2s/payment.rs b/frame/fee-market/src/s2s/payment.rs index 6eb70ca25a..6ef8c852d2 100644 --- a/frame/fee-market/src/s2s/payment.rs +++ b/frame/fee-market/src/s2s/payment.rs @@ -139,7 +139,6 @@ where break; } } - println!("the message relayer is {:?}", message_relayer); match order.lowest_and_highest_fee() { (Some(lowest_fee), Some(message_fee)) => { @@ -192,12 +191,6 @@ where } } } - - println!("messages_relayers_rewards {:?}", messages_rewards); - println!("confirmation_relayer_rewards {:?}", confirmation_rewards); - println!("assigned_relayers_rewards {:?}", assigned_relayers_rewards); - println!("treasury_total_rewards {:?}", treasury_total_rewards); - RewardsBook { messages_relayers_rewards: messages_rewards, confirmation_relayer_rewards: confirmation_rewards, @@ -217,19 +210,10 @@ pub fn slash_assigned_relayers( let timeout = confirm_time - end_time; let message_fee = order.lowest_and_highest_fee().1.unwrap_or_default(); let slash_max = T::Slasher::slash(message_fee, timeout); - debug_assert!( - slash_max <= T::MiniumLockCollateral::get(), - "The maximum slash value returned from Slasher is MiniumLockCollateral" - ); for assigned_relayer in order.relayers_slice() { let slashed_asset = do_slash::(&assigned_relayer.id, relayer_fund_account, slash_max); - println!( - "slash {:?}, {:?}", - assigned_relayer.id, - slashed_asset.clone() - ); total_slash += slashed_asset; } } @@ -246,8 +230,10 @@ pub fn do_slash( ) -> RingBalance { let slashed; let locked_collateral = crate::Pallet::::relayer_locked_collateral(&slash_account); + T::RingCurrency::remove_lock(T::LockId::get(), &slash_account); if locked_collateral >= slash_max { + // The original locked collateral is able to cover slash. slashed = slash_max; let locked_reserved = locked_collateral.saturating_sub(slashed); let _ = ::RingCurrency::transfer( @@ -256,8 +242,9 @@ pub fn do_slash( slashed, ExistenceRequirement::AllowDeath, ); - crate::Pallet::::update_collateral(&slash_account, locked_reserved); + crate::Pallet::::update_relayer_after_slash(&slash_account, locked_reserved); } else { + // The original locked collateral is not enough, slash all locked collateral before. slashed = locked_collateral; let _ = ::RingCurrency::transfer( slash_account, @@ -265,7 +252,7 @@ pub fn do_slash( slashed, ExistenceRequirement::AllowDeath, ); - crate::Pallet::::update_collateral(&slash_account, RingBalance::::zero()); + crate::Pallet::::update_relayer_after_slash(&slash_account, RingBalance::::zero()); } slashed } From 7669a5d4d9dbda56e599d6644a2510e4e7f67ed9 Mon Sep 17 00:00:00 2001 From: ouwenkg <2630582710@qq.com> Date: Mon, 8 Nov 2021 17:42:28 +0800 Subject: [PATCH 11/46] Use / to get new order capacity --- frame/fee-market/src/lib.rs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/frame/fee-market/src/lib.rs b/frame/fee-market/src/lib.rs index 330e11a3ad..aa8cb59c69 100644 --- a/frame/fee-market/src/lib.rs +++ b/frame/fee-market/src/lib.rs @@ -42,7 +42,7 @@ use frame_system::{ensure_signed, pallet_prelude::*}; use num_traits::Zero; use sp_runtime::{ traits::{Saturating, UniqueSaturatedInto}, - Permill, + Permill, SaturatedConversion, }; use sp_std::{default::Default, vec::Vec}; // --- darwinia-network --- @@ -377,10 +377,11 @@ impl Pallet { ) .map_err(|_| >::ExtendLockFailed); // Update order capacity - let new_capacity = new_collateral.saturating_div(T::CollateralEachOrder::get()); + let new_capacity: u32 = + (new_collateral / T::CollateralEachOrder::get()).saturated_into::(); >::mutate(who.clone(), |relayer| { relayer.collateral = new_collateral; - relayer.order_capacity += new_capacity - relayer.order_capacity; + relayer.order_capacity = new_capacity; }); Self::update_market(); From 99155a040089712f9eb60244413c3844be9ed184 Mon Sep 17 00:00:00 2001 From: ouwenkg <2630582710@qq.com> Date: Mon, 8 Nov 2021 17:50:39 +0800 Subject: [PATCH 12/46] Do not break api, use original interface --- frame/fee-market/src/lib.rs | 33 ++++++++++++++------------------- 1 file changed, 14 insertions(+), 19 deletions(-) diff --git a/frame/fee-market/src/lib.rs b/frame/fee-market/src/lib.rs index aa8cb59c69..b7b7946b75 100644 --- a/frame/fee-market/src/lib.rs +++ b/frame/fee-market/src/lib.rs @@ -130,8 +130,8 @@ pub mod pallet { AlreadyEnrolled, /// This relayer doesn't enroll ever. NotEnrolled, - /// Only increase order capacity is allowed. - OnlyIncreaseOrderCapacityAllowed, + /// Only increase lock collateral is allowed when update_locked_balance. + OnlyIncreaseLockedCollateralAllowed, /// The fee is lower than MinimumRelayFee. RelayFeeTooLow, /// The relayer is occupied, and can't cancel enrollment now. @@ -192,24 +192,22 @@ pub mod pallet { /// Any accounts can enroll to be a relayer by lock collateral. The relay fee is optional, /// the default value is MinimumRelayFee in runtime. /// Note: One account can enroll only once. - /// todo: update the weight function #[pallet::weight(::WeightInfo::enroll_and_lock_collateral())] #[transactional] - pub fn enroll( + pub fn enroll_and_lock_collateral( origin: OriginFor, - order_capacity: u32, + lock_collateral: RingBalance, relay_fee: Option>, ) -> DispatchResultWithPostInfo { let who = ensure_signed(origin)?; ensure!(!Self::is_enrolled(&who), >::AlreadyEnrolled); - // Calculate how many collateral needs for this order capacity. - let lock_collateral = - T::CollateralEachOrder::get().saturating_mul(order_capacity.into()); ensure!( T::RingCurrency::free_balance(&who) >= lock_collateral, >::InsufficientBalance ); + let order_capacity: u32 = + (lock_collateral / T::CollateralEachOrder::get()).saturated_into::(); if let Some(fee) = relay_fee { ensure!(fee >= T::MinimumRelayFee::get(), >::RelayFeeTooLow); @@ -242,28 +240,25 @@ pub mod pallet { } /// Increase the order capacity for the enrolled relayer. - // todo: update the weight function #[pallet::weight(::WeightInfo::update_locked_collateral())] #[transactional] - pub fn increase_order_capacity( + pub fn update_locked_collateral( origin: OriginFor, - new_order_capacity: u32, + new_collateral: RingBalance, ) -> DispatchResultWithPostInfo { let who = ensure_signed(origin)?; ensure!(Self::is_enrolled(&who), >::NotEnrolled); - ensure!( - new_order_capacity > Self::get_relayer(&who).order_capacity, - >::OnlyIncreaseOrderCapacityAllowed - ); - - // Calculate how many collateral needs for this order capacity. - let new_collateral = - T::CollateralEachOrder::get().saturating_mul(new_order_capacity.into()); ensure!( T::RingCurrency::free_balance(&who) >= new_collateral, >::InsufficientBalance ); + ensure!( + new_collateral > Self::get_relayer(&who).collateral, + >::OnlyIncreaseLockedCollateralAllowed + ); + let new_order_capacity: u32 = + (new_collateral / T::CollateralEachOrder::get()).saturated_into::(); let _ = T::RingCurrency::extend_lock( T::LockId::get(), &who, From b0324159122c76ec18c8290cad504d26c41d8d88 Mon Sep 17 00:00:00 2001 From: ouwenkg <2630582710@qq.com> Date: Mon, 8 Nov 2021 17:55:24 +0800 Subject: [PATCH 13/46] The code part finished, More unit tests needed. --- frame/fee-market/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frame/fee-market/src/lib.rs b/frame/fee-market/src/lib.rs index b7b7946b75..0024e920d8 100644 --- a/frame/fee-market/src/lib.rs +++ b/frame/fee-market/src/lib.rs @@ -239,7 +239,7 @@ pub mod pallet { Ok(().into()) } - /// Increase the order capacity for the enrolled relayer. + /// Update locked collateral for enrolled relayer, only supporting lock more. #[pallet::weight(::WeightInfo::update_locked_collateral())] #[transactional] pub fn update_locked_collateral( From 760fc378270201b83f0b4800f7628c35f38387bd Mon Sep 17 00:00:00 2001 From: ouwenkg <2630582710@qq.com> Date: Mon, 8 Nov 2021 20:44:00 +0800 Subject: [PATCH 14/46] Remove slasher --- frame/fee-market/src/lib.rs | 35 ++++------------------------- frame/fee-market/src/s2s/payment.rs | 11 +++++++-- frame/fee-market/src/tests.rs | 4 ++-- 3 files changed, 15 insertions(+), 35 deletions(-) diff --git a/frame/fee-market/src/lib.rs b/frame/fee-market/src/lib.rs index 0024e920d8..35d6aa2876 100644 --- a/frame/fee-market/src/lib.rs +++ b/frame/fee-market/src/lib.rs @@ -40,10 +40,7 @@ use frame_support::{ }; use frame_system::{ensure_signed, pallet_prelude::*}; use num_traits::Zero; -use sp_runtime::{ - traits::{Saturating, UniqueSaturatedInto}, - Permill, SaturatedConversion, -}; +use sp_runtime::{traits::UniqueSaturatedInto, Permill, SaturatedConversion}; use sp_std::{default::Default, vec::Vec}; // --- darwinia-network --- use darwinia_support::{ @@ -73,6 +70,7 @@ pub mod pallet { /// The minimum fee for relaying. #[pallet::constant] type MinimumRelayFee: Get>; + /// The assigned relayers number for each order. #[pallet::constant] type AssignedRelayersNumber: Get; /// The slot times set @@ -88,8 +86,8 @@ pub mod pallet { type ConfirmRelayersRewardRatio: Get; /// The slash rule - type Slasher: Slasher; - /// TODO: ADD more comment + type SlashForEachBlock: Get>; + /// The collateral relayer need to lock for each order. #[pallet::constant] type CollateralEachOrder: Get>; @@ -447,28 +445,3 @@ impl Pallet { false } } - -pub trait Slasher { - fn slash(base_fee: RingBalance, timeout: T::BlockNumber) -> RingBalance; -} - -impl Slasher for () { - // The slash result = base_fee + slash_each_block * timeout - // Note: The maximum slash result is the MiniumLockCollateral. We mush ensures that all enrolled - // relayers have ability to pay this slash result. - fn slash(base_fee: Fee, timeout: T::BlockNumber) -> RingBalance { - let slash_each_block = 2_000_000_000u128; - let timeout_u128: u128 = timeout.unique_saturated_into(); - let mut slash = base_fee.saturating_add( - timeout_u128 - .saturating_mul(slash_each_block) - .unique_saturated_into(), - ); - - // todo: need more tests. - if slash >= T::CollateralEachOrder::get() { - slash = T::CollateralEachOrder::get(); - } - slash - } -} diff --git a/frame/fee-market/src/s2s/payment.rs b/frame/fee-market/src/s2s/payment.rs index 6ef8c852d2..542eeb05c1 100644 --- a/frame/fee-market/src/s2s/payment.rs +++ b/frame/fee-market/src/s2s/payment.rs @@ -207,9 +207,16 @@ pub fn slash_assigned_relayers( let mut total_slash = RingBalance::::zero(); match (order.confirm_time, order.range_end()) { (Some(confirm_time), Some(end_time)) if confirm_time >= end_time => { - let timeout = confirm_time - end_time; + let timeout: u128 = (confirm_time - end_time).unique_saturated_into(); let message_fee = order.lowest_and_highest_fee().1.unwrap_or_default(); - let slash_max = T::Slasher::slash(message_fee, timeout); + let slash = message_fee.saturating_add( + timeout + .saturating_mul(UniqueSaturatedInto::::unique_saturated_into( + T::SlashForEachBlock::get(), + )) + .unique_saturated_into(), + ); + let slash_max = sp_std::cmp::min(slash, T::CollateralEachOrder::get()); for assigned_relayer in order.relayers_slice() { let slashed_asset = diff --git a/frame/fee-market/src/tests.rs b/frame/fee-market/src/tests.rs index 7b6e7227bd..b8681d4517 100644 --- a/frame/fee-market/src/tests.rs +++ b/frame/fee-market/src/tests.rs @@ -420,7 +420,7 @@ frame_support::parameter_types! { pub const TreasuryPalletId: PalletId = PalletId(*b"da/trsry"); pub const FeeMarketLockId: LockIdentifier = *b"da/feelf"; pub const MinimumRelayFee: Balance = 30; - pub const MiniumLockCollateral: Balance = 100; + pub const CollateralEachOrder: Balance = 100; pub const AssignedRelayersNumber: u64 = 3; pub const Slot: u64 = 50; @@ -452,7 +452,7 @@ impl Config for Test { type PalletId = FeeMarketPalletId; type TreasuryPalletId = TreasuryPalletId; type LockId = FeeMarketLockId; - type MiniumLockCollateral = MiniumLockCollateral; + type CollateralEachOrder = CollateralEachOrder; type MinimumRelayFee = MinimumRelayFee; type AssignedRelayersNumber = AssignedRelayersNumber; type Slot = Slot; From aefc80ccb9a2ce3cdc228a6e7740bd4088e75ae7 Mon Sep 17 00:00:00 2001 From: ouwenkg <2630582710@qq.com> Date: Mon, 8 Nov 2021 21:48:20 +0800 Subject: [PATCH 15/46] Test 1 --- frame/fee-market/src/lib.rs | 27 +++--- frame/fee-market/src/tests.rs | 166 ++++++++++++++++------------------ 2 files changed, 90 insertions(+), 103 deletions(-) diff --git a/frame/fee-market/src/lib.rs b/frame/fee-market/src/lib.rs index 35d6aa2876..e22dae89c4 100644 --- a/frame/fee-market/src/lib.rs +++ b/frame/fee-market/src/lib.rs @@ -40,7 +40,10 @@ use frame_support::{ }; use frame_system::{ensure_signed, pallet_prelude::*}; use num_traits::Zero; -use sp_runtime::{traits::UniqueSaturatedInto, Permill, SaturatedConversion}; +use sp_runtime::{ + traits::{Saturating, UniqueSaturatedInto}, + Permill, SaturatedConversion, +}; use sp_std::{default::Default, vec::Vec}; // --- darwinia-network --- use darwinia_support::{ @@ -122,14 +125,12 @@ pub mod pallet { pub enum Error { /// Insufficient balance. InsufficientBalance, - /// The locked collateral is lower than MiniumLockLimit. - LockCollateralTooLow, /// The relayer has been enrolled. AlreadyEnrolled, /// This relayer doesn't enroll ever. NotEnrolled, /// Only increase lock collateral is allowed when update_locked_balance. - OnlyIncreaseLockedCollateralAllowed, + OnlyIncCollateralAllowed, /// The fee is lower than MinimumRelayFee. RelayFeeTooLow, /// The relayer is occupied, and can't cancel enrollment now. @@ -225,7 +226,7 @@ pub mod pallet { &who, Relayer::new(who.clone(), lock_collateral, fee, order_capacity), ); - >::append(who.clone()); + >::append(&who); Self::update_market(); Self::deposit_event(Event::::Enroll( @@ -250,13 +251,10 @@ pub mod pallet { T::RingCurrency::free_balance(&who) >= new_collateral, >::InsufficientBalance ); - ensure!( - new_collateral > Self::get_relayer(&who).collateral, - >::OnlyIncreaseLockedCollateralAllowed - ); - let new_order_capacity: u32 = - (new_collateral / T::CollateralEachOrder::get()).saturated_into::(); + let collat_diff = new_collateral.saturating_sub(Self::get_relayer(&who).collateral); + ensure!(collat_diff > >::zero(), >::OnlyIncCollateralAllowed); + let _ = T::RingCurrency::extend_lock( T::LockId::get(), &who, @@ -266,14 +264,15 @@ pub mod pallet { .map_err(|_| >::ExtendLockFailed); >::mutate(who.clone(), |relayer| { relayer.collateral = new_collateral; - relayer.order_capacity += new_order_capacity - relayer.order_capacity; + relayer.order_capacity += + (collat_diff / T::CollateralEachOrder::get()).saturated_into::(); }); Self::update_market(); Self::deposit_event(Event::::UpdateRelayer( - who, + who.clone(), Some(new_collateral), - Some(new_order_capacity), + Some(Self::get_relayer(&who).order_capacity), None, )); Ok(().into()) diff --git a/frame/fee-market/src/tests.rs b/frame/fee-market/src/tests.rs index b8681d4517..22445747d6 100644 --- a/frame/fee-market/src/tests.rs +++ b/frame/fee-market/src/tests.rs @@ -423,6 +423,7 @@ frame_support::parameter_types! { pub const CollateralEachOrder: Balance = 100; pub const AssignedRelayersNumber: u64 = 3; pub const Slot: u64 = 50; + pub const SlashForEachBlock: Balance = 2; pub const AssignedRelayersRewardRatio: Permill = Permill::from_percent(60); pub const MessageRelayersRewardRatio: Permill = Permill::from_percent(80); @@ -430,24 +431,6 @@ frame_support::parameter_types! { pub const TreasuryPalletAccount: u64 = 666; } -pub struct MockSlasher; -impl Slasher for MockSlasher { - fn slash(base: Fee, timeout: T::BlockNumber) -> RingBalance { - let slash_each_block = 2u128; - let timeout_u128: u128 = timeout.unique_saturated_into(); - let mut slash = base.saturating_add( - timeout_u128 - .saturating_mul(slash_each_block) - .unique_saturated_into(), - ); - - if slash >= T::MiniumLockCollateral::get() { - slash = T::MiniumLockCollateral::get(); - } - slash - } -} - impl Config for Test { type PalletId = FeeMarketPalletId; type TreasuryPalletId = TreasuryPalletId; @@ -456,11 +439,11 @@ impl Config for Test { type MinimumRelayFee = MinimumRelayFee; type AssignedRelayersNumber = AssignedRelayersNumber; type Slot = Slot; + type SlashForEachBlock = SlashForEachBlock; type AssignedRelayersRewardRatio = AssignedRelayersRewardRatio; type MessageRelayersRewardRatio = MessageRelayersRewardRatio; type ConfirmRelayersRewardRatio = ConfirmRelayersRewardRatio; - type Slasher = MockSlasher; type RingCurrency = Ring; type Event = Event; @@ -534,13 +517,9 @@ pub fn unrewarded_relayer( } #[test] -fn test_single_relayer_registration_workflow_works() { +fn test_single_relayer_enroll_workflow_works() { new_test_ext().execute_with(|| { assert_eq!(Ring::free_balance(1), 150); - assert_err!( - FeeMarket::enroll_and_lock_collateral(Origin::signed(1), 1, None), - >::LockCollateralTooLow - ); assert_err!( FeeMarket::enroll_and_lock_collateral(Origin::signed(1), 200, None), >::InsufficientBalance @@ -556,35 +535,44 @@ fn test_single_relayer_registration_workflow_works() { assert_eq!(Ring::free_balance(1), 150); assert_eq!(Ring::usable_balance(&1), 50); assert_eq!(FeeMarket::relayer_locked_collateral(&1), 100); + assert_eq!(FeeMarket::get_relayer(1).order_capacity, 1); assert_eq!(FeeMarket::market_fee(), None); - assert_err!( FeeMarket::enroll_and_lock_collateral(Origin::signed(1), 100, None), >::AlreadyEnrolled ); + + assert_ok!(FeeMarket::enroll_and_lock_collateral( + Origin::signed(3), + 250, + None + )); + assert_eq!(FeeMarket::get_relayer(3).order_capacity, 2); }); } #[test] fn test_single_relayer_update_lock_collateral() { new_test_ext().execute_with(|| { assert_err!( - FeeMarket::update_locked_collateral(Origin::signed(1), 120), + FeeMarket::update_locked_collateral(Origin::signed(6), 100), >::NotEnrolled ); assert_ok!(FeeMarket::enroll_and_lock_collateral( - Origin::signed(1), - 100, + Origin::signed(6), + 200, None )); - assert_eq!(FeeMarket::relayer_locked_collateral(&1), 100); + assert_eq!(FeeMarket::relayer_locked_collateral(&6), 200); + assert_eq!(FeeMarket::get_relayer(6).order_capacity, 2); // Increase locked balance - assert_ok!(FeeMarket::update_locked_collateral(Origin::signed(1), 120)); - assert_eq!(FeeMarket::relayer_locked_collateral(&1), 120); + assert_ok!(FeeMarket::update_locked_collateral(Origin::signed(6), 500)); + assert_eq!(FeeMarket::relayer_locked_collateral(&6), 500); + assert_eq!(FeeMarket::get_relayer(6).order_capacity, 5); // Decrease locked balance assert_err!( - FeeMarket::update_locked_collateral(Origin::signed(1), 100), - >::OnlyIncreaseLockedCollateralAllowed + FeeMarket::update_locked_collateral(Origin::signed(6), 80), + >::OnlyIncCollateralAllowed ); }); } @@ -657,14 +645,14 @@ fn test_multiple_relayers_cancel_registration() { assert_eq!(FeeMarket::relayer_locked_collateral(&1), 100); assert_eq!(FeeMarket::relayer_locked_collateral(&2), 100); assert_eq!(FeeMarket::market_fee().unwrap(), 30); - assert_eq!( - FeeMarket::assigned_relayers().unwrap(), - vec![ - Relayer::::new(1, 100, 30), - Relayer::::new(2, 100, 30), - Relayer::::new(3, 100, 30), - ] - ); + // assert_eq!( + // FeeMarket::assigned_relayers().unwrap(), + // vec![ + // Relayer::::new(1, 100, 30), + // Relayer::::new(2, 100, 30), + // Relayer::::new(3, 100, 30), + // ] + // ); // Test enrolled relayer not allowed to cancel cancel_enrollment when occupied let market_fee = FeeMarket::market_fee().unwrap(); @@ -722,14 +710,14 @@ fn test_multiple_relayers_choose_assigned_relayers_with_same_default_fee() { let _ = FeeMarket::enroll_and_lock_collateral(Origin::signed(5), 140, None); assert_eq!(FeeMarket::relayers().len(), 5); - assert_eq!( - FeeMarket::assigned_relayers().unwrap(), - vec![ - Relayer::::new(5, 140, 30), - Relayer::::new(4, 130, 30), - Relayer::::new(3, 120, 30), - ] - ); + // assert_eq!( + // FeeMarket::assigned_relayers().unwrap(), + // vec![ + // Relayer::::new(5, 140, 30), + // Relayer::::new(4, 130, 30), + // Relayer::::new(3, 120, 30), + // ] + // ); assert_eq!(FeeMarket::market_fee().unwrap(), 30); }); } @@ -744,14 +732,14 @@ fn test_multiple_relayers_choose_assigned_relayers_with_same_lock_balance() { let _ = FeeMarket::enroll_and_lock_collateral(Origin::signed(5), 100, Some(70)); assert_eq!(FeeMarket::relayers().len(), 5); - assert_eq!( - FeeMarket::assigned_relayers().unwrap(), - vec![ - Relayer::::new(1, 100, 30), - Relayer::::new(2, 100, 40), - Relayer::::new(3, 100, 50), - ] - ); + // assert_eq!( + // FeeMarket::assigned_relayers().unwrap(), + // vec![ + // Relayer::::new(1, 100, 30), + // Relayer::::new(2, 100, 40), + // Relayer::::new(3, 100, 50), + // ] + // ); assert_eq!(FeeMarket::market_fee().unwrap(), 50); }); } @@ -766,14 +754,14 @@ fn test_multiple_relayers_choose_assigned_relayers_with_diff_lock_and_fee() { let _ = FeeMarket::enroll_and_lock_collateral(Origin::signed(4), 100, Some(50)); assert_eq!(FeeMarket::relayers().len(), 4); - assert_eq!( - FeeMarket::assigned_relayers().unwrap(), - vec![ - Relayer::::new(1, 100, 30), - Relayer::::new(2, 100, 40), - Relayer::::new(3, 120, 50), - ] - ); + // assert_eq!( + // FeeMarket::assigned_relayers().unwrap(), + // vec![ + // Relayer::::new(1, 100, 30), + // Relayer::::new(2, 100, 40), + // Relayer::::new(3, 120, 50), + // ] + // ); assert_eq!(FeeMarket::market_fee().unwrap(), 50); }); } @@ -1089,14 +1077,14 @@ fn test_assigned_relayers_slash_kick_out_market_fee_hung() { assert_eq!(Ring::usable_balance(&1), 50); assert_eq!(Ring::usable_balance(&2), 90); assert_eq!(Ring::usable_balance(&3), 230); - assert_eq!( - FeeMarket::assigned_relayers().unwrap(), - vec![ - Relayer::::new(1, 100, 30), - Relayer::::new(2, 110, 50), - Relayer::::new(3, 120, 70), - ] - ); + // assert_eq!( + // FeeMarket::assigned_relayers().unwrap(), + // vec![ + // Relayer::::new(1, 100, 30), + // Relayer::::new(2, 110, 50), + // Relayer::::new(3, 120, 70), + // ] + // ); order.confirm_time = Some(order.range_end().unwrap() + 50); assert_eq!(slash_assigned_relayers::(order.clone(), &0), 300); @@ -1125,14 +1113,14 @@ fn test_assigned_relayers_slash_kick_out_market_fee_works() { assert_eq!(Ring::usable_balance(&1), 50); assert_eq!(Ring::usable_balance(&3), 100); assert_eq!(Ring::usable_balance(&6), 200); - assert_eq!( - FeeMarket::assigned_relayers().unwrap(), - vec![ - Relayer::::new(1, 100, 30), - Relayer::::new(3, 250, 50), - Relayer::::new(6, 300, 70), - ] - ); + // assert_eq!( + // FeeMarket::assigned_relayers().unwrap(), + // vec![ + // Relayer::::new(1, 100, 30), + // Relayer::::new(3, 250, 50), + // Relayer::::new(6, 300, 70), + // ] + // ); order.confirm_time = Some(order.range_end().unwrap() + 50); assert_eq!(slash_assigned_relayers::(order.clone(), &0), 300); @@ -1142,14 +1130,14 @@ fn test_assigned_relayers_slash_kick_out_market_fee_works() { assert!(FeeMarket::is_enrolled(&3)); assert_eq!(Ring::usable_balance(&6), 200); assert!(FeeMarket::is_enrolled(&6)); - assert_eq!( - FeeMarket::assigned_relayers().unwrap(), - vec![ - Relayer::::new(3, 150, 50), - Relayer::::new(6, 200, 70), - Relayer::::new(7, 300, 80), - ] - ); + // assert_eq!( + // FeeMarket::assigned_relayers().unwrap(), + // vec![ + // Relayer::::new(3, 150, 50), + // Relayer::::new(6, 200, 70), + // Relayer::::new(7, 300, 80), + // ] + // ); assert_eq!(FeeMarket::market_fee().unwrap(), 80); }); } From 06729d4cc65d2a423d75a991b93f04cd52903532 Mon Sep 17 00:00:00 2001 From: ouwenkg <2630582710@qq.com> Date: Tue, 9 Nov 2021 15:11:31 +0800 Subject: [PATCH 16/46] Test 2 --- frame/fee-market/src/lib.rs | 37 +++++-- frame/fee-market/src/tests.rs | 183 +++++++++++-------------------- primitives/fee-market/src/lib.rs | 20 +++- 3 files changed, 102 insertions(+), 138 deletions(-) diff --git a/frame/fee-market/src/lib.rs b/frame/fee-market/src/lib.rs index e22dae89c4..5bef32cd25 100644 --- a/frame/fee-market/src/lib.rs +++ b/frame/fee-market/src/lib.rs @@ -125,6 +125,8 @@ pub mod pallet { pub enum Error { /// Insufficient balance. InsufficientBalance, + /// The locked collateral is lower than CollateralEachOrder. + LockCollateralTooLow, /// The relayer has been enrolled. AlreadyEnrolled, /// This relayer doesn't enroll ever. @@ -205,6 +207,10 @@ pub mod pallet { T::RingCurrency::free_balance(&who) >= lock_collateral, >::InsufficientBalance ); + ensure!( + lock_collateral >= T::CollateralEachOrder::get(), + >::LockCollateralTooLow + ); let order_capacity: u32 = (lock_collateral / T::CollateralEachOrder::get()).saturated_into::(); @@ -252,8 +258,18 @@ pub mod pallet { >::InsufficientBalance ); - let collat_diff = new_collateral.saturating_sub(Self::get_relayer(&who).collateral); - ensure!(collat_diff > >::zero(), >::OnlyIncCollateralAllowed); + let relayer = Self::get_relayer(&who); + let old_capacity: u32 = + (relayer.collateral / T::CollateralEachOrder::get()).saturated_into::(); + let used_capacity = old_capacity.saturating_sub(relayer.order_capacity); + + let new_capacity: u32 = + (new_collateral / T::CollateralEachOrder::get()).saturated_into::(); + // let collat_diff = new_collateral.saturating_sub(Self::get_relayer(&who).collateral); + ensure!( + new_collateral > relayer.collateral, + >::OnlyIncCollateralAllowed + ); let _ = T::RingCurrency::extend_lock( T::LockId::get(), @@ -264,8 +280,7 @@ pub mod pallet { .map_err(|_| >::ExtendLockFailed); >::mutate(who.clone(), |relayer| { relayer.collateral = new_collateral; - relayer.order_capacity += - (collat_diff / T::CollateralEachOrder::get()).saturated_into::(); + relayer.order_capacity = new_capacity - used_capacity; }); Self::update_market(); @@ -323,29 +338,27 @@ impl Pallet { /// - When enrolled relayer wants to update fee or order capacity. /// - When enrolled relayer wants to cancel enrollment. pub fn update_market() { - // Sort all enrolled relayers firstly. + // Sort all enrolled relayers who are able to accept orders. let mut relayers: Vec>> = >::get() .iter() .map(RelayersMap::::get) + .filter(|r| r.order_capacity >= 1) .collect(); // Select the first `AssignedRelayersNumber` relayers as AssignedRelayer. - // Only when total relayer's number greater than `AssignedRelayersNumber`, selection happens. let assigned_relayers_len = T::AssignedRelayersNumber::get() as usize; if relayers.len() >= assigned_relayers_len { relayers.sort(); let mut assigned_relayers = Vec::with_capacity(assigned_relayers_len); - // todo: need more tests. - while let Some(r) = relayers.iter().next() { + let mut relayer_iterator = relayers.into_iter(); + while let Some(r) = relayer_iterator.next() { if assigned_relayers.len() == assigned_relayers_len { break; } - - if r.order_capacity >= 1 { - assigned_relayers.push(r); - } + assigned_relayers.push(r); } + >::put(assigned_relayers); } else { // The enrolled relayers not enough, pallet can't provide any fee advice. diff --git a/frame/fee-market/src/tests.rs b/frame/fee-market/src/tests.rs index 22445747d6..e2a3fb5597 100644 --- a/frame/fee-market/src/tests.rs +++ b/frame/fee-market/src/tests.rs @@ -548,6 +548,11 @@ fn test_single_relayer_enroll_workflow_works() { None )); assert_eq!(FeeMarket::get_relayer(3).order_capacity, 2); + + assert_err!( + FeeMarket::enroll_and_lock_collateral(Origin::signed(4), 30, None), + >::LockCollateralTooLow + ); }); } #[test] @@ -578,7 +583,7 @@ fn test_single_relayer_update_lock_collateral() { } #[test] -fn test_single_relayer_cancel_registration() { +fn test_relayer_cancel_registration() { new_test_ext().execute_with(|| { assert_err!( FeeMarket::cancel_enrollment(Origin::signed(1)), @@ -593,70 +598,21 @@ fn test_single_relayer_cancel_registration() { assert!(FeeMarket::is_enrolled(&1)); assert_ok!(FeeMarket::cancel_enrollment(Origin::signed(1))); assert!(!FeeMarket::is_enrolled(&1)); - }); -} - -#[test] -fn test_single_relayer_update_fee_works() { - new_test_ext().execute_with(|| { - assert_err!( - FeeMarket::update_relay_fee(Origin::signed(1), 1), - >::NotEnrolled - ); - assert_ok!(FeeMarket::enroll_and_lock_collateral( - Origin::signed(1), - 100, - None - )); - assert_err!( - FeeMarket::update_relay_fee(Origin::signed(1), 1), - >::RelayFeeTooLow - ); - - assert_eq!(FeeMarket::relayer_fee(&1), 30); - assert_ok!(FeeMarket::update_relay_fee(Origin::signed(1), 40)); - assert_eq!(FeeMarket::relayer_fee(&1), 40); - }); -} -#[test] -fn test_multiple_relayers_registration_with_same_lock_value_and_default_fee() { - new_test_ext().execute_with(|| { - let _ = FeeMarket::enroll_and_lock_collateral(Origin::signed(1), 100, None); - let _ = FeeMarket::enroll_and_lock_collateral(Origin::signed(2), 100, None); - let _ = FeeMarket::enroll_and_lock_collateral(Origin::signed(3), 100, None); - let _ = FeeMarket::enroll_and_lock_collateral(Origin::signed(4), 100, None); - - assert_eq!(FeeMarket::relayers(), vec![1, 2, 3, 4]); - assert_eq!(FeeMarket::market_fee().unwrap(), 30); - }); -} - -#[test] -fn test_multiple_relayers_cancel_registration() { - new_test_ext().execute_with(|| { System::set_block_number(2); let _ = FeeMarket::enroll_and_lock_collateral(Origin::signed(1), 100, None); - let _ = FeeMarket::enroll_and_lock_collateral(Origin::signed(2), 100, None); - let _ = FeeMarket::enroll_and_lock_collateral(Origin::signed(3), 100, None); - let _ = FeeMarket::enroll_and_lock_collateral(Origin::signed(4), 100, None); - let _ = FeeMarket::enroll_and_lock_collateral(Origin::signed(5), 100, None); - assert_eq!(FeeMarket::relayers(), vec![1, 2, 3, 4, 5]); - assert_eq!(FeeMarket::relayer_locked_collateral(&1), 100); - assert_eq!(FeeMarket::relayer_locked_collateral(&2), 100); - assert_eq!(FeeMarket::market_fee().unwrap(), 30); - // assert_eq!( - // FeeMarket::assigned_relayers().unwrap(), - // vec![ - // Relayer::::new(1, 100, 30), - // Relayer::::new(2, 100, 30), - // Relayer::::new(3, 100, 30), - // ] - // ); - - // Test enrolled relayer not allowed to cancel cancel_enrollment when occupied - let market_fee = FeeMarket::market_fee().unwrap(); - let (_, _) = send_regular_message(market_fee); + let _ = FeeMarket::enroll_and_lock_collateral(Origin::signed(2), 110, Some(50)); + let _ = FeeMarket::enroll_and_lock_collateral(Origin::signed(3), 120, Some(100)); + assert_eq!(FeeMarket::relayers(), vec![1, 2, 3]); + assert_eq!( + FeeMarket::assigned_relayers().unwrap(), + vec![ + Relayer::::new(1, 100, 30, 1), + Relayer::::new(2, 110, 50, 1), + Relayer::::new(3, 120, 100, 1), + ] + ); + let _ = send_regular_message(FeeMarket::market_fee().unwrap()); assert_err!( FeeMarket::cancel_enrollment(Origin::signed(1)), >::OccupiedRelayer @@ -670,12 +626,6 @@ fn test_multiple_relayers_cancel_registration() { >::OccupiedRelayer ); - assert_ok!(FeeMarket::cancel_enrollment(Origin::signed(5))); - assert!(!FeeMarket::is_enrolled(&5)); - assert_eq!(FeeMarket::relayer_locked_collateral(&5), 0); - assert_eq!(FeeMarket::relayers(), vec![1, 2, 3, 4]); - assert_eq!(FeeMarket::market_fee().unwrap(), 30); - // clean order info, then 3 is able to cancel enrollment. System::set_block_number(3); assert_ok!(Messages::receive_messages_delivery_proof( @@ -696,75 +646,68 @@ fn test_multiple_relayers_cancel_registration() { }, )); assert_ok!(FeeMarket::cancel_enrollment(Origin::signed(3))); - assert!(!FeeMarket::market_fee().is_none()); + assert_eq!(FeeMarket::relayers(), vec![1, 2]); + assert!(FeeMarket::assigned_relayers().is_none()); + assert!(FeeMarket::market_fee().is_none()); }); } #[test] -fn test_multiple_relayers_choose_assigned_relayers_with_same_default_fee() { +fn test_single_relayer_update_fee_works() { new_test_ext().execute_with(|| { + assert_err!( + FeeMarket::update_relay_fee(Origin::signed(1), 1), + >::NotEnrolled + ); let _ = FeeMarket::enroll_and_lock_collateral(Origin::signed(1), 100, None); - let _ = FeeMarket::enroll_and_lock_collateral(Origin::signed(2), 110, None); - let _ = FeeMarket::enroll_and_lock_collateral(Origin::signed(3), 120, None); - let _ = FeeMarket::enroll_and_lock_collateral(Origin::signed(4), 130, None); - let _ = FeeMarket::enroll_and_lock_collateral(Origin::signed(5), 140, None); + let _ = FeeMarket::enroll_and_lock_collateral(Origin::signed(2), 110, Some(50)); + let _ = FeeMarket::enroll_and_lock_collateral(Origin::signed(3), 120, Some(100)); + assert_eq!(FeeMarket::market_fee(), Some(100)); + assert_err!( + FeeMarket::update_relay_fee(Origin::signed(1), 1), + >::RelayFeeTooLow + ); - assert_eq!(FeeMarket::relayers().len(), 5); - // assert_eq!( - // FeeMarket::assigned_relayers().unwrap(), - // vec![ - // Relayer::::new(5, 140, 30), - // Relayer::::new(4, 130, 30), - // Relayer::::new(3, 120, 30), - // ] - // ); - assert_eq!(FeeMarket::market_fee().unwrap(), 30); + assert_eq!(FeeMarket::relayer_fee(&1), 30); + assert_ok!(FeeMarket::update_relay_fee(Origin::signed(1), 40)); + assert_eq!(FeeMarket::relayer_fee(&1), 40); + + assert_ok!(FeeMarket::update_relay_fee(Origin::signed(3), 150)); + assert_eq!(FeeMarket::relayer_fee(&3), 150); + assert_eq!(FeeMarket::market_fee(), Some(150)); }); } #[test] -fn test_multiple_relayers_choose_assigned_relayers_with_same_lock_balance() { +fn test_market_fee() { new_test_ext().execute_with(|| { - let _ = FeeMarket::enroll_and_lock_collateral(Origin::signed(1), 100, Some(30)); - let _ = FeeMarket::enroll_and_lock_collateral(Origin::signed(2), 100, Some(40)); - let _ = FeeMarket::enroll_and_lock_collateral(Origin::signed(3), 100, Some(50)); - let _ = FeeMarket::enroll_and_lock_collateral(Origin::signed(4), 100, Some(60)); - let _ = FeeMarket::enroll_and_lock_collateral(Origin::signed(5), 100, Some(70)); + let _ = FeeMarket::enroll_and_lock_collateral(Origin::signed(1), 100, None); + let _ = FeeMarket::enroll_and_lock_collateral(Origin::signed(2), 110, None); + assert!(FeeMarket::market_fee().is_none()); - assert_eq!(FeeMarket::relayers().len(), 5); - // assert_eq!( - // FeeMarket::assigned_relayers().unwrap(), - // vec![ - // Relayer::::new(1, 100, 30), - // Relayer::::new(2, 100, 40), - // Relayer::::new(3, 100, 50), - // ] - // ); - assert_eq!(FeeMarket::market_fee().unwrap(), 50); + assert_err!( + FeeMarket::enroll_and_lock_collateral(Origin::signed(3), 110, None), + >::LockCollateralTooLow + ); + assert!(FeeMarket::market_fee().is_none()); + assert_ok!(FeeMarket::update_locked_collateral(Origin::signed(3), 200)); + assert_eq!(FeeMarket::market_fee(), Some(30)); + assert_eq!( + FeeMarket::assigned_relayers().unwrap(), + vec![ + Relayer::::new(3, 200, 30, 2), + Relayer::::new(2, 110, 30, 1), + Relayer::::new(1, 100, 30, 1), + ] + ); }); } -#[test] -#[test] -fn test_multiple_relayers_choose_assigned_relayers_with_diff_lock_and_fee() { - new_test_ext().execute_with(|| { - let _ = FeeMarket::enroll_and_lock_collateral(Origin::signed(1), 100, Some(30)); - let _ = FeeMarket::enroll_and_lock_collateral(Origin::signed(2), 100, Some(40)); - let _ = FeeMarket::enroll_and_lock_collateral(Origin::signed(3), 120, Some(50)); - let _ = FeeMarket::enroll_and_lock_collateral(Origin::signed(4), 100, Some(50)); +// A -> enroll 1000 -> order capacity = 10 -> send 2 message -> order capacity = 8 +// update_locked_collateral to 2000 -> diff = 1000 -> 18 个 - assert_eq!(FeeMarket::relayers().len(), 4); - // assert_eq!( - // FeeMarket::assigned_relayers().unwrap(), - // vec![ - // Relayer::::new(1, 100, 30), - // Relayer::::new(2, 100, 40), - // Relayer::::new(3, 120, 50), - // ] - // ); - assert_eq!(FeeMarket::market_fee().unwrap(), 50); - }); -} +// B -> enroll 120 -> order capacity = 1 +// update_locked_collateral to 400 -> diff = 280 -> 2 个 fn send_regular_message(fee: Balance) -> (LaneId, u64) { let message_nonce = Messages::outbound_latest_generated_nonce(TEST_LANE_ID) + 1; diff --git a/primitives/fee-market/src/lib.rs b/primitives/fee-market/src/lib.rs index 5240385ade..2e53e868a9 100644 --- a/primitives/fee-market/src/lib.rs +++ b/primitives/fee-market/src/lib.rs @@ -52,8 +52,10 @@ impl Relayer { impl PartialOrd for Relayer { fn partial_cmp(&self, other: &Self) -> Option { - if self.fee == other.fee { + if self.fee == other.fee && self.order_capacity != other.order_capacity { return other.order_capacity.partial_cmp(&self.order_capacity); + } else if self.fee == other.fee && self.order_capacity == other.order_capacity { + return other.collateral.partial_cmp(&self.collateral); } self.fee.partial_cmp(&other.fee) } @@ -61,8 +63,10 @@ impl PartialOrd for Relayer Ord for Relayer { fn cmp(&self, other: &Self) -> Ordering { - if self.fee == other.fee { - return self.order_capacity.cmp(&other.order_capacity); + if self.fee == other.fee && self.order_capacity != other.order_capacity { + return other.order_capacity.cmp(&self.order_capacity); + } else if self.fee == other.fee && self.order_capacity == other.order_capacity { + return other.collateral.cmp(&self.collateral); } self.fee.cmp(&other.fee) } @@ -220,13 +224,17 @@ mod test { #[test] fn test_multi_relayers_sort() { - let r1 = Relayer::::new(1, 100, 30, 0); + let r1 = Relayer::::new(1, 150, 30, 0); let r2 = Relayer::::new(2, 100, 40, 0); assert!(r1 < r2); - let r3 = Relayer::::new(3, 150, 30, 30); + let r3 = Relayer::::new(3, 150, 30, 10); let r4 = Relayer::::new(4, 100, 30, 20); - assert!(r3 < r4); + assert!(r4 < r3); + + let r5 = Relayer::::new(3, 150, 30, 10); + let r6 = Relayer::::new(4, 100, 30, 10); + assert!(r5 < r6); } #[test] From 1d2569264e1ce0228d2e128f32fd0f2b1fe40917 Mon Sep 17 00:00:00 2001 From: ouwenkg <2630582710@qq.com> Date: Tue, 9 Nov 2021 17:23:37 +0800 Subject: [PATCH 17/46] Test 3 --- frame/fee-market/src/lib.rs | 33 ++--- frame/fee-market/src/s2s/payment.rs | 59 ++++---- frame/fee-market/src/tests.rs | 211 +++++++++++++++++----------- 3 files changed, 173 insertions(+), 130 deletions(-) diff --git a/frame/fee-market/src/lib.rs b/frame/fee-market/src/lib.rs index 5bef32cd25..9e24a3ce18 100644 --- a/frame/fee-market/src/lib.rs +++ b/frame/fee-market/src/lib.rs @@ -125,8 +125,6 @@ pub mod pallet { pub enum Error { /// Insufficient balance. InsufficientBalance, - /// The locked collateral is lower than CollateralEachOrder. - LockCollateralTooLow, /// The relayer has been enrolled. AlreadyEnrolled, /// This relayer doesn't enroll ever. @@ -207,10 +205,6 @@ pub mod pallet { T::RingCurrency::free_balance(&who) >= lock_collateral, >::InsufficientBalance ); - ensure!( - lock_collateral >= T::CollateralEachOrder::get(), - >::LockCollateralTooLow - ); let order_capacity: u32 = (lock_collateral / T::CollateralEachOrder::get()).saturated_into::(); @@ -259,17 +253,15 @@ pub mod pallet { ); let relayer = Self::get_relayer(&who); + ensure!( + new_collateral > relayer.collateral, + >::OnlyIncCollateralAllowed + ); let old_capacity: u32 = (relayer.collateral / T::CollateralEachOrder::get()).saturated_into::(); let used_capacity = old_capacity.saturating_sub(relayer.order_capacity); - let new_capacity: u32 = (new_collateral / T::CollateralEachOrder::get()).saturated_into::(); - // let collat_diff = new_collateral.saturating_sub(Self::get_relayer(&who).collateral); - ensure!( - new_collateral > relayer.collateral, - >::OnlyIncCollateralAllowed - ); let _ = T::RingCurrency::extend_lock( T::LockId::get(), @@ -367,8 +359,12 @@ impl Pallet { } /// Update relayer after slash occurred, this will changes RelayersMap storage. - pub fn update_relayer_after_slash(who: &T::AccountId, new_collateral: RingBalance) { - if new_collateral == RingBalance::::zero() { + pub fn update_relayer_after_slash( + who: &T::AccountId, + new_collateral: RingBalance, + new_order_capacity: u32, + ) { + if new_collateral == RingBalance::::zero() || new_order_capacity == 0 { Self::remove_enrolled_relayer(who); return; } @@ -381,12 +377,9 @@ impl Pallet { WithdrawReasons::all(), ) .map_err(|_| >::ExtendLockFailed); - // Update order capacity - let new_capacity: u32 = - (new_collateral / T::CollateralEachOrder::get()).saturated_into::(); >::mutate(who.clone(), |relayer| { relayer.collateral = new_collateral; - relayer.order_capacity = new_capacity; + relayer.order_capacity = new_order_capacity; }); Self::update_market(); @@ -411,7 +404,7 @@ impl Pallet { // todo: need to check 0-1 case. for who in relayers { >::mutate(who.clone(), |r| { - r.order_capacity -= 1; + r.order_capacity = r.order_capacity.saturating_sub(1); }); } Self::update_market(); @@ -421,7 +414,7 @@ impl Pallet { pub fn inc_relayer_order_capacity(relayers: &[T::AccountId]) { for who in relayers { >::mutate(who.clone(), |r| { - r.order_capacity += 1; + r.order_capacity = r.order_capacity.saturating_add(1); }); } Self::update_market(); diff --git a/frame/fee-market/src/s2s/payment.rs b/frame/fee-market/src/s2s/payment.rs index 542eeb05c1..4b34f04300 100644 --- a/frame/fee-market/src/s2s/payment.rs +++ b/frame/fee-market/src/s2s/payment.rs @@ -191,6 +191,17 @@ where } } } + println!("book: messages_relayers_rewards {:?}", messages_rewards); + println!( + "book: confirmation_relayer_rewards {:?}", + confirmation_rewards + ); + println!( + "book: assigned_relayers_rewards {:?}", + assigned_relayers_rewards + ); + println!("book: treasury_total_rewards {:?}", treasury_total_rewards); + RewardsBook { messages_relayers_rewards: messages_rewards, confirmation_relayer_rewards: confirmation_rewards, @@ -233,35 +244,31 @@ pub fn slash_assigned_relayers( pub fn do_slash( slash_account: &T::AccountId, fund_account: &T::AccountId, - slash_max: RingBalance, + slash_value: RingBalance, ) -> RingBalance { - let slashed; - let locked_collateral = crate::Pallet::::relayer_locked_collateral(&slash_account); + let relayer = crate::Pallet::::get_relayer(&slash_account); + let (locked_collateral, usable_order_capacity) = (relayer.collateral, relayer.order_capacity); + let slash_capacity: u32 = (slash_value / T::CollateralEachOrder::get()).saturated_into::(); T::RingCurrency::remove_lock(T::LockId::get(), &slash_account); - if locked_collateral >= slash_max { - // The original locked collateral is able to cover slash. - slashed = slash_max; - let locked_reserved = locked_collateral.saturating_sub(slashed); - let _ = ::RingCurrency::transfer( - slash_account, - fund_account, - slashed, - ExistenceRequirement::AllowDeath, - ); - crate::Pallet::::update_relayer_after_slash(&slash_account, locked_reserved); - } else { - // The original locked collateral is not enough, slash all locked collateral before. - slashed = locked_collateral; - let _ = ::RingCurrency::transfer( - slash_account, - fund_account, - slashed, - ExistenceRequirement::AllowDeath, - ); - crate::Pallet::::update_relayer_after_slash(&slash_account, RingBalance::::zero()); - } - slashed + debug_assert!( + locked_collateral >= slash_value, + "The locked collateral must alway greater than slash max" + ); + + let _ = ::RingCurrency::transfer( + slash_account, + fund_account, + slash_value, + ExistenceRequirement::AllowDeath, + ); + crate::Pallet::::update_relayer_after_slash( + &slash_account, + locked_collateral.saturating_sub(slash_value), + usable_order_capacity.saturating_sub(slash_capacity), + ); + + slash_value } /// Do reward diff --git a/frame/fee-market/src/tests.rs b/frame/fee-market/src/tests.rs index e2a3fb5597..9252cb723a 100644 --- a/frame/fee-market/src/tests.rs +++ b/frame/fee-market/src/tests.rs @@ -476,7 +476,10 @@ pub fn new_test_ext() -> sp_io::TestExternalities { (5, 350), (6, 500), (7, 500), - (12, 400), + (8, 500), + (12, 2000), + (13, 2000), + (14, 2000), ], } .assimilate_storage(&mut t) @@ -549,10 +552,11 @@ fn test_single_relayer_enroll_workflow_works() { )); assert_eq!(FeeMarket::get_relayer(3).order_capacity, 2); - assert_err!( - FeeMarket::enroll_and_lock_collateral(Origin::signed(4), 30, None), - >::LockCollateralTooLow - ); + assert_ok!(FeeMarket::enroll_and_lock_collateral( + Origin::signed(4), + 0, + None + ),); }); } #[test] @@ -562,6 +566,7 @@ fn test_single_relayer_update_lock_collateral() { FeeMarket::update_locked_collateral(Origin::signed(6), 100), >::NotEnrolled ); + assert_ok!(FeeMarket::enroll_and_lock_collateral( Origin::signed(6), 200, @@ -579,6 +584,24 @@ fn test_single_relayer_update_lock_collateral() { FeeMarket::update_locked_collateral(Origin::signed(6), 80), >::OnlyIncCollateralAllowed ); + + assert_ok!(FeeMarket::enroll_and_lock_collateral( + Origin::signed(4), + 20, + None + )); + assert_eq!(FeeMarket::get_relayer(4).order_capacity, 0); + assert_ok!(FeeMarket::update_locked_collateral(Origin::signed(4), 200)); + assert_eq!(FeeMarket::get_relayer(4).order_capacity, 2); + + assert_ok!(FeeMarket::enroll_and_lock_collateral( + Origin::signed(7), + 120, + None + )); + assert_eq!(FeeMarket::get_relayer(7).order_capacity, 1); + assert_ok!(FeeMarket::update_locked_collateral(Origin::signed(7), 400)); + assert_eq!(FeeMarket::get_relayer(7).order_capacity, 4); }); } @@ -682,33 +705,24 @@ fn test_single_relayer_update_fee_works() { fn test_market_fee() { new_test_ext().execute_with(|| { let _ = FeeMarket::enroll_and_lock_collateral(Origin::signed(1), 100, None); - let _ = FeeMarket::enroll_and_lock_collateral(Origin::signed(2), 110, None); + let _ = FeeMarket::enroll_and_lock_collateral(Origin::signed(2), 110, Some(40)); assert!(FeeMarket::market_fee().is_none()); - assert_err!( - FeeMarket::enroll_and_lock_collateral(Origin::signed(3), 110, None), - >::LockCollateralTooLow - ); - assert!(FeeMarket::market_fee().is_none()); - assert_ok!(FeeMarket::update_locked_collateral(Origin::signed(3), 200)); - assert_eq!(FeeMarket::market_fee(), Some(30)); + let _ = FeeMarket::enroll_and_lock_collateral(Origin::signed(3), 200, Some(40)); + let _ = FeeMarket::enroll_and_lock_collateral(Origin::signed(4), 120, Some(40)); + let _ = FeeMarket::enroll_and_lock_collateral(Origin::signed(5), 150, Some(50)); + assert_eq!(FeeMarket::market_fee(), Some(40)); assert_eq!( FeeMarket::assigned_relayers().unwrap(), vec![ - Relayer::::new(3, 200, 30, 2), - Relayer::::new(2, 110, 30, 1), Relayer::::new(1, 100, 30, 1), + Relayer::::new(3, 200, 40, 2), + Relayer::::new(4, 120, 40, 1), ] ); }); } -// A -> enroll 1000 -> order capacity = 10 -> send 2 message -> order capacity = 8 -// update_locked_collateral to 2000 -> diff = 1000 -> 18 个 - -// B -> enroll 120 -> order capacity = 1 -// update_locked_collateral to 400 -> diff = 280 -> 2 个 - fn send_regular_message(fee: Balance) -> (LaneId, u64) { let message_nonce = Messages::outbound_latest_generated_nonce(TEST_LANE_ID) + 1; assert_ok!(Messages::send_message( @@ -750,11 +764,20 @@ fn test_order_creation_when_bridged_pallet_accept_message() { let _ = FeeMarket::enroll_and_lock_collateral(Origin::signed(1), 100, Some(30)); let _ = FeeMarket::enroll_and_lock_collateral(Origin::signed(2), 110, Some(50)); let _ = FeeMarket::enroll_and_lock_collateral(Origin::signed(3), 120, Some(100)); + assert_eq!(FeeMarket::get_relayer(&1).order_capacity, 1); + assert_eq!(FeeMarket::get_relayer(&2).order_capacity, 1); + assert_eq!(FeeMarket::get_relayer(&3).order_capacity, 1); System::set_block_number(2); let assigned_relayers = FeeMarket::assigned_relayers().unwrap(); let market_fee = FeeMarket::market_fee().unwrap(); let (lane, message_nonce) = send_regular_message(market_fee); + assert_eq!(FeeMarket::get_relayer(&1).order_capacity, 0); + assert_eq!(FeeMarket::get_relayer(&2).order_capacity, 0); + assert_eq!(FeeMarket::get_relayer(&3).order_capacity, 0); + assert!(FeeMarket::market_fee().is_none()); + assert!(FeeMarket::assigned_relayers().is_none()); + let order = FeeMarket::order((&lane, &message_nonce)).unwrap(); let relayers = order.relayers_slice(); assert_eq!(relayers[0].id, assigned_relayers.get(0).unwrap().id); @@ -792,6 +815,9 @@ fn test_order_confirm_time_set_when_bridged_pallet_confirmed_message() { let _ = FeeMarket::enroll_and_lock_collateral(Origin::signed(3), 120, Some(100)); let market_fee = FeeMarket::market_fee().unwrap(); let (lane, message_nonce) = send_regular_message(market_fee); + assert_eq!(FeeMarket::get_relayer(&1).order_capacity, 0); + assert_eq!(FeeMarket::get_relayer(&2).order_capacity, 0); + assert_eq!(FeeMarket::get_relayer(&3).order_capacity, 0); let order = FeeMarket::order((&lane, &message_nonce)).unwrap(); assert_eq!(order.confirm_time, None); @@ -800,6 +826,11 @@ fn test_order_confirm_time_set_when_bridged_pallet_confirmed_message() { let order = FeeMarket::order((&lane, &message_nonce)).unwrap(); assert_eq!(order.confirm_time, Some(4)); assert_eq!(>::get().len(), 1); + assert_eq!(FeeMarket::get_relayer(&1).order_capacity, 1); + assert_eq!(FeeMarket::get_relayer(&2).order_capacity, 1); + assert_eq!(FeeMarket::get_relayer(&3).order_capacity, 1); + assert!(FeeMarket::market_fee().is_some()); + assert!(FeeMarket::assigned_relayers().is_some()); }); } @@ -854,9 +885,9 @@ fn test_payment_reward_calculation_assigned_relayer_finish_delivery_single_messa fn test_payment_reward_calculation_assigned_relayer_finish_delivery_with_multiple_messages() { new_test_ext().execute_with(|| { System::set_block_number(2); - let _ = FeeMarket::enroll_and_lock_collateral(Origin::signed(1), 100, Some(300)); - let _ = FeeMarket::enroll_and_lock_collateral(Origin::signed(2), 110, Some(500)); - let _ = FeeMarket::enroll_and_lock_collateral(Origin::signed(3), 120, Some(1000)); + let _ = FeeMarket::enroll_and_lock_collateral(Origin::signed(5), 300, Some(30)); + let _ = FeeMarket::enroll_and_lock_collateral(Origin::signed(6), 300, Some(50)); + let _ = FeeMarket::enroll_and_lock_collateral(Origin::signed(7), 300, Some(100)); // Send message let market_fee = FeeMarket::market_fee().unwrap(); @@ -867,7 +898,7 @@ fn test_payment_reward_calculation_assigned_relayer_finish_delivery_with_multipl // Receive delivery message proof System::set_block_number(4); assert_ok!(Messages::receive_messages_delivery_proof( - Origin::signed(5), + Origin::signed(1), TestMessagesDeliveryProof(Ok(( TEST_LANE_ID, InboundLaneData { @@ -889,19 +920,17 @@ fn test_payment_reward_calculation_assigned_relayer_finish_delivery_with_multipl let t: AccountId = ::TreasuryPalletId::get().into_account(); assert!(TestMessageDeliveryAndDispatchPayment::is_reward_paid( - t, 1400 + t, 140 )); - assert!(TestMessageDeliveryAndDispatchPayment::is_reward_paid( - 1, 360 - )); - assert!(TestMessageDeliveryAndDispatchPayment::is_reward_paid(5, 48)); + assert!(TestMessageDeliveryAndDispatchPayment::is_reward_paid(1, 4)); + assert!(TestMessageDeliveryAndDispatchPayment::is_reward_paid(5, 36)); assert!(TestMessageDeliveryAndDispatchPayment::is_reward_paid( TEST_RELAYER_A, - 96 + 10 )); assert!(TestMessageDeliveryAndDispatchPayment::is_reward_paid( TEST_RELAYER_B, - 96 + 10 )); }); } @@ -970,18 +999,24 @@ fn test_payment_reward_calculation_assigned_relayer_single_message_with_multiple } #[test] -fn test_assigned_relayers_slash_calculation() { +fn test_assigned_relayers_slash_calculation_with_clean() { new_test_ext().execute_with(|| { System::set_block_number(2); let _ = FeeMarket::enroll_and_lock_collateral(Origin::signed(5), 200, Some(30)); let _ = FeeMarket::enroll_and_lock_collateral(Origin::signed(6), 200, Some(50)); let _ = FeeMarket::enroll_and_lock_collateral(Origin::signed(7), 200, Some(70)); + assert_eq!(FeeMarket::get_relayer(&5).order_capacity, 2); + assert_eq!(FeeMarket::get_relayer(&6).order_capacity, 2); + assert_eq!(FeeMarket::get_relayer(&7).order_capacity, 2); let market_fee = FeeMarket::market_fee().unwrap(); let (lane, message_nonce) = send_regular_message(market_fee); let mut order = FeeMarket::order((&lane, &message_nonce)).unwrap(); assert_eq!(Ring::usable_balance(&5), 150); assert_eq!(Ring::usable_balance(&6), 300); assert_eq!(Ring::usable_balance(&7), 300); + assert_eq!(FeeMarket::get_relayer(&5).order_capacity, 1); + assert_eq!(FeeMarket::get_relayer(&6).order_capacity, 1); + assert_eq!(FeeMarket::get_relayer(&7).order_capacity, 1); order.confirm_time = order.range_end(); assert_eq!(slash_assigned_relayers::(order.clone(), &0), 210); @@ -992,6 +1027,9 @@ fn test_assigned_relayers_slash_calculation() { assert_eq!(FeeMarket::relayer_locked_collateral(&6), 130); assert_eq!(FeeMarket::relayer_locked_collateral(&7), 130); assert_eq!(FeeMarket::assigned_relayers().unwrap().len(), 3); + assert_eq!(FeeMarket::get_relayer(&5).order_capacity, 1); + assert_eq!(FeeMarket::get_relayer(&6).order_capacity, 1); + assert_eq!(FeeMarket::get_relayer(&7).order_capacity, 1); // slash value = 70 + 30 * 2 = 130 > 100 order.confirm_time = Some(order.range_end().unwrap() + 30); @@ -1002,10 +1040,56 @@ fn test_assigned_relayers_slash_calculation() { assert_eq!(FeeMarket::relayer_locked_collateral(&5), 0); assert_eq!(FeeMarket::relayer_locked_collateral(&6), 0); assert_eq!(FeeMarket::relayer_locked_collateral(&7), 0); + assert_eq!(FeeMarket::get_relayer(&5).order_capacity, 0); + assert_eq!(FeeMarket::get_relayer(&6).order_capacity, 0); + assert_eq!(FeeMarket::get_relayer(&7).order_capacity, 0); assert!(FeeMarket::assigned_relayers().is_none()); }); } +#[test] +fn test_assigned_relayers_slash_order_capacity_correctly() { + new_test_ext().execute_with(|| { + System::set_block_number(2); + let _ = FeeMarket::enroll_and_lock_collateral(Origin::signed(12), 1000, Some(30)); + let _ = FeeMarket::enroll_and_lock_collateral(Origin::signed(13), 1000, Some(50)); + let _ = FeeMarket::enroll_and_lock_collateral(Origin::signed(14), 1000, Some(70)); + assert_eq!(FeeMarket::get_relayer(&12).order_capacity, 10); + assert_eq!(FeeMarket::get_relayer(&13).order_capacity, 10); + assert_eq!(FeeMarket::get_relayer(&14).order_capacity, 10); + let market_fee = FeeMarket::market_fee().unwrap(); + let (lane, message_nonce) = send_regular_message(market_fee); + let mut order = FeeMarket::order((&lane, &message_nonce)).unwrap(); + assert_eq!(Ring::usable_balance(&12), 1000); + assert_eq!(Ring::usable_balance(&13), 1000); + assert_eq!(Ring::usable_balance(&14), 1000); + assert_eq!(FeeMarket::get_relayer(&12).order_capacity, 9); + assert_eq!(FeeMarket::get_relayer(&13).order_capacity, 9); + assert_eq!(FeeMarket::get_relayer(&14).order_capacity, 9); + let (lane, message_nonce) = send_regular_message(market_fee); + let mut order = FeeMarket::order((&lane, &message_nonce)).unwrap(); + assert_eq!(Ring::usable_balance(&12), 1000); + assert_eq!(Ring::usable_balance(&13), 1000); + assert_eq!(Ring::usable_balance(&14), 1000); + assert_eq!(FeeMarket::get_relayer(&12).order_capacity, 8); + assert_eq!(FeeMarket::get_relayer(&13).order_capacity, 8); + assert_eq!(FeeMarket::get_relayer(&14).order_capacity, 8); + + // slash value = 70 + 30 * 2 = 130 > 100 + order.confirm_time = Some(order.range_end().unwrap() + 30); + assert_eq!(slash_assigned_relayers::(order, &10), 300); + assert_eq!(Ring::usable_balance(&12), 1000); + assert_eq!(Ring::usable_balance(&13), 1000); + assert_eq!(Ring::usable_balance(&14), 1000); + assert_eq!(FeeMarket::relayer_locked_collateral(&12), 900); + assert_eq!(FeeMarket::relayer_locked_collateral(&13), 900); + assert_eq!(FeeMarket::relayer_locked_collateral(&14), 900); + assert_eq!(FeeMarket::get_relayer(&12).order_capacity, 7); + assert_eq!(FeeMarket::get_relayer(&13).order_capacity, 7); + assert_eq!(FeeMarket::get_relayer(&14).order_capacity, 7); + }); +} + #[test] fn test_assigned_relayers_slash_kick_out_market_fee_hung() { new_test_ext().execute_with(|| { @@ -1042,49 +1126,6 @@ fn test_assigned_relayers_slash_kick_out_market_fee_hung() { }); } -#[test] -fn test_assigned_relayers_slash_kick_out_market_fee_works() { - new_test_ext().execute_with(|| { - System::set_block_number(2); - let _ = FeeMarket::enroll_and_lock_collateral(Origin::signed(1), 100, Some(30)); - let _ = FeeMarket::enroll_and_lock_collateral(Origin::signed(3), 250, Some(50)); - let _ = FeeMarket::enroll_and_lock_collateral(Origin::signed(6), 300, Some(70)); - let _ = FeeMarket::enroll_and_lock_collateral(Origin::signed(7), 300, Some(80)); - let market_fee = FeeMarket::market_fee().unwrap(); - let (lane, message_nonce) = send_regular_message(market_fee); - let mut order = FeeMarket::order((&lane, &message_nonce)).unwrap(); - assert_eq!(Ring::usable_balance(&1), 50); - assert_eq!(Ring::usable_balance(&3), 100); - assert_eq!(Ring::usable_balance(&6), 200); - // assert_eq!( - // FeeMarket::assigned_relayers().unwrap(), - // vec![ - // Relayer::::new(1, 100, 30), - // Relayer::::new(3, 250, 50), - // Relayer::::new(6, 300, 70), - // ] - // ); - - order.confirm_time = Some(order.range_end().unwrap() + 50); - assert_eq!(slash_assigned_relayers::(order.clone(), &0), 300); - assert_eq!(Ring::usable_balance(&1), 50); - assert!(!FeeMarket::is_enrolled(&1)); - assert_eq!(Ring::usable_balance(&3), 100); - assert!(FeeMarket::is_enrolled(&3)); - assert_eq!(Ring::usable_balance(&6), 200); - assert!(FeeMarket::is_enrolled(&6)); - // assert_eq!( - // FeeMarket::assigned_relayers().unwrap(), - // vec![ - // Relayer::::new(3, 150, 50), - // Relayer::::new(6, 200, 70), - // Relayer::::new(7, 300, 80), - // ] - // ); - assert_eq!(FeeMarket::market_fee().unwrap(), 80); - }); -} - #[test] fn test_payment_reward_calculation_assigned_relayers_absent_with_single_message() { new_test_ext().execute_with(|| { @@ -1127,9 +1168,9 @@ fn test_payment_reward_calculation_assigned_relayers_absent_with_single_message( fn test_payment_reward_calculation_assigned_relayers_absent_with_multiple_message() { new_test_ext().execute_with(|| { System::set_block_number(2); - let _ = FeeMarket::enroll_and_lock_collateral(Origin::signed(1), 100, Some(300)); - let _ = FeeMarket::enroll_and_lock_collateral(Origin::signed(2), 110, Some(500)); - let _ = FeeMarket::enroll_and_lock_collateral(Origin::signed(3), 120, Some(1000)); + let _ = FeeMarket::enroll_and_lock_collateral(Origin::signed(6), 400, Some(300)); + let _ = FeeMarket::enroll_and_lock_collateral(Origin::signed(7), 400, Some(500)); + let _ = FeeMarket::enroll_and_lock_collateral(Origin::signed(8), 400, Some(1000)); // Send message let market_fee = FeeMarket::market_fee().unwrap(); @@ -1159,14 +1200,16 @@ fn test_payment_reward_calculation_assigned_relayers_absent_with_multiple_messag ..Default::default() }, )); - assert!(TestMessageDeliveryAndDispatchPayment::is_reward_paid(5, 60)); + assert!(TestMessageDeliveryAndDispatchPayment::is_reward_paid( + 5, 120 + )); assert!(TestMessageDeliveryAndDispatchPayment::is_reward_paid( TEST_RELAYER_A, 240 )); assert!(TestMessageDeliveryAndDispatchPayment::is_reward_paid( TEST_RELAYER_B, - 0 + 240 )); }); } @@ -1175,9 +1218,9 @@ fn test_payment_reward_calculation_assigned_relayers_absent_with_multiple_messag fn test_clean_order_state_at_the_end_of_block() { new_test_ext().execute_with(|| { System::set_block_number(2); - let _ = FeeMarket::enroll_and_lock_collateral(Origin::signed(1), 100, Some(300)); - let _ = FeeMarket::enroll_and_lock_collateral(Origin::signed(2), 110, Some(500)); - let _ = FeeMarket::enroll_and_lock_collateral(Origin::signed(3), 120, Some(1000)); + let _ = FeeMarket::enroll_and_lock_collateral(Origin::signed(6), 400, Some(300)); + let _ = FeeMarket::enroll_and_lock_collateral(Origin::signed(7), 400, Some(500)); + let _ = FeeMarket::enroll_and_lock_collateral(Origin::signed(8), 400, Some(1000)); let market_fee = FeeMarket::market_fee().unwrap(); let (lane1, nonce1) = send_regular_message(market_fee); let (lane2, nonce2) = send_regular_message(market_fee); From 711bb6625d4294cfd0e8a0a701785e1fa5d93b81 Mon Sep 17 00:00:00 2001 From: ouwenkg <2630582710@qq.com> Date: Tue, 9 Nov 2021 20:52:32 +0800 Subject: [PATCH 18/46] Good news, it's close to ready --- frame/fee-market/src/lib.rs | 5 +---- frame/fee-market/src/s2s/payment.rs | 10 ---------- frame/fee-market/src/tests.rs | 3 +-- node/runtime/pangolin/src/pallets/fee_market.rs | 7 ++++--- node/runtime/pangoro/src/pallets/fee_market.rs | 7 ++++--- 5 files changed, 10 insertions(+), 22 deletions(-) diff --git a/frame/fee-market/src/lib.rs b/frame/fee-market/src/lib.rs index 9e24a3ce18..277eccee72 100644 --- a/frame/fee-market/src/lib.rs +++ b/frame/fee-market/src/lib.rs @@ -40,10 +40,7 @@ use frame_support::{ }; use frame_system::{ensure_signed, pallet_prelude::*}; use num_traits::Zero; -use sp_runtime::{ - traits::{Saturating, UniqueSaturatedInto}, - Permill, SaturatedConversion, -}; +use sp_runtime::{traits::UniqueSaturatedInto, Permill, SaturatedConversion}; use sp_std::{default::Default, vec::Vec}; // --- darwinia-network --- use darwinia_support::{ diff --git a/frame/fee-market/src/s2s/payment.rs b/frame/fee-market/src/s2s/payment.rs index 4b34f04300..c6bc895973 100644 --- a/frame/fee-market/src/s2s/payment.rs +++ b/frame/fee-market/src/s2s/payment.rs @@ -191,16 +191,6 @@ where } } } - println!("book: messages_relayers_rewards {:?}", messages_rewards); - println!( - "book: confirmation_relayer_rewards {:?}", - confirmation_rewards - ); - println!( - "book: assigned_relayers_rewards {:?}", - assigned_relayers_rewards - ); - println!("book: treasury_total_rewards {:?}", treasury_total_rewards); RewardsBook { messages_relayers_rewards: messages_rewards, diff --git a/frame/fee-market/src/tests.rs b/frame/fee-market/src/tests.rs index 9252cb723a..631fc880db 100644 --- a/frame/fee-market/src/tests.rs +++ b/frame/fee-market/src/tests.rs @@ -1058,8 +1058,7 @@ fn test_assigned_relayers_slash_order_capacity_correctly() { assert_eq!(FeeMarket::get_relayer(&13).order_capacity, 10); assert_eq!(FeeMarket::get_relayer(&14).order_capacity, 10); let market_fee = FeeMarket::market_fee().unwrap(); - let (lane, message_nonce) = send_regular_message(market_fee); - let mut order = FeeMarket::order((&lane, &message_nonce)).unwrap(); + let _ = send_regular_message(market_fee); assert_eq!(Ring::usable_balance(&12), 1000); assert_eq!(Ring::usable_balance(&13), 1000); assert_eq!(Ring::usable_balance(&14), 1000); diff --git a/node/runtime/pangolin/src/pallets/fee_market.rs b/node/runtime/pangolin/src/pallets/fee_market.rs index ea6046efc4..ab48139dd0 100644 --- a/node/runtime/pangolin/src/pallets/fee_market.rs +++ b/node/runtime/pangolin/src/pallets/fee_market.rs @@ -11,9 +11,10 @@ frame_support::parameter_types! { pub const AssignedRelayersNumber: u64 = 1; pub const FeeMarketLockId: LockIdentifier = *b"da/feelf"; - pub const MiniumLockCollateral: Balance = 3000 * COIN; pub const MinimumRelayFee: Balance = 15 * COIN; pub const Slot: BlockNumber = 50; + pub const SlashForEachBlock: Balance = 2 * COIN; + pub const CollateralEachOrder: Balance = 100 * COIN; pub const AssignedRelayersRewardRatio: Permill = Permill::from_percent(60); pub const MessageRelayersRewardRatio: Permill = Permill::from_percent(80); @@ -26,14 +27,14 @@ impl Config for Runtime { type LockId = FeeMarketLockId; type AssignedRelayersNumber = AssignedRelayersNumber; - type MiniumLockCollateral = MiniumLockCollateral; type MinimumRelayFee = MinimumRelayFee; + type SlashForEachBlock = SlashForEachBlock; + type CollateralEachOrder = CollateralEachOrder; type Slot = Slot; type AssignedRelayersRewardRatio = AssignedRelayersRewardRatio; type MessageRelayersRewardRatio = MessageRelayersRewardRatio; type ConfirmRelayersRewardRatio = ConfirmRelayersRewardRatio; - type Slasher = (); type RingCurrency = Ring; type Event = Event; diff --git a/node/runtime/pangoro/src/pallets/fee_market.rs b/node/runtime/pangoro/src/pallets/fee_market.rs index 351035ee7d..9ea87dd0c9 100644 --- a/node/runtime/pangoro/src/pallets/fee_market.rs +++ b/node/runtime/pangoro/src/pallets/fee_market.rs @@ -11,8 +11,9 @@ frame_support::parameter_types! { pub const FeeMarketLockId: LockIdentifier = *b"da/feelf"; pub const AssignedRelayersNumber: u64 = 3; - pub const MiniumLockCollateral: Balance = 3000 * COIN; pub const MinimumRelayFee: Balance = 15 * COIN; + pub const SlashForEachBlock: Balance = 2 * COIN; + pub const CollateralEachOrder: Balance = 100 * COIN; pub const Slot: BlockNumber = 50; pub const AssignedRelayersRewardRatio: Permill = Permill::from_percent(60); @@ -26,14 +27,14 @@ impl Config for Runtime { type LockId = FeeMarketLockId; type AssignedRelayersNumber = AssignedRelayersNumber; - type MiniumLockCollateral = MiniumLockCollateral; type MinimumRelayFee = MinimumRelayFee; + type SlashForEachBlock = SlashForEachBlock; + type CollateralEachOrder = CollateralEachOrder; type Slot = Slot; type AssignedRelayersRewardRatio = AssignedRelayersRewardRatio; type MessageRelayersRewardRatio = MessageRelayersRewardRatio; type ConfirmRelayersRewardRatio = ConfirmRelayersRewardRatio; - type Slasher = (); type RingCurrency = Ring; type Event = Event; From 0199bcfbfad628caff0ba626f9d5a9f93c8975bc Mon Sep 17 00:00:00 2001 From: ouwenkg <2630582710@qq.com> Date: Tue, 9 Nov 2021 21:39:38 +0800 Subject: [PATCH 19/46] Code clean --- frame/fee-market/src/lib.rs | 10 +++++----- frame/fee-market/src/s2s/payment.rs | 6 +++--- frame/fee-market/src/tests.rs | 8 ++++---- node/runtime/pangolin/src/pallets/fee_market.rs | 8 ++++---- node/runtime/pangoro/src/pallets/fee_market.rs | 8 ++++---- 5 files changed, 20 insertions(+), 20 deletions(-) diff --git a/frame/fee-market/src/lib.rs b/frame/fee-market/src/lib.rs index 277eccee72..8ec066ed5f 100644 --- a/frame/fee-market/src/lib.rs +++ b/frame/fee-market/src/lib.rs @@ -86,10 +86,10 @@ pub mod pallet { type ConfirmRelayersRewardRatio: Get; /// The slash rule - type SlashForEachBlock: Get>; + type SlashPerBlockDelay: Get>; /// The collateral relayer need to lock for each order. #[pallet::constant] - type CollateralEachOrder: Get>; + type CollateralPerOrder: Get>; type RingCurrency: LockableCurrency + Currency; @@ -203,7 +203,7 @@ pub mod pallet { >::InsufficientBalance ); let order_capacity: u32 = - (lock_collateral / T::CollateralEachOrder::get()).saturated_into::(); + (lock_collateral / T::CollateralPerOrder::get()).saturated_into::(); if let Some(fee) = relay_fee { ensure!(fee >= T::MinimumRelayFee::get(), >::RelayFeeTooLow); @@ -255,10 +255,10 @@ pub mod pallet { >::OnlyIncCollateralAllowed ); let old_capacity: u32 = - (relayer.collateral / T::CollateralEachOrder::get()).saturated_into::(); + (relayer.collateral / T::CollateralPerOrder::get()).saturated_into::(); let used_capacity = old_capacity.saturating_sub(relayer.order_capacity); let new_capacity: u32 = - (new_collateral / T::CollateralEachOrder::get()).saturated_into::(); + (new_collateral / T::CollateralPerOrder::get()).saturated_into::(); let _ = T::RingCurrency::extend_lock( T::LockId::get(), diff --git a/frame/fee-market/src/s2s/payment.rs b/frame/fee-market/src/s2s/payment.rs index c6bc895973..2e4a643c23 100644 --- a/frame/fee-market/src/s2s/payment.rs +++ b/frame/fee-market/src/s2s/payment.rs @@ -213,11 +213,11 @@ pub fn slash_assigned_relayers( let slash = message_fee.saturating_add( timeout .saturating_mul(UniqueSaturatedInto::::unique_saturated_into( - T::SlashForEachBlock::get(), + T::SlashPerBlockDelay::get(), )) .unique_saturated_into(), ); - let slash_max = sp_std::cmp::min(slash, T::CollateralEachOrder::get()); + let slash_max = sp_std::cmp::min(slash, T::CollateralPerOrder::get()); for assigned_relayer in order.relayers_slice() { let slashed_asset = @@ -238,7 +238,7 @@ pub fn do_slash( ) -> RingBalance { let relayer = crate::Pallet::::get_relayer(&slash_account); let (locked_collateral, usable_order_capacity) = (relayer.collateral, relayer.order_capacity); - let slash_capacity: u32 = (slash_value / T::CollateralEachOrder::get()).saturated_into::(); + let slash_capacity: u32 = (slash_value / T::CollateralPerOrder::get()).saturated_into::(); T::RingCurrency::remove_lock(T::LockId::get(), &slash_account); debug_assert!( diff --git a/frame/fee-market/src/tests.rs b/frame/fee-market/src/tests.rs index 631fc880db..2e0e789c9a 100644 --- a/frame/fee-market/src/tests.rs +++ b/frame/fee-market/src/tests.rs @@ -420,10 +420,10 @@ frame_support::parameter_types! { pub const TreasuryPalletId: PalletId = PalletId(*b"da/trsry"); pub const FeeMarketLockId: LockIdentifier = *b"da/feelf"; pub const MinimumRelayFee: Balance = 30; - pub const CollateralEachOrder: Balance = 100; + pub const CollateralPerOrder: Balance = 100; pub const AssignedRelayersNumber: u64 = 3; pub const Slot: u64 = 50; - pub const SlashForEachBlock: Balance = 2; + pub const SlashPerBlockDelay: Balance = 2; pub const AssignedRelayersRewardRatio: Permill = Permill::from_percent(60); pub const MessageRelayersRewardRatio: Permill = Permill::from_percent(80); @@ -435,11 +435,11 @@ impl Config for Test { type PalletId = FeeMarketPalletId; type TreasuryPalletId = TreasuryPalletId; type LockId = FeeMarketLockId; - type CollateralEachOrder = CollateralEachOrder; + type CollateralPerOrder = CollateralPerOrder; type MinimumRelayFee = MinimumRelayFee; type AssignedRelayersNumber = AssignedRelayersNumber; type Slot = Slot; - type SlashForEachBlock = SlashForEachBlock; + type SlashPerBlockDelay = SlashPerBlockDelay; type AssignedRelayersRewardRatio = AssignedRelayersRewardRatio; type MessageRelayersRewardRatio = MessageRelayersRewardRatio; diff --git a/node/runtime/pangolin/src/pallets/fee_market.rs b/node/runtime/pangolin/src/pallets/fee_market.rs index ab48139dd0..4ca4795ba4 100644 --- a/node/runtime/pangolin/src/pallets/fee_market.rs +++ b/node/runtime/pangolin/src/pallets/fee_market.rs @@ -13,8 +13,8 @@ frame_support::parameter_types! { pub const MinimumRelayFee: Balance = 15 * COIN; pub const Slot: BlockNumber = 50; - pub const SlashForEachBlock: Balance = 2 * COIN; - pub const CollateralEachOrder: Balance = 100 * COIN; + pub const SlashPerBlockDelay: Balance = 2 * COIN; + pub const CollateralPerOrder: Balance = 100 * COIN; pub const AssignedRelayersRewardRatio: Permill = Permill::from_percent(60); pub const MessageRelayersRewardRatio: Permill = Permill::from_percent(80); @@ -28,8 +28,8 @@ impl Config for Runtime { type AssignedRelayersNumber = AssignedRelayersNumber; type MinimumRelayFee = MinimumRelayFee; - type SlashForEachBlock = SlashForEachBlock; - type CollateralEachOrder = CollateralEachOrder; + type SlashPerBlockDelay = SlashPerBlockDelay; + type CollateralPerOrder = CollateralPerOrder; type Slot = Slot; type AssignedRelayersRewardRatio = AssignedRelayersRewardRatio; diff --git a/node/runtime/pangoro/src/pallets/fee_market.rs b/node/runtime/pangoro/src/pallets/fee_market.rs index 9ea87dd0c9..ba3122a78d 100644 --- a/node/runtime/pangoro/src/pallets/fee_market.rs +++ b/node/runtime/pangoro/src/pallets/fee_market.rs @@ -12,8 +12,8 @@ frame_support::parameter_types! { pub const AssignedRelayersNumber: u64 = 3; pub const MinimumRelayFee: Balance = 15 * COIN; - pub const SlashForEachBlock: Balance = 2 * COIN; - pub const CollateralEachOrder: Balance = 100 * COIN; + pub const SlashPerBlockDelay: Balance = 2 * COIN; + pub const CollateralPerOrder: Balance = 100 * COIN; pub const Slot: BlockNumber = 50; pub const AssignedRelayersRewardRatio: Permill = Permill::from_percent(60); @@ -28,8 +28,8 @@ impl Config for Runtime { type AssignedRelayersNumber = AssignedRelayersNumber; type MinimumRelayFee = MinimumRelayFee; - type SlashForEachBlock = SlashForEachBlock; - type CollateralEachOrder = CollateralEachOrder; + type SlashPerBlockDelay = SlashPerBlockDelay; + type CollateralPerOrder = CollateralPerOrder; type Slot = Slot; type AssignedRelayersRewardRatio = AssignedRelayersRewardRatio; From e631671cdbf46ce9dbe483fee9e1130f6353fa6d Mon Sep 17 00:00:00 2001 From: ouwenkg <2630582710@qq.com> Date: Tue, 9 Nov 2021 22:16:27 +0800 Subject: [PATCH 20/46] Add more comment --- frame/fee-market/src/lib.rs | 50 +++++++++++++++-------------------- frame/fee-market/src/tests.rs | 44 +++++++++++++++--------------- 2 files changed, 42 insertions(+), 52 deletions(-) diff --git a/frame/fee-market/src/lib.rs b/frame/fee-market/src/lib.rs index 8ec066ed5f..43fedf99ae 100644 --- a/frame/fee-market/src/lib.rs +++ b/frame/fee-market/src/lib.rs @@ -85,7 +85,7 @@ pub mod pallet { #[pallet::constant] type ConfirmRelayersRewardRatio: Get; - /// The slash rule + /// The slash value for each block when order delay. type SlashPerBlockDelay: Get>; /// The collateral relayer need to lock for each order. #[pallet::constant] @@ -126,7 +126,7 @@ pub mod pallet { AlreadyEnrolled, /// This relayer doesn't enroll ever. NotEnrolled, - /// Only increase lock collateral is allowed when update_locked_balance. + /// Only increase lock collateral is allowed when update_locked_collateral. OnlyIncCollateralAllowed, /// The fee is lower than MinimumRelayFee. RelayFeeTooLow, @@ -186,7 +186,7 @@ pub mod pallet { #[pallet::call] impl Pallet { /// Any accounts can enroll to be a relayer by lock collateral. The relay fee is optional, - /// the default value is MinimumRelayFee in runtime. + /// the default value is MinimumRelayFee in runtime. (Update market needed) /// Note: One account can enroll only once. #[pallet::weight(::WeightInfo::enroll_and_lock_collateral())] #[transactional] @@ -235,7 +235,7 @@ pub mod pallet { Ok(().into()) } - /// Update locked collateral for enrolled relayer, only supporting lock more. + /// Update locked collateral for enrolled relayer, only supporting lock more. (Update market needed) #[pallet::weight(::WeightInfo::update_locked_collateral())] #[transactional] pub fn update_locked_collateral( @@ -282,7 +282,7 @@ pub mod pallet { Ok(().into()) } - /// Update relay fee for enrolled relayer + /// Update relay fee for enrolled relayer. (Update market needed) #[pallet::weight(::WeightInfo::update_relay_fee())] #[transactional] pub fn update_relay_fee( @@ -305,7 +305,7 @@ pub mod pallet { Ok(().into()) } - /// Cancel enrolled relayer + /// Cancel enrolled relayer(Update market needed) #[pallet::weight(::WeightInfo::cancel_enrollment())] #[transactional] pub fn cancel_enrollment(origin: OriginFor) -> DispatchResultWithPostInfo { @@ -326,7 +326,8 @@ impl Pallet { /// - When new relayer enroll. /// - When enrolled relayer wants to update fee or order capacity. /// - When enrolled relayer wants to cancel enrollment. - pub fn update_market() { + /// - All order assigned relayers's order capacity sub 1 in `on_messages_accepted()` and add 1 in `on_messages_delivered`. + pub(crate) fn update_market() { // Sort all enrolled relayers who are able to accept orders. let mut relayers: Vec>> = >::get() .iter() @@ -350,13 +351,14 @@ impl Pallet { >::put(assigned_relayers); } else { - // The enrolled relayers not enough, pallet can't provide any fee advice. + // The market fee comes from the last item in AssignedRelayers, + // It's would be essential to wipe this storage if relayers not enough. >::kill(); } } - /// Update relayer after slash occurred, this will changes RelayersMap storage. - pub fn update_relayer_after_slash( + /// Update relayer after slash occurred, this will changes RelayersMap storage. (Update market needed) + pub(crate) fn update_relayer_after_slash( who: &T::AccountId, new_collateral: RingBalance, new_order_capacity: u32, @@ -382,8 +384,8 @@ impl Pallet { Self::update_market(); } - /// Remove enrolled relayer, then update market fee. - pub fn remove_enrolled_relayer(who: &T::AccountId) { + /// Remove enrolled relayer, then update market fee. (Update market needed) + pub(crate) fn remove_enrolled_relayer(who: &T::AccountId) { T::RingCurrency::remove_lock(T::LockId::get(), who); >::remove(who.clone()); @@ -396,8 +398,8 @@ impl Pallet { Self::update_market(); } - /// Decrease relayer order capacity by 1 after message order created. - pub fn dec_relayer_order_capacity(relayers: &[T::AccountId]) { + /// Decrease relayer order capacity by 1 after message order created. (Update market needed) + pub(crate) fn dec_relayer_order_capacity(relayers: &[T::AccountId]) { // todo: need to check 0-1 case. for who in relayers { >::mutate(who.clone(), |r| { @@ -407,8 +409,8 @@ impl Pallet { Self::update_market(); } - /// Increase relayer order capacity by 1 after message order confirmed. - pub fn inc_relayer_order_capacity(relayers: &[T::AccountId]) { + /// Increase relayer order capacity by 1 after message order confirmed. (Update market needed) + pub(crate) fn inc_relayer_order_capacity(relayers: &[T::AccountId]) { for who in relayers { >::mutate(who.clone(), |r| { r.order_capacity = r.order_capacity.saturating_add(1); @@ -418,27 +420,17 @@ impl Pallet { } /// Whether the relayer has enrolled - pub fn is_enrolled(who: &T::AccountId) -> bool { + pub(crate) fn is_enrolled(who: &T::AccountId) -> bool { >::get().iter().any(|r| *r == *who) } - /// Get relayer fee - pub fn relayer_fee(who: &T::AccountId) -> Fee { - Self::get_relayer(who).fee - } - - /// Get relayer locked collateral - pub fn relayer_locked_collateral(who: &T::AccountId) -> RingBalance { - Self::get_relayer(who).collateral - } - - /// Get market fee(P3), If the enrolled relayers less then MIN_RELAYERS_NUMBER, return NONE. + /// Get market fee, If there is not enough relayers have order capacity to accept new order, return None. pub fn market_fee() -> Option> { Self::assigned_relayers().and_then(|relayers| relayers.last().map(|r| r.fee)) } /// Whether the enrolled relayer is occupied(Responsible for order relaying) - pub fn is_occupied(who: &T::AccountId) -> bool { + pub(crate) fn is_occupied(who: &T::AccountId) -> bool { for (_, order) in >::iter() { if order.relayers_slice().iter().any(|r| r.id == *who) && !order.is_confirmed() { return true; diff --git a/frame/fee-market/src/tests.rs b/frame/fee-market/src/tests.rs index 2e0e789c9a..7539e314c0 100644 --- a/frame/fee-market/src/tests.rs +++ b/frame/fee-market/src/tests.rs @@ -537,7 +537,7 @@ fn test_single_relayer_enroll_workflow_works() { assert_eq!(FeeMarket::relayers().len(), 1); assert_eq!(Ring::free_balance(1), 150); assert_eq!(Ring::usable_balance(&1), 50); - assert_eq!(FeeMarket::relayer_locked_collateral(&1), 100); + assert_eq!(FeeMarket::get_relayer(&1).collateral, 100); assert_eq!(FeeMarket::get_relayer(1).order_capacity, 1); assert_eq!(FeeMarket::market_fee(), None); assert_err!( @@ -572,12 +572,12 @@ fn test_single_relayer_update_lock_collateral() { 200, None )); - assert_eq!(FeeMarket::relayer_locked_collateral(&6), 200); + assert_eq!(FeeMarket::get_relayer(&6).collateral, 200); assert_eq!(FeeMarket::get_relayer(6).order_capacity, 2); // Increase locked balance assert_ok!(FeeMarket::update_locked_collateral(Origin::signed(6), 500)); - assert_eq!(FeeMarket::relayer_locked_collateral(&6), 500); + assert_eq!(FeeMarket::get_relayer(&6).collateral, 500); assert_eq!(FeeMarket::get_relayer(6).order_capacity, 5); // Decrease locked balance assert_err!( @@ -691,12 +691,12 @@ fn test_single_relayer_update_fee_works() { >::RelayFeeTooLow ); - assert_eq!(FeeMarket::relayer_fee(&1), 30); + assert_eq!(FeeMarket::get_relayer(&1).fee, 30); assert_ok!(FeeMarket::update_relay_fee(Origin::signed(1), 40)); - assert_eq!(FeeMarket::relayer_fee(&1), 40); + assert_eq!(FeeMarket::get_relayer(&1).fee, 40); assert_ok!(FeeMarket::update_relay_fee(Origin::signed(3), 150)); - assert_eq!(FeeMarket::relayer_fee(&3), 150); + assert_eq!(FeeMarket::get_relayer(&3).fee, 150); assert_eq!(FeeMarket::market_fee(), Some(150)); }); } @@ -1023,9 +1023,9 @@ fn test_assigned_relayers_slash_calculation_with_clean() { assert_eq!(Ring::usable_balance(&5), 150); assert_eq!(Ring::usable_balance(&6), 300); assert_eq!(Ring::usable_balance(&7), 300); - assert_eq!(FeeMarket::relayer_locked_collateral(&5), 130); - assert_eq!(FeeMarket::relayer_locked_collateral(&6), 130); - assert_eq!(FeeMarket::relayer_locked_collateral(&7), 130); + assert_eq!(FeeMarket::get_relayer(&5).collateral, 130); + assert_eq!(FeeMarket::get_relayer(&6).collateral, 130); + assert_eq!(FeeMarket::get_relayer(&7).collateral, 130); assert_eq!(FeeMarket::assigned_relayers().unwrap().len(), 3); assert_eq!(FeeMarket::get_relayer(&5).order_capacity, 1); assert_eq!(FeeMarket::get_relayer(&6).order_capacity, 1); @@ -1037,9 +1037,9 @@ fn test_assigned_relayers_slash_calculation_with_clean() { assert_eq!(Ring::usable_balance(&5), 180); assert_eq!(Ring::usable_balance(&6), 330); assert_eq!(Ring::usable_balance(&7), 330); - assert_eq!(FeeMarket::relayer_locked_collateral(&5), 0); - assert_eq!(FeeMarket::relayer_locked_collateral(&6), 0); - assert_eq!(FeeMarket::relayer_locked_collateral(&7), 0); + assert_eq!(FeeMarket::get_relayer(&5).collateral, 0); + assert_eq!(FeeMarket::get_relayer(&6).collateral, 0); + assert_eq!(FeeMarket::get_relayer(&7).collateral, 0); assert_eq!(FeeMarket::get_relayer(&5).order_capacity, 0); assert_eq!(FeeMarket::get_relayer(&6).order_capacity, 0); assert_eq!(FeeMarket::get_relayer(&7).order_capacity, 0); @@ -1080,9 +1080,15 @@ fn test_assigned_relayers_slash_order_capacity_correctly() { assert_eq!(Ring::usable_balance(&12), 1000); assert_eq!(Ring::usable_balance(&13), 1000); assert_eq!(Ring::usable_balance(&14), 1000); - assert_eq!(FeeMarket::relayer_locked_collateral(&12), 900); - assert_eq!(FeeMarket::relayer_locked_collateral(&13), 900); - assert_eq!(FeeMarket::relayer_locked_collateral(&14), 900); + assert_eq!(FeeMarket::get_relayer(&12).collateral, 900); + assert_eq!(FeeMarket::get_relayer(&13).collateral, 900); + assert_eq!(FeeMarket::get_relayer(&14).collateral, 900); + assert_eq!(FeeMarket::get_relayer(&12).collateral, 900); + assert_eq!(FeeMarket::get_relayer(&13).collateral, 900); + assert_eq!(FeeMarket::get_relayer(&14).collateral, 900); + assert_eq!(FeeMarket::get_relayer(&12).collateral, 900); + assert_eq!(FeeMarket::get_relayer(&13).collateral, 900); + assert_eq!(FeeMarket::get_relayer(&14).collateral, 900); assert_eq!(FeeMarket::get_relayer(&12).order_capacity, 7); assert_eq!(FeeMarket::get_relayer(&13).order_capacity, 7); assert_eq!(FeeMarket::get_relayer(&14).order_capacity, 7); @@ -1103,14 +1109,6 @@ fn test_assigned_relayers_slash_kick_out_market_fee_hung() { assert_eq!(Ring::usable_balance(&1), 50); assert_eq!(Ring::usable_balance(&2), 90); assert_eq!(Ring::usable_balance(&3), 230); - // assert_eq!( - // FeeMarket::assigned_relayers().unwrap(), - // vec![ - // Relayer::::new(1, 100, 30), - // Relayer::::new(2, 110, 50), - // Relayer::::new(3, 120, 70), - // ] - // ); order.confirm_time = Some(order.range_end().unwrap() + 50); assert_eq!(slash_assigned_relayers::(order.clone(), &0), 300); From 39a5f25b56620bced2ca5fb0660a661da8e40e01 Mon Sep 17 00:00:00 2001 From: ouwenkg <2630582710@qq.com> Date: Wed, 10 Nov 2021 10:29:58 +0800 Subject: [PATCH 21/46] Add `accept_order` and `finish_order` --- frame/fee-market/src/lib.rs | 27 ++++++++++++------ frame/fee-market/src/s2s/callbacks.rs | 16 +++++------ primitives/fee-market/src/lib.rs | 41 ++++++++++++++++++++++++++- 3 files changed, 67 insertions(+), 17 deletions(-) diff --git a/frame/fee-market/src/lib.rs b/frame/fee-market/src/lib.rs index 43fedf99ae..22ad332274 100644 --- a/frame/fee-market/src/lib.rs +++ b/frame/fee-market/src/lib.rs @@ -398,22 +398,33 @@ impl Pallet { Self::update_market(); } - /// Decrease relayer order capacity by 1 after message order created. (Update market needed) - pub(crate) fn dec_relayer_order_capacity(relayers: &[T::AccountId]) { - // todo: need to check 0-1 case. - for who in relayers { + /// Update relayer order capacity after message order created. (Update market needed) + pub(crate) fn relayer_accept_order( + order: &Order>, + ) { + let assigned_relayers_ids: Vec = order + .relayers + .iter() + .map(|relayer| relayer.id.clone()) + .collect(); + + for who in assigned_relayers_ids { >::mutate(who.clone(), |r| { - r.order_capacity = r.order_capacity.saturating_sub(1); + r.accept_order(&order.lane, &order.message); }); } Self::update_market(); } - /// Increase relayer order capacity by 1 after message order confirmed. (Update market needed) - pub(crate) fn inc_relayer_order_capacity(relayers: &[T::AccountId]) { + /// Update relayer order capacity after message order confirmed. (Update market needed) + pub(crate) fn relayer_finish_order( + lane_id: &LaneId, + nonce: &MessageNonce, + relayers: &[T::AccountId], + ) { for who in relayers { >::mutate(who.clone(), |r| { - r.order_capacity = r.order_capacity.saturating_add(1); + r.finish_order(lane_id, nonce); }); } Self::update_market(); diff --git a/frame/fee-market/src/s2s/callbacks.rs b/frame/fee-market/src/s2s/callbacks.rs index 3aed65244b..aab0cd711e 100644 --- a/frame/fee-market/src/s2s/callbacks.rs +++ b/frame/fee-market/src/s2s/callbacks.rs @@ -38,13 +38,9 @@ impl OnMessageAccepted for FeeMarketMessageAcceptedHandler { T::Slot::get(), ); // Store the create order - >::insert((order.lane, order.message), order); - - let assigned_relayers_ids: Vec = assigned_relayers - .iter() - .map(|relayer| relayer.id.clone()) - .collect(); - Pallet::::dec_relayer_order_capacity(&assigned_relayers_ids); + >::insert((order.lane, order.message), order.clone()); + // Update relayer orders and order_capacity + Pallet::::relayer_accept_order(&order); } // TODO: The returned weight should be more accurately. See: https://github.com/darwinia-network/darwinia-common/issues/911 @@ -72,7 +68,11 @@ impl OnDeliveryConfirmed for FeeMarketMessageConfirmedHandler { .map(|r| r.id.clone()) .collect(); // todo: should we move this part after the reward? - Pallet::::inc_relayer_order_capacity(&assigned_relayers_ids); + Pallet::::relayer_finish_order( + &order.lane, + &order.message, + &assigned_relayers_ids, + ); } } } diff --git a/primitives/fee-market/src/lib.rs b/primitives/fee-market/src/lib.rs index 2e53e868a9..e3cfc39894 100644 --- a/primitives/fee-market/src/lib.rs +++ b/primitives/fee-market/src/lib.rs @@ -25,13 +25,15 @@ use sp_std::{ ops::{Add, AddAssign, Range}, vec::Vec, }; + /// Relayer who has enrolled the fee market -#[derive(Encode, Decode, Clone, Eq, Debug, Copy)] +#[derive(Encode, Decode, Clone, Eq, Debug)] pub struct Relayer { pub id: AccountId, pub collateral: Balance, pub fee: Balance, pub order_capacity: u32, + pub orders: Vec<(LaneId, MessageNonce)>, } impl Relayer { @@ -46,8 +48,20 @@ impl Relayer { collateral, fee, order_capacity, + orders: Vec::new(), } } + + pub fn accept_order(&mut self, lane_id: &LaneId, message_nonce: &MessageNonce) { + self.orders.push((*lane_id, *message_nonce)); + self.order_capacity = self.order_capacity.saturating_sub(1); + } + + pub fn finish_order(&mut self, lane_id: &LaneId, message_nonce: &MessageNonce) { + self.orders + .retain(|(id, nonce)| (id, nonce) != (lane_id, message_nonce)); + self.order_capacity = self.order_capacity.saturating_add(1); + } } impl PartialOrd for Relayer { @@ -78,6 +92,7 @@ impl PartialEq for Relayer Default for Relayer::new(1, 150, 30, 1); + r1.accept_order(&[0, 0, 0, 1], &1); + assert_eq!(r1.order_capacity, 0); + assert_eq!(r1.orders, vec![([0, 0, 0, 1], 1)]); + } + + #[test] + fn test_finish_order() { + let mut r2 = Relayer::::new(1, 150, 30, 3); + r2.accept_order(&[0, 0, 0, 1], &1); + r2.accept_order(&[0, 0, 0, 1], &2); + r2.accept_order(&[0, 0, 0, 1], &3); + assert_eq!( + r2.orders, + vec![([0, 0, 0, 1], 1), ([0, 0, 0, 1], 2), ([0, 0, 0, 1], 3)] + ); + r2.finish_order(&[0, 0, 0, 1], &1); + assert_eq!(r2.order_capacity, 1); + assert_eq!(r2.orders, vec![([0, 0, 0, 1], 2), ([0, 0, 0, 1], 3)]); + } } From 1ee8da06830bb10c1663a837b368eacc3d820cf8 Mon Sep 17 00:00:00 2001 From: ouwenkg <2630582710@qq.com> Date: Wed, 10 Nov 2021 11:27:43 +0800 Subject: [PATCH 22/46] Update the whole slash logic --- frame/fee-market/src/benchmarking.rs | 4 +- frame/fee-market/src/lib.rs | 47 ++-- frame/fee-market/src/s2s/callbacks.rs | 12 - frame/fee-market/src/s2s/payment.rs | 59 ++--- frame/fee-market/src/tests.rs | 306 +++++++++++++------------- primitives/fee-market/src/lib.rs | 27 +-- 6 files changed, 198 insertions(+), 257 deletions(-) diff --git a/frame/fee-market/src/benchmarking.rs b/frame/fee-market/src/benchmarking.rs index 71c62e5bed..b96434591d 100644 --- a/frame/fee-market/src/benchmarking.rs +++ b/frame/fee-market/src/benchmarking.rs @@ -82,7 +82,7 @@ benchmarks! { let new_collateral = T::MiniumLockCollateral::get().saturating_mul(5u32.into()); }: update_locked_collateral(RawOrigin::Signed(caller3.clone()), new_collateral) verify { - let relayer = >::get_relayer(&caller3); + let relayer = >::relayer(&caller3); assert_eq!(relayer.collateral, T::MiniumLockCollateral::get().saturating_mul(5u32.into())); } @@ -92,7 +92,7 @@ benchmarks! { let new_fee = T::MinimumRelayFee::get().saturating_mul(10u32.into()); }: update_relay_fee(RawOrigin::Signed(caller3.clone()), new_fee) verify { - let relayer = >::get_relayer(&caller3); + let relayer = >::relayer(&caller3); assert_eq!(relayer.fee, T::MinimumRelayFee::get().saturating_mul(10u32.into())); } diff --git a/frame/fee-market/src/lib.rs b/frame/fee-market/src/lib.rs index 22ad332274..898a278edc 100644 --- a/frame/fee-market/src/lib.rs +++ b/frame/fee-market/src/lib.rs @@ -40,7 +40,7 @@ use frame_support::{ }; use frame_system::{ensure_signed, pallet_prelude::*}; use num_traits::Zero; -use sp_runtime::{traits::UniqueSaturatedInto, Permill, SaturatedConversion}; +use sp_runtime::{Permill, SaturatedConversion}; use sp_std::{default::Default, vec::Vec}; // --- darwinia-network --- use darwinia_support::{ @@ -73,6 +73,9 @@ pub mod pallet { /// The assigned relayers number for each order. #[pallet::constant] type AssignedRelayersNumber: Get; + /// The collateral relayer need to lock for each order. + #[pallet::constant] + type CollateralPerOrder: Get>; /// The slot times set #[pallet::constant] type Slot: Get; @@ -85,12 +88,6 @@ pub mod pallet { #[pallet::constant] type ConfirmRelayersRewardRatio: Get; - /// The slash value for each block when order delay. - type SlashPerBlockDelay: Get>; - /// The collateral relayer need to lock for each order. - #[pallet::constant] - type CollateralPerOrder: Get>; - type RingCurrency: LockableCurrency + Currency; type Event: From> + IsType<::Event>; @@ -138,7 +135,7 @@ pub mod pallet { // Enrolled relayers storage #[pallet::storage] - #[pallet::getter(fn get_relayer)] + #[pallet::getter(fn relayer)] pub type RelayersMap = StorageMap< _, Blake2_128Concat, @@ -249,7 +246,7 @@ pub mod pallet { >::InsufficientBalance ); - let relayer = Self::get_relayer(&who); + let relayer = Self::relayer(&who); ensure!( new_collateral > relayer.collateral, >::OnlyIncCollateralAllowed @@ -276,7 +273,7 @@ pub mod pallet { Self::deposit_event(Event::::UpdateRelayer( who.clone(), Some(new_collateral), - Some(Self::get_relayer(&who).order_capacity), + Some(Self::relayer(&who).order_capacity), None, )); Ok(().into()) @@ -358,12 +355,8 @@ impl Pallet { } /// Update relayer after slash occurred, this will changes RelayersMap storage. (Update market needed) - pub(crate) fn update_relayer_after_slash( - who: &T::AccountId, - new_collateral: RingBalance, - new_order_capacity: u32, - ) { - if new_collateral == RingBalance::::zero() || new_order_capacity == 0 { + pub(crate) fn update_relayer_after_slash(who: &T::AccountId, new_collateral: RingBalance) { + if new_collateral == RingBalance::::zero() || Self::relayer(&who).order_capacity == 0 { Self::remove_enrolled_relayer(who); return; } @@ -378,7 +371,6 @@ impl Pallet { .map_err(|_| >::ExtendLockFailed); >::mutate(who.clone(), |relayer| { relayer.collateral = new_collateral; - relayer.order_capacity = new_order_capacity; }); Self::update_market(); @@ -402,15 +394,12 @@ impl Pallet { pub(crate) fn relayer_accept_order( order: &Order>, ) { - let assigned_relayers_ids: Vec = order - .relayers - .iter() - .map(|relayer| relayer.id.clone()) - .collect(); + let assigned_relayers: Vec = + order.relayers.iter().map(|r| r.id.clone()).collect(); - for who in assigned_relayers_ids { + for who in assigned_relayers { >::mutate(who.clone(), |r| { - r.accept_order(&order.lane, &order.message); + r.accept_order(); }); } Self::update_market(); @@ -418,13 +407,13 @@ impl Pallet { /// Update relayer order capacity after message order confirmed. (Update market needed) pub(crate) fn relayer_finish_order( - lane_id: &LaneId, - nonce: &MessageNonce, - relayers: &[T::AccountId], + order: &Order>, ) { - for who in relayers { + let assigned_relayers: Vec = + order.relayers.iter().map(|r| r.id.clone()).collect(); + for who in assigned_relayers { >::mutate(who.clone(), |r| { - r.finish_order(lane_id, nonce); + r.finish_order(); }); } Self::update_market(); diff --git a/frame/fee-market/src/s2s/callbacks.rs b/frame/fee-market/src/s2s/callbacks.rs index aab0cd711e..1cba798c12 100644 --- a/frame/fee-market/src/s2s/callbacks.rs +++ b/frame/fee-market/src/s2s/callbacks.rs @@ -61,18 +61,6 @@ impl OnDeliveryConfirmed for FeeMarketMessageConfirmedHandler { None => {} }); >::append((lane, message_nonce)); - - let assigned_relayers_ids: Vec = order - .relayers_slice() - .iter() - .map(|r| r.id.clone()) - .collect(); - // todo: should we move this part after the reward? - Pallet::::relayer_finish_order( - &order.lane, - &order.message, - &assigned_relayers_ids, - ); } } } diff --git a/frame/fee-market/src/s2s/payment.rs b/frame/fee-market/src/s2s/payment.rs index 2e4a643c23..ff9bef9443 100644 --- a/frame/fee-market/src/s2s/payment.rs +++ b/frame/fee-market/src/s2s/payment.rs @@ -168,15 +168,26 @@ where // 20% * (1 - 60%) * lowest_fee => confirm relayer confirm_reward = T::ConfirmRelayersRewardRatio::get() * bridger_relayers_reward; + + // The order is confirmed in time, recover relayer order capacity + Pallet::::relayer_finish_order(&order); } else { - // The message is delivered by common relayer instead of order assigned relayers, all assigned relayers of this order should be punished. - let slashed_reward = - slash_assigned_relayers::(order, relayer_fund_account); + // The message is delivered by common relayer instead of order assigned relayers, all assigned relayers of this order should be slash. + // Total slash = message fee + assigned_relayers slash + // For each assigned relayer, slash CollateralPerOrder per order, then order capacity will decrease by 1. + let mut total_slash = message_fee; + + let mut assigned_relayers_slash = RingBalance::::zero(); + for assigned_relayer in order.relayers_slice() { + let slashed = do_slash::(&assigned_relayer.id, relayer_fund_account); + assigned_relayers_slash += slashed; + } + total_slash += assigned_relayers_slash; // 80% total slash => confirm relayer - message_reward = T::MessageRelayersRewardRatio::get() * slashed_reward; + message_reward = T::MessageRelayersRewardRatio::get() * total_slash; // 20% total slash => confirm relayer - confirm_reward = T::ConfirmRelayersRewardRatio::get() * slashed_reward; + confirm_reward = T::ConfirmRelayersRewardRatio::get() * total_slash; } // Update confirmation relayer total rewards @@ -200,46 +211,13 @@ where } } -/// Slash order assigned relayers -pub fn slash_assigned_relayers( - order: Order>, - relayer_fund_account: &T::AccountId, -) -> RingBalance { - let mut total_slash = RingBalance::::zero(); - match (order.confirm_time, order.range_end()) { - (Some(confirm_time), Some(end_time)) if confirm_time >= end_time => { - let timeout: u128 = (confirm_time - end_time).unique_saturated_into(); - let message_fee = order.lowest_and_highest_fee().1.unwrap_or_default(); - let slash = message_fee.saturating_add( - timeout - .saturating_mul(UniqueSaturatedInto::::unique_saturated_into( - T::SlashPerBlockDelay::get(), - )) - .unique_saturated_into(), - ); - let slash_max = sp_std::cmp::min(slash, T::CollateralPerOrder::get()); - - for assigned_relayer in order.relayers_slice() { - let slashed_asset = - do_slash::(&assigned_relayer.id, relayer_fund_account, slash_max); - total_slash += slashed_asset; - } - } - _ => {} - } - total_slash -} - /// Do slash for absent assigned relayers pub fn do_slash( slash_account: &T::AccountId, fund_account: &T::AccountId, - slash_value: RingBalance, ) -> RingBalance { - let relayer = crate::Pallet::::get_relayer(&slash_account); - let (locked_collateral, usable_order_capacity) = (relayer.collateral, relayer.order_capacity); - let slash_capacity: u32 = (slash_value / T::CollateralPerOrder::get()).saturated_into::(); - + let locked_collateral = crate::Pallet::::relayer(&slash_account).collateral; + let slash_value = T::CollateralPerOrder::get(); T::RingCurrency::remove_lock(T::LockId::get(), &slash_account); debug_assert!( locked_collateral >= slash_value, @@ -255,7 +233,6 @@ pub fn do_slash( crate::Pallet::::update_relayer_after_slash( &slash_account, locked_collateral.saturating_sub(slash_value), - usable_order_capacity.saturating_sub(slash_capacity), ); slash_value diff --git a/frame/fee-market/src/tests.rs b/frame/fee-market/src/tests.rs index 7539e314c0..6f45dda1e2 100644 --- a/frame/fee-market/src/tests.rs +++ b/frame/fee-market/src/tests.rs @@ -48,7 +48,7 @@ use std::{collections::VecDeque, ops::RangeInclusive}; use crate::{ self as darwinia_fee_market, s2s::{ - payment::{slash_and_calculate_rewards, slash_assigned_relayers, RewardsBook}, + payment::{slash_and_calculate_rewards, RewardsBook}, FeeMarketMessageAcceptedHandler, FeeMarketMessageConfirmedHandler, }, *, @@ -423,7 +423,6 @@ frame_support::parameter_types! { pub const CollateralPerOrder: Balance = 100; pub const AssignedRelayersNumber: u64 = 3; pub const Slot: u64 = 50; - pub const SlashPerBlockDelay: Balance = 2; pub const AssignedRelayersRewardRatio: Permill = Permill::from_percent(60); pub const MessageRelayersRewardRatio: Permill = Permill::from_percent(80); @@ -439,7 +438,6 @@ impl Config for Test { type MinimumRelayFee = MinimumRelayFee; type AssignedRelayersNumber = AssignedRelayersNumber; type Slot = Slot; - type SlashPerBlockDelay = SlashPerBlockDelay; type AssignedRelayersRewardRatio = AssignedRelayersRewardRatio; type MessageRelayersRewardRatio = MessageRelayersRewardRatio; @@ -537,8 +535,8 @@ fn test_single_relayer_enroll_workflow_works() { assert_eq!(FeeMarket::relayers().len(), 1); assert_eq!(Ring::free_balance(1), 150); assert_eq!(Ring::usable_balance(&1), 50); - assert_eq!(FeeMarket::get_relayer(&1).collateral, 100); - assert_eq!(FeeMarket::get_relayer(1).order_capacity, 1); + assert_eq!(FeeMarket::relayer(&1).collateral, 100); + assert_eq!(FeeMarket::relayer(1).order_capacity, 1); assert_eq!(FeeMarket::market_fee(), None); assert_err!( FeeMarket::enroll_and_lock_collateral(Origin::signed(1), 100, None), @@ -550,7 +548,7 @@ fn test_single_relayer_enroll_workflow_works() { 250, None )); - assert_eq!(FeeMarket::get_relayer(3).order_capacity, 2); + assert_eq!(FeeMarket::relayer(3).order_capacity, 2); assert_ok!(FeeMarket::enroll_and_lock_collateral( Origin::signed(4), @@ -572,13 +570,13 @@ fn test_single_relayer_update_lock_collateral() { 200, None )); - assert_eq!(FeeMarket::get_relayer(&6).collateral, 200); - assert_eq!(FeeMarket::get_relayer(6).order_capacity, 2); + assert_eq!(FeeMarket::relayer(&6).collateral, 200); + assert_eq!(FeeMarket::relayer(6).order_capacity, 2); // Increase locked balance assert_ok!(FeeMarket::update_locked_collateral(Origin::signed(6), 500)); - assert_eq!(FeeMarket::get_relayer(&6).collateral, 500); - assert_eq!(FeeMarket::get_relayer(6).order_capacity, 5); + assert_eq!(FeeMarket::relayer(&6).collateral, 500); + assert_eq!(FeeMarket::relayer(6).order_capacity, 5); // Decrease locked balance assert_err!( FeeMarket::update_locked_collateral(Origin::signed(6), 80), @@ -590,18 +588,18 @@ fn test_single_relayer_update_lock_collateral() { 20, None )); - assert_eq!(FeeMarket::get_relayer(4).order_capacity, 0); + assert_eq!(FeeMarket::relayer(4).order_capacity, 0); assert_ok!(FeeMarket::update_locked_collateral(Origin::signed(4), 200)); - assert_eq!(FeeMarket::get_relayer(4).order_capacity, 2); + assert_eq!(FeeMarket::relayer(4).order_capacity, 2); assert_ok!(FeeMarket::enroll_and_lock_collateral( Origin::signed(7), 120, None )); - assert_eq!(FeeMarket::get_relayer(7).order_capacity, 1); + assert_eq!(FeeMarket::relayer(7).order_capacity, 1); assert_ok!(FeeMarket::update_locked_collateral(Origin::signed(7), 400)); - assert_eq!(FeeMarket::get_relayer(7).order_capacity, 4); + assert_eq!(FeeMarket::relayer(7).order_capacity, 4); }); } @@ -691,12 +689,12 @@ fn test_single_relayer_update_fee_works() { >::RelayFeeTooLow ); - assert_eq!(FeeMarket::get_relayer(&1).fee, 30); + assert_eq!(FeeMarket::relayer(&1).fee, 30); assert_ok!(FeeMarket::update_relay_fee(Origin::signed(1), 40)); - assert_eq!(FeeMarket::get_relayer(&1).fee, 40); + assert_eq!(FeeMarket::relayer(&1).fee, 40); assert_ok!(FeeMarket::update_relay_fee(Origin::signed(3), 150)); - assert_eq!(FeeMarket::get_relayer(&3).fee, 150); + assert_eq!(FeeMarket::relayer(&3).fee, 150); assert_eq!(FeeMarket::market_fee(), Some(150)); }); } @@ -764,17 +762,17 @@ fn test_order_creation_when_bridged_pallet_accept_message() { let _ = FeeMarket::enroll_and_lock_collateral(Origin::signed(1), 100, Some(30)); let _ = FeeMarket::enroll_and_lock_collateral(Origin::signed(2), 110, Some(50)); let _ = FeeMarket::enroll_and_lock_collateral(Origin::signed(3), 120, Some(100)); - assert_eq!(FeeMarket::get_relayer(&1).order_capacity, 1); - assert_eq!(FeeMarket::get_relayer(&2).order_capacity, 1); - assert_eq!(FeeMarket::get_relayer(&3).order_capacity, 1); + assert_eq!(FeeMarket::relayer(&1).order_capacity, 1); + assert_eq!(FeeMarket::relayer(&2).order_capacity, 1); + assert_eq!(FeeMarket::relayer(&3).order_capacity, 1); System::set_block_number(2); let assigned_relayers = FeeMarket::assigned_relayers().unwrap(); let market_fee = FeeMarket::market_fee().unwrap(); let (lane, message_nonce) = send_regular_message(market_fee); - assert_eq!(FeeMarket::get_relayer(&1).order_capacity, 0); - assert_eq!(FeeMarket::get_relayer(&2).order_capacity, 0); - assert_eq!(FeeMarket::get_relayer(&3).order_capacity, 0); + assert_eq!(FeeMarket::relayer(&1).order_capacity, 0); + assert_eq!(FeeMarket::relayer(&2).order_capacity, 0); + assert_eq!(FeeMarket::relayer(&3).order_capacity, 0); assert!(FeeMarket::market_fee().is_none()); assert!(FeeMarket::assigned_relayers().is_none()); @@ -815,9 +813,9 @@ fn test_order_confirm_time_set_when_bridged_pallet_confirmed_message() { let _ = FeeMarket::enroll_and_lock_collateral(Origin::signed(3), 120, Some(100)); let market_fee = FeeMarket::market_fee().unwrap(); let (lane, message_nonce) = send_regular_message(market_fee); - assert_eq!(FeeMarket::get_relayer(&1).order_capacity, 0); - assert_eq!(FeeMarket::get_relayer(&2).order_capacity, 0); - assert_eq!(FeeMarket::get_relayer(&3).order_capacity, 0); + assert_eq!(FeeMarket::relayer(&1).order_capacity, 0); + assert_eq!(FeeMarket::relayer(&2).order_capacity, 0); + assert_eq!(FeeMarket::relayer(&3).order_capacity, 0); let order = FeeMarket::order((&lane, &message_nonce)).unwrap(); assert_eq!(order.confirm_time, None); @@ -826,9 +824,9 @@ fn test_order_confirm_time_set_when_bridged_pallet_confirmed_message() { let order = FeeMarket::order((&lane, &message_nonce)).unwrap(); assert_eq!(order.confirm_time, Some(4)); assert_eq!(>::get().len(), 1); - assert_eq!(FeeMarket::get_relayer(&1).order_capacity, 1); - assert_eq!(FeeMarket::get_relayer(&2).order_capacity, 1); - assert_eq!(FeeMarket::get_relayer(&3).order_capacity, 1); + assert_eq!(FeeMarket::relayer(&1).order_capacity, 1); + assert_eq!(FeeMarket::relayer(&2).order_capacity, 1); + assert_eq!(FeeMarket::relayer(&3).order_capacity, 1); assert!(FeeMarket::market_fee().is_some()); assert!(FeeMarket::assigned_relayers().is_some()); }); @@ -998,130 +996,132 @@ fn test_payment_reward_calculation_assigned_relayer_single_message_with_multiple }); } -#[test] -fn test_assigned_relayers_slash_calculation_with_clean() { - new_test_ext().execute_with(|| { - System::set_block_number(2); - let _ = FeeMarket::enroll_and_lock_collateral(Origin::signed(5), 200, Some(30)); - let _ = FeeMarket::enroll_and_lock_collateral(Origin::signed(6), 200, Some(50)); - let _ = FeeMarket::enroll_and_lock_collateral(Origin::signed(7), 200, Some(70)); - assert_eq!(FeeMarket::get_relayer(&5).order_capacity, 2); - assert_eq!(FeeMarket::get_relayer(&6).order_capacity, 2); - assert_eq!(FeeMarket::get_relayer(&7).order_capacity, 2); - let market_fee = FeeMarket::market_fee().unwrap(); - let (lane, message_nonce) = send_regular_message(market_fee); - let mut order = FeeMarket::order((&lane, &message_nonce)).unwrap(); - assert_eq!(Ring::usable_balance(&5), 150); - assert_eq!(Ring::usable_balance(&6), 300); - assert_eq!(Ring::usable_balance(&7), 300); - assert_eq!(FeeMarket::get_relayer(&5).order_capacity, 1); - assert_eq!(FeeMarket::get_relayer(&6).order_capacity, 1); - assert_eq!(FeeMarket::get_relayer(&7).order_capacity, 1); - - order.confirm_time = order.range_end(); - assert_eq!(slash_assigned_relayers::(order.clone(), &0), 210); - assert_eq!(Ring::usable_balance(&5), 150); - assert_eq!(Ring::usable_balance(&6), 300); - assert_eq!(Ring::usable_balance(&7), 300); - assert_eq!(FeeMarket::get_relayer(&5).collateral, 130); - assert_eq!(FeeMarket::get_relayer(&6).collateral, 130); - assert_eq!(FeeMarket::get_relayer(&7).collateral, 130); - assert_eq!(FeeMarket::assigned_relayers().unwrap().len(), 3); - assert_eq!(FeeMarket::get_relayer(&5).order_capacity, 1); - assert_eq!(FeeMarket::get_relayer(&6).order_capacity, 1); - assert_eq!(FeeMarket::get_relayer(&7).order_capacity, 1); - - // slash value = 70 + 30 * 2 = 130 > 100 - order.confirm_time = Some(order.range_end().unwrap() + 30); - assert_eq!(slash_assigned_relayers::(order, &10), 300); - assert_eq!(Ring::usable_balance(&5), 180); - assert_eq!(Ring::usable_balance(&6), 330); - assert_eq!(Ring::usable_balance(&7), 330); - assert_eq!(FeeMarket::get_relayer(&5).collateral, 0); - assert_eq!(FeeMarket::get_relayer(&6).collateral, 0); - assert_eq!(FeeMarket::get_relayer(&7).collateral, 0); - assert_eq!(FeeMarket::get_relayer(&5).order_capacity, 0); - assert_eq!(FeeMarket::get_relayer(&6).order_capacity, 0); - assert_eq!(FeeMarket::get_relayer(&7).order_capacity, 0); - assert!(FeeMarket::assigned_relayers().is_none()); - }); -} - -#[test] -fn test_assigned_relayers_slash_order_capacity_correctly() { - new_test_ext().execute_with(|| { - System::set_block_number(2); - let _ = FeeMarket::enroll_and_lock_collateral(Origin::signed(12), 1000, Some(30)); - let _ = FeeMarket::enroll_and_lock_collateral(Origin::signed(13), 1000, Some(50)); - let _ = FeeMarket::enroll_and_lock_collateral(Origin::signed(14), 1000, Some(70)); - assert_eq!(FeeMarket::get_relayer(&12).order_capacity, 10); - assert_eq!(FeeMarket::get_relayer(&13).order_capacity, 10); - assert_eq!(FeeMarket::get_relayer(&14).order_capacity, 10); - let market_fee = FeeMarket::market_fee().unwrap(); - let _ = send_regular_message(market_fee); - assert_eq!(Ring::usable_balance(&12), 1000); - assert_eq!(Ring::usable_balance(&13), 1000); - assert_eq!(Ring::usable_balance(&14), 1000); - assert_eq!(FeeMarket::get_relayer(&12).order_capacity, 9); - assert_eq!(FeeMarket::get_relayer(&13).order_capacity, 9); - assert_eq!(FeeMarket::get_relayer(&14).order_capacity, 9); - let (lane, message_nonce) = send_regular_message(market_fee); - let mut order = FeeMarket::order((&lane, &message_nonce)).unwrap(); - assert_eq!(Ring::usable_balance(&12), 1000); - assert_eq!(Ring::usable_balance(&13), 1000); - assert_eq!(Ring::usable_balance(&14), 1000); - assert_eq!(FeeMarket::get_relayer(&12).order_capacity, 8); - assert_eq!(FeeMarket::get_relayer(&13).order_capacity, 8); - assert_eq!(FeeMarket::get_relayer(&14).order_capacity, 8); - - // slash value = 70 + 30 * 2 = 130 > 100 - order.confirm_time = Some(order.range_end().unwrap() + 30); - assert_eq!(slash_assigned_relayers::(order, &10), 300); - assert_eq!(Ring::usable_balance(&12), 1000); - assert_eq!(Ring::usable_balance(&13), 1000); - assert_eq!(Ring::usable_balance(&14), 1000); - assert_eq!(FeeMarket::get_relayer(&12).collateral, 900); - assert_eq!(FeeMarket::get_relayer(&13).collateral, 900); - assert_eq!(FeeMarket::get_relayer(&14).collateral, 900); - assert_eq!(FeeMarket::get_relayer(&12).collateral, 900); - assert_eq!(FeeMarket::get_relayer(&13).collateral, 900); - assert_eq!(FeeMarket::get_relayer(&14).collateral, 900); - assert_eq!(FeeMarket::get_relayer(&12).collateral, 900); - assert_eq!(FeeMarket::get_relayer(&13).collateral, 900); - assert_eq!(FeeMarket::get_relayer(&14).collateral, 900); - assert_eq!(FeeMarket::get_relayer(&12).order_capacity, 7); - assert_eq!(FeeMarket::get_relayer(&13).order_capacity, 7); - assert_eq!(FeeMarket::get_relayer(&14).order_capacity, 7); - }); -} - -#[test] -fn test_assigned_relayers_slash_kick_out_market_fee_hung() { - new_test_ext().execute_with(|| { - System::set_block_number(2); - let _ = FeeMarket::enroll_and_lock_collateral(Origin::signed(1), 100, Some(30)); - let _ = FeeMarket::enroll_and_lock_collateral(Origin::signed(2), 110, Some(50)); - let _ = FeeMarket::enroll_and_lock_collateral(Origin::signed(3), 120, Some(70)); - let _ = FeeMarket::enroll_and_lock_collateral(Origin::signed(4), 120, Some(80)); - let market_fee = FeeMarket::market_fee().unwrap(); - let (lane, message_nonce) = send_regular_message(market_fee); - let mut order = FeeMarket::order((&lane, &message_nonce)).unwrap(); - assert_eq!(Ring::usable_balance(&1), 50); - assert_eq!(Ring::usable_balance(&2), 90); - assert_eq!(Ring::usable_balance(&3), 230); - - order.confirm_time = Some(order.range_end().unwrap() + 50); - assert_eq!(slash_assigned_relayers::(order.clone(), &0), 300); - assert_eq!(Ring::usable_balance(&1), 50); - assert!(!FeeMarket::is_enrolled(&1)); - assert_eq!(Ring::usable_balance(&2), 100); - assert!(!FeeMarket::is_enrolled(&2)); - assert_eq!(Ring::usable_balance(&3), 250); - assert!(!FeeMarket::is_enrolled(&3)); - assert!(FeeMarket::assigned_relayers().is_none()); - assert!(FeeMarket::market_fee().is_none()); - }); -} +// #[test] +// #[ignore] +// fn test_assigned_relayers_slash_calculation_with_clean() { +// new_test_ext().execute_with(|| { +// System::set_block_number(2); +// let _ = FeeMarket::enroll_and_lock_collateral(Origin::signed(5), 200, Some(30)); +// let _ = FeeMarket::enroll_and_lock_collateral(Origin::signed(6), 200, Some(50)); +// let _ = FeeMarket::enroll_and_lock_collateral(Origin::signed(7), 200, Some(70)); +// assert_eq!(FeeMarket::relayer(&5).order_capacity, 2); +// assert_eq!(FeeMarket::relayer(&6).order_capacity, 2); +// assert_eq!(FeeMarket::relayer(&7).order_capacity, 2); +// let market_fee = FeeMarket::market_fee().unwrap(); +// let (lane, message_nonce) = send_regular_message(market_fee); +// let mut order = FeeMarket::order((&lane, &message_nonce)).unwrap(); +// assert_eq!(Ring::usable_balance(&5), 150); +// assert_eq!(Ring::usable_balance(&6), 300); +// assert_eq!(Ring::usable_balance(&7), 300); +// assert_eq!(FeeMarket::relayer(&5).order_capacity, 1); +// assert_eq!(FeeMarket::relayer(&6).order_capacity, 1); +// assert_eq!(FeeMarket::relayer(&7).order_capacity, 1); + +// order.confirm_time = order.range_end(); +// assert_eq!(slash_assigned_relayers::(order.clone(), &0), 210); +// assert_eq!(Ring::usable_balance(&5), 150); +// assert_eq!(Ring::usable_balance(&6), 300); +// assert_eq!(Ring::usable_balance(&7), 300); +// assert_eq!(FeeMarket::relayer(&5).collateral, 130); +// assert_eq!(FeeMarket::relayer(&6).collateral, 130); +// assert_eq!(FeeMarket::relayer(&7).collateral, 130); +// assert_eq!(FeeMarket::assigned_relayers().unwrap().len(), 3); +// assert_eq!(FeeMarket::relayer(&5).order_capacity, 1); +// assert_eq!(FeeMarket::relayer(&6).order_capacity, 1); +// assert_eq!(FeeMarket::relayer(&7).order_capacity, 1); + +// // slash value = 70 + 30 * 2 = 130 > 100 +// order.confirm_time = Some(order.range_end().unwrap() + 30); +// assert_eq!(slash_assigned_relayers::(order, &10), 300); +// assert_eq!(Ring::usable_balance(&5), 180); +// assert_eq!(Ring::usable_balance(&6), 330); +// assert_eq!(Ring::usable_balance(&7), 330); +// assert_eq!(FeeMarket::relayer(&5).collateral, 0); +// assert_eq!(FeeMarket::relayer(&6).collateral, 0); +// assert_eq!(FeeMarket::relayer(&7).collateral, 0); +// assert_eq!(FeeMarket::relayer(&5).order_capacity, 0); +// assert_eq!(FeeMarket::relayer(&6).order_capacity, 0); +// assert_eq!(FeeMarket::relayer(&7).order_capacity, 0); +// assert!(FeeMarket::assigned_relayers().is_none()); +// }); +// } + +// #[test] +// #[ignore] +// fn test_assigned_relayers_slash_order_capacity_correctly() { +// new_test_ext().execute_with(|| { +// System::set_block_number(2); +// let _ = FeeMarket::enroll_and_lock_collateral(Origin::signed(12), 1000, Some(30)); +// let _ = FeeMarket::enroll_and_lock_collateral(Origin::signed(13), 1000, Some(50)); +// let _ = FeeMarket::enroll_and_lock_collateral(Origin::signed(14), 1000, Some(70)); +// assert_eq!(FeeMarket::relayer(&12).order_capacity, 10); +// assert_eq!(FeeMarket::relayer(&13).order_capacity, 10); +// assert_eq!(FeeMarket::relayer(&14).order_capacity, 10); +// let market_fee = FeeMarket::market_fee().unwrap(); +// let _ = send_regular_message(market_fee); +// assert_eq!(Ring::usable_balance(&12), 1000); +// assert_eq!(Ring::usable_balance(&13), 1000); +// assert_eq!(Ring::usable_balance(&14), 1000); +// assert_eq!(FeeMarket::relayer(&12).order_capacity, 9); +// assert_eq!(FeeMarket::relayer(&13).order_capacity, 9); +// assert_eq!(FeeMarket::relayer(&14).order_capacity, 9); +// let (lane, message_nonce) = send_regular_message(market_fee); +// let mut order = FeeMarket::order((&lane, &message_nonce)).unwrap(); +// assert_eq!(Ring::usable_balance(&12), 1000); +// assert_eq!(Ring::usable_balance(&13), 1000); +// assert_eq!(Ring::usable_balance(&14), 1000); +// assert_eq!(FeeMarket::relayer(&12).order_capacity, 8); +// assert_eq!(FeeMarket::relayer(&13).order_capacity, 8); +// assert_eq!(FeeMarket::relayer(&14).order_capacity, 8); + +// // slash value = 70 + 30 * 2 = 130 > 100 +// order.confirm_time = Some(order.range_end().unwrap() + 30); +// assert_eq!(slash_assigned_relayers::(order, &10), 300); +// assert_eq!(Ring::usable_balance(&12), 1000); +// assert_eq!(Ring::usable_balance(&13), 1000); +// assert_eq!(Ring::usable_balance(&14), 1000); +// assert_eq!(FeeMarket::relayer(&12).collateral, 900); +// assert_eq!(FeeMarket::relayer(&13).collateral, 900); +// assert_eq!(FeeMarket::relayer(&14).collateral, 900); +// assert_eq!(FeeMarket::relayer(&12).collateral, 900); +// assert_eq!(FeeMarket::relayer(&13).collateral, 900); +// assert_eq!(FeeMarket::relayer(&14).collateral, 900); +// assert_eq!(FeeMarket::relayer(&12).collateral, 900); +// assert_eq!(FeeMarket::relayer(&13).collateral, 900); +// assert_eq!(FeeMarket::relayer(&14).collateral, 900); +// assert_eq!(FeeMarket::relayer(&12).order_capacity, 7); +// assert_eq!(FeeMarket::relayer(&13).order_capacity, 7); +// assert_eq!(FeeMarket::relayer(&14).order_capacity, 7); +// }); +// } + +// #[test] +// fn test_assigned_relayers_slash_kick_out_market_fee_hung() { +// new_test_ext().execute_with(|| { +// System::set_block_number(2); +// let _ = FeeMarket::enroll_and_lock_collateral(Origin::signed(1), 100, Some(30)); +// let _ = FeeMarket::enroll_and_lock_collateral(Origin::signed(2), 110, Some(50)); +// let _ = FeeMarket::enroll_and_lock_collateral(Origin::signed(3), 120, Some(70)); +// let _ = FeeMarket::enroll_and_lock_collateral(Origin::signed(4), 120, Some(80)); +// let market_fee = FeeMarket::market_fee().unwrap(); +// let (lane, message_nonce) = send_regular_message(market_fee); +// let mut order = FeeMarket::order((&lane, &message_nonce)).unwrap(); +// assert_eq!(Ring::usable_balance(&1), 50); +// assert_eq!(Ring::usable_balance(&2), 90); +// assert_eq!(Ring::usable_balance(&3), 230); + +// order.confirm_time = Some(order.range_end().unwrap() + 50); +// assert_eq!(slash_assigned_relayers::(order.clone(), &0), 300); +// assert_eq!(Ring::usable_balance(&1), 50); +// assert!(!FeeMarket::is_enrolled(&1)); +// assert_eq!(Ring::usable_balance(&2), 100); +// assert!(!FeeMarket::is_enrolled(&2)); +// assert_eq!(Ring::usable_balance(&3), 250); +// assert!(!FeeMarket::is_enrolled(&3)); +// assert!(FeeMarket::assigned_relayers().is_none()); +// assert!(FeeMarket::market_fee().is_none()); +// }); +// } #[test] fn test_payment_reward_calculation_assigned_relayers_absent_with_single_message() { diff --git a/primitives/fee-market/src/lib.rs b/primitives/fee-market/src/lib.rs index e3cfc39894..ecd6d3c8bb 100644 --- a/primitives/fee-market/src/lib.rs +++ b/primitives/fee-market/src/lib.rs @@ -33,7 +33,6 @@ pub struct Relayer { pub collateral: Balance, pub fee: Balance, pub order_capacity: u32, - pub orders: Vec<(LaneId, MessageNonce)>, } impl Relayer { @@ -48,18 +47,14 @@ impl Relayer { collateral, fee, order_capacity, - orders: Vec::new(), } } - pub fn accept_order(&mut self, lane_id: &LaneId, message_nonce: &MessageNonce) { - self.orders.push((*lane_id, *message_nonce)); + pub fn accept_order(&mut self) { self.order_capacity = self.order_capacity.saturating_sub(1); } - pub fn finish_order(&mut self, lane_id: &LaneId, message_nonce: &MessageNonce) { - self.orders - .retain(|(id, nonce)| (id, nonce) != (lane_id, message_nonce)); + pub fn finish_order(&mut self) { self.order_capacity = self.order_capacity.saturating_add(1); } } @@ -92,7 +87,6 @@ impl PartialEq for Relayer Default for Relayer::new(1, 150, 30, 1); - r1.accept_order(&[0, 0, 0, 1], &1); + r1.accept_order(); assert_eq!(r1.order_capacity, 0); - assert_eq!(r1.orders, vec![([0, 0, 0, 1], 1)]); } #[test] fn test_finish_order() { let mut r2 = Relayer::::new(1, 150, 30, 3); - r2.accept_order(&[0, 0, 0, 1], &1); - r2.accept_order(&[0, 0, 0, 1], &2); - r2.accept_order(&[0, 0, 0, 1], &3); - assert_eq!( - r2.orders, - vec![([0, 0, 0, 1], 1), ([0, 0, 0, 1], 2), ([0, 0, 0, 1], 3)] - ); - r2.finish_order(&[0, 0, 0, 1], &1); + r2.accept_order(); + r2.accept_order(); + r2.accept_order(); + r2.finish_order(); assert_eq!(r2.order_capacity, 1); - assert_eq!(r2.orders, vec![([0, 0, 0, 1], 2), ([0, 0, 0, 1], 3)]); } } From fb388eabbdaf8ab68e9359f5748d49ced2841371 Mon Sep 17 00:00:00 2001 From: ouwenkg <2630582710@qq.com> Date: Wed, 10 Nov 2021 12:02:07 +0800 Subject: [PATCH 23/46] Clean the tests --- frame/fee-market/src/lib.rs | 11 +- frame/fee-market/src/tests.rs | 222 ++++++------------ .../pangolin/src/pallets/fee_market.rs | 2 - .../runtime/pangoro/src/pallets/fee_market.rs | 2 - 4 files changed, 81 insertions(+), 156 deletions(-) diff --git a/frame/fee-market/src/lib.rs b/frame/fee-market/src/lib.rs index 898a278edc..b448e7fcaf 100644 --- a/frame/fee-market/src/lib.rs +++ b/frame/fee-market/src/lib.rs @@ -362,13 +362,14 @@ impl Pallet { } // Update locked collateral - let _ = T::RingCurrency::extend_lock( + T::RingCurrency::set_lock( T::LockId::get(), - who, - new_collateral, + &who, + LockFor::Common { + amount: new_collateral, + }, WithdrawReasons::all(), - ) - .map_err(|_| >::ExtendLockFailed); + ); >::mutate(who.clone(), |relayer| { relayer.collateral = new_collateral; }); diff --git a/frame/fee-market/src/tests.rs b/frame/fee-market/src/tests.rs index 6f45dda1e2..3252e96db2 100644 --- a/frame/fee-market/src/tests.rs +++ b/frame/fee-market/src/tests.rs @@ -518,7 +518,7 @@ pub fn unrewarded_relayer( } #[test] -fn test_single_relayer_enroll_workflow_works() { +fn test_call_relayer_enroll_works() { new_test_ext().execute_with(|| { assert_eq!(Ring::free_balance(1), 150); assert_err!( @@ -558,7 +558,7 @@ fn test_single_relayer_enroll_workflow_works() { }); } #[test] -fn test_single_relayer_update_lock_collateral() { +fn test_call_relayer_update_lock_collateral_works() { new_test_ext().execute_with(|| { assert_err!( FeeMarket::update_locked_collateral(Origin::signed(6), 100), @@ -604,7 +604,7 @@ fn test_single_relayer_update_lock_collateral() { } #[test] -fn test_relayer_cancel_registration() { +fn test_call_relayer_cancel_registration_works() { new_test_ext().execute_with(|| { assert_err!( FeeMarket::cancel_enrollment(Origin::signed(1)), @@ -674,7 +674,7 @@ fn test_relayer_cancel_registration() { } #[test] -fn test_single_relayer_update_fee_works() { +fn test_call_relayer_update_fee_works() { new_test_ext().execute_with(|| { assert_err!( FeeMarket::update_relay_fee(Origin::signed(1), 1), @@ -700,7 +700,7 @@ fn test_single_relayer_update_fee_works() { } #[test] -fn test_market_fee() { +fn test_rpc_market_fee_works() { new_test_ext().execute_with(|| { let _ = FeeMarket::enroll_and_lock_collateral(Origin::signed(1), 100, None); let _ = FeeMarket::enroll_and_lock_collateral(Origin::signed(2), 110, Some(40)); @@ -757,7 +757,7 @@ fn receive_messages_delivery_proof() { } #[test] -fn test_order_creation_when_bridged_pallet_accept_message() { +fn test_callback_order_creation() { new_test_ext().execute_with(|| { let _ = FeeMarket::enroll_and_lock_collateral(Origin::signed(1), 100, Some(30)); let _ = FeeMarket::enroll_and_lock_collateral(Origin::signed(2), 110, Some(50)); @@ -786,7 +786,7 @@ fn test_order_creation_when_bridged_pallet_accept_message() { } #[test] -fn test_no_order_created_after_send_message_when_fee_market_not_ready() { +fn test_callback_no_order_created_when_fee_market_not_ready() { new_test_ext().execute_with(|| { let _ = FeeMarket::enroll_and_lock_collateral(Origin::signed(1), 100, Some(30)); let _ = FeeMarket::enroll_and_lock_collateral(Origin::signed(2), 110, Some(50)); @@ -805,7 +805,7 @@ fn test_no_order_created_after_send_message_when_fee_market_not_ready() { } #[test] -fn test_order_confirm_time_set_when_bridged_pallet_confirmed_message() { +fn test_callback_order_confirm() { new_test_ext().execute_with(|| { System::set_block_number(2); let _ = FeeMarket::enroll_and_lock_collateral(Origin::signed(1), 100, Some(30)); @@ -833,7 +833,7 @@ fn test_order_confirm_time_set_when_bridged_pallet_confirmed_message() { } #[test] -fn test_payment_reward_calculation_assigned_relayer_finish_delivery_single_message() { +fn test_payment_cal_reward_normally_single_message() { new_test_ext().execute_with(|| { // Send message System::set_block_number(2); @@ -880,7 +880,7 @@ fn test_payment_reward_calculation_assigned_relayer_finish_delivery_single_messa } #[test] -fn test_payment_reward_calculation_assigned_relayer_finish_delivery_with_multiple_messages() { +fn test_payment_cal_reward_normally_multi_message() { new_test_ext().execute_with(|| { System::set_block_number(2); let _ = FeeMarket::enroll_and_lock_collateral(Origin::signed(5), 300, Some(30)); @@ -934,8 +934,7 @@ fn test_payment_reward_calculation_assigned_relayer_finish_delivery_with_multipl } #[test] -fn test_payment_reward_calculation_assigned_relayer_single_message_with_multiple_duplicated_delivery_proof( -) { +fn test_payment_cal_reward_with_duplicated_delivery_proof() { new_test_ext().execute_with(|| { System::set_block_number(2); let _ = FeeMarket::enroll_and_lock_collateral(Origin::signed(1), 100, Some(30)); @@ -996,143 +995,63 @@ fn test_payment_reward_calculation_assigned_relayer_single_message_with_multiple }); } -// #[test] -// #[ignore] -// fn test_assigned_relayers_slash_calculation_with_clean() { -// new_test_ext().execute_with(|| { -// System::set_block_number(2); -// let _ = FeeMarket::enroll_and_lock_collateral(Origin::signed(5), 200, Some(30)); -// let _ = FeeMarket::enroll_and_lock_collateral(Origin::signed(6), 200, Some(50)); -// let _ = FeeMarket::enroll_and_lock_collateral(Origin::signed(7), 200, Some(70)); -// assert_eq!(FeeMarket::relayer(&5).order_capacity, 2); -// assert_eq!(FeeMarket::relayer(&6).order_capacity, 2); -// assert_eq!(FeeMarket::relayer(&7).order_capacity, 2); -// let market_fee = FeeMarket::market_fee().unwrap(); -// let (lane, message_nonce) = send_regular_message(market_fee); -// let mut order = FeeMarket::order((&lane, &message_nonce)).unwrap(); -// assert_eq!(Ring::usable_balance(&5), 150); -// assert_eq!(Ring::usable_balance(&6), 300); -// assert_eq!(Ring::usable_balance(&7), 300); -// assert_eq!(FeeMarket::relayer(&5).order_capacity, 1); -// assert_eq!(FeeMarket::relayer(&6).order_capacity, 1); -// assert_eq!(FeeMarket::relayer(&7).order_capacity, 1); - -// order.confirm_time = order.range_end(); -// assert_eq!(slash_assigned_relayers::(order.clone(), &0), 210); -// assert_eq!(Ring::usable_balance(&5), 150); -// assert_eq!(Ring::usable_balance(&6), 300); -// assert_eq!(Ring::usable_balance(&7), 300); -// assert_eq!(FeeMarket::relayer(&5).collateral, 130); -// assert_eq!(FeeMarket::relayer(&6).collateral, 130); -// assert_eq!(FeeMarket::relayer(&7).collateral, 130); -// assert_eq!(FeeMarket::assigned_relayers().unwrap().len(), 3); -// assert_eq!(FeeMarket::relayer(&5).order_capacity, 1); -// assert_eq!(FeeMarket::relayer(&6).order_capacity, 1); -// assert_eq!(FeeMarket::relayer(&7).order_capacity, 1); - -// // slash value = 70 + 30 * 2 = 130 > 100 -// order.confirm_time = Some(order.range_end().unwrap() + 30); -// assert_eq!(slash_assigned_relayers::(order, &10), 300); -// assert_eq!(Ring::usable_balance(&5), 180); -// assert_eq!(Ring::usable_balance(&6), 330); -// assert_eq!(Ring::usable_balance(&7), 330); -// assert_eq!(FeeMarket::relayer(&5).collateral, 0); -// assert_eq!(FeeMarket::relayer(&6).collateral, 0); -// assert_eq!(FeeMarket::relayer(&7).collateral, 0); -// assert_eq!(FeeMarket::relayer(&5).order_capacity, 0); -// assert_eq!(FeeMarket::relayer(&6).order_capacity, 0); -// assert_eq!(FeeMarket::relayer(&7).order_capacity, 0); -// assert!(FeeMarket::assigned_relayers().is_none()); -// }); -// } - -// #[test] -// #[ignore] -// fn test_assigned_relayers_slash_order_capacity_correctly() { -// new_test_ext().execute_with(|| { -// System::set_block_number(2); -// let _ = FeeMarket::enroll_and_lock_collateral(Origin::signed(12), 1000, Some(30)); -// let _ = FeeMarket::enroll_and_lock_collateral(Origin::signed(13), 1000, Some(50)); -// let _ = FeeMarket::enroll_and_lock_collateral(Origin::signed(14), 1000, Some(70)); -// assert_eq!(FeeMarket::relayer(&12).order_capacity, 10); -// assert_eq!(FeeMarket::relayer(&13).order_capacity, 10); -// assert_eq!(FeeMarket::relayer(&14).order_capacity, 10); -// let market_fee = FeeMarket::market_fee().unwrap(); -// let _ = send_regular_message(market_fee); -// assert_eq!(Ring::usable_balance(&12), 1000); -// assert_eq!(Ring::usable_balance(&13), 1000); -// assert_eq!(Ring::usable_balance(&14), 1000); -// assert_eq!(FeeMarket::relayer(&12).order_capacity, 9); -// assert_eq!(FeeMarket::relayer(&13).order_capacity, 9); -// assert_eq!(FeeMarket::relayer(&14).order_capacity, 9); -// let (lane, message_nonce) = send_regular_message(market_fee); -// let mut order = FeeMarket::order((&lane, &message_nonce)).unwrap(); -// assert_eq!(Ring::usable_balance(&12), 1000); -// assert_eq!(Ring::usable_balance(&13), 1000); -// assert_eq!(Ring::usable_balance(&14), 1000); -// assert_eq!(FeeMarket::relayer(&12).order_capacity, 8); -// assert_eq!(FeeMarket::relayer(&13).order_capacity, 8); -// assert_eq!(FeeMarket::relayer(&14).order_capacity, 8); - -// // slash value = 70 + 30 * 2 = 130 > 100 -// order.confirm_time = Some(order.range_end().unwrap() + 30); -// assert_eq!(slash_assigned_relayers::(order, &10), 300); -// assert_eq!(Ring::usable_balance(&12), 1000); -// assert_eq!(Ring::usable_balance(&13), 1000); -// assert_eq!(Ring::usable_balance(&14), 1000); -// assert_eq!(FeeMarket::relayer(&12).collateral, 900); -// assert_eq!(FeeMarket::relayer(&13).collateral, 900); -// assert_eq!(FeeMarket::relayer(&14).collateral, 900); -// assert_eq!(FeeMarket::relayer(&12).collateral, 900); -// assert_eq!(FeeMarket::relayer(&13).collateral, 900); -// assert_eq!(FeeMarket::relayer(&14).collateral, 900); -// assert_eq!(FeeMarket::relayer(&12).collateral, 900); -// assert_eq!(FeeMarket::relayer(&13).collateral, 900); -// assert_eq!(FeeMarket::relayer(&14).collateral, 900); -// assert_eq!(FeeMarket::relayer(&12).order_capacity, 7); -// assert_eq!(FeeMarket::relayer(&13).order_capacity, 7); -// assert_eq!(FeeMarket::relayer(&14).order_capacity, 7); -// }); -// } - -// #[test] -// fn test_assigned_relayers_slash_kick_out_market_fee_hung() { -// new_test_ext().execute_with(|| { -// System::set_block_number(2); -// let _ = FeeMarket::enroll_and_lock_collateral(Origin::signed(1), 100, Some(30)); -// let _ = FeeMarket::enroll_and_lock_collateral(Origin::signed(2), 110, Some(50)); -// let _ = FeeMarket::enroll_and_lock_collateral(Origin::signed(3), 120, Some(70)); -// let _ = FeeMarket::enroll_and_lock_collateral(Origin::signed(4), 120, Some(80)); -// let market_fee = FeeMarket::market_fee().unwrap(); -// let (lane, message_nonce) = send_regular_message(market_fee); -// let mut order = FeeMarket::order((&lane, &message_nonce)).unwrap(); -// assert_eq!(Ring::usable_balance(&1), 50); -// assert_eq!(Ring::usable_balance(&2), 90); -// assert_eq!(Ring::usable_balance(&3), 230); - -// order.confirm_time = Some(order.range_end().unwrap() + 50); -// assert_eq!(slash_assigned_relayers::(order.clone(), &0), 300); -// assert_eq!(Ring::usable_balance(&1), 50); -// assert!(!FeeMarket::is_enrolled(&1)); -// assert_eq!(Ring::usable_balance(&2), 100); -// assert!(!FeeMarket::is_enrolled(&2)); -// assert_eq!(Ring::usable_balance(&3), 250); -// assert!(!FeeMarket::is_enrolled(&3)); -// assert!(FeeMarket::assigned_relayers().is_none()); -// assert!(FeeMarket::market_fee().is_none()); -// }); -// } - #[test] -fn test_payment_reward_calculation_assigned_relayers_absent_with_single_message() { +fn test_payment_with_slash_and_remove_enroll() { new_test_ext().execute_with(|| { // Send message System::set_block_number(2); let _ = FeeMarket::enroll_and_lock_collateral(Origin::signed(1), 100, Some(30)); let _ = FeeMarket::enroll_and_lock_collateral(Origin::signed(2), 110, Some(50)); let _ = FeeMarket::enroll_and_lock_collateral(Origin::signed(3), 120, Some(100)); + assert_eq!(FeeMarket::relayer(&1).collateral, 100); + assert_eq!(FeeMarket::relayer(&1).order_capacity, 1); + let market_fee = FeeMarket::market_fee().unwrap(); + let (_, _) = send_regular_message(market_fee); + assert_eq!(FeeMarket::relayer(&1).order_capacity, 0); + + // Receive delivery message proof + System::set_block_number(200); + assert_ok!(Messages::receive_messages_delivery_proof( + Origin::signed(5), + TestMessagesDeliveryProof(Ok(( + TEST_LANE_ID, + InboundLaneData { + relayers: vec![unrewarded_relayer(1, 1, TEST_RELAYER_A)] + .into_iter() + .collect(), + ..Default::default() + } + ))), + UnrewardedRelayersState { + unrewarded_relayer_entries: 1, + total_messages: 1, + ..Default::default() + }, + )); + assert!(!FeeMarket::is_enrolled(&1)); + assert!(!FeeMarket::is_enrolled(&2)); + assert!(!FeeMarket::is_enrolled(&3)); + assert!(TestMessageDeliveryAndDispatchPayment::is_reward_paid(5, 80)); + assert!(TestMessageDeliveryAndDispatchPayment::is_reward_paid( + TEST_RELAYER_A, + 320 + )); + }); +} + +#[test] +fn test_payment_with_slash_and_reduce_order_capacity() { + new_test_ext().execute_with(|| { + // Send message + System::set_block_number(2); + let _ = FeeMarket::enroll_and_lock_collateral(Origin::signed(6), 400, Some(30)); + let _ = FeeMarket::enroll_and_lock_collateral(Origin::signed(7), 400, Some(50)); + let _ = FeeMarket::enroll_and_lock_collateral(Origin::signed(8), 400, Some(100)); + assert_eq!(FeeMarket::relayer(&6).collateral, 400); + assert_eq!(FeeMarket::relayer(&6).order_capacity, 4); let market_fee = FeeMarket::market_fee().unwrap(); let (_, _) = send_regular_message(market_fee); + assert_eq!(FeeMarket::relayer(&6).order_capacity, 3); // Receive delivery message proof System::set_block_number(200); @@ -1153,16 +1072,25 @@ fn test_payment_reward_calculation_assigned_relayers_absent_with_single_message( ..Default::default() }, )); - assert!(TestMessageDeliveryAndDispatchPayment::is_reward_paid(5, 60)); + assert!(FeeMarket::is_enrolled(&6)); + assert!(FeeMarket::is_enrolled(&6)); + assert!(FeeMarket::is_enrolled(&6)); + assert_eq!(FeeMarket::relayer(&6).collateral, 300); + assert_eq!(FeeMarket::relayer(&7).collateral, 300); + assert_eq!(FeeMarket::relayer(&8).collateral, 300); + assert_eq!(FeeMarket::relayer(&6).order_capacity, 3); + assert_eq!(FeeMarket::relayer(&7).order_capacity, 3); + assert_eq!(FeeMarket::relayer(&8).order_capacity, 3); + assert!(TestMessageDeliveryAndDispatchPayment::is_reward_paid(5, 80)); assert!(TestMessageDeliveryAndDispatchPayment::is_reward_paid( TEST_RELAYER_A, - 240 + 320 )); }); } #[test] -fn test_payment_reward_calculation_assigned_relayers_absent_with_multiple_message() { +fn test_payment_cal_slash_with_multiple_message() { new_test_ext().execute_with(|| { System::set_block_number(2); let _ = FeeMarket::enroll_and_lock_collateral(Origin::signed(6), 400, Some(300)); @@ -1198,15 +1126,15 @@ fn test_payment_reward_calculation_assigned_relayers_absent_with_multiple_messag }, )); assert!(TestMessageDeliveryAndDispatchPayment::is_reward_paid( - 5, 120 + 5, 520 )); assert!(TestMessageDeliveryAndDispatchPayment::is_reward_paid( TEST_RELAYER_A, - 240 + 1040 )); assert!(TestMessageDeliveryAndDispatchPayment::is_reward_paid( TEST_RELAYER_B, - 240 + 1040 )); }); } @@ -1264,7 +1192,7 @@ fn test_clean_order_state_at_the_end_of_block() { } #[test] -fn test_check_submitted_fee_with_fee_market() { +fn test_fee_verification_when_send_message() { new_test_ext().execute_with(|| { let _ = FeeMarket::enroll_and_lock_collateral(Origin::signed(1), 100, Some(30)); let _ = FeeMarket::enroll_and_lock_collateral(Origin::signed(2), 100, Some(40)); diff --git a/node/runtime/pangolin/src/pallets/fee_market.rs b/node/runtime/pangolin/src/pallets/fee_market.rs index 4ca4795ba4..9edf226f2e 100644 --- a/node/runtime/pangolin/src/pallets/fee_market.rs +++ b/node/runtime/pangolin/src/pallets/fee_market.rs @@ -13,7 +13,6 @@ frame_support::parameter_types! { pub const MinimumRelayFee: Balance = 15 * COIN; pub const Slot: BlockNumber = 50; - pub const SlashPerBlockDelay: Balance = 2 * COIN; pub const CollateralPerOrder: Balance = 100 * COIN; pub const AssignedRelayersRewardRatio: Permill = Permill::from_percent(60); @@ -28,7 +27,6 @@ impl Config for Runtime { type AssignedRelayersNumber = AssignedRelayersNumber; type MinimumRelayFee = MinimumRelayFee; - type SlashPerBlockDelay = SlashPerBlockDelay; type CollateralPerOrder = CollateralPerOrder; type Slot = Slot; diff --git a/node/runtime/pangoro/src/pallets/fee_market.rs b/node/runtime/pangoro/src/pallets/fee_market.rs index ba3122a78d..053a3494bf 100644 --- a/node/runtime/pangoro/src/pallets/fee_market.rs +++ b/node/runtime/pangoro/src/pallets/fee_market.rs @@ -12,7 +12,6 @@ frame_support::parameter_types! { pub const AssignedRelayersNumber: u64 = 3; pub const MinimumRelayFee: Balance = 15 * COIN; - pub const SlashPerBlockDelay: Balance = 2 * COIN; pub const CollateralPerOrder: Balance = 100 * COIN; pub const Slot: BlockNumber = 50; @@ -28,7 +27,6 @@ impl Config for Runtime { type AssignedRelayersNumber = AssignedRelayersNumber; type MinimumRelayFee = MinimumRelayFee; - type SlashPerBlockDelay = SlashPerBlockDelay; type CollateralPerOrder = CollateralPerOrder; type Slot = Slot; From 061f59ff8be8de44c5ebc79e5d71500e96ff1485 Mon Sep 17 00:00:00 2001 From: ouwenkg <2630582710@qq.com> Date: Wed, 10 Nov 2021 14:01:25 +0800 Subject: [PATCH 24/46] Fix benchmark compile && update weight --- frame/fee-market/src/benchmarking.rs | 16 +++++----- frame/fee-market/src/s2s/callbacks.rs | 8 +---- frame/fee-market/src/weight.rs | 43 ++++++++++++++------------- 3 files changed, 31 insertions(+), 36 deletions(-) diff --git a/frame/fee-market/src/benchmarking.rs b/frame/fee-market/src/benchmarking.rs index b96434591d..cb6a9f9fc1 100644 --- a/frame/fee-market/src/benchmarking.rs +++ b/frame/fee-market/src/benchmarking.rs @@ -24,6 +24,7 @@ use crate::Pallet as FeeMarket; use frame_benchmarking::{account, benchmarks}; use frame_support::assert_ok; use frame_system::RawOrigin; +use sp_runtime::traits::Saturating; const SEED: u32 = 0; @@ -32,7 +33,7 @@ fn fee_market_ready() { let caller1: T::AccountId = account("source", 1, SEED); let caller2: T::AccountId = account("source", 2, SEED); let caller3: T::AccountId = account("source", 3, SEED); - let collateral = T::MiniumLockCollateral::get(); + let collateral = T::CollateralPerOrder::get(); T::RingCurrency::make_free_balance_be(&caller0, collateral.saturating_mul(10u32.into())); T::RingCurrency::make_free_balance_be(&caller1, collateral.saturating_mul(10u32.into())); T::RingCurrency::make_free_balance_be(&caller2, collateral.saturating_mul(10u32.into())); @@ -68,8 +69,8 @@ benchmarks! { enroll_and_lock_collateral { fee_market_ready::(); let relayer: T::AccountId = account("source", 100, SEED); - T::RingCurrency::make_free_balance_be(&relayer, T::MiniumLockCollateral::get().saturating_mul(10u32.into())); - let lock_collateral = T::MiniumLockCollateral::get().saturating_mul(5u32.into()); + T::RingCurrency::make_free_balance_be(&relayer, T::CollateralPerOrder::get().saturating_mul(10u32.into())); + let lock_collateral = T::CollateralPerOrder::get().saturating_mul(5u32.into()); }: enroll_and_lock_collateral(RawOrigin::Signed(relayer.clone()), lock_collateral, None) verify { assert!(>::is_enrolled(&relayer)); @@ -79,21 +80,21 @@ benchmarks! { update_locked_collateral { fee_market_ready::(); let caller3: T::AccountId = account("source", 3, SEED); - let new_collateral = T::MiniumLockCollateral::get().saturating_mul(5u32.into()); + let new_collateral = T::CollateralPerOrder::get().saturating_mul(5u32.into()); }: update_locked_collateral(RawOrigin::Signed(caller3.clone()), new_collateral) verify { let relayer = >::relayer(&caller3); - assert_eq!(relayer.collateral, T::MiniumLockCollateral::get().saturating_mul(5u32.into())); + assert_eq!(relayer.collateral, T::CollateralPerOrder::get().saturating_mul(5u32.into())); } update_relay_fee { fee_market_ready::(); let caller3: T::AccountId = account("source", 3, SEED); - let new_fee = T::MinimumRelayFee::get().saturating_mul(10u32.into()); + let new_fee = T::CollateralPerOrder::get().saturating_mul(10u32.into()); }: update_relay_fee(RawOrigin::Signed(caller3.clone()), new_fee) verify { let relayer = >::relayer(&caller3); - assert_eq!(relayer.fee, T::MinimumRelayFee::get().saturating_mul(10u32.into())); + assert_eq!(relayer.fee, T::CollateralPerOrder::get().saturating_mul(10u32.into())); } cancel_enrollment { @@ -104,5 +105,4 @@ benchmarks! { assert!(!>::is_enrolled(&caller1)); assert_eq!(>::relayers().len(), 3); } - } diff --git a/frame/fee-market/src/s2s/callbacks.rs b/frame/fee-market/src/s2s/callbacks.rs index 1cba798c12..d320391226 100644 --- a/frame/fee-market/src/s2s/callbacks.rs +++ b/frame/fee-market/src/s2s/callbacks.rs @@ -30,13 +30,7 @@ impl OnMessageAccepted for FeeMarketMessageAcceptedHandler { // Create a new order based on the latest block, assign relayers which have priority to relaying let now = frame_system::Pallet::::block_number(); if let Some(assigned_relayers) = >::assigned_relayers() { - let order = Order::new( - *lane, - *message, - now, - assigned_relayers.clone(), - T::Slot::get(), - ); + let order = Order::new(*lane, *message, now, assigned_relayers, T::Slot::get()); // Store the create order >::insert((order.lane, order.message), order.clone()); // Update relayer orders and order_capacity diff --git a/frame/fee-market/src/weight.rs b/frame/fee-market/src/weight.rs index c3c5582134..ab637cb646 100644 --- a/frame/fee-market/src/weight.rs +++ b/frame/fee-market/src/weight.rs @@ -18,7 +18,7 @@ //! Autogenerated weights for darwinia_fee_market //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 3.0.0 -//! DATE: 2021-09-29, STEPS: [10, ], REPEAT: 50, LOW RANGE: [], HIGH RANGE: [] +//! DATE: 2021-11-10, STEPS: [100, ], REPEAT: 50, LOW RANGE: [], HIGH RANGE: [] //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 128 // Executed Command: @@ -32,9 +32,10 @@ // darwinia_fee_market // --execution // wasm -// --extrinsic=* +// --extrinsic +// * // --steps -// 10 +// 100 // --repeat // 50 // --raw @@ -63,47 +64,47 @@ pub trait WeightInfo { pub struct SubstrateWeight(PhantomData); impl WeightInfo for SubstrateWeight { fn enroll_and_lock_collateral() -> Weight { - (93_604_000 as Weight) + (98_863_000 as Weight) .saturating_add(T::DbWeight::get().reads(11 as Weight)) - .saturating_add(T::DbWeight::get().writes(8 as Weight)) + .saturating_add(T::DbWeight::get().writes(7 as Weight)) } fn update_locked_collateral() -> Weight { - (86_772_000 as Weight) + (90_257_000 as Weight) .saturating_add(T::DbWeight::get().reads(11 as Weight)) - .saturating_add(T::DbWeight::get().writes(6 as Weight)) + .saturating_add(T::DbWeight::get().writes(5 as Weight)) } fn update_relay_fee() -> Weight { - (62_427_000 as Weight) + (62_045_000 as Weight) .saturating_add(T::DbWeight::get().reads(9 as Weight)) - .saturating_add(T::DbWeight::get().writes(5 as Weight)) + .saturating_add(T::DbWeight::get().writes(4 as Weight)) } fn cancel_enrollment() -> Weight { - (83_676_000 as Weight) - .saturating_add(T::DbWeight::get().reads(10 as Weight)) - .saturating_add(T::DbWeight::get().writes(8 as Weight)) + (96_118_000 as Weight) + .saturating_add(T::DbWeight::get().reads(12 as Weight)) + .saturating_add(T::DbWeight::get().writes(7 as Weight)) } } // For backwards compatibility and tests impl WeightInfo for () { fn enroll_and_lock_collateral() -> Weight { - (93_604_000 as Weight) + (98_863_000 as Weight) .saturating_add(RocksDbWeight::get().reads(11 as Weight)) - .saturating_add(RocksDbWeight::get().writes(8 as Weight)) + .saturating_add(RocksDbWeight::get().writes(7 as Weight)) } fn update_locked_collateral() -> Weight { - (86_772_000 as Weight) + (90_257_000 as Weight) .saturating_add(RocksDbWeight::get().reads(11 as Weight)) - .saturating_add(RocksDbWeight::get().writes(6 as Weight)) + .saturating_add(RocksDbWeight::get().writes(5 as Weight)) } fn update_relay_fee() -> Weight { - (62_427_000 as Weight) + (62_045_000 as Weight) .saturating_add(RocksDbWeight::get().reads(9 as Weight)) - .saturating_add(RocksDbWeight::get().writes(5 as Weight)) + .saturating_add(RocksDbWeight::get().writes(4 as Weight)) } fn cancel_enrollment() -> Weight { - (83_676_000 as Weight) - .saturating_add(RocksDbWeight::get().reads(10 as Weight)) - .saturating_add(RocksDbWeight::get().writes(8 as Weight)) + (96_118_000 as Weight) + .saturating_add(RocksDbWeight::get().reads(12 as Weight)) + .saturating_add(RocksDbWeight::get().writes(7 as Weight)) } } From 355cff45f1b0701af6345e5388cf59341959d090 Mon Sep 17 00:00:00 2001 From: ouwenkg <2630582710@qq.com> Date: Wed, 10 Nov 2021 15:54:11 +0800 Subject: [PATCH 25/46] Update type json --- node/runtime/pangolin/types.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/node/runtime/pangolin/types.json b/node/runtime/pangolin/types.json index 156af94d19..1aa6a79c04 100644 --- a/node/runtime/pangolin/types.json +++ b/node/runtime/pangolin/types.json @@ -256,7 +256,8 @@ "Relayer": { "id": "AccountId", "collateral": "Balance", - "fee": "Balance" + "fee": "Balance", + "order_capacity":"u32" }, "Fee": "Balance", "Order": { From 5a04b75ac11e566abb12f9b2e0aa06c1cd6029b6 Mon Sep 17 00:00:00 2001 From: ouwenkg <2630582710@qq.com> Date: Wed, 10 Nov 2021 18:10:31 +0800 Subject: [PATCH 26/46] Update locked collateral support decrease --- frame/fee-market/src/lib.rs | 90 +++++++++++++++---------- frame/fee-market/src/tests.rs | 119 ++++++++++++++++++++++++---------- 2 files changed, 138 insertions(+), 71 deletions(-) diff --git a/frame/fee-market/src/lib.rs b/frame/fee-market/src/lib.rs index b448e7fcaf..56c2468f47 100644 --- a/frame/fee-market/src/lib.rs +++ b/frame/fee-market/src/lib.rs @@ -40,7 +40,7 @@ use frame_support::{ }; use frame_system::{ensure_signed, pallet_prelude::*}; use num_traits::Zero; -use sp_runtime::{Permill, SaturatedConversion}; +use sp_runtime::{traits::Saturating, Permill, SaturatedConversion}; use sp_std::{default::Default, vec::Vec}; // --- darwinia-network --- use darwinia_support::{ @@ -199,9 +199,7 @@ pub mod pallet { T::RingCurrency::free_balance(&who) >= lock_collateral, >::InsufficientBalance ); - let order_capacity: u32 = - (lock_collateral / T::CollateralPerOrder::get()).saturated_into::(); - + let order_capacity = Self::collateral_to_order_capacity(lock_collateral); if let Some(fee) = relay_fee { ensure!(fee >= T::MinimumRelayFee::get(), >::RelayFeeTooLow); } @@ -246,29 +244,45 @@ pub mod pallet { >::InsufficientBalance ); - let relayer = Self::relayer(&who); - ensure!( - new_collateral > relayer.collateral, - >::OnlyIncCollateralAllowed - ); - let old_capacity: u32 = - (relayer.collateral / T::CollateralPerOrder::get()).saturated_into::(); - let used_capacity = old_capacity.saturating_sub(relayer.order_capacity); - let new_capacity: u32 = - (new_collateral / T::CollateralPerOrder::get()).saturated_into::(); + let new_capacity = Self::collateral_to_order_capacity(new_collateral); + let occupied_capacity = Self::is_occupied(&who).unwrap_or_default(); + let available_capacity = new_capacity.saturating_sub(occupied_capacity); + + // Increase the locked collateral + if new_collateral >= Self::relayer(&who).collateral { + let _ = T::RingCurrency::extend_lock( + T::LockId::get(), + &who, + new_collateral, + WithdrawReasons::all(), + ) + .map_err(|_| >::ExtendLockFailed); + } else { + // Decrease the locked collateral + if let Some(necessary_collateral) = Self::is_occupied(&who) { + ensure!( + new_collateral + >= T::CollateralPerOrder::get() + .saturating_mul(necessary_collateral.into()), + >::OnlyIncCollateralAllowed + ); + + T::RingCurrency::remove_lock(T::LockId::get(), &who); + T::RingCurrency::set_lock( + T::LockId::get(), + &who, + LockFor::Common { + amount: new_collateral, + }, + WithdrawReasons::all(), + ); + } + } - let _ = T::RingCurrency::extend_lock( - T::LockId::get(), - &who, - new_collateral, - WithdrawReasons::all(), - ) - .map_err(|_| >::ExtendLockFailed); >::mutate(who.clone(), |relayer| { relayer.collateral = new_collateral; - relayer.order_capacity = new_capacity - used_capacity; + relayer.order_capacity = available_capacity; }); - Self::update_market(); Self::deposit_event(Event::::UpdateRelayer( who.clone(), @@ -308,7 +322,10 @@ pub mod pallet { pub fn cancel_enrollment(origin: OriginFor) -> DispatchResultWithPostInfo { let who = ensure_signed(origin)?; ensure!(Self::is_enrolled(&who), >::NotEnrolled); - ensure!(!Self::is_occupied(&who), >::OccupiedRelayer); + ensure!( + Self::is_occupied(&who).is_none(), + >::OccupiedRelayer + ); Self::remove_enrolled_relayer(&who); Self::deposit_event(Event::::CancelEnrollment(who)); @@ -337,15 +354,7 @@ impl Pallet { if relayers.len() >= assigned_relayers_len { relayers.sort(); - let mut assigned_relayers = Vec::with_capacity(assigned_relayers_len); - let mut relayer_iterator = relayers.into_iter(); - while let Some(r) = relayer_iterator.next() { - if assigned_relayers.len() == assigned_relayers_len { - break; - } - assigned_relayers.push(r); - } - + let assigned_relayers: Vec<_> = relayers.iter().take(assigned_relayers_len).collect(); >::put(assigned_relayers); } else { // The market fee comes from the last item in AssignedRelayers, @@ -431,12 +440,21 @@ impl Pallet { } /// Whether the enrolled relayer is occupied(Responsible for order relaying) - pub(crate) fn is_occupied(who: &T::AccountId) -> bool { + pub(crate) fn is_occupied(who: &T::AccountId) -> Option { + let mut count = 0u32; for (_, order) in >::iter() { if order.relayers_slice().iter().any(|r| r.id == *who) && !order.is_confirmed() { - return true; + count += 1; } } - false + + if count == 0 { + return None; + } + Some(count) + } + + pub(crate) fn collateral_to_order_capacity(collateral: RingBalance) -> u32 { + (collateral / T::CollateralPerOrder::get()).saturated_into::() } } diff --git a/frame/fee-market/src/tests.rs b/frame/fee-market/src/tests.rs index 3252e96db2..f7e28d0ee3 100644 --- a/frame/fee-market/src/tests.rs +++ b/frame/fee-market/src/tests.rs @@ -557,49 +557,75 @@ fn test_call_relayer_enroll_works() { ),); }); } + #[test] -fn test_call_relayer_update_lock_collateral_works() { +fn test_call_relayer_increase_lock_collateral_works() { new_test_ext().execute_with(|| { assert_err!( - FeeMarket::update_locked_collateral(Origin::signed(6), 100), + FeeMarket::update_locked_collateral(Origin::signed(12), 100), >::NotEnrolled ); - assert_ok!(FeeMarket::enroll_and_lock_collateral( - Origin::signed(6), - 200, - None - )); - assert_eq!(FeeMarket::relayer(&6).collateral, 200); - assert_eq!(FeeMarket::relayer(6).order_capacity, 2); - - // Increase locked balance - assert_ok!(FeeMarket::update_locked_collateral(Origin::signed(6), 500)); - assert_eq!(FeeMarket::relayer(&6).collateral, 500); - assert_eq!(FeeMarket::relayer(6).order_capacity, 5); - // Decrease locked balance - assert_err!( - FeeMarket::update_locked_collateral(Origin::signed(6), 80), - >::OnlyIncCollateralAllowed - ); + let _ = FeeMarket::enroll_and_lock_collateral(Origin::signed(12), 200, None); + assert_eq!(FeeMarket::relayer(&12).collateral, 200); + assert_eq!(FeeMarket::relayer(12).order_capacity, 2); - assert_ok!(FeeMarket::enroll_and_lock_collateral( - Origin::signed(4), - 20, - None - )); - assert_eq!(FeeMarket::relayer(4).order_capacity, 0); - assert_ok!(FeeMarket::update_locked_collateral(Origin::signed(4), 200)); - assert_eq!(FeeMarket::relayer(4).order_capacity, 2); + // Increase locked balance from 200 to 500 + assert_ok!(FeeMarket::update_locked_collateral(Origin::signed(12), 500)); + assert_eq!(FeeMarket::relayer(&12).collateral, 500); + assert_eq!(FeeMarket::relayer(12).order_capacity, 5); - assert_ok!(FeeMarket::enroll_and_lock_collateral( - Origin::signed(7), - 120, - None - )); - assert_eq!(FeeMarket::relayer(7).order_capacity, 1); - assert_ok!(FeeMarket::update_locked_collateral(Origin::signed(7), 400)); - assert_eq!(FeeMarket::relayer(7).order_capacity, 4); + // Increase locked balance from 20 to 200 + let _ = FeeMarket::enroll_and_lock_collateral(Origin::signed(13), 20, None); + assert_eq!(FeeMarket::relayer(13).order_capacity, 0); + assert_ok!(FeeMarket::update_locked_collateral(Origin::signed(13), 200)); + assert_eq!(FeeMarket::relayer(13).order_capacity, 2); + + let _ = FeeMarket::enroll_and_lock_collateral(Origin::signed(14), 300, None); + assert_eq!(FeeMarket::relayer(14).order_capacity, 3); + let market_fee = FeeMarket::market_fee().unwrap(); + let _ = send_regular_message(market_fee); + let _ = send_regular_message(market_fee); + assert_eq!(FeeMarket::relayer(12).order_capacity, 3); + assert_eq!(FeeMarket::relayer(13).order_capacity, 0); + assert_eq!(FeeMarket::relayer(14).order_capacity, 1); + assert_ok!(FeeMarket::update_locked_collateral(Origin::signed(12), 800)); + assert_ok!(FeeMarket::update_locked_collateral(Origin::signed(13), 800)); + assert_ok!(FeeMarket::update_locked_collateral(Origin::signed(14), 800)); + assert_eq!(FeeMarket::relayer(&12).collateral, 800); + assert_eq!(FeeMarket::relayer(&13).collateral, 800); + assert_eq!(FeeMarket::relayer(&14).collateral, 800); + assert_eq!(FeeMarket::relayer(12).order_capacity, 6); + assert_eq!(FeeMarket::relayer(13).order_capacity, 6); + assert_eq!(FeeMarket::relayer(14).order_capacity, 6); + }); +} + +#[test] +fn test_call_relayer_decrease_lock_collateral_works() { + new_test_ext().execute_with(|| { + let _ = FeeMarket::enroll_and_lock_collateral(Origin::signed(12), 800, None); + let _ = FeeMarket::enroll_and_lock_collateral(Origin::signed(13), 800, None); + let _ = FeeMarket::enroll_and_lock_collateral(Origin::signed(14), 800, None); + let market_fee = FeeMarket::market_fee().unwrap(); + let _ = send_regular_message(market_fee); + let _ = send_regular_message(market_fee); + let _ = send_regular_message(market_fee); + let _ = send_regular_message(market_fee); + + assert_err!( + FeeMarket::update_locked_collateral(Origin::signed(12), 300), + >::OnlyIncCollateralAllowed + ); + assert_ok!(FeeMarket::update_locked_collateral(Origin::signed(12), 400)); + assert_eq!(FeeMarket::relayer(&12).collateral, 400); + assert_eq!(FeeMarket::relayer(12).order_capacity, 0); + assert_ok!(FeeMarket::update_locked_collateral(Origin::signed(13), 500)); + assert_eq!(FeeMarket::relayer(&13).collateral, 500); + assert_eq!(FeeMarket::relayer(13).order_capacity, 1); + assert_ok!(FeeMarket::update_locked_collateral(Origin::signed(14), 700)); + assert_eq!(FeeMarket::relayer(&14).collateral, 700); + assert_eq!(FeeMarket::relayer(14).order_capacity, 3); }); } @@ -1228,3 +1254,26 @@ fn test_fee_verification_when_send_message() { ),); }); } + +#[test] +fn test_relayer_is_occupied() { + new_test_ext().execute_with(|| { + System::set_block_number(2); + let _ = FeeMarket::enroll_and_lock_collateral(Origin::signed(5), 300, Some(30)); + let _ = FeeMarket::enroll_and_lock_collateral(Origin::signed(6), 300, Some(50)); + let _ = FeeMarket::enroll_and_lock_collateral(Origin::signed(7), 300, Some(100)); + + // Send message + let market_fee = FeeMarket::market_fee().unwrap(); + let _ = send_regular_message(market_fee); + let _ = send_regular_message(market_fee); + + assert_eq!(FeeMarket::is_occupied(&5), Some(2)); + assert_eq!(FeeMarket::is_occupied(&6), Some(2)); + assert_eq!(FeeMarket::is_occupied(&7), Some(2)); + receive_messages_delivery_proof(); + assert_eq!(FeeMarket::is_occupied(&5), Some(1)); + assert_eq!(FeeMarket::is_occupied(&6), Some(1)); + assert_eq!(FeeMarket::is_occupied(&7), Some(1)); + }); +} From 902fe8937ae0afcf514960eda50527896e2c0cfa Mon Sep 17 00:00:00 2001 From: ouwenkg <2630582710@qq.com> Date: Wed, 10 Nov 2021 18:12:27 +0800 Subject: [PATCH 27/46] Update error type --- frame/fee-market/src/lib.rs | 6 +++--- frame/fee-market/src/tests.rs | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/frame/fee-market/src/lib.rs b/frame/fee-market/src/lib.rs index 56c2468f47..e762c8adc7 100644 --- a/frame/fee-market/src/lib.rs +++ b/frame/fee-market/src/lib.rs @@ -123,8 +123,8 @@ pub mod pallet { AlreadyEnrolled, /// This relayer doesn't enroll ever. NotEnrolled, - /// Only increase lock collateral is allowed when update_locked_collateral. - OnlyIncCollateralAllowed, + /// Update locked collateral is not allow since some orders are not confirm. + StillHasOrdersNotConfirmed, /// The fee is lower than MinimumRelayFee. RelayFeeTooLow, /// The relayer is occupied, and can't cancel enrollment now. @@ -264,7 +264,7 @@ pub mod pallet { new_collateral >= T::CollateralPerOrder::get() .saturating_mul(necessary_collateral.into()), - >::OnlyIncCollateralAllowed + >::StillHasOrdersNotConfirmed ); T::RingCurrency::remove_lock(T::LockId::get(), &who); diff --git a/frame/fee-market/src/tests.rs b/frame/fee-market/src/tests.rs index f7e28d0ee3..cb6d0f93b5 100644 --- a/frame/fee-market/src/tests.rs +++ b/frame/fee-market/src/tests.rs @@ -615,7 +615,7 @@ fn test_call_relayer_decrease_lock_collateral_works() { assert_err!( FeeMarket::update_locked_collateral(Origin::signed(12), 300), - >::OnlyIncCollateralAllowed + >::StillHasOrdersNotConfirmed ); assert_ok!(FeeMarket::update_locked_collateral(Origin::signed(12), 400)); assert_eq!(FeeMarket::relayer(&12).collateral, 400); From 3d48b6cc484761d67f689f4e65a47de28d917b18 Mon Sep 17 00:00:00 2001 From: ouwenkg <2630582710@qq.com> Date: Thu, 11 Nov 2021 13:36:20 +0800 Subject: [PATCH 28/46] Add locked_collateral to order struct --- primitives/fee-market/src/lib.rs | 123 ++++++++++++++----------------- 1 file changed, 55 insertions(+), 68 deletions(-) diff --git a/primitives/fee-market/src/lib.rs b/primitives/fee-market/src/lib.rs index ecd6d3c8bb..8e82f3f75a 100644 --- a/primitives/fee-market/src/lib.rs +++ b/primitives/fee-market/src/lib.rs @@ -32,38 +32,21 @@ pub struct Relayer { pub id: AccountId, pub collateral: Balance, pub fee: Balance, - pub order_capacity: u32, } impl Relayer { - pub fn new( - id: AccountId, - collateral: Balance, - fee: Balance, - order_capacity: u32, - ) -> Relayer { + pub fn new(id: AccountId, collateral: Balance, fee: Balance) -> Relayer { Relayer { id, collateral, fee, - order_capacity, } } - - pub fn accept_order(&mut self) { - self.order_capacity = self.order_capacity.saturating_sub(1); - } - - pub fn finish_order(&mut self) { - self.order_capacity = self.order_capacity.saturating_add(1); - } } impl PartialOrd for Relayer { fn partial_cmp(&self, other: &Self) -> Option { - if self.fee == other.fee && self.order_capacity != other.order_capacity { - return other.order_capacity.partial_cmp(&self.order_capacity); - } else if self.fee == other.fee && self.order_capacity == other.order_capacity { + if self.fee == other.fee { return other.collateral.partial_cmp(&self.collateral); } self.fee.partial_cmp(&other.fee) @@ -72,10 +55,8 @@ impl PartialOrd for Relayer Ord for Relayer { fn cmp(&self, other: &Self) -> Ordering { - if self.fee == other.fee && self.order_capacity != other.order_capacity { - return other.order_capacity.cmp(&self.order_capacity); - } else if self.fee == other.fee && self.order_capacity == other.order_capacity { - return other.collateral.cmp(&self.collateral); + if self.fee == other.fee { + return self.collateral.cmp(&other.collateral); } self.fee.cmp(&other.fee) } @@ -83,10 +64,7 @@ impl Ord for Relayer { impl PartialEq for Relayer { fn eq(&self, other: &Self) -> bool { - self.fee == other.fee - && self.id == other.id - && self.collateral == other.collateral - && self.order_capacity == other.order_capacity + self.fee == other.fee && self.id == other.id && self.collateral == other.collateral } } @@ -96,7 +74,6 @@ impl Default for Relayer { pub message: MessageNonce, pub sent_time: BlockNumber, pub confirm_time: Option, + pub locked_collateral: Balance, pub relayers: Vec>, } @@ -121,6 +99,7 @@ where lane: LaneId, message: MessageNonce, sent_time: BlockNumber, + locked_collateral: Balance, assigned_relayers: Vec>, slot: BlockNumber, ) -> Self { @@ -143,6 +122,7 @@ where message, sent_time, confirm_time: None, + locked_collateral, relayers, } } @@ -233,33 +213,43 @@ mod test { #[test] fn test_multi_relayers_sort() { - let r1 = Relayer::::new(1, 150, 30, 0); - let r2 = Relayer::::new(2, 100, 40, 0); + let r1 = Relayer::::new(1, 100, 30); + let r2 = Relayer::::new(2, 100, 40); assert!(r1 < r2); - let r3 = Relayer::::new(3, 150, 30, 10); - let r4 = Relayer::::new(4, 100, 30, 20); - assert!(r4 < r3); - - let r5 = Relayer::::new(3, 150, 30, 10); - let r6 = Relayer::::new(4, 100, 30, 10); - assert!(r5 < r6); + let r3 = Relayer::::new(3, 150, 30); + let r4 = Relayer::::new(4, 100, 30); + assert!(r3 < r4); } #[test] fn test_assign_order_relayers_one() { let mut assigned_relayers = Vec::new(); - assigned_relayers.push(Relayer::::new(1, 100, 30, 0)); - let order = Order::new(TEST_LANE_ID, TEST_MESSAGE_NONCE, 100, assigned_relayers, 50); + assigned_relayers.push(Relayer::::new(1, 100, 30)); + let order = Order::new( + TEST_LANE_ID, + TEST_MESSAGE_NONCE, + 100, + 100, + assigned_relayers, + 50, + ); assert_eq!(order.relayer_valid_range(1).unwrap(), (100..150)); } #[test] fn test_assign_order_relayers_two() { let mut assigned_relayers = Vec::new(); - assigned_relayers.push(Relayer::::new(1, 100, 30, 0)); - assigned_relayers.push(Relayer::::new(2, 100, 30, 0)); - let order = Order::new(TEST_LANE_ID, TEST_MESSAGE_NONCE, 100, assigned_relayers, 50); + assigned_relayers.push(Relayer::::new(1, 100, 30)); + assigned_relayers.push(Relayer::::new(2, 100, 30)); + let order = Order::new( + TEST_LANE_ID, + TEST_MESSAGE_NONCE, + 100, + 100, + assigned_relayers, + 50, + ); assert_eq!(order.relayer_valid_range(1).unwrap(), (100..150)); assert_eq!(order.relayer_valid_range(2).unwrap(), (150..200)); } @@ -267,10 +257,17 @@ mod test { #[test] fn test_assign_order_relayers_three() { let mut assigned_relayers = Vec::new(); - assigned_relayers.push(Relayer::::new(1, 100, 30, 0)); - assigned_relayers.push(Relayer::::new(2, 100, 40, 0)); - assigned_relayers.push(Relayer::::new(3, 100, 80, 0)); - let order = Order::new(TEST_LANE_ID, TEST_MESSAGE_NONCE, 100, assigned_relayers, 50); + assigned_relayers.push(Relayer::::new(1, 100, 30)); + assigned_relayers.push(Relayer::::new(2, 100, 40)); + assigned_relayers.push(Relayer::::new(3, 100, 80)); + let order = Order::new( + TEST_LANE_ID, + TEST_MESSAGE_NONCE, + 100, + 100, + assigned_relayers, + 50, + ); assert_eq!(order.relayer_valid_range(1).unwrap(), (100..150)); assert_eq!(order.relayer_valid_range(2).unwrap(), (150..200)); assert_eq!(order.relayer_valid_range(3).unwrap(), (200..250)); @@ -281,31 +278,21 @@ mod test { #[test] fn test_assign_order_relayers_four() { let mut assigned_relayers = Vec::new(); - assigned_relayers.push(Relayer::::new(1, 100, 30, 0)); - assigned_relayers.push(Relayer::::new(2, 100, 30, 0)); - assigned_relayers.push(Relayer::::new(3, 100, 30, 0)); - assigned_relayers.push(Relayer::::new(4, 100, 30, 0)); - let order = Order::new(TEST_LANE_ID, TEST_MESSAGE_NONCE, 100, assigned_relayers, 50); + assigned_relayers.push(Relayer::::new(1, 100, 30)); + assigned_relayers.push(Relayer::::new(2, 100, 30)); + assigned_relayers.push(Relayer::::new(3, 100, 30)); + assigned_relayers.push(Relayer::::new(4, 100, 30)); + let order = Order::new( + TEST_LANE_ID, + TEST_MESSAGE_NONCE, + 100, + 100, + assigned_relayers, + 50, + ); assert_eq!(order.relayer_valid_range(1).unwrap(), (100..150)); assert_eq!(order.relayer_valid_range(2).unwrap(), (150..200)); assert_eq!(order.relayer_valid_range(3).unwrap(), (200..250)); assert_eq!(order.relayer_valid_range(4).unwrap(), (250..300)); } - - #[test] - fn test_accept_order() { - let mut r1 = Relayer::::new(1, 150, 30, 1); - r1.accept_order(); - assert_eq!(r1.order_capacity, 0); - } - - #[test] - fn test_finish_order() { - let mut r2 = Relayer::::new(1, 150, 30, 3); - r2.accept_order(); - r2.accept_order(); - r2.accept_order(); - r2.finish_order(); - assert_eq!(r2.order_capacity, 1); - } } From e96516beaa87bffc059b67360bfd9bdb6ec0f220 Mon Sep 17 00:00:00 2001 From: ouwenkg <2630582710@qq.com> Date: Thu, 11 Nov 2021 15:01:07 +0800 Subject: [PATCH 29/46] Remove order_capacity, fix review issues --- frame/fee-market/src/lib.rs | 106 ++++++++------------------ frame/fee-market/src/s2s/callbacks.rs | 11 ++- frame/fee-market/src/s2s/payment.rs | 11 +-- frame/fee-market/src/tests.rs | 63 ++++----------- node/runtime/pangolin/types.json | 3 +- 5 files changed, 62 insertions(+), 132 deletions(-) diff --git a/frame/fee-market/src/lib.rs b/frame/fee-market/src/lib.rs index e762c8adc7..acdda1597b 100644 --- a/frame/fee-market/src/lib.rs +++ b/frame/fee-market/src/lib.rs @@ -103,14 +103,9 @@ pub mod pallet { )] pub enum Event { /// Relayer enrollment - Enroll(T::AccountId, RingBalance, Fee, u32), + Enroll(T::AccountId, RingBalance, Fee), /// Update relayer - UpdateRelayer( - T::AccountId, - Option>, - Option, - Option>, - ), + UpdateRelayer(T::AccountId, Option>, Option>), /// Relayer cancel enrollment CancelEnrollment(T::AccountId), } @@ -199,7 +194,6 @@ pub mod pallet { T::RingCurrency::free_balance(&who) >= lock_collateral, >::InsufficientBalance ); - let order_capacity = Self::collateral_to_order_capacity(lock_collateral); if let Some(fee) = relay_fee { ensure!(fee >= T::MinimumRelayFee::get(), >::RelayFeeTooLow); } @@ -214,19 +208,11 @@ pub mod pallet { WithdrawReasons::all(), ); // Store enrollment detail information. - >::insert( - &who, - Relayer::new(who.clone(), lock_collateral, fee, order_capacity), - ); + >::insert(&who, Relayer::new(who.clone(), lock_collateral, fee)); >::append(&who); Self::update_market(); - Self::deposit_event(Event::::Enroll( - who, - lock_collateral, - fee, - order_capacity, - )); + Self::deposit_event(Event::::Enroll(who, lock_collateral, fee)); Ok(().into()) } @@ -244,10 +230,6 @@ pub mod pallet { >::InsufficientBalance ); - let new_capacity = Self::collateral_to_order_capacity(new_collateral); - let occupied_capacity = Self::is_occupied(&who).unwrap_or_default(); - let available_capacity = new_capacity.saturating_sub(occupied_capacity); - // Increase the locked collateral if new_collateral >= Self::relayer(&who).collateral { let _ = T::RingCurrency::extend_lock( @@ -259,11 +241,9 @@ pub mod pallet { .map_err(|_| >::ExtendLockFailed); } else { // Decrease the locked collateral - if let Some(necessary_collateral) = Self::is_occupied(&who) { + if let Some((_, orders_locked_collateral)) = Self::occupied(&who) { ensure!( - new_collateral - >= T::CollateralPerOrder::get() - .saturating_mul(necessary_collateral.into()), + new_collateral >= orders_locked_collateral, >::StillHasOrdersNotConfirmed ); @@ -281,13 +261,11 @@ pub mod pallet { >::mutate(who.clone(), |relayer| { relayer.collateral = new_collateral; - relayer.order_capacity = available_capacity; }); Self::update_market(); Self::deposit_event(Event::::UpdateRelayer( who.clone(), Some(new_collateral), - Some(Self::relayer(&who).order_capacity), None, )); Ok(().into()) @@ -312,7 +290,7 @@ pub mod pallet { }); Self::update_market(); - Self::deposit_event(Event::::UpdateRelayer(who, None, None, Some(new_fee))); + Self::deposit_event(Event::::UpdateRelayer(who, None, Some(new_fee))); Ok(().into()) } @@ -322,10 +300,7 @@ pub mod pallet { pub fn cancel_enrollment(origin: OriginFor) -> DispatchResultWithPostInfo { let who = ensure_signed(origin)?; ensure!(Self::is_enrolled(&who), >::NotEnrolled); - ensure!( - Self::is_occupied(&who).is_none(), - >::OccupiedRelayer - ); + ensure!(Self::occupied(&who).is_none(), >::OccupiedRelayer); Self::remove_enrolled_relayer(&who); Self::deposit_event(Event::::CancelEnrollment(who)); @@ -346,7 +321,7 @@ impl Pallet { let mut relayers: Vec>> = >::get() .iter() .map(RelayersMap::::get) - .filter(|r| r.order_capacity >= 1) + .filter(|r| Self::usable_order_capacity(&r.id) >= 1) .collect(); // Select the first `AssignedRelayersNumber` relayers as AssignedRelayer. @@ -365,12 +340,6 @@ impl Pallet { /// Update relayer after slash occurred, this will changes RelayersMap storage. (Update market needed) pub(crate) fn update_relayer_after_slash(who: &T::AccountId, new_collateral: RingBalance) { - if new_collateral == RingBalance::::zero() || Self::relayer(&who).order_capacity == 0 { - Self::remove_enrolled_relayer(who); - return; - } - - // Update locked collateral T::RingCurrency::set_lock( T::LockId::get(), &who, @@ -383,6 +352,11 @@ impl Pallet { relayer.collateral = new_collateral; }); + if Self::usable_order_capacity(&who) == 0 { + Self::remove_enrolled_relayer(who); + return; + } + Self::update_market(); } @@ -400,35 +374,6 @@ impl Pallet { Self::update_market(); } - /// Update relayer order capacity after message order created. (Update market needed) - pub(crate) fn relayer_accept_order( - order: &Order>, - ) { - let assigned_relayers: Vec = - order.relayers.iter().map(|r| r.id.clone()).collect(); - - for who in assigned_relayers { - >::mutate(who.clone(), |r| { - r.accept_order(); - }); - } - Self::update_market(); - } - - /// Update relayer order capacity after message order confirmed. (Update market needed) - pub(crate) fn relayer_finish_order( - order: &Order>, - ) { - let assigned_relayers: Vec = - order.relayers.iter().map(|r| r.id.clone()).collect(); - for who in assigned_relayers { - >::mutate(who.clone(), |r| { - r.finish_order(); - }); - } - Self::update_market(); - } - /// Whether the relayer has enrolled pub(crate) fn is_enrolled(who: &T::AccountId) -> bool { >::get().iter().any(|r| *r == *who) @@ -439,22 +384,37 @@ impl Pallet { Self::assigned_relayers().and_then(|relayers| relayers.last().map(|r| r.fee)) } - /// Whether the enrolled relayer is occupied(Responsible for order relaying) - pub(crate) fn is_occupied(who: &T::AccountId) -> Option { + /// Whether the enrolled relayer is occupied, If occupied, return the number of orders and orders locked collateral, otherwise, return None. + pub(crate) fn occupied(who: &T::AccountId) -> Option<(u32, RingBalance)> { let mut count = 0u32; + let mut orders_locked_collateral = RingBalance::::zero(); for (_, order) in >::iter() { if order.relayers_slice().iter().any(|r| r.id == *who) && !order.is_confirmed() { count += 1; + orders_locked_collateral = + orders_locked_collateral.saturating_add(order.locked_collateral); } } if count == 0 { return None; } - Some(count) + Some((count, orders_locked_collateral)) + } + + /// The relayer collateral is composed of two part: fee_collateral and orders_locked_collateral. + /// Calculate the order capacity with fee_collateral + pub(crate) fn usable_order_capacity(who: &T::AccountId) -> u32 { + if let Some((_, orders_locked_collateral)) = Self::occupied(&who) { + let free_collateral = Self::relayer(who) + .collateral + .saturating_sub(orders_locked_collateral); + return Self::collateral_to_order_capacity(free_collateral); + } + Self::collateral_to_order_capacity(Self::relayer(who).collateral) } - pub(crate) fn collateral_to_order_capacity(collateral: RingBalance) -> u32 { + fn collateral_to_order_capacity(collateral: RingBalance) -> u32 { (collateral / T::CollateralPerOrder::get()).saturated_into::() } } diff --git a/frame/fee-market/src/s2s/callbacks.rs b/frame/fee-market/src/s2s/callbacks.rs index d320391226..e4b3b1c3f5 100644 --- a/frame/fee-market/src/s2s/callbacks.rs +++ b/frame/fee-market/src/s2s/callbacks.rs @@ -30,11 +30,16 @@ impl OnMessageAccepted for FeeMarketMessageAcceptedHandler { // Create a new order based on the latest block, assign relayers which have priority to relaying let now = frame_system::Pallet::::block_number(); if let Some(assigned_relayers) = >::assigned_relayers() { - let order = Order::new(*lane, *message, now, assigned_relayers, T::Slot::get()); + let order = Order::new( + *lane, + *message, + now, + T::CollateralPerOrder::get(), + assigned_relayers, + T::Slot::get(), + ); // Store the create order >::insert((order.lane, order.message), order.clone()); - // Update relayer orders and order_capacity - Pallet::::relayer_accept_order(&order); } // TODO: The returned weight should be more accurately. See: https://github.com/darwinia-network/darwinia-common/issues/911 diff --git a/frame/fee-market/src/s2s/payment.rs b/frame/fee-market/src/s2s/payment.rs index ff9bef9443..42e8f3a7ce 100644 --- a/frame/fee-market/src/s2s/payment.rs +++ b/frame/fee-market/src/s2s/payment.rs @@ -168,9 +168,6 @@ where // 20% * (1 - 60%) * lowest_fee => confirm relayer confirm_reward = T::ConfirmRelayersRewardRatio::get() * bridger_relayers_reward; - - // The order is confirmed in time, recover relayer order capacity - Pallet::::relayer_finish_order(&order); } else { // The message is delivered by common relayer instead of order assigned relayers, all assigned relayers of this order should be slash. // Total slash = message fee + assigned_relayers slash @@ -179,7 +176,11 @@ where let mut assigned_relayers_slash = RingBalance::::zero(); for assigned_relayer in order.relayers_slice() { - let slashed = do_slash::(&assigned_relayer.id, relayer_fund_account); + let slashed = do_slash::( + &assigned_relayer.id, + relayer_fund_account, + order.locked_collateral, + ); assigned_relayers_slash += slashed; } @@ -215,9 +216,9 @@ where pub fn do_slash( slash_account: &T::AccountId, fund_account: &T::AccountId, + slash_value: RingBalance, ) -> RingBalance { let locked_collateral = crate::Pallet::::relayer(&slash_account).collateral; - let slash_value = T::CollateralPerOrder::get(); T::RingCurrency::remove_lock(T::LockId::get(), &slash_account); debug_assert!( locked_collateral >= slash_value, diff --git a/frame/fee-market/src/tests.rs b/frame/fee-market/src/tests.rs index cb6d0f93b5..4e7655cf70 100644 --- a/frame/fee-market/src/tests.rs +++ b/frame/fee-market/src/tests.rs @@ -536,7 +536,6 @@ fn test_call_relayer_enroll_works() { assert_eq!(Ring::free_balance(1), 150); assert_eq!(Ring::usable_balance(&1), 50); assert_eq!(FeeMarket::relayer(&1).collateral, 100); - assert_eq!(FeeMarket::relayer(1).order_capacity, 1); assert_eq!(FeeMarket::market_fee(), None); assert_err!( FeeMarket::enroll_and_lock_collateral(Origin::signed(1), 100, None), @@ -548,7 +547,6 @@ fn test_call_relayer_enroll_works() { 250, None )); - assert_eq!(FeeMarket::relayer(3).order_capacity, 2); assert_ok!(FeeMarket::enroll_and_lock_collateral( Origin::signed(4), @@ -568,36 +566,25 @@ fn test_call_relayer_increase_lock_collateral_works() { let _ = FeeMarket::enroll_and_lock_collateral(Origin::signed(12), 200, None); assert_eq!(FeeMarket::relayer(&12).collateral, 200); - assert_eq!(FeeMarket::relayer(12).order_capacity, 2); // Increase locked balance from 200 to 500 assert_ok!(FeeMarket::update_locked_collateral(Origin::signed(12), 500)); assert_eq!(FeeMarket::relayer(&12).collateral, 500); - assert_eq!(FeeMarket::relayer(12).order_capacity, 5); // Increase locked balance from 20 to 200 let _ = FeeMarket::enroll_and_lock_collateral(Origin::signed(13), 20, None); - assert_eq!(FeeMarket::relayer(13).order_capacity, 0); assert_ok!(FeeMarket::update_locked_collateral(Origin::signed(13), 200)); - assert_eq!(FeeMarket::relayer(13).order_capacity, 2); let _ = FeeMarket::enroll_and_lock_collateral(Origin::signed(14), 300, None); - assert_eq!(FeeMarket::relayer(14).order_capacity, 3); let market_fee = FeeMarket::market_fee().unwrap(); let _ = send_regular_message(market_fee); let _ = send_regular_message(market_fee); - assert_eq!(FeeMarket::relayer(12).order_capacity, 3); - assert_eq!(FeeMarket::relayer(13).order_capacity, 0); - assert_eq!(FeeMarket::relayer(14).order_capacity, 1); assert_ok!(FeeMarket::update_locked_collateral(Origin::signed(12), 800)); assert_ok!(FeeMarket::update_locked_collateral(Origin::signed(13), 800)); assert_ok!(FeeMarket::update_locked_collateral(Origin::signed(14), 800)); assert_eq!(FeeMarket::relayer(&12).collateral, 800); assert_eq!(FeeMarket::relayer(&13).collateral, 800); assert_eq!(FeeMarket::relayer(&14).collateral, 800); - assert_eq!(FeeMarket::relayer(12).order_capacity, 6); - assert_eq!(FeeMarket::relayer(13).order_capacity, 6); - assert_eq!(FeeMarket::relayer(14).order_capacity, 6); }); } @@ -619,13 +606,10 @@ fn test_call_relayer_decrease_lock_collateral_works() { ); assert_ok!(FeeMarket::update_locked_collateral(Origin::signed(12), 400)); assert_eq!(FeeMarket::relayer(&12).collateral, 400); - assert_eq!(FeeMarket::relayer(12).order_capacity, 0); assert_ok!(FeeMarket::update_locked_collateral(Origin::signed(13), 500)); assert_eq!(FeeMarket::relayer(&13).collateral, 500); - assert_eq!(FeeMarket::relayer(13).order_capacity, 1); assert_ok!(FeeMarket::update_locked_collateral(Origin::signed(14), 700)); assert_eq!(FeeMarket::relayer(&14).collateral, 700); - assert_eq!(FeeMarket::relayer(14).order_capacity, 3); }); } @@ -654,9 +638,9 @@ fn test_call_relayer_cancel_registration_works() { assert_eq!( FeeMarket::assigned_relayers().unwrap(), vec![ - Relayer::::new(1, 100, 30, 1), - Relayer::::new(2, 110, 50, 1), - Relayer::::new(3, 120, 100, 1), + Relayer::::new(1, 100, 30), + Relayer::::new(2, 110, 50), + Relayer::::new(3, 120, 100), ] ); let _ = send_regular_message(FeeMarket::market_fee().unwrap()); @@ -739,9 +723,9 @@ fn test_rpc_market_fee_works() { assert_eq!( FeeMarket::assigned_relayers().unwrap(), vec![ - Relayer::::new(1, 100, 30, 1), - Relayer::::new(3, 200, 40, 2), - Relayer::::new(4, 120, 40, 1), + Relayer::::new(1, 100, 30), + Relayer::::new(3, 200, 40), + Relayer::::new(4, 120, 40), ] ); }); @@ -788,19 +772,13 @@ fn test_callback_order_creation() { let _ = FeeMarket::enroll_and_lock_collateral(Origin::signed(1), 100, Some(30)); let _ = FeeMarket::enroll_and_lock_collateral(Origin::signed(2), 110, Some(50)); let _ = FeeMarket::enroll_and_lock_collateral(Origin::signed(3), 120, Some(100)); - assert_eq!(FeeMarket::relayer(&1).order_capacity, 1); - assert_eq!(FeeMarket::relayer(&2).order_capacity, 1); - assert_eq!(FeeMarket::relayer(&3).order_capacity, 1); System::set_block_number(2); let assigned_relayers = FeeMarket::assigned_relayers().unwrap(); let market_fee = FeeMarket::market_fee().unwrap(); let (lane, message_nonce) = send_regular_message(market_fee); - assert_eq!(FeeMarket::relayer(&1).order_capacity, 0); - assert_eq!(FeeMarket::relayer(&2).order_capacity, 0); - assert_eq!(FeeMarket::relayer(&3).order_capacity, 0); - assert!(FeeMarket::market_fee().is_none()); - assert!(FeeMarket::assigned_relayers().is_none()); + assert!(FeeMarket::market_fee().is_some()); + assert!(FeeMarket::assigned_relayers().is_some()); let order = FeeMarket::order((&lane, &message_nonce)).unwrap(); let relayers = order.relayers_slice(); @@ -839,9 +817,6 @@ fn test_callback_order_confirm() { let _ = FeeMarket::enroll_and_lock_collateral(Origin::signed(3), 120, Some(100)); let market_fee = FeeMarket::market_fee().unwrap(); let (lane, message_nonce) = send_regular_message(market_fee); - assert_eq!(FeeMarket::relayer(&1).order_capacity, 0); - assert_eq!(FeeMarket::relayer(&2).order_capacity, 0); - assert_eq!(FeeMarket::relayer(&3).order_capacity, 0); let order = FeeMarket::order((&lane, &message_nonce)).unwrap(); assert_eq!(order.confirm_time, None); @@ -850,9 +825,6 @@ fn test_callback_order_confirm() { let order = FeeMarket::order((&lane, &message_nonce)).unwrap(); assert_eq!(order.confirm_time, Some(4)); assert_eq!(>::get().len(), 1); - assert_eq!(FeeMarket::relayer(&1).order_capacity, 1); - assert_eq!(FeeMarket::relayer(&2).order_capacity, 1); - assert_eq!(FeeMarket::relayer(&3).order_capacity, 1); assert!(FeeMarket::market_fee().is_some()); assert!(FeeMarket::assigned_relayers().is_some()); }); @@ -1030,10 +1002,8 @@ fn test_payment_with_slash_and_remove_enroll() { let _ = FeeMarket::enroll_and_lock_collateral(Origin::signed(2), 110, Some(50)); let _ = FeeMarket::enroll_and_lock_collateral(Origin::signed(3), 120, Some(100)); assert_eq!(FeeMarket::relayer(&1).collateral, 100); - assert_eq!(FeeMarket::relayer(&1).order_capacity, 1); let market_fee = FeeMarket::market_fee().unwrap(); let (_, _) = send_regular_message(market_fee); - assert_eq!(FeeMarket::relayer(&1).order_capacity, 0); // Receive delivery message proof System::set_block_number(200); @@ -1074,10 +1044,8 @@ fn test_payment_with_slash_and_reduce_order_capacity() { let _ = FeeMarket::enroll_and_lock_collateral(Origin::signed(7), 400, Some(50)); let _ = FeeMarket::enroll_and_lock_collateral(Origin::signed(8), 400, Some(100)); assert_eq!(FeeMarket::relayer(&6).collateral, 400); - assert_eq!(FeeMarket::relayer(&6).order_capacity, 4); let market_fee = FeeMarket::market_fee().unwrap(); let (_, _) = send_regular_message(market_fee); - assert_eq!(FeeMarket::relayer(&6).order_capacity, 3); // Receive delivery message proof System::set_block_number(200); @@ -1104,9 +1072,6 @@ fn test_payment_with_slash_and_reduce_order_capacity() { assert_eq!(FeeMarket::relayer(&6).collateral, 300); assert_eq!(FeeMarket::relayer(&7).collateral, 300); assert_eq!(FeeMarket::relayer(&8).collateral, 300); - assert_eq!(FeeMarket::relayer(&6).order_capacity, 3); - assert_eq!(FeeMarket::relayer(&7).order_capacity, 3); - assert_eq!(FeeMarket::relayer(&8).order_capacity, 3); assert!(TestMessageDeliveryAndDispatchPayment::is_reward_paid(5, 80)); assert!(TestMessageDeliveryAndDispatchPayment::is_reward_paid( TEST_RELAYER_A, @@ -1268,12 +1233,12 @@ fn test_relayer_is_occupied() { let _ = send_regular_message(market_fee); let _ = send_regular_message(market_fee); - assert_eq!(FeeMarket::is_occupied(&5), Some(2)); - assert_eq!(FeeMarket::is_occupied(&6), Some(2)); - assert_eq!(FeeMarket::is_occupied(&7), Some(2)); + assert_eq!(FeeMarket::occupied(&5), Some((2, 200))); + assert_eq!(FeeMarket::occupied(&6), Some((2, 200))); + assert_eq!(FeeMarket::occupied(&7), Some((2, 200))); receive_messages_delivery_proof(); - assert_eq!(FeeMarket::is_occupied(&5), Some(1)); - assert_eq!(FeeMarket::is_occupied(&6), Some(1)); - assert_eq!(FeeMarket::is_occupied(&7), Some(1)); + assert_eq!(FeeMarket::occupied(&5), Some((1, 100))); + assert_eq!(FeeMarket::occupied(&6), Some((1, 100))); + assert_eq!(FeeMarket::occupied(&7), Some((1, 100))); }); } diff --git a/node/runtime/pangolin/types.json b/node/runtime/pangolin/types.json index 1aa6a79c04..156af94d19 100644 --- a/node/runtime/pangolin/types.json +++ b/node/runtime/pangolin/types.json @@ -256,8 +256,7 @@ "Relayer": { "id": "AccountId", "collateral": "Balance", - "fee": "Balance", - "order_capacity":"u32" + "fee": "Balance" }, "Fee": "Balance", "Order": { From 7edd4e566bcee9268e39c933961ce9d489723556 Mon Sep 17 00:00:00 2001 From: ouwenkg <2630582710@qq.com> Date: Thu, 11 Nov 2021 15:10:19 +0800 Subject: [PATCH 30/46] Update comments --- frame/fee-market/src/lib.rs | 8 ++++---- frame/fee-market/src/s2s/payment.rs | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/frame/fee-market/src/lib.rs b/frame/fee-market/src/lib.rs index acdda1597b..afead2d1fb 100644 --- a/frame/fee-market/src/lib.rs +++ b/frame/fee-market/src/lib.rs @@ -312,10 +312,10 @@ pub mod pallet { impl Pallet { /// An important update in this pallet, need to update market information in the following cases: /// - /// - When new relayer enroll. - /// - When enrolled relayer wants to update fee or order capacity. - /// - When enrolled relayer wants to cancel enrollment. - /// - All order assigned relayers's order capacity sub 1 in `on_messages_accepted()` and add 1 in `on_messages_delivered`. + /// - New relayer enroll. + /// - The enrolled relayer wants to update fee or order capacity. + /// - The enrolled relayer wants to cancel enrollment. + /// - The order didn't confirm in-time, slash occurred. pub(crate) fn update_market() { // Sort all enrolled relayers who are able to accept orders. let mut relayers: Vec>> = >::get() diff --git a/frame/fee-market/src/s2s/payment.rs b/frame/fee-market/src/s2s/payment.rs index 42e8f3a7ce..24d9a2da40 100644 --- a/frame/fee-market/src/s2s/payment.rs +++ b/frame/fee-market/src/s2s/payment.rs @@ -171,7 +171,7 @@ where } else { // The message is delivered by common relayer instead of order assigned relayers, all assigned relayers of this order should be slash. // Total slash = message fee + assigned_relayers slash - // For each assigned relayer, slash CollateralPerOrder per order, then order capacity will decrease by 1. + // For each assigned relayer, slash CollateralPerOrder per order let mut total_slash = message_fee; let mut assigned_relayers_slash = RingBalance::::zero(); From b5fc958cb8bce90355734009e99e2cae6f9f76b0 Mon Sep 17 00:00:00 2001 From: ouwenkg <2630582710@qq.com> Date: Thu, 11 Nov 2021 16:45:59 +0800 Subject: [PATCH 31/46] Add data migration and update json type --- Cargo.lock | 1 + node/runtime/pangolin/src/lib.rs | 35 ++++++++++++++++++++++++++-- node/runtime/pangolin/types.json | 1 + node/runtime/pangoro/Cargo.toml | 2 ++ node/runtime/pangoro/src/lib.rs | 40 ++++++++++++++++++++++++++++---- 5 files changed, 73 insertions(+), 6 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index e4fb451207..c668d75c3a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -6227,6 +6227,7 @@ dependencies = [ "darwinia-staking", "darwinia-support", "dp-asset", + "dp-fee", "dp-s2s", "frame-benchmarking", "frame-executive", diff --git a/node/runtime/pangolin/src/lib.rs b/node/runtime/pangolin/src/lib.rs index 3eb8dd49df..470575379b 100644 --- a/node/runtime/pangolin/src/lib.rs +++ b/node/runtime/pangolin/src/lib.rs @@ -792,23 +792,54 @@ impl dvm_rpc_runtime_api::ConvertTransaction for TransactionCon #[allow(unused)] fn migrate() -> Weight { + use dp_fee::Relayer; // TODO: Move to S2S // const CrabBackingPalletId: PalletId = PalletId(*b"da/crabk"); // const CrabIssuingPalletId: PalletId = PalletId(*b"da/crais"); + log::info!("Start migrate all storage items in AssignedRelayersStorage"); + if let Some(value) = migration::take_storage_value::>>( + b"FeeMarket", + b"AssignedRelayersStorage", + &[], + ) { + log::info!("the migrate content {:?}", value); + migration::put_storage_value(b"FeeMarket", b"AssignedRelayers", &[], value); + } + log::info!("Migrate finished"); - 0 - // RuntimeBlockWeights::get().max_block + // 0 + RuntimeBlockWeights::get().max_block } pub struct CustomOnRuntimeUpgrade; impl OnRuntimeUpgrade for CustomOnRuntimeUpgrade { #[cfg(feature = "try-runtime")] fn pre_upgrade() -> Result<(), &'static str> { + assert!(migration::have_storage_value( + b"FeeMarket", + b"AssignedRelayersStorage", + &[] + )); + assert!(!migration::have_storage_value( + b"FeeMarket", + b"AssignedRelayers", + &[] + )); Ok(()) } #[cfg(feature = "try-runtime")] fn post_upgrade() -> Result<(), &'static str> { + assert!(!migration::have_storage_value( + b"FeeMarket", + b"AssignedRelayersStorage", + &[] + )); + assert!(migration::have_storage_value( + b"FeeMarket", + b"AssignedRelayers", + &[] + )); Ok(()) } diff --git a/node/runtime/pangolin/types.json b/node/runtime/pangolin/types.json index 156af94d19..098aa610e9 100644 --- a/node/runtime/pangolin/types.json +++ b/node/runtime/pangolin/types.json @@ -264,6 +264,7 @@ "message": "MessageNonce", "sent_time": "BlockNumber", "confirm_time": "BlockNumber", + "locked_collateral": "Balance", "assigned_relayers": "Vec" }, "PriorRelayer": { diff --git a/node/runtime/pangoro/Cargo.toml b/node/runtime/pangoro/Cargo.toml index 7da9dcd271..9c5d97a03d 100644 --- a/node/runtime/pangoro/Cargo.toml +++ b/node/runtime/pangoro/Cargo.toml @@ -24,6 +24,7 @@ darwinia-fee-market-rpc-runtime-api = { default-features = false, path = "../../ darwinia-staking = { default-features = false, path = "../../../frame/staking" } darwinia-support = { default-features = false, path = "../../../frame/support" } dp-asset = { default-features = false, path = "../../../primitives/asset" } +dp-fee = { default-features = false, path = "../../../primitives/fee-market" } dp-s2s = { default-features = false, path = "../../../primitives/s2s" } pangolin-constants = { default-features = false, path = "../pangolin/src/constants" } pangolin-runtime-system-params = { default-features = false, path = "../pangolin/src/pallets/system/params" } @@ -99,6 +100,7 @@ std = [ "darwinia-staking/std", "darwinia-support/std", "dp-asset/std", + "dp-fee/std", "dp-s2s/std", "pangolin-constants/std", "pangolin-runtime-system-params/std", diff --git a/node/runtime/pangoro/src/lib.rs b/node/runtime/pangoro/src/lib.rs index 8cb8362bf6..b5ab68ed68 100644 --- a/node/runtime/pangoro/src/lib.rs +++ b/node/runtime/pangoro/src/lib.rs @@ -72,6 +72,8 @@ use codec::{Decode, Encode}; use bridge_runtime_common::messages::{ source::estimate_message_dispatch_and_delivery_fee, MessageBridge, }; +#[allow(unused)] +use frame_support::migration; use frame_support::{ traits::{KeyOwnerProofSystem, OnRuntimeUpgrade}, weights::Weight, @@ -536,22 +538,52 @@ sp_api::impl_runtime_apis! { #[allow(unused)] fn migrate() -> Weight { // --- paritytech --- - #[allow(unused)] - use frame_support::migration; + use dp_fee::Relayer; + + log::info!("Start migrate all storage items in AssignedRelayersStorage"); + if let Some(value) = migration::take_storage_value::>>( + b"FeeMarket", + b"AssignedRelayersStorage", + &[], + ) { + log::info!("the migrate content {:?}", value); + migration::put_storage_value(b"FeeMarket", b"AssignedRelayers", &[], value); + } + log::info!("Migrate finished"); - 0 - // RuntimeBlockWeights::get().max_block + // 0 + RuntimeBlockWeights::get().max_block } pub struct CustomOnRuntimeUpgrade; impl OnRuntimeUpgrade for CustomOnRuntimeUpgrade { #[cfg(feature = "try-runtime")] fn pre_upgrade() -> Result<(), &'static str> { + assert!(migration::have_storage_value( + b"FeeMarket", + b"AssignedRelayersStorage", + &[] + )); + assert!(!migration::have_storage_value( + b"FeeMarket", + b"AssignedRelayers", + &[] + )); Ok(()) } #[cfg(feature = "try-runtime")] fn post_upgrade() -> Result<(), &'static str> { + assert!(!migration::have_storage_value( + b"FeeMarket", + b"AssignedRelayersStorage", + &[] + )); + assert!(migration::have_storage_value( + b"FeeMarket", + b"AssignedRelayers", + &[] + )); Ok(()) } From be9a7bb99c97e0af81d789471afe01196b7c708b Mon Sep 17 00:00:00 2001 From: ouwenkg <2630582710@qq.com> Date: Thu, 11 Nov 2021 17:31:23 +0800 Subject: [PATCH 32/46] Update docs --- frame/fee-market/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/frame/fee-market/README.md b/frame/fee-market/README.md index fe97a05979..4aa43d239f 100644 --- a/frame/fee-market/README.md +++ b/frame/fee-market/README.md @@ -26,7 +26,7 @@ For simplicity, if count of relayers in current market are less than MIN_ASSIGNE ### Detailed Steps in Implementation 1. Enroll and lock collateral - 1. `enroll_and_lock_collateral` dispatch call + 1. `enroll_and_lock_collateral` dispatch call, this lock collateral will be distributed to order it accepted. 2. `cancel_enrollment()` dispatch call, remember to check if the relayer is in priority time slots. 2. Ask price We use simple constant price function for messages currently: fn(message) = const_price * 1 where const_price means fee per message. We might later improve this fn(message) with [relayer defined fee functions](https://github.com/darwinia-network/darwinia-common/issues/813). @@ -38,7 +38,7 @@ For simplicity, if count of relayers in current market are less than MIN_ASSIGNE 4. Message delivery and confirmed by bridger. 5. Reward and Slash Strategy. 1. If the order is confirmed in Rn's slot, then Rn can claim 60% from the reward P1, and message relayer can claim 80% * (1 - 60%) from P1, confirm relayer can claim 20% * (1 - 60%) from P1, (P3 - P1) will go to treasury. - 2. If the order is confirmed beyond all assigned relayers slot, and then The reward will be S(t) where S(t) > P3, the part S(t) - P3 comes from funds slashed from R1, R2, R3's collateral. Message relayer can claim 80% from S(t), confirm relayer can claim 20% from S(t). + 2. If the order is confirmed beyond all assigned relayers slot, and then The reward(R) consist of two parts, P3 and `CollaterPerOrder`. The `CollaterPerOrder` comes from each assigned relayer for this order was configure in the runtime. Message relayer can claim 80% from R, confirm relayer can claim 20% from R. Note: The ratio parameters in the strategy can be defined in runtime, and there might be update to them for refinement after more benchmark and statistics. From 76ed9161c159fdf857a0e52636848dd09251c635 Mon Sep 17 00:00:00 2001 From: ouwenkg <2630582710@qq.com> Date: Thu, 11 Nov 2021 17:34:41 +0800 Subject: [PATCH 33/46] Fix typo --- frame/fee-market/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/frame/fee-market/README.md b/frame/fee-market/README.md index 4aa43d239f..a455d14f5d 100644 --- a/frame/fee-market/README.md +++ b/frame/fee-market/README.md @@ -26,7 +26,7 @@ For simplicity, if count of relayers in current market are less than MIN_ASSIGNE ### Detailed Steps in Implementation 1. Enroll and lock collateral - 1. `enroll_and_lock_collateral` dispatch call, this lock collateral will be distributed to order it accepted. + 1. `enroll_and_lock_collateral` dispatch call. 2. `cancel_enrollment()` dispatch call, remember to check if the relayer is in priority time slots. 2. Ask price We use simple constant price function for messages currently: fn(message) = const_price * 1 where const_price means fee per message. We might later improve this fn(message) with [relayer defined fee functions](https://github.com/darwinia-network/darwinia-common/issues/813). @@ -38,7 +38,7 @@ For simplicity, if count of relayers in current market are less than MIN_ASSIGNE 4. Message delivery and confirmed by bridger. 5. Reward and Slash Strategy. 1. If the order is confirmed in Rn's slot, then Rn can claim 60% from the reward P1, and message relayer can claim 80% * (1 - 60%) from P1, confirm relayer can claim 20% * (1 - 60%) from P1, (P3 - P1) will go to treasury. - 2. If the order is confirmed beyond all assigned relayers slot, and then The reward(R) consist of two parts, P3 and `CollaterPerOrder`. The `CollaterPerOrder` comes from each assigned relayer for this order was configure in the runtime. Message relayer can claim 80% from R, confirm relayer can claim 20% from R. + 2. If the order is confirmed beyond all assigned relayers slot, and then The reward(R) consists of two parts, P3 and `CollaterPerOrder`. The `CollaterPerOrder` comes from each assigned relayer for this order was configure in the runtime. Message relayer can claim 80% from R, confirm relayer can claim 20% from R. Note: The ratio parameters in the strategy can be defined in runtime, and there might be update to them for refinement after more benchmark and statistics. From 6d137878cf01cc771a241348e4a8fbc939c097bf Mon Sep 17 00:00:00 2001 From: ouwenkg <2630582710@qq.com> Date: Thu, 11 Nov 2021 18:17:59 +0800 Subject: [PATCH 34/46] No need to remove slashed relayer --- frame/fee-market/src/lib.rs | 5 ----- frame/fee-market/src/tests.rs | 42 ----------------------------------- 2 files changed, 47 deletions(-) diff --git a/frame/fee-market/src/lib.rs b/frame/fee-market/src/lib.rs index afead2d1fb..a9699d5cbc 100644 --- a/frame/fee-market/src/lib.rs +++ b/frame/fee-market/src/lib.rs @@ -352,11 +352,6 @@ impl Pallet { relayer.collateral = new_collateral; }); - if Self::usable_order_capacity(&who) == 0 { - Self::remove_enrolled_relayer(who); - return; - } - Self::update_market(); } diff --git a/frame/fee-market/src/tests.rs b/frame/fee-market/src/tests.rs index 4e7655cf70..bc29db18ae 100644 --- a/frame/fee-market/src/tests.rs +++ b/frame/fee-market/src/tests.rs @@ -993,48 +993,6 @@ fn test_payment_cal_reward_with_duplicated_delivery_proof() { }); } -#[test] -fn test_payment_with_slash_and_remove_enroll() { - new_test_ext().execute_with(|| { - // Send message - System::set_block_number(2); - let _ = FeeMarket::enroll_and_lock_collateral(Origin::signed(1), 100, Some(30)); - let _ = FeeMarket::enroll_and_lock_collateral(Origin::signed(2), 110, Some(50)); - let _ = FeeMarket::enroll_and_lock_collateral(Origin::signed(3), 120, Some(100)); - assert_eq!(FeeMarket::relayer(&1).collateral, 100); - let market_fee = FeeMarket::market_fee().unwrap(); - let (_, _) = send_regular_message(market_fee); - - // Receive delivery message proof - System::set_block_number(200); - assert_ok!(Messages::receive_messages_delivery_proof( - Origin::signed(5), - TestMessagesDeliveryProof(Ok(( - TEST_LANE_ID, - InboundLaneData { - relayers: vec![unrewarded_relayer(1, 1, TEST_RELAYER_A)] - .into_iter() - .collect(), - ..Default::default() - } - ))), - UnrewardedRelayersState { - unrewarded_relayer_entries: 1, - total_messages: 1, - ..Default::default() - }, - )); - assert!(!FeeMarket::is_enrolled(&1)); - assert!(!FeeMarket::is_enrolled(&2)); - assert!(!FeeMarket::is_enrolled(&3)); - assert!(TestMessageDeliveryAndDispatchPayment::is_reward_paid(5, 80)); - assert!(TestMessageDeliveryAndDispatchPayment::is_reward_paid( - TEST_RELAYER_A, - 320 - )); - }); -} - #[test] fn test_payment_with_slash_and_reduce_order_capacity() { new_test_ext().execute_with(|| { From 4f59e384b17becc46faea700e9f9a82c472bb20a Mon Sep 17 00:00:00 2001 From: ouwenkg <2630582710@qq.com> Date: Fri, 12 Nov 2021 09:33:27 +0800 Subject: [PATCH 35/46] Revert to the original event --- frame/fee-market/src/lib.rs | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/frame/fee-market/src/lib.rs b/frame/fee-market/src/lib.rs index a9699d5cbc..0edb3724ee 100644 --- a/frame/fee-market/src/lib.rs +++ b/frame/fee-market/src/lib.rs @@ -104,8 +104,10 @@ pub mod pallet { pub enum Event { /// Relayer enrollment Enroll(T::AccountId, RingBalance, Fee), - /// Update relayer - UpdateRelayer(T::AccountId, Option>, Option>), + /// Update relayer locked collateral + UpdateLockedCollateral(T::AccountId, RingBalance), + /// Update relayer fee + UpdateRelayFee(T::AccountId, Fee), /// Relayer cancel enrollment CancelEnrollment(T::AccountId), } @@ -263,11 +265,7 @@ pub mod pallet { relayer.collateral = new_collateral; }); Self::update_market(); - Self::deposit_event(Event::::UpdateRelayer( - who.clone(), - Some(new_collateral), - None, - )); + Self::deposit_event(Event::::UpdateLockedCollateral(who, new_collateral)); Ok(().into()) } @@ -290,7 +288,7 @@ pub mod pallet { }); Self::update_market(); - Self::deposit_event(Event::::UpdateRelayer(who, None, Some(new_fee))); + Self::deposit_event(Event::::UpdateRelayFee(who, new_fee)); Ok(().into()) } From 348814ee19215f3879995ba38c56934e457ecb85 Mon Sep 17 00:00:00 2001 From: ouwenkg <2630582710@qq.com> Date: Fri, 12 Nov 2021 09:40:27 +0800 Subject: [PATCH 36/46] Remove Fee --- frame/fee-market/src/lib.rs | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/frame/fee-market/src/lib.rs b/frame/fee-market/src/lib.rs index 0edb3724ee..dd82cf5423 100644 --- a/frame/fee-market/src/lib.rs +++ b/frame/fee-market/src/lib.rs @@ -50,9 +50,8 @@ use darwinia_support::{ use dp_fee::{Order, Relayer}; pub type RingBalance = <::RingCurrency as Currency>>::Balance; -pub type Fee = RingBalance; - pub use pallet::*; + #[frame_support::pallet] pub mod pallet { use super::*; @@ -69,7 +68,7 @@ pub mod pallet { /// The minimum fee for relaying. #[pallet::constant] - type MinimumRelayFee: Get>; + type MinimumRelayFee: Get>; /// The assigned relayers number for each order. #[pallet::constant] type AssignedRelayersNumber: Get; @@ -99,15 +98,14 @@ pub mod pallet { #[pallet::metadata( T::AccountId = "AccountId", RingBalance = "RingBalance", - Fee = "Fee" )] pub enum Event { /// Relayer enrollment - Enroll(T::AccountId, RingBalance, Fee), + Enroll(T::AccountId, RingBalance, RingBalance), /// Update relayer locked collateral UpdateLockedCollateral(T::AccountId, RingBalance), /// Update relayer fee - UpdateRelayFee(T::AccountId, Fee), + UpdateRelayFee(T::AccountId, RingBalance), /// Relayer cancel enrollment CancelEnrollment(T::AccountId), } @@ -157,7 +155,7 @@ pub mod pallet { _, Blake2_128Concat, (LaneId, MessageNonce), - Order>, + Order>, OptionQuery, >; #[pallet::storage] @@ -187,7 +185,7 @@ pub mod pallet { pub fn enroll_and_lock_collateral( origin: OriginFor, lock_collateral: RingBalance, - relay_fee: Option>, + relay_fee: Option>, ) -> DispatchResultWithPostInfo { let who = ensure_signed(origin)?; ensure!(!Self::is_enrolled(&who), >::AlreadyEnrolled); @@ -274,7 +272,7 @@ pub mod pallet { #[transactional] pub fn update_relay_fee( origin: OriginFor, - new_fee: Fee, + new_fee: RingBalance, ) -> DispatchResultWithPostInfo { let who = ensure_signed(origin)?; ensure!(Self::is_enrolled(&who), >::NotEnrolled); @@ -373,7 +371,7 @@ impl Pallet { } /// Get market fee, If there is not enough relayers have order capacity to accept new order, return None. - pub fn market_fee() -> Option> { + pub fn market_fee() -> Option> { Self::assigned_relayers().and_then(|relayers| relayers.last().map(|r| r.fee)) } From 7aa6d50126caece4fcd22fe01b4874d976ac8657 Mon Sep 17 00:00:00 2001 From: ouwenkg <2630582710@qq.com> Date: Fri, 12 Nov 2021 12:01:17 +0800 Subject: [PATCH 37/46] Add orders data migration --- node/runtime/pangolin/src/lib.rs | 44 ++++++++++++++++++++++++++++++-- node/runtime/pangoro/src/lib.rs | 44 +++++++++++++++++++++++++++++--- primitives/fee-market/src/lib.rs | 4 +-- 3 files changed, 85 insertions(+), 7 deletions(-) diff --git a/node/runtime/pangolin/src/lib.rs b/node/runtime/pangolin/src/lib.rs index c24769362f..5c6b87031d 100644 --- a/node/runtime/pangolin/src/lib.rs +++ b/node/runtime/pangolin/src/lib.rs @@ -804,7 +804,11 @@ fn migrate() -> Weight { // TODO: Move to S2S // const CrabBackingPalletId: PalletId = PalletId(*b"da/crabk"); // const CrabIssuingPalletId: PalletId = PalletId(*b"da/crais"); - log::info!("Start migrate all storage items in AssignedRelayersStorage"); + use bp_messages::{LaneId, MessageNonce}; + use dp_fee::{Order, PriorRelayer}; + use frame_support::{Blake2_128Concat, StorageHasher}; + + log::info!("===> Start migrate all storage items in AssignedRelayersStorage"); if let Some(value) = migration::take_storage_value::>>( b"FeeMarket", b"AssignedRelayersStorage", @@ -813,7 +817,32 @@ fn migrate() -> Weight { log::info!("the migrate content {:?}", value); migration::put_storage_value(b"FeeMarket", b"AssignedRelayers", &[], value); } - log::info!("Migrate finished"); + log::info!("===> End migrate all storage items in AssignedRelayersStorage"); + + log::info!("===> Start migrate all storage items in Orders"); + #[derive(Encode, Decode, Debug, Clone)] + struct OldOrder { + lane: LaneId, + message: MessageNonce, + sent_time: BlockNumber, + confirm_time: Option, + relayers: Vec>, + } + for (index, order) in migration::storage_iter::(b"FeeMarket", b"Orders").drain() { + let new_order = Order { + lane: order.lane, + message: order.message, + sent_time: order.sent_time, + confirm_time: order.confirm_time, + locked_collateral: 100 * COIN, + relayers: order.relayers, + }; + log::info!("The new order: order {:?}", new_order); + let hash = Blake2_128Concat::hash(&(new_order.lane, new_order.message).encode()); + migration::put_storage_value(b"FeeMarket", b"Orders", &hash, new_order); + } + log::info!("===> End migrate all storage items in Orders"); + log::info!("===> All Migrates finished"); // 0 RuntimeBlockWeights::get().max_block @@ -838,6 +867,7 @@ impl OnRuntimeUpgrade for CustomOnRuntimeUpgrade { #[cfg(feature = "try-runtime")] fn post_upgrade() -> Result<(), &'static str> { + use dp_fee::Order; assert!(!migration::have_storage_value( b"FeeMarket", b"AssignedRelayersStorage", @@ -848,6 +878,16 @@ impl OnRuntimeUpgrade for CustomOnRuntimeUpgrade { b"AssignedRelayers", &[] )); + + for (_index, new_order) in + migration::storage_iter::>( + b"FeeMarket", + b"Orders", + ) + .drain() + { + assert_eq!(new_order.locked_collateral, 100 * COIN); + } Ok(()) } diff --git a/node/runtime/pangoro/src/lib.rs b/node/runtime/pangoro/src/lib.rs index ac400f8256..c46e3a5bab 100644 --- a/node/runtime/pangoro/src/lib.rs +++ b/node/runtime/pangoro/src/lib.rs @@ -547,9 +547,11 @@ sp_api::impl_runtime_apis! { #[allow(unused)] fn migrate() -> Weight { // --- paritytech --- - use dp_fee::Relayer; + use bp_messages::{LaneId, MessageNonce}; + use dp_fee::{Order, PriorRelayer, Relayer}; + use frame_support::{Blake2_128Concat, StorageHasher}; - log::info!("Start migrate all storage items in AssignedRelayersStorage"); + log::info!("===> Start migrate all storage items in AssignedRelayersStorage"); if let Some(value) = migration::take_storage_value::>>( b"FeeMarket", b"AssignedRelayersStorage", @@ -558,7 +560,32 @@ fn migrate() -> Weight { log::info!("the migrate content {:?}", value); migration::put_storage_value(b"FeeMarket", b"AssignedRelayers", &[], value); } - log::info!("Migrate finished"); + log::info!("===> End migrate all storage items in AssignedRelayersStorage"); + + log::info!("===> Start migrate all storage items in Orders"); + #[derive(Encode, Decode, Debug, Clone)] + struct OldOrder { + lane: LaneId, + message: MessageNonce, + sent_time: BlockNumber, + confirm_time: Option, + relayers: Vec>, + } + for (index, order) in migration::storage_iter::(b"FeeMarket", b"Orders").drain() { + let new_order = Order { + lane: order.lane, + message: order.message, + sent_time: order.sent_time, + confirm_time: order.confirm_time, + locked_collateral: 100 * COIN, + relayers: order.relayers, + }; + log::info!("The new order: order {:?}", new_order); + let hash = Blake2_128Concat::hash(&(new_order.lane, new_order.message).encode()); + migration::put_storage_value(b"FeeMarket", b"Orders", &hash, new_order); + } + log::info!("===> End migrate all storage items in Orders"); + log::info!("===> All Migrates finished"); // 0 RuntimeBlockWeights::get().max_block @@ -583,6 +610,7 @@ impl OnRuntimeUpgrade for CustomOnRuntimeUpgrade { #[cfg(feature = "try-runtime")] fn post_upgrade() -> Result<(), &'static str> { + use dp_fee::Order; assert!(!migration::have_storage_value( b"FeeMarket", b"AssignedRelayersStorage", @@ -593,6 +621,16 @@ impl OnRuntimeUpgrade for CustomOnRuntimeUpgrade { b"AssignedRelayers", &[] )); + + for (_index, new_order) in + migration::storage_iter::>( + b"FeeMarket", + b"Orders", + ) + .drain() + { + assert_eq!(new_order.locked_collateral, 100 * COIN); + } Ok(()) } diff --git a/primitives/fee-market/src/lib.rs b/primitives/fee-market/src/lib.rs index 8e82f3f75a..5e9a247d3d 100644 --- a/primitives/fee-market/src/lib.rs +++ b/primitives/fee-market/src/lib.rs @@ -79,7 +79,7 @@ impl Default for Relayer { pub lane: LaneId, pub message: MessageNonce, @@ -174,7 +174,7 @@ where /// Relayers selected by the fee market. Each prior relayer has a valid slot, if the order can finished in time, /// will be rewarded with more percentage. PriorRelayer are responsible for the messages relay in most time. -#[derive(Clone, Encode, Decode, Default)] +#[derive(Clone, Encode, Decode, Default, Debug)] pub struct PriorRelayer { pub id: AccountId, pub fee: Balance, From 7ac1eaa67e401bb9ebbf65ba15b358d4f70c5efe Mon Sep 17 00:00:00 2001 From: ouwenkg <2630582710@qq.com> Date: Fri, 12 Nov 2021 13:31:34 +0800 Subject: [PATCH 38/46] Update type.json --- node/runtime/pangolin/types.json | 1 - 1 file changed, 1 deletion(-) diff --git a/node/runtime/pangolin/types.json b/node/runtime/pangolin/types.json index acfffa73f0..790a519627 100644 --- a/node/runtime/pangolin/types.json +++ b/node/runtime/pangolin/types.json @@ -258,7 +258,6 @@ "collateral": "Balance", "fee": "Balance" }, - "Fee": "Balance", "Order": { "lane": "LaneId", "message": "MessageNonce", From f5d65f7d5909b2865bb8aebaa7cf096b085c9a39 Mon Sep 17 00:00:00 2001 From: ouwenkg <2630582710@qq.com> Date: Fri, 12 Nov 2021 14:34:45 +0800 Subject: [PATCH 39/46] Add `RewardMode` to the fee market --- frame/fee-market/src/benchmarking.rs | 3 ++ frame/fee-market/src/lib.rs | 25 ++++++++++++++++- frame/fee-market/src/s2s/payment.rs | 24 ++++++++-------- frame/fee-market/src/weight.rs | 41 ++++++++++++++++++---------- node/runtime/pangolin/types.json | 6 ++++ primitives/fee-market/src/lib.rs | 6 ++++ 6 files changed, 77 insertions(+), 28 deletions(-) diff --git a/frame/fee-market/src/benchmarking.rs b/frame/fee-market/src/benchmarking.rs index cb6a9f9fc1..fb1ebbe9ee 100644 --- a/frame/fee-market/src/benchmarking.rs +++ b/frame/fee-market/src/benchmarking.rs @@ -105,4 +105,7 @@ benchmarks! { assert!(!>::is_enrolled(&caller1)); assert_eq!(>::relayers().len(), 3); } + + set_operating_mode { + }:set_operating_mode(RawOrigin::Root, RewardMode::NoSlash) } diff --git a/frame/fee-market/src/lib.rs b/frame/fee-market/src/lib.rs index 34f594af15..5211a2604b 100644 --- a/frame/fee-market/src/lib.rs +++ b/frame/fee-market/src/lib.rs @@ -47,7 +47,7 @@ use darwinia_support::{ balance::{LockFor, LockableCurrency}, AccountId, }; -use dp_fee::{Order, Relayer}; +use dp_fee::{Order, Relayer, RewardMode}; pub type RingBalance = <::RingCurrency as Currency>>::Balance; pub use pallet::*; @@ -108,6 +108,8 @@ pub mod pallet { UpdateRelayFee(T::AccountId, RingBalance), /// Relayer cancel enrollment CancelEnrollment(T::AccountId), + /// Change operating mode + UpdateOperatingMode(RewardMode), } #[pallet::error] @@ -162,6 +164,15 @@ pub mod pallet { pub type ConfirmedMessagesThisBlock = StorageValue<_, Vec<(LaneId, MessageNonce)>, ValueQuery>; + #[pallet::storage] + #[pallet::getter(fn reward_mode)] + pub type RewardModeStorage = + StorageValue<_, RewardMode, ValueQuery, DefaultRewardMode>; + #[pallet::type_value] + pub fn DefaultRewardMode() -> RewardMode { + RewardMode::Normal + } + #[pallet::pallet] pub struct Pallet(_); #[pallet::hooks] @@ -302,6 +313,18 @@ pub mod pallet { Self::deposit_event(Event::::CancelEnrollment(who)); Ok(().into()) } + + #[pallet::weight(::WeightInfo::set_reward_mode())] + #[transactional] + pub fn set_reward_mode( + origin: OriginFor, + mode: RewardMode, + ) -> DispatchResultWithPostInfo { + ensure_root(origin)?; + RewardModeStorage::::put(mode); + Self::deposit_event(Event::::UpdateOperatingMode(mode)); + Ok(().into()) + } } } diff --git a/frame/fee-market/src/s2s/payment.rs b/frame/fee-market/src/s2s/payment.rs index 24d9a2da40..bae0dc66ec 100644 --- a/frame/fee-market/src/s2s/payment.rs +++ b/frame/fee-market/src/s2s/payment.rs @@ -169,22 +169,22 @@ where confirm_reward = T::ConfirmRelayersRewardRatio::get() * bridger_relayers_reward; } else { - // The message is delivered by common relayer instead of order assigned relayers, all assigned relayers of this order should be slash. - // Total slash = message fee + assigned_relayers slash - // For each assigned relayer, slash CollateralPerOrder per order + // The order is delayed, slash assigned relayers in operating normal mode. let mut total_slash = message_fee; - let mut assigned_relayers_slash = RingBalance::::zero(); - for assigned_relayer in order.relayers_slice() { - let slashed = do_slash::( - &assigned_relayer.id, - relayer_fund_account, - order.locked_collateral, - ); - assigned_relayers_slash += slashed; + if crate::Pallet::::reward_mode() == RewardMode::NoSlash { + let mut assigned_relayers_slash = RingBalance::::zero(); + for assigned_relayer in order.relayers_slice() { + let slashed = do_slash::( + &assigned_relayer.id, + relayer_fund_account, + order.locked_collateral, + ); + assigned_relayers_slash += slashed; + } + total_slash += assigned_relayers_slash; } - total_slash += assigned_relayers_slash; // 80% total slash => confirm relayer message_reward = T::MessageRelayersRewardRatio::get() * total_slash; // 20% total slash => confirm relayer diff --git a/frame/fee-market/src/weight.rs b/frame/fee-market/src/weight.rs index ab637cb646..0a05876b61 100644 --- a/frame/fee-market/src/weight.rs +++ b/frame/fee-market/src/weight.rs @@ -18,7 +18,7 @@ //! Autogenerated weights for darwinia_fee_market //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 3.0.0 -//! DATE: 2021-11-10, STEPS: [100, ], REPEAT: 50, LOW RANGE: [], HIGH RANGE: [] +//! DATE: 2021-11-12, STEPS: [100, ], REPEAT: 50, LOW RANGE: [], HIGH RANGE: [] //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 128 // Executed Command: @@ -58,53 +58,64 @@ pub trait WeightInfo { fn update_locked_collateral() -> Weight; fn update_relay_fee() -> Weight; fn cancel_enrollment() -> Weight; + fn set_reward_mode() -> Weight; } /// Weights for darwinia_fee_market using the Substrate node and recommended hardware. pub struct SubstrateWeight(PhantomData); impl WeightInfo for SubstrateWeight { fn enroll_and_lock_collateral() -> Weight { - (98_863_000 as Weight) - .saturating_add(T::DbWeight::get().reads(11 as Weight)) + (125_404_000 as Weight) + .saturating_add(T::DbWeight::get().reads(12 as Weight)) .saturating_add(T::DbWeight::get().writes(7 as Weight)) } fn update_locked_collateral() -> Weight { - (90_257_000 as Weight) - .saturating_add(T::DbWeight::get().reads(11 as Weight)) + (111_939_000 as Weight) + .saturating_add(T::DbWeight::get().reads(12 as Weight)) .saturating_add(T::DbWeight::get().writes(5 as Weight)) } fn update_relay_fee() -> Weight { - (62_045_000 as Weight) - .saturating_add(T::DbWeight::get().reads(9 as Weight)) + (89_316_000 as Weight) + .saturating_add(T::DbWeight::get().reads(10 as Weight)) .saturating_add(T::DbWeight::get().writes(4 as Weight)) } fn cancel_enrollment() -> Weight { - (96_118_000 as Weight) + (110_125_000 as Weight) .saturating_add(T::DbWeight::get().reads(12 as Weight)) .saturating_add(T::DbWeight::get().writes(7 as Weight)) } + fn set_reward_mode() -> Weight { + (17_924_000 as Weight) + .saturating_add(T::DbWeight::get().reads(4 as Weight)) + .saturating_add(T::DbWeight::get().writes(3 as Weight)) + } } // For backwards compatibility and tests impl WeightInfo for () { fn enroll_and_lock_collateral() -> Weight { - (98_863_000 as Weight) - .saturating_add(RocksDbWeight::get().reads(11 as Weight)) + (125_404_000 as Weight) + .saturating_add(RocksDbWeight::get().reads(12 as Weight)) .saturating_add(RocksDbWeight::get().writes(7 as Weight)) } fn update_locked_collateral() -> Weight { - (90_257_000 as Weight) - .saturating_add(RocksDbWeight::get().reads(11 as Weight)) + (111_939_000 as Weight) + .saturating_add(RocksDbWeight::get().reads(12 as Weight)) .saturating_add(RocksDbWeight::get().writes(5 as Weight)) } fn update_relay_fee() -> Weight { - (62_045_000 as Weight) - .saturating_add(RocksDbWeight::get().reads(9 as Weight)) + (89_316_000 as Weight) + .saturating_add(RocksDbWeight::get().reads(10 as Weight)) .saturating_add(RocksDbWeight::get().writes(4 as Weight)) } fn cancel_enrollment() -> Weight { - (96_118_000 as Weight) + (110_125_000 as Weight) .saturating_add(RocksDbWeight::get().reads(12 as Weight)) .saturating_add(RocksDbWeight::get().writes(7 as Weight)) } + fn set_reward_mode() -> Weight { + (17_924_000 as Weight) + .saturating_add(RocksDbWeight::get().reads(4 as Weight)) + .saturating_add(RocksDbWeight::get().writes(3 as Weight)) + } } diff --git a/node/runtime/pangolin/types.json b/node/runtime/pangolin/types.json index 790a519627..64ff882edc 100644 --- a/node/runtime/pangolin/types.json +++ b/node/runtime/pangolin/types.json @@ -271,6 +271,12 @@ "fee": "Balance", "valid_range": "BlockNumber" }, + "RewardMode": { + "_enum": { + "Normal": "null", + "NoSlash": "null" + } + }, "__[pangolin.runtime]__": { "ProxyType": { "_enum": { diff --git a/primitives/fee-market/src/lib.rs b/primitives/fee-market/src/lib.rs index 5e9a247d3d..a6a4e24c14 100644 --- a/primitives/fee-market/src/lib.rs +++ b/primitives/fee-market/src/lib.rs @@ -26,6 +26,12 @@ use sp_std::{ vec::Vec, }; +#[derive(Encode, Decode, Clone, Eq, PartialEq, Debug, Copy)] +pub enum RewardMode { + Normal, + NoSlash, +} + /// Relayer who has enrolled the fee market #[derive(Encode, Decode, Clone, Eq, Debug)] pub struct Relayer { From dfdbb80dfd05bf4433af2e00469c974f3b3d303c Mon Sep 17 00:00:00 2001 From: ouwenkg <2630582710@qq.com> Date: Fri, 12 Nov 2021 15:45:30 +0800 Subject: [PATCH 40/46] Support S(t) --- frame/fee-market/src/lib.rs | 2 + frame/fee-market/src/s2s/payment.rs | 40 ++++++++++++++++--- frame/fee-market/src/tests.rs | 6 ++- .../pangolin/src/pallets/fee_market.rs | 2 + .../runtime/pangoro/src/pallets/fee_market.rs | 2 + primitives/fee-market/src/lib.rs | 15 ++++++- 6 files changed, 57 insertions(+), 10 deletions(-) diff --git a/frame/fee-market/src/lib.rs b/frame/fee-market/src/lib.rs index 5211a2604b..5a1f768e50 100644 --- a/frame/fee-market/src/lib.rs +++ b/frame/fee-market/src/lib.rs @@ -75,6 +75,8 @@ pub mod pallet { /// The collateral relayer need to lock for each order. #[pallet::constant] type CollateralPerOrder: Get>; + #[pallet::constant] + type SlashPerBlock: Get>; /// The slot times set #[pallet::constant] type Slot: Get; diff --git a/frame/fee-market/src/s2s/payment.rs b/frame/fee-market/src/s2s/payment.rs index bae0dc66ec..307a04f443 100644 --- a/frame/fee-market/src/s2s/payment.rs +++ b/frame/fee-market/src/s2s/payment.rs @@ -22,7 +22,7 @@ use bp_messages::{ MessageNonce, UnrewardedRelayer, }; use frame_support::traits::{Currency as CurrencyT, ExistenceRequirement, Get}; -use sp_runtime::traits::{AccountIdConversion, Saturating}; +use sp_runtime::traits::{AccountIdConversion, Saturating, UniqueSaturatedInto}; use sp_std::{ collections::{btree_map::BTreeMap, vec_deque::VecDeque}, ops::RangeInclusive, @@ -172,13 +172,17 @@ where // The order is delayed, slash assigned relayers in operating normal mode. let mut total_slash = message_fee; - if crate::Pallet::::reward_mode() == RewardMode::NoSlash { + if crate::Pallet::::reward_mode() == RewardMode::Normal { let mut assigned_relayers_slash = RingBalance::::zero(); for assigned_relayer in order.relayers_slice() { + let slash_value: RingBalance = cal_slash_value::( + order.delivery_delay(), + order.locked_collateral, + ); let slashed = do_slash::( &assigned_relayer.id, relayer_fund_account, - order.locked_collateral, + slash_value, ); assigned_relayers_slash += slashed; } @@ -212,8 +216,23 @@ where } } +pub(crate) fn cal_slash_value( + delay: Option, + locked_collateral: RingBalance, +) -> RingBalance { + let mut slash_value = RingBalance::::zero(); + if let Some(delay_blocks) = delay { + slash_value = UniqueSaturatedInto::::unique_saturated_into(delay_blocks) + .saturating_mul(UniqueSaturatedInto::::unique_saturated_into( + T::SlashPerBlock::get(), + )) + .unique_saturated_into(); + } + sp_std::cmp::min(locked_collateral, slash_value) +} + /// Do slash for absent assigned relayers -pub fn do_slash( +pub(crate) fn do_slash( slash_account: &T::AccountId, fund_account: &T::AccountId, slash_value: RingBalance, @@ -225,12 +244,21 @@ pub fn do_slash( "The locked collateral must alway greater than slash max" ); - let _ = ::RingCurrency::transfer( + let pay_result = ::RingCurrency::transfer( slash_account, fund_account, slash_value, ExistenceRequirement::AllowDeath, ); + match pay_result { + Ok(_) => log::trace!("Slash {:?} amount: {:?}", slash_account, slash_value), + Err(e) => log::error!( + "Slash {:?} amount {:?}, err {:?}", + slash_account, + slash_value, + e + ), + } crate::Pallet::::update_relayer_after_slash( &slash_account, locked_collateral.saturating_sub(slash_value), @@ -240,7 +268,7 @@ pub fn do_slash( } /// Do reward -fn do_reward(from: &T::AccountId, to: &T::AccountId, reward: RingBalance) { +pub(crate) fn do_reward(from: &T::AccountId, to: &T::AccountId, reward: RingBalance) { if reward.is_zero() { return; } diff --git a/frame/fee-market/src/tests.rs b/frame/fee-market/src/tests.rs index bc29db18ae..303efa97ee 100644 --- a/frame/fee-market/src/tests.rs +++ b/frame/fee-market/src/tests.rs @@ -421,6 +421,7 @@ frame_support::parameter_types! { pub const FeeMarketLockId: LockIdentifier = *b"da/feelf"; pub const MinimumRelayFee: Balance = 30; pub const CollateralPerOrder: Balance = 100; + pub const SlashPerBlock: Balance = 2; pub const AssignedRelayersNumber: u64 = 3; pub const Slot: u64 = 50; @@ -435,6 +436,7 @@ impl Config for Test { type TreasuryPalletId = TreasuryPalletId; type LockId = FeeMarketLockId; type CollateralPerOrder = CollateralPerOrder; + type SlashPerBlock = SlashPerBlock; type MinimumRelayFee = MinimumRelayFee; type AssignedRelayersNumber = AssignedRelayersNumber; type Slot = Slot; @@ -1006,7 +1008,7 @@ fn test_payment_with_slash_and_reduce_order_capacity() { let (_, _) = send_regular_message(market_fee); // Receive delivery message proof - System::set_block_number(200); + System::set_block_number(2000); assert_ok!(Messages::receive_messages_delivery_proof( Origin::signed(5), TestMessagesDeliveryProof(Ok(( @@ -1053,7 +1055,7 @@ fn test_payment_cal_slash_with_multiple_message() { assert_eq!(message_nonce1 + 1, message_nonce2); // Receive delivery message proof - System::set_block_number(200); + System::set_block_number(2000); assert_ok!(Messages::receive_messages_delivery_proof( Origin::signed(5), TestMessagesDeliveryProof(Ok(( diff --git a/node/runtime/pangolin/src/pallets/fee_market.rs b/node/runtime/pangolin/src/pallets/fee_market.rs index 9edf226f2e..b658024390 100644 --- a/node/runtime/pangolin/src/pallets/fee_market.rs +++ b/node/runtime/pangolin/src/pallets/fee_market.rs @@ -14,6 +14,7 @@ frame_support::parameter_types! { pub const MinimumRelayFee: Balance = 15 * COIN; pub const Slot: BlockNumber = 50; pub const CollateralPerOrder: Balance = 100 * COIN; + pub const SlashPerBlock: Balance = 2 * COIN; pub const AssignedRelayersRewardRatio: Permill = Permill::from_percent(60); pub const MessageRelayersRewardRatio: Permill = Permill::from_percent(80); @@ -28,6 +29,7 @@ impl Config for Runtime { type AssignedRelayersNumber = AssignedRelayersNumber; type MinimumRelayFee = MinimumRelayFee; type CollateralPerOrder = CollateralPerOrder; + type SlashPerBlock = SlashPerBlock; type Slot = Slot; type AssignedRelayersRewardRatio = AssignedRelayersRewardRatio; diff --git a/node/runtime/pangoro/src/pallets/fee_market.rs b/node/runtime/pangoro/src/pallets/fee_market.rs index 053a3494bf..d606bcecd6 100644 --- a/node/runtime/pangoro/src/pallets/fee_market.rs +++ b/node/runtime/pangoro/src/pallets/fee_market.rs @@ -13,6 +13,7 @@ frame_support::parameter_types! { pub const AssignedRelayersNumber: u64 = 3; pub const MinimumRelayFee: Balance = 15 * COIN; pub const CollateralPerOrder: Balance = 100 * COIN; + pub const SlashPerBlock: Balance = 2 * COIN; pub const Slot: BlockNumber = 50; pub const AssignedRelayersRewardRatio: Permill = Permill::from_percent(60); @@ -28,6 +29,7 @@ impl Config for Runtime { type AssignedRelayersNumber = AssignedRelayersNumber; type MinimumRelayFee = MinimumRelayFee; type CollateralPerOrder = CollateralPerOrder; + type SlashPerBlock = SlashPerBlock; type Slot = Slot; type AssignedRelayersRewardRatio = AssignedRelayersRewardRatio; diff --git a/primitives/fee-market/src/lib.rs b/primitives/fee-market/src/lib.rs index a6a4e24c14..f2044f1d48 100644 --- a/primitives/fee-market/src/lib.rs +++ b/primitives/fee-market/src/lib.rs @@ -22,10 +22,11 @@ use frame_support::Parameter; use sp_std::{ cmp::{Ord, Ordering, PartialEq}, default::Default, - ops::{Add, AddAssign, Range}, + ops::{Add, AddAssign, Range, Sub}, vec::Vec, }; +/// Reward mode for the fee market #[derive(Encode, Decode, Clone, Eq, PartialEq, Debug, Copy)] pub enum RewardMode { Normal, @@ -97,7 +98,8 @@ pub struct Order { impl Order where - BlockNumber: Add + Copy + AddAssign + PartialOrd, + BlockNumber: + Add + Copy + AddAssign + PartialOrd + Sub, Balance: Copy + PartialOrd, AccountId: Clone + PartialEq, { @@ -155,6 +157,15 @@ where self.relayers.iter().last().map(|r| r.valid_range.end) } + pub fn delivery_delay(&self) -> Option { + if let (Some(confirm_time), Some(range_end)) = (self.confirm_time, self.range_end()) { + if confirm_time > range_end { + return Some(confirm_time - range_end); + } + } + None + } + pub fn required_delivery_relayer_for_time( &self, message_confirm_time: BlockNumber, From 8bed97331c4ed0a2a5a6a9396a7b75c0178f0ced Mon Sep 17 00:00:00 2001 From: ouwenkg <2630582710@qq.com> Date: Fri, 12 Nov 2021 15:47:18 +0800 Subject: [PATCH 41/46] Update docs --- frame/fee-market/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/frame/fee-market/README.md b/frame/fee-market/README.md index a455d14f5d..fe97a05979 100644 --- a/frame/fee-market/README.md +++ b/frame/fee-market/README.md @@ -26,7 +26,7 @@ For simplicity, if count of relayers in current market are less than MIN_ASSIGNE ### Detailed Steps in Implementation 1. Enroll and lock collateral - 1. `enroll_and_lock_collateral` dispatch call. + 1. `enroll_and_lock_collateral` dispatch call 2. `cancel_enrollment()` dispatch call, remember to check if the relayer is in priority time slots. 2. Ask price We use simple constant price function for messages currently: fn(message) = const_price * 1 where const_price means fee per message. We might later improve this fn(message) with [relayer defined fee functions](https://github.com/darwinia-network/darwinia-common/issues/813). @@ -38,7 +38,7 @@ For simplicity, if count of relayers in current market are less than MIN_ASSIGNE 4. Message delivery and confirmed by bridger. 5. Reward and Slash Strategy. 1. If the order is confirmed in Rn's slot, then Rn can claim 60% from the reward P1, and message relayer can claim 80% * (1 - 60%) from P1, confirm relayer can claim 20% * (1 - 60%) from P1, (P3 - P1) will go to treasury. - 2. If the order is confirmed beyond all assigned relayers slot, and then The reward(R) consists of two parts, P3 and `CollaterPerOrder`. The `CollaterPerOrder` comes from each assigned relayer for this order was configure in the runtime. Message relayer can claim 80% from R, confirm relayer can claim 20% from R. + 2. If the order is confirmed beyond all assigned relayers slot, and then The reward will be S(t) where S(t) > P3, the part S(t) - P3 comes from funds slashed from R1, R2, R3's collateral. Message relayer can claim 80% from S(t), confirm relayer can claim 20% from S(t). Note: The ratio parameters in the strategy can be defined in runtime, and there might be update to them for refinement after more benchmark and statistics. From f0da25905199ad8395c794b841701e1ea69de7a8 Mon Sep 17 00:00:00 2001 From: ouwenkg <2630582710@qq.com> Date: Fri, 12 Nov 2021 15:49:26 +0800 Subject: [PATCH 42/46] Use UpdateRewardMode instead of OperatingMode --- frame/fee-market/src/lib.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/frame/fee-market/src/lib.rs b/frame/fee-market/src/lib.rs index 5a1f768e50..69818d537e 100644 --- a/frame/fee-market/src/lib.rs +++ b/frame/fee-market/src/lib.rs @@ -110,8 +110,8 @@ pub mod pallet { UpdateRelayFee(T::AccountId, RingBalance), /// Relayer cancel enrollment CancelEnrollment(T::AccountId), - /// Change operating mode - UpdateOperatingMode(RewardMode), + /// Update reward mode + UpdateRewardMode(RewardMode), } #[pallet::error] @@ -324,7 +324,7 @@ pub mod pallet { ) -> DispatchResultWithPostInfo { ensure_root(origin)?; RewardModeStorage::::put(mode); - Self::deposit_event(Event::::UpdateOperatingMode(mode)); + Self::deposit_event(Event::::UpdateRewardMode(mode)); Ok(().into()) } } From 02b9174921f4c6af5dacb47dc36c3704d5193d71 Mon Sep 17 00:00:00 2001 From: ouwenkg <2630582710@qq.com> Date: Fri, 12 Nov 2021 17:20:44 +0800 Subject: [PATCH 43/46] Bring Slasher back --- frame/fee-market/src/lib.rs | 8 +++++-- frame/fee-market/src/s2s/payment.rs | 21 +++---------------- frame/fee-market/src/tests.rs | 18 +++++++++++++--- .../pangolin/src/pallets/fee_market.rs | 20 ++++++++++++++---- .../runtime/pangoro/src/pallets/fee_market.rs | 19 ++++++++++++++--- 5 files changed, 56 insertions(+), 30 deletions(-) diff --git a/frame/fee-market/src/lib.rs b/frame/fee-market/src/lib.rs index 69818d537e..901575cda9 100644 --- a/frame/fee-market/src/lib.rs +++ b/frame/fee-market/src/lib.rs @@ -75,8 +75,6 @@ pub mod pallet { /// The collateral relayer need to lock for each order. #[pallet::constant] type CollateralPerOrder: Get>; - #[pallet::constant] - type SlashPerBlock: Get>; /// The slot times set #[pallet::constant] type Slot: Get; @@ -89,6 +87,8 @@ pub mod pallet { #[pallet::constant] type ConfirmRelayersRewardRatio: Get; + /// The slash rule + type Slasher: Slasher; type RingCurrency: LockableCurrency + Currency; type Event: From> + IsType<::Event>; @@ -440,3 +440,7 @@ impl Pallet { (collateral / T::CollateralPerOrder::get()).saturated_into::() } } + +pub trait Slasher { + fn slash(locked_collateral: RingBalance, timeout: T::BlockNumber) -> RingBalance; +} diff --git a/frame/fee-market/src/s2s/payment.rs b/frame/fee-market/src/s2s/payment.rs index 307a04f443..3207df6130 100644 --- a/frame/fee-market/src/s2s/payment.rs +++ b/frame/fee-market/src/s2s/payment.rs @@ -22,7 +22,7 @@ use bp_messages::{ MessageNonce, UnrewardedRelayer, }; use frame_support::traits::{Currency as CurrencyT, ExistenceRequirement, Get}; -use sp_runtime::traits::{AccountIdConversion, Saturating, UniqueSaturatedInto}; +use sp_runtime::traits::{AccountIdConversion, Saturating}; use sp_std::{ collections::{btree_map::BTreeMap, vec_deque::VecDeque}, ops::RangeInclusive, @@ -175,9 +175,9 @@ where if crate::Pallet::::reward_mode() == RewardMode::Normal { let mut assigned_relayers_slash = RingBalance::::zero(); for assigned_relayer in order.relayers_slice() { - let slash_value: RingBalance = cal_slash_value::( - order.delivery_delay(), + let slash_value: RingBalance = T::Slasher::slash( order.locked_collateral, + order.delivery_delay().unwrap_or_default(), ); let slashed = do_slash::( &assigned_relayer.id, @@ -216,21 +216,6 @@ where } } -pub(crate) fn cal_slash_value( - delay: Option, - locked_collateral: RingBalance, -) -> RingBalance { - let mut slash_value = RingBalance::::zero(); - if let Some(delay_blocks) = delay { - slash_value = UniqueSaturatedInto::::unique_saturated_into(delay_blocks) - .saturating_mul(UniqueSaturatedInto::::unique_saturated_into( - T::SlashPerBlock::get(), - )) - .unique_saturated_into(); - } - sp_std::cmp::min(locked_collateral, slash_value) -} - /// Do slash for absent assigned relayers pub(crate) fn do_slash( slash_account: &T::AccountId, diff --git a/frame/fee-market/src/tests.rs b/frame/fee-market/src/tests.rs index 303efa97ee..689bfbb2d2 100644 --- a/frame/fee-market/src/tests.rs +++ b/frame/fee-market/src/tests.rs @@ -38,7 +38,7 @@ use frame_system::mocking::*; use sp_core::H256; use sp_runtime::{ testing::Header, - traits::{AccountIdConversion, BlakeTwo256, IdentityLookup}, + traits::{AccountIdConversion, BlakeTwo256, IdentityLookup, UniqueSaturatedInto}, FixedU128, Permill, RuntimeDebug, }; // --- std --- @@ -421,7 +421,6 @@ frame_support::parameter_types! { pub const FeeMarketLockId: LockIdentifier = *b"da/feelf"; pub const MinimumRelayFee: Balance = 30; pub const CollateralPerOrder: Balance = 100; - pub const SlashPerBlock: Balance = 2; pub const AssignedRelayersNumber: u64 = 3; pub const Slot: u64 = 50; @@ -431,12 +430,24 @@ frame_support::parameter_types! { pub const TreasuryPalletAccount: u64 = 666; } +pub struct TestSlasher; +impl Slasher for TestSlasher { + fn slash(locked_collateral: RingBalance, timeout: T::BlockNumber) -> RingBalance { + let slash_each_block = 2; + let slash_value = UniqueSaturatedInto::::unique_saturated_into(timeout) + .saturating_mul(UniqueSaturatedInto::::unique_saturated_into( + slash_each_block, + )) + .unique_saturated_into(); + sp_std::cmp::min(locked_collateral, slash_value) + } +} + impl Config for Test { type PalletId = FeeMarketPalletId; type TreasuryPalletId = TreasuryPalletId; type LockId = FeeMarketLockId; type CollateralPerOrder = CollateralPerOrder; - type SlashPerBlock = SlashPerBlock; type MinimumRelayFee = MinimumRelayFee; type AssignedRelayersNumber = AssignedRelayersNumber; type Slot = Slot; @@ -445,6 +456,7 @@ impl Config for Test { type MessageRelayersRewardRatio = MessageRelayersRewardRatio; type ConfirmRelayersRewardRatio = ConfirmRelayersRewardRatio; + type Slasher = TestSlasher; type RingCurrency = Ring; type Event = Event; type WeightInfo = (); diff --git a/node/runtime/pangolin/src/pallets/fee_market.rs b/node/runtime/pangolin/src/pallets/fee_market.rs index b658024390..2f501ca4f8 100644 --- a/node/runtime/pangolin/src/pallets/fee_market.rs +++ b/node/runtime/pangolin/src/pallets/fee_market.rs @@ -1,9 +1,9 @@ // --- substrate --- use frame_support::{traits::LockIdentifier, PalletId}; +use sp_runtime::{traits::UniqueSaturatedInto, Permill}; // --- darwinia --- use crate::*; -use darwinia_fee_market::Config; -use sp_runtime::Permill; +use darwinia_fee_market::{Config, RingBalance, Slasher}; frame_support::parameter_types! { pub const FeeMarketPalletId: PalletId = PalletId(*b"da/feemk"); @@ -14,7 +14,6 @@ frame_support::parameter_types! { pub const MinimumRelayFee: Balance = 15 * COIN; pub const Slot: BlockNumber = 50; pub const CollateralPerOrder: Balance = 100 * COIN; - pub const SlashPerBlock: Balance = 2 * COIN; pub const AssignedRelayersRewardRatio: Permill = Permill::from_percent(60); pub const MessageRelayersRewardRatio: Permill = Permill::from_percent(80); @@ -29,14 +28,27 @@ impl Config for Runtime { type AssignedRelayersNumber = AssignedRelayersNumber; type MinimumRelayFee = MinimumRelayFee; type CollateralPerOrder = CollateralPerOrder; - type SlashPerBlock = SlashPerBlock; type Slot = Slot; type AssignedRelayersRewardRatio = AssignedRelayersRewardRatio; type MessageRelayersRewardRatio = MessageRelayersRewardRatio; type ConfirmRelayersRewardRatio = ConfirmRelayersRewardRatio; + type Slasher = FeeMarketSlasher; type RingCurrency = Ring; type Event = Event; type WeightInfo = (); } + +pub struct FeeMarketSlasher; +impl Slasher for FeeMarketSlasher { + fn slash(locked_collateral: RingBalance, timeout: T::BlockNumber) -> RingBalance { + let slash_each_block = 2 * COIN; + let slash_value = UniqueSaturatedInto::::unique_saturated_into(timeout) + .saturating_mul(UniqueSaturatedInto::::unique_saturated_into( + slash_each_block, + )) + .unique_saturated_into(); + sp_std::cmp::min(locked_collateral, slash_value) + } +} diff --git a/node/runtime/pangoro/src/pallets/fee_market.rs b/node/runtime/pangoro/src/pallets/fee_market.rs index d606bcecd6..1599de3c5d 100644 --- a/node/runtime/pangoro/src/pallets/fee_market.rs +++ b/node/runtime/pangoro/src/pallets/fee_market.rs @@ -1,9 +1,9 @@ // --- substrate --- use frame_support::{traits::LockIdentifier, PalletId}; +use sp_runtime::{traits::UniqueSaturatedInto, Permill}; // --- darwinia --- use crate::*; -use darwinia_fee_market::Config; -use sp_runtime::Permill; +use darwinia_fee_market::{Config, RingBalance, Slasher}; frame_support::parameter_types! { pub const FeeMarketPalletId: PalletId = PalletId(*b"da/feemk"); @@ -29,14 +29,27 @@ impl Config for Runtime { type AssignedRelayersNumber = AssignedRelayersNumber; type MinimumRelayFee = MinimumRelayFee; type CollateralPerOrder = CollateralPerOrder; - type SlashPerBlock = SlashPerBlock; type Slot = Slot; type AssignedRelayersRewardRatio = AssignedRelayersRewardRatio; type MessageRelayersRewardRatio = MessageRelayersRewardRatio; type ConfirmRelayersRewardRatio = ConfirmRelayersRewardRatio; + type Slasher = FeeMarketSlasher; type RingCurrency = Ring; type Event = Event; type WeightInfo = (); } + +pub struct FeeMarketSlasher; +impl Slasher for FeeMarketSlasher { + fn slash(locked_collateral: RingBalance, timeout: T::BlockNumber) -> RingBalance { + let slash_each_block = 2 * COIN; + let slash_value = UniqueSaturatedInto::::unique_saturated_into(timeout) + .saturating_mul(UniqueSaturatedInto::::unique_saturated_into( + slash_each_block, + )) + .unique_saturated_into(); + sp_std::cmp::min(locked_collateral, slash_value) + } +} From 9ff3e3dc9c94f9fb0438e5598b5398907c0a06f1 Mon Sep 17 00:00:00 2001 From: ouwenkg <2630582710@qq.com> Date: Fri, 12 Nov 2021 17:34:18 +0800 Subject: [PATCH 44/46] Return zero, if transfer failed --- frame/fee-market/src/s2s/payment.rs | 43 +++++++++++++++-------------- 1 file changed, 22 insertions(+), 21 deletions(-) diff --git a/frame/fee-market/src/s2s/payment.rs b/frame/fee-market/src/s2s/payment.rs index 3207df6130..1aed4571d5 100644 --- a/frame/fee-market/src/s2s/payment.rs +++ b/frame/fee-market/src/s2s/payment.rs @@ -175,14 +175,14 @@ where if crate::Pallet::::reward_mode() == RewardMode::Normal { let mut assigned_relayers_slash = RingBalance::::zero(); for assigned_relayer in order.relayers_slice() { - let slash_value: RingBalance = T::Slasher::slash( + let amount: RingBalance = T::Slasher::slash( order.locked_collateral, order.delivery_delay().unwrap_or_default(), ); let slashed = do_slash::( &assigned_relayer.id, relayer_fund_account, - slash_value, + amount, ); assigned_relayers_slash += slashed; } @@ -218,38 +218,39 @@ where /// Do slash for absent assigned relayers pub(crate) fn do_slash( - slash_account: &T::AccountId, + who: &T::AccountId, fund_account: &T::AccountId, - slash_value: RingBalance, + amount: RingBalance, ) -> RingBalance { - let locked_collateral = crate::Pallet::::relayer(&slash_account).collateral; - T::RingCurrency::remove_lock(T::LockId::get(), &slash_account); + let locked_collateral = crate::Pallet::::relayer(&who).collateral; + T::RingCurrency::remove_lock(T::LockId::get(), &who); debug_assert!( - locked_collateral >= slash_value, + locked_collateral >= amount, "The locked collateral must alway greater than slash max" ); let pay_result = ::RingCurrency::transfer( - slash_account, + who, fund_account, - slash_value, + amount, ExistenceRequirement::AllowDeath, ); match pay_result { - Ok(_) => log::trace!("Slash {:?} amount: {:?}", slash_account, slash_value), - Err(e) => log::error!( - "Slash {:?} amount {:?}, err {:?}", - slash_account, - slash_value, - e - ), + Ok(_) => { + crate::Pallet::::update_relayer_after_slash( + &who, + locked_collateral.saturating_sub(amount), + ); + log::trace!("Slash {:?} amount: {:?}", who, amount); + return amount; + } + Err(e) => { + crate::Pallet::::update_relayer_after_slash(&who, locked_collateral); + log::error!("Slash {:?} amount {:?}, err {:?}", who, amount, e) + } } - crate::Pallet::::update_relayer_after_slash( - &slash_account, - locked_collateral.saturating_sub(slash_value), - ); - slash_value + RingBalance::::zero() } /// Do reward From 1ee88ec0f7286cfaee1843886879bac6122002c9 Mon Sep 17 00:00:00 2001 From: ouwenkg <2630582710@qq.com> Date: Fri, 12 Nov 2021 18:52:13 +0800 Subject: [PATCH 45/46] Add CollateralSlashProtect and test --- frame/fee-market/src/benchmarking.rs | 4 +-- frame/fee-market/src/lib.rs | 25 ++++++--------- frame/fee-market/src/s2s/payment.rs | 37 +++++++++++----------- frame/fee-market/src/tests.rs | 46 ++++++++++++++++++++++++++++ frame/fee-market/src/weight.rs | 6 ++-- node/runtime/pangolin/types.json | 6 ---- primitives/fee-market/src/lib.rs | 8 ----- 7 files changed, 80 insertions(+), 52 deletions(-) diff --git a/frame/fee-market/src/benchmarking.rs b/frame/fee-market/src/benchmarking.rs index fb1ebbe9ee..e92751878c 100644 --- a/frame/fee-market/src/benchmarking.rs +++ b/frame/fee-market/src/benchmarking.rs @@ -106,6 +106,6 @@ benchmarks! { assert_eq!(>::relayers().len(), 3); } - set_operating_mode { - }:set_operating_mode(RawOrigin::Root, RewardMode::NoSlash) + set_slash_protect { + }:set_slash_protect(RawOrigin::Root, T::CollateralPerOrder::get().saturating_mul(1u32.into())) } diff --git a/frame/fee-market/src/lib.rs b/frame/fee-market/src/lib.rs index 901575cda9..0f50693deb 100644 --- a/frame/fee-market/src/lib.rs +++ b/frame/fee-market/src/lib.rs @@ -47,7 +47,7 @@ use darwinia_support::{ balance::{LockFor, LockableCurrency}, AccountId, }; -use dp_fee::{Order, Relayer, RewardMode}; +use dp_fee::{Order, Relayer}; pub type RingBalance = <::RingCurrency as Currency>>::Balance; pub use pallet::*; @@ -110,8 +110,8 @@ pub mod pallet { UpdateRelayFee(T::AccountId, RingBalance), /// Relayer cancel enrollment CancelEnrollment(T::AccountId), - /// Update reward mode - UpdateRewardMode(RewardMode), + /// Update collateral slash protect value + UpdateCollateralSlashProtect(RingBalance), } #[pallet::error] @@ -167,13 +167,8 @@ pub mod pallet { StorageValue<_, Vec<(LaneId, MessageNonce)>, ValueQuery>; #[pallet::storage] - #[pallet::getter(fn reward_mode)] - pub type RewardModeStorage = - StorageValue<_, RewardMode, ValueQuery, DefaultRewardMode>; - #[pallet::type_value] - pub fn DefaultRewardMode() -> RewardMode { - RewardMode::Normal - } + #[pallet::getter(fn collateral_slash_protect)] + pub type CollateralSlashProtect = StorageValue<_, RingBalance, OptionQuery>; #[pallet::pallet] pub struct Pallet(_); @@ -316,15 +311,15 @@ pub mod pallet { Ok(().into()) } - #[pallet::weight(::WeightInfo::set_reward_mode())] + #[pallet::weight(::WeightInfo::set_slash_protect())] #[transactional] - pub fn set_reward_mode( + pub fn set_slash_protect( origin: OriginFor, - mode: RewardMode, + slash_protect: RingBalance, ) -> DispatchResultWithPostInfo { ensure_root(origin)?; - RewardModeStorage::::put(mode); - Self::deposit_event(Event::::UpdateRewardMode(mode)); + CollateralSlashProtect::::put(slash_protect); + Self::deposit_event(Event::::UpdateCollateralSlashProtect(slash_protect)); Ok(().into()) } } diff --git a/frame/fee-market/src/s2s/payment.rs b/frame/fee-market/src/s2s/payment.rs index 1aed4571d5..b9bd5f651f 100644 --- a/frame/fee-market/src/s2s/payment.rs +++ b/frame/fee-market/src/s2s/payment.rs @@ -28,7 +28,7 @@ use sp_std::{ ops::RangeInclusive, }; // --- darwinia-network --- -use crate::{Config, ConfirmedMessagesThisBlock, Orders, *}; +use crate::{Config, ConfirmedMessagesThisBlock, Orders, Pallet, *}; // --- std --- use num_traits::Zero; @@ -169,26 +169,27 @@ where confirm_reward = T::ConfirmRelayersRewardRatio::get() * bridger_relayers_reward; } else { - // The order is delayed, slash assigned relayers in operating normal mode. + // The order delivery is delay let mut total_slash = message_fee; - if crate::Pallet::::reward_mode() == RewardMode::Normal { - let mut assigned_relayers_slash = RingBalance::::zero(); - for assigned_relayer in order.relayers_slice() { - let amount: RingBalance = T::Slasher::slash( - order.locked_collateral, - order.delivery_delay().unwrap_or_default(), - ); - let slashed = do_slash::( - &assigned_relayer.id, - relayer_fund_account, - amount, - ); - assigned_relayers_slash += slashed; - } - total_slash += assigned_relayers_slash; + // calculate slash amount + let mut amount: RingBalance = T::Slasher::slash( + order.locked_collateral, + order.delivery_delay().unwrap_or_default(), + ); + if let Some(slash_protect) = Pallet::::collateral_slash_protect() { + amount = sp_std::cmp::min(amount, slash_protect); } + // Slash order's assigned relayers + let mut assigned_relayers_slash = RingBalance::::zero(); + for assigned_relayer in order.relayers_slice() { + let slashed = + do_slash::(&assigned_relayer.id, relayer_fund_account, amount); + assigned_relayers_slash += slashed; + } + total_slash += assigned_relayers_slash; + // 80% total slash => confirm relayer message_reward = T::MessageRelayersRewardRatio::get() * total_slash; // 20% total slash => confirm relayer @@ -222,7 +223,7 @@ pub(crate) fn do_slash( fund_account: &T::AccountId, amount: RingBalance, ) -> RingBalance { - let locked_collateral = crate::Pallet::::relayer(&who).collateral; + let locked_collateral = Pallet::::relayer(&who).collateral; T::RingCurrency::remove_lock(T::LockId::get(), &who); debug_assert!( locked_collateral >= amount, diff --git a/frame/fee-market/src/tests.rs b/frame/fee-market/src/tests.rs index 689bfbb2d2..066dce2b5f 100644 --- a/frame/fee-market/src/tests.rs +++ b/frame/fee-market/src/tests.rs @@ -1052,6 +1052,52 @@ fn test_payment_with_slash_and_reduce_order_capacity() { }); } +#[test] +fn test_payment_slash_with_protect() { + new_test_ext().execute_with(|| { + // Send message + System::set_block_number(2); + let _ = FeeMarket::enroll_and_lock_collateral(Origin::signed(6), 400, Some(30)); + let _ = FeeMarket::enroll_and_lock_collateral(Origin::signed(7), 400, Some(50)); + let _ = FeeMarket::enroll_and_lock_collateral(Origin::signed(8), 400, Some(100)); + assert_eq!(FeeMarket::relayer(&6).collateral, 400); + let market_fee = FeeMarket::market_fee().unwrap(); + let (_, _) = send_regular_message(market_fee); + assert_ok!(FeeMarket::set_slash_protect(Origin::root(), 50)); + + // Receive delivery message proof + System::set_block_number(2000); + assert_ok!(Messages::receive_messages_delivery_proof( + Origin::signed(5), + TestMessagesDeliveryProof(Ok(( + TEST_LANE_ID, + InboundLaneData { + relayers: vec![unrewarded_relayer(1, 1, TEST_RELAYER_A)] + .into_iter() + .collect(), + ..Default::default() + } + ))), + UnrewardedRelayersState { + unrewarded_relayer_entries: 1, + total_messages: 1, + ..Default::default() + }, + )); + assert!(FeeMarket::is_enrolled(&6)); + assert!(FeeMarket::is_enrolled(&6)); + assert!(FeeMarket::is_enrolled(&6)); + assert_eq!(FeeMarket::relayer(&6).collateral, 350); + assert_eq!(FeeMarket::relayer(&7).collateral, 350); + assert_eq!(FeeMarket::relayer(&8).collateral, 350); + assert!(TestMessageDeliveryAndDispatchPayment::is_reward_paid(5, 50)); + assert!(TestMessageDeliveryAndDispatchPayment::is_reward_paid( + TEST_RELAYER_A, + 200 + )); + }); +} + #[test] fn test_payment_cal_slash_with_multiple_message() { new_test_ext().execute_with(|| { diff --git a/frame/fee-market/src/weight.rs b/frame/fee-market/src/weight.rs index 0a05876b61..31eb2315f1 100644 --- a/frame/fee-market/src/weight.rs +++ b/frame/fee-market/src/weight.rs @@ -58,7 +58,7 @@ pub trait WeightInfo { fn update_locked_collateral() -> Weight; fn update_relay_fee() -> Weight; fn cancel_enrollment() -> Weight; - fn set_reward_mode() -> Weight; + fn set_slash_protect() -> Weight; } /// Weights for darwinia_fee_market using the Substrate node and recommended hardware. @@ -84,7 +84,7 @@ impl WeightInfo for SubstrateWeight { .saturating_add(T::DbWeight::get().reads(12 as Weight)) .saturating_add(T::DbWeight::get().writes(7 as Weight)) } - fn set_reward_mode() -> Weight { + fn set_slash_protect() -> Weight { (17_924_000 as Weight) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(3 as Weight)) @@ -113,7 +113,7 @@ impl WeightInfo for () { .saturating_add(RocksDbWeight::get().reads(12 as Weight)) .saturating_add(RocksDbWeight::get().writes(7 as Weight)) } - fn set_reward_mode() -> Weight { + fn set_slash_protect() -> Weight { (17_924_000 as Weight) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(3 as Weight)) diff --git a/node/runtime/pangolin/types.json b/node/runtime/pangolin/types.json index 64ff882edc..790a519627 100644 --- a/node/runtime/pangolin/types.json +++ b/node/runtime/pangolin/types.json @@ -271,12 +271,6 @@ "fee": "Balance", "valid_range": "BlockNumber" }, - "RewardMode": { - "_enum": { - "Normal": "null", - "NoSlash": "null" - } - }, "__[pangolin.runtime]__": { "ProxyType": { "_enum": { diff --git a/primitives/fee-market/src/lib.rs b/primitives/fee-market/src/lib.rs index f2044f1d48..f8ae5c900a 100644 --- a/primitives/fee-market/src/lib.rs +++ b/primitives/fee-market/src/lib.rs @@ -25,14 +25,6 @@ use sp_std::{ ops::{Add, AddAssign, Range, Sub}, vec::Vec, }; - -/// Reward mode for the fee market -#[derive(Encode, Decode, Clone, Eq, PartialEq, Debug, Copy)] -pub enum RewardMode { - Normal, - NoSlash, -} - /// Relayer who has enrolled the fee market #[derive(Encode, Decode, Clone, Eq, Debug)] pub struct Relayer { From 58366e24fbfba53b0d3fd590e487eaf4978484fa Mon Sep 17 00:00:00 2001 From: ouwenkg <2630582710@qq.com> Date: Mon, 15 Nov 2021 10:48:05 +0800 Subject: [PATCH 46/46] Add more docs about the event params --- frame/fee-market/src/lib.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/frame/fee-market/src/lib.rs b/frame/fee-market/src/lib.rs index 0f50693deb..c83d6a47f9 100644 --- a/frame/fee-market/src/lib.rs +++ b/frame/fee-market/src/lib.rs @@ -102,15 +102,15 @@ pub mod pallet { RingBalance = "RingBalance", )] pub enum Event { - /// Relayer enrollment + /// Relayer enrollment. \[account_id, locked_collateral, relay_fee\] Enroll(T::AccountId, RingBalance, RingBalance), - /// Update relayer locked collateral + /// Update relayer locked collateral. \[account_id, new_collateral\] UpdateLockedCollateral(T::AccountId, RingBalance), - /// Update relayer fee + /// Update relayer fee. \[account_id, new_fee\] UpdateRelayFee(T::AccountId, RingBalance), - /// Relayer cancel enrollment + /// Relayer cancel enrollment. \[account_id\] CancelEnrollment(T::AccountId), - /// Update collateral slash protect value + /// Update collateral slash protect value. \[slash_protect_value\] UpdateCollateralSlashProtect(RingBalance), }