diff --git a/bin/runtime-common/src/messages.rs b/bin/runtime-common/src/messages.rs index 7f6a0330a..51704c6f5 100644 --- a/bin/runtime-common/src/messages.rs +++ b/bin/runtime-common/src/messages.rs @@ -523,7 +523,7 @@ pub mod target { /// /// Our Call is opaque (`Vec`) for Bridged chain. So it is encoded, prefixed with /// vector length. Custom decode implementation here is exactly to deal with this. - #[derive(Decode, Encode, RuntimeDebug, PartialEq)] + #[derive(Decode, Encode, Clone, RuntimeDebug, PartialEq)] pub struct FromBridgedChainEncodedMessageCall { encoded_call: Vec, _marker: PhantomData, @@ -573,6 +573,16 @@ pub mod target { message.data.payload.as_ref().map(|payload| payload.weight).unwrap_or(0) } + fn pre_dispatch( + relayer_account: &AccountIdOf>, + message: &DispatchMessage>>, + ) -> Result<(), &'static str> { + pallet_bridge_dispatch::Pallet::::pre_dispatch( + relayer_account, + message.data.payload.as_ref().map_err(drop), + ) + } + fn dispatch( relayer_account: &AccountIdOf>, message: DispatchMessage>>, diff --git a/modules/dispatch/src/lib.rs b/modules/dispatch/src/lib.rs index 0bb9b566e..e1e969d87 100644 --- a/modules/dispatch/src/lib.rs +++ b/modules/dispatch/src/lib.rs @@ -92,7 +92,7 @@ pub mod pallet { /// that all other stuff (like `spec_version`) is ok. If we would try to decode /// `Call` which has been encoded using previous `spec_version`, then we might end /// up with decoding error, instead of `MessageVersionSpecMismatch`. - type EncodedCall: Decode + Encode + Into>::Call, ()>>; + type EncodedCall: Decode + Encode + Into>::Call, ()>> + Clone; /// A type which can be turned into an AccountId from a 256-bit hash. /// /// Used when deriving target chain AccountIds from source chain AccountIds. @@ -160,6 +160,16 @@ impl, I: 'static> MessageDispatch message.weight } + fn pre_dispatch( + relayer_account: &T::AccountId, + message: Result<&Self::Message, ()>, + ) -> Result<(), &'static str> { + let raw_message = message.map_err(|_| "Invalid Message")?; + let call = raw_message.clone().call.into().map_err(|_| "Invalid Call")?; + + T::CallValidator::check_receiving_before_dispatch(relayer_account, &call) + } + fn dispatch Result<(), ()>>( source_chain: ChainId, target_chain: ChainId, @@ -275,8 +285,8 @@ impl, I: 'static> MessageDispatch let dispatch_origin = T::IntoDispatchOrigin::into_dispatch_origin(&origin_derived_account, &call); - // filter the call - if let Err(_) = T::CallValidator::pre_dispatch(relayer_account, &dispatch_origin, &call) { + // validate the call + if let Err(_e) = T::CallValidator::call_validate(relayer_account, &dispatch_origin, &call) { log::trace!( target: "runtime::bridge-dispatch", "Message {:?}/{:?}: the call ({:?}) is rejected by filter", @@ -560,7 +570,7 @@ mod tests { type TargetChainSignature = TestSignature; } - #[derive(Decode, Encode)] + #[derive(Decode, Encode, Clone)] pub struct EncodedCall(Vec); impl From for Result { @@ -571,7 +581,14 @@ mod tests { pub struct CallValidator; impl CallValidate for CallValidator { - fn pre_dispatch( + fn check_receiving_before_dispatch( + _relayer_account: &AccountId, + _call: &Call, + ) -> Result<(), &'static str> { + Ok(()) + } + + fn call_validate( _relayer_account: &AccountId, _origin: &Origin, call: &Call, diff --git a/modules/fee-market/src/tests.rs b/modules/fee-market/src/tests.rs index 400346a0f..a9f55b666 100644 --- a/modules/fee-market/src/tests.rs +++ b/modules/fee-market/src/tests.rs @@ -344,6 +344,13 @@ impl MessageDispatch for TestMessageDispatch { } } + fn pre_dispatch( + _relayer_account: &AccountId, + _message: &DispatchMessage, + ) -> Result<(), &'static str> { + Ok(()) + } + fn dispatch( _relayer_account: &AccountId, message: DispatchMessage, diff --git a/modules/messages/src/inbound_lane.rs b/modules/messages/src/inbound_lane.rs index 924691251..78df0877a 100644 --- a/modules/messages/src/inbound_lane.rs +++ b/modules/messages/src/inbound_lane.rs @@ -149,7 +149,7 @@ impl InboundLane { }; // if there are some extra pre-dispatch validation errors, reject this message. if P::pre_dispatch(relayer_at_this_chain, &dispatch_message).is_err() { - return ReceivalResult::PreDispatchValidateFailed; + return ReceivalResult::PreDispatchValidateFailed } // then, dispatch message diff --git a/modules/messages/src/lib.rs b/modules/messages/src/lib.rs index b96445ac8..6c2659800 100644 --- a/modules/messages/src/lib.rs +++ b/modules/messages/src/lib.rs @@ -466,10 +466,10 @@ pub mod pallet { !dispatch_result.dispatch_fee_paid_during_dispatch, ) }, - ReceivalResult::InvalidNonce - | ReceivalResult::TooManyUnrewardedRelayers - | ReceivalResult::PreDispatchValidateFailed - | ReceivalResult::TooManyUnconfirmedMessages => (dispatch_weight, true), + ReceivalResult::InvalidNonce | + ReceivalResult::TooManyUnrewardedRelayers | + ReceivalResult::PreDispatchValidateFailed | + ReceivalResult::TooManyUnconfirmedMessages => (dispatch_weight, true), }; let unspent_weight = sp_std::cmp::min(unspent_weight, dispatch_weight); @@ -761,41 +761,6 @@ pub mod pallet { ) -> Option> { OutboundMessages::::get(MessageKey { lane_id: lane, nonce }) } - - /// Get nonce of the latest generated message at given outbound lane. - pub fn outbound_latest_generated_nonce(lane: LaneId) -> MessageNonce { - OutboundLanes::::get(&lane).latest_generated_nonce - } - - /// Get nonce of the latest confirmed message at given outbound lane. - pub fn outbound_latest_received_nonce(lane: LaneId) -> MessageNonce { - OutboundLanes::::get(&lane).latest_received_nonce - } - - /// Get nonce of the latest received message at given inbound lane. - pub fn inbound_latest_received_nonce(lane: LaneId) -> MessageNonce { - InboundLanes::::get(&lane).last_delivered_nonce() - } - - /// Get nonce of the latest confirmed message at given inbound lane. - pub fn inbound_latest_confirmed_nonce(lane: LaneId) -> MessageNonce { - InboundLanes::::get(&lane).last_confirmed_nonce - } - - /// Get state of unrewarded relayers set. - pub fn inbound_unrewarded_relayers_state( - lane: bp_messages::LaneId, - ) -> bp_messages::UnrewardedRelayersState { - let relayers = InboundLanes::::get(&lane).relayers; - bp_messages::UnrewardedRelayersState { - unrewarded_relayer_entries: relayers.len() as _, - messages_in_oldest_entry: relayers - .front() - .map(|entry| 1 + entry.messages.end - entry.messages.begin) - .unwrap_or(0), - total_messages: total_unrewarded_messages(&relayers).unwrap_or(MessageNonce::MAX), - } - } } } diff --git a/primitives/message-dispatch/src/lib.rs b/primitives/message-dispatch/src/lib.rs index e6f68cc35..2cde19ffb 100644 --- a/primitives/message-dispatch/src/lib.rs +++ b/primitives/message-dispatch/src/lib.rs @@ -46,6 +46,15 @@ pub trait MessageDispatch { /// of dispatch weight. fn dispatch_weight(message: &Self::Message) -> Weight; + /// Checking in message receiving step before dispatch + /// + /// This will be called before the call enter dispatch phase. If failed, the message(call) will + /// be not be processed by this relayer, latter relayers can still continue process it. + fn pre_dispatch( + relayer_account: &AccountId, + message: Result<&Self::Message, ()>, + ) -> Result<(), &'static str>; + /// Dispatches the message internally. /// /// `source_chain` indicates the chain where the message came from. @@ -154,8 +163,15 @@ pub trait IntoDispatchOrigin { /// A generic trait to validate message before dispatch. pub trait CallValidate { - /// call validation - fn pre_dispatch( + /// Checking in message receiving step before dispatch + /// + /// This will be called before the call enter dispatch phase. If failed, the message(call) will + /// be not be processed by this relayer, latter relayers can still continue process it. + fn check_receiving_before_dispatch(relayer_account: &AccountId, call: &Call) -> Result<(), &'static str>; + /// In-dispatch call validation + /// + /// This will be called in the dispatch process, If failed, return message dispatch errors. + fn call_validate( relayer_account: &AccountId, origin: &Origin, call: &Call,