diff --git a/bridges/bin/millau/runtime/src/rialto_messages.rs b/bridges/bin/millau/runtime/src/rialto_messages.rs index 5674f738e19e..b7467e63a5ae 100644 --- a/bridges/bin/millau/runtime/src/rialto_messages.rs +++ b/bridges/bin/millau/runtime/src/rialto_messages.rs @@ -30,6 +30,7 @@ use frame_support::{ RuntimeDebug, }; use sp_core::storage::StorageKey; +use sp_std::{convert::TryFrom, ops::RangeInclusive}; /// Storage key of the Millau -> Rialto message in the runtime storage. pub fn message_key(lane: &LaneId, nonce: MessageNonce) -> StorageKey { @@ -87,9 +88,15 @@ impl MessageBridge for WithRialtoMessageBridge { type ThisChain = Millau; type BridgedChain = Rialto; - fn maximal_dispatch_weight_of_message_on_bridged_chain() -> Weight { + fn weight_limits_of_message_on_bridged_chain(message_payload: &[u8]) -> RangeInclusive { // we don't want to relay too large messages + keep reserve for future upgrades - bp_rialto::MAXIMUM_EXTRINSIC_WEIGHT / 2 + let upper_limit = bp_rialto::MAXIMUM_EXTRINSIC_WEIGHT / 2; + + // given Rialto chain parameters (`TransactionByteFee`, `WeightToFee`, `FeeMultiplierUpdate`), + // the minimal weight of the message may be computed as message.length() + let lower_limit = Weight::try_from(message_payload.len()).unwrap_or(Weight::MAX); + + lower_limit..=upper_limit } fn weight_of_delivery_transaction() -> Weight { @@ -160,8 +167,9 @@ impl TargetHeaderChain for Rialto type MessagesDeliveryProof = ToRialtoMessagesDeliveryProof; fn verify_message(payload: &ToRialtoMessagePayload) -> Result<(), Self::Error> { - if payload.weight > WithRialtoMessageBridge::maximal_dispatch_weight_of_message_on_bridged_chain() { - return Err("Too large weight declared"); + let weight_limits = WithRialtoMessageBridge::weight_limits_of_message_on_bridged_chain(&payload.call); + if !weight_limits.contains(&payload.weight) { + return Err("Incorrect message weight declared"); } Ok(()) diff --git a/bridges/bin/rialto/runtime/src/millau_messages.rs b/bridges/bin/rialto/runtime/src/millau_messages.rs index 6972a11eef09..2f087423aa49 100644 --- a/bridges/bin/rialto/runtime/src/millau_messages.rs +++ b/bridges/bin/rialto/runtime/src/millau_messages.rs @@ -30,6 +30,7 @@ use frame_support::{ RuntimeDebug, }; use sp_core::storage::StorageKey; +use sp_std::{convert::TryFrom, ops::RangeInclusive}; /// Storage key of the Rialto -> Millau message in the runtime storage. pub fn message_key(lane: &LaneId, nonce: MessageNonce) -> StorageKey { @@ -87,9 +88,15 @@ impl MessageBridge for WithMillauMessageBridge { type ThisChain = Rialto; type BridgedChain = Millau; - fn maximal_dispatch_weight_of_message_on_bridged_chain() -> Weight { + fn weight_limits_of_message_on_bridged_chain(message_payload: &[u8]) -> RangeInclusive { // we don't want to relay too large messages + keep reserve for future upgrades - bp_millau::MAXIMUM_EXTRINSIC_WEIGHT / 2 + let upper_limit = bp_millau::MAXIMUM_EXTRINSIC_WEIGHT / 2; + + // given Millau chain parameters (`TransactionByteFee`, `WeightToFee`, `FeeMultiplierUpdate`), + // the minimal weight of the message may be computed as message.length() + let lower_limit = Weight::try_from(message_payload.len()).unwrap_or(Weight::MAX); + + lower_limit..=upper_limit } fn weight_of_delivery_transaction() -> Weight { @@ -160,8 +167,9 @@ impl TargetHeaderChain for Millau type MessagesDeliveryProof = ToMillauMessagesDeliveryProof; fn verify_message(payload: &ToMillauMessagePayload) -> Result<(), Self::Error> { - if payload.weight > WithMillauMessageBridge::maximal_dispatch_weight_of_message_on_bridged_chain() { - return Err("Payload has weight larger than maximum allowed weight"); + let weight_limits = WithMillauMessageBridge::weight_limits_of_message_on_bridged_chain(&payload.call); + if !weight_limits.contains(&payload.weight) { + return Err("Incorrect message weight declared"); } Ok(()) diff --git a/bridges/bin/runtime-common/src/messages.rs b/bridges/bin/runtime-common/src/messages.rs index b26d9435cd6b..db05c700c533 100644 --- a/bridges/bin/runtime-common/src/messages.rs +++ b/bridges/bin/runtime-common/src/messages.rs @@ -30,7 +30,7 @@ use bp_runtime::InstanceId; use codec::{Compact, Decode, Input}; use frame_support::{traits::Instance, RuntimeDebug}; use sp_runtime::traits::{CheckedAdd, CheckedDiv, CheckedMul}; -use sp_std::{cmp::PartialOrd, marker::PhantomData, vec::Vec}; +use sp_std::{cmp::PartialOrd, marker::PhantomData, ops::RangeInclusive, vec::Vec}; use sp_trie::StorageProof; /// Bidirectional message bridge. @@ -46,8 +46,18 @@ pub trait MessageBridge { /// Bridged chain in context of message bridge. type BridgedChain: ChainWithMessageLanes; - /// Maximal (dispatch) weight of the message that we are able to send to Bridged chain. - fn maximal_dispatch_weight_of_message_on_bridged_chain() -> WeightOf>; + /// Returns feasible weights range for given message payload on the target chain. + /// + /// If message is being sent with the weight that is out of this range, then it + /// should be rejected. + /// + /// Weights returned from this function shall not include transaction overhead + /// (like weight of signature and signed extensions verification), because they're + /// already accounted by the `weight_of_delivery_transaction`. So this function should + /// return pure call dispatch weights range. + fn weight_limits_of_message_on_bridged_chain( + message_payload: &[u8], + ) -> RangeInclusive>>; /// Maximal weight of single message delivery transaction on Bridged chain. fn weight_of_delivery_transaction() -> WeightOf>; @@ -425,7 +435,7 @@ mod tests { type ThisChain = ThisChain; type BridgedChain = BridgedChain; - fn maximal_dispatch_weight_of_message_on_bridged_chain() -> Weight { + fn weight_limits_of_message_on_bridged_chain(_message_payload: &[u8]) -> RangeInclusive { unreachable!() } @@ -464,7 +474,7 @@ mod tests { type ThisChain = BridgedChain; type BridgedChain = ThisChain; - fn maximal_dispatch_weight_of_message_on_bridged_chain() -> Weight { + fn weight_limits_of_message_on_bridged_chain(_message_payload: &[u8]) -> RangeInclusive { unreachable!() }