mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-05-30 15:11:02 +00:00
BridgeHub[Rococo/Wococo] test batched relaying of messages and their dispatch (#2578)
Added some tests that aim to cover the runtime configuration that is exercised when BH receives relayed complex message. * checks correct importing of proofs for: bridged chain finality, bridged para heads, bridged messages, * checks relayer extension correctly configured to reward submitting relayer, * checks relayed message is successfully dispatched. Also moved generic test-utils from `asset-test-utils: parachains/runtimes/assets/test-utils` one level up to new crate `parachains-runtimes-test-utils: parachains/runtimes/test-utils` to be reused by BridgeHubs. Signed-off-by: acatangiu <adrian@parity.io> Co-authored-by: Branislav Kontur <bkontur@gmail.com>
This commit is contained in:
@@ -91,6 +91,7 @@ bridge-runtime-common = { path = "../../../../bridges/bin/runtime-common", defau
|
||||
static_assertions = "1.1"
|
||||
bridge-hub-test-utils = { path = "../test-utils"}
|
||||
bridge-runtime-common = { path = "../../../../bridges/bin/runtime-common", features = ["integrity-test"] }
|
||||
sp-keyring = { git = "https://github.com/paritytech/substrate", branch = "master" }
|
||||
|
||||
[features]
|
||||
default = [
|
||||
@@ -119,6 +120,7 @@ std = [
|
||||
"cumulus-primitives-core/std",
|
||||
"cumulus-primitives-timestamp/std",
|
||||
"cumulus-primitives-utility/std",
|
||||
"frame-benchmarking/std",
|
||||
"frame-executive/std",
|
||||
"frame-support/std",
|
||||
"frame-system-rpc-runtime-api/std",
|
||||
|
||||
@@ -122,9 +122,6 @@ pub type SignedExtra = (
|
||||
pub type UncheckedExtrinsic =
|
||||
generic::UncheckedExtrinsic<Address, RuntimeCall, Signature, SignedExtra>;
|
||||
|
||||
/// Extrinsic type that has already been checked.
|
||||
pub type CheckedExtrinsic = generic::CheckedExtrinsic<AccountId, RuntimeCall, SignedExtra>;
|
||||
|
||||
/// Executive: handles dispatch to the various modules.
|
||||
pub type Executive = frame_executive::Executive<
|
||||
Runtime,
|
||||
|
||||
@@ -14,32 +14,94 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Cumulus. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
pub use bridge_hub_rococo_runtime::{
|
||||
#![cfg(test)]
|
||||
|
||||
use bp_polkadot_core::Signature;
|
||||
use bridge_hub_rococo_runtime::{
|
||||
bridge_hub_rococo_config, bridge_hub_wococo_config,
|
||||
constants::fee::WeightToFee,
|
||||
xcm_config::{RelayNetwork, XcmConfig, XcmRouter},
|
||||
Balances, BridgeGrandpaRococoInstance, BridgeGrandpaWococoInstance, BridgeWococoMessages,
|
||||
DeliveryRewardInBalance, ExistentialDeposit, ParachainSystem, PolkadotXcm,
|
||||
RequiredStakeForStakeAndSlash, Runtime, RuntimeCall, RuntimeEvent, SessionKeys,
|
||||
xcm_config::{RelayNetwork, XcmConfig},
|
||||
BridgeRejectObsoleteHeadersAndMessages, DeliveryRewardInBalance, Executive, ExistentialDeposit,
|
||||
ParachainSystem, PolkadotXcm, RequiredStakeForStakeAndSlash, Runtime, RuntimeCall,
|
||||
RuntimeEvent, SessionKeys, SignedExtra, UncheckedExtrinsic,
|
||||
};
|
||||
use codec::{Decode, Encode};
|
||||
use xcm::latest::prelude::*;
|
||||
|
||||
use bridge_hub_rococo_runtime::{
|
||||
bridge_hub_rococo_config, bridge_hub_wococo_config, WithBridgeHubRococoMessagesInstance,
|
||||
WithBridgeHubWococoMessagesInstance,
|
||||
};
|
||||
|
||||
use frame_support::parameter_types;
|
||||
use parachains_common::{AccountId, AuraId, Balance};
|
||||
use sp_keyring::AccountKeyring::Alice;
|
||||
use sp_runtime::{
|
||||
generic::{Era, SignedPayload},
|
||||
AccountId32,
|
||||
};
|
||||
use xcm::latest::prelude::*;
|
||||
|
||||
const ALICE: [u8; 32] = [1u8; 32];
|
||||
// Para id of sibling chain (Rockmine/Wockmint) used in tests.
|
||||
pub const SIBLING_PARACHAIN_ID: u32 = 1000;
|
||||
|
||||
parameter_types! {
|
||||
pub CheckingAccount: AccountId = PolkadotXcm::check_account();
|
||||
}
|
||||
|
||||
fn construct_extrinsic(
|
||||
sender: sp_keyring::AccountKeyring,
|
||||
call: RuntimeCall,
|
||||
) -> UncheckedExtrinsic {
|
||||
let extra: SignedExtra = (
|
||||
frame_system::CheckNonZeroSender::<Runtime>::new(),
|
||||
frame_system::CheckSpecVersion::<Runtime>::new(),
|
||||
frame_system::CheckTxVersion::<Runtime>::new(),
|
||||
frame_system::CheckGenesis::<Runtime>::new(),
|
||||
frame_system::CheckEra::<Runtime>::from(Era::immortal()),
|
||||
frame_system::CheckNonce::<Runtime>::from(0),
|
||||
frame_system::CheckWeight::<Runtime>::new(),
|
||||
pallet_transaction_payment::ChargeTransactionPayment::<Runtime>::from(0),
|
||||
BridgeRejectObsoleteHeadersAndMessages {},
|
||||
(
|
||||
bridge_hub_wococo_config::BridgeRefundBridgeHubRococoMessages::default(),
|
||||
bridge_hub_rococo_config::BridgeRefundBridgeHubWococoMessages::default(),
|
||||
),
|
||||
);
|
||||
let payload = SignedPayload::new(call.clone(), extra.clone()).unwrap();
|
||||
let signature = payload.using_encoded(|e| sender.sign(e));
|
||||
UncheckedExtrinsic::new_signed(
|
||||
call,
|
||||
AccountId32::from(sender.public()).into(),
|
||||
Signature::Sr25519(signature.clone()),
|
||||
extra,
|
||||
)
|
||||
}
|
||||
|
||||
fn construct_and_apply_extrinsic(
|
||||
relayer_at_target: sp_keyring::AccountKeyring,
|
||||
batch: pallet_utility::Call<Runtime>,
|
||||
) -> sp_runtime::DispatchOutcome {
|
||||
let batch_call = RuntimeCall::Utility(batch);
|
||||
let xt = construct_extrinsic(relayer_at_target, batch_call);
|
||||
let r = Executive::apply_extrinsic(xt);
|
||||
r.unwrap()
|
||||
}
|
||||
|
||||
fn executive_init_block(header: &<Runtime as frame_system::Config>::Header) {
|
||||
Executive::initialize_block(header)
|
||||
}
|
||||
|
||||
fn collator_session_keys() -> bridge_hub_test_utils::CollatorSessionKeys<Runtime> {
|
||||
bridge_hub_test_utils::CollatorSessionKeys::new(
|
||||
AccountId::from(Alice),
|
||||
AccountId::from(Alice),
|
||||
SessionKeys { aura: AuraId::from(Alice.public()) },
|
||||
)
|
||||
}
|
||||
|
||||
mod bridge_hub_rococo_tests {
|
||||
use super::*;
|
||||
use bridge_hub_rococo_config::{
|
||||
WithBridgeHubWococoMessageBridge, DEFAULT_XCM_LANE_TO_BRIDGE_HUB_WOCOCO,
|
||||
};
|
||||
use bridge_hub_rococo_runtime::{
|
||||
BridgeGrandpaWococoInstance, BridgeParachainWococoInstance,
|
||||
WithBridgeHubWococoMessagesInstance,
|
||||
};
|
||||
|
||||
bridge_hub_test_utils::test_cases::include_teleports_for_native_asset_works!(
|
||||
Runtime,
|
||||
@@ -47,11 +109,7 @@ mod bridge_hub_rococo_tests {
|
||||
CheckingAccount,
|
||||
WeightToFee,
|
||||
ParachainSystem,
|
||||
bridge_hub_test_utils::CollatorSessionKeys::new(
|
||||
AccountId::from(ALICE),
|
||||
AccountId::from(ALICE),
|
||||
SessionKeys { aura: AuraId::from(sp_core::sr25519::Public::from_raw(ALICE)) }
|
||||
),
|
||||
collator_session_keys(),
|
||||
ExistentialDeposit::get(),
|
||||
Box::new(|runtime_event_encoded: Vec<u8>| {
|
||||
match RuntimeEvent::decode(&mut &runtime_event_encoded[..]) {
|
||||
@@ -68,101 +126,157 @@ mod bridge_hub_rococo_tests {
|
||||
bp_bridge_hub_rococo::BRIDGE_HUB_ROCOCO_PARACHAIN_ID
|
||||
);
|
||||
|
||||
bridge_hub_test_utils::include_initialize_bridge_by_governance_works!(
|
||||
Runtime,
|
||||
BridgeGrandpaWococoInstance,
|
||||
bridge_hub_test_utils::CollatorSessionKeys::new(
|
||||
AccountId::from(ALICE),
|
||||
AccountId::from(ALICE),
|
||||
SessionKeys { aura: AuraId::from(sp_core::sr25519::Public::from_raw(ALICE)) }
|
||||
),
|
||||
bp_bridge_hub_rococo::BRIDGE_HUB_ROCOCO_PARACHAIN_ID,
|
||||
Box::new(|call| RuntimeCall::BridgeWococoGrandpa(call).encode())
|
||||
);
|
||||
#[test]
|
||||
fn initialize_bridge_by_governance_works() {
|
||||
bridge_hub_test_utils::test_cases::initialize_bridge_by_governance_works::<
|
||||
Runtime,
|
||||
BridgeGrandpaWococoInstance,
|
||||
>(
|
||||
collator_session_keys(),
|
||||
bp_bridge_hub_rococo::BRIDGE_HUB_ROCOCO_PARACHAIN_ID,
|
||||
Box::new(|call| RuntimeCall::BridgeWococoGrandpa(call).encode()),
|
||||
)
|
||||
}
|
||||
|
||||
bridge_hub_test_utils::include_change_storage_constant_by_governance_works!(
|
||||
change_delivery_reward_by_governance_works,
|
||||
Runtime,
|
||||
bridge_hub_test_utils::CollatorSessionKeys::new(
|
||||
AccountId::from(ALICE),
|
||||
AccountId::from(ALICE),
|
||||
SessionKeys { aura: AuraId::from(sp_core::sr25519::Public::from_raw(ALICE)) }
|
||||
),
|
||||
bp_bridge_hub_rococo::BRIDGE_HUB_ROCOCO_PARACHAIN_ID,
|
||||
Box::new(|call| RuntimeCall::System(call).encode()),
|
||||
(DeliveryRewardInBalance, u64),
|
||||
|| (DeliveryRewardInBalance::key().to_vec(), DeliveryRewardInBalance::get()),
|
||||
|old_value| old_value.checked_mul(2).unwrap()
|
||||
);
|
||||
#[test]
|
||||
fn change_delivery_reward_by_governance_works() {
|
||||
bridge_hub_test_utils::test_cases::change_storage_constant_by_governance_works::<
|
||||
Runtime,
|
||||
DeliveryRewardInBalance,
|
||||
u64,
|
||||
>(
|
||||
collator_session_keys(),
|
||||
bp_bridge_hub_rococo::BRIDGE_HUB_ROCOCO_PARACHAIN_ID,
|
||||
Box::new(|call| RuntimeCall::System(call).encode()),
|
||||
|| (DeliveryRewardInBalance::key().to_vec(), DeliveryRewardInBalance::get()),
|
||||
|old_value| old_value.checked_mul(2).unwrap(),
|
||||
)
|
||||
}
|
||||
|
||||
bridge_hub_test_utils::include_change_storage_constant_by_governance_works!(
|
||||
change_required_stake_by_governance_works,
|
||||
Runtime,
|
||||
bridge_hub_test_utils::CollatorSessionKeys::new(
|
||||
AccountId::from(ALICE),
|
||||
AccountId::from(ALICE),
|
||||
SessionKeys { aura: AuraId::from(sp_core::sr25519::Public::from_raw(ALICE)) }
|
||||
),
|
||||
bp_bridge_hub_rococo::BRIDGE_HUB_ROCOCO_PARACHAIN_ID,
|
||||
Box::new(|call| RuntimeCall::System(call).encode()),
|
||||
(RequiredStakeForStakeAndSlash, Balance),
|
||||
|| (RequiredStakeForStakeAndSlash::key().to_vec(), RequiredStakeForStakeAndSlash::get()),
|
||||
|old_value| old_value.checked_mul(2).unwrap()
|
||||
);
|
||||
#[test]
|
||||
fn change_required_stake_by_governance_works() {
|
||||
bridge_hub_test_utils::test_cases::change_storage_constant_by_governance_works::<
|
||||
Runtime,
|
||||
RequiredStakeForStakeAndSlash,
|
||||
Balance,
|
||||
>(
|
||||
collator_session_keys(),
|
||||
bp_bridge_hub_rococo::BRIDGE_HUB_ROCOCO_PARACHAIN_ID,
|
||||
Box::new(|call| RuntimeCall::System(call).encode()),
|
||||
|| {
|
||||
(
|
||||
RequiredStakeForStakeAndSlash::key().to_vec(),
|
||||
RequiredStakeForStakeAndSlash::get(),
|
||||
)
|
||||
},
|
||||
|old_value| old_value.checked_mul(2).unwrap(),
|
||||
)
|
||||
}
|
||||
|
||||
bridge_hub_test_utils::include_handle_export_message_from_system_parachain_to_outbound_queue_works!(
|
||||
Runtime,
|
||||
XcmConfig,
|
||||
WithBridgeHubWococoMessagesInstance,
|
||||
bridge_hub_test_utils::CollatorSessionKeys::new(
|
||||
AccountId::from(ALICE),
|
||||
AccountId::from(ALICE),
|
||||
SessionKeys { aura: AuraId::from(sp_core::sr25519::Public::from_raw(ALICE)) }
|
||||
),
|
||||
bp_bridge_hub_rococo::BRIDGE_HUB_ROCOCO_PARACHAIN_ID,
|
||||
1000,
|
||||
Box::new(|runtime_event_encoded: Vec<u8>| {
|
||||
match RuntimeEvent::decode(&mut &runtime_event_encoded[..]) {
|
||||
Ok(RuntimeEvent::BridgeWococoMessages(event)) => Some(event),
|
||||
_ => None,
|
||||
}
|
||||
}),
|
||||
|| ExportMessage { network: Wococo, destination: X1(Parachain(1234)), xcm: Xcm(vec![]) },
|
||||
bridge_hub_rococo_config::DEFAULT_XCM_LANE_TO_BRIDGE_HUB_WOCOCO
|
||||
);
|
||||
#[test]
|
||||
fn handle_export_message_from_system_parachain_add_to_outbound_queue_works() {
|
||||
bridge_hub_test_utils::test_cases::handle_export_message_from_system_parachain_to_outbound_queue_works::<
|
||||
Runtime,
|
||||
XcmConfig,
|
||||
WithBridgeHubWococoMessagesInstance,
|
||||
>(
|
||||
collator_session_keys(),
|
||||
bp_bridge_hub_rococo::BRIDGE_HUB_ROCOCO_PARACHAIN_ID,
|
||||
SIBLING_PARACHAIN_ID,
|
||||
Box::new(|runtime_event_encoded: Vec<u8>| {
|
||||
match RuntimeEvent::decode(&mut &runtime_event_encoded[..]) {
|
||||
Ok(RuntimeEvent::BridgeWococoMessages(event)) => Some(event),
|
||||
_ => None,
|
||||
}
|
||||
}),
|
||||
|| ExportMessage { network: Wococo, destination: X1(Parachain(1234)), xcm: Xcm(vec![]) },
|
||||
bridge_hub_rococo_config::DEFAULT_XCM_LANE_TO_BRIDGE_HUB_WOCOCO
|
||||
)
|
||||
}
|
||||
|
||||
bridge_hub_test_utils::include_message_dispatch_routing_works!(
|
||||
Runtime,
|
||||
XcmConfig,
|
||||
ParachainSystem,
|
||||
WithBridgeHubWococoMessagesInstance,
|
||||
RelayNetwork,
|
||||
bridge_hub_rococo_config::WococoGlobalConsensusNetwork,
|
||||
bridge_hub_test_utils::CollatorSessionKeys::new(
|
||||
AccountId::from(ALICE),
|
||||
AccountId::from(ALICE),
|
||||
SessionKeys { aura: AuraId::from(sp_core::sr25519::Public::from_raw(ALICE)) }
|
||||
),
|
||||
bp_bridge_hub_rococo::BRIDGE_HUB_ROCOCO_PARACHAIN_ID,
|
||||
1000,
|
||||
Box::new(|runtime_event_encoded: Vec<u8>| {
|
||||
match RuntimeEvent::decode(&mut &runtime_event_encoded[..]) {
|
||||
Ok(RuntimeEvent::ParachainSystem(event)) => Some(event),
|
||||
_ => None,
|
||||
}
|
||||
}),
|
||||
Box::new(|runtime_event_encoded: Vec<u8>| {
|
||||
match RuntimeEvent::decode(&mut &runtime_event_encoded[..]) {
|
||||
Ok(RuntimeEvent::XcmpQueue(event)) => Some(event),
|
||||
_ => None,
|
||||
}
|
||||
}),
|
||||
bridge_hub_rococo_config::DEFAULT_XCM_LANE_TO_BRIDGE_HUB_WOCOCO
|
||||
);
|
||||
#[test]
|
||||
fn message_dispatch_routing_works() {
|
||||
bridge_hub_test_utils::test_cases::message_dispatch_routing_works::<
|
||||
Runtime,
|
||||
XcmConfig,
|
||||
ParachainSystem,
|
||||
WithBridgeHubWococoMessagesInstance,
|
||||
RelayNetwork,
|
||||
bridge_hub_rococo_config::WococoGlobalConsensusNetwork,
|
||||
>(
|
||||
collator_session_keys(),
|
||||
bp_bridge_hub_rococo::BRIDGE_HUB_ROCOCO_PARACHAIN_ID,
|
||||
SIBLING_PARACHAIN_ID,
|
||||
Box::new(|runtime_event_encoded: Vec<u8>| {
|
||||
match RuntimeEvent::decode(&mut &runtime_event_encoded[..]) {
|
||||
Ok(RuntimeEvent::ParachainSystem(event)) => Some(event),
|
||||
_ => None,
|
||||
}
|
||||
}),
|
||||
Box::new(|runtime_event_encoded: Vec<u8>| {
|
||||
match RuntimeEvent::decode(&mut &runtime_event_encoded[..]) {
|
||||
Ok(RuntimeEvent::XcmpQueue(event)) => Some(event),
|
||||
_ => None,
|
||||
}
|
||||
}),
|
||||
bridge_hub_rococo_config::DEFAULT_XCM_LANE_TO_BRIDGE_HUB_WOCOCO,
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn relayed_incoming_message_works() {
|
||||
bridge_hub_test_utils::test_cases::relayed_incoming_message_works::<
|
||||
Runtime,
|
||||
XcmConfig,
|
||||
ParachainSystem,
|
||||
BridgeGrandpaWococoInstance,
|
||||
BridgeParachainWococoInstance,
|
||||
WithBridgeHubWococoMessagesInstance,
|
||||
WithBridgeHubWococoMessageBridge,
|
||||
>(
|
||||
collator_session_keys(),
|
||||
bp_bridge_hub_rococo::BRIDGE_HUB_ROCOCO_PARACHAIN_ID,
|
||||
bp_bridge_hub_wococo::BRIDGE_HUB_WOCOCO_PARACHAIN_ID,
|
||||
SIBLING_PARACHAIN_ID,
|
||||
Rococo,
|
||||
DEFAULT_XCM_LANE_TO_BRIDGE_HUB_WOCOCO,
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
pub fn complex_relay_extrinsic_works() {
|
||||
bridge_hub_test_utils::test_cases::complex_relay_extrinsic_works::<
|
||||
Runtime,
|
||||
XcmConfig,
|
||||
ParachainSystem,
|
||||
BridgeGrandpaWococoInstance,
|
||||
BridgeParachainWococoInstance,
|
||||
WithBridgeHubWococoMessagesInstance,
|
||||
WithBridgeHubWococoMessageBridge,
|
||||
>(
|
||||
collator_session_keys(),
|
||||
bp_bridge_hub_rococo::BRIDGE_HUB_ROCOCO_PARACHAIN_ID,
|
||||
bp_bridge_hub_wococo::BRIDGE_HUB_WOCOCO_PARACHAIN_ID,
|
||||
SIBLING_PARACHAIN_ID,
|
||||
bridge_hub_rococo_config::BridgeHubWococoChainId::get(),
|
||||
Rococo,
|
||||
DEFAULT_XCM_LANE_TO_BRIDGE_HUB_WOCOCO,
|
||||
ExistentialDeposit::get(),
|
||||
executive_init_block,
|
||||
construct_and_apply_extrinsic,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
mod bridge_hub_wococo_tests {
|
||||
use super::*;
|
||||
use bridge_hub_rococo_runtime::{
|
||||
BridgeGrandpaRococoInstance, BridgeParachainRococoInstance,
|
||||
WithBridgeHubRococoMessagesInstance,
|
||||
};
|
||||
use bridge_hub_wococo_config::{
|
||||
WithBridgeHubRococoMessageBridge, DEFAULT_XCM_LANE_TO_BRIDGE_HUB_ROCOCO,
|
||||
};
|
||||
|
||||
bridge_hub_test_utils::test_cases::include_teleports_for_native_asset_works!(
|
||||
Runtime,
|
||||
@@ -170,11 +284,7 @@ mod bridge_hub_wococo_tests {
|
||||
CheckingAccount,
|
||||
WeightToFee,
|
||||
ParachainSystem,
|
||||
bridge_hub_test_utils::CollatorSessionKeys::new(
|
||||
AccountId::from(ALICE),
|
||||
AccountId::from(ALICE),
|
||||
SessionKeys { aura: AuraId::from(sp_core::sr25519::Public::from_raw(ALICE)) }
|
||||
),
|
||||
collator_session_keys(),
|
||||
ExistentialDeposit::get(),
|
||||
Box::new(|runtime_event_encoded: Vec<u8>| {
|
||||
match RuntimeEvent::decode(&mut &runtime_event_encoded[..]) {
|
||||
@@ -191,95 +301,144 @@ mod bridge_hub_wococo_tests {
|
||||
bp_bridge_hub_wococo::BRIDGE_HUB_WOCOCO_PARACHAIN_ID
|
||||
);
|
||||
|
||||
bridge_hub_test_utils::include_initialize_bridge_by_governance_works!(
|
||||
Runtime,
|
||||
BridgeGrandpaRococoInstance,
|
||||
bridge_hub_test_utils::CollatorSessionKeys::new(
|
||||
AccountId::from(ALICE),
|
||||
AccountId::from(ALICE),
|
||||
SessionKeys { aura: AuraId::from(sp_core::sr25519::Public::from_raw(ALICE)) }
|
||||
),
|
||||
bp_bridge_hub_wococo::BRIDGE_HUB_WOCOCO_PARACHAIN_ID,
|
||||
Box::new(|call| RuntimeCall::BridgeRococoGrandpa(call).encode())
|
||||
);
|
||||
#[test]
|
||||
fn initialize_bridge_by_governance_works() {
|
||||
bridge_hub_test_utils::test_cases::initialize_bridge_by_governance_works::<
|
||||
Runtime,
|
||||
BridgeGrandpaRococoInstance,
|
||||
>(
|
||||
collator_session_keys(),
|
||||
bp_bridge_hub_wococo::BRIDGE_HUB_WOCOCO_PARACHAIN_ID,
|
||||
Box::new(|call| RuntimeCall::BridgeRococoGrandpa(call).encode()),
|
||||
)
|
||||
}
|
||||
|
||||
bridge_hub_test_utils::include_change_storage_constant_by_governance_works!(
|
||||
change_delivery_reward_by_governance_works,
|
||||
Runtime,
|
||||
bridge_hub_test_utils::CollatorSessionKeys::new(
|
||||
AccountId::from(ALICE),
|
||||
AccountId::from(ALICE),
|
||||
SessionKeys { aura: AuraId::from(sp_core::sr25519::Public::from_raw(ALICE)) }
|
||||
),
|
||||
bp_bridge_hub_wococo::BRIDGE_HUB_WOCOCO_PARACHAIN_ID,
|
||||
Box::new(|call| RuntimeCall::System(call).encode()),
|
||||
(DeliveryRewardInBalance, u64),
|
||||
|| (DeliveryRewardInBalance::key().to_vec(), DeliveryRewardInBalance::get()),
|
||||
|old_value| old_value.checked_mul(2).unwrap()
|
||||
);
|
||||
#[test]
|
||||
fn change_delivery_reward_by_governance_works() {
|
||||
bridge_hub_test_utils::test_cases::change_storage_constant_by_governance_works::<
|
||||
Runtime,
|
||||
DeliveryRewardInBalance,
|
||||
u64,
|
||||
>(
|
||||
collator_session_keys(),
|
||||
bp_bridge_hub_wococo::BRIDGE_HUB_WOCOCO_PARACHAIN_ID,
|
||||
Box::new(|call| RuntimeCall::System(call).encode()),
|
||||
|| (DeliveryRewardInBalance::key().to_vec(), DeliveryRewardInBalance::get()),
|
||||
|old_value| old_value.checked_mul(2).unwrap(),
|
||||
)
|
||||
}
|
||||
|
||||
bridge_hub_test_utils::include_change_storage_constant_by_governance_works!(
|
||||
change_required_stake_by_governance_works,
|
||||
Runtime,
|
||||
bridge_hub_test_utils::CollatorSessionKeys::new(
|
||||
AccountId::from(ALICE),
|
||||
AccountId::from(ALICE),
|
||||
SessionKeys { aura: AuraId::from(sp_core::sr25519::Public::from_raw(ALICE)) }
|
||||
),
|
||||
bp_bridge_hub_wococo::BRIDGE_HUB_WOCOCO_PARACHAIN_ID,
|
||||
Box::new(|call| RuntimeCall::System(call).encode()),
|
||||
(RequiredStakeForStakeAndSlash, Balance),
|
||||
|| (RequiredStakeForStakeAndSlash::key().to_vec(), RequiredStakeForStakeAndSlash::get()),
|
||||
|old_value| old_value.checked_mul(2).unwrap()
|
||||
);
|
||||
#[test]
|
||||
fn change_required_stake_by_governance_works() {
|
||||
bridge_hub_test_utils::test_cases::change_storage_constant_by_governance_works::<
|
||||
Runtime,
|
||||
RequiredStakeForStakeAndSlash,
|
||||
Balance,
|
||||
>(
|
||||
collator_session_keys(),
|
||||
bp_bridge_hub_wococo::BRIDGE_HUB_WOCOCO_PARACHAIN_ID,
|
||||
Box::new(|call| RuntimeCall::System(call).encode()),
|
||||
|| {
|
||||
(
|
||||
RequiredStakeForStakeAndSlash::key().to_vec(),
|
||||
RequiredStakeForStakeAndSlash::get(),
|
||||
)
|
||||
},
|
||||
|old_value| old_value.checked_mul(2).unwrap(),
|
||||
)
|
||||
}
|
||||
|
||||
bridge_hub_test_utils::include_handle_export_message_from_system_parachain_to_outbound_queue_works!(
|
||||
Runtime,
|
||||
XcmConfig,
|
||||
WithBridgeHubRococoMessagesInstance,
|
||||
bridge_hub_test_utils::CollatorSessionKeys::new(
|
||||
AccountId::from(ALICE),
|
||||
AccountId::from(ALICE),
|
||||
SessionKeys { aura: AuraId::from(sp_core::sr25519::Public::from_raw(ALICE)) }
|
||||
),
|
||||
bp_bridge_hub_wococo::BRIDGE_HUB_WOCOCO_PARACHAIN_ID,
|
||||
1000,
|
||||
Box::new(|runtime_event_encoded: Vec<u8>| {
|
||||
match RuntimeEvent::decode(&mut &runtime_event_encoded[..]) {
|
||||
Ok(RuntimeEvent::BridgeRococoMessages(event)) => Some(event),
|
||||
_ => None,
|
||||
}
|
||||
}),
|
||||
|| ExportMessage { network: Rococo, destination: X1(Parachain(4321)), xcm: Xcm(vec![]) },
|
||||
bridge_hub_wococo_config::DEFAULT_XCM_LANE_TO_BRIDGE_HUB_ROCOCO
|
||||
);
|
||||
#[test]
|
||||
fn handle_export_message_from_system_parachain_add_to_outbound_queue_works() {
|
||||
bridge_hub_test_utils::test_cases::handle_export_message_from_system_parachain_to_outbound_queue_works::<
|
||||
Runtime,
|
||||
XcmConfig,
|
||||
WithBridgeHubRococoMessagesInstance,
|
||||
>(
|
||||
collator_session_keys(),
|
||||
bp_bridge_hub_wococo::BRIDGE_HUB_WOCOCO_PARACHAIN_ID,
|
||||
SIBLING_PARACHAIN_ID,
|
||||
Box::new(|runtime_event_encoded: Vec<u8>| {
|
||||
match RuntimeEvent::decode(&mut &runtime_event_encoded[..]) {
|
||||
Ok(RuntimeEvent::BridgeRococoMessages(event)) => Some(event),
|
||||
_ => None,
|
||||
}
|
||||
}),
|
||||
|| ExportMessage { network: Rococo, destination: X1(Parachain(4321)), xcm: Xcm(vec![]) },
|
||||
bridge_hub_wococo_config::DEFAULT_XCM_LANE_TO_BRIDGE_HUB_ROCOCO
|
||||
)
|
||||
}
|
||||
|
||||
bridge_hub_test_utils::include_message_dispatch_routing_works!(
|
||||
Runtime,
|
||||
XcmConfig,
|
||||
ParachainSystem,
|
||||
WithBridgeHubRococoMessagesInstance,
|
||||
RelayNetwork,
|
||||
bridge_hub_wococo_config::RococoGlobalConsensusNetwork,
|
||||
bridge_hub_test_utils::CollatorSessionKeys::new(
|
||||
AccountId::from(ALICE),
|
||||
AccountId::from(ALICE),
|
||||
SessionKeys { aura: AuraId::from(sp_core::sr25519::Public::from_raw(ALICE)) }
|
||||
),
|
||||
bp_bridge_hub_wococo::BRIDGE_HUB_WOCOCO_PARACHAIN_ID,
|
||||
1000,
|
||||
Box::new(|runtime_event_encoded: Vec<u8>| {
|
||||
match RuntimeEvent::decode(&mut &runtime_event_encoded[..]) {
|
||||
Ok(RuntimeEvent::ParachainSystem(event)) => Some(event),
|
||||
_ => None,
|
||||
}
|
||||
}),
|
||||
Box::new(|runtime_event_encoded: Vec<u8>| {
|
||||
match RuntimeEvent::decode(&mut &runtime_event_encoded[..]) {
|
||||
Ok(RuntimeEvent::XcmpQueue(event)) => Some(event),
|
||||
_ => None,
|
||||
}
|
||||
}),
|
||||
bridge_hub_wococo_config::DEFAULT_XCM_LANE_TO_BRIDGE_HUB_ROCOCO
|
||||
);
|
||||
#[test]
|
||||
fn message_dispatch_routing_works() {
|
||||
bridge_hub_test_utils::test_cases::message_dispatch_routing_works::<
|
||||
Runtime,
|
||||
XcmConfig,
|
||||
ParachainSystem,
|
||||
WithBridgeHubRococoMessagesInstance,
|
||||
RelayNetwork,
|
||||
bridge_hub_wococo_config::RococoGlobalConsensusNetwork,
|
||||
>(
|
||||
collator_session_keys(),
|
||||
bp_bridge_hub_wococo::BRIDGE_HUB_WOCOCO_PARACHAIN_ID,
|
||||
SIBLING_PARACHAIN_ID,
|
||||
Box::new(|runtime_event_encoded: Vec<u8>| {
|
||||
match RuntimeEvent::decode(&mut &runtime_event_encoded[..]) {
|
||||
Ok(RuntimeEvent::ParachainSystem(event)) => Some(event),
|
||||
_ => None,
|
||||
}
|
||||
}),
|
||||
Box::new(|runtime_event_encoded: Vec<u8>| {
|
||||
match RuntimeEvent::decode(&mut &runtime_event_encoded[..]) {
|
||||
Ok(RuntimeEvent::XcmpQueue(event)) => Some(event),
|
||||
_ => None,
|
||||
}
|
||||
}),
|
||||
bridge_hub_wococo_config::DEFAULT_XCM_LANE_TO_BRIDGE_HUB_ROCOCO,
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn relayed_incoming_message_works() {
|
||||
bridge_hub_test_utils::test_cases::relayed_incoming_message_works::<
|
||||
Runtime,
|
||||
XcmConfig,
|
||||
ParachainSystem,
|
||||
BridgeGrandpaRococoInstance,
|
||||
BridgeParachainRococoInstance,
|
||||
WithBridgeHubRococoMessagesInstance,
|
||||
WithBridgeHubRococoMessageBridge,
|
||||
>(
|
||||
collator_session_keys(),
|
||||
bp_bridge_hub_wococo::BRIDGE_HUB_WOCOCO_PARACHAIN_ID,
|
||||
bp_bridge_hub_rococo::BRIDGE_HUB_ROCOCO_PARACHAIN_ID,
|
||||
SIBLING_PARACHAIN_ID,
|
||||
Wococo,
|
||||
DEFAULT_XCM_LANE_TO_BRIDGE_HUB_ROCOCO,
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
pub fn complex_relay_extrinsic_works() {
|
||||
bridge_hub_test_utils::test_cases::complex_relay_extrinsic_works::<
|
||||
Runtime,
|
||||
XcmConfig,
|
||||
ParachainSystem,
|
||||
BridgeGrandpaRococoInstance,
|
||||
BridgeParachainRococoInstance,
|
||||
WithBridgeHubRococoMessagesInstance,
|
||||
WithBridgeHubRococoMessageBridge,
|
||||
>(
|
||||
collator_session_keys(),
|
||||
bp_bridge_hub_wococo::BRIDGE_HUB_WOCOCO_PARACHAIN_ID,
|
||||
bp_bridge_hub_rococo::BRIDGE_HUB_ROCOCO_PARACHAIN_ID,
|
||||
SIBLING_PARACHAIN_ID,
|
||||
bridge_hub_wococo_config::BridgeHubRococoChainId::get(),
|
||||
Wococo,
|
||||
DEFAULT_XCM_LANE_TO_BRIDGE_HUB_ROCOCO,
|
||||
ExistentialDeposit::get(),
|
||||
executive_init_block,
|
||||
construct_and_apply_extrinsic,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,20 +10,26 @@ codec = { package = "parity-scale-codec", version = "3.0.0", default-features =
|
||||
log = { version = "0.4.17", default-features = false }
|
||||
|
||||
# Substrate
|
||||
frame-benchmarking = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false, optional = true }
|
||||
frame-executive = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
|
||||
frame-support = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
|
||||
frame-system = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
|
||||
sp-core = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
|
||||
sp-io = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
|
||||
sp-keyring = { git = "https://github.com/paritytech/substrate", branch = "master" }
|
||||
sp-runtime = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
|
||||
pallet-session = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
|
||||
pallet-balances = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
|
||||
pallet-utility = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
|
||||
pallet-session = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
|
||||
|
||||
# Cumulus
|
||||
asset-test-utils = { path = "../../assets/test-utils"}
|
||||
cumulus-pallet-dmp-queue = { path = "../../../../pallets/dmp-queue", default-features = false }
|
||||
pallet-collator-selection = { path = "../../../../pallets/collator-selection", default-features = false }
|
||||
cumulus-pallet-parachain-system = { path = "../../../../pallets/parachain-system", default-features = false }
|
||||
cumulus-pallet-xcmp-queue = { path = "../../../../pallets/xcmp-queue", default-features = false }
|
||||
pallet-collator-selection = { path = "../../../../pallets/collator-selection", default-features = false }
|
||||
parachain-info = { path = "../../../../parachains/pallets/parachain-info", default-features = false }
|
||||
asset-test-utils = { path = "../../assets/test-utils"}
|
||||
parachains-runtimes-test-utils = { path = "../../test-utils", default-features = false }
|
||||
|
||||
# Polkadot
|
||||
pallet-xcm = { git = "https://github.com/paritytech/polkadot", default-features = false, branch = "master" }
|
||||
@@ -33,13 +39,19 @@ xcm-builder = { git = "https://github.com/paritytech/polkadot", default-features
|
||||
xcm-executor = { git = "https://github.com/paritytech/polkadot", default-features = false, branch = "master" }
|
||||
|
||||
# Bridges
|
||||
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-header-chain = { path = "../../../../bridges/primitives/header-chain", default-features = false }
|
||||
bp-messages = { path = "../../../../bridges/primitives/messages", default-features = false }
|
||||
bp-parachains = { path = "../../../../bridges/primitives/parachains", default-features = false }
|
||||
bp-polkadot-core = { path = "../../../../bridges/primitives/polkadot-core", default-features = false }
|
||||
bp-relayers = { path = "../../../../bridges/primitives/relayers", default-features = false }
|
||||
bp-runtime = { path = "../../../../bridges/primitives/runtime", default-features = false }
|
||||
bp-test-utils = { path = "../../../../bridges/primitives/test-utils", default-features = false }
|
||||
pallet-bridge-grandpa = { path = "../../../../bridges/modules/grandpa", default-features = false }
|
||||
pallet-bridge-parachains = { path = "../../../../bridges/modules/parachains", default-features = false }
|
||||
pallet-bridge-messages = { path = "../../../../bridges/modules/messages", default-features = false }
|
||||
pallet-bridge-relayers = { path = "../../../../bridges/modules/relayers", default-features = false }
|
||||
bridge-runtime-common = { path = "../../../../bridges/bin/runtime-common", default-features = false }
|
||||
|
||||
[features]
|
||||
@@ -47,20 +59,28 @@ default = [ "std" ]
|
||||
std = [
|
||||
"codec/std",
|
||||
"log/std",
|
||||
"frame-benchmarking/std",
|
||||
"frame-executive/std",
|
||||
"frame-support/std",
|
||||
"frame-system/std",
|
||||
"bp-messages/std",
|
||||
"bp-parachains/std",
|
||||
"bp-polkadot-core/std",
|
||||
"bp-header-chain/std",
|
||||
"bp-relayers/std",
|
||||
"bp-runtime/std",
|
||||
"bp-test-utils/std",
|
||||
"bridge-runtime-common/std",
|
||||
"pallet-bridge-grandpa/std",
|
||||
"pallet-bridge-parachains/std",
|
||||
"pallet-bridge-messages/std",
|
||||
"pallet-bridge-relayers/std",
|
||||
"parachain-info/std",
|
||||
"parachains-runtimes-test-utils/std",
|
||||
"cumulus-pallet-parachain-system/std",
|
||||
"cumulus-pallet-xcmp-queue/std",
|
||||
"pallet-xcm/std",
|
||||
"sp-core/std",
|
||||
"sp-io/std",
|
||||
"sp-runtime/std",
|
||||
"xcm/std",
|
||||
@@ -70,4 +90,5 @@ std = [
|
||||
"cumulus-pallet-dmp-queue/std",
|
||||
"pallet-session/std",
|
||||
"pallet-balances/std",
|
||||
"pallet-utility/std",
|
||||
]
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright 2023 Parity Technologies (UK) Ltd.
|
||||
// Copyright Parity Technologies (UK) Ltd.
|
||||
// This file is part of Cumulus.
|
||||
|
||||
// Cumulus is free software: you can redistribute it and/or modify
|
||||
@@ -14,6 +14,8 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Cumulus. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
pub use bp_test_utils::test_header;
|
||||
//! Module contains predefined test-case scenarios for "BridgeHub" `Runtime`s.
|
||||
|
||||
pub mod test_cases;
|
||||
pub use test_cases::CollatorSessionKeys;
|
||||
pub use bp_test_utils::test_header;
|
||||
pub use parachains_runtimes_test_utils::*;
|
||||
|
||||
@@ -16,28 +16,41 @@
|
||||
|
||||
//! Module contains predefined test-case scenarios for `Runtime` with bridging capabilities.
|
||||
|
||||
use bp_messages::{
|
||||
target_chain::{DispatchMessage, DispatchMessageData, MessageDispatch, SourceHeaderChain},
|
||||
LaneId, MessageKey, OutboundLaneData, Weight,
|
||||
};
|
||||
use bp_parachains::{BestParaHeadHash, ParaInfo};
|
||||
use bp_polkadot_core::parachains::{ParaHash, ParaId};
|
||||
use bp_relayers::{RewardsAccountOwner, RewardsAccountParams};
|
||||
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,
|
||||
},
|
||||
messages_generation::{encode_all_messages, encode_lane_data, prepare_messages_storage_proof},
|
||||
messages_xcm_extension::{XcmAsPlainPayload, XcmBlobMessageDispatchResult},
|
||||
};
|
||||
use codec::Encode;
|
||||
use frame_support::{assert_ok, traits::Get};
|
||||
use frame_support::{
|
||||
assert_ok,
|
||||
traits::{Get, OriginTrait},
|
||||
};
|
||||
use pallet_bridge_grandpa::BridgedHeader;
|
||||
use parachains_runtimes_test_utils::{
|
||||
mock_open_hrmp_channel, AccountIdOf, BalanceOf, CollatorSessionKeys, ExtBuilder, RuntimeHelper,
|
||||
ValidatorIdOf, XcmReceivedFrom,
|
||||
};
|
||||
use sp_core::H256;
|
||||
use sp_keyring::AccountKeyring::*;
|
||||
use sp_runtime::{traits::Header as HeaderT, AccountId32};
|
||||
use xcm::latest::prelude::*;
|
||||
use xcm_builder::DispatchBlobError;
|
||||
use xcm_executor::XcmExecutor;
|
||||
|
||||
// Lets re-use this stuff from assets (later we plan to move it outside of assets as `runtimes/test-utils`)
|
||||
use asset_test_utils::{
|
||||
mock_open_hrmp_channel, AccountIdOf, ExtBuilder, RuntimeHelper, ValidatorIdOf,
|
||||
};
|
||||
|
||||
// Re-export test_cases from assets
|
||||
pub use asset_test_utils::{
|
||||
include_teleports_for_native_asset_works, CollatorSessionKeys, XcmReceivedFrom,
|
||||
};
|
||||
use bp_messages::{
|
||||
target_chain::{DispatchMessage, DispatchMessageData, MessageDispatch},
|
||||
LaneId, MessageKey, OutboundLaneData,
|
||||
};
|
||||
use bridge_runtime_common::messages_xcm_extension::{
|
||||
XcmAsPlainPayload, XcmBlobMessageDispatchResult,
|
||||
};
|
||||
// Re-export test_case from assets
|
||||
pub use asset_test_utils::include_teleports_for_native_asset_works;
|
||||
|
||||
/// Test-case makes sure that `Runtime` can process bridging initialize via governance-like call
|
||||
pub fn initialize_bridge_by_governance_works<Runtime, GrandpaPalletInstance>(
|
||||
@@ -99,29 +112,6 @@ pub fn initialize_bridge_by_governance_works<Runtime, GrandpaPalletInstance>(
|
||||
})
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! include_initialize_bridge_by_governance_works(
|
||||
(
|
||||
$runtime:path,
|
||||
$pallet_bridge_grandpa_instance:path,
|
||||
$collator_session_key:expr,
|
||||
$runtime_para_id:expr,
|
||||
$runtime_call_encode:expr
|
||||
) => {
|
||||
#[test]
|
||||
fn initialize_bridge_by_governance_works() {
|
||||
$crate::test_cases::initialize_bridge_by_governance_works::<
|
||||
$runtime,
|
||||
$pallet_bridge_grandpa_instance,
|
||||
>(
|
||||
$collator_session_key,
|
||||
$runtime_para_id,
|
||||
$runtime_call_encode
|
||||
)
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
/// Test-case makes sure that `Runtime` can change storage constant via governance-like call
|
||||
pub fn change_storage_constant_by_governance_works<Runtime, StorageConstant, StorageConstantType>(
|
||||
collator_session_key: CollatorSessionKeys<Runtime>,
|
||||
@@ -192,35 +182,6 @@ pub fn change_storage_constant_by_governance_works<Runtime, StorageConstant, Sto
|
||||
})
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! include_change_storage_constant_by_governance_works(
|
||||
(
|
||||
$test_name:tt,
|
||||
$runtime:path,
|
||||
$collator_session_key:expr,
|
||||
$runtime_para_id:expr,
|
||||
$runtime_call_encode:expr,
|
||||
($storage_constant:path, $storage_constant_type:path),
|
||||
$storage_constant_key_value:expr,
|
||||
$new_storage_constant_value:expr
|
||||
) => {
|
||||
#[test]
|
||||
fn $test_name() {
|
||||
$crate::test_cases::change_storage_constant_by_governance_works::<
|
||||
$runtime,
|
||||
$storage_constant,
|
||||
$storage_constant_type,
|
||||
>(
|
||||
$collator_session_key,
|
||||
$runtime_para_id,
|
||||
$runtime_call_encode,
|
||||
$storage_constant_key_value,
|
||||
$new_storage_constant_value,
|
||||
)
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
/// Test-case makes sure that `Runtime` can handle xcm `ExportMessage`:
|
||||
/// Checks if received XCM messages is correctly added to the message outbound queue for delivery.
|
||||
/// For SystemParachains we expect unpaid execution.
|
||||
@@ -307,37 +268,6 @@ pub fn handle_export_message_from_system_parachain_to_outbound_queue_works<
|
||||
})
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! include_handle_export_message_from_system_parachain_to_outbound_queue_works(
|
||||
(
|
||||
$runtime:path,
|
||||
$xcm_config:path,
|
||||
$pallet_bridge_messages_instance:path,
|
||||
$collator_session_key:expr,
|
||||
$runtime_para_id:expr,
|
||||
$sibling_parachain_id:expr,
|
||||
$unwrap_pallet_bridge_messages_event:expr,
|
||||
$export_message_instruction:expr,
|
||||
$expected_lane_id:expr
|
||||
) => {
|
||||
#[test]
|
||||
fn handle_export_message_from_system_parachain_add_to_outbound_queue_works() {
|
||||
$crate::test_cases::handle_export_message_from_system_parachain_to_outbound_queue_works::<
|
||||
$runtime,
|
||||
$xcm_config,
|
||||
$pallet_bridge_messages_instance
|
||||
>(
|
||||
$collator_session_key,
|
||||
$runtime_para_id,
|
||||
$sibling_parachain_id,
|
||||
$unwrap_pallet_bridge_messages_event,
|
||||
$export_message_instruction,
|
||||
$expected_lane_id
|
||||
)
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
/// Test-case makes sure that Runtime can route XCM messages received in inbound queue,
|
||||
/// We just test here `MessageDispatch` configuration.
|
||||
/// We expect that runtime can route messages:
|
||||
@@ -392,123 +322,573 @@ pub fn message_dispatch_routing_works<
|
||||
.with_tracing()
|
||||
.build()
|
||||
.execute_with(|| {
|
||||
// 1. this message is sent from other global consensus with destination of this Runtime relay chain (UMP)
|
||||
let bridging_message =
|
||||
test_data::simulate_message_exporter_on_bridged_chain::<BridgedNetwork, RuntimeNetwork>(
|
||||
(RuntimeNetwork::get(), Here)
|
||||
);
|
||||
let result = <<Runtime as pallet_bridge_messages::Config<MessagesPalletInstance>>::MessageDispatch>::dispatch(
|
||||
test_data::dispatch_message(expected_lane_id, 1, bridging_message)
|
||||
// 1. this message is sent from other global consensus with destination of this Runtime relay chain (UMP)
|
||||
let bridging_message =
|
||||
test_data::simulate_message_exporter_on_bridged_chain::<BridgedNetwork, RuntimeNetwork>(
|
||||
(RuntimeNetwork::get(), Here)
|
||||
);
|
||||
assert_eq!(format!("{:?}", result.dispatch_level_result), format!("{:?}", XcmBlobMessageDispatchResult::Dispatched));
|
||||
let result = <<Runtime as pallet_bridge_messages::Config<MessagesPalletInstance>>::MessageDispatch>::dispatch(
|
||||
test_data::dispatch_message(expected_lane_id, 1, bridging_message)
|
||||
);
|
||||
assert_eq!(format!("{:?}", result.dispatch_level_result), format!("{:?}", XcmBlobMessageDispatchResult::Dispatched));
|
||||
|
||||
// check events - UpwardMessageSent
|
||||
let mut events = <frame_system::Pallet<Runtime>>::events()
|
||||
.into_iter()
|
||||
.filter_map(|e| unwrap_cumulus_pallet_parachain_system_event(e.event.encode()));
|
||||
assert!(
|
||||
events.any(|e| matches!(e, cumulus_pallet_parachain_system::Event::UpwardMessageSent { .. }))
|
||||
// check events - UpwardMessageSent
|
||||
let mut events = <frame_system::Pallet<Runtime>>::events()
|
||||
.into_iter()
|
||||
.filter_map(|e| unwrap_cumulus_pallet_parachain_system_event(e.event.encode()));
|
||||
assert!(
|
||||
events.any(|e| matches!(e, cumulus_pallet_parachain_system::Event::UpwardMessageSent { .. }))
|
||||
);
|
||||
|
||||
// 2. this message is sent from other global consensus with destination of this Runtime sibling parachain (HRMP)
|
||||
let bridging_message =
|
||||
test_data::simulate_message_exporter_on_bridged_chain::<BridgedNetwork, RuntimeNetwork>(
|
||||
(RuntimeNetwork::get(), X1(Parachain(sibling_parachain_id))),
|
||||
);
|
||||
|
||||
// 2. this message is sent from other global consensus with destination of this Runtime sibling parachain (HRMP)
|
||||
let bridging_message =
|
||||
test_data::simulate_message_exporter_on_bridged_chain::<BridgedNetwork, RuntimeNetwork>(
|
||||
(RuntimeNetwork::get(), X1(Parachain(sibling_parachain_id))),
|
||||
);
|
||||
|
||||
// 2.1. WITHOUT opened hrmp channel -> RoutingError
|
||||
let result =
|
||||
<<Runtime as pallet_bridge_messages::Config<MessagesPalletInstance>>::MessageDispatch>::dispatch(
|
||||
DispatchMessage {
|
||||
key: MessageKey { lane_id: expected_lane_id, nonce: 1 },
|
||||
data: DispatchMessageData { payload: Ok(bridging_message.clone()) },
|
||||
}
|
||||
);
|
||||
assert_eq!(format!("{:?}", result.dispatch_level_result), format!("{:?}", XcmBlobMessageDispatchResult::NotDispatched(Some(DispatchBlobError::RoutingError))));
|
||||
|
||||
// check events - no XcmpMessageSent
|
||||
assert_eq!(<frame_system::Pallet<Runtime>>::events()
|
||||
.into_iter()
|
||||
.filter_map(|e| unwrap_cumulus_pallet_xcmp_queue_event(e.event.encode()))
|
||||
.count(), 0);
|
||||
|
||||
// 2.1. WITH hrmp channel -> Ok
|
||||
mock_open_hrmp_channel::<Runtime, HrmpChannelOpener>(runtime_para_id.into(), sibling_parachain_id.into());
|
||||
let result = <<Runtime as pallet_bridge_messages::Config<MessagesPalletInstance>>::MessageDispatch>::dispatch(
|
||||
// 2.1. WITHOUT opened hrmp channel -> RoutingError
|
||||
let result =
|
||||
<<Runtime as pallet_bridge_messages::Config<MessagesPalletInstance>>::MessageDispatch>::dispatch(
|
||||
DispatchMessage {
|
||||
key: MessageKey { lane_id: expected_lane_id, nonce: 1 },
|
||||
data: DispatchMessageData { payload: Ok(bridging_message) },
|
||||
data: DispatchMessageData { payload: Ok(bridging_message.clone()) },
|
||||
}
|
||||
);
|
||||
assert_eq!(format!("{:?}", result.dispatch_level_result), format!("{:?}", XcmBlobMessageDispatchResult::Dispatched));
|
||||
assert_eq!(format!("{:?}", result.dispatch_level_result), format!("{:?}", XcmBlobMessageDispatchResult::NotDispatched(Some(DispatchBlobError::RoutingError))));
|
||||
|
||||
// check events - XcmpMessageSent
|
||||
let mut events = <frame_system::Pallet<Runtime>>::events()
|
||||
.into_iter()
|
||||
.filter_map(|e| unwrap_cumulus_pallet_xcmp_queue_event(e.event.encode()));
|
||||
assert!(
|
||||
events.any(|e| matches!(e, cumulus_pallet_xcmp_queue::Event::XcmpMessageSent { .. }))
|
||||
);
|
||||
// check events - no XcmpMessageSent
|
||||
assert_eq!(<frame_system::Pallet<Runtime>>::events()
|
||||
.into_iter()
|
||||
.filter_map(|e| unwrap_cumulus_pallet_xcmp_queue_event(e.event.encode()))
|
||||
.count(), 0);
|
||||
|
||||
// 2.1. WITH hrmp channel -> Ok
|
||||
mock_open_hrmp_channel::<Runtime, HrmpChannelOpener>(runtime_para_id.into(), sibling_parachain_id.into());
|
||||
let result = <<Runtime as pallet_bridge_messages::Config<MessagesPalletInstance>>::MessageDispatch>::dispatch(
|
||||
DispatchMessage {
|
||||
key: MessageKey { lane_id: expected_lane_id, nonce: 1 },
|
||||
data: DispatchMessageData { payload: Ok(bridging_message) },
|
||||
}
|
||||
);
|
||||
assert_eq!(format!("{:?}", result.dispatch_level_result), format!("{:?}", XcmBlobMessageDispatchResult::Dispatched));
|
||||
|
||||
// check events - XcmpMessageSent
|
||||
let mut events = <frame_system::Pallet<Runtime>>::events()
|
||||
.into_iter()
|
||||
.filter_map(|e| unwrap_cumulus_pallet_xcmp_queue_event(e.event.encode()));
|
||||
assert!(
|
||||
events.any(|e| matches!(e, cumulus_pallet_xcmp_queue::Event::XcmpMessageSent { .. }))
|
||||
);
|
||||
})
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! include_message_dispatch_routing_works(
|
||||
(
|
||||
$runtime:path,
|
||||
$xcm_config:path,
|
||||
$hrmp_channel_opener:path,
|
||||
$pallet_bridge_messages_instance:path,
|
||||
$runtime_network:path,
|
||||
$bridged_network:path,
|
||||
$collator_session_key:expr,
|
||||
$runtime_para_id:expr,
|
||||
$sibling_parachain_id:expr,
|
||||
$unwrap_cumulus_pallet_parachain_system_event:expr,
|
||||
$unwrap_cumulus_pallet_xcmp_queue_event:expr,
|
||||
$expected_lane_id:expr
|
||||
) => {
|
||||
#[test]
|
||||
fn message_dispatch_routing_works() {
|
||||
$crate::test_cases::message_dispatch_routing_works::<
|
||||
$runtime,
|
||||
$xcm_config,
|
||||
$hrmp_channel_opener,
|
||||
$pallet_bridge_messages_instance,
|
||||
$runtime_network,
|
||||
$bridged_network
|
||||
>(
|
||||
$collator_session_key,
|
||||
$runtime_para_id,
|
||||
$sibling_parachain_id,
|
||||
$unwrap_cumulus_pallet_parachain_system_event,
|
||||
$unwrap_cumulus_pallet_xcmp_queue_event,
|
||||
$expected_lane_id,
|
||||
)
|
||||
}
|
||||
}
|
||||
);
|
||||
/// Test-case makes sure that Runtime can dispatch XCM messages submitted by relayer,
|
||||
/// with proofs (finality, para heads, message) independently submitted.
|
||||
pub fn relayed_incoming_message_works<Runtime, XcmConfig, HrmpChannelOpener, GPI, PPI, MPI, MB>(
|
||||
collator_session_key: CollatorSessionKeys<Runtime>,
|
||||
runtime_para_id: u32,
|
||||
bridged_para_id: u32,
|
||||
sibling_parachain_id: u32,
|
||||
local_relay_chain_id: NetworkId,
|
||||
lane_id: LaneId,
|
||||
) where
|
||||
Runtime: frame_system::Config
|
||||
+ pallet_balances::Config
|
||||
+ pallet_session::Config
|
||||
+ pallet_xcm::Config
|
||||
+ parachain_info::Config
|
||||
+ pallet_collator_selection::Config
|
||||
+ cumulus_pallet_dmp_queue::Config
|
||||
+ cumulus_pallet_parachain_system::Config
|
||||
+ cumulus_pallet_xcmp_queue::Config
|
||||
+ pallet_bridge_grandpa::Config<GPI>
|
||||
+ pallet_bridge_parachains::Config<PPI>
|
||||
+ pallet_bridge_messages::Config<MPI, InboundPayload = XcmAsPlainPayload>,
|
||||
GPI: 'static,
|
||||
PPI: 'static,
|
||||
MPI: 'static,
|
||||
MB: MessageBridge,
|
||||
<MB as MessageBridge>::BridgedChain: Send + Sync + 'static,
|
||||
UnderlyingChainOf<MessageBridgedChain<MB>>: bp_runtime::Chain<Hash = ParaHash> + Parachain,
|
||||
XcmConfig: xcm_executor::Config,
|
||||
HrmpChannelOpener: frame_support::inherent::ProvideInherent<
|
||||
Call = cumulus_pallet_parachain_system::Call<Runtime>,
|
||||
>,
|
||||
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>,
|
||||
AccountIdOf<Runtime>: From<sp_core::sr25519::Public>,
|
||||
<Runtime as pallet_bridge_messages::Config<MPI>>::InboundRelayer: From<AccountId32>,
|
||||
{
|
||||
assert_ne!(runtime_para_id, sibling_parachain_id);
|
||||
assert_ne!(runtime_para_id, bridged_para_id);
|
||||
|
||||
mod test_data {
|
||||
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(runtime_para_id.into())
|
||||
.with_tracing()
|
||||
.build()
|
||||
.execute_with(|| {
|
||||
mock_open_hrmp_channel::<Runtime, HrmpChannelOpener>(
|
||||
runtime_para_id.into(),
|
||||
sibling_parachain_id.into(),
|
||||
);
|
||||
|
||||
// start with bridged chain block#0
|
||||
let init_data = test_data::initialization_data::<Runtime, GPI>(0);
|
||||
pallet_bridge_grandpa::Pallet::<Runtime, GPI>::initialize(
|
||||
RuntimeHelper::<Runtime>::root_origin(),
|
||||
init_data,
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
// set up relayer details and proofs
|
||||
|
||||
let message_destination =
|
||||
X2(GlobalConsensus(local_relay_chain_id), Parachain(sibling_parachain_id));
|
||||
// some random numbers (checked by test)
|
||||
let message_nonce = 1;
|
||||
let para_header_number = 5;
|
||||
let relay_header_number = 1;
|
||||
|
||||
let relayer_at_target = Bob;
|
||||
let relayer_id_on_target: AccountIdOf<Runtime> = relayer_at_target.public().into();
|
||||
let relayer_at_source = Dave;
|
||||
let relayer_id_on_source: AccountId32 = relayer_at_source.public().into();
|
||||
|
||||
let xcm = vec![xcm::v3::Instruction::<()>::ClearOrigin; 42];
|
||||
let expected_dispatch = xcm::VersionedXcm::<()>::V3(xcm.clone().into());
|
||||
// generate bridged relay chain finality, parachain heads and message proofs,
|
||||
// to be submitted by relayer to this chain.
|
||||
let (
|
||||
relay_chain_header,
|
||||
grandpa_justification,
|
||||
bridged_para_head,
|
||||
parachain_heads,
|
||||
para_heads_proof,
|
||||
message_proof,
|
||||
) = test_data::make_complex_relayer_proofs::<BridgedHeader<Runtime, GPI>, MB, ()>(
|
||||
lane_id,
|
||||
xcm.into(),
|
||||
message_nonce,
|
||||
message_destination,
|
||||
para_header_number,
|
||||
relay_header_number,
|
||||
bridged_para_id,
|
||||
);
|
||||
|
||||
// submit bridged relay chain finality proof
|
||||
{
|
||||
let result = pallet_bridge_grandpa::Pallet::<Runtime, GPI>::submit_finality_proof(
|
||||
RuntimeHelper::<Runtime>::origin_of(relayer_id_on_target.clone()),
|
||||
Box::new(relay_chain_header.clone()),
|
||||
grandpa_justification,
|
||||
);
|
||||
assert_ok!(result);
|
||||
assert_eq!(result.unwrap().pays_fee, frame_support::dispatch::Pays::Yes);
|
||||
}
|
||||
|
||||
// verify finality proof correctly imported
|
||||
assert_eq!(
|
||||
pallet_bridge_grandpa::BestFinalized::<Runtime, GPI>::get().unwrap().1,
|
||||
relay_chain_header.hash()
|
||||
);
|
||||
assert!(pallet_bridge_grandpa::ImportedHeaders::<Runtime, GPI>::contains_key(
|
||||
relay_chain_header.hash()
|
||||
));
|
||||
|
||||
// submit parachain heads proof
|
||||
{
|
||||
let result =
|
||||
pallet_bridge_parachains::Pallet::<Runtime, PPI>::submit_parachain_heads(
|
||||
RuntimeHelper::<Runtime>::origin_of(relayer_id_on_target.clone()),
|
||||
(relay_header_number, relay_chain_header.hash().into()),
|
||||
parachain_heads,
|
||||
para_heads_proof,
|
||||
);
|
||||
assert_ok!(result);
|
||||
assert_eq!(result.unwrap().pays_fee, frame_support::dispatch::Pays::Yes);
|
||||
}
|
||||
// verify parachain head proof correctly imported
|
||||
assert_eq!(
|
||||
pallet_bridge_parachains::ParasInfo::<Runtime, PPI>::get(ParaId(bridged_para_id)),
|
||||
Some(ParaInfo {
|
||||
best_head_hash: BestParaHeadHash {
|
||||
at_relay_block_number: relay_header_number,
|
||||
head_hash: bridged_para_head.hash()
|
||||
},
|
||||
next_imported_hash_position: 1,
|
||||
})
|
||||
);
|
||||
|
||||
// import message
|
||||
assert!(RuntimeHelper::<cumulus_pallet_xcmp_queue::Pallet<Runtime>>::take_xcm(
|
||||
sibling_parachain_id.into()
|
||||
)
|
||||
.is_none());
|
||||
assert_eq!(
|
||||
pallet_bridge_messages::InboundLanes::<Runtime, MPI>::get(lane_id)
|
||||
.last_delivered_nonce(),
|
||||
0,
|
||||
);
|
||||
// submit message proof
|
||||
{
|
||||
let result = pallet_bridge_messages::Pallet::<Runtime, MPI>::receive_messages_proof(
|
||||
RuntimeHelper::<Runtime>::origin_of(relayer_id_on_target),
|
||||
relayer_id_on_source.into(),
|
||||
message_proof.into(),
|
||||
1,
|
||||
Weight::MAX / 1000,
|
||||
);
|
||||
assert_ok!(result);
|
||||
assert_eq!(result.unwrap().pays_fee, frame_support::dispatch::Pays::Yes);
|
||||
}
|
||||
// verify message correctly imported and dispatched
|
||||
assert_eq!(
|
||||
pallet_bridge_messages::InboundLanes::<Runtime, MPI>::get(lane_id)
|
||||
.last_delivered_nonce(),
|
||||
1,
|
||||
);
|
||||
// verify relayed bridged XCM message is dispatched to destination sibling para
|
||||
let dispatched = RuntimeHelper::<cumulus_pallet_xcmp_queue::Pallet<Runtime>>::take_xcm(
|
||||
sibling_parachain_id.into(),
|
||||
)
|
||||
.unwrap();
|
||||
assert_eq!(dispatched, expected_dispatch);
|
||||
})
|
||||
}
|
||||
|
||||
/// Test-case makes sure that Runtime can dispatch XCM messages submitted by relayer,
|
||||
/// with proofs (finality, para heads, message) batched together in signed extrinsic.
|
||||
/// Also verifies relayer transaction signed extensions work as intended.
|
||||
pub fn complex_relay_extrinsic_works<Runtime, XcmConfig, HrmpChannelOpener, GPI, PPI, MPI, MB>(
|
||||
collator_session_key: CollatorSessionKeys<Runtime>,
|
||||
runtime_para_id: u32,
|
||||
bridged_para_id: u32,
|
||||
sibling_parachain_id: u32,
|
||||
bridged_chain_id: bp_runtime::ChainId,
|
||||
local_relay_chain_id: NetworkId,
|
||||
lane_id: LaneId,
|
||||
existential_deposit: BalanceOf<Runtime>,
|
||||
executive_init_block: fn(&<Runtime as frame_system::Config>::Header),
|
||||
construct_and_apply_extrinsic: fn(
|
||||
sp_keyring::AccountKeyring,
|
||||
pallet_utility::Call::<Runtime>
|
||||
) -> sp_runtime::DispatchOutcome,
|
||||
) where
|
||||
Runtime: frame_system::Config
|
||||
+ pallet_balances::Config
|
||||
+ pallet_utility::Config
|
||||
+ pallet_session::Config
|
||||
+ pallet_xcm::Config
|
||||
+ parachain_info::Config
|
||||
+ pallet_collator_selection::Config
|
||||
+ cumulus_pallet_dmp_queue::Config
|
||||
+ cumulus_pallet_parachain_system::Config
|
||||
+ cumulus_pallet_xcmp_queue::Config
|
||||
+ pallet_bridge_grandpa::Config<GPI>
|
||||
+ pallet_bridge_parachains::Config<PPI>
|
||||
+ pallet_bridge_messages::Config<MPI, InboundPayload = XcmAsPlainPayload>
|
||||
+ pallet_bridge_relayers::Config,
|
||||
GPI: 'static,
|
||||
PPI: 'static,
|
||||
MPI: 'static,
|
||||
MB: MessageBridge,
|
||||
<MB as MessageBridge>::BridgedChain: Send + Sync + 'static,
|
||||
UnderlyingChainOf<MessageBridgedChain<MB>>: bp_runtime::Chain<Hash = ParaHash> + Parachain,
|
||||
XcmConfig: xcm_executor::Config,
|
||||
HrmpChannelOpener: frame_support::inherent::ProvideInherent<
|
||||
Call = cumulus_pallet_parachain_system::Call<Runtime>,
|
||||
>,
|
||||
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>,
|
||||
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>>
|
||||
{
|
||||
assert_ne!(runtime_para_id, sibling_parachain_id);
|
||||
assert_ne!(runtime_para_id, bridged_para_id);
|
||||
|
||||
// Relayer account at local/this BH.
|
||||
let relayer_at_target = Bob;
|
||||
let relayer_id_on_target: AccountIdOf<Runtime> = relayer_at_target.public().into();
|
||||
let relayer_initial_balance = existential_deposit * 100000u32.into();
|
||||
// Relayer account at remote/bridged BH.
|
||||
let relayer_at_source = Dave;
|
||||
let relayer_id_on_source: AccountId32 = relayer_at_source.public().into();
|
||||
|
||||
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(runtime_para_id.into())
|
||||
.with_balances(vec![(relayer_id_on_target.clone(), relayer_initial_balance)])
|
||||
.with_tracing()
|
||||
.build()
|
||||
.execute_with(|| {
|
||||
let zero: <Runtime as frame_system::Config>::BlockNumber = 0u32.into();
|
||||
let genesis_hash = frame_system::Pallet::<Runtime>::block_hash(zero);
|
||||
let mut header: <Runtime as frame_system::Config>::Header =
|
||||
bp_test_utils::test_header(1u32.into());
|
||||
header.set_parent_hash(genesis_hash);
|
||||
executive_init_block(&header);
|
||||
|
||||
mock_open_hrmp_channel::<Runtime, HrmpChannelOpener>(
|
||||
runtime_para_id.into(),
|
||||
sibling_parachain_id.into(),
|
||||
);
|
||||
|
||||
// start with bridged chain block#0
|
||||
let init_data = test_data::initialization_data::<Runtime, GPI>(0);
|
||||
pallet_bridge_grandpa::Pallet::<Runtime, GPI>::initialize(
|
||||
RuntimeHelper::<Runtime>::root_origin(),
|
||||
init_data,
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
// set up relayer details and proofs
|
||||
|
||||
let message_destination =
|
||||
X2(GlobalConsensus(local_relay_chain_id), Parachain(sibling_parachain_id));
|
||||
// some random numbers (checked by test)
|
||||
let message_nonce = 1;
|
||||
let para_header_number = 5;
|
||||
let relay_header_number = 1;
|
||||
|
||||
let xcm = vec![xcm::v3::Instruction::<()>::ClearOrigin; 42];
|
||||
let expected_dispatch = xcm::VersionedXcm::<()>::V3(xcm.clone().into());
|
||||
// generate bridged relay chain finality, parachain heads and message proofs,
|
||||
// to be submitted by relayer to this chain.
|
||||
let (
|
||||
relay_chain_header,
|
||||
grandpa_justification,
|
||||
bridged_para_head,
|
||||
parachain_heads,
|
||||
para_heads_proof,
|
||||
message_proof,
|
||||
) = test_data::make_complex_relayer_proofs::<BridgedHeader<Runtime, GPI>, MB, ()>(
|
||||
lane_id,
|
||||
xcm.into(),
|
||||
message_nonce,
|
||||
message_destination,
|
||||
para_header_number,
|
||||
relay_header_number,
|
||||
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()],
|
||||
};
|
||||
|
||||
// sanity checks - before relayer extrinsic
|
||||
assert!(RuntimeHelper::<cumulus_pallet_xcmp_queue::Pallet<Runtime>>::take_xcm(
|
||||
sibling_parachain_id.into()
|
||||
)
|
||||
.is_none());
|
||||
assert_eq!(
|
||||
pallet_bridge_messages::InboundLanes::<Runtime, MPI>::get(lane_id)
|
||||
.last_delivered_nonce(),
|
||||
0,
|
||||
);
|
||||
let msg_proofs_rewards_account = RewardsAccountParams::new(
|
||||
lane_id,
|
||||
bridged_chain_id,
|
||||
RewardsAccountOwner::ThisChain,
|
||||
);
|
||||
assert_eq!(
|
||||
pallet_bridge_relayers::RelayerRewards::<Runtime>::get(
|
||||
relayer_id_on_target.clone(),
|
||||
msg_proofs_rewards_account
|
||||
),
|
||||
None,
|
||||
);
|
||||
|
||||
// construct and apply extrinsic containing batch calls:
|
||||
// bridged relay chain finality proof
|
||||
// + parachain heads proof
|
||||
// + submit message proof
|
||||
let dispatch_outcome = construct_and_apply_extrinsic(relayer_at_target, batch);
|
||||
|
||||
// verify finality proof correctly imported
|
||||
assert_ok!(dispatch_outcome);
|
||||
assert_eq!(
|
||||
<pallet_bridge_grandpa::BestFinalized<Runtime, GPI>>::get().unwrap().1,
|
||||
relay_chain_header.hash()
|
||||
);
|
||||
assert!(<pallet_bridge_grandpa::ImportedHeaders<Runtime, GPI>>::contains_key(
|
||||
relay_chain_header.hash()
|
||||
));
|
||||
// verify parachain head proof correctly imported
|
||||
assert_eq!(
|
||||
pallet_bridge_parachains::ParasInfo::<Runtime, PPI>::get(ParaId(bridged_para_id)),
|
||||
Some(ParaInfo {
|
||||
best_head_hash: BestParaHeadHash {
|
||||
at_relay_block_number: relay_header_number,
|
||||
head_hash: bridged_para_head.hash()
|
||||
},
|
||||
next_imported_hash_position: 1,
|
||||
})
|
||||
);
|
||||
// verify message correctly imported and dispatched
|
||||
assert_eq!(
|
||||
pallet_bridge_messages::InboundLanes::<Runtime, MPI>::get(lane_id)
|
||||
.last_delivered_nonce(),
|
||||
1,
|
||||
);
|
||||
// verify relayer is refunded
|
||||
assert!(pallet_bridge_relayers::RelayerRewards::<Runtime>::get(
|
||||
relayer_id_on_target,
|
||||
msg_proofs_rewards_account
|
||||
)
|
||||
.is_some());
|
||||
// verify relayed bridged XCM message is dispatched to destination sibling para
|
||||
let dispatched = RuntimeHelper::<cumulus_pallet_xcmp_queue::Pallet<Runtime>>::take_xcm(
|
||||
sibling_parachain_id.into(),
|
||||
)
|
||||
.unwrap();
|
||||
assert_eq!(dispatched, expected_dispatch);
|
||||
})
|
||||
}
|
||||
|
||||
pub mod test_data {
|
||||
use super::*;
|
||||
use bp_header_chain::justification::GrandpaJustification;
|
||||
use bp_messages::MessageNonce;
|
||||
use bp_polkadot_core::parachains::{ParaHash, ParaHead, ParaHeadsProof, ParaId};
|
||||
use bp_runtime::BasicOperatingMode;
|
||||
use bp_test_utils::authority_list;
|
||||
use xcm_builder::{HaulBlob, HaulBlobError, HaulBlobExporter};
|
||||
use xcm_executor::traits::{validate_export, ExportXcm};
|
||||
|
||||
pub fn prepare_inbound_xcm<InnerXcmRuntimeCall>(
|
||||
xcm_message: Xcm<InnerXcmRuntimeCall>,
|
||||
destination: InteriorMultiLocation,
|
||||
) -> Vec<u8> {
|
||||
let location = xcm::VersionedInteriorMultiLocation::V3(destination);
|
||||
let xcm = xcm::VersionedXcm::<InnerXcmRuntimeCall>::V3(xcm_message);
|
||||
// this is the `BridgeMessage` from polkadot xcm builder, but it has no constructor
|
||||
// or public fields, so just tuple
|
||||
// (double encoding, because `.encode()` is called on original Xcm BLOB when it is pushed
|
||||
// to the storage)
|
||||
(location, xcm).encode().encode()
|
||||
}
|
||||
|
||||
pub fn make_complex_relayer_proofs<BridgedRelayHeader, MB, InnerXcmRuntimeCall>(
|
||||
lane_id: LaneId,
|
||||
xcm_message: Xcm<InnerXcmRuntimeCall>,
|
||||
message_nonce: MessageNonce,
|
||||
message_destination: Junctions,
|
||||
para_header_number: u32,
|
||||
relay_header_number: u32,
|
||||
bridged_para_id: u32,
|
||||
) -> (
|
||||
BridgedRelayHeader,
|
||||
GrandpaJustification<BridgedRelayHeader>,
|
||||
ParaHead,
|
||||
Vec<(ParaId, ParaHash)>,
|
||||
ParaHeadsProof,
|
||||
FromBridgedChainMessagesProof<ParaHash>,
|
||||
)
|
||||
where
|
||||
BridgedRelayHeader: HeaderT,
|
||||
<BridgedRelayHeader as HeaderT>::Hash: From<H256>,
|
||||
MB: MessageBridge,
|
||||
<MB as MessageBridge>::BridgedChain: Send + Sync + 'static,
|
||||
UnderlyingChainOf<MessageBridgedChain<MB>>: bp_runtime::Chain<Hash = ParaHash> + Parachain,
|
||||
{
|
||||
let message_payload = prepare_inbound_xcm(xcm_message, message_destination);
|
||||
let message_size = StorageProofSize::Minimal(message_payload.len() as u32);
|
||||
// prepare para storage proof containing message
|
||||
let (para_state_root, para_storage_proof) = prepare_messages_storage_proof::<MB>(
|
||||
lane_id,
|
||||
message_nonce..=message_nonce,
|
||||
None,
|
||||
message_size,
|
||||
message_payload,
|
||||
encode_all_messages,
|
||||
encode_lane_data,
|
||||
);
|
||||
|
||||
let bridged_para_head = ParaHead(
|
||||
bp_test_utils::test_header_with_root::<HeaderOf<MB::BridgedChain>>(
|
||||
para_header_number.into(),
|
||||
para_state_root.into(),
|
||||
)
|
||||
.encode(),
|
||||
);
|
||||
let (relay_state_root, para_heads_proof, parachain_heads) =
|
||||
prepare_parachain_heads_proof::<HeaderOf<MB::BridgedChain>>(vec![(
|
||||
bridged_para_id,
|
||||
bridged_para_head.clone(),
|
||||
)]);
|
||||
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 justification = make_default_justification(&relay_chain_header);
|
||||
(
|
||||
relay_chain_header,
|
||||
justification,
|
||||
bridged_para_head,
|
||||
parachain_heads,
|
||||
para_heads_proof,
|
||||
message_proof,
|
||||
)
|
||||
}
|
||||
|
||||
/// Helper that creates InitializationData mock data, that can be used to initialize bridge GRANDPA pallet
|
||||
pub(crate) fn initialization_data<
|
||||
pub fn initialization_data<
|
||||
Runtime: pallet_bridge_grandpa::Config<GrandpaPalletInstance>,
|
||||
GrandpaPalletInstance: 'static,
|
||||
>(
|
||||
block_number: u32,
|
||||
) -> bp_header_chain::InitializationData<
|
||||
pallet_bridge_grandpa::BridgedHeader<Runtime, GrandpaPalletInstance>,
|
||||
> {
|
||||
) -> bp_header_chain::InitializationData<BridgedHeader<Runtime, GrandpaPalletInstance>> {
|
||||
bp_header_chain::InitializationData {
|
||||
header: Box::new(bp_test_utils::test_header(block_number.into())),
|
||||
authority_list: Default::default(),
|
||||
set_id: 6,
|
||||
operating_mode: bp_runtime::BasicOperatingMode::Normal,
|
||||
authority_list: authority_list(),
|
||||
set_id: 1,
|
||||
operating_mode: BasicOperatingMode::Normal,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user