Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Introduce Tinkernet multisig XCM configs to Kusama/Asset Hub Kusama #52

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

Filter by extension

Filter by extension


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

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

92 changes: 89 additions & 3 deletions relay/kusama/src/xcm_config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,19 +21,23 @@ use super::{
RuntimeCall, RuntimeEvent, RuntimeOrigin, StakingAdmin, TransactionByteFee, WeightToFee,
XcmPallet,
};
use core::marker::PhantomData;
use frame_support::{
match_types, parameter_types,
traits::{Contains, Everything, Nothing},
traits::{Contains, Everything, Nothing, OriginTrait},
weights::Weight,
};
use frame_system::EnsureRoot;
use kusama_runtime_constants::currency::CENTS;
use parity_scale_codec::{Decode, Encode};
use runtime_common::{
crowdloan, paras_registrar,
xcm_sender::{ChildParachainRouter, ExponentialPrice},
ToAuthor,
};
use sp_core::ConstU32;
use sp_core::{ConstU32, H256};
use sp_io::hashing::blake2_256;
use sp_runtime::traits::TrailingZeroInput;
use xcm::latest::prelude::*;
use xcm_builder::{
AccountId32Aliases, AllowExplicitUnpaidExecutionFrom, AllowKnownQueryResponses,
Expand All @@ -44,7 +48,7 @@ use xcm_builder::{
SovereignSignedViaLocation, TakeWeightCredit, TrailingSetTopicAsId, UsingComponents,
WeightInfoBounds, WithComputedOrigin, WithUniqueTopic,
};
use xcm_executor::traits::WithOriginFilter;
use xcm_executor::traits::{ConvertLocation, ConvertOrigin, WithOriginFilter};

parameter_types! {
/// The location of the KSM token, from the context of this chain. Since this token is native to this
Expand All @@ -70,6 +74,8 @@ pub type SovereignAccountOf = (
ChildParachainConvertsVia<ParaId, AccountId>,
// We can directly alias an `AccountId32` into a local account.
AccountId32Aliases<ThisNetwork, AccountId>,
// Mapping Tinkernet multisig to the correctly derived AccountId.
TinkernetMultisigAsAccountId<AccountId>,
);

/// Our asset transactor. This is what allows us to interest with the runtime facilities from the
Expand Down Expand Up @@ -99,6 +105,8 @@ type LocalOriginConverter = (
SignedAccountId32AsNative<ThisNetwork, RuntimeOrigin>,
// A system child parachain, expressed as a Superuser, converts to the `Root` origin.
ChildSystemParachainAsSuperuser<ParaId, RuntimeOrigin>,
// Derives signed AccountId origins for Tinkernet multisigs.
TinkernetMultisigAsNativeOrigin<RuntimeOrigin>,
);

parameter_types! {
Expand Down Expand Up @@ -424,6 +432,84 @@ impl pallet_xcm::Config for Runtime {
type AdminOrigin = EnsureRoot<AccountId>;
}

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

/// Tinkernet Multisig pallet instance used when matching Multisig MultiLocations.
const 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: 0,
interior:
X3(
Parachain(TINKERNET_PARA_ID),
PalletInstance(TINKERNET_MULTISIG_PALLET),
// Index from which the multisig account is derived.
GeneralIndex(id),
),
} => derive_tinkernet_multisig(*id).ok(),
_ => None,
}
}
}

/// Convert a Tinkernet Multisig `MultiLocation` value into a `Signed` origin.
pub struct TinkernetMultisigAsNativeOrigin<RuntimeOrigin>(PhantomData<RuntimeOrigin>);
impl<RuntimeOrigin: OriginTrait> ConvertOrigin<RuntimeOrigin>
for TinkernetMultisigAsNativeOrigin<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: 0,
interior:
X3(
Junction::Parachain(TINKERNET_PARA_ID),
Junction::PalletInstance(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),
}
}
}

#[test]
fn karura_liquid_staking_xcm_has_sane_weight_upper_limt() {
use frame_support::dispatch::GetDispatchInfo;
Expand Down
2 changes: 2 additions & 0 deletions system-parachains/asset-hubs/asset-hub-kusama/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ sp-block-builder = { default-features = false, version = "21.0.0" }
sp-consensus-aura = { default-features = false, version = "0.27.0" }
sp-core = { default-features = false, version = "23.0.0" }
sp-inherents = { default-features = false, version = "21.0.0" }
sp-io = { default-features = false , version = "25.0.0" }
sp-offchain = { default-features = false, version = "21.0.0" }
sp-runtime = { default-features = false, version = "26.0.0" }
sp-session = { default-features = false, version = "22.0.0" }
Expand Down Expand Up @@ -208,6 +209,7 @@ std = [
"sp-consensus-aura/std",
"sp-core/std",
"sp-inherents/std",
"sp-io/std",
"sp-offchain/std",
"sp-runtime/std",
"sp-session/std",
Expand Down
95 changes: 92 additions & 3 deletions system-parachains/asset-hubs/asset-hub-kusama/src/xcm_config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,15 +25,19 @@ use assets_common::{
FromSiblingParachain, IsForeignConcreteAsset, StartsWith, StartsWithExplicitGlobalConsensus,
},
};
use codec::{Decode, Encode};
use core::marker::PhantomData;
use frame_support::{
match_types, parameter_types,
traits::{ConstU32, Contains, Everything, Nothing, PalletInfoAccess},
traits::{ConstU32, Contains, Everything, Nothing, OriginTrait, PalletInfoAccess},
};
use frame_system::EnsureRoot;
use pallet_xcm::XcmPassthrough;
use parachains_common::{impls::ToStakingPot, xcm_config::AssetFeeAsExistentialDepositMultiplier};
use polkadot_parachain_primitives::primitives::Sibling;
use sp_runtime::traits::ConvertInto;
use sp_core::H256;
use sp_io::hashing::blake2_256;
use sp_runtime::traits::{ConvertInto, TrailingZeroInput};
use xcm::latest::prelude::*;
use xcm_builder::{
AccountId32Aliases, AllowExplicitUnpaidExecutionFrom, AllowKnownQueryResponses,
Expand All @@ -45,7 +49,10 @@ use xcm_builder::{
SovereignSignedViaLocation, TakeWeightCredit, TrailingSetTopicAsId, UsingComponents,
WeightInfoBounds, WithComputedOrigin, WithUniqueTopic,
};
use xcm_executor::{traits::WithOriginFilter, XcmExecutor};
use xcm_executor::{
traits::{ConvertLocation, ConvertOrigin, WithOriginFilter},
XcmExecutor,
};

#[cfg(feature = "runtime-benchmarks")]
use {cumulus_primitives_core::ParaId, sp_core::Get};
Expand Down Expand Up @@ -78,6 +85,8 @@ pub type LocationToAccountId = (
SiblingParachainConvertsVia<Sibling, AccountId>,
// Straight up local `AccountId32` origins just alias directly to `AccountId`.
AccountId32Aliases<RelayNetwork, AccountId>,
// Mapping Tinkernet multisig to the correctly derived AccountId.
TinkernetMultisigAsAccountId<AccountId>,
// Foreign locations alias into accounts according to a hash of their standard description.
HashedDescription<AccountId, DescribeFamily<DescribeAllTerminal>>,
);
Expand Down Expand Up @@ -211,6 +220,8 @@ pub type XcmOriginToTransactDispatchOrigin = (
// Native signed account converter; this just converts an `AccountId32` origin into a normal
// `RuntimeOrigin::Signed` origin of the same 32-byte value.
SignedAccountId32AsNative<RelayNetwork, RuntimeOrigin>,
// Derives signed AccountId origins for Tinkernet multisigs.
TinkernetMultisigAsNativeOrigin<RuntimeOrigin>,
// Xcm origins can be represented natively under the Xcm pallet's Xcm origin.
XcmPassthrough<RuntimeOrigin>,
);
Expand Down Expand Up @@ -624,3 +635,81 @@ where
sp_std::boxed::Box::new(Self::asset_id(asset_id))
}
}

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

/// Tinkernet Multisig pallet instance used when matching Multisig MultiLocations.
const 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: 1,
interior:
X3(
Parachain(TINKERNET_PARA_ID),
PalletInstance(TINKERNET_MULTISIG_PALLET),
// Index from which the multisig account is derived.
GeneralIndex(id),
),
} => derive_tinkernet_multisig(*id).ok(),
_ => None,
}
}
}

/// Convert a Tinkernet Multisig `MultiLocation` value into a `Signed` origin.
pub struct TinkernetMultisigAsNativeOrigin<RuntimeOrigin>(PhantomData<RuntimeOrigin>);
impl<RuntimeOrigin: OriginTrait> ConvertOrigin<RuntimeOrigin>
for TinkernetMultisigAsNativeOrigin<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: 1,
interior:
X3(
Junction::Parachain(TINKERNET_PARA_ID),
Junction::PalletInstance(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),
}
}
}