mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-05-31 02:51:01 +00:00
Squashed 'bridges/' changes from b2099c5..23dda62 (#3369)
23dda62 Rococo <> Wococo messages relay (#1030) bcde21d Update the wasm builder to substrate master (#1029) a8318ce Make target signer optional when sending message. (#1018) f8602e1 Fix insufficient balance when send message. (#1020) d95c0a7 greedy relayer don't need message dispatch to be prepaid if dispatch is supposed to be paid at the target chain (#1016) ad5876f Update types. (#1027) 116cbbc CI: fix starting the pipeline (#1022) 7e0fadd Add temporary `canary` job (#1019) 6787091 Update types to contain dispatch_fee_payment (#1017) 03f79ad Allow Root to assume SourceAccount. (#1011) 372d019 Return dispatch_fee_payment from message details RPC (#1014) 604eb1c Relay basic single-bit message dispatch results back to the source chain (#935) bf52fff Use plain source_queue view when selecting nonces for delivery (#1010) fc5cf7d pay dispatch fee at target chain (#911) 1e35477 Bump Substrate to `286d7ce` (#1006) 7ad07b3 Add --only-mandatory-headers mode (#1004) 5351dc9 Messages relayer operating mode (#995) 9bc29a7 Rococo <> Wococo relayer balance guard (#998) bc17341 rename messages_dispatch_weight -> message_details (#996) 95be244 Bump Rococo and Wococo spec versions (#999) c35567b Move ChainWithBalances::NativeBalance -> Chain::Balance (#990) 1bfece1 Fix some nits (#988) 334ea0f Increase pause before starting relays again (#989) 7fb8248 Fix clippy in test code (#993) d60ae50 fix clippy issues (#991) 75ca813 Make sure GRANDPA shares state with RPC. (#987) da2a38a Bump Substrate (#986) 5a9862f Update submit finality proof weight formula (#981) 69df513 Flag for rejecting all outbound messages (#982) 14d0506 Add script to setup bench machine. (#984) e74e8ab Move CI from GitHub Actions to GitLab (#814) c5ca5dd Custom justification verification (#979) 643f10d Always run on-demand headers relay in complex relay (#975) a35b0ef Add JSON type definitions for Rococo<>Wococo bridge (#977) 0eb83f2 Update cargo.deny (#980) e1d1f4c Bump Rococo/Wococo spec_version (#976) deac90d increase pause before starting relays (#974) 68d6d79 Revert to use InspectCmd, bump substrate `6bef4f4` (#966) 66e1508 Avoid hashing headers twice in verify_justification (#973) a31844f Bump `environmental` dependency (#972) 2a4c29a in auto-relays keep trying to connect to nodes until connection is established (#971) 0e767b3 removed stray file (#969) b9545dc Serve multiple lanes with single complex relay instance (#964) 73419f4 Correct type error (#968) bac256f Start finality relay spec-version guards for Rococo <> Wococo finality relays (#965) bfd7037 pass source and target chain ids to account_ownership_proof (#963) 8436073 Upstream changes from Polkadot repo (#961) e58d851 Increase account endowment amount (#960) git-subtree-dir: bridges git-subtree-split: 23dda6248236b27f20d76cbedc30e189cc6f736c
This commit is contained in:
committed by
GitHub
parent
022e8bc11c
commit
feefc34567
@@ -34,28 +34,34 @@
|
||||
//! or some benchmarks assumptions are broken for your runtime.
|
||||
|
||||
#![cfg_attr(not(feature = "std"), no_std)]
|
||||
// Generated by `decl_event!`
|
||||
#![allow(clippy::unused_unit)]
|
||||
|
||||
pub use crate::weights_ext::{
|
||||
ensure_able_to_receive_confirmation, ensure_able_to_receive_message, ensure_weights_are_correct, WeightInfoExt,
|
||||
EXPECTED_DEFAULT_MESSAGE_LENGTH,
|
||||
};
|
||||
|
||||
use crate::inbound_lane::{InboundLane, InboundLaneStorage};
|
||||
use crate::outbound_lane::{OutboundLane, OutboundLaneStorage};
|
||||
use crate::inbound_lane::{InboundLane, InboundLaneStorage, ReceivalResult};
|
||||
use crate::outbound_lane::{OutboundLane, OutboundLaneStorage, ReceivalConfirmationResult};
|
||||
use crate::weights::WeightInfo;
|
||||
|
||||
use bp_messages::{
|
||||
source_chain::{LaneMessageVerifier, MessageDeliveryAndDispatchPayment, RelayersRewards, TargetHeaderChain},
|
||||
source_chain::{
|
||||
LaneMessageVerifier, MessageDeliveryAndDispatchPayment, OnDeliveryConfirmed, RelayersRewards, TargetHeaderChain,
|
||||
},
|
||||
target_chain::{DispatchMessage, MessageDispatch, ProvedLaneMessages, ProvedMessages, SourceHeaderChain},
|
||||
total_unrewarded_messages, InboundLaneData, LaneId, MessageData, MessageKey, MessageNonce, MessagePayload,
|
||||
OutboundLaneData, Parameter as MessagesParameter, UnrewardedRelayersState,
|
||||
total_unrewarded_messages, DeliveredMessages, InboundLaneData, LaneId, MessageData, MessageKey, MessageNonce,
|
||||
OperatingMode, OutboundLaneData, Parameter as MessagesParameter, UnrewardedRelayersState,
|
||||
};
|
||||
use bp_runtime::Size;
|
||||
use codec::{Decode, Encode};
|
||||
use frame_support::{
|
||||
decl_error, decl_event, decl_module, decl_storage, ensure,
|
||||
decl_error, decl_event, decl_module, decl_storage,
|
||||
dispatch::DispatchResultWithPostInfo,
|
||||
ensure, fail,
|
||||
traits::Get,
|
||||
weights::{DispatchClass, Weight},
|
||||
weights::{DispatchClass, Pays, PostDispatchInfo, Weight},
|
||||
Parameter, StorageMap,
|
||||
};
|
||||
use frame_system::{ensure_signed, RawOrigin};
|
||||
@@ -142,13 +148,19 @@ pub trait Config<I = DefaultInstance>: frame_system::Config {
|
||||
type LaneMessageVerifier: LaneMessageVerifier<Self::AccountId, Self::OutboundPayload, Self::OutboundMessageFee>;
|
||||
/// Message delivery payment.
|
||||
type MessageDeliveryAndDispatchPayment: MessageDeliveryAndDispatchPayment<Self::AccountId, Self::OutboundMessageFee>;
|
||||
/// Handler for delivered messages.
|
||||
type OnDeliveryConfirmed: OnDeliveryConfirmed;
|
||||
|
||||
// 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>;
|
||||
/// Message dispatch.
|
||||
type MessageDispatch: MessageDispatch<Self::InboundMessageFee, DispatchPayload = Self::InboundPayload>;
|
||||
type MessageDispatch: MessageDispatch<
|
||||
Self::AccountId,
|
||||
Self::InboundMessageFee,
|
||||
DispatchPayload = Self::InboundPayload,
|
||||
>;
|
||||
}
|
||||
|
||||
/// Shortcut to messages proof type for Config.
|
||||
@@ -178,6 +190,8 @@ decl_error! {
|
||||
InvalidMessagesDispatchWeight,
|
||||
/// Invalid messages delivery proof has been submitted.
|
||||
InvalidMessagesDeliveryProof,
|
||||
/// The bridged chain has invalid `UnrewardedRelayers` in its storage (fatal for the lane).
|
||||
InvalidUnrewardedRelayers,
|
||||
/// The relayer has declared invalid unrewarded relayers state in the `receive_messages_delivery_proof` call.
|
||||
InvalidUnrewardedRelayersState,
|
||||
/// The message someone is trying to work with (i.e. increase fee) is already-delivered.
|
||||
@@ -196,8 +210,10 @@ decl_storage! {
|
||||
/// runtime methods may still be used to do that (i.e. democracy::referendum to update halt
|
||||
/// flag directly or call the `halt_operations`).
|
||||
pub PalletOwner get(fn module_owner): Option<T::AccountId>;
|
||||
/// If true, all pallet transactions are failed immediately.
|
||||
pub IsHalted get(fn is_halted) config(): bool;
|
||||
/// The current operating mode of the pallet.
|
||||
///
|
||||
/// Depending on the mode either all, some, or no transactions will be allowed.
|
||||
pub PalletOperatingMode get(fn operating_mode) config(): OperatingMode;
|
||||
/// Map of lane id => inbound lane data.
|
||||
pub InboundLanes: map hasher(blake2_128_concat) LaneId => InboundLaneData<T::InboundRelayer>;
|
||||
/// Map of lane id => outbound lane data.
|
||||
@@ -226,8 +242,8 @@ decl_event!(
|
||||
ParameterUpdated(Parameter),
|
||||
/// Message has been accepted and is waiting to be delivered.
|
||||
MessageAccepted(LaneId, MessageNonce),
|
||||
/// Messages in the inclusive range have been delivered and processed by the bridged chain.
|
||||
MessagesDelivered(LaneId, MessageNonce, MessageNonce),
|
||||
/// Messages in the inclusive range have been delivered to the bridged chain.
|
||||
MessagesDelivered(LaneId, DeliveredMessages),
|
||||
/// Phantom member, never used.
|
||||
Dummy(PhantomData<(AccountId, I)>),
|
||||
}
|
||||
@@ -264,19 +280,18 @@ decl_module! {
|
||||
}
|
||||
}
|
||||
|
||||
/// Halt or resume all pallet operations.
|
||||
/// Halt or resume all/some pallet operations.
|
||||
///
|
||||
/// May only be called either by root, or by `PalletOwner`.
|
||||
#[weight = (T::DbWeight::get().reads_writes(1, 1), DispatchClass::Operational)]
|
||||
pub fn set_operational(origin, operational: bool) {
|
||||
pub fn set_operating_mode(origin, operating_mode: OperatingMode) {
|
||||
ensure_owner_or_root::<T, I>(origin)?;
|
||||
<IsHalted<I>>::put(operational);
|
||||
|
||||
if operational {
|
||||
log::info!(target: "runtime::bridge-messages", "Resuming pallet operations.");
|
||||
} else {
|
||||
log::warn!(target: "runtime::bridge-messages", "Stopping pallet operations.");
|
||||
}
|
||||
<PalletOperatingMode<I>>::put(operating_mode);
|
||||
log::info!(
|
||||
target: "runtime::bridge-messages",
|
||||
"Setting messages pallet operating mode to {:?}.",
|
||||
operating_mode,
|
||||
);
|
||||
}
|
||||
|
||||
/// Update pallet parameter.
|
||||
@@ -299,7 +314,7 @@ decl_module! {
|
||||
payload: T::OutboundPayload,
|
||||
delivery_and_dispatch_fee: T::OutboundMessageFee,
|
||||
) -> DispatchResult {
|
||||
ensure_operational::<T, I>()?;
|
||||
ensure_normal_operating_mode::<T, I>()?;
|
||||
let submitter = origin.into().map_err(|_| BadOrigin)?;
|
||||
|
||||
// let's first check if message can be delivered to target chain
|
||||
@@ -382,6 +397,7 @@ decl_module! {
|
||||
nonce: MessageNonce,
|
||||
additional_fee: T::OutboundMessageFee,
|
||||
) -> DispatchResult {
|
||||
ensure_not_halted::<T, I>()?;
|
||||
// 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)
|
||||
//
|
||||
@@ -434,13 +450,13 @@ decl_module! {
|
||||
#[weight = T::WeightInfo::receive_messages_proof_weight(proof, *messages_count, *dispatch_weight)]
|
||||
pub fn receive_messages_proof(
|
||||
origin,
|
||||
relayer_id: T::InboundRelayer,
|
||||
relayer_id_at_bridged_chain: T::InboundRelayer,
|
||||
proof: MessagesProofOf<T, I>,
|
||||
messages_count: u32,
|
||||
dispatch_weight: Weight,
|
||||
) -> DispatchResult {
|
||||
ensure_operational::<T, I>()?;
|
||||
let _ = ensure_signed(origin)?;
|
||||
) -> DispatchResultWithPostInfo {
|
||||
ensure_not_halted::<T, I>()?;
|
||||
let relayer_id_at_this_chain = ensure_signed(origin)?;
|
||||
|
||||
// reject transactions that are declaring too many messages
|
||||
ensure!(
|
||||
@@ -448,6 +464,23 @@ decl_module! {
|
||||
Error::<T, I>::TooManyMessagesInTheProof
|
||||
);
|
||||
|
||||
// why do we need to know the weight of this (`receive_messages_proof`) call? Because
|
||||
// we may want to return some funds for not-dispatching (or partially dispatching) some
|
||||
// messages to the call origin (relayer). And this is done by returning actual weight
|
||||
// from the call. But we only know dispatch weight of every messages. So to refund relayer
|
||||
// because we have not dispatched Message, we need to:
|
||||
//
|
||||
// ActualWeight = DeclaredWeight - Message.DispatchWeight
|
||||
//
|
||||
// The DeclaredWeight is exactly what's computed here. Unfortunately it is impossible
|
||||
// to get pre-computed value (and it has been already computed by the executive).
|
||||
let declared_weight = T::WeightInfo::receive_messages_proof_weight(
|
||||
&proof,
|
||||
messages_count,
|
||||
dispatch_weight,
|
||||
);
|
||||
let mut actual_weight = declared_weight;
|
||||
|
||||
// verify messages proof && convert proof into messages
|
||||
let messages = verify_and_decode_messages_proof::<
|
||||
T::SourceHeaderChain,
|
||||
@@ -507,20 +540,57 @@ decl_module! {
|
||||
debug_assert_eq!(message.key.lane_id, lane_id);
|
||||
|
||||
total_messages += 1;
|
||||
if lane.receive_message::<T::MessageDispatch>(relayer_id.clone(), message.key.nonce, message.data) {
|
||||
valid_messages += 1;
|
||||
}
|
||||
let dispatch_weight = T::MessageDispatch::dispatch_weight(&message);
|
||||
let receival_result = lane.receive_message::<T::MessageDispatch, T::AccountId>(
|
||||
&relayer_id_at_bridged_chain,
|
||||
&relayer_id_at_this_chain,
|
||||
message.key.nonce,
|
||||
message.data,
|
||||
);
|
||||
|
||||
// note that we're returning unspent weight to relayer even if message has been
|
||||
// rejected by the lane. This allows relayers to submit spam transactions with
|
||||
// e.g. the same set of already delivered messages over and over again, without
|
||||
// losing funds for messages dispatch. But keep in mind that relayer pays base
|
||||
// delivery transaction cost anyway. And base cost covers everything except
|
||||
// dispatch, so we have a balance here.
|
||||
let (unspent_weight, refund_pay_dispatch_fee) = match receival_result {
|
||||
ReceivalResult::Dispatched(dispatch_result) => {
|
||||
valid_messages += 1;
|
||||
(dispatch_result.unspent_weight, !dispatch_result.dispatch_fee_paid_during_dispatch)
|
||||
},
|
||||
ReceivalResult::InvalidNonce
|
||||
| ReceivalResult::TooManyUnrewardedRelayers
|
||||
| ReceivalResult::TooManyUnconfirmedMessages => (dispatch_weight, true),
|
||||
};
|
||||
actual_weight = actual_weight
|
||||
.saturating_sub(sp_std::cmp::min(unspent_weight, dispatch_weight))
|
||||
.saturating_sub(
|
||||
// delivery call weight formula assumes that the fee is paid at
|
||||
// this (target) chain. If the message is prepaid at the source
|
||||
// chain, let's refund relayer with this extra cost.
|
||||
if refund_pay_dispatch_fee {
|
||||
T::WeightInfo::pay_inbound_dispatch_fee_overhead()
|
||||
} else {
|
||||
0
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
log::trace!(
|
||||
target: "runtime::bridge-messages",
|
||||
"Received messages: total={}, valid={}",
|
||||
"Received messages: total={}, valid={}. Weight used: {}/{}",
|
||||
total_messages,
|
||||
valid_messages,
|
||||
actual_weight,
|
||||
declared_weight,
|
||||
);
|
||||
|
||||
Ok(())
|
||||
Ok(PostDispatchInfo {
|
||||
actual_weight: Some(actual_weight),
|
||||
pays_fee: Pays::Yes,
|
||||
})
|
||||
}
|
||||
|
||||
/// Receive messages delivery proof from bridged chain.
|
||||
@@ -530,7 +600,7 @@ decl_module! {
|
||||
proof: MessagesDeliveryProofOf<T, I>,
|
||||
relayers_state: UnrewardedRelayersState,
|
||||
) -> DispatchResult {
|
||||
ensure_operational::<T, I>()?;
|
||||
ensure_not_halted::<T, I>()?;
|
||||
|
||||
let confirmation_relayer = ensure_signed(origin)?;
|
||||
let (lane_id, lane_data) = T::TargetHeaderChain::verify_messages_delivery_proof(proof).map_err(|err| {
|
||||
@@ -556,19 +626,36 @@ decl_module! {
|
||||
let mut lane = outbound_lane::<T, I>(lane_id);
|
||||
let mut relayers_rewards: RelayersRewards<_, T::OutboundMessageFee> = RelayersRewards::new();
|
||||
let last_delivered_nonce = lane_data.last_delivered_nonce();
|
||||
let received_range = lane.confirm_delivery(last_delivered_nonce);
|
||||
if let Some(received_range) = received_range {
|
||||
Self::deposit_event(RawEvent::MessagesDelivered(lane_id, received_range.0, received_range.1));
|
||||
let confirmed_messages = match lane.confirm_delivery(last_delivered_nonce, &lane_data.relayers) {
|
||||
ReceivalConfirmationResult::ConfirmedMessages(confirmed_messages) => Some(confirmed_messages),
|
||||
ReceivalConfirmationResult::NoNewConfirmations => None,
|
||||
error => {
|
||||
log::trace!(
|
||||
target: "runtime::bridge-messages",
|
||||
"Messages delivery proof contains invalid unrewarded relayers vec: {:?}",
|
||||
error,
|
||||
);
|
||||
|
||||
fail!(Error::<T, I>::InvalidUnrewardedRelayers);
|
||||
},
|
||||
};
|
||||
if let Some(confirmed_messages) = confirmed_messages {
|
||||
// handle messages delivery confirmation
|
||||
T::OnDeliveryConfirmed::on_messages_delivered(&lane_id, &confirmed_messages);
|
||||
|
||||
// emit 'delivered' event
|
||||
let received_range = confirmed_messages.begin..=confirmed_messages.end;
|
||||
Self::deposit_event(RawEvent::MessagesDelivered(lane_id, confirmed_messages));
|
||||
|
||||
// remember to reward relayers that have delivered messages
|
||||
// this loop is bounded by `T::MaxUnrewardedRelayerEntriesAtInboundLane` on the bridged chain
|
||||
for (nonce_low, nonce_high, relayer) in lane_data.relayers {
|
||||
let nonce_begin = sp_std::cmp::max(nonce_low, received_range.0);
|
||||
let nonce_end = sp_std::cmp::min(nonce_high, received_range.1);
|
||||
for entry in lane_data.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(relayer).or_default();
|
||||
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,
|
||||
@@ -603,9 +690,9 @@ decl_module! {
|
||||
}
|
||||
|
||||
impl<T: Config<I>, I: Instance> Pallet<T, I> {
|
||||
/// Get payload of given outbound message.
|
||||
pub fn outbound_message_payload(lane: LaneId, nonce: MessageNonce) -> Option<MessagePayload> {
|
||||
OutboundMessages::<T, I>::get(MessageKey { lane_id: lane, nonce }).map(|message_data| message_data.payload)
|
||||
/// Get stored data of the outbound message with given nonce.
|
||||
pub fn outbound_message_data(lane: LaneId, nonce: MessageNonce) -> Option<MessageData<T::OutboundMessageFee>> {
|
||||
OutboundMessages::<T, I>::get(MessageKey { lane_id: lane, nonce })
|
||||
}
|
||||
|
||||
/// Get nonce of latest generated message at given outbound lane.
|
||||
@@ -633,7 +720,10 @@ impl<T: Config<I>, I: Instance> Pallet<T, I> {
|
||||
let relayers = InboundLanes::<T, I>::get(&lane).relayers;
|
||||
bp_messages::UnrewardedRelayersState {
|
||||
unrewarded_relayer_entries: relayers.len() as _,
|
||||
messages_in_oldest_entry: relayers.front().map(|(begin, end, _)| 1 + end - begin).unwrap_or(0),
|
||||
messages_in_oldest_entry: relayers
|
||||
.front()
|
||||
.map(|entry| 1 + entry.messages.end - entry.messages.begin)
|
||||
.unwrap_or(0),
|
||||
total_messages: total_unrewarded_messages(&relayers).unwrap_or(MessageNonce::MAX),
|
||||
}
|
||||
}
|
||||
@@ -665,24 +755,38 @@ impl<T: Config<I>, I: Instance> Pallet<T, I> {
|
||||
/// trying to avoid here) - by using strings like "Instance2", "OutboundMessages", etc.
|
||||
pub mod storage_keys {
|
||||
use super::*;
|
||||
use frame_support::storage::generator::StorageMap;
|
||||
use frame_support::{traits::Instance, StorageHasher};
|
||||
use sp_core::storage::StorageKey;
|
||||
|
||||
/// Storage key of the outbound message in the runtime storage.
|
||||
pub fn message_key<T: Config<I>, I: Instance>(lane: &LaneId, nonce: MessageNonce) -> StorageKey {
|
||||
let message_key = MessageKey { lane_id: *lane, nonce };
|
||||
let raw_storage_key = OutboundMessages::<T, I>::storage_map_final_key(message_key);
|
||||
StorageKey(raw_storage_key)
|
||||
pub fn message_key<I: Instance>(lane: &LaneId, nonce: MessageNonce) -> StorageKey {
|
||||
storage_map_final_key::<I>("OutboundMessages", &MessageKey { lane_id: *lane, nonce }.encode())
|
||||
}
|
||||
|
||||
/// Storage key of the outbound message lane state in the runtime storage.
|
||||
pub fn outbound_lane_data_key<I: Instance>(lane: &LaneId) -> StorageKey {
|
||||
StorageKey(OutboundLanes::<I>::storage_map_final_key(*lane))
|
||||
storage_map_final_key::<I>("OutboundLanes", lane)
|
||||
}
|
||||
|
||||
/// Storage key of the inbound message lane state in the runtime storage.
|
||||
pub fn inbound_lane_data_key<T: Config<I>, I: Instance>(lane: &LaneId) -> StorageKey {
|
||||
StorageKey(InboundLanes::<T, I>::storage_map_final_key(*lane))
|
||||
pub fn inbound_lane_data_key<I: Instance>(lane: &LaneId) -> StorageKey {
|
||||
storage_map_final_key::<I>("InboundLanes", lane)
|
||||
}
|
||||
|
||||
/// This is a copypaste of the `frame_support::storage::generator::StorageMap::storage_map_final_key`.
|
||||
fn storage_map_final_key<I: Instance>(map_name: &str, key: &[u8]) -> StorageKey {
|
||||
let module_prefix_hashed = frame_support::Twox128::hash(I::PREFIX.as_bytes());
|
||||
let storage_prefix_hashed = frame_support::Twox128::hash(map_name.as_bytes());
|
||||
let key_hashed = frame_support::Blake2_128Concat::hash(key);
|
||||
|
||||
let mut final_key =
|
||||
Vec::with_capacity(module_prefix_hashed.len() + storage_prefix_hashed.len() + key_hashed.len());
|
||||
|
||||
final_key.extend_from_slice(&module_prefix_hashed[..]);
|
||||
final_key.extend_from_slice(&storage_prefix_hashed[..]);
|
||||
final_key.extend_from_slice(key_hashed.as_ref());
|
||||
|
||||
StorageKey(final_key)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -695,9 +799,18 @@ fn ensure_owner_or_root<T: Config<I>, I: Instance>(origin: T::Origin) -> Result<
|
||||
}
|
||||
}
|
||||
|
||||
/// Ensure that the pallet is in operational mode (not halted).
|
||||
fn ensure_operational<T: Config<I>, I: Instance>() -> Result<(), Error<T, I>> {
|
||||
if IsHalted::<I>::get() {
|
||||
/// Ensure that the pallet is in normal operational mode.
|
||||
fn ensure_normal_operating_mode<T: Config<I>, I: Instance>() -> Result<(), Error<T, I>> {
|
||||
if PalletOperatingMode::<I>::get() != OperatingMode::Normal {
|
||||
Err(Error::<T, I>::Halted)
|
||||
} else {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
/// Ensure that the pallet is not halted.
|
||||
fn ensure_not_halted<T: Config<I>, I: Instance>() -> Result<(), Error<T, I>> {
|
||||
if PalletOperatingMode::<I>::get() == OperatingMode::Halted {
|
||||
Err(Error::<T, I>::Halted)
|
||||
} else {
|
||||
Ok(())
|
||||
@@ -847,12 +960,12 @@ fn verify_and_decode_messages_proof<Chain: SourceHeaderChain<Fee>, Fee, Dispatch
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::mock::{
|
||||
message, run_test, Event as TestEvent, Origin, TestMessageDeliveryAndDispatchPayment,
|
||||
TestMessagesDeliveryProof, TestMessagesParameter, TestMessagesProof, TestPayload, TestRuntime,
|
||||
TokenConversionRate, PAYLOAD_REJECTED_BY_TARGET_CHAIN, REGULAR_PAYLOAD, TEST_LANE_ID, TEST_RELAYER_A,
|
||||
TEST_RELAYER_B,
|
||||
message, message_payload, run_test, unrewarded_relayer, Event as TestEvent, Origin,
|
||||
TestMessageDeliveryAndDispatchPayment, TestMessagesDeliveryProof, TestMessagesParameter, TestMessagesProof,
|
||||
TestRuntime, TokenConversionRate, PAYLOAD_REJECTED_BY_TARGET_CHAIN, REGULAR_PAYLOAD, TEST_LANE_ID,
|
||||
TEST_RELAYER_A, TEST_RELAYER_B,
|
||||
};
|
||||
use bp_messages::UnrewardedRelayersState;
|
||||
use bp_messages::{UnrewardedRelayer, UnrewardedRelayersState};
|
||||
use frame_support::{assert_noop, assert_ok};
|
||||
use frame_system::{EventRecord, Pallet as System, Phase};
|
||||
use hex_literal::hex;
|
||||
@@ -866,11 +979,15 @@ mod tests {
|
||||
fn send_regular_message() {
|
||||
get_ready_for_events();
|
||||
|
||||
let message_nonce = outbound_lane::<TestRuntime, DefaultInstance>(TEST_LANE_ID)
|
||||
.data()
|
||||
.latest_generated_nonce
|
||||
+ 1;
|
||||
assert_ok!(Pallet::<TestRuntime>::send_message(
|
||||
Origin::signed(1),
|
||||
TEST_LANE_ID,
|
||||
REGULAR_PAYLOAD,
|
||||
REGULAR_PAYLOAD.1,
|
||||
REGULAR_PAYLOAD.declared_weight,
|
||||
));
|
||||
|
||||
// check event with assigned nonce
|
||||
@@ -878,13 +995,16 @@ mod tests {
|
||||
System::<TestRuntime>::events(),
|
||||
vec![EventRecord {
|
||||
phase: Phase::Initialization,
|
||||
event: TestEvent::Messages(RawEvent::MessageAccepted(TEST_LANE_ID, 1)),
|
||||
event: TestEvent::Messages(RawEvent::MessageAccepted(TEST_LANE_ID, message_nonce)),
|
||||
topics: vec![],
|
||||
}],
|
||||
);
|
||||
|
||||
// check that fee has been withdrawn from submitter
|
||||
assert!(TestMessageDeliveryAndDispatchPayment::is_fee_paid(1, REGULAR_PAYLOAD.1));
|
||||
assert!(TestMessageDeliveryAndDispatchPayment::is_fee_paid(
|
||||
1,
|
||||
REGULAR_PAYLOAD.declared_weight
|
||||
));
|
||||
}
|
||||
|
||||
fn receive_messages_delivery_proof() {
|
||||
@@ -897,17 +1017,29 @@ mod tests {
|
||||
TEST_LANE_ID,
|
||||
InboundLaneData {
|
||||
last_confirmed_nonce: 1,
|
||||
..Default::default()
|
||||
relayers: vec![UnrewardedRelayer {
|
||||
relayer: 0,
|
||||
messages: DeliveredMessages::new(1, true),
|
||||
}]
|
||||
.into_iter()
|
||||
.collect(),
|
||||
},
|
||||
))),
|
||||
Default::default(),
|
||||
UnrewardedRelayersState {
|
||||
unrewarded_relayer_entries: 1,
|
||||
total_messages: 1,
|
||||
..Default::default()
|
||||
},
|
||||
));
|
||||
|
||||
assert_eq!(
|
||||
System::<TestRuntime>::events(),
|
||||
vec![EventRecord {
|
||||
phase: Phase::Initialization,
|
||||
event: TestEvent::Messages(RawEvent::MessagesDelivered(TEST_LANE_ID, 1, 1)),
|
||||
event: TestEvent::Messages(RawEvent::MessagesDelivered(
|
||||
TEST_LANE_ID,
|
||||
DeliveredMessages::new(1, true),
|
||||
)),
|
||||
topics: vec![],
|
||||
}],
|
||||
);
|
||||
@@ -920,29 +1052,41 @@ mod tests {
|
||||
|
||||
assert_ok!(Pallet::<TestRuntime>::set_owner(Origin::root(), Some(1)));
|
||||
assert_noop!(
|
||||
Pallet::<TestRuntime>::set_operational(Origin::signed(2), false),
|
||||
Pallet::<TestRuntime>::set_operating_mode(Origin::signed(2), OperatingMode::Halted),
|
||||
DispatchError::BadOrigin,
|
||||
);
|
||||
assert_ok!(Pallet::<TestRuntime>::set_operational(Origin::root(), false));
|
||||
assert_ok!(Pallet::<TestRuntime>::set_operating_mode(
|
||||
Origin::root(),
|
||||
OperatingMode::Halted
|
||||
));
|
||||
|
||||
assert_ok!(Pallet::<TestRuntime>::set_owner(Origin::signed(1), None));
|
||||
assert_noop!(
|
||||
Pallet::<TestRuntime>::set_operational(Origin::signed(1), true),
|
||||
Pallet::<TestRuntime>::set_operating_mode(Origin::signed(1), OperatingMode::Normal),
|
||||
DispatchError::BadOrigin,
|
||||
);
|
||||
assert_noop!(
|
||||
Pallet::<TestRuntime>::set_operational(Origin::signed(2), true),
|
||||
Pallet::<TestRuntime>::set_operating_mode(Origin::signed(2), OperatingMode::Normal),
|
||||
DispatchError::BadOrigin,
|
||||
);
|
||||
assert_ok!(Pallet::<TestRuntime>::set_operational(Origin::root(), true));
|
||||
assert_ok!(Pallet::<TestRuntime>::set_operating_mode(
|
||||
Origin::root(),
|
||||
OperatingMode::Normal
|
||||
));
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn pallet_may_be_halted_by_root() {
|
||||
run_test(|| {
|
||||
assert_ok!(Pallet::<TestRuntime>::set_operational(Origin::root(), false));
|
||||
assert_ok!(Pallet::<TestRuntime>::set_operational(Origin::root(), true));
|
||||
assert_ok!(Pallet::<TestRuntime>::set_operating_mode(
|
||||
Origin::root(),
|
||||
OperatingMode::Halted
|
||||
));
|
||||
assert_ok!(Pallet::<TestRuntime>::set_operating_mode(
|
||||
Origin::root(),
|
||||
OperatingMode::Normal
|
||||
));
|
||||
});
|
||||
}
|
||||
|
||||
@@ -951,21 +1095,30 @@ mod tests {
|
||||
run_test(|| {
|
||||
PalletOwner::<TestRuntime>::put(2);
|
||||
|
||||
assert_ok!(Pallet::<TestRuntime>::set_operational(Origin::signed(2), false));
|
||||
assert_ok!(Pallet::<TestRuntime>::set_operational(Origin::signed(2), true));
|
||||
assert_ok!(Pallet::<TestRuntime>::set_operating_mode(
|
||||
Origin::signed(2),
|
||||
OperatingMode::Halted
|
||||
));
|
||||
assert_ok!(Pallet::<TestRuntime>::set_operating_mode(
|
||||
Origin::signed(2),
|
||||
OperatingMode::Normal
|
||||
));
|
||||
|
||||
assert_noop!(
|
||||
Pallet::<TestRuntime>::set_operational(Origin::signed(1), false),
|
||||
Pallet::<TestRuntime>::set_operating_mode(Origin::signed(1), OperatingMode::Halted),
|
||||
DispatchError::BadOrigin,
|
||||
);
|
||||
assert_noop!(
|
||||
Pallet::<TestRuntime>::set_operational(Origin::signed(1), true),
|
||||
Pallet::<TestRuntime>::set_operating_mode(Origin::signed(1), OperatingMode::Normal),
|
||||
DispatchError::BadOrigin,
|
||||
);
|
||||
|
||||
assert_ok!(Pallet::<TestRuntime>::set_operational(Origin::signed(2), false));
|
||||
assert_ok!(Pallet::<TestRuntime>::set_operating_mode(
|
||||
Origin::signed(2),
|
||||
OperatingMode::Halted
|
||||
));
|
||||
assert_noop!(
|
||||
Pallet::<TestRuntime>::set_operational(Origin::signed(1), true),
|
||||
Pallet::<TestRuntime>::set_operating_mode(Origin::signed(1), OperatingMode::Normal),
|
||||
DispatchError::BadOrigin,
|
||||
);
|
||||
});
|
||||
@@ -1072,25 +1225,30 @@ mod tests {
|
||||
// send message first to be able to check that delivery_proof fails later
|
||||
send_regular_message();
|
||||
|
||||
IsHalted::<DefaultInstance>::put(true);
|
||||
PalletOperatingMode::<DefaultInstance>::put(OperatingMode::Halted);
|
||||
|
||||
assert_noop!(
|
||||
Pallet::<TestRuntime>::send_message(
|
||||
Origin::signed(1),
|
||||
TEST_LANE_ID,
|
||||
REGULAR_PAYLOAD,
|
||||
REGULAR_PAYLOAD.1,
|
||||
REGULAR_PAYLOAD.declared_weight,
|
||||
),
|
||||
Error::<TestRuntime, DefaultInstance>::Halted,
|
||||
);
|
||||
|
||||
assert_noop!(
|
||||
Pallet::<TestRuntime>::increase_message_fee(Origin::signed(1), TEST_LANE_ID, 1, 1,),
|
||||
Error::<TestRuntime, DefaultInstance>::Halted,
|
||||
);
|
||||
|
||||
assert_noop!(
|
||||
Pallet::<TestRuntime>::receive_messages_proof(
|
||||
Origin::signed(1),
|
||||
TEST_RELAYER_A,
|
||||
Ok(vec![message(2, REGULAR_PAYLOAD)]).into(),
|
||||
1,
|
||||
REGULAR_PAYLOAD.1,
|
||||
REGULAR_PAYLOAD.declared_weight,
|
||||
),
|
||||
Error::<TestRuntime, DefaultInstance>::Halted,
|
||||
);
|
||||
@@ -1112,6 +1270,53 @@ mod tests {
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn pallet_rejects_new_messages_in_rejecting_outbound_messages_operating_mode() {
|
||||
run_test(|| {
|
||||
// send message first to be able to check that delivery_proof fails later
|
||||
send_regular_message();
|
||||
|
||||
PalletOperatingMode::<DefaultInstance>::put(OperatingMode::RejectingOutboundMessages);
|
||||
|
||||
assert_noop!(
|
||||
Pallet::<TestRuntime>::send_message(
|
||||
Origin::signed(1),
|
||||
TEST_LANE_ID,
|
||||
REGULAR_PAYLOAD,
|
||||
REGULAR_PAYLOAD.declared_weight,
|
||||
),
|
||||
Error::<TestRuntime, DefaultInstance>::Halted,
|
||||
);
|
||||
|
||||
assert_ok!(Pallet::<TestRuntime>::increase_message_fee(
|
||||
Origin::signed(1),
|
||||
TEST_LANE_ID,
|
||||
1,
|
||||
1,
|
||||
));
|
||||
|
||||
assert_ok!(Pallet::<TestRuntime>::receive_messages_proof(
|
||||
Origin::signed(1),
|
||||
TEST_RELAYER_A,
|
||||
Ok(vec![message(1, REGULAR_PAYLOAD)]).into(),
|
||||
1,
|
||||
REGULAR_PAYLOAD.declared_weight,
|
||||
),);
|
||||
|
||||
assert_ok!(Pallet::<TestRuntime>::receive_messages_delivery_proof(
|
||||
Origin::signed(1),
|
||||
TestMessagesDeliveryProof(Ok((
|
||||
TEST_LANE_ID,
|
||||
InboundLaneData {
|
||||
last_confirmed_nonce: 1,
|
||||
..Default::default()
|
||||
},
|
||||
))),
|
||||
Default::default(),
|
||||
));
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn send_message_works() {
|
||||
run_test(|| {
|
||||
@@ -1128,7 +1333,7 @@ mod tests {
|
||||
Origin::signed(1),
|
||||
TEST_LANE_ID,
|
||||
PAYLOAD_REJECTED_BY_TARGET_CHAIN,
|
||||
PAYLOAD_REJECTED_BY_TARGET_CHAIN.1
|
||||
PAYLOAD_REJECTED_BY_TARGET_CHAIN.declared_weight
|
||||
),
|
||||
Error::<TestRuntime, DefaultInstance>::MessageRejectedByChainVerifier,
|
||||
);
|
||||
@@ -1155,7 +1360,7 @@ mod tests {
|
||||
Origin::signed(1),
|
||||
TEST_LANE_ID,
|
||||
REGULAR_PAYLOAD,
|
||||
REGULAR_PAYLOAD.1
|
||||
REGULAR_PAYLOAD.declared_weight
|
||||
),
|
||||
Error::<TestRuntime, DefaultInstance>::FailedToWithdrawMessageFee,
|
||||
);
|
||||
@@ -1170,7 +1375,7 @@ mod tests {
|
||||
TEST_RELAYER_A,
|
||||
Ok(vec![message(1, REGULAR_PAYLOAD)]).into(),
|
||||
1,
|
||||
REGULAR_PAYLOAD.1,
|
||||
REGULAR_PAYLOAD.declared_weight,
|
||||
));
|
||||
|
||||
assert_eq!(InboundLanes::<TestRuntime>::get(TEST_LANE_ID).last_delivered_nonce(), 1);
|
||||
@@ -1185,9 +1390,12 @@ mod tests {
|
||||
TEST_LANE_ID,
|
||||
InboundLaneData {
|
||||
last_confirmed_nonce: 8,
|
||||
relayers: vec![(9, 9, TEST_RELAYER_A), (10, 10, TEST_RELAYER_B)]
|
||||
.into_iter()
|
||||
.collect(),
|
||||
relayers: vec![
|
||||
unrewarded_relayer(9, 9, TEST_RELAYER_A),
|
||||
unrewarded_relayer(10, 10, TEST_RELAYER_B),
|
||||
]
|
||||
.into_iter()
|
||||
.collect(),
|
||||
},
|
||||
);
|
||||
assert_eq!(
|
||||
@@ -1211,16 +1419,19 @@ mod tests {
|
||||
TEST_RELAYER_A,
|
||||
message_proof,
|
||||
1,
|
||||
REGULAR_PAYLOAD.1,
|
||||
REGULAR_PAYLOAD.declared_weight,
|
||||
));
|
||||
|
||||
assert_eq!(
|
||||
InboundLanes::<TestRuntime>::get(TEST_LANE_ID),
|
||||
InboundLaneData {
|
||||
last_confirmed_nonce: 9,
|
||||
relayers: vec![(10, 10, TEST_RELAYER_B), (11, 11, TEST_RELAYER_A)]
|
||||
.into_iter()
|
||||
.collect(),
|
||||
relayers: vec![
|
||||
unrewarded_relayer(10, 10, TEST_RELAYER_B),
|
||||
unrewarded_relayer(11, 11, TEST_RELAYER_A)
|
||||
]
|
||||
.into_iter()
|
||||
.collect(),
|
||||
},
|
||||
);
|
||||
assert_eq!(
|
||||
@@ -1243,7 +1454,7 @@ mod tests {
|
||||
TEST_RELAYER_A,
|
||||
Ok(vec![message(1, REGULAR_PAYLOAD)]).into(),
|
||||
1,
|
||||
REGULAR_PAYLOAD.1 - 1,
|
||||
REGULAR_PAYLOAD.declared_weight - 1,
|
||||
),
|
||||
Error::<TestRuntime, DefaultInstance>::InvalidMessagesDispatchWeight,
|
||||
);
|
||||
@@ -1317,7 +1528,7 @@ mod tests {
|
||||
TestMessagesDeliveryProof(Ok((
|
||||
TEST_LANE_ID,
|
||||
InboundLaneData {
|
||||
relayers: vec![(1, 1, TEST_RELAYER_A)].into_iter().collect(),
|
||||
relayers: vec![unrewarded_relayer(1, 1, TEST_RELAYER_A)].into_iter().collect(),
|
||||
..Default::default()
|
||||
}
|
||||
))),
|
||||
@@ -1342,9 +1553,12 @@ mod tests {
|
||||
TestMessagesDeliveryProof(Ok((
|
||||
TEST_LANE_ID,
|
||||
InboundLaneData {
|
||||
relayers: vec![(1, 1, TEST_RELAYER_A), (2, 2, TEST_RELAYER_B)]
|
||||
.into_iter()
|
||||
.collect(),
|
||||
relayers: vec![
|
||||
unrewarded_relayer(1, 1, TEST_RELAYER_A),
|
||||
unrewarded_relayer(2, 2, TEST_RELAYER_B)
|
||||
]
|
||||
.into_iter()
|
||||
.collect(),
|
||||
..Default::default()
|
||||
}
|
||||
))),
|
||||
@@ -1389,9 +1603,12 @@ mod tests {
|
||||
TestMessagesDeliveryProof(Ok((
|
||||
TEST_LANE_ID,
|
||||
InboundLaneData {
|
||||
relayers: vec![(1, 1, TEST_RELAYER_A), (2, 2, TEST_RELAYER_B)]
|
||||
.into_iter()
|
||||
.collect(),
|
||||
relayers: vec![
|
||||
unrewarded_relayer(1, 1, TEST_RELAYER_A),
|
||||
unrewarded_relayer(2, 2, TEST_RELAYER_B)
|
||||
]
|
||||
.into_iter()
|
||||
.collect(),
|
||||
..Default::default()
|
||||
}
|
||||
))),
|
||||
@@ -1411,9 +1628,12 @@ mod tests {
|
||||
TestMessagesDeliveryProof(Ok((
|
||||
TEST_LANE_ID,
|
||||
InboundLaneData {
|
||||
relayers: vec![(1, 1, TEST_RELAYER_A), (2, 2, TEST_RELAYER_B)]
|
||||
.into_iter()
|
||||
.collect(),
|
||||
relayers: vec![
|
||||
unrewarded_relayer(1, 1, TEST_RELAYER_A),
|
||||
unrewarded_relayer(2, 2, TEST_RELAYER_B)
|
||||
]
|
||||
.into_iter()
|
||||
.collect(),
|
||||
..Default::default()
|
||||
}
|
||||
))),
|
||||
@@ -1465,7 +1685,7 @@ mod tests {
|
||||
])
|
||||
.into(),
|
||||
3,
|
||||
REGULAR_PAYLOAD.1 + REGULAR_PAYLOAD.1,
|
||||
REGULAR_PAYLOAD.declared_weight + REGULAR_PAYLOAD.declared_weight,
|
||||
),);
|
||||
|
||||
assert_eq!(
|
||||
@@ -1479,7 +1699,7 @@ mod tests {
|
||||
fn storage_message_key_computed_properly() {
|
||||
// If this test fails, then something has been changed in module storage that is breaking all
|
||||
// previously crafted messages proofs.
|
||||
let storage_key = storage_keys::message_key::<TestRuntime, DefaultInstance>(&*b"test", 42).0;
|
||||
let storage_key = storage_keys::message_key::<DefaultInstance>(&*b"test", 42).0;
|
||||
assert_eq!(
|
||||
storage_key,
|
||||
hex!("dd16c784ebd3390a9bc0357c7511ed018a395e6242c6813b196ca31ed0547ea79446af0e09063bd4a7874aef8a997cec746573742a00000000000000").to_vec(),
|
||||
@@ -1505,7 +1725,7 @@ mod tests {
|
||||
fn inbound_lane_data_key_computed_properly() {
|
||||
// If this test fails, then something has been changed in module storage that is breaking all
|
||||
// previously crafted inbound lane state proofs.
|
||||
let storage_key = storage_keys::inbound_lane_data_key::<TestRuntime, DefaultInstance>(&*b"test").0;
|
||||
let storage_key = storage_keys::inbound_lane_data_key::<DefaultInstance>(&*b"test").0;
|
||||
assert_eq!(
|
||||
storage_key,
|
||||
hex!("dd16c784ebd3390a9bc0357c7511ed01e5f83cf83f2127eb47afdc35d6e43fab44a8995dd50b6657a037a7839304535b74657374").to_vec(),
|
||||
@@ -1517,9 +1737,9 @@ mod tests {
|
||||
#[test]
|
||||
fn actual_dispatch_weight_does_not_overlow() {
|
||||
run_test(|| {
|
||||
let message1 = message(1, TestPayload(0, Weight::MAX / 2));
|
||||
let message2 = message(2, TestPayload(0, Weight::MAX / 2));
|
||||
let message3 = message(2, TestPayload(0, Weight::MAX / 2));
|
||||
let message1 = message(1, message_payload(0, Weight::MAX / 2));
|
||||
let message2 = message(2, message_payload(0, Weight::MAX / 2));
|
||||
let message3 = message(2, message_payload(0, Weight::MAX / 2));
|
||||
|
||||
assert_noop!(
|
||||
Pallet::<TestRuntime, DefaultInstance>::receive_messages_proof(
|
||||
@@ -1586,4 +1806,127 @@ mod tests {
|
||||
assert!(TestMessageDeliveryAndDispatchPayment::is_fee_paid(1, 100));
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn weight_refund_from_receive_messages_proof_works() {
|
||||
run_test(|| {
|
||||
fn submit_with_unspent_weight(
|
||||
nonce: MessageNonce,
|
||||
unspent_weight: Weight,
|
||||
is_prepaid: bool,
|
||||
) -> (Weight, Weight) {
|
||||
let mut payload = REGULAR_PAYLOAD;
|
||||
payload.dispatch_result.unspent_weight = unspent_weight;
|
||||
payload.dispatch_result.dispatch_fee_paid_during_dispatch = !is_prepaid;
|
||||
let proof = Ok(vec![message(nonce, payload)]).into();
|
||||
let messages_count = 1;
|
||||
let pre_dispatch_weight = <TestRuntime as Config>::WeightInfo::receive_messages_proof_weight(
|
||||
&proof,
|
||||
messages_count,
|
||||
REGULAR_PAYLOAD.declared_weight,
|
||||
);
|
||||
let post_dispatch_weight = Pallet::<TestRuntime>::receive_messages_proof(
|
||||
Origin::signed(1),
|
||||
TEST_RELAYER_A,
|
||||
proof,
|
||||
messages_count,
|
||||
REGULAR_PAYLOAD.declared_weight,
|
||||
)
|
||||
.expect("delivery has failed")
|
||||
.actual_weight
|
||||
.expect("receive_messages_proof always returns Some");
|
||||
|
||||
(pre_dispatch_weight, post_dispatch_weight)
|
||||
}
|
||||
|
||||
// when dispatch is returning `unspent_weight < declared_weight`
|
||||
let (pre, post) = submit_with_unspent_weight(1, 1, false);
|
||||
assert_eq!(post, pre - 1);
|
||||
|
||||
// when dispatch is returning `unspent_weight = declared_weight`
|
||||
let (pre, post) = submit_with_unspent_weight(2, REGULAR_PAYLOAD.declared_weight, false);
|
||||
assert_eq!(post, pre - REGULAR_PAYLOAD.declared_weight);
|
||||
|
||||
// when dispatch is returning `unspent_weight > declared_weight`
|
||||
let (pre, post) = submit_with_unspent_weight(3, REGULAR_PAYLOAD.declared_weight + 1, false);
|
||||
assert_eq!(post, pre - REGULAR_PAYLOAD.declared_weight);
|
||||
|
||||
// when there's no unspent weight
|
||||
let (pre, post) = submit_with_unspent_weight(4, 0, false);
|
||||
assert_eq!(post, pre);
|
||||
|
||||
// when dispatch is returning `unspent_weight < declared_weight` AND message is prepaid
|
||||
let (pre, post) = submit_with_unspent_weight(5, 1, true);
|
||||
assert_eq!(
|
||||
post,
|
||||
pre - 1 - <TestRuntime as Config>::WeightInfo::pay_inbound_dispatch_fee_overhead()
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn messages_delivered_callbacks_are_called() {
|
||||
run_test(|| {
|
||||
send_regular_message();
|
||||
send_regular_message();
|
||||
send_regular_message();
|
||||
|
||||
// messages 1+2 are confirmed in 1 tx, message 3 in a separate tx
|
||||
// dispatch of message 2 has failed
|
||||
let mut delivered_messages_1_and_2 = DeliveredMessages::new(1, true);
|
||||
delivered_messages_1_and_2.note_dispatched_message(false);
|
||||
let messages_1_and_2_proof = Ok((
|
||||
TEST_LANE_ID,
|
||||
InboundLaneData {
|
||||
last_confirmed_nonce: 0,
|
||||
relayers: vec![UnrewardedRelayer {
|
||||
relayer: 0,
|
||||
messages: delivered_messages_1_and_2.clone(),
|
||||
}]
|
||||
.into_iter()
|
||||
.collect(),
|
||||
},
|
||||
));
|
||||
let delivered_message_3 = DeliveredMessages::new(3, true);
|
||||
let messages_3_proof = Ok((
|
||||
TEST_LANE_ID,
|
||||
InboundLaneData {
|
||||
last_confirmed_nonce: 0,
|
||||
relayers: vec![UnrewardedRelayer {
|
||||
relayer: 0,
|
||||
messages: delivered_message_3.clone(),
|
||||
}]
|
||||
.into_iter()
|
||||
.collect(),
|
||||
},
|
||||
));
|
||||
|
||||
// first tx with messages 1+2
|
||||
assert_ok!(Pallet::<TestRuntime>::receive_messages_delivery_proof(
|
||||
Origin::signed(1),
|
||||
TestMessagesDeliveryProof(messages_1_and_2_proof),
|
||||
UnrewardedRelayersState {
|
||||
unrewarded_relayer_entries: 1,
|
||||
total_messages: 2,
|
||||
..Default::default()
|
||||
},
|
||||
));
|
||||
// second tx with message 3
|
||||
assert_ok!(Pallet::<TestRuntime>::receive_messages_delivery_proof(
|
||||
Origin::signed(1),
|
||||
TestMessagesDeliveryProof(messages_3_proof),
|
||||
UnrewardedRelayersState {
|
||||
unrewarded_relayer_entries: 1,
|
||||
total_messages: 1,
|
||||
..Default::default()
|
||||
},
|
||||
));
|
||||
|
||||
// ensure that both callbacks have been called twice: for 1+2, then for 3
|
||||
crate::mock::TestOnDeliveryConfirmed1::ensure_called(&TEST_LANE_ID, &delivered_messages_1_and_2);
|
||||
crate::mock::TestOnDeliveryConfirmed1::ensure_called(&TEST_LANE_ID, &delivered_message_3);
|
||||
crate::mock::TestOnDeliveryConfirmed2::ensure_called(&TEST_LANE_ID, &delivered_messages_1_and_2);
|
||||
crate::mock::TestOnDeliveryConfirmed2::ensure_called(&TEST_LANE_ID, &delivered_message_3);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user