Skip to content

Commit 6f5442a

Browse files
imstar15chrisli30
andauthored
Generates private AccountIds from MultiLocations, in a stable & safe way (#484)
Co-authored-by: Chris Li <chrisli30@users.noreply.github.com>
1 parent b1f2c29 commit 6f5442a

File tree

6 files changed

+139
-6
lines changed

6 files changed

+139
-6
lines changed

Cargo.lock

Lines changed: 3 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

primitives/Cargo.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ repository = 'https://github.com/OAK-Foundation/OAK-blockchain'
99
edition = "2021"
1010

1111
[dependencies]
12+
impl-trait-for-tuples = "0.2.2"
1213
codec = { package = "parity-scale-codec", version = "3.0.0", features = [
1314
"derive",
1415
], default-features = false }
@@ -22,12 +23,14 @@ sp-std = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v
2223
sp-consensus-aura = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.43" }
2324
sp-core = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.43" }
2425
sp-runtime = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.43" }
26+
sp-io = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.43" }
2527

2628
## Substrate FRAME Dependencies
2729
frame-support = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.43" }
2830

2931
## Polkdadot deps
3032
xcm = { git = "https://github.com/paritytech/polkadot", branch = "release-v0.9.43", default-features = false }
33+
xcm-executor = { git = "https://github.com/paritytech/polkadot", default-features = false, branch = "release-v0.9.43" }
3134

3235
## ORML deps
3336
orml-traits = { git = "https://github.com/open-web3-stack/open-runtime-module-library", default-features = false, branch = "polkadot-v0.9.43" }

primitives/src/lib.rs

Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,3 +94,118 @@ impl<AbsoluteLocation: Get<MultiLocation>> Reserve
9494
})
9595
}
9696
}
97+
98+
// https://github.com/AstarNetwork/Astar/blob/2a8df8d098f6abc3fdf5aaf6514e94f615f9bdab/primitives/src/xcm/mod.rs#L276-L418
99+
// TODO: remove this after uplift to `polkadot-v0.9.44` or beyond, and replace it with code in XCM builder.
100+
101+
use codec::{Compact, Encode};
102+
use sp_io::hashing::blake2_256;
103+
use sp_std::prelude::*;
104+
use xcm_executor::traits::Convert as XcmConvert;
105+
106+
/// Means of converting a location into a stable and unique descriptive identifier.
107+
pub trait DescribeLocation {
108+
/// Create a description of the given `location` if possible. No two locations should have the
109+
/// same descriptor.
110+
fn describe_location(location: &MultiLocation) -> Option<Vec<u8>>;
111+
}
112+
113+
#[impl_trait_for_tuples::impl_for_tuples(30)]
114+
impl DescribeLocation for Tuple {
115+
fn describe_location(l: &MultiLocation) -> Option<Vec<u8>> {
116+
for_tuples!( #(
117+
match Tuple::describe_location(l) {
118+
Some(result) => return Some(result),
119+
None => {},
120+
}
121+
)* );
122+
None
123+
}
124+
}
125+
126+
pub struct DescribeTerminus;
127+
impl DescribeLocation for DescribeTerminus {
128+
fn describe_location(l: &MultiLocation) -> Option<Vec<u8>> {
129+
match (l.parents, &l.interior) {
130+
(0, Here) => Some(Vec::new()),
131+
_ => return None,
132+
}
133+
}
134+
}
135+
136+
pub struct DescribePalletTerminal;
137+
impl DescribeLocation for DescribePalletTerminal {
138+
fn describe_location(l: &MultiLocation) -> Option<Vec<u8>> {
139+
match (l.parents, &l.interior) {
140+
(0, X1(PalletInstance(i))) =>
141+
Some((b"Pallet", Compact::<u32>::from(*i as u32)).encode()),
142+
_ => return None,
143+
}
144+
}
145+
}
146+
147+
pub struct DescribeAccountId32Terminal;
148+
impl DescribeLocation for DescribeAccountId32Terminal {
149+
fn describe_location(l: &MultiLocation) -> Option<Vec<u8>> {
150+
match (l.parents, &l.interior) {
151+
(0, X1(AccountId32 { id, .. })) => Some((b"AccountId32", id).encode()),
152+
_ => return None,
153+
}
154+
}
155+
}
156+
157+
pub struct DescribeAccountKey20Terminal;
158+
impl DescribeLocation for DescribeAccountKey20Terminal {
159+
fn describe_location(l: &MultiLocation) -> Option<Vec<u8>> {
160+
match (l.parents, &l.interior) {
161+
(0, X1(AccountKey20 { key, .. })) => Some((b"AccountKey20", key).encode()),
162+
_ => return None,
163+
}
164+
}
165+
}
166+
167+
pub type DescribeAccountIdTerminal = (DescribeAccountId32Terminal, DescribeAccountKey20Terminal);
168+
169+
pub type DescribeAllTerminal = (
170+
DescribeTerminus,
171+
DescribePalletTerminal,
172+
DescribeAccountId32Terminal,
173+
DescribeAccountKey20Terminal,
174+
);
175+
176+
pub struct DescribeFamily<DescribeInterior>(PhantomData<DescribeInterior>);
177+
impl<Suffix: DescribeLocation> DescribeLocation for DescribeFamily<Suffix> {
178+
fn describe_location(l: &MultiLocation) -> Option<Vec<u8>> {
179+
match (l.parents, l.interior.first()) {
180+
(0, Some(Parachain(index))) => {
181+
let tail = l.interior.split_first().0;
182+
let interior = Suffix::describe_location(&tail.into())?;
183+
Some((b"ChildChain", Compact::<u32>::from(*index), interior).encode())
184+
},
185+
(1, Some(Parachain(index))) => {
186+
let tail = l.interior.split_first().0;
187+
let interior = Suffix::describe_location(&tail.into())?;
188+
Some((b"SiblingChain", Compact::<u32>::from(*index), interior).encode())
189+
},
190+
(1, _) => {
191+
let tail = l.interior.into();
192+
let interior = Suffix::describe_location(&tail)?;
193+
Some((b"ParentChain", interior).encode())
194+
},
195+
_ => return None,
196+
}
197+
}
198+
}
199+
200+
pub struct HashedDescription<AccountId, Describe>(PhantomData<(AccountId, Describe)>);
201+
impl<AccountId: From<[u8; 32]> + Clone, Describe: DescribeLocation>
202+
XcmConvert<MultiLocation, AccountId> for HashedDescription<AccountId, Describe>
203+
{
204+
fn convert(value: MultiLocation) -> Result<AccountId, MultiLocation> {
205+
if let Some(description) = Describe::describe_location(&value) {
206+
Ok(blake2_256(&description).into())
207+
} else {
208+
Err(value)
209+
}
210+
}
211+
}

runtime/neumann/src/xcm_config.rs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,9 @@ use orml_xcm_support::{
3636
DepositToAlternative, IsNativeConcrete, MultiCurrencyAdapter, MultiNativeAsset,
3737
};
3838

39-
use primitives::AbsoluteAndRelativeReserveProvider;
39+
use primitives::{
40+
AbsoluteAndRelativeReserveProvider, DescribeAllTerminal, DescribeFamily, HashedDescription,
41+
};
4042

4143
parameter_types! {
4244
pub const RelayLocation: MultiLocation = MultiLocation::parent();
@@ -55,7 +57,9 @@ pub type LocationToAccountId = (
5557
SiblingParachainConvertsVia<Sibling, AccountId>,
5658
// Straight up local `AccountId32` origins just alias directly to `AccountId`.
5759
AccountId32Aliases<RelayNetwork, AccountId>,
58-
Account32Hash<RelayNetwork, AccountId>,
60+
// Generates private `AccountId`s from `MultiLocation`s, in a stable & safe way.
61+
// Replaces the old `Account32Hash` approach.
62+
HashedDescription<AccountId, DescribeFamily<DescribeAllTerminal>>,
5963
);
6064

6165
pub type LocalAssetTransactor = MultiCurrencyAdapter<

runtime/oak/src/xcm_config.rs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,9 @@ use orml_xcm_support::{
3838
DepositToAlternative, IsNativeConcrete, MultiCurrencyAdapter, MultiNativeAsset,
3939
};
4040

41-
use primitives::AbsoluteAndRelativeReserveProvider;
41+
use primitives::{
42+
AbsoluteAndRelativeReserveProvider, DescribeAllTerminal, DescribeFamily, HashedDescription,
43+
};
4244

4345
parameter_types! {
4446
pub const RelayLocation: MultiLocation = MultiLocation::parent();
@@ -57,7 +59,9 @@ pub type LocationToAccountId = (
5759
SiblingParachainConvertsVia<Sibling, AccountId>,
5860
// Straight up local `AccountId32` origins just alias directly to `AccountId`.
5961
AccountId32Aliases<RelayNetwork, AccountId>,
60-
Account32Hash<RelayNetwork, AccountId>,
62+
// Generates private `AccountId`s from `MultiLocation`s, in a stable & safe way.
63+
// Replaces the old `Account32Hash` approach.
64+
HashedDescription<AccountId, DescribeFamily<DescribeAllTerminal>>,
6165
);
6266

6367
pub type LocalAssetTransactor = MultiCurrencyAdapter<

runtime/turing/src/xcm_config.rs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,9 @@ use orml_xcm_support::{
3737
DepositToAlternative, IsNativeConcrete, MultiCurrencyAdapter, MultiNativeAsset,
3838
};
3939

40-
use primitives::AbsoluteAndRelativeReserveProvider;
40+
use primitives::{
41+
AbsoluteAndRelativeReserveProvider, DescribeAllTerminal, DescribeFamily, HashedDescription,
42+
};
4143

4244
parameter_types! {
4345
pub const RelayLocation: MultiLocation = MultiLocation::parent();
@@ -57,7 +59,9 @@ pub type LocationToAccountId = (
5759
SiblingParachainConvertsVia<Sibling, AccountId>,
5860
// Straight up local `AccountId32` origins just alias directly to `AccountId`.
5961
AccountId32Aliases<RelayNetwork, AccountId>,
60-
Account32Hash<RelayNetwork, AccountId>,
62+
// Generates private `AccountId`s from `MultiLocation`s, in a stable & safe way.
63+
// Replaces the old `Account32Hash` approach.
64+
HashedDescription<AccountId, DescribeFamily<DescribeAllTerminal>>,
6165
);
6266

6367
pub type LocalAssetTransactor = MultiCurrencyAdapter<

0 commit comments

Comments
 (0)