mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-05-30 21:01:02 +00:00
Relay basic single-bit message dispatch results back to the source chain (#935)
* relay dispatch result flags back to the source chain * OnMessagesDelivered callback * add lane id to OnDeliveredMessages callback * fix benchmarks && upate weights * clippy * clippy * clipy another try * OnMessagesDelivered -> OnDeliveryConfirmed * Update primitives/messages/src/source_chain.rs Co-authored-by: Tomasz Drwięga <tomusdrw@users.noreply.github.com> Co-authored-by: Tomasz Drwięga <tomusdrw@users.noreply.github.com>
This commit is contained in:
committed by
Bastian Köcher
parent
87c48f649b
commit
ee43a560f8
@@ -384,6 +384,7 @@ impl pallet_bridge_messages::Config<WithRialtoMessagesInstance> for Runtime {
|
|||||||
GetDeliveryConfirmationTransactionFee,
|
GetDeliveryConfirmationTransactionFee,
|
||||||
RootAccountForPayments,
|
RootAccountForPayments,
|
||||||
>;
|
>;
|
||||||
|
type OnDeliveryConfirmed = ();
|
||||||
|
|
||||||
type SourceHeaderChain = crate::rialto_messages::Rialto;
|
type SourceHeaderChain = crate::rialto_messages::Rialto;
|
||||||
type MessageDispatch = crate::rialto_messages::FromRialtoMessageDispatch;
|
type MessageDispatch = crate::rialto_messages::FromRialtoMessageDispatch;
|
||||||
@@ -702,6 +703,7 @@ mod tests {
|
|||||||
let max_incoming_inbound_lane_data_proof_size = bp_messages::InboundLaneData::<()>::encoded_size_hint(
|
let max_incoming_inbound_lane_data_proof_size = bp_messages::InboundLaneData::<()>::encoded_size_hint(
|
||||||
bp_millau::MAXIMAL_ENCODED_ACCOUNT_ID_SIZE,
|
bp_millau::MAXIMAL_ENCODED_ACCOUNT_ID_SIZE,
|
||||||
bp_rialto::MAX_UNREWARDED_RELAYER_ENTRIES_AT_INBOUND_LANE as _,
|
bp_rialto::MAX_UNREWARDED_RELAYER_ENTRIES_AT_INBOUND_LANE as _,
|
||||||
|
bp_rialto::MAX_UNCONFIRMED_MESSAGES_AT_INBOUND_LANE as _,
|
||||||
)
|
)
|
||||||
.unwrap_or(u32::MAX);
|
.unwrap_or(u32::MAX);
|
||||||
pallet_bridge_messages::ensure_able_to_receive_confirmation::<Weights>(
|
pallet_bridge_messages::ensure_able_to_receive_confirmation::<Weights>(
|
||||||
|
|||||||
@@ -113,9 +113,12 @@ impl messages::ThisChainWithMessages for Millau {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn estimate_delivery_confirmation_transaction() -> MessageTransaction<Weight> {
|
fn estimate_delivery_confirmation_transaction() -> MessageTransaction<Weight> {
|
||||||
let inbound_data_size =
|
let inbound_data_size = InboundLaneData::<bp_millau::AccountId>::encoded_size_hint(
|
||||||
InboundLaneData::<bp_millau::AccountId>::encoded_size_hint(bp_millau::MAXIMAL_ENCODED_ACCOUNT_ID_SIZE, 1)
|
bp_millau::MAXIMAL_ENCODED_ACCOUNT_ID_SIZE,
|
||||||
.unwrap_or(u32::MAX);
|
1,
|
||||||
|
1,
|
||||||
|
)
|
||||||
|
.unwrap_or(u32::MAX);
|
||||||
|
|
||||||
MessageTransaction {
|
MessageTransaction {
|
||||||
dispatch_weight: bp_millau::MAX_SINGLE_MESSAGE_DELIVERY_CONFIRMATION_TX_WEIGHT,
|
dispatch_weight: bp_millau::MAX_SINGLE_MESSAGE_DELIVERY_CONFIRMATION_TX_WEIGHT,
|
||||||
|
|||||||
@@ -491,6 +491,7 @@ impl pallet_bridge_messages::Config<WithMillauMessagesInstance> for Runtime {
|
|||||||
GetDeliveryConfirmationTransactionFee,
|
GetDeliveryConfirmationTransactionFee,
|
||||||
RootAccountForPayments,
|
RootAccountForPayments,
|
||||||
>;
|
>;
|
||||||
|
type OnDeliveryConfirmed = ();
|
||||||
|
|
||||||
type SourceHeaderChain = crate::millau_messages::Millau;
|
type SourceHeaderChain = crate::millau_messages::Millau;
|
||||||
type MessageDispatch = crate::millau_messages::FromMillauMessageDispatch;
|
type MessageDispatch = crate::millau_messages::FromMillauMessageDispatch;
|
||||||
@@ -1028,7 +1029,7 @@ impl_runtime_apis! {
|
|||||||
.map(|event_record| event_record.event)
|
.map(|event_record| event_record.event)
|
||||||
.any(|event| matches!(
|
.any(|event| matches!(
|
||||||
event,
|
event,
|
||||||
Event::pallet_bridge_dispatch(pallet_bridge_dispatch::Event::<Runtime, _>::MessageDispatched(
|
Event::BridgeDispatch(pallet_bridge_dispatch::Event::<Runtime, _>::MessageDispatched(
|
||||||
_, ([0, 0, 0, 0], nonce_from_event), _,
|
_, ([0, 0, 0, 0], nonce_from_event), _,
|
||||||
)) if nonce_from_event == nonce
|
)) if nonce_from_event == nonce
|
||||||
))
|
))
|
||||||
@@ -1144,6 +1145,7 @@ mod tests {
|
|||||||
let max_incoming_inbound_lane_data_proof_size = bp_messages::InboundLaneData::<()>::encoded_size_hint(
|
let max_incoming_inbound_lane_data_proof_size = bp_messages::InboundLaneData::<()>::encoded_size_hint(
|
||||||
bp_rialto::MAXIMAL_ENCODED_ACCOUNT_ID_SIZE,
|
bp_rialto::MAXIMAL_ENCODED_ACCOUNT_ID_SIZE,
|
||||||
bp_millau::MAX_UNREWARDED_RELAYER_ENTRIES_AT_INBOUND_LANE as _,
|
bp_millau::MAX_UNREWARDED_RELAYER_ENTRIES_AT_INBOUND_LANE as _,
|
||||||
|
bp_millau::MAX_UNCONFIRMED_MESSAGES_AT_INBOUND_LANE as _,
|
||||||
)
|
)
|
||||||
.unwrap_or(u32::MAX);
|
.unwrap_or(u32::MAX);
|
||||||
pallet_bridge_messages::ensure_able_to_receive_confirmation::<Weights>(
|
pallet_bridge_messages::ensure_able_to_receive_confirmation::<Weights>(
|
||||||
|
|||||||
@@ -113,9 +113,12 @@ impl messages::ThisChainWithMessages for Rialto {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn estimate_delivery_confirmation_transaction() -> MessageTransaction<Weight> {
|
fn estimate_delivery_confirmation_transaction() -> MessageTransaction<Weight> {
|
||||||
let inbound_data_size =
|
let inbound_data_size = InboundLaneData::<bp_rialto::AccountId>::encoded_size_hint(
|
||||||
InboundLaneData::<bp_rialto::AccountId>::encoded_size_hint(bp_rialto::MAXIMAL_ENCODED_ACCOUNT_ID_SIZE, 1)
|
bp_rialto::MAXIMAL_ENCODED_ACCOUNT_ID_SIZE,
|
||||||
.unwrap_or(u32::MAX);
|
1,
|
||||||
|
1,
|
||||||
|
)
|
||||||
|
.unwrap_or(u32::MAX);
|
||||||
|
|
||||||
MessageTransaction {
|
MessageTransaction {
|
||||||
dispatch_weight: bp_rialto::MAX_SINGLE_MESSAGE_DELIVERY_CONFIRMATION_TX_WEIGHT,
|
dispatch_weight: bp_rialto::MAX_SINGLE_MESSAGE_DELIVERY_CONFIRMATION_TX_WEIGHT,
|
||||||
|
|||||||
@@ -154,6 +154,7 @@ impl<T: Config<I>, I: Instance> MessageDispatch<T::AccountId, T::MessageId> for
|
|||||||
);
|
);
|
||||||
Self::deposit_event(RawEvent::MessageRejected(source_chain, id));
|
Self::deposit_event(RawEvent::MessageRejected(source_chain, id));
|
||||||
return MessageDispatchResult {
|
return MessageDispatchResult {
|
||||||
|
dispatch_result: false,
|
||||||
unspent_weight: 0,
|
unspent_weight: 0,
|
||||||
dispatch_fee_paid_during_dispatch: false,
|
dispatch_fee_paid_during_dispatch: false,
|
||||||
};
|
};
|
||||||
@@ -163,6 +164,7 @@ impl<T: Config<I>, I: Instance> MessageDispatch<T::AccountId, T::MessageId> for
|
|||||||
// verify spec version
|
// verify spec version
|
||||||
// (we want it to be the same, because otherwise we may decode Call improperly)
|
// (we want it to be the same, because otherwise we may decode Call improperly)
|
||||||
let mut dispatch_result = MessageDispatchResult {
|
let mut dispatch_result = MessageDispatchResult {
|
||||||
|
dispatch_result: false,
|
||||||
unspent_weight: message.weight,
|
unspent_weight: message.weight,
|
||||||
dispatch_fee_paid_during_dispatch: false,
|
dispatch_fee_paid_during_dispatch: false,
|
||||||
};
|
};
|
||||||
@@ -303,6 +305,7 @@ impl<T: Config<I>, I: Instance> MessageDispatch<T::AccountId, T::MessageId> for
|
|||||||
log::trace!(target: "runtime::bridge-dispatch", "Message being dispatched is: {:.4096?}", &call);
|
log::trace!(target: "runtime::bridge-dispatch", "Message being dispatched is: {:.4096?}", &call);
|
||||||
let result = call.dispatch(origin);
|
let result = call.dispatch(origin);
|
||||||
let actual_call_weight = extract_actual_weight(&result, &dispatch_info);
|
let actual_call_weight = extract_actual_weight(&result, &dispatch_info);
|
||||||
|
dispatch_result.dispatch_result = result.is_ok();
|
||||||
dispatch_result.unspent_weight = message.weight.saturating_sub(actual_call_weight);
|
dispatch_result.unspent_weight = message.weight.saturating_sub(actual_call_weight);
|
||||||
|
|
||||||
log::trace!(
|
log::trace!(
|
||||||
@@ -573,6 +576,7 @@ mod tests {
|
|||||||
System::set_block_number(1);
|
System::set_block_number(1);
|
||||||
let result = Dispatch::dispatch(SOURCE_CHAIN_ID, TARGET_CHAIN_ID, id, Ok(message), |_, _| unreachable!());
|
let result = Dispatch::dispatch(SOURCE_CHAIN_ID, TARGET_CHAIN_ID, id, Ok(message), |_, _| unreachable!());
|
||||||
assert_eq!(result.unspent_weight, weight);
|
assert_eq!(result.unspent_weight, weight);
|
||||||
|
assert!(!result.dispatch_result);
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
System::events(),
|
System::events(),
|
||||||
@@ -601,6 +605,7 @@ mod tests {
|
|||||||
System::set_block_number(1);
|
System::set_block_number(1);
|
||||||
let result = Dispatch::dispatch(SOURCE_CHAIN_ID, TARGET_CHAIN_ID, id, Ok(message), |_, _| unreachable!());
|
let result = Dispatch::dispatch(SOURCE_CHAIN_ID, TARGET_CHAIN_ID, id, Ok(message), |_, _| unreachable!());
|
||||||
assert_eq!(result.unspent_weight, 7);
|
assert_eq!(result.unspent_weight, 7);
|
||||||
|
assert!(!result.dispatch_result);
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
System::events(),
|
System::events(),
|
||||||
@@ -633,6 +638,7 @@ mod tests {
|
|||||||
System::set_block_number(1);
|
System::set_block_number(1);
|
||||||
let result = Dispatch::dispatch(SOURCE_CHAIN_ID, TARGET_CHAIN_ID, id, Ok(message), |_, _| unreachable!());
|
let result = Dispatch::dispatch(SOURCE_CHAIN_ID, TARGET_CHAIN_ID, id, Ok(message), |_, _| unreachable!());
|
||||||
assert_eq!(result.unspent_weight, weight);
|
assert_eq!(result.unspent_weight, weight);
|
||||||
|
assert!(!result.dispatch_result);
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
System::events(),
|
System::events(),
|
||||||
@@ -683,6 +689,7 @@ mod tests {
|
|||||||
System::set_block_number(1);
|
System::set_block_number(1);
|
||||||
let result = Dispatch::dispatch(SOURCE_CHAIN_ID, TARGET_CHAIN_ID, id, Ok(message), |_, _| unreachable!());
|
let result = Dispatch::dispatch(SOURCE_CHAIN_ID, TARGET_CHAIN_ID, id, Ok(message), |_, _| unreachable!());
|
||||||
assert_eq!(result.unspent_weight, weight);
|
assert_eq!(result.unspent_weight, weight);
|
||||||
|
assert!(!result.dispatch_result);
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
System::events(),
|
System::events(),
|
||||||
@@ -711,6 +718,7 @@ mod tests {
|
|||||||
System::set_block_number(1);
|
System::set_block_number(1);
|
||||||
let result = Dispatch::dispatch(SOURCE_CHAIN_ID, TARGET_CHAIN_ID, id, Ok(message), |_, _| unreachable!());
|
let result = Dispatch::dispatch(SOURCE_CHAIN_ID, TARGET_CHAIN_ID, id, Ok(message), |_, _| unreachable!());
|
||||||
assert_eq!(result.unspent_weight, weight);
|
assert_eq!(result.unspent_weight, weight);
|
||||||
|
assert!(!result.dispatch_result);
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
System::events(),
|
System::events(),
|
||||||
@@ -739,12 +747,13 @@ mod tests {
|
|||||||
System::set_block_number(1);
|
System::set_block_number(1);
|
||||||
let result = Dispatch::dispatch(SOURCE_CHAIN_ID, TARGET_CHAIN_ID, id, Ok(message), |_, _| Err(()));
|
let result = Dispatch::dispatch(SOURCE_CHAIN_ID, TARGET_CHAIN_ID, id, Ok(message), |_, _| Err(()));
|
||||||
assert_eq!(result.unspent_weight, weight);
|
assert_eq!(result.unspent_weight, weight);
|
||||||
|
assert!(!result.dispatch_result);
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
System::events(),
|
System::events(),
|
||||||
vec![EventRecord {
|
vec![EventRecord {
|
||||||
phase: Phase::Initialization,
|
phase: Phase::Initialization,
|
||||||
event: Event::call_dispatch(call_dispatch::Event::<TestRuntime>::MessageDispatchPaymentFailed(
|
event: Event::Dispatch(call_dispatch::Event::<TestRuntime>::MessageDispatchPaymentFailed(
|
||||||
SOURCE_CHAIN_ID,
|
SOURCE_CHAIN_ID,
|
||||||
id,
|
id,
|
||||||
AccountIdConverter::convert(derive_account_id::<AccountId>(
|
AccountIdConverter::convert(derive_account_id::<AccountId>(
|
||||||
@@ -771,12 +780,13 @@ mod tests {
|
|||||||
System::set_block_number(1);
|
System::set_block_number(1);
|
||||||
let result = Dispatch::dispatch(SOURCE_CHAIN_ID, TARGET_CHAIN_ID, id, Ok(message), |_, _| Ok(()));
|
let result = Dispatch::dispatch(SOURCE_CHAIN_ID, TARGET_CHAIN_ID, id, Ok(message), |_, _| Ok(()));
|
||||||
assert!(result.dispatch_fee_paid_during_dispatch);
|
assert!(result.dispatch_fee_paid_during_dispatch);
|
||||||
|
assert!(result.dispatch_result);
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
System::events(),
|
System::events(),
|
||||||
vec![EventRecord {
|
vec![EventRecord {
|
||||||
phase: Phase::Initialization,
|
phase: Phase::Initialization,
|
||||||
event: Event::call_dispatch(call_dispatch::Event::<TestRuntime>::MessageDispatched(
|
event: Event::Dispatch(call_dispatch::Event::<TestRuntime>::MessageDispatched(
|
||||||
SOURCE_CHAIN_ID,
|
SOURCE_CHAIN_ID,
|
||||||
id,
|
id,
|
||||||
Ok(())
|
Ok(())
|
||||||
@@ -787,6 +797,34 @@ mod tests {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn should_return_dispatch_failed_flag_if_dispatch_happened_but_failed() {
|
||||||
|
new_test_ext().execute_with(|| {
|
||||||
|
let id = [0; 4];
|
||||||
|
|
||||||
|
let call = Call::System(<frame_system::Call<TestRuntime>>::set_heap_pages(1));
|
||||||
|
let message = prepare_target_message(call);
|
||||||
|
|
||||||
|
System::set_block_number(1);
|
||||||
|
let result = Dispatch::dispatch(SOURCE_CHAIN_ID, TARGET_CHAIN_ID, id, Ok(message), |_, _| unreachable!());
|
||||||
|
assert!(!result.dispatch_fee_paid_during_dispatch);
|
||||||
|
assert!(!result.dispatch_result);
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
System::events(),
|
||||||
|
vec![EventRecord {
|
||||||
|
phase: Phase::Initialization,
|
||||||
|
event: Event::Dispatch(call_dispatch::Event::<TestRuntime>::MessageDispatched(
|
||||||
|
SOURCE_CHAIN_ID,
|
||||||
|
id,
|
||||||
|
Err(sp_runtime::DispatchError::BadOrigin)
|
||||||
|
)),
|
||||||
|
topics: vec![],
|
||||||
|
}],
|
||||||
|
);
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn should_dispatch_bridge_message_from_root_origin() {
|
fn should_dispatch_bridge_message_from_root_origin() {
|
||||||
new_test_ext().execute_with(|| {
|
new_test_ext().execute_with(|| {
|
||||||
@@ -796,6 +834,7 @@ mod tests {
|
|||||||
System::set_block_number(1);
|
System::set_block_number(1);
|
||||||
let result = Dispatch::dispatch(SOURCE_CHAIN_ID, TARGET_CHAIN_ID, id, Ok(message), |_, _| unreachable!());
|
let result = Dispatch::dispatch(SOURCE_CHAIN_ID, TARGET_CHAIN_ID, id, Ok(message), |_, _| unreachable!());
|
||||||
assert!(!result.dispatch_fee_paid_during_dispatch);
|
assert!(!result.dispatch_fee_paid_during_dispatch);
|
||||||
|
assert!(result.dispatch_result);
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
System::events(),
|
System::events(),
|
||||||
@@ -823,6 +862,7 @@ mod tests {
|
|||||||
System::set_block_number(1);
|
System::set_block_number(1);
|
||||||
let result = Dispatch::dispatch(SOURCE_CHAIN_ID, TARGET_CHAIN_ID, id, Ok(message), |_, _| unreachable!());
|
let result = Dispatch::dispatch(SOURCE_CHAIN_ID, TARGET_CHAIN_ID, id, Ok(message), |_, _| unreachable!());
|
||||||
assert!(!result.dispatch_fee_paid_during_dispatch);
|
assert!(!result.dispatch_fee_paid_during_dispatch);
|
||||||
|
assert!(result.dispatch_result);
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
System::events(),
|
System::events(),
|
||||||
@@ -850,6 +890,7 @@ mod tests {
|
|||||||
System::set_block_number(1);
|
System::set_block_number(1);
|
||||||
let result = Dispatch::dispatch(SOURCE_CHAIN_ID, TARGET_CHAIN_ID, id, Ok(message), |_, _| unreachable!());
|
let result = Dispatch::dispatch(SOURCE_CHAIN_ID, TARGET_CHAIN_ID, id, Ok(message), |_, _| unreachable!());
|
||||||
assert!(!result.dispatch_fee_paid_during_dispatch);
|
assert!(!result.dispatch_fee_paid_during_dispatch);
|
||||||
|
assert!(result.dispatch_result);
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
System::events(),
|
System::events(),
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ edition = "2018"
|
|||||||
license = "GPL-3.0-or-later WITH Classpath-exception-2.0"
|
license = "GPL-3.0-or-later WITH Classpath-exception-2.0"
|
||||||
|
|
||||||
[dependencies]
|
[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.0.0", default-features = false }
|
||||||
log = { version = "0.4.14", default-features = false }
|
log = { version = "0.4.14", default-features = false }
|
||||||
num-traits = { version = "0.2", default-features = false }
|
num-traits = { version = "0.2", default-features = false }
|
||||||
|
|||||||
@@ -101,7 +101,14 @@ the `MessageAccepted` event is emitted in the `send_message()` transaction. The
|
|||||||
message lane identifier and nonce that has been assigned to the message. When a message is delivered
|
message lane identifier and nonce that has been assigned to the message. When a message is delivered
|
||||||
to the target chain, the `MessagesDelivered` event is emitted from the
|
to the target chain, the `MessagesDelivered` event is emitted from the
|
||||||
`receive_messages_delivery_proof()` transaction. The `MessagesDelivered` contains the message lane
|
`receive_messages_delivery_proof()` transaction. The `MessagesDelivered` contains the message lane
|
||||||
identifier and inclusive range of delivered message nonces.
|
identifier, inclusive range of delivered message nonces and their single-bit dispatch results.
|
||||||
|
|
||||||
|
Please note that the meaning of the 'dispatch result' is determined by the message dispatcher at
|
||||||
|
the target chain. For example, in case of immediate call dispatcher it will be the `true` if call
|
||||||
|
has been successfully dispatched and `false` if it has only been delivered. This simple mechanism
|
||||||
|
built into the messages module allows building basic bridge applications, which only care whether
|
||||||
|
their messages have been successfully dispatched or not. More sophisticated applications may use
|
||||||
|
their own dispatch result delivery mechanism to deliver something larger than single bit.
|
||||||
|
|
||||||
### How to plug-in Messages Module to Send Messages to the Bridged Chain?
|
### How to plug-in Messages Module to Send Messages to the Bridged Chain?
|
||||||
|
|
||||||
|
|||||||
@@ -17,17 +17,25 @@
|
|||||||
//! Messages pallet benchmarking.
|
//! Messages pallet benchmarking.
|
||||||
|
|
||||||
use crate::weights_ext::EXPECTED_DEFAULT_MESSAGE_LENGTH;
|
use crate::weights_ext::EXPECTED_DEFAULT_MESSAGE_LENGTH;
|
||||||
use crate::{inbound_lane::InboundLaneStorage, inbound_lane_storage, outbound_lane, Call, Instance};
|
use crate::{
|
||||||
|
inbound_lane::InboundLaneStorage, inbound_lane_storage, outbound_lane, outbound_lane::ReceivalConfirmationResult,
|
||||||
|
Call, Instance,
|
||||||
|
};
|
||||||
|
|
||||||
use bp_messages::{
|
use bp_messages::{
|
||||||
source_chain::TargetHeaderChain, target_chain::SourceHeaderChain, InboundLaneData, LaneId, MessageData,
|
source_chain::TargetHeaderChain, target_chain::SourceHeaderChain, DeliveredMessages, InboundLaneData, LaneId,
|
||||||
MessageNonce, OutboundLaneData, UnrewardedRelayersState,
|
MessageData, MessageNonce, OutboundLaneData, UnrewardedRelayer, UnrewardedRelayersState,
|
||||||
};
|
};
|
||||||
use bp_runtime::messages::DispatchFeePayment;
|
use bp_runtime::messages::DispatchFeePayment;
|
||||||
use frame_benchmarking::{account, benchmarks_instance};
|
use frame_benchmarking::{account, benchmarks_instance};
|
||||||
use frame_support::{traits::Get, weights::Weight};
|
use frame_support::{traits::Get, weights::Weight};
|
||||||
use frame_system::RawOrigin;
|
use frame_system::RawOrigin;
|
||||||
use sp_std::{collections::btree_map::BTreeMap, convert::TryInto, ops::RangeInclusive, prelude::*};
|
use sp_std::{
|
||||||
|
collections::{btree_map::BTreeMap, vec_deque::VecDeque},
|
||||||
|
convert::TryInto,
|
||||||
|
ops::RangeInclusive,
|
||||||
|
prelude::*,
|
||||||
|
};
|
||||||
|
|
||||||
/// Fee paid by submitter for single message delivery.
|
/// Fee paid by submitter for single message delivery.
|
||||||
pub const MESSAGE_FEE: u64 = 10_000_000_000;
|
pub const MESSAGE_FEE: u64 = 10_000_000_000;
|
||||||
@@ -471,7 +479,10 @@ benchmarks_instance! {
|
|||||||
let proof = T::prepare_message_delivery_proof(MessageDeliveryProofParams {
|
let proof = T::prepare_message_delivery_proof(MessageDeliveryProofParams {
|
||||||
lane: T::bench_lane_id(),
|
lane: T::bench_lane_id(),
|
||||||
inbound_lane_data: InboundLaneData {
|
inbound_lane_data: InboundLaneData {
|
||||||
relayers: vec![(1, 1, relayer_id.clone())].into_iter().collect(),
|
relayers: vec![UnrewardedRelayer {
|
||||||
|
relayer: relayer_id.clone(),
|
||||||
|
messages: DeliveredMessages::new(1, true),
|
||||||
|
}].into_iter().collect(),
|
||||||
last_confirmed_nonce: 0,
|
last_confirmed_nonce: 0,
|
||||||
},
|
},
|
||||||
size: ProofSize::Minimal(0),
|
size: ProofSize::Minimal(0),
|
||||||
@@ -506,10 +517,15 @@ benchmarks_instance! {
|
|||||||
messages_in_oldest_entry: 2,
|
messages_in_oldest_entry: 2,
|
||||||
total_messages: 2,
|
total_messages: 2,
|
||||||
};
|
};
|
||||||
|
let mut delivered_messages = DeliveredMessages::new(1, true);
|
||||||
|
delivered_messages.note_dispatched_message(true);
|
||||||
let proof = T::prepare_message_delivery_proof(MessageDeliveryProofParams {
|
let proof = T::prepare_message_delivery_proof(MessageDeliveryProofParams {
|
||||||
lane: T::bench_lane_id(),
|
lane: T::bench_lane_id(),
|
||||||
inbound_lane_data: InboundLaneData {
|
inbound_lane_data: InboundLaneData {
|
||||||
relayers: vec![(1, 2, relayer_id.clone())].into_iter().collect(),
|
relayers: vec![UnrewardedRelayer {
|
||||||
|
relayer: relayer_id.clone(),
|
||||||
|
messages: delivered_messages,
|
||||||
|
}].into_iter().collect(),
|
||||||
last_confirmed_nonce: 0,
|
last_confirmed_nonce: 0,
|
||||||
},
|
},
|
||||||
size: ProofSize::Minimal(0),
|
size: ProofSize::Minimal(0),
|
||||||
@@ -547,8 +563,14 @@ benchmarks_instance! {
|
|||||||
lane: T::bench_lane_id(),
|
lane: T::bench_lane_id(),
|
||||||
inbound_lane_data: InboundLaneData {
|
inbound_lane_data: InboundLaneData {
|
||||||
relayers: vec![
|
relayers: vec![
|
||||||
(1, 1, relayer1_id.clone()),
|
UnrewardedRelayer {
|
||||||
(2, 2, relayer2_id.clone()),
|
relayer: relayer1_id.clone(),
|
||||||
|
messages: DeliveredMessages::new(1, true),
|
||||||
|
},
|
||||||
|
UnrewardedRelayer {
|
||||||
|
relayer: relayer2_id.clone(),
|
||||||
|
messages: DeliveredMessages::new(2, true),
|
||||||
|
},
|
||||||
].into_iter().collect(),
|
].into_iter().collect(),
|
||||||
last_confirmed_nonce: 0,
|
last_confirmed_nonce: 0,
|
||||||
},
|
},
|
||||||
@@ -783,10 +805,17 @@ benchmarks_instance! {
|
|||||||
messages_in_oldest_entry: 1,
|
messages_in_oldest_entry: 1,
|
||||||
total_messages: i as MessageNonce,
|
total_messages: i as MessageNonce,
|
||||||
};
|
};
|
||||||
|
let mut delivered_messages = DeliveredMessages::new(1, true);
|
||||||
|
for nonce in 2..=i {
|
||||||
|
delivered_messages.note_dispatched_message(true);
|
||||||
|
}
|
||||||
let proof = T::prepare_message_delivery_proof(MessageDeliveryProofParams {
|
let proof = T::prepare_message_delivery_proof(MessageDeliveryProofParams {
|
||||||
lane: T::bench_lane_id(),
|
lane: T::bench_lane_id(),
|
||||||
inbound_lane_data: InboundLaneData {
|
inbound_lane_data: InboundLaneData {
|
||||||
relayers: vec![(1, i as MessageNonce, relayer_id.clone())].into_iter().collect(),
|
relayers: vec![UnrewardedRelayer {
|
||||||
|
relayer: relayer_id.clone(),
|
||||||
|
messages: delivered_messages,
|
||||||
|
}].into_iter().collect(),
|
||||||
last_confirmed_nonce: 0,
|
last_confirmed_nonce: 0,
|
||||||
},
|
},
|
||||||
size: ProofSize::Minimal(0),
|
size: ProofSize::Minimal(0),
|
||||||
@@ -831,7 +860,10 @@ benchmarks_instance! {
|
|||||||
relayers: relayers
|
relayers: relayers
|
||||||
.keys()
|
.keys()
|
||||||
.enumerate()
|
.enumerate()
|
||||||
.map(|(j, relayer_id)| (j as MessageNonce + 1, j as MessageNonce + 1, relayer_id.clone()))
|
.map(|(j, relayer)| UnrewardedRelayer {
|
||||||
|
relayer: relayer.clone(),
|
||||||
|
messages: DeliveredMessages::new(j as MessageNonce + 1, true),
|
||||||
|
})
|
||||||
.collect(),
|
.collect(),
|
||||||
last_confirmed_nonce: 0,
|
last_confirmed_nonce: 0,
|
||||||
},
|
},
|
||||||
@@ -863,13 +895,29 @@ fn send_regular_message_with_payload<T: Config<I>, I: Instance>(payload: Vec<u8>
|
|||||||
|
|
||||||
fn confirm_message_delivery<T: Config<I>, I: Instance>(nonce: MessageNonce) {
|
fn confirm_message_delivery<T: Config<I>, I: Instance>(nonce: MessageNonce) {
|
||||||
let mut outbound_lane = outbound_lane::<T, I>(T::bench_lane_id());
|
let mut outbound_lane = outbound_lane::<T, I>(T::bench_lane_id());
|
||||||
assert!(outbound_lane.confirm_delivery(nonce).is_some());
|
let latest_received_nonce = outbound_lane.data().latest_received_nonce;
|
||||||
|
let mut relayers = VecDeque::with_capacity((nonce - latest_received_nonce) as usize);
|
||||||
|
for nonce in latest_received_nonce + 1..=nonce {
|
||||||
|
relayers.push_back(UnrewardedRelayer {
|
||||||
|
relayer: (),
|
||||||
|
messages: DeliveredMessages::new(nonce, true),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
assert!(matches!(
|
||||||
|
outbound_lane.confirm_delivery(nonce, &relayers),
|
||||||
|
ReceivalConfirmationResult::ConfirmedMessages(_),
|
||||||
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn receive_messages<T: Config<I>, I: Instance>(nonce: MessageNonce) {
|
fn receive_messages<T: Config<I>, I: Instance>(nonce: MessageNonce) {
|
||||||
let mut inbound_lane_storage = inbound_lane_storage::<T, I>(T::bench_lane_id());
|
let mut inbound_lane_storage = inbound_lane_storage::<T, I>(T::bench_lane_id());
|
||||||
inbound_lane_storage.set_data(InboundLaneData {
|
inbound_lane_storage.set_data(InboundLaneData {
|
||||||
relayers: vec![(1, nonce, T::bridged_relayer_id())].into_iter().collect(),
|
relayers: vec![UnrewardedRelayer {
|
||||||
|
relayer: T::bridged_relayer_id(),
|
||||||
|
messages: DeliveredMessages::new(nonce, true),
|
||||||
|
}]
|
||||||
|
.into_iter()
|
||||||
|
.collect(),
|
||||||
last_confirmed_nonce: 0,
|
last_confirmed_nonce: 0,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,7 +18,7 @@
|
|||||||
|
|
||||||
use bp_messages::{
|
use bp_messages::{
|
||||||
target_chain::{DispatchMessage, DispatchMessageData, MessageDispatch},
|
target_chain::{DispatchMessage, DispatchMessageData, MessageDispatch},
|
||||||
InboundLaneData, LaneId, MessageKey, MessageNonce, OutboundLaneData,
|
DeliveredMessages, InboundLaneData, LaneId, MessageKey, MessageNonce, OutboundLaneData, UnrewardedRelayer,
|
||||||
};
|
};
|
||||||
use bp_runtime::messages::MessageDispatchResult;
|
use bp_runtime::messages::MessageDispatchResult;
|
||||||
use frame_support::RuntimeDebug;
|
use frame_support::RuntimeDebug;
|
||||||
@@ -89,7 +89,7 @@ impl<S: InboundLaneStorage> InboundLane<S> {
|
|||||||
while data
|
while data
|
||||||
.relayers
|
.relayers
|
||||||
.front()
|
.front()
|
||||||
.map(|(_, nonce_high, _)| *nonce_high <= new_confirmed_nonce)
|
.map(|entry| entry.messages.end <= new_confirmed_nonce)
|
||||||
.unwrap_or(false)
|
.unwrap_or(false)
|
||||||
{
|
{
|
||||||
data.relayers.pop_front();
|
data.relayers.pop_front();
|
||||||
@@ -97,8 +97,12 @@ impl<S: InboundLaneStorage> InboundLane<S> {
|
|||||||
// Secondly, update the next record with lower nonce equal to new confirmed nonce if needed.
|
// 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() {
|
match data.relayers.front_mut() {
|
||||||
Some((nonce_low, _, _)) if *nonce_low < new_confirmed_nonce => {
|
Some(entry) if entry.messages.begin < new_confirmed_nonce => {
|
||||||
*nonce_low = new_confirmed_nonce + 1;
|
entry.messages.dispatch_results = entry
|
||||||
|
.messages
|
||||||
|
.dispatch_results
|
||||||
|
.split_off((new_confirmed_nonce + 1 - entry.messages.begin) as _);
|
||||||
|
entry.messages.begin = new_confirmed_nonce + 1;
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
@@ -132,21 +136,10 @@ impl<S: InboundLaneStorage> InboundLane<S> {
|
|||||||
return ReceivalResult::TooManyUnconfirmedMessages;
|
return ReceivalResult::TooManyUnconfirmedMessages;
|
||||||
}
|
}
|
||||||
|
|
||||||
let push_new = match data.relayers.back_mut() {
|
// dispatch message before updating anything in the storage. If dispatch would panic,
|
||||||
Some((_, nonce_high, last_relayer)) if last_relayer == relayer_at_bridged_chain => {
|
// (which should not happen in the runtime) then we simply won't consider message as
|
||||||
*nonce_high = nonce;
|
// delivered (no changes to the inbound lane storage have been made).
|
||||||
false
|
let dispatch_result = P::dispatch(
|
||||||
}
|
|
||||||
_ => true,
|
|
||||||
};
|
|
||||||
if push_new {
|
|
||||||
data.relayers
|
|
||||||
.push_back((nonce, nonce, (*relayer_at_bridged_chain).clone()));
|
|
||||||
}
|
|
||||||
|
|
||||||
self.storage.set_data(data);
|
|
||||||
|
|
||||||
ReceivalResult::Dispatched(P::dispatch(
|
|
||||||
relayer_at_this_chain,
|
relayer_at_this_chain,
|
||||||
DispatchMessage {
|
DispatchMessage {
|
||||||
key: MessageKey {
|
key: MessageKey {
|
||||||
@@ -155,7 +148,25 @@ impl<S: InboundLaneStorage> InboundLane<S> {
|
|||||||
},
|
},
|
||||||
data: message_data,
|
data: message_data,
|
||||||
},
|
},
|
||||||
))
|
);
|
||||||
|
|
||||||
|
// now let's update inbound lane storage
|
||||||
|
let push_new = match data.relayers.back_mut() {
|
||||||
|
Some(entry) if entry.relayer == *relayer_at_bridged_chain => {
|
||||||
|
entry.messages.note_dispatched_message(dispatch_result.dispatch_result);
|
||||||
|
false
|
||||||
|
}
|
||||||
|
_ => true,
|
||||||
|
};
|
||||||
|
if push_new {
|
||||||
|
data.relayers.push_back(UnrewardedRelayer {
|
||||||
|
relayer: (*relayer_at_bridged_chain).clone(),
|
||||||
|
messages: DeliveredMessages::new(nonce, dispatch_result.dispatch_result),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
self.storage.set_data(data);
|
||||||
|
|
||||||
|
ReceivalResult::Dispatched(dispatch_result)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -165,8 +176,8 @@ mod tests {
|
|||||||
use crate::{
|
use crate::{
|
||||||
inbound_lane,
|
inbound_lane,
|
||||||
mock::{
|
mock::{
|
||||||
dispatch_result, message_data, run_test, TestMessageDispatch, TestRuntime, REGULAR_PAYLOAD, TEST_LANE_ID,
|
dispatch_result, message_data, run_test, unrewarded_relayer, TestMessageDispatch, TestRuntime,
|
||||||
TEST_RELAYER_A, TEST_RELAYER_B, TEST_RELAYER_C,
|
REGULAR_PAYLOAD, TEST_LANE_ID, TEST_RELAYER_A, TEST_RELAYER_B, TEST_RELAYER_C,
|
||||||
},
|
},
|
||||||
DefaultInstance, RuntimeInboundLaneStorage,
|
DefaultInstance, RuntimeInboundLaneStorage,
|
||||||
};
|
};
|
||||||
@@ -238,7 +249,10 @@ mod tests {
|
|||||||
receive_regular_message(&mut lane, 2);
|
receive_regular_message(&mut lane, 2);
|
||||||
receive_regular_message(&mut lane, 3);
|
receive_regular_message(&mut lane, 3);
|
||||||
assert_eq!(lane.storage.data().last_confirmed_nonce, 0);
|
assert_eq!(lane.storage.data().last_confirmed_nonce, 0);
|
||||||
assert_eq!(lane.storage.data().relayers, vec![(1, 3, TEST_RELAYER_A)]);
|
assert_eq!(
|
||||||
|
lane.storage.data().relayers,
|
||||||
|
vec![unrewarded_relayer(1, 3, TEST_RELAYER_A)]
|
||||||
|
);
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
lane.receive_state_update(OutboundLaneData {
|
lane.receive_state_update(OutboundLaneData {
|
||||||
@@ -248,7 +262,10 @@ mod tests {
|
|||||||
Some(2),
|
Some(2),
|
||||||
);
|
);
|
||||||
assert_eq!(lane.storage.data().last_confirmed_nonce, 2);
|
assert_eq!(lane.storage.data().last_confirmed_nonce, 2);
|
||||||
assert_eq!(lane.storage.data().relayers, vec![(3, 3, TEST_RELAYER_A)]);
|
assert_eq!(
|
||||||
|
lane.storage.data().relayers,
|
||||||
|
vec![unrewarded_relayer(3, 3, TEST_RELAYER_A)]
|
||||||
|
);
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
lane.receive_state_update(OutboundLaneData {
|
lane.receive_state_update(OutboundLaneData {
|
||||||
@@ -269,10 +286,16 @@ mod tests {
|
|||||||
let mut seed_storage_data = lane.storage.data();
|
let mut seed_storage_data = lane.storage.data();
|
||||||
// Prepare data
|
// Prepare data
|
||||||
seed_storage_data.last_confirmed_nonce = 0;
|
seed_storage_data.last_confirmed_nonce = 0;
|
||||||
seed_storage_data.relayers.push_back((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
|
// Simulate messages batch (2, 3, 4) from relayer #2
|
||||||
seed_storage_data.relayers.push_back((2, 4, TEST_RELAYER_B));
|
seed_storage_data
|
||||||
seed_storage_data.relayers.push_back((5, 5, TEST_RELAYER_C));
|
.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);
|
lane.storage.set_data(seed_storage_data);
|
||||||
// Check
|
// Check
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
@@ -285,7 +308,10 @@ mod tests {
|
|||||||
assert_eq!(lane.storage.data().last_confirmed_nonce, 3);
|
assert_eq!(lane.storage.data().last_confirmed_nonce, 3);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
lane.storage.data().relayers,
|
lane.storage.data().relayers,
|
||||||
vec![(4, 4, TEST_RELAYER_B), (5, 5, TEST_RELAYER_C)]
|
vec![
|
||||||
|
unrewarded_relayer(4, 4, TEST_RELAYER_B),
|
||||||
|
unrewarded_relayer(5, 5, TEST_RELAYER_C)
|
||||||
|
]
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -418,7 +444,11 @@ mod tests {
|
|||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
lane.storage.data().relayers,
|
lane.storage.data().relayers,
|
||||||
vec![(1, 1, TEST_RELAYER_A), (2, 2, TEST_RELAYER_B), (3, 3, TEST_RELAYER_A)]
|
vec![
|
||||||
|
unrewarded_relayer(1, 1, TEST_RELAYER_A),
|
||||||
|
unrewarded_relayer(2, 2, TEST_RELAYER_B),
|
||||||
|
unrewarded_relayer(3, 3, TEST_RELAYER_A)
|
||||||
|
]
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -43,21 +43,23 @@ pub use crate::weights_ext::{
|
|||||||
};
|
};
|
||||||
|
|
||||||
use crate::inbound_lane::{InboundLane, InboundLaneStorage, ReceivalResult};
|
use crate::inbound_lane::{InboundLane, InboundLaneStorage, ReceivalResult};
|
||||||
use crate::outbound_lane::{OutboundLane, OutboundLaneStorage};
|
use crate::outbound_lane::{OutboundLane, OutboundLaneStorage, ReceivalConfirmationResult};
|
||||||
use crate::weights::WeightInfo;
|
use crate::weights::WeightInfo;
|
||||||
|
|
||||||
use bp_messages::{
|
use bp_messages::{
|
||||||
source_chain::{LaneMessageVerifier, MessageDeliveryAndDispatchPayment, RelayersRewards, TargetHeaderChain},
|
source_chain::{
|
||||||
|
LaneMessageVerifier, MessageDeliveryAndDispatchPayment, OnDeliveryConfirmed, RelayersRewards, TargetHeaderChain,
|
||||||
|
},
|
||||||
target_chain::{DispatchMessage, MessageDispatch, ProvedLaneMessages, ProvedMessages, SourceHeaderChain},
|
target_chain::{DispatchMessage, MessageDispatch, ProvedLaneMessages, ProvedMessages, SourceHeaderChain},
|
||||||
total_unrewarded_messages, InboundLaneData, LaneId, MessageData, MessageKey, MessageNonce, OperatingMode,
|
total_unrewarded_messages, DeliveredMessages, InboundLaneData, LaneId, MessageData, MessageKey, MessageNonce,
|
||||||
OutboundLaneData, Parameter as MessagesParameter, UnrewardedRelayersState,
|
OperatingMode, OutboundLaneData, Parameter as MessagesParameter, UnrewardedRelayersState,
|
||||||
};
|
};
|
||||||
use bp_runtime::Size;
|
use bp_runtime::Size;
|
||||||
use codec::{Decode, Encode};
|
use codec::{Decode, Encode};
|
||||||
use frame_support::{
|
use frame_support::{
|
||||||
decl_error, decl_event, decl_module, decl_storage,
|
decl_error, decl_event, decl_module, decl_storage,
|
||||||
dispatch::DispatchResultWithPostInfo,
|
dispatch::DispatchResultWithPostInfo,
|
||||||
ensure,
|
ensure, fail,
|
||||||
traits::Get,
|
traits::Get,
|
||||||
weights::{DispatchClass, Pays, PostDispatchInfo, Weight},
|
weights::{DispatchClass, Pays, PostDispatchInfo, Weight},
|
||||||
Parameter, StorageMap,
|
Parameter, StorageMap,
|
||||||
@@ -146,6 +148,8 @@ pub trait Config<I = DefaultInstance>: frame_system::Config {
|
|||||||
type LaneMessageVerifier: LaneMessageVerifier<Self::AccountId, Self::OutboundPayload, Self::OutboundMessageFee>;
|
type LaneMessageVerifier: LaneMessageVerifier<Self::AccountId, Self::OutboundPayload, Self::OutboundMessageFee>;
|
||||||
/// Message delivery payment.
|
/// Message delivery payment.
|
||||||
type MessageDeliveryAndDispatchPayment: MessageDeliveryAndDispatchPayment<Self::AccountId, Self::OutboundMessageFee>;
|
type MessageDeliveryAndDispatchPayment: MessageDeliveryAndDispatchPayment<Self::AccountId, Self::OutboundMessageFee>;
|
||||||
|
/// Handler for delivered messages.
|
||||||
|
type OnDeliveryConfirmed: OnDeliveryConfirmed;
|
||||||
|
|
||||||
// Types that are used by inbound_lane (on target chain).
|
// Types that are used by inbound_lane (on target chain).
|
||||||
|
|
||||||
@@ -186,6 +190,8 @@ decl_error! {
|
|||||||
InvalidMessagesDispatchWeight,
|
InvalidMessagesDispatchWeight,
|
||||||
/// Invalid messages delivery proof has been submitted.
|
/// Invalid messages delivery proof has been submitted.
|
||||||
InvalidMessagesDeliveryProof,
|
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.
|
/// The relayer has declared invalid unrewarded relayers state in the `receive_messages_delivery_proof` call.
|
||||||
InvalidUnrewardedRelayersState,
|
InvalidUnrewardedRelayersState,
|
||||||
/// The message someone is trying to work with (i.e. increase fee) is already-delivered.
|
/// The message someone is trying to work with (i.e. increase fee) is already-delivered.
|
||||||
@@ -236,8 +242,8 @@ decl_event!(
|
|||||||
ParameterUpdated(Parameter),
|
ParameterUpdated(Parameter),
|
||||||
/// Message has been accepted and is waiting to be delivered.
|
/// Message has been accepted and is waiting to be delivered.
|
||||||
MessageAccepted(LaneId, MessageNonce),
|
MessageAccepted(LaneId, MessageNonce),
|
||||||
/// Messages in the inclusive range have been delivered and processed by the bridged chain.
|
/// Messages in the inclusive range have been delivered to the bridged chain.
|
||||||
MessagesDelivered(LaneId, MessageNonce, MessageNonce),
|
MessagesDelivered(LaneId, DeliveredMessages),
|
||||||
/// Phantom member, never used.
|
/// Phantom member, never used.
|
||||||
Dummy(PhantomData<(AccountId, I)>),
|
Dummy(PhantomData<(AccountId, I)>),
|
||||||
}
|
}
|
||||||
@@ -620,19 +626,36 @@ decl_module! {
|
|||||||
let mut lane = outbound_lane::<T, I>(lane_id);
|
let mut lane = outbound_lane::<T, I>(lane_id);
|
||||||
let mut relayers_rewards: RelayersRewards<_, T::OutboundMessageFee> = RelayersRewards::new();
|
let mut relayers_rewards: RelayersRewards<_, T::OutboundMessageFee> = RelayersRewards::new();
|
||||||
let last_delivered_nonce = lane_data.last_delivered_nonce();
|
let last_delivered_nonce = lane_data.last_delivered_nonce();
|
||||||
let received_range = lane.confirm_delivery(last_delivered_nonce);
|
let confirmed_messages = match lane.confirm_delivery(last_delivered_nonce, &lane_data.relayers) {
|
||||||
if let Some(received_range) = received_range {
|
ReceivalConfirmationResult::ConfirmedMessages(confirmed_messages) => Some(confirmed_messages),
|
||||||
Self::deposit_event(RawEvent::MessagesDelivered(lane_id, received_range.0, received_range.1));
|
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
|
// remember to reward relayers that have delivered messages
|
||||||
// this loop is bounded by `T::MaxUnrewardedRelayerEntriesAtInboundLane` on the bridged chain
|
// this loop is bounded by `T::MaxUnrewardedRelayerEntriesAtInboundLane` on the bridged chain
|
||||||
for (nonce_low, nonce_high, relayer) in lane_data.relayers {
|
for entry in lane_data.relayers {
|
||||||
let nonce_begin = sp_std::cmp::max(nonce_low, received_range.0);
|
let nonce_begin = sp_std::cmp::max(entry.messages.begin, *received_range.start());
|
||||||
let nonce_end = sp_std::cmp::min(nonce_high, received_range.1);
|
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).
|
// 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
|
// 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 {
|
for nonce in nonce_begin..nonce_end + 1 {
|
||||||
let message_data = OutboundMessages::<T, I>::get(MessageKey {
|
let message_data = OutboundMessages::<T, I>::get(MessageKey {
|
||||||
lane_id,
|
lane_id,
|
||||||
@@ -697,7 +720,10 @@ impl<T: Config<I>, I: Instance> Pallet<T, I> {
|
|||||||
let relayers = InboundLanes::<T, I>::get(&lane).relayers;
|
let relayers = InboundLanes::<T, I>::get(&lane).relayers;
|
||||||
bp_messages::UnrewardedRelayersState {
|
bp_messages::UnrewardedRelayersState {
|
||||||
unrewarded_relayer_entries: relayers.len() as _,
|
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),
|
total_messages: total_unrewarded_messages(&relayers).unwrap_or(MessageNonce::MAX),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -920,11 +946,12 @@ fn verify_and_decode_messages_proof<Chain: SourceHeaderChain<Fee>, Fee, Dispatch
|
|||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::mock::{
|
use crate::mock::{
|
||||||
message, message_payload, run_test, Event as TestEvent, Origin, TestMessageDeliveryAndDispatchPayment,
|
message, message_payload, run_test, unrewarded_relayer, Event as TestEvent, Origin,
|
||||||
TestMessagesDeliveryProof, TestMessagesParameter, TestMessagesProof, TestRuntime, TokenConversionRate,
|
TestMessageDeliveryAndDispatchPayment, TestMessagesDeliveryProof, TestMessagesParameter, TestMessagesProof,
|
||||||
PAYLOAD_REJECTED_BY_TARGET_CHAIN, REGULAR_PAYLOAD, TEST_LANE_ID, TEST_RELAYER_A, TEST_RELAYER_B,
|
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_support::{assert_noop, assert_ok};
|
||||||
use frame_system::{EventRecord, Pallet as System, Phase};
|
use frame_system::{EventRecord, Pallet as System, Phase};
|
||||||
use hex_literal::hex;
|
use hex_literal::hex;
|
||||||
@@ -938,6 +965,10 @@ mod tests {
|
|||||||
fn send_regular_message() {
|
fn send_regular_message() {
|
||||||
get_ready_for_events();
|
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(
|
assert_ok!(Pallet::<TestRuntime>::send_message(
|
||||||
Origin::signed(1),
|
Origin::signed(1),
|
||||||
TEST_LANE_ID,
|
TEST_LANE_ID,
|
||||||
@@ -950,7 +981,7 @@ mod tests {
|
|||||||
System::<TestRuntime>::events(),
|
System::<TestRuntime>::events(),
|
||||||
vec![EventRecord {
|
vec![EventRecord {
|
||||||
phase: Phase::Initialization,
|
phase: Phase::Initialization,
|
||||||
event: TestEvent::Messages(RawEvent::MessageAccepted(TEST_LANE_ID, 1)),
|
event: TestEvent::Messages(RawEvent::MessageAccepted(TEST_LANE_ID, message_nonce)),
|
||||||
topics: vec![],
|
topics: vec![],
|
||||||
}],
|
}],
|
||||||
);
|
);
|
||||||
@@ -972,17 +1003,29 @@ mod tests {
|
|||||||
TEST_LANE_ID,
|
TEST_LANE_ID,
|
||||||
InboundLaneData {
|
InboundLaneData {
|
||||||
last_confirmed_nonce: 1,
|
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!(
|
assert_eq!(
|
||||||
System::<TestRuntime>::events(),
|
System::<TestRuntime>::events(),
|
||||||
vec![EventRecord {
|
vec![EventRecord {
|
||||||
phase: Phase::Initialization,
|
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![],
|
topics: vec![],
|
||||||
}],
|
}],
|
||||||
);
|
);
|
||||||
@@ -1333,9 +1376,12 @@ mod tests {
|
|||||||
TEST_LANE_ID,
|
TEST_LANE_ID,
|
||||||
InboundLaneData {
|
InboundLaneData {
|
||||||
last_confirmed_nonce: 8,
|
last_confirmed_nonce: 8,
|
||||||
relayers: vec![(9, 9, TEST_RELAYER_A), (10, 10, TEST_RELAYER_B)]
|
relayers: vec![
|
||||||
.into_iter()
|
unrewarded_relayer(9, 9, TEST_RELAYER_A),
|
||||||
.collect(),
|
unrewarded_relayer(10, 10, TEST_RELAYER_B),
|
||||||
|
]
|
||||||
|
.into_iter()
|
||||||
|
.collect(),
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
@@ -1366,9 +1412,12 @@ mod tests {
|
|||||||
InboundLanes::<TestRuntime>::get(TEST_LANE_ID),
|
InboundLanes::<TestRuntime>::get(TEST_LANE_ID),
|
||||||
InboundLaneData {
|
InboundLaneData {
|
||||||
last_confirmed_nonce: 9,
|
last_confirmed_nonce: 9,
|
||||||
relayers: vec![(10, 10, TEST_RELAYER_B), (11, 11, TEST_RELAYER_A)]
|
relayers: vec![
|
||||||
.into_iter()
|
unrewarded_relayer(10, 10, TEST_RELAYER_B),
|
||||||
.collect(),
|
unrewarded_relayer(11, 11, TEST_RELAYER_A)
|
||||||
|
]
|
||||||
|
.into_iter()
|
||||||
|
.collect(),
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
@@ -1465,7 +1514,7 @@ mod tests {
|
|||||||
TestMessagesDeliveryProof(Ok((
|
TestMessagesDeliveryProof(Ok((
|
||||||
TEST_LANE_ID,
|
TEST_LANE_ID,
|
||||||
InboundLaneData {
|
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()
|
..Default::default()
|
||||||
}
|
}
|
||||||
))),
|
))),
|
||||||
@@ -1490,9 +1539,12 @@ mod tests {
|
|||||||
TestMessagesDeliveryProof(Ok((
|
TestMessagesDeliveryProof(Ok((
|
||||||
TEST_LANE_ID,
|
TEST_LANE_ID,
|
||||||
InboundLaneData {
|
InboundLaneData {
|
||||||
relayers: vec![(1, 1, TEST_RELAYER_A), (2, 2, TEST_RELAYER_B)]
|
relayers: vec![
|
||||||
.into_iter()
|
unrewarded_relayer(1, 1, TEST_RELAYER_A),
|
||||||
.collect(),
|
unrewarded_relayer(2, 2, TEST_RELAYER_B)
|
||||||
|
]
|
||||||
|
.into_iter()
|
||||||
|
.collect(),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
}
|
}
|
||||||
))),
|
))),
|
||||||
@@ -1537,9 +1589,12 @@ mod tests {
|
|||||||
TestMessagesDeliveryProof(Ok((
|
TestMessagesDeliveryProof(Ok((
|
||||||
TEST_LANE_ID,
|
TEST_LANE_ID,
|
||||||
InboundLaneData {
|
InboundLaneData {
|
||||||
relayers: vec![(1, 1, TEST_RELAYER_A), (2, 2, TEST_RELAYER_B)]
|
relayers: vec![
|
||||||
.into_iter()
|
unrewarded_relayer(1, 1, TEST_RELAYER_A),
|
||||||
.collect(),
|
unrewarded_relayer(2, 2, TEST_RELAYER_B)
|
||||||
|
]
|
||||||
|
.into_iter()
|
||||||
|
.collect(),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
}
|
}
|
||||||
))),
|
))),
|
||||||
@@ -1559,9 +1614,12 @@ mod tests {
|
|||||||
TestMessagesDeliveryProof(Ok((
|
TestMessagesDeliveryProof(Ok((
|
||||||
TEST_LANE_ID,
|
TEST_LANE_ID,
|
||||||
InboundLaneData {
|
InboundLaneData {
|
||||||
relayers: vec![(1, 1, TEST_RELAYER_A), (2, 2, TEST_RELAYER_B)]
|
relayers: vec![
|
||||||
.into_iter()
|
unrewarded_relayer(1, 1, TEST_RELAYER_A),
|
||||||
.collect(),
|
unrewarded_relayer(2, 2, TEST_RELAYER_B)
|
||||||
|
]
|
||||||
|
.into_iter()
|
||||||
|
.collect(),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
}
|
}
|
||||||
))),
|
))),
|
||||||
@@ -1791,4 +1849,70 @@ mod tests {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[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);
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,13 +19,15 @@
|
|||||||
|
|
||||||
use crate::Config;
|
use crate::Config;
|
||||||
|
|
||||||
|
use bitvec::prelude::*;
|
||||||
use bp_messages::{
|
use bp_messages::{
|
||||||
source_chain::{
|
source_chain::{
|
||||||
LaneMessageVerifier, MessageDeliveryAndDispatchPayment, RelayersRewards, Sender, TargetHeaderChain,
|
LaneMessageVerifier, MessageDeliveryAndDispatchPayment, OnDeliveryConfirmed, RelayersRewards, Sender,
|
||||||
|
TargetHeaderChain,
|
||||||
},
|
},
|
||||||
target_chain::{DispatchMessage, MessageDispatch, ProvedLaneMessages, ProvedMessages, SourceHeaderChain},
|
target_chain::{DispatchMessage, MessageDispatch, ProvedLaneMessages, ProvedMessages, SourceHeaderChain},
|
||||||
InboundLaneData, LaneId, Message, MessageData, MessageKey, MessageNonce, OutboundLaneData,
|
DeliveredMessages, InboundLaneData, LaneId, Message, MessageData, MessageKey, MessageNonce, OutboundLaneData,
|
||||||
Parameter as MessagesParameter,
|
Parameter as MessagesParameter, UnrewardedRelayer,
|
||||||
};
|
};
|
||||||
use bp_runtime::{messages::MessageDispatchResult, Size};
|
use bp_runtime::{messages::MessageDispatchResult, Size};
|
||||||
use codec::{Decode, Encode};
|
use codec::{Decode, Encode};
|
||||||
@@ -169,6 +171,7 @@ impl Config for TestRuntime {
|
|||||||
type TargetHeaderChain = TestTargetHeaderChain;
|
type TargetHeaderChain = TestTargetHeaderChain;
|
||||||
type LaneMessageVerifier = TestLaneMessageVerifier;
|
type LaneMessageVerifier = TestLaneMessageVerifier;
|
||||||
type MessageDeliveryAndDispatchPayment = TestMessageDeliveryAndDispatchPayment;
|
type MessageDeliveryAndDispatchPayment = TestMessageDeliveryAndDispatchPayment;
|
||||||
|
type OnDeliveryConfirmed = (TestOnDeliveryConfirmed1, TestOnDeliveryConfirmed2);
|
||||||
|
|
||||||
type SourceHeaderChain = TestSourceHeaderChain;
|
type SourceHeaderChain = TestSourceHeaderChain;
|
||||||
type MessageDispatch = TestMessageDispatch;
|
type MessageDispatch = TestMessageDispatch;
|
||||||
@@ -345,6 +348,44 @@ impl MessageDeliveryAndDispatchPayment<AccountId, TestMessageFee> for TestMessag
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// First on-messages-delivered callback.
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct TestOnDeliveryConfirmed1;
|
||||||
|
|
||||||
|
impl TestOnDeliveryConfirmed1 {
|
||||||
|
/// Verify that the callback has been called with given delivered messages.
|
||||||
|
pub fn ensure_called(lane: &LaneId, messages: &DeliveredMessages) {
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Seconde on-messages-delivered callback.
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct TestOnDeliveryConfirmed2;
|
||||||
|
|
||||||
|
impl TestOnDeliveryConfirmed2 {
|
||||||
|
/// Verify that the callback has been called with given delivered messages.
|
||||||
|
pub fn ensure_called(lane: &LaneId, messages: &DeliveredMessages) {
|
||||||
|
let key = (b"TestOnDeliveryConfirmed2", lane, messages).encode();
|
||||||
|
assert_eq!(frame_support::storage::unhashed::get(&key), Some(true));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl OnDeliveryConfirmed for TestOnDeliveryConfirmed2 {
|
||||||
|
fn on_messages_delivered(lane: &LaneId, messages: &DeliveredMessages) {
|
||||||
|
let key = (b"TestOnDeliveryConfirmed2", lane, messages).encode();
|
||||||
|
frame_support::storage::unhashed::put(&key, &true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Source header chain that is used in tests.
|
/// Source header chain that is used in tests.
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct TestSourceHeaderChain;
|
pub struct TestSourceHeaderChain;
|
||||||
@@ -421,11 +462,32 @@ pub fn message_data(payload: TestPayload) -> MessageData<TestMessageFee> {
|
|||||||
/// Returns message dispatch result with given unspent weight.
|
/// Returns message dispatch result with given unspent weight.
|
||||||
pub const fn dispatch_result(unspent_weight: Weight) -> MessageDispatchResult {
|
pub const fn dispatch_result(unspent_weight: Weight) -> MessageDispatchResult {
|
||||||
MessageDispatchResult {
|
MessageDispatchResult {
|
||||||
|
dispatch_result: true,
|
||||||
unspent_weight,
|
unspent_weight,
|
||||||
dispatch_fee_paid_during_dispatch: true,
|
dispatch_fee_paid_during_dispatch: true,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Constructs unrewarded relayer entry from nonces range and relayer id.
|
||||||
|
pub fn unrewarded_relayer(
|
||||||
|
begin: MessageNonce,
|
||||||
|
end: MessageNonce,
|
||||||
|
relayer: TestRelayer,
|
||||||
|
) -> UnrewardedRelayer<TestRelayer> {
|
||||||
|
UnrewardedRelayer {
|
||||||
|
relayer,
|
||||||
|
messages: DeliveredMessages {
|
||||||
|
begin,
|
||||||
|
end,
|
||||||
|
dispatch_results: if end >= begin {
|
||||||
|
bitvec![Msb0, u8; 1; (end - begin + 1) as _]
|
||||||
|
} else {
|
||||||
|
Default::default()
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Run pallet test.
|
/// Run pallet test.
|
||||||
pub fn run_test<T>(test: impl FnOnce() -> T) -> T {
|
pub fn run_test<T>(test: impl FnOnce() -> T) -> T {
|
||||||
let mut t = frame_system::GenesisConfig::default()
|
let mut t = frame_system::GenesisConfig::default()
|
||||||
|
|||||||
@@ -16,7 +16,12 @@
|
|||||||
|
|
||||||
//! Everything about outgoing messages sending.
|
//! Everything about outgoing messages sending.
|
||||||
|
|
||||||
use bp_messages::{LaneId, MessageData, MessageNonce, OutboundLaneData};
|
use bitvec::prelude::*;
|
||||||
|
use bp_messages::{
|
||||||
|
DeliveredMessages, DispatchResultsBitVec, LaneId, MessageData, MessageNonce, OutboundLaneData, UnrewardedRelayer,
|
||||||
|
};
|
||||||
|
use frame_support::RuntimeDebug;
|
||||||
|
use sp_std::collections::vec_deque::VecDeque;
|
||||||
|
|
||||||
/// Outbound lane storage.
|
/// Outbound lane storage.
|
||||||
pub trait OutboundLaneStorage {
|
pub trait OutboundLaneStorage {
|
||||||
@@ -38,6 +43,28 @@ pub trait OutboundLaneStorage {
|
|||||||
fn remove_message(&mut self, nonce: &MessageNonce);
|
fn remove_message(&mut self, nonce: &MessageNonce);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Result of messages receival confirmation.
|
||||||
|
#[derive(RuntimeDebug, PartialEq, Eq)]
|
||||||
|
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.
|
||||||
|
NoNewConfirmations,
|
||||||
|
/// Bridged chain is trying to confirm more messages than we have generated. May be a result
|
||||||
|
/// of invalid bridged chain storage.
|
||||||
|
FailedToConfirmFutureMessages,
|
||||||
|
/// 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.
|
||||||
|
NonConsecutiveUnrewardedRelayerEntries,
|
||||||
|
/// The unrewarded relayers vec contains entry with mismatched number of dispatch results. May be
|
||||||
|
/// a result of invalid bridged chain storage.
|
||||||
|
InvalidNumberOfDispatchResults,
|
||||||
|
}
|
||||||
|
|
||||||
/// Outbound messages lane.
|
/// Outbound messages lane.
|
||||||
pub struct OutboundLane<S> {
|
pub struct OutboundLane<S> {
|
||||||
storage: S,
|
storage: S,
|
||||||
@@ -69,20 +96,34 @@ impl<S: OutboundLaneStorage> OutboundLane<S> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Confirm messages delivery.
|
/// Confirm messages delivery.
|
||||||
///
|
pub fn confirm_delivery<RelayerId>(
|
||||||
/// Returns `None` if confirmation is wrong/duplicate.
|
&mut self,
|
||||||
/// Returns `Some` with inclusive ranges of message nonces that have been received.
|
latest_received_nonce: MessageNonce,
|
||||||
pub fn confirm_delivery(&mut self, latest_received_nonce: MessageNonce) -> Option<(MessageNonce, MessageNonce)> {
|
relayers: &VecDeque<UnrewardedRelayer<RelayerId>>,
|
||||||
|
) -> ReceivalConfirmationResult {
|
||||||
let mut data = self.storage.data();
|
let mut data = self.storage.data();
|
||||||
if latest_received_nonce <= data.latest_received_nonce || latest_received_nonce > data.latest_generated_nonce {
|
if latest_received_nonce <= data.latest_received_nonce {
|
||||||
return None;
|
return ReceivalConfirmationResult::NoNewConfirmations;
|
||||||
}
|
}
|
||||||
|
if latest_received_nonce > data.latest_generated_nonce {
|
||||||
|
return ReceivalConfirmationResult::FailedToConfirmFutureMessages;
|
||||||
|
}
|
||||||
|
|
||||||
|
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 prev_latest_received_nonce = data.latest_received_nonce;
|
let prev_latest_received_nonce = data.latest_received_nonce;
|
||||||
data.latest_received_nonce = latest_received_nonce;
|
data.latest_received_nonce = latest_received_nonce;
|
||||||
self.storage.set_data(data);
|
self.storage.set_data(data);
|
||||||
|
|
||||||
Some((prev_latest_received_nonce + 1, latest_received_nonce))
|
ReceivalConfirmationResult::ConfirmedMessages(DeliveredMessages {
|
||||||
|
begin: prev_latest_received_nonce + 1,
|
||||||
|
end: latest_received_nonce,
|
||||||
|
dispatch_results,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Prune at most `max_messages_to_prune` already received messages.
|
/// Prune at most `max_messages_to_prune` already received messages.
|
||||||
@@ -108,13 +149,108 @@ impl<S: OutboundLaneStorage> OutboundLane<S> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Extract new dispatch results from the unrewarded relayers vec.
|
||||||
|
///
|
||||||
|
/// Returns `Err(_)` if unrewarded relayers vec contains invalid data, meaning that the bridged
|
||||||
|
/// chain has invalid runtime storage.
|
||||||
|
fn extract_dispatch_results<RelayerId>(
|
||||||
|
prev_latest_received_nonce: MessageNonce,
|
||||||
|
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
|
||||||
|
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;
|
||||||
|
for entry in relayers {
|
||||||
|
// 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);
|
||||||
|
}
|
||||||
|
// 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
// 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);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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_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;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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..],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(received_dispatch_result)
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::{
|
use crate::{
|
||||||
mock::{message_data, run_test, TestRuntime, REGULAR_PAYLOAD, TEST_LANE_ID},
|
mock::{message_data, run_test, unrewarded_relayer, TestRelayer, TestRuntime, REGULAR_PAYLOAD, TEST_LANE_ID},
|
||||||
outbound_lane,
|
outbound_lane,
|
||||||
};
|
};
|
||||||
|
use sp_std::ops::RangeInclusive;
|
||||||
|
|
||||||
|
fn unrewarded_relayers(nonces: RangeInclusive<MessageNonce>) -> VecDeque<UnrewardedRelayer<TestRelayer>> {
|
||||||
|
vec![unrewarded_relayer(*nonces.start(), *nonces.end(), 0)]
|
||||||
|
.into_iter()
|
||||||
|
.collect()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn delivered_messages(nonces: RangeInclusive<MessageNonce>) -> DeliveredMessages {
|
||||||
|
DeliveredMessages {
|
||||||
|
begin: *nonces.start(),
|
||||||
|
end: *nonces.end(),
|
||||||
|
dispatch_results: bitvec![Msb0, u8; 1; (nonces.end() - nonces.start() + 1) as _],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn assert_3_messages_confirmation_fails(
|
||||||
|
latest_received_nonce: MessageNonce,
|
||||||
|
relayers: &VecDeque<UnrewardedRelayer<TestRelayer>>,
|
||||||
|
) -> ReceivalConfirmationResult {
|
||||||
|
run_test(|| {
|
||||||
|
let mut lane = outbound_lane::<TestRuntime, _>(TEST_LANE_ID);
|
||||||
|
lane.send_message(message_data(REGULAR_PAYLOAD));
|
||||||
|
lane.send_message(message_data(REGULAR_PAYLOAD));
|
||||||
|
lane.send_message(message_data(REGULAR_PAYLOAD));
|
||||||
|
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);
|
||||||
|
assert_eq!(lane.storage.data().latest_generated_nonce, 3);
|
||||||
|
assert_eq!(lane.storage.data().latest_received_nonce, 0);
|
||||||
|
result
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn send_message_works() {
|
fn send_message_works() {
|
||||||
@@ -136,7 +272,10 @@ mod tests {
|
|||||||
assert_eq!(lane.send_message(message_data(REGULAR_PAYLOAD)), 3);
|
assert_eq!(lane.send_message(message_data(REGULAR_PAYLOAD)), 3);
|
||||||
assert_eq!(lane.storage.data().latest_generated_nonce, 3);
|
assert_eq!(lane.storage.data().latest_generated_nonce, 3);
|
||||||
assert_eq!(lane.storage.data().latest_received_nonce, 0);
|
assert_eq!(lane.storage.data().latest_received_nonce, 0);
|
||||||
assert_eq!(lane.confirm_delivery(3), Some((1, 3)));
|
assert_eq!(
|
||||||
|
lane.confirm_delivery(3, &unrewarded_relayers(1..=3)),
|
||||||
|
ReceivalConfirmationResult::ConfirmedMessages(delivered_messages(1..=3)),
|
||||||
|
);
|
||||||
assert_eq!(lane.storage.data().latest_generated_nonce, 3);
|
assert_eq!(lane.storage.data().latest_generated_nonce, 3);
|
||||||
assert_eq!(lane.storage.data().latest_received_nonce, 3);
|
assert_eq!(lane.storage.data().latest_received_nonce, 3);
|
||||||
});
|
});
|
||||||
@@ -151,12 +290,21 @@ mod tests {
|
|||||||
lane.send_message(message_data(REGULAR_PAYLOAD));
|
lane.send_message(message_data(REGULAR_PAYLOAD));
|
||||||
assert_eq!(lane.storage.data().latest_generated_nonce, 3);
|
assert_eq!(lane.storage.data().latest_generated_nonce, 3);
|
||||||
assert_eq!(lane.storage.data().latest_received_nonce, 0);
|
assert_eq!(lane.storage.data().latest_received_nonce, 0);
|
||||||
assert_eq!(lane.confirm_delivery(3), Some((1, 3)));
|
assert_eq!(
|
||||||
assert_eq!(lane.confirm_delivery(3), None);
|
lane.confirm_delivery(3, &unrewarded_relayers(1..=3)),
|
||||||
|
ReceivalConfirmationResult::ConfirmedMessages(delivered_messages(1..=3)),
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
lane.confirm_delivery(3, &unrewarded_relayers(1..=3)),
|
||||||
|
ReceivalConfirmationResult::NoNewConfirmations,
|
||||||
|
);
|
||||||
assert_eq!(lane.storage.data().latest_generated_nonce, 3);
|
assert_eq!(lane.storage.data().latest_generated_nonce, 3);
|
||||||
assert_eq!(lane.storage.data().latest_received_nonce, 3);
|
assert_eq!(lane.storage.data().latest_received_nonce, 3);
|
||||||
|
|
||||||
assert_eq!(lane.confirm_delivery(2), None);
|
assert_eq!(
|
||||||
|
lane.confirm_delivery(2, &unrewarded_relayers(1..=1)),
|
||||||
|
ReceivalConfirmationResult::NoNewConfirmations,
|
||||||
|
);
|
||||||
assert_eq!(lane.storage.data().latest_generated_nonce, 3);
|
assert_eq!(lane.storage.data().latest_generated_nonce, 3);
|
||||||
assert_eq!(lane.storage.data().latest_received_nonce, 3);
|
assert_eq!(lane.storage.data().latest_received_nonce, 3);
|
||||||
});
|
});
|
||||||
@@ -164,17 +312,70 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn confirm_delivery_rejects_nonce_larger_than_last_generated() {
|
fn confirm_delivery_rejects_nonce_larger_than_last_generated() {
|
||||||
run_test(|| {
|
assert_eq!(
|
||||||
let mut lane = outbound_lane::<TestRuntime, _>(TEST_LANE_ID);
|
assert_3_messages_confirmation_fails(10, &unrewarded_relayers(1..=10),),
|
||||||
lane.send_message(message_data(REGULAR_PAYLOAD));
|
ReceivalConfirmationResult::FailedToConfirmFutureMessages,
|
||||||
lane.send_message(message_data(REGULAR_PAYLOAD));
|
);
|
||||||
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);
|
#[test]
|
||||||
assert_eq!(lane.confirm_delivery(10), None);
|
fn confirm_delivery_fails_if_entry_confirms_future_messages() {
|
||||||
assert_eq!(lane.storage.data().latest_generated_nonce, 3);
|
assert_eq!(
|
||||||
assert_eq!(lane.storage.data().latest_received_nonce, 0);
|
assert_3_messages_confirmation_fails(
|
||||||
});
|
3,
|
||||||
|
&unrewarded_relayers(1..=1)
|
||||||
|
.into_iter()
|
||||||
|
.chain(unrewarded_relayers(2..=30).into_iter())
|
||||||
|
.chain(unrewarded_relayers(3..=3).into_iter())
|
||||||
|
.collect(),
|
||||||
|
),
|
||||||
|
ReceivalConfirmationResult::FailedToConfirmFutureMessages,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[allow(clippy::reversed_empty_ranges)]
|
||||||
|
fn confirm_delivery_fails_if_entry_is_empty() {
|
||||||
|
assert_eq!(
|
||||||
|
assert_3_messages_confirmation_fails(
|
||||||
|
3,
|
||||||
|
&unrewarded_relayers(1..=1)
|
||||||
|
.into_iter()
|
||||||
|
.chain(unrewarded_relayers(2..=1).into_iter())
|
||||||
|
.chain(unrewarded_relayers(2..=3).into_iter())
|
||||||
|
.collect(),
|
||||||
|
),
|
||||||
|
ReceivalConfirmationResult::EmptyUnrewardedRelayerEntry,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn confirm_delivery_fails_if_entries_are_non_consecutive() {
|
||||||
|
assert_eq!(
|
||||||
|
assert_3_messages_confirmation_fails(
|
||||||
|
3,
|
||||||
|
&unrewarded_relayers(1..=1)
|
||||||
|
.into_iter()
|
||||||
|
.chain(unrewarded_relayers(3..=3).into_iter())
|
||||||
|
.chain(unrewarded_relayers(2..=2).into_iter())
|
||||||
|
.collect(),
|
||||||
|
),
|
||||||
|
ReceivalConfirmationResult::NonConsecutiveUnrewardedRelayerEntries,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn confirm_delivery_fails_if_number_of_dispatch_results_in_entry_is_invalid() {
|
||||||
|
let mut relayers: VecDeque<_> = unrewarded_relayers(1..=1)
|
||||||
|
.into_iter()
|
||||||
|
.chain(unrewarded_relayers(2..=2).into_iter())
|
||||||
|
.chain(unrewarded_relayers(3..=3).into_iter())
|
||||||
|
.collect();
|
||||||
|
relayers[0].messages.dispatch_results.clear();
|
||||||
|
assert_eq!(
|
||||||
|
assert_3_messages_confirmation_fails(3, &relayers),
|
||||||
|
ReceivalConfirmationResult::InvalidNumberOfDispatchResults,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@@ -191,11 +392,17 @@ mod tests {
|
|||||||
assert_eq!(lane.prune_messages(100), 0);
|
assert_eq!(lane.prune_messages(100), 0);
|
||||||
assert_eq!(lane.storage.data().oldest_unpruned_nonce, 1);
|
assert_eq!(lane.storage.data().oldest_unpruned_nonce, 1);
|
||||||
// after confirmation, some messages are received
|
// after confirmation, some messages are received
|
||||||
assert_eq!(lane.confirm_delivery(2), Some((1, 2)));
|
assert_eq!(
|
||||||
|
lane.confirm_delivery(2, &unrewarded_relayers(1..=2)),
|
||||||
|
ReceivalConfirmationResult::ConfirmedMessages(delivered_messages(1..=2)),
|
||||||
|
);
|
||||||
assert_eq!(lane.prune_messages(100), 2);
|
assert_eq!(lane.prune_messages(100), 2);
|
||||||
assert_eq!(lane.storage.data().oldest_unpruned_nonce, 3);
|
assert_eq!(lane.storage.data().oldest_unpruned_nonce, 3);
|
||||||
// after last message is confirmed, everything is pruned
|
// after last message is confirmed, everything is pruned
|
||||||
assert_eq!(lane.confirm_delivery(3), Some((3, 3)));
|
assert_eq!(
|
||||||
|
lane.confirm_delivery(3, &unrewarded_relayers(3..=3)),
|
||||||
|
ReceivalConfirmationResult::ConfirmedMessages(delivered_messages(3..=3)),
|
||||||
|
);
|
||||||
assert_eq!(lane.prune_messages(100), 1);
|
assert_eq!(lane.prune_messages(100), 1);
|
||||||
assert_eq!(lane.storage.data().oldest_unpruned_nonce, 4);
|
assert_eq!(lane.storage.data().oldest_unpruned_nonce, 4);
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -17,7 +17,7 @@
|
|||||||
//! 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
|
//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 3.0.0
|
||||||
//! DATE: 2021-06-15, STEPS: [50, ], REPEAT: 20
|
//! DATE: 2021-06-18, STEPS: [50, ], REPEAT: 20
|
||||||
//! LOW RANGE: [], HIGH RANGE: []
|
//! LOW RANGE: [], HIGH RANGE: []
|
||||||
//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled
|
//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled
|
||||||
//! CHAIN: Some("dev"), DB CACHE: 128
|
//! CHAIN: Some("dev"), DB CACHE: 128
|
||||||
@@ -74,110 +74,110 @@ pub trait WeightInfo {
|
|||||||
pub struct RialtoWeight<T>(PhantomData<T>);
|
pub struct RialtoWeight<T>(PhantomData<T>);
|
||||||
impl<T: frame_system::Config> WeightInfo for RialtoWeight<T> {
|
impl<T: frame_system::Config> WeightInfo for RialtoWeight<T> {
|
||||||
fn send_minimal_message_worst_case() -> Weight {
|
fn send_minimal_message_worst_case() -> Weight {
|
||||||
(154_371_000 as Weight)
|
(159_305_000 as Weight)
|
||||||
.saturating_add(T::DbWeight::get().reads(5 as Weight))
|
.saturating_add(T::DbWeight::get().reads(5 as Weight))
|
||||||
.saturating_add(T::DbWeight::get().writes(12 as Weight))
|
.saturating_add(T::DbWeight::get().writes(12 as Weight))
|
||||||
}
|
}
|
||||||
fn send_1_kb_message_worst_case() -> Weight {
|
fn send_1_kb_message_worst_case() -> Weight {
|
||||||
(157_479_000 as Weight)
|
(164_394_000 as Weight)
|
||||||
.saturating_add(T::DbWeight::get().reads(5 as Weight))
|
.saturating_add(T::DbWeight::get().reads(5 as Weight))
|
||||||
.saturating_add(T::DbWeight::get().writes(12 as Weight))
|
.saturating_add(T::DbWeight::get().writes(12 as Weight))
|
||||||
}
|
}
|
||||||
fn send_16_kb_message_worst_case() -> Weight {
|
fn send_16_kb_message_worst_case() -> Weight {
|
||||||
(186_840_000 as Weight)
|
(223_521_000 as Weight)
|
||||||
.saturating_add(T::DbWeight::get().reads(5 as Weight))
|
.saturating_add(T::DbWeight::get().reads(5 as Weight))
|
||||||
.saturating_add(T::DbWeight::get().writes(12 as Weight))
|
.saturating_add(T::DbWeight::get().writes(12 as Weight))
|
||||||
}
|
}
|
||||||
fn increase_message_fee() -> Weight {
|
fn increase_message_fee() -> Weight {
|
||||||
(4_377_567_000 as Weight)
|
(6_709_925_000 as Weight)
|
||||||
.saturating_add(T::DbWeight::get().reads(5 as Weight))
|
.saturating_add(T::DbWeight::get().reads(5 as Weight))
|
||||||
.saturating_add(T::DbWeight::get().writes(3 as Weight))
|
.saturating_add(T::DbWeight::get().writes(3 as Weight))
|
||||||
}
|
}
|
||||||
fn receive_single_message_proof() -> Weight {
|
fn receive_single_message_proof() -> Weight {
|
||||||
(205_350_000 as Weight)
|
(206_769_000 as Weight)
|
||||||
.saturating_add(T::DbWeight::get().reads(5 as Weight))
|
.saturating_add(T::DbWeight::get().reads(5 as Weight))
|
||||||
.saturating_add(T::DbWeight::get().writes(3 as Weight))
|
.saturating_add(T::DbWeight::get().writes(3 as Weight))
|
||||||
}
|
}
|
||||||
fn receive_two_messages_proof() -> Weight {
|
fn receive_two_messages_proof() -> Weight {
|
||||||
(337_102_000 as Weight)
|
(343_982_000 as Weight)
|
||||||
.saturating_add(T::DbWeight::get().reads(5 as Weight))
|
.saturating_add(T::DbWeight::get().reads(5 as Weight))
|
||||||
.saturating_add(T::DbWeight::get().writes(3 as Weight))
|
.saturating_add(T::DbWeight::get().writes(3 as Weight))
|
||||||
}
|
}
|
||||||
fn receive_single_message_proof_with_outbound_lane_state() -> Weight {
|
fn receive_single_message_proof_with_outbound_lane_state() -> Weight {
|
||||||
(218_825_000 as Weight)
|
(223_738_000 as Weight)
|
||||||
.saturating_add(T::DbWeight::get().reads(5 as Weight))
|
.saturating_add(T::DbWeight::get().reads(5 as Weight))
|
||||||
.saturating_add(T::DbWeight::get().writes(3 as Weight))
|
.saturating_add(T::DbWeight::get().writes(3 as Weight))
|
||||||
}
|
}
|
||||||
fn receive_single_message_proof_1_kb() -> Weight {
|
fn receive_single_message_proof_1_kb() -> Weight {
|
||||||
(230_759_000 as Weight)
|
(235_369_000 as Weight)
|
||||||
.saturating_add(T::DbWeight::get().reads(5 as Weight))
|
.saturating_add(T::DbWeight::get().reads(5 as Weight))
|
||||||
.saturating_add(T::DbWeight::get().writes(3 as Weight))
|
.saturating_add(T::DbWeight::get().writes(3 as Weight))
|
||||||
}
|
}
|
||||||
fn receive_single_message_proof_16_kb() -> Weight {
|
fn receive_single_message_proof_16_kb() -> Weight {
|
||||||
(490_522_000 as Weight)
|
(510_338_000 as Weight)
|
||||||
.saturating_add(T::DbWeight::get().reads(5 as Weight))
|
.saturating_add(T::DbWeight::get().reads(5 as Weight))
|
||||||
.saturating_add(T::DbWeight::get().writes(3 as Weight))
|
.saturating_add(T::DbWeight::get().writes(3 as Weight))
|
||||||
}
|
}
|
||||||
fn receive_single_prepaid_message_proof() -> Weight {
|
fn receive_single_prepaid_message_proof() -> Weight {
|
||||||
(136_550_000 as Weight)
|
(141_536_000 as Weight)
|
||||||
.saturating_add(T::DbWeight::get().reads(3 as Weight))
|
.saturating_add(T::DbWeight::get().reads(3 as Weight))
|
||||||
.saturating_add(T::DbWeight::get().writes(1 as Weight))
|
.saturating_add(T::DbWeight::get().writes(1 as Weight))
|
||||||
}
|
}
|
||||||
fn receive_delivery_proof_for_single_message() -> Weight {
|
fn receive_delivery_proof_for_single_message() -> Weight {
|
||||||
(131_397_000 as Weight)
|
(128_805_000 as Weight)
|
||||||
.saturating_add(T::DbWeight::get().reads(6 as Weight))
|
.saturating_add(T::DbWeight::get().reads(6 as Weight))
|
||||||
.saturating_add(T::DbWeight::get().writes(3 as Weight))
|
.saturating_add(T::DbWeight::get().writes(3 as Weight))
|
||||||
}
|
}
|
||||||
fn receive_delivery_proof_for_two_messages_by_single_relayer() -> Weight {
|
fn receive_delivery_proof_for_two_messages_by_single_relayer() -> Weight {
|
||||||
(137_946_000 as Weight)
|
(137_143_000 as Weight)
|
||||||
.saturating_add(T::DbWeight::get().reads(7 as Weight))
|
.saturating_add(T::DbWeight::get().reads(7 as Weight))
|
||||||
.saturating_add(T::DbWeight::get().writes(3 as Weight))
|
.saturating_add(T::DbWeight::get().writes(3 as Weight))
|
||||||
}
|
}
|
||||||
fn receive_delivery_proof_for_two_messages_by_two_relayers() -> Weight {
|
fn receive_delivery_proof_for_two_messages_by_two_relayers() -> Weight {
|
||||||
(194_448_000 as Weight)
|
(193_108_000 as Weight)
|
||||||
.saturating_add(T::DbWeight::get().reads(8 as Weight))
|
.saturating_add(T::DbWeight::get().reads(8 as Weight))
|
||||||
.saturating_add(T::DbWeight::get().writes(4 as Weight))
|
.saturating_add(T::DbWeight::get().writes(4 as Weight))
|
||||||
}
|
}
|
||||||
fn send_messages_of_various_lengths(i: u32) -> Weight {
|
fn send_messages_of_various_lengths(i: u32) -> Weight {
|
||||||
(142_576_000 as Weight)
|
(133_632_000 as Weight)
|
||||||
.saturating_add((2_000 as Weight).saturating_mul(i as Weight))
|
.saturating_add((4_000 as Weight).saturating_mul(i as Weight))
|
||||||
.saturating_add(T::DbWeight::get().reads(5 as Weight))
|
.saturating_add(T::DbWeight::get().reads(5 as Weight))
|
||||||
.saturating_add(T::DbWeight::get().writes(12 as Weight))
|
.saturating_add(T::DbWeight::get().writes(12 as Weight))
|
||||||
}
|
}
|
||||||
fn receive_multiple_messages_proof(i: u32) -> Weight {
|
fn receive_multiple_messages_proof(i: u32) -> Weight {
|
||||||
(0 as Weight)
|
(0 as Weight)
|
||||||
.saturating_add((138_341_000 as Weight).saturating_mul(i as Weight))
|
.saturating_add((145_006_000 as Weight).saturating_mul(i as Weight))
|
||||||
.saturating_add(T::DbWeight::get().reads(5 as Weight))
|
.saturating_add(T::DbWeight::get().reads(5 as Weight))
|
||||||
.saturating_add(T::DbWeight::get().writes(3 as Weight))
|
.saturating_add(T::DbWeight::get().writes(3 as Weight))
|
||||||
}
|
}
|
||||||
fn receive_message_proofs_with_extra_nodes(i: u32) -> Weight {
|
fn receive_message_proofs_with_extra_nodes(i: u32) -> Weight {
|
||||||
(472_752_000 as Weight)
|
(486_301_000 as Weight)
|
||||||
.saturating_add((9_000 as Weight).saturating_mul(i as Weight))
|
.saturating_add((10_000 as Weight).saturating_mul(i as Weight))
|
||||||
.saturating_add(T::DbWeight::get().reads(5 as Weight))
|
.saturating_add(T::DbWeight::get().reads(5 as Weight))
|
||||||
.saturating_add(T::DbWeight::get().writes(3 as Weight))
|
.saturating_add(T::DbWeight::get().writes(3 as Weight))
|
||||||
}
|
}
|
||||||
fn receive_message_proofs_with_large_leaf(i: u32) -> Weight {
|
fn receive_message_proofs_with_large_leaf(i: u32) -> Weight {
|
||||||
(175_300_000 as Weight)
|
(178_139_000 as Weight)
|
||||||
.saturating_add((6_000 as Weight).saturating_mul(i as Weight))
|
.saturating_add((7_000 as Weight).saturating_mul(i as Weight))
|
||||||
.saturating_add(T::DbWeight::get().reads(5 as Weight))
|
.saturating_add(T::DbWeight::get().reads(5 as Weight))
|
||||||
.saturating_add(T::DbWeight::get().writes(3 as Weight))
|
.saturating_add(T::DbWeight::get().writes(3 as Weight))
|
||||||
}
|
}
|
||||||
fn receive_multiple_messages_proof_with_outbound_lane_state(i: u32) -> Weight {
|
fn receive_multiple_messages_proof_with_outbound_lane_state(i: u32) -> Weight {
|
||||||
(0 as Weight)
|
(0 as Weight)
|
||||||
.saturating_add((142_176_000 as Weight).saturating_mul(i as Weight))
|
.saturating_add((150_844_000 as Weight).saturating_mul(i as Weight))
|
||||||
.saturating_add(T::DbWeight::get().reads(5 as Weight))
|
.saturating_add(T::DbWeight::get().reads(5 as Weight))
|
||||||
.saturating_add(T::DbWeight::get().writes(3 as Weight))
|
.saturating_add(T::DbWeight::get().writes(3 as Weight))
|
||||||
}
|
}
|
||||||
fn receive_delivery_proof_for_multiple_messages_by_single_relayer(i: u32) -> Weight {
|
fn receive_delivery_proof_for_multiple_messages_by_single_relayer(i: u32) -> Weight {
|
||||||
(127_372_000 as Weight)
|
(113_140_000 as Weight)
|
||||||
.saturating_add((7_927_000 as Weight).saturating_mul(i as Weight))
|
.saturating_add((7_656_000 as Weight).saturating_mul(i as Weight))
|
||||||
.saturating_add(T::DbWeight::get().reads(5 as Weight))
|
.saturating_add(T::DbWeight::get().reads(5 as Weight))
|
||||||
.saturating_add(T::DbWeight::get().reads((1 as Weight).saturating_mul(i as Weight)))
|
.saturating_add(T::DbWeight::get().reads((1 as Weight).saturating_mul(i as Weight)))
|
||||||
.saturating_add(T::DbWeight::get().writes(3 as Weight))
|
.saturating_add(T::DbWeight::get().writes(3 as Weight))
|
||||||
}
|
}
|
||||||
fn receive_delivery_proof_for_multiple_messages_by_multiple_relayers(i: u32) -> Weight {
|
fn receive_delivery_proof_for_multiple_messages_by_multiple_relayers(i: u32) -> Weight {
|
||||||
(99_781_000 as Weight)
|
(97_424_000 as Weight)
|
||||||
.saturating_add((64_001_000 as Weight).saturating_mul(i as Weight))
|
.saturating_add((63_128_000 as Weight).saturating_mul(i as Weight))
|
||||||
.saturating_add(T::DbWeight::get().reads(5 as Weight))
|
.saturating_add(T::DbWeight::get().reads(5 as Weight))
|
||||||
.saturating_add(T::DbWeight::get().reads((2 as Weight).saturating_mul(i as Weight)))
|
.saturating_add(T::DbWeight::get().reads((2 as Weight).saturating_mul(i as Weight)))
|
||||||
.saturating_add(T::DbWeight::get().writes(3 as Weight))
|
.saturating_add(T::DbWeight::get().writes(3 as Weight))
|
||||||
@@ -188,110 +188,110 @@ impl<T: frame_system::Config> WeightInfo for RialtoWeight<T> {
|
|||||||
// For backwards compatibility and tests
|
// For backwards compatibility and tests
|
||||||
impl WeightInfo for () {
|
impl WeightInfo for () {
|
||||||
fn send_minimal_message_worst_case() -> Weight {
|
fn send_minimal_message_worst_case() -> Weight {
|
||||||
(154_371_000 as Weight)
|
(159_305_000 as Weight)
|
||||||
.saturating_add(RocksDbWeight::get().reads(5 as Weight))
|
.saturating_add(RocksDbWeight::get().reads(5 as Weight))
|
||||||
.saturating_add(RocksDbWeight::get().writes(12 as Weight))
|
.saturating_add(RocksDbWeight::get().writes(12 as Weight))
|
||||||
}
|
}
|
||||||
fn send_1_kb_message_worst_case() -> Weight {
|
fn send_1_kb_message_worst_case() -> Weight {
|
||||||
(157_479_000 as Weight)
|
(164_394_000 as Weight)
|
||||||
.saturating_add(RocksDbWeight::get().reads(5 as Weight))
|
.saturating_add(RocksDbWeight::get().reads(5 as Weight))
|
||||||
.saturating_add(RocksDbWeight::get().writes(12 as Weight))
|
.saturating_add(RocksDbWeight::get().writes(12 as Weight))
|
||||||
}
|
}
|
||||||
fn send_16_kb_message_worst_case() -> Weight {
|
fn send_16_kb_message_worst_case() -> Weight {
|
||||||
(186_840_000 as Weight)
|
(223_521_000 as Weight)
|
||||||
.saturating_add(RocksDbWeight::get().reads(5 as Weight))
|
.saturating_add(RocksDbWeight::get().reads(5 as Weight))
|
||||||
.saturating_add(RocksDbWeight::get().writes(12 as Weight))
|
.saturating_add(RocksDbWeight::get().writes(12 as Weight))
|
||||||
}
|
}
|
||||||
fn increase_message_fee() -> Weight {
|
fn increase_message_fee() -> Weight {
|
||||||
(4_377_567_000 as Weight)
|
(6_709_925_000 as Weight)
|
||||||
.saturating_add(RocksDbWeight::get().reads(5 as Weight))
|
.saturating_add(RocksDbWeight::get().reads(5 as Weight))
|
||||||
.saturating_add(RocksDbWeight::get().writes(3 as Weight))
|
.saturating_add(RocksDbWeight::get().writes(3 as Weight))
|
||||||
}
|
}
|
||||||
fn receive_single_message_proof() -> Weight {
|
fn receive_single_message_proof() -> Weight {
|
||||||
(205_350_000 as Weight)
|
(206_769_000 as Weight)
|
||||||
.saturating_add(RocksDbWeight::get().reads(5 as Weight))
|
.saturating_add(RocksDbWeight::get().reads(5 as Weight))
|
||||||
.saturating_add(RocksDbWeight::get().writes(3 as Weight))
|
.saturating_add(RocksDbWeight::get().writes(3 as Weight))
|
||||||
}
|
}
|
||||||
fn receive_two_messages_proof() -> Weight {
|
fn receive_two_messages_proof() -> Weight {
|
||||||
(337_102_000 as Weight)
|
(343_982_000 as Weight)
|
||||||
.saturating_add(RocksDbWeight::get().reads(5 as Weight))
|
.saturating_add(RocksDbWeight::get().reads(5 as Weight))
|
||||||
.saturating_add(RocksDbWeight::get().writes(3 as Weight))
|
.saturating_add(RocksDbWeight::get().writes(3 as Weight))
|
||||||
}
|
}
|
||||||
fn receive_single_message_proof_with_outbound_lane_state() -> Weight {
|
fn receive_single_message_proof_with_outbound_lane_state() -> Weight {
|
||||||
(218_825_000 as Weight)
|
(223_738_000 as Weight)
|
||||||
.saturating_add(RocksDbWeight::get().reads(5 as Weight))
|
.saturating_add(RocksDbWeight::get().reads(5 as Weight))
|
||||||
.saturating_add(RocksDbWeight::get().writes(3 as Weight))
|
.saturating_add(RocksDbWeight::get().writes(3 as Weight))
|
||||||
}
|
}
|
||||||
fn receive_single_message_proof_1_kb() -> Weight {
|
fn receive_single_message_proof_1_kb() -> Weight {
|
||||||
(230_759_000 as Weight)
|
(235_369_000 as Weight)
|
||||||
.saturating_add(RocksDbWeight::get().reads(5 as Weight))
|
.saturating_add(RocksDbWeight::get().reads(5 as Weight))
|
||||||
.saturating_add(RocksDbWeight::get().writes(3 as Weight))
|
.saturating_add(RocksDbWeight::get().writes(3 as Weight))
|
||||||
}
|
}
|
||||||
fn receive_single_message_proof_16_kb() -> Weight {
|
fn receive_single_message_proof_16_kb() -> Weight {
|
||||||
(490_522_000 as Weight)
|
(510_338_000 as Weight)
|
||||||
.saturating_add(RocksDbWeight::get().reads(5 as Weight))
|
.saturating_add(RocksDbWeight::get().reads(5 as Weight))
|
||||||
.saturating_add(RocksDbWeight::get().writes(3 as Weight))
|
.saturating_add(RocksDbWeight::get().writes(3 as Weight))
|
||||||
}
|
}
|
||||||
fn receive_single_prepaid_message_proof() -> Weight {
|
fn receive_single_prepaid_message_proof() -> Weight {
|
||||||
(136_550_000 as Weight)
|
(141_536_000 as Weight)
|
||||||
.saturating_add(RocksDbWeight::get().reads(3 as Weight))
|
.saturating_add(RocksDbWeight::get().reads(3 as Weight))
|
||||||
.saturating_add(RocksDbWeight::get().writes(1 as Weight))
|
.saturating_add(RocksDbWeight::get().writes(1 as Weight))
|
||||||
}
|
}
|
||||||
fn receive_delivery_proof_for_single_message() -> Weight {
|
fn receive_delivery_proof_for_single_message() -> Weight {
|
||||||
(131_397_000 as Weight)
|
(128_805_000 as Weight)
|
||||||
.saturating_add(RocksDbWeight::get().reads(6 as Weight))
|
.saturating_add(RocksDbWeight::get().reads(6 as Weight))
|
||||||
.saturating_add(RocksDbWeight::get().writes(3 as Weight))
|
.saturating_add(RocksDbWeight::get().writes(3 as Weight))
|
||||||
}
|
}
|
||||||
fn receive_delivery_proof_for_two_messages_by_single_relayer() -> Weight {
|
fn receive_delivery_proof_for_two_messages_by_single_relayer() -> Weight {
|
||||||
(137_946_000 as Weight)
|
(137_143_000 as Weight)
|
||||||
.saturating_add(RocksDbWeight::get().reads(7 as Weight))
|
.saturating_add(RocksDbWeight::get().reads(7 as Weight))
|
||||||
.saturating_add(RocksDbWeight::get().writes(3 as Weight))
|
.saturating_add(RocksDbWeight::get().writes(3 as Weight))
|
||||||
}
|
}
|
||||||
fn receive_delivery_proof_for_two_messages_by_two_relayers() -> Weight {
|
fn receive_delivery_proof_for_two_messages_by_two_relayers() -> Weight {
|
||||||
(194_448_000 as Weight)
|
(193_108_000 as Weight)
|
||||||
.saturating_add(RocksDbWeight::get().reads(8 as Weight))
|
.saturating_add(RocksDbWeight::get().reads(8 as Weight))
|
||||||
.saturating_add(RocksDbWeight::get().writes(4 as Weight))
|
.saturating_add(RocksDbWeight::get().writes(4 as Weight))
|
||||||
}
|
}
|
||||||
fn send_messages_of_various_lengths(i: u32) -> Weight {
|
fn send_messages_of_various_lengths(i: u32) -> Weight {
|
||||||
(142_576_000 as Weight)
|
(133_632_000 as Weight)
|
||||||
.saturating_add((2_000 as Weight).saturating_mul(i as Weight))
|
.saturating_add((4_000 as Weight).saturating_mul(i as Weight))
|
||||||
.saturating_add(RocksDbWeight::get().reads(5 as Weight))
|
.saturating_add(RocksDbWeight::get().reads(5 as Weight))
|
||||||
.saturating_add(RocksDbWeight::get().writes(12 as Weight))
|
.saturating_add(RocksDbWeight::get().writes(12 as Weight))
|
||||||
}
|
}
|
||||||
fn receive_multiple_messages_proof(i: u32) -> Weight {
|
fn receive_multiple_messages_proof(i: u32) -> Weight {
|
||||||
(0 as Weight)
|
(0 as Weight)
|
||||||
.saturating_add((138_341_000 as Weight).saturating_mul(i as Weight))
|
.saturating_add((145_006_000 as Weight).saturating_mul(i as Weight))
|
||||||
.saturating_add(RocksDbWeight::get().reads(5 as Weight))
|
.saturating_add(RocksDbWeight::get().reads(5 as Weight))
|
||||||
.saturating_add(RocksDbWeight::get().writes(3 as Weight))
|
.saturating_add(RocksDbWeight::get().writes(3 as Weight))
|
||||||
}
|
}
|
||||||
fn receive_message_proofs_with_extra_nodes(i: u32) -> Weight {
|
fn receive_message_proofs_with_extra_nodes(i: u32) -> Weight {
|
||||||
(472_752_000 as Weight)
|
(486_301_000 as Weight)
|
||||||
.saturating_add((9_000 as Weight).saturating_mul(i as Weight))
|
.saturating_add((10_000 as Weight).saturating_mul(i as Weight))
|
||||||
.saturating_add(RocksDbWeight::get().reads(5 as Weight))
|
.saturating_add(RocksDbWeight::get().reads(5 as Weight))
|
||||||
.saturating_add(RocksDbWeight::get().writes(3 as Weight))
|
.saturating_add(RocksDbWeight::get().writes(3 as Weight))
|
||||||
}
|
}
|
||||||
fn receive_message_proofs_with_large_leaf(i: u32) -> Weight {
|
fn receive_message_proofs_with_large_leaf(i: u32) -> Weight {
|
||||||
(175_300_000 as Weight)
|
(178_139_000 as Weight)
|
||||||
.saturating_add((6_000 as Weight).saturating_mul(i as Weight))
|
.saturating_add((7_000 as Weight).saturating_mul(i as Weight))
|
||||||
.saturating_add(RocksDbWeight::get().reads(5 as Weight))
|
.saturating_add(RocksDbWeight::get().reads(5 as Weight))
|
||||||
.saturating_add(RocksDbWeight::get().writes(3 as Weight))
|
.saturating_add(RocksDbWeight::get().writes(3 as Weight))
|
||||||
}
|
}
|
||||||
fn receive_multiple_messages_proof_with_outbound_lane_state(i: u32) -> Weight {
|
fn receive_multiple_messages_proof_with_outbound_lane_state(i: u32) -> Weight {
|
||||||
(0 as Weight)
|
(0 as Weight)
|
||||||
.saturating_add((142_176_000 as Weight).saturating_mul(i as Weight))
|
.saturating_add((150_844_000 as Weight).saturating_mul(i as Weight))
|
||||||
.saturating_add(RocksDbWeight::get().reads(5 as Weight))
|
.saturating_add(RocksDbWeight::get().reads(5 as Weight))
|
||||||
.saturating_add(RocksDbWeight::get().writes(3 as Weight))
|
.saturating_add(RocksDbWeight::get().writes(3 as Weight))
|
||||||
}
|
}
|
||||||
fn receive_delivery_proof_for_multiple_messages_by_single_relayer(i: u32) -> Weight {
|
fn receive_delivery_proof_for_multiple_messages_by_single_relayer(i: u32) -> Weight {
|
||||||
(127_372_000 as Weight)
|
(113_140_000 as Weight)
|
||||||
.saturating_add((7_927_000 as Weight).saturating_mul(i as Weight))
|
.saturating_add((7_656_000 as Weight).saturating_mul(i as Weight))
|
||||||
.saturating_add(RocksDbWeight::get().reads(5 as Weight))
|
.saturating_add(RocksDbWeight::get().reads(5 as Weight))
|
||||||
.saturating_add(RocksDbWeight::get().reads((1 as Weight).saturating_mul(i as Weight)))
|
.saturating_add(RocksDbWeight::get().reads((1 as Weight).saturating_mul(i as Weight)))
|
||||||
.saturating_add(RocksDbWeight::get().writes(3 as Weight))
|
.saturating_add(RocksDbWeight::get().writes(3 as Weight))
|
||||||
}
|
}
|
||||||
fn receive_delivery_proof_for_multiple_messages_by_multiple_relayers(i: u32) -> Weight {
|
fn receive_delivery_proof_for_multiple_messages_by_multiple_relayers(i: u32) -> Weight {
|
||||||
(99_781_000 as Weight)
|
(97_424_000 as Weight)
|
||||||
.saturating_add((64_001_000 as Weight).saturating_mul(i as Weight))
|
.saturating_add((63_128_000 as Weight).saturating_mul(i as Weight))
|
||||||
.saturating_add(RocksDbWeight::get().reads(5 as Weight))
|
.saturating_add(RocksDbWeight::get().reads(5 as Weight))
|
||||||
.saturating_add(RocksDbWeight::get().reads((2 as Weight).saturating_mul(i as Weight)))
|
.saturating_add(RocksDbWeight::get().reads((2 as Weight).saturating_mul(i as Weight)))
|
||||||
.saturating_add(RocksDbWeight::get().writes(3 as Weight))
|
.saturating_add(RocksDbWeight::get().writes(3 as Weight))
|
||||||
|
|||||||
@@ -7,7 +7,9 @@ edition = "2018"
|
|||||||
license = "GPL-3.0-or-later WITH Classpath-exception-2.0"
|
license = "GPL-3.0-or-later WITH Classpath-exception-2.0"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = ["derive"] }
|
bitvec = { version = "0.20", default-features = false, features = ["alloc"] }
|
||||||
|
codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = ["derive", "bit-vec"] }
|
||||||
|
impl-trait-for-tuples = "0.2"
|
||||||
serde = { version = "1.0.101", optional = true, features = ["derive"] }
|
serde = { version = "1.0.101", optional = true, features = ["derive"] }
|
||||||
|
|
||||||
# Bridge dependencies
|
# Bridge dependencies
|
||||||
|
|||||||
@@ -22,6 +22,7 @@
|
|||||||
// Generated by `DecodeLimit::decode_with_depth_limit`
|
// Generated by `DecodeLimit::decode_with_depth_limit`
|
||||||
#![allow(clippy::unnecessary_mut_passed)]
|
#![allow(clippy::unnecessary_mut_passed)]
|
||||||
|
|
||||||
|
use bitvec::prelude::*;
|
||||||
use codec::{Decode, Encode};
|
use codec::{Decode, Encode};
|
||||||
use frame_support::RuntimeDebug;
|
use frame_support::RuntimeDebug;
|
||||||
use sp_std::{collections::vec_deque::VecDeque, prelude::*};
|
use sp_std::{collections::vec_deque::VecDeque, prelude::*};
|
||||||
@@ -120,7 +121,7 @@ pub struct InboundLaneData<RelayerId> {
|
|||||||
/// When a relayer sends a single message, both of MessageNonces are the same.
|
/// When a relayer sends a single message, both of MessageNonces are the same.
|
||||||
/// When relayer sends messages in a batch, the first arg is the lowest nonce, second arg the highest nonce.
|
/// When relayer sends messages in a batch, the first arg is the lowest nonce, second arg the highest nonce.
|
||||||
/// Multiple dispatches from the same relayer are allowed.
|
/// Multiple dispatches from the same relayer are allowed.
|
||||||
pub relayers: VecDeque<(MessageNonce, MessageNonce, RelayerId)>,
|
pub relayers: VecDeque<UnrewardedRelayer<RelayerId>>,
|
||||||
|
|
||||||
/// Nonce of the last message that
|
/// Nonce of the last message that
|
||||||
/// a) has been delivered to the target (this) chain and
|
/// a) has been delivered to the target (this) chain and
|
||||||
@@ -147,18 +148,22 @@ impl<RelayerId> InboundLaneData<RelayerId> {
|
|||||||
/// size of each entry.
|
/// size of each entry.
|
||||||
///
|
///
|
||||||
/// Returns `None` if size overflows `u32` limits.
|
/// Returns `None` if size overflows `u32` limits.
|
||||||
pub fn encoded_size_hint(relayer_id_encoded_size: u32, relayers_entries: u32) -> Option<u32> {
|
pub fn encoded_size_hint(relayer_id_encoded_size: u32, relayers_entries: u32, messages_count: u32) -> Option<u32> {
|
||||||
let message_nonce_size = 8;
|
let message_nonce_size = 8;
|
||||||
let relayers_entry_size = relayer_id_encoded_size.checked_add(2 * message_nonce_size)?;
|
let relayers_entry_size = relayer_id_encoded_size.checked_add(2 * message_nonce_size)?;
|
||||||
let relayers_size = relayers_entries.checked_mul(relayers_entry_size)?;
|
let relayers_size = relayers_entries.checked_mul(relayers_entry_size)?;
|
||||||
relayers_size.checked_add(message_nonce_size)
|
let dispatch_results_per_byte = 8;
|
||||||
|
let dispatch_result_size = sp_std::cmp::max(relayers_entries, messages_count / dispatch_results_per_byte);
|
||||||
|
relayers_size
|
||||||
|
.checked_add(message_nonce_size)
|
||||||
|
.and_then(|result| result.checked_add(dispatch_result_size))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Nonce of the last message that has been delivered to this (target) chain.
|
/// Nonce of the last message that has been delivered to this (target) chain.
|
||||||
pub fn last_delivered_nonce(&self) -> MessageNonce {
|
pub fn last_delivered_nonce(&self) -> MessageNonce {
|
||||||
self.relayers
|
self.relayers
|
||||||
.back()
|
.back()
|
||||||
.map(|(_, last_nonce, _)| *last_nonce)
|
.map(|entry| entry.messages.end)
|
||||||
.unwrap_or(self.last_confirmed_nonce)
|
.unwrap_or(self.last_confirmed_nonce)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -176,6 +181,71 @@ pub struct MessageDetails<OutboundMessageFee> {
|
|||||||
pub delivery_and_dispatch_fee: OutboundMessageFee,
|
pub delivery_and_dispatch_fee: OutboundMessageFee,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Bit vector of message dispatch results.
|
||||||
|
pub type DispatchResultsBitVec = BitVec<Msb0, u8>;
|
||||||
|
|
||||||
|
/// Unrewarded relayer entry stored in the inbound lane data.
|
||||||
|
///
|
||||||
|
/// This struct represents a continuous range of messages that have been delivered by the same relayer
|
||||||
|
/// and whose confirmations are still pending.
|
||||||
|
#[derive(Encode, Decode, Clone, RuntimeDebug, PartialEq, Eq)]
|
||||||
|
pub struct UnrewardedRelayer<RelayerId> {
|
||||||
|
/// Identifier of the relayer.
|
||||||
|
pub relayer: RelayerId,
|
||||||
|
/// Messages range, delivered by this relayer.
|
||||||
|
pub messages: DeliveredMessages,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Delivered messages with their dispatch result.
|
||||||
|
#[derive(Clone, Default, Encode, Decode, RuntimeDebug, PartialEq, Eq)]
|
||||||
|
pub struct DeliveredMessages {
|
||||||
|
/// Nonce of the first message that has been delivered (inclusive).
|
||||||
|
pub begin: MessageNonce,
|
||||||
|
/// Nonce of the last message that has been delivered (inclusive).
|
||||||
|
pub end: MessageNonce,
|
||||||
|
/// Dispatch result (`false`/`true`), returned by the message dispatcher for every
|
||||||
|
/// message in the `[begin; end]` range. See `dispatch_result` field of the
|
||||||
|
/// `bp_runtime::messages::MessageDispatchResult` structure for more information.
|
||||||
|
pub dispatch_results: DispatchResultsBitVec,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl DeliveredMessages {
|
||||||
|
/// Create new `DeliveredMessages` struct that confirms delivery of single nonce with given dispatch result.
|
||||||
|
pub fn new(nonce: MessageNonce, dispatch_result: bool) -> Self {
|
||||||
|
DeliveredMessages {
|
||||||
|
begin: nonce,
|
||||||
|
end: nonce,
|
||||||
|
dispatch_results: bitvec![Msb0, u8; if dispatch_result { 1 } else { 0 }],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Note new dispatched message.
|
||||||
|
pub fn note_dispatched_message(&mut self, dispatch_result: bool) {
|
||||||
|
self.end += 1;
|
||||||
|
self.dispatch_results.push(dispatch_result);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns true if delivered messages contain message with given nonce.
|
||||||
|
pub fn contains_message(&self, nonce: MessageNonce) -> bool {
|
||||||
|
(self.begin..=self.end).contains(&nonce)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get dispatch result flag by message nonce.
|
||||||
|
///
|
||||||
|
/// Dispatch result flag must be interpreted using the knowledge of dispatch mechanism
|
||||||
|
/// at the target chain. See `dispatch_result` field of the
|
||||||
|
/// `bp_runtime::messages::MessageDispatchResult` structure for more information.
|
||||||
|
///
|
||||||
|
/// Panics if message nonce is not in the `begin..=end` range. Typically you'll first
|
||||||
|
/// check if message is within the range by calling `contains_message`.
|
||||||
|
pub fn message_dispatch_result(&self, nonce: MessageNonce) -> bool {
|
||||||
|
const INVALID_NONCE: &str = "Invalid nonce used to index dispatch_results";
|
||||||
|
|
||||||
|
let index = nonce.checked_sub(self.begin).expect(INVALID_NONCE) as usize;
|
||||||
|
*self.dispatch_results.get(index).expect(INVALID_NONCE)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Gist of `InboundLaneData::relayers` field used by runtime APIs.
|
/// Gist of `InboundLaneData::relayers` field used by runtime APIs.
|
||||||
#[derive(Clone, Default, Encode, Decode, RuntimeDebug, PartialEq, Eq)]
|
#[derive(Clone, Default, Encode, Decode, RuntimeDebug, PartialEq, Eq)]
|
||||||
pub struct UnrewardedRelayersState {
|
pub struct UnrewardedRelayersState {
|
||||||
@@ -214,12 +284,10 @@ impl Default for OutboundLaneData {
|
|||||||
/// Returns total number of messages in the `InboundLaneData::relayers` vector.
|
/// Returns total number of messages in the `InboundLaneData::relayers` vector.
|
||||||
///
|
///
|
||||||
/// Returns `None` if there are more messages that `MessageNonce` may fit (i.e. `MessageNonce + 1`).
|
/// Returns `None` if there are more messages that `MessageNonce` may fit (i.e. `MessageNonce + 1`).
|
||||||
pub fn total_unrewarded_messages<RelayerId>(
|
pub fn total_unrewarded_messages<RelayerId>(relayers: &VecDeque<UnrewardedRelayer<RelayerId>>) -> Option<MessageNonce> {
|
||||||
relayers: &VecDeque<(MessageNonce, MessageNonce, RelayerId)>,
|
|
||||||
) -> Option<MessageNonce> {
|
|
||||||
match (relayers.front(), relayers.back()) {
|
match (relayers.front(), relayers.back()) {
|
||||||
(Some((begin, _, _)), Some((_, end, _))) => {
|
(Some(front), Some(back)) => {
|
||||||
if let Some(difference) = end.checked_sub(*begin) {
|
if let Some(difference) = back.messages.end.checked_sub(front.messages.begin) {
|
||||||
difference.checked_add(1)
|
difference.checked_add(1)
|
||||||
} else {
|
} else {
|
||||||
Some(0)
|
Some(0)
|
||||||
@@ -237,9 +305,18 @@ mod tests {
|
|||||||
fn total_unrewarded_messages_does_not_overflow() {
|
fn total_unrewarded_messages_does_not_overflow() {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
total_unrewarded_messages(
|
total_unrewarded_messages(
|
||||||
&vec![(0, 0, 1), (MessageNonce::MAX, MessageNonce::MAX, 2)]
|
&vec![
|
||||||
.into_iter()
|
UnrewardedRelayer {
|
||||||
.collect()
|
relayer: 1,
|
||||||
|
messages: DeliveredMessages::new(0, true)
|
||||||
|
},
|
||||||
|
UnrewardedRelayer {
|
||||||
|
relayer: 2,
|
||||||
|
messages: DeliveredMessages::new(MessageNonce::MAX, true)
|
||||||
|
},
|
||||||
|
]
|
||||||
|
.into_iter()
|
||||||
|
.collect()
|
||||||
),
|
),
|
||||||
None,
|
None,
|
||||||
);
|
);
|
||||||
@@ -247,19 +324,60 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn inbound_lane_data_returns_correct_hint() {
|
fn inbound_lane_data_returns_correct_hint() {
|
||||||
let expected_size = InboundLaneData::<u8>::encoded_size_hint(1, 13);
|
let test_cases = vec![
|
||||||
let actual_size = InboundLaneData {
|
// single relayer, multiple messages
|
||||||
relayers: (1u8..=13u8).map(|i| (i as _, i as _, i)).collect(),
|
(1, 128u8),
|
||||||
last_confirmed_nonce: 13,
|
// multiple relayers, single message per relayer
|
||||||
|
(128u8, 128u8),
|
||||||
|
// several messages per relayer
|
||||||
|
(13u8, 128u8),
|
||||||
|
];
|
||||||
|
for (relayer_entries, messages_count) in test_cases {
|
||||||
|
let expected_size = InboundLaneData::<u8>::encoded_size_hint(1, relayer_entries as _, messages_count as _);
|
||||||
|
let actual_size = InboundLaneData {
|
||||||
|
relayers: (1u8..=relayer_entries)
|
||||||
|
.map(|i| {
|
||||||
|
let mut entry = UnrewardedRelayer {
|
||||||
|
relayer: i,
|
||||||
|
messages: DeliveredMessages::new(i as _, true),
|
||||||
|
};
|
||||||
|
entry.messages.dispatch_results = bitvec![
|
||||||
|
Msb0, u8;
|
||||||
|
1;
|
||||||
|
(messages_count / relayer_entries) as _
|
||||||
|
];
|
||||||
|
entry
|
||||||
|
})
|
||||||
|
.collect(),
|
||||||
|
last_confirmed_nonce: messages_count as _,
|
||||||
|
}
|
||||||
|
.encode()
|
||||||
|
.len();
|
||||||
|
let difference = (expected_size.unwrap() as f64 - actual_size as f64).abs();
|
||||||
|
assert!(
|
||||||
|
difference / (std::cmp::min(actual_size, expected_size.unwrap() as usize) as f64) < 0.1,
|
||||||
|
"Too large difference between actual ({}) and expected ({:?}) inbound lane data size. Test case: {}+{}",
|
||||||
|
actual_size,
|
||||||
|
expected_size,
|
||||||
|
relayer_entries,
|
||||||
|
messages_count,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
.encode()
|
}
|
||||||
.len();
|
|
||||||
let difference = (expected_size.unwrap() as f64 - actual_size as f64).abs();
|
#[test]
|
||||||
assert!(
|
fn message_dispatch_result_works() {
|
||||||
difference / (std::cmp::min(actual_size, expected_size.unwrap() as usize) as f64) < 0.1,
|
let delivered_messages = DeliveredMessages {
|
||||||
"Too large difference between actual ({}) and expected ({:?}) inbound lane data size",
|
begin: 100,
|
||||||
actual_size,
|
end: 150,
|
||||||
expected_size,
|
dispatch_results: bitvec![Msb0, u8; 1; 151],
|
||||||
);
|
};
|
||||||
|
|
||||||
|
assert!(!delivered_messages.contains_message(99));
|
||||||
|
assert!(delivered_messages.contains_message(100));
|
||||||
|
assert!(delivered_messages.contains_message(150));
|
||||||
|
assert!(!delivered_messages.contains_message(151));
|
||||||
|
|
||||||
|
assert!(delivered_messages.message_dispatch_result(125));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,7 +16,7 @@
|
|||||||
|
|
||||||
//! Primitives of messages module, that are used on the source chain.
|
//! Primitives of messages module, that are used on the source chain.
|
||||||
|
|
||||||
use crate::{InboundLaneData, LaneId, MessageNonce, OutboundLaneData};
|
use crate::{DeliveredMessages, InboundLaneData, LaneId, MessageNonce, OutboundLaneData};
|
||||||
|
|
||||||
use bp_runtime::Size;
|
use bp_runtime::Size;
|
||||||
use frame_support::{Parameter, RuntimeDebug};
|
use frame_support::{Parameter, RuntimeDebug};
|
||||||
@@ -135,6 +135,15 @@ pub trait MessageDeliveryAndDispatchPayment<AccountId, Balance> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Handler for messages delivery confirmation.
|
||||||
|
#[impl_trait_for_tuples::impl_for_tuples(30)]
|
||||||
|
pub trait OnDeliveryConfirmed {
|
||||||
|
/// Called when we receive confirmation that our messages have been delivered to the
|
||||||
|
/// target chain. The confirmation also has single bit dispatch result for every
|
||||||
|
/// confirmed message (see `DeliveredMessages` for details).
|
||||||
|
fn on_messages_delivered(_lane: &LaneId, _messages: &DeliveredMessages) {}
|
||||||
|
}
|
||||||
|
|
||||||
/// Structure that may be used in place of `TargetHeaderChain`, `LaneMessageVerifier` and
|
/// Structure that may be used in place of `TargetHeaderChain`, `LaneMessageVerifier` and
|
||||||
/// `MessageDeliveryAndDispatchPayment` on chains, where outbound messages are forbidden.
|
/// `MessageDeliveryAndDispatchPayment` on chains, where outbound messages are forbidden.
|
||||||
pub struct ForbidOutboundMessages;
|
pub struct ForbidOutboundMessages;
|
||||||
|
|||||||
@@ -164,6 +164,7 @@ impl<AccountId, Fee> MessageDispatch<AccountId, Fee> for ForbidInboundMessages {
|
|||||||
|
|
||||||
fn dispatch(_: &AccountId, _: DispatchMessage<Self::DispatchPayload, Fee>) -> MessageDispatchResult {
|
fn dispatch(_: &AccountId, _: DispatchMessage<Self::DispatchPayload, Fee>) -> MessageDispatchResult {
|
||||||
MessageDispatchResult {
|
MessageDispatchResult {
|
||||||
|
dispatch_result: false,
|
||||||
unspent_weight: 0,
|
unspent_weight: 0,
|
||||||
dispatch_fee_paid_during_dispatch: false,
|
dispatch_fee_paid_during_dispatch: false,
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -36,6 +36,12 @@ pub enum DispatchFeePayment {
|
|||||||
/// Message dispatch result.
|
/// Message dispatch result.
|
||||||
#[derive(Encode, Decode, RuntimeDebug, Clone, PartialEq, Eq)]
|
#[derive(Encode, Decode, RuntimeDebug, Clone, PartialEq, Eq)]
|
||||||
pub struct MessageDispatchResult {
|
pub struct MessageDispatchResult {
|
||||||
|
/// Dispatch result flag. This flag is relayed back to the source chain and, generally
|
||||||
|
/// speaking, may bring any (that fits in single bit) information from the dispatcher at
|
||||||
|
/// the target chain to the message submitter at the source chain. If you're using immediate
|
||||||
|
/// call dispatcher, then it'll be result of the dispatch - `true` if dispatch has succeeded
|
||||||
|
/// and `false` otherwise.
|
||||||
|
pub dispatch_result: bool,
|
||||||
/// Unspent dispatch weight. This weight that will be deducted from total delivery transaction
|
/// Unspent dispatch weight. This weight that will be deducted from total delivery transaction
|
||||||
/// weight, thus reducing the transaction cost. This shall not be zero in (at least) two cases:
|
/// weight, thus reducing the transaction cost. This shall not be zero in (at least) two cases:
|
||||||
///
|
///
|
||||||
|
|||||||
@@ -204,7 +204,7 @@ mod tests {
|
|||||||
// reserved for messages dispatch allows dispatch of non-trivial messages.
|
// reserved for messages dispatch allows dispatch of non-trivial messages.
|
||||||
//
|
//
|
||||||
// Any significant change in this values should attract additional attention.
|
// Any significant change in this values should attract additional attention.
|
||||||
(814, 216_583_333_334),
|
(782, 216_583_333_334),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user