mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-05-30 21:01:02 +00:00
pay dispatch fee at target chain (#911)
* pay dispatch fee at target chain
* refund unspent dispatch weight to messages relayer
* test that transfer actually happens
* pay-at-target-cchain benchmarks + fix previous benchmarks (invalid signature)
* include/exclude pay-dispatch-fee weight from delivery_and_dispatch_fee/delivery tx cost
* remvoe some redundant traces
* enum DispatchFeePayment {}
* typo
* update docs
* (revert removal of valid check)
* Update modules/messages/src/benchmarking.rs
Co-authored-by: Tomasz Drwięga <tomusdrw@users.noreply.github.com>
* Update modules/messages/src/benchmarking.rs
Co-authored-by: Tomasz Drwięga <tomusdrw@users.noreply.github.com>
* Update modules/messages/src/benchmarking.rs
Co-authored-by: Tomasz Drwięga <tomusdrw@users.noreply.github.com>
* Update modules/messages/src/benchmarking.rs
Co-authored-by: Tomasz Drwięga <tomusdrw@users.noreply.github.com>
Co-authored-by: Tomasz Drwięga <tomusdrw@users.noreply.github.com>
Co-authored-by: Tomasz Drwięga <tomasz@parity.io>
This commit is contained in:
committed by
Bastian Köcher
parent
613803a15d
commit
20b7f341e1
@@ -686,6 +686,7 @@ mod tests {
|
|||||||
bp_millau::DEFAULT_MESSAGE_DELIVERY_TX_WEIGHT,
|
bp_millau::DEFAULT_MESSAGE_DELIVERY_TX_WEIGHT,
|
||||||
bp_millau::ADDITIONAL_MESSAGE_BYTE_DELIVERY_WEIGHT,
|
bp_millau::ADDITIONAL_MESSAGE_BYTE_DELIVERY_WEIGHT,
|
||||||
bp_millau::MAX_SINGLE_MESSAGE_DELIVERY_CONFIRMATION_TX_WEIGHT,
|
bp_millau::MAX_SINGLE_MESSAGE_DELIVERY_CONFIRMATION_TX_WEIGHT,
|
||||||
|
bp_millau::PAY_INBOUND_DISPATCH_FEE_WEIGHT,
|
||||||
);
|
);
|
||||||
|
|
||||||
let max_incoming_message_proof_size = bp_rialto::EXTRA_STORAGE_PROOF_SIZE.saturating_add(
|
let max_incoming_message_proof_size = bp_rialto::EXTRA_STORAGE_PROOF_SIZE.saturating_add(
|
||||||
|
|||||||
@@ -64,6 +64,7 @@ type ToRialtoMessagesDeliveryProof = messages::source::FromBridgedChainMessagesD
|
|||||||
pub type FromRialtoMessageDispatch = messages::target::FromBridgedChainMessageDispatch<
|
pub type FromRialtoMessageDispatch = messages::target::FromBridgedChainMessageDispatch<
|
||||||
WithRialtoMessageBridge,
|
WithRialtoMessageBridge,
|
||||||
crate::Runtime,
|
crate::Runtime,
|
||||||
|
pallet_balances::Pallet<Runtime>,
|
||||||
pallet_bridge_dispatch::DefaultInstance,
|
pallet_bridge_dispatch::DefaultInstance,
|
||||||
>;
|
>;
|
||||||
|
|
||||||
@@ -172,6 +173,7 @@ impl messages::BridgedChainWithMessages for Rialto {
|
|||||||
|
|
||||||
fn estimate_delivery_transaction(
|
fn estimate_delivery_transaction(
|
||||||
message_payload: &[u8],
|
message_payload: &[u8],
|
||||||
|
include_pay_dispatch_fee_cost: bool,
|
||||||
message_dispatch_weight: Weight,
|
message_dispatch_weight: Weight,
|
||||||
) -> MessageTransaction<Weight> {
|
) -> MessageTransaction<Weight> {
|
||||||
let message_payload_len = u32::try_from(message_payload.len()).unwrap_or(u32::MAX);
|
let message_payload_len = u32::try_from(message_payload.len()).unwrap_or(u32::MAX);
|
||||||
@@ -182,6 +184,11 @@ impl messages::BridgedChainWithMessages for Rialto {
|
|||||||
dispatch_weight: extra_bytes_in_payload
|
dispatch_weight: extra_bytes_in_payload
|
||||||
.saturating_mul(bp_rialto::ADDITIONAL_MESSAGE_BYTE_DELIVERY_WEIGHT)
|
.saturating_mul(bp_rialto::ADDITIONAL_MESSAGE_BYTE_DELIVERY_WEIGHT)
|
||||||
.saturating_add(bp_rialto::DEFAULT_MESSAGE_DELIVERY_TX_WEIGHT)
|
.saturating_add(bp_rialto::DEFAULT_MESSAGE_DELIVERY_TX_WEIGHT)
|
||||||
|
.saturating_sub(if include_pay_dispatch_fee_cost {
|
||||||
|
0
|
||||||
|
} else {
|
||||||
|
bp_rialto::PAY_INBOUND_DISPATCH_FEE_WEIGHT
|
||||||
|
})
|
||||||
.saturating_add(message_dispatch_weight),
|
.saturating_add(message_dispatch_weight),
|
||||||
size: message_payload_len
|
size: message_payload_len
|
||||||
.saturating_add(bp_millau::EXTRA_STORAGE_PROOF_SIZE)
|
.saturating_add(bp_millau::EXTRA_STORAGE_PROOF_SIZE)
|
||||||
|
|||||||
@@ -862,6 +862,7 @@ impl_runtime_apis! {
|
|||||||
}
|
}
|
||||||
|
|
||||||
use crate::millau_messages::{ToMillauMessagePayload, WithMillauMessageBridge};
|
use crate::millau_messages::{ToMillauMessagePayload, WithMillauMessageBridge};
|
||||||
|
use bp_runtime::messages::DispatchFeePayment;
|
||||||
use bridge_runtime_common::messages;
|
use bridge_runtime_common::messages;
|
||||||
use pallet_bridge_messages::benchmarking::{
|
use pallet_bridge_messages::benchmarking::{
|
||||||
Pallet as MessagesBench,
|
Pallet as MessagesBench,
|
||||||
@@ -905,6 +906,7 @@ impl_runtime_apis! {
|
|||||||
weight: params.size as _,
|
weight: params.size as _,
|
||||||
origin: dispatch_origin,
|
origin: dispatch_origin,
|
||||||
call: message_payload,
|
call: message_payload,
|
||||||
|
dispatch_fee_payment: DispatchFeePayment::AtSourceChain,
|
||||||
};
|
};
|
||||||
(message, pallet_bridge_messages::benchmarking::MESSAGE_FEE.into())
|
(message, pallet_bridge_messages::benchmarking::MESSAGE_FEE.into())
|
||||||
}
|
}
|
||||||
@@ -921,7 +923,7 @@ impl_runtime_apis! {
|
|||||||
use codec::Encode;
|
use codec::Encode;
|
||||||
use frame_support::weights::GetDispatchInfo;
|
use frame_support::weights::GetDispatchInfo;
|
||||||
use pallet_bridge_messages::storage_keys;
|
use pallet_bridge_messages::storage_keys;
|
||||||
use sp_runtime::traits::Header;
|
use sp_runtime::traits::{Header, IdentifyAccount};
|
||||||
|
|
||||||
let remark = match params.size {
|
let remark = match params.size {
|
||||||
MessagesProofSize::Minimal(ref size) => vec![0u8; *size as _],
|
MessagesProofSize::Minimal(ref size) => vec![0u8; *size as _],
|
||||||
@@ -934,12 +936,19 @@ impl_runtime_apis! {
|
|||||||
let (rialto_raw_public, rialto_raw_signature) = ed25519_sign(
|
let (rialto_raw_public, rialto_raw_signature) = ed25519_sign(
|
||||||
&call,
|
&call,
|
||||||
&millau_account_id,
|
&millau_account_id,
|
||||||
|
VERSION.spec_version,
|
||||||
|
bp_runtime::MILLAU_CHAIN_ID,
|
||||||
|
bp_runtime::RIALTO_CHAIN_ID,
|
||||||
);
|
);
|
||||||
let rialto_public = MultiSigner::Ed25519(sp_core::ed25519::Public::from_raw(rialto_raw_public));
|
let rialto_public = MultiSigner::Ed25519(sp_core::ed25519::Public::from_raw(rialto_raw_public));
|
||||||
let rialto_signature = MultiSignature::Ed25519(sp_core::ed25519::Signature::from_raw(
|
let rialto_signature = MultiSignature::Ed25519(sp_core::ed25519::Signature::from_raw(
|
||||||
rialto_raw_signature,
|
rialto_raw_signature,
|
||||||
));
|
));
|
||||||
|
|
||||||
|
if params.dispatch_fee_payment == DispatchFeePayment::AtTargetChain {
|
||||||
|
Self::endow_account(&rialto_public.clone().into_account());
|
||||||
|
}
|
||||||
|
|
||||||
let make_millau_message_key = |message_key: MessageKey| storage_keys::message_key::<
|
let make_millau_message_key = |message_key: MessageKey| storage_keys::message_key::<
|
||||||
Runtime,
|
Runtime,
|
||||||
<Millau as ChainWithMessages>::MessagesInstance,
|
<Millau as ChainWithMessages>::MessagesInstance,
|
||||||
@@ -960,6 +969,7 @@ impl_runtime_apis! {
|
|||||||
Default::default(),
|
Default::default(),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
let dispatch_fee_payment = params.dispatch_fee_payment.clone();
|
||||||
prepare_message_proof::<WithMillauMessageBridge, bp_millau::Hasher, Runtime, (), _, _, _>(
|
prepare_message_proof::<WithMillauMessageBridge, bp_millau::Hasher, Runtime, (), _, _, _>(
|
||||||
params,
|
params,
|
||||||
make_millau_message_key,
|
make_millau_message_key,
|
||||||
@@ -978,6 +988,7 @@ impl_runtime_apis! {
|
|||||||
rialto_public,
|
rialto_public,
|
||||||
rialto_signature,
|
rialto_signature,
|
||||||
),
|
),
|
||||||
|
dispatch_fee_payment,
|
||||||
call: call.encode(),
|
call: call.encode(),
|
||||||
}.encode(),
|
}.encode(),
|
||||||
)
|
)
|
||||||
@@ -1010,6 +1021,18 @@ impl_runtime_apis! {
|
|||||||
),
|
),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn is_message_dispatched(nonce: bp_messages::MessageNonce) -> bool {
|
||||||
|
frame_system::Pallet::<Runtime>::events()
|
||||||
|
.into_iter()
|
||||||
|
.map(|event_record| event_record.event)
|
||||||
|
.any(|event| matches!(
|
||||||
|
event,
|
||||||
|
Event::pallet_bridge_dispatch(pallet_bridge_dispatch::Event::<Runtime, _>::MessageDispatched(
|
||||||
|
_, ([0, 0, 0, 0], nonce_from_event), _,
|
||||||
|
)) if nonce_from_event == nonce
|
||||||
|
))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
add_benchmark!(
|
add_benchmark!(
|
||||||
@@ -1105,6 +1128,7 @@ mod tests {
|
|||||||
bp_rialto::DEFAULT_MESSAGE_DELIVERY_TX_WEIGHT,
|
bp_rialto::DEFAULT_MESSAGE_DELIVERY_TX_WEIGHT,
|
||||||
bp_rialto::ADDITIONAL_MESSAGE_BYTE_DELIVERY_WEIGHT,
|
bp_rialto::ADDITIONAL_MESSAGE_BYTE_DELIVERY_WEIGHT,
|
||||||
bp_rialto::MAX_SINGLE_MESSAGE_DELIVERY_CONFIRMATION_TX_WEIGHT,
|
bp_rialto::MAX_SINGLE_MESSAGE_DELIVERY_CONFIRMATION_TX_WEIGHT,
|
||||||
|
bp_rialto::PAY_INBOUND_DISPATCH_FEE_WEIGHT,
|
||||||
);
|
);
|
||||||
|
|
||||||
let max_incoming_message_proof_size = bp_millau::EXTRA_STORAGE_PROOF_SIZE.saturating_add(
|
let max_incoming_message_proof_size = bp_millau::EXTRA_STORAGE_PROOF_SIZE.saturating_add(
|
||||||
|
|||||||
@@ -58,6 +58,7 @@ pub type FromMillauEncodedCall = messages::target::FromBridgedChainEncodedMessag
|
|||||||
pub type FromMillauMessageDispatch = messages::target::FromBridgedChainMessageDispatch<
|
pub type FromMillauMessageDispatch = messages::target::FromBridgedChainMessageDispatch<
|
||||||
WithMillauMessageBridge,
|
WithMillauMessageBridge,
|
||||||
crate::Runtime,
|
crate::Runtime,
|
||||||
|
pallet_balances::Pallet<Runtime>,
|
||||||
pallet_bridge_dispatch::DefaultInstance,
|
pallet_bridge_dispatch::DefaultInstance,
|
||||||
>;
|
>;
|
||||||
|
|
||||||
@@ -172,6 +173,7 @@ impl messages::BridgedChainWithMessages for Millau {
|
|||||||
|
|
||||||
fn estimate_delivery_transaction(
|
fn estimate_delivery_transaction(
|
||||||
message_payload: &[u8],
|
message_payload: &[u8],
|
||||||
|
include_pay_dispatch_fee_cost: bool,
|
||||||
message_dispatch_weight: Weight,
|
message_dispatch_weight: Weight,
|
||||||
) -> MessageTransaction<Weight> {
|
) -> MessageTransaction<Weight> {
|
||||||
let message_payload_len = u32::try_from(message_payload.len()).unwrap_or(u32::MAX);
|
let message_payload_len = u32::try_from(message_payload.len()).unwrap_or(u32::MAX);
|
||||||
@@ -182,6 +184,11 @@ impl messages::BridgedChainWithMessages for Millau {
|
|||||||
dispatch_weight: extra_bytes_in_payload
|
dispatch_weight: extra_bytes_in_payload
|
||||||
.saturating_mul(bp_millau::ADDITIONAL_MESSAGE_BYTE_DELIVERY_WEIGHT)
|
.saturating_mul(bp_millau::ADDITIONAL_MESSAGE_BYTE_DELIVERY_WEIGHT)
|
||||||
.saturating_add(bp_millau::DEFAULT_MESSAGE_DELIVERY_TX_WEIGHT)
|
.saturating_add(bp_millau::DEFAULT_MESSAGE_DELIVERY_TX_WEIGHT)
|
||||||
|
.saturating_sub(if include_pay_dispatch_fee_cost {
|
||||||
|
0
|
||||||
|
} else {
|
||||||
|
bp_millau::PAY_INBOUND_DISPATCH_FEE_WEIGHT
|
||||||
|
})
|
||||||
.saturating_add(message_dispatch_weight),
|
.saturating_add(message_dispatch_weight),
|
||||||
size: message_payload_len
|
size: message_payload_len
|
||||||
.saturating_add(bp_rialto::EXTRA_STORAGE_PROOF_SIZE)
|
.saturating_add(bp_rialto::EXTRA_STORAGE_PROOF_SIZE)
|
||||||
@@ -258,3 +265,87 @@ impl MessagesParameter for RialtoToMillauMessagesParameter {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
use crate::{AccountId, Call, ExistentialDeposit, Runtime, SystemCall, SystemConfig, VERSION};
|
||||||
|
use bp_message_dispatch::CallOrigin;
|
||||||
|
use bp_messages::{
|
||||||
|
target_chain::{DispatchMessage, DispatchMessageData, MessageDispatch},
|
||||||
|
MessageKey,
|
||||||
|
};
|
||||||
|
use bp_runtime::{derive_account_id, messages::DispatchFeePayment, SourceAccount};
|
||||||
|
use bridge_runtime_common::messages::target::{FromBridgedChainEncodedMessageCall, FromBridgedChainMessagePayload};
|
||||||
|
use frame_support::{
|
||||||
|
traits::Currency,
|
||||||
|
weights::{GetDispatchInfo, WeightToFeePolynomial},
|
||||||
|
};
|
||||||
|
use sp_runtime::traits::Convert;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn transfer_happens_when_dispatch_fee_is_paid_at_target_chain() {
|
||||||
|
// this test actually belongs to the `bridge-runtime-common` crate, but there we have no
|
||||||
|
// mock runtime. Making another one there just for this test, given that both crates
|
||||||
|
// live n single repo is an overkill
|
||||||
|
let mut ext: sp_io::TestExternalities = SystemConfig::default().build_storage::<Runtime>().unwrap().into();
|
||||||
|
ext.execute_with(|| {
|
||||||
|
let bridge = MILLAU_CHAIN_ID;
|
||||||
|
let call: Call = SystemCall::remark(vec![]).into();
|
||||||
|
let dispatch_weight = call.get_dispatch_info().weight;
|
||||||
|
let dispatch_fee = <Runtime as pallet_transaction_payment::Config>::WeightToFee::calc(&dispatch_weight);
|
||||||
|
assert!(dispatch_fee > 0);
|
||||||
|
|
||||||
|
// create relayer account with minimal balance
|
||||||
|
let relayer_account: AccountId = [1u8; 32].into();
|
||||||
|
let initial_amount = ExistentialDeposit::get();
|
||||||
|
let _ = <pallet_balances::Pallet<Runtime> as Currency<AccountId>>::deposit_creating(
|
||||||
|
&relayer_account,
|
||||||
|
initial_amount,
|
||||||
|
);
|
||||||
|
|
||||||
|
// create dispatch account with minimal balance + dispatch fee
|
||||||
|
let dispatch_account = derive_account_id::<<Runtime as pallet_bridge_dispatch::Config>::SourceChainAccountId>(
|
||||||
|
bridge,
|
||||||
|
SourceAccount::Root,
|
||||||
|
);
|
||||||
|
let dispatch_account =
|
||||||
|
<Runtime as pallet_bridge_dispatch::Config>::AccountIdConverter::convert(dispatch_account);
|
||||||
|
let _ = <pallet_balances::Pallet<Runtime> as Currency<AccountId>>::deposit_creating(
|
||||||
|
&dispatch_account,
|
||||||
|
initial_amount + dispatch_fee,
|
||||||
|
);
|
||||||
|
|
||||||
|
// dispatch message with intention to pay dispatch fee at the target chain
|
||||||
|
FromMillauMessageDispatch::dispatch(
|
||||||
|
&relayer_account,
|
||||||
|
DispatchMessage {
|
||||||
|
key: MessageKey {
|
||||||
|
lane_id: Default::default(),
|
||||||
|
nonce: 0,
|
||||||
|
},
|
||||||
|
data: DispatchMessageData {
|
||||||
|
payload: Ok(FromBridgedChainMessagePayload::<WithMillauMessageBridge> {
|
||||||
|
spec_version: VERSION.spec_version,
|
||||||
|
weight: dispatch_weight,
|
||||||
|
origin: CallOrigin::SourceRoot,
|
||||||
|
dispatch_fee_payment: DispatchFeePayment::AtTargetChain,
|
||||||
|
call: FromBridgedChainEncodedMessageCall::new(call.encode()),
|
||||||
|
}),
|
||||||
|
fee: 1,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
// ensure that fee has been transferred from dispatch to relayer account
|
||||||
|
assert_eq!(
|
||||||
|
<pallet_balances::Pallet<Runtime> as Currency<AccountId>>::free_balance(&relayer_account),
|
||||||
|
initial_amount + dispatch_fee,
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
<pallet_balances::Pallet<Runtime> as Currency<AccountId>>::free_balance(&dispatch_account),
|
||||||
|
initial_amount,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ pallet-bridge-messages = { path = "../../modules/messages", default-features = f
|
|||||||
# Substrate dependencies
|
# Substrate dependencies
|
||||||
|
|
||||||
frame-support = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false }
|
frame-support = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false }
|
||||||
|
pallet-transaction-payment = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false }
|
||||||
sp-core = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false }
|
sp-core = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false }
|
||||||
sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false }
|
sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false }
|
||||||
sp-state-machine = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false, optional = true }
|
sp-state-machine = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false, optional = true }
|
||||||
@@ -42,6 +43,7 @@ std = [
|
|||||||
"pallet-bridge-dispatch/std",
|
"pallet-bridge-dispatch/std",
|
||||||
"pallet-bridge-grandpa/std",
|
"pallet-bridge-grandpa/std",
|
||||||
"pallet-bridge-messages/std",
|
"pallet-bridge-messages/std",
|
||||||
|
"pallet-transaction-payment/std",
|
||||||
"sp-core/std",
|
"sp-core/std",
|
||||||
"sp-runtime/std",
|
"sp-runtime/std",
|
||||||
"sp-state-machine/std",
|
"sp-state-machine/std",
|
||||||
|
|||||||
@@ -102,7 +102,9 @@ This trait represents this chain from bridge point of view. Let's review every m
|
|||||||
have declared dispatch weight larger than 50% of the maximal bridged extrinsic weight.
|
have declared dispatch weight larger than 50% of the maximal bridged extrinsic weight.
|
||||||
|
|
||||||
- `MessageBridge::estimate_delivery_transaction`: you will need to return estimated dispatch weight and
|
- `MessageBridge::estimate_delivery_transaction`: you will need to return estimated dispatch weight and
|
||||||
size of the delivery transaction that delivers a given message to the target chain.
|
size of the delivery transaction that delivers a given message to the target chain. The transaction
|
||||||
|
weight must or must not include the weight of pay-dispatch-fee operation, depending on the value
|
||||||
|
of `include_pay_dispatch_fee_cost` argument.
|
||||||
|
|
||||||
- `MessageBridge::transaction_payment`: you'll need to return fee that the submitter
|
- `MessageBridge::transaction_payment`: you'll need to return fee that the submitter
|
||||||
must pay for given transaction on bridged chain. The best case is when you have the same conversion
|
must pay for given transaction on bridged chain. The best case is when you have the same conversion
|
||||||
|
|||||||
@@ -26,9 +26,16 @@ use bp_messages::{
|
|||||||
target_chain::{DispatchMessage, MessageDispatch, ProvedLaneMessages, ProvedMessages},
|
target_chain::{DispatchMessage, MessageDispatch, ProvedLaneMessages, ProvedMessages},
|
||||||
InboundLaneData, LaneId, Message, MessageData, MessageKey, MessageNonce, OutboundLaneData,
|
InboundLaneData, LaneId, Message, MessageData, MessageKey, MessageNonce, OutboundLaneData,
|
||||||
};
|
};
|
||||||
use bp_runtime::{ChainId, Size, StorageProofChecker};
|
use bp_runtime::{
|
||||||
|
messages::{DispatchFeePayment, MessageDispatchResult},
|
||||||
|
ChainId, Size, StorageProofChecker,
|
||||||
|
};
|
||||||
use codec::{Decode, Encode};
|
use codec::{Decode, Encode};
|
||||||
use frame_support::{traits::Instance, weights::Weight, RuntimeDebug};
|
use frame_support::{
|
||||||
|
traits::{Currency, ExistenceRequirement, Instance},
|
||||||
|
weights::{Weight, WeightToFeePolynomial},
|
||||||
|
RuntimeDebug,
|
||||||
|
};
|
||||||
use hash_db::Hasher;
|
use hash_db::Hasher;
|
||||||
use sp_runtime::{
|
use sp_runtime::{
|
||||||
traits::{AtLeast32BitUnsigned, CheckedAdd, CheckedDiv, CheckedMul},
|
traits::{AtLeast32BitUnsigned, CheckedAdd, CheckedDiv, CheckedMul},
|
||||||
@@ -124,6 +131,7 @@ pub trait BridgedChainWithMessages: ChainWithMessages {
|
|||||||
/// Estimate size and weight of single message delivery transaction at the Bridged chain.
|
/// Estimate size and weight of single message delivery transaction at the Bridged chain.
|
||||||
fn estimate_delivery_transaction(
|
fn estimate_delivery_transaction(
|
||||||
message_payload: &[u8],
|
message_payload: &[u8],
|
||||||
|
include_pay_dispatch_fee_cost: bool,
|
||||||
message_dispatch_weight: WeightOf<Self>,
|
message_dispatch_weight: WeightOf<Self>,
|
||||||
) -> MessageTransaction<WeightOf<Self>>;
|
) -> MessageTransaction<WeightOf<Self>>;
|
||||||
|
|
||||||
@@ -326,8 +334,19 @@ pub mod source {
|
|||||||
relayer_fee_percent: u32,
|
relayer_fee_percent: u32,
|
||||||
) -> Result<BalanceOf<ThisChain<B>>, &'static str> {
|
) -> Result<BalanceOf<ThisChain<B>>, &'static str> {
|
||||||
// the fee (in Bridged tokens) of all transactions that are made on the Bridged chain
|
// the fee (in Bridged tokens) of all transactions that are made on the Bridged chain
|
||||||
let delivery_transaction =
|
//
|
||||||
BridgedChain::<B>::estimate_delivery_transaction(&payload.call, payload.weight.into());
|
// if we're going to pay dispatch fee at the target chain, then we don't include weight
|
||||||
|
// of the message dispatch in the delivery transaction cost
|
||||||
|
let pay_dispatch_fee_at_target_chain = payload.dispatch_fee_payment == DispatchFeePayment::AtTargetChain;
|
||||||
|
let delivery_transaction = BridgedChain::<B>::estimate_delivery_transaction(
|
||||||
|
&payload.call,
|
||||||
|
pay_dispatch_fee_at_target_chain,
|
||||||
|
if pay_dispatch_fee_at_target_chain {
|
||||||
|
0.into()
|
||||||
|
} else {
|
||||||
|
payload.weight.into()
|
||||||
|
},
|
||||||
|
);
|
||||||
let delivery_transaction_fee = BridgedChain::<B>::transaction_payment(delivery_transaction);
|
let delivery_transaction_fee = BridgedChain::<B>::transaction_payment(delivery_transaction);
|
||||||
|
|
||||||
// the fee (in This tokens) of all transactions that are made on This chain
|
// the fee (in This tokens) of all transactions that are made on This chain
|
||||||
@@ -445,8 +464,18 @@ pub mod target {
|
|||||||
/// vector length. Custom decode implementation here is exactly to deal with this.
|
/// vector length. Custom decode implementation here is exactly to deal with this.
|
||||||
#[derive(Decode, Encode, RuntimeDebug, PartialEq)]
|
#[derive(Decode, Encode, RuntimeDebug, PartialEq)]
|
||||||
pub struct FromBridgedChainEncodedMessageCall<B> {
|
pub struct FromBridgedChainEncodedMessageCall<B> {
|
||||||
pub(crate) encoded_call: Vec<u8>,
|
encoded_call: Vec<u8>,
|
||||||
pub(crate) _marker: PhantomData<B>,
|
_marker: PhantomData<B>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<B: MessageBridge> FromBridgedChainEncodedMessageCall<B> {
|
||||||
|
/// Create encoded call.
|
||||||
|
pub fn new(encoded_call: Vec<u8>) -> Self {
|
||||||
|
FromBridgedChainEncodedMessageCall {
|
||||||
|
encoded_call,
|
||||||
|
_marker: PhantomData::default(),
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<B: MessageBridge> From<FromBridgedChainEncodedMessageCall<B>> for Result<CallOf<ThisChain<B>>, ()> {
|
impl<B: MessageBridge> From<FromBridgedChainEncodedMessageCall<B>> for Result<CallOf<ThisChain<B>>, ()> {
|
||||||
@@ -457,20 +486,28 @@ pub mod target {
|
|||||||
|
|
||||||
/// Dispatching Bridged -> This chain messages.
|
/// Dispatching Bridged -> This chain messages.
|
||||||
#[derive(RuntimeDebug, Clone, Copy)]
|
#[derive(RuntimeDebug, Clone, Copy)]
|
||||||
pub struct FromBridgedChainMessageDispatch<B, ThisRuntime, ThisDispatchInstance> {
|
pub struct FromBridgedChainMessageDispatch<B, ThisRuntime, ThisCurrency, ThisDispatchInstance> {
|
||||||
_marker: PhantomData<(B, ThisRuntime, ThisDispatchInstance)>,
|
_marker: PhantomData<(B, ThisRuntime, ThisCurrency, ThisDispatchInstance)>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<B: MessageBridge, ThisRuntime, ThisDispatchInstance>
|
impl<B: MessageBridge, ThisRuntime, ThisCurrency, ThisDispatchInstance>
|
||||||
MessageDispatch<<BridgedChain<B> as ChainWithMessages>::Balance>
|
MessageDispatch<AccountIdOf<ThisChain<B>>, BalanceOf<BridgedChain<B>>>
|
||||||
for FromBridgedChainMessageDispatch<B, ThisRuntime, ThisDispatchInstance>
|
for FromBridgedChainMessageDispatch<B, ThisRuntime, ThisCurrency, ThisDispatchInstance>
|
||||||
where
|
where
|
||||||
ThisDispatchInstance: frame_support::traits::Instance,
|
ThisDispatchInstance: frame_support::traits::Instance,
|
||||||
ThisRuntime: pallet_bridge_dispatch::Config<ThisDispatchInstance, MessageId = (LaneId, MessageNonce)>,
|
ThisRuntime: pallet_bridge_dispatch::Config<ThisDispatchInstance, MessageId = (LaneId, MessageNonce)>
|
||||||
<ThisRuntime as pallet_bridge_dispatch::Config<ThisDispatchInstance>>::Event:
|
+ pallet_transaction_payment::Config,
|
||||||
From<pallet_bridge_dispatch::RawEvent<(LaneId, MessageNonce), ThisDispatchInstance>>,
|
<ThisRuntime as pallet_transaction_payment::Config>::OnChargeTransaction:
|
||||||
pallet_bridge_dispatch::Pallet<ThisRuntime, ThisDispatchInstance>:
|
pallet_transaction_payment::OnChargeTransaction<ThisRuntime, Balance = BalanceOf<ThisChain<B>>>,
|
||||||
bp_message_dispatch::MessageDispatch<(LaneId, MessageNonce), Message = FromBridgedChainMessagePayload<B>>,
|
ThisCurrency: Currency<AccountIdOf<ThisChain<B>>, Balance = BalanceOf<ThisChain<B>>>,
|
||||||
|
<ThisRuntime as pallet_bridge_dispatch::Config<ThisDispatchInstance>>::Event: From<
|
||||||
|
pallet_bridge_dispatch::RawEvent<(LaneId, MessageNonce), AccountIdOf<ThisChain<B>>, ThisDispatchInstance>,
|
||||||
|
>,
|
||||||
|
pallet_bridge_dispatch::Pallet<ThisRuntime, ThisDispatchInstance>: bp_message_dispatch::MessageDispatch<
|
||||||
|
AccountIdOf<ThisChain<B>>,
|
||||||
|
(LaneId, MessageNonce),
|
||||||
|
Message = FromBridgedChainMessagePayload<B>,
|
||||||
|
>,
|
||||||
{
|
{
|
||||||
type DispatchPayload = FromBridgedChainMessagePayload<B>;
|
type DispatchPayload = FromBridgedChainMessagePayload<B>;
|
||||||
|
|
||||||
@@ -480,14 +517,26 @@ pub mod target {
|
|||||||
message.data.payload.as_ref().map(|payload| payload.weight).unwrap_or(0)
|
message.data.payload.as_ref().map(|payload| payload.weight).unwrap_or(0)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn dispatch(message: DispatchMessage<Self::DispatchPayload, BalanceOf<BridgedChain<B>>>) {
|
fn dispatch(
|
||||||
|
relayer_account: &AccountIdOf<ThisChain<B>>,
|
||||||
|
message: DispatchMessage<Self::DispatchPayload, BalanceOf<BridgedChain<B>>>,
|
||||||
|
) -> MessageDispatchResult {
|
||||||
let message_id = (message.key.lane_id, message.key.nonce);
|
let message_id = (message.key.lane_id, message.key.nonce);
|
||||||
pallet_bridge_dispatch::Pallet::<ThisRuntime, ThisDispatchInstance>::dispatch(
|
pallet_bridge_dispatch::Pallet::<ThisRuntime, ThisDispatchInstance>::dispatch(
|
||||||
B::BridgedChain::ID,
|
B::BridgedChain::ID,
|
||||||
B::ThisChain::ID,
|
B::ThisChain::ID,
|
||||||
message_id,
|
message_id,
|
||||||
message.data.payload.map_err(drop),
|
message.data.payload.map_err(drop),
|
||||||
);
|
|dispatch_origin, dispatch_weight| {
|
||||||
|
ThisCurrency::transfer(
|
||||||
|
dispatch_origin,
|
||||||
|
relayer_account,
|
||||||
|
ThisRuntime::WeightToFee::calc(&dispatch_weight),
|
||||||
|
ExistenceRequirement::AllowDeath,
|
||||||
|
)
|
||||||
|
.map_err(drop)
|
||||||
|
},
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -854,6 +903,7 @@ mod tests {
|
|||||||
|
|
||||||
fn estimate_delivery_transaction(
|
fn estimate_delivery_transaction(
|
||||||
_message_payload: &[u8],
|
_message_payload: &[u8],
|
||||||
|
_include_pay_dispatch_fee_cost: bool,
|
||||||
_message_dispatch_weight: WeightOf<Self>,
|
_message_dispatch_weight: WeightOf<Self>,
|
||||||
) -> MessageTransaction<WeightOf<Self>> {
|
) -> MessageTransaction<WeightOf<Self>> {
|
||||||
unreachable!()
|
unreachable!()
|
||||||
@@ -911,6 +961,7 @@ mod tests {
|
|||||||
|
|
||||||
fn estimate_delivery_transaction(
|
fn estimate_delivery_transaction(
|
||||||
_message_payload: &[u8],
|
_message_payload: &[u8],
|
||||||
|
_include_pay_dispatch_fee_cost: bool,
|
||||||
message_dispatch_weight: WeightOf<Self>,
|
message_dispatch_weight: WeightOf<Self>,
|
||||||
) -> MessageTransaction<WeightOf<Self>> {
|
) -> MessageTransaction<WeightOf<Self>> {
|
||||||
MessageTransaction {
|
MessageTransaction {
|
||||||
@@ -935,6 +986,7 @@ mod tests {
|
|||||||
spec_version: 1,
|
spec_version: 1,
|
||||||
weight: 100,
|
weight: 100,
|
||||||
origin: bp_message_dispatch::CallOrigin::SourceRoot,
|
origin: bp_message_dispatch::CallOrigin::SourceRoot,
|
||||||
|
dispatch_fee_payment: DispatchFeePayment::AtTargetChain,
|
||||||
call: ThisChainCall::Transfer.encode(),
|
call: ThisChainCall::Transfer.encode(),
|
||||||
}
|
}
|
||||||
.encode();
|
.encode();
|
||||||
@@ -949,10 +1001,10 @@ mod tests {
|
|||||||
spec_version: 1,
|
spec_version: 1,
|
||||||
weight: 100,
|
weight: 100,
|
||||||
origin: bp_message_dispatch::CallOrigin::SourceRoot,
|
origin: bp_message_dispatch::CallOrigin::SourceRoot,
|
||||||
call: target::FromBridgedChainEncodedMessageCall::<OnThisChainBridge> {
|
dispatch_fee_payment: DispatchFeePayment::AtTargetChain,
|
||||||
encoded_call: ThisChainCall::Transfer.encode(),
|
call: target::FromBridgedChainEncodedMessageCall::<OnThisChainBridge>::new(
|
||||||
_marker: PhantomData::default(),
|
ThisChainCall::Transfer.encode(),
|
||||||
},
|
),
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
assert_eq!(Ok(ThisChainCall::Transfer), message_on_this_chain.call.into());
|
assert_eq!(Ok(ThisChainCall::Transfer), message_on_this_chain.call.into());
|
||||||
@@ -966,6 +1018,7 @@ mod tests {
|
|||||||
spec_version: 1,
|
spec_version: 1,
|
||||||
weight: 100,
|
weight: 100,
|
||||||
origin: bp_message_dispatch::CallOrigin::SourceRoot,
|
origin: bp_message_dispatch::CallOrigin::SourceRoot,
|
||||||
|
dispatch_fee_payment: DispatchFeePayment::AtSourceChain,
|
||||||
call: vec![42],
|
call: vec![42],
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -986,6 +1039,21 @@ mod tests {
|
|||||||
Ok(ThisChainBalance(EXPECTED_MINIMAL_FEE)),
|
Ok(ThisChainBalance(EXPECTED_MINIMAL_FEE)),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// let's check if estimation is less than hardcoded, if dispatch is paid at target chain
|
||||||
|
let mut payload_with_pay_on_target = regular_outbound_message_payload();
|
||||||
|
payload_with_pay_on_target.dispatch_fee_payment = DispatchFeePayment::AtTargetChain;
|
||||||
|
let fee_at_source = source::estimate_message_dispatch_and_delivery_fee::<OnThisChainBridge>(
|
||||||
|
&payload_with_pay_on_target,
|
||||||
|
OnThisChainBridge::RELAYER_FEE_PERCENT,
|
||||||
|
)
|
||||||
|
.expect("estimate_message_dispatch_and_delivery_fee failed for pay-at-target-chain message");
|
||||||
|
assert!(
|
||||||
|
fee_at_source < EXPECTED_MINIMAL_FEE.into(),
|
||||||
|
"Computed fee {:?} without prepaid dispatch must be less than the fee with prepaid dispatch {}",
|
||||||
|
fee_at_source,
|
||||||
|
EXPECTED_MINIMAL_FEE,
|
||||||
|
);
|
||||||
|
|
||||||
// and now check that the verifier checks the fee
|
// and now check that the verifier checks the fee
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
source::FromThisChainMessageVerifier::<OnThisChainBridge>::verify_message(
|
source::FromThisChainMessageVerifier::<OnThisChainBridge>::verify_message(
|
||||||
@@ -1016,6 +1084,7 @@ mod tests {
|
|||||||
spec_version: 1,
|
spec_version: 1,
|
||||||
weight: 100,
|
weight: 100,
|
||||||
origin: bp_message_dispatch::CallOrigin::SourceRoot,
|
origin: bp_message_dispatch::CallOrigin::SourceRoot,
|
||||||
|
dispatch_fee_payment: DispatchFeePayment::AtSourceChain,
|
||||||
call: vec![42],
|
call: vec![42],
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -1059,6 +1128,7 @@ mod tests {
|
|||||||
spec_version: 1,
|
spec_version: 1,
|
||||||
weight: 100,
|
weight: 100,
|
||||||
origin: bp_message_dispatch::CallOrigin::SourceAccount(ThisChainAccountId(1)),
|
origin: bp_message_dispatch::CallOrigin::SourceAccount(ThisChainAccountId(1)),
|
||||||
|
dispatch_fee_payment: DispatchFeePayment::AtSourceChain,
|
||||||
call: vec![42],
|
call: vec![42],
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -1126,6 +1196,7 @@ mod tests {
|
|||||||
spec_version: 1,
|
spec_version: 1,
|
||||||
weight: 5,
|
weight: 5,
|
||||||
origin: bp_message_dispatch::CallOrigin::SourceRoot,
|
origin: bp_message_dispatch::CallOrigin::SourceRoot,
|
||||||
|
dispatch_fee_payment: DispatchFeePayment::AtSourceChain,
|
||||||
call: vec![1, 2, 3, 4, 5, 6],
|
call: vec![1, 2, 3, 4, 5, 6],
|
||||||
},)
|
},)
|
||||||
.is_err()
|
.is_err()
|
||||||
@@ -1141,6 +1212,7 @@ mod tests {
|
|||||||
spec_version: 1,
|
spec_version: 1,
|
||||||
weight: BRIDGED_CHAIN_MAX_EXTRINSIC_WEIGHT + 1,
|
weight: BRIDGED_CHAIN_MAX_EXTRINSIC_WEIGHT + 1,
|
||||||
origin: bp_message_dispatch::CallOrigin::SourceRoot,
|
origin: bp_message_dispatch::CallOrigin::SourceRoot,
|
||||||
|
dispatch_fee_payment: DispatchFeePayment::AtSourceChain,
|
||||||
call: vec![1, 2, 3, 4, 5, 6],
|
call: vec![1, 2, 3, 4, 5, 6],
|
||||||
},)
|
},)
|
||||||
.is_err()
|
.is_err()
|
||||||
@@ -1156,6 +1228,7 @@ mod tests {
|
|||||||
spec_version: 1,
|
spec_version: 1,
|
||||||
weight: BRIDGED_CHAIN_MAX_EXTRINSIC_WEIGHT,
|
weight: BRIDGED_CHAIN_MAX_EXTRINSIC_WEIGHT,
|
||||||
origin: bp_message_dispatch::CallOrigin::SourceRoot,
|
origin: bp_message_dispatch::CallOrigin::SourceRoot,
|
||||||
|
dispatch_fee_payment: DispatchFeePayment::AtSourceChain,
|
||||||
call: vec![0; source::maximal_message_size::<OnThisChainBridge>() as usize + 1],
|
call: vec![0; source::maximal_message_size::<OnThisChainBridge>() as usize + 1],
|
||||||
},)
|
},)
|
||||||
.is_err()
|
.is_err()
|
||||||
@@ -1171,6 +1244,7 @@ mod tests {
|
|||||||
spec_version: 1,
|
spec_version: 1,
|
||||||
weight: BRIDGED_CHAIN_MAX_EXTRINSIC_WEIGHT,
|
weight: BRIDGED_CHAIN_MAX_EXTRINSIC_WEIGHT,
|
||||||
origin: bp_message_dispatch::CallOrigin::SourceRoot,
|
origin: bp_message_dispatch::CallOrigin::SourceRoot,
|
||||||
|
dispatch_fee_payment: DispatchFeePayment::AtSourceChain,
|
||||||
call: vec![0; source::maximal_message_size::<OnThisChainBridge>() as _],
|
call: vec![0; source::maximal_message_size::<OnThisChainBridge>() as _],
|
||||||
},),
|
},),
|
||||||
Ok(()),
|
Ok(()),
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ use crate::messages::{
|
|||||||
};
|
};
|
||||||
|
|
||||||
use bp_messages::{LaneId, MessageData, MessageKey, MessagePayload};
|
use bp_messages::{LaneId, MessageData, MessageKey, MessagePayload};
|
||||||
|
use bp_runtime::ChainId;
|
||||||
use codec::Encode;
|
use codec::Encode;
|
||||||
use ed25519_dalek::{PublicKey, SecretKey, Signer, KEYPAIR_LENGTH, SECRET_KEY_LENGTH};
|
use ed25519_dalek::{PublicKey, SecretKey, Signer, KEYPAIR_LENGTH, SECRET_KEY_LENGTH};
|
||||||
use frame_support::weights::Weight;
|
use frame_support::weights::Weight;
|
||||||
@@ -37,7 +38,13 @@ use sp_trie::{record_all_keys, trie_types::TrieDBMut, Layout, MemoryDB, Recorder
|
|||||||
/// Generate ed25519 signature to be used in `pallet_brdige_call_dispatch::CallOrigin::TargetAccount`.
|
/// Generate ed25519 signature to be used in `pallet_brdige_call_dispatch::CallOrigin::TargetAccount`.
|
||||||
///
|
///
|
||||||
/// Returns public key of the signer and the signature itself.
|
/// Returns public key of the signer and the signature itself.
|
||||||
pub fn ed25519_sign(target_call: &impl Encode, source_account_id: &impl Encode) -> ([u8; 32], [u8; 64]) {
|
pub fn ed25519_sign(
|
||||||
|
target_call: &impl Encode,
|
||||||
|
source_account_id: &impl Encode,
|
||||||
|
target_spec_version: u32,
|
||||||
|
source_chain_id: ChainId,
|
||||||
|
target_chain_id: ChainId,
|
||||||
|
) -> ([u8; 32], [u8; 64]) {
|
||||||
// key from the repo example (https://docs.rs/ed25519-dalek/1.0.1/ed25519_dalek/struct.SecretKey.html)
|
// key from the repo example (https://docs.rs/ed25519-dalek/1.0.1/ed25519_dalek/struct.SecretKey.html)
|
||||||
let target_secret = SecretKey::from_bytes(&[
|
let target_secret = SecretKey::from_bytes(&[
|
||||||
157, 097, 177, 157, 239, 253, 090, 096, 186, 132, 074, 244, 146, 236, 044, 196, 068, 073, 197, 105, 123, 050,
|
157, 097, 177, 157, 239, 253, 090, 096, 186, 132, 074, 244, 146, 236, 044, 196, 068, 073, 197, 105, 123, 050,
|
||||||
@@ -51,9 +58,13 @@ pub fn ed25519_sign(target_call: &impl Encode, source_account_id: &impl Encode)
|
|||||||
target_pair_bytes[SECRET_KEY_LENGTH..].copy_from_slice(&target_public.to_bytes());
|
target_pair_bytes[SECRET_KEY_LENGTH..].copy_from_slice(&target_public.to_bytes());
|
||||||
let target_pair = ed25519_dalek::Keypair::from_bytes(&target_pair_bytes).expect("hardcoded pair is valid");
|
let target_pair = ed25519_dalek::Keypair::from_bytes(&target_pair_bytes).expect("hardcoded pair is valid");
|
||||||
|
|
||||||
let mut signature_message = Vec::new();
|
let signature_message = pallet_bridge_dispatch::account_ownership_digest(
|
||||||
target_call.encode_to(&mut signature_message);
|
target_call,
|
||||||
source_account_id.encode_to(&mut signature_message);
|
source_account_id,
|
||||||
|
target_spec_version,
|
||||||
|
source_chain_id,
|
||||||
|
target_chain_id,
|
||||||
|
);
|
||||||
let target_origin_signature = target_pair
|
let target_origin_signature = target_pair
|
||||||
.try_sign(&signature_message)
|
.try_sign(&signature_message)
|
||||||
.expect("Ed25519 try_sign should not fail in benchmarks");
|
.expect("Ed25519 try_sign should not fail in benchmarks");
|
||||||
|
|||||||
@@ -44,6 +44,8 @@ module events set:
|
|||||||
weight, the dispatch is rejected. Keep in mind, that even if post-dispatch weight will be less
|
weight, the dispatch is rejected. Keep in mind, that even if post-dispatch weight will be less
|
||||||
than specified, the submitter still have to declare (and pay for) the maximal possible weight
|
than specified, the submitter still have to declare (and pay for) the maximal possible weight
|
||||||
(that is the pre-dispatch weight);
|
(that is the pre-dispatch weight);
|
||||||
|
- `MessageDispatchPaymentFailed` event is emitted if the message submitter has selected to pay
|
||||||
|
dispatch fee at the target chain, but has failed to do that;
|
||||||
- `MessageDispatched` event is emitted if the message has passed all checks and we have actually
|
- `MessageDispatched` event is emitted if the message has passed all checks and we have actually
|
||||||
dispatched it. The dispatch may still fail, though - that's why we are including the dispatch
|
dispatched it. The dispatch may still fail, though - that's why we are including the dispatch
|
||||||
result in the event payload.
|
result in the event payload.
|
||||||
|
|||||||
@@ -27,7 +27,11 @@
|
|||||||
#![allow(clippy::unused_unit)]
|
#![allow(clippy::unused_unit)]
|
||||||
|
|
||||||
use bp_message_dispatch::{CallOrigin, MessageDispatch, MessagePayload, SpecVersion, Weight};
|
use bp_message_dispatch::{CallOrigin, MessageDispatch, MessagePayload, SpecVersion, Weight};
|
||||||
use bp_runtime::{derive_account_id, ChainId, SourceAccount};
|
use bp_runtime::{
|
||||||
|
derive_account_id,
|
||||||
|
messages::{DispatchFeePayment, MessageDispatchResult},
|
||||||
|
ChainId, SourceAccount,
|
||||||
|
};
|
||||||
use codec::{Decode, Encode};
|
use codec::{Decode, Encode};
|
||||||
use frame_support::{
|
use frame_support::{
|
||||||
decl_event, decl_module, decl_storage,
|
decl_event, decl_module, decl_storage,
|
||||||
@@ -89,7 +93,8 @@ decl_storage! {
|
|||||||
|
|
||||||
decl_event!(
|
decl_event!(
|
||||||
pub enum Event<T, I = DefaultInstance> where
|
pub enum Event<T, I = DefaultInstance> where
|
||||||
<T as Config<I>>::MessageId
|
<T as Config<I>>::MessageId,
|
||||||
|
AccountId = <T as frame_system::Config>::AccountId,
|
||||||
{
|
{
|
||||||
/// Message has been rejected before reaching dispatch.
|
/// Message has been rejected before reaching dispatch.
|
||||||
MessageRejected(ChainId, MessageId),
|
MessageRejected(ChainId, MessageId),
|
||||||
@@ -101,12 +106,14 @@ decl_event!(
|
|||||||
MessageWeightMismatch(ChainId, MessageId, Weight, Weight),
|
MessageWeightMismatch(ChainId, MessageId, Weight, Weight),
|
||||||
/// Message signature mismatch.
|
/// Message signature mismatch.
|
||||||
MessageSignatureMismatch(ChainId, MessageId),
|
MessageSignatureMismatch(ChainId, MessageId),
|
||||||
/// Message has been dispatched with given result.
|
|
||||||
MessageDispatched(ChainId, MessageId, DispatchResult),
|
|
||||||
/// We have failed to decode Call from the message.
|
/// We have failed to decode Call from the message.
|
||||||
MessageCallDecodeFailed(ChainId, MessageId),
|
MessageCallDecodeFailed(ChainId, MessageId),
|
||||||
/// The call from the message has been rejected by the call filter.
|
/// The call from the message has been rejected by the call filter.
|
||||||
MessageCallRejected(ChainId, MessageId),
|
MessageCallRejected(ChainId, MessageId),
|
||||||
|
/// The origin account has failed to pay fee for dispatching the message.
|
||||||
|
MessageDispatchPaymentFailed(ChainId, MessageId, AccountId, Weight),
|
||||||
|
/// Message has been dispatched with given result.
|
||||||
|
MessageDispatched(ChainId, MessageId, DispatchResult),
|
||||||
/// Phantom member, never used. Needed to handle multiple pallet instances.
|
/// Phantom member, never used. Needed to handle multiple pallet instances.
|
||||||
_Dummy(PhantomData<I>),
|
_Dummy(PhantomData<I>),
|
||||||
}
|
}
|
||||||
@@ -120,7 +127,7 @@ decl_module! {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: Config<I>, I: Instance> MessageDispatch<T::MessageId> for Pallet<T, I> {
|
impl<T: Config<I>, I: Instance> MessageDispatch<T::AccountId, T::MessageId> for Pallet<T, I> {
|
||||||
type Message =
|
type Message =
|
||||||
MessagePayload<T::SourceChainAccountId, T::TargetChainAccountPublic, T::TargetChainSignature, T::EncodedCall>;
|
MessagePayload<T::SourceChainAccountId, T::TargetChainAccountPublic, T::TargetChainSignature, T::EncodedCall>;
|
||||||
|
|
||||||
@@ -128,7 +135,13 @@ impl<T: Config<I>, I: Instance> MessageDispatch<T::MessageId> for Pallet<T, I> {
|
|||||||
message.weight
|
message.weight
|
||||||
}
|
}
|
||||||
|
|
||||||
fn dispatch(source_chain: ChainId, target_chain: ChainId, id: T::MessageId, message: Result<Self::Message, ()>) {
|
fn dispatch<P: FnOnce(&T::AccountId, Weight) -> Result<(), ()>>(
|
||||||
|
source_chain: ChainId,
|
||||||
|
target_chain: ChainId,
|
||||||
|
id: T::MessageId,
|
||||||
|
message: Result<Self::Message, ()>,
|
||||||
|
pay_dispatch_fee: P,
|
||||||
|
) -> MessageDispatchResult {
|
||||||
// emit special even if message has been rejected by external component
|
// emit special even if message has been rejected by external component
|
||||||
let message = match message {
|
let message = match message {
|
||||||
Ok(message) => message,
|
Ok(message) => message,
|
||||||
@@ -140,12 +153,19 @@ impl<T: Config<I>, I: Instance> MessageDispatch<T::MessageId> for Pallet<T, I> {
|
|||||||
id,
|
id,
|
||||||
);
|
);
|
||||||
Self::deposit_event(RawEvent::MessageRejected(source_chain, id));
|
Self::deposit_event(RawEvent::MessageRejected(source_chain, id));
|
||||||
return;
|
return MessageDispatchResult {
|
||||||
|
unspent_weight: 0,
|
||||||
|
dispatch_fee_paid_during_dispatch: false,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// 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 {
|
||||||
|
unspent_weight: message.weight,
|
||||||
|
dispatch_fee_paid_during_dispatch: false,
|
||||||
|
};
|
||||||
let expected_version = <T as frame_system::Config>::Version::get().spec_version;
|
let expected_version = <T as frame_system::Config>::Version::get().spec_version;
|
||||||
if message.spec_version != expected_version {
|
if message.spec_version != expected_version {
|
||||||
log::trace!(
|
log::trace!(
|
||||||
@@ -161,7 +181,7 @@ impl<T: Config<I>, I: Instance> MessageDispatch<T::MessageId> for Pallet<T, I> {
|
|||||||
expected_version,
|
expected_version,
|
||||||
message.spec_version,
|
message.spec_version,
|
||||||
));
|
));
|
||||||
return;
|
return dispatch_result;
|
||||||
}
|
}
|
||||||
|
|
||||||
// now that we have spec version checked, let's decode the call
|
// now that we have spec version checked, let's decode the call
|
||||||
@@ -175,7 +195,7 @@ impl<T: Config<I>, I: Instance> MessageDispatch<T::MessageId> for Pallet<T, I> {
|
|||||||
id,
|
id,
|
||||||
);
|
);
|
||||||
Self::deposit_event(RawEvent::MessageCallDecodeFailed(source_chain, id));
|
Self::deposit_event(RawEvent::MessageCallDecodeFailed(source_chain, id));
|
||||||
return;
|
return dispatch_result;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -207,7 +227,7 @@ impl<T: Config<I>, I: Instance> MessageDispatch<T::MessageId> for Pallet<T, I> {
|
|||||||
target_signature,
|
target_signature,
|
||||||
);
|
);
|
||||||
Self::deposit_event(RawEvent::MessageSignatureMismatch(source_chain, id));
|
Self::deposit_event(RawEvent::MessageSignatureMismatch(source_chain, id));
|
||||||
return;
|
return dispatch_result;
|
||||||
}
|
}
|
||||||
|
|
||||||
log::trace!(target: "runtime::bridge-dispatch", "Target Account: {:?}", &target_account);
|
log::trace!(target: "runtime::bridge-dispatch", "Target Account: {:?}", &target_account);
|
||||||
@@ -231,7 +251,7 @@ impl<T: Config<I>, I: Instance> MessageDispatch<T::MessageId> for Pallet<T, I> {
|
|||||||
call,
|
call,
|
||||||
);
|
);
|
||||||
Self::deposit_event(RawEvent::MessageCallRejected(source_chain, id));
|
Self::deposit_event(RawEvent::MessageCallRejected(source_chain, id));
|
||||||
return;
|
return dispatch_result;
|
||||||
}
|
}
|
||||||
|
|
||||||
// verify weight
|
// verify weight
|
||||||
@@ -254,21 +274,43 @@ impl<T: Config<I>, I: Instance> MessageDispatch<T::MessageId> for Pallet<T, I> {
|
|||||||
expected_weight,
|
expected_weight,
|
||||||
message.weight,
|
message.weight,
|
||||||
));
|
));
|
||||||
return;
|
return dispatch_result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// pay dispatch fee right before dispatch
|
||||||
|
let pay_dispatch_fee_at_target_chain = message.dispatch_fee_payment == DispatchFeePayment::AtTargetChain;
|
||||||
|
if pay_dispatch_fee_at_target_chain && pay_dispatch_fee(&origin_account, message.weight).is_err() {
|
||||||
|
log::trace!(
|
||||||
|
target: "runtime::bridge-dispatch",
|
||||||
|
"Failed to pay dispatch fee for dispatching message {:?}/{:?} with weight {}",
|
||||||
|
source_chain,
|
||||||
|
id,
|
||||||
|
message.weight,
|
||||||
|
);
|
||||||
|
Self::deposit_event(RawEvent::MessageDispatchPaymentFailed(
|
||||||
|
source_chain,
|
||||||
|
id,
|
||||||
|
origin_account,
|
||||||
|
message.weight,
|
||||||
|
));
|
||||||
|
return dispatch_result;
|
||||||
|
}
|
||||||
|
dispatch_result.dispatch_fee_paid_during_dispatch = pay_dispatch_fee_at_target_chain;
|
||||||
|
|
||||||
// finally dispatch message
|
// finally dispatch message
|
||||||
let origin = RawOrigin::Signed(origin_account).into();
|
let origin = RawOrigin::Signed(origin_account).into();
|
||||||
|
|
||||||
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 dispatch_result = call.dispatch(origin);
|
let result = call.dispatch(origin);
|
||||||
let actual_call_weight = extract_actual_weight(&dispatch_result, &dispatch_info);
|
let actual_call_weight = extract_actual_weight(&result, &dispatch_info);
|
||||||
|
dispatch_result.unspent_weight = message.weight.saturating_sub(actual_call_weight);
|
||||||
|
|
||||||
log::trace!(
|
log::trace!(
|
||||||
target: "runtime::bridge-dispatch",
|
target: "runtime::bridge-dispatch",
|
||||||
"Message {:?}/{:?} has been dispatched. Weight: {} of {}. Result: {:?}",
|
"Message {:?}/{:?} has been dispatched. Weight: {} of {}. Result: {:?}",
|
||||||
source_chain,
|
source_chain,
|
||||||
id,
|
id,
|
||||||
actual_call_weight,
|
dispatch_result.unspent_weight,
|
||||||
message.weight,
|
message.weight,
|
||||||
dispatch_result,
|
dispatch_result,
|
||||||
);
|
);
|
||||||
@@ -276,8 +318,10 @@ impl<T: Config<I>, I: Instance> MessageDispatch<T::MessageId> for Pallet<T, I> {
|
|||||||
Self::deposit_event(RawEvent::MessageDispatched(
|
Self::deposit_event(RawEvent::MessageDispatched(
|
||||||
source_chain,
|
source_chain,
|
||||||
id,
|
id,
|
||||||
dispatch_result.map(drop).map_err(|e| e.error),
|
result.map(drop).map_err(|e| e.error),
|
||||||
));
|
));
|
||||||
|
|
||||||
|
dispatch_result
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -485,31 +529,32 @@ mod tests {
|
|||||||
fn prepare_message(
|
fn prepare_message(
|
||||||
origin: CallOrigin<AccountId, TestAccountPublic, TestSignature>,
|
origin: CallOrigin<AccountId, TestAccountPublic, TestSignature>,
|
||||||
call: Call,
|
call: Call,
|
||||||
) -> <Pallet<TestRuntime> as MessageDispatch<<TestRuntime as Config>::MessageId>>::Message {
|
) -> <Pallet<TestRuntime> as MessageDispatch<AccountId, <TestRuntime as Config>::MessageId>>::Message {
|
||||||
MessagePayload {
|
MessagePayload {
|
||||||
spec_version: TEST_SPEC_VERSION,
|
spec_version: TEST_SPEC_VERSION,
|
||||||
weight: TEST_WEIGHT,
|
weight: TEST_WEIGHT,
|
||||||
origin,
|
origin,
|
||||||
|
dispatch_fee_payment: DispatchFeePayment::AtSourceChain,
|
||||||
call: EncodedCall(call.encode()),
|
call: EncodedCall(call.encode()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn prepare_root_message(
|
fn prepare_root_message(
|
||||||
call: Call,
|
call: Call,
|
||||||
) -> <Pallet<TestRuntime> as MessageDispatch<<TestRuntime as Config>::MessageId>>::Message {
|
) -> <Pallet<TestRuntime> as MessageDispatch<AccountId, <TestRuntime as Config>::MessageId>>::Message {
|
||||||
prepare_message(CallOrigin::SourceRoot, call)
|
prepare_message(CallOrigin::SourceRoot, call)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn prepare_target_message(
|
fn prepare_target_message(
|
||||||
call: Call,
|
call: Call,
|
||||||
) -> <Pallet<TestRuntime> as MessageDispatch<<TestRuntime as Config>::MessageId>>::Message {
|
) -> <Pallet<TestRuntime> as MessageDispatch<AccountId, <TestRuntime as Config>::MessageId>>::Message {
|
||||||
let origin = CallOrigin::TargetAccount(1, TestAccountPublic(1), TestSignature(1));
|
let origin = CallOrigin::TargetAccount(1, TestAccountPublic(1), TestSignature(1));
|
||||||
prepare_message(origin, call)
|
prepare_message(origin, call)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn prepare_source_message(
|
fn prepare_source_message(
|
||||||
call: Call,
|
call: Call,
|
||||||
) -> <Pallet<TestRuntime> as MessageDispatch<<TestRuntime as Config>::MessageId>>::Message {
|
) -> <Pallet<TestRuntime> as MessageDispatch<AccountId, <TestRuntime as Config>::MessageId>>::Message {
|
||||||
let origin = CallOrigin::SourceAccount(1);
|
let origin = CallOrigin::SourceAccount(1);
|
||||||
prepare_message(origin, call)
|
prepare_message(origin, call)
|
||||||
}
|
}
|
||||||
@@ -522,10 +567,12 @@ mod tests {
|
|||||||
const BAD_SPEC_VERSION: SpecVersion = 99;
|
const BAD_SPEC_VERSION: SpecVersion = 99;
|
||||||
let mut message =
|
let mut message =
|
||||||
prepare_root_message(Call::System(<frame_system::Call<TestRuntime>>::remark(vec![1, 2, 3])));
|
prepare_root_message(Call::System(<frame_system::Call<TestRuntime>>::remark(vec![1, 2, 3])));
|
||||||
|
let weight = message.weight;
|
||||||
message.spec_version = BAD_SPEC_VERSION;
|
message.spec_version = BAD_SPEC_VERSION;
|
||||||
|
|
||||||
System::set_block_number(1);
|
System::set_block_number(1);
|
||||||
Dispatch::dispatch(SOURCE_CHAIN_ID, TARGET_CHAIN_ID, id, Ok(message));
|
let result = Dispatch::dispatch(SOURCE_CHAIN_ID, TARGET_CHAIN_ID, id, Ok(message), |_, _| unreachable!());
|
||||||
|
assert_eq!(result.unspent_weight, weight);
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
System::events(),
|
System::events(),
|
||||||
@@ -549,10 +596,11 @@ mod tests {
|
|||||||
let id = [0; 4];
|
let id = [0; 4];
|
||||||
let mut message =
|
let mut message =
|
||||||
prepare_root_message(Call::System(<frame_system::Call<TestRuntime>>::remark(vec![1, 2, 3])));
|
prepare_root_message(Call::System(<frame_system::Call<TestRuntime>>::remark(vec![1, 2, 3])));
|
||||||
message.weight = 0;
|
message.weight = 7;
|
||||||
|
|
||||||
System::set_block_number(1);
|
System::set_block_number(1);
|
||||||
Dispatch::dispatch(SOURCE_CHAIN_ID, TARGET_CHAIN_ID, id, Ok(message));
|
let result = Dispatch::dispatch(SOURCE_CHAIN_ID, TARGET_CHAIN_ID, id, Ok(message), |_, _| unreachable!());
|
||||||
|
assert_eq!(result.unspent_weight, 7);
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
System::events(),
|
System::events(),
|
||||||
@@ -562,7 +610,7 @@ mod tests {
|
|||||||
SOURCE_CHAIN_ID,
|
SOURCE_CHAIN_ID,
|
||||||
id,
|
id,
|
||||||
1345000,
|
1345000,
|
||||||
0,
|
7,
|
||||||
)),
|
)),
|
||||||
topics: vec![],
|
topics: vec![],
|
||||||
}],
|
}],
|
||||||
@@ -580,9 +628,11 @@ mod tests {
|
|||||||
call_origin,
|
call_origin,
|
||||||
Call::System(<frame_system::Call<TestRuntime>>::remark(vec![1, 2, 3])),
|
Call::System(<frame_system::Call<TestRuntime>>::remark(vec![1, 2, 3])),
|
||||||
);
|
);
|
||||||
|
let weight = message.weight;
|
||||||
|
|
||||||
System::set_block_number(1);
|
System::set_block_number(1);
|
||||||
Dispatch::dispatch(SOURCE_CHAIN_ID, TARGET_CHAIN_ID, id, Ok(message));
|
let result = Dispatch::dispatch(SOURCE_CHAIN_ID, TARGET_CHAIN_ID, id, Ok(message), |_, _| unreachable!());
|
||||||
|
assert_eq!(result.unspent_weight, weight);
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
System::events(),
|
System::events(),
|
||||||
@@ -604,7 +654,7 @@ mod tests {
|
|||||||
let id = [0; 4];
|
let id = [0; 4];
|
||||||
|
|
||||||
System::set_block_number(1);
|
System::set_block_number(1);
|
||||||
Dispatch::dispatch(SOURCE_CHAIN_ID, TARGET_CHAIN_ID, id, Err(()));
|
Dispatch::dispatch(SOURCE_CHAIN_ID, TARGET_CHAIN_ID, id, Err(()), |_, _| unreachable!());
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
System::events(),
|
System::events(),
|
||||||
@@ -627,10 +677,12 @@ mod tests {
|
|||||||
|
|
||||||
let mut message =
|
let mut message =
|
||||||
prepare_root_message(Call::System(<frame_system::Call<TestRuntime>>::remark(vec![1, 2, 3])));
|
prepare_root_message(Call::System(<frame_system::Call<TestRuntime>>::remark(vec![1, 2, 3])));
|
||||||
|
let weight = message.weight;
|
||||||
message.call.0 = vec![];
|
message.call.0 = vec![];
|
||||||
|
|
||||||
System::set_block_number(1);
|
System::set_block_number(1);
|
||||||
Dispatch::dispatch(SOURCE_CHAIN_ID, TARGET_CHAIN_ID, id, Ok(message));
|
let result = Dispatch::dispatch(SOURCE_CHAIN_ID, TARGET_CHAIN_ID, id, Ok(message), |_, _| unreachable!());
|
||||||
|
assert_eq!(result.unspent_weight, weight);
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
System::events(),
|
System::events(),
|
||||||
@@ -657,7 +709,8 @@ mod tests {
|
|||||||
message.weight = weight;
|
message.weight = weight;
|
||||||
|
|
||||||
System::set_block_number(1);
|
System::set_block_number(1);
|
||||||
Dispatch::dispatch(SOURCE_CHAIN_ID, TARGET_CHAIN_ID, id, Ok(message));
|
let result = Dispatch::dispatch(SOURCE_CHAIN_ID, TARGET_CHAIN_ID, id, Ok(message), |_, _| unreachable!());
|
||||||
|
assert_eq!(result.unspent_weight, weight);
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
System::events(),
|
System::events(),
|
||||||
@@ -673,6 +726,67 @@ mod tests {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn should_emit_event_for_unpaid_calls() {
|
||||||
|
new_test_ext().execute_with(|| {
|
||||||
|
let id = [0; 4];
|
||||||
|
|
||||||
|
let mut message =
|
||||||
|
prepare_root_message(Call::System(<frame_system::Call<TestRuntime>>::remark(vec![1, 2, 3])));
|
||||||
|
let weight = message.weight;
|
||||||
|
message.dispatch_fee_payment = DispatchFeePayment::AtTargetChain;
|
||||||
|
|
||||||
|
System::set_block_number(1);
|
||||||
|
let result = Dispatch::dispatch(SOURCE_CHAIN_ID, TARGET_CHAIN_ID, id, Ok(message), |_, _| Err(()));
|
||||||
|
assert_eq!(result.unspent_weight, weight);
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
System::events(),
|
||||||
|
vec![EventRecord {
|
||||||
|
phase: Phase::Initialization,
|
||||||
|
event: Event::call_dispatch(call_dispatch::Event::<TestRuntime>::MessageDispatchPaymentFailed(
|
||||||
|
SOURCE_CHAIN_ID,
|
||||||
|
id,
|
||||||
|
AccountIdConverter::convert(derive_account_id::<AccountId>(
|
||||||
|
SOURCE_CHAIN_ID,
|
||||||
|
SourceAccount::Root
|
||||||
|
)),
|
||||||
|
TEST_WEIGHT,
|
||||||
|
)),
|
||||||
|
topics: vec![],
|
||||||
|
}],
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn should_dispatch_calls_paid_at_target_chain() {
|
||||||
|
new_test_ext().execute_with(|| {
|
||||||
|
let id = [0; 4];
|
||||||
|
|
||||||
|
let mut message =
|
||||||
|
prepare_root_message(Call::System(<frame_system::Call<TestRuntime>>::remark(vec![1, 2, 3])));
|
||||||
|
message.dispatch_fee_payment = DispatchFeePayment::AtTargetChain;
|
||||||
|
|
||||||
|
System::set_block_number(1);
|
||||||
|
let result = Dispatch::dispatch(SOURCE_CHAIN_ID, TARGET_CHAIN_ID, id, Ok(message), |_, _| Ok(()));
|
||||||
|
assert!(result.dispatch_fee_paid_during_dispatch);
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
System::events(),
|
||||||
|
vec![EventRecord {
|
||||||
|
phase: Phase::Initialization,
|
||||||
|
event: Event::call_dispatch(call_dispatch::Event::<TestRuntime>::MessageDispatched(
|
||||||
|
SOURCE_CHAIN_ID,
|
||||||
|
id,
|
||||||
|
Ok(())
|
||||||
|
)),
|
||||||
|
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(|| {
|
||||||
@@ -680,7 +794,8 @@ mod tests {
|
|||||||
let message = prepare_root_message(Call::System(<frame_system::Call<TestRuntime>>::remark(vec![1, 2, 3])));
|
let message = prepare_root_message(Call::System(<frame_system::Call<TestRuntime>>::remark(vec![1, 2, 3])));
|
||||||
|
|
||||||
System::set_block_number(1);
|
System::set_block_number(1);
|
||||||
Dispatch::dispatch(SOURCE_CHAIN_ID, TARGET_CHAIN_ID, id, Ok(message));
|
let result = Dispatch::dispatch(SOURCE_CHAIN_ID, TARGET_CHAIN_ID, id, Ok(message), |_, _| unreachable!());
|
||||||
|
assert!(!result.dispatch_fee_paid_during_dispatch);
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
System::events(),
|
System::events(),
|
||||||
@@ -706,7 +821,8 @@ mod tests {
|
|||||||
let message = prepare_target_message(call);
|
let message = prepare_target_message(call);
|
||||||
|
|
||||||
System::set_block_number(1);
|
System::set_block_number(1);
|
||||||
Dispatch::dispatch(SOURCE_CHAIN_ID, TARGET_CHAIN_ID, id, Ok(message));
|
let result = Dispatch::dispatch(SOURCE_CHAIN_ID, TARGET_CHAIN_ID, id, Ok(message), |_, _| unreachable!());
|
||||||
|
assert!(!result.dispatch_fee_paid_during_dispatch);
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
System::events(),
|
System::events(),
|
||||||
@@ -732,7 +848,8 @@ mod tests {
|
|||||||
let message = prepare_source_message(call);
|
let message = prepare_source_message(call);
|
||||||
|
|
||||||
System::set_block_number(1);
|
System::set_block_number(1);
|
||||||
Dispatch::dispatch(SOURCE_CHAIN_ID, TARGET_CHAIN_ID, id, Ok(message));
|
let result = Dispatch::dispatch(SOURCE_CHAIN_ID, TARGET_CHAIN_ID, id, Ok(message), |_, _| unreachable!());
|
||||||
|
assert!(!result.dispatch_fee_paid_during_dispatch);
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
System::events(),
|
System::events(),
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ serde = { version = "1.0.101", optional = true, features = ["derive"] }
|
|||||||
|
|
||||||
# Bridge dependencies
|
# Bridge dependencies
|
||||||
|
|
||||||
|
bp-message-dispatch = { path = "../../primitives/message-dispatch", default-features = false }
|
||||||
bp-messages = { path = "../../primitives/messages", default-features = false }
|
bp-messages = { path = "../../primitives/messages", default-features = false }
|
||||||
bp-rialto = { path = "../../primitives/chain-rialto", default-features = false }
|
bp-rialto = { path = "../../primitives/chain-rialto", default-features = false }
|
||||||
bp-runtime = { path = "../../primitives/runtime", default-features = false }
|
bp-runtime = { path = "../../primitives/runtime", default-features = false }
|
||||||
@@ -36,6 +37,7 @@ pallet-balances = { git = "https://github.com/paritytech/substrate", branch = "m
|
|||||||
[features]
|
[features]
|
||||||
default = ["std"]
|
default = ["std"]
|
||||||
std = [
|
std = [
|
||||||
|
"bp-message-dispatch/std",
|
||||||
"bp-messages/std",
|
"bp-messages/std",
|
||||||
"bp-runtime/std",
|
"bp-runtime/std",
|
||||||
"bp-rialto/std",
|
"bp-rialto/std",
|
||||||
|
|||||||
@@ -347,6 +347,23 @@ Both conditions are verified by `pallet_bridge_messages::ensure_weights_are_corr
|
|||||||
`pallet_bridge_messages::ensure_able_to_receive_messages` functions, which must be called from every
|
`pallet_bridge_messages::ensure_able_to_receive_messages` functions, which must be called from every
|
||||||
runtime's tests.
|
runtime's tests.
|
||||||
|
|
||||||
|
### Post-dispatch weight refunds of the `receive_messages_proof` call
|
||||||
|
|
||||||
|
Weight formula of the `receive_messages_proof` call assumes that the dispatch fee of every message is
|
||||||
|
paid at the target chain (where call is executed), that every message will be dispatched and that
|
||||||
|
dispatch weight of the message will be exactly the weight that is returned from the
|
||||||
|
`MessageDispatch::dispatch_weight` method call. This isn't true for all messages, so the call returns
|
||||||
|
actual weight used to dispatch messages.
|
||||||
|
|
||||||
|
This actual weight is the weight, returned by the weight formula, minus:
|
||||||
|
- the weight of undispatched messages, if we have failed to dispatch because of different issues;
|
||||||
|
- the unspent dispatch weight if the declared weight of some messages is less than their actual post-dispatch weight;
|
||||||
|
- the pay-dispatch-fee weight for every message that had dispatch fee paid at the source chain.
|
||||||
|
|
||||||
|
The last component is computed as a difference between two benchmarks results - the `receive_single_message_proof`
|
||||||
|
benchmark (that assumes that the fee is paid during dispatch) and the `receive_single_prepaid_message_proof`
|
||||||
|
(that assumes that the dispatch fee is already paid).
|
||||||
|
|
||||||
### Weight of `receive_messages_delivery_proof` call
|
### Weight of `receive_messages_delivery_proof` call
|
||||||
|
|
||||||
#### Related benchmarks
|
#### Related benchmarks
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ use bp_messages::{
|
|||||||
source_chain::TargetHeaderChain, target_chain::SourceHeaderChain, InboundLaneData, LaneId, MessageData,
|
source_chain::TargetHeaderChain, target_chain::SourceHeaderChain, InboundLaneData, LaneId, MessageData,
|
||||||
MessageNonce, OutboundLaneData, UnrewardedRelayersState,
|
MessageNonce, OutboundLaneData, UnrewardedRelayersState,
|
||||||
};
|
};
|
||||||
|
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;
|
||||||
@@ -67,6 +68,8 @@ pub struct MessageProofParams {
|
|||||||
pub outbound_lane_data: Option<OutboundLaneData>,
|
pub outbound_lane_data: Option<OutboundLaneData>,
|
||||||
/// Proof size requirements.
|
/// Proof size requirements.
|
||||||
pub size: ProofSize,
|
pub size: ProofSize,
|
||||||
|
/// If true, dispatch fee is paid at the target chain (if supported by configuration).
|
||||||
|
pub dispatch_fee_payment: DispatchFeePayment,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Benchmark-specific message delivery proof parameters.
|
/// Benchmark-specific message delivery proof parameters.
|
||||||
@@ -108,6 +111,8 @@ pub trait Config<I: Instance>: crate::Config<I> {
|
|||||||
fn prepare_message_delivery_proof(
|
fn prepare_message_delivery_proof(
|
||||||
params: MessageDeliveryProofParams<Self::AccountId>,
|
params: MessageDeliveryProofParams<Self::AccountId>,
|
||||||
) -> <Self::TargetHeaderChain as TargetHeaderChain<Self::OutboundPayload, Self::AccountId>>::MessagesDeliveryProof;
|
) -> <Self::TargetHeaderChain as TargetHeaderChain<Self::OutboundPayload, Self::AccountId>>::MessagesDeliveryProof;
|
||||||
|
/// Returns true if message has been dispatched (either successfully or not).
|
||||||
|
fn is_message_dispatched(nonce: MessageNonce) -> bool;
|
||||||
}
|
}
|
||||||
|
|
||||||
benchmarks_instance! {
|
benchmarks_instance! {
|
||||||
@@ -242,7 +247,8 @@ benchmarks_instance! {
|
|||||||
// * proof does not include outbound lane state proof;
|
// * proof does not include outbound lane state proof;
|
||||||
// * inbound lane already has state, so it needs to be read and decoded;
|
// * inbound lane already has state, so it needs to be read and decoded;
|
||||||
// * message is successfully dispatched;
|
// * message is successfully dispatched;
|
||||||
// * message requires all heavy checks done by dispatcher.
|
// * message requires all heavy checks done by dispatcher;
|
||||||
|
// * message dispatch fee is paid at target (this) chain.
|
||||||
//
|
//
|
||||||
// This is base benchmark for all other message delivery benchmarks.
|
// This is base benchmark for all other message delivery benchmarks.
|
||||||
receive_single_message_proof {
|
receive_single_message_proof {
|
||||||
@@ -257,6 +263,7 @@ benchmarks_instance! {
|
|||||||
message_nonces: 21..=21,
|
message_nonces: 21..=21,
|
||||||
outbound_lane_data: None,
|
outbound_lane_data: None,
|
||||||
size: ProofSize::Minimal(EXPECTED_DEFAULT_MESSAGE_LENGTH),
|
size: ProofSize::Minimal(EXPECTED_DEFAULT_MESSAGE_LENGTH),
|
||||||
|
dispatch_fee_payment: DispatchFeePayment::AtTargetChain,
|
||||||
});
|
});
|
||||||
}: receive_messages_proof(RawOrigin::Signed(relayer_id_on_target), relayer_id_on_source, proof, 1, dispatch_weight)
|
}: receive_messages_proof(RawOrigin::Signed(relayer_id_on_target), relayer_id_on_source, proof, 1, dispatch_weight)
|
||||||
verify {
|
verify {
|
||||||
@@ -264,13 +271,15 @@ benchmarks_instance! {
|
|||||||
crate::Pallet::<T, I>::inbound_latest_received_nonce(T::bench_lane_id()),
|
crate::Pallet::<T, I>::inbound_latest_received_nonce(T::bench_lane_id()),
|
||||||
21,
|
21,
|
||||||
);
|
);
|
||||||
|
assert!(T::is_message_dispatched(21));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Benchmark `receive_messages_proof` extrinsic with two minimal-weight messages and following conditions:
|
// Benchmark `receive_messages_proof` extrinsic with two minimal-weight messages and following conditions:
|
||||||
// * proof does not include outbound lane state proof;
|
// * proof does not include outbound lane state proof;
|
||||||
// * inbound lane already has state, so it needs to be read and decoded;
|
// * inbound lane already has state, so it needs to be read and decoded;
|
||||||
// * message is successfully dispatched;
|
// * message is successfully dispatched;
|
||||||
// * message requires all heavy checks done by dispatcher.
|
// * message requires all heavy checks done by dispatcher;
|
||||||
|
// * message dispatch fee is paid at target (this) chain.
|
||||||
//
|
//
|
||||||
// The weight of single message delivery could be approximated as
|
// The weight of single message delivery could be approximated as
|
||||||
// `weight(receive_two_messages_proof) - weight(receive_single_message_proof)`.
|
// `weight(receive_two_messages_proof) - weight(receive_single_message_proof)`.
|
||||||
@@ -288,6 +297,7 @@ benchmarks_instance! {
|
|||||||
message_nonces: 21..=22,
|
message_nonces: 21..=22,
|
||||||
outbound_lane_data: None,
|
outbound_lane_data: None,
|
||||||
size: ProofSize::Minimal(EXPECTED_DEFAULT_MESSAGE_LENGTH),
|
size: ProofSize::Minimal(EXPECTED_DEFAULT_MESSAGE_LENGTH),
|
||||||
|
dispatch_fee_payment: DispatchFeePayment::AtTargetChain,
|
||||||
});
|
});
|
||||||
}: receive_messages_proof(RawOrigin::Signed(relayer_id_on_target), relayer_id_on_source, proof, 2, dispatch_weight)
|
}: receive_messages_proof(RawOrigin::Signed(relayer_id_on_target), relayer_id_on_source, proof, 2, dispatch_weight)
|
||||||
verify {
|
verify {
|
||||||
@@ -295,13 +305,15 @@ benchmarks_instance! {
|
|||||||
crate::Pallet::<T, I>::inbound_latest_received_nonce(T::bench_lane_id()),
|
crate::Pallet::<T, I>::inbound_latest_received_nonce(T::bench_lane_id()),
|
||||||
22,
|
22,
|
||||||
);
|
);
|
||||||
|
assert!(T::is_message_dispatched(22));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Benchmark `receive_messages_proof` extrinsic with single minimal-weight message and following conditions:
|
// Benchmark `receive_messages_proof` extrinsic with single minimal-weight message and following conditions:
|
||||||
// * proof includes outbound lane state proof;
|
// * proof includes outbound lane state proof;
|
||||||
// * inbound lane already has state, so it needs to be read and decoded;
|
// * inbound lane already has state, so it needs to be read and decoded;
|
||||||
// * message is successfully dispatched;
|
// * message is successfully dispatched;
|
||||||
// * message requires all heavy checks done by dispatcher.
|
// * message requires all heavy checks done by dispatcher;
|
||||||
|
// * message dispatch fee is paid at target (this) chain.
|
||||||
//
|
//
|
||||||
// The weight of outbound lane state delivery would be
|
// The weight of outbound lane state delivery would be
|
||||||
// `weight(receive_single_message_proof_with_outbound_lane_state) - weight(receive_single_message_proof)`.
|
// `weight(receive_single_message_proof_with_outbound_lane_state) - weight(receive_single_message_proof)`.
|
||||||
@@ -323,6 +335,7 @@ benchmarks_instance! {
|
|||||||
latest_generated_nonce: 21,
|
latest_generated_nonce: 21,
|
||||||
}),
|
}),
|
||||||
size: ProofSize::Minimal(EXPECTED_DEFAULT_MESSAGE_LENGTH),
|
size: ProofSize::Minimal(EXPECTED_DEFAULT_MESSAGE_LENGTH),
|
||||||
|
dispatch_fee_payment: DispatchFeePayment::AtTargetChain,
|
||||||
});
|
});
|
||||||
}: receive_messages_proof(RawOrigin::Signed(relayer_id_on_target), relayer_id_on_source, proof, 1, dispatch_weight)
|
}: receive_messages_proof(RawOrigin::Signed(relayer_id_on_target), relayer_id_on_source, proof, 1, dispatch_weight)
|
||||||
verify {
|
verify {
|
||||||
@@ -334,6 +347,7 @@ benchmarks_instance! {
|
|||||||
crate::Pallet::<T, I>::inbound_latest_confirmed_nonce(T::bench_lane_id()),
|
crate::Pallet::<T, I>::inbound_latest_confirmed_nonce(T::bench_lane_id()),
|
||||||
20,
|
20,
|
||||||
);
|
);
|
||||||
|
assert!(T::is_message_dispatched(21));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Benchmark `receive_messages_proof` extrinsic with single minimal-weight message and following conditions:
|
// Benchmark `receive_messages_proof` extrinsic with single minimal-weight message and following conditions:
|
||||||
@@ -357,6 +371,7 @@ benchmarks_instance! {
|
|||||||
message_nonces: 21..=21,
|
message_nonces: 21..=21,
|
||||||
outbound_lane_data: None,
|
outbound_lane_data: None,
|
||||||
size: ProofSize::HasExtraNodes(1024),
|
size: ProofSize::HasExtraNodes(1024),
|
||||||
|
dispatch_fee_payment: DispatchFeePayment::AtTargetChain,
|
||||||
});
|
});
|
||||||
}: receive_messages_proof(RawOrigin::Signed(relayer_id_on_target), relayer_id_on_source, proof, 1, dispatch_weight)
|
}: receive_messages_proof(RawOrigin::Signed(relayer_id_on_target), relayer_id_on_source, proof, 1, dispatch_weight)
|
||||||
verify {
|
verify {
|
||||||
@@ -364,6 +379,7 @@ benchmarks_instance! {
|
|||||||
crate::Pallet::<T, I>::inbound_latest_received_nonce(T::bench_lane_id()),
|
crate::Pallet::<T, I>::inbound_latest_received_nonce(T::bench_lane_id()),
|
||||||
21,
|
21,
|
||||||
);
|
);
|
||||||
|
assert!(T::is_message_dispatched(21));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Benchmark `receive_messages_proof` extrinsic with single minimal-weight message and following conditions:
|
// Benchmark `receive_messages_proof` extrinsic with single minimal-weight message and following conditions:
|
||||||
@@ -389,6 +405,7 @@ benchmarks_instance! {
|
|||||||
message_nonces: 21..=21,
|
message_nonces: 21..=21,
|
||||||
outbound_lane_data: None,
|
outbound_lane_data: None,
|
||||||
size: ProofSize::HasExtraNodes(16 * 1024),
|
size: ProofSize::HasExtraNodes(16 * 1024),
|
||||||
|
dispatch_fee_payment: DispatchFeePayment::AtTargetChain,
|
||||||
});
|
});
|
||||||
}: receive_messages_proof(RawOrigin::Signed(relayer_id_on_target), relayer_id_on_source, proof, 1, dispatch_weight)
|
}: receive_messages_proof(RawOrigin::Signed(relayer_id_on_target), relayer_id_on_source, proof, 1, dispatch_weight)
|
||||||
verify {
|
verify {
|
||||||
@@ -396,6 +413,40 @@ benchmarks_instance! {
|
|||||||
crate::Pallet::<T, I>::inbound_latest_received_nonce(T::bench_lane_id()),
|
crate::Pallet::<T, I>::inbound_latest_received_nonce(T::bench_lane_id()),
|
||||||
21,
|
21,
|
||||||
);
|
);
|
||||||
|
assert!(T::is_message_dispatched(21));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Benchmark `receive_messages_proof` extrinsic with single minimal-weight message and following conditions:
|
||||||
|
// * proof does not include outbound lane state proof;
|
||||||
|
// * inbound lane already has state, so it needs to be read and decoded;
|
||||||
|
// * message is successfully dispatched;
|
||||||
|
// * message requires all heavy checks done by dispatcher;
|
||||||
|
// * message dispatch fee is paid at source (bridged) chain.
|
||||||
|
//
|
||||||
|
// This benchmark is used to compute extra weight spent at target chain when fee is paid there. Then we use
|
||||||
|
// this information in two places: (1) to reduce weight of delivery tx if sender pays fee at the source chain
|
||||||
|
// and (2) to refund relayer with this weight if fee has been paid at the source chain.
|
||||||
|
receive_single_prepaid_message_proof {
|
||||||
|
let relayer_id_on_source = T::bridged_relayer_id();
|
||||||
|
let relayer_id_on_target = account("relayer", 0, SEED);
|
||||||
|
|
||||||
|
// mark messages 1..=20 as delivered
|
||||||
|
receive_messages::<T, I>(20);
|
||||||
|
|
||||||
|
let (proof, dispatch_weight) = T::prepare_message_proof(MessageProofParams {
|
||||||
|
lane: T::bench_lane_id(),
|
||||||
|
message_nonces: 21..=21,
|
||||||
|
outbound_lane_data: None,
|
||||||
|
size: ProofSize::Minimal(EXPECTED_DEFAULT_MESSAGE_LENGTH),
|
||||||
|
dispatch_fee_payment: DispatchFeePayment::AtSourceChain,
|
||||||
|
});
|
||||||
|
}: receive_messages_proof(RawOrigin::Signed(relayer_id_on_target), relayer_id_on_source, proof, 1, dispatch_weight)
|
||||||
|
verify {
|
||||||
|
assert_eq!(
|
||||||
|
crate::Pallet::<T, I>::inbound_latest_received_nonce(T::bench_lane_id()),
|
||||||
|
21,
|
||||||
|
);
|
||||||
|
assert!(T::is_message_dispatched(21));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Benchmark `receive_messages_delivery_proof` extrinsic with following conditions:
|
// Benchmark `receive_messages_delivery_proof` extrinsic with following conditions:
|
||||||
@@ -569,6 +620,7 @@ benchmarks_instance! {
|
|||||||
message_nonces: 21..=(20 + i as MessageNonce),
|
message_nonces: 21..=(20 + i as MessageNonce),
|
||||||
outbound_lane_data: None,
|
outbound_lane_data: None,
|
||||||
size: ProofSize::Minimal(EXPECTED_DEFAULT_MESSAGE_LENGTH),
|
size: ProofSize::Minimal(EXPECTED_DEFAULT_MESSAGE_LENGTH),
|
||||||
|
dispatch_fee_payment: DispatchFeePayment::AtTargetChain,
|
||||||
});
|
});
|
||||||
}: receive_messages_proof(
|
}: receive_messages_proof(
|
||||||
RawOrigin::Signed(relayer_id_on_target),
|
RawOrigin::Signed(relayer_id_on_target),
|
||||||
@@ -606,6 +658,7 @@ benchmarks_instance! {
|
|||||||
message_nonces: 21..=21,
|
message_nonces: 21..=21,
|
||||||
outbound_lane_data: None,
|
outbound_lane_data: None,
|
||||||
size: ProofSize::HasExtraNodes(i as _),
|
size: ProofSize::HasExtraNodes(i as _),
|
||||||
|
dispatch_fee_payment: DispatchFeePayment::AtTargetChain,
|
||||||
});
|
});
|
||||||
}: receive_messages_proof(
|
}: receive_messages_proof(
|
||||||
RawOrigin::Signed(relayer_id_on_target),
|
RawOrigin::Signed(relayer_id_on_target),
|
||||||
@@ -643,6 +696,7 @@ benchmarks_instance! {
|
|||||||
message_nonces: 21..=21,
|
message_nonces: 21..=21,
|
||||||
outbound_lane_data: None,
|
outbound_lane_data: None,
|
||||||
size: ProofSize::HasLargeLeaf(i as _),
|
size: ProofSize::HasLargeLeaf(i as _),
|
||||||
|
dispatch_fee_payment: DispatchFeePayment::AtTargetChain,
|
||||||
});
|
});
|
||||||
}: receive_messages_proof(
|
}: receive_messages_proof(
|
||||||
RawOrigin::Signed(relayer_id_on_target),
|
RawOrigin::Signed(relayer_id_on_target),
|
||||||
@@ -686,6 +740,7 @@ benchmarks_instance! {
|
|||||||
latest_generated_nonce: 21,
|
latest_generated_nonce: 21,
|
||||||
}),
|
}),
|
||||||
size: ProofSize::Minimal(0),
|
size: ProofSize::Minimal(0),
|
||||||
|
dispatch_fee_payment: DispatchFeePayment::AtTargetChain,
|
||||||
});
|
});
|
||||||
}: receive_messages_proof(
|
}: receive_messages_proof(
|
||||||
RawOrigin::Signed(relayer_id_on_target),
|
RawOrigin::Signed(relayer_id_on_target),
|
||||||
|
|||||||
@@ -20,6 +20,8 @@ use bp_messages::{
|
|||||||
target_chain::{DispatchMessage, DispatchMessageData, MessageDispatch},
|
target_chain::{DispatchMessage, DispatchMessageData, MessageDispatch},
|
||||||
InboundLaneData, LaneId, MessageKey, MessageNonce, OutboundLaneData,
|
InboundLaneData, LaneId, MessageKey, MessageNonce, OutboundLaneData,
|
||||||
};
|
};
|
||||||
|
use bp_runtime::messages::MessageDispatchResult;
|
||||||
|
use frame_support::RuntimeDebug;
|
||||||
use sp_std::prelude::PartialEq;
|
use sp_std::prelude::PartialEq;
|
||||||
|
|
||||||
/// Inbound lane storage.
|
/// Inbound lane storage.
|
||||||
@@ -27,7 +29,7 @@ pub trait InboundLaneStorage {
|
|||||||
/// Delivery and dispatch fee type on source chain.
|
/// Delivery and dispatch fee type on source chain.
|
||||||
type MessageFee;
|
type MessageFee;
|
||||||
/// Id of relayer on source chain.
|
/// Id of relayer on source chain.
|
||||||
type Relayer: PartialEq;
|
type Relayer: Clone + PartialEq;
|
||||||
|
|
||||||
/// Lane id.
|
/// Lane id.
|
||||||
fn id(&self) -> LaneId;
|
fn id(&self) -> LaneId;
|
||||||
@@ -41,6 +43,22 @@ pub trait InboundLaneStorage {
|
|||||||
fn set_data(&mut self, data: InboundLaneData<Self::Relayer>);
|
fn set_data(&mut self, data: InboundLaneData<Self::Relayer>);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Result of single message receival.
|
||||||
|
#[derive(RuntimeDebug, PartialEq, Eq)]
|
||||||
|
pub enum ReceivalResult {
|
||||||
|
/// Message has been received and dispatched. Note that we don't care whether dispatch has
|
||||||
|
/// been successful or not - in both case message falls into this category.
|
||||||
|
///
|
||||||
|
/// The message dispatch result is also returned.
|
||||||
|
Dispatched(MessageDispatchResult),
|
||||||
|
/// Message has invalid nonce and lane has rejected to accept this message.
|
||||||
|
InvalidNonce,
|
||||||
|
/// There are too many unrewarded relayer entires at the lane.
|
||||||
|
TooManyUnrewardedRelayers,
|
||||||
|
/// There are too many unconfirmed messages at the lane.
|
||||||
|
TooManyUnconfirmedMessages,
|
||||||
|
}
|
||||||
|
|
||||||
/// Inbound messages lane.
|
/// Inbound messages lane.
|
||||||
pub struct InboundLane<S> {
|
pub struct InboundLane<S> {
|
||||||
storage: S,
|
storage: S,
|
||||||
@@ -90,51 +108,54 @@ impl<S: InboundLaneStorage> InboundLane<S> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Receive new message.
|
/// Receive new message.
|
||||||
pub fn receive_message<P: MessageDispatch<S::MessageFee>>(
|
pub fn receive_message<P: MessageDispatch<AccountId, S::MessageFee>, AccountId>(
|
||||||
&mut self,
|
&mut self,
|
||||||
relayer: S::Relayer,
|
relayer_at_bridged_chain: &S::Relayer,
|
||||||
|
relayer_at_this_chain: &AccountId,
|
||||||
nonce: MessageNonce,
|
nonce: MessageNonce,
|
||||||
message_data: DispatchMessageData<P::DispatchPayload, S::MessageFee>,
|
message_data: DispatchMessageData<P::DispatchPayload, S::MessageFee>,
|
||||||
) -> bool {
|
) -> ReceivalResult {
|
||||||
let mut data = self.storage.data();
|
let mut data = self.storage.data();
|
||||||
let is_correct_message = nonce == data.last_delivered_nonce() + 1;
|
let is_correct_message = nonce == data.last_delivered_nonce() + 1;
|
||||||
if !is_correct_message {
|
if !is_correct_message {
|
||||||
return false;
|
return ReceivalResult::InvalidNonce;
|
||||||
}
|
}
|
||||||
|
|
||||||
// if there are more unrewarded relayer entries than we may accept, reject this message
|
// if there are more unrewarded relayer entries than we may accept, reject this message
|
||||||
if data.relayers.len() as MessageNonce >= self.storage.max_unrewarded_relayer_entries() {
|
if data.relayers.len() as MessageNonce >= self.storage.max_unrewarded_relayer_entries() {
|
||||||
return false;
|
return ReceivalResult::TooManyUnrewardedRelayers;
|
||||||
}
|
}
|
||||||
|
|
||||||
// if there are more unconfirmed messages than we may accept, reject this message
|
// if there are more unconfirmed messages than we may accept, reject this message
|
||||||
let unconfirmed_messages_count = nonce.saturating_sub(data.last_confirmed_nonce);
|
let unconfirmed_messages_count = nonce.saturating_sub(data.last_confirmed_nonce);
|
||||||
if unconfirmed_messages_count > self.storage.max_unconfirmed_messages() {
|
if unconfirmed_messages_count > self.storage.max_unconfirmed_messages() {
|
||||||
return false;
|
return ReceivalResult::TooManyUnconfirmedMessages;
|
||||||
}
|
}
|
||||||
|
|
||||||
let push_new = match data.relayers.back_mut() {
|
let push_new = match data.relayers.back_mut() {
|
||||||
Some((_, nonce_high, last_relayer)) if last_relayer == &relayer => {
|
Some((_, nonce_high, last_relayer)) if last_relayer == relayer_at_bridged_chain => {
|
||||||
*nonce_high = nonce;
|
*nonce_high = nonce;
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
_ => true,
|
_ => true,
|
||||||
};
|
};
|
||||||
if push_new {
|
if push_new {
|
||||||
data.relayers.push_back((nonce, nonce, relayer));
|
data.relayers
|
||||||
|
.push_back((nonce, nonce, (*relayer_at_bridged_chain).clone()));
|
||||||
}
|
}
|
||||||
|
|
||||||
self.storage.set_data(data);
|
self.storage.set_data(data);
|
||||||
|
|
||||||
P::dispatch(DispatchMessage {
|
ReceivalResult::Dispatched(P::dispatch(
|
||||||
|
relayer_at_this_chain,
|
||||||
|
DispatchMessage {
|
||||||
key: MessageKey {
|
key: MessageKey {
|
||||||
lane_id: self.storage.id(),
|
lane_id: self.storage.id(),
|
||||||
nonce,
|
nonce,
|
||||||
},
|
},
|
||||||
data: message_data,
|
data: message_data,
|
||||||
});
|
},
|
||||||
|
))
|
||||||
true
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -144,8 +165,8 @@ mod tests {
|
|||||||
use crate::{
|
use crate::{
|
||||||
inbound_lane,
|
inbound_lane,
|
||||||
mock::{
|
mock::{
|
||||||
message_data, run_test, TestMessageDispatch, TestRuntime, REGULAR_PAYLOAD, TEST_LANE_ID, TEST_RELAYER_A,
|
dispatch_result, message_data, run_test, TestMessageDispatch, TestRuntime, REGULAR_PAYLOAD, TEST_LANE_ID,
|
||||||
TEST_RELAYER_B, TEST_RELAYER_C,
|
TEST_RELAYER_A, TEST_RELAYER_B, TEST_RELAYER_C,
|
||||||
},
|
},
|
||||||
DefaultInstance, RuntimeInboundLaneStorage,
|
DefaultInstance, RuntimeInboundLaneStorage,
|
||||||
};
|
};
|
||||||
@@ -154,11 +175,15 @@ mod tests {
|
|||||||
lane: &mut InboundLane<RuntimeInboundLaneStorage<TestRuntime, DefaultInstance>>,
|
lane: &mut InboundLane<RuntimeInboundLaneStorage<TestRuntime, DefaultInstance>>,
|
||||||
nonce: MessageNonce,
|
nonce: MessageNonce,
|
||||||
) {
|
) {
|
||||||
assert!(lane.receive_message::<TestMessageDispatch>(
|
assert_eq!(
|
||||||
TEST_RELAYER_A,
|
lane.receive_message::<TestMessageDispatch, _>(
|
||||||
|
&TEST_RELAYER_A,
|
||||||
|
&TEST_RELAYER_A,
|
||||||
nonce,
|
nonce,
|
||||||
message_data(REGULAR_PAYLOAD).into()
|
message_data(REGULAR_PAYLOAD).into()
|
||||||
));
|
),
|
||||||
|
ReceivalResult::Dispatched(dispatch_result(0))
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@@ -269,11 +294,15 @@ mod tests {
|
|||||||
fn fails_to_receive_message_with_incorrect_nonce() {
|
fn fails_to_receive_message_with_incorrect_nonce() {
|
||||||
run_test(|| {
|
run_test(|| {
|
||||||
let mut lane = inbound_lane::<TestRuntime, _>(TEST_LANE_ID);
|
let mut lane = inbound_lane::<TestRuntime, _>(TEST_LANE_ID);
|
||||||
assert!(!lane.receive_message::<TestMessageDispatch>(
|
assert_eq!(
|
||||||
TEST_RELAYER_A,
|
lane.receive_message::<TestMessageDispatch, _>(
|
||||||
|
&TEST_RELAYER_A,
|
||||||
|
&TEST_RELAYER_A,
|
||||||
10,
|
10,
|
||||||
message_data(REGULAR_PAYLOAD).into()
|
message_data(REGULAR_PAYLOAD).into()
|
||||||
));
|
),
|
||||||
|
ReceivalResult::InvalidNonce
|
||||||
|
);
|
||||||
assert_eq!(lane.storage.data().last_delivered_nonce(), 0);
|
assert_eq!(lane.storage.data().last_delivered_nonce(), 0);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -284,24 +313,36 @@ mod tests {
|
|||||||
let mut lane = inbound_lane::<TestRuntime, _>(TEST_LANE_ID);
|
let mut lane = inbound_lane::<TestRuntime, _>(TEST_LANE_ID);
|
||||||
let max_nonce = <TestRuntime as crate::Config>::MaxUnrewardedRelayerEntriesAtInboundLane::get();
|
let max_nonce = <TestRuntime as crate::Config>::MaxUnrewardedRelayerEntriesAtInboundLane::get();
|
||||||
for current_nonce in 1..max_nonce + 1 {
|
for current_nonce in 1..max_nonce + 1 {
|
||||||
assert!(lane.receive_message::<TestMessageDispatch>(
|
assert_eq!(
|
||||||
TEST_RELAYER_A + current_nonce,
|
lane.receive_message::<TestMessageDispatch, _>(
|
||||||
|
&(TEST_RELAYER_A + current_nonce),
|
||||||
|
&(TEST_RELAYER_A + current_nonce),
|
||||||
current_nonce,
|
current_nonce,
|
||||||
message_data(REGULAR_PAYLOAD).into()
|
message_data(REGULAR_PAYLOAD).into()
|
||||||
));
|
),
|
||||||
|
ReceivalResult::Dispatched(dispatch_result(0))
|
||||||
|
);
|
||||||
}
|
}
|
||||||
// Fails to dispatch new message from different than latest relayer.
|
// Fails to dispatch new message from different than latest relayer.
|
||||||
assert!(!lane.receive_message::<TestMessageDispatch>(
|
assert_eq!(
|
||||||
TEST_RELAYER_A + max_nonce + 1,
|
lane.receive_message::<TestMessageDispatch, _>(
|
||||||
|
&(TEST_RELAYER_A + max_nonce + 1),
|
||||||
|
&(TEST_RELAYER_A + max_nonce + 1),
|
||||||
max_nonce + 1,
|
max_nonce + 1,
|
||||||
message_data(REGULAR_PAYLOAD).into()
|
message_data(REGULAR_PAYLOAD).into()
|
||||||
));
|
),
|
||||||
|
ReceivalResult::TooManyUnrewardedRelayers,
|
||||||
|
);
|
||||||
// Fails to dispatch new messages from latest relayer. Prevents griefing attacks.
|
// Fails to dispatch new messages from latest relayer. Prevents griefing attacks.
|
||||||
assert!(!lane.receive_message::<TestMessageDispatch>(
|
assert_eq!(
|
||||||
TEST_RELAYER_A + max_nonce,
|
lane.receive_message::<TestMessageDispatch, _>(
|
||||||
|
&(TEST_RELAYER_A + max_nonce),
|
||||||
|
&(TEST_RELAYER_A + max_nonce),
|
||||||
max_nonce + 1,
|
max_nonce + 1,
|
||||||
message_data(REGULAR_PAYLOAD).into()
|
message_data(REGULAR_PAYLOAD).into()
|
||||||
));
|
),
|
||||||
|
ReceivalResult::TooManyUnrewardedRelayers,
|
||||||
|
);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -311,24 +352,36 @@ mod tests {
|
|||||||
let mut lane = inbound_lane::<TestRuntime, _>(TEST_LANE_ID);
|
let mut lane = inbound_lane::<TestRuntime, _>(TEST_LANE_ID);
|
||||||
let max_nonce = <TestRuntime as crate::Config>::MaxUnconfirmedMessagesAtInboundLane::get();
|
let max_nonce = <TestRuntime as crate::Config>::MaxUnconfirmedMessagesAtInboundLane::get();
|
||||||
for current_nonce in 1..=max_nonce {
|
for current_nonce in 1..=max_nonce {
|
||||||
assert!(lane.receive_message::<TestMessageDispatch>(
|
assert_eq!(
|
||||||
TEST_RELAYER_A,
|
lane.receive_message::<TestMessageDispatch, _>(
|
||||||
|
&TEST_RELAYER_A,
|
||||||
|
&TEST_RELAYER_A,
|
||||||
current_nonce,
|
current_nonce,
|
||||||
message_data(REGULAR_PAYLOAD).into()
|
message_data(REGULAR_PAYLOAD).into()
|
||||||
));
|
),
|
||||||
|
ReceivalResult::Dispatched(dispatch_result(0))
|
||||||
|
);
|
||||||
}
|
}
|
||||||
// Fails to dispatch new message from different than latest relayer.
|
// Fails to dispatch new message from different than latest relayer.
|
||||||
assert!(!lane.receive_message::<TestMessageDispatch>(
|
assert_eq!(
|
||||||
TEST_RELAYER_B,
|
lane.receive_message::<TestMessageDispatch, _>(
|
||||||
|
&TEST_RELAYER_B,
|
||||||
|
&TEST_RELAYER_B,
|
||||||
max_nonce + 1,
|
max_nonce + 1,
|
||||||
message_data(REGULAR_PAYLOAD).into()
|
message_data(REGULAR_PAYLOAD).into()
|
||||||
));
|
),
|
||||||
|
ReceivalResult::TooManyUnconfirmedMessages,
|
||||||
|
);
|
||||||
// Fails to dispatch new messages from latest relayer.
|
// Fails to dispatch new messages from latest relayer.
|
||||||
assert!(!lane.receive_message::<TestMessageDispatch>(
|
assert_eq!(
|
||||||
TEST_RELAYER_A,
|
lane.receive_message::<TestMessageDispatch, _>(
|
||||||
|
&TEST_RELAYER_A,
|
||||||
|
&TEST_RELAYER_A,
|
||||||
max_nonce + 1,
|
max_nonce + 1,
|
||||||
message_data(REGULAR_PAYLOAD).into()
|
message_data(REGULAR_PAYLOAD).into()
|
||||||
));
|
),
|
||||||
|
ReceivalResult::TooManyUnconfirmedMessages,
|
||||||
|
);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -336,21 +389,33 @@ mod tests {
|
|||||||
fn correctly_receives_following_messages_from_two_relayers_alternately() {
|
fn correctly_receives_following_messages_from_two_relayers_alternately() {
|
||||||
run_test(|| {
|
run_test(|| {
|
||||||
let mut lane = inbound_lane::<TestRuntime, _>(TEST_LANE_ID);
|
let mut lane = inbound_lane::<TestRuntime, _>(TEST_LANE_ID);
|
||||||
assert!(lane.receive_message::<TestMessageDispatch>(
|
assert_eq!(
|
||||||
TEST_RELAYER_A,
|
lane.receive_message::<TestMessageDispatch, _>(
|
||||||
|
&TEST_RELAYER_A,
|
||||||
|
&TEST_RELAYER_A,
|
||||||
1,
|
1,
|
||||||
message_data(REGULAR_PAYLOAD).into()
|
message_data(REGULAR_PAYLOAD).into()
|
||||||
));
|
),
|
||||||
assert!(lane.receive_message::<TestMessageDispatch>(
|
ReceivalResult::Dispatched(dispatch_result(0))
|
||||||
TEST_RELAYER_B,
|
);
|
||||||
|
assert_eq!(
|
||||||
|
lane.receive_message::<TestMessageDispatch, _>(
|
||||||
|
&TEST_RELAYER_B,
|
||||||
|
&TEST_RELAYER_B,
|
||||||
2,
|
2,
|
||||||
message_data(REGULAR_PAYLOAD).into()
|
message_data(REGULAR_PAYLOAD).into()
|
||||||
));
|
),
|
||||||
assert!(lane.receive_message::<TestMessageDispatch>(
|
ReceivalResult::Dispatched(dispatch_result(0))
|
||||||
TEST_RELAYER_A,
|
);
|
||||||
|
assert_eq!(
|
||||||
|
lane.receive_message::<TestMessageDispatch, _>(
|
||||||
|
&TEST_RELAYER_A,
|
||||||
|
&TEST_RELAYER_A,
|
||||||
3,
|
3,
|
||||||
message_data(REGULAR_PAYLOAD).into()
|
message_data(REGULAR_PAYLOAD).into()
|
||||||
));
|
),
|
||||||
|
ReceivalResult::Dispatched(dispatch_result(0))
|
||||||
|
);
|
||||||
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![(1, 1, TEST_RELAYER_A), (2, 2, TEST_RELAYER_B), (3, 3, TEST_RELAYER_A)]
|
||||||
@@ -362,16 +427,24 @@ mod tests {
|
|||||||
fn rejects_same_message_from_two_different_relayers() {
|
fn rejects_same_message_from_two_different_relayers() {
|
||||||
run_test(|| {
|
run_test(|| {
|
||||||
let mut lane = inbound_lane::<TestRuntime, _>(TEST_LANE_ID);
|
let mut lane = inbound_lane::<TestRuntime, _>(TEST_LANE_ID);
|
||||||
assert!(lane.receive_message::<TestMessageDispatch>(
|
assert_eq!(
|
||||||
TEST_RELAYER_A,
|
lane.receive_message::<TestMessageDispatch, _>(
|
||||||
|
&TEST_RELAYER_A,
|
||||||
|
&TEST_RELAYER_A,
|
||||||
1,
|
1,
|
||||||
message_data(REGULAR_PAYLOAD).into()
|
message_data(REGULAR_PAYLOAD).into()
|
||||||
));
|
),
|
||||||
assert!(!lane.receive_message::<TestMessageDispatch>(
|
ReceivalResult::Dispatched(dispatch_result(0))
|
||||||
TEST_RELAYER_B,
|
);
|
||||||
|
assert_eq!(
|
||||||
|
lane.receive_message::<TestMessageDispatch, _>(
|
||||||
|
&TEST_RELAYER_B,
|
||||||
|
&TEST_RELAYER_B,
|
||||||
1,
|
1,
|
||||||
message_data(REGULAR_PAYLOAD).into()
|
message_data(REGULAR_PAYLOAD).into()
|
||||||
));
|
),
|
||||||
|
ReceivalResult::InvalidNonce,
|
||||||
|
);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -383,4 +456,22 @@ mod tests {
|
|||||||
assert_eq!(lane.storage.data().last_delivered_nonce(), 1);
|
assert_eq!(lane.storage.data().last_delivered_nonce(), 1);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn unspent_weight_is_returned_by_receive_message() {
|
||||||
|
run_test(|| {
|
||||||
|
let mut lane = inbound_lane::<TestRuntime, _>(TEST_LANE_ID);
|
||||||
|
let mut payload = REGULAR_PAYLOAD;
|
||||||
|
payload.dispatch_result.unspent_weight = 1;
|
||||||
|
assert_eq!(
|
||||||
|
lane.receive_message::<TestMessageDispatch, _>(
|
||||||
|
&TEST_RELAYER_A,
|
||||||
|
&TEST_RELAYER_A,
|
||||||
|
1,
|
||||||
|
message_data(payload).into()
|
||||||
|
),
|
||||||
|
ReceivalResult::Dispatched(dispatch_result(1))
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -42,7 +42,7 @@ pub use crate::weights_ext::{
|
|||||||
EXPECTED_DEFAULT_MESSAGE_LENGTH,
|
EXPECTED_DEFAULT_MESSAGE_LENGTH,
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::inbound_lane::{InboundLane, InboundLaneStorage};
|
use crate::inbound_lane::{InboundLane, InboundLaneStorage, ReceivalResult};
|
||||||
use crate::outbound_lane::{OutboundLane, OutboundLaneStorage};
|
use crate::outbound_lane::{OutboundLane, OutboundLaneStorage};
|
||||||
use crate::weights::WeightInfo;
|
use crate::weights::WeightInfo;
|
||||||
|
|
||||||
@@ -55,9 +55,11 @@ use bp_messages::{
|
|||||||
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, ensure,
|
decl_error, decl_event, decl_module, decl_storage,
|
||||||
|
dispatch::DispatchResultWithPostInfo,
|
||||||
|
ensure,
|
||||||
traits::Get,
|
traits::Get,
|
||||||
weights::{DispatchClass, Weight},
|
weights::{DispatchClass, Pays, PostDispatchInfo, Weight},
|
||||||
Parameter, StorageMap,
|
Parameter, StorageMap,
|
||||||
};
|
};
|
||||||
use frame_system::{ensure_signed, RawOrigin};
|
use frame_system::{ensure_signed, RawOrigin};
|
||||||
@@ -150,7 +152,11 @@ pub trait Config<I = DefaultInstance>: frame_system::Config {
|
|||||||
/// Source header chain, as it is represented on target chain.
|
/// Source header chain, as it is represented on target chain.
|
||||||
type SourceHeaderChain: SourceHeaderChain<Self::InboundMessageFee>;
|
type SourceHeaderChain: SourceHeaderChain<Self::InboundMessageFee>;
|
||||||
/// Message dispatch.
|
/// Message dispatch.
|
||||||
type MessageDispatch: MessageDispatch<Self::InboundMessageFee, DispatchPayload = Self::InboundPayload>;
|
type MessageDispatch: MessageDispatch<
|
||||||
|
Self::AccountId,
|
||||||
|
Self::InboundMessageFee,
|
||||||
|
DispatchPayload = Self::InboundPayload,
|
||||||
|
>;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Shortcut to messages proof type for Config.
|
/// Shortcut to messages proof type for Config.
|
||||||
@@ -438,13 +444,13 @@ decl_module! {
|
|||||||
#[weight = T::WeightInfo::receive_messages_proof_weight(proof, *messages_count, *dispatch_weight)]
|
#[weight = T::WeightInfo::receive_messages_proof_weight(proof, *messages_count, *dispatch_weight)]
|
||||||
pub fn receive_messages_proof(
|
pub fn receive_messages_proof(
|
||||||
origin,
|
origin,
|
||||||
relayer_id: T::InboundRelayer,
|
relayer_id_at_bridged_chain: T::InboundRelayer,
|
||||||
proof: MessagesProofOf<T, I>,
|
proof: MessagesProofOf<T, I>,
|
||||||
messages_count: u32,
|
messages_count: u32,
|
||||||
dispatch_weight: Weight,
|
dispatch_weight: Weight,
|
||||||
) -> DispatchResult {
|
) -> DispatchResultWithPostInfo {
|
||||||
ensure_not_halted::<T, I>()?;
|
ensure_not_halted::<T, I>()?;
|
||||||
let _ = ensure_signed(origin)?;
|
let relayer_id_at_this_chain = ensure_signed(origin)?;
|
||||||
|
|
||||||
// reject transactions that are declaring too many messages
|
// reject transactions that are declaring too many messages
|
||||||
ensure!(
|
ensure!(
|
||||||
@@ -452,6 +458,23 @@ decl_module! {
|
|||||||
Error::<T, I>::TooManyMessagesInTheProof
|
Error::<T, I>::TooManyMessagesInTheProof
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// why do we need to know the weight of this (`receive_messages_proof`) call? Because
|
||||||
|
// we may want to return some funds for not-dispatching (or partially dispatching) some
|
||||||
|
// messages to the call origin (relayer). And this is done by returning actual weight
|
||||||
|
// from the call. But we only know dispatch weight of every messages. So to refund relayer
|
||||||
|
// because we have not dispatched Message, we need to:
|
||||||
|
//
|
||||||
|
// ActualWeight = DeclaredWeight - Message.DispatchWeight
|
||||||
|
//
|
||||||
|
// The DeclaredWeight is exactly what's computed here. Unfortunately it is impossible
|
||||||
|
// to get pre-computed value (and it has been already computed by the executive).
|
||||||
|
let declared_weight = T::WeightInfo::receive_messages_proof_weight(
|
||||||
|
&proof,
|
||||||
|
messages_count,
|
||||||
|
dispatch_weight,
|
||||||
|
);
|
||||||
|
let mut actual_weight = declared_weight;
|
||||||
|
|
||||||
// verify messages proof && convert proof into messages
|
// verify messages proof && convert proof into messages
|
||||||
let messages = verify_and_decode_messages_proof::<
|
let messages = verify_and_decode_messages_proof::<
|
||||||
T::SourceHeaderChain,
|
T::SourceHeaderChain,
|
||||||
@@ -511,20 +534,57 @@ decl_module! {
|
|||||||
debug_assert_eq!(message.key.lane_id, lane_id);
|
debug_assert_eq!(message.key.lane_id, lane_id);
|
||||||
|
|
||||||
total_messages += 1;
|
total_messages += 1;
|
||||||
if lane.receive_message::<T::MessageDispatch>(relayer_id.clone(), message.key.nonce, message.data) {
|
let dispatch_weight = T::MessageDispatch::dispatch_weight(&message);
|
||||||
|
let receival_result = lane.receive_message::<T::MessageDispatch, T::AccountId>(
|
||||||
|
&relayer_id_at_bridged_chain,
|
||||||
|
&relayer_id_at_this_chain,
|
||||||
|
message.key.nonce,
|
||||||
|
message.data,
|
||||||
|
);
|
||||||
|
|
||||||
|
// note that we're returning unspent weight to relayer even if message has been
|
||||||
|
// rejected by the lane. This allows relayers to submit spam transactions with
|
||||||
|
// e.g. the same set of already delivered messages over and over again, without
|
||||||
|
// losing funds for messages dispatch. But keep in mind that relayer pays base
|
||||||
|
// delivery transaction cost anyway. And base cost covers everything except
|
||||||
|
// dispatch, so we have a balance here.
|
||||||
|
let (unspent_weight, refund_pay_dispatch_fee) = match receival_result {
|
||||||
|
ReceivalResult::Dispatched(dispatch_result) => {
|
||||||
valid_messages += 1;
|
valid_messages += 1;
|
||||||
|
(dispatch_result.unspent_weight, !dispatch_result.dispatch_fee_paid_during_dispatch)
|
||||||
|
},
|
||||||
|
ReceivalResult::InvalidNonce
|
||||||
|
| ReceivalResult::TooManyUnrewardedRelayers
|
||||||
|
| ReceivalResult::TooManyUnconfirmedMessages => (dispatch_weight, true),
|
||||||
|
};
|
||||||
|
actual_weight = actual_weight
|
||||||
|
.saturating_sub(sp_std::cmp::min(unspent_weight, dispatch_weight))
|
||||||
|
.saturating_sub(
|
||||||
|
// delivery call weight formula assumes that the fee is paid at
|
||||||
|
// this (target) chain. If the message is prepaid at the source
|
||||||
|
// chain, let's refund relayer with this extra cost.
|
||||||
|
if refund_pay_dispatch_fee {
|
||||||
|
T::WeightInfo::pay_inbound_dispatch_fee_overhead()
|
||||||
|
} else {
|
||||||
|
0
|
||||||
}
|
}
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
log::trace!(
|
log::trace!(
|
||||||
target: "runtime::bridge-messages",
|
target: "runtime::bridge-messages",
|
||||||
"Received messages: total={}, valid={}",
|
"Received messages: total={}, valid={}. Weight used: {}/{}",
|
||||||
total_messages,
|
total_messages,
|
||||||
valid_messages,
|
valid_messages,
|
||||||
|
actual_weight,
|
||||||
|
declared_weight,
|
||||||
);
|
);
|
||||||
|
|
||||||
Ok(())
|
Ok(PostDispatchInfo {
|
||||||
|
actual_weight: Some(actual_weight),
|
||||||
|
pays_fee: Pays::Yes,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Receive messages delivery proof from bridged chain.
|
/// Receive messages delivery proof from bridged chain.
|
||||||
@@ -860,10 +920,9 @@ 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, run_test, Event as TestEvent, Origin, TestMessageDeliveryAndDispatchPayment,
|
message, message_payload, run_test, Event as TestEvent, Origin, TestMessageDeliveryAndDispatchPayment,
|
||||||
TestMessagesDeliveryProof, TestMessagesParameter, TestMessagesProof, TestPayload, TestRuntime,
|
TestMessagesDeliveryProof, TestMessagesParameter, TestMessagesProof, TestRuntime, TokenConversionRate,
|
||||||
TokenConversionRate, PAYLOAD_REJECTED_BY_TARGET_CHAIN, REGULAR_PAYLOAD, TEST_LANE_ID, TEST_RELAYER_A,
|
PAYLOAD_REJECTED_BY_TARGET_CHAIN, REGULAR_PAYLOAD, TEST_LANE_ID, TEST_RELAYER_A, TEST_RELAYER_B,
|
||||||
TEST_RELAYER_B,
|
|
||||||
};
|
};
|
||||||
use bp_messages::UnrewardedRelayersState;
|
use bp_messages::UnrewardedRelayersState;
|
||||||
use frame_support::{assert_noop, assert_ok};
|
use frame_support::{assert_noop, assert_ok};
|
||||||
@@ -883,7 +942,7 @@ mod tests {
|
|||||||
Origin::signed(1),
|
Origin::signed(1),
|
||||||
TEST_LANE_ID,
|
TEST_LANE_ID,
|
||||||
REGULAR_PAYLOAD,
|
REGULAR_PAYLOAD,
|
||||||
REGULAR_PAYLOAD.1,
|
REGULAR_PAYLOAD.declared_weight,
|
||||||
));
|
));
|
||||||
|
|
||||||
// check event with assigned nonce
|
// check event with assigned nonce
|
||||||
@@ -897,7 +956,10 @@ mod tests {
|
|||||||
);
|
);
|
||||||
|
|
||||||
// check that fee has been withdrawn from submitter
|
// check that fee has been withdrawn from submitter
|
||||||
assert!(TestMessageDeliveryAndDispatchPayment::is_fee_paid(1, REGULAR_PAYLOAD.1));
|
assert!(TestMessageDeliveryAndDispatchPayment::is_fee_paid(
|
||||||
|
1,
|
||||||
|
REGULAR_PAYLOAD.declared_weight
|
||||||
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn receive_messages_delivery_proof() {
|
fn receive_messages_delivery_proof() {
|
||||||
@@ -1113,7 +1175,7 @@ mod tests {
|
|||||||
Origin::signed(1),
|
Origin::signed(1),
|
||||||
TEST_LANE_ID,
|
TEST_LANE_ID,
|
||||||
REGULAR_PAYLOAD,
|
REGULAR_PAYLOAD,
|
||||||
REGULAR_PAYLOAD.1,
|
REGULAR_PAYLOAD.declared_weight,
|
||||||
),
|
),
|
||||||
Error::<TestRuntime, DefaultInstance>::Halted,
|
Error::<TestRuntime, DefaultInstance>::Halted,
|
||||||
);
|
);
|
||||||
@@ -1129,7 +1191,7 @@ mod tests {
|
|||||||
TEST_RELAYER_A,
|
TEST_RELAYER_A,
|
||||||
Ok(vec![message(2, REGULAR_PAYLOAD)]).into(),
|
Ok(vec![message(2, REGULAR_PAYLOAD)]).into(),
|
||||||
1,
|
1,
|
||||||
REGULAR_PAYLOAD.1,
|
REGULAR_PAYLOAD.declared_weight,
|
||||||
),
|
),
|
||||||
Error::<TestRuntime, DefaultInstance>::Halted,
|
Error::<TestRuntime, DefaultInstance>::Halted,
|
||||||
);
|
);
|
||||||
@@ -1164,7 +1226,7 @@ mod tests {
|
|||||||
Origin::signed(1),
|
Origin::signed(1),
|
||||||
TEST_LANE_ID,
|
TEST_LANE_ID,
|
||||||
REGULAR_PAYLOAD,
|
REGULAR_PAYLOAD,
|
||||||
REGULAR_PAYLOAD.1,
|
REGULAR_PAYLOAD.declared_weight,
|
||||||
),
|
),
|
||||||
Error::<TestRuntime, DefaultInstance>::Halted,
|
Error::<TestRuntime, DefaultInstance>::Halted,
|
||||||
);
|
);
|
||||||
@@ -1181,7 +1243,7 @@ mod tests {
|
|||||||
TEST_RELAYER_A,
|
TEST_RELAYER_A,
|
||||||
Ok(vec![message(1, REGULAR_PAYLOAD)]).into(),
|
Ok(vec![message(1, REGULAR_PAYLOAD)]).into(),
|
||||||
1,
|
1,
|
||||||
REGULAR_PAYLOAD.1,
|
REGULAR_PAYLOAD.declared_weight,
|
||||||
),);
|
),);
|
||||||
|
|
||||||
assert_ok!(Pallet::<TestRuntime>::receive_messages_delivery_proof(
|
assert_ok!(Pallet::<TestRuntime>::receive_messages_delivery_proof(
|
||||||
@@ -1214,7 +1276,7 @@ mod tests {
|
|||||||
Origin::signed(1),
|
Origin::signed(1),
|
||||||
TEST_LANE_ID,
|
TEST_LANE_ID,
|
||||||
PAYLOAD_REJECTED_BY_TARGET_CHAIN,
|
PAYLOAD_REJECTED_BY_TARGET_CHAIN,
|
||||||
PAYLOAD_REJECTED_BY_TARGET_CHAIN.1
|
PAYLOAD_REJECTED_BY_TARGET_CHAIN.declared_weight
|
||||||
),
|
),
|
||||||
Error::<TestRuntime, DefaultInstance>::MessageRejectedByChainVerifier,
|
Error::<TestRuntime, DefaultInstance>::MessageRejectedByChainVerifier,
|
||||||
);
|
);
|
||||||
@@ -1241,7 +1303,7 @@ mod tests {
|
|||||||
Origin::signed(1),
|
Origin::signed(1),
|
||||||
TEST_LANE_ID,
|
TEST_LANE_ID,
|
||||||
REGULAR_PAYLOAD,
|
REGULAR_PAYLOAD,
|
||||||
REGULAR_PAYLOAD.1
|
REGULAR_PAYLOAD.declared_weight
|
||||||
),
|
),
|
||||||
Error::<TestRuntime, DefaultInstance>::FailedToWithdrawMessageFee,
|
Error::<TestRuntime, DefaultInstance>::FailedToWithdrawMessageFee,
|
||||||
);
|
);
|
||||||
@@ -1256,7 +1318,7 @@ mod tests {
|
|||||||
TEST_RELAYER_A,
|
TEST_RELAYER_A,
|
||||||
Ok(vec![message(1, REGULAR_PAYLOAD)]).into(),
|
Ok(vec![message(1, REGULAR_PAYLOAD)]).into(),
|
||||||
1,
|
1,
|
||||||
REGULAR_PAYLOAD.1,
|
REGULAR_PAYLOAD.declared_weight,
|
||||||
));
|
));
|
||||||
|
|
||||||
assert_eq!(InboundLanes::<TestRuntime>::get(TEST_LANE_ID).last_delivered_nonce(), 1);
|
assert_eq!(InboundLanes::<TestRuntime>::get(TEST_LANE_ID).last_delivered_nonce(), 1);
|
||||||
@@ -1297,7 +1359,7 @@ mod tests {
|
|||||||
TEST_RELAYER_A,
|
TEST_RELAYER_A,
|
||||||
message_proof,
|
message_proof,
|
||||||
1,
|
1,
|
||||||
REGULAR_PAYLOAD.1,
|
REGULAR_PAYLOAD.declared_weight,
|
||||||
));
|
));
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
@@ -1329,7 +1391,7 @@ mod tests {
|
|||||||
TEST_RELAYER_A,
|
TEST_RELAYER_A,
|
||||||
Ok(vec![message(1, REGULAR_PAYLOAD)]).into(),
|
Ok(vec![message(1, REGULAR_PAYLOAD)]).into(),
|
||||||
1,
|
1,
|
||||||
REGULAR_PAYLOAD.1 - 1,
|
REGULAR_PAYLOAD.declared_weight - 1,
|
||||||
),
|
),
|
||||||
Error::<TestRuntime, DefaultInstance>::InvalidMessagesDispatchWeight,
|
Error::<TestRuntime, DefaultInstance>::InvalidMessagesDispatchWeight,
|
||||||
);
|
);
|
||||||
@@ -1551,7 +1613,7 @@ mod tests {
|
|||||||
])
|
])
|
||||||
.into(),
|
.into(),
|
||||||
3,
|
3,
|
||||||
REGULAR_PAYLOAD.1 + REGULAR_PAYLOAD.1,
|
REGULAR_PAYLOAD.declared_weight + REGULAR_PAYLOAD.declared_weight,
|
||||||
),);
|
),);
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
@@ -1603,9 +1665,9 @@ mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
fn actual_dispatch_weight_does_not_overlow() {
|
fn actual_dispatch_weight_does_not_overlow() {
|
||||||
run_test(|| {
|
run_test(|| {
|
||||||
let message1 = message(1, TestPayload(0, Weight::MAX / 2));
|
let message1 = message(1, message_payload(0, Weight::MAX / 2));
|
||||||
let message2 = message(2, TestPayload(0, Weight::MAX / 2));
|
let message2 = message(2, message_payload(0, Weight::MAX / 2));
|
||||||
let message3 = message(2, TestPayload(0, Weight::MAX / 2));
|
let message3 = message(2, message_payload(0, Weight::MAX / 2));
|
||||||
|
|
||||||
assert_noop!(
|
assert_noop!(
|
||||||
Pallet::<TestRuntime, DefaultInstance>::receive_messages_proof(
|
Pallet::<TestRuntime, DefaultInstance>::receive_messages_proof(
|
||||||
@@ -1672,4 +1734,61 @@ mod tests {
|
|||||||
assert!(TestMessageDeliveryAndDispatchPayment::is_fee_paid(1, 100));
|
assert!(TestMessageDeliveryAndDispatchPayment::is_fee_paid(1, 100));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn weight_refund_from_receive_messages_proof_works() {
|
||||||
|
run_test(|| {
|
||||||
|
fn submit_with_unspent_weight(
|
||||||
|
nonce: MessageNonce,
|
||||||
|
unspent_weight: Weight,
|
||||||
|
is_prepaid: bool,
|
||||||
|
) -> (Weight, Weight) {
|
||||||
|
let mut payload = REGULAR_PAYLOAD;
|
||||||
|
payload.dispatch_result.unspent_weight = unspent_weight;
|
||||||
|
payload.dispatch_result.dispatch_fee_paid_during_dispatch = !is_prepaid;
|
||||||
|
let proof = Ok(vec![message(nonce, payload)]).into();
|
||||||
|
let messages_count = 1;
|
||||||
|
let pre_dispatch_weight = <TestRuntime as Config>::WeightInfo::receive_messages_proof_weight(
|
||||||
|
&proof,
|
||||||
|
messages_count,
|
||||||
|
REGULAR_PAYLOAD.declared_weight,
|
||||||
|
);
|
||||||
|
let post_dispatch_weight = Pallet::<TestRuntime>::receive_messages_proof(
|
||||||
|
Origin::signed(1),
|
||||||
|
TEST_RELAYER_A,
|
||||||
|
proof,
|
||||||
|
messages_count,
|
||||||
|
REGULAR_PAYLOAD.declared_weight,
|
||||||
|
)
|
||||||
|
.expect("delivery has failed")
|
||||||
|
.actual_weight
|
||||||
|
.expect("receive_messages_proof always returns Some");
|
||||||
|
|
||||||
|
(pre_dispatch_weight, post_dispatch_weight)
|
||||||
|
}
|
||||||
|
|
||||||
|
// when dispatch is returning `unspent_weight < declared_weight`
|
||||||
|
let (pre, post) = submit_with_unspent_weight(1, 1, false);
|
||||||
|
assert_eq!(post, pre - 1);
|
||||||
|
|
||||||
|
// when dispatch is returning `unspent_weight = declared_weight`
|
||||||
|
let (pre, post) = submit_with_unspent_weight(2, REGULAR_PAYLOAD.declared_weight, false);
|
||||||
|
assert_eq!(post, pre - REGULAR_PAYLOAD.declared_weight);
|
||||||
|
|
||||||
|
// when dispatch is returning `unspent_weight > declared_weight`
|
||||||
|
let (pre, post) = submit_with_unspent_weight(3, REGULAR_PAYLOAD.declared_weight + 1, false);
|
||||||
|
assert_eq!(post, pre - REGULAR_PAYLOAD.declared_weight);
|
||||||
|
|
||||||
|
// when there's no unspent weight
|
||||||
|
let (pre, post) = submit_with_unspent_weight(4, 0, false);
|
||||||
|
assert_eq!(post, pre);
|
||||||
|
|
||||||
|
// when dispatch is returning `unspent_weight < declared_weight` AND message is prepaid
|
||||||
|
let (pre, post) = submit_with_unspent_weight(5, 1, true);
|
||||||
|
assert_eq!(
|
||||||
|
post,
|
||||||
|
pre - 1 - <TestRuntime as Config>::WeightInfo::pay_inbound_dispatch_fee_overhead()
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ use bp_messages::{
|
|||||||
InboundLaneData, LaneId, Message, MessageData, MessageKey, MessageNonce, OutboundLaneData,
|
InboundLaneData, LaneId, Message, MessageData, MessageKey, MessageNonce, OutboundLaneData,
|
||||||
Parameter as MessagesParameter,
|
Parameter as MessagesParameter,
|
||||||
};
|
};
|
||||||
use bp_runtime::Size;
|
use bp_runtime::{messages::MessageDispatchResult, Size};
|
||||||
use codec::{Decode, Encode};
|
use codec::{Decode, Encode};
|
||||||
use frame_support::{parameter_types, weights::Weight};
|
use frame_support::{parameter_types, weights::Weight};
|
||||||
use sp_core::H256;
|
use sp_core::H256;
|
||||||
@@ -41,7 +41,17 @@ use std::collections::BTreeMap;
|
|||||||
pub type AccountId = u64;
|
pub type AccountId = u64;
|
||||||
pub type Balance = u64;
|
pub type Balance = u64;
|
||||||
#[derive(Decode, Encode, Clone, Debug, PartialEq, Eq)]
|
#[derive(Decode, Encode, Clone, Debug, PartialEq, Eq)]
|
||||||
pub struct TestPayload(pub u64, pub Weight);
|
pub struct TestPayload {
|
||||||
|
/// Field that may be used to identify messages.
|
||||||
|
pub id: u64,
|
||||||
|
/// Dispatch weight that is declared by the message sender.
|
||||||
|
pub declared_weight: Weight,
|
||||||
|
/// Message dispatch result.
|
||||||
|
///
|
||||||
|
/// Note: in correct code `dispatch_result.unspent_weight` will always be <= `declared_weight`, but for test
|
||||||
|
/// purposes we'll be making it larger than `declared_weight` sometimes.
|
||||||
|
pub dispatch_result: MessageDispatchResult,
|
||||||
|
}
|
||||||
pub type TestMessageFee = u64;
|
pub type TestMessageFee = u64;
|
||||||
pub type TestRelayer = u64;
|
pub type TestRelayer = u64;
|
||||||
|
|
||||||
@@ -189,10 +199,10 @@ pub const TEST_ERROR: &str = "Test error";
|
|||||||
pub const TEST_LANE_ID: LaneId = [0, 0, 0, 1];
|
pub const TEST_LANE_ID: LaneId = [0, 0, 0, 1];
|
||||||
|
|
||||||
/// Regular message payload.
|
/// Regular message payload.
|
||||||
pub const REGULAR_PAYLOAD: TestPayload = TestPayload(0, 50);
|
pub const REGULAR_PAYLOAD: TestPayload = message_payload(0, 50);
|
||||||
|
|
||||||
/// Payload that is rejected by `TestTargetHeaderChain`.
|
/// Payload that is rejected by `TestTargetHeaderChain`.
|
||||||
pub const PAYLOAD_REJECTED_BY_TARGET_CHAIN: TestPayload = TestPayload(1, 50);
|
pub const PAYLOAD_REJECTED_BY_TARGET_CHAIN: TestPayload = message_payload(1, 50);
|
||||||
|
|
||||||
/// Vec of proved messages, grouped by lane.
|
/// Vec of proved messages, grouped by lane.
|
||||||
pub type MessagesByLaneVec = Vec<(LaneId, ProvedLaneMessages<Message<TestMessageFee>>)>;
|
pub type MessagesByLaneVec = Vec<(LaneId, ProvedLaneMessages<Message<TestMessageFee>>)>;
|
||||||
@@ -359,17 +369,25 @@ impl SourceHeaderChain<TestMessageFee> for TestSourceHeaderChain {
|
|||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct TestMessageDispatch;
|
pub struct TestMessageDispatch;
|
||||||
|
|
||||||
impl MessageDispatch<TestMessageFee> for TestMessageDispatch {
|
impl MessageDispatch<AccountId, TestMessageFee> for TestMessageDispatch {
|
||||||
type DispatchPayload = TestPayload;
|
type DispatchPayload = TestPayload;
|
||||||
|
|
||||||
fn dispatch_weight(message: &DispatchMessage<TestPayload, TestMessageFee>) -> Weight {
|
fn dispatch_weight(message: &DispatchMessage<TestPayload, TestMessageFee>) -> Weight {
|
||||||
match message.data.payload.as_ref() {
|
match message.data.payload.as_ref() {
|
||||||
Ok(payload) => payload.1,
|
Ok(payload) => payload.declared_weight,
|
||||||
Err(_) => 0,
|
Err(_) => 0,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn dispatch(_message: DispatchMessage<TestPayload, TestMessageFee>) {}
|
fn dispatch(
|
||||||
|
_relayer_account: &AccountId,
|
||||||
|
message: DispatchMessage<TestPayload, TestMessageFee>,
|
||||||
|
) -> MessageDispatchResult {
|
||||||
|
match message.data.payload.as_ref() {
|
||||||
|
Ok(payload) => payload.dispatch_result.clone(),
|
||||||
|
Err(_) => dispatch_result(0),
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return test lane message with given nonce and payload.
|
/// Return test lane message with given nonce and payload.
|
||||||
@@ -383,6 +401,15 @@ pub fn message(nonce: MessageNonce, payload: TestPayload) -> Message<TestMessage
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Constructs message payload using given arguments and zero unspent weight.
|
||||||
|
pub const fn message_payload(id: u64, declared_weight: Weight) -> TestPayload {
|
||||||
|
TestPayload {
|
||||||
|
id,
|
||||||
|
declared_weight,
|
||||||
|
dispatch_result: dispatch_result(0),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Return message data with valid fee for given payload.
|
/// Return message data with valid fee for given payload.
|
||||||
pub fn message_data(payload: TestPayload) -> MessageData<TestMessageFee> {
|
pub fn message_data(payload: TestPayload) -> MessageData<TestMessageFee> {
|
||||||
MessageData {
|
MessageData {
|
||||||
@@ -391,6 +418,14 @@ pub fn message_data(payload: TestPayload) -> MessageData<TestMessageFee> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns message dispatch result with given unspent weight.
|
||||||
|
pub const fn dispatch_result(unspent_weight: Weight) -> MessageDispatchResult {
|
||||||
|
MessageDispatchResult {
|
||||||
|
unspent_weight,
|
||||||
|
dispatch_fee_paid_during_dispatch: true,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Run pallet test.
|
/// 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()
|
||||||
|
|||||||
@@ -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-03, STEPS: [50, ], REPEAT: 20
|
//! DATE: 2021-06-15, 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
|
||||||
@@ -57,6 +57,7 @@ pub trait WeightInfo {
|
|||||||
fn receive_single_message_proof_with_outbound_lane_state() -> Weight;
|
fn receive_single_message_proof_with_outbound_lane_state() -> Weight;
|
||||||
fn receive_single_message_proof_1_kb() -> Weight;
|
fn receive_single_message_proof_1_kb() -> Weight;
|
||||||
fn receive_single_message_proof_16_kb() -> Weight;
|
fn receive_single_message_proof_16_kb() -> Weight;
|
||||||
|
fn receive_single_prepaid_message_proof() -> Weight;
|
||||||
fn receive_delivery_proof_for_single_message() -> Weight;
|
fn receive_delivery_proof_for_single_message() -> Weight;
|
||||||
fn receive_delivery_proof_for_two_messages_by_single_relayer() -> Weight;
|
fn receive_delivery_proof_for_two_messages_by_single_relayer() -> Weight;
|
||||||
fn receive_delivery_proof_for_two_messages_by_two_relayers() -> Weight;
|
fn receive_delivery_proof_for_two_messages_by_two_relayers() -> Weight;
|
||||||
@@ -73,105 +74,110 @@ pub trait WeightInfo {
|
|||||||
pub struct RialtoWeight<T>(PhantomData<T>);
|
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 {
|
||||||
(140_457_000 as Weight)
|
(154_371_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 {
|
||||||
(138_097_000 as Weight)
|
(157_479_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 {
|
||||||
(196_192_000 as Weight)
|
(186_840_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 {
|
||||||
(6_244_063_000 as Weight)
|
(4_377_567_000 as Weight)
|
||||||
.saturating_add(T::DbWeight::get().reads(4 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 {
|
||||||
(135_633_000 as Weight)
|
(205_350_000 as Weight)
|
||||||
.saturating_add(T::DbWeight::get().reads(3 as Weight))
|
.saturating_add(T::DbWeight::get().reads(5 as Weight))
|
||||||
.saturating_add(T::DbWeight::get().writes(1 as Weight))
|
.saturating_add(T::DbWeight::get().writes(3 as Weight))
|
||||||
}
|
}
|
||||||
fn receive_two_messages_proof() -> Weight {
|
fn receive_two_messages_proof() -> Weight {
|
||||||
(229_415_000 as Weight)
|
(337_102_000 as Weight)
|
||||||
.saturating_add(T::DbWeight::get().reads(3 as Weight))
|
.saturating_add(T::DbWeight::get().reads(5 as Weight))
|
||||||
.saturating_add(T::DbWeight::get().writes(1 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 {
|
||||||
(147_408_000 as Weight)
|
(218_825_000 as Weight)
|
||||||
.saturating_add(T::DbWeight::get().reads(3 as Weight))
|
.saturating_add(T::DbWeight::get().reads(5 as Weight))
|
||||||
.saturating_add(T::DbWeight::get().writes(1 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 {
|
||||||
(160_092_000 as Weight)
|
(230_759_000 as Weight)
|
||||||
.saturating_add(T::DbWeight::get().reads(3 as Weight))
|
.saturating_add(T::DbWeight::get().reads(5 as Weight))
|
||||||
.saturating_add(T::DbWeight::get().writes(1 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 {
|
||||||
(452_140_000 as Weight)
|
(490_522_000 as Weight)
|
||||||
|
.saturating_add(T::DbWeight::get().reads(5 as Weight))
|
||||||
|
.saturating_add(T::DbWeight::get().writes(3 as Weight))
|
||||||
|
}
|
||||||
|
fn receive_single_prepaid_message_proof() -> Weight {
|
||||||
|
(136_550_000 as Weight)
|
||||||
.saturating_add(T::DbWeight::get().reads(3 as Weight))
|
.saturating_add(T::DbWeight::get().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 {
|
||||||
(123_704_000 as Weight)
|
(131_397_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 {
|
||||||
(127_844_000 as Weight)
|
(137_946_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 {
|
||||||
(183_119_000 as Weight)
|
(194_448_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 {
|
||||||
(162_249_000 as Weight)
|
(142_576_000 as Weight)
|
||||||
.saturating_add((3_000 as Weight).saturating_mul(i as Weight))
|
.saturating_add((2_000 as Weight).saturating_mul(i as Weight))
|
||||||
.saturating_add(T::DbWeight::get().reads(5 as Weight))
|
.saturating_add(T::DbWeight::get().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((107_235_000 as Weight).saturating_mul(i as Weight))
|
.saturating_add((138_341_000 as Weight).saturating_mul(i as Weight))
|
||||||
.saturating_add(T::DbWeight::get().reads(3 as Weight))
|
.saturating_add(T::DbWeight::get().reads(5 as Weight))
|
||||||
.saturating_add(T::DbWeight::get().writes(1 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 {
|
||||||
(450_232_000 as Weight)
|
(472_752_000 as Weight)
|
||||||
.saturating_add((9_000 as Weight).saturating_mul(i as Weight))
|
.saturating_add((9_000 as Weight).saturating_mul(i as Weight))
|
||||||
.saturating_add(T::DbWeight::get().reads(3 as Weight))
|
.saturating_add(T::DbWeight::get().reads(5 as Weight))
|
||||||
.saturating_add(T::DbWeight::get().writes(1 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 {
|
||||||
(181_851_000 as Weight)
|
(175_300_000 as Weight)
|
||||||
.saturating_add((7_000 as Weight).saturating_mul(i as Weight))
|
.saturating_add((6_000 as Weight).saturating_mul(i as Weight))
|
||||||
.saturating_add(T::DbWeight::get().reads(3 as Weight))
|
.saturating_add(T::DbWeight::get().reads(5 as Weight))
|
||||||
.saturating_add(T::DbWeight::get().writes(1 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((114_622_000 as Weight).saturating_mul(i as Weight))
|
.saturating_add((142_176_000 as Weight).saturating_mul(i as Weight))
|
||||||
.saturating_add(T::DbWeight::get().reads(3 as Weight))
|
.saturating_add(T::DbWeight::get().reads(5 as Weight))
|
||||||
.saturating_add(T::DbWeight::get().writes(1 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 {
|
||||||
(103_133_000 as Weight)
|
(127_372_000 as Weight)
|
||||||
.saturating_add((6_676_000 as Weight).saturating_mul(i as Weight))
|
.saturating_add((7_927_000 as Weight).saturating_mul(i as Weight))
|
||||||
.saturating_add(T::DbWeight::get().reads(5 as Weight))
|
.saturating_add(T::DbWeight::get().reads(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 {
|
||||||
(100_321_000 as Weight)
|
(99_781_000 as Weight)
|
||||||
.saturating_add((59_736_000 as Weight).saturating_mul(i as Weight))
|
.saturating_add((64_001_000 as Weight).saturating_mul(i as Weight))
|
||||||
.saturating_add(T::DbWeight::get().reads(5 as Weight))
|
.saturating_add(T::DbWeight::get().reads(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))
|
||||||
@@ -182,105 +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 {
|
||||||
(140_457_000 as Weight)
|
(154_371_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 {
|
||||||
(138_097_000 as Weight)
|
(157_479_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 {
|
||||||
(196_192_000 as Weight)
|
(186_840_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 {
|
||||||
(6_244_063_000 as Weight)
|
(4_377_567_000 as Weight)
|
||||||
.saturating_add(RocksDbWeight::get().reads(4 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 {
|
||||||
(135_633_000 as Weight)
|
(205_350_000 as Weight)
|
||||||
.saturating_add(RocksDbWeight::get().reads(3 as Weight))
|
.saturating_add(RocksDbWeight::get().reads(5 as Weight))
|
||||||
.saturating_add(RocksDbWeight::get().writes(1 as Weight))
|
.saturating_add(RocksDbWeight::get().writes(3 as Weight))
|
||||||
}
|
}
|
||||||
fn receive_two_messages_proof() -> Weight {
|
fn receive_two_messages_proof() -> Weight {
|
||||||
(229_415_000 as Weight)
|
(337_102_000 as Weight)
|
||||||
.saturating_add(RocksDbWeight::get().reads(3 as Weight))
|
.saturating_add(RocksDbWeight::get().reads(5 as Weight))
|
||||||
.saturating_add(RocksDbWeight::get().writes(1 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 {
|
||||||
(147_408_000 as Weight)
|
(218_825_000 as Weight)
|
||||||
.saturating_add(RocksDbWeight::get().reads(3 as Weight))
|
.saturating_add(RocksDbWeight::get().reads(5 as Weight))
|
||||||
.saturating_add(RocksDbWeight::get().writes(1 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 {
|
||||||
(160_092_000 as Weight)
|
(230_759_000 as Weight)
|
||||||
.saturating_add(RocksDbWeight::get().reads(3 as Weight))
|
.saturating_add(RocksDbWeight::get().reads(5 as Weight))
|
||||||
.saturating_add(RocksDbWeight::get().writes(1 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 {
|
||||||
(452_140_000 as Weight)
|
(490_522_000 as Weight)
|
||||||
|
.saturating_add(RocksDbWeight::get().reads(5 as Weight))
|
||||||
|
.saturating_add(RocksDbWeight::get().writes(3 as Weight))
|
||||||
|
}
|
||||||
|
fn receive_single_prepaid_message_proof() -> Weight {
|
||||||
|
(136_550_000 as Weight)
|
||||||
.saturating_add(RocksDbWeight::get().reads(3 as Weight))
|
.saturating_add(RocksDbWeight::get().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 {
|
||||||
(123_704_000 as Weight)
|
(131_397_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 {
|
||||||
(127_844_000 as Weight)
|
(137_946_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 {
|
||||||
(183_119_000 as Weight)
|
(194_448_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 {
|
||||||
(162_249_000 as Weight)
|
(142_576_000 as Weight)
|
||||||
.saturating_add((3_000 as Weight).saturating_mul(i as Weight))
|
.saturating_add((2_000 as Weight).saturating_mul(i as Weight))
|
||||||
.saturating_add(RocksDbWeight::get().reads(5 as Weight))
|
.saturating_add(RocksDbWeight::get().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((107_235_000 as Weight).saturating_mul(i as Weight))
|
.saturating_add((138_341_000 as Weight).saturating_mul(i as Weight))
|
||||||
.saturating_add(RocksDbWeight::get().reads(3 as Weight))
|
.saturating_add(RocksDbWeight::get().reads(5 as Weight))
|
||||||
.saturating_add(RocksDbWeight::get().writes(1 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 {
|
||||||
(450_232_000 as Weight)
|
(472_752_000 as Weight)
|
||||||
.saturating_add((9_000 as Weight).saturating_mul(i as Weight))
|
.saturating_add((9_000 as Weight).saturating_mul(i as Weight))
|
||||||
.saturating_add(RocksDbWeight::get().reads(3 as Weight))
|
.saturating_add(RocksDbWeight::get().reads(5 as Weight))
|
||||||
.saturating_add(RocksDbWeight::get().writes(1 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 {
|
||||||
(181_851_000 as Weight)
|
(175_300_000 as Weight)
|
||||||
.saturating_add((7_000 as Weight).saturating_mul(i as Weight))
|
.saturating_add((6_000 as Weight).saturating_mul(i as Weight))
|
||||||
.saturating_add(RocksDbWeight::get().reads(3 as Weight))
|
.saturating_add(RocksDbWeight::get().reads(5 as Weight))
|
||||||
.saturating_add(RocksDbWeight::get().writes(1 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((114_622_000 as Weight).saturating_mul(i as Weight))
|
.saturating_add((142_176_000 as Weight).saturating_mul(i as Weight))
|
||||||
.saturating_add(RocksDbWeight::get().reads(3 as Weight))
|
.saturating_add(RocksDbWeight::get().reads(5 as Weight))
|
||||||
.saturating_add(RocksDbWeight::get().writes(1 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 {
|
||||||
(103_133_000 as Weight)
|
(127_372_000 as Weight)
|
||||||
.saturating_add((6_676_000 as Weight).saturating_mul(i as Weight))
|
.saturating_add((7_927_000 as Weight).saturating_mul(i as Weight))
|
||||||
.saturating_add(RocksDbWeight::get().reads(5 as Weight))
|
.saturating_add(RocksDbWeight::get().reads(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 {
|
||||||
(100_321_000 as Weight)
|
(99_781_000 as Weight)
|
||||||
.saturating_add((59_736_000 as Weight).saturating_mul(i as Weight))
|
.saturating_add((64_001_000 as Weight).saturating_mul(i as Weight))
|
||||||
.saturating_add(RocksDbWeight::get().reads(5 as Weight))
|
.saturating_add(RocksDbWeight::get().reads(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))
|
||||||
|
|||||||
@@ -34,6 +34,7 @@ pub fn ensure_weights_are_correct<W: WeightInfoExt>(
|
|||||||
expected_default_message_delivery_tx_weight: Weight,
|
expected_default_message_delivery_tx_weight: Weight,
|
||||||
expected_additional_byte_delivery_weight: Weight,
|
expected_additional_byte_delivery_weight: Weight,
|
||||||
expected_messages_delivery_confirmation_tx_weight: Weight,
|
expected_messages_delivery_confirmation_tx_weight: Weight,
|
||||||
|
expected_pay_inbound_dispatch_fee_weight: Weight,
|
||||||
) {
|
) {
|
||||||
// verify `send_message` weight components
|
// verify `send_message` weight components
|
||||||
assert_ne!(W::send_message_overhead(), 0);
|
assert_ne!(W::send_message_overhead(), 0);
|
||||||
@@ -88,6 +89,15 @@ pub fn ensure_weights_are_correct<W: WeightInfoExt>(
|
|||||||
actual_messages_delivery_confirmation_tx_weight,
|
actual_messages_delivery_confirmation_tx_weight,
|
||||||
expected_messages_delivery_confirmation_tx_weight,
|
expected_messages_delivery_confirmation_tx_weight,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// verify pay-dispatch-fee overhead for inbound messages
|
||||||
|
let actual_pay_inbound_dispatch_fee_weight = W::pay_inbound_dispatch_fee_overhead();
|
||||||
|
assert!(
|
||||||
|
actual_pay_inbound_dispatch_fee_weight <= expected_pay_inbound_dispatch_fee_weight,
|
||||||
|
"Weight {} of pay-dispatch-fee overhead for inbound messages is larger than expected weight {}",
|
||||||
|
actual_pay_inbound_dispatch_fee_weight,
|
||||||
|
expected_pay_inbound_dispatch_fee_weight,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Ensure that we're able to receive maximal (by-size and by-weight) message from other chain.
|
/// Ensure that we're able to receive maximal (by-size and by-weight) message from other chain.
|
||||||
@@ -304,6 +314,13 @@ pub trait WeightInfoExt: WeightInfo {
|
|||||||
(Self::receive_single_message_proof_16_kb() - Self::receive_single_message_proof_1_kb()) / (15 * 1024);
|
(Self::receive_single_message_proof_16_kb() - Self::receive_single_message_proof_1_kb()) / (15 * 1024);
|
||||||
proof_size_in_bytes * byte_weight
|
proof_size_in_bytes * byte_weight
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns weight of the pay-dispatch-fee operation for inbound messages.
|
||||||
|
///
|
||||||
|
/// This function may return zero if runtime doesn't support pay-dispatch-fee-at-target-chain option.
|
||||||
|
fn pay_inbound_dispatch_fee_overhead() -> Weight {
|
||||||
|
Self::receive_single_message_proof().saturating_sub(Self::receive_single_prepaid_message_proof())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl WeightInfoExt for () {
|
impl WeightInfoExt for () {
|
||||||
|
|||||||
@@ -80,7 +80,7 @@ pub const MAX_UNCONFIRMED_MESSAGES_AT_INBOUND_LANE: MessageNonce = 1024;
|
|||||||
/// for the case when single message of `pallet_bridge_messages::EXPECTED_DEFAULT_MESSAGE_LENGTH` bytes is delivered.
|
/// for the case when single message of `pallet_bridge_messages::EXPECTED_DEFAULT_MESSAGE_LENGTH` bytes is delivered.
|
||||||
/// The message must have dispatch weight set to zero. The result then must be rounded up to account
|
/// The message must have dispatch weight set to zero. The result then must be rounded up to account
|
||||||
/// possible future runtime upgrades.
|
/// possible future runtime upgrades.
|
||||||
pub const DEFAULT_MESSAGE_DELIVERY_TX_WEIGHT: Weight = 1_000_000_000;
|
pub const DEFAULT_MESSAGE_DELIVERY_TX_WEIGHT: Weight = 1_500_000_000;
|
||||||
|
|
||||||
/// Increase of delivery transaction weight on Millau chain with every additional message byte.
|
/// Increase of delivery transaction weight on Millau chain with every additional message byte.
|
||||||
///
|
///
|
||||||
@@ -95,6 +95,13 @@ pub const ADDITIONAL_MESSAGE_BYTE_DELIVERY_WEIGHT: Weight = 25_000;
|
|||||||
/// runtime upgrades.
|
/// runtime upgrades.
|
||||||
pub const MAX_SINGLE_MESSAGE_DELIVERY_CONFIRMATION_TX_WEIGHT: Weight = 2_000_000_000;
|
pub const MAX_SINGLE_MESSAGE_DELIVERY_CONFIRMATION_TX_WEIGHT: Weight = 2_000_000_000;
|
||||||
|
|
||||||
|
/// Weight of pay-dispatch-fee operation for inbound messages at Millau chain.
|
||||||
|
///
|
||||||
|
/// This value corresponds to the result of `pallet_bridge_messages::WeightInfoExt::pay_inbound_dispatch_fee_overhead()`
|
||||||
|
/// call for your chain. Don't put too much reserve there, because it is used to **decrease**
|
||||||
|
/// `DEFAULT_MESSAGE_DELIVERY_TX_WEIGHT` cost. So putting large reserve would make delivery transactions cheaper.
|
||||||
|
pub const PAY_INBOUND_DISPATCH_FEE_WEIGHT: Weight = 600_000_000;
|
||||||
|
|
||||||
/// The target length of a session (how often authorities change) on Millau measured in of number of
|
/// The target length of a session (how often authorities change) on Millau measured in of number of
|
||||||
/// blocks.
|
/// blocks.
|
||||||
///
|
///
|
||||||
|
|||||||
@@ -71,7 +71,7 @@ pub const MAX_UNCONFIRMED_MESSAGES_AT_INBOUND_LANE: MessageNonce = 128;
|
|||||||
/// for the case when single message of `pallet_bridge_messages::EXPECTED_DEFAULT_MESSAGE_LENGTH` bytes is delivered.
|
/// for the case when single message of `pallet_bridge_messages::EXPECTED_DEFAULT_MESSAGE_LENGTH` bytes is delivered.
|
||||||
/// The message must have dispatch weight set to zero. The result then must be rounded up to account
|
/// The message must have dispatch weight set to zero. The result then must be rounded up to account
|
||||||
/// possible future runtime upgrades.
|
/// possible future runtime upgrades.
|
||||||
pub const DEFAULT_MESSAGE_DELIVERY_TX_WEIGHT: Weight = 1_000_000_000;
|
pub const DEFAULT_MESSAGE_DELIVERY_TX_WEIGHT: Weight = 1_500_000_000;
|
||||||
|
|
||||||
/// Increase of delivery transaction weight on Rialto chain with every additional message byte.
|
/// Increase of delivery transaction weight on Rialto chain with every additional message byte.
|
||||||
///
|
///
|
||||||
@@ -86,6 +86,13 @@ pub const ADDITIONAL_MESSAGE_BYTE_DELIVERY_WEIGHT: Weight = 25_000;
|
|||||||
/// runtime upgrades.
|
/// runtime upgrades.
|
||||||
pub const MAX_SINGLE_MESSAGE_DELIVERY_CONFIRMATION_TX_WEIGHT: Weight = 2_000_000_000;
|
pub const MAX_SINGLE_MESSAGE_DELIVERY_CONFIRMATION_TX_WEIGHT: Weight = 2_000_000_000;
|
||||||
|
|
||||||
|
/// Weight of pay-dispatch-fee operation for inbound messages at Rialto chain.
|
||||||
|
///
|
||||||
|
/// This value corresponds to the result of `pallet_bridge_messages::WeightInfoExt::pay_inbound_dispatch_fee_overhead()`
|
||||||
|
/// call for your chain. Don't put too much reserve there, because it is used to **decrease**
|
||||||
|
/// `DEFAULT_MESSAGE_DELIVERY_TX_WEIGHT` cost. So putting large reserve would make delivery transactions cheaper.
|
||||||
|
pub const PAY_INBOUND_DISPATCH_FEE_WEIGHT: Weight = 600_000_000;
|
||||||
|
|
||||||
/// The target length of a session (how often authorities change) on Rialto measured in of number of
|
/// The target length of a session (how often authorities change) on Rialto measured in of number of
|
||||||
/// blocks.
|
/// blocks.
|
||||||
///
|
///
|
||||||
|
|||||||
@@ -19,7 +19,10 @@
|
|||||||
#![cfg_attr(not(feature = "std"), no_std)]
|
#![cfg_attr(not(feature = "std"), no_std)]
|
||||||
#![warn(missing_docs)]
|
#![warn(missing_docs)]
|
||||||
|
|
||||||
use bp_runtime::{ChainId, Size};
|
use bp_runtime::{
|
||||||
|
messages::{DispatchFeePayment, MessageDispatchResult},
|
||||||
|
ChainId, Size,
|
||||||
|
};
|
||||||
use codec::{Decode, Encode};
|
use codec::{Decode, Encode};
|
||||||
use frame_support::RuntimeDebug;
|
use frame_support::RuntimeDebug;
|
||||||
use sp_std::prelude::*;
|
use sp_std::prelude::*;
|
||||||
@@ -31,7 +34,7 @@ pub type Weight = u64;
|
|||||||
pub type SpecVersion = u32;
|
pub type SpecVersion = u32;
|
||||||
|
|
||||||
/// A generic trait to dispatch arbitrary messages delivered over the bridge.
|
/// A generic trait to dispatch arbitrary messages delivered over the bridge.
|
||||||
pub trait MessageDispatch<MessageId> {
|
pub trait MessageDispatch<AccountId, MessageId> {
|
||||||
/// A type of the message to be dispatched.
|
/// A type of the message to be dispatched.
|
||||||
type Message: codec::Decode;
|
type Message: codec::Decode;
|
||||||
|
|
||||||
@@ -52,7 +55,15 @@ pub trait MessageDispatch<MessageId> {
|
|||||||
/// a sign that some other component has rejected the message even before it has
|
/// a sign that some other component has rejected the message even before it has
|
||||||
/// reached `dispatch` method (right now this may only be caused if we fail to decode
|
/// reached `dispatch` method (right now this may only be caused if we fail to decode
|
||||||
/// the whole message).
|
/// the whole message).
|
||||||
fn dispatch(source_chain: ChainId, target_chain: ChainId, id: MessageId, message: Result<Self::Message, ()>);
|
///
|
||||||
|
/// Returns unspent dispatch weight.
|
||||||
|
fn dispatch<P: FnOnce(&AccountId, Weight) -> Result<(), ()>>(
|
||||||
|
source_chain: ChainId,
|
||||||
|
target_chain: ChainId,
|
||||||
|
id: MessageId,
|
||||||
|
message: Result<Self::Message, ()>,
|
||||||
|
pay_dispatch_fee: P,
|
||||||
|
) -> MessageDispatchResult;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Origin of a Call when it is dispatched on the target chain.
|
/// Origin of a Call when it is dispatched on the target chain.
|
||||||
@@ -110,6 +121,8 @@ pub struct MessagePayload<SourceChainAccountId, TargetChainAccountPublic, Target
|
|||||||
pub weight: Weight,
|
pub weight: Weight,
|
||||||
/// Call origin to be used during dispatch.
|
/// Call origin to be used during dispatch.
|
||||||
pub origin: CallOrigin<SourceChainAccountId, TargetChainAccountPublic, TargetChainSignature>,
|
pub origin: CallOrigin<SourceChainAccountId, TargetChainAccountPublic, TargetChainSignature>,
|
||||||
|
/// Where message dispatch fee is paid?
|
||||||
|
pub dispatch_fee_payment: DispatchFeePayment,
|
||||||
/// The call itself.
|
/// The call itself.
|
||||||
pub call: Call,
|
pub call: Call,
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,7 +18,7 @@
|
|||||||
|
|
||||||
use crate::{LaneId, Message, MessageData, MessageKey, OutboundLaneData};
|
use crate::{LaneId, Message, MessageData, MessageKey, OutboundLaneData};
|
||||||
|
|
||||||
use bp_runtime::Size;
|
use bp_runtime::{messages::MessageDispatchResult, Size};
|
||||||
use codec::{Decode, Encode, Error as CodecError};
|
use codec::{Decode, Encode, Error as CodecError};
|
||||||
use frame_support::{weights::Weight, Parameter, RuntimeDebug};
|
use frame_support::{weights::Weight, Parameter, RuntimeDebug};
|
||||||
use sp_std::{collections::btree_map::BTreeMap, fmt::Debug, prelude::*};
|
use sp_std::{collections::btree_map::BTreeMap, fmt::Debug, prelude::*};
|
||||||
@@ -84,7 +84,7 @@ pub trait SourceHeaderChain<Fee> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Called when inbound message is received.
|
/// Called when inbound message is received.
|
||||||
pub trait MessageDispatch<Fee> {
|
pub trait MessageDispatch<AccountId, Fee> {
|
||||||
/// Decoded message payload type. Valid message may contain invalid payload. In this case
|
/// Decoded message payload type. Valid message may contain invalid payload. In this case
|
||||||
/// message is delivered, but dispatch fails. Therefore, two separate types of payload
|
/// message is delivered, but dispatch fails. Therefore, two separate types of payload
|
||||||
/// (opaque `MessagePayload` used in delivery and this `DispatchPayload` used in dispatch).
|
/// (opaque `MessagePayload` used in delivery and this `DispatchPayload` used in dispatch).
|
||||||
@@ -100,7 +100,13 @@ pub trait MessageDispatch<Fee> {
|
|||||||
///
|
///
|
||||||
/// It is up to the implementers of this trait to determine whether the message
|
/// It is up to the implementers of this trait to determine whether the message
|
||||||
/// is invalid (i.e. improperly encoded, has too large weight, ...) or not.
|
/// is invalid (i.e. improperly encoded, has too large weight, ...) or not.
|
||||||
fn dispatch(message: DispatchMessage<Self::DispatchPayload, Fee>);
|
///
|
||||||
|
/// If your configuration allows paying dispatch fee at the target chain, then
|
||||||
|
/// it must be paid inside this method to the `relayer_account`.
|
||||||
|
fn dispatch(
|
||||||
|
relayer_account: &AccountId,
|
||||||
|
message: DispatchMessage<Self::DispatchPayload, Fee>,
|
||||||
|
) -> MessageDispatchResult;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<Message> Default for ProvedLaneMessages<Message> {
|
impl<Message> Default for ProvedLaneMessages<Message> {
|
||||||
@@ -149,12 +155,17 @@ impl<Fee> SourceHeaderChain<Fee> for ForbidInboundMessages {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<Fee> MessageDispatch<Fee> for ForbidInboundMessages {
|
impl<AccountId, Fee> MessageDispatch<AccountId, Fee> for ForbidInboundMessages {
|
||||||
type DispatchPayload = ();
|
type DispatchPayload = ();
|
||||||
|
|
||||||
fn dispatch_weight(_message: &DispatchMessage<Self::DispatchPayload, Fee>) -> Weight {
|
fn dispatch_weight(_message: &DispatchMessage<Self::DispatchPayload, Fee>) -> Weight {
|
||||||
Weight::MAX
|
Weight::MAX
|
||||||
}
|
}
|
||||||
|
|
||||||
fn dispatch(_message: DispatchMessage<Self::DispatchPayload, Fee>) {}
|
fn dispatch(_: &AccountId, _: DispatchMessage<Self::DispatchPayload, Fee>) -> MessageDispatchResult {
|
||||||
|
MessageDispatchResult {
|
||||||
|
unspent_weight: 0,
|
||||||
|
dispatch_fee_paid_during_dispatch: false,
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,6 +29,8 @@ pub use storage_proof::{Error as StorageProofError, StorageProofChecker};
|
|||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
pub use storage_proof::craft_valid_storage_proof;
|
pub use storage_proof::craft_valid_storage_proof;
|
||||||
|
|
||||||
|
pub mod messages;
|
||||||
|
|
||||||
mod chain;
|
mod chain;
|
||||||
mod storage_proof;
|
mod storage_proof;
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,50 @@
|
|||||||
|
// Copyright 2019-2021 Parity Technologies (UK) Ltd.
|
||||||
|
// This file is part of Parity Bridges Common.
|
||||||
|
|
||||||
|
// Parity Bridges Common is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
|
||||||
|
// Parity Bridges Common is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with Parity Bridges Common. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
//! Primitives that may be used by different message delivery and dispatch mechanisms.
|
||||||
|
|
||||||
|
use codec::{Decode, Encode};
|
||||||
|
use frame_support::{weights::Weight, RuntimeDebug};
|
||||||
|
|
||||||
|
/// Where message dispatch fee is paid?
|
||||||
|
#[derive(Encode, Decode, RuntimeDebug, Clone, PartialEq, Eq)]
|
||||||
|
pub enum DispatchFeePayment {
|
||||||
|
/// The dispacth fee is paid at the source chain.
|
||||||
|
AtSourceChain,
|
||||||
|
/// The dispatch fee is paid at the target chain.
|
||||||
|
///
|
||||||
|
/// The fee will be paid right before the message is dispatched. So in case of any other
|
||||||
|
/// issues (like invalid call encoding, invalid signature, ...) the dispatch module won't
|
||||||
|
/// do any direct transfers. Instead, it'll return fee related to this message dispatch to the
|
||||||
|
/// relayer.
|
||||||
|
AtTargetChain,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Message dispatch result.
|
||||||
|
#[derive(Encode, Decode, RuntimeDebug, Clone, PartialEq, Eq)]
|
||||||
|
pub struct MessageDispatchResult {
|
||||||
|
/// 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:
|
||||||
|
///
|
||||||
|
/// 1) if message has been dispatched successfully, but post-dispatch weight is less than
|
||||||
|
/// the weight, declared by the message sender;
|
||||||
|
/// 2) if message has not been dispatched at all.
|
||||||
|
pub unspent_weight: Weight,
|
||||||
|
/// Whether the message dispatch fee has been paid during dispatch. This will be true if your
|
||||||
|
/// configuration supports pay-dispatch-fee-at-target-chain option and message sender has enabled
|
||||||
|
/// this option.
|
||||||
|
pub dispatch_fee_paid_during_dispatch: bool,
|
||||||
|
}
|
||||||
@@ -72,7 +72,7 @@ mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
fn should_encode_raw_message() {
|
fn should_encode_raw_message() {
|
||||||
// given
|
// given
|
||||||
let msg = "01000000e88514000000000002d43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d3c040130000000000000000000000000";
|
let msg = "01000000e88514000000000002d43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d003c040130000000000000000000000000";
|
||||||
let encode_message = EncodeMessage::from_iter(vec!["encode-message", "MillauToRialto", "raw", msg]);
|
let encode_message = EncodeMessage::from_iter(vec!["encode-message", "MillauToRialto", "raw", msg]);
|
||||||
|
|
||||||
// when
|
// when
|
||||||
@@ -101,6 +101,6 @@ mod tests {
|
|||||||
let hex = encode_message.encode().unwrap();
|
let hex = encode_message.encode().unwrap();
|
||||||
|
|
||||||
// then
|
// then
|
||||||
assert_eq!(format!("{:?}", hex), "0x01000000e88514000000000002d43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d3c040130000000000000000000000000");
|
assert_eq!(format!("{:?}", hex), "0x01000000e88514000000000002d43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d003c040130000000000000000000000000");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ use crate::cli::{
|
|||||||
TargetSigningParams,
|
TargetSigningParams,
|
||||||
};
|
};
|
||||||
use bp_message_dispatch::{CallOrigin, MessagePayload};
|
use bp_message_dispatch::{CallOrigin, MessagePayload};
|
||||||
|
use bp_runtime::messages::DispatchFeePayment;
|
||||||
use codec::Encode;
|
use codec::Encode;
|
||||||
use frame_support::{dispatch::GetDispatchInfo, weights::Weight};
|
use frame_support::{dispatch::GetDispatchInfo, weights::Weight};
|
||||||
use relay_substrate_client::{Chain, TransactionSignScheme};
|
use relay_substrate_client::{Chain, TransactionSignScheme};
|
||||||
@@ -211,6 +212,7 @@ where
|
|||||||
spec_version,
|
spec_version,
|
||||||
weight,
|
weight,
|
||||||
origin,
|
origin,
|
||||||
|
dispatch_fee_payment: DispatchFeePayment::AtSourceChain,
|
||||||
call: HexBytes::encode(call),
|
call: HexBytes::encode(call),
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -222,12 +224,14 @@ where
|
|||||||
spec_version,
|
spec_version,
|
||||||
weight,
|
weight,
|
||||||
origin,
|
origin,
|
||||||
|
dispatch_fee_payment,
|
||||||
call,
|
call,
|
||||||
} = payload;
|
} = payload;
|
||||||
MessagePayload {
|
MessagePayload {
|
||||||
spec_version,
|
spec_version,
|
||||||
weight,
|
weight,
|
||||||
origin,
|
origin,
|
||||||
|
dispatch_fee_payment,
|
||||||
call: call.0,
|
call: call.0,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -268,6 +272,7 @@ mod tests {
|
|||||||
spec_version: relay_millau_client::Millau::RUNTIME_VERSION.spec_version,
|
spec_version: relay_millau_client::Millau::RUNTIME_VERSION.spec_version,
|
||||||
weight: 1345000,
|
weight: 1345000,
|
||||||
origin: CallOrigin::SourceAccount(sp_keyring::AccountKeyring::Alice.to_account_id()),
|
origin: CallOrigin::SourceAccount(sp_keyring::AccountKeyring::Alice.to_account_id()),
|
||||||
|
dispatch_fee_payment: DispatchFeePayment::AtSourceChain,
|
||||||
call: hex!("0401081234").to_vec(),
|
call: hex!("0401081234").to_vec(),
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
@@ -311,6 +316,7 @@ mod tests {
|
|||||||
sp_keyring::AccountKeyring::Bob.into(),
|
sp_keyring::AccountKeyring::Bob.into(),
|
||||||
signature,
|
signature,
|
||||||
),
|
),
|
||||||
|
dispatch_fee_payment: DispatchFeePayment::AtSourceChain,
|
||||||
call: hex!("0701081234").to_vec(),
|
call: hex!("0701081234").to_vec(),
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -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.
|
||||||
(1024, 216_583_333_334),
|
(814, 216_583_333_334),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user