6b597bebcf
- Fix pezpallet-welati EnsureOrigin implementations (3 fixes)
- Remove incorrect #[cfg(not(feature = "runtime-benchmarks"))] blocks
- Affects EnsureSerok, EnsureParlementer, EnsureDiwan
- Fix asset-hub-zagros governance origins macros (2 fixes)
- Remove non-benchmark try_successful_origin from decl_unit_ensures!
- Remove non-benchmark try_successful_origin from decl_ensure!
- Rename snowbridge -> pezsnowbridge for consistency
- Update WORKFLOW_PLAN.md with build status and package names
- Correct package names: pezkuwi-teyrchain-bin, pezstaging-node-cli
- Mark completed builds: pezkuwi, pezkuwi-teyrchain-bin,
pezstaging-node-cli, teyrchain-template-node
233 lines
6.5 KiB
Rust
233 lines
6.5 KiB
Rust
// SPDX-License-Identifier: Apache-2.0
|
|
// SPDX-FileCopyrightText: 2023 Snowfork <hello@snowfork.com>
|
|
//! # Location
|
|
//!
|
|
//! Location helpers for dealing with Tokens and Agents
|
|
|
|
pub use pezkuwi_teyrchain_primitives::primitives::{
|
|
Id as ParaId, IsSystem, Sibling as SiblingParaId,
|
|
};
|
|
pub use pezsp_core::U256;
|
|
|
|
use codec::Encode;
|
|
use pezsp_core::H256;
|
|
use pezsp_std::prelude::*;
|
|
use xcm::prelude::{
|
|
AccountId32, AccountKey20, GeneralIndex, GeneralKey, GlobalConsensus, Location, PalletInstance,
|
|
};
|
|
use xcm_builder::{
|
|
DescribeAllTerminal, DescribeFamily, DescribeLocation, DescribeTerminus, HashedDescription,
|
|
};
|
|
|
|
pub type AgentId = H256;
|
|
|
|
/// Creates an AgentId from a Location. An AgentId is a unique mapping to an Agent contract on
|
|
/// Ethereum which acts as the sovereign account for the Location.
|
|
/// Resolves Pezkuwi locations (as seen by Ethereum) to unique `AgentId` identifiers.
|
|
pub type AgentIdOf = HashedDescription<
|
|
AgentId,
|
|
(
|
|
DescribeHere,
|
|
DescribeFamily<DescribeAllTerminal>,
|
|
DescribeGlobalPrefix<(DescribeTerminus, DescribeFamily<DescribeTokenTerminal>)>,
|
|
),
|
|
>;
|
|
|
|
pub type TokenId = H256;
|
|
|
|
/// Convert a token location (relative to Ethereum) to a stable ID that can be used on the Ethereum
|
|
/// side
|
|
pub type TokenIdOf = HashedDescription<
|
|
TokenId,
|
|
DescribeGlobalPrefix<(DescribeTerminus, DescribeFamily<DescribeTokenTerminal>)>,
|
|
>;
|
|
|
|
/// This looks like DescribeTerminus that was added to xcm-builder. However this does an extra
|
|
/// `encode` to the Vector producing a different output to DescribeTerminus. `DescribeHere`
|
|
/// should NOT be used for new code. This is left here for backwards compatibility of channels and
|
|
/// agents.
|
|
pub struct DescribeHere;
|
|
#[allow(deprecated)]
|
|
impl DescribeLocation for DescribeHere {
|
|
fn describe_location(l: &Location) -> Option<Vec<u8>> {
|
|
match l.unpack() {
|
|
(0, []) => Some(Vec::<u8>::new().encode()),
|
|
_ => None,
|
|
}
|
|
}
|
|
}
|
|
pub struct DescribeGlobalPrefix<DescribeInterior>(pezsp_std::marker::PhantomData<DescribeInterior>);
|
|
impl<Suffix: DescribeLocation> DescribeLocation for DescribeGlobalPrefix<Suffix> {
|
|
fn describe_location(l: &Location) -> Option<Vec<u8>> {
|
|
match (l.parent_count(), l.first_interior()) {
|
|
(1, Some(GlobalConsensus(network))) => {
|
|
let mut tail = l.clone().split_first_interior().0;
|
|
tail.dec_parent();
|
|
let interior = Suffix::describe_location(&tail)?;
|
|
Some((b"GlobalConsensus", network, interior).encode())
|
|
},
|
|
_ => None,
|
|
}
|
|
}
|
|
}
|
|
|
|
pub struct DescribeTokenTerminal;
|
|
impl DescribeLocation for DescribeTokenTerminal {
|
|
fn describe_location(l: &Location) -> Option<Vec<u8>> {
|
|
match l.unpack().1 {
|
|
[] => Some(Vec::<u8>::new().encode()),
|
|
[GeneralIndex(index)] => Some((b"GeneralIndex", *index).encode()),
|
|
[GeneralKey { data, .. }] => Some((b"GeneralKey", *data).encode()),
|
|
[AccountKey20 { key, .. }] => Some((b"AccountKey20", *key).encode()),
|
|
[AccountId32 { id, .. }] => Some((b"AccountId32", *id).encode()),
|
|
|
|
// Pezpallet
|
|
[PalletInstance(instance)] => Some((b"PalletInstance", *instance).encode()),
|
|
[PalletInstance(instance), GeneralIndex(index)] => {
|
|
Some((b"PalletInstance", *instance, b"GeneralIndex", *index).encode())
|
|
},
|
|
[PalletInstance(instance), GeneralKey { data, .. }] => {
|
|
Some((b"PalletInstance", *instance, b"GeneralKey", *data).encode())
|
|
},
|
|
|
|
[PalletInstance(instance), AccountKey20 { key, .. }] => {
|
|
Some((b"PalletInstance", *instance, b"AccountKey20", *key).encode())
|
|
},
|
|
[PalletInstance(instance), AccountId32 { id, .. }] => {
|
|
Some((b"PalletInstance", *instance, b"AccountId32", *id).encode())
|
|
},
|
|
|
|
// Reject all other locations
|
|
_ => None,
|
|
}
|
|
}
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod tests {
|
|
use crate::TokenIdOf;
|
|
use xcm::{
|
|
latest::ZAGROS_GENESIS_HASH,
|
|
prelude::{
|
|
GeneralIndex, GeneralKey, GlobalConsensus, Junction::*, Location, NetworkId::ByGenesis,
|
|
PalletInstance, Teyrchain,
|
|
},
|
|
};
|
|
use xcm_executor::traits::ConvertLocation;
|
|
|
|
#[test]
|
|
fn test_token_of_id() {
|
|
let token_locations = [
|
|
// Relay Chain cases
|
|
// Relay Chain relative to Ethereum
|
|
Location::new(1, [GlobalConsensus(ByGenesis(ZAGROS_GENESIS_HASH))]),
|
|
// Teyrchain cases
|
|
// Teyrchain relative to Ethereum
|
|
Location::new(1, [GlobalConsensus(ByGenesis(ZAGROS_GENESIS_HASH)), Teyrchain(2000)]),
|
|
// Teyrchain general index
|
|
Location::new(
|
|
1,
|
|
[GlobalConsensus(ByGenesis(ZAGROS_GENESIS_HASH)), Teyrchain(2000), GeneralIndex(1)],
|
|
),
|
|
// Teyrchain general key
|
|
Location::new(
|
|
1,
|
|
[
|
|
GlobalConsensus(ByGenesis(ZAGROS_GENESIS_HASH)),
|
|
Teyrchain(2000),
|
|
GeneralKey { length: 32, data: [0; 32] },
|
|
],
|
|
),
|
|
// Teyrchain account key 20
|
|
Location::new(
|
|
1,
|
|
[
|
|
GlobalConsensus(ByGenesis(ZAGROS_GENESIS_HASH)),
|
|
Teyrchain(2000),
|
|
AccountKey20 { network: None, key: [0; 20] },
|
|
],
|
|
),
|
|
// Teyrchain account id 32
|
|
Location::new(
|
|
1,
|
|
[
|
|
GlobalConsensus(ByGenesis(ZAGROS_GENESIS_HASH)),
|
|
Teyrchain(2000),
|
|
AccountId32 { network: None, id: [0; 32] },
|
|
],
|
|
),
|
|
// Parchain Pezpallet instance cases
|
|
// Teyrchain pezpallet instance
|
|
Location::new(
|
|
1,
|
|
[
|
|
GlobalConsensus(ByGenesis(ZAGROS_GENESIS_HASH)),
|
|
Teyrchain(2000),
|
|
PalletInstance(8),
|
|
],
|
|
),
|
|
// Teyrchain Pezpallet general index
|
|
Location::new(
|
|
1,
|
|
[
|
|
GlobalConsensus(ByGenesis(ZAGROS_GENESIS_HASH)),
|
|
Teyrchain(2000),
|
|
PalletInstance(8),
|
|
GeneralIndex(1),
|
|
],
|
|
),
|
|
// Teyrchain Pezpallet general key
|
|
Location::new(
|
|
1,
|
|
[
|
|
GlobalConsensus(ByGenesis(ZAGROS_GENESIS_HASH)),
|
|
Teyrchain(2000),
|
|
PalletInstance(8),
|
|
GeneralKey { length: 32, data: [0; 32] },
|
|
],
|
|
),
|
|
// Teyrchain Pezpallet account key 20
|
|
Location::new(
|
|
1,
|
|
[
|
|
GlobalConsensus(ByGenesis(ZAGROS_GENESIS_HASH)),
|
|
Teyrchain(2000),
|
|
PalletInstance(8),
|
|
AccountKey20 { network: None, key: [0; 20] },
|
|
],
|
|
),
|
|
// Teyrchain Pezpallet account id 32
|
|
Location::new(
|
|
1,
|
|
[
|
|
GlobalConsensus(ByGenesis(ZAGROS_GENESIS_HASH)),
|
|
Teyrchain(2000),
|
|
PalletInstance(8),
|
|
AccountId32 { network: None, id: [0; 32] },
|
|
],
|
|
),
|
|
];
|
|
|
|
for token in token_locations {
|
|
assert!(
|
|
TokenIdOf::convert_location(&token).is_some(),
|
|
"Valid token = {token:?} yields no TokenId."
|
|
);
|
|
}
|
|
|
|
let non_token_locations = [
|
|
// Relative location for a token should fail.
|
|
Location::new(1, []),
|
|
// Relative location for a token should fail.
|
|
Location::new(1, [Teyrchain(1000)]),
|
|
];
|
|
|
|
for token in non_token_locations {
|
|
assert!(
|
|
TokenIdOf::convert_location(&token).is_none(),
|
|
"Invalid token = {token:?} yields a TokenId."
|
|
);
|
|
}
|
|
}
|
|
}
|