fix: Complete snowbridge pezpallet rebrand and critical bug fixes
- snowbridge-pezpallet-* → pezsnowbridge-pezpallet-* (201 refs) - pallet/ directories → pezpallet/ (4 locations) - Fixed pezpallet.rs self-include recursion bug - Fixed sc-chain-spec hardcoded crate name in derive macro - Reverted .pezpallet_by_name() to .pallet_by_name() (subxt API) - Added BizinikiwiConfig type alias for zombienet tests - Deleted obsolete session state files Verified: pezsnowbridge-pezpallet-*, pezpallet-staking, pezpallet-staking-async, pezframe-benchmarking-cli all pass cargo check
This commit is contained in:
@@ -0,0 +1,72 @@
|
||||
[package]
|
||||
name = "pezpallet-xcm-bridge-hub-router"
|
||||
description = "Bridge hub interface for sibling/parent chains with dynamic fees support."
|
||||
version = "0.5.0"
|
||||
authors.workspace = true
|
||||
edition.workspace = true
|
||||
license = "GPL-3.0-or-later WITH Classpath-exception-2.0"
|
||||
repository.workspace = true
|
||||
documentation = "https://docs.rs/pezpallet-xcm-bridge-hub-router"
|
||||
homepage = { workspace = true }
|
||||
|
||||
[lints]
|
||||
workspace = true
|
||||
|
||||
[dependencies]
|
||||
codec = { workspace = true }
|
||||
scale-info = { features = ["bit-vec", "derive", "serde"], workspace = true }
|
||||
tracing = { workspace = true }
|
||||
|
||||
# Bridge dependencies
|
||||
bp-xcm-bridge-hub-router = { workspace = true }
|
||||
|
||||
# Bizinikiwi Dependencies
|
||||
pezframe-benchmarking = { optional = true, workspace = true }
|
||||
pezframe-support = { workspace = true }
|
||||
pezframe-system = { workspace = true }
|
||||
pezsp-core = { workspace = true }
|
||||
pezsp-runtime = { workspace = true }
|
||||
pezsp-std = { workspace = true }
|
||||
|
||||
# Pezkuwi Dependencies
|
||||
pezkuwi-runtime-teyrchains = { workspace = true }
|
||||
xcm = { workspace = true }
|
||||
xcm-builder = { workspace = true }
|
||||
|
||||
[dev-dependencies]
|
||||
pezsp-io = { workspace = true, default-features = true }
|
||||
|
||||
[features]
|
||||
default = ["std"]
|
||||
std = [
|
||||
"bp-xcm-bridge-hub-router/std",
|
||||
"codec/std",
|
||||
"pezframe-benchmarking/std",
|
||||
"pezframe-support/std",
|
||||
"pezframe-system/std",
|
||||
"pezkuwi-runtime-teyrchains/std",
|
||||
"scale-info/std",
|
||||
"pezsp-core/std",
|
||||
"pezsp-runtime/std",
|
||||
"pezsp-std/std",
|
||||
"tracing/std",
|
||||
"xcm-builder/std",
|
||||
"xcm/std",
|
||||
]
|
||||
runtime-benchmarks = [
|
||||
"bp-xcm-bridge-hub-router/runtime-benchmarks",
|
||||
"pezframe-benchmarking/runtime-benchmarks",
|
||||
"pezframe-support/runtime-benchmarks",
|
||||
"pezframe-system/runtime-benchmarks",
|
||||
"pezkuwi-runtime-teyrchains/runtime-benchmarks",
|
||||
"pezsp-io/runtime-benchmarks",
|
||||
"pezsp-runtime/runtime-benchmarks",
|
||||
"xcm-builder/runtime-benchmarks",
|
||||
"xcm/runtime-benchmarks",
|
||||
]
|
||||
try-runtime = [
|
||||
"pezframe-support/try-runtime",
|
||||
"pezframe-system/try-runtime",
|
||||
"pezkuwi-runtime-teyrchains/try-runtime",
|
||||
"pezsp-runtime/try-runtime",
|
||||
]
|
||||
@@ -0,0 +1,80 @@
|
||||
// Copyright (C) Parity Technologies (UK) Ltd.
|
||||
// This file is part of Parity Bridges Common.
|
||||
|
||||
// Parity Bridges Common is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
|
||||
// Parity Bridges Common is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Parity Bridges Common. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
//! XCM bridge hub router pezpallet benchmarks.
|
||||
|
||||
#![cfg(feature = "runtime-benchmarks")]
|
||||
|
||||
use crate::{Bridge, BridgeState, Call};
|
||||
use pezframe_benchmarking::{benchmarks_instance_pallet, BenchmarkError};
|
||||
use pezframe_support::traits::{EnsureOrigin, Get, Hooks, UnfilteredDispatchable};
|
||||
use pezkuwi_runtime_teyrchains::FeeTracker;
|
||||
use pezsp_runtime::{traits::Zero, Saturating};
|
||||
use xcm::prelude::*;
|
||||
|
||||
/// Pezpallet we're benchmarking here.
|
||||
pub struct Pezpallet<T: Config<I>, I: 'static = ()>(crate::Pezpallet<T, I>);
|
||||
|
||||
/// Trait that must be implemented by runtime to be able to benchmark pezpallet properly.
|
||||
pub trait Config<I: 'static>: crate::Config<I> {
|
||||
/// Fill up queue so it becomes congested.
|
||||
fn make_congested();
|
||||
|
||||
/// Returns destination which is valid for this router instance.
|
||||
/// (Needs to pass `T::Bridges`)
|
||||
/// Make sure that `SendXcm` will pass.
|
||||
fn ensure_bridged_target_destination() -> Result<Location, BenchmarkError> {
|
||||
Ok(Location::new(
|
||||
Self::UniversalLocation::get().len() as u8,
|
||||
[GlobalConsensus(Self::BridgedNetworkId::get().unwrap())],
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
benchmarks_instance_pallet! {
|
||||
on_initialize_when_non_congested {
|
||||
Bridge::<T, I>::put(BridgeState {
|
||||
is_congested: false,
|
||||
delivery_fee_factor: crate::Pezpallet::<T, I>::MIN_FEE_FACTOR.saturating_mul(2.into()),
|
||||
});
|
||||
}: {
|
||||
crate::Pezpallet::<T, I>::on_initialize(Zero::zero())
|
||||
}
|
||||
|
||||
on_initialize_when_congested {
|
||||
Bridge::<T, I>::put(BridgeState {
|
||||
is_congested: false,
|
||||
delivery_fee_factor: crate::Pezpallet::<T, I>::MIN_FEE_FACTOR.saturating_mul(2.into()),
|
||||
});
|
||||
let _ = T::ensure_bridged_target_destination()?;
|
||||
T::make_congested();
|
||||
}: {
|
||||
crate::Pezpallet::<T, I>::on_initialize(Zero::zero())
|
||||
}
|
||||
|
||||
report_bridge_status {
|
||||
Bridge::<T, I>::put(BridgeState::default());
|
||||
|
||||
let origin: T::RuntimeOrigin = T::BridgeHubOrigin::try_successful_origin().expect("expected valid BridgeHubOrigin");
|
||||
let bridge_id = Default::default();
|
||||
let is_congested = true;
|
||||
|
||||
let call = Call::<T, I>::report_bridge_status { bridge_id, is_congested };
|
||||
}: { call.dispatch_bypass_filter(origin)? }
|
||||
verify {
|
||||
assert!(Bridge::<T, I>::get().is_congested);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,747 @@
|
||||
// Copyright (C) Parity Technologies (UK) Ltd.
|
||||
// This file is part of Parity Bridges Common.
|
||||
|
||||
// Parity Bridges Common is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
|
||||
// Parity Bridges Common is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Parity Bridges Common. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
//! Pezpallet that may be used instead of `SovereignPaidRemoteExporter` in the XCM router
|
||||
//! configuration. The main thing that the pezpallet offers is the dynamic message fee,
|
||||
//! that is computed based on the bridge queues state. It starts exponentially increasing
|
||||
//! if the queue between this chain and the sibling/child bridge hub is congested.
|
||||
//!
|
||||
//! All other bridge hub queues offer some backpressure mechanisms. So if at least one
|
||||
//! of all queues is congested, it will eventually lead to the growth of the queue at
|
||||
//! this chain.
|
||||
//!
|
||||
//! **A note on terminology**: when we mention the bridge hub here, we mean the chain that
|
||||
//! has the messages pezpallet deployed (`pezpallet-bridge-grandpa`, `pezpallet-bridge-messages`,
|
||||
//! `pezpallet-xcm-bridge-hub`, ...). It may be the system bridge hub teyrchain or any other
|
||||
//! chain.
|
||||
|
||||
#![cfg_attr(not(feature = "std"), no_std)]
|
||||
|
||||
use bp_xcm_bridge_hub_router::MINIMAL_DELIVERY_FEE_FACTOR;
|
||||
pub use bp_xcm_bridge_hub_router::{BridgeState, XcmChannelStatusProvider};
|
||||
use codec::Encode;
|
||||
use pezframe_support::traits::Get;
|
||||
use pezkuwi_runtime_teyrchains::FeeTracker;
|
||||
use pezsp_core::H256;
|
||||
use pezsp_runtime::{FixedPointNumber, FixedU128};
|
||||
use pezsp_std::vec::Vec;
|
||||
use xcm::prelude::*;
|
||||
use xcm_builder::{ExporterFor, InspectMessageQueues, SovereignPaidRemoteExporter};
|
||||
|
||||
pub use pezpallet::*;
|
||||
pub use weights::WeightInfo;
|
||||
|
||||
pub mod benchmarking;
|
||||
pub mod weights;
|
||||
|
||||
mod mock;
|
||||
|
||||
/// Maximal size of the XCM message that may be sent over bridge.
|
||||
///
|
||||
/// This should be less than the maximal size, allowed by the messages pezpallet, because
|
||||
/// the message itself is wrapped in other structs and is double encoded.
|
||||
pub const HARD_MESSAGE_SIZE_LIMIT: u32 = 32 * 1024;
|
||||
|
||||
/// The target that will be used when publishing logs related to this pezpallet.
|
||||
///
|
||||
/// This doesn't match the pattern used by other bridge pallets (`runtime::bridge-*`). But this
|
||||
/// pezpallet has significant differences with those pallets. The main one is that is intended to
|
||||
/// be deployed at sending chains. Other bridge pallets are likely to be deployed at the separate
|
||||
/// bridge hub teyrchain.
|
||||
pub const LOG_TARGET: &str = "xcm::bridge-hub-router";
|
||||
|
||||
#[pezframe_support::pezpallet]
|
||||
pub mod pezpallet {
|
||||
use super::*;
|
||||
use pezframe_support::pezpallet_prelude::*;
|
||||
use pezframe_system::pezpallet_prelude::*;
|
||||
|
||||
#[pezpallet::config]
|
||||
pub trait Config<I: 'static = ()>: pezframe_system::Config {
|
||||
/// The overarching event type.
|
||||
#[allow(deprecated)]
|
||||
type RuntimeEvent: From<Event<Self, I>>
|
||||
+ IsType<<Self as pezframe_system::Config>::RuntimeEvent>;
|
||||
/// Benchmarks results from runtime we're plugged into.
|
||||
type WeightInfo: WeightInfo;
|
||||
|
||||
/// Universal location of this runtime.
|
||||
type UniversalLocation: Get<InteriorLocation>;
|
||||
/// Relative location of the supported sibling bridge hub.
|
||||
type SiblingBridgeHubLocation: Get<Location>;
|
||||
/// The bridged network that this config is for if specified.
|
||||
/// Also used for filtering `Bridges` by `BridgedNetworkId`.
|
||||
/// If not specified, allows all networks pass through.
|
||||
type BridgedNetworkId: Get<Option<NetworkId>>;
|
||||
/// Configuration for supported **bridged networks/locations** with **bridge location** and
|
||||
/// **possible fee**. Allows to externalize better control over allowed **bridged
|
||||
/// networks/locations**.
|
||||
type Bridges: ExporterFor;
|
||||
/// Checks the XCM version for the destination.
|
||||
type DestinationVersion: GetVersion;
|
||||
|
||||
/// Origin of the sibling bridge hub that is allowed to report bridge status.
|
||||
type BridgeHubOrigin: EnsureOrigin<Self::RuntimeOrigin>;
|
||||
/// Actual message sender (`HRMP` or `DMP`) to the sibling bridge hub location.
|
||||
type ToBridgeHubSender: SendXcm;
|
||||
/// Local XCM channel manager.
|
||||
type LocalXcmChannelManager: XcmChannelStatusProvider;
|
||||
|
||||
/// Additional fee that is paid for every byte of the outbound message.
|
||||
type ByteFee: Get<u128>;
|
||||
/// Asset that is used to paid bridge fee.
|
||||
type FeeAsset: Get<AssetId>;
|
||||
}
|
||||
|
||||
#[pezpallet::pezpallet]
|
||||
pub struct Pezpallet<T, I = ()>(PhantomData<(T, I)>);
|
||||
|
||||
#[pezpallet::hooks]
|
||||
impl<T: Config<I>, I: 'static> Hooks<BlockNumberFor<T>> for Pezpallet<T, I> {
|
||||
fn on_initialize(_n: BlockNumberFor<T>) -> Weight {
|
||||
// if XCM channel is still congested, we don't change anything
|
||||
if T::LocalXcmChannelManager::is_congested(&T::SiblingBridgeHubLocation::get()) {
|
||||
return T::WeightInfo::on_initialize_when_congested();
|
||||
}
|
||||
|
||||
// if bridge has reported congestion, we don't change anything
|
||||
let mut bridge = Self::bridge();
|
||||
if bridge.is_congested {
|
||||
return T::WeightInfo::on_initialize_when_congested();
|
||||
}
|
||||
|
||||
let previous_factor = Self::get_fee_factor(());
|
||||
// if we can't decrease the delivery fee factor anymore, we don't change anything
|
||||
if !Self::do_decrease_fee_factor(&mut bridge.delivery_fee_factor) {
|
||||
return T::WeightInfo::on_initialize_when_congested();
|
||||
}
|
||||
|
||||
tracing::info!(
|
||||
target: LOG_TARGET,
|
||||
from=%previous_factor,
|
||||
to=%bridge.delivery_fee_factor,
|
||||
"Bridge channel is uncongested. Decreased fee factor"
|
||||
);
|
||||
Self::deposit_event(Event::DeliveryFeeFactorDecreased {
|
||||
new_value: bridge.delivery_fee_factor,
|
||||
});
|
||||
|
||||
Bridge::<T, I>::put(bridge);
|
||||
|
||||
T::WeightInfo::on_initialize_when_non_congested()
|
||||
}
|
||||
}
|
||||
|
||||
#[pezpallet::call]
|
||||
impl<T: Config<I>, I: 'static> Pezpallet<T, I> {
|
||||
/// Notification about congested bridge queue.
|
||||
#[pezpallet::call_index(0)]
|
||||
#[pezpallet::weight(T::WeightInfo::report_bridge_status())]
|
||||
pub fn report_bridge_status(
|
||||
origin: OriginFor<T>,
|
||||
// this argument is not currently used, but to ease future migration, we'll keep it
|
||||
// here
|
||||
bridge_id: H256,
|
||||
is_congested: bool,
|
||||
) -> DispatchResult {
|
||||
T::BridgeHubOrigin::ensure_origin(origin)?;
|
||||
|
||||
tracing::info!(
|
||||
target: LOG_TARGET,
|
||||
from=?bridge_id,
|
||||
congested=%is_congested,
|
||||
"Received bridge status"
|
||||
);
|
||||
|
||||
Bridge::<T, I>::mutate(|bridge| {
|
||||
bridge.is_congested = is_congested;
|
||||
});
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
/// Bridge that we are using.
|
||||
///
|
||||
/// **bridges-v1** assumptions: all outbound messages through this router are using single lane
|
||||
/// and to single remote consensus. If there is some other remote consensus that uses the same
|
||||
/// bridge hub, the separate pezpallet instance shall be used, In `v2` we'll have all required
|
||||
/// primitives (lane-id aka bridge-id, derived from XCM locations) to support multiple bridges
|
||||
/// by the same pezpallet instance.
|
||||
#[pezpallet::storage]
|
||||
pub type Bridge<T: Config<I>, I: 'static = ()> = StorageValue<_, BridgeState, ValueQuery>;
|
||||
|
||||
impl<T: Config<I>, I: 'static> Pezpallet<T, I> {
|
||||
/// Bridge that we are using.
|
||||
pub fn bridge() -> BridgeState {
|
||||
Bridge::<T, I>::get()
|
||||
}
|
||||
|
||||
/// Called when new message is sent (queued to local outbound XCM queue) over the bridge.
|
||||
pub(crate) fn on_message_sent_to_bridge(message_size: u32) {
|
||||
tracing::trace!(
|
||||
target: LOG_TARGET,
|
||||
?message_size, "on_message_sent_to_bridge"
|
||||
);
|
||||
let _ = Bridge::<T, I>::try_mutate(|bridge| {
|
||||
let is_channel_with_bridge_hub_congested =
|
||||
T::LocalXcmChannelManager::is_congested(&T::SiblingBridgeHubLocation::get());
|
||||
let is_bridge_congested = bridge.is_congested;
|
||||
|
||||
// if outbound queue is not congested AND bridge has not reported congestion, do
|
||||
// nothing
|
||||
if !is_channel_with_bridge_hub_congested && !is_bridge_congested {
|
||||
return Err(());
|
||||
}
|
||||
|
||||
let previous_factor = Self::get_fee_factor(());
|
||||
// ok - we need to increase the fee factor, let's do that
|
||||
<Self as FeeTracker>::do_increase_fee_factor(
|
||||
&mut bridge.delivery_fee_factor,
|
||||
message_size as u128,
|
||||
);
|
||||
|
||||
tracing::info!(
|
||||
target: LOG_TARGET,
|
||||
from=%previous_factor,
|
||||
to=%bridge.delivery_fee_factor,
|
||||
"Bridge channel is congested. Increased fee factor"
|
||||
);
|
||||
Self::deposit_event(Event::DeliveryFeeFactorIncreased {
|
||||
new_value: bridge.delivery_fee_factor,
|
||||
});
|
||||
Ok(())
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
#[pezpallet::event]
|
||||
#[pezpallet::generate_deposit(pub(super) fn deposit_event)]
|
||||
pub enum Event<T: Config<I>, I: 'static = ()> {
|
||||
/// Delivery fee factor has been decreased.
|
||||
DeliveryFeeFactorDecreased {
|
||||
/// New value of the `DeliveryFeeFactor`.
|
||||
new_value: FixedU128,
|
||||
},
|
||||
/// Delivery fee factor has been increased.
|
||||
DeliveryFeeFactorIncreased {
|
||||
/// New value of the `DeliveryFeeFactor`.
|
||||
new_value: FixedU128,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
/// We'll be using `SovereignPaidRemoteExporter` to send remote messages over the sibling/child
|
||||
/// bridge hub.
|
||||
type ViaBridgeHubExporter<T, I> = SovereignPaidRemoteExporter<
|
||||
Pezpallet<T, I>,
|
||||
<T as Config<I>>::ToBridgeHubSender,
|
||||
<T as Config<I>>::UniversalLocation,
|
||||
>;
|
||||
|
||||
// This pezpallet acts as the `ExporterFor` for the `SovereignPaidRemoteExporter` to compute
|
||||
// message fee using fee factor.
|
||||
impl<T: Config<I>, I: 'static> ExporterFor for Pezpallet<T, I> {
|
||||
fn exporter_for(
|
||||
network: &NetworkId,
|
||||
remote_location: &InteriorLocation,
|
||||
message: &Xcm<()>,
|
||||
) -> Option<(Location, Option<Asset>)> {
|
||||
tracing::trace!(
|
||||
target: LOG_TARGET,
|
||||
?network, ?remote_location, msg=?message, "exporter_for"
|
||||
);
|
||||
// ensure that the message is sent to the expected bridged network (if specified).
|
||||
if let Some(bridged_network) = T::BridgedNetworkId::get() {
|
||||
if *network != bridged_network {
|
||||
tracing::trace!(
|
||||
target: LOG_TARGET,
|
||||
bridged_network_id=?bridged_network, ?network, "Router does not support bridging!"
|
||||
);
|
||||
return None;
|
||||
}
|
||||
}
|
||||
|
||||
// ensure that the message is sent to the expected bridged network and location.
|
||||
let (bridge_hub_location, maybe_payment) =
|
||||
match T::Bridges::exporter_for(network, remote_location, message) {
|
||||
Some((bridge_hub_location, maybe_payment))
|
||||
if bridge_hub_location.eq(&T::SiblingBridgeHubLocation::get()) =>
|
||||
(bridge_hub_location, maybe_payment),
|
||||
_ => {
|
||||
tracing::trace!(
|
||||
target: LOG_TARGET,
|
||||
bridged_network_id=?T::BridgedNetworkId::get(),
|
||||
sibling_bridge_hub_location=?T::SiblingBridgeHubLocation::get(),
|
||||
?network,
|
||||
?remote_location,
|
||||
"Router configured does not support bridging!"
|
||||
);
|
||||
return None;
|
||||
},
|
||||
};
|
||||
|
||||
// take `base_fee` from `T::Brides`, but it has to be the same `T::FeeAsset`
|
||||
let base_fee = match maybe_payment {
|
||||
Some(payment) => match payment {
|
||||
Asset { fun: Fungible(amount), id } if id.eq(&T::FeeAsset::get()) => amount,
|
||||
invalid_asset => {
|
||||
tracing::error!(
|
||||
target: LOG_TARGET,
|
||||
bridged_network_id=?T::BridgedNetworkId::get(),
|
||||
fee_asset=?T::FeeAsset::get(),
|
||||
with=?invalid_asset,
|
||||
?bridge_hub_location,
|
||||
?network,
|
||||
?remote_location,
|
||||
"Router is configured for `T::FeeAsset` which is not compatible for bridging!"
|
||||
);
|
||||
return None;
|
||||
},
|
||||
},
|
||||
None => 0,
|
||||
};
|
||||
|
||||
// compute fee amount. Keep in mind that this is only the bridge fee. The fee for sending
|
||||
// message from this chain to child/sibling bridge hub is determined by the
|
||||
// `Config::ToBridgeHubSender`
|
||||
let message_size = message.encoded_size();
|
||||
let message_fee = (message_size as u128).saturating_mul(T::ByteFee::get());
|
||||
let fee_sum = base_fee.saturating_add(message_fee);
|
||||
let fee_factor = Self::get_fee_factor(());
|
||||
let fee = fee_factor.saturating_mul_int(fee_sum);
|
||||
|
||||
let fee = if fee > 0 { Some((T::FeeAsset::get(), fee).into()) } else { None };
|
||||
|
||||
tracing::info!(
|
||||
target: LOG_TARGET,
|
||||
to=?(network, remote_location),
|
||||
bridge_fee=?fee,
|
||||
%fee_factor,
|
||||
"Going to send message ({message_size} bytes) over bridge."
|
||||
);
|
||||
|
||||
Some((bridge_hub_location, fee))
|
||||
}
|
||||
}
|
||||
|
||||
// This pezpallet acts as the `SendXcm` to the sibling/child bridge hub instead of regular
|
||||
// XCMP/DMP transport. This allows injecting dynamic message fees into XCM programs that
|
||||
// are going to the bridged network.
|
||||
impl<T: Config<I>, I: 'static> SendXcm for Pezpallet<T, I> {
|
||||
type Ticket = (u32, <T::ToBridgeHubSender as SendXcm>::Ticket);
|
||||
|
||||
fn validate(
|
||||
dest: &mut Option<Location>,
|
||||
xcm: &mut Option<Xcm<()>>,
|
||||
) -> SendResult<Self::Ticket> {
|
||||
tracing::trace!(target: LOG_TARGET, msg=?xcm, destination=?dest, "validate");
|
||||
|
||||
// In case of success, the `ViaBridgeHubExporter` can modify XCM instructions and consume
|
||||
// `dest` / `xcm`, so we retain the clone of original message and the destination for later
|
||||
// `DestinationVersion` validation.
|
||||
let xcm_to_dest_clone = xcm.clone();
|
||||
let dest_clone = dest.clone();
|
||||
|
||||
// First, use the inner exporter to validate the destination to determine if it is even
|
||||
// routable. If it is not, return an error. If it is, then the XCM is extended with
|
||||
// instructions to pay the message fee at the sibling/child bridge hub. The cost will
|
||||
// include both the cost of (1) delivery to the sibling bridge hub (returned by
|
||||
// `Config::ToBridgeHubSender`) and (2) delivery to the bridged bridge hub (returned by
|
||||
// `Self::exporter_for`).
|
||||
match ViaBridgeHubExporter::<T, I>::validate(dest, xcm) {
|
||||
Ok((ticket, cost)) => {
|
||||
// If the ticket is ok, it means we are routing with this router, so we need to
|
||||
// apply more validations to the cloned `dest` and `xcm`, which are required here.
|
||||
let xcm_to_dest_clone = xcm_to_dest_clone.ok_or(SendError::MissingArgument)?;
|
||||
let dest_clone = dest_clone.ok_or(SendError::MissingArgument)?;
|
||||
|
||||
// We won't have access to `dest` and `xcm` in the `deliver` method, so we need to
|
||||
// precompute everything required here. However, `dest` and `xcm` were consumed by
|
||||
// `ViaBridgeHubExporter`, so we need to use their clones.
|
||||
let message_size = xcm_to_dest_clone.encoded_size() as _;
|
||||
|
||||
// The bridge doesn't support oversized or overweight messages. Therefore, it's
|
||||
// better to drop such messages here rather than at the bridge hub. Let's check the
|
||||
// message size."
|
||||
if message_size > HARD_MESSAGE_SIZE_LIMIT {
|
||||
return Err(SendError::ExceedsMaxMessageSize);
|
||||
}
|
||||
|
||||
// We need to ensure that the known `dest`'s XCM version can comprehend the current
|
||||
// `xcm` program. This may seem like an additional, unnecessary check, but it is
|
||||
// not. A similar check is probably performed by the `ViaBridgeHubExporter`, which
|
||||
// attempts to send a versioned message to the sibling bridge hub. However, the
|
||||
// local bridge hub may have a higher XCM version than the remote `dest`. Once
|
||||
// again, it is better to discard such messages here than at the bridge hub (e.g.,
|
||||
// to avoid losing funds).
|
||||
let destination_version = T::DestinationVersion::get_version_for(&dest_clone)
|
||||
.ok_or(SendError::DestinationUnsupported)?;
|
||||
VersionedXcm::from(xcm_to_dest_clone)
|
||||
.into_version(destination_version)
|
||||
.map_err(|()| SendError::DestinationUnsupported)?;
|
||||
|
||||
Ok(((message_size, ticket), cost))
|
||||
},
|
||||
Err(e) => {
|
||||
tracing::trace!(target: LOG_TARGET, error=?e, "validate - ViaBridgeHubExporter");
|
||||
Err(e)
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
fn deliver(ticket: Self::Ticket) -> Result<XcmHash, SendError> {
|
||||
// use router to enqueue message to the sibling/child bridge hub. This also should handle
|
||||
// payment for passing through this queue.
|
||||
let (message_size, ticket) = ticket;
|
||||
let xcm_hash = ViaBridgeHubExporter::<T, I>::deliver(ticket)?;
|
||||
|
||||
// increase delivery fee factor if required
|
||||
Self::on_message_sent_to_bridge(message_size);
|
||||
|
||||
tracing::trace!(target: LOG_TARGET, ?xcm_hash, "deliver - message sent");
|
||||
Ok(xcm_hash)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Config<I>, I: 'static> InspectMessageQueues for Pezpallet<T, I> {
|
||||
fn clear_messages() {}
|
||||
|
||||
/// This router needs to implement `InspectMessageQueues` but doesn't have to
|
||||
/// return any messages, since it just reuses the `XcmpQueue` router.
|
||||
fn get_messages() -> Vec<(VersionedLocation, Vec<VersionedXcm<()>>)> {
|
||||
Vec::new()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Config<I>, I: 'static> FeeTracker for Pezpallet<T, I> {
|
||||
type Id = ();
|
||||
|
||||
const MIN_FEE_FACTOR: FixedU128 = MINIMAL_DELIVERY_FEE_FACTOR;
|
||||
|
||||
fn get_fee_factor(_id: Self::Id) -> FixedU128 {
|
||||
Self::bridge().delivery_fee_factor
|
||||
}
|
||||
|
||||
fn set_fee_factor(_id: Self::Id, val: FixedU128) {
|
||||
let mut bridge = Self::bridge();
|
||||
bridge.delivery_fee_factor = val;
|
||||
Bridge::<T, I>::put(bridge);
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use pezframe_support::assert_ok;
|
||||
use mock::*;
|
||||
|
||||
use pezframe_support::traits::Hooks;
|
||||
use pezframe_system::{EventRecord, Phase};
|
||||
use pezsp_runtime::traits::One;
|
||||
|
||||
fn congested_bridge(delivery_fee_factor: FixedU128) -> BridgeState {
|
||||
BridgeState { is_congested: true, delivery_fee_factor }
|
||||
}
|
||||
|
||||
fn uncongested_bridge(delivery_fee_factor: FixedU128) -> BridgeState {
|
||||
BridgeState { is_congested: false, delivery_fee_factor }
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn initial_fee_factor_is_one() {
|
||||
run_test(|| {
|
||||
assert_eq!(
|
||||
Bridge::<TestRuntime, ()>::get(),
|
||||
uncongested_bridge(Pezpallet::<TestRuntime, ()>::MIN_FEE_FACTOR),
|
||||
);
|
||||
})
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn fee_factor_is_not_decreased_from_on_initialize_when_xcm_channel_is_congested() {
|
||||
run_test(|| {
|
||||
Bridge::<TestRuntime, ()>::put(uncongested_bridge(FixedU128::from_rational(125, 100)));
|
||||
TestLocalXcmChannelManager::make_congested(&SiblingBridgeHubLocation::get());
|
||||
|
||||
// it should not decrease, because queue is congested
|
||||
let old_delivery = XcmBridgeHubRouter::bridge();
|
||||
XcmBridgeHubRouter::on_initialize(One::one());
|
||||
assert_eq!(XcmBridgeHubRouter::bridge(), old_delivery);
|
||||
assert_eq!(System::events(), vec![]);
|
||||
})
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn fee_factor_is_not_decreased_from_on_initialize_when_bridge_has_reported_congestion() {
|
||||
run_test(|| {
|
||||
Bridge::<TestRuntime, ()>::put(congested_bridge(FixedU128::from_rational(125, 100)));
|
||||
|
||||
// it should not decrease, because bridge congested
|
||||
let old_bridge = XcmBridgeHubRouter::bridge();
|
||||
XcmBridgeHubRouter::on_initialize(One::one());
|
||||
assert_eq!(XcmBridgeHubRouter::bridge(), old_bridge);
|
||||
assert_eq!(System::events(), vec![]);
|
||||
})
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn fee_factor_is_decreased_from_on_initialize_when_xcm_channel_is_uncongested() {
|
||||
run_test(|| {
|
||||
let initial_fee_factor = FixedU128::from_rational(125, 100);
|
||||
Bridge::<TestRuntime, ()>::put(uncongested_bridge(initial_fee_factor));
|
||||
|
||||
// it should eventually decrease to one
|
||||
while XcmBridgeHubRouter::bridge().delivery_fee_factor >
|
||||
Pezpallet::<TestRuntime, ()>::MIN_FEE_FACTOR
|
||||
{
|
||||
XcmBridgeHubRouter::on_initialize(One::one());
|
||||
}
|
||||
|
||||
// verify that it doesn't decrease anymore
|
||||
XcmBridgeHubRouter::on_initialize(One::one());
|
||||
assert_eq!(
|
||||
XcmBridgeHubRouter::bridge(),
|
||||
uncongested_bridge(Pezpallet::<TestRuntime, ()>::MIN_FEE_FACTOR)
|
||||
);
|
||||
|
||||
// check emitted event
|
||||
let first_system_event = System::events().first().cloned();
|
||||
assert_eq!(
|
||||
first_system_event,
|
||||
Some(EventRecord {
|
||||
phase: Phase::Initialization,
|
||||
event: RuntimeEvent::XcmBridgeHubRouter(Event::DeliveryFeeFactorDecreased {
|
||||
new_value: initial_fee_factor / XcmBridgeHubRouter::EXPONENTIAL_FEE_BASE,
|
||||
}),
|
||||
topics: vec![],
|
||||
})
|
||||
);
|
||||
})
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn not_applicable_if_destination_is_within_other_network() {
|
||||
run_test(|| {
|
||||
// unroutable dest
|
||||
let dest = Location::new(2, [GlobalConsensus(ByGenesis([0; 32])), Teyrchain(1000)]);
|
||||
let xcm: Xcm<()> = vec![ClearOrigin].into();
|
||||
|
||||
// check that router does not consume when `NotApplicable`
|
||||
let mut xcm_wrapper = Some(xcm.clone());
|
||||
assert_eq!(
|
||||
XcmBridgeHubRouter::validate(&mut Some(dest.clone()), &mut xcm_wrapper),
|
||||
Err(SendError::NotApplicable),
|
||||
);
|
||||
// XCM is NOT consumed and untouched
|
||||
assert_eq!(Some(xcm.clone()), xcm_wrapper);
|
||||
|
||||
// check the full `send_xcm`
|
||||
assert_eq!(send_xcm::<XcmBridgeHubRouter>(dest, xcm,), Err(SendError::NotApplicable),);
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn exceeds_max_message_size_if_size_is_above_hard_limit() {
|
||||
run_test(|| {
|
||||
// routable dest with XCM version
|
||||
let dest =
|
||||
Location::new(2, [GlobalConsensus(BridgedNetworkId::get()), Teyrchain(1000)]);
|
||||
// oversized XCM
|
||||
let xcm: Xcm<()> = vec![ClearOrigin; HARD_MESSAGE_SIZE_LIMIT as usize].into();
|
||||
|
||||
// dest is routable with the inner router
|
||||
assert_ok!(ViaBridgeHubExporter::<TestRuntime, ()>::validate(
|
||||
&mut Some(dest.clone()),
|
||||
&mut Some(xcm.clone())
|
||||
));
|
||||
|
||||
// check for oversized message
|
||||
let mut xcm_wrapper = Some(xcm.clone());
|
||||
assert_eq!(
|
||||
XcmBridgeHubRouter::validate(&mut Some(dest.clone()), &mut xcm_wrapper),
|
||||
Err(SendError::ExceedsMaxMessageSize),
|
||||
);
|
||||
// XCM is consumed by the inner router
|
||||
assert!(xcm_wrapper.is_none());
|
||||
|
||||
// check the full `send_xcm`
|
||||
assert_eq!(
|
||||
send_xcm::<XcmBridgeHubRouter>(dest, xcm,),
|
||||
Err(SendError::ExceedsMaxMessageSize),
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn destination_unsupported_if_wrap_version_fails() {
|
||||
run_test(|| {
|
||||
// routable dest but we don't know XCM version
|
||||
let dest = UnknownXcmVersionForRoutableLocation::get();
|
||||
let xcm: Xcm<()> = vec![ClearOrigin].into();
|
||||
|
||||
// dest is routable with the inner router
|
||||
assert_ok!(ViaBridgeHubExporter::<TestRuntime, ()>::validate(
|
||||
&mut Some(dest.clone()),
|
||||
&mut Some(xcm.clone())
|
||||
));
|
||||
|
||||
// check that it does not pass XCM version check
|
||||
let mut xcm_wrapper = Some(xcm.clone());
|
||||
assert_eq!(
|
||||
XcmBridgeHubRouter::validate(&mut Some(dest.clone()), &mut xcm_wrapper),
|
||||
Err(SendError::DestinationUnsupported),
|
||||
);
|
||||
// XCM is consumed by the inner router
|
||||
assert!(xcm_wrapper.is_none());
|
||||
|
||||
// check the full `send_xcm`
|
||||
assert_eq!(
|
||||
send_xcm::<XcmBridgeHubRouter>(dest, xcm,),
|
||||
Err(SendError::DestinationUnsupported),
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn returns_proper_delivery_price() {
|
||||
run_test(|| {
|
||||
let dest = Location::new(2, [GlobalConsensus(BridgedNetworkId::get())]);
|
||||
let xcm: Xcm<()> = vec![ClearOrigin].into();
|
||||
let msg_size = xcm.encoded_size();
|
||||
|
||||
// initially the base fee is used: `BASE_FEE + BYTE_FEE * msg_size + HRMP_FEE`
|
||||
let expected_fee = BASE_FEE + BYTE_FEE * (msg_size as u128) + HRMP_FEE;
|
||||
assert_eq!(
|
||||
XcmBridgeHubRouter::validate(&mut Some(dest.clone()), &mut Some(xcm.clone()))
|
||||
.unwrap()
|
||||
.1
|
||||
.get(0),
|
||||
Some(&(BridgeFeeAsset::get(), expected_fee).into()),
|
||||
);
|
||||
|
||||
// but when factor is larger than one, it increases the fee, so it becomes:
|
||||
// `(BASE_FEE + BYTE_FEE * msg_size) * F + HRMP_FEE`
|
||||
let factor = FixedU128::from_rational(125, 100);
|
||||
Bridge::<TestRuntime, ()>::put(uncongested_bridge(factor));
|
||||
let expected_fee =
|
||||
(FixedU128::saturating_from_integer(BASE_FEE + BYTE_FEE * (msg_size as u128)) *
|
||||
factor)
|
||||
.into_inner() / FixedU128::DIV +
|
||||
HRMP_FEE;
|
||||
assert_eq!(
|
||||
XcmBridgeHubRouter::validate(&mut Some(dest), &mut Some(xcm)).unwrap().1.get(0),
|
||||
Some(&(BridgeFeeAsset::get(), expected_fee).into()),
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn sent_message_doesnt_increase_factor_if_queue_is_uncongested() {
|
||||
run_test(|| {
|
||||
let old_bridge = XcmBridgeHubRouter::bridge();
|
||||
assert_eq!(
|
||||
send_xcm::<XcmBridgeHubRouter>(
|
||||
Location::new(2, [GlobalConsensus(BridgedNetworkId::get()), Teyrchain(1000)]),
|
||||
vec![ClearOrigin].into(),
|
||||
)
|
||||
.map(drop),
|
||||
Ok(()),
|
||||
);
|
||||
|
||||
assert!(TestToBridgeHubSender::is_message_sent());
|
||||
assert_eq!(old_bridge, XcmBridgeHubRouter::bridge());
|
||||
|
||||
assert_eq!(System::events(), vec![]);
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn sent_message_increases_factor_if_xcm_channel_is_congested() {
|
||||
run_test(|| {
|
||||
TestLocalXcmChannelManager::make_congested(&SiblingBridgeHubLocation::get());
|
||||
|
||||
let old_bridge = XcmBridgeHubRouter::bridge();
|
||||
assert_ok!(send_xcm::<XcmBridgeHubRouter>(
|
||||
Location::new(2, [GlobalConsensus(BridgedNetworkId::get()), Teyrchain(1000)]),
|
||||
vec![ClearOrigin].into(),
|
||||
)
|
||||
.map(drop));
|
||||
|
||||
assert!(TestToBridgeHubSender::is_message_sent());
|
||||
assert!(
|
||||
old_bridge.delivery_fee_factor < XcmBridgeHubRouter::bridge().delivery_fee_factor
|
||||
);
|
||||
|
||||
// check emitted event
|
||||
let first_system_event = System::events().first().cloned();
|
||||
assert!(matches!(
|
||||
first_system_event,
|
||||
Some(EventRecord {
|
||||
phase: Phase::Initialization,
|
||||
event: RuntimeEvent::XcmBridgeHubRouter(
|
||||
Event::DeliveryFeeFactorIncreased { .. }
|
||||
),
|
||||
..
|
||||
})
|
||||
));
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn sent_message_increases_factor_if_bridge_has_reported_congestion() {
|
||||
run_test(|| {
|
||||
Bridge::<TestRuntime, ()>::put(congested_bridge(
|
||||
Pezpallet::<TestRuntime, ()>::MIN_FEE_FACTOR,
|
||||
));
|
||||
|
||||
let old_bridge = XcmBridgeHubRouter::bridge();
|
||||
assert_ok!(send_xcm::<XcmBridgeHubRouter>(
|
||||
Location::new(2, [GlobalConsensus(BridgedNetworkId::get()), Teyrchain(1000)]),
|
||||
vec![ClearOrigin].into(),
|
||||
)
|
||||
.map(drop));
|
||||
|
||||
assert!(TestToBridgeHubSender::is_message_sent());
|
||||
assert!(
|
||||
old_bridge.delivery_fee_factor < XcmBridgeHubRouter::bridge().delivery_fee_factor
|
||||
);
|
||||
|
||||
// check emitted event
|
||||
let first_system_event = System::events().first().cloned();
|
||||
assert!(matches!(
|
||||
first_system_event,
|
||||
Some(EventRecord {
|
||||
phase: Phase::Initialization,
|
||||
event: RuntimeEvent::XcmBridgeHubRouter(
|
||||
Event::DeliveryFeeFactorIncreased { .. }
|
||||
),
|
||||
..
|
||||
})
|
||||
));
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn get_messages_does_not_return_anything() {
|
||||
run_test(|| {
|
||||
assert_ok!(send_xcm::<XcmBridgeHubRouter>(
|
||||
(Parent, Parent, GlobalConsensus(BridgedNetworkId::get()), Teyrchain(1000)).into(),
|
||||
vec![ClearOrigin].into()
|
||||
));
|
||||
assert_eq!(XcmBridgeHubRouter::get_messages(), vec![]);
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,191 @@
|
||||
// Copyright (C) Parity Technologies (UK) Ltd.
|
||||
// This file is part of Parity Bridges Common.
|
||||
|
||||
// Parity Bridges Common is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
|
||||
// Parity Bridges Common is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Parity Bridges Common. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
#![cfg(test)]
|
||||
|
||||
use crate as pezpallet_xcm_bridge_hub_router;
|
||||
|
||||
use bp_xcm_bridge_hub_router::XcmChannelStatusProvider;
|
||||
use codec::Encode;
|
||||
use pezframe_support::{
|
||||
construct_runtime, derive_impl, parameter_types,
|
||||
traits::{Contains, Equals},
|
||||
};
|
||||
use pezsp_runtime::{traits::ConstU128, BuildStorage};
|
||||
use pezsp_std::cell::RefCell;
|
||||
use xcm::prelude::*;
|
||||
use xcm_builder::{InspectMessageQueues, NetworkExportTable, NetworkExportTableItem};
|
||||
|
||||
type Block = pezframe_system::mocking::MockBlock<TestRuntime>;
|
||||
|
||||
/// HRMP fee.
|
||||
pub const HRMP_FEE: u128 = 500;
|
||||
/// Base bridge fee.
|
||||
pub const BASE_FEE: u128 = 1_000_000;
|
||||
/// Byte bridge fee.
|
||||
pub const BYTE_FEE: u128 = 1_000;
|
||||
|
||||
construct_runtime! {
|
||||
pub enum TestRuntime
|
||||
{
|
||||
System: pezframe_system::{Pezpallet, Call, Config<T>, Storage, Event<T>},
|
||||
XcmBridgeHubRouter: pezpallet_xcm_bridge_hub_router::{Pezpallet, Storage, Event<T>},
|
||||
}
|
||||
}
|
||||
|
||||
parameter_types! {
|
||||
pub ThisNetworkId: NetworkId = Pezkuwi;
|
||||
pub BridgedNetworkId: NetworkId = Kusama;
|
||||
pub UniversalLocation: InteriorLocation = [GlobalConsensus(ThisNetworkId::get()), Teyrchain(1000)].into();
|
||||
pub SiblingBridgeHubLocation: Location = ParentThen([Teyrchain(1002)].into()).into();
|
||||
pub BridgeFeeAsset: AssetId = Location::parent().into();
|
||||
pub BridgeTable: Vec<NetworkExportTableItem>
|
||||
= vec![
|
||||
NetworkExportTableItem::new(
|
||||
BridgedNetworkId::get(),
|
||||
None,
|
||||
SiblingBridgeHubLocation::get(),
|
||||
Some((BridgeFeeAsset::get(), BASE_FEE).into())
|
||||
)
|
||||
];
|
||||
pub UnknownXcmVersionForRoutableLocation: Location = Location::new(2, [GlobalConsensus(BridgedNetworkId::get()), Teyrchain(9999)]);
|
||||
}
|
||||
|
||||
#[derive_impl(pezframe_system::config_preludes::TestDefaultConfig)]
|
||||
impl pezframe_system::Config for TestRuntime {
|
||||
type Block = Block;
|
||||
}
|
||||
|
||||
impl pezpallet_xcm_bridge_hub_router::Config<()> for TestRuntime {
|
||||
type RuntimeEvent = RuntimeEvent;
|
||||
type WeightInfo = ();
|
||||
|
||||
type UniversalLocation = UniversalLocation;
|
||||
type SiblingBridgeHubLocation = SiblingBridgeHubLocation;
|
||||
type BridgedNetworkId = BridgedNetworkId;
|
||||
type Bridges = NetworkExportTable<BridgeTable>;
|
||||
type DestinationVersion =
|
||||
LatestOrNoneForLocationVersionChecker<Equals<UnknownXcmVersionForRoutableLocation>>;
|
||||
|
||||
type BridgeHubOrigin = pezframe_system::EnsureRoot<u64>;
|
||||
type ToBridgeHubSender = TestToBridgeHubSender;
|
||||
type LocalXcmChannelManager = TestLocalXcmChannelManager;
|
||||
|
||||
type ByteFee = ConstU128<BYTE_FEE>;
|
||||
type FeeAsset = BridgeFeeAsset;
|
||||
}
|
||||
|
||||
pub struct LatestOrNoneForLocationVersionChecker<Location>(pezsp_std::marker::PhantomData<Location>);
|
||||
impl<LocationValue: Contains<Location>> GetVersion
|
||||
for LatestOrNoneForLocationVersionChecker<LocationValue>
|
||||
{
|
||||
fn get_version_for(dest: &Location) -> Option<XcmVersion> {
|
||||
if LocationValue::contains(dest) {
|
||||
return None;
|
||||
}
|
||||
Some(XCM_VERSION)
|
||||
}
|
||||
}
|
||||
|
||||
pub struct TestToBridgeHubSender;
|
||||
|
||||
impl TestToBridgeHubSender {
|
||||
pub fn is_message_sent() -> bool {
|
||||
!Self::get_messages().is_empty()
|
||||
}
|
||||
}
|
||||
|
||||
thread_local! {
|
||||
pub static SENT_XCM: RefCell<Vec<(Location, Xcm<()>)>> = RefCell::new(Vec::new());
|
||||
}
|
||||
|
||||
impl SendXcm for TestToBridgeHubSender {
|
||||
type Ticket = (Location, Xcm<()>);
|
||||
|
||||
fn validate(
|
||||
destination: &mut Option<Location>,
|
||||
message: &mut Option<Xcm<()>>,
|
||||
) -> SendResult<Self::Ticket> {
|
||||
let pair = (destination.take().unwrap(), message.take().unwrap());
|
||||
Ok((pair, (BridgeFeeAsset::get(), HRMP_FEE).into()))
|
||||
}
|
||||
|
||||
fn deliver(pair: Self::Ticket) -> Result<XcmHash, SendError> {
|
||||
let hash = fake_message_hash(&pair.1);
|
||||
SENT_XCM.with(|q| q.borrow_mut().push(pair));
|
||||
Ok(hash)
|
||||
}
|
||||
}
|
||||
|
||||
impl InspectMessageQueues for TestToBridgeHubSender {
|
||||
fn clear_messages() {
|
||||
SENT_XCM.with(|q| q.borrow_mut().clear());
|
||||
}
|
||||
|
||||
fn get_messages() -> Vec<(VersionedLocation, Vec<VersionedXcm<()>>)> {
|
||||
SENT_XCM.with(|q| {
|
||||
(*q.borrow())
|
||||
.clone()
|
||||
.iter()
|
||||
.map(|(location, message)| {
|
||||
(
|
||||
VersionedLocation::from(location.clone()),
|
||||
vec![VersionedXcm::from(message.clone())],
|
||||
)
|
||||
})
|
||||
.collect()
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
pub struct TestLocalXcmChannelManager;
|
||||
|
||||
impl TestLocalXcmChannelManager {
|
||||
pub fn make_congested(with: &Location) {
|
||||
pezframe_support::storage::unhashed::put(
|
||||
&(b"TestLocalXcmChannelManager.Congested", with).encode()[..],
|
||||
&true,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
impl XcmChannelStatusProvider for TestLocalXcmChannelManager {
|
||||
fn is_congested(with: &Location) -> bool {
|
||||
pezframe_support::storage::unhashed::get_or_default(
|
||||
&(b"TestLocalXcmChannelManager.Congested", with).encode()[..],
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/// Return test externalities to use in tests.
|
||||
pub fn new_test_ext() -> pezsp_io::TestExternalities {
|
||||
let t = pezframe_system::GenesisConfig::<TestRuntime>::default().build_storage().unwrap();
|
||||
pezsp_io::TestExternalities::new(t)
|
||||
}
|
||||
|
||||
/// Run pezpallet test.
|
||||
pub fn run_test<T>(test: impl FnOnce() -> T) -> T {
|
||||
new_test_ext().execute_with(|| {
|
||||
System::set_block_number(1);
|
||||
System::reset_events();
|
||||
|
||||
test()
|
||||
})
|
||||
}
|
||||
|
||||
pub(crate) fn fake_message_hash<T>(message: &Xcm<T>) -> XcmHash {
|
||||
message.using_encoded(pezsp_io::hashing::blake2_256)
|
||||
}
|
||||
@@ -0,0 +1,150 @@
|
||||
// Copyright (C) Parity Technologies (UK) Ltd.
|
||||
// This file is part of Parity Bridges Common.
|
||||
|
||||
// Parity Bridges Common is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
|
||||
// Parity Bridges Common is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Parity Bridges Common. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
//! Autogenerated weights for pezpallet_xcm_bridge_hub_router
|
||||
//!
|
||||
//! THIS FILE WAS AUTO-GENERATED USING THE BIZINIKIWI BENCHMARK CLI VERSION 4.0.0-dev
|
||||
//! DATE: 2023-08-03, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]`
|
||||
//! WORST CASE MAP SIZE: `1000000`
|
||||
//! HOSTNAME: `covid`, CPU: `11th Gen Intel(R) Core(TM) i7-11800H @ 2.30GHz`
|
||||
//! EXECUTION: , WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024
|
||||
|
||||
// Executed Command:
|
||||
// target/release/rip-bridge-node
|
||||
// benchmark
|
||||
// pezpallet
|
||||
// --chain=dev
|
||||
// --steps=50
|
||||
// --repeat=20
|
||||
// --pezpallet=pezpallet_xcm_bridge_hub_router
|
||||
// --extrinsic=*
|
||||
// --execution=wasm
|
||||
// --wasm-execution=Compiled
|
||||
// --heap-pages=4096
|
||||
// --output=./modules/xcm-bridge-hub-router/src/weights.rs
|
||||
// --template=./.maintain/bridge-weight-template.hbs
|
||||
|
||||
#![allow(clippy::all)]
|
||||
#![allow(unused_parens)]
|
||||
#![allow(unused_imports)]
|
||||
#![allow(missing_docs)]
|
||||
|
||||
use pezframe_support::{
|
||||
traits::Get,
|
||||
weights::{constants::RocksDbWeight, Weight},
|
||||
};
|
||||
use pezsp_std::marker::PhantomData;
|
||||
|
||||
/// Weight functions needed for pezpallet_xcm_bridge_hub_router.
|
||||
pub trait WeightInfo {
|
||||
fn on_initialize_when_non_congested() -> Weight;
|
||||
fn on_initialize_when_congested() -> Weight;
|
||||
fn report_bridge_status() -> Weight;
|
||||
}
|
||||
|
||||
/// Weights for `pezpallet_xcm_bridge_hub_router` that are generated using one of the Bridge testnets.
|
||||
///
|
||||
/// Those weights are test only and must never be used in production.
|
||||
pub struct BridgeWeight<T>(PhantomData<T>);
|
||||
impl<T: pezframe_system::Config> WeightInfo for BridgeWeight<T> {
|
||||
///
|
||||
/// Storage: `XcmBridgeHubRouter::DeliveryFeeFactor` (r:1 w:1)
|
||||
///
|
||||
/// Proof: `XcmBridgeHubRouter::DeliveryFeeFactor` (`max_values`: Some(1), `max_size`: Some(16),
|
||||
/// added: 511, mode: `MaxEncodedLen`)
|
||||
fn on_initialize_when_non_congested() -> Weight {
|
||||
// Proof Size summary in bytes:
|
||||
// Measured: `52`
|
||||
// Estimated: `3517`
|
||||
// Minimum execution time: 11_141 nanoseconds.
|
||||
Weight::from_parts(11_339_000, 3517)
|
||||
.saturating_add(T::DbWeight::get().reads(2_u64))
|
||||
.saturating_add(T::DbWeight::get().writes(1_u64))
|
||||
}
|
||||
/// Storage: UNKNOWN KEY `0x456d756c617465645369626c696e6758636d704368616e6e656c2e436f6e6765`
|
||||
/// (r:1 w:0)
|
||||
///
|
||||
/// Proof: UNKNOWN KEY `0x456d756c617465645369626c696e6758636d704368616e6e656c2e436f6e6765` (r:1
|
||||
/// w:0)
|
||||
fn on_initialize_when_congested() -> Weight {
|
||||
// Proof Size summary in bytes:
|
||||
// Measured: `82`
|
||||
// Estimated: `3547`
|
||||
// Minimum execution time: 4_239 nanoseconds.
|
||||
Weight::from_parts(4_383_000, 3547).saturating_add(T::DbWeight::get().reads(1_u64))
|
||||
}
|
||||
/// Storage: `XcmBridgeHubRouter::Bridge` (r:1 w:1)
|
||||
///
|
||||
/// Proof: `XcmBridgeHubRouter::Bridge` (`max_values`: Some(1), `max_size`: Some(17), added:
|
||||
/// 512, mode: `MaxEncodedLen`)
|
||||
fn report_bridge_status() -> Weight {
|
||||
// Proof Size summary in bytes:
|
||||
// Measured: `53`
|
||||
// Estimated: `1502`
|
||||
// Minimum execution time: 10_427 nanoseconds.
|
||||
Weight::from_parts(10_682_000, 1502)
|
||||
.saturating_add(T::DbWeight::get().reads(1_u64))
|
||||
.saturating_add(T::DbWeight::get().writes(1_u64))
|
||||
}
|
||||
}
|
||||
|
||||
// For backwards compatibility and tests
|
||||
impl WeightInfo for () {
|
||||
/// Storage: UNKNOWN KEY `0x456d756c617465645369626c696e6758636d704368616e6e656c2e436f6e6765`
|
||||
/// (r:1 w:0)
|
||||
///
|
||||
/// Proof: UNKNOWN KEY `0x456d756c617465645369626c696e6758636d704368616e6e656c2e436f6e6765` (r:1
|
||||
/// w:0)
|
||||
///
|
||||
/// Storage: `XcmBridgeHubRouter::DeliveryFeeFactor` (r:1 w:1)
|
||||
///
|
||||
/// Proof: `XcmBridgeHubRouter::DeliveryFeeFactor` (`max_values`: Some(1), `max_size`: Some(16),
|
||||
/// added: 511, mode: `MaxEncodedLen`)
|
||||
fn on_initialize_when_non_congested() -> Weight {
|
||||
// Proof Size summary in bytes:
|
||||
// Measured: `52`
|
||||
// Estimated: `3517`
|
||||
// Minimum execution time: 11_141 nanoseconds.
|
||||
Weight::from_parts(11_339_000, 3517)
|
||||
.saturating_add(RocksDbWeight::get().reads(2_u64))
|
||||
.saturating_add(RocksDbWeight::get().writes(1_u64))
|
||||
}
|
||||
/// Storage: UNKNOWN KEY `0x456d756c617465645369626c696e6758636d704368616e6e656c2e436f6e6765`
|
||||
/// (r:1 w:0)
|
||||
///
|
||||
/// Proof: UNKNOWN KEY `0x456d756c617465645369626c696e6758636d704368616e6e656c2e436f6e6765` (r:1
|
||||
/// w:0)
|
||||
fn on_initialize_when_congested() -> Weight {
|
||||
// Proof Size summary in bytes:
|
||||
// Measured: `82`
|
||||
// Estimated: `3547`
|
||||
// Minimum execution time: 4_239 nanoseconds.
|
||||
Weight::from_parts(4_383_000, 3547).saturating_add(RocksDbWeight::get().reads(1_u64))
|
||||
}
|
||||
/// Storage: `XcmBridgeHubRouter::Bridge` (r:1 w:1)
|
||||
///
|
||||
/// Proof: `XcmBridgeHubRouter::Bridge` (`max_values`: Some(1), `max_size`: Some(17), added:
|
||||
/// 512, mode: `MaxEncodedLen`)
|
||||
fn report_bridge_status() -> Weight {
|
||||
// Proof Size summary in bytes:
|
||||
// Measured: `53`
|
||||
// Estimated: `1502`
|
||||
// Minimum execution time: 10_427 nanoseconds.
|
||||
Weight::from_parts(10_682_000, 1502)
|
||||
.saturating_add(RocksDbWeight::get().reads(1_u64))
|
||||
.saturating_add(RocksDbWeight::get().writes(1_u64))
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user