Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix Snowbridge test resulting in overweight block #3

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Cargo.lock

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

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,7 @@ snowbridge-outbound-queue-runtime-api = { version = "0.10.0", default-features =
snowbridge-pallet-ethereum-client = { version = "0.10.0", default-features = false }
snowbridge-pallet-inbound-queue = { version = "0.10.0", default-features = false }
snowbridge-pallet-inbound-queue-fixtures = { version = "0.18.0" }
snowbridge-pallet-ethereum-client-fixtures = { version = "0.18.0" }
snowbridge-pallet-outbound-queue = { version = "0.10.0", default-features = false }
snowbridge-pallet-system = { version = "0.10.0", default-features = false }
snowbridge-router-primitives = { version = "0.16.0", default-features = false }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,7 @@ pallet-bridge-relayers = { workspace = true, features = ["integrity-test"] }
sp-keyring = { workspace = true }
static_assertions = { workspace = true }
snowbridge-runtime-test-common = { workspace = true }
snowbridge-pallet-ethereum-client-fixtures = { workspace = true }
parachains-runtimes-test-utils = { workspace = true }

[features]
Expand Down

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

162 changes: 153 additions & 9 deletions system-parachains/bridge-hubs/bridge-hub-polkadot/tests/snowbridge.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,23 +27,31 @@ use bridge_hub_polkadot_runtime::{
};
use codec::{Decode, Encode};
use cumulus_primitives_core::XcmError::{FailedToTransactAsset, TooExpensive};
use frame_support::{parameter_types, traits::Contains};
use frame_support::{
assert_err, assert_ok, parameter_types,
traits::{fungible::Mutate, Contains},
};
use parachains_common::{AccountId, AuraId, Balance};
pub use parachains_runtimes_test_utils::test_cases::change_storage_constant_by_governance_works;
use parachains_runtimes_test_utils::{
AccountIdOf, BalanceOf, CollatorSessionKeys, ExtBuilder, ValidatorIdOf,
};
use snowbridge_pallet_ethereum_client::WeightInfo;
use sp_core::H160;
use snowbridge_pallet_ethereum_client_fixtures::*;
use sp_core::{Get, H160};
use sp_keyring::AccountKeyring::Alice;
use sp_runtime::{
generic::{Era, SignedPayload},
AccountId32,
AccountId32, SaturatedConversion,
};
use xcm::latest::prelude::*;
use xcm_builder::HandleFee;
use xcm_executor::traits::{FeeManager, FeeReason};

parameter_types! {
pub const DefaultBridgeHubEthereumBaseFee: Balance = 2_750_872_500_000;
}
type RuntimeHelper<Runtime, AllPalletsWithoutSystem = ()> =
parachains_runtimes_test_utils::RuntimeHelper<Runtime, AllPalletsWithoutSystem>;

fn collator_session_keys() -> bridge_hub_test_utils::CollatorSessionKeys<Runtime> {
bridge_hub_test_utils::CollatorSessionKeys::new(
Expand Down Expand Up @@ -199,11 +207,7 @@ fn max_message_queue_service_weight_is_more_than_beacon_extrinsic_weights() {
// FAIL-CI @bkontur can you help me to check why it's exceeding the weight limits?
#[test]
fn ethereum_client_consensus_extrinsics_work() {
snowbridge_runtime_test_common::ethereum_extrinsic(
collator_session_keys(),
1013,
construct_and_apply_extrinsic,
);
ethereum_extrinsic(collator_session_keys(), 1013, construct_and_apply_extrinsic);
}

#[test]
Expand Down Expand Up @@ -238,6 +242,146 @@ fn ethereum_outbound_queue_processes_messages_before_message_queue_works() {
)
}

// TODO replace with snowbridge runtime common method in stable-2412 release.
pub fn ethereum_extrinsic<Runtime>(
collator_session_key: CollatorSessionKeys<Runtime>,
runtime_para_id: u32,
construct_and_apply_extrinsic: fn(
sp_keyring::AccountKeyring,
<Runtime as frame_system::Config>::RuntimeCall,
) -> sp_runtime::DispatchOutcome,
) where
Runtime: frame_system::Config
+ pallet_balances::Config
+ pallet_session::Config
+ pallet_xcm::Config
+ pallet_utility::Config
+ parachain_info::Config
+ pallet_collator_selection::Config
+ cumulus_pallet_parachain_system::Config
+ snowbridge_pallet_outbound_queue::Config
+ snowbridge_pallet_system::Config
+ snowbridge_pallet_ethereum_client::Config
+ pallet_timestamp::Config,
ValidatorIdOf<Runtime>: From<AccountIdOf<Runtime>>,
<Runtime as pallet_utility::Config>::RuntimeCall:
From<snowbridge_pallet_ethereum_client::Call<Runtime>>,
<Runtime as frame_system::Config>::RuntimeCall: From<pallet_utility::Call<Runtime>>,
AccountIdOf<Runtime>: From<AccountId32>,
{
ExtBuilder::<Runtime>::default()
.with_collators(collator_session_key.collators())
.with_session_keys(collator_session_key.session_keys())
.with_para_id(runtime_para_id.into())
.with_tracing()
.build()
.execute_with(|| {
let initial_checkpoint = make_checkpoint();
let update = make_finalized_header_update();
let sync_committee_update = make_sync_committee_update();
let mut invalid_update = make_finalized_header_update();
let mut invalid_sync_committee_update = make_sync_committee_update();
invalid_update.finalized_header.slot = 4354;
invalid_sync_committee_update.finalized_header.slot = 4354;

let alice = Alice;
let alice_account = alice.to_account_id();
<pallet_balances::Pallet<Runtime>>::mint_into(
&alice_account.clone().into(),
10_000_000_000_000_u128.saturated_into::<BalanceOf<Runtime>>(),
)
.unwrap();
let balance_before =
<pallet_balances::Pallet<Runtime>>::free_balance(&alice_account.clone().into());

assert_ok!(<snowbridge_pallet_ethereum_client::Pallet<Runtime>>::force_checkpoint(
RuntimeHelper::<Runtime>::root_origin(),
initial_checkpoint.clone(),
));
let balance_after_checkpoint =
<pallet_balances::Pallet<Runtime>>::free_balance(&alice_account.clone().into());

let update_call: <Runtime as pallet_utility::Config>::RuntimeCall =
snowbridge_pallet_ethereum_client::Call::<Runtime>::submit {
update: Box::new(*update.clone()),
}
.into();

let invalid_update_call: <Runtime as pallet_utility::Config>::RuntimeCall =
snowbridge_pallet_ethereum_client::Call::<Runtime>::submit {
update: Box::new(*invalid_update),
}
.into();

let update_sync_committee_call: <Runtime as pallet_utility::Config>::RuntimeCall =
snowbridge_pallet_ethereum_client::Call::<Runtime>::submit {
update: Box::new(*sync_committee_update),
}
.into();

let invalid_update_sync_committee_call: <Runtime as pallet_utility::Config>::RuntimeCall =
snowbridge_pallet_ethereum_client::Call::<Runtime>::submit {
update: Box::new(*invalid_sync_committee_update),
}
.into();

// Finalized header update
let update_outcome = construct_and_apply_extrinsic(alice, update_call.into());
assert_ok!(update_outcome);
let balance_after_update =
<pallet_balances::Pallet<Runtime>>::free_balance(&alice_account.clone().into());

// All the extrinsics in this test do no fit into 1 block
let _ = RuntimeHelper::<Runtime>::run_to_block(2, AccountId::from(alice).into());

// Invalid finalized header update
let invalid_update_outcome =
construct_and_apply_extrinsic(alice, invalid_update_call.into());
assert_err!(
invalid_update_outcome,
snowbridge_pallet_ethereum_client::Error::<Runtime>::InvalidUpdateSlot
);
let balance_after_invalid_update =
<pallet_balances::Pallet<Runtime>>::free_balance(&alice_account.clone().into());

// Sync committee update
let sync_committee_outcome =
construct_and_apply_extrinsic(alice, update_sync_committee_call.into());
assert_ok!(sync_committee_outcome);
let balance_after_sync_com_update =
<pallet_balances::Pallet<Runtime>>::free_balance(&alice_account.clone().into());

// Invalid sync committee update
let invalid_sync_committee_outcome =
construct_and_apply_extrinsic(alice, invalid_update_sync_committee_call.into());
assert_err!(
invalid_sync_committee_outcome,
snowbridge_pallet_ethereum_client::Error::<Runtime>::InvalidUpdateSlot
);
let balance_after_invalid_sync_com_update =
<pallet_balances::Pallet<Runtime>>::free_balance(&alice_account.clone().into());

// Assert paid operations are charged and free operations are free
// Checkpoint is a free operation
assert!(balance_before == balance_after_checkpoint);
let gap =
<Runtime as snowbridge_pallet_ethereum_client::Config>::FreeHeadersInterval::get();
// Large enough header gap is free
if update.finalized_header.slot >= initial_checkpoint.header.slot + gap as u64 {
assert!(balance_after_checkpoint == balance_after_update);
} else {
// Otherwise paid
assert!(balance_after_checkpoint > balance_after_update);
}
// An invalid update is paid
assert!(balance_after_update > balance_after_invalid_update);
// A successful sync committee update is free
assert!(balance_after_invalid_update == balance_after_sync_com_update);
// An invalid sync committee update is paid
assert!(balance_after_sync_com_update > balance_after_invalid_sync_com_update);
});
}

fn construct_extrinsic(
sender: sp_keyring::AccountKeyring,
call: RuntimeCall,
Expand Down
Loading