diff --git a/bin/millau/runtime/src/lib.rs b/bin/millau/runtime/src/lib.rs index f08f5e1c749..8ed2f0a97e4 100644 --- a/bin/millau/runtime/src/lib.rs +++ b/bin/millau/runtime/src/lib.rs @@ -1007,7 +1007,7 @@ impl_runtime_apis! { Runtime, WithRialtoParachainsInstance, WithRialtoParachainMessageBridge, - >(params) + >(params, xcm::v3::Junctions::Here) } fn prepare_message_delivery_proof( @@ -1038,7 +1038,7 @@ impl_runtime_apis! { Runtime, RialtoGrandpaInstance, WithRialtoMessageBridge, - >(params) + >(params, xcm::v3::Junctions::Here) } fn prepare_message_delivery_proof( diff --git a/bin/millau/runtime/src/rialto_messages.rs b/bin/millau/runtime/src/rialto_messages.rs index 311805c9849..84535283d48 100644 --- a/bin/millau/runtime/src/rialto_messages.rs +++ b/bin/millau/runtime/src/rialto_messages.rs @@ -67,7 +67,7 @@ pub type FromRialtoMessageDispatch = bp_millau::Millau, bp_rialto::Rialto, crate::xcm_config::OnMillauBlobDispatcher, - bridge_runtime_common::messages_xcm_extension::XcmRouterWeigher, + (), >; /// Maximal outbound payload size of Millau -> Rialto messages. diff --git a/bin/millau/runtime/src/rialto_parachain_messages.rs b/bin/millau/runtime/src/rialto_parachain_messages.rs index 17495e26ae2..b3d33c1cefd 100644 --- a/bin/millau/runtime/src/rialto_parachain_messages.rs +++ b/bin/millau/runtime/src/rialto_parachain_messages.rs @@ -62,7 +62,7 @@ pub type FromRialtoParachainMessageDispatch = bp_millau::Millau, bp_rialto::Rialto, crate::xcm_config::OnMillauBlobDispatcher, - bridge_runtime_common::messages_xcm_extension::XcmRouterWeigher, + (), >; /// Maximal outbound payload size of Millau -> RialtoParachain messages. diff --git a/bin/millau/runtime/src/xcm_config.rs b/bin/millau/runtime/src/xcm_config.rs index c477a684526..384835f8bbc 100644 --- a/bin/millau/runtime/src/xcm_config.rs +++ b/bin/millau/runtime/src/xcm_config.rs @@ -233,20 +233,16 @@ impl ExportXcm for ToRialtoOrRialtoParachainSwitchExporter { mod tests { use super::*; use crate::{ - rialto_messages::FromRialtoMessageDispatch, - rialto_parachain_messages::FromRialtoParachainMessageDispatch, DbWeight, - WithRialtoMessagesInstance, WithRialtoParachainMessagesInstance, + rialto_messages::FromRialtoMessageDispatch, WithRialtoMessagesInstance, + WithRialtoParachainMessagesInstance, }; use bp_messages::{ target_chain::{DispatchMessage, DispatchMessageData, MessageDispatch}, LaneId, MessageKey, }; - use bridge_runtime_common::messages_xcm_extension::{ - XcmBlobMessageDispatchResult, XcmRouterWeigher, - }; + use bridge_runtime_common::messages_xcm_extension::XcmBlobMessageDispatchResult; use codec::Encode; use pallet_bridge_messages::OutboundLanes; - use sp_core::Get; use xcm_executor::XcmExecutor; fn new_test_ext() -> sp_io::TestExternalities { @@ -347,10 +343,7 @@ mod tests { #[test] fn xcm_messages_from_rialto_are_dispatched() { - let mut incoming_message = prepare_inbound_bridge_message(); - - let dispatch_weight = FromRialtoMessageDispatch::dispatch_weight(&mut incoming_message); - assert_eq!(dispatch_weight, XcmRouterWeigher::::get()); + let incoming_message = prepare_inbound_bridge_message(); // we care only about handing message to the XCM dispatcher, so we don't care about its // actual dispatch @@ -364,11 +357,7 @@ mod tests { #[test] fn xcm_messages_from_rialto_parachain_are_dispatched() { - let mut incoming_message = prepare_inbound_bridge_message(); - - let dispatch_weight = - FromRialtoParachainMessageDispatch::dispatch_weight(&mut incoming_message); - assert_eq!(dispatch_weight, XcmRouterWeigher::::get()); + let incoming_message = prepare_inbound_bridge_message(); // we care only about handing message to the XCM dispatcher, so we don't care about its // actual dispatch diff --git a/bin/rialto-parachain/runtime/src/lib.rs b/bin/rialto-parachain/runtime/src/lib.rs index 58c6a8c673f..460f4aa6a68 100644 --- a/bin/rialto-parachain/runtime/src/lib.rs +++ b/bin/rialto-parachain/runtime/src/lib.rs @@ -844,12 +844,10 @@ mod tests { LaneId, MessageKey, }; use bridge_runtime_common::{ - integrity::check_additional_signed, - messages_xcm_extension::{XcmBlobMessageDispatchResult, XcmRouterWeigher}, + integrity::check_additional_signed, messages_xcm_extension::XcmBlobMessageDispatchResult, }; use codec::Encode; use pallet_bridge_messages::OutboundLanes; - use sp_core::Get; use sp_runtime::generic::Era; use xcm_executor::XcmExecutor; @@ -914,10 +912,7 @@ mod tests { #[test] fn xcm_messages_from_millau_are_dispatched() { new_test_ext().execute_with(|| { - let mut incoming_message = prepare_inbound_bridge_message(); - - let dispatch_weight = FromMillauMessageDispatch::dispatch_weight(&mut incoming_message); - assert_eq!(dispatch_weight, XcmRouterWeigher::<()>::get()); + let incoming_message = prepare_inbound_bridge_message(); // we care only about handing message to the XCM dispatcher, so we don't care about its // actual dispatch diff --git a/bin/rialto-parachain/runtime/src/millau_messages.rs b/bin/rialto-parachain/runtime/src/millau_messages.rs index 3fff141bf84..5d4a92b5091 100644 --- a/bin/rialto-parachain/runtime/src/millau_messages.rs +++ b/bin/rialto-parachain/runtime/src/millau_messages.rs @@ -63,7 +63,7 @@ pub type FromMillauMessageDispatch = bp_rialto_parachain::RialtoParachain, bp_millau::Millau, crate::OnRialtoParachainBlobDispatcher, - bridge_runtime_common::messages_xcm_extension::XcmRouterWeigher<()>, + (), >; /// Messages proof for Millau -> RialtoParachain messages. diff --git a/bin/rialto/runtime/src/millau_messages.rs b/bin/rialto/runtime/src/millau_messages.rs index 9d0c4f97c89..ab4b7dd521d 100644 --- a/bin/rialto/runtime/src/millau_messages.rs +++ b/bin/rialto/runtime/src/millau_messages.rs @@ -60,7 +60,7 @@ pub type FromMillauMessageDispatch = bp_rialto::Rialto, bp_millau::Millau, crate::xcm_config::OnRialtoBlobDispatcher, - bridge_runtime_common::messages_xcm_extension::XcmRouterWeigher, + (), >; /// Messages proof for Millau -> Rialto messages. diff --git a/bin/rialto/runtime/src/xcm_config.rs b/bin/rialto/runtime/src/xcm_config.rs index 64a5a896f95..7a4966d92dd 100644 --- a/bin/rialto/runtime/src/xcm_config.rs +++ b/bin/rialto/runtime/src/xcm_config.rs @@ -189,18 +189,15 @@ mod tests { use super::*; use crate::{ millau_messages::{FromMillauMessageDispatch, XCM_LANE}, - DbWeight, WithMillauMessagesInstance, + WithMillauMessagesInstance, }; use bp_messages::{ target_chain::{DispatchMessage, DispatchMessageData, MessageDispatch}, LaneId, MessageKey, }; - use bridge_runtime_common::messages_xcm_extension::{ - XcmBlobMessageDispatchResult, XcmRouterWeigher, - }; + use bridge_runtime_common::messages_xcm_extension::XcmBlobMessageDispatchResult; use codec::Encode; use pallet_bridge_messages::OutboundLanes; - use sp_core::Get; use xcm_executor::XcmExecutor; fn new_test_ext() -> sp_io::TestExternalities { @@ -263,10 +260,7 @@ mod tests { #[test] fn xcm_messages_from_millau_are_dispatched() { - let mut incoming_message = prepare_inbound_bridge_message(); - - let dispatch_weight = FromMillauMessageDispatch::dispatch_weight(&mut incoming_message); - assert_eq!(dispatch_weight, XcmRouterWeigher::::get()); + let incoming_message = prepare_inbound_bridge_message(); // we care only about handing message to the XCM dispatcher, so we don't care about its // actual dispatch diff --git a/bin/runtime-common/src/messages_benchmarking.rs b/bin/runtime-common/src/messages_benchmarking.rs index 028172e7ab4..b067523c305 100644 --- a/bin/runtime-common/src/messages_benchmarking.rs +++ b/bin/runtime-common/src/messages_benchmarking.rs @@ -40,6 +40,39 @@ use pallet_bridge_messages::benchmarking::{MessageDeliveryProofParams, MessagePr use sp_runtime::traits::{Header, Zero}; use sp_std::prelude::*; use sp_trie::{trie_types::TrieDBMutBuilderV1, LayoutV1, MemoryDB, TrieMut}; +use xcm::v3::prelude::*; + +/// Prepare inbound bridge message according to given message proof parameters. +fn prepare_inbound_message( + params: &MessageProofParams, + destination: InteriorMultiLocation, +) -> Vec { + // we only care about **this** message size when message proof needs to be `Minimal` + let expected_size = match params.size { + StorageProofSize::Minimal(size) => size as usize, + _ => 0, + }; + + // if we don't need a correct message, then we may just return some random blob + if !params.is_successful_dispatch_expected { + return vec![0u8; expected_size] + } + + // else let's prepare successful message. For XCM bridge hubs, it is the message that + // will be pushed further to some XCM queue (XCMP/UMP) + let location = xcm::VersionedInteriorMultiLocation::V3(destination); + let location_encoded_size = location.encoded_size(); + + // we don't need to be super-precise with `expected_size` here + let xcm_size = expected_size.saturating_sub(location_encoded_size); + let xcm = xcm::VersionedXcm::<()>::V3(vec![Instruction::ClearOrigin; xcm_size].into()); + + // this is the `BridgeMessage` from polkadot xcm builder, but it has no constructor + // or public fields, so just tuple + // (double encoding, because `.encode()` is called on original Xcm BLOB when it is pushed + // to the storage) + (location, xcm).encode().encode() +} /// Prepare proof of messages for the `receive_messages_proof` call. /// @@ -51,6 +84,7 @@ use sp_trie::{trie_types::TrieDBMutBuilderV1, LayoutV1, MemoryDB, TrieMut}; /// function. pub fn prepare_message_proof_from_grandpa_chain( params: MessageProofParams, + message_destination: InteriorMultiLocation, ) -> (FromBridgedChainMessagesProof>>, Weight) where R: pallet_bridge_grandpa::Config>>, @@ -61,12 +95,9 @@ where let (state_root, storage_proof) = prepare_messages_storage_proof::( params.lane, params.message_nonces.clone(), - params.outbound_lane_data, + params.outbound_lane_data.clone(), params.size, - match params.size { - StorageProofSize::Minimal(ref size) => vec![0u8; *size as _], - _ => vec![], - }, + prepare_inbound_message(¶ms, message_destination), encode_all_messages, encode_lane_data, ); @@ -82,7 +113,7 @@ where nonces_start: *params.message_nonces.start(), nonces_end: *params.message_nonces.end(), }, - Weight::zero(), + Weight::MAX / 1000, ) } @@ -96,6 +127,7 @@ where /// `prepare_message_proof_from_grandpa_chain` function. pub fn prepare_message_proof_from_parachain( params: MessageProofParams, + message_destination: InteriorMultiLocation, ) -> (FromBridgedChainMessagesProof>>, Weight) where R: pallet_bridge_parachains::Config, @@ -107,12 +139,9 @@ where let (state_root, storage_proof) = prepare_messages_storage_proof::( params.lane, params.message_nonces.clone(), - params.outbound_lane_data, + params.outbound_lane_data.clone(), params.size, - match params.size { - StorageProofSize::Minimal(ref size) => vec![0u8; *size as _], - _ => vec![], - }, + prepare_inbound_message(¶ms, message_destination), encode_all_messages, encode_lane_data, ); @@ -129,7 +158,7 @@ where nonces_start: *params.message_nonces.start(), nonces_end: *params.message_nonces.end(), }, - Weight::zero(), + Weight::MAX / 1000, ) } diff --git a/bin/runtime-common/src/messages_xcm_extension.rs b/bin/runtime-common/src/messages_xcm_extension.rs index a8ca86c85c3..d4bf2bc1bed 100644 --- a/bin/runtime-common/src/messages_xcm_extension.rs +++ b/bin/runtime-common/src/messages_xcm_extension.rs @@ -28,43 +28,15 @@ use bp_messages::{ }; use bp_runtime::{messages::MessageDispatchResult, AccountIdOf, Chain}; use codec::{Decode, Encode}; -use frame_support::{ - dispatch::Weight, traits::Get, weights::RuntimeDbWeight, CloneNoBound, EqNoBound, - PartialEqNoBound, -}; +use frame_support::{dispatch::Weight, CloneNoBound, EqNoBound, PartialEqNoBound}; +use pallet_bridge_messages::WeightInfoExt as MessagesPalletWeights; use scale_info::TypeInfo; -use sp_std::marker::PhantomData; +use sp_runtime::SaturatedConversion; use xcm_builder::{DispatchBlob, DispatchBlobError, HaulBlob, HaulBlobError}; /// Plain "XCM" payload, which we transfer through bridge pub type XcmAsPlainPayload = sp_std::prelude::Vec; -// TODO: below are just rough estimations. Other things also happen there (including hashing and so -// on). Shall we do some benchmarking??? TODO: add proof_size component here -// https://github.com/paritytech/parity-bridges-common/issues/1986 - -/// Simple weigher for incoming XCM dispatch at **bridge hubs** to use with -/// `XcmBlobMessageDispatch`. -/// -/// By our design, message at bridge hub is simply pushed to some other queue. This implementation -/// is for this case only. If your runtime performs some other actions with incoming XCM messages, -/// you shall use your own implementation. -/// -/// If message is redirected to the relay chain, then `ParentAsUmp` is used and it roughly does -/// 1 db read and 1 db write (in its `send_upward_message` method). -/// -/// If message is redirected to some sibling parachain, then `XcmpQueue` is used and -/// it roughly does 2 db reads and 2 db writes (in its `SendXcm` implementation). -/// -/// The difference is not that big, so let's choose maximal. -pub struct XcmRouterWeigher(PhantomData); - -impl> Get for XcmRouterWeigher { - fn get() -> Weight { - T::get().reads_writes(2, 2) - } -} - /// Message dispatch result type for single message #[derive(CloneNoBound, EqNoBound, PartialEqNoBound, Encode, Decode, Debug, TypeInfo)] pub enum XcmBlobMessageDispatchResult { @@ -74,17 +46,13 @@ pub enum XcmBlobMessageDispatchResult { } /// [`XcmBlobMessageDispatch`] is responsible for dispatching received messages -pub struct XcmBlobMessageDispatch< - SourceBridgeHubChain, - TargetBridgeHubChain, - DispatchBlob, - DispatchBlobWeigher, -> { +pub struct XcmBlobMessageDispatch +{ _marker: sp_std::marker::PhantomData<( SourceBridgeHubChain, TargetBridgeHubChain, DispatchBlob, - DispatchBlobWeigher, + Weights, )>, } @@ -92,20 +60,21 @@ impl< SourceBridgeHubChain: Chain, TargetBridgeHubChain: Chain, BlobDispatcher: DispatchBlob, - DispatchBlobWeigher: Get, + Weights: MessagesPalletWeights, > MessageDispatch> - for XcmBlobMessageDispatch< - SourceBridgeHubChain, - TargetBridgeHubChain, - BlobDispatcher, - DispatchBlobWeigher, - > + for XcmBlobMessageDispatch { type DispatchPayload = XcmAsPlainPayload; type DispatchLevelResult = XcmBlobMessageDispatchResult; - fn dispatch_weight(_message: &mut DispatchMessage) -> Weight { - DispatchBlobWeigher::get() + fn dispatch_weight(message: &mut DispatchMessage) -> Weight { + match message.data.payload { + Ok(ref payload) => { + let payload_size = payload.encoded_size().saturated_into(); + Weights::message_dispatch_weight(payload_size) + }, + Err(_) => Weight::zero(), + } } fn dispatch( @@ -122,7 +91,6 @@ impl< message.key.nonce ); return MessageDispatchResult { - // TODO:check-parameter - setup uspent_weight? https://github.com/paritytech/polkadot/issues/6629 unspent_weight: Weight::zero(), dispatch_level_result: XcmBlobMessageDispatchResult::InvalidPayload, } @@ -158,11 +126,7 @@ impl< XcmBlobMessageDispatchResult::NotDispatched(e) }, }; - MessageDispatchResult { - // TODO:check-parameter - setup uspent_weight? https://github.com/paritytech/polkadot/issues/6629 - unspent_weight: Weight::zero(), - dispatch_level_result, - } + MessageDispatchResult { unspent_weight: Weight::zero(), dispatch_level_result } } } diff --git a/modules/messages/src/benchmarking.rs b/modules/messages/src/benchmarking.rs index 955dd3da2c5..bc9c1f75257 100644 --- a/modules/messages/src/benchmarking.rs +++ b/modules/messages/src/benchmarking.rs @@ -48,6 +48,11 @@ pub struct MessageProofParams { pub message_nonces: RangeInclusive, /// If `Some`, the proof needs to include this outbound lane data. pub outbound_lane_data: Option, + /// If `true`, the caller expects that the proof will contain correct messages that will + /// be successfully dispatched. This is only called from the "optional" + /// `receive_single_message_proof_with_dispatch` benchmark. If you don't need it, just + /// return `true` from the `is_message_successfully_dispatched`. + pub is_successful_dispatch_expected: bool, /// Proof size requirements. pub size: StorageProofSize, } @@ -95,32 +100,25 @@ pub trait Config: crate::Config { params: MessageDeliveryProofParams, ) -> >::MessagesDeliveryProof; - /// Returns true if message has been dispatched (either successfully or not). - /// - /// We assume that messages have near-zero dispatch weight, so most of times it - /// is hard to determine whether messages has been dispatched or not. For example, - /// XCM message can be a call that leaves entry in `frame_system::Events` vector, - /// but not all XCM messages do that and we don't want to include weight of this - /// action to the base weight of message delivery. Hence, the default `true` return - /// value. - fn is_message_dispatched(_nonce: MessageNonce) -> bool { + /// Returns true if message has been successfully dispatched or not. + fn is_message_successfully_dispatched(_nonce: MessageNonce) -> bool { true } + /// Returns true if given relayer has been rewarded for some of its actions. fn is_relayer_rewarded(relayer: &Self::AccountId) -> bool; } benchmarks_instance_pallet! { // - // Benchmarks that are used directly by the runtime. + // Benchmarks that are used directly by the runtime calls weight formulae. // // Benchmark `receive_messages_proof` extrinsic with single minimal-weight message and following conditions: // * proof does not include outbound lane state proof; // * inbound lane already has state, so it needs to be read and decoded; - // * message is successfully dispatched; - // * message requires all heavy checks done by dispatcher; - // * message dispatch fee is paid at target (this) chain. + // * message is dispatched (reminder: dispatch weight should be minimal); + // * message requires all heavy checks done by dispatcher. // // This is base benchmark for all other message delivery benchmarks. receive_single_message_proof { @@ -135,6 +133,7 @@ benchmarks_instance_pallet! { lane: T::bench_lane_id(), message_nonces: 21..=21, outbound_lane_data: None, + is_successful_dispatch_expected: false, size: StorageProofSize::Minimal(EXPECTED_DEFAULT_MESSAGE_LENGTH), }); }: receive_messages_proof(RawOrigin::Signed(relayer_id_on_target), relayer_id_on_source, proof, 1, dispatch_weight) @@ -143,15 +142,13 @@ benchmarks_instance_pallet! { crate::InboundLanes::::get(&T::bench_lane_id()).last_delivered_nonce(), 21, ); - assert!(T::is_message_dispatched(21)); } // Benchmark `receive_messages_proof` extrinsic with two minimal-weight messages and following conditions: // * proof does not include outbound lane state proof; // * inbound lane already has state, so it needs to be read and decoded; - // * message is successfully dispatched; - // * message requires all heavy checks done by dispatcher; - // * message dispatch fee is paid at target (this) chain. + // * message is dispatched (reminder: dispatch weight should be minimal); + // * message requires all heavy checks done by dispatcher. // // The weight of single message delivery could be approximated as // `weight(receive_two_messages_proof) - weight(receive_single_message_proof)`. @@ -169,6 +166,7 @@ benchmarks_instance_pallet! { lane: T::bench_lane_id(), message_nonces: 21..=22, outbound_lane_data: None, + is_successful_dispatch_expected: false, size: StorageProofSize::Minimal(EXPECTED_DEFAULT_MESSAGE_LENGTH), }); }: receive_messages_proof(RawOrigin::Signed(relayer_id_on_target), relayer_id_on_source, proof, 2, dispatch_weight) @@ -177,15 +175,13 @@ benchmarks_instance_pallet! { crate::InboundLanes::::get(&T::bench_lane_id()).last_delivered_nonce(), 22, ); - assert!(T::is_message_dispatched(22)); } // Benchmark `receive_messages_proof` extrinsic with single minimal-weight message and following conditions: // * proof includes outbound lane state proof; // * inbound lane already has state, so it needs to be read and decoded; - // * message is successfully dispatched; - // * message requires all heavy checks done by dispatcher; - // * message dispatch fee is paid at target (this) chain. + // * message is successfully dispatched (reminder: dispatch weight should be minimal); + // * message requires all heavy checks done by dispatcher. // // The weight of outbound lane state delivery would be // `weight(receive_single_message_proof_with_outbound_lane_state) - weight(receive_single_message_proof)`. @@ -207,6 +203,7 @@ benchmarks_instance_pallet! { latest_received_nonce: 20, latest_generated_nonce: 21, }), + is_successful_dispatch_expected: false, size: StorageProofSize::Minimal(EXPECTED_DEFAULT_MESSAGE_LENGTH), }); }: receive_messages_proof(RawOrigin::Signed(relayer_id_on_target), relayer_id_on_source, proof, 1, dispatch_weight) @@ -214,14 +211,13 @@ benchmarks_instance_pallet! { let lane_state = crate::InboundLanes::::get(&T::bench_lane_id()); assert_eq!(lane_state.last_delivered_nonce(), 21); assert_eq!(lane_state.last_confirmed_nonce, 20); - assert!(T::is_message_dispatched(21)); } // Benchmark `receive_messages_proof` extrinsic with single minimal-weight message and following conditions: - // * the proof has many redundand trie nodes with total size of approximately 1KB; + // * the proof has large leaf with total size of approximately 1KB; // * proof does not include outbound lane state proof; // * inbound lane already has state, so it needs to be read and decoded; - // * message is successfully dispatched; + // * message is dispatched (reminder: dispatch weight should be minimal); // * message requires all heavy checks done by dispatcher. // // With single KB of messages proof, the weight of the call is increased (roughly) by @@ -238,6 +234,7 @@ benchmarks_instance_pallet! { lane: T::bench_lane_id(), message_nonces: 21..=21, outbound_lane_data: None, + is_successful_dispatch_expected: false, size: StorageProofSize::HasLargeLeaf(1024), }); }: receive_messages_proof(RawOrigin::Signed(relayer_id_on_target), relayer_id_on_source, proof, 1, dispatch_weight) @@ -246,14 +243,13 @@ benchmarks_instance_pallet! { crate::InboundLanes::::get(&T::bench_lane_id()).last_delivered_nonce(), 21, ); - assert!(T::is_message_dispatched(21)); } // Benchmark `receive_messages_proof` extrinsic with single minimal-weight message and following conditions: - // * the proof has many redundand trie nodes with total size of approximately 16KB; + // * the proof has large leaf with total size of approximately 16KB; // * proof does not include outbound lane state proof; // * inbound lane already has state, so it needs to be read and decoded; - // * message is successfully dispatched; + // * message is dispatched (reminder: dispatch weight should be minimal); // * message requires all heavy checks done by dispatcher. // // Size of proof grows because it contains extra trie nodes in it. @@ -272,6 +268,7 @@ benchmarks_instance_pallet! { lane: T::bench_lane_id(), message_nonces: 21..=21, outbound_lane_data: None, + is_successful_dispatch_expected: false, size: StorageProofSize::HasLargeLeaf(16 * 1024), }); }: receive_messages_proof(RawOrigin::Signed(relayer_id_on_target), relayer_id_on_source, proof, 1, dispatch_weight) @@ -280,7 +277,6 @@ benchmarks_instance_pallet! { crate::InboundLanes::::get(&T::bench_lane_id()).last_delivered_nonce(), 21, ); - assert!(T::is_message_dispatched(21)); } // Benchmark `receive_messages_delivery_proof` extrinsic with following conditions: @@ -400,6 +396,47 @@ benchmarks_instance_pallet! { assert!(T::is_relayer_rewarded(&relayer1_id)); assert!(T::is_relayer_rewarded(&relayer2_id)); } + + // + // Benchmarks that the runtime developers may use for proper pallet configuration. + // + + // This benchmark is optional and may be used when runtime developer need a way to compute + // message dispatch weight. In this case, he needs to provide messages that can go the whole + // dispatch + // + // Benchmark `receive_messages_proof` extrinsic with single message and following conditions: + // + // * proof does not include outbound lane state proof; + // * inbound lane already has state, so it needs to be read and decoded; + // * message is **SUCCESSFULLY** dispatched; + // * message requires all heavy checks done by dispatcher. + receive_single_message_proof_with_dispatch { + // maybe dispatch weight relies on the message size too? + let i in EXPECTED_DEFAULT_MESSAGE_LENGTH .. EXPECTED_DEFAULT_MESSAGE_LENGTH * 16; + + let relayer_id_on_source = T::bridged_relayer_id(); + let relayer_id_on_target = account("relayer", 0, SEED); + T::endow_account(&relayer_id_on_target); + + // mark messages 1..=20 as delivered + receive_messages::(20); + + let (proof, dispatch_weight) = T::prepare_message_proof(MessageProofParams { + lane: T::bench_lane_id(), + message_nonces: 21..=21, + outbound_lane_data: None, + is_successful_dispatch_expected: true, + size: StorageProofSize::Minimal(i), + }); + }: receive_messages_proof(RawOrigin::Signed(relayer_id_on_target), relayer_id_on_source, proof, 1, dispatch_weight) + verify { + assert_eq!( + crate::InboundLanes::::get(&T::bench_lane_id()).last_delivered_nonce(), + 21, + ); + assert!(T::is_message_successfully_dispatched(21)); + } } fn send_regular_message, I: 'static>() { diff --git a/modules/messages/src/weights.rs b/modules/messages/src/weights.rs index 4b2e5b48ee2..baaef317241 100644 --- a/modules/messages/src/weights.rs +++ b/modules/messages/src/weights.rs @@ -17,7 +17,7 @@ //! Autogenerated weights for RialtoMessages //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2023-03-02, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2023-03-23, 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` //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024 @@ -58,6 +58,7 @@ pub trait WeightInfo { fn receive_delivery_proof_for_single_message() -> Weight; fn receive_delivery_proof_for_two_messages_by_single_relayer() -> Weight; fn receive_delivery_proof_for_two_messages_by_two_relayers() -> Weight; + fn receive_single_message_proof_with_dispatch(i: u32) -> Weight; } /// Weights for `RialtoMessages` that are generated using one of the Bridge testnets. @@ -79,19 +80,14 @@ impl WeightInfo for BridgeWeight { /// /// Proof: BridgeRialtoMessages InboundLanes (max_values: None, max_size: Some(49180), added: /// 51655, mode: MaxEncodedLen) - /// - /// Storage: Balances TotalIssuance (r:1 w:1) - /// - /// Proof: Balances TotalIssuance (max_values: Some(1), max_size: Some(8), added: 503, mode: - /// MaxEncodedLen) fn receive_single_message_proof() -> Weight { // Proof Size summary in bytes: - // Measured: `693` - // Estimated: `54703` - // Minimum execution time: 48_058 nanoseconds. - Weight::from_parts(50_422_000, 54703) - .saturating_add(T::DbWeight::get().reads(4_u64)) - .saturating_add(T::DbWeight::get().writes(2_u64)) + // Measured: `618` + // Estimated: `57170` + // Minimum execution time: 52_321 nanoseconds. + Weight::from_parts(54_478_000, 57170) + .saturating_add(T::DbWeight::get().reads(3_u64)) + .saturating_add(T::DbWeight::get().writes(1_u64)) } /// Storage: BridgeRialtoMessages PalletOperatingMode (r:1 w:0) /// @@ -107,19 +103,14 @@ impl WeightInfo for BridgeWeight { /// /// Proof: BridgeRialtoMessages InboundLanes (max_values: None, max_size: Some(49180), added: /// 51655, mode: MaxEncodedLen) - /// - /// Storage: Balances TotalIssuance (r:1 w:1) - /// - /// Proof: Balances TotalIssuance (max_values: Some(1), max_size: Some(8), added: 503, mode: - /// MaxEncodedLen) fn receive_two_messages_proof() -> Weight { // Proof Size summary in bytes: - // Measured: `693` - // Estimated: `54703` - // Minimum execution time: 59_371 nanoseconds. - Weight::from_parts(61_726_000, 54703) - .saturating_add(T::DbWeight::get().reads(4_u64)) - .saturating_add(T::DbWeight::get().writes(2_u64)) + // Measured: `618` + // Estimated: `57170` + // Minimum execution time: 64_597 nanoseconds. + Weight::from_parts(69_267_000, 57170) + .saturating_add(T::DbWeight::get().reads(3_u64)) + .saturating_add(T::DbWeight::get().writes(1_u64)) } /// Storage: BridgeRialtoMessages PalletOperatingMode (r:1 w:0) /// @@ -135,19 +126,14 @@ impl WeightInfo for BridgeWeight { /// /// Proof: BridgeRialtoMessages InboundLanes (max_values: None, max_size: Some(49180), added: /// 51655, mode: MaxEncodedLen) - /// - /// Storage: Balances TotalIssuance (r:1 w:1) - /// - /// Proof: Balances TotalIssuance (max_values: Some(1), max_size: Some(8), added: 503, mode: - /// MaxEncodedLen) fn receive_single_message_proof_with_outbound_lane_state() -> Weight { // Proof Size summary in bytes: - // Measured: `693` - // Estimated: `54703` - // Minimum execution time: 53_398 nanoseconds. - Weight::from_parts(54_351_000, 54703) - .saturating_add(T::DbWeight::get().reads(4_u64)) - .saturating_add(T::DbWeight::get().writes(2_u64)) + // Measured: `618` + // Estimated: `57170` + // Minimum execution time: 64_079 nanoseconds. + Weight::from_parts(65_905_000, 57170) + .saturating_add(T::DbWeight::get().reads(3_u64)) + .saturating_add(T::DbWeight::get().writes(1_u64)) } /// Storage: BridgeRialtoMessages PalletOperatingMode (r:1 w:0) /// @@ -166,9 +152,9 @@ impl WeightInfo for BridgeWeight { fn receive_single_message_proof_1_kb() -> Weight { // Proof Size summary in bytes: // Measured: `618` - // Estimated: `54200` - // Minimum execution time: 50_064 nanoseconds. - Weight::from_parts(51_306_000, 54200) + // Estimated: `57170` + // Minimum execution time: 50_588 nanoseconds. + Weight::from_parts(53_544_000, 57170) .saturating_add(T::DbWeight::get().reads(3_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -189,9 +175,9 @@ impl WeightInfo for BridgeWeight { fn receive_single_message_proof_16_kb() -> Weight { // Proof Size summary in bytes: // Measured: `618` - // Estimated: `54200` - // Minimum execution time: 75_403 nanoseconds. - Weight::from_parts(77_006_000, 54200) + // Estimated: `57170` + // Minimum execution time: 78_269 nanoseconds. + Weight::from_parts(81_748_000, 57170) .saturating_add(T::DbWeight::get().reads(3_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -217,9 +203,9 @@ impl WeightInfo for BridgeWeight { fn receive_delivery_proof_for_single_message() -> Weight { // Proof Size summary in bytes: // Measured: `579` - // Estimated: `5624` - // Minimum execution time: 41_670 nanoseconds. - Weight::from_parts(42_863_000, 5624) + // Estimated: `9584` + // Minimum execution time: 45_786 nanoseconds. + Weight::from_parts(47_382_000, 9584) .saturating_add(T::DbWeight::get().reads(4_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } @@ -245,9 +231,9 @@ impl WeightInfo for BridgeWeight { fn receive_delivery_proof_for_two_messages_by_single_relayer() -> Weight { // Proof Size summary in bytes: // Measured: `596` - // Estimated: `5624` - // Minimum execution time: 40_928 nanoseconds. - Weight::from_parts(42_165_000, 5624) + // Estimated: `9584` + // Minimum execution time: 44_544 nanoseconds. + Weight::from_parts(45_451_000, 9584) .saturating_add(T::DbWeight::get().reads(4_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } @@ -273,12 +259,39 @@ impl WeightInfo for BridgeWeight { fn receive_delivery_proof_for_two_messages_by_two_relayers() -> Weight { // Proof Size summary in bytes: // Measured: `596` - // Estimated: `8164` - // Minimum execution time: 44_022 nanoseconds. - Weight::from_parts(44_657_000, 8164) + // Estimated: `12124` + // Minimum execution time: 47_344 nanoseconds. + Weight::from_parts(48_311_000, 12124) .saturating_add(T::DbWeight::get().reads(5_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) } + /// Storage: BridgeRialtoMessages PalletOperatingMode (r:1 w:0) + /// + /// Proof: BridgeRialtoMessages PalletOperatingMode (max_values: Some(1), max_size: Some(2), + /// added: 497, mode: MaxEncodedLen) + /// + /// Storage: BridgeRialtoGrandpa ImportedHeaders (r:1 w:0) + /// + /// Proof: BridgeRialtoGrandpa ImportedHeaders (max_values: Some(14400), max_size: Some(68), + /// added: 2048, mode: MaxEncodedLen) + /// + /// Storage: BridgeRialtoMessages InboundLanes (r:1 w:1) + /// + /// Proof: BridgeRialtoMessages InboundLanes (max_values: None, max_size: Some(49180), added: + /// 51655, mode: MaxEncodedLen) + /// + /// The range of component `i` is `[128, 2048]`. + fn receive_single_message_proof_with_dispatch(i: u32) -> Weight { + // Proof Size summary in bytes: + // Measured: `618` + // Estimated: `57170` + // Minimum execution time: 52_385 nanoseconds. + Weight::from_parts(54_919_468, 57170) + // Standard Error: 108 + .saturating_add(Weight::from_parts(3_286, 0).saturating_mul(i.into())) + .saturating_add(T::DbWeight::get().reads(3_u64)) + .saturating_add(T::DbWeight::get().writes(1_u64)) + } } // For backwards compatibility and tests @@ -297,19 +310,14 @@ impl WeightInfo for () { /// /// Proof: BridgeRialtoMessages InboundLanes (max_values: None, max_size: Some(49180), added: /// 51655, mode: MaxEncodedLen) - /// - /// Storage: Balances TotalIssuance (r:1 w:1) - /// - /// Proof: Balances TotalIssuance (max_values: Some(1), max_size: Some(8), added: 503, mode: - /// MaxEncodedLen) fn receive_single_message_proof() -> Weight { // Proof Size summary in bytes: - // Measured: `693` - // Estimated: `54703` - // Minimum execution time: 48_058 nanoseconds. - Weight::from_parts(50_422_000, 54703) - .saturating_add(RocksDbWeight::get().reads(4_u64)) - .saturating_add(RocksDbWeight::get().writes(2_u64)) + // Measured: `618` + // Estimated: `57170` + // Minimum execution time: 52_321 nanoseconds. + Weight::from_parts(54_478_000, 57170) + .saturating_add(RocksDbWeight::get().reads(3_u64)) + .saturating_add(RocksDbWeight::get().writes(1_u64)) } /// Storage: BridgeRialtoMessages PalletOperatingMode (r:1 w:0) /// @@ -325,19 +333,14 @@ impl WeightInfo for () { /// /// Proof: BridgeRialtoMessages InboundLanes (max_values: None, max_size: Some(49180), added: /// 51655, mode: MaxEncodedLen) - /// - /// Storage: Balances TotalIssuance (r:1 w:1) - /// - /// Proof: Balances TotalIssuance (max_values: Some(1), max_size: Some(8), added: 503, mode: - /// MaxEncodedLen) fn receive_two_messages_proof() -> Weight { // Proof Size summary in bytes: - // Measured: `693` - // Estimated: `54703` - // Minimum execution time: 59_371 nanoseconds. - Weight::from_parts(61_726_000, 54703) - .saturating_add(RocksDbWeight::get().reads(4_u64)) - .saturating_add(RocksDbWeight::get().writes(2_u64)) + // Measured: `618` + // Estimated: `57170` + // Minimum execution time: 64_597 nanoseconds. + Weight::from_parts(69_267_000, 57170) + .saturating_add(RocksDbWeight::get().reads(3_u64)) + .saturating_add(RocksDbWeight::get().writes(1_u64)) } /// Storage: BridgeRialtoMessages PalletOperatingMode (r:1 w:0) /// @@ -353,19 +356,14 @@ impl WeightInfo for () { /// /// Proof: BridgeRialtoMessages InboundLanes (max_values: None, max_size: Some(49180), added: /// 51655, mode: MaxEncodedLen) - /// - /// Storage: Balances TotalIssuance (r:1 w:1) - /// - /// Proof: Balances TotalIssuance (max_values: Some(1), max_size: Some(8), added: 503, mode: - /// MaxEncodedLen) fn receive_single_message_proof_with_outbound_lane_state() -> Weight { // Proof Size summary in bytes: - // Measured: `693` - // Estimated: `54703` - // Minimum execution time: 53_398 nanoseconds. - Weight::from_parts(54_351_000, 54703) - .saturating_add(RocksDbWeight::get().reads(4_u64)) - .saturating_add(RocksDbWeight::get().writes(2_u64)) + // Measured: `618` + // Estimated: `57170` + // Minimum execution time: 64_079 nanoseconds. + Weight::from_parts(65_905_000, 57170) + .saturating_add(RocksDbWeight::get().reads(3_u64)) + .saturating_add(RocksDbWeight::get().writes(1_u64)) } /// Storage: BridgeRialtoMessages PalletOperatingMode (r:1 w:0) /// @@ -384,9 +382,9 @@ impl WeightInfo for () { fn receive_single_message_proof_1_kb() -> Weight { // Proof Size summary in bytes: // Measured: `618` - // Estimated: `54200` - // Minimum execution time: 50_064 nanoseconds. - Weight::from_parts(51_306_000, 54200) + // Estimated: `57170` + // Minimum execution time: 50_588 nanoseconds. + Weight::from_parts(53_544_000, 57170) .saturating_add(RocksDbWeight::get().reads(3_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -407,9 +405,9 @@ impl WeightInfo for () { fn receive_single_message_proof_16_kb() -> Weight { // Proof Size summary in bytes: // Measured: `618` - // Estimated: `54200` - // Minimum execution time: 75_403 nanoseconds. - Weight::from_parts(77_006_000, 54200) + // Estimated: `57170` + // Minimum execution time: 78_269 nanoseconds. + Weight::from_parts(81_748_000, 57170) .saturating_add(RocksDbWeight::get().reads(3_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -435,9 +433,9 @@ impl WeightInfo for () { fn receive_delivery_proof_for_single_message() -> Weight { // Proof Size summary in bytes: // Measured: `579` - // Estimated: `5624` - // Minimum execution time: 41_670 nanoseconds. - Weight::from_parts(42_863_000, 5624) + // Estimated: `9584` + // Minimum execution time: 45_786 nanoseconds. + Weight::from_parts(47_382_000, 9584) .saturating_add(RocksDbWeight::get().reads(4_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } @@ -463,9 +461,9 @@ impl WeightInfo for () { fn receive_delivery_proof_for_two_messages_by_single_relayer() -> Weight { // Proof Size summary in bytes: // Measured: `596` - // Estimated: `5624` - // Minimum execution time: 40_928 nanoseconds. - Weight::from_parts(42_165_000, 5624) + // Estimated: `9584` + // Minimum execution time: 44_544 nanoseconds. + Weight::from_parts(45_451_000, 9584) .saturating_add(RocksDbWeight::get().reads(4_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } @@ -491,10 +489,37 @@ impl WeightInfo for () { fn receive_delivery_proof_for_two_messages_by_two_relayers() -> Weight { // Proof Size summary in bytes: // Measured: `596` - // Estimated: `8164` - // Minimum execution time: 44_022 nanoseconds. - Weight::from_parts(44_657_000, 8164) + // Estimated: `12124` + // Minimum execution time: 47_344 nanoseconds. + Weight::from_parts(48_311_000, 12124) .saturating_add(RocksDbWeight::get().reads(5_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) } + /// Storage: BridgeRialtoMessages PalletOperatingMode (r:1 w:0) + /// + /// Proof: BridgeRialtoMessages PalletOperatingMode (max_values: Some(1), max_size: Some(2), + /// added: 497, mode: MaxEncodedLen) + /// + /// Storage: BridgeRialtoGrandpa ImportedHeaders (r:1 w:0) + /// + /// Proof: BridgeRialtoGrandpa ImportedHeaders (max_values: Some(14400), max_size: Some(68), + /// added: 2048, mode: MaxEncodedLen) + /// + /// Storage: BridgeRialtoMessages InboundLanes (r:1 w:1) + /// + /// Proof: BridgeRialtoMessages InboundLanes (max_values: None, max_size: Some(49180), added: + /// 51655, mode: MaxEncodedLen) + /// + /// The range of component `i` is `[128, 2048]`. + fn receive_single_message_proof_with_dispatch(i: u32) -> Weight { + // Proof Size summary in bytes: + // Measured: `618` + // Estimated: `57170` + // Minimum execution time: 52_385 nanoseconds. + Weight::from_parts(54_919_468, 57170) + // Standard Error: 108 + .saturating_add(Weight::from_parts(3_286, 0).saturating_mul(i.into())) + .saturating_add(RocksDbWeight::get().reads(3_u64)) + .saturating_add(RocksDbWeight::get().writes(1_u64)) + } } diff --git a/modules/messages/src/weights_ext.rs b/modules/messages/src/weights_ext.rs index 5598706b5db..090c03390ba 100644 --- a/modules/messages/src/weights_ext.rs +++ b/modules/messages/src/weights_ext.rs @@ -403,6 +403,21 @@ pub trait WeightInfoExt: WeightInfo { (15 * 1024); proof_size_in_bytes * byte_weight } + + // Functions that may be used by runtime developers. + + /// Returns dispatch weight of message of given size. + /// + /// This function would return correct value only if your runtime is configured to run + /// `receive_single_message_proof_with_dispatch` benchmark. See its requirements for + /// details. + fn message_dispatch_weight(message_size: u32) -> Weight { + // There may be a tiny overweight/underweight here, because we don't account how message + // size affects all steps before dispatch. But the effect should be small enough and we + // may ignore it. + Self::receive_single_message_proof_with_dispatch(message_size) + .saturating_sub(Self::receive_single_message_proof()) + } } impl WeightInfoExt for () {