Merge commit '392447f5c8f986ded2559a78457f4cd87942f393' into update-bridges-subtree-r/w

This commit is contained in:
antonio-dropulic
2021-12-01 09:46:14 +01:00
321 changed files with 28385 additions and 10466 deletions
+7 -9
View File
@@ -8,7 +8,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0"
[dependencies]
bitvec = { version = "0.20", default-features = false, features = ["alloc"] }
codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false }
codec = { package = "parity-scale-codec", version = "2.2.0", default-features = false }
log = { version = "0.4.14", default-features = false }
num-traits = { version = "0.2", default-features = false }
scale-info = { version = "1.0", default-features = false, features = ["derive"] }
@@ -18,17 +18,16 @@ serde = { version = "1.0.101", optional = true, features = ["derive"] }
bp-message-dispatch = { path = "../../primitives/message-dispatch", default-features = false }
bp-messages = { path = "../../primitives/messages", default-features = false }
bp-rialto = { path = "../../primitives/chain-rialto", default-features = false }
bp-runtime = { path = "../../primitives/runtime", default-features = false }
# Substrate Dependencies
frame-benchmarking = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false, optional = true }
frame-support = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false }
frame-system = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false }
sp-core = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false }
sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false }
sp-std = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false }
frame-benchmarking = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false, optional = true }
frame-support = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
frame-system = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
sp-core = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
sp-std = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
[dev-dependencies]
hex = "0.4"
@@ -42,7 +41,6 @@ std = [
"bp-message-dispatch/std",
"bp-messages/std",
"bp-runtime/std",
"bp-rialto/std",
"codec/std",
"frame-support/std",
"frame-system/std",
+11 -1
View File
@@ -354,7 +354,7 @@ Both conditions are verified by `pallet_bridge_messages::ensure_weights_are_corr
`pallet_bridge_messages::ensure_able_to_receive_messages` functions, which must be called from every
runtime's tests.
### Post-dispatch weight refunds of the `receive_messages_proof` call
#### Post-dispatch weight refunds of the `receive_messages_proof` call
Weight formula of the `receive_messages_proof` call assumes that the dispatch fee of every message is
paid at the target chain (where call is executed), that every message will be dispatched and that
@@ -388,6 +388,7 @@ The weight formula is:
Weight = BaseWeight + MessagesCount * MessageConfirmationWeight
+ RelayersCount * RelayerRewardWeight
+ Max(0, ActualProofSize - ExpectedProofSize) * ProofByteDeliveryWeight
+ MessagesCount * (DbReadWeight + DbWriteWeight)
```
Where:
@@ -403,6 +404,15 @@ Where:
| `ExpectedProofSize` | `EXTRA_STORAGE_PROOF_SIZE` | Size of proof that we are expecting |
| `ProofByteDeliveryWeight` | `(receive_single_message_proof_16_kb - receive_single_message_proof_1_kb) / (15 * 1024)` | Weight of processing every additional proof byte over `ExpectedProofSize` limit. We're using the same formula, as for message delivery, because proof mechanism is assumed to be the same in both cases |
#### Post-dispatch weight refunds of the `receive_messages_delivery_proof` call
Weight formula of the `receive_messages_delivery_proof` call assumes that all messages in the proof
are actually delivered (so there are no already confirmed messages) and every messages is processed
by the `OnDeliveryConfirmed` callback. This means that for every message, we're adding single db read
weight and single db write weight. If, by some reason, messages are not processed by the
`OnDeliveryConfirmed` callback, or their processing is faster than that additional weight, the
difference is refunded to the submitter.
#### Why we're always able to craft `receive_messages_delivery_proof` transaction?
There can be at most `<PeerRuntime as pallet_bridge_messages::Config>::MaxUnconfirmedMessagesAtInboundLane`
@@ -16,18 +16,18 @@
//! Messages pallet benchmarking.
use crate::weights_ext::EXPECTED_DEFAULT_MESSAGE_LENGTH;
use crate::{
inbound_lane::InboundLaneStorage, inbound_lane_storage, outbound_lane, outbound_lane::ReceivalConfirmationResult,
Call, Instance,
inbound_lane::InboundLaneStorage, inbound_lane_storage, outbound_lane,
outbound_lane::ReceivalConfirmationResult, weights_ext::EXPECTED_DEFAULT_MESSAGE_LENGTH, Call,
};
use bp_messages::{
source_chain::TargetHeaderChain, target_chain::SourceHeaderChain, DeliveredMessages, InboundLaneData, LaneId,
MessageData, MessageNonce, OutboundLaneData, UnrewardedRelayer, UnrewardedRelayersState,
source_chain::TargetHeaderChain, target_chain::SourceHeaderChain, DeliveredMessages,
InboundLaneData, LaneId, MessageData, MessageNonce, OutboundLaneData, UnrewardedRelayer,
UnrewardedRelayersState,
};
use bp_runtime::messages::DispatchFeePayment;
use frame_benchmarking::{account, benchmarks_instance};
use frame_benchmarking::{account, benchmarks_instance_pallet};
use frame_support::{traits::Get, weights::Weight};
use frame_system::RawOrigin;
use sp_std::{
@@ -38,23 +38,23 @@ use sp_std::{
};
/// Fee paid by submitter for single message delivery.
pub const MESSAGE_FEE: u64 = 10_000_000_000;
pub const MESSAGE_FEE: u64 = 100_000_000_000;
const SEED: u32 = 0;
/// Pallet we're benchmarking here.
pub struct Pallet<T: Config<I>, I: crate::Instance>(crate::Pallet<T, I>);
pub struct Pallet<T: Config<I>, I: 'static>(crate::Pallet<T, I>);
/// Proof size requirements.
pub enum ProofSize {
/// The proof is expected to be minimal. If value size may be changed, then it is expected to
/// have given size.
Minimal(u32),
/// The proof is expected to have at least given size and grow by increasing number of trie nodes
/// included in the proof.
/// The proof is expected to have at least given size and grow by increasing number of trie
/// nodes included in the proof.
HasExtraNodes(u32),
/// The proof is expected to have at least given size and grow by increasing value that is stored
/// in the trie.
/// The proof is expected to have at least given size and grow by increasing value that is
/// stored in the trie.
HasLargeLeaf(u32),
}
@@ -91,7 +91,7 @@ pub struct MessageDeliveryProofParams<ThisChainAccountId> {
}
/// Trait that must be implemented by runtime.
pub trait Config<I: Instance>: crate::Config<I> {
pub trait Config<I: 'static>: crate::Config<I> {
/// Lane id to use in benchmarks.
fn bench_lane_id() -> LaneId {
Default::default()
@@ -123,7 +123,7 @@ pub trait Config<I: Instance>: crate::Config<I> {
fn is_message_dispatched(nonce: MessageNonce) -> bool;
}
benchmarks_instance! {
benchmarks_instance_pallet! {
//
// Benchmarks that are used directly by the runtime.
//
@@ -237,7 +237,9 @@ benchmarks_instance! {
// Benchmark `increase_message_fee` with following conditions:
// * message has maximal message;
// * submitter account is killed because its balance is less than ED after payment.
increase_message_fee {
//
// 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);
@@ -251,6 +253,25 @@ benchmarks_instance! {
assert_eq!(T::account_balance(&sender), 0.into());
}
// 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!(T::account_balance(&sender), 0.into());
}
// 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;
@@ -463,7 +484,7 @@ benchmarks_instance! {
//
// This is base benchmark for all other confirmations delivery benchmarks.
receive_delivery_proof_for_single_message {
let relayers_fund_id = crate::Pallet::<T, I>::relayer_fund_account_id();
let relayers_fund_id = crate::relayer_fund_account_id::<T::AccountId, T::AccountIdConverter>();
let relayer_id: T::AccountId = account("relayer", 0, SEED);
let relayer_balance = T::account_balance(&relayer_id);
T::endow_account(&relayers_fund_id);
@@ -503,7 +524,7 @@ benchmarks_instance! {
// as `weight(receive_delivery_proof_for_two_messages_by_single_relayer)
// - weight(receive_delivery_proof_for_single_message)`.
receive_delivery_proof_for_two_messages_by_single_relayer {
let relayers_fund_id = crate::Pallet::<T, I>::relayer_fund_account_id();
let relayers_fund_id = crate::relayer_fund_account_id::<T::AccountId, T::AccountIdConverter>();
let relayer_id: T::AccountId = account("relayer", 0, SEED);
let relayer_balance = T::account_balance(&relayer_id);
T::endow_account(&relayers_fund_id);
@@ -543,7 +564,7 @@ benchmarks_instance! {
// as `weight(receive_delivery_proof_for_two_messages_by_two_relayers)
// - weight(receive_delivery_proof_for_two_messages_by_single_relayer)`.
receive_delivery_proof_for_two_messages_by_two_relayers {
let relayers_fund_id = crate::Pallet::<T, I>::relayer_fund_account_id();
let relayers_fund_id = crate::relayer_fund_account_id::<T::AccountId, T::AccountIdConverter>();
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);
@@ -790,7 +811,7 @@ benchmarks_instance! {
.try_into()
.expect("Value of MaxUnrewardedRelayerEntriesAtInboundLane is too large");
let relayers_fund_id = crate::Pallet::<T, I>::relayer_fund_account_id();
let relayers_fund_id = crate::relayer_fund_account_id::<T::AccountId, T::AccountIdConverter>();
let relayer_id: T::AccountId = account("relayer", 0, SEED);
let relayer_balance = T::account_balance(&relayer_id);
T::endow_account(&relayers_fund_id);
@@ -833,7 +854,7 @@ benchmarks_instance! {
.try_into()
.expect("Value of MaxUnconfirmedMessagesAtInboundLane is too large ");
let relayers_fund_id = crate::Pallet::<T, I>::relayer_fund_account_id();
let relayers_fund_id = crate::relayer_fund_account_id::<T::AccountId, T::AccountIdConverter>();
let confirmation_relayer_id = account("relayer", 0, SEED);
let relayers: BTreeMap<T::AccountId, T::OutboundMessageFee> = (1..=i)
.map(|j| {
@@ -877,23 +898,17 @@ benchmarks_instance! {
}
}
fn send_regular_message<T: Config<I>, I: Instance>() {
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: MESSAGE_FEE.into(),
});
outbound_lane.send_message(MessageData { payload: vec![], fee: MESSAGE_FEE.into() });
}
fn send_regular_message_with_payload<T: Config<I>, I: Instance>(payload: Vec<u8>) {
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: MESSAGE_FEE.into(),
});
outbound_lane.send_message(MessageData { payload, fee: MESSAGE_FEE.into() });
}
fn confirm_message_delivery<T: Config<I>, I: Instance>(nonce: MessageNonce) {
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);
@@ -904,12 +919,12 @@ fn confirm_message_delivery<T: Config<I>, I: Instance>(nonce: MessageNonce) {
});
}
assert!(matches!(
outbound_lane.confirm_delivery(nonce, &relayers),
outbound_lane.confirm_delivery(nonce - latest_received_nonce, nonce, &relayers),
ReceivalConfirmationResult::ConfirmedMessages(_),
));
}
fn receive_messages<T: Config<I>, I: Instance>(nonce: MessageNonce) {
fn receive_messages<T: Config<I>, I: 'static>(nonce: MessageNonce) {
let mut inbound_lane_storage = inbound_lane_storage::<T, I>(T::bench_lane_id());
inbound_lane_storage.set_data(InboundLaneData {
relayers: vec![UnrewardedRelayer {
@@ -922,7 +937,10 @@ fn receive_messages<T: Config<I>, I: Instance>(nonce: MessageNonce) {
});
}
fn ensure_relayer_rewarded<T: Config<I>, I: Instance>(relayer_id: &T::AccountId, old_balance: &T::OutboundMessageFee) {
fn ensure_relayer_rewarded<T: Config<I>, I: 'static>(
relayer_id: &T::AccountId,
old_balance: &T::OutboundMessageFee,
) {
let new_balance = T::account_balance(relayer_id);
assert!(
new_balance > *old_balance,
@@ -18,7 +18,8 @@
use bp_messages::{
target_chain::{DispatchMessage, DispatchMessageData, MessageDispatch},
DeliveredMessages, InboundLaneData, LaneId, MessageKey, MessageNonce, OutboundLaneData, UnrewardedRelayer,
DeliveredMessages, InboundLaneData, LaneId, MessageKey, MessageNonce, OutboundLaneData,
UnrewardedRelayer,
};
use bp_runtime::messages::MessageDispatchResult;
use frame_support::RuntimeDebug;
@@ -53,7 +54,7 @@ pub enum ReceivalResult {
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.
/// There are too many unrewarded relayer entries at the lane.
TooManyUnrewardedRelayers,
/// There are too many unconfirmed messages at the lane.
TooManyUnconfirmedMessages,
@@ -71,16 +72,19 @@ impl<S: InboundLaneStorage> InboundLane<S> {
}
/// Receive state of the corresponding outbound lane.
pub fn receive_state_update(&mut self, outbound_lane_data: OutboundLaneData) -> Option<MessageNonce> {
pub fn receive_state_update(
&mut self,
outbound_lane_data: OutboundLaneData,
) -> Option<MessageNonce> {
let mut data = self.storage.data();
let last_delivered_nonce = data.last_delivered_nonce();
if outbound_lane_data.latest_received_nonce > last_delivered_nonce {
// this is something that should never happen if proofs are correct
return None;
return None
}
if outbound_lane_data.latest_received_nonce <= data.last_confirmed_nonce {
return None;
return None
}
let new_confirmed_nonce = outbound_lane_data.latest_received_nonce;
@@ -95,7 +99,8 @@ impl<S: InboundLaneStorage> InboundLane<S> {
data.relayers.pop_front();
}
// Secondly, update the next record with lower nonce equal to new confirmed nonce if needed.
// Note: There will be max. 1 record to update as we don't allow messages from relayers to overlap.
// Note: There will be max. 1 record to update as we don't allow messages from relayers to
// overlap.
match data.relayers.front_mut() {
Some(entry) if entry.messages.begin < new_confirmed_nonce => {
entry.messages.dispatch_results = entry
@@ -103,8 +108,8 @@ impl<S: InboundLaneStorage> InboundLane<S> {
.dispatch_results
.split_off((new_confirmed_nonce + 1 - entry.messages.begin) as _);
entry.messages.begin = new_confirmed_nonce + 1;
}
_ => {}
},
_ => {},
}
self.storage.set_data(data);
@@ -122,30 +127,25 @@ impl<S: InboundLaneStorage> InboundLane<S> {
let mut data = self.storage.data();
let is_correct_message = nonce == data.last_delivered_nonce() + 1;
if !is_correct_message {
return ReceivalResult::InvalidNonce;
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 ReceivalResult::TooManyUnrewardedRelayers;
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 ReceivalResult::TooManyUnconfirmedMessages;
return ReceivalResult::TooManyUnconfirmedMessages
}
// dispatch message before updating anything in the storage. If dispatch would panic,
// (which should not happen in the runtime) then we simply won't consider message as
// delivered (no changes to the inbound lane storage have been made).
// then, dispatch message
let dispatch_result = P::dispatch(
relayer_at_this_chain,
DispatchMessage {
key: MessageKey {
lane_id: self.storage.id(),
nonce,
},
key: MessageKey { lane_id: self.storage.id(), nonce },
data: message_data,
},
);
@@ -155,7 +155,7 @@ impl<S: InboundLaneStorage> InboundLane<S> {
Some(entry) if entry.relayer == *relayer_at_bridged_chain => {
entry.messages.note_dispatched_message(dispatch_result.dispatch_result);
false
}
},
_ => true,
};
if push_new {
@@ -176,14 +176,15 @@ 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, message_data, run_test, unrewarded_relayer, TestMessageDispatch,
TestRuntime, REGULAR_PAYLOAD, TEST_LANE_ID, TEST_RELAYER_A, TEST_RELAYER_B,
TEST_RELAYER_C,
},
DefaultInstance, RuntimeInboundLaneStorage,
RuntimeInboundLaneStorage,
};
fn receive_regular_message(
lane: &mut InboundLane<RuntimeInboundLaneStorage<TestRuntime, DefaultInstance>>,
lane: &mut InboundLane<RuntimeInboundLaneStorage<TestRuntime, ()>>,
nonce: MessageNonce,
) {
assert_eq!(
@@ -286,16 +287,10 @@ mod tests {
let mut seed_storage_data = lane.storage.data();
// Prepare data
seed_storage_data.last_confirmed_nonce = 0;
seed_storage_data
.relayers
.push_back(unrewarded_relayer(1, 1, TEST_RELAYER_A));
seed_storage_data.relayers.push_back(unrewarded_relayer(1, 1, TEST_RELAYER_A));
// Simulate messages batch (2, 3, 4) from relayer #2
seed_storage_data
.relayers
.push_back(unrewarded_relayer(2, 4, TEST_RELAYER_B));
seed_storage_data
.relayers
.push_back(unrewarded_relayer(5, 5, TEST_RELAYER_C));
seed_storage_data.relayers.push_back(unrewarded_relayer(2, 4, TEST_RELAYER_B));
seed_storage_data.relayers.push_back(unrewarded_relayer(5, 5, TEST_RELAYER_C));
lane.storage.set_data(seed_storage_data);
// Check
assert_eq!(
@@ -337,7 +332,8 @@ mod tests {
fn fails_to_receive_messages_above_unrewarded_relayer_entries_limit_per_lane() {
run_test(|| {
let mut lane = inbound_lane::<TestRuntime, _>(TEST_LANE_ID);
let max_nonce = <TestRuntime as crate::Config>::MaxUnrewardedRelayerEntriesAtInboundLane::get();
let max_nonce =
<TestRuntime as crate::Config>::MaxUnrewardedRelayerEntriesAtInboundLane::get();
for current_nonce in 1..max_nonce + 1 {
assert_eq!(
lane.receive_message::<TestMessageDispatch, _>(
@@ -376,7 +372,8 @@ mod tests {
fn fails_to_receive_messages_above_unconfirmed_messages_limit_per_lane() {
run_test(|| {
let mut lane = inbound_lane::<TestRuntime, _>(TEST_LANE_ID);
let max_nonce = <TestRuntime as crate::Config>::MaxUnconfirmedMessagesAtInboundLane::get();
let max_nonce =
<TestRuntime as crate::Config>::MaxUnconfirmedMessagesAtInboundLane::get();
for current_nonce in 1..=max_nonce {
assert_eq!(
lane.receive_message::<TestMessageDispatch, _>(
@@ -19,58 +19,57 @@
//! The payment is first transferred to a special `relayers-fund` account and only transferred
//! to the actual relayer in case confirmation is received.
use crate::OutboundMessages;
use bp_messages::{
source_chain::{MessageDeliveryAndDispatchPayment, RelayersRewards, Sender},
MessageNonce,
LaneId, MessageKey, MessageNonce, UnrewardedRelayer,
};
use codec::Encode;
use frame_support::traits::{Currency as CurrencyT, ExistenceRequirement, Get};
use num_traits::Zero;
use num_traits::{SaturatingAdd, Zero};
use sp_runtime::traits::Saturating;
use sp_std::fmt::Debug;
use sp_std::{collections::vec_deque::VecDeque, fmt::Debug, ops::RangeInclusive};
/// Instant message payments made in given currency.
///
/// The balance is initally reserved in a special `relayers-fund` account, and transferred
/// The balance is initially reserved in a special `relayers-fund` account, and transferred
/// to the relayer when message delivery is confirmed.
///
/// Additionaly, confirmation transaction submitter (`confirmation_relayer`) is reimbursed
/// Additionally, confirmation transaction submitter (`confirmation_relayer`) is reimbursed
/// with the confirmation rewards (part of message fee, reserved to pay for delivery confirmation).
///
/// NOTE The `relayers-fund` account must always exist i.e. be over Existential Deposit (ED; the
/// pallet enforces that) to make sure that even if the message cost is below ED it is still payed
/// pallet enforces that) to make sure that even if the message cost is below ED it is still paid
/// to the relayer account.
/// NOTE It's within relayer's interest to keep their balance above ED as well, to make sure they
/// can receive the payment.
pub struct InstantCurrencyPayments<T, Currency, GetConfirmationFee, RootAccount> {
_phantom: sp_std::marker::PhantomData<(T, Currency, GetConfirmationFee, RootAccount)>,
pub struct InstantCurrencyPayments<T, I, Currency, GetConfirmationFee, RootAccount> {
_phantom: sp_std::marker::PhantomData<(T, I, Currency, GetConfirmationFee, RootAccount)>,
}
impl<T, Currency, GetConfirmationFee, RootAccount> MessageDeliveryAndDispatchPayment<T::AccountId, Currency::Balance>
for InstantCurrencyPayments<T, Currency, GetConfirmationFee, RootAccount>
impl<T, I, Currency, GetConfirmationFee, RootAccount>
MessageDeliveryAndDispatchPayment<T::AccountId, Currency::Balance>
for InstantCurrencyPayments<T, I, Currency, GetConfirmationFee, RootAccount>
where
T: frame_system::Config,
Currency: CurrencyT<T::AccountId>,
T: frame_system::Config + crate::Config<I>,
I: 'static,
Currency: CurrencyT<T::AccountId, Balance = T::OutboundMessageFee>,
Currency::Balance: From<MessageNonce>,
GetConfirmationFee: Get<Currency::Balance>,
RootAccount: Get<Option<T::AccountId>>,
{
type Error = &'static str;
fn initialize(relayer_fund_account: &T::AccountId) -> usize {
assert!(
frame_system::Pallet::<T>::account_exists(relayer_fund_account),
"The relayer fund account ({:?}) must exist for the message lanes pallet to work correctly.",
relayer_fund_account,
);
1
}
fn pay_delivery_and_dispatch_fee(
submitter: &Sender<T::AccountId>,
fee: &Currency::Balance,
relayer_fund_account: &T::AccountId,
) -> Result<(), Self::Error> {
if !frame_system::Pallet::<T>::account_exists(relayer_fund_account) {
return Err("The relayer fund account must exist for the message lanes pallet to work correctly.");
}
let root_account = RootAccount::get();
let account = match submitter {
Sender::Signed(submitter) => submitter,
@@ -90,19 +89,55 @@ where
}
fn pay_relayers_rewards(
lane_id: LaneId,
messages_relayers: VecDeque<UnrewardedRelayer<T::AccountId>>,
confirmation_relayer: &T::AccountId,
relayers_rewards: RelayersRewards<T::AccountId, Currency::Balance>,
received_range: &RangeInclusive<MessageNonce>,
relayer_fund_account: &T::AccountId,
) {
pay_relayers_rewards::<Currency, _>(
confirmation_relayer,
relayers_rewards,
relayer_fund_account,
GetConfirmationFee::get(),
);
let relayers_rewards =
cal_relayers_rewards::<T, I>(lane_id, messages_relayers, received_range);
if !relayers_rewards.is_empty() {
pay_relayers_rewards::<Currency, _>(
confirmation_relayer,
relayers_rewards,
relayer_fund_account,
GetConfirmationFee::get(),
);
}
}
}
/// Calculate the relayers rewards
pub(crate) fn cal_relayers_rewards<T, I>(
lane_id: LaneId,
messages_relayers: VecDeque<UnrewardedRelayer<T::AccountId>>,
received_range: &RangeInclusive<MessageNonce>,
) -> RelayersRewards<T::AccountId, T::OutboundMessageFee>
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();
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 + 1 {
let message_data = OutboundMessages::<T, I>::get(MessageKey { lane_id, nonce })
.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;
}
}
relayers_rewards
}
/// Pay rewards to given relayers, optionally rewarding confirmation relayer.
fn pay_relayers_rewards<Currency, AccountId>(
confirmation_relayer: &AccountId,
@@ -123,26 +158,31 @@ fn pay_relayers_rewards<Currency, AccountId>(
// If delivery confirmation is submitted by other relayer, let's deduct confirmation fee
// from relayer reward.
//
// If confirmation fee has been increased (or if it was the only component of message fee),
// then messages relayer may receive zero reward.
// If confirmation fee has been increased (or if it was the only component of message
// fee), then messages relayer may receive zero reward.
let mut confirmation_reward = confirmation_fee.saturating_mul(reward.messages.into());
if confirmation_reward > relayer_reward {
confirmation_reward = relayer_reward;
}
relayer_reward = relayer_reward.saturating_sub(confirmation_reward);
confirmation_relayer_reward = confirmation_relayer_reward.saturating_add(confirmation_reward);
confirmation_relayer_reward =
confirmation_relayer_reward.saturating_add(confirmation_reward);
} else {
// If delivery confirmation is submitted by this relayer, let's add confirmation fee
// from other relayers to this relayer reward.
confirmation_relayer_reward = confirmation_relayer_reward.saturating_add(reward.reward);
continue;
continue
}
pay_relayer_reward::<Currency, _>(relayer_fund_account, &relayer, relayer_reward);
}
// finally - pay reward to confirmation relayer
pay_relayer_reward::<Currency, _>(relayer_fund_account, confirmation_relayer, confirmation_relayer_reward);
pay_relayer_reward::<Currency, _>(
relayer_fund_account,
confirmation_relayer,
confirmation_relayer_reward,
);
}
/// Transfer funds from relayers fund account to given relayer.
@@ -155,7 +195,7 @@ fn pay_relayer_reward<Currency, AccountId>(
Currency: CurrencyT<AccountId>,
{
if reward.is_zero() {
return;
return
}
let pay_result = Currency::transfer(
@@ -198,20 +238,8 @@ mod tests {
fn relayers_rewards() -> RelayersRewards<TestAccountId, TestBalance> {
vec![
(
RELAYER_1,
RelayerRewards {
reward: 100,
messages: 2,
},
),
(
RELAYER_2,
RelayerRewards {
reward: 100,
messages: 3,
},
),
(RELAYER_1, RelayerRewards { reward: 100, messages: 2 }),
(RELAYER_2, RelayerRewards { reward: 100, messages: 3 }),
]
.into_iter()
.collect()
@@ -220,7 +248,12 @@ mod tests {
#[test]
fn confirmation_relayer_is_rewarded_if_it_has_also_delivered_messages() {
run_test(|| {
pay_relayers_rewards::<Balances, _>(&RELAYER_2, relayers_rewards(), &RELAYERS_FUND_ACCOUNT, 10);
pay_relayers_rewards::<Balances, _>(
&RELAYER_2,
relayers_rewards(),
&RELAYERS_FUND_ACCOUNT,
10,
);
assert_eq!(Balances::free_balance(&RELAYER_1), 80);
assert_eq!(Balances::free_balance(&RELAYER_2), 120);
@@ -230,7 +263,12 @@ mod tests {
#[test]
fn confirmation_relayer_is_rewarded_if_it_has_not_delivered_any_delivered_messages() {
run_test(|| {
pay_relayers_rewards::<Balances, _>(&RELAYER_3, relayers_rewards(), &RELAYERS_FUND_ACCOUNT, 10);
pay_relayers_rewards::<Balances, _>(
&RELAYER_3,
relayers_rewards(),
&RELAYERS_FUND_ACCOUNT,
10,
);
assert_eq!(Balances::free_balance(&RELAYER_1), 80);
assert_eq!(Balances::free_balance(&RELAYER_2), 70);
@@ -241,7 +279,12 @@ mod tests {
#[test]
fn only_confirmation_relayer_is_rewarded_if_confirmation_fee_has_significantly_increased() {
run_test(|| {
pay_relayers_rewards::<Balances, _>(&RELAYER_3, relayers_rewards(), &RELAYERS_FUND_ACCOUNT, 1000);
pay_relayers_rewards::<Balances, _>(
&RELAYER_3,
relayers_rewards(),
&RELAYERS_FUND_ACCOUNT,
1000,
);
assert_eq!(Balances::free_balance(&RELAYER_1), 0);
assert_eq!(Balances::free_balance(&RELAYER_2), 0);
File diff suppressed because it is too large Load Diff
+103 -59
View File
@@ -17,21 +17,26 @@
// From construct_runtime macro
#![allow(clippy::from_over_into)]
use crate::Config;
use crate::{instant_payments::cal_relayers_rewards, Config};
use bitvec::prelude::*;
use bp_messages::{
source_chain::{
LaneMessageVerifier, MessageDeliveryAndDispatchPayment, OnDeliveryConfirmed, RelayersRewards, Sender,
TargetHeaderChain,
LaneMessageVerifier, MessageDeliveryAndDispatchPayment, OnDeliveryConfirmed,
OnMessageAccepted, Sender, TargetHeaderChain,
},
target_chain::{DispatchMessage, MessageDispatch, ProvedLaneMessages, ProvedMessages, SourceHeaderChain},
DeliveredMessages, InboundLaneData, LaneId, Message, MessageData, MessageKey, MessageNonce, OutboundLaneData,
Parameter as MessagesParameter, UnrewardedRelayer,
target_chain::{
DispatchMessage, MessageDispatch, ProvedLaneMessages, ProvedMessages, SourceHeaderChain,
},
DeliveredMessages, InboundLaneData, LaneId, Message, MessageData, MessageKey, MessageNonce,
OutboundLaneData, Parameter as MessagesParameter, UnrewardedRelayer,
};
use bp_runtime::{messages::MessageDispatchResult, Size};
use codec::{Decode, Encode};
use frame_support::{parameter_types, weights::Weight};
use frame_support::{
parameter_types,
weights::{RuntimeDbWeight, Weight},
};
use scale_info::TypeInfo;
use sp_core::H256;
use sp_runtime::{
@@ -39,7 +44,10 @@ use sp_runtime::{
traits::{BlakeTwo256, IdentityLookup},
FixedU128, Perbill,
};
use std::collections::BTreeMap;
use std::{
collections::{BTreeMap, VecDeque},
ops::RangeInclusive,
};
pub type AccountId = u64;
pub type Balance = u64;
@@ -51,9 +59,11 @@ pub struct TestPayload {
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.
/// 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,
/// Extra bytes that affect payload size.
pub extra: Vec<u8>,
}
pub type TestMessageFee = u64;
pub type TestRelayer = u64;
@@ -88,6 +98,7 @@ parameter_types! {
pub const MaximumBlockWeight: Weight = 1024;
pub const MaximumBlockLength: u32 = 2 * 1024;
pub const AvailableBlockRatio: Perbill = Perbill::one();
pub const DbWeight: RuntimeDbWeight = RuntimeDbWeight { read: 1, write: 2 };
}
impl frame_system::Config for TestRuntime {
@@ -111,7 +122,7 @@ impl frame_system::Config for TestRuntime {
type SystemWeightInfo = ();
type BlockWeights = ();
type BlockLength = ();
type DbWeight = ();
type DbWeight = DbWeight;
type SS58Prefix = ();
type OnSetCode = ();
}
@@ -137,6 +148,7 @@ parameter_types! {
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)]
@@ -147,7 +159,8 @@ pub enum TestMessagesParameter {
impl MessagesParameter for TestMessagesParameter {
fn save(&self) {
match *self {
TestMessagesParameter::TokenConversionRate(conversion_rate) => TokenConversionRate::set(&conversion_rate),
TestMessagesParameter::TokenConversionRate(conversion_rate) =>
TokenConversionRate::set(&conversion_rate),
}
}
}
@@ -172,15 +185,17 @@ impl Config for TestRuntime {
type TargetHeaderChain = TestTargetHeaderChain;
type LaneMessageVerifier = TestLaneMessageVerifier;
type MessageDeliveryAndDispatchPayment = TestMessageDeliveryAndDispatchPayment;
type OnMessageAccepted = TestOnMessageAccepted;
type OnDeliveryConfirmed = (TestOnDeliveryConfirmed1, TestOnDeliveryConfirmed2);
type SourceHeaderChain = TestSourceHeaderChain;
type MessageDispatch = TestMessageDispatch;
type BridgedChainId = TestBridgedChainId;
}
impl Size for TestPayload {
fn size_hint(&self) -> u32 {
16
16 + self.extra.len() as u32
}
}
@@ -227,14 +242,12 @@ impl From<Result<Vec<Message<TestMessageFee>>, ()>> for TestMessagesProof {
fn from(result: Result<Vec<Message<TestMessageFee>>, ()>) -> 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<TestMessageFee>>,
> = BTreeMap::new();
for message in messages {
messages_by_lane
.entry(message.key.lane_id)
.or_default()
.messages
.push(message);
messages_by_lane.entry(message.key.lane_id).or_default().messages.push(message);
}
messages_by_lane.into_iter().collect()
}),
@@ -310,7 +323,8 @@ impl TestMessageDeliveryAndDispatchPayment {
/// Returns true if given fee has been paid by given submitter.
pub fn is_fee_paid(submitter: AccountId, fee: TestMessageFee) -> bool {
frame_support::storage::unhashed::get(b":message-fee:") == Some((Sender::Signed(submitter), fee))
frame_support::storage::unhashed::get(b":message-fee:") ==
Some((Sender::Signed(submitter), fee))
}
/// Returns true if given relayer has been rewarded with given balance. The reward-paid flag is
@@ -321,7 +335,9 @@ impl TestMessageDeliveryAndDispatchPayment {
}
}
impl MessageDeliveryAndDispatchPayment<AccountId, TestMessageFee> for TestMessageDeliveryAndDispatchPayment {
impl MessageDeliveryAndDispatchPayment<AccountId, TestMessageFee>
for TestMessageDeliveryAndDispatchPayment
{
type Error = &'static str;
fn pay_delivery_and_dispatch_fee(
@@ -330,7 +346,7 @@ impl MessageDeliveryAndDispatchPayment<AccountId, TestMessageFee> for TestMessag
_relayer_fund_account: &AccountId,
) -> Result<(), Self::Error> {
if frame_support::storage::unhashed::get(b":reject-message-fee:") == Some(true) {
return Err(TEST_ERROR);
return Err(TEST_ERROR)
}
frame_support::storage::unhashed::put(b":message-fee:", &(submitter, fee));
@@ -338,17 +354,51 @@ impl MessageDeliveryAndDispatchPayment<AccountId, TestMessageFee> for TestMessag
}
fn pay_relayers_rewards(
lane_id: LaneId,
message_relayers: VecDeque<UnrewardedRelayer<AccountId>>,
_confirmation_relayer: &AccountId,
relayers_rewards: RelayersRewards<AccountId, TestMessageFee>,
received_range: &RangeInclusive<MessageNonce>,
_relayer_fund_account: &AccountId,
) {
for (relayer, reward) in relayers_rewards {
let relayers_rewards =
cal_relayers_rewards::<TestRuntime, ()>(lane_id, message_relayers, received_range);
for (relayer, reward) in &relayers_rewards {
let key = (b":relayer-reward:", relayer, reward.reward).encode();
frame_support::storage::unhashed::put(&key, &true);
}
}
}
#[derive(Debug)]
pub struct TestOnMessageAccepted;
impl TestOnMessageAccepted {
/// Verify that the callback has been called when the message is accepted.
pub fn ensure_called(lane: &LaneId, message: &MessageNonce) {
let key = (b"TestOnMessageAccepted", lane, message).encode();
assert_eq!(frame_support::storage::unhashed::get(&key), Some(true));
}
/// Set consumed weight returned by the callback.
pub fn set_consumed_weight_per_message(weight: Weight) {
frame_support::storage::unhashed::put(b"TestOnMessageAccepted_Weight", &weight);
}
/// Get consumed weight returned by the callback.
pub fn get_consumed_weight_per_message() -> Option<Weight> {
frame_support::storage::unhashed::get(b"TestOnMessageAccepted_Weight")
}
}
impl OnMessageAccepted for TestOnMessageAccepted {
fn on_messages_accepted(lane: &LaneId, message: &MessageNonce) -> Weight {
let key = (b"TestOnMessageAccepted", lane, message).encode();
frame_support::storage::unhashed::put(&key, &true);
Self::get_consumed_weight_per_message()
.unwrap_or_else(|| DbWeight::get().reads_writes(1, 1))
}
}
/// First on-messages-delivered callback.
#[derive(Debug)]
pub struct TestOnDeliveryConfirmed1;
@@ -359,16 +409,29 @@ impl TestOnDeliveryConfirmed1 {
let key = (b"TestOnDeliveryConfirmed1", lane, messages).encode();
assert_eq!(frame_support::storage::unhashed::get(&key), Some(true));
}
}
impl OnDeliveryConfirmed for TestOnDeliveryConfirmed1 {
fn on_messages_delivered(lane: &LaneId, messages: &DeliveredMessages) {
let key = (b"TestOnDeliveryConfirmed1", lane, messages).encode();
frame_support::storage::unhashed::put(&key, &true);
/// Set consumed weight returned by the callback.
pub fn set_consumed_weight_per_message(weight: Weight) {
frame_support::storage::unhashed::put(b"TestOnDeliveryConfirmed1_Weight", &weight);
}
/// Get consumed weight returned by the callback.
pub fn get_consumed_weight_per_message() -> Option<Weight> {
frame_support::storage::unhashed::get(b"TestOnDeliveryConfirmed1_Weight")
}
}
/// Seconde on-messages-delivered callback.
impl OnDeliveryConfirmed for TestOnDeliveryConfirmed1 {
fn on_messages_delivered(lane: &LaneId, messages: &DeliveredMessages) -> Weight {
let key = (b"TestOnDeliveryConfirmed1", lane, messages).encode();
frame_support::storage::unhashed::put(&key, &true);
Self::get_consumed_weight_per_message()
.unwrap_or_else(|| DbWeight::get().reads_writes(1, 1))
.saturating_mul(messages.total_messages())
}
}
/// Second on-messages-delivered callback.
#[derive(Debug)]
pub struct TestOnDeliveryConfirmed2;
@@ -381,9 +444,10 @@ impl TestOnDeliveryConfirmed2 {
}
impl OnDeliveryConfirmed for TestOnDeliveryConfirmed2 {
fn on_messages_delivered(lane: &LaneId, messages: &DeliveredMessages) {
fn on_messages_delivered(lane: &LaneId, messages: &DeliveredMessages) -> Weight {
let key = (b"TestOnDeliveryConfirmed2", lane, messages).encode();
frame_support::storage::unhashed::put(&key, &true);
0
}
}
@@ -400,10 +464,7 @@ impl SourceHeaderChain<TestMessageFee> for TestSourceHeaderChain {
proof: Self::MessagesProof,
_messages_count: u32,
) -> Result<ProvedMessages<Message<TestMessageFee>>, Self::Error> {
proof
.result
.map(|proof| proof.into_iter().collect())
.map_err(|_| TEST_ERROR)
proof.result.map(|proof| proof.into_iter().collect()).map_err(|_| TEST_ERROR)
}
}
@@ -434,30 +495,17 @@ 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),
}
Message { key: MessageKey { lane_id: TEST_LANE_ID, nonce }, data: message_data(payload) }
}
/// 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),
}
TestPayload { id, 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,
}
MessageData { payload: payload.encode(), fee: 1 }
}
/// Returns message dispatch result with given unspent weight.
@@ -491,14 +539,10 @@ pub fn unrewarded_relayer(
/// Run pallet test.
pub fn run_test<T>(test: impl FnOnce() -> T) -> T {
let mut t = frame_system::GenesisConfig::default()
.build_storage::<TestRuntime>()
let mut t = frame_system::GenesisConfig::default().build_storage::<TestRuntime>().unwrap();
pallet_balances::GenesisConfig::<TestRuntime> { balances: vec![(ENDOWED_ACCOUNT, 1_000_000)] }
.assimilate_storage(&mut t)
.unwrap();
pallet_balances::GenesisConfig::<TestRuntime> {
balances: vec![(ENDOWED_ACCOUNT, 1_000_000)],
}
.assimilate_storage(&mut t)
.unwrap();
let mut ext = sp_io::TestExternalities::new(t);
ext.execute_with(test)
}
@@ -18,7 +18,8 @@
use bitvec::prelude::*;
use bp_messages::{
DeliveredMessages, DispatchResultsBitVec, LaneId, MessageData, MessageNonce, OutboundLaneData, UnrewardedRelayer,
DeliveredMessages, DispatchResultsBitVec, LaneId, MessageData, MessageNonce, OutboundLaneData,
UnrewardedRelayer,
};
use frame_support::RuntimeDebug;
use sp_std::collections::vec_deque::VecDeque;
@@ -49,7 +50,7 @@ pub enum ReceivalConfirmationResult {
/// New messages have been confirmed by the confirmation transaction.
ConfirmedMessages(DeliveredMessages),
/// Confirmation transaction brings no new confirmation. This may be a result of relayer
/// error or several relayers runnng.
/// error or several relayers running.
NoNewConfirmations,
/// Bridged chain is trying to confirm more messages than we have generated. May be a result
/// of invalid bridged chain storage.
@@ -57,12 +58,14 @@ pub enum ReceivalConfirmationResult {
/// The unrewarded relayers vec contains an empty entry. May be a result of invalid bridged
/// chain storage.
EmptyUnrewardedRelayerEntry,
/// The unrewarded relayers vec contains non-consecutive entries. May be a result of invalid bridged
/// chain storage.
/// The unrewarded relayers vec contains non-consecutive entries. May be a result of invalid
/// bridged chain storage.
NonConsecutiveUnrewardedRelayerEntries,
/// The unrewarded relayers vec contains entry with mismatched number of dispatch results. May be
/// a result of invalid bridged chain storage.
/// The unrewarded relayers vec contains entry with mismatched number of dispatch results. May
/// be a result of invalid bridged chain storage.
InvalidNumberOfDispatchResults,
/// The chain has more messages that need to be confirmed than there is in the proof.
TryingToConfirmMoreMessagesThanExpected(MessageNonce),
}
/// Outbound messages lane.
@@ -98,30 +101,44 @@ impl<S: OutboundLaneStorage> OutboundLane<S> {
/// Confirm messages delivery.
pub fn confirm_delivery<RelayerId>(
&mut self,
latest_received_nonce: MessageNonce,
max_allowed_messages: MessageNonce,
latest_delivered_nonce: MessageNonce,
relayers: &VecDeque<UnrewardedRelayer<RelayerId>>,
) -> ReceivalConfirmationResult {
let mut data = self.storage.data();
if latest_received_nonce <= data.latest_received_nonce {
return ReceivalConfirmationResult::NoNewConfirmations;
if latest_delivered_nonce <= data.latest_received_nonce {
return ReceivalConfirmationResult::NoNewConfirmations
}
if latest_received_nonce > data.latest_generated_nonce {
return ReceivalConfirmationResult::FailedToConfirmFutureMessages;
if latest_delivered_nonce > data.latest_generated_nonce {
return ReceivalConfirmationResult::FailedToConfirmFutureMessages
}
if latest_delivered_nonce - data.latest_received_nonce > max_allowed_messages {
// that the relayer has declared correct number of messages that the proof contains (it
// is checked outside of the function). But it may happen (but only if this/bridged
// chain storage is corrupted, though) that the actual number of confirmed messages if
// larger than declared. This would mean that 'reward loop' will take more time than the
// weight formula accounts, so we can't allow that.
return ReceivalConfirmationResult::TryingToConfirmMoreMessagesThanExpected(
latest_delivered_nonce - data.latest_received_nonce,
)
}
let dispatch_results =
match extract_dispatch_results(data.latest_received_nonce, latest_received_nonce, relayers) {
Ok(dispatch_results) => dispatch_results,
Err(extract_error) => return extract_error,
};
let dispatch_results = match extract_dispatch_results(
data.latest_received_nonce,
latest_delivered_nonce,
relayers,
) {
Ok(dispatch_results) => dispatch_results,
Err(extract_error) => return extract_error,
};
let prev_latest_received_nonce = data.latest_received_nonce;
data.latest_received_nonce = latest_received_nonce;
data.latest_received_nonce = latest_delivered_nonce;
self.storage.set_data(data);
ReceivalConfirmationResult::ConfirmedMessages(DeliveredMessages {
begin: prev_latest_received_nonce + 1,
end: latest_received_nonce,
end: latest_delivered_nonce,
dispatch_results,
})
}
@@ -133,7 +150,9 @@ impl<S: OutboundLaneStorage> OutboundLane<S> {
let mut pruned_messages = 0;
let mut anything_changed = false;
let mut data = self.storage.data();
while pruned_messages < max_messages_to_prune && data.oldest_unpruned_nonce <= data.latest_received_nonce {
while pruned_messages < max_messages_to_prune &&
data.oldest_unpruned_nonce <= data.latest_received_nonce
{
self.storage.remove_message(&data.oldest_unpruned_nonce);
anything_changed = true;
@@ -158,9 +177,10 @@ fn extract_dispatch_results<RelayerId>(
latest_received_nonce: MessageNonce,
relayers: &VecDeque<UnrewardedRelayer<RelayerId>>,
) -> Result<DispatchResultsBitVec, ReceivalConfirmationResult> {
// the only caller of this functions checks that the prev_latest_received_nonce..=latest_received_nonce
// is valid, so we're ready to accept messages in this range
// => with_capacity call must succeed here or we'll be unable to receive confirmations at all
// the only caller of this functions checks that the
// prev_latest_received_nonce..=latest_received_nonce is valid, so we're ready to accept
// messages in this range => with_capacity call must succeed here or we'll be unable to receive
// confirmations at all
let mut received_dispatch_result =
BitVec::with_capacity((latest_received_nonce - prev_latest_received_nonce + 1) as _);
let mut last_entry_end: Option<MessageNonce> = None;
@@ -168,43 +188,48 @@ fn extract_dispatch_results<RelayerId>(
// unrewarded relayer entry must have at least 1 unconfirmed message
// (guaranteed by the `InboundLane::receive_message()`)
if entry.messages.end < entry.messages.begin {
return Err(ReceivalConfirmationResult::EmptyUnrewardedRelayerEntry);
return Err(ReceivalConfirmationResult::EmptyUnrewardedRelayerEntry)
}
// every entry must confirm range of messages that follows previous entry range
// (guaranteed by the `InboundLane::receive_message()`)
if let Some(last_entry_end) = last_entry_end {
let expected_entry_begin = last_entry_end.checked_add(1);
if expected_entry_begin != Some(entry.messages.begin) {
return Err(ReceivalConfirmationResult::NonConsecutiveUnrewardedRelayerEntries);
return Err(ReceivalConfirmationResult::NonConsecutiveUnrewardedRelayerEntries)
}
}
last_entry_end = Some(entry.messages.end);
// entry can't confirm messages larger than `inbound_lane_data.latest_received_nonce()`
// (guaranteed by the `InboundLane::receive_message()`)
if entry.messages.end > latest_received_nonce {
// technically this will be detected in the next loop iteration as `InvalidNumberOfDispatchResults`
// but to guarantee safety of loop operations below this is detected now
return Err(ReceivalConfirmationResult::FailedToConfirmFutureMessages);
// technically this will be detected in the next loop iteration as
// `InvalidNumberOfDispatchResults` but to guarantee safety of loop operations below
// this is detected now
return Err(ReceivalConfirmationResult::FailedToConfirmFutureMessages)
}
// entry must have single dispatch result for every message
// (guaranteed by the `InboundLane::receive_message()`)
if entry.messages.dispatch_results.len() as MessageNonce != entry.messages.end - entry.messages.begin + 1 {
return Err(ReceivalConfirmationResult::InvalidNumberOfDispatchResults);
if entry.messages.dispatch_results.len() as MessageNonce !=
entry.messages.end - entry.messages.begin + 1
{
return Err(ReceivalConfirmationResult::InvalidNumberOfDispatchResults)
}
// now we know that the entry is valid
// => let's check if it brings new confirmations
let new_messages_begin = sp_std::cmp::max(entry.messages.begin, prev_latest_received_nonce + 1);
let new_messages_begin =
sp_std::cmp::max(entry.messages.begin, prev_latest_received_nonce + 1);
let new_messages_end = sp_std::cmp::min(entry.messages.end, latest_received_nonce);
let new_messages_range = new_messages_begin..=new_messages_end;
if new_messages_range.is_empty() {
continue;
continue
}
// now we know that entry brings new confirmations
// => let's extract dispatch results
received_dispatch_result.extend_from_bitslice(
&entry.messages.dispatch_results[(new_messages_begin - entry.messages.begin) as usize..],
&entry.messages.dispatch_results
[(new_messages_begin - entry.messages.begin) as usize..],
);
}
@@ -215,12 +240,17 @@ fn extract_dispatch_results<RelayerId>(
mod tests {
use super::*;
use crate::{
mock::{message_data, run_test, unrewarded_relayer, TestRelayer, TestRuntime, REGULAR_PAYLOAD, TEST_LANE_ID},
mock::{
message_data, run_test, unrewarded_relayer, TestRelayer, TestRuntime, REGULAR_PAYLOAD,
TEST_LANE_ID,
},
outbound_lane,
};
use sp_std::ops::RangeInclusive;
fn unrewarded_relayers(nonces: RangeInclusive<MessageNonce>) -> VecDeque<UnrewardedRelayer<TestRelayer>> {
fn unrewarded_relayers(
nonces: RangeInclusive<MessageNonce>,
) -> VecDeque<UnrewardedRelayer<TestRelayer>> {
vec![unrewarded_relayer(*nonces.start(), *nonces.end(), 0)]
.into_iter()
.collect()
@@ -245,7 +275,7 @@ mod tests {
lane.send_message(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(latest_received_nonce, relayers);
let result = lane.confirm_delivery(3, latest_received_nonce, relayers);
assert_eq!(lane.storage.data().latest_generated_nonce, 3);
assert_eq!(lane.storage.data().latest_received_nonce, 0);
result
@@ -273,7 +303,7 @@ mod tests {
assert_eq!(lane.storage.data().latest_generated_nonce, 3);
assert_eq!(lane.storage.data().latest_received_nonce, 0);
assert_eq!(
lane.confirm_delivery(3, &unrewarded_relayers(1..=3)),
lane.confirm_delivery(3, 3, &unrewarded_relayers(1..=3)),
ReceivalConfirmationResult::ConfirmedMessages(delivered_messages(1..=3)),
);
assert_eq!(lane.storage.data().latest_generated_nonce, 3);
@@ -291,18 +321,18 @@ mod tests {
assert_eq!(lane.storage.data().latest_generated_nonce, 3);
assert_eq!(lane.storage.data().latest_received_nonce, 0);
assert_eq!(
lane.confirm_delivery(3, &unrewarded_relayers(1..=3)),
lane.confirm_delivery(3, 3, &unrewarded_relayers(1..=3)),
ReceivalConfirmationResult::ConfirmedMessages(delivered_messages(1..=3)),
);
assert_eq!(
lane.confirm_delivery(3, &unrewarded_relayers(1..=3)),
lane.confirm_delivery(3, 3, &unrewarded_relayers(1..=3)),
ReceivalConfirmationResult::NoNewConfirmations,
);
assert_eq!(lane.storage.data().latest_generated_nonce, 3);
assert_eq!(lane.storage.data().latest_received_nonce, 3);
assert_eq!(
lane.confirm_delivery(2, &unrewarded_relayers(1..=1)),
lane.confirm_delivery(1, 2, &unrewarded_relayers(1..=1)),
ReceivalConfirmationResult::NoNewConfirmations,
);
assert_eq!(lane.storage.data().latest_generated_nonce, 3);
@@ -393,18 +423,40 @@ mod tests {
assert_eq!(lane.storage.data().oldest_unpruned_nonce, 1);
// after confirmation, some messages are received
assert_eq!(
lane.confirm_delivery(2, &unrewarded_relayers(1..=2)),
lane.confirm_delivery(2, 2, &unrewarded_relayers(1..=2)),
ReceivalConfirmationResult::ConfirmedMessages(delivered_messages(1..=2)),
);
assert_eq!(lane.prune_messages(100), 2);
assert_eq!(lane.storage.data().oldest_unpruned_nonce, 3);
// after last message is confirmed, everything is pruned
assert_eq!(
lane.confirm_delivery(3, &unrewarded_relayers(3..=3)),
lane.confirm_delivery(1, 3, &unrewarded_relayers(3..=3)),
ReceivalConfirmationResult::ConfirmedMessages(delivered_messages(3..=3)),
);
assert_eq!(lane.prune_messages(100), 1);
assert_eq!(lane.storage.data().oldest_unpruned_nonce, 4);
});
}
#[test]
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));
assert_eq!(
lane.confirm_delivery(0, 3, &unrewarded_relayers(1..=3)),
ReceivalConfirmationResult::TryingToConfirmMoreMessagesThanExpected(3),
);
assert_eq!(
lane.confirm_delivery(2, 3, &unrewarded_relayers(1..=3)),
ReceivalConfirmationResult::TryingToConfirmMoreMessagesThanExpected(3),
);
assert_eq!(
lane.confirm_delivery(3, 3, &unrewarded_relayers(1..=3)),
ReceivalConfirmationResult::ConfirmedMessages(delivered_messages(1..=3)),
);
});
}
}
@@ -14,7 +14,7 @@
// You should have received a copy of the GNU General Public License
// along with Parity Bridges Common. If not, see <http://www.gnu.org/licenses/>.
//! Autogenerated weights for pallet_bridge_messages
//! Autogenerated weights for `pallet_bridge_messages`
//!
//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 3.0.0
//! DATE: 2021-06-18, STEPS: [50, ], REPEAT: 20
@@ -46,12 +46,13 @@ use frame_support::{
};
use sp_std::marker::PhantomData;
/// Weight functions needed for pallet_bridge_messages.
/// 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 increase_message_fee() -> 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;
@@ -70,7 +71,7 @@ pub trait WeightInfo {
fn receive_delivery_proof_for_multiple_messages_by_multiple_relayers(i: u32) -> Weight;
}
/// Weights for pallet_bridge_messages using the Rialto node and recommended hardware.
/// Weights for `pallet_bridge_messages` using the Rialto node and recommended hardware.
pub struct RialtoWeight<T>(PhantomData<T>);
impl<T: frame_system::Config> WeightInfo for RialtoWeight<T> {
fn send_minimal_message_worst_case() -> Weight {
@@ -88,8 +89,14 @@ impl<T: frame_system::Config> WeightInfo for RialtoWeight<T> {
.saturating_add(T::DbWeight::get().reads(5 as Weight))
.saturating_add(T::DbWeight::get().writes(12 as Weight))
}
fn increase_message_fee() -> Weight {
(6_709_925_000 as Weight)
fn maximal_increase_message_fee() -> Weight {
(6_781_470_000 as Weight)
.saturating_add(T::DbWeight::get().reads(5 as Weight))
.saturating_add(T::DbWeight::get().writes(3 as Weight))
}
fn increase_message_fee(i: u32) -> Weight {
(114_963_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))
}
@@ -202,8 +209,14 @@ impl WeightInfo for () {
.saturating_add(RocksDbWeight::get().reads(5 as Weight))
.saturating_add(RocksDbWeight::get().writes(12 as Weight))
}
fn increase_message_fee() -> Weight {
(6_709_925_000 as Weight)
fn maximal_increase_message_fee() -> Weight {
(6_781_470_000 as Weight)
.saturating_add(RocksDbWeight::get().reads(5 as Weight))
.saturating_add(RocksDbWeight::get().writes(3 as Weight))
}
fn increase_message_fee(i: u32) -> Weight {
(114_963_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))
}
@@ -20,21 +20,27 @@ use crate::weights::WeightInfo;
use bp_messages::{MessageNonce, UnrewardedRelayersState};
use bp_runtime::{PreComputedSize, Size};
use frame_support::weights::Weight;
use frame_support::weights::{RuntimeDbWeight, Weight};
/// Size of the message being delivered in benchmarks.
pub const EXPECTED_DEFAULT_MESSAGE_LENGTH: u32 = 128;
/// We assume that size of signed extensions on all our chains and size of all 'small' arguments of calls
/// we're checking here would fit 1KB.
/// We assume that size of signed extensions on all our chains and size of all 'small' arguments of
/// calls we're checking here would fit 1KB.
const SIGNED_EXTENSIONS_SIZE: u32 = 1024;
/// Number of extra bytes (excluding size of storage value itself) of storage proof, built at
/// Rialto chain. This mostly depends on number of entries (and their density) in the storage trie.
/// Some reserve is reserved to account future chain growth.
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(), 0);
@@ -48,12 +54,15 @@ pub fn ensure_weights_are_correct<W: WeightInfoExt>(
// 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),
&PreComputedSize(
(EXPECTED_DEFAULT_MESSAGE_LENGTH + W::expected_extra_storage_proof_size()) as usize,
),
1,
0,
);
assert!(
actual_single_regular_message_delivery_tx_weight <= expected_default_message_delivery_tx_weight,
actual_single_regular_message_delivery_tx_weight <=
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,
@@ -82,9 +91,11 @@ pub fn ensure_weights_are_correct<W: WeightInfoExt>(
total_messages: 1,
..Default::default()
},
db_weight,
);
assert!(
actual_messages_delivery_confirmation_tx_weight <= expected_messages_delivery_confirmation_tx_weight,
actual_messages_delivery_confirmation_tx_weight <=
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,
@@ -108,7 +119,8 @@ pub fn ensure_able_to_receive_message<W: WeightInfoExt>(
max_incoming_message_dispatch_weight: Weight,
) {
// verify that we're able to receive proof of maximal-size message
let max_delivery_transaction_size = max_incoming_message_proof_size.saturating_add(SIGNED_EXTENSIONS_SIZE);
let max_delivery_transaction_size =
max_incoming_message_proof_size.saturating_add(SIGNED_EXTENSIONS_SIZE);
assert!(
max_delivery_transaction_size <= max_extrinsic_size,
"Size of maximal message delivery transaction {} + {} is larger than maximal possible transaction size {}",
@@ -119,7 +131,9 @@ pub fn ensure_able_to_receive_message<W: WeightInfoExt>(
// verify that we're able to receive proof of maximal-size message with maximal dispatch weight
let max_delivery_transaction_dispatch_weight = W::receive_messages_proof_weight(
&PreComputedSize((max_incoming_message_proof_size + W::expected_extra_storage_proof_size()) as usize),
&PreComputedSize(
(max_incoming_message_proof_size + W::expected_extra_storage_proof_size()) as usize,
),
1,
max_incoming_message_dispatch_weight,
);
@@ -138,6 +152,7 @@ pub fn ensure_able_to_receive_confirmation<W: WeightInfoExt>(
max_inbound_lane_data_proof_size_from_peer_chain: u32,
max_unrewarded_relayer_entries_at_peer_inbound_lane: MessageNonce,
max_unconfirmed_messages_at_inbound_lane: MessageNonce,
db_weight: RuntimeDbWeight,
) {
// verify that we're able to receive confirmation of maximal-size
let max_confirmation_transaction_size =
@@ -150,7 +165,8 @@ pub fn ensure_able_to_receive_confirmation<W: WeightInfoExt>(
max_extrinsic_size,
);
// verify that we're able to reward maximal number of relayers that have delivered maximal number of messages
// verify that we're able to reward maximal number of relayers that have delivered maximal
// number of messages
let max_confirmation_transaction_dispatch_weight = W::receive_messages_delivery_proof_weight(
&PreComputedSize(max_inbound_lane_data_proof_size_from_peer_chain as usize),
&UnrewardedRelayersState {
@@ -158,6 +174,7 @@ pub fn ensure_able_to_receive_confirmation<W: WeightInfoExt>(
total_messages: max_unconfirmed_messages_at_inbound_lane,
..Default::default()
},
db_weight,
);
assert!(
max_confirmation_transaction_dispatch_weight <= max_extrinsic_weight,
@@ -180,18 +197,26 @@ pub trait WeightInfoExt: WeightInfo {
// Functions that are directly mapped to extrinsics weights.
/// Weight of message send extrinsic.
fn send_message_weight(message: &impl Size) -> Weight {
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_hint());
let call_back_overhead = Self::single_message_callback_overhead(db_weight);
transaction_overhead.saturating_add(message_size_overhead)
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, messages_count: u32, dispatch_weight: Weight) -> Weight {
fn receive_messages_proof_weight(
proof: &impl Size,
messages_count: u32,
dispatch_weight: Weight,
) -> Weight {
// basic components of extrinsic weight
let transaction_overhead = Self::receive_messages_proof_overhead();
let outbound_state_delivery_weight = Self::receive_messages_proof_outbound_lane_state_overhead();
let outbound_state_delivery_weight =
Self::receive_messages_proof_outbound_lane_state_overhead();
let messages_delivery_weight =
Self::receive_messages_proof_messages_overhead(MessageNonce::from(messages_count));
let messages_dispatch_weight = dispatch_weight;
@@ -201,8 +226,9 @@ pub trait WeightInfoExt: WeightInfo {
.saturating_mul(messages_count.saturating_sub(1))
.saturating_add(Self::expected_extra_storage_proof_size());
let actual_proof_size = proof.size_hint();
let proof_size_overhead =
Self::storage_proof_size_overhead(actual_proof_size.saturating_sub(expected_proof_size));
let proof_size_overhead = Self::storage_proof_size_overhead(
actual_proof_size.saturating_sub(expected_proof_size),
);
transaction_overhead
.saturating_add(outbound_state_delivery_weight)
@@ -212,23 +238,37 @@ pub trait WeightInfoExt: WeightInfo {
}
/// Weight of confirmation delivery extrinsic.
fn receive_messages_delivery_proof_weight(proof: &impl Size, relayers_state: &UnrewardedRelayersState) -> Weight {
fn receive_messages_delivery_proof_weight(
proof: &impl Size,
relayers_state: &UnrewardedRelayersState,
db_weight: RuntimeDbWeight,
) -> Weight {
// basic components of extrinsic weight
let transaction_overhead = Self::receive_messages_delivery_proof_overhead();
let messages_overhead = Self::receive_messages_delivery_proof_messages_overhead(relayers_state.total_messages);
let relayers_overhead =
Self::receive_messages_delivery_proof_relayers_overhead(relayers_state.unrewarded_relayer_entries);
let messages_overhead =
Self::receive_messages_delivery_proof_messages_overhead(relayers_state.total_messages);
let relayers_overhead = Self::receive_messages_delivery_proof_relayers_overhead(
relayers_state.unrewarded_relayer_entries,
);
// proof size overhead weight
let expected_proof_size = Self::expected_extra_storage_proof_size();
let actual_proof_size = proof.size_hint();
let proof_size_overhead =
Self::storage_proof_size_overhead(actual_proof_size.saturating_sub(expected_proof_size));
let proof_size_overhead = Self::storage_proof_size_overhead(
actual_proof_size.saturating_sub(expected_proof_size),
);
// and cost of calling `OnDeliveryConfirmed::on_messages_delivered()` for every confirmed
// message
let callback_overhead = relayers_state
.total_messages
.saturating_mul(Self::single_message_callback_overhead(db_weight));
transaction_overhead
.saturating_add(messages_overhead)
.saturating_add(relayers_overhead)
.saturating_add(proof_size_overhead)
.saturating_add(callback_overhead)
}
// Functions that are used by extrinsics weights formulas.
@@ -238,22 +278,26 @@ pub trait WeightInfoExt: WeightInfo {
Self::send_minimal_message_worst_case()
}
/// Returns weight that needs to be accounted when message of given size is sent (`send_message`).
/// 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;
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 = Self::receive_single_message_proof().saturating_mul(2);
let weight_of_two_messages_and_two_tx_overheads =
Self::receive_single_message_proof().saturating_mul(2);
let weight_of_two_messages_and_single_tx_overhead = Self::receive_two_messages_proof();
weight_of_two_messages_and_two_tx_overheads.saturating_sub(weight_of_two_messages_and_single_tx_overhead)
weight_of_two_messages_and_two_tx_overheads
.saturating_sub(weight_of_two_messages_and_single_tx_overhead)
}
/// Returns weight that needs to be accounted when receiving given number of messages with message
/// delivery transaction (`receive_messages_proof`).
/// Returns weight that needs to be accounted when receiving given a number of messages with
/// message delivery transaction (`receive_messages_proof`).
fn receive_messages_proof_messages_overhead(messages: MessageNonce) -> Weight {
let weight_of_two_messages_and_single_tx_overhead = Self::receive_two_messages_proof();
let weight_of_single_message_and_single_tx_overhead = Self::receive_single_message_proof();
@@ -262,37 +306,42 @@ pub trait WeightInfoExt: WeightInfo {
.saturating_mul(messages as Weight)
}
/// Returns weight that needs to be accounted when message delivery transaction (`receive_messages_proof`)
/// is carrying outbound lane state proof.
/// Returns weight that needs to be accounted when message delivery transaction
/// (`receive_messages_proof`) is carrying outbound lane state proof.
fn receive_messages_proof_outbound_lane_state_overhead() -> Weight {
let weight_of_single_message_and_lane_state = Self::receive_single_message_proof_with_outbound_lane_state();
let weight_of_single_message_and_lane_state =
Self::receive_single_message_proof_with_outbound_lane_state();
let weight_of_single_message = Self::receive_single_message_proof();
weight_of_single_message_and_lane_state.saturating_sub(weight_of_single_message)
}
/// Returns weight overhead of delivery confirmation transaction (`receive_messages_delivery_proof`).
/// Returns weight overhead of delivery confirmation transaction
/// (`receive_messages_delivery_proof`).
fn receive_messages_delivery_proof_overhead() -> Weight {
let weight_of_two_messages_and_two_tx_overheads =
Self::receive_delivery_proof_for_single_message().saturating_mul(2);
let weight_of_two_messages_and_single_tx_overhead =
Self::receive_delivery_proof_for_two_messages_by_single_relayer();
weight_of_two_messages_and_two_tx_overheads.saturating_sub(weight_of_two_messages_and_single_tx_overhead)
weight_of_two_messages_and_two_tx_overheads
.saturating_sub(weight_of_two_messages_and_single_tx_overhead)
}
/// Returns weight that needs to be accounted when receiving confirmations for given number of
/// Returns weight that needs to be accounted when receiving confirmations for given a number of
/// messages with delivery confirmation transaction (`receive_messages_delivery_proof`).
fn receive_messages_delivery_proof_messages_overhead(messages: MessageNonce) -> Weight {
let weight_of_two_messages = Self::receive_delivery_proof_for_two_messages_by_single_relayer();
let weight_of_two_messages =
Self::receive_delivery_proof_for_two_messages_by_single_relayer();
let weight_of_single_message = Self::receive_delivery_proof_for_single_message();
weight_of_two_messages
.saturating_sub(weight_of_single_message)
.saturating_mul(messages as Weight)
}
/// Returns weight that needs to be accounted when receiving confirmations for given number of
/// Returns weight that needs to be accounted when receiving confirmations for given a number of
/// relayers entries with delivery confirmation transaction (`receive_messages_delivery_proof`).
fn receive_messages_delivery_proof_relayers_overhead(relayers: MessageNonce) -> Weight {
let weight_of_two_messages_by_two_relayers = Self::receive_delivery_proof_for_two_messages_by_two_relayers();
let weight_of_two_messages_by_two_relayers =
Self::receive_delivery_proof_for_two_messages_by_two_relayers();
let weight_of_two_messages_by_single_relayer =
Self::receive_delivery_proof_for_two_messages_by_single_relayer();
weight_of_two_messages_by_two_relayers
@@ -300,8 +349,8 @@ pub trait WeightInfoExt: WeightInfo {
.saturating_mul(relayers as Weight)
}
/// Returns weight that needs to be accounted when storage proof of given size is recieved (either in
/// `receive_messages_proof` or `receive_messages_delivery_proof`).
/// Returns weight that needs to be accounted when storage proof of given size is received
/// (either in `receive_messages_proof` or `receive_messages_delivery_proof`).
///
/// **IMPORTANT**: this overhead is already included in the 'base' transaction cost - e.g. proof
/// size depends on messages count or number of entries in the unrewarded relayers set. So this
@@ -310,27 +359,39 @@ pub trait WeightInfoExt: WeightInfo {
/// is less than that cost).
fn storage_proof_size_overhead(proof_size: u32) -> Weight {
let proof_size_in_bytes = proof_size as Weight;
let byte_weight =
(Self::receive_single_message_proof_16_kb() - Self::receive_single_message_proof_1_kb()) / (15 * 1024);
let byte_weight = (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.
/// 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())
Self::receive_single_message_proof()
.saturating_sub(Self::receive_single_prepaid_message_proof())
}
/// Returns pre-dispatch weight of single callback call.
///
/// When benchmarking the weight please take into consideration both the `OnMessageAccepted` and
/// `OnDeliveryConfirmed` callbacks. The method should return the greater of the two, because
/// it's used to estimate the weight in both contexts.
fn single_message_callback_overhead(db_weight: RuntimeDbWeight) -> Weight {
db_weight.reads_writes(1, 1)
}
}
impl WeightInfoExt for () {
fn expected_extra_storage_proof_size() -> u32 {
bp_rialto::EXTRA_STORAGE_PROOF_SIZE
EXTRA_STORAGE_PROOF_SIZE
}
}
impl<T: frame_system::Config> WeightInfoExt for crate::weights::RialtoWeight<T> {
fn expected_extra_storage_proof_size() -> u32 {
bp_rialto::EXTRA_STORAGE_PROOF_SIZE
EXTRA_STORAGE_PROOF_SIZE
}
}