Skip to content
This repository has been archived by the owner on Nov 15, 2023. It is now read-only.

Introduce Tinkernet multisig XCM configs to Kusama/Rococo through xcm-builder #7165

Merged
merged 14 commits into from Jun 28, 2023
Merged
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.

9 changes: 7 additions & 2 deletions runtime/kusama/src/xcm_config.rs
Expand Up @@ -41,8 +41,9 @@ use xcm_builder::{
ChildParachainConvertsVia, ChildSystemParachainAsSuperuser,
CurrencyAdapter as XcmCurrencyAdapter, FixedWeightBounds, IsChildSystemParachain, IsConcrete,
MintLocation, OriginToPluralityVoice, SignedAccountId32AsNative, SignedToAccountId32,
SovereignSignedViaLocation, TakeWeightCredit, TrailingSetTopicAsId, UsingComponents,
WeightInfoBounds, WithComputedOrigin, WithUniqueTopic,
SovereignSignedViaLocation, TakeWeightCredit, TinkernetMultisigAsAccountId,
TinkernetMultisigAsNative, TrailingSetTopicAsId, UsingComponents, WeightInfoBounds,
WithComputedOrigin, WithUniqueTopic,
};
use xcm_executor::traits::WithOriginFilter;

Expand Down Expand Up @@ -70,6 +71,8 @@ pub type SovereignAccountOf = (
ChildParachainConvertsVia<ParaId, AccountId>,
// We can directly alias an `AccountId32` into a local account.
AccountId32Aliases<ThisNetwork, AccountId>,
// We can derive a local account from a Tinkernet XCMultisig MultiLocation.
TinkernetMultisigAsAccountId<AccountId>,
);

/// Our asset transactor. This is what allows us to interest with the runtime facilities from the point of
Expand Down Expand Up @@ -99,6 +102,8 @@ type LocalOriginConverter = (
SignedAccountId32AsNative<ThisNetwork, RuntimeOrigin>,
// A system child parachain, expressed as a Superuser, converts to the `Root` origin.
ChildSystemParachainAsSuperuser<ParaId, RuntimeOrigin>,
// Converts a Tinkernet XCMultisig MultiLocation into a `Signed` origin.
TinkernetMultisigAsNative<RuntimeOrigin>,
);

parameter_types! {
Expand Down
14 changes: 10 additions & 4 deletions runtime/rococo/src/xcm_config.rs
Expand Up @@ -40,8 +40,8 @@ use xcm_builder::{
ChildParachainAsNative, ChildParachainConvertsVia, ChildSystemParachainAsSuperuser,
CurrencyAdapter as XcmCurrencyAdapter, FixedWeightBounds, IsChildSystemParachain, IsConcrete,
MintLocation, SignedAccountId32AsNative, SignedToAccountId32, SovereignSignedViaLocation,
TakeWeightCredit, TrailingSetTopicAsId, UsingComponents, WeightInfoBounds, WithComputedOrigin,
WithUniqueTopic,
TakeWeightCredit, TinkernetMultisigAsAccountId, TinkernetMultisigAsNative,
TrailingSetTopicAsId, UsingComponents, WeightInfoBounds, WithComputedOrigin, WithUniqueTopic,
};
use xcm_executor::{traits::WithOriginFilter, XcmExecutor};

Expand All @@ -53,8 +53,12 @@ parameter_types! {
pub LocalCheckAccount: (AccountId, MintLocation) = (CheckAccount::get(), MintLocation::Local);
}

pub type LocationConverter =
(ChildParachainConvertsVia<ParaId, AccountId>, AccountId32Aliases<ThisNetwork, AccountId>);
pub type LocationConverter = (
ChildParachainConvertsVia<ParaId, AccountId>,
AccountId32Aliases<ThisNetwork, AccountId>,
// We can derive a local account from a Tinkernet XCMultisig MultiLocation.
TinkernetMultisigAsAccountId<AccountId>,
);

/// Our asset transactor. This is what allows us to interest with the runtime facilities from the point of
/// view of XCM-only concepts like `MultiLocation` and `MultiAsset`.
Expand Down Expand Up @@ -83,6 +87,8 @@ type LocalOriginConverter = (
SignedAccountId32AsNative<ThisNetwork, RuntimeOrigin>,
// A system child parachain, expressed as a Superuser, converts to the `Root` origin.
ChildSystemParachainAsSuperuser<ParaId, RuntimeOrigin>,
// Converts a Tinkernet XCMultisig MultiLocation into a `Signed` origin.
TinkernetMultisigAsNative<RuntimeOrigin>,
);

parameter_types! {
Expand Down
2 changes: 2 additions & 0 deletions xcm/xcm-builder/Cargo.toml
Expand Up @@ -15,6 +15,7 @@ sp-std = { git = "https://github.com/paritytech/substrate", branch = "master", d
sp-arithmetic = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
sp-io = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
sp-core = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
sp-weights = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
frame-support = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
frame-system = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
Expand Down Expand Up @@ -49,6 +50,7 @@ std = [
"sp-arithmetic/std",
"sp-io/std",
"sp-runtime/std",
"sp-core/std",
"sp-weights/std",
"frame-support/std",
"frame-system/std",
Expand Down
4 changes: 2 additions & 2 deletions xcm/xcm-builder/src/lib.rs
Expand Up @@ -34,15 +34,15 @@ pub use location_conversion::{
ChildParachainConvertsVia, DescribeAccountId32Terminal, DescribeAccountIdTerminal,
DescribeAccountKey20Terminal, DescribeAllTerminal, DescribeFamily, DescribeLocation,
DescribePalletTerminal, DescribeTerminus, GlobalConsensusParachainConvertsFor,
HashedDescription, ParentIsPreset, SiblingParachainConvertsVia,
HashedDescription, ParentIsPreset, SiblingParachainConvertsVia, TinkernetMultisigAsAccountId,
};

mod origin_conversion;
pub use origin_conversion::{
BackingToPlurality, ChildParachainAsNative, ChildSystemParachainAsSuperuser, EnsureXcmOrigin,
OriginToPluralityVoice, ParentAsSuperuser, RelayChainAsNative, SiblingParachainAsNative,
SiblingSystemParachainAsSuperuser, SignedAccountId32AsNative, SignedAccountKey20AsNative,
SignedToAccountId32, SovereignSignedViaLocation,
SignedToAccountId32, SovereignSignedViaLocation, TinkernetMultisigAsNative,
};

mod asset_conversion;
Expand Down
67 changes: 67 additions & 0 deletions xcm/xcm-builder/src/location_conversion.rs
Expand Up @@ -17,6 +17,7 @@
use crate::universal_exports::ensure_is_remote;
use frame_support::traits::Get;
use parity_scale_codec::{Compact, Decode, Encode};
use sp_core::H256;
use sp_io::hashing::blake2_256;
use sp_runtime::traits::{AccountIdConversion, Convert, TrailingZeroInput};
use sp_std::{marker::PhantomData, prelude::*};
Expand Down Expand Up @@ -345,6 +346,52 @@ impl<Network: Get<Option<NetworkId>>, AccountId: From<[u8; 20]> + Into<[u8; 20]>
}
}

/// Tinkernet ParaId used when matching Multisig MultiLocations.
pub const KUSAMA_TINKERNET_PARA_ID: u32 = 2125;

/// Tinkernet Multisig pallet instance used when matching Multisig MultiLocations.
pub const KUSAMA_TINKERNET_MULTISIG_PALLET: u8 = 71;

/// Constant derivation function for Tinkernet Multisigs.
/// Uses the Tinkernet genesis hash as a salt.
pub fn derive_tinkernet_multisig<AccountId: Decode>(id: u128) -> Result<AccountId, ()> {
AccountId::decode(&mut TrailingZeroInput::new(
&(
// The constant salt used to derive Tinkernet Multisigs, this is Tinkernet's genesis hash.
H256([
212, 46, 150, 6, 169, 149, 223, 228, 51, 220, 121, 85, 220, 42, 112, 244, 149, 243,
80, 243, 115, 218, 162, 0, 9, 138, 232, 68, 55, 129, 106, 210,
]),
// The actual multisig integer id.
u32::try_from(id).map_err(|_| ())?,
)
.using_encoded(blake2_256),
))
.map_err(|_| ())
}

/// Convert a Tinkernet Multisig `MultiLocation` value into a local `AccountId`.
pub struct TinkernetMultisigAsAccountId<AccountId>(PhantomData<AccountId>);
impl<AccountId: Decode + Clone> ConvertLocation<AccountId>
for TinkernetMultisigAsAccountId<AccountId>
{
fn convert_location(location: &MultiLocation) -> Option<AccountId> {
match location {
MultiLocation {
parents: _,
interior:
X3(
Parachain(KUSAMA_TINKERNET_PARA_ID),
PalletInstance(KUSAMA_TINKERNET_MULTISIG_PALLET),
// Index from which the multisig account is derived.
GeneralIndex(id),
),
} => derive_tinkernet_multisig(*id).ok(),
_ => None,
}
}
}

/// Converts a location which is a top-level parachain (i.e. a parachain held on a
/// Relay-chain which provides its own consensus) into a 32-byte `AccountId`.
///
Expand Down Expand Up @@ -789,4 +836,24 @@ mod tests {
};
assert!(ForeignChainAliasAccount::<[u8; 32]>::convert_location(&mul).is_none());
}

#[test]
fn remote_tinkernet_multisig_convert_to_account() {
let mul = MultiLocation {
parents: 0,
interior: X3(
Parachain(KUSAMA_TINKERNET_PARA_ID),
PalletInstance(KUSAMA_TINKERNET_MULTISIG_PALLET),
GeneralIndex(0),
),
};

assert_eq!(
[
97, 160, 244, 60, 133, 145, 170, 26, 202, 108, 203, 156, 114, 116, 175, 30, 156,
195, 43, 101, 243, 51, 193, 162, 152, 188, 30, 165, 244, 81, 70, 90
],
TinkernetMultisigAsAccountId::<[u8; 32]>::convert_location(&mul).unwrap()
);
}
}
35 changes: 35 additions & 0 deletions xcm/xcm-builder/src/origin_conversion.rs
Expand Up @@ -16,8 +16,12 @@

//! Various implementations for `ConvertOrigin`.

use crate::location_conversion::{
derive_tinkernet_multisig, KUSAMA_TINKERNET_MULTISIG_PALLET, KUSAMA_TINKERNET_PARA_ID,
};
use frame_support::traits::{EnsureOrigin, Get, GetBacking, OriginTrait};
use frame_system::RawOrigin as SystemRawOrigin;
use parity_scale_codec::Decode;
use polkadot_parachain::primitives::IsSystem;
use sp_runtime::traits::TryConvert;
use sp_std::marker::PhantomData;
Expand Down Expand Up @@ -241,6 +245,37 @@ where
}
}

/// Convert a Tinkernet Multisig `MultiLocation` value into a `Signed` origin.
pub struct TinkernetMultisigAsNative<RuntimeOrigin>(PhantomData<RuntimeOrigin>);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Similarly, I think from an organization perspective, it is more correct for this configuration to be placed in the kusama runtime, as it is the only user of it. But I see that it is more "convenient" to do it like this.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Kusama is not the only user of these converters, parachains will also import these into their xcm configurations from xcm-builder. I believe this also responds the previous comment.

Copy link
Member

@ggwpez ggwpez Jun 28, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

About the previous comment: the TINKERNET_PARA_ID is only valid on Kusama, right? So could be named KUSAMA_ TINKERNET_PARA_ID.

impl<RuntimeOrigin: OriginTrait> ConvertOrigin<RuntimeOrigin>
for TinkernetMultisigAsNative<RuntimeOrigin>
where
RuntimeOrigin::AccountId: Decode,
{
fn convert_origin(
origin: impl Into<MultiLocation>,
kind: OriginKind,
) -> Result<RuntimeOrigin, MultiLocation> {
let origin = origin.into();
match (kind, origin) {
(
OriginKind::Native,
MultiLocation {
parents: _,
interior:
X3(
Junction::Parachain(KUSAMA_TINKERNET_PARA_ID),
Junction::PalletInstance(KUSAMA_TINKERNET_MULTISIG_PALLET),
// Index from which the multisig account is derived.
Junction::GeneralIndex(id),
),
},
) => Ok(RuntimeOrigin::signed(derive_tinkernet_multisig(id).map_err(|_| origin)?)),
(_, origin) => Err(origin),
}
}
}

/// `EnsureOrigin` barrier to convert from dispatch origin to XCM origin, if one exists.
pub struct EnsureXcmOrigin<RuntimeOrigin, Conversion>(PhantomData<(RuntimeOrigin, Conversion)>);
impl<RuntimeOrigin: OriginTrait + Clone, Conversion: TryConvert<RuntimeOrigin, MultiLocation>>
Expand Down