Skip to content
This repository has been archived by the owner on Nov 15, 2023. It is now read-only.

Commit

Permalink
verify relayed bridged message is dispatched to sibling parachain
Browse files Browse the repository at this point in the history
  • Loading branch information
acatangiu committed May 16, 2023
1 parent 8eb9ac2 commit 099cbef
Show file tree
Hide file tree
Showing 2 changed files with 82 additions and 136 deletions.
31 changes: 10 additions & 21 deletions parachains/runtimes/bridge-hubs/bridge-hub-rococo/tests/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -172,27 +172,6 @@ mod bridge_hub_rococo_tests {
Rococo,
);

#[test]
fn receive_single_message_proof() {
bridge_hub_test_utils::test_cases::receive_single_message_proof::<
Runtime,
XcmConfig,
ParachainSystem,
BridgeGrandpaWococoInstance,
BridgeParachainWococoInstance,
WithBridgeHubWococoMessagesInstance,
WithBridgeHubWococoMessageBridge,
>(
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,
);
}

pub fn construct_extrinsic(
sender: sp_core::sr25519::Pair,
call: RuntimeCall,
Expand Down Expand Up @@ -308,6 +287,8 @@ mod bridge_hub_rococo_tests {
let some_currency = ExistentialDeposit::get() * 100000;
Balances::mint_into(&relayer_id_on_target, some_currency).unwrap();

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 (
Expand All @@ -320,8 +301,10 @@ mod bridge_hub_rococo_tests {
) = test_data::make_complex_relayer_proofs::<
BridgedHeader<Runtime, BridgeGrandpaWococoInstance>,
WithBridgeHubWococoMessageBridge,
(),
>(
lane_id,
xcm.into(),
message_nonce,
message_destination,
para_header_number,
Expand Down Expand Up @@ -435,6 +418,12 @@ mod bridge_hub_rococo_tests {
msg_proofs_rewards_account
)
.is_some());
// verify relayed bridged XCM message is dispatched to destination sibling para
let dispatched = test_data::take_outbound_message::<
cumulus_pallet_xcmp_queue::Pallet<Runtime>,
>(sibling_parachain_id.into())
.unwrap();
assert_eq!(dispatched, expected_dispatch);
})
}
}
Expand Down
187 changes: 72 additions & 115 deletions parachains/runtimes/bridge-hubs/test-utils/src/test_cases.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@

//! Module contains predefined test-case scenarios for `Runtime` with bridging capabilities.
use codec::Encode;
use codec::{DecodeLimit, Encode};
use frame_benchmarking::account;
use frame_support::{
assert_ok,
Expand Down Expand Up @@ -53,11 +53,10 @@ use bridge_runtime_common::{
target::FromBridgedChainMessagesProof, BridgedChain as MessageBridgedChain, MessageBridge,
},
messages_generation::{encode_all_messages, encode_lane_data, prepare_messages_storage_proof},
messages_utils::{prepare_inbound_message, prepare_message_proof_from_parachain},
messages_xcm_extension::{XcmAsPlainPayload, XcmBlobMessageDispatchResult},
};
use cumulus_primitives_core::XcmpMessageSource;
use pallet_bridge_grandpa::BridgedHeader;
use pallet_bridge_messages::{test_utils::MessageProofParams, EXPECTED_DEFAULT_MESSAGE_LENGTH};

/// Test-case makes sure that `Runtime` can process bridging initialize via governance-like call
pub fn initialize_bridge_by_governance_works<Runtime, GrandpaPalletInstance>(
Expand Down Expand Up @@ -498,6 +497,8 @@ pub fn relayed_incoming_message_works<Runtime, XcmConfig, HrmpChannelOpener, GPI
relayer_at_target.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 (
Expand All @@ -507,8 +508,9 @@ pub fn relayed_incoming_message_works<Runtime, XcmConfig, HrmpChannelOpener, GPI
parachain_heads,
para_heads_proof,
message_proof,
) = test_data::make_complex_relayer_proofs::<BridgedHeader<Runtime, GPI>, MB>(
) = test_data::make_complex_relayer_proofs::<BridgedHeader<Runtime, GPI>, MB, ()>(
lane_id,
xcm.into(),
message_nonce,
message_destination,
para_header_number,
Expand Down Expand Up @@ -553,7 +555,6 @@ pub fn relayed_incoming_message_works<Runtime, XcmConfig, HrmpChannelOpener, GPI
);

// import message
use cumulus_primitives_core::XcmpMessageSource;
assert!(cumulus_pallet_xcmp_queue::Pallet::<Runtime>::take_outbound_messages(
usize::MAX
)
Expand All @@ -578,6 +579,12 @@ pub fn relayed_incoming_message_works<Runtime, XcmConfig, HrmpChannelOpener, GPI
.last_delivered_nonce(),
1,
);
// verify relayed bridged XCM message is dispatched to destination sibling para
let dispatched = test_data::take_outbound_message::<
cumulus_pallet_xcmp_queue::Pallet<Runtime>,
>(sibling_parachain_id.into())
.unwrap();
assert_eq!(dispatched, expected_dispatch);
})
}

Expand Down Expand Up @@ -670,6 +677,8 @@ pub fn relayed_batch_works<Runtime, XcmConfig, HrmpChannelOpener, GPI, PPI, MPI,
let relayer_id_on_target =
account::<<Runtime as frame_system::Config>::AccountId>("relayer", 0, 0);

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 (
Expand All @@ -679,8 +688,9 @@ pub fn relayed_batch_works<Runtime, XcmConfig, HrmpChannelOpener, GPI, PPI, MPI,
parachain_heads,
para_heads_proof,
message_proof,
) = test_data::make_complex_relayer_proofs::<BridgedHeader<Runtime, GPI>, MB>(
) = test_data::make_complex_relayer_proofs::<BridgedHeader<Runtime, GPI>, MB, ()>(
lane_id,
xcm.into(),
message_nonce,
message_destination,
para_header_number,
Expand All @@ -689,7 +699,6 @@ pub fn relayed_batch_works<Runtime, XcmConfig, HrmpChannelOpener, GPI, PPI, MPI,
);

// import message sanity checks
use cumulus_primitives_core::XcmpMessageSource;
assert!(cumulus_pallet_xcmp_queue::Pallet::<Runtime>::take_outbound_messages(
usize::MAX
)
Expand Down Expand Up @@ -748,6 +757,12 @@ pub fn relayed_batch_works<Runtime, XcmConfig, HrmpChannelOpener, GPI, PPI, MPI,
.last_delivered_nonce(),
1,
);
// verify relayed bridged XCM message is dispatched to destination sibling para
let dispatched = test_data::take_outbound_message::<
cumulus_pallet_xcmp_queue::Pallet<Runtime>,
>(sibling_parachain_id.into())
.unwrap();
assert_eq!(dispatched, expected_dispatch);
})
}

Expand Down Expand Up @@ -790,104 +805,15 @@ macro_rules! include_relayed_incoming_message_works(
}
);

pub fn receive_single_message_proof<Runtime, XcmConfig, HrmpChannelOpener, GPI, PPI, MPI, MB>(
collator_session_key: CollatorSessionKeys<Runtime>,
runtime_para_id: u32,
sibling_parachain_id: u32,
) 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<GPI>
+ pallet_bridge_parachains::Config<PPI>
+ pallet_bridge_messages::Config<MPI, InboundPayload = XcmAsPlainPayload>,
ValidatorIdOf<Runtime>: From<AccountIdOf<Runtime>>,
XcmConfig: xcm_executor::Config,
HrmpChannelOpener: frame_support::inherent::ProvideInherent<
Call = cumulus_pallet_parachain_system::Call<Runtime>,
>,
GPI: 'static,
PPI: 'static,
MPI: 'static,
MB: MessageBridge,
UnderlyingChainOf<MessageBridgedChain<MB>>: bp_runtime::Chain<Hash = ParaHash> + Parachain,
<<Runtime as pallet_bridge_messages::Config<MPI>>::SourceHeaderChain as SourceHeaderChain>::MessagesProof: From<FromBridgedChainMessagesProof<H256>>,
{
assert_ne!(runtime_para_id, sibling_parachain_id);

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(|| {
// import message
let relayer_id_on_source =
pallet_bridge_messages::test_utils::default_bridged_relayer_id::<Runtime, MPI>();
let relayer_id_on_target =
account::<<Runtime as frame_system::Config>::AccountId>("relayer", 0, 0);

use cumulus_primitives_core::XcmpMessageSource;
assert!(cumulus_pallet_xcmp_queue::Pallet::<Runtime>::take_outbound_messages(
usize::MAX
)
.is_empty());

mock_open_hrmp_channel::<Runtime, HrmpChannelOpener>(runtime_para_id.into(), sibling_parachain_id.into());

let lane_id = LaneId([0, 0, 0, 0]);

let params = MessageProofParams {
// TODO: customize this with test parameters
lane: lane_id.clone(),
message_nonces: 1..=1,
outbound_lane_data: None,
is_successful_dispatch_expected: true,
size: StorageProofSize::Minimal(EXPECTED_DEFAULT_MESSAGE_LENGTH),
};

let (
proof,
dispatch_weight,
_
) = prepare_message_proof_from_parachain::<
Runtime,
PPI,
MB,
>(params, X2(GlobalConsensus(Rococo), Parachain(sibling_parachain_id)), None);

let proof: <<Runtime as pallet_bridge_messages::Config<MPI>>::SourceHeaderChain as SourceHeaderChain>::MessagesProof = proof.into();

assert_eq!(
pallet_bridge_messages::InboundLanes::<Runtime, MPI>::get(lane_id).last_delivered_nonce(),
0,
);
let result = pallet_bridge_messages::Pallet::<Runtime, MPI>::receive_messages_proof(RawOrigin::Signed(relayer_id_on_target).into(), relayer_id_on_source, proof, 1, dispatch_weight);
assert_ok!(result);
assert_eq!(
pallet_bridge_messages::InboundLanes::<Runtime, MPI>::get(lane_id).last_delivered_nonce(),
1,
);
// assert!(T::is_message_successfully_dispatched(21));
})
}

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 cumulus_primitives_core::XcmpMessageFormat;
use xcm::MAX_XCM_DECODE_DEPTH;
use xcm_builder::{HaulBlob, HaulBlobError, HaulBlobExporter};
use xcm_executor::traits::{validate_export, ExportXcm};

Expand All @@ -908,8 +834,22 @@ pub mod test_data {
)
}

pub fn make_complex_relayer_proofs<BridgedRelayHeader, MB>(
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,
Expand All @@ -930,21 +870,15 @@ pub mod test_data {
<MB as MessageBridge>::BridgedChain: Send + Sync + 'static,
UnderlyingChainOf<MessageBridgedChain<MB>>: bp_runtime::Chain<Hash = ParaHash> + Parachain,
{
let params = MessageProofParams {
lane: lane_id,
message_nonces: message_nonce..=message_nonce,
outbound_lane_data: None,
is_successful_dispatch_expected: true,
size: StorageProofSize::Minimal(EXPECTED_DEFAULT_MESSAGE_LENGTH),
};

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>(
params.lane,
params.message_nonces.clone(),
params.outbound_lane_data.clone(),
params.size,
prepare_inbound_message(&params, message_destination),
lane_id,
message_nonce..=message_nonce,
None,
message_size,
message_payload,
encode_all_messages,
encode_lane_data,
);
Expand All @@ -963,9 +897,9 @@ pub mod test_data {
let message_proof = FromBridgedChainMessagesProof {
bridged_header_hash: bridged_para_head.hash(),
storage_proof: para_storage_proof,
lane: params.lane,
nonces_start: *params.message_nonces.start(),
nonces_end: *params.message_nonces.end(),
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
Expand All @@ -984,6 +918,29 @@ pub mod test_data {
)
}

pub fn take_outbound_message<HrmpChannelSource: XcmpMessageSource>(
sent_to_para_id: cumulus_primitives_core::ParaId,
) -> Option<xcm::VersionedXcm<()>> {
match HrmpChannelSource::take_outbound_messages(10)[..] {
[(para_id, ref mut xcm_message_data)] if para_id.eq(&sent_to_para_id.into()) => {
let mut xcm_message_data = &xcm_message_data[..];
// decode
let _ = XcmpMessageFormat::decode_with_depth_limit(
MAX_XCM_DECODE_DEPTH,
&mut xcm_message_data,
)
.expect("valid format");
xcm::VersionedXcm::<()>::decode_with_depth_limit(
MAX_XCM_DECODE_DEPTH,
&mut xcm_message_data,
)
.map(|x| Some(x))
.expect("result with xcm")
},
_ => return None,
}
}

/// Helper that creates InitializationData mock data, that can be used to initialize bridge GRANDPA pallet
pub fn initialization_data<
Runtime: pallet_bridge_grandpa::Config<GrandpaPalletInstance>,
Expand Down

0 comments on commit 099cbef

Please sign in to comment.