Allow (hacky) xcm::transact for remark/remark_with_event

This commit is contained in:
Branislav Kontur
2023-01-04 15:38:06 +01:00
parent fe7817e7cd
commit a80781e83d
2 changed files with 160 additions and 6 deletions
@@ -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<RelayNetwork, RuntimeOrigin>,
// Xcm origins can be represented natively under the Xcm pallet's Xcm origin.
XcmPassthrough<RuntimeOrigin>,
// TODO:check-parameter - find a better solution
// Bridged account origins from different globalConsensus converts as SovereignAccount
BridgedSignedAccountId32AsNative<LocationToAccountId, RuntimeOrigin, TrustedBridgedNetworks>,
// 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<Everything>,
// TODO:check-parameter - verify, if we need for production
AllowExecutionForTransactFrom<Everything>,
// Expected responses are OK.
AllowKnownQueryResponses<PolkadotXcm>,
// Subscriptions for version tracking are OK.
@@ -349,3 +359,87 @@ impl<T: Contains<MultiLocation>> ShouldExecute for AllowExecutionForTrapFrom<T>
}
}
}
pub struct AllowExecutionForTransactFrom<T>(sp_std::marker::PhantomData<T>);
impl<T: Contains<MultiLocation>> ShouldExecute for AllowExecutionForTransactFrom<T> {
fn should_execute<RuntimeCall>(
origin: &MultiLocation,
instructions: &mut [Instruction<RuntimeCall>],
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<LocationConverter, RuntimeOrigin, BridgedNetworks>(
sp_std::marker::PhantomData<(LocationConverter, RuntimeOrigin, BridgedNetworks)>,
);
impl<
LocationConverter: Convert<MultiLocation, RuntimeOrigin::AccountId>,
RuntimeOrigin: OriginTrait,
BridgedNetworks: Get<sp_std::vec::Vec<(MultiLocation, Junction)>>,
> ConvertOrigin<RuntimeOrigin>
for BridgedSignedAccountId32AsNative<LocationConverter, RuntimeOrigin, BridgedNetworks>
where
RuntimeOrigin::AccountId: Clone,
{
fn convert_origin(
origin: impl Into<MultiLocation>,
kind: OriginKind,
) -> Result<RuntimeOrigin, MultiLocation> {
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)
}
}
}
@@ -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::<Runtime>::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::<Runtime>::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::<XcmConfig>::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: <Runtime as frame_system::Config>::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::<Runtime>::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::<XcmConfig>::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)));
});
}