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
This commit is contained in:
2025-12-25 01:26:18 +03:00
parent ee2385e28f
commit 3ddf58cef9
194 changed files with 129 additions and 129 deletions
@@ -0,0 +1,11 @@
// SPDX-License-Identifier: Apache-2.0
// SPDX-FileCopyrightText: 2023 Snowfork <hello@snowfork.com>
pub mod mock_converter;
pub mod mock_inbound_queue;
pub mod mock_origin;
pub mod mock_outbound_queue;
pub mod mock_rewards;
pub mod mock_swap_executor;
pub mod mock_xcm;
pub const FAILING_NONCE: u64 = 3;
@@ -0,0 +1,42 @@
// SPDX-License-Identifier: Apache-2.0
// SPDX-FileCopyrightText: 2023 Snowfork <hello@snowfork.com>
use codec::Encode;
use pezframe_support::pezsp_runtime::traits::MaybeConvert;
use pezsnowbridge_core::TokenIdOf;
use pezsp_core::H256;
use std::{cell::RefCell, collections::HashMap};
use xcm::{
latest::InteriorLocation,
prelude::{Location, Reanchorable},
};
use xcm_executor::traits::ConvertLocation;
thread_local! {
pub static IDENTIFIER_TO_LOCATION: RefCell<HashMap<H256, Location>> = RefCell::new(HashMap::new());
pub static LOCATION_TO_IDENTIFIER: RefCell<HashMap<Vec<u8>, H256>> = RefCell::new(HashMap::new());
}
pub fn add_location_override(location: Location, ethereum: Location, bh_context: InteriorLocation) {
let (token_id, reanchored_location) = reanchor_to_ethereum(location, ethereum, bh_context);
IDENTIFIER_TO_LOCATION.with(|b| b.borrow_mut().insert(token_id, reanchored_location.clone()));
LOCATION_TO_IDENTIFIER.with(|b| b.borrow_mut().insert(reanchored_location.encode(), token_id));
}
pub fn reanchor_to_ethereum(
location: Location,
ethereum: Location,
bh_context: InteriorLocation,
) -> (H256, Location) {
let mut reanchored_lol = location.clone();
let _ = reanchored_lol.reanchor(&ethereum, &bh_context);
let token_id = TokenIdOf::convert_location(&reanchored_lol).unwrap();
(token_id, reanchored_lol)
}
pub struct LocationIdConvert;
impl MaybeConvert<H256, Location> for LocationIdConvert {
fn maybe_convert(id: H256) -> Option<Location> {
IDENTIFIER_TO_LOCATION.with(|b| b.borrow().get(&id).and_then(|l| Option::from(l.clone())))
}
}
@@ -0,0 +1,17 @@
// SPDX-License-Identifier: Apache-2.0
// SPDX-FileCopyrightText: 2023 Snowfork <hello@snowfork.com>
use crate::FAILING_NONCE;
use pezsnowbridge_core::reward::{AddTip, AddTipError};
pub struct MockOkInboundQueue;
impl AddTip for MockOkInboundQueue {
fn add_tip(nonce: u64, _amount: u128) -> Result<(), AddTipError> {
// Force an error condition
if nonce == FAILING_NONCE {
return Err(AddTipError::NonceConsumed);
}
Ok(())
}
}
@@ -0,0 +1,66 @@
// SPDX-License-Identifier: Apache-2.0
// SPDX-FileCopyrightText: 2023 Snowfork <hello@snowfork.com>
// A stripped-down version of pezpallet-xcm that only inserts an XCM origin into the runtime
#[pezframe_support::pezpallet]
pub mod pezpallet_xcm_origin {
use codec::DecodeWithMemTracking;
use pezframe_support::{
pezpallet_prelude::*,
traits::{Contains, OriginTrait},
};
use xcm::latest::prelude::*;
#[pezpallet::pezpallet]
pub struct Pezpallet<T>(_);
#[pezpallet::config]
pub trait Config: pezframe_system::Config {
type RuntimeOrigin: From<Origin> + From<<Self as pezframe_system::Config>::RuntimeOrigin>;
}
// Insert this custom Origin into the aggregate RuntimeOrigin
#[pezpallet::origin]
#[derive(
PartialEq,
Eq,
Clone,
Encode,
Decode,
DecodeWithMemTracking,
RuntimeDebug,
TypeInfo,
MaxEncodedLen,
)]
pub struct Origin(pub Location);
impl From<Location> for Origin {
fn from(location: Location) -> Origin {
Origin(location)
}
}
/// `EnsureOrigin` implementation succeeding with a `Location` value to recognize and
/// filter the contained location
pub struct EnsureXcm<F>(PhantomData<F>);
impl<O: OriginTrait + From<Origin>, F: Contains<Location>> EnsureOrigin<O> for EnsureXcm<F>
where
O::PalletsOrigin: From<Origin> + TryInto<Origin, Error = O::PalletsOrigin>,
{
type Success = Location;
fn try_origin(outer: O) -> Result<Self::Success, O> {
outer.try_with_caller(|caller| {
caller.try_into().and_then(|o| match o {
Origin(location) if F::contains(&location) => Ok(location),
o => Err(o.into()),
})
})
}
#[cfg(feature = "runtime-benchmarks")]
fn try_successful_origin() -> Result<O, ()> {
Ok(O::from(Origin(Location::here().into())))
}
}
}
@@ -0,0 +1,73 @@
// SPDX-License-Identifier: Apache-2.0
// SPDX-FileCopyrightText: 2023 Snowfork <hello@snowfork.com>
use crate::FAILING_NONCE;
use pezsnowbridge_core::reward::{AddTip, AddTipError};
use pezsnowbridge_outbound_queue_primitives::{
v1::{Fee, Message as MessageV1, SendMessage as SendMessageV1},
v2::{Message, SendMessage},
SendMessageFeeProvider,
};
use pezsp_core::H256;
pub struct MockOkOutboundQueue;
impl SendMessage for MockOkOutboundQueue {
type Ticket = ();
fn validate(
_: &Message,
) -> Result<Self::Ticket, pezsnowbridge_outbound_queue_primitives::SendError> {
Ok(())
}
fn deliver(
_: Self::Ticket,
) -> Result<H256, pezsnowbridge_outbound_queue_primitives::SendError> {
Ok(H256::zero())
}
}
impl SendMessageFeeProvider for MockOkOutboundQueue {
type Balance = u128;
fn local_fee() -> Self::Balance {
0
}
}
impl AddTip for MockOkOutboundQueue {
fn add_tip(nonce: u64, _amount: u128) -> Result<(), AddTipError> {
if nonce == FAILING_NONCE {
return Err(AddTipError::NonceConsumed);
}
Ok(())
}
}
pub struct MockOkOutboundQueueV1;
impl SendMessageV1 for MockOkOutboundQueueV1 {
type Ticket = ();
fn validate(
_: &MessageV1,
) -> Result<
(Self::Ticket, Fee<<Self as SendMessageFeeProvider>::Balance>),
pezsnowbridge_outbound_queue_primitives::SendError,
> {
Ok(((), Fee::from((0, 0))))
}
fn deliver(
_: Self::Ticket,
) -> Result<H256, pezsnowbridge_outbound_queue_primitives::SendError> {
Ok(H256::zero())
}
}
impl SendMessageFeeProvider for MockOkOutboundQueueV1 {
type Balance = u128;
fn local_fee() -> Self::Balance {
0
}
}
@@ -0,0 +1,67 @@
// SPDX-License-Identifier: Apache-2.0
// SPDX-FileCopyrightText: 2023 Snowfork <hello@snowfork.com>
use bp_relayers::{PaymentProcedure, RewardLedger, RewardsAccountOwner, RewardsAccountParams};
use codec::{Decode, DecodeWithMemTracking, Encode, MaxEncodedLen};
use pezframe_support::{parameter_types, pezpallet_prelude::DispatchResult, pezsp_runtime};
use scale_info::TypeInfo;
use xcm::opaque::latest::Location;
/// Showcasing that we can handle multiple different rewards with the same pezpallet.
#[derive(
Clone,
Copy,
Debug,
Decode,
DecodeWithMemTracking,
Encode,
Eq,
MaxEncodedLen,
PartialEq,
TypeInfo,
)]
pub enum BridgeReward {
/// Rewards for Snowbridge.
Snowbridge,
}
pub struct MockPaymentProcedure;
// Provide a no-op or mock implementation for the required trait
impl PaymentProcedure<pezsp_runtime::AccountId32, RewardsAccountParams<u64>, u128>
for MockPaymentProcedure
{
type Error = DispatchResult;
type Beneficiary = Location;
fn pay_reward(
_who: &pezsp_runtime::AccountId32,
_reward_params: bp_relayers::RewardsAccountParams<u64>,
_reward_balance: u128,
_beneficiary: Self::Beneficiary,
) -> Result<(), Self::Error> {
Ok(())
}
}
impl From<BridgeReward> for RewardsAccountParams<u64> {
fn from(_bridge_reward: BridgeReward) -> Self {
RewardsAccountParams::new(1, [0; 4], RewardsAccountOwner::ThisChain)
}
}
parameter_types! {
pub static RegisteredRewardsCount: u128 = 0;
pub static RegisteredRewardAmount: u128 = 0;
}
pub struct MockRewardLedger;
impl RewardLedger<pezsp_runtime::AccountId32, BridgeReward, u128> for MockRewardLedger {
fn register_reward(
_relayer: &pezsp_runtime::AccountId32,
_reward: BridgeReward,
reward_balance: u128,
) {
RegisteredRewardsCount::set(RegisteredRewardsCount::get().saturating_add(1));
RegisteredRewardAmount::set(reward_balance);
}
}
@@ -0,0 +1,48 @@
// SPDX-License-Identifier: Apache-2.0
// SPDX-FileCopyrightText: 2023 Snowfork <hello@snowfork.com>
use pezframe_support::pezpallet_prelude::DispatchError;
use pezpallet_asset_conversion::Swap;
use xcm::opaque::latest::Location;
pub struct SwapExecutor;
pub const TRIGGER_SWAP_ERROR_AMOUNT: u128 = 12345;
impl<AccountId> Swap<AccountId> for SwapExecutor
where
AccountId: AsRef<[u8; 32]>,
{
type Balance = u128;
type AssetKind = Location;
fn max_path_len() -> u32 {
2
}
fn swap_exact_tokens_for_tokens(
_sender: AccountId,
_path: Vec<Self::AssetKind>,
amount_in: Self::Balance,
_amount_out_min: Option<Self::Balance>,
_send_to: AccountId,
_keep_alive: bool,
) -> Result<Self::Balance, DispatchError> {
// Special case for testing SwapError:
// If amount_in is exactly 12345, return an error
if amount_in == TRIGGER_SWAP_ERROR_AMOUNT {
return Err(DispatchError::Other("Swap failed for test"));
}
Ok(1_000_000_000u128)
}
fn swap_tokens_for_exact_tokens(
_sender: AccountId,
_path: Vec<Self::AssetKind>,
_amount_out: Self::Balance,
_amount_in_max: Option<Self::Balance>,
_send_to: AccountId,
_keep_alive: bool,
) -> Result<Self::Balance, DispatchError> {
unimplemented!()
}
}
@@ -0,0 +1,157 @@
// SPDX-License-Identifier: Apache-2.0
// SPDX-FileCopyrightText: 2023 Snowfork <hello@snowfork.com>
use codec::Encode;
use core::cell::RefCell;
use xcm::prelude::*;
use xcm_executor::{
traits::{FeeManager, FeeReason, TransactAsset},
AssetsInHolding,
};
thread_local! {
pub static IS_WAIVED: RefCell<Vec<FeeReason>> = RefCell::new(vec![]);
pub static SENDER_OVERRIDE: RefCell<Option<(
fn(
&mut Option<Location>,
&mut Option<Xcm<()>>,
) -> Result<(Xcm<()>, Assets), SendError>,
fn(
Xcm<()>,
) -> Result<XcmHash, SendError>,
)>> = RefCell::new(None);
pub static CHARGE_FEES_OVERRIDE: RefCell<Option<
fn(Location, Assets) -> xcm::latest::Result
>> = RefCell::new(None);
}
#[allow(dead_code)]
pub fn set_fee_waiver(waived: Vec<FeeReason>) {
IS_WAIVED.with(|l| l.replace(waived));
}
#[allow(dead_code)]
pub fn set_sender_override(
validate: fn(&mut Option<Location>, &mut Option<Xcm<()>>) -> SendResult<Xcm<()>>,
deliver: fn(Xcm<()>) -> Result<XcmHash, SendError>,
) {
SENDER_OVERRIDE.with(|x| x.replace(Some((validate, deliver))));
}
#[allow(dead_code)]
pub fn clear_sender_override() {
SENDER_OVERRIDE.with(|x| x.replace(None));
}
#[allow(dead_code)]
pub fn set_charge_fees_override(charge_fees: fn(Location, Assets) -> xcm::latest::Result) {
CHARGE_FEES_OVERRIDE.with(|x| x.replace(Some(charge_fees)));
}
#[allow(dead_code)]
pub fn clear_charge_fees_override() {
CHARGE_FEES_OVERRIDE.with(|x| x.replace(None));
}
/// Mock XCM sender with an overridable `validate` and `deliver` function.
pub struct MockXcmSender;
impl SendXcm for MockXcmSender {
type Ticket = Xcm<()>;
fn validate(
dest: &mut Option<Location>,
xcm: &mut Option<Xcm<()>>,
) -> SendResult<Self::Ticket> {
let r: SendResult<Self::Ticket> = SENDER_OVERRIDE.with(|s| {
if let Some((ref f, _)) = &*s.borrow() {
f(dest, xcm)
} else {
Ok((xcm.take().unwrap(), Assets::default()))
}
});
r
}
fn deliver(ticket: Self::Ticket) -> Result<XcmHash, SendError> {
let r: Result<XcmHash, SendError> = SENDER_OVERRIDE.with(|s| {
if let Some((_, ref f)) = &*s.borrow() {
f(ticket)
} else {
let hash = ticket.using_encoded(pezsp_core::hashing::blake2_256);
Ok(hash)
}
});
r
}
}
/// Mock XCM transactor that always succeeds
pub struct SuccessfulTransactor;
impl TransactAsset for SuccessfulTransactor {
fn can_check_in(_origin: &Location, _what: &Asset, _context: &XcmContext) -> XcmResult {
Ok(())
}
fn can_check_out(_dest: &Location, _what: &Asset, _context: &XcmContext) -> XcmResult {
Ok(())
}
fn deposit_asset(_what: &Asset, _who: &Location, _context: Option<&XcmContext>) -> XcmResult {
Ok(())
}
fn withdraw_asset(
_what: &Asset,
_who: &Location,
_context: Option<&XcmContext>,
) -> Result<AssetsInHolding, XcmError> {
Ok(AssetsInHolding::default())
}
fn internal_transfer_asset(
_what: &Asset,
_from: &Location,
_to: &Location,
_context: &XcmContext,
) -> Result<AssetsInHolding, XcmError> {
Ok(AssetsInHolding::default())
}
}
pub enum Weightless {}
impl PreparedMessage for Weightless {
fn weight_of(&self) -> Weight {
unreachable!();
}
}
/// Mock the XCM executor with an overridable `charge_fees` function.
pub struct MockXcmExecutor;
impl<C> ExecuteXcm<C> for MockXcmExecutor {
type Prepared = Weightless;
fn prepare(_: Xcm<C>, _: Weight) -> Result<Self::Prepared, InstructionError> {
unreachable!()
}
fn execute(_: impl Into<Location>, _: Self::Prepared, _: &mut XcmHash, _: Weight) -> Outcome {
unreachable!()
}
fn charge_fees(location: impl Into<Location>, assets: Assets) -> xcm::latest::Result {
let r: xcm::latest::Result = CHARGE_FEES_OVERRIDE.with(|s| {
if let Some(ref f) = &*s.borrow() {
f(location.into(), assets)
} else {
Ok(())
}
});
r
}
}
impl FeeManager for MockXcmExecutor {
fn is_waived(_: Option<&Location>, r: FeeReason) -> bool {
IS_WAIVED.with(|l| l.borrow().contains(&r))
}
fn handle_fee(_: Assets, _: Option<&XcmContext>, _: FeeReason) {}
}