From a80781e83dc184115caa3ef85aa4e70f2d30f5a9 Mon Sep 17 00:00:00 2001 From: Branislav Kontur Date: Wed, 4 Jan 2023 15:38:06 +0100 Subject: [PATCH] Allow (hacky) xcm::transact for remark/remark_with_event --- .../assets/westmint/src/xcm_config.rs | 98 ++++++++++++++++++- .../runtimes/assets/westmint/tests/tests.rs | 68 ++++++++++++- 2 files changed, 160 insertions(+), 6 deletions(-) diff --git a/parachains/runtimes/assets/westmint/src/xcm_config.rs b/parachains/runtimes/assets/westmint/src/xcm_config.rs index 352d2a31ac..adee19cc1a 100644 --- a/parachains/runtimes/assets/westmint/src/xcm_config.rs +++ b/parachains/runtimes/assets/westmint/src/xcm_config.rs @@ -20,7 +20,10 @@ use super::{ }; use frame_support::{ match_types, parameter_types, - traits::{ConstU32, Contains, EnsureOrigin, EnsureOriginWithArg, Everything, PalletInfoAccess}, + traits::{ + ConstU32, Contains, EnsureOrigin, EnsureOriginWithArg, Everything, OriginTrait, + PalletInfoAccess, + }, }; use pallet_xcm::{EnsureXcm, XcmPassthrough}; use parachains_common::{ @@ -30,6 +33,7 @@ use parachains_common::{ }, }; use polkadot_parachain::primitives::{Id as ParaId, Sibling}; +use sp_core::Get; use sp_runtime::traits::ConvertInto; use xcm::latest::prelude::*; use xcm_builder::{ @@ -42,7 +46,7 @@ use xcm_builder::{ WithComputedOrigin, }; use xcm_executor::{ - traits::{Convert, JustTry, ShouldExecute}, + traits::{Convert, ConvertOrigin, JustTry, ShouldExecute}, XcmExecutor, }; @@ -140,6 +144,10 @@ pub type XcmOriginToTransactDispatchOrigin = ( SignedAccountId32AsNative, // Xcm origins can be represented natively under the Xcm pallet's Xcm origin. XcmPassthrough, + // TODO:check-parameter - find a better solution + // Bridged account origins from different globalConsensus converts as SovereignAccount + BridgedSignedAccountId32AsNative, + // TODO: add here alternative for BridgedRelayChainAs... or BridgedParachainAs... ); parameter_types! { @@ -323,6 +331,8 @@ impl Contains<(MultiLocation, Junction)> for TrustedBridgedNetworks { pub type BridgedCallsBarrier = ( // TODO:check-parameter - verify, if we need for production (usefull at least for testing connection in production) AllowExecutionForTrapFrom, + // TODO:check-parameter - verify, if we need for production + AllowExecutionForTransactFrom, // Expected responses are OK. AllowKnownQueryResponses, // Subscriptions for version tracking are OK. @@ -349,3 +359,87 @@ impl> ShouldExecute for AllowExecutionForTrapFrom } } } + +pub struct AllowExecutionForTransactFrom(sp_std::marker::PhantomData); +impl> ShouldExecute for AllowExecutionForTransactFrom { + fn should_execute( + origin: &MultiLocation, + instructions: &mut [Instruction], + max_weight: xcm::latest::Weight, + _weight_credit: &mut xcm::latest::Weight, + ) -> Result<(), ()> { + log::error!( + target: "xcm::barriers", + "(TODO:change/remove-in-production) AllowExecutionForTransactFrom origin: {:?}, instructions: {:?}, max_weight: {:?}, weight_credit: {:?}", + origin, instructions, max_weight, _weight_credit, + ); + + match instructions.first() { + // TODO:check-parameter - filter just remark/remark_with_event + Some(Transact { .. }) => Ok(()), + _ => Err(()), + } + } +} + +pub struct BridgedSignedAccountId32AsNative( + sp_std::marker::PhantomData<(LocationConverter, RuntimeOrigin, BridgedNetworks)>, +); +impl< + LocationConverter: Convert, + RuntimeOrigin: OriginTrait, + BridgedNetworks: Get>, + > ConvertOrigin + for BridgedSignedAccountId32AsNative +where + RuntimeOrigin::AccountId: Clone, +{ + fn convert_origin( + origin: impl Into, + kind: OriginKind, + ) -> Result { + let origin = origin.into(); + if let OriginKind::SovereignAccount = kind { + match origin { + MultiLocation { + parents: 2, + interior: + X2( + GlobalConsensus(remote_network), + AccountId32 { network: Some(account_remote_network), id: _id }, + ), + } => { + // TODO:check-parameter - hack - configured local bridge-hub behaves on behalf of any origin from configured bridged network (just to pass Transact/System::remark_with_event - ensure_signed) + // find configured local bridge_hub for remote network + let bridge_hub_location = BridgedNetworks::get() + .iter() + .find(|(_, configured_bridged_network)| match configured_bridged_network { + GlobalConsensus(bridged_network) => + bridged_network.eq(&account_remote_network) && + bridged_network.eq(&remote_network), + _ => false, + }) + .map(|(bridge_hub_location, _)| bridge_hub_location.clone()); + + // try to convert local bridge-hub location + match bridge_hub_location { + Some(bridge_hub_location) => { + let new_origin = bridge_hub_location; + log::error!( + target: "xcm::origin_conversion", + "BridgedSignedAccountId32AsNative replacing origin: {:?} to new_origin: {:?}, kind: {:?}", + origin, new_origin, kind, + ); + let location = LocationConverter::convert(new_origin)?; + Ok(RuntimeOrigin::signed(location).into()) + }, + _ => Err(origin), + } + }, + _ => Err(origin), + } + } else { + Err(origin) + } + } +} diff --git a/parachains/runtimes/assets/westmint/tests/tests.rs b/parachains/runtimes/assets/westmint/tests/tests.rs index a8461b7f5d..5bad97a034 100644 --- a/parachains/runtimes/assets/westmint/tests/tests.rs +++ b/parachains/runtimes/assets/westmint/tests/tests.rs @@ -7,8 +7,10 @@ use frame_support::{ }; use parachains_common::{AccountId, AuraId}; pub use westmint_runtime::{ - constants::fee::WeightToFee, xcm_config::XcmConfig, Balances, ExistentialDeposit, Runtime, - RuntimeCall, RuntimeEvent, SessionKeys, System, TrustBackedAssets, + constants::fee::WeightToFee, + xcm_config::{LocationToAccountId, XcmConfig}, + Balances, ExistentialDeposit, Runtime, RuntimeCall, RuntimeEvent, SessionKeys, System, + TrustBackedAssets, }; use xcm::latest::prelude::*; use xcm_executor::{traits::WeightTrader, XcmExecutor}; @@ -306,7 +308,66 @@ fn test_that_buying_ed_refund_does_not_refund() { } #[test] -fn test_bridged_xcm_trap_works() { +fn test_receive_bridged_xcm_transact_with_remark_with_event_works() { + ExtBuilder::::default() + .with_collators(vec![AccountId::from(ALICE)]) + .with_session_keys(vec![( + AccountId::from(ALICE), + AccountId::from(ALICE), + SessionKeys { aura: AuraId::from(sp_core::sr25519::Public::from_raw(ALICE)) }, + )]) + .with_tracing() + .build() + .execute_with(|| { + let remark_with_event: RuntimeCall = + RuntimeCall::System(frame_system::Call::::remark_with_event { + remark: b"Hello".to_vec(), + }); + + // simulate received message: + // 2022-12-21 14:38:54.047 DEBUG tokio-runtime-worker xcm::execute_xcm: [Parachain] origin: MultiLocation { parents: 1, interior: X1(Parachain(1014)) }, message: Xcm([UniversalOrigin(GlobalConsensus(Rococo)), DescendOrigin(X1(AccountId32 { network: Some(Rococo), id: [28, 189, 45, 67, 83, 10, 68, 112, 90, 208, 136, 175, 49, 62, 24, 248, 11, 83, 239, 22, 179, 97, 119, 205, 75, 119, 184, 70, 242, 165, 240, 124] })), Transact { origin_kind: SovereignAccount, require_weight_at_most: 1000000000, call: [0, 8, 20, 104, 101, 108, 108, 111] }]), weight_limit: 41666666666 + // origin as local BridgeHub (Wococo) + let origin = MultiLocation { parents: 1, interior: X1(Parachain(1014)) }; + let xcm = Xcm(vec![ + UniversalOrigin(GlobalConsensus(Rococo)), + DescendOrigin(X1(AccountId32 { + network: Some(Rococo), + id: [ + 28, 189, 45, 67, 83, 10, 68, 112, 90, 208, 136, 175, 49, 62, 24, 248, 11, + 83, 239, 22, 179, 97, 119, 205, 75, 119, 184, 70, 242, 165, 240, 124, + ], + })), + Transact { + origin_kind: OriginKind::SovereignAccount, + require_weight_at_most: 1000000000, + call: remark_with_event.encode().into(), + }, + ]); + let hash = xcm.using_encoded(sp_io::hashing::blake2_256); + let weight_limit = 41666666666; + + let outcome = XcmExecutor::::execute_xcm(origin, xcm, hash, weight_limit); + assert_eq!(outcome.ensure_complete(), Ok(())); + + // check Event::Remarked occured + let events = System::events(); + assert!(!events.is_empty()); + + let expected_event = { + use sp_runtime::traits::Hash; + use xcm_executor::traits::Convert; + RuntimeEvent::System(frame_system::Event::Remarked { + hash: ::Hashing::hash(b"Hello"), + // origin should match here according to [`BridgedSignedAccountId32AsNative`] + sender: LocationToAccountId::convert(origin).unwrap(), + }) + }; + assert!(System::events().iter().any(|r| r.event == expected_event)); + }); +} + +#[test] +fn test_receive_bridged_xcm_trap_works() { ExtBuilder::::default() .with_collators(vec![AccountId::from(ALICE)]) .with_session_keys(vec![( @@ -336,7 +397,6 @@ fn test_bridged_xcm_trap_works() { let weight_limit = 41666666666; let outcome = XcmExecutor::::execute_xcm(origin, xcm, hash, weight_limit); - log::trace!(target: "xcm::execute", "outcome: {:?}", outcome); assert_eq!(outcome.ensure_complete(), Err(xcm::latest::Error::Trap(1234))); }); }