[testnet] Allow governance to control fees for Rococo <> Westend bridge (#2139)

Right now governance could only control byte-fee component of Rococo <>
Westend message fees (paid at Asset Hubs). This PR changes it a bit:
1) governance now allowed to control both fee components - byte fee and
base fee;
2) base fee now includes cost of "default" delivery and confirmation
transactions, in addition to `ExportMessage` instruction cost.
This commit is contained in:
Svyatoslav Nikolsky
2023-11-03 11:32:41 +03:00
committed by GitHub
parent 15a3483881
commit 0d3c67d96b
16 changed files with 803 additions and 133 deletions
Generated
+2
View File
@@ -910,6 +910,7 @@ dependencies = [
"bp-asset-hub-westend",
"bp-asset-hub-wococo",
"bp-bridge-hub-rococo",
"bp-bridge-hub-westend",
"bp-bridge-hub-wococo",
"cumulus-pallet-aura-ext",
"cumulus-pallet-dmp-queue",
@@ -1022,6 +1023,7 @@ dependencies = [
"assets-common",
"bp-asset-hub-rococo",
"bp-asset-hub-westend",
"bp-bridge-hub-rococo",
"bp-bridge-hub-westend",
"cumulus-pallet-aura-ext",
"cumulus-pallet-dmp-queue",
@@ -22,24 +22,22 @@
use crate::{
messages::{
source::FromBridgedChainMessagesDeliveryProof, target::FromBridgedChainMessagesProof,
AccountIdOf, BridgedChain, HashOf, HasherOf, MessageBridge, ThisChain,
AccountIdOf, BridgedChain, HashOf, MessageBridge, ThisChain,
},
messages_generation::{
encode_all_messages, encode_lane_data, grow_trie_leaf_value, prepare_messages_storage_proof,
encode_all_messages, encode_lane_data, prepare_message_delivery_storage_proof,
prepare_messages_storage_proof,
},
};
use bp_messages::{storage_keys, MessagePayload};
use bp_messages::MessagePayload;
use bp_polkadot_core::parachains::ParaHash;
use bp_runtime::{
record_all_trie_keys, Chain, Parachain, RawStorageProof, StorageProofSize, UnderlyingChainOf,
};
use bp_runtime::{Chain, Parachain, StorageProofSize, UnderlyingChainOf};
use codec::Encode;
use frame_support::weights::Weight;
use pallet_bridge_messages::benchmarking::{MessageDeliveryProofParams, MessageProofParams};
use sp_runtime::traits::{Header, Zero};
use sp_std::prelude::*;
use sp_trie::{trie_types::TrieDBMutBuilderV1, LayoutV1, MemoryDB, TrieMut};
use xcm::v3::prelude::*;
/// Prepare inbound bridge message according to given message proof parameters.
@@ -172,7 +170,11 @@ where
{
// prepare storage proof
let lane = params.lane;
let (state_root, storage_proof) = prepare_message_delivery_proof::<B>(params);
let (state_root, storage_proof) = prepare_message_delivery_storage_proof::<B>(
params.lane,
params.inbound_lane_data,
params.size,
);
// update runtime storage
let (_, bridged_header_hash) = insert_header_to_grandpa_pallet::<R, FI>(state_root);
@@ -200,7 +202,11 @@ where
{
// prepare storage proof
let lane = params.lane;
let (state_root, storage_proof) = prepare_message_delivery_proof::<B>(params);
let (state_root, storage_proof) = prepare_message_delivery_storage_proof::<B>(
params.lane,
params.inbound_lane_data,
params.size,
);
// update runtime storage
let (_, bridged_header_hash) =
@@ -213,36 +219,6 @@ where
}
}
/// Prepare in-memory message delivery proof, without inserting anything to the runtime storage.
fn prepare_message_delivery_proof<B>(
params: MessageDeliveryProofParams<AccountIdOf<ThisChain<B>>>,
) -> (HashOf<BridgedChain<B>>, RawStorageProof)
where
B: MessageBridge,
{
// prepare Bridged chain storage with inbound lane state
let storage_key =
storage_keys::inbound_lane_data_key(B::BRIDGED_MESSAGES_PALLET_NAME, &params.lane).0;
let mut root = Default::default();
let mut mdb = MemoryDB::default();
{
let mut trie =
TrieDBMutBuilderV1::<HasherOf<BridgedChain<B>>>::new(&mut mdb, &mut root).build();
let inbound_lane_data =
grow_trie_leaf_value(params.inbound_lane_data.encode(), params.size);
trie.insert(&storage_key, &inbound_lane_data)
.map_err(|_| "TrieMut::insert has failed")
.expect("TrieMut::insert should not fail in benchmarks");
}
// generate storage proof to be delivered to This chain
let storage_proof = record_all_trie_keys::<LayoutV1<HasherOf<BridgedChain<B>>>, _>(&mdb, &root)
.map_err(|_| "record_all_trie_keys has failed")
.expect("record_all_trie_keys should not fail in benchmarks");
(root, storage_proof)
}
/// Insert header to the bridge GRANDPA pallet.
pub(crate) fn insert_header_to_grandpa_pallet<R, GI>(
state_root: bp_runtime::HashOf<R::BridgedChain>,
@@ -16,10 +16,11 @@
//! Helpers for generating message storage proofs, that are used by tests and by benchmarks.
use crate::messages::{BridgedChain, HashOf, HasherOf, MessageBridge};
use crate::messages::{AccountIdOf, BridgedChain, HashOf, HasherOf, MessageBridge, ThisChain};
use bp_messages::{
storage_keys, LaneId, MessageKey, MessageNonce, MessagePayload, OutboundLaneData,
storage_keys, InboundLaneData, LaneId, MessageKey, MessageNonce, MessagePayload,
OutboundLaneData,
};
use bp_runtime::{record_all_trie_keys, RawStorageProof, StorageProofSize};
use codec::Encode;
@@ -104,6 +105,38 @@ where
(root, storage_proof)
}
/// Prepare storage proof of given messages delivery.
///
/// Returns state trie root and nodes with prepared messages.
pub fn prepare_message_delivery_storage_proof<B>(
lane: LaneId,
inbound_lane_data: InboundLaneData<AccountIdOf<ThisChain<B>>>,
size: StorageProofSize,
) -> (HashOf<BridgedChain<B>>, RawStorageProof)
where
B: MessageBridge,
{
// prepare Bridged chain storage with inbound lane state
let storage_key = storage_keys::inbound_lane_data_key(B::BRIDGED_MESSAGES_PALLET_NAME, &lane).0;
let mut root = Default::default();
let mut mdb = MemoryDB::default();
{
let mut trie =
TrieDBMutBuilderV1::<HasherOf<BridgedChain<B>>>::new(&mut mdb, &mut root).build();
let inbound_lane_data = grow_trie_leaf_value(inbound_lane_data.encode(), size);
trie.insert(&storage_key, &inbound_lane_data)
.map_err(|_| "TrieMut::insert has failed")
.expect("TrieMut::insert should not fail in benchmarks");
}
// generate storage proof to be delivered to This chain
let storage_proof = record_all_trie_keys::<LayoutV1<HasherOf<BridgedChain<B>>>, _>(&mdb, &root)
.map_err(|_| "record_all_trie_keys has failed")
.expect("record_all_trie_keys should not fail in benchmarks");
(root, storage_proof)
}
/// Add extra data to the trie leaf value so that it'll be of given size.
pub fn grow_trie_leaf_value(mut value: Vec<u8>, size: StorageProofSize) -> Vec<u8> {
match size {
@@ -45,10 +45,6 @@ pub enum Call {
frame_support::parameter_types! {
/// Some sane weight to execute `xcm::Transact(pallet-xcm-bridge-hub-router::Call::report_bridge_status)`.
pub const XcmBridgeHubRouterTransactCallMaxWeight: frame_support::weights::Weight = frame_support::weights::Weight::from_parts(200_000_000, 6144);
/// Base delivery fee to `BridgeHubRococo`.
/// (initially was calculated by test `BridgeHubRococo::can_calculate_weight_for_paid_export_message_with_reserve_transfer` + `33%`)
pub const BridgeHubRococoBaseFeeInRocs: u128 = 1624803349;
}
/// Identifier of AssetHubRococo in the Rococo relay chain.
@@ -42,10 +42,6 @@ pub enum Call {
frame_support::parameter_types! {
/// Some sane weight to execute `xcm::Transact(pallet-xcm-bridge-hub-router::Call::report_bridge_status)`.
pub const XcmBridgeHubRouterTransactCallMaxWeight: frame_support::weights::Weight = frame_support::weights::Weight::from_parts(200_000_000, 6144);
/// Base delivery fee to `BridgeHubWestend`.
/// (initially was calculated by test `BridgeHubWestend::can_calculate_weight_for_paid_export_message_with_reserve_transfer` + `33%`)
pub const BridgeHubWestendBaseFeeInWnds: u128 = 487441010000;
}
/// Identifier of AssetHubWestend in the Westend relay chain.
@@ -42,10 +42,6 @@ pub enum Call {
frame_support::parameter_types! {
/// Some sane weight to execute `xcm::Transact(pallet-xcm-bridge-hub-router::Call::report_bridge_status)`.
pub const XcmBridgeHubRouterTransactCallMaxWeight: frame_support::weights::Weight = frame_support::weights::Weight::from_parts(200_000_000, 6144);
/// Base delivery fee to `BridgeHubWococo`.
/// (initially was calculated by test `BridgeHubWococo::can_calculate_weight_for_paid_export_message_with_reserve_transfer` + `33%`)
pub const BridgeHubWococoBaseFeeInWocs: u128 = 1624803349;
}
/// Identifier of AssetHubWococo in the Wococo relay chain.
@@ -82,3 +82,18 @@ pub const WITH_BRIDGE_ROCOCO_TO_WESTEND_MESSAGES_PALLET_INDEX: u8 = 51;
decl_bridge_finality_runtime_apis!(bridge_hub_rococo);
decl_bridge_messages_runtime_apis!(bridge_hub_rococo);
frame_support::parameter_types! {
/// The XCM fee that is paid for executing XCM program (with `ExportMessage` instruction) at the Rococo
/// BridgeHub.
/// (initially was calculated by test `BridgeHubRococo::can_calculate_weight_for_paid_export_message_with_reserve_transfer` + `33%`)
pub const BridgeHubRococoBaseXcmFeeInRocs: u128 = 1628875538;
/// Transaction fee that is paid at the Rococo BridgeHub for delivering single inbound message.
/// (initially was calculated by test `BridgeHubRococo::can_calculate_fee_for_complex_message_delivery_transaction` + `33%`)
pub const BridgeHubRococoBaseDeliveryFeeInRocs: u128 = 6417262881;
/// Transaction fee that is paid at the Rococo BridgeHub for delivering single outbound message confirmation.
/// (initially was calculated by test `BridgeHubRococo::can_calculate_fee_for_complex_message_confirmation_transaction` + `33%`)
pub const BridgeHubRococoBaseConfirmationFeeInRocs: u128 = 6159996668;
}
@@ -73,3 +73,18 @@ pub const WITH_BRIDGE_WESTEND_TO_ROCOCO_MESSAGES_PALLET_INDEX: u8 = 44;
decl_bridge_finality_runtime_apis!(bridge_hub_westend);
decl_bridge_messages_runtime_apis!(bridge_hub_westend);
frame_support::parameter_types! {
/// The XCM fee that is paid for executing XCM program (with `ExportMessage` instruction) at the Westend
/// BridgeHub.
/// (initially was calculated by test `BridgeHubWestend::can_calculate_weight_for_paid_export_message_with_reserve_transfer` + `33%`)
pub const BridgeHubWestendBaseXcmFeeInWnds: u128 = 488662666666;
/// Transaction fee that is paid at the Westend BridgeHub for delivering single inbound message.
/// (initially was calculated by test `BridgeHubWestend::can_calculate_fee_for_complex_message_delivery_transaction` + `33%`)
pub const BridgeHubWestendBaseDeliveryFeeInWnds: u128 = 1925196628010;
/// Transaction fee that is paid at the Westend BridgeHub for delivering single outbound message confirmation.
/// (initially was calculated by test `BridgeHubWestend::can_calculate_fee_for_complex_message_confirmation_transaction` + `33%`)
pub const BridgeHubWestendBaseConfirmationFeeInWnds: u128 = 1848016628010;
}
@@ -73,3 +73,18 @@ pub const WITH_BRIDGE_WOCOCO_TO_ROCOCO_MESSAGES_PALLET_INDEX: u8 = 45;
decl_bridge_finality_runtime_apis!(bridge_hub_wococo);
decl_bridge_messages_runtime_apis!(bridge_hub_wococo);
frame_support::parameter_types! {
/// The XCM fee that is paid for executing XCM program (with `ExportMessage` instruction) at the Wococo
/// BridgeHub.
/// (initially was calculated by test `BridgeHubWococo::can_calculate_weight_for_paid_export_message_with_reserve_transfer` + `33%`)
pub const BridgeHubWococoBaseXcmFeeInWocs: u128 = 1624803349;
/// Transaction fee that is paid at the Wococo BridgeHub for delivering single inbound message.
/// (initially was calculated by test `BridgeHubWococo::can_calculate_fee_for_complex_message_delivery_transaction` + `33%`)
pub const BridgeHubWococoBaseDeliveryFeeInWocs: u128 = 6417262881;
/// Transaction fee that is paid at the Wococo BridgeHub for delivering single outbound message confirmation.
/// (initially was calculated by test `BridgeHubWococo::can_calculate_fee_for_complex_message_confirmation_transaction` + `33%`)
pub const BridgeHubWococoBaseConfirmationFeeInWocs: u128 = 6159996668;
}
@@ -88,6 +88,7 @@ bp-asset-hub-westend = { path = "../../../../../bridges/primitives/chain-asset-h
bp-asset-hub-wococo = { path = "../../../../../bridges/primitives/chain-asset-hub-wococo", default-features = false }
bp-bridge-hub-rococo = { path = "../../../../../bridges/primitives/chain-bridge-hub-rococo", default-features = false }
bp-bridge-hub-wococo = { path = "../../../../../bridges/primitives/chain-bridge-hub-wococo", default-features = false }
bp-bridge-hub-westend = { path = "../../../../../bridges/primitives/chain-bridge-hub-westend", default-features = false }
[dev-dependencies]
asset-test-utils = { path = "../test-utils" }
@@ -177,6 +178,7 @@ std = [
"bp-asset-hub-wococo/std",
"bp-bridge-hub-rococo/std",
"bp-bridge-hub-wococo/std",
"bp-bridge-hub-westend/std",
"codec/std",
"cumulus-pallet-aura-ext/std",
"cumulus-pallet-dmp-queue/std",
@@ -283,6 +283,9 @@ impl Contains<RuntimeCall> for SafeCallFilter {
match call {
RuntimeCall::System(frame_system::Call::set_storage { items })
if items.iter().all(|(k, _)| k.eq(&bridging::XcmBridgeHubRouterByteFee::key())) ||
items
.iter()
.all(|(k, _)| k.eq(&bridging::XcmBridgeHubRouterBaseFee::key())) ||
items.iter().all(|(k, _)| k.eq(&Flavor::key())) =>
return true,
_ => (),
@@ -760,6 +763,25 @@ pub mod bridging {
// common/shared parameters for Wococo/Rococo
parameter_types! {
/// Base price of every byte of the Rococo -> Westend message. Can be adjusted via
/// governance `set_storage` call.
///
/// Default value is our estimation of the:
///
/// 1) an approximate cost of XCM execution (`ExportMessage` and surroundings) at Rococo bridge hub;
///
/// 2) the approximate cost of Rococo -> Westend message delivery transaction on Westend Bridge Hub,
/// converted into ROCs using 1:1 conversion rate;
///
/// 3) the approximate cost of Rococo -> Westend message confirmation transaction on Rococo Bridge Hub.
pub storage XcmBridgeHubRouterBaseFee: Balance =
bp_bridge_hub_rococo::BridgeHubRococoBaseXcmFeeInRocs::get()
.saturating_add(bp_bridge_hub_westend::BridgeHubWestendBaseDeliveryFeeInWnds::get())
.saturating_add(bp_bridge_hub_rococo::BridgeHubRococoBaseConfirmationFeeInRocs::get());
/// Price of every byte of the Rococo -> Westend message. Can be adjusted via
/// governance `set_storage` call.
pub storage XcmBridgeHubRouterByteFee: Balance = TransactionByteFee::get();
pub SiblingBridgeHubParaId: u32 = match Flavor::get() {
RuntimeFlavor::Rococo => bp_bridge_hub_rococo::BRIDGE_HUB_ROCOCO_PARACHAIN_ID,
RuntimeFlavor::Wococo => bp_bridge_hub_wococo::BRIDGE_HUB_WOCOCO_PARACHAIN_ID,
@@ -768,8 +790,6 @@ pub mod bridging {
/// Router expects payment with this `AssetId`.
/// (`AssetId` has to be aligned with `BridgeTable`)
pub XcmBridgeHubRouterFeeAssetId: AssetId = TokenLocation::get().into();
/// Price per byte - can be adjusted via governance `set_storage` call.
pub storage XcmBridgeHubRouterByteFee: Balance = TransactionByteFee::get();
pub BridgeTable: sp_std::vec::Vec<NetworkExportTableItem> =
sp_std::vec::Vec::new().into_iter()
@@ -814,7 +834,7 @@ pub mod bridging {
// base delivery fee to local `BridgeHub`
Some((
XcmBridgeHubRouterFeeAssetId::get(),
bp_asset_hub_rococo::BridgeHubRococoBaseFeeInRocs::get(),
XcmBridgeHubRouterBaseFee::get(),
).into())
)
];
@@ -890,7 +910,7 @@ pub mod bridging {
// base delivery fee to local `BridgeHub`
Some((
XcmBridgeHubRouterFeeAssetId::get(),
bp_asset_hub_rococo::BridgeHubRococoBaseFeeInRocs::get(),
XcmBridgeHubRouterBaseFee::get(),
).into())
)
];
@@ -966,7 +986,7 @@ pub mod bridging {
// base delivery fee to local `BridgeHub`
Some((
XcmBridgeHubRouterFeeAssetId::get(),
bp_asset_hub_wococo::BridgeHubWococoBaseFeeInWocs::get(),
XcmBridgeHubRouterBaseFee::get(),
).into())
)
];
@@ -84,6 +84,7 @@ assets-common = { path = "../common", default-features = false }
pallet-xcm-bridge-hub-router = { path = "../../../../../bridges/modules/xcm-bridge-hub-router", default-features = false }
bp-asset-hub-rococo = { path = "../../../../../bridges/primitives/chain-asset-hub-rococo", default-features = false }
bp-asset-hub-westend = { path = "../../../../../bridges/primitives/chain-asset-hub-westend", default-features = false }
bp-bridge-hub-rococo = { path = "../../../../../bridges/primitives/chain-bridge-hub-rococo", default-features = false }
bp-bridge-hub-westend = { path = "../../../../../bridges/primitives/chain-bridge-hub-westend", default-features = false }
[dev-dependencies]
@@ -167,6 +168,7 @@ std = [
"assets-common/std",
"bp-asset-hub-rococo/std",
"bp-asset-hub-westend/std",
"bp-bridge-hub-rococo/std",
"bp-bridge-hub-westend/std",
"codec/std",
"cumulus-pallet-aura-ext/std",
@@ -262,7 +262,10 @@ impl Contains<RuntimeCall> for SafeCallFilter {
// Allow to change dedicated storage items (called by governance-like)
match call {
RuntimeCall::System(frame_system::Call::set_storage { items })
if items.iter().all(|(k, _)| k.eq(&bridging::XcmBridgeHubRouterByteFee::key())) =>
if items.iter().all(|(k, _)| k.eq(&bridging::XcmBridgeHubRouterByteFee::key())) ||
items
.iter()
.all(|(k, _)| k.eq(&bridging::XcmBridgeHubRouterBaseFee::key())) =>
return true,
_ => (),
};
@@ -725,13 +728,30 @@ pub mod bridging {
use sp_std::collections::btree_set::BTreeSet;
parameter_types! {
/// Base price of every byte of the Westend -> Rococo message. Can be adjusted via
/// governance `set_storage` call.
///
/// Default value is our estimation of the:
///
/// 1) an approximate cost of XCM execution (`ExportMessage` and surroundings) at Westend bridge hub;
///
/// 2) the approximate cost of Westend -> Rococo message delivery transaction on Rococo Bridge Hub,
/// converted into WNDs using 1:1 conversion rate;
///
/// 3) the approximate cost of Westend -> Rococo message confirmation transaction on Westend Bridge Hub.
pub storage XcmBridgeHubRouterBaseFee: Balance =
bp_bridge_hub_westend::BridgeHubWestendBaseXcmFeeInWnds::get()
.saturating_add(bp_bridge_hub_rococo::BridgeHubRococoBaseDeliveryFeeInRocs::get())
.saturating_add(bp_bridge_hub_westend::BridgeHubWestendBaseConfirmationFeeInWnds::get());
/// Price of every byte of the Westend -> Rococo message. Can be adjusted via
/// governance `set_storage` call.
pub storage XcmBridgeHubRouterByteFee: Balance = TransactionByteFee::get();
pub SiblingBridgeHubParaId: u32 = bp_bridge_hub_westend::BRIDGE_HUB_WESTEND_PARACHAIN_ID;
pub SiblingBridgeHub: MultiLocation = MultiLocation::new(1, X1(Parachain(SiblingBridgeHubParaId::get())));
/// Router expects payment with this `AssetId`.
/// (`AssetId` has to be aligned with `BridgeTable`)
pub XcmBridgeHubRouterFeeAssetId: AssetId = WestendLocation::get().into();
/// Price per byte - can be adjusted via governance `set_storage` call.
pub storage XcmBridgeHubRouterByteFee: Balance = TransactionByteFee::get();
pub BridgeTable: sp_std::vec::Vec<NetworkExportTableItem> =
sp_std::vec::Vec::new().into_iter()
@@ -774,7 +794,7 @@ pub mod bridging {
// base delivery fee to local `BridgeHub`
Some((
XcmBridgeHubRouterFeeAssetId::get(),
bp_asset_hub_westend::BridgeHubWestendBaseFeeInWnds::get(),
XcmBridgeHubRouterBaseFee::get(),
).into())
)
];
@@ -23,10 +23,10 @@ use bridge_hub_rococo_runtime::{
xcm_config::{RelayNetwork, TokenLocation, XcmConfig},
AllPalletsWithoutSystem, BridgeRejectObsoleteHeadersAndMessages, Executive, ExistentialDeposit,
ParachainSystem, PolkadotXcm, Runtime, RuntimeCall, RuntimeEvent, SessionKeys, SignedExtra,
UncheckedExtrinsic,
TransactionPayment, UncheckedExtrinsic,
};
use codec::{Decode, Encode};
use frame_support::parameter_types;
use frame_support::{dispatch::GetDispatchInfo, parameter_types};
use frame_system::pallet_prelude::HeaderFor;
use parachains_common::{rococo::fee::WeightToFee, AccountId, AuraId, Balance};
use sp_keyring::AccountKeyring::Alice;
@@ -83,6 +83,13 @@ fn construct_and_apply_extrinsic(
r.unwrap()
}
fn construct_and_estimate_extrinsic_fee(batch: pallet_utility::Call<Runtime>) -> Balance {
let batch_call = RuntimeCall::Utility(batch);
let batch_info = batch_call.get_dispatch_info();
let xt = construct_extrinsic(Alice, batch_call);
TransactionPayment::compute_fee(xt.encoded_size() as _, &batch_info, 0)
}
fn executive_init_block(header: &HeaderFor<Runtime>) {
Executive::initialize_block(header)
}
@@ -213,7 +220,7 @@ mod bridge_hub_rococo_tests {
XCM_LANE_FOR_ASSET_HUB_ROCOCO_TO_ASSET_HUB_WOCOCO,
Some((TokenLocation::get(), ExistentialDeposit::get()).into()),
// value should be >= than value generated by `can_calculate_weight_for_paid_export_message_with_reserve_transfer`
Some((TokenLocation::get(), bp_asset_hub_rococo::BridgeHubRococoBaseFeeInRocs::get()).into()),
Some((TokenLocation::get(), bp_bridge_hub_rococo::BridgeHubRococoBaseXcmFeeInRocs::get()).into()),
|| (),
);
// for Westend
@@ -235,7 +242,7 @@ mod bridge_hub_rococo_tests {
XCM_LANE_FOR_ASSET_HUB_ROCOCO_TO_ASSET_HUB_WESTEND,
Some((TokenLocation::get(), ExistentialDeposit::get()).into()),
// value should be >= than value generated by `can_calculate_weight_for_paid_export_message_with_reserve_transfer`
Some((TokenLocation::get(), bp_asset_hub_rococo::BridgeHubRococoBaseFeeInRocs::get()).into()),
Some((TokenLocation::get(), bp_bridge_hub_rococo::BridgeHubRococoBaseXcmFeeInRocs::get()).into()),
|| (),
)
}
@@ -401,10 +408,56 @@ mod bridge_hub_rococo_tests {
>();
// check if estimated value is sane
let max_expected = bp_asset_hub_rococo::BridgeHubRococoBaseFeeInRocs::get();
let max_expected = bp_bridge_hub_rococo::BridgeHubRococoBaseXcmFeeInRocs::get();
assert!(
estimated <= max_expected,
"calculated: {:?}, max_expected: {:?}, please adjust `bp_asset_hub_rococo::BridgeHubRococoBaseFeeInRocs` value",
"calculated: {:?}, max_expected: {:?}, please adjust `bp_bridge_hub_rococo::BridgeHubRococoBaseXcmFeeInRocs` value",
estimated,
max_expected
);
}
#[test]
pub fn can_calculate_fee_for_complex_message_delivery_transaction() {
let estimated = bridge_hub_test_utils::test_cases::can_calculate_fee_for_complex_message_delivery_transaction::<
Runtime,
BridgeGrandpaWestendInstance,
BridgeParachainWestendInstance,
WithBridgeHubWestendMessagesInstance,
WithBridgeHubWestendMessageBridge,
>(
collator_session_keys(),
construct_and_estimate_extrinsic_fee
);
// check if estimated value is sane
let max_expected = bp_bridge_hub_rococo::BridgeHubRococoBaseDeliveryFeeInRocs::get();
assert!(
estimated <= max_expected,
"calculated: {:?}, max_expected: {:?}, please adjust `bp_bridge_hub_rococo::BridgeHubRococoBaseDeliveryFeeInRocs` value",
estimated,
max_expected
);
}
#[test]
pub fn can_calculate_fee_for_complex_message_confirmation_transaction() {
let estimated = bridge_hub_test_utils::test_cases::can_calculate_fee_for_complex_message_confirmation_transaction::<
Runtime,
BridgeGrandpaWestendInstance,
BridgeParachainWestendInstance,
WithBridgeHubWestendMessagesInstance,
WithBridgeHubWestendMessageBridge,
>(
collator_session_keys(),
construct_and_estimate_extrinsic_fee
);
// check if estimated value is sane
let max_expected = bp_bridge_hub_rococo::BridgeHubRococoBaseConfirmationFeeInRocs::get();
assert!(
estimated <= max_expected,
"calculated: {:?}, max_expected: {:?}, please adjust `bp_bridge_hub_rococo::BridgeHubRococoBaseConfirmationFeeInRocs` value",
estimated,
max_expected
);
@@ -540,7 +593,7 @@ mod bridge_hub_wococo_tests {
XCM_LANE_FOR_ASSET_HUB_WOCOCO_TO_ASSET_HUB_ROCOCO,
Some((TokenLocation::get(), ExistentialDeposit::get()).into()),
// value should be >= than value generated by `can_calculate_weight_for_paid_export_message_with_reserve_transfer`
Some((TokenLocation::get(), bp_asset_hub_wococo::BridgeHubWococoBaseFeeInWocs::get()).into()),
Some((TokenLocation::get(), bp_bridge_hub_wococo::BridgeHubWococoBaseXcmFeeInWocs::get()).into()),
set_wococo_flavor,
)
}
@@ -633,10 +686,56 @@ mod bridge_hub_wococo_tests {
>();
// check if estimated value is sane
let max_expected = bp_asset_hub_wococo::BridgeHubWococoBaseFeeInWocs::get();
let max_expected = bp_bridge_hub_wococo::BridgeHubWococoBaseXcmFeeInWocs::get();
assert!(
estimated <= max_expected,
"calculated: {:?}, max_expected: {:?}, please adjust `bp_asset_hub_wococo::BridgeHubWococoBaseFeeInWocs` value",
"calculated: {:?}, max_expected: {:?}, please adjust `bp_bridge_hub_wococo::BridgeHubWococoBaseXcmFeeInWocs` value",
estimated,
max_expected
);
}
#[test]
pub fn can_calculate_fee_for_complex_message_delivery_transaction() {
let estimated = bridge_hub_test_utils::test_cases::can_calculate_fee_for_complex_message_delivery_transaction::<
Runtime,
BridgeGrandpaRococoInstance,
BridgeParachainRococoInstance,
WithBridgeHubRococoMessagesInstance,
WithBridgeHubRococoMessageBridge,
>(
collator_session_keys(),
construct_and_estimate_extrinsic_fee
);
// check if estimated value is sane
let max_expected = bp_bridge_hub_wococo::BridgeHubWococoBaseDeliveryFeeInWocs::get();
assert!(
estimated <= max_expected,
"calculated: {:?}, max_expected: {:?}, please adjust `bp_bridge_hub_wococo::BridgeHubWococoBaseDeliveryFeeInWocs` value",
estimated,
max_expected
);
}
#[test]
pub fn can_calculate_fee_for_complex_message_confirmation_transaction() {
let estimated = bridge_hub_test_utils::test_cases::can_calculate_fee_for_complex_message_confirmation_transaction::<
Runtime,
BridgeGrandpaRococoInstance,
BridgeParachainRococoInstance,
WithBridgeHubRococoMessagesInstance,
WithBridgeHubRococoMessageBridge,
>(
collator_session_keys(),
construct_and_estimate_extrinsic_fee
);
// check if estimated value is sane
let max_expected = bp_bridge_hub_wococo::BridgeHubWococoBaseConfirmationFeeInWocs::get();
assert!(
estimated <= max_expected,
"calculated: {:?}, max_expected: {:?}, please adjust `bp_bridge_hub_wococo::BridgeHubWococoBaseConfirmationFeeInWocs` value",
estimated,
max_expected
);
@@ -23,7 +23,7 @@ use bridge_hub_westend_runtime::{
xcm_config::{RelayNetwork, WestendLocation, XcmConfig},
AllPalletsWithoutSystem, BridgeRejectObsoleteHeadersAndMessages, Executive, ExistentialDeposit,
ParachainSystem, PolkadotXcm, Runtime, RuntimeCall, RuntimeEvent, SessionKeys, SignedExtra,
UncheckedExtrinsic,
TransactionPayment, UncheckedExtrinsic,
};
use bridge_to_rococo_config::{
BridgeGrandpaRococoInstance, BridgeHubRococoChainId, BridgeParachainRococoInstance,
@@ -31,7 +31,7 @@ use bridge_to_rococo_config::{
XCM_LANE_FOR_ASSET_HUB_WESTEND_TO_ASSET_HUB_ROCOCO,
};
use codec::{Decode, Encode};
use frame_support::parameter_types;
use frame_support::{dispatch::GetDispatchInfo, parameter_types};
use frame_system::pallet_prelude::HeaderFor;
use parachains_common::{westend::fee::WeightToFee, AccountId, AuraId, Balance};
use sp_keyring::AccountKeyring::Alice;
@@ -84,6 +84,13 @@ fn construct_and_apply_extrinsic(
r.unwrap()
}
fn construct_and_estimate_extrinsic_fee(batch: pallet_utility::Call<Runtime>) -> Balance {
let batch_call = RuntimeCall::Utility(batch);
let batch_info = batch_call.get_dispatch_info();
let xt = construct_extrinsic(Alice, batch_call);
TransactionPayment::compute_fee(xt.encoded_size() as _, &batch_info, 0)
}
fn executive_init_block(header: &HeaderFor<Runtime>) {
Executive::initialize_block(header)
}
@@ -182,7 +189,7 @@ fn handle_export_message_from_system_parachain_add_to_outbound_queue_works() {
XCM_LANE_FOR_ASSET_HUB_WESTEND_TO_ASSET_HUB_ROCOCO,
Some((WestendLocation::get(), ExistentialDeposit::get()).into()),
// value should be >= than value generated by `can_calculate_weight_for_paid_export_message_with_reserve_transfer`
Some((WestendLocation::get(), bp_asset_hub_westend::BridgeHubWestendBaseFeeInWnds::get()).into()),
Some((WestendLocation::get(), bp_bridge_hub_westend::BridgeHubWestendBaseXcmFeeInWnds::get()).into()),
|| (),
)
}
@@ -275,11 +282,57 @@ pub fn can_calculate_weight_for_paid_export_message_with_reserve_transfer() {
>();
// check if estimated value is sane
let max_expected = bp_asset_hub_westend::BridgeHubWestendBaseFeeInWnds::get();
let max_expected = bp_bridge_hub_westend::BridgeHubWestendBaseXcmFeeInWnds::get();
assert!(
estimated <= max_expected,
"calculated: {:?}, max_expected: {:?}, please adjust `bp_asset_hub_westend::BridgeHubWestendBaseFeeInWnds` value",
"calculated: {:?}, max_expected: {:?}, please adjust `bp_bridge_hub_westend::BridgeHubWestendBaseXcmFeeInWnds` value",
estimated,
max_expected
);
}
#[test]
pub fn can_calculate_fee_for_complex_message_delivery_transaction() {
let estimated = bridge_hub_test_utils::test_cases::can_calculate_fee_for_complex_message_delivery_transaction::<
Runtime,
BridgeGrandpaRococoInstance,
BridgeParachainRococoInstance,
WithBridgeHubRococoMessagesInstance,
WithBridgeHubRococoMessageBridge,
>(
collator_session_keys(),
construct_and_estimate_extrinsic_fee
);
// check if estimated value is sane
let max_expected = bp_bridge_hub_westend::BridgeHubWestendBaseDeliveryFeeInWnds::get();
assert!(
estimated <= max_expected,
"calculated: {:?}, max_expected: {:?}, please adjust `bp_bridge_hub_westend::BridgeHubWestendBaseDeliveryFeeInWnds` value",
estimated,
max_expected
);
}
#[test]
pub fn can_calculate_fee_for_complex_message_confirmation_transaction() {
let estimated = bridge_hub_test_utils::test_cases::can_calculate_fee_for_complex_message_confirmation_transaction::<
Runtime,
BridgeGrandpaRococoInstance,
BridgeParachainRococoInstance,
WithBridgeHubRococoMessagesInstance,
WithBridgeHubRococoMessageBridge,
>(
collator_session_keys(),
construct_and_estimate_extrinsic_fee
);
// check if estimated value is sane
let max_expected = bp_bridge_hub_westend::BridgeHubWestendBaseConfirmationFeeInWnds::get();
assert!(
estimated <= max_expected,
"calculated: {:?}, max_expected: {:?}, please adjust `bp_bridge_hub_westend::BridgeHubWestendBaseConfirmationFeeInWnds` value",
estimated,
max_expected
);
}
@@ -17,8 +17,9 @@
//! Module contains predefined test-case scenarios for `Runtime` with bridging capabilities.
use bp_messages::{
source_chain::TargetHeaderChain,
target_chain::{DispatchMessage, DispatchMessageData, MessageDispatch, SourceHeaderChain},
LaneId, MessageKey, OutboundLaneData, Weight,
LaneId, MessageKey, OutboundLaneData, UnrewardedRelayersState, Weight,
};
use bp_parachains::{BestParaHeadHash, ParaInfo};
use bp_polkadot_core::parachains::{ParaHash, ParaId};
@@ -27,9 +28,13 @@ use bp_runtime::{HeaderOf, Parachain, StorageProofSize, UnderlyingChainOf};
use bp_test_utils::{make_default_justification, prepare_parachain_heads_proof};
use bridge_runtime_common::{
messages::{
target::FromBridgedChainMessagesProof, BridgedChain as MessageBridgedChain, MessageBridge,
source::FromBridgedChainMessagesDeliveryProof, target::FromBridgedChainMessagesProof,
BridgedChain as MessageBridgedChain, MessageBridge,
},
messages_generation::{
encode_all_messages, encode_lane_data, prepare_message_delivery_storage_proof,
prepare_messages_storage_proof,
},
messages_generation::{encode_all_messages, encode_lane_data, prepare_messages_storage_proof},
messages_xcm_extension::{XcmAsPlainPayload, XcmBlobMessageDispatchResult},
};
use codec::Encode;
@@ -399,6 +404,7 @@ pub fn relayed_incoming_message_works<Runtime, AllPalletsWithoutSystem, XcmConfi
MPI: 'static,
MB: MessageBridge,
<MB as MessageBridge>::BridgedChain: Send + Sync + 'static,
<MB as MessageBridge>::ThisChain: Send + Sync + 'static,
UnderlyingChainOf<MessageBridgedChain<MB>>: bp_runtime::Chain<Hash = ParaHash> + Parachain,
XcmConfig: xcm_executor::Config,
HrmpChannelOpener: frame_support::inherent::ProvideInherent<
@@ -484,7 +490,11 @@ pub fn relayed_incoming_message_works<Runtime, AllPalletsWithoutSystem, XcmConfi
parachain_heads,
para_heads_proof,
message_proof,
) = test_data::make_complex_relayer_proofs::<BridgedHeader<Runtime, GPI>, MB, ()>(
) = test_data::make_complex_relayer_delivery_proofs::<
<Runtime as pallet_bridge_grandpa::Config<GPI>>::BridgedChain,
MB,
(),
>(
lane_id,
xcm.into(),
message_nonce,
@@ -626,6 +636,7 @@ pub fn complex_relay_extrinsic_works<Runtime, AllPalletsWithoutSystem, XcmConfig
MPI: 'static,
MB: MessageBridge,
<MB as MessageBridge>::BridgedChain: Send + Sync + 'static,
<MB as MessageBridge>::ThisChain: Send + Sync + 'static,
UnderlyingChainOf<MessageBridgedChain<MB>>: bp_runtime::Chain<Hash = ParaHash> + Parachain,
XcmConfig: xcm_executor::Config,
HrmpChannelOpener: frame_support::inherent::ProvideInherent<
@@ -725,7 +736,11 @@ pub fn complex_relay_extrinsic_works<Runtime, AllPalletsWithoutSystem, XcmConfig
parachain_heads,
para_heads_proof,
message_proof,
) = test_data::make_complex_relayer_proofs::<BridgedHeader<Runtime, GPI>, MB, ()>(
) = test_data::make_complex_relayer_delivery_proofs::<
<Runtime as pallet_bridge_grandpa::Config<GPI>>::BridgedChain,
MB,
(),
>(
lane_id,
xcm.clone().into(),
message_nonce,
@@ -735,27 +750,15 @@ pub fn complex_relay_extrinsic_works<Runtime, AllPalletsWithoutSystem, XcmConfig
bridged_para_id,
);
let submit_grandpa =
pallet_bridge_grandpa::Call::<Runtime, GPI>::submit_finality_proof {
finality_target: Box::new(relay_chain_header.clone()),
justification: grandpa_justification,
};
let submit_para_head =
pallet_bridge_parachains::Call::<Runtime, PPI>::submit_parachain_heads {
at_relay_block: (relay_header_number, relay_chain_header.hash().into()),
parachains: parachain_heads,
parachain_heads_proof: para_heads_proof,
};
let submit_message =
pallet_bridge_messages::Call::<Runtime, MPI>::receive_messages_proof {
relayer_id_at_bridged_chain: relayer_id_on_source.into(),
proof: message_proof.into(),
messages_count: 1,
dispatch_weight: Weight::from_parts(1000000000, 0),
};
let batch = pallet_utility::Call::<Runtime>::batch_all {
calls: vec![submit_grandpa.into(), submit_para_head.into(), submit_message.into()],
};
let relay_chain_header_hash = relay_chain_header.hash();
let batch = test_data::make_complex_relayer_delivery_batch::<Runtime, GPI, PPI, MPI>(
relay_chain_header,
grandpa_justification,
parachain_heads,
para_heads_proof,
message_proof,
relayer_id_on_source,
);
// sanity checks - before relayer extrinsic
assert!(RuntimeHelper::<cumulus_pallet_xcmp_queue::Pallet<Runtime>>::take_xcm(
@@ -790,10 +793,10 @@ pub fn complex_relay_extrinsic_works<Runtime, AllPalletsWithoutSystem, XcmConfig
assert_ok!(dispatch_outcome);
assert_eq!(
<pallet_bridge_grandpa::BestFinalized<Runtime, GPI>>::get().unwrap().1,
relay_chain_header.hash()
relay_chain_header_hash
);
assert!(<pallet_bridge_grandpa::ImportedHeaders<Runtime, GPI>>::contains_key(
relay_chain_header.hash()
relay_chain_header_hash
));
// verify parachain head proof correctly imported
assert_eq!(
@@ -839,7 +842,7 @@ pub fn complex_relay_extrinsic_works<Runtime, AllPalletsWithoutSystem, XcmConfig
})
}
/// Estimates fee for paid `ExportMessage` processing.
/// Estimates XCM execution fee for paid `ExportMessage` processing.
pub fn can_calculate_weight_for_paid_export_message_with_reserve_transfer<
Runtime,
XcmConfig,
@@ -945,13 +948,208 @@ where
estimated_fee.into()
}
/// Estimates transaction fee for default message delivery transaction (batched with required
/// proofs) from bridged parachain.
pub fn can_calculate_fee_for_complex_message_delivery_transaction<Runtime, GPI, PPI, MPI, MB>(
collator_session_key: CollatorSessionKeys<Runtime>,
compute_extrinsic_fee: fn(pallet_utility::Call::<Runtime>) -> u128,
) -> u128
where
Runtime: frame_system::Config
+ pallet_balances::Config
+ pallet_session::Config
+ pallet_xcm::Config
+ parachain_info::Config
+ pallet_collator_selection::Config
+ cumulus_pallet_parachain_system::Config
+ pallet_bridge_grandpa::Config<GPI>
+ pallet_bridge_parachains::Config<PPI>
+ pallet_bridge_messages::Config<MPI, InboundPayload = XcmAsPlainPayload>
+ pallet_utility::Config,
GPI: 'static,
PPI: 'static,
MPI: 'static,
MB: MessageBridge,
<MB as MessageBridge>::BridgedChain: Send + Sync + 'static,
<MB as MessageBridge>::ThisChain: Send + Sync + 'static,
UnderlyingChainOf<MessageBridgedChain<MB>>: bp_runtime::Chain<Hash = ParaHash> + Parachain,
ValidatorIdOf<Runtime>: From<AccountIdOf<Runtime>>,
<<Runtime as pallet_bridge_messages::Config<MPI>>::SourceHeaderChain as SourceHeaderChain>::MessagesProof:
From<FromBridgedChainMessagesProof<ParaHash>>,
<<Runtime as pallet_bridge_grandpa::Config<GPI>>::BridgedChain as bp_runtime::Chain>::Hash: From<ParaHash>,
ParaHash: From<<<Runtime as pallet_bridge_grandpa::Config<GPI>>::BridgedChain as bp_runtime::Chain>::Hash>,
<Runtime as frame_system::Config>::AccountId:
Into<<<Runtime as frame_system::Config>::RuntimeOrigin as OriginTrait>::AccountId>,
<Runtime as frame_system::Config>::AccountId: From<AccountId32>,
AccountIdOf<Runtime>: From<sp_core::sr25519::Public>,
<Runtime as pallet_bridge_messages::Config<MPI>>::InboundRelayer: From<AccountId32>,
<Runtime as pallet_utility::Config>::RuntimeCall:
From<pallet_bridge_grandpa::Call<Runtime, GPI>>
+ From<pallet_bridge_parachains::Call<Runtime, PPI>>
+ From<pallet_bridge_messages::Call<Runtime, MPI>>,
{
ExtBuilder::<Runtime>::default()
.with_collators(collator_session_key.collators())
.with_session_keys(collator_session_key.session_keys())
.with_safe_xcm_version(XCM_VERSION)
.with_para_id(1000.into())
.with_tracing()
.build()
.execute_with(|| {
// generate bridged relay chain finality, parachain heads and message proofs,
// to be submitted by relayer to this chain.
//
// we don't care about parameter values here, apart from the XCM message size. But we
// do not need to have a large message here, because we're charging for every byte of
// the message additionally
let (
relay_chain_header,
grandpa_justification,
_,
parachain_heads,
para_heads_proof,
message_proof,
) = test_data::make_complex_relayer_delivery_proofs::<
<Runtime as pallet_bridge_grandpa::Config<GPI>>::BridgedChain,
MB,
(),
>(
LaneId::default(),
vec![xcm::v3::Instruction::<()>::ClearOrigin; 1_024].into(),
1,
X2(GlobalConsensus(Polkadot), Parachain(1_000)),
1,
5,
1_000,
);
// generate batch call that provides finality for bridged relay and parachains + message
// proof
let batch = test_data::make_complex_relayer_delivery_batch::<Runtime, GPI, PPI, MPI>(
relay_chain_header,
grandpa_justification,
parachain_heads,
para_heads_proof,
message_proof,
Dave.public().into(),
);
let estimated_fee = compute_extrinsic_fee(batch);
log::error!(
target: "bridges::estimate",
"Estimate fee: {:?} for single message delivery for runtime: {:?}",
estimated_fee,
Runtime::Version::get(),
);
estimated_fee
})
}
/// Estimates transaction fee for default message confirmation transaction (batched with required
/// proofs) from bridged parachain.
pub fn can_calculate_fee_for_complex_message_confirmation_transaction<Runtime, GPI, PPI, MPI, MB>(
collator_session_key: CollatorSessionKeys<Runtime>,
compute_extrinsic_fee: fn(pallet_utility::Call::<Runtime>) -> u128,
) -> u128
where
Runtime: frame_system::Config
+ pallet_balances::Config
+ pallet_session::Config
+ pallet_xcm::Config
+ parachain_info::Config
+ pallet_collator_selection::Config
+ cumulus_pallet_parachain_system::Config
+ pallet_bridge_grandpa::Config<GPI>
+ pallet_bridge_parachains::Config<PPI>
+ pallet_bridge_messages::Config<MPI, OutboundPayload = XcmAsPlainPayload>
+ pallet_utility::Config,
GPI: 'static,
PPI: 'static,
MPI: 'static,
MB: MessageBridge,
<MB as MessageBridge>::BridgedChain: Send + Sync + 'static,
<MB as MessageBridge>::ThisChain: Send + Sync + 'static,
<<MB as MessageBridge>::ThisChain as bp_runtime::Chain>::AccountId: From<AccountId32>,
UnderlyingChainOf<MessageBridgedChain<MB>>: bp_runtime::Chain<Hash = ParaHash> + Parachain,
ValidatorIdOf<Runtime>: From<AccountIdOf<Runtime>>,
<<Runtime as pallet_bridge_messages::Config<MPI>>::SourceHeaderChain as SourceHeaderChain>::MessagesProof:
From<FromBridgedChainMessagesProof<ParaHash>>,
<<Runtime as pallet_bridge_grandpa::Config<GPI>>::BridgedChain as bp_runtime::Chain>::Hash: From<ParaHash>,
ParaHash: From<<<Runtime as pallet_bridge_grandpa::Config<GPI>>::BridgedChain as bp_runtime::Chain>::Hash>,
<Runtime as frame_system::Config>::AccountId:
Into<<<Runtime as frame_system::Config>::RuntimeOrigin as OriginTrait>::AccountId>,
<Runtime as frame_system::Config>::AccountId: From<AccountId32>,
AccountIdOf<Runtime>: From<sp_core::sr25519::Public>,
<Runtime as pallet_bridge_messages::Config<MPI>>::InboundRelayer: From<AccountId32>,
<<Runtime as pallet_bridge_messages::Config<MPI>>::TargetHeaderChain as TargetHeaderChain<
XcmAsPlainPayload,
Runtime::AccountId,
>>::MessagesDeliveryProof: From<FromBridgedChainMessagesDeliveryProof<ParaHash>>,
<Runtime as pallet_utility::Config>::RuntimeCall:
From<pallet_bridge_grandpa::Call<Runtime, GPI>>
+ From<pallet_bridge_parachains::Call<Runtime, PPI>>
+ From<pallet_bridge_messages::Call<Runtime, MPI>>,
{
ExtBuilder::<Runtime>::default()
.with_collators(collator_session_key.collators())
.with_session_keys(collator_session_key.session_keys())
.with_safe_xcm_version(XCM_VERSION)
.with_para_id(1000.into())
.with_tracing()
.build()
.execute_with(|| {
// generate bridged relay chain finality, parachain heads and message proofs,
// to be submitted by relayer to this chain.
let unrewarded_relayers = UnrewardedRelayersState {
unrewarded_relayer_entries: 1,
total_messages: 1,
..Default::default()
};
let (
relay_chain_header,
grandpa_justification,
_,
parachain_heads,
para_heads_proof,
message_delivery_proof,
) = test_data::make_complex_relayer_confirmation_proofs::<
<Runtime as pallet_bridge_grandpa::Config<GPI>>::BridgedChain,
MB,
(),
>(LaneId::default(), 1, 5, 1_000, Alice.public().into(), unrewarded_relayers.clone());
// generate batch call that provides finality for bridged relay and parachains + message
// proof
let batch = test_data::make_complex_relayer_confirmation_batch::<Runtime, GPI, PPI, MPI>(
relay_chain_header,
grandpa_justification,
parachain_heads,
para_heads_proof,
message_delivery_proof,
unrewarded_relayers,
);
let estimated_fee = compute_extrinsic_fee(batch);
log::error!(
target: "bridges::estimate",
"Estimate fee: {:?} for single message confirmation for runtime: {:?}",
estimated_fee,
Runtime::Version::get(),
);
estimated_fee
})
}
pub mod test_data {
use super::*;
use bp_header_chain::justification::GrandpaJustification;
use bp_messages::MessageNonce;
use bp_header_chain::{justification::GrandpaJustification, ChainWithGrandpa};
use bp_messages::{DeliveredMessages, InboundLaneData, MessageNonce, UnrewardedRelayer};
use bp_polkadot_core::parachains::{ParaHash, ParaHead, ParaHeadsProof, ParaId};
use bp_runtime::BasicOperatingMode;
use bp_runtime::{BasicOperatingMode, HashOf};
use bp_test_utils::authority_list;
use sp_runtime::{DigestItem, SaturatedConversion};
use xcm_builder::{HaulBlob, HaulBlobError, HaulBlobExporter};
use xcm_executor::traits::{validate_export, ExportXcm};
@@ -968,7 +1166,117 @@ pub mod test_data {
(location, xcm).encode().encode()
}
pub fn make_complex_relayer_proofs<BridgedRelayHeader, MB, InnerXcmRuntimeCall>(
/// Prepare a batch call with relay finality proof, parachain head proof and message proof.
pub fn make_complex_relayer_delivery_batch<Runtime, GPI, PPI, MPI>(
relay_chain_header: BridgedHeader<Runtime, GPI>,
grandpa_justification: GrandpaJustification<BridgedHeader<Runtime, GPI>>,
parachain_heads: Vec<(ParaId, ParaHash)>,
para_heads_proof: ParaHeadsProof,
message_proof: FromBridgedChainMessagesProof<ParaHash>,
relayer_id_at_bridged_chain: AccountId32,
) -> pallet_utility::Call<Runtime> where
Runtime:pallet_bridge_grandpa::Config<GPI>
+ pallet_bridge_parachains::Config<PPI>
+ pallet_bridge_messages::Config<MPI, InboundPayload = XcmAsPlainPayload>
+ pallet_utility::Config,
GPI: 'static,
PPI: 'static,
MPI: 'static,
ParaHash: From<<<Runtime as pallet_bridge_grandpa::Config<GPI>>::BridgedChain as bp_runtime::Chain>::Hash>,
<<Runtime as pallet_bridge_grandpa::Config<GPI>>::BridgedChain as bp_runtime::Chain>::Hash: From<ParaHash>,
<<Runtime as pallet_bridge_messages::Config<MPI>>::SourceHeaderChain as SourceHeaderChain>::MessagesProof:
From<FromBridgedChainMessagesProof<ParaHash>>,
<Runtime as pallet_bridge_messages::Config<MPI>>::InboundRelayer: From<AccountId32>,
<Runtime as pallet_utility::Config>::RuntimeCall:
From<pallet_bridge_grandpa::Call<Runtime, GPI>>
+ From<pallet_bridge_parachains::Call<Runtime, PPI>>
+ From<pallet_bridge_messages::Call<Runtime, MPI>>,
{
let relay_chain_header_hash = relay_chain_header.hash();
let relay_chain_header_number = *relay_chain_header.number();
let submit_grandpa = pallet_bridge_grandpa::Call::<Runtime, GPI>::submit_finality_proof {
finality_target: Box::new(relay_chain_header),
justification: grandpa_justification,
};
let submit_para_head =
pallet_bridge_parachains::Call::<Runtime, PPI>::submit_parachain_heads {
at_relay_block: (
relay_chain_header_number.saturated_into(),
relay_chain_header_hash.into(),
),
parachains: parachain_heads,
parachain_heads_proof: para_heads_proof,
};
let submit_message = pallet_bridge_messages::Call::<Runtime, MPI>::receive_messages_proof {
relayer_id_at_bridged_chain: relayer_id_at_bridged_chain.into(),
proof: message_proof.into(),
messages_count: 1,
dispatch_weight: Weight::from_parts(1000000000, 0),
};
pallet_utility::Call::<Runtime>::batch_all {
calls: vec![submit_grandpa.into(), submit_para_head.into(), submit_message.into()],
}
}
/// Prepare a batch call with relay finality proof, parachain head proof and message delivery
/// proof.
pub fn make_complex_relayer_confirmation_batch<Runtime, GPI, PPI, MPI>(
relay_chain_header: BridgedHeader<Runtime, GPI>,
grandpa_justification: GrandpaJustification<BridgedHeader<Runtime, GPI>>,
parachain_heads: Vec<(ParaId, ParaHash)>,
para_heads_proof: ParaHeadsProof,
message_delivery_proof: FromBridgedChainMessagesDeliveryProof<ParaHash>,
relayers_state: UnrewardedRelayersState,
) -> pallet_utility::Call<Runtime> where
Runtime:pallet_bridge_grandpa::Config<GPI>
+ pallet_bridge_parachains::Config<PPI>
+ pallet_bridge_messages::Config<MPI, OutboundPayload = XcmAsPlainPayload>
+ pallet_utility::Config,
GPI: 'static,
PPI: 'static,
MPI: 'static,
ParaHash: From<<<Runtime as pallet_bridge_grandpa::Config<GPI>>::BridgedChain as bp_runtime::Chain>::Hash>,
<<Runtime as pallet_bridge_grandpa::Config<GPI>>::BridgedChain as bp_runtime::Chain>::Hash: From<ParaHash>,
<<Runtime as pallet_bridge_messages::Config<MPI>>::TargetHeaderChain as TargetHeaderChain<
XcmAsPlainPayload,
Runtime::AccountId,
>>::MessagesDeliveryProof: From<FromBridgedChainMessagesDeliveryProof<ParaHash>>,
<Runtime as pallet_utility::Config>::RuntimeCall:
From<pallet_bridge_grandpa::Call<Runtime, GPI>>
+ From<pallet_bridge_parachains::Call<Runtime, PPI>>
+ From<pallet_bridge_messages::Call<Runtime, MPI>>,
{
let relay_chain_header_hash = relay_chain_header.hash();
let relay_chain_header_number = *relay_chain_header.number();
let submit_grandpa = pallet_bridge_grandpa::Call::<Runtime, GPI>::submit_finality_proof {
finality_target: Box::new(relay_chain_header),
justification: grandpa_justification,
};
let submit_para_head =
pallet_bridge_parachains::Call::<Runtime, PPI>::submit_parachain_heads {
at_relay_block: (
relay_chain_header_number.saturated_into(),
relay_chain_header_hash.into(),
),
parachains: parachain_heads,
parachain_heads_proof: para_heads_proof,
};
let submit_message_delivery_proof =
pallet_bridge_messages::Call::<Runtime, MPI>::receive_messages_delivery_proof {
proof: message_delivery_proof.into(),
relayers_state,
};
pallet_utility::Call::<Runtime>::batch_all {
calls: vec![
submit_grandpa.into(),
submit_para_head.into(),
submit_message_delivery_proof.into(),
],
}
}
/// Prepare storage proofs of messages, stored at the source chain.
pub fn make_complex_relayer_delivery_proofs<BridgedRelayChain, MB, InnerXcmRuntimeCall>(
lane_id: LaneId,
xcm_message: Xcm<InnerXcmRuntimeCall>,
message_nonce: MessageNonce,
@@ -977,18 +1285,19 @@ pub mod test_data {
relay_header_number: u32,
bridged_para_id: u32,
) -> (
BridgedRelayHeader,
GrandpaJustification<BridgedRelayHeader>,
HeaderOf<BridgedRelayChain>,
GrandpaJustification<HeaderOf<BridgedRelayChain>>,
ParaHead,
Vec<(ParaId, ParaHash)>,
ParaHeadsProof,
FromBridgedChainMessagesProof<ParaHash>,
)
where
BridgedRelayHeader: HeaderT,
<BridgedRelayHeader as HeaderT>::Hash: From<H256>,
BridgedRelayChain: ChainWithGrandpa,
HashOf<BridgedRelayChain>: From<H256>,
MB: MessageBridge,
<MB as MessageBridge>::BridgedChain: Send + Sync + 'static,
<MB as MessageBridge>::ThisChain: Send + Sync + 'static,
UnderlyingChainOf<MessageBridgedChain<MB>>: bp_runtime::Chain<Hash = ParaHash> + Parachain,
{
let message_payload = prepare_inbound_xcm(xcm_message, message_destination);
@@ -1004,6 +1313,129 @@ pub mod test_data {
encode_lane_data,
);
let (
relay_chain_header,
justification,
bridged_para_head,
parachain_heads,
para_heads_proof,
) = make_complex_bridged_heads_proof::<BridgedRelayChain, MB>(
para_state_root,
para_header_number,
relay_header_number,
bridged_para_id,
);
let message_proof = FromBridgedChainMessagesProof {
bridged_header_hash: bridged_para_head.hash(),
storage_proof: para_storage_proof,
lane: lane_id,
nonces_start: message_nonce,
nonces_end: message_nonce,
};
(
relay_chain_header,
justification,
bridged_para_head,
parachain_heads,
para_heads_proof,
message_proof,
)
}
/// Prepare storage proofs of message confirmations, stored at the target chain.
pub fn make_complex_relayer_confirmation_proofs<BridgedRelayChain, MB, InnerXcmRuntimeCall>(
lane_id: LaneId,
para_header_number: u32,
relay_header_number: u32,
bridged_para_id: u32,
relayer_id_at_this_chain: AccountId32,
relayers_state: UnrewardedRelayersState,
) -> (
HeaderOf<BridgedRelayChain>,
GrandpaJustification<HeaderOf<BridgedRelayChain>>,
ParaHead,
Vec<(ParaId, ParaHash)>,
ParaHeadsProof,
FromBridgedChainMessagesDeliveryProof<ParaHash>,
)
where
BridgedRelayChain: ChainWithGrandpa,
HashOf<BridgedRelayChain>: From<H256>,
MB: MessageBridge,
<MB as MessageBridge>::BridgedChain: Send + Sync + 'static,
<MB as MessageBridge>::ThisChain: Send + Sync + 'static,
<<MB as MessageBridge>::ThisChain as bp_runtime::Chain>::AccountId: From<AccountId32>,
UnderlyingChainOf<MessageBridgedChain<MB>>: bp_runtime::Chain<Hash = ParaHash> + Parachain,
{
// prepare para storage proof containing message delivery proof
let (para_state_root, para_storage_proof) = prepare_message_delivery_storage_proof::<MB>(
lane_id,
InboundLaneData {
relayers: vec![
UnrewardedRelayer {
relayer: relayer_id_at_this_chain.into(),
messages: DeliveredMessages::new(1)
};
relayers_state.unrewarded_relayer_entries as usize
]
.into(),
last_confirmed_nonce: 1,
},
StorageProofSize::Minimal(0),
);
let (
relay_chain_header,
justification,
bridged_para_head,
parachain_heads,
para_heads_proof,
) = make_complex_bridged_heads_proof::<BridgedRelayChain, MB>(
para_state_root,
para_header_number,
relay_header_number,
bridged_para_id,
);
let message_delivery_proof = FromBridgedChainMessagesDeliveryProof {
bridged_header_hash: bridged_para_head.hash(),
storage_proof: para_storage_proof,
lane: lane_id,
};
(
relay_chain_header,
justification,
bridged_para_head,
parachain_heads,
para_heads_proof,
message_delivery_proof,
)
}
/// Make bridged parachain header with given state root and relay header that is finalizing it.
pub fn make_complex_bridged_heads_proof<BridgedRelayChain, MB>(
para_state_root: ParaHash,
para_header_number: u32,
relay_header_number: u32,
bridged_para_id: u32,
) -> (
HeaderOf<BridgedRelayChain>,
GrandpaJustification<HeaderOf<BridgedRelayChain>>,
ParaHead,
Vec<(ParaId, ParaHash)>,
ParaHeadsProof,
)
where
BridgedRelayChain: ChainWithGrandpa,
HashOf<BridgedRelayChain>: From<H256>,
MB: MessageBridge,
<MB as MessageBridge>::BridgedChain: Send + Sync + 'static,
<MB as MessageBridge>::ThisChain: Send + Sync + 'static,
UnderlyingChainOf<MessageBridgedChain<MB>>: bp_runtime::Chain<Hash = ParaHash> + Parachain,
{
let bridged_para_head = ParaHead(
bp_test_utils::test_header_with_root::<HeaderOf<MB::BridgedChain>>(
para_header_number.into(),
@@ -1018,28 +1450,26 @@ pub mod test_data {
)]);
assert_eq!(bridged_para_head.hash(), parachain_heads[0].1);
let message_proof = FromBridgedChainMessagesProof {
bridged_header_hash: bridged_para_head.hash(),
storage_proof: para_storage_proof,
lane: lane_id,
nonces_start: message_nonce,
nonces_end: message_nonce,
};
// import bridged relay chain block#1 with state root containing head#5 of bridged parachain
let relay_chain_header: BridgedRelayHeader = bp_test_utils::test_header_with_root(
relay_header_number.into(),
relay_state_root.into(),
);
let mut relay_chain_header: BridgedRelayChain::Header =
bp_test_utils::test_header_with_root(
relay_header_number.into(),
relay_state_root.into(),
);
// to compute proper cost of GRANDPA call, let's add some dummy bytes to header, so that the
// `submit_finality_proof` call size would be close to maximal expected (and refundable)
let expected_bytes_in_grandpa_call = BridgedRelayChain::AVERAGE_HEADER_SIZE_IN_JUSTIFICATION
.saturating_mul(BridgedRelayChain::REASONABLE_HEADERS_IN_JUSTIFICATON_ANCESTRY)
.saturating_add(BridgedRelayChain::MAX_HEADER_SIZE)
as usize;
let extra_bytes_required =
expected_bytes_in_grandpa_call.saturating_sub(relay_chain_header.encoded_size());
relay_chain_header
.digest_mut()
.push(DigestItem::Other(vec![42; extra_bytes_required]));
let justification = make_default_justification(&relay_chain_header);
(
relay_chain_header,
justification,
bridged_para_head,
parachain_heads,
para_heads_proof,
message_proof,
)
(relay_chain_header, justification, bridged_para_head, parachain_heads, para_heads_proof)
}
/// Helper that creates InitializationData mock data, that can be used to initialize bridge