Skip to content
Merged
Show file tree
Hide file tree
Changes from 10 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions bin/millau/runtime/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -679,6 +679,7 @@ mod tests {
bp_millau::DEFAULT_MESSAGE_DELIVERY_TX_WEIGHT,
bp_millau::ADDITIONAL_MESSAGE_BYTE_DELIVERY_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(
Expand Down
7 changes: 7 additions & 0 deletions bin/millau/runtime/src/rialto_messages.rs
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ type ToRialtoMessagesDeliveryProof = messages::source::FromBridgedChainMessagesD
pub type FromRialtoMessageDispatch = messages::target::FromBridgedChainMessageDispatch<
WithRialtoMessageBridge,
crate::Runtime,
pallet_balances::Pallet<Runtime>,
pallet_bridge_dispatch::DefaultInstance,
>;

Expand Down Expand Up @@ -170,6 +171,7 @@ impl messages::BridgedChainWithMessages for Rialto {

fn estimate_delivery_transaction(
message_payload: &[u8],
include_pay_dispatch_fee_cost: bool,
message_dispatch_weight: Weight,
) -> MessageTransaction<Weight> {
let message_payload_len = u32::try_from(message_payload.len()).unwrap_or(u32::MAX);
Expand All @@ -180,6 +182,11 @@ impl messages::BridgedChainWithMessages for Rialto {
dispatch_weight: extra_bytes_in_payload
.saturating_mul(bp_rialto::ADDITIONAL_MESSAGE_BYTE_DELIVERY_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),
size: message_payload_len
.saturating_add(bp_millau::EXTRA_STORAGE_PROOF_SIZE)
Expand Down
25 changes: 24 additions & 1 deletion bin/rialto/runtime/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -840,6 +840,7 @@ impl_runtime_apis! {
}

use crate::millau_messages::{ToMillauMessagePayload, WithMillauMessageBridge};
use bp_runtime::messages::DispatchFeePayment;
use bridge_runtime_common::messages;
use pallet_bridge_messages::benchmarking::{
Pallet as MessagesBench,
Expand Down Expand Up @@ -883,6 +884,7 @@ impl_runtime_apis! {
weight: params.size as _,
origin: dispatch_origin,
call: message_payload,
dispatch_fee_payment: DispatchFeePayment::AtSourceChain,
};
(message, pallet_bridge_messages::benchmarking::MESSAGE_FEE.into())
}
Expand All @@ -899,7 +901,7 @@ impl_runtime_apis! {
use codec::Encode;
use frame_support::weights::GetDispatchInfo;
use pallet_bridge_messages::storage_keys;
use sp_runtime::traits::Header;
use sp_runtime::traits::{Header, IdentifyAccount};

let remark = match params.size {
MessagesProofSize::Minimal(ref size) => vec![0u8; *size as _],
Expand All @@ -912,12 +914,18 @@ impl_runtime_apis! {
let (rialto_raw_public, rialto_raw_signature) = ed25519_sign(
&call,
&millau_account_id,
VERSION.spec_version,
bp_runtime::MILLAU_BRIDGE_INSTANCE,
);
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(
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::<
Runtime,
<Millau as ChainWithMessages>::MessagesInstance,
Expand All @@ -938,6 +946,7 @@ impl_runtime_apis! {
Default::default(),
);

let dispatch_fee_payment = params.dispatch_fee_payment.clone();
prepare_message_proof::<WithMillauMessageBridge, bp_millau::Hasher, Runtime, (), _, _, _>(
params,
make_millau_message_key,
Expand All @@ -956,6 +965,7 @@ impl_runtime_apis! {
rialto_public,
rialto_signature,
),
dispatch_fee_payment,
call: call.encode(),
}.encode(),
)
Expand Down Expand Up @@ -988,6 +998,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!(
Expand Down Expand Up @@ -1082,6 +1104,7 @@ mod tests {
bp_rialto::DEFAULT_MESSAGE_DELIVERY_TX_WEIGHT,
bp_rialto::ADDITIONAL_MESSAGE_BYTE_DELIVERY_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(
Expand Down
91 changes: 91 additions & 0 deletions bin/rialto/runtime/src/millau_messages.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ pub type FromMillauEncodedCall = messages::target::FromBridgedChainEncodedMessag
pub type FromMillauMessageDispatch = messages::target::FromBridgedChainMessageDispatch<
WithMillauMessageBridge,
crate::Runtime,
pallet_balances::Pallet<Runtime>,
pallet_bridge_dispatch::DefaultInstance,
>;

Expand Down Expand Up @@ -170,6 +171,7 @@ impl messages::BridgedChainWithMessages for Millau {

fn estimate_delivery_transaction(
message_payload: &[u8],
include_pay_dispatch_fee_cost: bool,
message_dispatch_weight: Weight,
) -> MessageTransaction<Weight> {
let message_payload_len = u32::try_from(message_payload.len()).unwrap_or(u32::MAX);
Expand All @@ -180,6 +182,11 @@ impl messages::BridgedChainWithMessages for Millau {
dispatch_weight: extra_bytes_in_payload
.saturating_mul(bp_millau::ADDITIONAL_MESSAGE_BYTE_DELIVERY_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),
size: message_payload_len
.saturating_add(bp_rialto::EXTRA_STORAGE_PROOF_SIZE)
Expand Down Expand Up @@ -251,3 +258,87 @@ impl MessagesParameter for RialtoToMillauMessagesParameter {
}
}
}

#[cfg(test)]
mod tests {
use super::*;
use crate::{AccountId, Call, ExistentialDeposit, Runtime, SystemCall, SystemConfig, VERSION};
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 pallet_bridge_dispatch::CallOrigin;
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_BRIDGE_INSTANCE;
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,
);
});
}
}
2 changes: 2 additions & 0 deletions bin/runtime-common/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ pallet-bridge-messages = { path = "../../modules/messages", default-features = f
# Substrate dependencies

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-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 }
Expand All @@ -42,6 +43,7 @@ std = [
"pallet-bridge-dispatch/std",
"pallet-bridge-grandpa/std",
"pallet-bridge-messages/std",
"pallet-transaction-payment/std",
"sp-core/std",
"sp-runtime/std",
"sp-state-machine/std",
Expand Down
4 changes: 3 additions & 1 deletion bin/runtime-common/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.

- `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
must pay for given transaction on bridged chain. The best case is when you have the same conversion
Expand Down
Loading