1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54
//! Core Account Derivation.
//!
//! ## Overview
//!
//! This module defines a method for generating account addresses, and how it's implemented within this
//! pallet. We use a custom derivation scheme to ensure that when a multisig is created, its AccountId
//! remains consistent across different parachains, promoting seamless interaction.
//!
//! ### The module contains:
//! - `CoreAccountDerivation` trait: The interface for our derivation method.
//! - Pallet implementation: The specific logic used to derive AccountIds.
use crate::{Config, Pallet};
use codec::{Compact, Encode};
use frame_support::traits::Get;
use sp_io::hashing::blake2_256;
use xcm::v3::{BodyId, BodyPart, Junction, Junctions};
/// Trait providing the XCM location and the derived account of a core.
pub trait CoreAccountDerivation<T: Config> {
/// Derives the core's AccountId.
fn derive_core_account(core_id: T::CoreId) -> T::AccountId;
/// Specifies a core's location.
fn core_location(core_id: T::CoreId) -> Junctions;
}
impl<T: Config> CoreAccountDerivation<T> for Pallet<T>
where
T::AccountId: From<[u8; 32]>,
{
/// HashedDescription of the core location from the perspective of a sibling chain.
/// This derivation allows the local account address to match the account address in other parachains.
/// Reference: https://github.com/paritytech/polkadot-sdk/blob/master/polkadot/xcm/xcm-builder/src/location_conversion.rs
fn derive_core_account(core_id: T::CoreId) -> T::AccountId {
blake2_256(
&(
b"SiblingChain",
Compact::<u32>::from(T::ParaId::get()),
(b"Body", BodyId::Index(core_id.into()), BodyPart::Voice).encode(),
)
.encode(),
)
.into()
}
/// Core location is defined as a plurality within the parachain.
fn core_location(core_id: T::CoreId) -> Junctions {
Junctions::X2(
Junction::Parachain(T::ParaId::get()),
Junction::Plurality {
id: BodyId::Index(core_id.into()),
part: BodyPart::Voice,
},
)
}
}