Files
pezkuwi-subxt/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/tests/snowbridge.rs
T
Clara van Staden 5a06771ecc Snowbridge - Test pallet order (#3381)
- Adds a test to check the correct digest for Snowbridge outbound
messages. For the correct digest to be in the block, the the
MessageQueue pallet should be configured after the EthereumOutbound
queue pallet. The added test fails if the EthereumOutbound is configured
after the MessageQueue pallet.
- Adds a helper method `run_to_block_with_finalize` to simulate the
block finalizing. The existing `run_to_block` method does not finalize
and so it cannot successfully test this condition.

Closes: https://github.com/paritytech/polkadot-sdk/issues/3208

---------

Co-authored-by: claravanstaden <Cats 4 life!>
2024-02-21 14:48:40 +00:00

204 lines
6.3 KiB
Rust

// Copyright (C) Parity Technologies (UK) Ltd.
// This file is part of Cumulus.
// Cumulus is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// Cumulus is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with Cumulus. If not, see <http://www.gnu.org/licenses/>.
#![cfg(test)]
use bp_polkadot_core::Signature;
use bridge_hub_rococo_runtime::{
bridge_to_bulletin_config::OnBridgeHubRococoRefundRococoBulletinMessages,
bridge_to_westend_config::OnBridgeHubRococoRefundBridgeHubWestendMessages,
xcm_config::XcmConfig, AllPalletsWithoutSystem, BridgeRejectObsoleteHeadersAndMessages,
Executive, MessageQueueServiceWeight, Runtime, RuntimeCall, RuntimeEvent, SessionKeys,
SignedExtra, UncheckedExtrinsic,
};
use codec::{Decode, Encode};
use cumulus_primitives_core::XcmError::{FailedToTransactAsset, NotHoldingFees};
use frame_support::parameter_types;
use parachains_common::{AccountId, AuraId, Balance};
use snowbridge_pallet_ethereum_client::WeightInfo;
use sp_core::H160;
use sp_keyring::AccountKeyring::Alice;
use sp_runtime::{
generic::{Era, SignedPayload},
AccountId32,
};
parameter_types! {
pub const DefaultBridgeHubEthereumBaseFee: Balance = 2_750_872_500_000;
}
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()) },
)
}
#[test]
pub fn transfer_token_to_ethereum_works() {
snowbridge_runtime_test_common::send_transfer_token_message_success::<Runtime, XcmConfig>(
collator_session_keys(),
1013,
1000,
H160::random(),
H160::random(),
DefaultBridgeHubEthereumBaseFee::get(),
Box::new(|runtime_event_encoded: Vec<u8>| {
match RuntimeEvent::decode(&mut &runtime_event_encoded[..]) {
Ok(RuntimeEvent::EthereumOutboundQueue(event)) => Some(event),
_ => None,
}
}),
)
}
#[test]
pub fn unpaid_transfer_token_to_ethereum_fails_with_barrier() {
snowbridge_runtime_test_common::send_unpaid_transfer_token_message::<Runtime, XcmConfig>(
collator_session_keys(),
1013,
1000,
H160::random(),
H160::random(),
)
}
#[test]
pub fn transfer_token_to_ethereum_fee_not_enough() {
snowbridge_runtime_test_common::send_transfer_token_message_failure::<Runtime, XcmConfig>(
collator_session_keys(),
1013,
1000,
DefaultBridgeHubEthereumBaseFee::get() + 1_000_000_000,
H160::random(),
H160::random(),
// fee not enough
1_000_000_000,
NotHoldingFees,
)
}
#[test]
pub fn transfer_token_to_ethereum_insufficient_fund() {
snowbridge_runtime_test_common::send_transfer_token_message_failure::<Runtime, XcmConfig>(
collator_session_keys(),
1013,
1000,
1_000_000_000,
H160::random(),
H160::random(),
DefaultBridgeHubEthereumBaseFee::get(),
FailedToTransactAsset("Funds are unavailable"),
)
}
#[test]
fn max_message_queue_service_weight_is_more_than_beacon_extrinsic_weights() {
let max_message_queue_weight = MessageQueueServiceWeight::get();
let force_checkpoint =
<Runtime as snowbridge_pallet_ethereum_client::Config>::WeightInfo::force_checkpoint();
let submit_checkpoint =
<Runtime as snowbridge_pallet_ethereum_client::Config>::WeightInfo::submit();
max_message_queue_weight.all_gt(force_checkpoint);
max_message_queue_weight.all_gt(submit_checkpoint);
}
#[test]
fn ethereum_client_consensus_extrinsics_work() {
snowbridge_runtime_test_common::ethereum_extrinsic(
collator_session_keys(),
1013,
construct_and_apply_extrinsic,
);
}
#[test]
fn ethereum_to_polkadot_message_extrinsics_work() {
snowbridge_runtime_test_common::ethereum_to_polkadot_message_extrinsics_work(
collator_session_keys(),
1013,
construct_and_apply_extrinsic,
);
}
/// Tests that the digest items are as expected when a Ethereum Outbound message is received.
/// If the MessageQueue pallet is configured before (i.e. the MessageQueue pallet is listed before
/// the EthereumOutboundQueue in the construct_runtime macro) the EthereumOutboundQueue, this test
/// will fail.
#[test]
pub fn ethereum_outbound_queue_processes_messages_before_message_queue_works() {
snowbridge_runtime_test_common::ethereum_outbound_queue_processes_messages_before_message_queue_works::<
Runtime,
XcmConfig,
AllPalletsWithoutSystem,
>(
collator_session_keys(),
1013,
1000,
H160::random(),
H160::random(),
DefaultBridgeHubEthereumBaseFee::get(),
Box::new(|runtime_event_encoded: Vec<u8>| {
match RuntimeEvent::decode(&mut &runtime_event_encoded[..]) {
Ok(RuntimeEvent::EthereumOutboundQueue(event)) => Some(event),
_ => None,
}
}),
)
}
fn construct_extrinsic(
sender: sp_keyring::AccountKeyring,
call: RuntimeCall,
) -> UncheckedExtrinsic {
let account_id = AccountId32::from(sender.public());
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(
frame_system::Pallet::<Runtime>::account(&account_id).nonce,
),
frame_system::CheckWeight::<Runtime>::new(),
pallet_transaction_payment::ChargeTransactionPayment::<Runtime>::from(0),
BridgeRejectObsoleteHeadersAndMessages::default(),
(
OnBridgeHubRococoRefundBridgeHubWestendMessages::default(),
OnBridgeHubRococoRefundRococoBulletinMessages::default(),
),
);
let payload = SignedPayload::new(call.clone(), extra.clone()).unwrap();
let signature = payload.using_encoded(|e| sender.sign(e));
UncheckedExtrinsic::new_signed(
call,
account_id.into(),
Signature::Sr25519(signature.clone()),
extra,
)
}
fn construct_and_apply_extrinsic(
origin: sp_keyring::AccountKeyring,
call: RuntimeCall,
) -> sp_runtime::DispatchOutcome {
let xt = construct_extrinsic(origin, call);
let r = Executive::apply_extrinsic(xt);
r.unwrap()
}