Remove message fee + message send calls (#1642)

* remove message fee

* it is compiling!

* fixes + fmt

* more cleanup

* more cleanup

* restore MessageDeliveryAndDispatchPayment since we'll need relayer rewards

* started rational relayer removal

* more removal

* removed estimate fee subcommand

* remove DispatchFeePayment

* more removals

* removed conversion rates && some metrics

* - unneeded associated type

* - OutboundMessageFee

* fix benchmarks compilation

* fmt

* test + fix benchmarks

* fix send message

* clippy
This commit is contained in:
Svyatoslav Nikolsky
2022-11-18 12:24:45 +03:00
committed by Bastian Köcher
parent 1217b2cf80
commit 8c845602cf
92 changed files with 589 additions and 5796 deletions
+8 -216
View File
@@ -18,35 +18,25 @@
use crate::{
inbound_lane::InboundLaneStorage, inbound_lane_storage, outbound_lane,
outbound_lane::ReceivalConfirmationResult, weights_ext::EXPECTED_DEFAULT_MESSAGE_LENGTH, Call,
OutboundLanes, OutboundMessages,
weights_ext::EXPECTED_DEFAULT_MESSAGE_LENGTH, Call, OutboundLanes,
};
use bp_messages::{
source_chain::TargetHeaderChain, target_chain::SourceHeaderChain, DeliveredMessages,
InboundLaneData, LaneId, MessageData, MessageKey, MessageNonce, OutboundLaneData,
UnrewardedRelayer, UnrewardedRelayersState,
InboundLaneData, LaneId, MessageNonce, OutboundLaneData, UnrewardedRelayer,
UnrewardedRelayersState,
};
use bp_runtime::{messages::DispatchFeePayment, StorageProofSize};
use bp_runtime::StorageProofSize;
use frame_benchmarking::{account, benchmarks_instance_pallet};
use frame_support::{traits::Get, weights::Weight};
use frame_support::weights::Weight;
use frame_system::RawOrigin;
use sp_std::{collections::vec_deque::VecDeque, convert::TryInto, ops::RangeInclusive, prelude::*};
use sp_std::{ops::RangeInclusive, prelude::*};
const SEED: u32 = 0;
/// Pallet we're benchmarking here.
pub struct Pallet<T: Config<I>, I: 'static>(crate::Pallet<T, I>);
/// Benchmark-specific message parameters.
#[derive(Debug)]
pub struct MessageParams<ThisAccountId> {
/// Size of the message payload.
pub size: u32,
/// Message sender account.
pub sender_account: ThisAccountId,
}
/// Benchmark-specific message proof parameters.
#[derive(Debug)]
pub struct MessageProofParams {
@@ -58,8 +48,6 @@ pub struct MessageProofParams {
pub outbound_lane_data: Option<OutboundLaneData>,
/// Proof size requirements.
pub size: StorageProofSize,
/// Where the fee for dispatching message is paid?
pub dispatch_fee_payment: DispatchFeePayment,
}
/// Benchmark-specific message delivery proof parameters.
@@ -79,29 +67,14 @@ pub trait Config<I: 'static>: crate::Config<I> {
fn bench_lane_id() -> LaneId {
Default::default()
}
/// Get maximal size of the message payload.
fn maximal_message_size() -> u32;
/// Return id of relayer account at the bridged chain.
fn bridged_relayer_id() -> Self::InboundRelayer;
/// Return balance of given account.
fn account_balance(account: &Self::AccountId) -> Self::OutboundMessageFee;
/// Create given account and give it enough balance for test purposes.
fn endow_account(account: &Self::AccountId);
/// Fee paid by submitter for single message delivery.
fn message_fee() -> Self::OutboundMessageFee {
100_000_000_000_000.into()
}
/// Prepare message to send over lane.
fn prepare_outbound_message(
params: MessageParams<Self::AccountId>,
) -> (Self::OutboundPayload, Self::OutboundMessageFee);
/// Prepare messages proof to receive by the module.
fn prepare_message_proof(
params: MessageProofParams,
) -> (
<Self::SourceHeaderChain as SourceHeaderChain<Self::InboundMessageFee>>::MessagesProof,
Weight,
);
) -> (<Self::SourceHeaderChain as SourceHeaderChain>::MessagesProof, Weight);
/// Prepare messages delivery proof to receive by the module.
fn prepare_message_delivery_proof(
params: MessageDeliveryProofParams<Self::AccountId>,
@@ -115,156 +88,6 @@ benchmarks_instance_pallet! {
// Benchmarks that are used directly by the runtime.
//
// Benchmark `send_message` extrinsic with the worst possible conditions:
// * outbound lane already has state, so it needs to be read and decoded;
// * relayers fund account does not exists (in practice it needs to exist in production environment);
// * maximal number of messages is being pruned during the call;
// * message size is minimal for the target chain.
//
// Result of this benchmark is used as a base weight for `send_message` call. Then the 'message weight'
// (estimated using `send_half_maximal_message_worst_case` and `send_maximal_message_worst_case`) is
// added.
send_minimal_message_worst_case {
let lane_id = T::bench_lane_id();
let sender = account("sender", 0, SEED);
T::endow_account(&sender);
// 'send' messages that are to be pruned when our message is sent
for _nonce in 1..=T::MaxMessagesToPruneAtOnce::get() {
send_regular_message::<T, I>();
}
confirm_message_delivery::<T, I>(T::MaxMessagesToPruneAtOnce::get());
let (payload, fee) = T::prepare_outbound_message(MessageParams {
size: 0,
sender_account: sender.clone(),
});
}: send_message(RawOrigin::Signed(sender), lane_id, payload, fee)
verify {
assert_eq!(
crate::OutboundLanes::<T, I>::get(&T::bench_lane_id()).latest_generated_nonce,
T::MaxMessagesToPruneAtOnce::get() + 1,
);
}
// Benchmark `send_message` extrinsic with the worst possible conditions:
// * outbound lane already has state, so it needs to be read and decoded;
// * relayers fund account does not exists (in practice it needs to exist in production environment);
// * maximal number of messages is being pruned during the call;
// * message size is 1KB.
//
// With single KB of message size, the weight of the call is increased (roughly) by
// `(send_16_kb_message_worst_case - send_1_kb_message_worst_case) / 15`.
send_1_kb_message_worst_case {
let lane_id = T::bench_lane_id();
let sender = account("sender", 0, SEED);
T::endow_account(&sender);
// 'send' messages that are to be pruned when our message is sent
for _nonce in 1..=T::MaxMessagesToPruneAtOnce::get() {
send_regular_message::<T, I>();
}
confirm_message_delivery::<T, I>(T::MaxMessagesToPruneAtOnce::get());
let size = 1024;
assert!(
T::maximal_message_size() > size,
"This benchmark can only be used with runtime that accepts 1KB messages",
);
let (payload, fee) = T::prepare_outbound_message(MessageParams {
size,
sender_account: sender.clone(),
});
}: send_message(RawOrigin::Signed(sender), lane_id, payload, fee)
verify {
assert_eq!(
crate::OutboundLanes::<T, I>::get(&T::bench_lane_id()).latest_generated_nonce,
T::MaxMessagesToPruneAtOnce::get() + 1,
);
}
// Benchmark `send_message` extrinsic with the worst possible conditions:
// * outbound lane already has state, so it needs to be read and decoded;
// * relayers fund account does not exists (in practice it needs to exist in production environment);
// * maximal number of messages is being pruned during the call;
// * message size is 16KB.
//
// With single KB of message size, the weight of the call is increased (roughly) by
// `(send_16_kb_message_worst_case - send_1_kb_message_worst_case) / 15`.
send_16_kb_message_worst_case {
let lane_id = T::bench_lane_id();
let sender = account("sender", 0, SEED);
T::endow_account(&sender);
// 'send' messages that are to be pruned when our message is sent
for _nonce in 1..=T::MaxMessagesToPruneAtOnce::get() {
send_regular_message::<T, I>();
}
confirm_message_delivery::<T, I>(T::MaxMessagesToPruneAtOnce::get());
let size = 16 * 1024;
assert!(
T::maximal_message_size() > size,
"This benchmark can only be used with runtime that accepts 16KB messages",
);
let (payload, fee) = T::prepare_outbound_message(MessageParams {
size,
sender_account: sender.clone(),
});
}: send_message(RawOrigin::Signed(sender), lane_id, payload, fee)
verify {
assert_eq!(
crate::OutboundLanes::<T, I>::get(&T::bench_lane_id()).latest_generated_nonce,
T::MaxMessagesToPruneAtOnce::get() + 1,
);
}
// Benchmark `increase_message_fee` with following conditions:
// * message has maximal message;
// * submitter account is killed because its balance is less than ED after payment.
//
// Result of this benchmark is directly used by weight formula of the call.
maximal_increase_message_fee {
let sender = account("sender", 42, SEED);
T::endow_account(&sender);
let additional_fee = T::account_balance(&sender);
let lane_id = T::bench_lane_id();
let nonce = 1;
send_regular_message_with_payload::<T, I>(vec![42u8; T::maximal_message_size() as _]);
}: increase_message_fee(RawOrigin::Signed(sender.clone()), lane_id, nonce, additional_fee)
verify {
assert_eq!(
OutboundMessages::<T, I>::get(MessageKey { lane_id, nonce }).unwrap().fee,
T::message_fee() + additional_fee,
);
}
// Benchmark `increase_message_fee` with following conditions:
// * message size varies from minimal to maximal;
// * submitter account is killed because its balance is less than ED after payment.
increase_message_fee {
let i in 0..T::maximal_message_size().try_into().unwrap_or_default();
let sender = account("sender", 42, SEED);
T::endow_account(&sender);
let additional_fee = T::account_balance(&sender);
let lane_id = T::bench_lane_id();
let nonce = 1;
send_regular_message_with_payload::<T, I>(vec![42u8; i as _]);
}: increase_message_fee(RawOrigin::Signed(sender.clone()), lane_id, nonce, additional_fee)
verify {
assert_eq!(
OutboundMessages::<T, I>::get(MessageKey { lane_id, nonce }).unwrap().fee,
T::message_fee() + additional_fee,
);
}
// 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;
@@ -286,7 +109,6 @@ benchmarks_instance_pallet! {
message_nonces: 21..=21,
outbound_lane_data: None,
size: StorageProofSize::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 {
@@ -321,7 +143,6 @@ benchmarks_instance_pallet! {
message_nonces: 21..=22,
outbound_lane_data: None,
size: StorageProofSize::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 {
@@ -360,7 +181,6 @@ benchmarks_instance_pallet! {
latest_generated_nonce: 21,
}),
size: StorageProofSize::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 {
@@ -392,7 +212,6 @@ benchmarks_instance_pallet! {
message_nonces: 21..=21,
outbound_lane_data: None,
size: StorageProofSize::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 {
@@ -427,7 +246,6 @@ benchmarks_instance_pallet! {
message_nonces: 21..=21,
outbound_lane_data: None,
size: StorageProofSize::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 {
@@ -461,7 +279,6 @@ benchmarks_instance_pallet! {
message_nonces: 21..=21,
outbound_lane_data: None,
size: StorageProofSize::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 {
@@ -479,7 +296,6 @@ benchmarks_instance_pallet! {
// This is base benchmark for all other confirmations delivery benchmarks.
receive_delivery_proof_for_single_message {
let relayer_id: T::AccountId = account("relayer", 0, SEED);
let relayer_balance = T::account_balance(&relayer_id);
// send message that we're going to confirm
send_regular_message::<T, I>();
@@ -515,7 +331,6 @@ benchmarks_instance_pallet! {
// - weight(receive_delivery_proof_for_single_message)`.
receive_delivery_proof_for_two_messages_by_single_relayer {
let relayer_id: T::AccountId = account("relayer", 0, SEED);
let relayer_balance = T::account_balance(&relayer_id);
// send message that we're going to confirm
send_regular_message::<T, I>();
@@ -554,9 +369,7 @@ benchmarks_instance_pallet! {
// - weight(receive_delivery_proof_for_two_messages_by_single_relayer)`.
receive_delivery_proof_for_two_messages_by_two_relayers {
let relayer1_id: T::AccountId = account("relayer1", 1, SEED);
let relayer1_balance = T::account_balance(&relayer1_id);
let relayer2_id: T::AccountId = account("relayer2", 2, SEED);
let relayer2_balance = T::account_balance(&relayer2_id);
// send message that we're going to confirm
send_regular_message::<T, I>();
@@ -593,28 +406,7 @@ benchmarks_instance_pallet! {
fn send_regular_message<T: Config<I>, I: 'static>() {
let mut outbound_lane = outbound_lane::<T, I>(T::bench_lane_id());
outbound_lane.send_message(MessageData { payload: vec![], fee: T::message_fee() });
}
fn send_regular_message_with_payload<T: Config<I>, I: 'static>(payload: Vec<u8>) {
let mut outbound_lane = outbound_lane::<T, I>(T::bench_lane_id());
outbound_lane.send_message(MessageData { payload, fee: T::message_fee() });
}
fn confirm_message_delivery<T: Config<I>, I: 'static>(nonce: MessageNonce) {
let mut outbound_lane = outbound_lane::<T, I>(T::bench_lane_id());
let latest_received_nonce = outbound_lane.data().latest_received_nonce;
let mut relayers = VecDeque::with_capacity((nonce - latest_received_nonce) as usize);
for nonce in latest_received_nonce + 1..=nonce {
relayers.push_back(UnrewardedRelayer {
relayer: (),
messages: DeliveredMessages::new(nonce, true),
});
}
assert!(matches!(
outbound_lane.confirm_delivery(nonce - latest_received_nonce, nonce, &relayers),
ReceivalConfirmationResult::ConfirmedMessages(_),
));
outbound_lane.send_message(vec![]);
}
fn receive_messages<T: Config<I>, I: 'static>(nonce: MessageNonce) {
+19 -21
View File
@@ -31,8 +31,6 @@ use sp_std::prelude::PartialEq;
/// Inbound lane storage.
pub trait InboundLaneStorage {
/// Delivery and dispatch fee type on source chain.
type MessageFee;
/// Id of relayer on source chain.
type Relayer: Clone + PartialEq;
@@ -183,12 +181,12 @@ impl<S: InboundLaneStorage> InboundLane<S> {
}
/// Receive new message.
pub fn receive_message<P: MessageDispatch<AccountId, S::MessageFee>, AccountId>(
pub fn receive_message<P: MessageDispatch<AccountId>, AccountId>(
&mut self,
relayer_at_bridged_chain: &S::Relayer,
relayer_at_this_chain: &AccountId,
nonce: MessageNonce,
message_data: DispatchMessageData<P::DispatchPayload, S::MessageFee>,
message_data: DispatchMessageData<P::DispatchPayload>,
) -> ReceivalResult {
let mut data = self.storage.data();
let is_correct_message = nonce == data.last_delivered_nonce() + 1;
@@ -242,9 +240,9 @@ mod tests {
use crate::{
inbound_lane,
mock::{
dispatch_result, message_data, run_test, unrewarded_relayer, TestMessageDispatch,
TestRuntime, REGULAR_PAYLOAD, TEST_LANE_ID, TEST_RELAYER_A, TEST_RELAYER_B,
TEST_RELAYER_C,
dispatch_result, inbound_message_data, run_test, unrewarded_relayer,
TestMessageDispatch, TestRuntime, REGULAR_PAYLOAD, TEST_LANE_ID, TEST_RELAYER_A,
TEST_RELAYER_B, TEST_RELAYER_C,
},
RuntimeInboundLaneStorage,
};
@@ -258,7 +256,7 @@ mod tests {
&TEST_RELAYER_A,
&TEST_RELAYER_A,
nonce,
message_data(REGULAR_PAYLOAD).into()
inbound_message_data(REGULAR_PAYLOAD)
),
ReceivalResult::Dispatched(dispatch_result(0))
);
@@ -386,7 +384,7 @@ mod tests {
&TEST_RELAYER_A,
&TEST_RELAYER_A,
10,
message_data(REGULAR_PAYLOAD).into()
inbound_message_data(REGULAR_PAYLOAD)
),
ReceivalResult::InvalidNonce
);
@@ -406,7 +404,7 @@ mod tests {
&(TEST_RELAYER_A + current_nonce),
&(TEST_RELAYER_A + current_nonce),
current_nonce,
message_data(REGULAR_PAYLOAD).into()
inbound_message_data(REGULAR_PAYLOAD)
),
ReceivalResult::Dispatched(dispatch_result(0))
);
@@ -417,7 +415,7 @@ mod tests {
&(TEST_RELAYER_A + max_nonce + 1),
&(TEST_RELAYER_A + max_nonce + 1),
max_nonce + 1,
message_data(REGULAR_PAYLOAD).into()
inbound_message_data(REGULAR_PAYLOAD)
),
ReceivalResult::TooManyUnrewardedRelayers,
);
@@ -427,7 +425,7 @@ mod tests {
&(TEST_RELAYER_A + max_nonce),
&(TEST_RELAYER_A + max_nonce),
max_nonce + 1,
message_data(REGULAR_PAYLOAD).into()
inbound_message_data(REGULAR_PAYLOAD)
),
ReceivalResult::TooManyUnrewardedRelayers,
);
@@ -445,7 +443,7 @@ mod tests {
&TEST_RELAYER_A,
&TEST_RELAYER_A,
current_nonce,
message_data(REGULAR_PAYLOAD).into()
inbound_message_data(REGULAR_PAYLOAD)
),
ReceivalResult::Dispatched(dispatch_result(0))
);
@@ -456,7 +454,7 @@ mod tests {
&TEST_RELAYER_B,
&TEST_RELAYER_B,
max_nonce + 1,
message_data(REGULAR_PAYLOAD).into()
inbound_message_data(REGULAR_PAYLOAD)
),
ReceivalResult::TooManyUnconfirmedMessages,
);
@@ -466,7 +464,7 @@ mod tests {
&TEST_RELAYER_A,
&TEST_RELAYER_A,
max_nonce + 1,
message_data(REGULAR_PAYLOAD).into()
inbound_message_data(REGULAR_PAYLOAD)
),
ReceivalResult::TooManyUnconfirmedMessages,
);
@@ -482,7 +480,7 @@ mod tests {
&TEST_RELAYER_A,
&TEST_RELAYER_A,
1,
message_data(REGULAR_PAYLOAD).into()
inbound_message_data(REGULAR_PAYLOAD)
),
ReceivalResult::Dispatched(dispatch_result(0))
);
@@ -491,7 +489,7 @@ mod tests {
&TEST_RELAYER_B,
&TEST_RELAYER_B,
2,
message_data(REGULAR_PAYLOAD).into()
inbound_message_data(REGULAR_PAYLOAD)
),
ReceivalResult::Dispatched(dispatch_result(0))
);
@@ -500,7 +498,7 @@ mod tests {
&TEST_RELAYER_A,
&TEST_RELAYER_A,
3,
message_data(REGULAR_PAYLOAD).into()
inbound_message_data(REGULAR_PAYLOAD)
),
ReceivalResult::Dispatched(dispatch_result(0))
);
@@ -524,7 +522,7 @@ mod tests {
&TEST_RELAYER_A,
&TEST_RELAYER_A,
1,
message_data(REGULAR_PAYLOAD).into()
inbound_message_data(REGULAR_PAYLOAD)
),
ReceivalResult::Dispatched(dispatch_result(0))
);
@@ -533,7 +531,7 @@ mod tests {
&TEST_RELAYER_B,
&TEST_RELAYER_B,
1,
message_data(REGULAR_PAYLOAD).into()
inbound_message_data(REGULAR_PAYLOAD)
),
ReceivalResult::InvalidNonce,
);
@@ -560,7 +558,7 @@ mod tests {
&TEST_RELAYER_A,
&TEST_RELAYER_A,
1,
message_data(payload).into()
inbound_message_data(payload)
),
ReceivalResult::Dispatched(dispatch_result(1))
);
+78 -573
View File
@@ -38,7 +38,7 @@
#![allow(clippy::unused_unit)]
pub use inbound_lane::StoredInboundLaneData;
pub use outbound_lane::StoredMessageData;
pub use outbound_lane::StoredMessagePayload;
pub use weights::WeightInfo;
pub use weights_ext::{
ensure_able_to_receive_confirmation, ensure_able_to_receive_message,
@@ -59,17 +59,16 @@ use bp_messages::{
DispatchMessage, MessageDispatch, ProvedLaneMessages, ProvedMessages, SourceHeaderChain,
},
total_unrewarded_messages, DeliveredMessages, InboundLaneData, InboundMessageDetails, LaneId,
MessageData, MessageKey, MessageNonce, MessagePayload, MessagesOperatingMode, OutboundLaneData,
OutboundMessageDetails, Parameter as MessagesParameter, UnrewardedRelayer,
UnrewardedRelayersState,
MessageKey, MessageNonce, MessagePayload, MessagesOperatingMode, OutboundLaneData,
OutboundMessageDetails, UnrewardedRelayer, UnrewardedRelayersState,
};
use bp_runtime::{BasicOperatingMode, ChainId, OwnedBridgeModule, Size};
use codec::{Decode, Encode, MaxEncodedLen};
use frame_support::{dispatch::PostDispatchInfo, ensure, fail, traits::Get};
use num_traits::{SaturatingAdd, Zero};
use num_traits::Zero;
use sp_std::{
cell::RefCell, cmp::PartialOrd, collections::vec_deque::VecDeque, marker::PhantomData,
ops::RangeInclusive, prelude::*,
cell::RefCell, collections::vec_deque::VecDeque, marker::PhantomData, ops::RangeInclusive,
prelude::*,
};
mod inbound_lane;
@@ -108,11 +107,6 @@ pub mod pallet {
/// Gets the chain id value from the instance.
#[pallet::constant]
type BridgedChainId: Get<ChainId>;
/// Pallet parameter that is opaque to the pallet itself, but may be used by the runtime
/// for integrating the pallet.
///
/// All pallet parameters may only be updated either by the root, or by the pallet owner.
type Parameter: MessagesParameter;
/// Maximal number of messages that may be pruned during maintenance. Maintenance occurs
/// whenever new message is sent. The reason is that if you want to use lane, you should
@@ -142,25 +136,14 @@ pub mod pallet {
/// these messages are from different lanes.
type MaxUnconfirmedMessagesAtInboundLane: Get<MessageNonce>;
/// Maximal size of the outbound payload.
/// Maximal encoded size of the outbound payload.
#[pallet::constant]
type MaximalOutboundPayloadSize: Get<u32>;
/// Payload type of outbound messages. This payload is dispatched on the bridged chain.
type OutboundPayload: Parameter + Size;
/// Message fee type of outbound messages. This fee is paid on this chain.
type OutboundMessageFee: Default
+ From<u64>
+ PartialOrd
+ Parameter
+ SaturatingAdd
+ Zero
+ Copy
+ MaxEncodedLen;
/// Payload type of inbound messages. This payload is dispatched on this chain.
type InboundPayload: Decode;
/// Message fee type of inbound messages. This fee is paid on the bridged chain.
type InboundMessageFee: Decode + Zero;
/// Identifier of relayer that deliver messages to this chain. Relayer reward is paid on the
/// bridged chain.
type InboundRelayer: Parameter + MaxEncodedLen;
@@ -170,16 +153,11 @@ pub mod pallet {
/// Target header chain.
type TargetHeaderChain: TargetHeaderChain<Self::OutboundPayload, Self::AccountId>;
/// Message payload verifier.
type LaneMessageVerifier: LaneMessageVerifier<
Self::RuntimeOrigin,
Self::OutboundPayload,
Self::OutboundMessageFee,
>;
type LaneMessageVerifier: LaneMessageVerifier<Self::RuntimeOrigin, Self::OutboundPayload>;
/// Message delivery payment.
type MessageDeliveryAndDispatchPayment: MessageDeliveryAndDispatchPayment<
Self::RuntimeOrigin,
Self::AccountId,
Self::OutboundMessageFee,
>;
/// Handler for accepted messages.
type OnMessageAccepted: OnMessageAccepted;
@@ -189,19 +167,17 @@ pub mod pallet {
// Types that are used by inbound_lane (on target chain).
/// Source header chain, as it is represented on target chain.
type SourceHeaderChain: SourceHeaderChain<Self::InboundMessageFee>;
type SourceHeaderChain: SourceHeaderChain;
/// Message dispatch.
type MessageDispatch: MessageDispatch<
Self::AccountId,
Self::InboundMessageFee,
DispatchPayload = Self::InboundPayload,
>;
}
/// Shortcut to messages proof type for Config.
type MessagesProofOf<T, I> = <<T as Config<I>>::SourceHeaderChain as SourceHeaderChain<
<T as Config<I>>::InboundMessageFee,
>>::MessagesProof;
type MessagesProofOf<T, I> =
<<T as Config<I>>::SourceHeaderChain as SourceHeaderChain>::MessagesProof;
/// Shortcut to messages delivery proof type for Config.
type MessagesDeliveryProofOf<T, I> =
<<T as Config<I>>::TargetHeaderChain as TargetHeaderChain<
@@ -241,101 +217,6 @@ pub mod pallet {
<Self as OwnedBridgeModule<_>>::set_operating_mode(origin, operating_mode)
}
/// Update pallet parameter.
///
/// May only be called either by root, or by `PalletOwner`.
///
/// The weight is: single read for permissions check + 2 writes for parameter value and
/// event.
#[pallet::weight((T::DbWeight::get().reads_writes(1, 2), DispatchClass::Operational))]
pub fn update_pallet_parameter(
origin: OriginFor<T>,
parameter: T::Parameter,
) -> DispatchResult {
Self::ensure_owner_or_root(origin)?;
parameter.save();
Self::deposit_event(Event::ParameterUpdated { parameter });
Ok(())
}
/// Send message over lane.
#[pallet::weight(T::WeightInfo::send_message_weight(payload, T::DbWeight::get()))]
pub fn send_message(
origin: OriginFor<T>,
lane_id: LaneId,
payload: T::OutboundPayload,
delivery_and_dispatch_fee: T::OutboundMessageFee,
) -> DispatchResultWithPostInfo {
crate::send_message::<T, I>(origin, lane_id, payload, delivery_and_dispatch_fee).map(
|sent_message| PostDispatchInfo {
actual_weight: Some(sent_message.weight),
pays_fee: Pays::Yes,
},
)
}
/// Pay additional fee for the message.
#[pallet::weight(T::WeightInfo::maximal_increase_message_fee())]
pub fn increase_message_fee(
origin: OriginFor<T>,
lane_id: LaneId,
nonce: MessageNonce,
additional_fee: T::OutboundMessageFee,
) -> DispatchResultWithPostInfo {
Self::ensure_not_halted().map_err(Error::<T, I>::BridgeModule)?;
// if someone tries to pay for already-delivered message, we're rejecting this intention
// (otherwise this additional fee will be locked forever in relayers fund)
//
// if someone tries to pay for not-yet-sent message, we're rejecting this intention, or
// we're risking to have mess in the storage
let lane = outbound_lane::<T, I>(lane_id);
ensure!(
nonce > lane.data().latest_received_nonce,
Error::<T, I>::MessageIsAlreadyDelivered
);
ensure!(
nonce <= lane.data().latest_generated_nonce,
Error::<T, I>::MessageIsNotYetSent
);
// withdraw additional fee from submitter
T::MessageDeliveryAndDispatchPayment::pay_delivery_and_dispatch_fee(
&origin,
&additional_fee,
)
.map_err(|err| {
log::trace!(
target: LOG_TARGET,
"Submitter can't pay additional fee {:?} for the message {:?}/{:?}: {:?}",
additional_fee,
lane_id,
nonce,
err,
);
Error::<T, I>::FailedToWithdrawMessageFee
})?;
// and finally update fee in the storage
let message_key = MessageKey { lane_id, nonce };
let message_size = OutboundMessages::<T, I>::mutate(message_key, |message_data| {
// saturating_add is fine here - overflow here means that someone controls all
// chain funds, which shouldn't ever happen + `pay_delivery_and_dispatch_fee`
// above will fail before we reach here
let message_data = message_data.as_mut().expect(
"the message is sent and not yet delivered; so it is in the storage; qed",
);
message_data.fee = message_data.fee.saturating_add(&additional_fee);
message_data.payload.len()
});
// compute actual dispatch weight that depends on the stored message size
let actual_weight = T::WeightInfo::maximal_increase_message_fee()
.min(T::WeightInfo::increase_message_fee(message_size as _));
Ok(PostDispatchInfo { actual_weight: Some(actual_weight), pays_fee: Pays::Yes })
}
/// Receive messages proof from bridged chain.
///
/// The weight of the call assumes that the transaction always brings outbound lane
@@ -378,7 +259,6 @@ pub mod pallet {
// verify messages proof && convert proof into messages
let messages = verify_and_decode_messages_proof::<
T::SourceHeaderChain,
T::InboundMessageFee,
T::InboundPayload,
>(proof, messages_count)
.map_err(|err| {
@@ -636,8 +516,6 @@ pub mod pallet {
#[pallet::event]
#[pallet::generate_deposit(pub(super) fn deposit_event)]
pub enum Event<T: Config<I>, I: 'static = ()> {
/// Pallet parameter has been updated.
ParameterUpdated { parameter: T::Parameter },
/// Message has been accepted and is waiting to be delivered.
MessageAccepted { lane_id: LaneId, nonce: MessageNonce },
/// Messages in the inclusive range have been delivered to the bridged chain.
@@ -709,7 +587,7 @@ pub mod pallet {
/// All queued outbound messages.
#[pallet::storage]
pub type OutboundMessages<T: Config<I>, I: 'static = ()> =
StorageMap<_, Blake2_128Concat, MessageKey, StoredMessageData<T, I>>;
StorageMap<_, Blake2_128Concat, MessageKey, StoredMessagePayload<T, I>>;
#[pallet::genesis_config]
pub struct GenesisConfig<T: Config<I>, I: 'static = ()> {
@@ -744,10 +622,7 @@ pub mod pallet {
impl<T: Config<I>, I: 'static> Pallet<T, I> {
/// Get stored data of the outbound message with given nonce.
pub fn outbound_message_data(
lane: LaneId,
nonce: MessageNonce,
) -> Option<MessageData<T::OutboundMessageFee>> {
pub fn outbound_message_data(lane: LaneId, nonce: MessageNonce) -> Option<MessagePayload> {
OutboundMessages::<T, I>::get(MessageKey { lane_id: lane, nonce }).map(Into::into)
}
@@ -755,12 +630,11 @@ pub mod pallet {
pub fn inbound_message_data(
lane: LaneId,
payload: MessagePayload,
outbound_details: OutboundMessageDetails<T::InboundMessageFee>,
outbound_details: OutboundMessageDetails,
) -> InboundMessageDetails {
let mut dispatch_message = DispatchMessage {
key: MessageKey { lane_id: lane, nonce: outbound_details.nonce },
data: MessageData { payload, fee: outbound_details.delivery_and_dispatch_fee }
.into(),
data: payload.into(),
};
InboundMessageDetails {
dispatch_weight: T::MessageDispatch::dispatch_weight(&mut dispatch_message),
@@ -769,12 +643,8 @@ pub mod pallet {
}
}
impl<T, I>
bp_messages::source_chain::MessagesBridge<
T::RuntimeOrigin,
T::OutboundMessageFee,
T::OutboundPayload,
> for Pallet<T, I>
impl<T, I> bp_messages::source_chain::MessagesBridge<T::RuntimeOrigin, T::OutboundPayload>
for Pallet<T, I>
where
T: Config<I>,
I: 'static,
@@ -785,9 +655,8 @@ where
sender: T::RuntimeOrigin,
lane: LaneId,
message: T::OutboundPayload,
delivery_and_dispatch_fee: T::OutboundMessageFee,
) -> Result<SendMessageArtifacts, Self::Error> {
crate::send_message::<T, I>(sender, lane, message, delivery_and_dispatch_fee)
crate::send_message::<T, I>(sender, lane, message)
}
}
@@ -796,21 +665,14 @@ fn send_message<T: Config<I>, I: 'static>(
submitter: T::RuntimeOrigin,
lane_id: LaneId,
payload: T::OutboundPayload,
delivery_and_dispatch_fee: T::OutboundMessageFee,
) -> sp_std::result::Result<
SendMessageArtifacts,
sp_runtime::DispatchErrorWithPostInfo<PostDispatchInfo>,
> {
ensure_normal_operating_mode::<T, I>()?;
// the most lightweigh check is the message size check
ensure!(
payload.size() <= T::MaximalOutboundPayloadSize::get(),
Error::<T, I>::MessageIsTooLarge,
);
// initially, actual (post-dispatch) weight is equal to pre-dispatch weight
let mut actual_weight = T::WeightInfo::send_message_weight(&payload, T::DbWeight::get());
let mut actual_weight = frame_support::weights::Weight::zero(); // TODO (https://github.com/paritytech/parity-bridges-common/issues/1647): remove this
// let's first check if message can be delivered to target chain
T::TargetHeaderChain::verify_message(&payload).map_err(|err| {
@@ -826,46 +688,28 @@ fn send_message<T: Config<I>, I: 'static>(
// now let's enforce any additional lane rules
let mut lane = outbound_lane::<T, I>(lane_id);
T::LaneMessageVerifier::verify_message(
&submitter,
&delivery_and_dispatch_fee,
&lane_id,
&lane.data(),
&payload,
)
.map_err(|err| {
log::trace!(
target: LOG_TARGET,
"Message to lane {:?} is rejected by lane verifier: {:?}",
lane_id,
err,
);
T::LaneMessageVerifier::verify_message(&submitter, &lane_id, &lane.data(), &payload).map_err(
|err| {
log::trace!(
target: LOG_TARGET,
"Message to lane {:?} is rejected by lane verifier: {:?}",
lane_id,
err,
);
Error::<T, I>::MessageRejectedByLaneVerifier
})?;
// let's withdraw delivery and dispatch fee from submitter
T::MessageDeliveryAndDispatchPayment::pay_delivery_and_dispatch_fee(
&submitter,
&delivery_and_dispatch_fee,
)
.map_err(|err| {
log::trace!(
target: LOG_TARGET,
"Message to lane {:?} is rejected because submitter is unable to pay fee {:?}: {:?}",
lane_id,
delivery_and_dispatch_fee,
err,
);
Error::<T, I>::FailedToWithdrawMessageFee
})?;
Error::<T, I>::MessageRejectedByLaneVerifier
},
)?;
// finally, save message in outbound storage and emit event
let encoded_payload = payload.encode();
let encoded_payload_len = encoded_payload.len();
let nonce =
lane.send_message(MessageData { payload: encoded_payload, fee: delivery_and_dispatch_fee });
ensure!(
encoded_payload_len <= T::MaximalOutboundPayloadSize::get() as usize,
Error::<T, I>::MessageIsTooLarge
);
let nonce = lane.send_message(encoded_payload);
// Guaranteed to be called outside only when the message is accepted.
// We assume that the maximum weight call back used is `single_message_callback_overhead`, so do
// not perform complex db operation in callback. If you want to, put these magic logic in
@@ -920,32 +764,26 @@ fn send_message<T: Config<I>, I: 'static>(
Ok(SendMessageArtifacts { nonce, weight: actual_weight })
}
/// Calculate the relayers rewards
/// Calculate the number of messages that the relayers have delivered.
pub fn calc_relayers_rewards<T, I>(
lane_id: LaneId,
messages_relayers: VecDeque<UnrewardedRelayer<T::AccountId>>,
received_range: &RangeInclusive<MessageNonce>,
) -> RelayersRewards<T::AccountId, T::OutboundMessageFee>
) -> RelayersRewards<T::AccountId>
where
T: frame_system::Config + crate::Config<I>,
I: 'static,
{
// remember to reward relayers that have delivered messages
// this loop is bounded by `T::MaxUnrewardedRelayerEntriesAtInboundLane` on the bridged chain
let mut relayers_rewards: RelayersRewards<_, T::OutboundMessageFee> = RelayersRewards::new();
let mut relayers_rewards = RelayersRewards::new();
for entry in messages_relayers {
let nonce_begin = sp_std::cmp::max(entry.messages.begin, *received_range.start());
let nonce_end = sp_std::cmp::min(entry.messages.end, *received_range.end());
// loop won't proceed if current entry is ahead of received range (begin > end).
// this loop is bound by `T::MaxUnconfirmedMessagesAtInboundLane` on the bridged chain
let mut relayer_reward = relayers_rewards.entry(entry.relayer).or_default();
for nonce in nonce_begin..=nonce_end {
let key = MessageKey { lane_id, nonce };
let message_data = OutboundMessages::<T, I>::get(key)
.expect("message was just confirmed; we never prune unconfirmed messages; qed");
relayer_reward.reward = relayer_reward.reward.saturating_add(&message_data.fee);
relayer_reward.messages += 1;
if nonce_end >= nonce_begin {
*relayers_rewards.entry(entry.relayer).or_default() += nonce_end - nonce_begin + 1;
}
}
relayers_rewards
@@ -995,7 +833,6 @@ struct RuntimeInboundLaneStorage<T: Config<I>, I: 'static = ()> {
}
impl<T: Config<I>, I: 'static> InboundLaneStorage for RuntimeInboundLaneStorage<T, I> {
type MessageFee = T::InboundMessageFee;
type Relayer = T::InboundRelayer;
fn id(&self) -> LaneId {
@@ -1041,8 +878,6 @@ struct RuntimeOutboundLaneStorage<T, I = ()> {
}
impl<T: Config<I>, I: 'static> OutboundLaneStorage for RuntimeOutboundLaneStorage<T, I> {
type MessageFee = T::OutboundMessageFee;
fn id(&self) -> LaneId {
self.lane_id
}
@@ -1056,17 +891,20 @@ impl<T: Config<I>, I: 'static> OutboundLaneStorage for RuntimeOutboundLaneStorag
}
#[cfg(test)]
fn message(&self, nonce: &MessageNonce) -> Option<MessageData<T::OutboundMessageFee>> {
fn message(&self, nonce: &MessageNonce) -> Option<MessagePayload> {
OutboundMessages::<T, I>::get(MessageKey { lane_id: self.lane_id, nonce: *nonce })
.map(Into::into)
}
fn save_message(
&mut self,
nonce: MessageNonce,
mesage_data: MessageData<T::OutboundMessageFee>,
) {
OutboundMessages::<T, I>::insert(MessageKey { lane_id: self.lane_id, nonce }, mesage_data);
fn save_message(&mut self, nonce: MessageNonce, message_payload: MessagePayload) {
OutboundMessages::<T, I>::insert(
MessageKey { lane_id: self.lane_id, nonce },
StoredMessagePayload::<T, I>::try_from(message_payload).expect(
"save_message is called after all checks in send_message; \
send_message checks message size; \
qed",
),
);
}
fn remove_message(&mut self, nonce: &MessageNonce) {
@@ -1075,10 +913,10 @@ impl<T: Config<I>, I: 'static> OutboundLaneStorage for RuntimeOutboundLaneStorag
}
/// Verify messages proof and return proved messages with decoded payload.
fn verify_and_decode_messages_proof<Chain: SourceHeaderChain<Fee>, Fee, DispatchPayload: Decode>(
fn verify_and_decode_messages_proof<Chain: SourceHeaderChain, DispatchPayload: Decode>(
proof: Chain::MessagesProof,
messages_count: u32,
) -> Result<ProvedMessages<DispatchMessage<DispatchPayload, Fee>>, Chain::Error> {
) -> Result<ProvedMessages<DispatchMessage<DispatchPayload>>, Chain::Error> {
// `receive_messages_proof` weight formula and `MaxUnconfirmedMessagesAtInboundLane` check
// guarantees that the `message_count` is sane and Vec<Message> may be allocated.
// (tx with too many messages will either be rejected from the pool, or will fail earlier)
@@ -1102,12 +940,12 @@ fn verify_and_decode_messages_proof<Chain: SourceHeaderChain<Fee>, Fee, Dispatch
mod tests {
use super::*;
use crate::mock::{
message, message_payload, run_test, unrewarded_relayer, Balance, RuntimeEvent as TestEvent,
message, message_payload, run_test, unrewarded_relayer, RuntimeEvent as TestEvent,
RuntimeOrigin, TestMessageDeliveryAndDispatchPayment, TestMessagesDeliveryProof,
TestMessagesParameter, TestMessagesProof, TestOnDeliveryConfirmed1,
TestOnDeliveryConfirmed2, TestOnMessageAccepted, TestRuntime, TokenConversionRate,
MAX_OUTBOUND_PAYLOAD_SIZE, PAYLOAD_REJECTED_BY_TARGET_CHAIN, REGULAR_PAYLOAD, TEST_LANE_ID,
TEST_RELAYER_A, TEST_RELAYER_B,
TestMessagesProof, TestOnDeliveryConfirmed1, TestOnDeliveryConfirmed2,
TestOnMessageAccepted, TestRuntime, MAX_OUTBOUND_PAYLOAD_SIZE,
PAYLOAD_REJECTED_BY_TARGET_CHAIN, REGULAR_PAYLOAD, TEST_LANE_ID, TEST_RELAYER_A,
TEST_RELAYER_B,
};
use bp_messages::{UnrewardedRelayer, UnrewardedRelayersState};
use bp_test_utils::generate_owned_bridge_module_tests;
@@ -1146,15 +984,13 @@ mod tests {
let message_nonce =
outbound_lane::<TestRuntime, ()>(TEST_LANE_ID).data().latest_generated_nonce + 1;
let weight = Pallet::<TestRuntime>::send_message(
let weight = send_message::<TestRuntime, ()>(
RuntimeOrigin::signed(1),
TEST_LANE_ID,
REGULAR_PAYLOAD,
REGULAR_PAYLOAD.declared_weight.ref_time(),
)
.expect("send_message has failed")
.actual_weight
.expect("send_message always returns Some");
.weight;
// check event with assigned nonce
assert_eq!(
@@ -1169,12 +1005,6 @@ mod tests {
}],
);
// check that fee has been withdrawn from submitter
assert!(TestMessageDeliveryAndDispatchPayment::is_fee_paid(
1,
REGULAR_PAYLOAD.declared_weight.ref_time()
));
weight
}
@@ -1217,102 +1047,6 @@ mod tests {
);
}
#[test]
fn pallet_parameter_may_be_updated_by_root() {
run_test(|| {
get_ready_for_events();
let parameter = TestMessagesParameter::TokenConversionRate(10.into());
assert_ok!(Pallet::<TestRuntime>::update_pallet_parameter(
RuntimeOrigin::root(),
parameter.clone(),
));
assert_eq!(TokenConversionRate::get(), 10.into());
assert_eq!(
System::<TestRuntime>::events(),
vec![EventRecord {
phase: Phase::Initialization,
event: TestEvent::Messages(Event::ParameterUpdated { parameter }),
topics: vec![],
}],
);
});
}
#[test]
fn pallet_parameter_may_be_updated_by_owner() {
run_test(|| {
PalletOwner::<TestRuntime>::put(2);
get_ready_for_events();
let parameter = TestMessagesParameter::TokenConversionRate(10.into());
assert_ok!(Pallet::<TestRuntime>::update_pallet_parameter(
RuntimeOrigin::signed(2),
parameter.clone(),
));
assert_eq!(TokenConversionRate::get(), 10.into());
assert_eq!(
System::<TestRuntime>::events(),
vec![EventRecord {
phase: Phase::Initialization,
event: TestEvent::Messages(Event::ParameterUpdated { parameter }),
topics: vec![],
}],
);
});
}
#[test]
fn pallet_parameter_cant_be_updated_by_arbitrary_submitter() {
run_test(|| {
assert_noop!(
Pallet::<TestRuntime>::update_pallet_parameter(
RuntimeOrigin::signed(2),
TestMessagesParameter::TokenConversionRate(10.into()),
),
DispatchError::BadOrigin,
);
PalletOwner::<TestRuntime>::put(2);
assert_noop!(
Pallet::<TestRuntime>::update_pallet_parameter(
RuntimeOrigin::signed(1),
TestMessagesParameter::TokenConversionRate(10.into()),
),
DispatchError::BadOrigin,
);
});
}
#[test]
fn fixed_u128_works_as_i_think() {
// this test is here just to be sure that conversion rate may be represented with FixedU128
run_test(|| {
use sp_runtime::{FixedPointNumber, FixedU128};
// 1:1 conversion that we use by default for testnets
let rialto_token = 1u64;
let rialto_token_in_millau_tokens =
TokenConversionRate::get().saturating_mul_int(rialto_token);
assert_eq!(rialto_token_in_millau_tokens, 1);
// let's say conversion rate is 1:1.7
let conversion_rate = FixedU128::saturating_from_rational(170, 100);
let rialto_tokens = 100u64;
let rialto_tokens_in_millau_tokens = conversion_rate.saturating_mul_int(rialto_tokens);
assert_eq!(rialto_tokens_in_millau_tokens, 170);
// let's say conversion rate is 1:0.25
let conversion_rate = FixedU128::saturating_from_rational(25, 100);
let rialto_tokens = 100u64;
let rialto_tokens_in_millau_tokens = conversion_rate.saturating_mul_int(rialto_tokens);
assert_eq!(rialto_tokens_in_millau_tokens, 25);
});
}
#[test]
fn pallet_rejects_transactions_if_halted() {
run_test(|| {
@@ -1324,25 +1058,14 @@ mod tests {
));
assert_noop!(
Pallet::<TestRuntime>::send_message(
send_message::<TestRuntime, ()>(
RuntimeOrigin::signed(1),
TEST_LANE_ID,
REGULAR_PAYLOAD,
REGULAR_PAYLOAD.declared_weight.ref_time(),
),
Error::<TestRuntime, ()>::NotOperatingNormally,
);
assert_noop!(
Pallet::<TestRuntime>::increase_message_fee(
RuntimeOrigin::signed(1),
TEST_LANE_ID,
1,
1,
),
Error::<TestRuntime, ()>::BridgeModule(bp_runtime::OwnedBridgeModuleError::Halted),
);
assert_noop!(
Pallet::<TestRuntime>::receive_messages_proof(
RuntimeOrigin::signed(1),
@@ -1389,22 +1112,14 @@ mod tests {
);
assert_noop!(
Pallet::<TestRuntime>::send_message(
send_message::<TestRuntime, ()>(
RuntimeOrigin::signed(1),
TEST_LANE_ID,
REGULAR_PAYLOAD,
REGULAR_PAYLOAD.declared_weight.ref_time(),
),
Error::<TestRuntime, ()>::NotOperatingNormally,
);
assert_ok!(Pallet::<TestRuntime>::increase_message_fee(
RuntimeOrigin::signed(1),
TEST_LANE_ID,
1,
1,
));
assert_ok!(Pallet::<TestRuntime>::receive_messages_proof(
RuntimeOrigin::signed(1),
TEST_RELAYER_A,
@@ -1451,25 +1166,23 @@ mod tests {
.extra
.extend_from_slice(&[0u8; MAX_OUTBOUND_PAYLOAD_SIZE as usize]);
assert_noop!(
Pallet::<TestRuntime>::send_message(
send_message::<TestRuntime, ()>(
RuntimeOrigin::signed(1),
TEST_LANE_ID,
message_payload.clone(),
Balance::MAX,
),
Error::<TestRuntime, ()>::MessageIsTooLarge,
);
// let's check that we're able to send `MAX_OUTBOUND_PAYLOAD_SIZE` messages
while message_payload.size() > MAX_OUTBOUND_PAYLOAD_SIZE {
while message_payload.encoded_size() as u32 > MAX_OUTBOUND_PAYLOAD_SIZE {
message_payload.extra.pop();
}
assert_eq!(message_payload.size(), MAX_OUTBOUND_PAYLOAD_SIZE);
assert_ok!(Pallet::<TestRuntime>::send_message(
assert_eq!(message_payload.encoded_size() as u32, MAX_OUTBOUND_PAYLOAD_SIZE);
assert_ok!(send_message::<TestRuntime, ()>(
RuntimeOrigin::signed(1),
TEST_LANE_ID,
message_payload,
Balance::MAX,
),);
})
}
@@ -1479,11 +1192,10 @@ mod tests {
run_test(|| {
// messages with this payload are rejected by target chain verifier
assert_noop!(
Pallet::<TestRuntime>::send_message(
send_message::<TestRuntime, ()>(
RuntimeOrigin::signed(1),
TEST_LANE_ID,
PAYLOAD_REJECTED_BY_TARGET_CHAIN,
PAYLOAD_REJECTED_BY_TARGET_CHAIN.declared_weight.ref_time(),
),
Error::<TestRuntime, ()>::MessageRejectedByChainVerifier,
);
@@ -1494,34 +1206,15 @@ mod tests {
fn lane_verifier_rejects_invalid_message_in_send_message() {
run_test(|| {
// messages with zero fee are rejected by lane verifier
let mut message = REGULAR_PAYLOAD;
message.reject_by_lane_verifier = true;
assert_noop!(
Pallet::<TestRuntime>::send_message(
RuntimeOrigin::signed(1),
TEST_LANE_ID,
REGULAR_PAYLOAD,
0
),
send_message::<TestRuntime, ()>(RuntimeOrigin::signed(1), TEST_LANE_ID, message,),
Error::<TestRuntime, ()>::MessageRejectedByLaneVerifier,
);
});
}
#[test]
fn message_send_fails_if_submitter_cant_pay_message_fee() {
run_test(|| {
TestMessageDeliveryAndDispatchPayment::reject_payments();
assert_noop!(
Pallet::<TestRuntime>::send_message(
RuntimeOrigin::signed(1),
TEST_LANE_ID,
REGULAR_PAYLOAD,
REGULAR_PAYLOAD.declared_weight.ref_time(),
),
Error::<TestRuntime, ()>::FailedToWithdrawMessageFee,
);
});
}
#[test]
fn receive_messages_proof_works() {
run_test(|| {
@@ -1665,17 +1358,15 @@ mod tests {
#[test]
fn receive_messages_delivery_proof_rewards_relayers() {
run_test(|| {
assert_ok!(Pallet::<TestRuntime>::send_message(
assert_ok!(send_message::<TestRuntime, ()>(
RuntimeOrigin::signed(1),
TEST_LANE_ID,
REGULAR_PAYLOAD,
1000,
));
assert_ok!(Pallet::<TestRuntime>::send_message(
assert_ok!(send_message::<TestRuntime, ()>(
RuntimeOrigin::signed(1),
TEST_LANE_ID,
REGULAR_PAYLOAD,
2000,
));
// this reports delivery of message 1 => reward is paid to TEST_RELAYER_A
@@ -1697,8 +1388,8 @@ mod tests {
..Default::default()
},
));
assert!(TestMessageDeliveryAndDispatchPayment::is_reward_paid(TEST_RELAYER_A, 1000));
assert!(!TestMessageDeliveryAndDispatchPayment::is_reward_paid(TEST_RELAYER_B, 2000));
assert!(TestMessageDeliveryAndDispatchPayment::is_reward_paid(TEST_RELAYER_A, 1));
assert!(!TestMessageDeliveryAndDispatchPayment::is_reward_paid(TEST_RELAYER_B, 1));
// this reports delivery of both message 1 and message 2 => reward is paid only to
// TEST_RELAYER_B
@@ -1723,8 +1414,8 @@ mod tests {
..Default::default()
},
));
assert!(!TestMessageDeliveryAndDispatchPayment::is_reward_paid(TEST_RELAYER_A, 1000));
assert!(TestMessageDeliveryAndDispatchPayment::is_reward_paid(TEST_RELAYER_B, 2000));
assert!(!TestMessageDeliveryAndDispatchPayment::is_reward_paid(TEST_RELAYER_A, 1));
assert!(TestMessageDeliveryAndDispatchPayment::is_reward_paid(TEST_RELAYER_B, 1));
});
}
@@ -1829,7 +1520,7 @@ mod tests {
fn receive_messages_accepts_single_message_with_invalid_payload() {
run_test(|| {
let mut invalid_message = message(1, REGULAR_PAYLOAD);
invalid_message.data.payload = Vec::new();
invalid_message.payload = Vec::new();
assert_ok!(Pallet::<TestRuntime, ()>::receive_messages_proof(
RuntimeOrigin::signed(1),
@@ -1848,7 +1539,7 @@ mod tests {
fn receive_messages_accepts_batch_with_message_with_invalid_payload() {
run_test(|| {
let mut invalid_message = message(2, REGULAR_PAYLOAD);
invalid_message.data.payload = Vec::new();
invalid_message.payload = Vec::new();
assert_ok!(Pallet::<TestRuntime, ()>::receive_messages_proof(
RuntimeOrigin::signed(1),
@@ -1884,73 +1575,6 @@ mod tests {
});
}
#[test]
fn increase_message_fee_fails_if_message_is_already_delivered() {
run_test(|| {
send_regular_message();
receive_messages_delivery_proof();
assert_noop!(
Pallet::<TestRuntime, ()>::increase_message_fee(
RuntimeOrigin::signed(1),
TEST_LANE_ID,
1,
100,
),
Error::<TestRuntime, ()>::MessageIsAlreadyDelivered,
);
});
}
#[test]
fn increase_message_fee_fails_if_message_is_not_yet_sent() {
run_test(|| {
assert_noop!(
Pallet::<TestRuntime, ()>::increase_message_fee(
RuntimeOrigin::signed(1),
TEST_LANE_ID,
1,
100,
),
Error::<TestRuntime, ()>::MessageIsNotYetSent,
);
});
}
#[test]
fn increase_message_fee_fails_if_submitter_cant_pay_additional_fee() {
run_test(|| {
send_regular_message();
TestMessageDeliveryAndDispatchPayment::reject_payments();
assert_noop!(
Pallet::<TestRuntime, ()>::increase_message_fee(
RuntimeOrigin::signed(1),
TEST_LANE_ID,
1,
100,
),
Error::<TestRuntime, ()>::FailedToWithdrawMessageFee,
);
});
}
#[test]
fn increase_message_fee_succeeds() {
run_test(|| {
send_regular_message();
assert_ok!(Pallet::<TestRuntime, ()>::increase_message_fee(
RuntimeOrigin::signed(1),
TEST_LANE_ID,
1,
100,
),);
assert!(TestMessageDeliveryAndDispatchPayment::is_fee_paid(1, 100));
});
}
#[test]
fn weight_refund_from_receive_messages_proof_works() {
run_test(|| {
@@ -2187,101 +1811,6 @@ mod tests {
});
}
#[test]
fn increase_message_fee_weight_depends_on_message_size() {
run_test(|| {
let mut small_payload = message_payload(0, 100);
let mut large_payload = message_payload(1, 100);
small_payload.extra = vec![1; MAX_OUTBOUND_PAYLOAD_SIZE as usize / 10];
large_payload.extra = vec![2; MAX_OUTBOUND_PAYLOAD_SIZE as usize / 5];
assert_ok!(Pallet::<TestRuntime>::send_message(
RuntimeOrigin::signed(1),
TEST_LANE_ID,
small_payload,
100,
));
assert_ok!(Pallet::<TestRuntime>::send_message(
RuntimeOrigin::signed(1),
TEST_LANE_ID,
large_payload,
100,
));
let small_weight = Pallet::<TestRuntime>::increase_message_fee(
RuntimeOrigin::signed(1),
TEST_LANE_ID,
1,
1,
)
.expect("increase_message_fee has failed")
.actual_weight
.expect("increase_message_fee always returns Some");
let large_weight = Pallet::<TestRuntime>::increase_message_fee(
RuntimeOrigin::signed(1),
TEST_LANE_ID,
2,
1,
)
.expect("increase_message_fee has failed")
.actual_weight
.expect("increase_message_fee always returns Some");
assert!(
large_weight.ref_time() > small_weight.ref_time(),
"Actual post-dispatch weigth for larger message {} must be larger than {} for small message",
large_weight,
small_weight,
);
});
}
#[test]
fn weight_is_refunded_for_messages_that_are_not_pruned() {
run_test(|| {
// send first MAX messages - no messages are pruned
let max_messages_to_prune = crate::mock::MaxMessagesToPruneAtOnce::get();
let when_zero_messages_are_pruned = send_regular_message();
let mut delivered_messages = DeliveredMessages::new(1, true);
for _ in 1..max_messages_to_prune {
assert_eq!(send_regular_message(), when_zero_messages_are_pruned);
delivered_messages.note_dispatched_message(true);
}
// confirm delivery of all sent messages
assert_ok!(Pallet::<TestRuntime>::receive_messages_delivery_proof(
RuntimeOrigin::signed(1),
TestMessagesDeliveryProof(Ok((
TEST_LANE_ID,
InboundLaneData {
last_confirmed_nonce: 1,
relayers: vec![UnrewardedRelayer {
relayer: 0,
messages: delivered_messages,
}]
.into_iter()
.collect(),
},
))),
UnrewardedRelayersState {
unrewarded_relayer_entries: 1,
total_messages: max_messages_to_prune,
last_delivered_nonce: max_messages_to_prune,
..Default::default()
},
));
// when next message is sent, MAX messages are pruned
let weight_when_max_messages_are_pruned = send_regular_message();
assert_eq!(
weight_when_max_messages_are_pruned,
when_zero_messages_are_pruned +
crate::mock::DbWeight::get().writes(max_messages_to_prune),
);
});
}
#[test]
fn message_accepted_callbacks_are_called() {
run_test(|| {
@@ -2302,27 +1831,6 @@ mod tests {
});
}
#[test]
fn message_accepted_refunds_non_zero_weight() {
run_test(|| {
TestOnMessageAccepted::set_consumed_weight_per_message(
crate::mock::DbWeight::get().writes(1),
);
let actual_callback_weight = send_regular_message();
let pre_dispatch_weight = <TestRuntime as Config>::WeightInfo::send_message_weight(
&REGULAR_PAYLOAD,
crate::mock::DbWeight::get(),
);
let prune_weight = crate::mock::DbWeight::get()
.writes(<TestRuntime as Config>::MaxMessagesToPruneAtOnce::get());
assert_eq!(
pre_dispatch_weight.saturating_sub(actual_callback_weight),
crate::mock::DbWeight::get().reads(1).saturating_add(prune_weight)
);
});
}
#[test]
fn storage_keys_computed_properly() {
assert_eq!(
@@ -2360,9 +1868,6 @@ mod tests {
nonce: 0,
dispatch_weight: Weight::from_ref_time(0),
size: 0,
delivery_and_dispatch_fee: 0,
dispatch_fee_payment:
bp_runtime::messages::DispatchFeePayment::AtTargetChain,
},
),
InboundMessageDetails { dispatch_weight: REGULAR_PAYLOAD.declared_weight },
+37 -74
View File
@@ -26,10 +26,11 @@ use bp_messages::{
OnMessageAccepted, TargetHeaderChain,
},
target_chain::{
DispatchMessage, MessageDispatch, ProvedLaneMessages, ProvedMessages, SourceHeaderChain,
DispatchMessage, DispatchMessageData, MessageDispatch, ProvedLaneMessages, ProvedMessages,
SourceHeaderChain,
},
DeliveredMessages, InboundLaneData, LaneId, Message, MessageData, MessageKey, MessageNonce,
OutboundLaneData, Parameter as MessagesParameter, UnrewardedRelayer,
DeliveredMessages, InboundLaneData, LaneId, Message, MessageKey, MessageNonce, MessagePayload,
OutboundLaneData, UnrewardedRelayer,
};
use bp_runtime::{messages::MessageDispatchResult, Size};
use codec::{Decode, Encode};
@@ -42,7 +43,7 @@ use sp_core::H256;
use sp_runtime::{
testing::Header as SubstrateHeader,
traits::{BlakeTwo256, IdentityLookup},
FixedU128, Perbill,
Perbill,
};
use std::{
collections::{BTreeMap, VecDeque},
@@ -55,6 +56,8 @@ pub type Balance = u64;
pub struct TestPayload {
/// Field that may be used to identify messages.
pub id: u64,
/// Reject this message by lane verifier?
pub reject_by_lane_verifier: bool,
/// Dispatch weight that is declared by the message sender.
pub declared_weight: Weight,
/// Message dispatch result.
@@ -140,38 +143,20 @@ parameter_types! {
pub const MaxMessagesToPruneAtOnce: u64 = 10;
pub const MaxUnrewardedRelayerEntriesAtInboundLane: u64 = 16;
pub const MaxUnconfirmedMessagesAtInboundLane: u64 = 32;
pub storage TokenConversionRate: FixedU128 = 1.into();
pub const TestBridgedChainId: bp_runtime::ChainId = *b"test";
}
#[derive(Debug, Clone, Encode, Decode, PartialEq, Eq, TypeInfo)]
pub enum TestMessagesParameter {
TokenConversionRate(FixedU128),
}
impl MessagesParameter for TestMessagesParameter {
fn save(&self) {
match *self {
TestMessagesParameter::TokenConversionRate(conversion_rate) =>
TokenConversionRate::set(&conversion_rate),
}
}
}
impl Config for TestRuntime {
type RuntimeEvent = RuntimeEvent;
type WeightInfo = ();
type Parameter = TestMessagesParameter;
type MaxMessagesToPruneAtOnce = MaxMessagesToPruneAtOnce;
type MaxUnrewardedRelayerEntriesAtInboundLane = MaxUnrewardedRelayerEntriesAtInboundLane;
type MaxUnconfirmedMessagesAtInboundLane = MaxUnconfirmedMessagesAtInboundLane;
type MaximalOutboundPayloadSize = frame_support::traits::ConstU32<MAX_OUTBOUND_PAYLOAD_SIZE>;
type OutboundPayload = TestPayload;
type OutboundMessageFee = TestMessageFee;
type InboundPayload = TestPayload;
type InboundMessageFee = TestMessageFee;
type InboundRelayer = TestRelayer;
type TargetHeaderChain = TestTargetHeaderChain;
@@ -219,7 +204,7 @@ pub const REGULAR_PAYLOAD: TestPayload = message_payload(0, 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>>)>;
pub type MessagesByLaneVec = Vec<(LaneId, ProvedLaneMessages<Message>)>;
/// Test messages proof.
#[derive(Debug, Encode, Decode, Clone, PartialEq, Eq, TypeInfo)]
@@ -233,14 +218,12 @@ impl Size for TestMessagesProof {
}
}
impl From<Result<Vec<Message<TestMessageFee>>, ()>> for TestMessagesProof {
fn from(result: Result<Vec<Message<TestMessageFee>>, ()>) -> Self {
impl From<Result<Vec<Message>, ()>> for TestMessagesProof {
fn from(result: Result<Vec<Message>, ()>) -> Self {
Self {
result: result.map(|messages| {
let mut messages_by_lane: BTreeMap<
LaneId,
ProvedLaneMessages<Message<TestMessageFee>>,
> = BTreeMap::new();
let mut messages_by_lane: BTreeMap<LaneId, ProvedLaneMessages<Message>> =
BTreeMap::new();
for message in messages {
messages_by_lane.entry(message.key.lane_id).or_default().messages.push(message);
}
@@ -288,17 +271,16 @@ impl TargetHeaderChain<TestPayload, TestRelayer> for TestTargetHeaderChain {
#[derive(Debug, Default)]
pub struct TestLaneMessageVerifier;
impl LaneMessageVerifier<RuntimeOrigin, TestPayload, TestMessageFee> for TestLaneMessageVerifier {
impl LaneMessageVerifier<RuntimeOrigin, TestPayload> for TestLaneMessageVerifier {
type Error = &'static str;
fn verify_message(
_submitter: &RuntimeOrigin,
delivery_and_dispatch_fee: &TestMessageFee,
_lane: &LaneId,
_lane_outbound_data: &OutboundLaneData,
_payload: &TestPayload,
payload: &TestPayload,
) -> Result<(), Self::Error> {
if *delivery_and_dispatch_fee != 0 {
if !payload.reject_by_lane_verifier {
Ok(())
} else {
Err(TEST_ERROR)
@@ -311,18 +293,6 @@ impl LaneMessageVerifier<RuntimeOrigin, TestPayload, TestMessageFee> for TestLan
pub struct TestMessageDeliveryAndDispatchPayment;
impl TestMessageDeliveryAndDispatchPayment {
/// Reject all payments.
pub fn reject_payments() {
frame_support::storage::unhashed::put(b":reject-message-fee:", &true);
}
/// Returns true if given fee has been paid by given submitter.
pub fn is_fee_paid(submitter: AccountId, fee: TestMessageFee) -> bool {
let raw_origin: Result<frame_system::RawOrigin<_>, _> =
RuntimeOrigin::signed(submitter).into();
frame_support::storage::unhashed::get(b":message-fee:") == Some((raw_origin.unwrap(), fee))
}
/// Returns true if given relayer has been rewarded with given balance. The reward-paid flag is
/// cleared after the call.
pub fn is_reward_paid(relayer: AccountId, fee: TestMessageFee) -> bool {
@@ -331,34 +301,21 @@ impl TestMessageDeliveryAndDispatchPayment {
}
}
impl MessageDeliveryAndDispatchPayment<RuntimeOrigin, AccountId, TestMessageFee>
impl MessageDeliveryAndDispatchPayment<RuntimeOrigin, AccountId>
for TestMessageDeliveryAndDispatchPayment
{
type Error = &'static str;
fn pay_delivery_and_dispatch_fee(
submitter: &RuntimeOrigin,
fee: &TestMessageFee,
) -> Result<(), Self::Error> {
if frame_support::storage::unhashed::get(b":reject-message-fee:") == Some(true) {
return Err(TEST_ERROR)
}
let raw_origin: Result<frame_system::RawOrigin<_>, _> = submitter.clone().into();
frame_support::storage::unhashed::put(b":message-fee:", &(raw_origin.unwrap(), fee));
Ok(())
}
fn pay_relayers_rewards(
lane_id: LaneId,
_lane_id: LaneId,
message_relayers: VecDeque<UnrewardedRelayer<AccountId>>,
_confirmation_relayer: &AccountId,
received_range: &RangeInclusive<MessageNonce>,
) {
let relayers_rewards =
calc_relayers_rewards::<TestRuntime, ()>(lane_id, message_relayers, received_range);
calc_relayers_rewards::<TestRuntime, ()>(message_relayers, received_range);
for (relayer, reward) in &relayers_rewards {
let key = (b":relayer-reward:", relayer, reward.reward).encode();
let key = (b":relayer-reward:", relayer, reward).encode();
frame_support::storage::unhashed::put(&key, &true);
}
}
@@ -450,7 +407,7 @@ impl OnDeliveryConfirmed for TestOnDeliveryConfirmed2 {
#[derive(Debug)]
pub struct TestSourceHeaderChain;
impl SourceHeaderChain<TestMessageFee> for TestSourceHeaderChain {
impl SourceHeaderChain for TestSourceHeaderChain {
type Error = &'static str;
type MessagesProof = TestMessagesProof;
@@ -458,7 +415,7 @@ impl SourceHeaderChain<TestMessageFee> for TestSourceHeaderChain {
fn verify_messages_proof(
proof: Self::MessagesProof,
_messages_count: u32,
) -> Result<ProvedMessages<Message<TestMessageFee>>, Self::Error> {
) -> Result<ProvedMessages<Message>, Self::Error> {
proof.result.map(|proof| proof.into_iter().collect()).map_err(|_| TEST_ERROR)
}
}
@@ -467,10 +424,10 @@ impl SourceHeaderChain<TestMessageFee> for TestSourceHeaderChain {
#[derive(Debug)]
pub struct TestMessageDispatch;
impl MessageDispatch<AccountId, TestMessageFee> for TestMessageDispatch {
impl MessageDispatch<AccountId> for TestMessageDispatch {
type DispatchPayload = TestPayload;
fn dispatch_weight(message: &mut DispatchMessage<TestPayload, TestMessageFee>) -> Weight {
fn dispatch_weight(message: &mut DispatchMessage<TestPayload>) -> Weight {
match message.data.payload.as_ref() {
Ok(payload) => payload.declared_weight,
Err(_) => Weight::from_ref_time(0),
@@ -479,7 +436,7 @@ impl MessageDispatch<AccountId, TestMessageFee> for TestMessageDispatch {
fn dispatch(
_relayer_account: &AccountId,
message: DispatchMessage<TestPayload, TestMessageFee>,
message: DispatchMessage<TestPayload>,
) -> MessageDispatchResult {
match message.data.payload.as_ref() {
Ok(payload) => payload.dispatch_result.clone(),
@@ -489,25 +446,31 @@ impl MessageDispatch<AccountId, TestMessageFee> for TestMessageDispatch {
}
/// Return test lane message with given nonce and payload.
pub fn message(nonce: MessageNonce, payload: TestPayload) -> Message<TestMessageFee> {
Message { key: MessageKey { lane_id: TEST_LANE_ID, nonce }, data: message_data(payload) }
pub fn message(nonce: MessageNonce, payload: TestPayload) -> Message {
Message { key: MessageKey { lane_id: TEST_LANE_ID, nonce }, payload: payload.encode() }
}
/// Return valid outbound message data, constructed from given payload.
pub fn outbound_message_data(payload: TestPayload) -> MessagePayload {
payload.encode()
}
/// Return valid inbound (dispatch) message data, constructed from given payload.
pub fn inbound_message_data(payload: TestPayload) -> DispatchMessageData<TestPayload> {
DispatchMessageData { payload: Ok(payload) }
}
/// Constructs message payload using given arguments and zero unspent weight.
pub const fn message_payload(id: u64, declared_weight: u64) -> TestPayload {
TestPayload {
id,
reject_by_lane_verifier: false,
declared_weight: Weight::from_ref_time(declared_weight),
dispatch_result: dispatch_result(0),
extra: Vec::new(),
}
}
/// Return message data with valid fee for given payload.
pub fn message_data(payload: TestPayload) -> MessageData<TestMessageFee> {
MessageData { payload: payload.encode(), fee: 1 }
}
/// Returns message dispatch result with given unspent weight.
pub const fn dispatch_result(unspent_weight: u64) -> MessageDispatchResult {
MessageDispatchResult {
+26 -80
View File
@@ -20,19 +20,14 @@ use crate::Config;
use bitvec::prelude::*;
use bp_messages::{
DeliveredMessages, DispatchResultsBitVec, LaneId, MessageData, MessageNonce, OutboundLaneData,
UnrewardedRelayer,
DeliveredMessages, DispatchResultsBitVec, LaneId, MessageNonce, MessagePayload,
OutboundLaneData, UnrewardedRelayer,
};
use codec::{Decode, Encode, EncodeLike, MaxEncodedLen};
use frame_support::{traits::Get, RuntimeDebug};
use scale_info::{Type, TypeInfo};
use frame_support::{BoundedVec, RuntimeDebug};
use sp_std::collections::vec_deque::VecDeque;
/// Outbound lane storage.
pub trait OutboundLaneStorage {
/// Delivery and dispatch fee type on source chain.
type MessageFee;
/// Lane id.
fn id(&self) -> LaneId;
/// Get lane data from the storage.
@@ -41,64 +36,15 @@ pub trait OutboundLaneStorage {
fn set_data(&mut self, data: OutboundLaneData);
/// Returns saved outbound message payload.
#[cfg(test)]
fn message(&self, nonce: &MessageNonce) -> Option<MessageData<Self::MessageFee>>;
fn message(&self, nonce: &MessageNonce) -> Option<MessagePayload>;
/// Save outbound message in the storage.
fn save_message(&mut self, nonce: MessageNonce, message_data: MessageData<Self::MessageFee>);
fn save_message(&mut self, nonce: MessageNonce, message_payload: MessagePayload);
/// Remove outbound message from the storage.
fn remove_message(&mut self, nonce: &MessageNonce);
}
/// Outbound message data wrapper that implements `MaxEncodedLen`.
///
/// We have already had `MaxEncodedLen`-like functionality before, but its usage has
/// been localized and we haven't been passing it everywhere. This wrapper allows us
/// to avoid passing these generic bounds all over the code.
///
/// The encoding of this type matches encoding of the corresponding `MessageData`.
#[derive(Encode, Decode, Clone, RuntimeDebug, PartialEq, Eq)]
pub struct StoredMessageData<T: Config<I>, I: 'static>(pub MessageData<T::OutboundMessageFee>);
impl<T: Config<I>, I: 'static> sp_std::ops::Deref for StoredMessageData<T, I> {
type Target = MessageData<T::OutboundMessageFee>;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl<T: Config<I>, I: 'static> sp_std::ops::DerefMut for StoredMessageData<T, I> {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.0
}
}
impl<T: Config<I>, I: 'static> From<StoredMessageData<T, I>>
for MessageData<T::OutboundMessageFee>
{
fn from(data: StoredMessageData<T, I>) -> Self {
data.0
}
}
impl<T: Config<I>, I: 'static> TypeInfo for StoredMessageData<T, I> {
type Identity = Self;
fn type_info() -> Type {
MessageData::<T::OutboundMessageFee>::type_info()
}
}
impl<T: Config<I>, I: 'static> EncodeLike<StoredMessageData<T, I>>
for MessageData<T::OutboundMessageFee>
{
}
impl<T: Config<I>, I: 'static> MaxEncodedLen for StoredMessageData<T, I> {
fn max_encoded_len() -> usize {
T::OutboundMessageFee::max_encoded_len()
.saturating_add(T::MaximalOutboundPayloadSize::get() as usize)
}
}
pub type StoredMessagePayload<T, I> = BoundedVec<u8, <T as Config<I>>::MaximalOutboundPayloadSize>;
/// Result of messages receival confirmation.
#[derive(RuntimeDebug, PartialEq, Eq)]
@@ -143,12 +89,12 @@ impl<S: OutboundLaneStorage> OutboundLane<S> {
/// Send message over lane.
///
/// Returns new message nonce.
pub fn send_message(&mut self, message_data: MessageData<S::MessageFee>) -> MessageNonce {
pub fn send_message(&mut self, message_payload: MessagePayload) -> MessageNonce {
let mut data = self.storage.data();
let nonce = data.latest_generated_nonce + 1;
data.latest_generated_nonce = nonce;
self.storage.save_message(nonce, message_data);
self.storage.save_message(nonce, message_payload);
self.storage.set_data(data);
nonce
@@ -295,8 +241,8 @@ mod tests {
use super::*;
use crate::{
mock::{
message_data, run_test, unrewarded_relayer, TestRelayer, TestRuntime, REGULAR_PAYLOAD,
TEST_LANE_ID,
outbound_message_data, run_test, unrewarded_relayer, TestRelayer, TestRuntime,
REGULAR_PAYLOAD, TEST_LANE_ID,
},
outbound_lane,
};
@@ -324,9 +270,9 @@ mod tests {
) -> ReceivalConfirmationResult {
run_test(|| {
let mut lane = outbound_lane::<TestRuntime, _>(TEST_LANE_ID);
lane.send_message(message_data(REGULAR_PAYLOAD));
lane.send_message(message_data(REGULAR_PAYLOAD));
lane.send_message(message_data(REGULAR_PAYLOAD));
lane.send_message(outbound_message_data(REGULAR_PAYLOAD));
lane.send_message(outbound_message_data(REGULAR_PAYLOAD));
lane.send_message(outbound_message_data(REGULAR_PAYLOAD));
assert_eq!(lane.storage.data().latest_generated_nonce, 3);
assert_eq!(lane.storage.data().latest_received_nonce, 0);
let result = lane.confirm_delivery(3, latest_received_nonce, relayers);
@@ -341,7 +287,7 @@ mod tests {
run_test(|| {
let mut lane = outbound_lane::<TestRuntime, _>(TEST_LANE_ID);
assert_eq!(lane.storage.data().latest_generated_nonce, 0);
assert_eq!(lane.send_message(message_data(REGULAR_PAYLOAD)), 1);
assert_eq!(lane.send_message(outbound_message_data(REGULAR_PAYLOAD)), 1);
assert!(lane.storage.message(&1).is_some());
assert_eq!(lane.storage.data().latest_generated_nonce, 1);
});
@@ -351,9 +297,9 @@ mod tests {
fn confirm_delivery_works() {
run_test(|| {
let mut lane = outbound_lane::<TestRuntime, _>(TEST_LANE_ID);
assert_eq!(lane.send_message(message_data(REGULAR_PAYLOAD)), 1);
assert_eq!(lane.send_message(message_data(REGULAR_PAYLOAD)), 2);
assert_eq!(lane.send_message(message_data(REGULAR_PAYLOAD)), 3);
assert_eq!(lane.send_message(outbound_message_data(REGULAR_PAYLOAD)), 1);
assert_eq!(lane.send_message(outbound_message_data(REGULAR_PAYLOAD)), 2);
assert_eq!(lane.send_message(outbound_message_data(REGULAR_PAYLOAD)), 3);
assert_eq!(lane.storage.data().latest_generated_nonce, 3);
assert_eq!(lane.storage.data().latest_received_nonce, 0);
assert_eq!(
@@ -369,9 +315,9 @@ mod tests {
fn confirm_delivery_rejects_nonce_lesser_than_latest_received() {
run_test(|| {
let mut lane = outbound_lane::<TestRuntime, _>(TEST_LANE_ID);
lane.send_message(message_data(REGULAR_PAYLOAD));
lane.send_message(message_data(REGULAR_PAYLOAD));
lane.send_message(message_data(REGULAR_PAYLOAD));
lane.send_message(outbound_message_data(REGULAR_PAYLOAD));
lane.send_message(outbound_message_data(REGULAR_PAYLOAD));
lane.send_message(outbound_message_data(REGULAR_PAYLOAD));
assert_eq!(lane.storage.data().latest_generated_nonce, 3);
assert_eq!(lane.storage.data().latest_received_nonce, 0);
assert_eq!(
@@ -470,9 +416,9 @@ mod tests {
assert_eq!(lane.prune_messages(100), 0);
assert_eq!(lane.storage.data().oldest_unpruned_nonce, 1);
// when nothing is confirmed, nothing is pruned
lane.send_message(message_data(REGULAR_PAYLOAD));
lane.send_message(message_data(REGULAR_PAYLOAD));
lane.send_message(message_data(REGULAR_PAYLOAD));
lane.send_message(outbound_message_data(REGULAR_PAYLOAD));
lane.send_message(outbound_message_data(REGULAR_PAYLOAD));
lane.send_message(outbound_message_data(REGULAR_PAYLOAD));
assert_eq!(lane.prune_messages(100), 0);
assert_eq!(lane.storage.data().oldest_unpruned_nonce, 1);
// after confirmation, some messages are received
@@ -496,9 +442,9 @@ mod tests {
fn confirm_delivery_detects_when_more_than_expected_messages_are_confirmed() {
run_test(|| {
let mut lane = outbound_lane::<TestRuntime, _>(TEST_LANE_ID);
lane.send_message(message_data(REGULAR_PAYLOAD));
lane.send_message(message_data(REGULAR_PAYLOAD));
lane.send_message(message_data(REGULAR_PAYLOAD));
lane.send_message(outbound_message_data(REGULAR_PAYLOAD));
lane.send_message(outbound_message_data(REGULAR_PAYLOAD));
lane.send_message(outbound_message_data(REGULAR_PAYLOAD));
assert_eq!(
lane.confirm_delivery(0, 3, &unrewarded_relayers(1..=3)),
ReceivalConfirmationResult::TryingToConfirmMoreMessagesThanExpected(3),
+25 -82
View File
@@ -17,7 +17,7 @@
//! Autogenerated weights for `pallet_bridge_messages`
//!
//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev
//! DATE: 2022-10-17, STEPS: 50, REPEAT: 20
//! DATE: 2022-11-17, STEPS: 50, REPEAT: 20
//! LOW RANGE: [], HIGH RANGE: []
//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled
//! CHAIN: Some("dev"), DB CACHE: 1024
@@ -50,11 +50,6 @@ use sp_std::marker::PhantomData;
/// Weight functions needed for `pallet_bridge_messages`.
pub trait WeightInfo {
fn send_minimal_message_worst_case() -> Weight;
fn send_1_kb_message_worst_case() -> Weight;
fn send_16_kb_message_worst_case() -> Weight;
fn maximal_increase_message_fee() -> Weight;
fn increase_message_fee(i: u32) -> Weight;
fn receive_single_message_proof() -> Weight;
fn receive_two_messages_proof() -> Weight;
fn receive_single_message_proof_with_outbound_lane_state() -> Weight;
@@ -71,150 +66,98 @@ pub trait WeightInfo {
/// Those weights are test only and must never be used in production.
pub struct BridgeWeight<T>(PhantomData<T>);
impl<T: frame_system::Config> WeightInfo for BridgeWeight<T> {
fn send_minimal_message_worst_case() -> Weight {
Weight::from_ref_time(61_807_000 as u64)
.saturating_add(T::DbWeight::get().reads(5 as u64))
.saturating_add(T::DbWeight::get().writes(10 as u64))
}
fn send_1_kb_message_worst_case() -> Weight {
Weight::from_ref_time(65_074_000 as u64)
.saturating_add(T::DbWeight::get().reads(5 as u64))
.saturating_add(T::DbWeight::get().writes(10 as u64))
}
fn send_16_kb_message_worst_case() -> Weight {
Weight::from_ref_time(73_584_000 as u64)
.saturating_add(T::DbWeight::get().reads(5 as u64))
.saturating_add(T::DbWeight::get().writes(10 as u64))
}
fn maximal_increase_message_fee() -> Weight {
Weight::from_ref_time(2_522_629_000 as u64)
.saturating_add(T::DbWeight::get().reads(3 as u64))
.saturating_add(T::DbWeight::get().writes(1 as u64))
}
fn increase_message_fee(i: u32) -> Weight {
Weight::from_ref_time(27_072_000 as u64)
.saturating_add(Weight::from_ref_time(892 as u64).saturating_mul(i as u64))
.saturating_add(T::DbWeight::get().reads(3 as u64))
.saturating_add(T::DbWeight::get().writes(1 as u64))
}
fn receive_single_message_proof() -> Weight {
Weight::from_ref_time(49_628_000 as u64)
Weight::from_ref_time(50_596_000 as u64)
.saturating_add(T::DbWeight::get().reads(4 as u64))
.saturating_add(T::DbWeight::get().writes(2 as u64))
}
fn receive_two_messages_proof() -> Weight {
Weight::from_ref_time(61_514_000 as u64)
Weight::from_ref_time(77_041_000 as u64)
.saturating_add(T::DbWeight::get().reads(4 as u64))
.saturating_add(T::DbWeight::get().writes(2 as u64))
}
fn receive_single_message_proof_with_outbound_lane_state() -> Weight {
Weight::from_ref_time(65_960_000 as u64)
Weight::from_ref_time(58_331_000 as u64)
.saturating_add(T::DbWeight::get().reads(4 as u64))
.saturating_add(T::DbWeight::get().writes(2 as u64))
}
fn receive_single_message_proof_1_kb() -> Weight {
Weight::from_ref_time(48_009_000 as u64)
Weight::from_ref_time(48_061_000 as u64)
.saturating_add(T::DbWeight::get().reads(3 as u64))
.saturating_add(T::DbWeight::get().writes(1 as u64))
}
fn receive_single_message_proof_16_kb() -> Weight {
Weight::from_ref_time(100_439_000 as u64)
Weight::from_ref_time(101_601_000 as u64)
.saturating_add(T::DbWeight::get().reads(3 as u64))
.saturating_add(T::DbWeight::get().writes(1 as u64))
}
fn receive_single_prepaid_message_proof() -> Weight {
Weight::from_ref_time(50_463_000 as u64)
Weight::from_ref_time(49_646_000 as u64)
.saturating_add(T::DbWeight::get().reads(4 as u64))
.saturating_add(T::DbWeight::get().writes(2 as u64))
}
fn receive_delivery_proof_for_single_message() -> Weight {
Weight::from_ref_time(57_383_000 as u64)
.saturating_add(T::DbWeight::get().reads(5 as u64))
Weight::from_ref_time(55_108_000 as u64)
.saturating_add(T::DbWeight::get().reads(4 as u64))
.saturating_add(T::DbWeight::get().writes(2 as u64))
}
fn receive_delivery_proof_for_two_messages_by_single_relayer() -> Weight {
Weight::from_ref_time(62_003_000 as u64)
.saturating_add(T::DbWeight::get().reads(6 as u64))
Weight::from_ref_time(53_917_000 as u64)
.saturating_add(T::DbWeight::get().reads(4 as u64))
.saturating_add(T::DbWeight::get().writes(2 as u64))
}
fn receive_delivery_proof_for_two_messages_by_two_relayers() -> Weight {
Weight::from_ref_time(64_401_000 as u64)
.saturating_add(T::DbWeight::get().reads(7 as u64))
Weight::from_ref_time(57_335_000 as u64)
.saturating_add(T::DbWeight::get().reads(5 as u64))
.saturating_add(T::DbWeight::get().writes(3 as u64))
}
}
// For backwards compatibility and tests
impl WeightInfo for () {
fn send_minimal_message_worst_case() -> Weight {
Weight::from_ref_time(61_807_000 as u64)
.saturating_add(RocksDbWeight::get().reads(5 as u64))
.saturating_add(RocksDbWeight::get().writes(10 as u64))
}
fn send_1_kb_message_worst_case() -> Weight {
Weight::from_ref_time(65_074_000 as u64)
.saturating_add(RocksDbWeight::get().reads(5 as u64))
.saturating_add(RocksDbWeight::get().writes(10 as u64))
}
fn send_16_kb_message_worst_case() -> Weight {
Weight::from_ref_time(73_584_000 as u64)
.saturating_add(RocksDbWeight::get().reads(5 as u64))
.saturating_add(RocksDbWeight::get().writes(10 as u64))
}
fn maximal_increase_message_fee() -> Weight {
Weight::from_ref_time(2_522_629_000 as u64)
.saturating_add(RocksDbWeight::get().reads(3 as u64))
.saturating_add(RocksDbWeight::get().writes(1 as u64))
}
fn increase_message_fee(i: u32) -> Weight {
Weight::from_ref_time(27_072_000 as u64)
.saturating_add(Weight::from_ref_time(892 as u64).saturating_mul(i as u64))
.saturating_add(RocksDbWeight::get().reads(3 as u64))
.saturating_add(RocksDbWeight::get().writes(1 as u64))
}
fn receive_single_message_proof() -> Weight {
Weight::from_ref_time(49_628_000 as u64)
Weight::from_ref_time(50_596_000 as u64)
.saturating_add(RocksDbWeight::get().reads(4 as u64))
.saturating_add(RocksDbWeight::get().writes(2 as u64))
}
fn receive_two_messages_proof() -> Weight {
Weight::from_ref_time(61_514_000 as u64)
Weight::from_ref_time(77_041_000 as u64)
.saturating_add(RocksDbWeight::get().reads(4 as u64))
.saturating_add(RocksDbWeight::get().writes(2 as u64))
}
fn receive_single_message_proof_with_outbound_lane_state() -> Weight {
Weight::from_ref_time(65_960_000 as u64)
Weight::from_ref_time(58_331_000 as u64)
.saturating_add(RocksDbWeight::get().reads(4 as u64))
.saturating_add(RocksDbWeight::get().writes(2 as u64))
}
fn receive_single_message_proof_1_kb() -> Weight {
Weight::from_ref_time(48_009_000 as u64)
Weight::from_ref_time(48_061_000 as u64)
.saturating_add(RocksDbWeight::get().reads(3 as u64))
.saturating_add(RocksDbWeight::get().writes(1 as u64))
}
fn receive_single_message_proof_16_kb() -> Weight {
Weight::from_ref_time(100_439_000 as u64)
Weight::from_ref_time(101_601_000 as u64)
.saturating_add(RocksDbWeight::get().reads(3 as u64))
.saturating_add(RocksDbWeight::get().writes(1 as u64))
}
fn receive_single_prepaid_message_proof() -> Weight {
Weight::from_ref_time(50_463_000 as u64)
Weight::from_ref_time(49_646_000 as u64)
.saturating_add(RocksDbWeight::get().reads(4 as u64))
.saturating_add(RocksDbWeight::get().writes(2 as u64))
}
fn receive_delivery_proof_for_single_message() -> Weight {
Weight::from_ref_time(57_383_000 as u64)
.saturating_add(RocksDbWeight::get().reads(5 as u64))
Weight::from_ref_time(55_108_000 as u64)
.saturating_add(RocksDbWeight::get().reads(4 as u64))
.saturating_add(RocksDbWeight::get().writes(2 as u64))
}
fn receive_delivery_proof_for_two_messages_by_single_relayer() -> Weight {
Weight::from_ref_time(62_003_000 as u64)
.saturating_add(RocksDbWeight::get().reads(6 as u64))
Weight::from_ref_time(53_917_000 as u64)
.saturating_add(RocksDbWeight::get().reads(4 as u64))
.saturating_add(RocksDbWeight::get().writes(2 as u64))
}
fn receive_delivery_proof_for_two_messages_by_two_relayers() -> Weight {
Weight::from_ref_time(64_401_000 as u64)
.saturating_add(RocksDbWeight::get().reads(7 as u64))
Weight::from_ref_time(57_335_000 as u64)
.saturating_add(RocksDbWeight::get().reads(5 as u64))
.saturating_add(RocksDbWeight::get().writes(3 as u64))
}
}
+1 -92
View File
@@ -35,82 +35,16 @@ const SIGNED_EXTENSIONS_SIZE: u32 = 1024;
pub const EXTRA_STORAGE_PROOF_SIZE: u32 = 1024;
/// Ensure that weights from `WeightInfoExt` implementation are looking correct.
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,
db_weight: RuntimeDbWeight,
) {
// verify `send_message` weight components
assert_ne!(W::send_message_overhead(), Weight::zero());
assert_ne!(W::send_message_size_overhead(0), Weight::zero());
pub fn ensure_weights_are_correct<W: WeightInfoExt>() {
// verify `receive_messages_proof` weight components
assert_ne!(W::receive_messages_proof_overhead(), Weight::zero());
assert_ne!(W::receive_messages_proof_messages_overhead(1), Weight::zero());
assert_ne!(W::receive_messages_proof_outbound_lane_state_overhead(), Weight::zero());
assert_ne!(W::storage_proof_size_overhead(1), Weight::zero());
// verify that the hardcoded value covers `receive_messages_proof` weight
let actual_single_regular_message_delivery_tx_weight = W::receive_messages_proof_weight(
&PreComputedSize(
(EXPECTED_DEFAULT_MESSAGE_LENGTH + W::expected_extra_storage_proof_size()) as usize,
),
1,
Weight::zero(),
);
assert!(
actual_single_regular_message_delivery_tx_weight
.all_lte(expected_default_message_delivery_tx_weight),
"Default message delivery transaction weight {} is larger than expected weight {}",
actual_single_regular_message_delivery_tx_weight,
expected_default_message_delivery_tx_weight,
);
// verify that hardcoded value covers additional byte length of `receive_messages_proof` weight
let actual_additional_byte_delivery_weight = W::storage_proof_size_overhead(1);
assert!(
actual_additional_byte_delivery_weight.all_lte(expected_additional_byte_delivery_weight),
"Single additional byte delivery weight {} is larger than expected weight {}",
actual_additional_byte_delivery_weight,
expected_additional_byte_delivery_weight,
);
// verify `receive_messages_delivery_proof` weight components
assert_ne!(W::receive_messages_delivery_proof_overhead(), Weight::zero());
assert_ne!(W::storage_proof_size_overhead(1), Weight::zero());
// `receive_messages_delivery_proof_messages_overhead` and
// `receive_messages_delivery_proof_relayers_overhead` may return zero if rewards are not paid
// during confirmations delivery, so we're not checking it here
// verify that the hardcoded value covers `receive_messages_delivery_proof` weight
let actual_messages_delivery_confirmation_tx_weight = W::receive_messages_delivery_proof_weight(
&PreComputedSize(W::expected_extra_storage_proof_size() as usize),
&UnrewardedRelayersState {
unrewarded_relayer_entries: 1,
total_messages: 1,
..Default::default()
},
db_weight,
);
assert!(
actual_messages_delivery_confirmation_tx_weight
.all_lte(expected_messages_delivery_confirmation_tx_weight),
"Messages delivery confirmation transaction weight {} is larger than expected weight {}",
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.all_lte(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.
@@ -198,17 +132,6 @@ pub trait WeightInfoExt: WeightInfo {
// Functions that are directly mapped to extrinsics weights.
/// Weight of message send extrinsic.
fn send_message_weight(message: &impl Size, db_weight: RuntimeDbWeight) -> Weight {
let transaction_overhead = Self::send_message_overhead();
let message_size_overhead = Self::send_message_size_overhead(message.size());
let call_back_overhead = Self::single_message_callback_overhead(db_weight);
transaction_overhead
.saturating_add(message_size_overhead)
.saturating_add(call_back_overhead)
}
/// Weight of message delivery extrinsic.
fn receive_messages_proof_weight(
proof: &impl Size,
@@ -274,20 +197,6 @@ pub trait WeightInfoExt: WeightInfo {
// Functions that are used by extrinsics weights formulas.
/// Returns weight of message send transaction (`send_message`).
fn send_message_overhead() -> Weight {
Self::send_minimal_message_worst_case()
}
/// Returns weight that needs to be accounted when message of given size is sent
/// (`send_message`).
fn send_message_size_overhead(message_size: u32) -> Weight {
let message_size_in_kb = (1024u64 + message_size as u64) / 1024;
let single_kb_weight =
(Self::send_16_kb_message_worst_case() - Self::send_1_kb_message_worst_case()) / 15;
message_size_in_kb * single_kb_weight
}
/// Returns weight overhead of message delivery transaction (`receive_messages_proof`).
fn receive_messages_proof_overhead() -> Weight {
let weight_of_two_messages_and_two_tx_overheads =