diff --git a/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-rococo/src/tests/treasury.rs b/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-rococo/src/tests/treasury.rs index f8190e11c51c8..0de87cf61adb6 100644 --- a/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-rococo/src/tests/treasury.rs +++ b/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-rococo/src/tests/treasury.rs @@ -77,7 +77,7 @@ fn spend_roc_on_asset_hub() { })), }); - // Dispatched from Root to `despatch_as` `Signed(treasury_account)`. + // Dispatched from Root to `dispatch_as` `Signed(treasury_account)`. assert_ok!(teleport_call.dispatch(root)); assert_expected_events!( diff --git a/cumulus/parachains/runtimes/assets/asset-hub-rococo/tests/tests.rs b/cumulus/parachains/runtimes/assets/asset-hub-rococo/tests/tests.rs index 5374a956bfac7..c121a0792e2d0 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-rococo/tests/tests.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-rococo/tests/tests.rs @@ -21,7 +21,11 @@ use asset_hub_rococo_runtime::{ xcm_config, xcm_config::{ bridging, AssetFeeAsExistentialDepositMultiplierFeeCharger, CheckingAccount, +<<<<<<< HEAD ForeignAssetFeeAsExistentialDepositMultiplierFeeCharger, ForeignCreatorsSovereignAccountOf, +======= + ForeignAssetFeeAsExistentialDepositMultiplierFeeCharger, GovernanceLocation, +>>>>>>> e9be92d6 (Authorize upgrade tests for testnet runtimes + `execute_as_governance` refactor (#7656)) LocationToAccountId, StakingPot, TokenLocation, TrustBackedAssetsPalletLocation, XcmConfig, }, AllPalletsWithoutSystem, AssetConversion, AssetDeposit, Assets, Balances, Block, @@ -31,13 +35,13 @@ use asset_hub_rococo_runtime::{ }; use asset_test_utils::{ test_cases_over_bridge::TestBridgingConfig, CollatorSessionKey, CollatorSessionKeys, - ExtBuilder, SlotDurations, + ExtBuilder, GovernanceOrigin, SlotDurations, }; use codec::{Decode, Encode}; use core::ops::Mul; use cumulus_primitives_utility::ChargeWeightInFungibles; use frame_support::{ - assert_noop, assert_ok, + assert_noop, assert_ok, parameter_types, traits::{ fungible::{Inspect, Mutate}, fungibles::{ @@ -58,6 +62,10 @@ use xcm_executor::traits::{JustTry, WeightTrader}; const ALICE: [u8; 32] = [1u8; 32]; const SOME_ASSET_ADMIN: [u8; 32] = [5u8; 32]; +parameter_types! { + pub Governance: GovernanceOrigin = GovernanceOrigin::Location(GovernanceLocation::get()); +} + type AssetIdForTrustBackedAssetsConvert = assets_common::AssetIdForTrustBackedAssetsConvert; @@ -1393,7 +1401,7 @@ fn change_xcm_bridge_hub_router_byte_fee_by_governance_works() { >( collator_session_keys(), 1000, - Box::new(|call| RuntimeCall::System(call).encode()), + Governance::get(), || { ( bridging::XcmBridgeHubRouterByteFee::key().to_vec(), @@ -1419,7 +1427,7 @@ fn change_xcm_bridge_hub_router_base_fee_by_governance_works() { >( collator_session_keys(), 1000, - Box::new(|call| RuntimeCall::System(call).encode()), + Governance::get(), || { log::error!( target: "bridges::estimate", @@ -1451,7 +1459,7 @@ fn change_xcm_bridge_hub_ethereum_base_fee_by_governance_works() { >( collator_session_keys(), 1000, - Box::new(|call| RuntimeCall::System(call).encode()), + Governance::get(), || { log::error!( target: "bridges::estimate", diff --git a/cumulus/parachains/runtimes/assets/asset-hub-westend/src/xcm_config.rs b/cumulus/parachains/runtimes/assets/asset-hub-westend/src/xcm_config.rs index 2deeb73eb127b..60367f8f88275 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-westend/src/xcm_config.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-westend/src/xcm_config.rs @@ -42,8 +42,15 @@ use parachains_common::{ }; use polkadot_parachain_primitives::primitives::Sibling; use polkadot_runtime_common::xcm_sender::ExponentialPrice; +<<<<<<< HEAD use sp_runtime::traits::{AccountIdConversion, ConvertInto}; use xcm::latest::prelude::*; +======= +use snowbridge_router_primitives::inbound::EthereumLocationsConverterFor; +use sp_runtime::traits::{AccountIdConversion, ConvertInto, TryConvertInto}; +use westend_runtime_constants::system_parachain::COLLECTIVES_ID; +use xcm::latest::{prelude::*, ROCOCO_GENESIS_HASH, WESTEND_GENESIS_HASH}; +>>>>>>> e9be92d6 (Authorize upgrade tests for testnet runtimes + `execute_as_governance` refactor (#7656)) use xcm_builder::{ AccountId32Aliases, AllowExplicitUnpaidExecutionFrom, AllowHrmpNotificationsFromRelayChain, AllowKnownQueryResponses, AllowSubscriptionsFrom, AllowTopLevelPaidExecutionFrom, @@ -261,9 +268,9 @@ impl Contains for FellowshipEntities { fn contains(location: &Location) -> bool { matches!( location.unpack(), - (1, [Parachain(1001), Plurality { id: BodyId::Technical, .. }]) | - (1, [Parachain(1001), PalletInstance(64)]) | - (1, [Parachain(1001), PalletInstance(65)]) + (1, [Parachain(COLLECTIVES_ID), Plurality { id: BodyId::Technical, .. }]) | + (1, [Parachain(COLLECTIVES_ID), PalletInstance(64)]) | + (1, [Parachain(COLLECTIVES_ID), PalletInstance(65)]) ) } } @@ -271,7 +278,7 @@ impl Contains for FellowshipEntities { pub struct AmbassadorEntities; impl Contains for AmbassadorEntities { fn contains(location: &Location) -> bool { - matches!(location.unpack(), (1, [Parachain(1001), PalletInstance(74)])) + matches!(location.unpack(), (1, [Parachain(COLLECTIVES_ID), PalletInstance(74)])) } } diff --git a/cumulus/parachains/runtimes/assets/asset-hub-westend/tests/tests.rs b/cumulus/parachains/runtimes/assets/asset-hub-westend/tests/tests.rs index 2620fc93992b8..177d56673dabd 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-westend/tests/tests.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-westend/tests/tests.rs @@ -21,7 +21,11 @@ use asset_hub_westend_runtime::{ xcm_config, xcm_config::{ bridging, AssetFeeAsExistentialDepositMultiplierFeeCharger, CheckingAccount, +<<<<<<< HEAD ForeignAssetFeeAsExistentialDepositMultiplierFeeCharger, ForeignCreatorsSovereignAccountOf, +======= + ForeignAssetFeeAsExistentialDepositMultiplierFeeCharger, GovernanceLocation, +>>>>>>> e9be92d6 (Authorize upgrade tests for testnet runtimes + `execute_as_governance` refactor (#7656)) LocationToAccountId, StakingPot, TrustBackedAssetsPalletLocation, WestendLocation, XcmConfig, }, @@ -33,12 +37,12 @@ use asset_hub_westend_runtime::{ pub use asset_hub_westend_runtime::{AssetConversion, AssetDeposit, CollatorSelection, System}; use asset_test_utils::{ test_cases_over_bridge::TestBridgingConfig, CollatorSessionKey, CollatorSessionKeys, - ExtBuilder, SlotDurations, + ExtBuilder, GovernanceOrigin, SlotDurations, }; use codec::{Decode, Encode}; use cumulus_primitives_utility::ChargeWeightInFungibles; use frame_support::{ - assert_noop, assert_ok, + assert_err, assert_noop, assert_ok, parameter_types, traits::{ fungible::{Inspect, Mutate}, fungibles::{ @@ -49,7 +53,12 @@ use frame_support::{ }; use parachains_common::{AccountId, AssetIdForTrustBackedAssets, AuraId, Balance}; use sp_consensus_aura::SlotDuration; +<<<<<<< HEAD use sp_runtime::traits::MaybeEquivalence; +======= +use sp_core::crypto::Ss58Codec; +use sp_runtime::{traits::MaybeEquivalence, Either}; +>>>>>>> e9be92d6 (Authorize upgrade tests for testnet runtimes + `execute_as_governance` refactor (#7656)) use std::{convert::Into, ops::Mul}; use testnet_parachains_constants::westend::{consensus::*, currency::UNITS, fee::WeightToFee}; use xcm::latest::prelude::{Assets as XcmAssets, *}; @@ -59,6 +68,10 @@ use xcm_executor::traits::{ConvertLocation, JustTry, WeightTrader}; const ALICE: [u8; 32] = [1u8; 32]; const SOME_ASSET_ADMIN: [u8; 32] = [5u8; 32]; +parameter_types! { + pub Governance: GovernanceOrigin = GovernanceOrigin::Location(GovernanceLocation::get()); +} + type AssetIdForTrustBackedAssetsConvert = assets_common::AssetIdForTrustBackedAssetsConvert; @@ -1341,7 +1354,7 @@ fn change_xcm_bridge_hub_router_byte_fee_by_governance_works() { >( collator_session_keys(), 1000, - Box::new(|call| RuntimeCall::System(call).encode()), + Governance::get(), || { ( bridging::XcmBridgeHubRouterByteFee::key().to_vec(), @@ -1367,7 +1380,7 @@ fn change_xcm_bridge_hub_router_base_fee_by_governance_works() { >( collator_session_keys(), 1000, - Box::new(|call| RuntimeCall::System(call).encode()), + Governance::get(), || { log::error!( target: "bridges::estimate", @@ -1435,3 +1448,54 @@ fn xcm_payment_api_works() { Block, >(); } + +#[test] +fn governance_authorize_upgrade_works() { + use westend_runtime_constants::system_parachain::{ASSET_HUB_ID, COLLECTIVES_ID}; + + // no - random para + assert_err!( + parachains_runtimes_test_utils::test_cases::can_governance_authorize_upgrade::< + Runtime, + RuntimeOrigin, + >(GovernanceOrigin::Location(Location::new(1, Parachain(12334)))), + Either::Right(XcmError::Barrier) + ); + // no - AssetHub + assert_err!( + parachains_runtimes_test_utils::test_cases::can_governance_authorize_upgrade::< + Runtime, + RuntimeOrigin, + >(GovernanceOrigin::Location(Location::new(1, Parachain(ASSET_HUB_ID)))), + Either::Right(XcmError::Barrier) + ); + // no - Collectives + assert_err!( + parachains_runtimes_test_utils::test_cases::can_governance_authorize_upgrade::< + Runtime, + RuntimeOrigin, + >(GovernanceOrigin::Location(Location::new(1, Parachain(COLLECTIVES_ID)))), + Either::Right(XcmError::Barrier) + ); + // no - Collectives Voice of Fellows plurality + assert_err!( + parachains_runtimes_test_utils::test_cases::can_governance_authorize_upgrade::< + Runtime, + RuntimeOrigin, + >(GovernanceOrigin::LocationAndDescendOrigin( + Location::new(1, Parachain(COLLECTIVES_ID)), + Plurality { id: BodyId::Technical, part: BodyPart::Voice }.into() + )), + Either::Right(XcmError::BadOrigin) + ); + + // ok - relaychain + assert_ok!(parachains_runtimes_test_utils::test_cases::can_governance_authorize_upgrade::< + Runtime, + RuntimeOrigin, + >(GovernanceOrigin::Location(Location::parent()))); + assert_ok!(parachains_runtimes_test_utils::test_cases::can_governance_authorize_upgrade::< + Runtime, + RuntimeOrigin, + >(GovernanceOrigin::Location(GovernanceLocation::get()))); +} diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/tests/tests.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/tests/tests.rs index 180785b18069a..1821217d10c4f 100644 --- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/tests/tests.rs +++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/tests/tests.rs @@ -24,7 +24,7 @@ use bridge_hub_rococo_runtime::{ ExistentialDeposit, ParachainSystem, PolkadotXcm, Runtime, RuntimeCall, RuntimeEvent, RuntimeOrigin, SessionKeys, SignedExtra, TransactionPayment, UncheckedExtrinsic, }; -use bridge_hub_test_utils::SlotDurations; +use bridge_hub_test_utils::{GovernanceOrigin, SlotDurations}; use codec::{Decode, Encode}; use frame_support::{dispatch::GetDispatchInfo, parameter_types, traits::ConstU8}; use parachains_common::{AccountId, AuraId, Balance}; @@ -41,6 +41,7 @@ use xcm::latest::prelude::*; parameter_types! { pub CheckingAccount: AccountId = PolkadotXcm::check_account(); + pub Governance: GovernanceOrigin = GovernanceOrigin::Location(Location::parent()); } fn construct_extrinsic( @@ -169,7 +170,11 @@ mod bridge_hub_westend_tests { bridge_hub_test_utils::test_cases::initialize_bridge_by_governance_works::< Runtime, BridgeGrandpaWestendInstance, - >(collator_session_keys(), bp_bridge_hub_rococo::BRIDGE_HUB_ROCOCO_PARACHAIN_ID) + >( + collator_session_keys(), + bp_bridge_hub_rococo::BRIDGE_HUB_ROCOCO_PARACHAIN_ID, + Governance::get(), + ) } #[test] @@ -178,7 +183,11 @@ mod bridge_hub_westend_tests { bridge_hub_test_utils::test_cases::change_bridge_grandpa_pallet_mode_by_governance_works::< Runtime, BridgeGrandpaWestendInstance, - >(collator_session_keys(), bp_bridge_hub_rococo::BRIDGE_HUB_ROCOCO_PARACHAIN_ID) + >( + collator_session_keys(), + bp_bridge_hub_rococo::BRIDGE_HUB_ROCOCO_PARACHAIN_ID, + Governance::get(), + ) } #[test] @@ -187,7 +196,11 @@ mod bridge_hub_westend_tests { bridge_hub_test_utils::test_cases::change_bridge_parachains_pallet_mode_by_governance_works::< Runtime, BridgeParachainWestendInstance, - >(collator_session_keys(), bp_bridge_hub_rococo::BRIDGE_HUB_ROCOCO_PARACHAIN_ID) + >( + collator_session_keys(), + bp_bridge_hub_rococo::BRIDGE_HUB_ROCOCO_PARACHAIN_ID, + Governance::get(), + ) } #[test] @@ -196,7 +209,11 @@ mod bridge_hub_westend_tests { bridge_hub_test_utils::test_cases::change_bridge_messages_pallet_mode_by_governance_works::< Runtime, WithBridgeHubWestendMessagesInstance, - >(collator_session_keys(), bp_bridge_hub_rococo::BRIDGE_HUB_ROCOCO_PARACHAIN_ID) + >( + collator_session_keys(), + bp_bridge_hub_rococo::BRIDGE_HUB_ROCOCO_PARACHAIN_ID, + Governance::get(), + ) } #[test] @@ -208,7 +225,7 @@ mod bridge_hub_westend_tests { >( collator_session_keys(), bp_bridge_hub_rococo::BRIDGE_HUB_ROCOCO_PARACHAIN_ID, - Box::new(|call| RuntimeCall::System(call).encode()), + Governance::get(), || (EthereumGatewayAddress::key().to_vec(), EthereumGatewayAddress::get()), |_| [1; 20].into(), ) @@ -224,7 +241,7 @@ mod bridge_hub_westend_tests { bridge_hub_test_utils::test_cases::set_storage_keys_by_governance_works::( collator_session_keys(), bp_bridge_hub_rococo::BRIDGE_HUB_ROCOCO_PARACHAIN_ID, - Box::new(|call| RuntimeCall::System(call).encode()), + Governance::get(), vec![ (snowbridge_pallet_outbound_queue::Nonce::::hashed_key_for::( channel_id_one, @@ -289,7 +306,7 @@ mod bridge_hub_westend_tests { >( collator_session_keys(), bp_bridge_hub_rococo::BRIDGE_HUB_ROCOCO_PARACHAIN_ID, - Box::new(|call| RuntimeCall::System(call).encode()), + Governance::get(), || (DeliveryRewardInBalance::key().to_vec(), DeliveryRewardInBalance::get()), |old_value| old_value.checked_mul(2).unwrap(), ) @@ -476,7 +493,11 @@ mod bridge_hub_bulletin_tests { bridge_hub_test_utils::test_cases::initialize_bridge_by_governance_works::< Runtime, BridgeGrandpaRococoBulletinInstance, - >(collator_session_keys(), bp_bridge_hub_rococo::BRIDGE_HUB_ROCOCO_PARACHAIN_ID) + >( + collator_session_keys(), + bp_bridge_hub_rococo::BRIDGE_HUB_ROCOCO_PARACHAIN_ID, + Governance::get(), + ) } #[test] @@ -485,7 +506,11 @@ mod bridge_hub_bulletin_tests { bridge_hub_test_utils::test_cases::change_bridge_grandpa_pallet_mode_by_governance_works::< Runtime, BridgeGrandpaRococoBulletinInstance, - >(collator_session_keys(), bp_bridge_hub_rococo::BRIDGE_HUB_ROCOCO_PARACHAIN_ID) + >( + collator_session_keys(), + bp_bridge_hub_rococo::BRIDGE_HUB_ROCOCO_PARACHAIN_ID, + Governance::get(), + ) } #[test] @@ -494,7 +519,11 @@ mod bridge_hub_bulletin_tests { bridge_hub_test_utils::test_cases::change_bridge_messages_pallet_mode_by_governance_works::< Runtime, WithRococoBulletinMessagesInstance, - >(collator_session_keys(), bp_bridge_hub_rococo::BRIDGE_HUB_ROCOCO_PARACHAIN_ID) + >( + collator_session_keys(), + bp_bridge_hub_rococo::BRIDGE_HUB_ROCOCO_PARACHAIN_ID, + Governance::get(), + ) } #[test] @@ -594,6 +623,140 @@ mod bridge_hub_bulletin_tests { } #[test] +<<<<<<< HEAD +======= +fn change_required_stake_by_governance_works() { + bridge_hub_test_utils::test_cases::change_storage_constant_by_governance_works::< + Runtime, + bridge_common_config::RequiredStakeForStakeAndSlash, + Balance, + >( + collator_session_keys(), + bp_bridge_hub_rococo::BRIDGE_HUB_ROCOCO_PARACHAIN_ID, + Governance::get(), + || { + ( + bridge_common_config::RequiredStakeForStakeAndSlash::key().to_vec(), + bridge_common_config::RequiredStakeForStakeAndSlash::get(), + ) + }, + |old_value| old_value.checked_mul(2).unwrap(), + ) +} + +#[test] +fn location_conversion_works() { + // the purpose of hardcoded values is to catch an unintended location conversion logic + // change. + struct TestCase { + description: &'static str, + location: Location, + expected_account_id_str: &'static str, + } + + let test_cases = vec![ + // DescribeTerminus + TestCase { + description: "DescribeTerminus Parent", + location: Location::new(1, Here), + expected_account_id_str: "5Dt6dpkWPwLaH4BBCKJwjiWrFVAGyYk3tLUabvyn4v7KtESG", + }, + TestCase { + description: "DescribeTerminus Sibling", + location: Location::new(1, [Parachain(1111)]), + expected_account_id_str: "5Eg2fnssmmJnF3z1iZ1NouAuzciDaaDQH7qURAy3w15jULDk", + }, + // DescribePalletTerminal + TestCase { + description: "DescribePalletTerminal Parent", + location: Location::new(1, [PalletInstance(50)]), + expected_account_id_str: "5CnwemvaAXkWFVwibiCvf2EjqwiqBi29S5cLLydZLEaEw6jZ", + }, + TestCase { + description: "DescribePalletTerminal Sibling", + location: Location::new(1, [Parachain(1111), PalletInstance(50)]), + expected_account_id_str: "5GFBgPjpEQPdaxEnFirUoa51u5erVx84twYxJVuBRAT2UP2g", + }, + // DescribeAccountId32Terminal + TestCase { + description: "DescribeAccountId32Terminal Parent", + location: Location::new( + 1, + [Junction::AccountId32 { network: None, id: AccountId::from(Alice).into() }], + ), + expected_account_id_str: "5EueAXd4h8u75nSbFdDJbC29cmi4Uo1YJssqEL9idvindxFL", + }, + TestCase { + description: "DescribeAccountId32Terminal Sibling", + location: Location::new( + 1, + [ + Parachain(1111), + Junction::AccountId32 { network: None, id: AccountId::from(Alice).into() }, + ], + ), + expected_account_id_str: "5Dmbuiq48fU4iW58FKYqoGbbfxFHjbAeGLMtjFg6NNCw3ssr", + }, + // DescribeAccountKey20Terminal + TestCase { + description: "DescribeAccountKey20Terminal Parent", + location: Location::new(1, [AccountKey20 { network: None, key: [0u8; 20] }]), + expected_account_id_str: "5F5Ec11567pa919wJkX6VHtv2ZXS5W698YCW35EdEbrg14cg", + }, + TestCase { + description: "DescribeAccountKey20Terminal Sibling", + location: Location::new( + 1, + [Parachain(1111), AccountKey20 { network: None, key: [0u8; 20] }], + ), + expected_account_id_str: "5CB2FbUds2qvcJNhDiTbRZwiS3trAy6ydFGMSVutmYijpPAg", + }, + // DescribeTreasuryVoiceTerminal + TestCase { + description: "DescribeTreasuryVoiceTerminal Parent", + location: Location::new(1, [Plurality { id: BodyId::Treasury, part: BodyPart::Voice }]), + expected_account_id_str: "5CUjnE2vgcUCuhxPwFoQ5r7p1DkhujgvMNDHaF2bLqRp4D5F", + }, + TestCase { + description: "DescribeTreasuryVoiceTerminal Sibling", + location: Location::new( + 1, + [Parachain(1111), Plurality { id: BodyId::Treasury, part: BodyPart::Voice }], + ), + expected_account_id_str: "5G6TDwaVgbWmhqRUKjBhRRnH4ry9L9cjRymUEmiRsLbSE4gB", + }, + // DescribeBodyTerminal + TestCase { + description: "DescribeBodyTerminal Parent", + location: Location::new(1, [Plurality { id: BodyId::Unit, part: BodyPart::Voice }]), + expected_account_id_str: "5EBRMTBkDisEXsaN283SRbzx9Xf2PXwUxxFCJohSGo4jYe6B", + }, + TestCase { + description: "DescribeBodyTerminal Sibling", + location: Location::new( + 1, + [Parachain(1111), Plurality { id: BodyId::Unit, part: BodyPart::Voice }], + ), + expected_account_id_str: "5DBoExvojy8tYnHgLL97phNH975CyT45PWTZEeGoBZfAyRMH", + }, + ]; + + for tc in test_cases { + let expected = + AccountId::from_string(tc.expected_account_id_str).expect("Invalid AccountId string"); + + let got = LocationToAccountHelper::< + AccountId, + bridge_hub_rococo_runtime::xcm_config::LocationToAccountId, + >::convert_location(tc.location.into()) + .unwrap(); + + assert_eq!(got, expected, "{}", tc.description); + } +} + +#[test] +>>>>>>> e9be92d6 (Authorize upgrade tests for testnet runtimes + `execute_as_governance` refactor (#7656)) fn xcm_payment_api_works() { parachains_runtimes_test_utils::test_cases::xcm_payment_api_with_native_token_works::< Runtime, diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/src/xcm_config.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/src/xcm_config.rs index c2ca8e47f2a61..711e8000f5ec9 100644 --- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/src/xcm_config.rs +++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/src/xcm_config.rs @@ -59,6 +59,7 @@ parameter_types! { pub const MaxAssetsIntoHolding: u32 = 64; pub TreasuryAccount: AccountId = TREASURY_PALLET_ID.into_account_truncating(); pub RelayTreasuryLocation: Location = (Parent, PalletInstance(westend_runtime_constants::TREASURY_PALLET_ID)).into(); + pub const GovernanceLocation: Location = Location::parent(); } /// Type for specifying how a `Location` can be converted into an `AccountId`. This is used diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/tests/tests.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/tests/tests.rs index 6e9cc90a71d62..5becb3dc063b1 100644 --- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/tests/tests.rs +++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/tests/tests.rs @@ -17,6 +17,7 @@ #![cfg(test)] use bp_polkadot_core::Signature; +<<<<<<< HEAD use bridge_common_config::{DeliveryRewardInBalance, RequiredStakeForStakeAndSlash}; use bridge_hub_test_utils::{test_cases::from_parachain, SlotDurations}; use bridge_hub_westend_runtime::{ @@ -25,6 +26,24 @@ use bridge_hub_westend_runtime::{ AllPalletsWithoutSystem, Block, BridgeRejectObsoleteHeadersAndMessages, Executive, ExistentialDeposit, ParachainSystem, PolkadotXcm, Runtime, RuntimeCall, RuntimeEvent, RuntimeOrigin, SessionKeys, SignedExtra, TransactionPayment, UncheckedExtrinsic, +======= +use bp_relayers::{PayRewardFromAccount, RewardsAccountOwner, RewardsAccountParams}; +use bridge_common_config::{BridgeRelayersInstance, BridgeReward, RequiredStakeForStakeAndSlash}; +use bridge_hub_test_utils::{ + test_cases::{from_parachain, run_test}, + GovernanceOrigin, SlotDurations, +}; +use bridge_hub_westend_runtime::{ + bridge_common_config, bridge_to_rococo_config, + bridge_to_rococo_config::RococoGlobalConsensusNetwork, + xcm_config::{ + GovernanceLocation, LocationToAccountId, RelayNetwork, WestendLocation, XcmConfig, + }, + AllPalletsWithoutSystem, Balances, Block, BridgeRejectObsoleteHeadersAndMessages, + BridgeRelayers, Executive, ExistentialDeposit, ParachainSystem, PolkadotXcm, Runtime, + RuntimeCall, RuntimeEvent, RuntimeOrigin, SessionKeys, TransactionPayment, TxExtension, + UncheckedExtrinsic, +>>>>>>> e9be92d6 (Authorize upgrade tests for testnet runtimes + `execute_as_governance` refactor (#7656)) }; use bridge_to_rococo_config::{ BridgeGrandpaRococoInstance, BridgeHubRococoChainId, BridgeHubRococoLocation, @@ -38,13 +57,30 @@ use sp_consensus_aura::SlotDuration; use sp_keyring::AccountKeyring::Alice; use sp_runtime::{ generic::{Era, SignedPayload}, - AccountId32, Perbill, + AccountId32, Either, Perbill, }; use testnet_parachains_constants::westend::{consensus::*, fee::WeightToFee}; use xcm::latest::prelude::*; +<<<<<<< HEAD // Para id of sibling chain used in tests. pub const SIBLING_PARACHAIN_ID: u32 = 1000; +======= +// Random para id of sibling chain used in tests. +pub const SIBLING_PARACHAIN_ID: u32 = 2053; +// Random para id of sibling chain used in tests. +pub const SIBLING_SYSTEM_PARACHAIN_ID: u32 = 1008; +// Random para id of bridged chain from different global consensus used in tests. +pub const BRIDGED_LOCATION_PARACHAIN_ID: u32 = 1075; + +parameter_types! { + pub SiblingParachainLocation: Location = Location::new(1, [Parachain(SIBLING_PARACHAIN_ID)]); + pub SiblingSystemParachainLocation: Location = Location::new(1, [Parachain(SIBLING_SYSTEM_PARACHAIN_ID)]); + pub BridgedUniversalLocation: InteriorLocation = [GlobalConsensus(RococoGlobalConsensusNetwork::get()), Parachain(BRIDGED_LOCATION_PARACHAIN_ID)].into(); + pub CheckingAccount: AccountId = PolkadotXcm::check_account(); + pub Governance: GovernanceOrigin = GovernanceOrigin::Location(GovernanceLocation::get()); +} +>>>>>>> e9be92d6 (Authorize upgrade tests for testnet runtimes + `execute_as_governance` refactor (#7656)) // Runtime from tests PoV type RuntimeTestsAdapter = from_parachain::WithRemoteParachainHelperAdapter< @@ -55,10 +91,6 @@ type RuntimeTestsAdapter = from_parachain::WithRemoteParachainHelperAdapter< WithBridgeHubRococoMessagesInstance, >; -parameter_types! { - pub CheckingAccount: AccountId = PolkadotXcm::check_account(); -} - fn construct_extrinsic( sender: sp_keyring::AccountKeyring, call: RuntimeCall, @@ -138,7 +170,11 @@ 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_westend::BRIDGE_HUB_WESTEND_PARACHAIN_ID) + >( + collator_session_keys(), + bp_bridge_hub_westend::BRIDGE_HUB_WESTEND_PARACHAIN_ID, + Governance::get(), + ) } #[test] @@ -146,7 +182,11 @@ fn change_bridge_grandpa_pallet_mode_by_governance_works() { bridge_hub_test_utils::test_cases::change_bridge_grandpa_pallet_mode_by_governance_works::< Runtime, BridgeGrandpaRococoInstance, - >(collator_session_keys(), bp_bridge_hub_westend::BRIDGE_HUB_WESTEND_PARACHAIN_ID) + >( + collator_session_keys(), + bp_bridge_hub_westend::BRIDGE_HUB_WESTEND_PARACHAIN_ID, + Governance::get(), + ) } #[test] @@ -154,7 +194,11 @@ fn change_bridge_parachains_pallet_mode_by_governance_works() { bridge_hub_test_utils::test_cases::change_bridge_parachains_pallet_mode_by_governance_works::< Runtime, BridgeParachainRococoInstance, - >(collator_session_keys(), bp_bridge_hub_westend::BRIDGE_HUB_WESTEND_PARACHAIN_ID) + >( + collator_session_keys(), + bp_bridge_hub_westend::BRIDGE_HUB_WESTEND_PARACHAIN_ID, + Governance::get(), + ) } #[test] @@ -162,7 +206,11 @@ fn change_bridge_messages_pallet_mode_by_governance_works() { bridge_hub_test_utils::test_cases::change_bridge_messages_pallet_mode_by_governance_works::< Runtime, WithBridgeHubRococoMessagesInstance, - >(collator_session_keys(), bp_bridge_hub_westend::BRIDGE_HUB_WESTEND_PARACHAIN_ID) + >( + collator_session_keys(), + bp_bridge_hub_westend::BRIDGE_HUB_WESTEND_PARACHAIN_ID, + Governance::get(), + ) } #[test] @@ -174,7 +222,7 @@ fn change_delivery_reward_by_governance_works() { >( collator_session_keys(), bp_bridge_hub_westend::BRIDGE_HUB_WESTEND_PARACHAIN_ID, - Box::new(|call| RuntimeCall::System(call).encode()), + Governance::get(), || (DeliveryRewardInBalance::key().to_vec(), DeliveryRewardInBalance::get()), |old_value| old_value.checked_mul(2).unwrap(), ) @@ -189,7 +237,7 @@ fn change_required_stake_by_governance_works() { >( collator_session_keys(), bp_bridge_hub_westend::BRIDGE_HUB_WESTEND_PARACHAIN_ID, - Box::new(|call| RuntimeCall::System(call).encode()), + Governance::get(), || (RequiredStakeForStakeAndSlash::key().to_vec(), RequiredStakeForStakeAndSlash::get()), |old_value| old_value.checked_mul(2).unwrap(), ) @@ -337,3 +385,137 @@ fn xcm_payment_api_works() { Block, >(); } +<<<<<<< HEAD +======= + +#[test] +pub fn bridge_rewards_works() { + run_test::( + collator_session_keys(), + bp_bridge_hub_westend::BRIDGE_HUB_WESTEND_PARACHAIN_ID, + vec![], + || { + // reward in WNDs + let reward1: u128 = 2_000_000_000; + // reward in WETH + let reward2: u128 = 3_000_000_000; + + // prepare accounts + let account1 = AccountId32::from(Alice); + let account2 = AccountId32::from(Bob); + let reward1_for = RewardsAccountParams::new( + LegacyLaneId([1; 4]), + *b"test", + RewardsAccountOwner::ThisChain, + ); + let expected_reward1_account = + PayRewardFromAccount::<(), AccountId, LegacyLaneId, ()>::rewards_account( + reward1_for, + ); + assert_ok!(Balances::mint_into(&expected_reward1_account, ExistentialDeposit::get())); + assert_ok!(Balances::mint_into(&expected_reward1_account, reward1.into())); + assert_ok!(Balances::mint_into(&account1, ExistentialDeposit::get())); + + // register rewards + use bp_relayers::RewardLedger; + BridgeRelayers::register_reward(&account1, BridgeReward::from(reward1_for), reward1); + BridgeRelayers::register_reward(&account2, BridgeReward::Snowbridge, reward2); + + // check stored rewards + assert_eq!( + BridgeRelayers::relayer_reward(&account1, BridgeReward::from(reward1_for)), + Some(reward1) + ); + assert_eq!(BridgeRelayers::relayer_reward(&account1, BridgeReward::Snowbridge), None,); + assert_eq!( + BridgeRelayers::relayer_reward(&account2, BridgeReward::Snowbridge), + Some(reward2), + ); + assert_eq!( + BridgeRelayers::relayer_reward(&account2, BridgeReward::from(reward1_for)), + None, + ); + + // claim rewards + assert_ok!(BridgeRelayers::claim_rewards( + RuntimeOrigin::signed(account1.clone()), + reward1_for.into() + )); + assert_eq!(Balances::total_balance(&account1), ExistentialDeposit::get() + reward1); + assert_eq!( + BridgeRelayers::relayer_reward(&account1, BridgeReward::from(reward1_for)), + None, + ); + + // already claimed + assert_err!( + BridgeRelayers::claim_rewards( + RuntimeOrigin::signed(account1.clone()), + reward1_for.into() + ), + pallet_bridge_relayers::Error::::NoRewardForRelayer + ); + + // not yet implemented for Snowbridge + assert_err!( + BridgeRelayers::claim_rewards( + RuntimeOrigin::signed(account2.clone()), + BridgeReward::Snowbridge + ), + pallet_bridge_relayers::Error::::FailedToPayReward + ); + }, + ); +} + +#[test] +fn governance_authorize_upgrade_works() { + use westend_runtime_constants::system_parachain::{ASSET_HUB_ID, COLLECTIVES_ID}; + + // no - random para + assert_err!( + parachains_runtimes_test_utils::test_cases::can_governance_authorize_upgrade::< + Runtime, + RuntimeOrigin, + >(GovernanceOrigin::Location(Location::new(1, Parachain(12334)))), + Either::Right(XcmError::Barrier) + ); + // no - AssetHub + assert_err!( + parachains_runtimes_test_utils::test_cases::can_governance_authorize_upgrade::< + Runtime, + RuntimeOrigin, + >(GovernanceOrigin::Location(Location::new(1, Parachain(ASSET_HUB_ID)))), + Either::Right(XcmError::Barrier) + ); + // no - Collectives + assert_err!( + parachains_runtimes_test_utils::test_cases::can_governance_authorize_upgrade::< + Runtime, + RuntimeOrigin, + >(GovernanceOrigin::Location(Location::new(1, Parachain(COLLECTIVES_ID)))), + Either::Right(XcmError::Barrier) + ); + // no - Collectives Voice of Fellows plurality + assert_err!( + parachains_runtimes_test_utils::test_cases::can_governance_authorize_upgrade::< + Runtime, + RuntimeOrigin, + >(GovernanceOrigin::LocationAndDescendOrigin( + Location::new(1, Parachain(COLLECTIVES_ID)), + Plurality { id: BodyId::Technical, part: BodyPart::Voice }.into() + )), + Either::Right(XcmError::Barrier) + ); + + // ok - relaychain + assert_ok!(parachains_runtimes_test_utils::test_cases::can_governance_authorize_upgrade::< + Runtime, + RuntimeOrigin, + >(GovernanceOrigin::Location(Location::parent()))); + assert_ok!(parachains_runtimes_test_utils::test_cases::can_governance_authorize_upgrade::< + Runtime, + RuntimeOrigin, + >(Governance::get())); +} +>>>>>>> e9be92d6 (Authorize upgrade tests for testnet runtimes + `execute_as_governance` refactor (#7656)) diff --git a/cumulus/parachains/runtimes/bridge-hubs/test-utils/src/test_cases/mod.rs b/cumulus/parachains/runtimes/bridge-hubs/test-utils/src/test_cases/mod.rs index bc1c7ec5e032c..afc28ed4ee856 100644 --- a/cumulus/parachains/runtimes/bridge-hubs/test-utils/src/test_cases/mod.rs +++ b/cumulus/parachains/runtimes/bridge-hubs/test-utils/src/test_cases/mod.rs @@ -44,8 +44,8 @@ use frame_support::{ use frame_system::pallet_prelude::BlockNumberFor; use parachains_common::AccountId; use parachains_runtimes_test_utils::{ - mock_open_hrmp_channel, AccountIdOf, BalanceOf, CollatorSessionKeys, ExtBuilder, RuntimeCallOf, - SlotDurations, XcmReceivedFrom, + mock_open_hrmp_channel, AccountIdOf, BalanceOf, CollatorSessionKeys, ExtBuilder, + GovernanceOrigin, RuntimeCallOf, RuntimeOriginOf, SlotDurations, XcmReceivedFrom, }; use sp_runtime::{traits::Zero, AccountId32}; use xcm::{latest::prelude::*, AlwaysLatest}; @@ -101,6 +101,7 @@ where pub fn initialize_bridge_by_governance_works( collator_session_key: CollatorSessionKeys, runtime_para_id: u32, + governance_origin: GovernanceOrigin>, ) where Runtime: BasicParachainRuntime + BridgeGrandpaConfig, GrandpaPalletInstance: 'static, @@ -123,11 +124,18 @@ pub fn initialize_bridge_by_governance_works( }); // execute XCM with Transacts to `initialize bridge` as governance does +<<<<<<< HEAD assert_ok!(RuntimeHelper::::execute_as_governance( initialize_call.encode(), initialize_call.get_dispatch_info().weight, ) .ensure_complete()); +======= + assert_ok!(RuntimeHelper::::execute_as_governance_call( + initialize_call, + governance_origin + )); +>>>>>>> e9be92d6 (Authorize upgrade tests for testnet runtimes + `execute_as_governance` refactor (#7656)) // check mode after assert_eq!( @@ -142,6 +150,7 @@ pub fn initialize_bridge_by_governance_works( pub fn change_bridge_grandpa_pallet_mode_by_governance_works( collator_session_key: CollatorSessionKeys, runtime_para_id: u32, + governance_origin: GovernanceOrigin>, ) where Runtime: BasicParachainRuntime + BridgeGrandpaConfig, GrandpaPalletInstance: 'static, @@ -164,11 +173,18 @@ pub fn change_bridge_grandpa_pallet_mode_by_governance_works::execute_as_governance( set_operating_mode_call.encode(), set_operating_mode_call.get_dispatch_info().weight, ) .ensure_complete()); +======= + assert_ok!(RuntimeHelper::::execute_as_governance_call( + set_operating_mode_call, + governance_origin.clone() + )); +>>>>>>> e9be92d6 (Authorize upgrade tests for testnet runtimes + `execute_as_governance` refactor (#7656)) // check mode after assert_eq!( @@ -193,6 +209,7 @@ pub fn change_bridge_grandpa_pallet_mode_by_governance_works( collator_session_key: CollatorSessionKeys, runtime_para_id: u32, + governance_origin: GovernanceOrigin>, ) where Runtime: BasicParachainRuntime + BridgeParachainsConfig, ParachainsPalletInstance: 'static, @@ -217,11 +234,18 @@ pub fn change_bridge_parachains_pallet_mode_by_governance_works::execute_as_governance( set_operating_mode_call.encode(), set_operating_mode_call.get_dispatch_info().weight, ) .ensure_complete()); +======= + assert_ok!(RuntimeHelper::::execute_as_governance_call( + set_operating_mode_call, + governance_origin.clone() + )); +>>>>>>> e9be92d6 (Authorize upgrade tests for testnet runtimes + `execute_as_governance` refactor (#7656)) // check mode after assert_eq!( @@ -246,6 +270,7 @@ pub fn change_bridge_parachains_pallet_mode_by_governance_works( collator_session_key: CollatorSessionKeys, runtime_para_id: u32, + governance_origin: GovernanceOrigin>, ) where Runtime: BasicParachainRuntime + BridgeMessagesConfig, MessagesPalletInstance: 'static, @@ -270,11 +295,18 @@ pub fn change_bridge_messages_pallet_mode_by_governance_works::execute_as_governance( set_operating_mode_call.encode(), set_operating_mode_call.get_dispatch_info().weight, ) .ensure_complete()); +======= + assert_ok!(RuntimeHelper::::execute_as_governance_call( + set_operating_mode_call, + governance_origin.clone() + )); +>>>>>>> e9be92d6 (Authorize upgrade tests for testnet runtimes + `execute_as_governance` refactor (#7656)) // check mode after assert_eq!( diff --git a/cumulus/parachains/runtimes/collectives/collectives-westend/src/xcm_config.rs b/cumulus/parachains/runtimes/collectives/collectives-westend/src/xcm_config.rs index c68f230a16dc3..9f4db93a2a7c9 100644 --- a/cumulus/parachains/runtimes/collectives/collectives-westend/src/xcm_config.rs +++ b/cumulus/parachains/runtimes/collectives/collectives-westend/src/xcm_config.rs @@ -32,8 +32,13 @@ use parachains_common::xcm_config::{ }; use polkadot_parachain_primitives::primitives::Sibling; use polkadot_runtime_common::xcm_sender::ExponentialPrice; +<<<<<<< HEAD use westend_runtime_constants::xcm as xcm_constants; use xcm::latest::prelude::*; +======= +use westend_runtime_constants::{system_parachain::ASSET_HUB_ID, xcm as xcm_constants}; +use xcm::latest::{prelude::*, WESTEND_GENESIS_HASH}; +>>>>>>> e9be92d6 (Authorize upgrade tests for testnet runtimes + `execute_as_governance` refactor (#7656)) use xcm_builder::{ AccountId32Aliases, AllowExplicitUnpaidExecutionFrom, AllowHrmpNotificationsFromRelayChain, AllowKnownQueryResponses, AllowSubscriptionsFrom, AllowTopLevelPaidExecutionFrom, @@ -57,7 +62,7 @@ parameter_types! { pub CheckingAccount: AccountId = PolkadotXcm::check_account(); pub const GovernanceLocation: Location = Location::parent(); pub const FellowshipAdminBodyId: BodyId = BodyId::Index(xcm_constants::body::FELLOWSHIP_ADMIN_INDEX); - pub AssetHub: Location = (Parent, Parachain(1000)).into(); + pub AssetHub: Location = (Parent, Parachain(ASSET_HUB_ID)).into(); pub const TreasurerBodyId: BodyId = BodyId::Treasury; pub AssetHubUsdtId: AssetId = (PalletInstance(50), GeneralIndex(1984)).into(); pub UsdtAssetHub: LocatableAssetId = LocatableAssetId { diff --git a/cumulus/parachains/runtimes/collectives/collectives-westend/tests/tests.rs b/cumulus/parachains/runtimes/collectives/collectives-westend/tests/tests.rs index fb0149303e51a..eec8e70112aa1 100644 --- a/cumulus/parachains/runtimes/collectives/collectives-westend/tests/tests.rs +++ b/cumulus/parachains/runtimes/collectives/collectives-westend/tests/tests.rs @@ -16,7 +16,132 @@ #![cfg(test)] +<<<<<<< HEAD use collectives_westend_runtime::{Block, Runtime, RuntimeCall, RuntimeOrigin}; +======= +use collectives_westend_runtime::{ + xcm_config::{GovernanceLocation, LocationToAccountId}, + Block, Runtime, RuntimeCall, RuntimeOrigin, +}; +use frame_support::{assert_err, assert_ok}; +use parachains_common::AccountId; +use parachains_runtimes_test_utils::GovernanceOrigin; +use sp_core::crypto::Ss58Codec; +use sp_runtime::Either; +use xcm::latest::prelude::*; +use xcm_runtime_apis::conversions::LocationToAccountHelper; + +const ALICE: [u8; 32] = [1u8; 32]; + +#[test] +fn location_conversion_works() { + // the purpose of hardcoded values is to catch an unintended location conversion logic change. + struct TestCase { + description: &'static str, + location: Location, + expected_account_id_str: &'static str, + } + + let test_cases = vec![ + // DescribeTerminus + TestCase { + description: "DescribeTerminus Parent", + location: Location::new(1, Here), + expected_account_id_str: "5Dt6dpkWPwLaH4BBCKJwjiWrFVAGyYk3tLUabvyn4v7KtESG", + }, + TestCase { + description: "DescribeTerminus Sibling", + location: Location::new(1, [Parachain(1111)]), + expected_account_id_str: "5Eg2fnssmmJnF3z1iZ1NouAuzciDaaDQH7qURAy3w15jULDk", + }, + // DescribePalletTerminal + TestCase { + description: "DescribePalletTerminal Parent", + location: Location::new(1, [PalletInstance(50)]), + expected_account_id_str: "5CnwemvaAXkWFVwibiCvf2EjqwiqBi29S5cLLydZLEaEw6jZ", + }, + TestCase { + description: "DescribePalletTerminal Sibling", + location: Location::new(1, [Parachain(1111), PalletInstance(50)]), + expected_account_id_str: "5GFBgPjpEQPdaxEnFirUoa51u5erVx84twYxJVuBRAT2UP2g", + }, + // DescribeAccountId32Terminal + TestCase { + description: "DescribeAccountId32Terminal Parent", + location: Location::new( + 1, + [Junction::AccountId32 { network: None, id: AccountId::from(ALICE).into() }], + ), + expected_account_id_str: "5DN5SGsuUG7PAqFL47J9meViwdnk9AdeSWKFkcHC45hEzVz4", + }, + TestCase { + description: "DescribeAccountId32Terminal Sibling", + location: Location::new( + 1, + [ + Parachain(1111), + Junction::AccountId32 { network: None, id: AccountId::from(ALICE).into() }, + ], + ), + expected_account_id_str: "5DGRXLYwWGce7wvm14vX1Ms4Vf118FSWQbJkyQigY2pfm6bg", + }, + // DescribeAccountKey20Terminal + TestCase { + description: "DescribeAccountKey20Terminal Parent", + location: Location::new(1, [AccountKey20 { network: None, key: [0u8; 20] }]), + expected_account_id_str: "5F5Ec11567pa919wJkX6VHtv2ZXS5W698YCW35EdEbrg14cg", + }, + TestCase { + description: "DescribeAccountKey20Terminal Sibling", + location: Location::new( + 1, + [Parachain(1111), AccountKey20 { network: None, key: [0u8; 20] }], + ), + expected_account_id_str: "5CB2FbUds2qvcJNhDiTbRZwiS3trAy6ydFGMSVutmYijpPAg", + }, + // DescribeTreasuryVoiceTerminal + TestCase { + description: "DescribeTreasuryVoiceTerminal Parent", + location: Location::new(1, [Plurality { id: BodyId::Treasury, part: BodyPart::Voice }]), + expected_account_id_str: "5CUjnE2vgcUCuhxPwFoQ5r7p1DkhujgvMNDHaF2bLqRp4D5F", + }, + TestCase { + description: "DescribeTreasuryVoiceTerminal Sibling", + location: Location::new( + 1, + [Parachain(1111), Plurality { id: BodyId::Treasury, part: BodyPart::Voice }], + ), + expected_account_id_str: "5G6TDwaVgbWmhqRUKjBhRRnH4ry9L9cjRymUEmiRsLbSE4gB", + }, + // DescribeBodyTerminal + TestCase { + description: "DescribeBodyTerminal Parent", + location: Location::new(1, [Plurality { id: BodyId::Unit, part: BodyPart::Voice }]), + expected_account_id_str: "5EBRMTBkDisEXsaN283SRbzx9Xf2PXwUxxFCJohSGo4jYe6B", + }, + TestCase { + description: "DescribeBodyTerminal Sibling", + location: Location::new( + 1, + [Parachain(1111), Plurality { id: BodyId::Unit, part: BodyPart::Voice }], + ), + expected_account_id_str: "5DBoExvojy8tYnHgLL97phNH975CyT45PWTZEeGoBZfAyRMH", + }, + ]; + + for tc in test_cases { + let expected = + AccountId::from_string(tc.expected_account_id_str).expect("Invalid AccountId string"); + + let got = LocationToAccountHelper::::convert_location( + tc.location.into(), + ) + .unwrap(); + + assert_eq!(got, expected, "{}", tc.description); + } +} +>>>>>>> e9be92d6 (Authorize upgrade tests for testnet runtimes + `execute_as_governance` refactor (#7656)) #[test] fn xcm_payment_api_works() { @@ -27,3 +152,54 @@ fn xcm_payment_api_works() { Block, >(); } + +#[test] +fn governance_authorize_upgrade_works() { + use westend_runtime_constants::system_parachain::{ASSET_HUB_ID, COLLECTIVES_ID}; + + // no - random para + assert_err!( + parachains_runtimes_test_utils::test_cases::can_governance_authorize_upgrade::< + Runtime, + RuntimeOrigin, + >(GovernanceOrigin::Location(Location::new(1, Parachain(12334)))), + Either::Right(XcmError::Barrier) + ); + // no - AssetHub + assert_err!( + parachains_runtimes_test_utils::test_cases::can_governance_authorize_upgrade::< + Runtime, + RuntimeOrigin, + >(GovernanceOrigin::Location(Location::new(1, Parachain(ASSET_HUB_ID)))), + Either::Right(XcmError::Barrier) + ); + // no - Collectives + assert_err!( + parachains_runtimes_test_utils::test_cases::can_governance_authorize_upgrade::< + Runtime, + RuntimeOrigin, + >(GovernanceOrigin::Location(Location::new(1, Parachain(COLLECTIVES_ID)))), + Either::Right(XcmError::Barrier) + ); + // no - Collectives Voice of Fellows plurality + assert_err!( + parachains_runtimes_test_utils::test_cases::can_governance_authorize_upgrade::< + Runtime, + RuntimeOrigin, + >(GovernanceOrigin::LocationAndDescendOrigin( + Location::new(1, Parachain(COLLECTIVES_ID)), + Plurality { id: BodyId::Technical, part: BodyPart::Voice }.into() + )), + Either::Right(XcmError::Barrier) + ); + + // ok - relaychain + assert_ok!(parachains_runtimes_test_utils::test_cases::can_governance_authorize_upgrade::< + Runtime, + RuntimeOrigin, + >(GovernanceOrigin::Location(Location::parent()))); + assert_ok!(parachains_runtimes_test_utils::test_cases::can_governance_authorize_upgrade::< + Runtime, + RuntimeOrigin, + >(GovernanceOrigin::Location(GovernanceLocation::get()))); +} diff --git a/cumulus/parachains/runtimes/coretime/coretime-westend/src/xcm_config.rs b/cumulus/parachains/runtimes/coretime/coretime-westend/src/xcm_config.rs index b12765870bfdb..74d44a6d8047b 100644 --- a/cumulus/parachains/runtimes/coretime/coretime-westend/src/xcm_config.rs +++ b/cumulus/parachains/runtimes/coretime/coretime-westend/src/xcm_config.rs @@ -37,7 +37,12 @@ use parachains_common::{ use polkadot_parachain_primitives::primitives::Sibling; use polkadot_runtime_common::xcm_sender::ExponentialPrice; use sp_runtime::traits::AccountIdConversion; +<<<<<<< HEAD use xcm::latest::prelude::*; +======= +use westend_runtime_constants::system_parachain::{ASSET_HUB_ID, COLLECTIVES_ID}; +use xcm::latest::{prelude::*, WESTEND_GENESIS_HASH}; +>>>>>>> e9be92d6 (Authorize upgrade tests for testnet runtimes + `execute_as_governance` refactor (#7656)) use xcm_builder::{ AccountId32Aliases, AllowExplicitUnpaidExecutionFrom, AllowHrmpNotificationsFromRelayChain, AllowKnownQueryResponses, AllowSubscriptionsFrom, AllowTopLevelPaidExecutionFrom, @@ -52,7 +57,12 @@ use xcm_executor::XcmExecutor; parameter_types! { pub const TokenRelayLocation: Location = Location::parent(); +<<<<<<< HEAD pub const RelayNetwork: Option = Some(NetworkId::Westend); +======= + pub AssetHubLocation: Location = Location::new(1, [Parachain(ASSET_HUB_ID)]); + pub const RelayNetwork: Option = Some(NetworkId::ByGenesis(WESTEND_GENESIS_HASH)); +>>>>>>> e9be92d6 (Authorize upgrade tests for testnet runtimes + `execute_as_governance` refactor (#7656)) pub RelayChainOrigin: RuntimeOrigin = cumulus_pallet_xcm::Origin::Relay.into(); pub UniversalLocation: InteriorLocation = [GlobalConsensus(RelayNetwork::get().unwrap()), Parachain(ParachainInfo::parachain_id().into())].into(); @@ -60,7 +70,7 @@ parameter_types! { PalletInstance(::index() as u8).into(); pub const MaxInstructions: u32 = 100; pub const MaxAssetsIntoHolding: u32 = 64; - pub FellowshipLocation: Location = Location::new(1, Parachain(1001)); + pub FellowshipLocation: Location = Location::new(1, Parachain(COLLECTIVES_ID)); pub const GovernanceLocation: Location = Location::parent(); } @@ -142,7 +152,10 @@ impl Contains for ParentOrParentsPlurality { pub struct FellowsPlurality; impl Contains for FellowsPlurality { fn contains(location: &Location) -> bool { - matches!(location.unpack(), (1, [Parachain(1001), Plurality { id: BodyId::Technical, .. }])) + matches!( + location.unpack(), + (1, [Parachain(COLLECTIVES_ID), Plurality { id: BodyId::Technical, .. }]) + ) } } diff --git a/cumulus/parachains/runtimes/coretime/coretime-westend/tests/tests.rs b/cumulus/parachains/runtimes/coretime/coretime-westend/tests/tests.rs index 7aeb2ba9393ad..f0446b1d1a674 100644 --- a/cumulus/parachains/runtimes/coretime/coretime-westend/tests/tests.rs +++ b/cumulus/parachains/runtimes/coretime/coretime-westend/tests/tests.rs @@ -16,7 +16,132 @@ #![cfg(test)] +<<<<<<< HEAD use coretime_westend_runtime::{Block, Runtime, RuntimeCall, RuntimeOrigin}; +======= +use coretime_westend_runtime::{ + xcm_config::{GovernanceLocation, LocationToAccountId}, + Block, Runtime, RuntimeCall, RuntimeOrigin, +}; +use frame_support::{assert_err, assert_ok}; +use parachains_common::AccountId; +use parachains_runtimes_test_utils::GovernanceOrigin; +use sp_core::crypto::Ss58Codec; +use sp_runtime::Either; +use xcm::latest::prelude::*; +use xcm_runtime_apis::conversions::LocationToAccountHelper; + +const ALICE: [u8; 32] = [1u8; 32]; + +#[test] +fn location_conversion_works() { + // the purpose of hardcoded values is to catch an unintended location conversion logic change. + struct TestCase { + description: &'static str, + location: Location, + expected_account_id_str: &'static str, + } + + let test_cases = vec![ + // DescribeTerminus + TestCase { + description: "DescribeTerminus Parent", + location: Location::new(1, Here), + expected_account_id_str: "5Dt6dpkWPwLaH4BBCKJwjiWrFVAGyYk3tLUabvyn4v7KtESG", + }, + TestCase { + description: "DescribeTerminus Sibling", + location: Location::new(1, [Parachain(1111)]), + expected_account_id_str: "5Eg2fnssmmJnF3z1iZ1NouAuzciDaaDQH7qURAy3w15jULDk", + }, + // DescribePalletTerminal + TestCase { + description: "DescribePalletTerminal Parent", + location: Location::new(1, [PalletInstance(50)]), + expected_account_id_str: "5CnwemvaAXkWFVwibiCvf2EjqwiqBi29S5cLLydZLEaEw6jZ", + }, + TestCase { + description: "DescribePalletTerminal Sibling", + location: Location::new(1, [Parachain(1111), PalletInstance(50)]), + expected_account_id_str: "5GFBgPjpEQPdaxEnFirUoa51u5erVx84twYxJVuBRAT2UP2g", + }, + // DescribeAccountId32Terminal + TestCase { + description: "DescribeAccountId32Terminal Parent", + location: Location::new( + 1, + [Junction::AccountId32 { network: None, id: AccountId::from(ALICE).into() }], + ), + expected_account_id_str: "5DN5SGsuUG7PAqFL47J9meViwdnk9AdeSWKFkcHC45hEzVz4", + }, + TestCase { + description: "DescribeAccountId32Terminal Sibling", + location: Location::new( + 1, + [ + Parachain(1111), + Junction::AccountId32 { network: None, id: AccountId::from(ALICE).into() }, + ], + ), + expected_account_id_str: "5DGRXLYwWGce7wvm14vX1Ms4Vf118FSWQbJkyQigY2pfm6bg", + }, + // DescribeAccountKey20Terminal + TestCase { + description: "DescribeAccountKey20Terminal Parent", + location: Location::new(1, [AccountKey20 { network: None, key: [0u8; 20] }]), + expected_account_id_str: "5F5Ec11567pa919wJkX6VHtv2ZXS5W698YCW35EdEbrg14cg", + }, + TestCase { + description: "DescribeAccountKey20Terminal Sibling", + location: Location::new( + 1, + [Parachain(1111), AccountKey20 { network: None, key: [0u8; 20] }], + ), + expected_account_id_str: "5CB2FbUds2qvcJNhDiTbRZwiS3trAy6ydFGMSVutmYijpPAg", + }, + // DescribeTreasuryVoiceTerminal + TestCase { + description: "DescribeTreasuryVoiceTerminal Parent", + location: Location::new(1, [Plurality { id: BodyId::Treasury, part: BodyPart::Voice }]), + expected_account_id_str: "5CUjnE2vgcUCuhxPwFoQ5r7p1DkhujgvMNDHaF2bLqRp4D5F", + }, + TestCase { + description: "DescribeTreasuryVoiceTerminal Sibling", + location: Location::new( + 1, + [Parachain(1111), Plurality { id: BodyId::Treasury, part: BodyPart::Voice }], + ), + expected_account_id_str: "5G6TDwaVgbWmhqRUKjBhRRnH4ry9L9cjRymUEmiRsLbSE4gB", + }, + // DescribeBodyTerminal + TestCase { + description: "DescribeBodyTerminal Parent", + location: Location::new(1, [Plurality { id: BodyId::Unit, part: BodyPart::Voice }]), + expected_account_id_str: "5EBRMTBkDisEXsaN283SRbzx9Xf2PXwUxxFCJohSGo4jYe6B", + }, + TestCase { + description: "DescribeBodyTerminal Sibling", + location: Location::new( + 1, + [Parachain(1111), Plurality { id: BodyId::Unit, part: BodyPart::Voice }], + ), + expected_account_id_str: "5DBoExvojy8tYnHgLL97phNH975CyT45PWTZEeGoBZfAyRMH", + }, + ]; + + for tc in test_cases { + let expected = + AccountId::from_string(tc.expected_account_id_str).expect("Invalid AccountId string"); + + let got = LocationToAccountHelper::::convert_location( + tc.location.into(), + ) + .unwrap(); + + assert_eq!(got, expected, "{}", tc.description); + } +} +>>>>>>> e9be92d6 (Authorize upgrade tests for testnet runtimes + `execute_as_governance` refactor (#7656)) #[test] fn xcm_payment_api_works() { @@ -27,3 +152,54 @@ fn xcm_payment_api_works() { Block, >(); } + +#[test] +fn governance_authorize_upgrade_works() { + use westend_runtime_constants::system_parachain::{ASSET_HUB_ID, COLLECTIVES_ID}; + + // no - random para + assert_err!( + parachains_runtimes_test_utils::test_cases::can_governance_authorize_upgrade::< + Runtime, + RuntimeOrigin, + >(GovernanceOrigin::Location(Location::new(1, Parachain(12334)))), + Either::Right(XcmError::Barrier) + ); + // no - AssetHub + assert_err!( + parachains_runtimes_test_utils::test_cases::can_governance_authorize_upgrade::< + Runtime, + RuntimeOrigin, + >(GovernanceOrigin::Location(Location::new(1, Parachain(ASSET_HUB_ID)))), + Either::Right(XcmError::Barrier) + ); + // no - Collectives + assert_err!( + parachains_runtimes_test_utils::test_cases::can_governance_authorize_upgrade::< + Runtime, + RuntimeOrigin, + >(GovernanceOrigin::Location(Location::new(1, Parachain(COLLECTIVES_ID)))), + Either::Right(XcmError::Barrier) + ); + // no - Collectives Voice of Fellows plurality + assert_err!( + parachains_runtimes_test_utils::test_cases::can_governance_authorize_upgrade::< + Runtime, + RuntimeOrigin, + >(GovernanceOrigin::LocationAndDescendOrigin( + Location::new(1, Parachain(COLLECTIVES_ID)), + Plurality { id: BodyId::Technical, part: BodyPart::Voice }.into() + )), + Either::Right(XcmError::BadOrigin) + ); + + // ok - relaychain + assert_ok!(parachains_runtimes_test_utils::test_cases::can_governance_authorize_upgrade::< + Runtime, + RuntimeOrigin, + >(GovernanceOrigin::Location(Location::parent()))); + assert_ok!(parachains_runtimes_test_utils::test_cases::can_governance_authorize_upgrade::< + Runtime, + RuntimeOrigin, + >(GovernanceOrigin::Location(GovernanceLocation::get()))); +} diff --git a/cumulus/parachains/runtimes/people/people-westend/src/xcm_config.rs b/cumulus/parachains/runtimes/people/people-westend/src/xcm_config.rs index 3926ddcf21efe..3a78ee061cd6c 100644 --- a/cumulus/parachains/runtimes/people/people-westend/src/xcm_config.rs +++ b/cumulus/parachains/runtimes/people/people-westend/src/xcm_config.rs @@ -34,7 +34,12 @@ use parachains_common::{ }; use polkadot_parachain_primitives::primitives::Sibling; use sp_runtime::traits::AccountIdConversion; +<<<<<<< HEAD use xcm::latest::prelude::*; +======= +use westend_runtime_constants::system_parachain::{ASSET_HUB_ID, COLLECTIVES_ID}; +use xcm::latest::{prelude::*, WESTEND_GENESIS_HASH}; +>>>>>>> e9be92d6 (Authorize upgrade tests for testnet runtimes + `execute_as_governance` refactor (#7656)) use xcm_builder::{ AccountId32Aliases, AllowExplicitUnpaidExecutionFrom, AllowHrmpNotificationsFromRelayChain, AllowKnownQueryResponses, AllowSubscriptionsFrom, AllowTopLevelPaidExecutionFrom, @@ -50,13 +55,18 @@ use xcm_executor::XcmExecutor; parameter_types! { pub const RootLocation: Location = Location::here(); pub const RelayLocation: Location = Location::parent(); +<<<<<<< HEAD pub const RelayNetwork: Option = Some(NetworkId::Westend); +======= + pub AssetHubLocation: Location = Location::new(1, [Parachain(ASSET_HUB_ID)]); + pub const RelayNetwork: Option = Some(NetworkId::ByGenesis(WESTEND_GENESIS_HASH)); +>>>>>>> e9be92d6 (Authorize upgrade tests for testnet runtimes + `execute_as_governance` refactor (#7656)) pub RelayChainOrigin: RuntimeOrigin = cumulus_pallet_xcm::Origin::Relay.into(); pub UniversalLocation: InteriorLocation = [GlobalConsensus(RelayNetwork::get().unwrap()), Parachain(ParachainInfo::parachain_id().into())].into(); pub const MaxInstructions: u32 = 100; pub const MaxAssetsIntoHolding: u32 = 64; - pub FellowshipLocation: Location = Location::new(1, Parachain(1001)); + pub FellowshipLocation: Location = Location::new(1, Parachain(COLLECTIVES_ID)); pub const GovernanceLocation: Location = Location::parent(); /// The asset ID for the asset that we use to pay for message delivery fees. Just WND. pub FeeAssetId: AssetId = AssetId(RelayLocation::get()); @@ -151,7 +161,10 @@ impl Contains for ParentOrParentsPlurality { pub struct FellowsPlurality; impl Contains for FellowsPlurality { fn contains(location: &Location) -> bool { - matches!(location.unpack(), (1, [Parachain(1001), Plurality { id: BodyId::Technical, .. }])) + matches!( + location.unpack(), + (1, [Parachain(COLLECTIVES_ID), Plurality { id: BodyId::Technical, .. }]) + ) } } diff --git a/cumulus/parachains/runtimes/people/people-westend/tests/tests.rs b/cumulus/parachains/runtimes/people/people-westend/tests/tests.rs index 4dd6ede05c7ca..f73c13ac02e97 100644 --- a/cumulus/parachains/runtimes/people/people-westend/tests/tests.rs +++ b/cumulus/parachains/runtimes/people/people-westend/tests/tests.rs @@ -16,7 +16,132 @@ #![cfg(test)] +<<<<<<< HEAD use people_westend_runtime::{Block, Runtime, RuntimeCall, RuntimeOrigin}; +======= +use frame_support::{assert_err, assert_ok}; +use parachains_common::AccountId; +use parachains_runtimes_test_utils::GovernanceOrigin; +use people_westend_runtime::{ + xcm_config::{GovernanceLocation, LocationToAccountId}, + Block, Runtime, RuntimeCall, RuntimeOrigin, +}; +use sp_core::crypto::Ss58Codec; +use sp_runtime::Either; +use xcm::latest::prelude::*; +use xcm_runtime_apis::conversions::LocationToAccountHelper; + +const ALICE: [u8; 32] = [1u8; 32]; + +#[test] +fn location_conversion_works() { + // the purpose of hardcoded values is to catch an unintended location conversion logic change. + struct TestCase { + description: &'static str, + location: Location, + expected_account_id_str: &'static str, + } + + let test_cases = vec![ + // DescribeTerminus + TestCase { + description: "DescribeTerminus Parent", + location: Location::new(1, Here), + expected_account_id_str: "5Dt6dpkWPwLaH4BBCKJwjiWrFVAGyYk3tLUabvyn4v7KtESG", + }, + TestCase { + description: "DescribeTerminus Sibling", + location: Location::new(1, [Parachain(1111)]), + expected_account_id_str: "5Eg2fnssmmJnF3z1iZ1NouAuzciDaaDQH7qURAy3w15jULDk", + }, + // DescribePalletTerminal + TestCase { + description: "DescribePalletTerminal Parent", + location: Location::new(1, [PalletInstance(50)]), + expected_account_id_str: "5CnwemvaAXkWFVwibiCvf2EjqwiqBi29S5cLLydZLEaEw6jZ", + }, + TestCase { + description: "DescribePalletTerminal Sibling", + location: Location::new(1, [Parachain(1111), PalletInstance(50)]), + expected_account_id_str: "5GFBgPjpEQPdaxEnFirUoa51u5erVx84twYxJVuBRAT2UP2g", + }, + // DescribeAccountId32Terminal + TestCase { + description: "DescribeAccountId32Terminal Parent", + location: Location::new( + 1, + [Junction::AccountId32 { network: None, id: AccountId::from(ALICE).into() }], + ), + expected_account_id_str: "5DN5SGsuUG7PAqFL47J9meViwdnk9AdeSWKFkcHC45hEzVz4", + }, + TestCase { + description: "DescribeAccountId32Terminal Sibling", + location: Location::new( + 1, + [ + Parachain(1111), + Junction::AccountId32 { network: None, id: AccountId::from(ALICE).into() }, + ], + ), + expected_account_id_str: "5DGRXLYwWGce7wvm14vX1Ms4Vf118FSWQbJkyQigY2pfm6bg", + }, + // DescribeAccountKey20Terminal + TestCase { + description: "DescribeAccountKey20Terminal Parent", + location: Location::new(1, [AccountKey20 { network: None, key: [0u8; 20] }]), + expected_account_id_str: "5F5Ec11567pa919wJkX6VHtv2ZXS5W698YCW35EdEbrg14cg", + }, + TestCase { + description: "DescribeAccountKey20Terminal Sibling", + location: Location::new( + 1, + [Parachain(1111), AccountKey20 { network: None, key: [0u8; 20] }], + ), + expected_account_id_str: "5CB2FbUds2qvcJNhDiTbRZwiS3trAy6ydFGMSVutmYijpPAg", + }, + // DescribeTreasuryVoiceTerminal + TestCase { + description: "DescribeTreasuryVoiceTerminal Parent", + location: Location::new(1, [Plurality { id: BodyId::Treasury, part: BodyPart::Voice }]), + expected_account_id_str: "5CUjnE2vgcUCuhxPwFoQ5r7p1DkhujgvMNDHaF2bLqRp4D5F", + }, + TestCase { + description: "DescribeTreasuryVoiceTerminal Sibling", + location: Location::new( + 1, + [Parachain(1111), Plurality { id: BodyId::Treasury, part: BodyPart::Voice }], + ), + expected_account_id_str: "5G6TDwaVgbWmhqRUKjBhRRnH4ry9L9cjRymUEmiRsLbSE4gB", + }, + // DescribeBodyTerminal + TestCase { + description: "DescribeBodyTerminal Parent", + location: Location::new(1, [Plurality { id: BodyId::Unit, part: BodyPart::Voice }]), + expected_account_id_str: "5EBRMTBkDisEXsaN283SRbzx9Xf2PXwUxxFCJohSGo4jYe6B", + }, + TestCase { + description: "DescribeBodyTerminal Sibling", + location: Location::new( + 1, + [Parachain(1111), Plurality { id: BodyId::Unit, part: BodyPart::Voice }], + ), + expected_account_id_str: "5DBoExvojy8tYnHgLL97phNH975CyT45PWTZEeGoBZfAyRMH", + }, + ]; + + for tc in test_cases { + let expected = + AccountId::from_string(tc.expected_account_id_str).expect("Invalid AccountId string"); + + let got = LocationToAccountHelper::::convert_location( + tc.location.into(), + ) + .unwrap(); + + assert_eq!(got, expected, "{}", tc.description); + } +} +>>>>>>> e9be92d6 (Authorize upgrade tests for testnet runtimes + `execute_as_governance` refactor (#7656)) #[test] fn xcm_payment_api_works() { @@ -27,3 +152,54 @@ fn xcm_payment_api_works() { Block, >(); } + +#[test] +fn governance_authorize_upgrade_works() { + use westend_runtime_constants::system_parachain::{ASSET_HUB_ID, COLLECTIVES_ID}; + + // no - random para + assert_err!( + parachains_runtimes_test_utils::test_cases::can_governance_authorize_upgrade::< + Runtime, + RuntimeOrigin, + >(GovernanceOrigin::Location(Location::new(1, Parachain(12334)))), + Either::Right(XcmError::Barrier) + ); + // no - AssetHub + assert_err!( + parachains_runtimes_test_utils::test_cases::can_governance_authorize_upgrade::< + Runtime, + RuntimeOrigin, + >(GovernanceOrigin::Location(Location::new(1, Parachain(ASSET_HUB_ID)))), + Either::Right(XcmError::Barrier) + ); + // no - Collectives + assert_err!( + parachains_runtimes_test_utils::test_cases::can_governance_authorize_upgrade::< + Runtime, + RuntimeOrigin, + >(GovernanceOrigin::Location(Location::new(1, Parachain(COLLECTIVES_ID)))), + Either::Right(XcmError::Barrier) + ); + // no - Collectives Voice of Fellows plurality + assert_err!( + parachains_runtimes_test_utils::test_cases::can_governance_authorize_upgrade::< + Runtime, + RuntimeOrigin, + >(GovernanceOrigin::LocationAndDescendOrigin( + Location::new(1, Parachain(COLLECTIVES_ID)), + Plurality { id: BodyId::Technical, part: BodyPart::Voice }.into() + )), + Either::Right(XcmError::BadOrigin) + ); + + // ok - relaychain + assert_ok!(parachains_runtimes_test_utils::test_cases::can_governance_authorize_upgrade::< + Runtime, + RuntimeOrigin, + >(GovernanceOrigin::Location(Location::parent()))); + assert_ok!(parachains_runtimes_test_utils::test_cases::can_governance_authorize_upgrade::< + Runtime, + RuntimeOrigin, + >(GovernanceOrigin::Location(GovernanceLocation::get()))); +} diff --git a/cumulus/parachains/runtimes/test-utils/src/lib.rs b/cumulus/parachains/runtimes/test-utils/src/lib.rs index 3fc3822a63eb9..a397c0e530af2 100644 --- a/cumulus/parachains/runtimes/test-utils/src/lib.rs +++ b/cumulus/parachains/runtimes/test-utils/src/lib.rs @@ -34,7 +34,10 @@ use polkadot_parachain_primitives::primitives::{ }; use sp_consensus_aura::{SlotDuration, AURA_ENGINE_ID}; use sp_core::{Encode, U256}; -use sp_runtime::{traits::Header, BuildStorage, Digest, DigestItem, SaturatedConversion}; +use sp_runtime::{ + traits::{Dispatchable, Header}, + BuildStorage, Digest, DigestItem, DispatchError, Either, SaturatedConversion, +}; use xcm::{ latest::{Asset, Location, XcmContext, XcmHash}, prelude::*, @@ -47,6 +50,7 @@ pub mod test_cases; pub type BalanceOf = ::Balance; pub type AccountIdOf = ::AccountId; pub type RuntimeCallOf = ::RuntimeCall; +pub type RuntimeOriginOf = ::RuntimeOrigin; pub type ValidatorIdOf = ::ValidatorId; pub type SessionKeysOf = ::Keys; @@ -441,7 +445,15 @@ impl< AllPalletsWithoutSystem, > RuntimeHelper { +<<<<<<< HEAD pub fn execute_as_governance(call: Vec, require_weight_at_most: Weight) -> Outcome { +======= + #[deprecated( + note = "Will be removed after Aug 2025; It uses hard-coded `Location::parent()`, \ + use `execute_as_governance_call` instead." + )] + pub fn execute_as_governance(call: Vec) -> Outcome { +>>>>>>> e9be92d6 (Authorize upgrade tests for testnet runtimes + `execute_as_governance` refactor (#7656)) // prepare xcm as governance will do let xcm = Xcm(vec![ UnpaidExecution { weight_limit: Unlimited, check_origin: None }, @@ -462,6 +474,91 @@ impl< Weight::zero(), ) } +<<<<<<< HEAD +======= + + pub fn execute_as_governance_call( + call: Call, + governance_origin: GovernanceOrigin, + ) -> Result<(), Either> { + // execute xcm as governance would send + let execute_xcm = |call: Call, governance_location, descend_origin| { + // prepare xcm + let xcm = if let Some(descend_origin) = descend_origin { + Xcm::builder_unsafe().descend_origin(descend_origin) + } else { + Xcm::builder_unsafe() + } + .unpaid_execution(Unlimited, None) + .transact(OriginKind::Superuser, None, call.encode()) + .expect_transact_status(MaybeErrorCode::Success) + .build(); + + let xcm_max_weight = Self::xcm_max_weight_for_location(&governance_location); + let mut hash = xcm.using_encoded(sp_io::hashing::blake2_256); + + <::XcmExecutor>::prepare_and_execute( + governance_location, + xcm, + &mut hash, + xcm_max_weight, + Weight::zero(), + ) + }; + + match governance_origin { + GovernanceOrigin::Location(location) => + execute_xcm(call, location, None).ensure_complete().map_err(Either::Right), + GovernanceOrigin::LocationAndDescendOrigin(location, descend_origin) => + execute_xcm(call, location, Some(descend_origin)) + .ensure_complete() + .map_err(Either::Right), + GovernanceOrigin::Origin(origin) => + call.dispatch(origin).map(|_| ()).map_err(|e| Either::Left(e.error)), + } + } + + pub fn execute_as_origin( + (origin, origin_kind): (Location, OriginKind), + call: Call, + maybe_buy_execution_fee: Option, + ) -> Outcome { + let mut instructions = if let Some(buy_execution_fee) = maybe_buy_execution_fee { + vec![ + WithdrawAsset(buy_execution_fee.clone().into()), + BuyExecution { fees: buy_execution_fee.clone(), weight_limit: Unlimited }, + ] + } else { + vec![UnpaidExecution { check_origin: None, weight_limit: Unlimited }] + }; + + // prepare `Transact` xcm + instructions.extend(vec![ + Transact { origin_kind, call: call.encode().into(), fallback_max_weight: None }, + ExpectTransactStatus(MaybeErrorCode::Success), + ]); + let xcm = Xcm(instructions); + let xcm_max_weight = Self::xcm_max_weight_for_location(&origin); + + // execute xcm as parent origin + let mut hash = xcm.using_encoded(sp_io::hashing::blake2_256); + <::XcmExecutor>::prepare_and_execute( + origin, + xcm, + &mut hash, + xcm_max_weight, + Weight::zero(), + ) + } +>>>>>>> e9be92d6 (Authorize upgrade tests for testnet runtimes + `execute_as_governance` refactor (#7656)) +} + +/// Enum representing governance origin/location. +#[derive(Clone)] +pub enum GovernanceOrigin { + Location(Location), + LocationAndDescendOrigin(Location, InteriorLocation), + Origin(RuntimeOrigin), } pub enum XcmReceivedFrom { @@ -478,6 +575,14 @@ impl ParachainSystem::ReservedXcmpWeight::get(), } } + + pub fn xcm_max_weight_for_location(location: &Location) -> Weight { + Self::xcm_max_weight(if location == &Location::parent() { + XcmReceivedFrom::Parent + } else { + XcmReceivedFrom::Sibling + }) + } } impl diff --git a/cumulus/parachains/runtimes/test-utils/src/test_cases.rs b/cumulus/parachains/runtimes/test-utils/src/test_cases.rs index 0f863291ee0bb..2125557656ba6 100644 --- a/cumulus/parachains/runtimes/test-utils/src/test_cases.rs +++ b/cumulus/parachains/runtimes/test-utils/src/test_cases.rs @@ -16,14 +16,21 @@ //! Module contains predefined test-case scenarios for `Runtime` with common functionality. -use crate::{AccountIdOf, CollatorSessionKeys, ExtBuilder, ValidatorIdOf}; +use crate::{ + AccountIdOf, BasicParachainRuntime, CollatorSessionKeys, ExtBuilder, GovernanceOrigin, + RuntimeCallOf, RuntimeOriginOf, ValidatorIdOf, +}; use codec::Encode; use frame_support::{ assert_ok, traits::{Get, OriginTrait}, }; use parachains_common::AccountId; -use sp_runtime::traits::{Block as BlockT, StaticLookup}; +use sp_runtime::{ + traits::{Block as BlockT, StaticLookup}, + DispatchError, Either, +}; +use xcm::prelude::XcmError; use xcm_runtime_apis::fees::{ runtime_decl_for_xcm_payment_api::XcmPaymentApiV1, Error as XcmPaymentApiError, }; @@ -35,7 +42,7 @@ type RuntimeHelper = pub fn change_storage_constant_by_governance_works( collator_session_key: CollatorSessionKeys, runtime_para_id: u32, - runtime_call_encode: Box) -> Vec>, + governance_origin: GovernanceOrigin>, storage_constant_key_value: fn() -> (Vec, StorageConstantType), new_storage_constant_value: fn(&StorageConstantType) -> StorageConstantType, ) where @@ -73,7 +80,7 @@ pub fn change_storage_constant_by_governance_works::set_storage { + RuntimeCallOf::::from(frame_system::Call::::set_storage { items: vec![( storage_constant_key.clone(), new_storage_constant_value.encode(), @@ -86,11 +93,18 @@ pub fn change_storage_constant_by_governance_works::SystemWeightInfo::set_storage(1); // execute XCM with Transact to `set_storage` as governance does +<<<<<<< HEAD assert_ok!(RuntimeHelper::::execute_as_governance( set_storage_call, require_weight_at_most ) .ensure_complete()); +======= + assert_ok!(RuntimeHelper::::execute_as_governance_call( + set_storage_call, + governance_origin + )); +>>>>>>> e9be92d6 (Authorize upgrade tests for testnet runtimes + `execute_as_governance` refactor (#7656)) // check delivery reward constant after (stored) assert_eq!(StorageConstant::get(), new_storage_constant_value); @@ -105,7 +119,7 @@ pub fn change_storage_constant_by_governance_works( collator_session_key: CollatorSessionKeys, runtime_para_id: u32, - runtime_call_encode: Box) -> Vec>, + governance_origin: GovernanceOrigin>, storage_items: Vec<(Vec, Vec)>, initialize_storage: impl FnOnce() -> (), assert_storage: impl FnOnce() -> (), @@ -131,9 +145,10 @@ pub fn set_storage_keys_by_governance_works( }); runtime.execute_with(|| { // encode `kill_storage` call - let kill_storage_call = runtime_call_encode(frame_system::Call::::set_storage { - items: storage_items.clone(), - }); + let kill_storage_call = + RuntimeCallOf::::from(frame_system::Call::::set_storage { + items: storage_items.clone(), + }); // estimate - storing just 1 value use frame_system::WeightInfo; @@ -143,11 +158,18 @@ pub fn set_storage_keys_by_governance_works( ); // execute XCM with Transact to `set_storage` as governance does +<<<<<<< HEAD assert_ok!(RuntimeHelper::::execute_as_governance( kill_storage_call, require_weight_at_most ) .ensure_complete()); +======= + assert_ok!(RuntimeHelper::::execute_as_governance_call( + kill_storage_call, + governance_origin + )); +>>>>>>> e9be92d6 (Authorize upgrade tests for testnet runtimes + `execute_as_governance` refactor (#7656)) }); runtime.execute_with(|| { assert_storage(); @@ -210,3 +232,33 @@ where assert_eq!(execution_fees, Err(XcmPaymentApiError::AssetNotFound)); }); } + +/// Generic test case for Cumulus-based parachain that verifies if runtime can process +/// `frame_system::Call::authorize_upgrade` from governance system. +pub fn can_governance_authorize_upgrade( + governance_origin: GovernanceOrigin, +) -> Result<(), Either> +where + Runtime: BasicParachainRuntime + + frame_system::Config, +{ + ExtBuilder::::default().build().execute_with(|| { + // check before + assert!(frame_system::Pallet::::authorized_upgrade().is_none()); + + // execute call as governance does + let code_hash = Runtime::Hash::default(); + let authorize_upgrade_call: ::RuntimeCall = + frame_system::Call::::authorize_upgrade { code_hash }.into(); + RuntimeHelper::::execute_as_governance_call( + authorize_upgrade_call, + governance_origin, + )?; + + // check after + match frame_system::Pallet::::authorized_upgrade() { + None => Err(Either::Left(frame_system::Error::::NothingAuthorized.into())), + Some(_) => Ok(()), + } + }) +} diff --git a/prdoc/pr_7656.prdoc b/prdoc/pr_7656.prdoc new file mode 100644 index 0000000000000..80a62c284daa1 --- /dev/null +++ b/prdoc/pr_7656.prdoc @@ -0,0 +1,25 @@ +title: Authorize upgrade tests for testnet runtimes + `execute_as_governance` refactor +doc: +- audience: Runtime Dev + description: |- + This PR contains improved test cases that rely on the governance location as preparation for AHM to capture the state as it is. + It introduces `execute_as_governance_call`, which can be configured with various governance location setups instead of the hard-coded `Location::parent()`. +crates: +- name: parachains-runtimes-test-utils + bump: major +- name: asset-hub-westend-runtime + bump: patch +- name: bridge-hub-westend-runtime + bump: minor +- name: collectives-westend-runtime + bump: patch +- name: coretime-westend-runtime + bump: patch +- name: people-westend-runtime + bump: patch +- name: asset-hub-rococo-runtime + bump: patch +- name: bridge-hub-rococo-runtime + bump: patch +- name: bridge-hub-test-utils + bump: major