Files
pezkuwi-sdk/pezbridges/pezsnowbridge/primitives/core/src/location.rs
T
pezkuwichain 6b597bebcf fix: EnsureOrigin try_successful_origin and snowbridge rename
- 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
2025-12-25 01:26:18 +03:00

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."
);
}
}
}