mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-05-31 19:11:02 +00:00
[xcm] Foreign global consensus parachain LocationToAccountId converter (#7016)
* **Foreign** global consensus parachain LocationToAccount converter * Review fix * Added `UniversalLocation` + `ensure_is_remote` handling * Added unique id to encoding * Update xcm/xcm-builder/src/location_conversion.rs Co-authored-by: Gavin Wood <gavin@parity.io> * Re-export `ensure_is_remote` * Test * fmt * Update xcm/xcm-builder/src/location_conversion.rs * Update xcm/xcm-builder/src/universal_exports.rs Co-authored-by: Gavin Wood <gavin@parity.io> --------- Co-authored-by: parity-processbot <> Co-authored-by: Gavin Wood <gavin@parity.io>
This commit is contained in:
@@ -84,7 +84,7 @@ pub use filter_asset_location::{Case, NativeAsset};
|
|||||||
|
|
||||||
mod universal_exports;
|
mod universal_exports;
|
||||||
pub use universal_exports::{
|
pub use universal_exports::{
|
||||||
BridgeBlobDispatcher, BridgeMessage, DispatchBlob, DispatchBlobError, ExporterFor, HaulBlob,
|
ensure_is_remote, BridgeBlobDispatcher, BridgeMessage, DispatchBlob, DispatchBlobError,
|
||||||
HaulBlobError, HaulBlobExporter, NetworkExportTable, SovereignPaidRemoteExporter,
|
ExporterFor, HaulBlob, HaulBlobError, HaulBlobExporter, NetworkExportTable,
|
||||||
UnpaidLocalExporter, UnpaidRemoteExporter,
|
SovereignPaidRemoteExporter, UnpaidLocalExporter, UnpaidRemoteExporter,
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -14,6 +14,7 @@
|
|||||||
// You should have received a copy of the GNU General Public License
|
// You should have received a copy of the GNU General Public License
|
||||||
// along with Polkadot. If not, see <http://www.gnu.org/licenses/>.
|
// along with Polkadot. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
use crate::universal_exports::ensure_is_remote;
|
||||||
use frame_support::traits::Get;
|
use frame_support::traits::Get;
|
||||||
use parity_scale_codec::{Decode, Encode};
|
use parity_scale_codec::{Decode, Encode};
|
||||||
use sp_io::hashing::blake2_256;
|
use sp_io::hashing::blake2_256;
|
||||||
@@ -22,15 +23,15 @@ use sp_std::{borrow::Borrow, marker::PhantomData};
|
|||||||
use xcm::latest::prelude::*;
|
use xcm::latest::prelude::*;
|
||||||
use xcm_executor::traits::Convert;
|
use xcm_executor::traits::Convert;
|
||||||
|
|
||||||
/// Prefix for generating alias account for accounts coming
|
/// Prefix for generating alias account for accounts coming
|
||||||
/// from chains that use 32 byte long representations.
|
/// from chains that use 32 byte long representations.
|
||||||
pub const FOREIGN_CHAIN_PREFIX_PARA_32: [u8; 37] = *b"ForeignChainAliasAccountPrefix_Para32";
|
pub const FOREIGN_CHAIN_PREFIX_PARA_32: [u8; 37] = *b"ForeignChainAliasAccountPrefix_Para32";
|
||||||
|
|
||||||
/// Prefix for generating alias account for accounts coming
|
/// Prefix for generating alias account for accounts coming
|
||||||
/// from chains that use 20 byte long representations.
|
/// from chains that use 20 byte long representations.
|
||||||
pub const FOREIGN_CHAIN_PREFIX_PARA_20: [u8; 37] = *b"ForeignChainAliasAccountPrefix_Para20";
|
pub const FOREIGN_CHAIN_PREFIX_PARA_20: [u8; 37] = *b"ForeignChainAliasAccountPrefix_Para20";
|
||||||
|
|
||||||
/// Prefix for generating alias account for accounts coming
|
/// Prefix for generating alias account for accounts coming
|
||||||
/// from the relay chain using 32 byte long representations.
|
/// from the relay chain using 32 byte long representations.
|
||||||
pub const FOREIGN_CHAIN_PREFIX_RELAY: [u8; 36] = *b"ForeignChainAliasAccountPrefix_Relay";
|
pub const FOREIGN_CHAIN_PREFIX_RELAY: [u8; 36] = *b"ForeignChainAliasAccountPrefix_Relay";
|
||||||
|
|
||||||
@@ -48,7 +49,7 @@ pub const FOREIGN_CHAIN_PREFIX_RELAY: [u8; 36] = *b"ForeignChainAliasAccountPref
|
|||||||
/// ```notrust
|
/// ```notrust
|
||||||
/// R
|
/// R
|
||||||
/// / \
|
/// / \
|
||||||
/// / \
|
/// / \
|
||||||
/// P1 P2
|
/// P1 P2
|
||||||
/// / \ / \
|
/// / \ / \
|
||||||
/// / \ / \
|
/// / \ / \
|
||||||
@@ -252,6 +253,58 @@ impl<Network: Get<Option<NetworkId>>, AccountId: From<[u8; 20]> + Into<[u8; 20]>
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// 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`.
|
||||||
|
///
|
||||||
|
/// This will always result in the *same account ID* being returned for the same
|
||||||
|
/// parachain index under the same Relay-chain, regardless of the relative security of
|
||||||
|
/// this Relay-chain compared to the local chain.
|
||||||
|
///
|
||||||
|
/// Note: No distinction is made when the local chain happens to be the parachain in
|
||||||
|
/// question or its Relay-chain.
|
||||||
|
///
|
||||||
|
/// WARNING: This results in the same `AccountId` value being generated regardless
|
||||||
|
/// of the relative security of the local chain and the Relay-chain of the input
|
||||||
|
/// location. This may not have any immediate security risks, however since it creates
|
||||||
|
/// commonalities between chains with different security characteristics, it could
|
||||||
|
/// possibly form part of a more sophisticated attack scenario.
|
||||||
|
pub struct GlobalConsensusParachainConvertsFor<UniversalLocation, AccountId>(
|
||||||
|
PhantomData<(UniversalLocation, AccountId)>,
|
||||||
|
);
|
||||||
|
impl<UniversalLocation: Get<InteriorMultiLocation>, AccountId: From<[u8; 32]> + Clone>
|
||||||
|
Convert<MultiLocation, AccountId>
|
||||||
|
for GlobalConsensusParachainConvertsFor<UniversalLocation, AccountId>
|
||||||
|
{
|
||||||
|
fn convert_ref(location: impl Borrow<MultiLocation>) -> Result<AccountId, ()> {
|
||||||
|
let universal_source = UniversalLocation::get();
|
||||||
|
log::trace!(
|
||||||
|
target: "xcm::location_conversion",
|
||||||
|
"GlobalConsensusParachainConvertsFor universal_source: {:?}, location: {:?}",
|
||||||
|
universal_source, location.borrow(),
|
||||||
|
);
|
||||||
|
let devolved = ensure_is_remote(universal_source, *location.borrow()).map_err(|_| ())?;
|
||||||
|
let (remote_network, remote_location) = devolved;
|
||||||
|
|
||||||
|
match remote_location {
|
||||||
|
X1(Parachain(remote_network_para_id)) =>
|
||||||
|
Ok(AccountId::from(Self::from_params(&remote_network, &remote_network_para_id))),
|
||||||
|
_ => Err(()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn reverse_ref(_: impl Borrow<AccountId>) -> Result<MultiLocation, ()> {
|
||||||
|
// if this will be needed, we could implement some kind of guessing, if we have configuration for supported networkId+paraId
|
||||||
|
Err(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl<UniversalLocation, AccountId>
|
||||||
|
GlobalConsensusParachainConvertsFor<UniversalLocation, AccountId>
|
||||||
|
{
|
||||||
|
fn from_params(network: &NetworkId, para_id: &u32) -> [u8; 32] {
|
||||||
|
(b"glblcnsnss/prchn_", network, para_id).using_encoded(blake2_256)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
@@ -331,6 +384,112 @@ mod tests {
|
|||||||
assert_eq!(inverted, Err(()));
|
assert_eq!(inverted, Err(()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn global_consensus_parachain_converts_for_works() {
|
||||||
|
parameter_types! {
|
||||||
|
pub UniversalLocation: InteriorMultiLocation = X2(GlobalConsensus(ByGenesis([9; 32])), Parachain(1234));
|
||||||
|
}
|
||||||
|
|
||||||
|
let test_data = vec![
|
||||||
|
(MultiLocation::parent(), false),
|
||||||
|
(MultiLocation::new(0, X1(Parachain(1000))), false),
|
||||||
|
(MultiLocation::new(1, X1(Parachain(1000))), false),
|
||||||
|
(
|
||||||
|
MultiLocation::new(
|
||||||
|
2,
|
||||||
|
X3(
|
||||||
|
GlobalConsensus(ByGenesis([0; 32])),
|
||||||
|
Parachain(1000),
|
||||||
|
AccountId32 { network: None, id: [1; 32].into() },
|
||||||
|
),
|
||||||
|
),
|
||||||
|
false,
|
||||||
|
),
|
||||||
|
(MultiLocation::new(2, X1(GlobalConsensus(ByGenesis([0; 32])))), false),
|
||||||
|
(
|
||||||
|
MultiLocation::new(0, X2(GlobalConsensus(ByGenesis([0; 32])), Parachain(1000))),
|
||||||
|
false,
|
||||||
|
),
|
||||||
|
(
|
||||||
|
MultiLocation::new(1, X2(GlobalConsensus(ByGenesis([0; 32])), Parachain(1000))),
|
||||||
|
false,
|
||||||
|
),
|
||||||
|
(MultiLocation::new(2, X2(GlobalConsensus(ByGenesis([0; 32])), Parachain(1000))), true),
|
||||||
|
(
|
||||||
|
MultiLocation::new(3, X2(GlobalConsensus(ByGenesis([0; 32])), Parachain(1000))),
|
||||||
|
false,
|
||||||
|
),
|
||||||
|
(
|
||||||
|
MultiLocation::new(9, X2(GlobalConsensus(ByGenesis([0; 32])), Parachain(1000))),
|
||||||
|
false,
|
||||||
|
),
|
||||||
|
];
|
||||||
|
|
||||||
|
for (location, expected_result) in test_data {
|
||||||
|
let result =
|
||||||
|
GlobalConsensusParachainConvertsFor::<UniversalLocation, [u8; 32]>::convert_ref(
|
||||||
|
&location,
|
||||||
|
);
|
||||||
|
match result {
|
||||||
|
Ok(account) => {
|
||||||
|
assert_eq!(
|
||||||
|
true, expected_result,
|
||||||
|
"expected_result: {}, but conversion passed: {:?}, location: {:?}",
|
||||||
|
expected_result, account, location
|
||||||
|
);
|
||||||
|
match &location {
|
||||||
|
MultiLocation { interior: X2(GlobalConsensus(network), Parachain(para_id)), .. } =>
|
||||||
|
assert_eq!(
|
||||||
|
account,
|
||||||
|
GlobalConsensusParachainConvertsFor::<UniversalLocation, [u8; 32]>::from_params(network, para_id),
|
||||||
|
"expected_result: {}, but conversion passed: {:?}, location: {:?}", expected_result, account, location
|
||||||
|
),
|
||||||
|
_ => assert_eq!(
|
||||||
|
true,
|
||||||
|
expected_result,
|
||||||
|
"expected_result: {}, conversion passed: {:?}, but MultiLocation does not match expected pattern, location: {:?}", expected_result, account, location
|
||||||
|
)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
Err(_) => {
|
||||||
|
assert_eq!(
|
||||||
|
false, expected_result,
|
||||||
|
"expected_result: {} - but conversion failed, location: {:?}",
|
||||||
|
expected_result, location
|
||||||
|
);
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// all success
|
||||||
|
let res_gc_a_p1000 =
|
||||||
|
GlobalConsensusParachainConvertsFor::<UniversalLocation, [u8; 32]>::convert_ref(
|
||||||
|
MultiLocation::new(2, X2(GlobalConsensus(ByGenesis([3; 32])), Parachain(1000))),
|
||||||
|
)
|
||||||
|
.expect("conversion is ok");
|
||||||
|
let res_gc_a_p1001 =
|
||||||
|
GlobalConsensusParachainConvertsFor::<UniversalLocation, [u8; 32]>::convert_ref(
|
||||||
|
MultiLocation::new(2, X2(GlobalConsensus(ByGenesis([3; 32])), Parachain(1001))),
|
||||||
|
)
|
||||||
|
.expect("conversion is ok");
|
||||||
|
let res_gc_b_p1000 =
|
||||||
|
GlobalConsensusParachainConvertsFor::<UniversalLocation, [u8; 32]>::convert_ref(
|
||||||
|
MultiLocation::new(2, X2(GlobalConsensus(ByGenesis([4; 32])), Parachain(1000))),
|
||||||
|
)
|
||||||
|
.expect("conversion is ok");
|
||||||
|
let res_gc_b_p1001 =
|
||||||
|
GlobalConsensusParachainConvertsFor::<UniversalLocation, [u8; 32]>::convert_ref(
|
||||||
|
MultiLocation::new(2, X2(GlobalConsensus(ByGenesis([4; 32])), Parachain(1001))),
|
||||||
|
)
|
||||||
|
.expect("conversion is ok");
|
||||||
|
assert_ne!(res_gc_a_p1000, res_gc_a_p1001);
|
||||||
|
assert_ne!(res_gc_a_p1000, res_gc_b_p1000);
|
||||||
|
assert_ne!(res_gc_a_p1000, res_gc_b_p1001);
|
||||||
|
assert_ne!(res_gc_b_p1000, res_gc_b_p1001);
|
||||||
|
assert_ne!(res_gc_b_p1000, res_gc_a_p1001);
|
||||||
|
assert_ne!(res_gc_b_p1001, res_gc_a_p1001);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn remote_account_convert_on_para_sending_para_32() {
|
fn remote_account_convert_on_para_sending_para_32() {
|
||||||
let mul = MultiLocation {
|
let mul = MultiLocation {
|
||||||
|
|||||||
@@ -23,7 +23,11 @@ use xcm::prelude::*;
|
|||||||
use xcm_executor::traits::{validate_export, ExportXcm};
|
use xcm_executor::traits::{validate_export, ExportXcm};
|
||||||
use SendError::*;
|
use SendError::*;
|
||||||
|
|
||||||
fn ensure_is_remote(
|
/// Returns the network ID and consensus location within that network of the remote
|
||||||
|
/// location `dest` which is itself specified as a location relative to the local
|
||||||
|
/// chain, itself situated at `universal_local` within the consensus universe. If
|
||||||
|
/// `dest` is not a location in remote consensus, then an error is returned.
|
||||||
|
pub fn ensure_is_remote(
|
||||||
universal_local: impl Into<InteriorMultiLocation>,
|
universal_local: impl Into<InteriorMultiLocation>,
|
||||||
dest: impl Into<MultiLocation>,
|
dest: impl Into<MultiLocation>,
|
||||||
) -> Result<(NetworkId, InteriorMultiLocation), MultiLocation> {
|
) -> Result<(NetworkId, InteriorMultiLocation), MultiLocation> {
|
||||||
|
|||||||
Reference in New Issue
Block a user