From 7a28ba70eb9db48464daea069cce799c90db7acc Mon Sep 17 00:00:00 2001 From: bear Date: Fri, 20 May 2022 17:11:34 +0800 Subject: [PATCH 1/8] Refactor the total reward cal --- modules/fee-market/src/lib.rs | 2 + modules/fee-market/src/s2s/mod.rs | 2 +- modules/fee-market/src/s2s/payment.rs | 123 +++++++++++++++++--------- modules/fee-market/src/tests.rs | 10 ++- 4 files changed, 92 insertions(+), 45 deletions(-) diff --git a/modules/fee-market/src/lib.rs b/modules/fee-market/src/lib.rs index 9a69fecee..e229b756a 100644 --- a/modules/fee-market/src/lib.rs +++ b/modules/fee-market/src/lib.rs @@ -47,6 +47,7 @@ use sp_runtime::{ }; use sp_std::vec::Vec; // --- darwinia-network --- +use s2s::RewardItem; use types::{Order, Relayer, SlashReport}; pub type AccountId = ::AccountId; @@ -107,6 +108,7 @@ pub mod pallet { UpdateAssignedRelayersNumber(u32), /// Slash report FeeMarketSlash(SlashReport>), + // OrderReward(LaneId, MessageNonce, RewardItem>), } #[pallet::error] diff --git a/modules/fee-market/src/s2s/mod.rs b/modules/fee-market/src/s2s/mod.rs index 1aaa10195..5321950d1 100644 --- a/modules/fee-market/src/s2s/mod.rs +++ b/modules/fee-market/src/s2s/mod.rs @@ -17,7 +17,7 @@ // along with Darwinia. If not, see . pub mod payment; -pub use payment::FeeMarketPayment; +pub use payment::{FeeMarketPayment, RewardItem}; pub mod callbacks; pub use callbacks::{FeeMarketMessageAcceptedHandler, FeeMarketMessageConfirmedHandler}; diff --git a/modules/fee-market/src/s2s/payment.rs b/modules/fee-market/src/s2s/payment.rs index 4fe12fef4..671103cc2 100644 --- a/modules/fee-market/src/s2s/payment.rs +++ b/modules/fee-market/src/s2s/payment.rs @@ -91,24 +91,25 @@ where ) { let RewardsBook { messages_relayers_rewards, - confirmation_relayer_rewards, - assigned_relayers_rewards, + confirm_relayer_rewards, + slot_relayers_rewards, treasury_total_rewards, } = slash_and_calculate_rewards::( lane_id, messages_relayers, + confirmation_relayer.clone(), received_range, relayer_fund_account, ); // Pay confirmation relayer rewards - do_reward::(relayer_fund_account, confirmation_relayer, confirmation_relayer_rewards); + do_reward::(relayer_fund_account, confirmation_relayer, confirm_relayer_rewards); // Pay messages relayers rewards for (relayer, reward) in messages_relayers_rewards { do_reward::(relayer_fund_account, &relayer, reward); } // Pay assign relayer reward - for (relayer, reward) in assigned_relayers_rewards { + for (relayer, reward) in slot_relayers_rewards { do_reward::(relayer_fund_account, &relayer, reward); } // Pay treasury reward @@ -125,18 +126,15 @@ where pub fn slash_and_calculate_rewards( lane_id: LaneId, messages_relayers: VecDeque>, + confirm_relayer: T::AccountId, received_range: &RangeInclusive, relayer_fund_account: &T::AccountId, -) -> RewardsBook> +) -> RewardsBook where T: frame_system::Config + Config, I: 'static, { - let mut confirmation_rewards = BalanceOf::::zero(); - let mut messages_rewards = BTreeMap::>::new(); - let mut assigned_relayers_rewards = BTreeMap::>::new(); - let mut treasury_total_rewards = BalanceOf::::zero(); - + let mut rewards_book = RewardsBook::new(); for entry in messages_relayers { let nonce_begin = sp_std::cmp::max(entry.messages.begin, *received_range.start()); let nonce_end = sp_std::cmp::min(entry.messages.end, *received_range.end()); @@ -145,6 +143,7 @@ where // The order created when message was accepted, so we can always get the order info // below. if let Some(order) = >::get(&(lane_id, message_nonce)) { + println!("find the order"); // The confirm_time of the order is set in the `OnDeliveryConfirmed` callback. And // the callback function was called as source chain received message delivery proof, // before the reward payment. @@ -152,25 +151,22 @@ where order.confirm_time.unwrap_or_else(|| frame_system::Pallet::::block_number()); let message_fee = order.fee(); + let mut reward_item = RewardItem::new(); let message_reward; let confirm_reward; if let Some((who, base_fee)) = order.required_delivery_relayer_for_time(order_confirm_time) { + println!("delivered in time"); // message fee - base fee => treasury - let treasury_reward = message_fee.saturating_sub(base_fee); - treasury_total_rewards = treasury_total_rewards.saturating_add(treasury_reward); - - // 60% * base fee => assigned_relayers_rewards - let assigned_relayers_reward = T::AssignedRelayersRewardRatio::get() * base_fee; - assigned_relayers_rewards - .entry(who) - .and_modify(|r| *r = r.saturating_add(assigned_relayers_reward)) - .or_insert(assigned_relayers_reward); + reward_item.to_treasury = Some(message_fee.saturating_sub(base_fee)); - let bridger_relayers_reward = base_fee.saturating_sub(assigned_relayers_reward); + // 60% * base fee => slot_relayer_reward + let slot_relayer_reward = T::AssignedRelayersRewardRatio::get() * base_fee; + reward_item.to_slot_relayer = Some((who, slot_relayer_reward)); + let bridger_relayers_reward = base_fee.saturating_sub(slot_relayer_reward); // 80% * (1 - 60%) * base_fee => message relayer message_reward = T::MessageRelayersRewardRatio::get() * bridger_relayers_reward; // 20% * (1 - 60%) * base_fee => confirm relayer @@ -202,29 +198,20 @@ where } total_slash += assigned_relayers_slash; - // 80% total slash => confirm relayer + // 80% total slash => message relayer message_reward = T::MessageRelayersRewardRatio::get() * total_slash; // 20% total slash => confirm relayer confirm_reward = T::ConfirmRelayersRewardRatio::get() * total_slash; } - // Update confirmation relayer total rewards - confirmation_rewards = confirmation_rewards.saturating_add(confirm_reward); - // Update message relayers total rewards - messages_rewards - .entry(entry.relayer.clone()) - .and_modify(|r| *r = r.saturating_add(message_reward)) - .or_insert(message_reward); + reward_item.to_message_relayer = Some((entry.clone().relayer, message_reward)); + reward_item.to_confirm_relayer = Some((confirm_relayer.clone(), confirm_reward)); + + rewards_book.add_reward_item(reward_item); } } } - - RewardsBook { - messages_relayers_rewards: messages_rewards, - confirmation_relayer_rewards: confirmation_rewards, - assigned_relayers_rewards, - treasury_total_rewards, - } + rewards_book } /// Do slash for absent assigned relayers @@ -290,10 +277,66 @@ pub(crate) fn do_reward, I: 'static>( } } +/// Record the concrete reward distribution of certain order +#[derive(Clone, Debug, Eq, PartialEq, TypeInfo)] +pub struct RewardItem { + pub to_slot_relayer: Option<(AccountId, Balance)>, + pub to_treasury: Option, + pub to_message_relayer: Option<(AccountId, Balance)>, + pub to_confirm_relayer: Option<(AccountId, Balance)>, +} + +impl RewardItem { + fn new() -> Self { + Self { + to_slot_relayer: None, + to_treasury: None, + to_message_relayer: None, + to_confirm_relayer: None, + } + } +} + /// Record the calculation rewards result -pub struct RewardsBook { - pub messages_relayers_rewards: BTreeMap, - pub confirmation_relayer_rewards: Balance, - pub assigned_relayers_rewards: BTreeMap, - pub treasury_total_rewards: Balance, +#[derive(Clone, Debug, Eq, PartialEq, TypeInfo)] +pub struct RewardsBook, I: 'static> { + pub messages_relayers_rewards: BTreeMap>, + pub confirm_relayer_rewards: BalanceOf, + pub slot_relayers_rewards: BTreeMap>, + pub treasury_total_rewards: BalanceOf, +} + +impl, I: 'static> RewardsBook { + fn new() -> Self { + Self { + messages_relayers_rewards: BTreeMap::new(), + confirm_relayer_rewards: BalanceOf::::zero(), + slot_relayers_rewards: BTreeMap::new(), + treasury_total_rewards: BalanceOf::::zero(), + } + } + + fn add_reward_item(&mut self, order_reward: RewardItem>) { + if let Some((id, reward)) = order_reward.to_slot_relayer { + self.slot_relayers_rewards + .entry(id) + .and_modify(|r| *r = r.saturating_add(reward)) + .or_insert(reward); + } + + if let Some(reward) = order_reward.to_treasury { + self.treasury_total_rewards = self.treasury_total_rewards.saturating_add(reward); + } + + if let Some((id, reward)) = order_reward.to_message_relayer { + self.messages_relayers_rewards + .entry(id) + .and_modify(|r| *r = r.saturating_add(reward)) + .or_insert(reward); + } + + if let Some((_id, reward)) = order_reward.to_confirm_relayer { + self.confirm_relayer_rewards = self.confirm_relayer_rewards.saturating_add(reward); + } + } } diff --git a/modules/fee-market/src/tests.rs b/modules/fee-market/src/tests.rs index 643ab3435..fdd5ffe13 100644 --- a/modules/fee-market/src/tests.rs +++ b/modules/fee-market/src/tests.rs @@ -292,17 +292,19 @@ impl MessageDeliveryAndDispatchPayment ) { let RewardsBook { messages_relayers_rewards, - confirmation_relayer_rewards, - assigned_relayers_rewards, + confirm_relayer_rewards, + slot_relayers_rewards, treasury_total_rewards, } = slash_and_calculate_rewards::( lane_id, message_relayers, + confirmation_relayer.clone(), received_range, relayer_fund_account, ); + let confimation_key = - (b":relayer-reward:", confirmation_relayer, confirmation_relayer_rewards).encode(); + (b":relayer-reward:", confirmation_relayer, confirm_relayer_rewards).encode(); frame_support::storage::unhashed::put(&confimation_key, &true); for (relayer, reward) in &messages_relayers_rewards { @@ -310,7 +312,7 @@ impl MessageDeliveryAndDispatchPayment frame_support::storage::unhashed::put(&key, &true); } - for (relayer, reward) in &assigned_relayers_rewards { + for (relayer, reward) in &slot_relayers_rewards { let key = (b":relayer-reward:", relayer, reward).encode(); frame_support::storage::unhashed::put(&key, &true); } From 92b28b7fe3b0436221153589591d97f57238644c Mon Sep 17 00:00:00 2001 From: bear Date: Fri, 20 May 2022 18:41:38 +0800 Subject: [PATCH 2/8] Code Clean --- modules/fee-market/src/lib.rs | 3 +- modules/fee-market/src/s2s/payment.rs | 71 ++++++++++++++------------- 2 files changed, 38 insertions(+), 36 deletions(-) diff --git a/modules/fee-market/src/lib.rs b/modules/fee-market/src/lib.rs index e229b756a..9309b504c 100644 --- a/modules/fee-market/src/lib.rs +++ b/modules/fee-market/src/lib.rs @@ -108,7 +108,8 @@ pub mod pallet { UpdateAssignedRelayersNumber(u32), /// Slash report FeeMarketSlash(SlashReport>), - // OrderReward(LaneId, MessageNonce, RewardItem>), + /// Order reward \[lane_id, message_nonce, rewards\] + OrderReward(LaneId, MessageNonce, RewardItem>), } #[pallet::error] diff --git a/modules/fee-market/src/s2s/payment.rs b/modules/fee-market/src/s2s/payment.rs index 671103cc2..c79a5d6c7 100644 --- a/modules/fee-market/src/s2s/payment.rs +++ b/modules/fee-market/src/s2s/payment.rs @@ -89,34 +89,30 @@ where received_range: &RangeInclusive, relayer_fund_account: &T::AccountId, ) { - let RewardsBook { - messages_relayers_rewards, - confirm_relayer_rewards, - slot_relayers_rewards, - treasury_total_rewards, - } = slash_and_calculate_rewards::( - lane_id, - messages_relayers, - confirmation_relayer.clone(), - received_range, - relayer_fund_account, - ); + let RewardsBook { for_deliver, for_confirm, slot_relayer, treasury } = + slash_and_calculate_rewards::( + lane_id, + messages_relayers, + confirmation_relayer.clone(), + received_range, + relayer_fund_account, + ); // Pay confirmation relayer rewards - do_reward::(relayer_fund_account, confirmation_relayer, confirm_relayer_rewards); + do_reward::(relayer_fund_account, confirmation_relayer, for_confirm); // Pay messages relayers rewards - for (relayer, reward) in messages_relayers_rewards { + for (relayer, reward) in for_deliver { do_reward::(relayer_fund_account, &relayer, reward); } // Pay assign relayer reward - for (relayer, reward) in slot_relayers_rewards { + for (relayer, reward) in slot_relayer { do_reward::(relayer_fund_account, &relayer, reward); } // Pay treasury reward do_reward::( relayer_fund_account, &T::TreasuryPalletId::get().into_account(), - treasury_total_rewards, + treasury, ); } } @@ -158,7 +154,6 @@ where if let Some((who, base_fee)) = order.required_delivery_relayer_for_time(order_confirm_time) { - println!("delivered in time"); // message fee - base fee => treasury reward_item.to_treasury = Some(message_fee.saturating_sub(base_fee)); @@ -207,6 +202,12 @@ where reward_item.to_message_relayer = Some((entry.clone().relayer, message_reward)); reward_item.to_confirm_relayer = Some((confirm_relayer.clone(), confirm_reward)); + Pallet::::deposit_event(Event::OrderReward( + lane_id, + message_nonce, + reward_item.clone(), + )); + rewards_book.add_reward_item(reward_item); } } @@ -278,7 +279,7 @@ pub(crate) fn do_reward, I: 'static>( } /// Record the concrete reward distribution of certain order -#[derive(Clone, Debug, Eq, PartialEq, TypeInfo)] +#[derive(Clone, Debug, Encode, Decode, Eq, PartialEq, TypeInfo)] pub struct RewardItem { pub to_slot_relayer: Option<(AccountId, Balance)>, pub to_treasury: Option, @@ -300,43 +301,43 @@ impl RewardItem { /// Record the calculation rewards result #[derive(Clone, Debug, Eq, PartialEq, TypeInfo)] pub struct RewardsBook, I: 'static> { - pub messages_relayers_rewards: BTreeMap>, - pub confirm_relayer_rewards: BalanceOf, - pub slot_relayers_rewards: BTreeMap>, - pub treasury_total_rewards: BalanceOf, + pub for_deliver: BTreeMap>, + pub for_confirm: BalanceOf, + pub slot_relayer: BTreeMap>, + pub treasury: BalanceOf, } impl, I: 'static> RewardsBook { fn new() -> Self { Self { - messages_relayers_rewards: BTreeMap::new(), - confirm_relayer_rewards: BalanceOf::::zero(), - slot_relayers_rewards: BTreeMap::new(), - treasury_total_rewards: BalanceOf::::zero(), + for_deliver: BTreeMap::new(), + for_confirm: BalanceOf::::zero(), + slot_relayer: BTreeMap::new(), + treasury: BalanceOf::::zero(), } } - fn add_reward_item(&mut self, order_reward: RewardItem>) { - if let Some((id, reward)) = order_reward.to_slot_relayer { - self.slot_relayers_rewards + fn add_reward_item(&mut self, item: RewardItem>) { + if let Some((id, reward)) = item.to_slot_relayer { + self.slot_relayer .entry(id) .and_modify(|r| *r = r.saturating_add(reward)) .or_insert(reward); } - if let Some(reward) = order_reward.to_treasury { - self.treasury_total_rewards = self.treasury_total_rewards.saturating_add(reward); + if let Some(reward) = item.to_treasury { + self.treasury = self.treasury.saturating_add(reward); } - if let Some((id, reward)) = order_reward.to_message_relayer { - self.messages_relayers_rewards + if let Some((id, reward)) = item.to_message_relayer { + self.for_deliver .entry(id) .and_modify(|r| *r = r.saturating_add(reward)) .or_insert(reward); } - if let Some((_id, reward)) = order_reward.to_confirm_relayer { - self.confirm_relayer_rewards = self.confirm_relayer_rewards.saturating_add(reward); + if let Some((_id, reward)) = item.to_confirm_relayer { + self.for_confirm = self.for_confirm.saturating_add(reward); } } } From 7a3330be354ce4772a703d427c719f888b0bb926 Mon Sep 17 00:00:00 2001 From: bear Date: Mon, 23 May 2022 14:13:38 +0800 Subject: [PATCH 3/8] Fix test --- modules/fee-market/src/tests.rs | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/modules/fee-market/src/tests.rs b/modules/fee-market/src/tests.rs index fdd5ffe13..76ee4cfbd 100644 --- a/modules/fee-market/src/tests.rs +++ b/modules/fee-market/src/tests.rs @@ -291,10 +291,10 @@ impl MessageDeliveryAndDispatchPayment relayer_fund_account: &AccountId, ) { let RewardsBook { - messages_relayers_rewards, - confirm_relayer_rewards, - slot_relayers_rewards, - treasury_total_rewards, + for_deliver, + for_confirm, + slot_relayer, + treasury, } = slash_and_calculate_rewards::( lane_id, message_relayers, @@ -304,22 +304,22 @@ impl MessageDeliveryAndDispatchPayment ); let confimation_key = - (b":relayer-reward:", confirmation_relayer, confirm_relayer_rewards).encode(); + (b":relayer-reward:", confirmation_relayer, for_confirm).encode(); frame_support::storage::unhashed::put(&confimation_key, &true); - for (relayer, reward) in &messages_relayers_rewards { + for (relayer, reward) in &for_deliver { let key = (b":relayer-reward:", relayer, reward).encode(); frame_support::storage::unhashed::put(&key, &true); } - for (relayer, reward) in &slot_relayers_rewards { + for (relayer, reward) in &slot_relayer { let key = (b":relayer-reward:", relayer, reward).encode(); frame_support::storage::unhashed::put(&key, &true); } let treasury_account: AccountId = ::TreasuryPalletId::get().into_account(); let treasury_key = - (b":relayer-reward:", &treasury_account, treasury_total_rewards).encode(); + (b":relayer-reward:", &treasury_account, treasury).encode(); frame_support::storage::unhashed::put(&treasury_key, &true); } } From 7ddeec677f5476126254a6a9aac6697d975d63ad Mon Sep 17 00:00:00 2001 From: bear Date: Mon, 23 May 2022 14:34:34 +0800 Subject: [PATCH 4/8] Add OrderCreated event --- modules/fee-market/README.md | 2 +- modules/fee-market/src/lib.rs | 4 +- modules/fee-market/src/s2s/callbacks.rs | 14 ++++-- modules/fee-market/src/s2s/payment.rs | 58 ++++++++++++------------- modules/fee-market/src/tests.rs | 34 ++++++--------- 5 files changed, 58 insertions(+), 54 deletions(-) diff --git a/modules/fee-market/README.md b/modules/fee-market/README.md index 180b67b01..f212deae8 100644 --- a/modules/fee-market/README.md +++ b/modules/fee-market/README.md @@ -37,7 +37,7 @@ For simplicity, if count of relayers in current market are less than MIN_ASSIGNE 2. **_Pn_** is consumed in the module relayer fund account. 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 Pn, and message relayer can claim 80% * (1 - 60%) from Pn, confirm relayer can claim 20% * (1 - 60%) from Pn, (P3 - Pn) will go to treasury. + 1. If the order is confirmed in Rn's slot, then Rn can claim 60% from the reward Pn, and message relayer can claim 80% * (1 - 60%) from Pn, confirm relayer can claim 20% * (1 - 60%) from Pn, (P3 - Pn) will go to treasury_sum. 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. diff --git a/modules/fee-market/src/lib.rs b/modules/fee-market/src/lib.rs index 9309b504c..873938686 100644 --- a/modules/fee-market/src/lib.rs +++ b/modules/fee-market/src/lib.rs @@ -108,7 +108,9 @@ pub mod pallet { UpdateAssignedRelayersNumber(u32), /// Slash report FeeMarketSlash(SlashReport>), - /// Order reward \[lane_id, message_nonce, rewards\] + /// Order Create. \[lane_id, message_nonce, order_fee, out_of_slot_time\] + OrderCreated(LaneId, MessageNonce, BalanceOf, Option), + /// Order reward. \[lane_id, message_nonce, rewards\] OrderReward(LaneId, MessageNonce, RewardItem>), } diff --git a/modules/fee-market/src/s2s/callbacks.rs b/modules/fee-market/src/s2s/callbacks.rs index d2895b543..ab25dd5fd 100644 --- a/modules/fee-market/src/s2s/callbacks.rs +++ b/modules/fee-market/src/s2s/callbacks.rs @@ -42,11 +42,19 @@ impl, I: 'static> OnMessageAccepted for FeeMarketMessageAcceptedHan ); // Store the create order >::insert((order.lane, order.message), order.clone()); + + Pallet::::deposit_event(Event::OrderCreated( + order.lane, + order.message, + order.fee(), + order.range_end(), + )); } - // one read for assigned relayers - // one write for store order - ::DbWeight::get().reads_writes(1, 1) + // Storage: FeeMarket AssignedRelayers (r:1 w:0) + // Storage: FeeMarket Orders (r:0 w:1) + // Storage: System Events (r:0 w:1) + ::DbWeight::get().reads_writes(1, 2) } } diff --git a/modules/fee-market/src/s2s/payment.rs b/modules/fee-market/src/s2s/payment.rs index c79a5d6c7..3d0e8184c 100644 --- a/modules/fee-market/src/s2s/payment.rs +++ b/modules/fee-market/src/s2s/payment.rs @@ -89,7 +89,7 @@ where received_range: &RangeInclusive, relayer_fund_account: &T::AccountId, ) { - let RewardsBook { for_deliver, for_confirm, slot_relayer, treasury } = + let RewardsBook { deliver_sum, confirm_sum, slot_relayer_sum, treasury_sum } = slash_and_calculate_rewards::( lane_id, messages_relayers, @@ -99,25 +99,25 @@ where ); // Pay confirmation relayer rewards - do_reward::(relayer_fund_account, confirmation_relayer, for_confirm); + do_reward::(relayer_fund_account, confirmation_relayer, confirm_sum); // Pay messages relayers rewards - for (relayer, reward) in for_deliver { + for (relayer, reward) in deliver_sum { do_reward::(relayer_fund_account, &relayer, reward); } // Pay assign relayer reward - for (relayer, reward) in slot_relayer { + for (relayer, reward) in slot_relayer_sum { do_reward::(relayer_fund_account, &relayer, reward); } - // Pay treasury reward + // Pay treasury_sum reward do_reward::( relayer_fund_account, &T::TreasuryPalletId::get().into_account(), - treasury, + treasury_sum, ); } } -/// Slash and calculate rewards for messages_relayers, confirmation relayers, treasury, +/// Slash and calculate rewards for messages_relayers, confirmation relayers, treasury_sum, /// assigned_relayers pub fn slash_and_calculate_rewards( lane_id: LaneId, @@ -136,10 +136,8 @@ where let nonce_end = sp_std::cmp::min(entry.messages.end, *received_range.end()); for message_nonce in nonce_begin..nonce_end + 1 { - // The order created when message was accepted, so we can always get the order info - // below. + // The order created when message was accepted, so we can always get the order info. if let Some(order) = >::get(&(lane_id, message_nonce)) { - println!("find the order"); // The confirm_time of the order is set in the `OnDeliveryConfirmed` callback. And // the callback function was called as source chain received message delivery proof, // before the reward payment. @@ -154,20 +152,22 @@ where if let Some((who, base_fee)) = order.required_delivery_relayer_for_time(order_confirm_time) { - // message fee - base fee => treasury + // message fee - base fee => treasury_sum reward_item.to_treasury = Some(message_fee.saturating_sub(base_fee)); - // 60% * base fee => slot_relayer_reward + // AssignedRelayersRewardRatio * base fee => slot relayer let slot_relayer_reward = T::AssignedRelayersRewardRatio::get() * base_fee; reward_item.to_slot_relayer = Some((who, slot_relayer_reward)); let bridger_relayers_reward = base_fee.saturating_sub(slot_relayer_reward); - // 80% * (1 - 60%) * base_fee => message relayer + // MessageRelayersRewardRatio * (1 - AssignedRelayersRewardRatio) * base_fee => + // message relayer message_reward = T::MessageRelayersRewardRatio::get() * bridger_relayers_reward; - // 20% * (1 - 60%) * base_fee => confirm relayer + // ConfirmRelayersRewardRatio * (1 - AssignedRelayersRewardRatio) * base_fee => + // confirm relayer confirm_reward = T::ConfirmRelayersRewardRatio::get() * bridger_relayers_reward; } else { - // The order delivery is delay + // The order delivery is delay, slash occurs. let mut total_slash = message_fee; // calculate slash amount @@ -193,9 +193,9 @@ where } total_slash += assigned_relayers_slash; - // 80% total slash => message relayer + // MessageRelayersRewardRatio total slash => message relayer message_reward = T::MessageRelayersRewardRatio::get() * total_slash; - // 20% total slash => confirm relayer + // ConfirmRelayersRewardRatio total slash => confirm relayer confirm_reward = T::ConfirmRelayersRewardRatio::get() * total_slash; } @@ -301,43 +301,43 @@ impl RewardItem { /// Record the calculation rewards result #[derive(Clone, Debug, Eq, PartialEq, TypeInfo)] pub struct RewardsBook, I: 'static> { - pub for_deliver: BTreeMap>, - pub for_confirm: BalanceOf, - pub slot_relayer: BTreeMap>, - pub treasury: BalanceOf, + pub deliver_sum: BTreeMap>, + pub confirm_sum: BalanceOf, + pub slot_relayer_sum: BTreeMap>, + pub treasury_sum: BalanceOf, } impl, I: 'static> RewardsBook { fn new() -> Self { Self { - for_deliver: BTreeMap::new(), - for_confirm: BalanceOf::::zero(), - slot_relayer: BTreeMap::new(), - treasury: BalanceOf::::zero(), + deliver_sum: BTreeMap::new(), + confirm_sum: BalanceOf::::zero(), + slot_relayer_sum: BTreeMap::new(), + treasury_sum: BalanceOf::::zero(), } } fn add_reward_item(&mut self, item: RewardItem>) { if let Some((id, reward)) = item.to_slot_relayer { - self.slot_relayer + self.slot_relayer_sum .entry(id) .and_modify(|r| *r = r.saturating_add(reward)) .or_insert(reward); } if let Some(reward) = item.to_treasury { - self.treasury = self.treasury.saturating_add(reward); + self.treasury_sum = self.treasury_sum.saturating_add(reward); } if let Some((id, reward)) = item.to_message_relayer { - self.for_deliver + self.deliver_sum .entry(id) .and_modify(|r| *r = r.saturating_add(reward)) .or_insert(reward); } if let Some((_id, reward)) = item.to_confirm_relayer { - self.for_confirm = self.for_confirm.saturating_add(reward); + self.confirm_sum = self.confirm_sum.saturating_add(reward); } } } diff --git a/modules/fee-market/src/tests.rs b/modules/fee-market/src/tests.rs index 76ee4cfbd..33762da2c 100644 --- a/modules/fee-market/src/tests.rs +++ b/modules/fee-market/src/tests.rs @@ -290,36 +290,30 @@ impl MessageDeliveryAndDispatchPayment received_range: &RangeInclusive, relayer_fund_account: &AccountId, ) { - let RewardsBook { - for_deliver, - for_confirm, - slot_relayer, - treasury, - } = slash_and_calculate_rewards::( - lane_id, - message_relayers, - confirmation_relayer.clone(), - received_range, - relayer_fund_account, - ); - - let confimation_key = - (b":relayer-reward:", confirmation_relayer, for_confirm).encode(); + let RewardsBook { deliver_sum, confirm_sum, slot_relayer_sum, treasury_sum } = + slash_and_calculate_rewards::( + lane_id, + message_relayers, + confirmation_relayer.clone(), + received_range, + relayer_fund_account, + ); + + let confimation_key = (b":relayer-reward:", confirmation_relayer, confirm_sum).encode(); frame_support::storage::unhashed::put(&confimation_key, &true); - for (relayer, reward) in &for_deliver { + for (relayer, reward) in &deliver_sum { let key = (b":relayer-reward:", relayer, reward).encode(); frame_support::storage::unhashed::put(&key, &true); } - for (relayer, reward) in &slot_relayer { + for (relayer, reward) in &slot_relayer_sum { let key = (b":relayer-reward:", relayer, reward).encode(); frame_support::storage::unhashed::put(&key, &true); } let treasury_account: AccountId = ::TreasuryPalletId::get().into_account(); - let treasury_key = - (b":relayer-reward:", &treasury_account, treasury).encode(); + let treasury_key = (b":relayer-reward:", &treasury_account, treasury_sum).encode(); frame_support::storage::unhashed::put(&treasury_key, &true); } } @@ -843,7 +837,7 @@ fn test_payment_cal_reward_normally_single_message() { // 1. assigned_relayers [(1, 30, 2-52),(2, 50, 52-102),(3, 100, 102-152)] -> id: 1, reward = // 60% * 30 = 18 2. message relayer -> id: 100, reward = 40% * 30 * 80% = 9.6 ~ 10 // 3. confirmation relayer -> id: 5, reward = 40% * 30 * 20% = 2.4 ~ 2 - // 4. treasury reward -> reward: 100 - 30 = 70 + // 4. treasury_sum reward -> reward: 100 - 30 = 70 let t: AccountId = ::TreasuryPalletId::get().into_account(); assert!(TestMessageDeliveryAndDispatchPayment::is_reward_paid(t, 70)); assert!(TestMessageDeliveryAndDispatchPayment::is_reward_paid(1, 18)); From 644e1269b8de9c85014a5e034f172dcb56506429 Mon Sep 17 00:00:00 2001 From: bear Date: Mon, 23 May 2022 14:43:52 +0800 Subject: [PATCH 5/8] Self review --- modules/fee-market/README.md | 2 +- modules/fee-market/src/lib.rs | 4 ++-- modules/fee-market/src/s2s/callbacks.rs | 2 +- modules/fee-market/src/s2s/payment.rs | 10 +++++----- modules/fee-market/src/tests.rs | 14 +++++++------- 5 files changed, 16 insertions(+), 16 deletions(-) diff --git a/modules/fee-market/README.md b/modules/fee-market/README.md index f212deae8..180b67b01 100644 --- a/modules/fee-market/README.md +++ b/modules/fee-market/README.md @@ -37,7 +37,7 @@ For simplicity, if count of relayers in current market are less than MIN_ASSIGNE 2. **_Pn_** is consumed in the module relayer fund account. 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 Pn, and message relayer can claim 80% * (1 - 60%) from Pn, confirm relayer can claim 20% * (1 - 60%) from Pn, (P3 - Pn) will go to treasury_sum. + 1. If the order is confirmed in Rn's slot, then Rn can claim 60% from the reward Pn, and message relayer can claim 80% * (1 - 60%) from Pn, confirm relayer can claim 20% * (1 - 60%) from Pn, (P3 - Pn) 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). 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. diff --git a/modules/fee-market/src/lib.rs b/modules/fee-market/src/lib.rs index 873938686..f3521ddd6 100644 --- a/modules/fee-market/src/lib.rs +++ b/modules/fee-market/src/lib.rs @@ -108,9 +108,9 @@ pub mod pallet { UpdateAssignedRelayersNumber(u32), /// Slash report FeeMarketSlash(SlashReport>), - /// Order Create. \[lane_id, message_nonce, order_fee, out_of_slot_time\] + /// Create new order. \[lane_id, message_nonce, order_fee, out_of_slots_time\] OrderCreated(LaneId, MessageNonce, BalanceOf, Option), - /// Order reward. \[lane_id, message_nonce, rewards\] + /// Reward distribute of the order. \[lane_id, message_nonce, rewards\] OrderReward(LaneId, MessageNonce, RewardItem>), } diff --git a/modules/fee-market/src/s2s/callbacks.rs b/modules/fee-market/src/s2s/callbacks.rs index ab25dd5fd..bf42e9074 100644 --- a/modules/fee-market/src/s2s/callbacks.rs +++ b/modules/fee-market/src/s2s/callbacks.rs @@ -54,7 +54,7 @@ impl, I: 'static> OnMessageAccepted for FeeMarketMessageAcceptedHan // Storage: FeeMarket AssignedRelayers (r:1 w:0) // Storage: FeeMarket Orders (r:0 w:1) // Storage: System Events (r:0 w:1) - ::DbWeight::get().reads_writes(1, 2) + ::DbWeight::get().reads_writes(1, 1) } } diff --git a/modules/fee-market/src/s2s/payment.rs b/modules/fee-market/src/s2s/payment.rs index 3d0e8184c..e3baca548 100644 --- a/modules/fee-market/src/s2s/payment.rs +++ b/modules/fee-market/src/s2s/payment.rs @@ -89,7 +89,7 @@ where received_range: &RangeInclusive, relayer_fund_account: &T::AccountId, ) { - let RewardsBook { deliver_sum, confirm_sum, slot_relayer_sum, treasury_sum } = + let RewardsBook { deliver_sum, confirm_sum, assigned_relayers_sum, treasury_sum } = slash_and_calculate_rewards::( lane_id, messages_relayers, @@ -105,7 +105,7 @@ where do_reward::(relayer_fund_account, &relayer, reward); } // Pay assign relayer reward - for (relayer, reward) in slot_relayer_sum { + for (relayer, reward) in assigned_relayers_sum { do_reward::(relayer_fund_account, &relayer, reward); } // Pay treasury_sum reward @@ -303,7 +303,7 @@ impl RewardItem { pub struct RewardsBook, I: 'static> { pub deliver_sum: BTreeMap>, pub confirm_sum: BalanceOf, - pub slot_relayer_sum: BTreeMap>, + pub assigned_relayers_sum: BTreeMap>, pub treasury_sum: BalanceOf, } @@ -312,14 +312,14 @@ impl, I: 'static> RewardsBook { Self { deliver_sum: BTreeMap::new(), confirm_sum: BalanceOf::::zero(), - slot_relayer_sum: BTreeMap::new(), + assigned_relayers_sum: BTreeMap::new(), treasury_sum: BalanceOf::::zero(), } } fn add_reward_item(&mut self, item: RewardItem>) { if let Some((id, reward)) = item.to_slot_relayer { - self.slot_relayer_sum + self.assigned_relayers_sum .entry(id) .and_modify(|r| *r = r.saturating_add(reward)) .or_insert(reward); diff --git a/modules/fee-market/src/tests.rs b/modules/fee-market/src/tests.rs index 33762da2c..c93aecac8 100644 --- a/modules/fee-market/src/tests.rs +++ b/modules/fee-market/src/tests.rs @@ -290,7 +290,7 @@ impl MessageDeliveryAndDispatchPayment received_range: &RangeInclusive, relayer_fund_account: &AccountId, ) { - let RewardsBook { deliver_sum, confirm_sum, slot_relayer_sum, treasury_sum } = + let RewardsBook { deliver_sum, confirm_sum, assigned_relayers_sum, treasury_sum } = slash_and_calculate_rewards::( lane_id, message_relayers, @@ -307,7 +307,7 @@ impl MessageDeliveryAndDispatchPayment frame_support::storage::unhashed::put(&key, &true); } - for (relayer, reward) in &slot_relayer_sum { + for (relayer, reward) in &assigned_relayers_sum { let key = (b":relayer-reward:", relayer, reward).encode(); frame_support::storage::unhashed::put(&key, &true); } @@ -833,11 +833,11 @@ fn test_payment_cal_reward_normally_single_message() { }, )); - // Analysis: - // 1. assigned_relayers [(1, 30, 2-52),(2, 50, 52-102),(3, 100, 102-152)] -> id: 1, reward = - // 60% * 30 = 18 2. message relayer -> id: 100, reward = 40% * 30 * 80% = 9.6 ~ 10 - // 3. confirmation relayer -> id: 5, reward = 40% * 30 * 20% = 2.4 ~ 2 - // 4. treasury_sum reward -> reward: 100 - 30 = 70 + // Reward Analysis: assigned_relayers [(1, 30, 2-52),(2, 50, 52-102),(3, 100, 102-152)] + // 1. slot relayer -> id: 1, reward = 60% * 30 = 18 + // 2. message relayer -> id: 100, reward = 40% * 30 * 80% = 9.6 ~ 10 + // 3. confirm relayer -> id: 5, reward = 40% * 30 * 20% = 2.4 ~ 2 + // 4. treasury reward -> reward = 100 - 30 = 70 let t: AccountId = ::TreasuryPalletId::get().into_account(); assert!(TestMessageDeliveryAndDispatchPayment::is_reward_paid(t, 70)); assert!(TestMessageDeliveryAndDispatchPayment::is_reward_paid(1, 18)); From 118fa9c38cb6b8af9abd2d5236c55655d3189c6c Mon Sep 17 00:00:00 2001 From: bear Date: Mon, 23 May 2022 15:02:49 +0800 Subject: [PATCH 6/8] Update comment --- modules/fee-market/src/s2s/callbacks.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/modules/fee-market/src/s2s/callbacks.rs b/modules/fee-market/src/s2s/callbacks.rs index bf42e9074..f0d8fa978 100644 --- a/modules/fee-market/src/s2s/callbacks.rs +++ b/modules/fee-market/src/s2s/callbacks.rs @@ -74,8 +74,7 @@ impl, I: 'static> OnDeliveryConfirmed for FeeMarketMessageConfirmed } } - // one db read for get order - // one db write for update order confirm time + // Storage: FeeMarket Orders (r:1 w:1) ::DbWeight::get().reads_writes(1, 1) } } From 4f2f202c0a0508deb5e9b8dca80d75ae697fd5f9 Mon Sep 17 00:00:00 2001 From: bear Date: Mon, 23 May 2022 17:42:27 +0800 Subject: [PATCH 7/8] Update OrderCreate event to include relayers --- modules/fee-market/src/lib.rs | 11 +++++++++-- modules/fee-market/src/s2s/callbacks.rs | 4 +++- modules/fee-market/src/tests.rs | 21 ++++++++++++++++++++- 3 files changed, 32 insertions(+), 4 deletions(-) diff --git a/modules/fee-market/src/lib.rs b/modules/fee-market/src/lib.rs index f3521ddd6..9cdaae89a 100644 --- a/modules/fee-market/src/lib.rs +++ b/modules/fee-market/src/lib.rs @@ -108,8 +108,15 @@ pub mod pallet { UpdateAssignedRelayersNumber(u32), /// Slash report FeeMarketSlash(SlashReport>), - /// Create new order. \[lane_id, message_nonce, order_fee, out_of_slots_time\] - OrderCreated(LaneId, MessageNonce, BalanceOf, Option), + /// Create new order. \[lane_id, message_nonce, assigned_relayers, order_fee, + /// out_of_slots_time\] + OrderCreated( + LaneId, + MessageNonce, + BalanceOf, + Vec, + Option, + ), /// Reward distribute of the order. \[lane_id, message_nonce, rewards\] OrderReward(LaneId, MessageNonce, RewardItem>), } diff --git a/modules/fee-market/src/s2s/callbacks.rs b/modules/fee-market/src/s2s/callbacks.rs index f0d8fa978..4ba1a470b 100644 --- a/modules/fee-market/src/s2s/callbacks.rs +++ b/modules/fee-market/src/s2s/callbacks.rs @@ -37,16 +37,18 @@ impl, I: 'static> OnMessageAccepted for FeeMarketMessageAcceptedHan *message, now, T::CollateralPerOrder::get(), - assigned_relayers, + assigned_relayers.clone(), T::Slot::get(), ); // Store the create order >::insert((order.lane, order.message), order.clone()); + let ids: Vec = assigned_relayers.iter().map(|r| r.id.clone()).collect(); Pallet::::deposit_event(Event::OrderCreated( order.lane, order.message, order.fee(), + ids, order.range_end(), )); } diff --git a/modules/fee-market/src/tests.rs b/modules/fee-market/src/tests.rs index c93aecac8..d07ca078a 100644 --- a/modules/fee-market/src/tests.rs +++ b/modules/fee-market/src/tests.rs @@ -761,6 +761,14 @@ fn test_callback_order_creation() { assert_eq!(relayers[1].id, assigned_relayers.get(1).unwrap().id); assert_eq!(relayers[2].id, assigned_relayers.get(2).unwrap().id); assert_eq!(order.sent_time, 2); + + System::assert_has_event(Event::FeeMarket(crate::Event::OrderCreated( + lane, + message_nonce, + order.fee(), + vec![relayers[0].id, relayers[1].id, relayers[2].id], + order.range_end(), + ))); }); } @@ -813,7 +821,7 @@ fn test_payment_cal_reward_normally_single_message() { let _ = FeeMarket::enroll_and_lock_collateral(Origin::signed(2), 110, Some(50)); let _ = FeeMarket::enroll_and_lock_collateral(Origin::signed(3), 120, Some(100)); let market_fee = FeeMarket::market_fee().unwrap(); - let (_, _) = send_regular_message(market_fee); + let (lane, message_nonce) = send_regular_message(market_fee); // Receive delivery message proof System::set_block_number(4); @@ -843,6 +851,17 @@ fn test_payment_cal_reward_normally_single_message() { assert!(TestMessageDeliveryAndDispatchPayment::is_reward_paid(1, 18)); assert!(TestMessageDeliveryAndDispatchPayment::is_reward_paid(5, 2)); assert!(TestMessageDeliveryAndDispatchPayment::is_reward_paid(TEST_RELAYER_A, 10)); + + System::assert_has_event(Event::FeeMarket(crate::Event::OrderReward( + lane, + message_nonce, + RewardItem { + to_slot_relayer: Some((1, 18)), + to_treasury: Some(70), + to_message_relayer: Some((100, 10)), + to_confirm_relayer: Some((5, 2)), + }, + ))); }); } From 622aeab04402dee45b29b6cc11a60e91effb0044 Mon Sep 17 00:00:00 2001 From: bear Date: Mon, 30 May 2022 13:56:45 +0800 Subject: [PATCH 8/8] Fix review --- modules/fee-market/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/fee-market/src/lib.rs b/modules/fee-market/src/lib.rs index 12414ebbd..d9c67b859 100644 --- a/modules/fee-market/src/lib.rs +++ b/modules/fee-market/src/lib.rs @@ -108,7 +108,7 @@ pub mod pallet { UpdateAssignedRelayersNumber(u32), /// Slash report FeeMarketSlash(SlashReport>), - /// Create new order. \[lane_id, message_nonce, assigned_relayers, order_fee, + /// Create new order. \[lane_id, message_nonce, order_fee, assigned_relayers, /// out_of_slots_time\] OrderCreated( LaneId,