pay dispatch fee at target chain (#911)

* pay dispatch fee at target chain

* refund unspent dispatch weight to messages relayer

* test that transfer actually happens

* pay-at-target-cchain benchmarks + fix previous benchmarks (invalid signature)

* include/exclude pay-dispatch-fee weight from delivery_and_dispatch_fee/delivery tx cost

* remvoe some redundant traces

* enum DispatchFeePayment {}

* typo

* update docs

* (revert removal of valid check)

* Update modules/messages/src/benchmarking.rs

Co-authored-by: Tomasz Drwięga <tomusdrw@users.noreply.github.com>

* Update modules/messages/src/benchmarking.rs

Co-authored-by: Tomasz Drwięga <tomusdrw@users.noreply.github.com>

* Update modules/messages/src/benchmarking.rs

Co-authored-by: Tomasz Drwięga <tomusdrw@users.noreply.github.com>

* Update modules/messages/src/benchmarking.rs

Co-authored-by: Tomasz Drwięga <tomusdrw@users.noreply.github.com>

Co-authored-by: Tomasz Drwięga <tomusdrw@users.noreply.github.com>
Co-authored-by: Tomasz Drwięga <tomasz@parity.io>
This commit is contained in:
Svyatoslav Nikolsky
2021-06-18 12:35:15 +03:00
committed by Bastian Köcher
parent 613803a15d
commit 20b7f341e1
27 changed files with 1052 additions and 278 deletions
+58 -3
View File
@@ -23,6 +23,7 @@ use bp_messages::{
source_chain::TargetHeaderChain, target_chain::SourceHeaderChain, InboundLaneData, LaneId, MessageData,
MessageNonce, OutboundLaneData, UnrewardedRelayersState,
};
use bp_runtime::messages::DispatchFeePayment;
use frame_benchmarking::{account, benchmarks_instance};
use frame_support::{traits::Get, weights::Weight};
use frame_system::RawOrigin;
@@ -67,6 +68,8 @@ pub struct MessageProofParams {
pub outbound_lane_data: Option<OutboundLaneData>,
/// Proof size requirements.
pub size: ProofSize,
/// If true, dispatch fee is paid at the target chain (if supported by configuration).
pub dispatch_fee_payment: DispatchFeePayment,
}
/// Benchmark-specific message delivery proof parameters.
@@ -108,6 +111,8 @@ pub trait Config<I: Instance>: crate::Config<I> {
fn prepare_message_delivery_proof(
params: MessageDeliveryProofParams<Self::AccountId>,
) -> <Self::TargetHeaderChain as TargetHeaderChain<Self::OutboundPayload, Self::AccountId>>::MessagesDeliveryProof;
/// Returns true if message has been dispatched (either successfully or not).
fn is_message_dispatched(nonce: MessageNonce) -> bool;
}
benchmarks_instance! {
@@ -242,7 +247,8 @@ benchmarks_instance! {
// * 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 requires all heavy checks done by dispatcher;
// * message dispatch fee is paid at target (this) chain.
//
// This is base benchmark for all other message delivery benchmarks.
receive_single_message_proof {
@@ -257,6 +263,7 @@ benchmarks_instance! {
message_nonces: 21..=21,
outbound_lane_data: None,
size: ProofSize::Minimal(EXPECTED_DEFAULT_MESSAGE_LENGTH),
dispatch_fee_payment: DispatchFeePayment::AtTargetChain,
});
}: receive_messages_proof(RawOrigin::Signed(relayer_id_on_target), relayer_id_on_source, proof, 1, dispatch_weight)
verify {
@@ -264,13 +271,15 @@ benchmarks_instance! {
crate::Pallet::<T, I>::inbound_latest_received_nonce(T::bench_lane_id()),
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 requires all heavy checks done by dispatcher;
// * message dispatch fee is paid at target (this) chain.
//
// The weight of single message delivery could be approximated as
// `weight(receive_two_messages_proof) - weight(receive_single_message_proof)`.
@@ -288,6 +297,7 @@ benchmarks_instance! {
message_nonces: 21..=22,
outbound_lane_data: None,
size: ProofSize::Minimal(EXPECTED_DEFAULT_MESSAGE_LENGTH),
dispatch_fee_payment: DispatchFeePayment::AtTargetChain,
});
}: receive_messages_proof(RawOrigin::Signed(relayer_id_on_target), relayer_id_on_source, proof, 2, dispatch_weight)
verify {
@@ -295,13 +305,15 @@ benchmarks_instance! {
crate::Pallet::<T, I>::inbound_latest_received_nonce(T::bench_lane_id()),
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 requires all heavy checks done by dispatcher;
// * message dispatch fee is paid at target (this) chain.
//
// The weight of outbound lane state delivery would be
// `weight(receive_single_message_proof_with_outbound_lane_state) - weight(receive_single_message_proof)`.
@@ -323,6 +335,7 @@ benchmarks_instance! {
latest_generated_nonce: 21,
}),
size: ProofSize::Minimal(EXPECTED_DEFAULT_MESSAGE_LENGTH),
dispatch_fee_payment: DispatchFeePayment::AtTargetChain,
});
}: receive_messages_proof(RawOrigin::Signed(relayer_id_on_target), relayer_id_on_source, proof, 1, dispatch_weight)
verify {
@@ -334,6 +347,7 @@ benchmarks_instance! {
crate::Pallet::<T, I>::inbound_latest_confirmed_nonce(T::bench_lane_id()),
20,
);
assert!(T::is_message_dispatched(21));
}
// Benchmark `receive_messages_proof` extrinsic with single minimal-weight message and following conditions:
@@ -357,6 +371,7 @@ benchmarks_instance! {
message_nonces: 21..=21,
outbound_lane_data: None,
size: ProofSize::HasExtraNodes(1024),
dispatch_fee_payment: DispatchFeePayment::AtTargetChain,
});
}: receive_messages_proof(RawOrigin::Signed(relayer_id_on_target), relayer_id_on_source, proof, 1, dispatch_weight)
verify {
@@ -364,6 +379,7 @@ benchmarks_instance! {
crate::Pallet::<T, I>::inbound_latest_received_nonce(T::bench_lane_id()),
21,
);
assert!(T::is_message_dispatched(21));
}
// Benchmark `receive_messages_proof` extrinsic with single minimal-weight message and following conditions:
@@ -389,6 +405,7 @@ benchmarks_instance! {
message_nonces: 21..=21,
outbound_lane_data: None,
size: ProofSize::HasExtraNodes(16 * 1024),
dispatch_fee_payment: DispatchFeePayment::AtTargetChain,
});
}: receive_messages_proof(RawOrigin::Signed(relayer_id_on_target), relayer_id_on_source, proof, 1, dispatch_weight)
verify {
@@ -396,6 +413,40 @@ benchmarks_instance! {
crate::Pallet::<T, I>::inbound_latest_received_nonce(T::bench_lane_id()),
21,
);
assert!(T::is_message_dispatched(21));
}
// 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 source (bridged) chain.
//
// This benchmark is used to compute extra weight spent at target chain when fee is paid there. Then we use
// this information in two places: (1) to reduce weight of delivery tx if sender pays fee at the source chain
// and (2) to refund relayer with this weight if fee has been paid at the source chain.
receive_single_prepaid_message_proof {
let relayer_id_on_source = T::bridged_relayer_id();
let relayer_id_on_target = account("relayer", 0, SEED);
// mark messages 1..=20 as delivered
receive_messages::<T, I>(20);
let (proof, dispatch_weight) = T::prepare_message_proof(MessageProofParams {
lane: T::bench_lane_id(),
message_nonces: 21..=21,
outbound_lane_data: None,
size: ProofSize::Minimal(EXPECTED_DEFAULT_MESSAGE_LENGTH),
dispatch_fee_payment: DispatchFeePayment::AtSourceChain,
});
}: receive_messages_proof(RawOrigin::Signed(relayer_id_on_target), relayer_id_on_source, proof, 1, dispatch_weight)
verify {
assert_eq!(
crate::Pallet::<T, I>::inbound_latest_received_nonce(T::bench_lane_id()),
21,
);
assert!(T::is_message_dispatched(21));
}
// Benchmark `receive_messages_delivery_proof` extrinsic with following conditions:
@@ -569,6 +620,7 @@ benchmarks_instance! {
message_nonces: 21..=(20 + i as MessageNonce),
outbound_lane_data: None,
size: ProofSize::Minimal(EXPECTED_DEFAULT_MESSAGE_LENGTH),
dispatch_fee_payment: DispatchFeePayment::AtTargetChain,
});
}: receive_messages_proof(
RawOrigin::Signed(relayer_id_on_target),
@@ -606,6 +658,7 @@ benchmarks_instance! {
message_nonces: 21..=21,
outbound_lane_data: None,
size: ProofSize::HasExtraNodes(i as _),
dispatch_fee_payment: DispatchFeePayment::AtTargetChain,
});
}: receive_messages_proof(
RawOrigin::Signed(relayer_id_on_target),
@@ -643,6 +696,7 @@ benchmarks_instance! {
message_nonces: 21..=21,
outbound_lane_data: None,
size: ProofSize::HasLargeLeaf(i as _),
dispatch_fee_payment: DispatchFeePayment::AtTargetChain,
});
}: receive_messages_proof(
RawOrigin::Signed(relayer_id_on_target),
@@ -686,6 +740,7 @@ benchmarks_instance! {
latest_generated_nonce: 21,
}),
size: ProofSize::Minimal(0),
dispatch_fee_payment: DispatchFeePayment::AtTargetChain,
});
}: receive_messages_proof(
RawOrigin::Signed(relayer_id_on_target),
+175 -84
View File
@@ -20,6 +20,8 @@ use bp_messages::{
target_chain::{DispatchMessage, DispatchMessageData, MessageDispatch},
InboundLaneData, LaneId, MessageKey, MessageNonce, OutboundLaneData,
};
use bp_runtime::messages::MessageDispatchResult;
use frame_support::RuntimeDebug;
use sp_std::prelude::PartialEq;
/// Inbound lane storage.
@@ -27,7 +29,7 @@ pub trait InboundLaneStorage {
/// Delivery and dispatch fee type on source chain.
type MessageFee;
/// Id of relayer on source chain.
type Relayer: PartialEq;
type Relayer: Clone + PartialEq;
/// Lane id.
fn id(&self) -> LaneId;
@@ -41,6 +43,22 @@ pub trait InboundLaneStorage {
fn set_data(&mut self, data: InboundLaneData<Self::Relayer>);
}
/// Result of single message receival.
#[derive(RuntimeDebug, PartialEq, Eq)]
pub enum ReceivalResult {
/// Message has been received and dispatched. Note that we don't care whether dispatch has
/// been successful or not - in both case message falls into this category.
///
/// The message dispatch result is also returned.
Dispatched(MessageDispatchResult),
/// Message has invalid nonce and lane has rejected to accept this message.
InvalidNonce,
/// There are too many unrewarded relayer entires at the lane.
TooManyUnrewardedRelayers,
/// There are too many unconfirmed messages at the lane.
TooManyUnconfirmedMessages,
}
/// Inbound messages lane.
pub struct InboundLane<S> {
storage: S,
@@ -90,51 +108,54 @@ impl<S: InboundLaneStorage> InboundLane<S> {
}
/// Receive new message.
pub fn receive_message<P: MessageDispatch<S::MessageFee>>(
pub fn receive_message<P: MessageDispatch<AccountId, S::MessageFee>, AccountId>(
&mut self,
relayer: S::Relayer,
relayer_at_bridged_chain: &S::Relayer,
relayer_at_this_chain: &AccountId,
nonce: MessageNonce,
message_data: DispatchMessageData<P::DispatchPayload, S::MessageFee>,
) -> bool {
) -> ReceivalResult {
let mut data = self.storage.data();
let is_correct_message = nonce == data.last_delivered_nonce() + 1;
if !is_correct_message {
return false;
return ReceivalResult::InvalidNonce;
}
// if there are more unrewarded relayer entries than we may accept, reject this message
if data.relayers.len() as MessageNonce >= self.storage.max_unrewarded_relayer_entries() {
return false;
return ReceivalResult::TooManyUnrewardedRelayers;
}
// if there are more unconfirmed messages than we may accept, reject this message
let unconfirmed_messages_count = nonce.saturating_sub(data.last_confirmed_nonce);
if unconfirmed_messages_count > self.storage.max_unconfirmed_messages() {
return false;
return ReceivalResult::TooManyUnconfirmedMessages;
}
let push_new = match data.relayers.back_mut() {
Some((_, nonce_high, last_relayer)) if last_relayer == &relayer => {
Some((_, nonce_high, last_relayer)) if last_relayer == relayer_at_bridged_chain => {
*nonce_high = nonce;
false
}
_ => true,
};
if push_new {
data.relayers.push_back((nonce, nonce, relayer));
data.relayers
.push_back((nonce, nonce, (*relayer_at_bridged_chain).clone()));
}
self.storage.set_data(data);
P::dispatch(DispatchMessage {
key: MessageKey {
lane_id: self.storage.id(),
nonce,
ReceivalResult::Dispatched(P::dispatch(
relayer_at_this_chain,
DispatchMessage {
key: MessageKey {
lane_id: self.storage.id(),
nonce,
},
data: message_data,
},
data: message_data,
});
true
))
}
}
@@ -144,8 +165,8 @@ mod tests {
use crate::{
inbound_lane,
mock::{
message_data, run_test, TestMessageDispatch, TestRuntime, REGULAR_PAYLOAD, TEST_LANE_ID, TEST_RELAYER_A,
TEST_RELAYER_B, TEST_RELAYER_C,
dispatch_result, message_data, run_test, TestMessageDispatch, TestRuntime, REGULAR_PAYLOAD, TEST_LANE_ID,
TEST_RELAYER_A, TEST_RELAYER_B, TEST_RELAYER_C,
},
DefaultInstance, RuntimeInboundLaneStorage,
};
@@ -154,11 +175,15 @@ mod tests {
lane: &mut InboundLane<RuntimeInboundLaneStorage<TestRuntime, DefaultInstance>>,
nonce: MessageNonce,
) {
assert!(lane.receive_message::<TestMessageDispatch>(
TEST_RELAYER_A,
nonce,
message_data(REGULAR_PAYLOAD).into()
));
assert_eq!(
lane.receive_message::<TestMessageDispatch, _>(
&TEST_RELAYER_A,
&TEST_RELAYER_A,
nonce,
message_data(REGULAR_PAYLOAD).into()
),
ReceivalResult::Dispatched(dispatch_result(0))
);
}
#[test]
@@ -269,11 +294,15 @@ mod tests {
fn fails_to_receive_message_with_incorrect_nonce() {
run_test(|| {
let mut lane = inbound_lane::<TestRuntime, _>(TEST_LANE_ID);
assert!(!lane.receive_message::<TestMessageDispatch>(
TEST_RELAYER_A,
10,
message_data(REGULAR_PAYLOAD).into()
));
assert_eq!(
lane.receive_message::<TestMessageDispatch, _>(
&TEST_RELAYER_A,
&TEST_RELAYER_A,
10,
message_data(REGULAR_PAYLOAD).into()
),
ReceivalResult::InvalidNonce
);
assert_eq!(lane.storage.data().last_delivered_nonce(), 0);
});
}
@@ -284,24 +313,36 @@ mod tests {
let mut lane = inbound_lane::<TestRuntime, _>(TEST_LANE_ID);
let max_nonce = <TestRuntime as crate::Config>::MaxUnrewardedRelayerEntriesAtInboundLane::get();
for current_nonce in 1..max_nonce + 1 {
assert!(lane.receive_message::<TestMessageDispatch>(
TEST_RELAYER_A + current_nonce,
current_nonce,
message_data(REGULAR_PAYLOAD).into()
));
assert_eq!(
lane.receive_message::<TestMessageDispatch, _>(
&(TEST_RELAYER_A + current_nonce),
&(TEST_RELAYER_A + current_nonce),
current_nonce,
message_data(REGULAR_PAYLOAD).into()
),
ReceivalResult::Dispatched(dispatch_result(0))
);
}
// Fails to dispatch new message from different than latest relayer.
assert!(!lane.receive_message::<TestMessageDispatch>(
TEST_RELAYER_A + max_nonce + 1,
max_nonce + 1,
message_data(REGULAR_PAYLOAD).into()
));
assert_eq!(
lane.receive_message::<TestMessageDispatch, _>(
&(TEST_RELAYER_A + max_nonce + 1),
&(TEST_RELAYER_A + max_nonce + 1),
max_nonce + 1,
message_data(REGULAR_PAYLOAD).into()
),
ReceivalResult::TooManyUnrewardedRelayers,
);
// Fails to dispatch new messages from latest relayer. Prevents griefing attacks.
assert!(!lane.receive_message::<TestMessageDispatch>(
TEST_RELAYER_A + max_nonce,
max_nonce + 1,
message_data(REGULAR_PAYLOAD).into()
));
assert_eq!(
lane.receive_message::<TestMessageDispatch, _>(
&(TEST_RELAYER_A + max_nonce),
&(TEST_RELAYER_A + max_nonce),
max_nonce + 1,
message_data(REGULAR_PAYLOAD).into()
),
ReceivalResult::TooManyUnrewardedRelayers,
);
});
}
@@ -311,24 +352,36 @@ mod tests {
let mut lane = inbound_lane::<TestRuntime, _>(TEST_LANE_ID);
let max_nonce = <TestRuntime as crate::Config>::MaxUnconfirmedMessagesAtInboundLane::get();
for current_nonce in 1..=max_nonce {
assert!(lane.receive_message::<TestMessageDispatch>(
TEST_RELAYER_A,
current_nonce,
message_data(REGULAR_PAYLOAD).into()
));
assert_eq!(
lane.receive_message::<TestMessageDispatch, _>(
&TEST_RELAYER_A,
&TEST_RELAYER_A,
current_nonce,
message_data(REGULAR_PAYLOAD).into()
),
ReceivalResult::Dispatched(dispatch_result(0))
);
}
// Fails to dispatch new message from different than latest relayer.
assert!(!lane.receive_message::<TestMessageDispatch>(
TEST_RELAYER_B,
max_nonce + 1,
message_data(REGULAR_PAYLOAD).into()
));
assert_eq!(
lane.receive_message::<TestMessageDispatch, _>(
&TEST_RELAYER_B,
&TEST_RELAYER_B,
max_nonce + 1,
message_data(REGULAR_PAYLOAD).into()
),
ReceivalResult::TooManyUnconfirmedMessages,
);
// Fails to dispatch new messages from latest relayer.
assert!(!lane.receive_message::<TestMessageDispatch>(
TEST_RELAYER_A,
max_nonce + 1,
message_data(REGULAR_PAYLOAD).into()
));
assert_eq!(
lane.receive_message::<TestMessageDispatch, _>(
&TEST_RELAYER_A,
&TEST_RELAYER_A,
max_nonce + 1,
message_data(REGULAR_PAYLOAD).into()
),
ReceivalResult::TooManyUnconfirmedMessages,
);
});
}
@@ -336,21 +389,33 @@ mod tests {
fn correctly_receives_following_messages_from_two_relayers_alternately() {
run_test(|| {
let mut lane = inbound_lane::<TestRuntime, _>(TEST_LANE_ID);
assert!(lane.receive_message::<TestMessageDispatch>(
TEST_RELAYER_A,
1,
message_data(REGULAR_PAYLOAD).into()
));
assert!(lane.receive_message::<TestMessageDispatch>(
TEST_RELAYER_B,
2,
message_data(REGULAR_PAYLOAD).into()
));
assert!(lane.receive_message::<TestMessageDispatch>(
TEST_RELAYER_A,
3,
message_data(REGULAR_PAYLOAD).into()
));
assert_eq!(
lane.receive_message::<TestMessageDispatch, _>(
&TEST_RELAYER_A,
&TEST_RELAYER_A,
1,
message_data(REGULAR_PAYLOAD).into()
),
ReceivalResult::Dispatched(dispatch_result(0))
);
assert_eq!(
lane.receive_message::<TestMessageDispatch, _>(
&TEST_RELAYER_B,
&TEST_RELAYER_B,
2,
message_data(REGULAR_PAYLOAD).into()
),
ReceivalResult::Dispatched(dispatch_result(0))
);
assert_eq!(
lane.receive_message::<TestMessageDispatch, _>(
&TEST_RELAYER_A,
&TEST_RELAYER_A,
3,
message_data(REGULAR_PAYLOAD).into()
),
ReceivalResult::Dispatched(dispatch_result(0))
);
assert_eq!(
lane.storage.data().relayers,
vec![(1, 1, TEST_RELAYER_A), (2, 2, TEST_RELAYER_B), (3, 3, TEST_RELAYER_A)]
@@ -362,16 +427,24 @@ mod tests {
fn rejects_same_message_from_two_different_relayers() {
run_test(|| {
let mut lane = inbound_lane::<TestRuntime, _>(TEST_LANE_ID);
assert!(lane.receive_message::<TestMessageDispatch>(
TEST_RELAYER_A,
1,
message_data(REGULAR_PAYLOAD).into()
));
assert!(!lane.receive_message::<TestMessageDispatch>(
TEST_RELAYER_B,
1,
message_data(REGULAR_PAYLOAD).into()
));
assert_eq!(
lane.receive_message::<TestMessageDispatch, _>(
&TEST_RELAYER_A,
&TEST_RELAYER_A,
1,
message_data(REGULAR_PAYLOAD).into()
),
ReceivalResult::Dispatched(dispatch_result(0))
);
assert_eq!(
lane.receive_message::<TestMessageDispatch, _>(
&TEST_RELAYER_B,
&TEST_RELAYER_B,
1,
message_data(REGULAR_PAYLOAD).into()
),
ReceivalResult::InvalidNonce,
);
});
}
@@ -383,4 +456,22 @@ mod tests {
assert_eq!(lane.storage.data().last_delivered_nonce(), 1);
});
}
#[test]
fn unspent_weight_is_returned_by_receive_message() {
run_test(|| {
let mut lane = inbound_lane::<TestRuntime, _>(TEST_LANE_ID);
let mut payload = REGULAR_PAYLOAD;
payload.dispatch_result.unspent_weight = 1;
assert_eq!(
lane.receive_message::<TestMessageDispatch, _>(
&TEST_RELAYER_A,
&TEST_RELAYER_A,
1,
message_data(payload).into()
),
ReceivalResult::Dispatched(dispatch_result(1))
);
});
}
}
+150 -31
View File
@@ -42,7 +42,7 @@ pub use crate::weights_ext::{
EXPECTED_DEFAULT_MESSAGE_LENGTH,
};
use crate::inbound_lane::{InboundLane, InboundLaneStorage};
use crate::inbound_lane::{InboundLane, InboundLaneStorage, ReceivalResult};
use crate::outbound_lane::{OutboundLane, OutboundLaneStorage};
use crate::weights::WeightInfo;
@@ -55,9 +55,11 @@ use bp_messages::{
use bp_runtime::Size;
use codec::{Decode, Encode};
use frame_support::{
decl_error, decl_event, decl_module, decl_storage, ensure,
decl_error, decl_event, decl_module, decl_storage,
dispatch::DispatchResultWithPostInfo,
ensure,
traits::Get,
weights::{DispatchClass, Weight},
weights::{DispatchClass, Pays, PostDispatchInfo, Weight},
Parameter, StorageMap,
};
use frame_system::{ensure_signed, RawOrigin};
@@ -150,7 +152,11 @@ pub trait Config<I = DefaultInstance>: frame_system::Config {
/// Source header chain, as it is represented on target chain.
type SourceHeaderChain: SourceHeaderChain<Self::InboundMessageFee>;
/// Message dispatch.
type MessageDispatch: MessageDispatch<Self::InboundMessageFee, DispatchPayload = Self::InboundPayload>;
type MessageDispatch: MessageDispatch<
Self::AccountId,
Self::InboundMessageFee,
DispatchPayload = Self::InboundPayload,
>;
}
/// Shortcut to messages proof type for Config.
@@ -438,13 +444,13 @@ decl_module! {
#[weight = T::WeightInfo::receive_messages_proof_weight(proof, *messages_count, *dispatch_weight)]
pub fn receive_messages_proof(
origin,
relayer_id: T::InboundRelayer,
relayer_id_at_bridged_chain: T::InboundRelayer,
proof: MessagesProofOf<T, I>,
messages_count: u32,
dispatch_weight: Weight,
) -> DispatchResult {
) -> DispatchResultWithPostInfo {
ensure_not_halted::<T, I>()?;
let _ = ensure_signed(origin)?;
let relayer_id_at_this_chain = ensure_signed(origin)?;
// reject transactions that are declaring too many messages
ensure!(
@@ -452,6 +458,23 @@ decl_module! {
Error::<T, I>::TooManyMessagesInTheProof
);
// why do we need to know the weight of this (`receive_messages_proof`) call? Because
// we may want to return some funds for not-dispatching (or partially dispatching) some
// messages to the call origin (relayer). And this is done by returning actual weight
// from the call. But we only know dispatch weight of every messages. So to refund relayer
// because we have not dispatched Message, we need to:
//
// ActualWeight = DeclaredWeight - Message.DispatchWeight
//
// The DeclaredWeight is exactly what's computed here. Unfortunately it is impossible
// to get pre-computed value (and it has been already computed by the executive).
let declared_weight = T::WeightInfo::receive_messages_proof_weight(
&proof,
messages_count,
dispatch_weight,
);
let mut actual_weight = declared_weight;
// verify messages proof && convert proof into messages
let messages = verify_and_decode_messages_proof::<
T::SourceHeaderChain,
@@ -511,20 +534,57 @@ decl_module! {
debug_assert_eq!(message.key.lane_id, lane_id);
total_messages += 1;
if lane.receive_message::<T::MessageDispatch>(relayer_id.clone(), message.key.nonce, message.data) {
valid_messages += 1;
}
let dispatch_weight = T::MessageDispatch::dispatch_weight(&message);
let receival_result = lane.receive_message::<T::MessageDispatch, T::AccountId>(
&relayer_id_at_bridged_chain,
&relayer_id_at_this_chain,
message.key.nonce,
message.data,
);
// note that we're returning unspent weight to relayer even if message has been
// rejected by the lane. This allows relayers to submit spam transactions with
// e.g. the same set of already delivered messages over and over again, without
// losing funds for messages dispatch. But keep in mind that relayer pays base
// delivery transaction cost anyway. And base cost covers everything except
// dispatch, so we have a balance here.
let (unspent_weight, refund_pay_dispatch_fee) = match receival_result {
ReceivalResult::Dispatched(dispatch_result) => {
valid_messages += 1;
(dispatch_result.unspent_weight, !dispatch_result.dispatch_fee_paid_during_dispatch)
},
ReceivalResult::InvalidNonce
| ReceivalResult::TooManyUnrewardedRelayers
| ReceivalResult::TooManyUnconfirmedMessages => (dispatch_weight, true),
};
actual_weight = actual_weight
.saturating_sub(sp_std::cmp::min(unspent_weight, dispatch_weight))
.saturating_sub(
// delivery call weight formula assumes that the fee is paid at
// this (target) chain. If the message is prepaid at the source
// chain, let's refund relayer with this extra cost.
if refund_pay_dispatch_fee {
T::WeightInfo::pay_inbound_dispatch_fee_overhead()
} else {
0
}
);
}
}
log::trace!(
target: "runtime::bridge-messages",
"Received messages: total={}, valid={}",
"Received messages: total={}, valid={}. Weight used: {}/{}",
total_messages,
valid_messages,
actual_weight,
declared_weight,
);
Ok(())
Ok(PostDispatchInfo {
actual_weight: Some(actual_weight),
pays_fee: Pays::Yes,
})
}
/// Receive messages delivery proof from bridged chain.
@@ -860,10 +920,9 @@ fn verify_and_decode_messages_proof<Chain: SourceHeaderChain<Fee>, Fee, Dispatch
mod tests {
use super::*;
use crate::mock::{
message, run_test, Event as TestEvent, Origin, TestMessageDeliveryAndDispatchPayment,
TestMessagesDeliveryProof, TestMessagesParameter, TestMessagesProof, TestPayload, TestRuntime,
TokenConversionRate, PAYLOAD_REJECTED_BY_TARGET_CHAIN, REGULAR_PAYLOAD, TEST_LANE_ID, TEST_RELAYER_A,
TEST_RELAYER_B,
message, message_payload, run_test, Event as TestEvent, Origin, TestMessageDeliveryAndDispatchPayment,
TestMessagesDeliveryProof, TestMessagesParameter, TestMessagesProof, TestRuntime, TokenConversionRate,
PAYLOAD_REJECTED_BY_TARGET_CHAIN, REGULAR_PAYLOAD, TEST_LANE_ID, TEST_RELAYER_A, TEST_RELAYER_B,
};
use bp_messages::UnrewardedRelayersState;
use frame_support::{assert_noop, assert_ok};
@@ -883,7 +942,7 @@ mod tests {
Origin::signed(1),
TEST_LANE_ID,
REGULAR_PAYLOAD,
REGULAR_PAYLOAD.1,
REGULAR_PAYLOAD.declared_weight,
));
// check event with assigned nonce
@@ -897,7 +956,10 @@ mod tests {
);
// check that fee has been withdrawn from submitter
assert!(TestMessageDeliveryAndDispatchPayment::is_fee_paid(1, REGULAR_PAYLOAD.1));
assert!(TestMessageDeliveryAndDispatchPayment::is_fee_paid(
1,
REGULAR_PAYLOAD.declared_weight
));
}
fn receive_messages_delivery_proof() {
@@ -1113,7 +1175,7 @@ mod tests {
Origin::signed(1),
TEST_LANE_ID,
REGULAR_PAYLOAD,
REGULAR_PAYLOAD.1,
REGULAR_PAYLOAD.declared_weight,
),
Error::<TestRuntime, DefaultInstance>::Halted,
);
@@ -1129,7 +1191,7 @@ mod tests {
TEST_RELAYER_A,
Ok(vec![message(2, REGULAR_PAYLOAD)]).into(),
1,
REGULAR_PAYLOAD.1,
REGULAR_PAYLOAD.declared_weight,
),
Error::<TestRuntime, DefaultInstance>::Halted,
);
@@ -1164,7 +1226,7 @@ mod tests {
Origin::signed(1),
TEST_LANE_ID,
REGULAR_PAYLOAD,
REGULAR_PAYLOAD.1,
REGULAR_PAYLOAD.declared_weight,
),
Error::<TestRuntime, DefaultInstance>::Halted,
);
@@ -1181,7 +1243,7 @@ mod tests {
TEST_RELAYER_A,
Ok(vec![message(1, REGULAR_PAYLOAD)]).into(),
1,
REGULAR_PAYLOAD.1,
REGULAR_PAYLOAD.declared_weight,
),);
assert_ok!(Pallet::<TestRuntime>::receive_messages_delivery_proof(
@@ -1214,7 +1276,7 @@ mod tests {
Origin::signed(1),
TEST_LANE_ID,
PAYLOAD_REJECTED_BY_TARGET_CHAIN,
PAYLOAD_REJECTED_BY_TARGET_CHAIN.1
PAYLOAD_REJECTED_BY_TARGET_CHAIN.declared_weight
),
Error::<TestRuntime, DefaultInstance>::MessageRejectedByChainVerifier,
);
@@ -1241,7 +1303,7 @@ mod tests {
Origin::signed(1),
TEST_LANE_ID,
REGULAR_PAYLOAD,
REGULAR_PAYLOAD.1
REGULAR_PAYLOAD.declared_weight
),
Error::<TestRuntime, DefaultInstance>::FailedToWithdrawMessageFee,
);
@@ -1256,7 +1318,7 @@ mod tests {
TEST_RELAYER_A,
Ok(vec![message(1, REGULAR_PAYLOAD)]).into(),
1,
REGULAR_PAYLOAD.1,
REGULAR_PAYLOAD.declared_weight,
));
assert_eq!(InboundLanes::<TestRuntime>::get(TEST_LANE_ID).last_delivered_nonce(), 1);
@@ -1297,7 +1359,7 @@ mod tests {
TEST_RELAYER_A,
message_proof,
1,
REGULAR_PAYLOAD.1,
REGULAR_PAYLOAD.declared_weight,
));
assert_eq!(
@@ -1329,7 +1391,7 @@ mod tests {
TEST_RELAYER_A,
Ok(vec![message(1, REGULAR_PAYLOAD)]).into(),
1,
REGULAR_PAYLOAD.1 - 1,
REGULAR_PAYLOAD.declared_weight - 1,
),
Error::<TestRuntime, DefaultInstance>::InvalidMessagesDispatchWeight,
);
@@ -1551,7 +1613,7 @@ mod tests {
])
.into(),
3,
REGULAR_PAYLOAD.1 + REGULAR_PAYLOAD.1,
REGULAR_PAYLOAD.declared_weight + REGULAR_PAYLOAD.declared_weight,
),);
assert_eq!(
@@ -1603,9 +1665,9 @@ mod tests {
#[test]
fn actual_dispatch_weight_does_not_overlow() {
run_test(|| {
let message1 = message(1, TestPayload(0, Weight::MAX / 2));
let message2 = message(2, TestPayload(0, Weight::MAX / 2));
let message3 = message(2, TestPayload(0, Weight::MAX / 2));
let message1 = message(1, message_payload(0, Weight::MAX / 2));
let message2 = message(2, message_payload(0, Weight::MAX / 2));
let message3 = message(2, message_payload(0, Weight::MAX / 2));
assert_noop!(
Pallet::<TestRuntime, DefaultInstance>::receive_messages_proof(
@@ -1672,4 +1734,61 @@ mod tests {
assert!(TestMessageDeliveryAndDispatchPayment::is_fee_paid(1, 100));
});
}
#[test]
fn weight_refund_from_receive_messages_proof_works() {
run_test(|| {
fn submit_with_unspent_weight(
nonce: MessageNonce,
unspent_weight: Weight,
is_prepaid: bool,
) -> (Weight, Weight) {
let mut payload = REGULAR_PAYLOAD;
payload.dispatch_result.unspent_weight = unspent_weight;
payload.dispatch_result.dispatch_fee_paid_during_dispatch = !is_prepaid;
let proof = Ok(vec![message(nonce, payload)]).into();
let messages_count = 1;
let pre_dispatch_weight = <TestRuntime as Config>::WeightInfo::receive_messages_proof_weight(
&proof,
messages_count,
REGULAR_PAYLOAD.declared_weight,
);
let post_dispatch_weight = Pallet::<TestRuntime>::receive_messages_proof(
Origin::signed(1),
TEST_RELAYER_A,
proof,
messages_count,
REGULAR_PAYLOAD.declared_weight,
)
.expect("delivery has failed")
.actual_weight
.expect("receive_messages_proof always returns Some");
(pre_dispatch_weight, post_dispatch_weight)
}
// when dispatch is returning `unspent_weight < declared_weight`
let (pre, post) = submit_with_unspent_weight(1, 1, false);
assert_eq!(post, pre - 1);
// when dispatch is returning `unspent_weight = declared_weight`
let (pre, post) = submit_with_unspent_weight(2, REGULAR_PAYLOAD.declared_weight, false);
assert_eq!(post, pre - REGULAR_PAYLOAD.declared_weight);
// when dispatch is returning `unspent_weight > declared_weight`
let (pre, post) = submit_with_unspent_weight(3, REGULAR_PAYLOAD.declared_weight + 1, false);
assert_eq!(post, pre - REGULAR_PAYLOAD.declared_weight);
// when there's no unspent weight
let (pre, post) = submit_with_unspent_weight(4, 0, false);
assert_eq!(post, pre);
// when dispatch is returning `unspent_weight < declared_weight` AND message is prepaid
let (pre, post) = submit_with_unspent_weight(5, 1, true);
assert_eq!(
post,
pre - 1 - <TestRuntime as Config>::WeightInfo::pay_inbound_dispatch_fee_overhead()
);
});
}
}
+42 -7
View File
@@ -27,7 +27,7 @@ use bp_messages::{
InboundLaneData, LaneId, Message, MessageData, MessageKey, MessageNonce, OutboundLaneData,
Parameter as MessagesParameter,
};
use bp_runtime::Size;
use bp_runtime::{messages::MessageDispatchResult, Size};
use codec::{Decode, Encode};
use frame_support::{parameter_types, weights::Weight};
use sp_core::H256;
@@ -41,7 +41,17 @@ use std::collections::BTreeMap;
pub type AccountId = u64;
pub type Balance = u64;
#[derive(Decode, Encode, Clone, Debug, PartialEq, Eq)]
pub struct TestPayload(pub u64, pub Weight);
pub struct TestPayload {
/// Field that may be used to identify messages.
pub id: u64,
/// Dispatch weight that is declared by the message sender.
pub declared_weight: Weight,
/// Message dispatch result.
///
/// Note: in correct code `dispatch_result.unspent_weight` will always be <= `declared_weight`, but for test
/// purposes we'll be making it larger than `declared_weight` sometimes.
pub dispatch_result: MessageDispatchResult,
}
pub type TestMessageFee = u64;
pub type TestRelayer = u64;
@@ -189,10 +199,10 @@ pub const TEST_ERROR: &str = "Test error";
pub const TEST_LANE_ID: LaneId = [0, 0, 0, 1];
/// Regular message payload.
pub const REGULAR_PAYLOAD: TestPayload = TestPayload(0, 50);
pub const REGULAR_PAYLOAD: TestPayload = message_payload(0, 50);
/// Payload that is rejected by `TestTargetHeaderChain`.
pub const PAYLOAD_REJECTED_BY_TARGET_CHAIN: TestPayload = TestPayload(1, 50);
pub const PAYLOAD_REJECTED_BY_TARGET_CHAIN: TestPayload = message_payload(1, 50);
/// Vec of proved messages, grouped by lane.
pub type MessagesByLaneVec = Vec<(LaneId, ProvedLaneMessages<Message<TestMessageFee>>)>;
@@ -359,17 +369,25 @@ impl SourceHeaderChain<TestMessageFee> for TestSourceHeaderChain {
#[derive(Debug)]
pub struct TestMessageDispatch;
impl MessageDispatch<TestMessageFee> for TestMessageDispatch {
impl MessageDispatch<AccountId, TestMessageFee> for TestMessageDispatch {
type DispatchPayload = TestPayload;
fn dispatch_weight(message: &DispatchMessage<TestPayload, TestMessageFee>) -> Weight {
match message.data.payload.as_ref() {
Ok(payload) => payload.1,
Ok(payload) => payload.declared_weight,
Err(_) => 0,
}
}
fn dispatch(_message: DispatchMessage<TestPayload, TestMessageFee>) {}
fn dispatch(
_relayer_account: &AccountId,
message: DispatchMessage<TestPayload, TestMessageFee>,
) -> MessageDispatchResult {
match message.data.payload.as_ref() {
Ok(payload) => payload.dispatch_result.clone(),
Err(_) => dispatch_result(0),
}
}
}
/// Return test lane message with given nonce and payload.
@@ -383,6 +401,15 @@ pub fn message(nonce: MessageNonce, payload: TestPayload) -> Message<TestMessage
}
}
/// Constructs message payload using given arguments and zero unspent weight.
pub const fn message_payload(id: u64, declared_weight: Weight) -> TestPayload {
TestPayload {
id,
declared_weight,
dispatch_result: dispatch_result(0),
}
}
/// Return message data with valid fee for given payload.
pub fn message_data(payload: TestPayload) -> MessageData<TestMessageFee> {
MessageData {
@@ -391,6 +418,14 @@ pub fn message_data(payload: TestPayload) -> MessageData<TestMessageFee> {
}
}
/// Returns message dispatch result with given unspent weight.
pub const fn dispatch_result(unspent_weight: Weight) -> MessageDispatchResult {
MessageDispatchResult {
unspent_weight,
dispatch_fee_paid_during_dispatch: true,
}
}
/// Run pallet test.
pub fn run_test<T>(test: impl FnOnce() -> T) -> T {
let mut t = frame_system::GenesisConfig::default()
+92 -81
View File
@@ -17,7 +17,7 @@
//! Autogenerated weights for pallet_bridge_messages
//!
//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 3.0.0
//! DATE: 2021-06-03, STEPS: [50, ], REPEAT: 20
//! DATE: 2021-06-15, STEPS: [50, ], REPEAT: 20
//! LOW RANGE: [], HIGH RANGE: []
//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled
//! CHAIN: Some("dev"), DB CACHE: 128
@@ -57,6 +57,7 @@ pub trait WeightInfo {
fn receive_single_message_proof_with_outbound_lane_state() -> Weight;
fn receive_single_message_proof_1_kb() -> Weight;
fn receive_single_message_proof_16_kb() -> Weight;
fn receive_single_prepaid_message_proof() -> Weight;
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;
@@ -73,105 +74,110 @@ pub trait WeightInfo {
pub struct RialtoWeight<T>(PhantomData<T>);
impl<T: frame_system::Config> WeightInfo for RialtoWeight<T> {
fn send_minimal_message_worst_case() -> Weight {
(140_457_000 as Weight)
(154_371_000 as Weight)
.saturating_add(T::DbWeight::get().reads(5 as Weight))
.saturating_add(T::DbWeight::get().writes(12 as Weight))
}
fn send_1_kb_message_worst_case() -> Weight {
(138_097_000 as Weight)
(157_479_000 as Weight)
.saturating_add(T::DbWeight::get().reads(5 as Weight))
.saturating_add(T::DbWeight::get().writes(12 as Weight))
}
fn send_16_kb_message_worst_case() -> Weight {
(196_192_000 as Weight)
(186_840_000 as Weight)
.saturating_add(T::DbWeight::get().reads(5 as Weight))
.saturating_add(T::DbWeight::get().writes(12 as Weight))
}
fn increase_message_fee() -> Weight {
(6_244_063_000 as Weight)
.saturating_add(T::DbWeight::get().reads(4 as Weight))
(4_377_567_000 as Weight)
.saturating_add(T::DbWeight::get().reads(5 as Weight))
.saturating_add(T::DbWeight::get().writes(3 as Weight))
}
fn receive_single_message_proof() -> Weight {
(135_633_000 as Weight)
.saturating_add(T::DbWeight::get().reads(3 as Weight))
.saturating_add(T::DbWeight::get().writes(1 as Weight))
(205_350_000 as Weight)
.saturating_add(T::DbWeight::get().reads(5 as Weight))
.saturating_add(T::DbWeight::get().writes(3 as Weight))
}
fn receive_two_messages_proof() -> Weight {
(229_415_000 as Weight)
.saturating_add(T::DbWeight::get().reads(3 as Weight))
.saturating_add(T::DbWeight::get().writes(1 as Weight))
(337_102_000 as Weight)
.saturating_add(T::DbWeight::get().reads(5 as Weight))
.saturating_add(T::DbWeight::get().writes(3 as Weight))
}
fn receive_single_message_proof_with_outbound_lane_state() -> Weight {
(147_408_000 as Weight)
.saturating_add(T::DbWeight::get().reads(3 as Weight))
.saturating_add(T::DbWeight::get().writes(1 as Weight))
(218_825_000 as Weight)
.saturating_add(T::DbWeight::get().reads(5 as Weight))
.saturating_add(T::DbWeight::get().writes(3 as Weight))
}
fn receive_single_message_proof_1_kb() -> Weight {
(160_092_000 as Weight)
.saturating_add(T::DbWeight::get().reads(3 as Weight))
.saturating_add(T::DbWeight::get().writes(1 as Weight))
(230_759_000 as Weight)
.saturating_add(T::DbWeight::get().reads(5 as Weight))
.saturating_add(T::DbWeight::get().writes(3 as Weight))
}
fn receive_single_message_proof_16_kb() -> Weight {
(452_140_000 as Weight)
(490_522_000 as Weight)
.saturating_add(T::DbWeight::get().reads(5 as Weight))
.saturating_add(T::DbWeight::get().writes(3 as Weight))
}
fn receive_single_prepaid_message_proof() -> Weight {
(136_550_000 as Weight)
.saturating_add(T::DbWeight::get().reads(3 as Weight))
.saturating_add(T::DbWeight::get().writes(1 as Weight))
}
fn receive_delivery_proof_for_single_message() -> Weight {
(123_704_000 as Weight)
(131_397_000 as Weight)
.saturating_add(T::DbWeight::get().reads(6 as Weight))
.saturating_add(T::DbWeight::get().writes(3 as Weight))
}
fn receive_delivery_proof_for_two_messages_by_single_relayer() -> Weight {
(127_844_000 as Weight)
(137_946_000 as Weight)
.saturating_add(T::DbWeight::get().reads(7 as Weight))
.saturating_add(T::DbWeight::get().writes(3 as Weight))
}
fn receive_delivery_proof_for_two_messages_by_two_relayers() -> Weight {
(183_119_000 as Weight)
(194_448_000 as Weight)
.saturating_add(T::DbWeight::get().reads(8 as Weight))
.saturating_add(T::DbWeight::get().writes(4 as Weight))
}
fn send_messages_of_various_lengths(i: u32) -> Weight {
(162_249_000 as Weight)
.saturating_add((3_000 as Weight).saturating_mul(i as Weight))
(142_576_000 as Weight)
.saturating_add((2_000 as Weight).saturating_mul(i as Weight))
.saturating_add(T::DbWeight::get().reads(5 as Weight))
.saturating_add(T::DbWeight::get().writes(12 as Weight))
}
fn receive_multiple_messages_proof(i: u32) -> Weight {
(0 as Weight)
.saturating_add((107_235_000 as Weight).saturating_mul(i as Weight))
.saturating_add(T::DbWeight::get().reads(3 as Weight))
.saturating_add(T::DbWeight::get().writes(1 as Weight))
.saturating_add((138_341_000 as Weight).saturating_mul(i as Weight))
.saturating_add(T::DbWeight::get().reads(5 as Weight))
.saturating_add(T::DbWeight::get().writes(3 as Weight))
}
fn receive_message_proofs_with_extra_nodes(i: u32) -> Weight {
(450_232_000 as Weight)
(472_752_000 as Weight)
.saturating_add((9_000 as Weight).saturating_mul(i as Weight))
.saturating_add(T::DbWeight::get().reads(3 as Weight))
.saturating_add(T::DbWeight::get().writes(1 as Weight))
.saturating_add(T::DbWeight::get().reads(5 as Weight))
.saturating_add(T::DbWeight::get().writes(3 as Weight))
}
fn receive_message_proofs_with_large_leaf(i: u32) -> Weight {
(181_851_000 as Weight)
.saturating_add((7_000 as Weight).saturating_mul(i as Weight))
.saturating_add(T::DbWeight::get().reads(3 as Weight))
.saturating_add(T::DbWeight::get().writes(1 as Weight))
(175_300_000 as Weight)
.saturating_add((6_000 as Weight).saturating_mul(i as Weight))
.saturating_add(T::DbWeight::get().reads(5 as Weight))
.saturating_add(T::DbWeight::get().writes(3 as Weight))
}
fn receive_multiple_messages_proof_with_outbound_lane_state(i: u32) -> Weight {
(0 as Weight)
.saturating_add((114_622_000 as Weight).saturating_mul(i as Weight))
.saturating_add(T::DbWeight::get().reads(3 as Weight))
.saturating_add(T::DbWeight::get().writes(1 as Weight))
.saturating_add((142_176_000 as Weight).saturating_mul(i as Weight))
.saturating_add(T::DbWeight::get().reads(5 as Weight))
.saturating_add(T::DbWeight::get().writes(3 as Weight))
}
fn receive_delivery_proof_for_multiple_messages_by_single_relayer(i: u32) -> Weight {
(103_133_000 as Weight)
.saturating_add((6_676_000 as Weight).saturating_mul(i as Weight))
(127_372_000 as Weight)
.saturating_add((7_927_000 as Weight).saturating_mul(i as Weight))
.saturating_add(T::DbWeight::get().reads(5 as Weight))
.saturating_add(T::DbWeight::get().reads((1 as Weight).saturating_mul(i as Weight)))
.saturating_add(T::DbWeight::get().writes(3 as Weight))
}
fn receive_delivery_proof_for_multiple_messages_by_multiple_relayers(i: u32) -> Weight {
(100_321_000 as Weight)
.saturating_add((59_736_000 as Weight).saturating_mul(i as Weight))
(99_781_000 as Weight)
.saturating_add((64_001_000 as Weight).saturating_mul(i as Weight))
.saturating_add(T::DbWeight::get().reads(5 as Weight))
.saturating_add(T::DbWeight::get().reads((2 as Weight).saturating_mul(i as Weight)))
.saturating_add(T::DbWeight::get().writes(3 as Weight))
@@ -182,105 +188,110 @@ impl<T: frame_system::Config> WeightInfo for RialtoWeight<T> {
// For backwards compatibility and tests
impl WeightInfo for () {
fn send_minimal_message_worst_case() -> Weight {
(140_457_000 as Weight)
(154_371_000 as Weight)
.saturating_add(RocksDbWeight::get().reads(5 as Weight))
.saturating_add(RocksDbWeight::get().writes(12 as Weight))
}
fn send_1_kb_message_worst_case() -> Weight {
(138_097_000 as Weight)
(157_479_000 as Weight)
.saturating_add(RocksDbWeight::get().reads(5 as Weight))
.saturating_add(RocksDbWeight::get().writes(12 as Weight))
}
fn send_16_kb_message_worst_case() -> Weight {
(196_192_000 as Weight)
(186_840_000 as Weight)
.saturating_add(RocksDbWeight::get().reads(5 as Weight))
.saturating_add(RocksDbWeight::get().writes(12 as Weight))
}
fn increase_message_fee() -> Weight {
(6_244_063_000 as Weight)
.saturating_add(RocksDbWeight::get().reads(4 as Weight))
(4_377_567_000 as Weight)
.saturating_add(RocksDbWeight::get().reads(5 as Weight))
.saturating_add(RocksDbWeight::get().writes(3 as Weight))
}
fn receive_single_message_proof() -> Weight {
(135_633_000 as Weight)
.saturating_add(RocksDbWeight::get().reads(3 as Weight))
.saturating_add(RocksDbWeight::get().writes(1 as Weight))
(205_350_000 as Weight)
.saturating_add(RocksDbWeight::get().reads(5 as Weight))
.saturating_add(RocksDbWeight::get().writes(3 as Weight))
}
fn receive_two_messages_proof() -> Weight {
(229_415_000 as Weight)
.saturating_add(RocksDbWeight::get().reads(3 as Weight))
.saturating_add(RocksDbWeight::get().writes(1 as Weight))
(337_102_000 as Weight)
.saturating_add(RocksDbWeight::get().reads(5 as Weight))
.saturating_add(RocksDbWeight::get().writes(3 as Weight))
}
fn receive_single_message_proof_with_outbound_lane_state() -> Weight {
(147_408_000 as Weight)
.saturating_add(RocksDbWeight::get().reads(3 as Weight))
.saturating_add(RocksDbWeight::get().writes(1 as Weight))
(218_825_000 as Weight)
.saturating_add(RocksDbWeight::get().reads(5 as Weight))
.saturating_add(RocksDbWeight::get().writes(3 as Weight))
}
fn receive_single_message_proof_1_kb() -> Weight {
(160_092_000 as Weight)
.saturating_add(RocksDbWeight::get().reads(3 as Weight))
.saturating_add(RocksDbWeight::get().writes(1 as Weight))
(230_759_000 as Weight)
.saturating_add(RocksDbWeight::get().reads(5 as Weight))
.saturating_add(RocksDbWeight::get().writes(3 as Weight))
}
fn receive_single_message_proof_16_kb() -> Weight {
(452_140_000 as Weight)
(490_522_000 as Weight)
.saturating_add(RocksDbWeight::get().reads(5 as Weight))
.saturating_add(RocksDbWeight::get().writes(3 as Weight))
}
fn receive_single_prepaid_message_proof() -> Weight {
(136_550_000 as Weight)
.saturating_add(RocksDbWeight::get().reads(3 as Weight))
.saturating_add(RocksDbWeight::get().writes(1 as Weight))
}
fn receive_delivery_proof_for_single_message() -> Weight {
(123_704_000 as Weight)
(131_397_000 as Weight)
.saturating_add(RocksDbWeight::get().reads(6 as Weight))
.saturating_add(RocksDbWeight::get().writes(3 as Weight))
}
fn receive_delivery_proof_for_two_messages_by_single_relayer() -> Weight {
(127_844_000 as Weight)
(137_946_000 as Weight)
.saturating_add(RocksDbWeight::get().reads(7 as Weight))
.saturating_add(RocksDbWeight::get().writes(3 as Weight))
}
fn receive_delivery_proof_for_two_messages_by_two_relayers() -> Weight {
(183_119_000 as Weight)
(194_448_000 as Weight)
.saturating_add(RocksDbWeight::get().reads(8 as Weight))
.saturating_add(RocksDbWeight::get().writes(4 as Weight))
}
fn send_messages_of_various_lengths(i: u32) -> Weight {
(162_249_000 as Weight)
.saturating_add((3_000 as Weight).saturating_mul(i as Weight))
(142_576_000 as Weight)
.saturating_add((2_000 as Weight).saturating_mul(i as Weight))
.saturating_add(RocksDbWeight::get().reads(5 as Weight))
.saturating_add(RocksDbWeight::get().writes(12 as Weight))
}
fn receive_multiple_messages_proof(i: u32) -> Weight {
(0 as Weight)
.saturating_add((107_235_000 as Weight).saturating_mul(i as Weight))
.saturating_add(RocksDbWeight::get().reads(3 as Weight))
.saturating_add(RocksDbWeight::get().writes(1 as Weight))
.saturating_add((138_341_000 as Weight).saturating_mul(i as Weight))
.saturating_add(RocksDbWeight::get().reads(5 as Weight))
.saturating_add(RocksDbWeight::get().writes(3 as Weight))
}
fn receive_message_proofs_with_extra_nodes(i: u32) -> Weight {
(450_232_000 as Weight)
(472_752_000 as Weight)
.saturating_add((9_000 as Weight).saturating_mul(i as Weight))
.saturating_add(RocksDbWeight::get().reads(3 as Weight))
.saturating_add(RocksDbWeight::get().writes(1 as Weight))
.saturating_add(RocksDbWeight::get().reads(5 as Weight))
.saturating_add(RocksDbWeight::get().writes(3 as Weight))
}
fn receive_message_proofs_with_large_leaf(i: u32) -> Weight {
(181_851_000 as Weight)
.saturating_add((7_000 as Weight).saturating_mul(i as Weight))
.saturating_add(RocksDbWeight::get().reads(3 as Weight))
.saturating_add(RocksDbWeight::get().writes(1 as Weight))
(175_300_000 as Weight)
.saturating_add((6_000 as Weight).saturating_mul(i as Weight))
.saturating_add(RocksDbWeight::get().reads(5 as Weight))
.saturating_add(RocksDbWeight::get().writes(3 as Weight))
}
fn receive_multiple_messages_proof_with_outbound_lane_state(i: u32) -> Weight {
(0 as Weight)
.saturating_add((114_622_000 as Weight).saturating_mul(i as Weight))
.saturating_add(RocksDbWeight::get().reads(3 as Weight))
.saturating_add(RocksDbWeight::get().writes(1 as Weight))
.saturating_add((142_176_000 as Weight).saturating_mul(i as Weight))
.saturating_add(RocksDbWeight::get().reads(5 as Weight))
.saturating_add(RocksDbWeight::get().writes(3 as Weight))
}
fn receive_delivery_proof_for_multiple_messages_by_single_relayer(i: u32) -> Weight {
(103_133_000 as Weight)
.saturating_add((6_676_000 as Weight).saturating_mul(i as Weight))
(127_372_000 as Weight)
.saturating_add((7_927_000 as Weight).saturating_mul(i as Weight))
.saturating_add(RocksDbWeight::get().reads(5 as Weight))
.saturating_add(RocksDbWeight::get().reads((1 as Weight).saturating_mul(i as Weight)))
.saturating_add(RocksDbWeight::get().writes(3 as Weight))
}
fn receive_delivery_proof_for_multiple_messages_by_multiple_relayers(i: u32) -> Weight {
(100_321_000 as Weight)
.saturating_add((59_736_000 as Weight).saturating_mul(i as Weight))
(99_781_000 as Weight)
.saturating_add((64_001_000 as Weight).saturating_mul(i as Weight))
.saturating_add(RocksDbWeight::get().reads(5 as Weight))
.saturating_add(RocksDbWeight::get().reads((2 as Weight).saturating_mul(i as Weight)))
.saturating_add(RocksDbWeight::get().writes(3 as Weight))
@@ -34,6 +34,7 @@ pub fn ensure_weights_are_correct<W: WeightInfoExt>(
expected_default_message_delivery_tx_weight: Weight,
expected_additional_byte_delivery_weight: Weight,
expected_messages_delivery_confirmation_tx_weight: Weight,
expected_pay_inbound_dispatch_fee_weight: Weight,
) {
// verify `send_message` weight components
assert_ne!(W::send_message_overhead(), 0);
@@ -88,6 +89,15 @@ pub fn ensure_weights_are_correct<W: WeightInfoExt>(
actual_messages_delivery_confirmation_tx_weight,
expected_messages_delivery_confirmation_tx_weight,
);
// verify pay-dispatch-fee overhead for inbound messages
let actual_pay_inbound_dispatch_fee_weight = W::pay_inbound_dispatch_fee_overhead();
assert!(
actual_pay_inbound_dispatch_fee_weight <= expected_pay_inbound_dispatch_fee_weight,
"Weight {} of pay-dispatch-fee overhead for inbound messages is larger than expected weight {}",
actual_pay_inbound_dispatch_fee_weight,
expected_pay_inbound_dispatch_fee_weight,
);
}
/// Ensure that we're able to receive maximal (by-size and by-weight) message from other chain.
@@ -304,6 +314,13 @@ pub trait WeightInfoExt: WeightInfo {
(Self::receive_single_message_proof_16_kb() - Self::receive_single_message_proof_1_kb()) / (15 * 1024);
proof_size_in_bytes * byte_weight
}
/// Returns weight of the pay-dispatch-fee operation for inbound messages.
///
/// This function may return zero if runtime doesn't support pay-dispatch-fee-at-target-chain option.
fn pay_inbound_dispatch_fee_overhead() -> Weight {
Self::receive_single_message_proof().saturating_sub(Self::receive_single_prepaid_message_proof())
}
}
impl WeightInfoExt for () {