[xcm] GlobalConsensusConvertsFor for remote relay chain (based on pevious GlobalConsensusParachainConvertsFor) (#7517)

* [xcm] `GlobalConsensusConvertsFor` for remote relay chain (based on previous GlobalConsensusParachainConvertsFor)

* Typo

* PR fix (constants in test)

* Re-export of `GlobalConsensusConvertsFor`

* assert to panic

* Update xcm/src/v3/multiasset.rs

Co-authored-by: joe petrowski <25483142+joepetrowski@users.noreply.github.com>

* Update xcm/xcm-builder/src/location_conversion.rs

Co-authored-by: joe petrowski <25483142+joepetrowski@users.noreply.github.com>

* Update xcm/xcm-builder/src/location_conversion.rs

Co-authored-by: joe petrowski <25483142+joepetrowski@users.noreply.github.com>

* Review fixes

---------

Co-authored-by: parity-processbot <>
Co-authored-by: joe petrowski <25483142+joepetrowski@users.noreply.github.com>
This commit is contained in:
Branislav Kontur
2023-08-03 10:32:49 +02:00
committed by GitHub
parent 2bbc7a73a3
commit ee54e62c90
3 changed files with 139 additions and 3 deletions
+1 -1
View File
@@ -406,7 +406,7 @@ pub struct MultiAsset {
/// The overall asset identity (aka *class*, in the case of a non-fungible).
pub id: AssetId,
/// The fungibility of the asset, which contains either the amount (in the case of a fungible
/// asset) or the *instance ID`, the secondary asset identifier.
/// asset) or the *instance ID*, the secondary asset identifier.
pub fun: Fungibility,
}
+3 -2
View File
@@ -33,8 +33,9 @@ pub use location_conversion::{
Account32Hash, AccountId32Aliases, AccountKey20Aliases, AliasesIntoAccountId32,
ChildParachainConvertsVia, DescribeAccountId32Terminal, DescribeAccountIdTerminal,
DescribeAccountKey20Terminal, DescribeAllTerminal, DescribeFamily, DescribeLocation,
DescribePalletTerminal, DescribeTerminus, GlobalConsensusParachainConvertsFor,
HashedDescription, ParentIsPreset, SiblingParachainConvertsVia,
DescribePalletTerminal, DescribeTerminus, GlobalConsensusConvertsFor,
GlobalConsensusParachainConvertsFor, HashedDescription, ParentIsPreset,
SiblingParachainConvertsVia,
};
mod origin_conversion;
@@ -345,6 +345,42 @@ impl<Network: Get<Option<NetworkId>>, AccountId: From<[u8; 20]> + Into<[u8; 20]>
}
}
/// Converts a location which is a top-level relay chain (which provides its own consensus) into a 32-byte `AccountId`.
///
/// This will always result in the *same account ID* being returned for the same Relay-chain, regardless of the relative security of
/// this Relay-chain compared to the local chain.
///
/// Note: No distinction is made between the cases when the given `UniversalLocation` lies within
/// the same consensus system (i.e. is itself or a parent) and when it is a foreign consensus
/// system.
pub struct GlobalConsensusConvertsFor<UniversalLocation, AccountId>(
PhantomData<(UniversalLocation, AccountId)>,
);
impl<UniversalLocation: Get<InteriorMultiLocation>, AccountId: From<[u8; 32]> + Clone>
ConvertLocation<AccountId> for GlobalConsensusConvertsFor<UniversalLocation, AccountId>
{
fn convert_location(location: &MultiLocation) -> Option<AccountId> {
let universal_source = UniversalLocation::get();
log::trace!(
target: "xcm::location_conversion",
"GlobalConsensusConvertsFor universal_source: {:?}, location: {:?}",
universal_source, location,
);
let (remote_network, remote_location) =
ensure_is_remote(universal_source, *location).ok()?;
match remote_location {
Here => Some(AccountId::from(Self::from_params(&remote_network))),
_ => None,
}
}
}
impl<UniversalLocation, AccountId> GlobalConsensusConvertsFor<UniversalLocation, AccountId> {
fn from_params(network: &NetworkId) -> [u8; 32] {
(b"glblcnsnss_", network).using_encoded(blake2_256)
}
}
/// 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`.
///
@@ -473,6 +509,105 @@ mod tests {
assert_eq!(inverted, Err(()));
}
#[test]
fn global_consensus_converts_for_works() {
parameter_types! {
pub UniversalLocationInNetwork1: InteriorMultiLocation = X2(GlobalConsensus(ByGenesis([1; 32])), Parachain(1234));
pub UniversalLocationInNetwork2: InteriorMultiLocation = X2(GlobalConsensus(ByGenesis([2; 32])), Parachain(1234));
}
let network_1 = UniversalLocationInNetwork1::get().global_consensus().expect("NetworkId");
let network_2 = UniversalLocationInNetwork2::get().global_consensus().expect("NetworkId");
let network_3 = ByGenesis([3; 32]);
let network_4 = ByGenesis([4; 32]);
let network_5 = ByGenesis([5; 32]);
let test_data = vec![
(MultiLocation::parent(), false),
(MultiLocation::new(0, Here), false),
(MultiLocation::new(0, X1(GlobalConsensus(network_1))), false),
(MultiLocation::new(1, X1(GlobalConsensus(network_1))), false),
(MultiLocation::new(2, X1(GlobalConsensus(network_1))), false),
(MultiLocation::new(0, X1(GlobalConsensus(network_2))), false),
(MultiLocation::new(1, X1(GlobalConsensus(network_2))), false),
(MultiLocation::new(2, X1(GlobalConsensus(network_2))), true),
(MultiLocation::new(0, X2(GlobalConsensus(network_2), Parachain(1000))), false),
(MultiLocation::new(1, X2(GlobalConsensus(network_2), Parachain(1000))), false),
(MultiLocation::new(2, X2(GlobalConsensus(network_2), Parachain(1000))), false),
];
for (location, expected_result) in test_data {
let result =
GlobalConsensusConvertsFor::<UniversalLocationInNetwork1, [u8; 32]>::convert_location(
&location,
);
match result {
Some(account) => {
assert_eq!(
true, expected_result,
"expected_result: {}, but conversion passed: {:?}, location: {:?}",
expected_result, account, location
);
match &location {
MultiLocation { interior: X1(GlobalConsensus(network)), .. } =>
assert_eq!(
account,
GlobalConsensusConvertsFor::<UniversalLocationInNetwork1, [u8; 32]>::from_params(network),
"expected_result: {}, but conversion passed: {:?}, location: {:?}", expected_result, account, location
),
_ => panic!("expected_result: {}, conversion passed: {:?}, but MultiLocation does not match expected pattern, location: {:?}", expected_result, account, location)
}
},
None => {
assert_eq!(
false, expected_result,
"expected_result: {} - but conversion failed, location: {:?}",
expected_result, location
);
},
}
}
// all success
let res_1_gc_network_3 =
GlobalConsensusConvertsFor::<UniversalLocationInNetwork1, [u8; 32]>::convert_location(
&MultiLocation::new(2, X1(GlobalConsensus(network_3))),
)
.expect("conversion is ok");
let res_2_gc_network_3 =
GlobalConsensusConvertsFor::<UniversalLocationInNetwork2, [u8; 32]>::convert_location(
&MultiLocation::new(2, X1(GlobalConsensus(network_3))),
)
.expect("conversion is ok");
let res_1_gc_network_4 =
GlobalConsensusConvertsFor::<UniversalLocationInNetwork1, [u8; 32]>::convert_location(
&MultiLocation::new(2, X1(GlobalConsensus(network_4))),
)
.expect("conversion is ok");
let res_2_gc_network_4 =
GlobalConsensusConvertsFor::<UniversalLocationInNetwork2, [u8; 32]>::convert_location(
&MultiLocation::new(2, X1(GlobalConsensus(network_4))),
)
.expect("conversion is ok");
let res_1_gc_network_5 =
GlobalConsensusConvertsFor::<UniversalLocationInNetwork1, [u8; 32]>::convert_location(
&MultiLocation::new(2, X1(GlobalConsensus(network_5))),
)
.expect("conversion is ok");
let res_2_gc_network_5 =
GlobalConsensusConvertsFor::<UniversalLocationInNetwork2, [u8; 32]>::convert_location(
&MultiLocation::new(2, X1(GlobalConsensus(network_5))),
)
.expect("conversion is ok");
assert_ne!(res_1_gc_network_3, res_1_gc_network_4);
assert_ne!(res_1_gc_network_4, res_1_gc_network_5);
assert_ne!(res_1_gc_network_3, res_1_gc_network_5);
assert_eq!(res_1_gc_network_3, res_2_gc_network_3);
assert_eq!(res_1_gc_network_4, res_2_gc_network_4);
assert_eq!(res_1_gc_network_5, res_2_gc_network_5);
}
#[test]
fn global_consensus_parachain_converts_for_works() {
parameter_types! {