mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-07-22 07:55:42 +00:00
8428f678fe
# Note for reviewer
Most changes are just syntax changes necessary for the new version.
Most important files should be the ones under the `xcm` folder.
# Description
Added XCMv4.
## Removed `Multi` prefix
The following types have been renamed:
- MultiLocation -> Location
- MultiAsset -> Asset
- MultiAssets -> Assets
- InteriorMultiLocation -> InteriorLocation
- MultiAssetFilter -> AssetFilter
- VersionedMultiAsset -> VersionedAsset
- WildMultiAsset -> WildAsset
- VersionedMultiLocation -> VersionedLocation
In order to fix a name conflict, the `Assets` in `xcm-executor` were
renamed to `HoldingAssets`, as they represent assets in holding.
## Removed `Abstract` asset id
It was not being used anywhere and this simplifies the code.
Now assets are just constructed as follows:
```rust
let asset: Asset = (AssetId(Location::new(1, Here)), 100u128).into();
```
No need for specifying `Concrete` anymore.
## Outcome is now a named fields struct
Instead of
```rust
pub enum Outcome {
Complete(Weight),
Incomplete(Weight, Error),
Error(Error),
}
```
we now have
```rust
pub enum Outcome {
Complete { used: Weight },
Incomplete { used: Weight, error: Error },
Error { error: Error },
}
```
## Added Reanchorable trait
Now both locations and assets implement this trait, making it easier to
reanchor both.
## New syntax for building locations and junctions
Now junctions are built using the following methods:
```rust
let location = Location {
parents: 1,
interior: [Parachain(1000), PalletInstance(50), GeneralIndex(1984)].into()
};
```
or
```rust
let location = Location::new(1, [Parachain(1000), PalletInstance(50), GeneralIndex(1984)]);
```
And they are matched like so:
```rust
match location.unpack() {
(1, [Parachain(id)]) => ...
(0, Here) => ...,
(1, [_]) => ...,
}
```
This syntax is mandatory in v4, and has been also implemented for v2 and
v3 for easier migration.
This was needed to make all sizes smaller.
# TODO
- [x] Scaffold v4
- [x] Port github.com/paritytech/polkadot/pull/7236
- [x] Remove `Multi` prefix
- [x] Remove `Abstract` asset id
---------
Co-authored-by: command-bot <>
Co-authored-by: Keith Yeung <kungfukeith11@gmail.com>
210 lines
6.0 KiB
Rust
210 lines
6.0 KiB
Rust
// Copyright 2019-2021 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/>.
|
|
|
|
//! The code that allows to use the pallet (`pallet-xcm-bridge-hub`) as XCM message
|
|
//! exporter at the sending bridge hub. Internally, it just enqueues outbound blob
|
|
//! in the messages pallet queue.
|
|
//!
|
|
//! This code is executed at the source bridge hub.
|
|
|
|
use crate::{Config, Pallet, LOG_TARGET};
|
|
|
|
use bp_messages::source_chain::MessagesBridge;
|
|
use bp_xcm_bridge_hub::XcmAsPlainPayload;
|
|
use bridge_runtime_common::messages_xcm_extension::{LocalXcmQueueManager, SenderAndLane};
|
|
use pallet_bridge_messages::{Config as BridgeMessagesConfig, Pallet as BridgeMessagesPallet};
|
|
use xcm::prelude::*;
|
|
use xcm_builder::{HaulBlob, HaulBlobError, HaulBlobExporter};
|
|
use xcm_executor::traits::ExportXcm;
|
|
|
|
/// An easy way to access `HaulBlobExporter`.
|
|
pub type PalletAsHaulBlobExporter<T, I> = HaulBlobExporter<
|
|
DummyHaulBlob,
|
|
<T as Config<I>>::BridgedNetwork,
|
|
<T as Config<I>>::DestinationVersion,
|
|
<T as Config<I>>::MessageExportPrice,
|
|
>;
|
|
/// An easy way to access associated messages pallet.
|
|
type MessagesPallet<T, I> = BridgeMessagesPallet<T, <T as Config<I>>::BridgeMessagesPalletInstance>;
|
|
|
|
impl<T: Config<I>, I: 'static> ExportXcm for Pallet<T, I>
|
|
where
|
|
T: BridgeMessagesConfig<
|
|
<T as Config<I>>::BridgeMessagesPalletInstance,
|
|
OutboundPayload = XcmAsPlainPayload,
|
|
>,
|
|
{
|
|
type Ticket = (SenderAndLane, XcmAsPlainPayload, XcmHash);
|
|
|
|
fn validate(
|
|
network: NetworkId,
|
|
channel: u32,
|
|
universal_source: &mut Option<InteriorLocation>,
|
|
destination: &mut Option<InteriorLocation>,
|
|
message: &mut Option<Xcm<()>>,
|
|
) -> Result<(Self::Ticket, Assets), SendError> {
|
|
// Find supported lane_id.
|
|
let sender_and_lane = Self::lane_for(
|
|
universal_source.as_ref().ok_or(SendError::MissingArgument)?,
|
|
(&network, destination.as_ref().ok_or(SendError::MissingArgument)?),
|
|
)
|
|
.ok_or(SendError::NotApplicable)?;
|
|
|
|
// check if we are able to route the message. We use existing `HaulBlobExporter` for that.
|
|
// It will make all required changes and will encode message properly, so that the
|
|
// `DispatchBlob` at the bridged bridge hub will be able to decode it
|
|
let ((blob, id), price) = PalletAsHaulBlobExporter::<T, I>::validate(
|
|
network,
|
|
channel,
|
|
universal_source,
|
|
destination,
|
|
message,
|
|
)?;
|
|
|
|
Ok(((sender_and_lane, blob, id), price))
|
|
}
|
|
|
|
fn deliver(
|
|
(sender_and_lane, blob, id): (SenderAndLane, XcmAsPlainPayload, XcmHash),
|
|
) -> Result<XcmHash, SendError> {
|
|
let lane_id = sender_and_lane.lane;
|
|
let send_result = MessagesPallet::<T, I>::send_message(lane_id, blob);
|
|
|
|
match send_result {
|
|
Ok(artifacts) => {
|
|
log::info!(
|
|
target: LOG_TARGET,
|
|
"XCM message {:?} has been enqueued at bridge {:?} with nonce {}",
|
|
id,
|
|
lane_id,
|
|
artifacts.nonce,
|
|
);
|
|
|
|
// notify XCM queue manager about updated lane state
|
|
LocalXcmQueueManager::<T::LanesSupport>::on_bridge_message_enqueued(
|
|
&sender_and_lane,
|
|
artifacts.enqueued_messages,
|
|
);
|
|
},
|
|
Err(error) => {
|
|
log::debug!(
|
|
target: LOG_TARGET,
|
|
"XCM message {:?} has been dropped because of bridge error {:?} on bridge {:?}",
|
|
id,
|
|
error,
|
|
lane_id,
|
|
);
|
|
return Err(SendError::Transport("BridgeSendError"))
|
|
},
|
|
}
|
|
|
|
Ok(id)
|
|
}
|
|
}
|
|
|
|
/// Dummy implementation of the `HaulBlob` trait that is never called.
|
|
///
|
|
/// We are using `HaulBlobExporter`, which requires `HaulBlob` implementation. It assumes that
|
|
/// there's a single channel between two bridge hubs - `HaulBlob` only accepts the blob and nothing
|
|
/// else. But bridge messages pallet may have a dedicated channel (lane) for every pair of bridged
|
|
/// chains. So we are using our own `ExportXcm` implementation, but to utilize `HaulBlobExporter` we
|
|
/// still need this `DummyHaulBlob`.
|
|
pub struct DummyHaulBlob;
|
|
|
|
impl HaulBlob for DummyHaulBlob {
|
|
fn haul_blob(_blob: XcmAsPlainPayload) -> Result<(), HaulBlobError> {
|
|
Err(HaulBlobError::Transport("DummyHaulBlob"))
|
|
}
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod tests {
|
|
use super::*;
|
|
use crate::mock::*;
|
|
use frame_support::assert_ok;
|
|
use xcm_executor::traits::export_xcm;
|
|
|
|
fn universal_source() -> InteriorLocation {
|
|
[GlobalConsensus(RelayNetwork::get()), Parachain(SIBLING_ASSET_HUB_ID)].into()
|
|
}
|
|
|
|
fn universal_destination() -> InteriorLocation {
|
|
BridgedDestination::get()
|
|
}
|
|
|
|
#[test]
|
|
fn export_works() {
|
|
run_test(|| {
|
|
assert_ok!(export_xcm::<XcmOverBridge>(
|
|
BridgedRelayNetwork::get(),
|
|
0,
|
|
universal_source(),
|
|
universal_destination(),
|
|
vec![Instruction::ClearOrigin].into(),
|
|
));
|
|
})
|
|
}
|
|
|
|
#[test]
|
|
fn export_fails_if_argument_is_missing() {
|
|
run_test(|| {
|
|
assert_eq!(
|
|
XcmOverBridge::validate(
|
|
BridgedRelayNetwork::get(),
|
|
0,
|
|
&mut None,
|
|
&mut Some(universal_destination()),
|
|
&mut Some(Vec::new().into()),
|
|
),
|
|
Err(SendError::MissingArgument),
|
|
);
|
|
|
|
assert_eq!(
|
|
XcmOverBridge::validate(
|
|
BridgedRelayNetwork::get(),
|
|
0,
|
|
&mut Some(universal_source()),
|
|
&mut None,
|
|
&mut Some(Vec::new().into()),
|
|
),
|
|
Err(SendError::MissingArgument),
|
|
);
|
|
})
|
|
}
|
|
|
|
#[test]
|
|
fn exporter_computes_correct_lane_id() {
|
|
run_test(|| {
|
|
let expected_lane_id = TEST_LANE_ID;
|
|
|
|
assert_eq!(
|
|
XcmOverBridge::validate(
|
|
BridgedRelayNetwork::get(),
|
|
0,
|
|
&mut Some(universal_source()),
|
|
&mut Some(universal_destination()),
|
|
&mut Some(Vec::new().into()),
|
|
)
|
|
.unwrap()
|
|
.0
|
|
.0
|
|
.lane,
|
|
expected_lane_id,
|
|
);
|
|
})
|
|
}
|
|
}
|