diff --git a/Cargo.lock b/Cargo.lock index b344a77d6f4..279fe33f983 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -815,6 +815,8 @@ dependencies = [ "frame-support", "hex", "hex-literal", + "parity-scale-codec", + "scale-info", "sp-runtime", "sp-std", ] @@ -849,7 +851,7 @@ dependencies = [ "sp-state-machine", "sp-std", "sp-trie", - "trie-db", + "trie-db 0.26.0", ] [[package]] @@ -1116,6 +1118,7 @@ dependencies = [ "bp-messages", "bp-parachains", "bp-polkadot-core", + "bp-relayers", "bp-runtime", "bp-test-utils", "frame-support", @@ -6479,6 +6482,7 @@ dependencies = [ "frame-system", "log", "pallet-balances", + "pallet-bridge-messages", "parity-scale-codec", "scale-info", "sp-arithmetic", @@ -12568,7 +12572,7 @@ dependencies = [ "sp-std", "thiserror", "tracing", - "trie-db", + "trie-db 0.25.1", "trie-root", ] @@ -12990,7 +12994,7 @@ dependencies = [ "sp-runtime", "sp-state-machine", "sp-trie", - "trie-db", + "trie-db 0.25.1", ] [[package]] @@ -13654,6 +13658,19 @@ dependencies = [ "smallvec", ] +[[package]] +name = "trie-db" +version = "0.26.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "879380c0061b165ba1f036325b7f3478bc1a947814d9fc36d22c5d8e960b11bd" +dependencies = [ + "hash-db", + "hashbrown 0.13.2", + "log", + "rustc-hex", + "smallvec", +] + [[package]] name = "trie-root" version = "0.17.0" diff --git a/bridges/bin/runtime-common/Cargo.toml b/bridges/bin/runtime-common/Cargo.toml index 27e305751e4..dde9e70f576 100644 --- a/bridges/bin/runtime-common/Cargo.toml +++ b/bridges/bin/runtime-common/Cargo.toml @@ -19,6 +19,7 @@ bp-header-chain = { path = "../../primitives/header-chain", default-features = f bp-messages = { path = "../../primitives/messages", default-features = false } bp-parachains = { path = "../../primitives/parachains", default-features = false } bp-polkadot-core = { path = "../../primitives/polkadot-core", default-features = false } +bp-relayers = { path = "../../primitives/relayers", default-features = false } bp-runtime = { path = "../../primitives/runtime", default-features = false } pallet-bridge-grandpa = { path = "../../modules/grandpa", default-features = false } pallet-bridge-messages = { path = "../../modules/messages", default-features = false } diff --git a/bridges/bin/runtime-common/src/lib.rs b/bridges/bin/runtime-common/src/lib.rs index 32ea500db3e..d9c87049077 100644 --- a/bridges/bin/runtime-common/src/lib.rs +++ b/bridges/bin/runtime-common/src/lib.rs @@ -77,8 +77,7 @@ where /// even honest relayers may lose their funds if there are multiple relays running and /// submitting the same messages/confirmations. fn validate(call: &T::RuntimeCall) -> TransactionValidity { - call.check_obsolete_receive_messages_proof()?; - call.check_obsolete_receive_messages_delivery_proof() + call.check_obsolete_call() } } diff --git a/bridges/bin/runtime-common/src/messages_call_ext.rs b/bridges/bin/runtime-common/src/messages_call_ext.rs index 740d17129c8..588afad106d 100644 --- a/bridges/bin/runtime-common/src/messages_call_ext.rs +++ b/bridges/bin/runtime-common/src/messages_call_ext.rs @@ -22,25 +22,57 @@ use frame_support::{dispatch::CallableCallFor, traits::IsSubType, RuntimeDebug}; use pallet_bridge_messages::{Config, Pallet}; use sp_runtime::transaction_validity::TransactionValidity; -/// Info about a `ReceiveMessagesProof` call which tries to update a single lane. +/// Generic info about a messages delivery/confirmation proof. #[derive(PartialEq, RuntimeDebug)] -pub struct ReceiveMessagesProofInfo { +pub struct BaseMessagesProofInfo { pub lane_id: LaneId, - pub best_proof_nonce: MessageNonce, + pub best_bundled_nonce: MessageNonce, pub best_stored_nonce: MessageNonce, } -/// Helper struct that provides methods for working with the `ReceiveMessagesProof` call. -pub struct ReceiveMessagesProofHelper, I: 'static> { +impl BaseMessagesProofInfo { + fn is_obsolete(&self) -> bool { + self.best_bundled_nonce <= self.best_stored_nonce + } +} + +/// Info about a `ReceiveMessagesProof` call which tries to update a single lane. +#[derive(PartialEq, RuntimeDebug)] +pub struct ReceiveMessagesProofInfo(pub BaseMessagesProofInfo); + +/// Info about a `ReceiveMessagesDeliveryProof` call which tries to update a single lane. +#[derive(PartialEq, RuntimeDebug)] +pub struct ReceiveMessagesDeliveryProofInfo(pub BaseMessagesProofInfo); + +/// Info about a `ReceiveMessagesProof` or a `ReceiveMessagesDeliveryProof` call +/// which tries to update a single lane. +#[derive(PartialEq, RuntimeDebug)] +pub enum CallInfo { + ReceiveMessagesProof(ReceiveMessagesProofInfo), + ReceiveMessagesDeliveryProof(ReceiveMessagesDeliveryProofInfo), +} + +/// Helper struct that provides methods for working with a call supported by `CallInfo`. +pub struct CallHelper, I: 'static> { pub _phantom_data: sp_std::marker::PhantomData<(T, I)>, } -impl, I: 'static> ReceiveMessagesProofHelper { - /// Check if the `ReceiveMessagesProof` call delivered at least some of the messages that - /// it contained. - pub fn was_partially_successful(info: &ReceiveMessagesProofInfo) -> bool { - let inbound_lane_data = pallet_bridge_messages::InboundLanes::::get(info.lane_id); - inbound_lane_data.last_delivered_nonce() > info.best_stored_nonce +impl, I: 'static> CallHelper { + /// Check if a call delivered proof/confirmation for at least some of the messages that it + /// contained. + pub fn was_partially_successful(info: &CallInfo) -> bool { + match info { + CallInfo::ReceiveMessagesProof(info) => { + let inbound_lane_data = + pallet_bridge_messages::InboundLanes::::get(info.0.lane_id); + inbound_lane_data.last_delivered_nonce() > info.0.best_stored_nonce + }, + CallInfo::ReceiveMessagesDeliveryProof(info) => { + let outbound_lane_data = + pallet_bridge_messages::OutboundLanes::::get(info.0.lane_id); + outbound_lane_data.latest_received_nonce > info.0.best_stored_nonce + }, + } } } @@ -51,17 +83,21 @@ pub trait MessagesCallSubType, I: 'static>: /// Create a new instance of `ReceiveMessagesProofInfo` from a `ReceiveMessagesProof` call. fn receive_messages_proof_info(&self) -> Option; - /// Create a new instance of `ReceiveMessagesProofInfo` from a `ReceiveMessagesProof` call, - /// if the call is for the provided lane. - fn receive_messages_proof_info_for(&self, lane_id: LaneId) -> Option; + /// Create a new instance of `ReceiveMessagesDeliveryProofInfo` from + /// a `ReceiveMessagesDeliveryProof` call. + fn receive_messages_delivery_proof_info(&self) -> Option; + + /// Create a new instance of `CallInfo` from a `ReceiveMessagesProof` + /// or a `ReceiveMessagesDeliveryProof` call. + fn call_info(&self) -> Option; - /// Check that a `ReceiveMessagesProof` call is trying to deliver at least some messages that - /// are better than the ones we know of. - fn check_obsolete_receive_messages_proof(&self) -> TransactionValidity; + /// Create a new instance of `CallInfo` from a `ReceiveMessagesProof` + /// or a `ReceiveMessagesDeliveryProof` call, if the call is for the provided lane. + fn call_info_for(&self, lane_id: LaneId) -> Option; - /// Check that a `ReceiveMessagesDeliveryProof` call is trying to deliver at least some message - /// confirmations that are better than the ones we know of. - fn check_obsolete_receive_messages_delivery_proof(&self) -> TransactionValidity; + /// Check that a `ReceiveMessagesProof` or a `ReceiveMessagesDeliveryProof` call is trying + /// to deliver/confirm at least some messages that are better than the ones we know of. + fn check_obsolete_call(&self) -> TransactionValidity; } impl< @@ -88,40 +124,17 @@ impl< { let inbound_lane_data = pallet_bridge_messages::InboundLanes::::get(proof.lane); - return Some(ReceiveMessagesProofInfo { + return Some(ReceiveMessagesProofInfo(BaseMessagesProofInfo { lane_id: proof.lane, - best_proof_nonce: proof.nonces_end, + best_bundled_nonce: proof.nonces_end, best_stored_nonce: inbound_lane_data.last_delivered_nonce(), - }) + })) } None } - fn receive_messages_proof_info_for(&self, lane_id: LaneId) -> Option { - self.receive_messages_proof_info().filter(|info| info.lane_id == lane_id) - } - - fn check_obsolete_receive_messages_proof(&self) -> TransactionValidity { - if let Some(proof_info) = self.receive_messages_proof_info() { - if proof_info.best_proof_nonce <= proof_info.best_stored_nonce { - log::trace!( - target: pallet_bridge_messages::LOG_TARGET, - "Rejecting obsolete messages delivery transaction: \ - lane {:?}, bundled {:?}, best {:?}", - proof_info.lane_id, - proof_info.best_proof_nonce, - proof_info.best_stored_nonce, - ); - - return sp_runtime::transaction_validity::InvalidTransaction::Stale.into() - } - } - - Ok(sp_runtime::transaction_validity::ValidTransaction::default()) - } - - fn check_obsolete_receive_messages_delivery_proof(&self) -> TransactionValidity { + fn receive_messages_delivery_proof_info(&self) -> Option { if let Some(pallet_bridge_messages::Call::::receive_messages_delivery_proof { ref proof, ref relayers_state, @@ -129,18 +142,62 @@ impl< }) = self.is_sub_type() { let outbound_lane_data = pallet_bridge_messages::OutboundLanes::::get(proof.lane); - if relayers_state.last_delivered_nonce <= outbound_lane_data.latest_received_nonce { + + return Some(ReceiveMessagesDeliveryProofInfo(BaseMessagesProofInfo { + lane_id: proof.lane, + best_bundled_nonce: relayers_state.last_delivered_nonce, + best_stored_nonce: outbound_lane_data.latest_received_nonce, + })) + } + + None + } + + fn call_info(&self) -> Option { + if let Some(info) = self.receive_messages_proof_info() { + return Some(CallInfo::ReceiveMessagesProof(info)) + } + + if let Some(info) = self.receive_messages_delivery_proof_info() { + return Some(CallInfo::ReceiveMessagesDeliveryProof(info)) + } + + None + } + + fn call_info_for(&self, lane_id: LaneId) -> Option { + self.call_info().filter(|info| { + let actual_lane_id = match info { + CallInfo::ReceiveMessagesProof(info) => info.0.lane_id, + CallInfo::ReceiveMessagesDeliveryProof(info) => info.0.lane_id, + }; + actual_lane_id == lane_id + }) + } + + fn check_obsolete_call(&self) -> TransactionValidity { + match self.call_info() { + Some(CallInfo::ReceiveMessagesProof(proof_info)) if proof_info.0.is_obsolete() => { log::trace!( target: pallet_bridge_messages::LOG_TARGET, - "Rejecting obsolete messages confirmation transaction: \ - lane {:?}, bundled {:?}, best {:?}", - proof.lane, - relayers_state.last_delivered_nonce, - outbound_lane_data.latest_received_nonce, + "Rejecting obsolete messages delivery transaction: {:?}", + proof_info ); return sp_runtime::transaction_validity::InvalidTransaction::Stale.into() - } + }, + Some(CallInfo::ReceiveMessagesDeliveryProof(proof_info)) + if proof_info.0.is_obsolete() => + { + log::trace!( + target: pallet_bridge_messages::LOG_TARGET, + "Rejecting obsolete messages confirmation transaction: {:?}", + proof_info, + ); + + return sp_runtime::transaction_validity::InvalidTransaction::Stale.into() + }, + _ => {}, } Ok(sp_runtime::transaction_validity::ValidTransaction::default()) @@ -153,8 +210,8 @@ mod tests { messages::{ source::FromBridgedChainMessagesDeliveryProof, target::FromBridgedChainMessagesProof, }, + messages_call_ext::MessagesCallSubType, mock::{TestRuntime, ThisChainRuntimeCall}, - BridgeRuntimeFilterCall, }; use bp_messages::UnrewardedRelayersState; @@ -169,22 +226,21 @@ mod tests { nonces_start: bp_messages::MessageNonce, nonces_end: bp_messages::MessageNonce, ) -> bool { - pallet_bridge_messages::Pallet::::validate( - &ThisChainRuntimeCall::BridgeMessages( - pallet_bridge_messages::Call::::receive_messages_proof { - relayer_id_at_bridged_chain: 42, - messages_count: (nonces_end - nonces_start + 1) as u32, - dispatch_weight: frame_support::weights::Weight::zero(), - proof: FromBridgedChainMessagesProof { - bridged_header_hash: Default::default(), - storage_proof: vec![], - lane: bp_messages::LaneId([0, 0, 0, 0]), - nonces_start, - nonces_end, - }, + ThisChainRuntimeCall::BridgeMessages( + pallet_bridge_messages::Call::::receive_messages_proof { + relayer_id_at_bridged_chain: 42, + messages_count: (nonces_end - nonces_start + 1) as u32, + dispatch_weight: frame_support::weights::Weight::zero(), + proof: FromBridgedChainMessagesProof { + bridged_header_hash: Default::default(), + storage_proof: vec![], + lane: bp_messages::LaneId([0, 0, 0, 0]), + nonces_start, + nonces_end, }, - ), + }, ) + .check_obsolete_call() .is_ok() } @@ -230,21 +286,20 @@ mod tests { } fn validate_message_confirmation(last_delivered_nonce: bp_messages::MessageNonce) -> bool { - pallet_bridge_messages::Pallet::::validate( - &ThisChainRuntimeCall::BridgeMessages( - pallet_bridge_messages::Call::::receive_messages_delivery_proof { - proof: FromBridgedChainMessagesDeliveryProof { - bridged_header_hash: Default::default(), - storage_proof: Vec::new(), - lane: bp_messages::LaneId([0, 0, 0, 0]), - }, - relayers_state: UnrewardedRelayersState { - last_delivered_nonce, - ..Default::default() - }, + ThisChainRuntimeCall::BridgeMessages( + pallet_bridge_messages::Call::::receive_messages_delivery_proof { + proof: FromBridgedChainMessagesDeliveryProof { + bridged_header_hash: Default::default(), + storage_proof: Vec::new(), + lane: bp_messages::LaneId([0, 0, 0, 0]), + }, + relayers_state: UnrewardedRelayersState { + last_delivered_nonce, + ..Default::default() }, - ), + }, ) + .check_obsolete_call() .is_ok() } diff --git a/bridges/bin/runtime-common/src/mock.rs b/bridges/bin/runtime-common/src/mock.rs index a5ae9131f03..c2cd8e9ba83 100644 --- a/bridges/bin/runtime-common/src/mock.rs +++ b/bridges/bin/runtime-common/src/mock.rs @@ -85,6 +85,8 @@ pub type BridgedChainHeader = /// Message lane used in tests. pub const TEST_LANE_ID: LaneId = LaneId([0, 0, 0, 0]); +/// Bridged chain id used in tests. +pub const TEST_BRIDGED_CHAIN_ID: ChainId = *b"brdg"; /// Maximal number of queued messages at the test lane. pub const MAXIMAL_PENDING_MESSAGES_AT_TEST_LANE: MessageNonce = 32; /// Minimal extrinsic weight at the `BridgedChain`. @@ -118,7 +120,7 @@ crate::generate_bridge_reject_obsolete_headers_and_messages! { parameter_types! { pub const ActiveOutboundLanes: &'static [LaneId] = &[TEST_LANE_ID]; - pub const BridgedChainId: ChainId = *b"brdg"; + pub const BridgedChainId: ChainId = TEST_BRIDGED_CHAIN_ID; pub const BridgedParasPalletName: &'static str = "Paras"; pub const ExistentialDeposit: ThisChainBalance = 500; pub const DbWeight: RuntimeDbWeight = RuntimeDbWeight { read: 1, write: 2 }; @@ -227,8 +229,8 @@ impl pallet_bridge_messages::Config for TestRuntime { type LaneMessageVerifier = FromThisChainMessageVerifier; type DeliveryConfirmationPayments = pallet_bridge_relayers::DeliveryConfirmationPaymentsAdapter< TestRuntime, - frame_support::traits::ConstU64<100_000>, - frame_support::traits::ConstU64<10_000>, + (), + ConstU64<100_000>, >; type SourceHeaderChain = SourceHeaderChainAdapter; @@ -251,7 +253,7 @@ pub struct OnThisChainBridge; impl MessageBridge for OnThisChainBridge { const THIS_CHAIN_ID: ChainId = *b"this"; - const BRIDGED_CHAIN_ID: ChainId = *b"brdg"; + const BRIDGED_CHAIN_ID: ChainId = TEST_BRIDGED_CHAIN_ID; const BRIDGED_MESSAGES_PALLET_NAME: &'static str = ""; type ThisChain = ThisChain; @@ -265,7 +267,7 @@ impl MessageBridge for OnThisChainBridge { pub struct OnBridgedChainBridge; impl MessageBridge for OnBridgedChainBridge { - const THIS_CHAIN_ID: ChainId = *b"brdg"; + const THIS_CHAIN_ID: ChainId = TEST_BRIDGED_CHAIN_ID; const BRIDGED_CHAIN_ID: ChainId = *b"this"; const BRIDGED_MESSAGES_PALLET_NAME: &'static str = ""; diff --git a/bridges/bin/runtime-common/src/refund_relayer_extension.rs b/bridges/bin/runtime-common/src/refund_relayer_extension.rs index df4eae6f737..0a61f4fdd02 100644 --- a/bridges/bin/runtime-common/src/refund_relayer_extension.rs +++ b/bridges/bin/runtime-common/src/refund_relayer_extension.rs @@ -20,9 +20,10 @@ //! (parachain or relay chain). use crate::messages_call_ext::{ - MessagesCallSubType, ReceiveMessagesProofHelper, ReceiveMessagesProofInfo, + CallHelper as MessagesCallHelper, CallInfo as MessagesCallInfo, MessagesCallSubType, }; use bp_messages::LaneId; +use bp_relayers::{RewardsAccountOwner, RewardsAccountParams}; use bp_runtime::StaticStrProvider; use codec::{Decode, Encode}; use frame_support::{ @@ -142,23 +143,23 @@ pub struct PreDispatchData { /// Type of the call that the extension recognizes. #[derive(RuntimeDebugNoBound, PartialEq)] pub enum CallInfo { - /// Relay chain finality + parachain finality + message delivery calls. - AllFinalityAndDelivery( + /// Relay chain finality + parachain finality + message delivery/confirmation calls. + AllFinalityAndMsgs( SubmitFinalityProofInfo, SubmitParachainHeadsInfo, - ReceiveMessagesProofInfo, + MessagesCallInfo, ), - /// Parachain finality + message delivery calls. - ParachainFinalityAndDelivery(SubmitParachainHeadsInfo, ReceiveMessagesProofInfo), - /// Standalone message delivery call. - Delivery(ReceiveMessagesProofInfo), + /// Parachain finality + message delivery/confirmation calls. + ParachainFinalityAndMsgs(SubmitParachainHeadsInfo, MessagesCallInfo), + /// Standalone message delivery/confirmation call. + Msgs(MessagesCallInfo), } impl CallInfo { /// Returns the pre-dispatch `finality_target` sent to the `SubmitFinalityProof` call. fn submit_finality_proof_info(&self) -> Option> { match *self { - Self::AllFinalityAndDelivery(info, _, _) => Some(info), + Self::AllFinalityAndMsgs(info, _, _) => Some(info), _ => None, } } @@ -166,18 +167,18 @@ impl CallInfo { /// Returns the pre-dispatch `SubmitParachainHeadsInfo`. fn submit_parachain_heads_info(&self) -> Option<&SubmitParachainHeadsInfo> { match self { - Self::AllFinalityAndDelivery(_, info, _) => Some(info), - Self::ParachainFinalityAndDelivery(info, _) => Some(info), + Self::AllFinalityAndMsgs(_, info, _) => Some(info), + Self::ParachainFinalityAndMsgs(info, _) => Some(info), _ => None, } } /// Returns the pre-dispatch `ReceiveMessagesProofInfo`. - fn receive_messages_proof_info(&self) -> &ReceiveMessagesProofInfo { + fn messages_call_info(&self) -> &MessagesCallInfo { match self { - Self::AllFinalityAndDelivery(_, _, info) => info, - Self::ParachainFinalityAndDelivery(_, info) => info, - Self::Delivery(info) => info, + Self::AllFinalityAndMsgs(_, _, info) => info, + Self::ParachainFinalityAndMsgs(_, info) => info, + Self::Msgs(info) => info, } } } @@ -268,7 +269,7 @@ where for nested_call in calls { nested_call.check_obsolete_submit_finality_proof()?; nested_call.check_obsolete_submit_parachain_heads()?; - nested_call.check_obsolete_receive_messages_proof()?; + nested_call.check_obsolete_call()?; } } @@ -289,18 +290,16 @@ where let parse_call = || { let mut calls = self.expand_call(call)?.into_iter(); match calls.len() { - 3 => Some(CallInfo::AllFinalityAndDelivery( + 3 => Some(CallInfo::AllFinalityAndMsgs( calls.next()?.submit_finality_proof_info()?, calls.next()?.submit_parachain_heads_info_for(Para::Id::get())?, - calls.next()?.receive_messages_proof_info_for(Msgs::Id::get())?, + calls.next()?.call_info_for(Msgs::Id::get())?, )), - 2 => Some(CallInfo::ParachainFinalityAndDelivery( + 2 => Some(CallInfo::ParachainFinalityAndMsgs( calls.next()?.submit_parachain_heads_info_for(Para::Id::get())?, - calls.next()?.receive_messages_proof_info_for(Msgs::Id::get())?, - )), - 1 => Some(CallInfo::Delivery( - calls.next()?.receive_messages_proof_info_for(Msgs::Id::get())?, + calls.next()?.call_info_for(Msgs::Id::get())?, )), + 1 => Some(CallInfo::Msgs(calls.next()?.call_info_for(Msgs::Id::get())?)), _ => None, } }; @@ -373,10 +372,9 @@ where // Check if the `ReceiveMessagesProof` call delivered at least some of the messages that // it contained. If this happens, we consider the transaction "helpful" and refund it. - let msgs_proof_info = call_info.receive_messages_proof_info(); - if !ReceiveMessagesProofHelper::::was_partially_successful( - msgs_proof_info, - ) { + let msgs_call_info = call_info.messages_call_info(); + if !MessagesCallHelper::::was_partially_successful(msgs_call_info) + { return Ok(()) } @@ -397,7 +395,19 @@ where let refund = Refund::compute_refund(info, &post_info, post_info_len, tip); // finally - register refund in relayers pallet - RelayersPallet::::register_relayer_reward(Msgs::Id::get(), &relayer, refund); + let rewards_account_owner = match msgs_call_info { + MessagesCallInfo::ReceiveMessagesProof(_) => RewardsAccountOwner::ThisChain, + MessagesCallInfo::ReceiveMessagesDeliveryProof(_) => RewardsAccountOwner::BridgedChain, + }; + RelayersPallet::::register_relayer_reward( + RewardsAccountParams::new( + Msgs::Id::get(), + Runtime::BridgedChainId::get(), + rewards_account_owner, + ), + &relayer, + refund, + ); log::trace!( target: "runtime::bridge", @@ -416,8 +426,16 @@ where #[cfg(test)] mod tests { use super::*; - use crate::{messages::target::FromBridgedChainMessagesProof, mock::*}; - use bp_messages::{InboundLaneData, MessageNonce}; + use crate::{ + messages::{ + source::FromBridgedChainMessagesDeliveryProof, target::FromBridgedChainMessagesProof, + }, + messages_call_ext::{ + BaseMessagesProofInfo, ReceiveMessagesDeliveryProofInfo, ReceiveMessagesProofInfo, + }, + mock::*, + }; + use bp_messages::{InboundLaneData, MessageNonce, OutboundLaneData, UnrewardedRelayersState}; use bp_parachains::{BestParaHeadHash, ParaInfo}; use bp_polkadot_core::parachains::{ParaHash, ParaHeadsProof, ParaId}; use bp_runtime::HeaderId; @@ -433,6 +451,8 @@ mod tests { parameter_types! { TestParachain: u32 = 1000; pub TestLaneId: LaneId = TEST_LANE_ID; + pub MsgProofsRewardsAccount: RewardsAccountParams = RewardsAccountParams::new(TEST_LANE_ID, TEST_BRIDGED_CHAIN_ID, RewardsAccountOwner::ThisChain); + pub MsgDeliveryProofsRewardsAccount: RewardsAccountParams = RewardsAccountParams::new(TEST_LANE_ID, TEST_BRIDGED_CHAIN_ID, RewardsAccountOwner::BridgedChain); } bp_runtime::generate_static_str_provider!(TestExtension); @@ -456,7 +476,7 @@ mod tests { best_relay_header_number: RelayBlockNumber, parachain_head_at_relay_header_number: RelayBlockNumber, parachain_head_hash: ParaHash, - best_delivered_message: MessageNonce, + best_message: MessageNonce, ) { let authorities = test_keyring().into_iter().map(|(a, w)| (a.into(), w)).collect(); let best_relay_header = HeaderId(best_relay_header_number, RelayBlockHash::default()); @@ -476,9 +496,13 @@ mod tests { pallet_bridge_parachains::ParasInfo::::insert(para_id, para_info); let lane_id = TestLaneId::get(); - let lane_data = - InboundLaneData { last_confirmed_nonce: best_delivered_message, ..Default::default() }; - pallet_bridge_messages::InboundLanes::::insert(lane_id, lane_data); + let in_lane_data = + InboundLaneData { last_confirmed_nonce: best_message, ..Default::default() }; + pallet_bridge_messages::InboundLanes::::insert(lane_id, in_lane_data); + + let out_lane_data = + OutboundLaneData { latest_received_nonce: best_message, ..Default::default() }; + pallet_bridge_messages::OutboundLanes::::insert(lane_id, out_lane_data); } fn submit_relay_header_call(relay_header_number: RelayBlockNumber) -> RuntimeCall { @@ -522,6 +546,20 @@ mod tests { }) } + fn message_confirmation_call(best_message: MessageNonce) -> RuntimeCall { + RuntimeCall::BridgeMessages(MessagesCall::receive_messages_delivery_proof { + proof: FromBridgedChainMessagesDeliveryProof { + bridged_header_hash: Default::default(), + storage_proof: vec![], + lane: TestLaneId::get(), + }, + relayers_state: UnrewardedRelayersState { + last_delivered_nonce: best_message, + ..Default::default() + }, + }) + } + fn parachain_finality_and_delivery_batch_call( parachain_head_at_relay_header_number: RelayBlockNumber, best_message: MessageNonce, @@ -534,6 +572,18 @@ mod tests { }) } + fn parachain_finality_and_confirmation_batch_call( + parachain_head_at_relay_header_number: RelayBlockNumber, + best_message: MessageNonce, + ) -> RuntimeCall { + RuntimeCall::Utility(UtilityCall::batch_all { + calls: vec![ + submit_parachain_head_call(parachain_head_at_relay_header_number), + message_confirmation_call(best_message), + ], + }) + } + fn all_finality_and_delivery_batch_call( relay_header_number: RelayBlockNumber, parachain_head_at_relay_header_number: RelayBlockNumber, @@ -548,10 +598,24 @@ mod tests { }) } + fn all_finality_and_confirmation_batch_call( + relay_header_number: RelayBlockNumber, + parachain_head_at_relay_header_number: RelayBlockNumber, + best_message: MessageNonce, + ) -> RuntimeCall { + RuntimeCall::Utility(UtilityCall::batch_all { + calls: vec![ + submit_relay_header_call(relay_header_number), + submit_parachain_head_call(parachain_head_at_relay_header_number), + message_confirmation_call(best_message), + ], + }) + } + fn all_finality_pre_dispatch_data() -> PreDispatchData { PreDispatchData { relayer: relayer_account_at_this_chain(), - call_info: CallInfo::AllFinalityAndDelivery( + call_info: CallInfo::AllFinalityAndMsgs( SubmitFinalityProofInfo { block_number: 200, extra_weight: Weight::zero(), @@ -562,11 +626,38 @@ mod tests { para_id: ParaId(TestParachain::get()), para_head_hash: [1u8; 32].into(), }, - ReceiveMessagesProofInfo { - lane_id: TEST_LANE_ID, - best_proof_nonce: 200, - best_stored_nonce: 100, + MessagesCallInfo::ReceiveMessagesProof(ReceiveMessagesProofInfo( + BaseMessagesProofInfo { + lane_id: TEST_LANE_ID, + best_bundled_nonce: 200, + best_stored_nonce: 100, + }, + )), + ), + } + } + + fn all_finality_confirmation_pre_dispatch_data() -> PreDispatchData { + PreDispatchData { + relayer: relayer_account_at_this_chain(), + call_info: CallInfo::AllFinalityAndMsgs( + SubmitFinalityProofInfo { + block_number: 200, + extra_weight: Weight::zero(), + extra_size: 0, + }, + SubmitParachainHeadsInfo { + at_relay_block_number: 200, + para_id: ParaId(TestParachain::get()), + para_head_hash: [1u8; 32].into(), }, + MessagesCallInfo::ReceiveMessagesDeliveryProof(ReceiveMessagesDeliveryProofInfo( + BaseMessagesProofInfo { + lane_id: TEST_LANE_ID, + best_bundled_nonce: 200, + best_stored_nonce: 100, + }, + )), ), } } @@ -574,17 +665,39 @@ mod tests { fn parachain_finality_pre_dispatch_data() -> PreDispatchData { PreDispatchData { relayer: relayer_account_at_this_chain(), - call_info: CallInfo::ParachainFinalityAndDelivery( + call_info: CallInfo::ParachainFinalityAndMsgs( SubmitParachainHeadsInfo { at_relay_block_number: 200, para_id: ParaId(TestParachain::get()), para_head_hash: [1u8; 32].into(), }, - ReceiveMessagesProofInfo { - lane_id: TEST_LANE_ID, - best_proof_nonce: 200, - best_stored_nonce: 100, + MessagesCallInfo::ReceiveMessagesProof(ReceiveMessagesProofInfo( + BaseMessagesProofInfo { + lane_id: TEST_LANE_ID, + best_bundled_nonce: 200, + best_stored_nonce: 100, + }, + )), + ), + } + } + + fn parachain_finality_confirmation_pre_dispatch_data() -> PreDispatchData { + PreDispatchData { + relayer: relayer_account_at_this_chain(), + call_info: CallInfo::ParachainFinalityAndMsgs( + SubmitParachainHeadsInfo { + at_relay_block_number: 200, + para_id: ParaId(TestParachain::get()), + para_head_hash: [1u8; 32].into(), }, + MessagesCallInfo::ReceiveMessagesDeliveryProof(ReceiveMessagesDeliveryProofInfo( + BaseMessagesProofInfo { + lane_id: TEST_LANE_ID, + best_bundled_nonce: 200, + best_stored_nonce: 100, + }, + )), ), } } @@ -592,11 +705,26 @@ mod tests { fn delivery_pre_dispatch_data() -> PreDispatchData { PreDispatchData { relayer: relayer_account_at_this_chain(), - call_info: CallInfo::Delivery(ReceiveMessagesProofInfo { - lane_id: TEST_LANE_ID, - best_proof_nonce: 200, - best_stored_nonce: 100, - }), + call_info: CallInfo::Msgs(MessagesCallInfo::ReceiveMessagesProof( + ReceiveMessagesProofInfo(BaseMessagesProofInfo { + lane_id: TEST_LANE_ID, + best_bundled_nonce: 200, + best_stored_nonce: 100, + }), + )), + } + } + + fn confirmation_pre_dispatch_data() -> PreDispatchData { + PreDispatchData { + relayer: relayer_account_at_this_chain(), + call_info: CallInfo::Msgs(MessagesCallInfo::ReceiveMessagesDeliveryProof( + ReceiveMessagesDeliveryProofInfo(BaseMessagesProofInfo { + lane_id: TEST_LANE_ID, + best_bundled_nonce: 200, + best_stored_nonce: 100, + }), + )), } } @@ -659,16 +787,28 @@ mod tests { initialize_environment(100, 100, Default::default(), 100); assert_eq!(run_validate(message_delivery_call(200)), Ok(ValidTransaction::default()),); + assert_eq!( + run_validate(message_confirmation_call(200)), + Ok(ValidTransaction::default()), + ); assert_eq!( run_validate(parachain_finality_and_delivery_batch_call(200, 200)), Ok(ValidTransaction::default()), ); + assert_eq!( + run_validate(parachain_finality_and_confirmation_batch_call(200, 200)), + Ok(ValidTransaction::default()), + ); assert_eq!( run_validate(all_finality_and_delivery_batch_call(200, 200, 200)), Ok(ValidTransaction::default()), ); + assert_eq!( + run_validate(all_finality_and_confirmation_batch_call(200, 200, 200)), + Ok(ValidTransaction::default()), + ); }); } @@ -698,17 +838,15 @@ mod tests { run_pre_dispatch(all_finality_and_delivery_batch_call(101, 100, 200)), Err(TransactionValidityError::Invalid(InvalidTransaction::Stale)), ); - assert_eq!( - run_pre_dispatch(parachain_finality_and_delivery_batch_call(100, 200)), + run_validate(all_finality_and_delivery_batch_call(101, 100, 200)), Err(TransactionValidityError::Invalid(InvalidTransaction::Stale)), ); assert_eq!( - run_validate(all_finality_and_delivery_batch_call(101, 100, 200)), + run_pre_dispatch(parachain_finality_and_delivery_batch_call(100, 200)), Err(TransactionValidityError::Invalid(InvalidTransaction::Stale)), ); - assert_eq!( run_validate(parachain_finality_and_delivery_batch_call(100, 200)), Err(TransactionValidityError::Invalid(InvalidTransaction::Stale)), @@ -725,9 +863,8 @@ mod tests { run_pre_dispatch(all_finality_and_delivery_batch_call(200, 200, 100)), Err(TransactionValidityError::Invalid(InvalidTransaction::Stale)), ); - assert_eq!( - run_pre_dispatch(parachain_finality_and_delivery_batch_call(200, 100)), + run_pre_dispatch(all_finality_and_confirmation_batch_call(200, 200, 100)), Err(TransactionValidityError::Invalid(InvalidTransaction::Stale)), ); @@ -735,11 +872,28 @@ mod tests { run_validate(all_finality_and_delivery_batch_call(200, 200, 100)), Err(TransactionValidityError::Invalid(InvalidTransaction::Stale)), ); + assert_eq!( + run_validate(all_finality_and_confirmation_batch_call(200, 200, 100)), + Err(TransactionValidityError::Invalid(InvalidTransaction::Stale)), + ); + + assert_eq!( + run_pre_dispatch(parachain_finality_and_delivery_batch_call(200, 100)), + Err(TransactionValidityError::Invalid(InvalidTransaction::Stale)), + ); + assert_eq!( + run_pre_dispatch(parachain_finality_and_confirmation_batch_call(200, 100)), + Err(TransactionValidityError::Invalid(InvalidTransaction::Stale)), + ); assert_eq!( run_validate(parachain_finality_and_delivery_batch_call(200, 100)), Err(TransactionValidityError::Invalid(InvalidTransaction::Stale)), ); + assert_eq!( + run_validate(parachain_finality_and_confirmation_batch_call(200, 100)), + Err(TransactionValidityError::Invalid(InvalidTransaction::Stale)), + ); }); } @@ -752,6 +906,10 @@ mod tests { run_pre_dispatch(all_finality_and_delivery_batch_call(200, 200, 200)), Ok(Some(all_finality_pre_dispatch_data())), ); + assert_eq!( + run_pre_dispatch(all_finality_and_confirmation_batch_call(200, 200, 200)), + Ok(Some(all_finality_confirmation_pre_dispatch_data())), + ); }); } @@ -764,6 +922,10 @@ mod tests { run_pre_dispatch(parachain_finality_and_delivery_batch_call(200, 200)), Ok(Some(parachain_finality_pre_dispatch_data())), ); + assert_eq!( + run_pre_dispatch(parachain_finality_and_confirmation_batch_call(200, 200)), + Ok(Some(parachain_finality_confirmation_pre_dispatch_data())), + ); }); } @@ -791,7 +953,7 @@ mod tests { } #[test] - fn pre_dispatch_parses_message_delivery_transaction() { + fn pre_dispatch_parses_message_transaction() { run_test(|| { initialize_environment(100, 100, Default::default(), 100); @@ -799,6 +961,10 @@ mod tests { run_pre_dispatch(message_delivery_call(200)), Ok(Some(delivery_pre_dispatch_data())), ); + assert_eq!( + run_pre_dispatch(message_confirmation_call(200)), + Ok(Some(confirmation_pre_dispatch_data())), + ); }); } @@ -852,6 +1018,16 @@ mod tests { Ok(()) )); assert_storage_noop!(run_post_dispatch(Some(delivery_pre_dispatch_data()), Ok(()))); + + assert_storage_noop!(run_post_dispatch( + Some(all_finality_confirmation_pre_dispatch_data()), + Ok(()) + )); + assert_storage_noop!(run_post_dispatch( + Some(parachain_finality_confirmation_pre_dispatch_data()), + Ok(()) + )); + assert_storage_noop!(run_post_dispatch(Some(confirmation_pre_dispatch_data()), Ok(()))); }); } @@ -872,7 +1048,7 @@ mod tests { assert_eq!( RelayersPallet::::relayer_reward( relayer_account_at_this_chain(), - TestLaneId::get() + MsgProofsRewardsAccount::get() ), Some(regular_reward), ); @@ -880,7 +1056,7 @@ mod tests { // now repeat the same with size+weight refund: we expect smaller reward let mut pre_dispatch_data = all_finality_pre_dispatch_data(); match pre_dispatch_data.call_info { - CallInfo::AllFinalityAndDelivery(ref mut info, ..) => { + CallInfo::AllFinalityAndMsgs(ref mut info, ..) => { info.extra_weight.set_ref_time( frame_support::weights::constants::WEIGHT_REF_TIME_PER_SECOND, ); @@ -891,7 +1067,7 @@ mod tests { run_post_dispatch(Some(pre_dispatch_data), Ok(())); let reward_after_two_calls = RelayersPallet::::relayer_reward( relayer_account_at_this_chain(), - TestLaneId::get(), + MsgProofsRewardsAccount::get(), ) .unwrap(); assert!( @@ -912,7 +1088,16 @@ mod tests { assert_eq!( RelayersPallet::::relayer_reward( relayer_account_at_this_chain(), - TestLaneId::get() + MsgProofsRewardsAccount::get() + ), + Some(expected_reward()), + ); + + run_post_dispatch(Some(all_finality_confirmation_pre_dispatch_data()), Ok(())); + assert_eq!( + RelayersPallet::::relayer_reward( + relayer_account_at_this_chain(), + MsgDeliveryProofsRewardsAccount::get() ), Some(expected_reward()), ); @@ -928,7 +1113,16 @@ mod tests { assert_eq!( RelayersPallet::::relayer_reward( relayer_account_at_this_chain(), - TestLaneId::get() + MsgProofsRewardsAccount::get() + ), + Some(expected_reward()), + ); + + run_post_dispatch(Some(parachain_finality_confirmation_pre_dispatch_data()), Ok(())); + assert_eq!( + RelayersPallet::::relayer_reward( + relayer_account_at_this_chain(), + MsgDeliveryProofsRewardsAccount::get() ), Some(expected_reward()), ); @@ -936,7 +1130,7 @@ mod tests { } #[test] - fn post_dispatch_refunds_relayer_in_message_delivery_transaction() { + fn post_dispatch_refunds_relayer_in_message_transaction() { run_test(|| { initialize_environment(200, 200, Default::default(), 200); @@ -944,7 +1138,16 @@ mod tests { assert_eq!( RelayersPallet::::relayer_reward( relayer_account_at_this_chain(), - TestLaneId::get() + MsgProofsRewardsAccount::get() + ), + Some(expected_reward()), + ); + + run_post_dispatch(Some(confirmation_pre_dispatch_data()), Ok(())); + assert_eq!( + RelayersPallet::::relayer_reward( + relayer_account_at_this_chain(), + MsgDeliveryProofsRewardsAccount::get() ), Some(expected_reward()), ); diff --git a/bridges/docs/dockerhub-bridges-common-relay.README.md b/bridges/docs/dockerhub-bridges-common-relay.README.md new file mode 100644 index 00000000000..d199227c9c6 --- /dev/null +++ b/bridges/docs/dockerhub-bridges-common-relay.README.md @@ -0,0 +1 @@ +# bridges-common-relay diff --git a/bridges/docs/dockerhub-millau-bridge-node.README.md b/bridges/docs/dockerhub-millau-bridge-node.README.md new file mode 100644 index 00000000000..481ad46b7c6 --- /dev/null +++ b/bridges/docs/dockerhub-millau-bridge-node.README.md @@ -0,0 +1 @@ +# millau-bridge-node diff --git a/bridges/docs/dockerhub-rialto-bridge-node.README.md b/bridges/docs/dockerhub-rialto-bridge-node.README.md new file mode 100644 index 00000000000..2393e6f8129 --- /dev/null +++ b/bridges/docs/dockerhub-rialto-bridge-node.README.md @@ -0,0 +1 @@ +# rialto-bridge-node diff --git a/bridges/docs/dockerhub-rialto-parachain-collator.README.md b/bridges/docs/dockerhub-rialto-parachain-collator.README.md new file mode 100644 index 00000000000..a09f6b1561b --- /dev/null +++ b/bridges/docs/dockerhub-rialto-parachain-collator.README.md @@ -0,0 +1 @@ +# rialto-parachain-collator diff --git a/bridges/docs/dockerhub-substrate-relay.README.md b/bridges/docs/dockerhub-substrate-relay.README.md new file mode 100644 index 00000000000..1a9f22c425c --- /dev/null +++ b/bridges/docs/dockerhub-substrate-relay.README.md @@ -0,0 +1 @@ +# substrate-relay diff --git a/bridges/modules/grandpa/src/lib.rs b/bridges/modules/grandpa/src/lib.rs index e94d91a5c16..4304e82eeb1 100644 --- a/bridges/modules/grandpa/src/lib.rs +++ b/bridges/modules/grandpa/src/lib.rs @@ -181,7 +181,7 @@ pub mod pallet { let is_authorities_change_enacted = try_enact_authority_change::(&finality_target, set_id)?; let may_refund_call_fee = is_authorities_change_enacted && - submit_finality_proof_info_from_args::(&*finality_target, &justification) + submit_finality_proof_info_from_args::(&finality_target, &justification) .fits_limits(); >::mutate(|count| *count += 1); insert_header::(*finality_target, hash); diff --git a/bridges/modules/relayers/Cargo.toml b/bridges/modules/relayers/Cargo.toml index 954818a3b50..200fbbca309 100644 --- a/bridges/modules/relayers/Cargo.toml +++ b/bridges/modules/relayers/Cargo.toml @@ -16,6 +16,7 @@ scale-info = { version = "2.1.1", default-features = false, features = ["derive" bp-messages = { path = "../../primitives/messages", default-features = false } bp-relayers = { path = "../../primitives/relayers", default-features = false } bp-runtime = { path = "../../primitives/runtime", default-features = false } +pallet-bridge-messages = { path = "../messages", default-features = false } # Substrate Dependencies diff --git a/bridges/modules/relayers/src/benchmarking.rs b/bridges/modules/relayers/src/benchmarking.rs index 7195b316bb6..7dcf77eb958 100644 --- a/bridges/modules/relayers/src/benchmarking.rs +++ b/bridges/modules/relayers/src/benchmarking.rs @@ -20,6 +20,8 @@ use crate::*; +use bp_messages::LaneId; +use bp_relayers::RewardsAccountOwner; use frame_benchmarking::{benchmarks, whitelisted_caller}; use frame_system::RawOrigin; @@ -32,19 +34,21 @@ pub struct Pallet(crate::Pallet); /// Trait that must be implemented by runtime. pub trait Config: crate::Config { /// Prepare environment for paying given reward for serving given lane. - fn prepare_environment(lane: LaneId, reward: Self::Reward); + fn prepare_environment(account_params: RewardsAccountParams, reward: Self::Reward); } benchmarks! { // Benchmark `claim_rewards` call. claim_rewards { let lane = LaneId([0, 0, 0, 0]); + let account_params = + RewardsAccountParams::new(lane, *b"test", RewardsAccountOwner::ThisChain); let relayer: T::AccountId = whitelisted_caller(); let reward = T::Reward::from(REWARD_AMOUNT); - T::prepare_environment(lane, reward); - RelayerRewards::::insert(&relayer, lane, reward); - }: _(RawOrigin::Signed(relayer), lane) + T::prepare_environment(account_params, reward); + RelayerRewards::::insert(&relayer, account_params, reward); + }: _(RawOrigin::Signed(relayer), account_params) verify { // we can't check anything here, because `PaymentProcedure` is responsible for // payment logic, so we assume that if call has succeeded, the procedure has diff --git a/bridges/modules/relayers/src/lib.rs b/bridges/modules/relayers/src/lib.rs index 2ceebd0336e..3d32e3c7a14 100644 --- a/bridges/modules/relayers/src/lib.rs +++ b/bridges/modules/relayers/src/lib.rs @@ -20,8 +20,7 @@ #![cfg_attr(not(feature = "std"), no_std)] #![warn(missing_docs)] -use bp_messages::LaneId; -use bp_relayers::{PaymentProcedure, RelayerRewardsKeyProvider}; +use bp_relayers::{PaymentProcedure, RelayerRewardsKeyProvider, RewardsAccountParams}; use bp_runtime::StorageDoubleMapKeyProvider; use frame_support::sp_runtime::Saturating; use sp_arithmetic::traits::{AtLeast32BitUnsigned, Zero}; @@ -72,28 +71,32 @@ pub mod pallet { /// Claim accumulated rewards. #[pallet::call_index(0)] #[pallet::weight(T::WeightInfo::claim_rewards())] - pub fn claim_rewards(origin: OriginFor, lane_id: LaneId) -> DispatchResult { + pub fn claim_rewards( + origin: OriginFor, + rewards_account_params: RewardsAccountParams, + ) -> DispatchResult { let relayer = ensure_signed(origin)?; RelayerRewards::::try_mutate_exists( &relayer, - lane_id, + rewards_account_params, |maybe_reward| -> DispatchResult { let reward = maybe_reward.take().ok_or(Error::::NoRewardForRelayer)?; - T::PaymentProcedure::pay_reward(&relayer, lane_id, reward).map_err(|e| { - log::trace!( - target: LOG_TARGET, - "Failed to pay {:?} rewards to {:?}: {:?}", - lane_id, - relayer, - e, - ); - Error::::FailedToPayReward - })?; + T::PaymentProcedure::pay_reward(&relayer, rewards_account_params, reward) + .map_err(|e| { + log::trace!( + target: LOG_TARGET, + "Failed to pay {:?} rewards to {:?}: {:?}", + rewards_account_params, + relayer, + e, + ); + Error::::FailedToPayReward + })?; Self::deposit_event(Event::::RewardPaid { relayer: relayer.clone(), - lane_id, + rewards_account_params, reward, }); Ok(()) @@ -104,23 +107,31 @@ pub mod pallet { impl Pallet { /// Register reward for given relayer. - pub fn register_relayer_reward(lane_id: LaneId, relayer: &T::AccountId, reward: T::Reward) { + pub fn register_relayer_reward( + rewards_account_params: RewardsAccountParams, + relayer: &T::AccountId, + reward: T::Reward, + ) { if reward.is_zero() { return } - RelayerRewards::::mutate(relayer, lane_id, |old_reward: &mut Option| { - let new_reward = old_reward.unwrap_or_else(Zero::zero).saturating_add(reward); - *old_reward = Some(new_reward); - - log::trace!( - target: crate::LOG_TARGET, - "Relayer {:?} can now claim reward for serving lane {:?}: {:?}", - relayer, - lane_id, - new_reward, - ); - }); + RelayerRewards::::mutate( + relayer, + rewards_account_params, + |old_reward: &mut Option| { + let new_reward = old_reward.unwrap_or_else(Zero::zero).saturating_add(reward); + *old_reward = Some(new_reward); + + log::trace!( + target: crate::LOG_TARGET, + "Relayer {:?} can now claim reward for serving payer {:?}: {:?}", + relayer, + rewards_account_params, + new_reward, + ); + }, + ); } } @@ -131,8 +142,8 @@ pub mod pallet { RewardPaid { /// Relayer account that has been rewarded. relayer: T::AccountId, - /// Relayer has received reward for serving this lane. - lane_id: LaneId, + /// Relayer has received reward from this account. + rewards_account_params: RewardsAccountParams, /// Reward amount. reward: T::Reward, }, @@ -166,6 +177,8 @@ mod tests { use mock::{RuntimeEvent as TestEvent, *}; use crate::Event::RewardPaid; + use bp_messages::LaneId; + use bp_relayers::RewardsAccountOwner; use frame_support::{ assert_noop, assert_ok, traits::fungible::{Inspect, Mutate}, @@ -182,7 +195,10 @@ mod tests { fn root_cant_claim_anything() { run_test(|| { assert_noop!( - Pallet::::claim_rewards(RuntimeOrigin::root(), TEST_LANE_ID), + Pallet::::claim_rewards( + RuntimeOrigin::root(), + TEST_REWARDS_ACCOUNT_PARAMS + ), DispatchError::BadOrigin, ); }); @@ -194,7 +210,7 @@ mod tests { assert_noop!( Pallet::::claim_rewards( RuntimeOrigin::signed(REGULAR_RELAYER), - TEST_LANE_ID + TEST_REWARDS_ACCOUNT_PARAMS ), Error::::NoRewardForRelayer, ); @@ -204,11 +220,15 @@ mod tests { #[test] fn relayer_cant_claim_if_payment_procedure_fails() { run_test(|| { - RelayerRewards::::insert(FAILING_RELAYER, TEST_LANE_ID, 100); + RelayerRewards::::insert( + FAILING_RELAYER, + TEST_REWARDS_ACCOUNT_PARAMS, + 100, + ); assert_noop!( Pallet::::claim_rewards( RuntimeOrigin::signed(FAILING_RELAYER), - TEST_LANE_ID + TEST_REWARDS_ACCOUNT_PARAMS ), Error::::FailedToPayReward, ); @@ -220,12 +240,19 @@ mod tests { run_test(|| { get_ready_for_events(); - RelayerRewards::::insert(REGULAR_RELAYER, TEST_LANE_ID, 100); + RelayerRewards::::insert( + REGULAR_RELAYER, + TEST_REWARDS_ACCOUNT_PARAMS, + 100, + ); assert_ok!(Pallet::::claim_rewards( RuntimeOrigin::signed(REGULAR_RELAYER), - TEST_LANE_ID + TEST_REWARDS_ACCOUNT_PARAMS )); - assert_eq!(RelayerRewards::::get(REGULAR_RELAYER, TEST_LANE_ID), None); + assert_eq!( + RelayerRewards::::get(REGULAR_RELAYER, TEST_REWARDS_ACCOUNT_PARAMS), + None + ); //Check if the `RewardPaid` event was emitted. assert_eq!( @@ -234,7 +261,7 @@ mod tests { phase: Phase::Initialization, event: TestEvent::Relayers(RewardPaid { relayer: REGULAR_RELAYER, - lane_id: TEST_LANE_ID, + rewards_account_params: TEST_REWARDS_ACCOUNT_PARAMS, reward: 100 }), topics: vec![], @@ -244,30 +271,39 @@ mod tests { } #[test] - fn pay_lane_reward_from_account_actually_pays_reward() { + fn pay_reward_from_account_actually_pays_reward() { type Balances = pallet_balances::Pallet; - type PayLaneRewardFromAccount = bp_relayers::PayLaneRewardFromAccount; + type PayLaneRewardFromAccount = bp_relayers::PayRewardFromAccount; run_test(|| { - let lane0_rewards_account = - PayLaneRewardFromAccount::lane_rewards_account(LaneId([0, 0, 0, 0])); - let lane1_rewards_account = - PayLaneRewardFromAccount::lane_rewards_account(LaneId([0, 0, 0, 1])); - - Balances::mint_into(&lane0_rewards_account, 100).unwrap(); - Balances::mint_into(&lane1_rewards_account, 100).unwrap(); - assert_eq!(Balances::balance(&lane0_rewards_account), 100); - assert_eq!(Balances::balance(&lane1_rewards_account), 100); + let in_lane_0 = RewardsAccountParams::new( + LaneId([0, 0, 0, 0]), + *b"test", + RewardsAccountOwner::ThisChain, + ); + let out_lane_1 = RewardsAccountParams::new( + LaneId([0, 0, 0, 1]), + *b"test", + RewardsAccountOwner::BridgedChain, + ); + + let in_lane0_rewards_account = PayLaneRewardFromAccount::rewards_account(in_lane_0); + let out_lane1_rewards_account = PayLaneRewardFromAccount::rewards_account(out_lane_1); + + Balances::mint_into(&in_lane0_rewards_account, 100).unwrap(); + Balances::mint_into(&out_lane1_rewards_account, 100).unwrap(); + assert_eq!(Balances::balance(&in_lane0_rewards_account), 100); + assert_eq!(Balances::balance(&out_lane1_rewards_account), 100); assert_eq!(Balances::balance(&1), 0); - PayLaneRewardFromAccount::pay_reward(&1, LaneId([0, 0, 0, 0]), 100).unwrap(); - assert_eq!(Balances::balance(&lane0_rewards_account), 0); - assert_eq!(Balances::balance(&lane1_rewards_account), 100); + PayLaneRewardFromAccount::pay_reward(&1, in_lane_0, 100).unwrap(); + assert_eq!(Balances::balance(&in_lane0_rewards_account), 0); + assert_eq!(Balances::balance(&out_lane1_rewards_account), 100); assert_eq!(Balances::balance(&1), 100); - PayLaneRewardFromAccount::pay_reward(&1, LaneId([0, 0, 0, 1]), 100).unwrap(); - assert_eq!(Balances::balance(&lane0_rewards_account), 0); - assert_eq!(Balances::balance(&lane1_rewards_account), 0); + PayLaneRewardFromAccount::pay_reward(&1, out_lane_1, 100).unwrap(); + assert_eq!(Balances::balance(&in_lane0_rewards_account), 0); + assert_eq!(Balances::balance(&out_lane1_rewards_account), 0); assert_eq!(Balances::balance(&1), 200); }); } diff --git a/bridges/modules/relayers/src/mock.rs b/bridges/modules/relayers/src/mock.rs index 89b3ead0411..c40c86f1db5 100644 --- a/bridges/modules/relayers/src/mock.rs +++ b/bridges/modules/relayers/src/mock.rs @@ -19,7 +19,7 @@ use crate as pallet_bridge_relayers; use bp_messages::LaneId; -use bp_relayers::PaymentProcedure; +use bp_relayers::{PaymentProcedure, RewardsAccountOwner, RewardsAccountParams}; use frame_support::{parameter_types, weights::RuntimeDbWeight}; use sp_core::H256; use sp_runtime::{ @@ -96,7 +96,8 @@ impl pallet_bridge_relayers::Config for TestRuntime { } /// Message lane that we're using in tests. -pub const TEST_LANE_ID: LaneId = LaneId([0, 0, 0, 0]); +pub const TEST_REWARDS_ACCOUNT_PARAMS: RewardsAccountParams = + RewardsAccountParams::new(LaneId([0, 0, 0, 0]), *b"test", RewardsAccountOwner::ThisChain); /// Regular relayer that may receive rewards. pub const REGULAR_RELAYER: AccountId = 1; @@ -112,7 +113,7 @@ impl PaymentProcedure for TestPaymentProcedure { fn pay_reward( relayer: &AccountId, - _lane_id: LaneId, + _lane_id: RewardsAccountParams, _reward: Balance, ) -> Result<(), Self::Error> { match *relayer { diff --git a/bridges/modules/relayers/src/payment_adapter.rs b/bridges/modules/relayers/src/payment_adapter.rs index 946b31cf7af..2752044958b 100644 --- a/bridges/modules/relayers/src/payment_adapter.rs +++ b/bridges/modules/relayers/src/payment_adapter.rs @@ -18,28 +18,32 @@ use crate::{Config, Pallet}; -use bp_messages::source_chain::{DeliveryConfirmationPayments, RelayersRewards}; +use bp_messages::{ + source_chain::{DeliveryConfirmationPayments, RelayersRewards}, + LaneId, +}; +use bp_relayers::{RewardsAccountOwner, RewardsAccountParams}; use frame_support::{sp_runtime::SaturatedConversion, traits::Get}; -use sp_arithmetic::traits::{Saturating, UniqueSaturatedFrom, Zero}; +use sp_arithmetic::traits::{Saturating, Zero}; use sp_std::{collections::vec_deque::VecDeque, marker::PhantomData, ops::RangeInclusive}; /// Adapter that allows relayers pallet to be used as a delivery+dispatch payment mechanism /// for the messages pallet. -pub struct DeliveryConfirmationPaymentsAdapter( - PhantomData<(T, DeliveryReward, ConfirmationReward)>, +pub struct DeliveryConfirmationPaymentsAdapter( + PhantomData<(T, MI, DeliveryReward)>, ); -impl DeliveryConfirmationPayments - for DeliveryConfirmationPaymentsAdapter +impl DeliveryConfirmationPayments + for DeliveryConfirmationPaymentsAdapter where - T: Config, + T: Config + pallet_bridge_messages::Config, + MI: 'static, DeliveryReward: Get, - ConfirmationReward: Get, { type Error = &'static str; fn pay_reward( - lane_id: bp_messages::LaneId, + lane_id: LaneId, messages_relayers: VecDeque>, confirmation_relayer: &T::AccountId, received_range: &RangeInclusive, @@ -50,9 +54,12 @@ where register_relayers_rewards::( confirmation_relayer, relayers_rewards, - lane_id, + RewardsAccountParams::new( + lane_id, + T::BridgedChainId::get(), + RewardsAccountOwner::BridgedChain, + ), DeliveryReward::get(), - ConfirmationReward::get(), ); } } @@ -61,34 +68,19 @@ where fn register_relayers_rewards( confirmation_relayer: &T::AccountId, relayers_rewards: RelayersRewards, - lane_id: bp_messages::LaneId, + lane_id: RewardsAccountParams, delivery_fee: T::Reward, - confirmation_fee: T::Reward, ) { // reward every relayer except `confirmation_relayer` let mut confirmation_relayer_reward = T::Reward::zero(); for (relayer, messages) in relayers_rewards { // sane runtime configurations guarantee that the number of messages will be below // `u32::MAX` - let mut relayer_reward = - T::Reward::unique_saturated_from(messages).saturating_mul(delivery_fee); + let relayer_reward = T::Reward::saturated_from(messages).saturating_mul(delivery_fee); if relayer != *confirmation_relayer { - // If delivery confirmation is submitted by other relayer, let's deduct confirmation fee - // from relayer reward. - // - // If confirmation fee has been increased (or if it was the only component of message - // fee), then messages relayer may receive zero reward. - let mut confirmation_reward = - T::Reward::saturated_from(messages).saturating_mul(confirmation_fee); - confirmation_reward = sp_std::cmp::min(confirmation_reward, relayer_reward); - relayer_reward = relayer_reward.saturating_sub(confirmation_reward); - confirmation_relayer_reward = - confirmation_relayer_reward.saturating_add(confirmation_reward); Pallet::::register_relayer_reward(lane_id, &relayer, relayer_reward); } else { - // If delivery confirmation is submitted by this relayer, let's add confirmation fee - // from other relayers to this relayer reward. confirmation_relayer_reward = confirmation_relayer_reward.saturating_add(relayer_reward); } @@ -121,47 +113,43 @@ mod tests { register_relayers_rewards::( &RELAYER_2, relayers_rewards(), - TEST_LANE_ID, + TEST_REWARDS_ACCOUNT_PARAMS, 50, - 10, ); - assert_eq!(RelayerRewards::::get(RELAYER_1, TEST_LANE_ID), Some(80)); - assert_eq!(RelayerRewards::::get(RELAYER_2, TEST_LANE_ID), Some(170)); - }); - } - - #[test] - fn confirmation_relayer_is_rewarded_if_it_has_not_delivered_any_delivered_messages() { - run_test(|| { - register_relayers_rewards::( - &RELAYER_3, - relayers_rewards(), - TEST_LANE_ID, - 50, - 10, + assert_eq!( + RelayerRewards::::get(RELAYER_1, TEST_REWARDS_ACCOUNT_PARAMS), + Some(100) + ); + assert_eq!( + RelayerRewards::::get(RELAYER_2, TEST_REWARDS_ACCOUNT_PARAMS), + Some(150) ); - - assert_eq!(RelayerRewards::::get(RELAYER_1, TEST_LANE_ID), Some(80)); - assert_eq!(RelayerRewards::::get(RELAYER_2, TEST_LANE_ID), Some(120)); - assert_eq!(RelayerRewards::::get(RELAYER_3, TEST_LANE_ID), Some(50)); }); } #[test] - fn only_confirmation_relayer_is_rewarded_if_confirmation_fee_has_significantly_increased() { + fn confirmation_relayer_is_not_rewarded_if_it_has_not_delivered_any_messages() { run_test(|| { register_relayers_rewards::( &RELAYER_3, relayers_rewards(), - TEST_LANE_ID, + TEST_REWARDS_ACCOUNT_PARAMS, 50, - 1000, ); - assert_eq!(RelayerRewards::::get(RELAYER_1, TEST_LANE_ID), None); - assert_eq!(RelayerRewards::::get(RELAYER_2, TEST_LANE_ID), None); - assert_eq!(RelayerRewards::::get(RELAYER_3, TEST_LANE_ID), Some(250)); + assert_eq!( + RelayerRewards::::get(RELAYER_1, TEST_REWARDS_ACCOUNT_PARAMS), + Some(100) + ); + assert_eq!( + RelayerRewards::::get(RELAYER_2, TEST_REWARDS_ACCOUNT_PARAMS), + Some(150) + ); + assert_eq!( + RelayerRewards::::get(RELAYER_3, TEST_REWARDS_ACCOUNT_PARAMS), + None + ); }); } } diff --git a/bridges/modules/relayers/src/weights.rs b/bridges/modules/relayers/src/weights.rs index fdaeee4f22a..572935f6302 100644 --- a/bridges/modules/relayers/src/weights.rs +++ b/bridges/modules/relayers/src/weights.rs @@ -17,9 +17,9 @@ //! Autogenerated weights for pallet_bridge_relayers //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2023-02-06, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2023-02-27, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `covid`, CPU: `11th Gen Intel(R) Core(TM) i7-11800H @ 2.30GHz` +//! HOSTNAME: `serban-ROG-Zephyrus`, CPU: `12th Gen Intel(R) Core(TM) i7-12700H` //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024 // Executed Command: @@ -60,7 +60,7 @@ pub struct BridgeWeight(PhantomData); impl WeightInfo for BridgeWeight { /// Storage: BridgeRelayers RelayerRewards (r:1 w:1) /// - /// Proof: BridgeRelayers RelayerRewards (max_values: None, max_size: Some(60), added: 2535, + /// Proof: BridgeRelayers RelayerRewards (max_values: None, max_size: Some(65), added: 2540, /// mode: MaxEncodedLen) /// /// Storage: System Account (r:1 w:1) @@ -69,10 +69,10 @@ impl WeightInfo for BridgeWeight { /// MaxEncodedLen) fn claim_rewards() -> Weight { // Proof Size summary in bytes: - // Measured: `534` - // Estimated: `5106` - // Minimum execution time: 48_239 nanoseconds. - Weight::from_parts(50_579_000, 5106) + // Measured: `275` + // Estimated: `5111` + // Minimum execution time: 43_031 nanoseconds. + Weight::from_parts(44_527_000, 5111) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } @@ -82,7 +82,7 @@ impl WeightInfo for BridgeWeight { impl WeightInfo for () { /// Storage: BridgeRelayers RelayerRewards (r:1 w:1) /// - /// Proof: BridgeRelayers RelayerRewards (max_values: None, max_size: Some(60), added: 2535, + /// Proof: BridgeRelayers RelayerRewards (max_values: None, max_size: Some(65), added: 2540, /// mode: MaxEncodedLen) /// /// Storage: System Account (r:1 w:1) @@ -91,10 +91,10 @@ impl WeightInfo for () { /// MaxEncodedLen) fn claim_rewards() -> Weight { // Proof Size summary in bytes: - // Measured: `534` - // Estimated: `5106` - // Minimum execution time: 48_239 nanoseconds. - Weight::from_parts(50_579_000, 5106) + // Measured: `275` + // Estimated: `5111` + // Minimum execution time: 43_031 nanoseconds. + Weight::from_parts(44_527_000, 5111) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } diff --git a/bridges/primitives/header-chain/src/justification.rs b/bridges/primitives/header-chain/src/justification.rs index 1e34f365621..88dac0acf9f 100644 --- a/bridges/primitives/header-chain/src/justification.rs +++ b/bridges/primitives/header-chain/src/justification.rs @@ -135,7 +135,7 @@ pub fn decode_justification_target( } /// Verify and optimize given justification by removing unknown and duplicate votes. -pub fn optimize_justification( +pub fn verify_and_optimize_justification( finalized_target: (Header::Hash, Header::Number), authorities_set_id: SetId, authorities_set: &VoterSet, diff --git a/bridges/primitives/header-chain/tests/justification.rs b/bridges/primitives/header-chain/tests/justification.rs index f01f4ea2f10..52fa33ae974 100644 --- a/bridges/primitives/header-chain/tests/justification.rs +++ b/bridges/primitives/header-chain/tests/justification.rs @@ -17,7 +17,8 @@ //! Tests for Grandpa Justification code. use bp_header_chain::justification::{ - optimize_justification, required_justification_precommits, verify_justification, Error, + required_justification_precommits, verify_and_optimize_justification, verify_justification, + Error, }; use bp_test_utils::*; @@ -199,7 +200,7 @@ fn optimizer_does_noting_with_minimal_justification() { let justification = make_default_justification::(&test_header(1)); let num_precommits_before = justification.commit.precommits.len(); - let justification = optimize_justification::( + let justification = verify_and_optimize_justification::( header_id::(1), TEST_GRANDPA_SET_ID, &voter_set(), @@ -222,7 +223,7 @@ fn unknown_authority_votes_are_removed_by_optimizer() { )); let num_precommits_before = justification.commit.precommits.len(); - let justification = optimize_justification::( + let justification = verify_and_optimize_justification::( header_id::(1), TEST_GRANDPA_SET_ID, &voter_set(), @@ -243,7 +244,7 @@ fn duplicate_authority_votes_are_removed_by_optimizer() { .push(justification.commit.precommits.first().cloned().unwrap()); let num_precommits_before = justification.commit.precommits.len(); - let justification = optimize_justification::( + let justification = verify_and_optimize_justification::( header_id::(1), TEST_GRANDPA_SET_ID, &voter_set(), @@ -266,7 +267,7 @@ fn redundant_authority_votes_are_removed_by_optimizer() { )); let num_precommits_before = justification.commit.precommits.len(); - let justification = optimize_justification::( + let justification = verify_and_optimize_justification::( header_id::(1), TEST_GRANDPA_SET_ID, &voter_set(), diff --git a/bridges/primitives/relayers/Cargo.toml b/bridges/primitives/relayers/Cargo.toml index 7479811a57d..ee91361a4e2 100644 --- a/bridges/primitives/relayers/Cargo.toml +++ b/bridges/primitives/relayers/Cargo.toml @@ -7,6 +7,8 @@ edition = "2021" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] +codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false, features = ["derive", "bit-vec"] } +scale-info = { version = "2.1.1", default-features = false, features = ["bit-vec", "derive"] } # Bridge Dependencies diff --git a/bridges/primitives/relayers/src/lib.rs b/bridges/primitives/relayers/src/lib.rs index 70a91ee941a..fb350958415 100644 --- a/bridges/primitives/relayers/src/lib.rs +++ b/bridges/primitives/relayers/src/lib.rs @@ -20,46 +20,95 @@ #![cfg_attr(not(feature = "std"), no_std)] use bp_messages::LaneId; -use bp_runtime::StorageDoubleMapKeyProvider; +use bp_runtime::{ChainId, StorageDoubleMapKeyProvider}; use frame_support::{Blake2_128Concat, Identity}; +use scale_info::TypeInfo; use sp_runtime::{ - codec::{Codec, Decode, Encode, EncodeLike}, + codec::{Codec, Decode, Encode, EncodeLike, MaxEncodedLen}, traits::AccountIdConversion, + TypeId, }; use sp_std::{fmt::Debug, marker::PhantomData}; +/// The owner of the sovereign account that should pay the rewards. +/// +/// Each of the 2 final points connected by a bridge owns a sovereign account at each end of the +/// bridge. So here, at this end of the bridge there can be 2 sovereign accounts that pay rewards. +#[derive(Copy, Clone, Debug, Decode, Encode, Eq, PartialEq, TypeInfo, MaxEncodedLen)] +pub enum RewardsAccountOwner { + /// The sovereign account of the final chain on this end of the bridge. + ThisChain, + /// The sovereign account of the final chain on the other end of the bridge. + BridgedChain, +} + +/// Structure used to identify the account that pays a reward to the relayer. +/// +/// A bridge connects 2 bridge ends. Each one is located on a separate relay chain. The bridge ends +/// can be the final destinations of the bridge, or they can be intermediary points +/// (e.g. a bridge hub) used to forward messages between pairs of parachains on the bridged relay +/// chains. A pair of such parachains is connected using a bridge lane. Each of the 2 final +/// destinations of a bridge lane must have a sovereign account at each end of the bridge and each +/// of the sovereign accounts will pay rewards for different operations. So we need multiple +/// parameters to identify the account that pays a reward to the relayer. +#[derive(Copy, Clone, Debug, Decode, Encode, Eq, PartialEq, TypeInfo, MaxEncodedLen)] +pub struct RewardsAccountParams { + lane_id: LaneId, + bridged_chain_id: ChainId, + owner: RewardsAccountOwner, +} + +impl RewardsAccountParams { + /// Create a new instance of `RewardsAccountParams`. + pub const fn new( + lane_id: LaneId, + bridged_chain_id: ChainId, + owner: RewardsAccountOwner, + ) -> Self { + Self { lane_id, bridged_chain_id, owner } + } +} + +impl TypeId for RewardsAccountParams { + const TYPE_ID: [u8; 4] = *b"brap"; +} + /// Reward payment procedure. pub trait PaymentProcedure { /// Error that may be returned by the procedure. type Error: Debug; - /// Pay reward to the relayer for serving given message lane. - fn pay_reward(relayer: &Relayer, lane_id: LaneId, reward: Reward) -> Result<(), Self::Error>; + /// Pay reward to the relayer from the account with provided params. + fn pay_reward( + relayer: &Relayer, + rewards_account_params: RewardsAccountParams, + reward: Reward, + ) -> Result<(), Self::Error>; } impl PaymentProcedure for () { type Error = &'static str; - fn pay_reward(_: &Relayer, _: LaneId, _: Reward) -> Result<(), Self::Error> { + fn pay_reward(_: &Relayer, _: RewardsAccountParams, _: Reward) -> Result<(), Self::Error> { Ok(()) } } /// Reward payment procedure that does `balances::transfer` call from the account, derived from -/// given lane. -pub struct PayLaneRewardFromAccount(PhantomData<(T, Relayer)>); +/// given params. +pub struct PayRewardFromAccount(PhantomData<(T, Relayer)>); -impl PayLaneRewardFromAccount +impl PayRewardFromAccount where Relayer: Decode + Encode, { - /// Return account that pay rewards for serving given lane. - pub fn lane_rewards_account(lane_id: LaneId) -> Relayer { - lane_id.into_sub_account_truncating(b"bridge-lane") + /// Return account that pays rewards based on the provided parameters. + pub fn rewards_account(params: RewardsAccountParams) -> Relayer { + params.into_sub_account_truncating(b"rewards-account") } } -impl PaymentProcedure for PayLaneRewardFromAccount +impl PaymentProcedure for PayRewardFromAccount where T: frame_support::traits::fungible::Transfer, Relayer: Decode + Encode, @@ -68,10 +117,11 @@ where fn pay_reward( relayer: &Relayer, - lane_id: LaneId, + rewards_account_params: RewardsAccountParams, reward: T::Balance, ) -> Result<(), Self::Error> { - T::transfer(&Self::lane_rewards_account(lane_id), relayer, reward, false).map(drop) + T::transfer(&Self::rewards_account(rewards_account_params), relayer, reward, false) + .map(drop) } } @@ -89,26 +139,58 @@ where type Hasher1 = Blake2_128Concat; type Key1 = AccountId; type Hasher2 = Identity; - type Key2 = LaneId; + type Key2 = RewardsAccountParams; type Value = Reward; } #[cfg(test)] mod tests { use super::*; + use bp_messages::LaneId; use sp_runtime::testing::H256; #[test] - fn lanes_are_using_different_accounts() { + fn different_lanes_are_using_different_accounts() { + assert_eq!( + PayRewardFromAccount::<(), H256>::rewards_account(RewardsAccountParams::new( + LaneId([0, 0, 0, 0]), + *b"test", + RewardsAccountOwner::ThisChain + )), + hex_literal::hex!("62726170000000007465737400726577617264732d6163636f756e7400000000") + .into(), + ); + + assert_eq!( + PayRewardFromAccount::<(), H256>::rewards_account(RewardsAccountParams::new( + LaneId([0, 0, 0, 1]), + *b"test", + RewardsAccountOwner::ThisChain + )), + hex_literal::hex!("62726170000000017465737400726577617264732d6163636f756e7400000000") + .into(), + ); + } + + #[test] + fn different_directions_are_using_different_accounts() { assert_eq!( - PayLaneRewardFromAccount::<(), H256>::lane_rewards_account(LaneId([0, 0, 0, 0])), - hex_literal::hex!("626c616e000000006272696467652d6c616e6500000000000000000000000000") + PayRewardFromAccount::<(), H256>::rewards_account(RewardsAccountParams::new( + LaneId([0, 0, 0, 0]), + *b"test", + RewardsAccountOwner::ThisChain + )), + hex_literal::hex!("62726170000000007465737400726577617264732d6163636f756e7400000000") .into(), ); assert_eq!( - PayLaneRewardFromAccount::<(), H256>::lane_rewards_account(LaneId([0, 0, 0, 1])), - hex_literal::hex!("626c616e000000016272696467652d6c616e6500000000000000000000000000") + PayRewardFromAccount::<(), H256>::rewards_account(RewardsAccountParams::new( + LaneId([0, 0, 0, 0]), + *b"test", + RewardsAccountOwner::BridgedChain + )), + hex_literal::hex!("62726170000000007465737401726577617264732d6163636f756e7400000000") .into(), ); } diff --git a/bridges/primitives/runtime/Cargo.toml b/bridges/primitives/runtime/Cargo.toml index c8829a508d9..3cd2fdd35ca 100644 --- a/bridges/primitives/runtime/Cargo.toml +++ b/bridges/primitives/runtime/Cargo.toml @@ -24,7 +24,7 @@ sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "master sp-state-machine = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } sp-std = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } sp-trie = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } -trie-db = { version = "0.25.1", default-features = false } +trie-db = { version = "0.26.0", default-features = false } [dev-dependencies] hex-literal = "0.3" diff --git a/bridges/primitives/runtime/src/lib.rs b/bridges/primitives/runtime/src/lib.rs index 0121b4ab84e..2d29b5aff0a 100644 --- a/bridges/primitives/runtime/src/lib.rs +++ b/bridges/primitives/runtime/src/lib.rs @@ -74,6 +74,12 @@ pub const POLKADOT_CHAIN_ID: ChainId = *b"pdot"; /// Bridge-with-Kusama instance id. pub const KUSAMA_CHAIN_ID: ChainId = *b"ksma"; +/// Bridge-with-Westend instance id. +pub const WESTEND_CHAIN_ID: ChainId = *b"wend"; + +/// Bridge-with-Westend instance id. +pub const WESTMINT_CHAIN_ID: ChainId = *b"wmnt"; + /// Bridge-with-Rococo instance id. pub const ROCOCO_CHAIN_ID: ChainId = *b"roco"; diff --git a/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/lib.rs b/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/lib.rs index c768477c8bb..f45d27b2ce9 100644 --- a/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/lib.rs +++ b/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/lib.rs @@ -426,7 +426,6 @@ parameter_types! { // TODO:check-parameter - setup initial values https://github.com/paritytech/parity-bridges-common/issues/1677 pub storage DeliveryRewardInBalance: u64 = 1_000_000; - pub storage ConfirmationRewardInBalance: u64 = 100_000; } /// Add parachain bridge pallet to track Wococo bridge hub parachain @@ -479,8 +478,8 @@ impl pallet_bridge_messages::Config for Run type LaneMessageVerifier = bridge_hub_rococo_config::ToBridgeHubWococoMessageVerifier; type DeliveryConfirmationPayments = pallet_bridge_relayers::DeliveryConfirmationPaymentsAdapter< Runtime, + WithBridgeHubWococoMessagesInstance, DeliveryRewardInBalance, - ConfirmationRewardInBalance, >; type SourceHeaderChain = SourceHeaderChainAdapter; @@ -515,8 +514,8 @@ impl pallet_bridge_messages::Config for Run type LaneMessageVerifier = bridge_hub_wococo_config::ToBridgeHubRococoMessageVerifier; type DeliveryConfirmationPayments = pallet_bridge_relayers::DeliveryConfirmationPaymentsAdapter< Runtime, + WithBridgeHubRococoMessagesInstance, DeliveryRewardInBalance, - ConfirmationRewardInBalance, >; type SourceHeaderChain = SourceHeaderChainAdapter; @@ -532,7 +531,7 @@ impl pallet_bridge_relayers::Config for Runtime { type RuntimeEvent = RuntimeEvent; type Reward = Balance; type PaymentProcedure = - bp_relayers::PayLaneRewardFromAccount, AccountId>; + bp_relayers::PayRewardFromAccount, AccountId>; type WeightInfo = weights::pallet_bridge_relayers::WeightInfo; }