Skip to content

Commit

Permalink
dry run xcm
Browse files Browse the repository at this point in the history
  • Loading branch information
claravanstaden committed Nov 8, 2024
1 parent 697b51c commit b20b728
Show file tree
Hide file tree
Showing 9 changed files with 145 additions and 24 deletions.
2 changes: 2 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

17 changes: 17 additions & 0 deletions bridges/snowbridge/pallets/inbound-queue-v2/src/api.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// SPDX-License-Identifier: Apache-2.0
// SPDX-FileCopyrightText: 2023 Snowfork <[email protected]>
//! Helpers for implementing runtime api
use crate::{Config, Error};
use snowbridge_core::inbound::Proof;
use snowbridge_router_primitives::inbound::v2::{ConvertMessage, Message};
use xcm::{
latest::Xcm,
prelude::{Junction::*, Location, SendError as XcmpSendError, SendXcm},
};
pub fn dry_run<T>(message: Message, proof: Proof) -> Result<(Xcm<()>, u128), Error<T>>
where
T: Config,
{
Ok((Xcm::<()>::new(), 0))
}
26 changes: 21 additions & 5 deletions bridges/snowbridge/pallets/inbound-queue-v2/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
//! * [`Call::submit`]: Submit a message for verification and dispatch the final destination
//! parachain.
#![cfg_attr(not(feature = "std"), no_std)]

pub mod api;
mod envelope;

#[cfg(feature = "runtime-benchmarks")]
Expand All @@ -41,18 +41,19 @@ use envelope::Envelope;
use frame_support::PalletError;
use frame_system::ensure_signed;
use scale_info::TypeInfo;
use snowbridge_core::inbound::Proof;
use sp_core::H160;
use sp_std::vec;
use xcm::{
latest::Xcm,
prelude::{send_xcm, Junction::*, Location, SendError as XcmpSendError, SendXcm},
};

use snowbridge_core::{
inbound::{Message, VerificationError, Verifier},
BasicOperatingMode,
};
use snowbridge_router_primitives::inbound::v2::Message as MessageV2;
use snowbridge_router_primitives::inbound::v2::ConvertMessage;
use snowbridge_router_primitives::inbound::v2::{ConvertMessage, Message as MessageV2};

pub use weights::WeightInfo;

Expand Down Expand Up @@ -89,7 +90,6 @@ pub mod pallet {

/// XCM message sender
type XcmSender: SendXcm;

/// Address of the Gateway contract
#[pallet::constant]
type GatewayAddress: Get<H160>;
Expand Down Expand Up @@ -208,7 +208,8 @@ pub mod pallet {
let message = MessageV2::decode_all(&mut envelope.payload.as_ref())
.map_err(|_| Error::<T>::InvalidPayload)?;

let xcm = T::MessageConverter::convert(message).map_err(|e| Error::<T>::ConvertMessage(e))?;
let xcm =
T::MessageConverter::convert(message).map_err(|e| Error::<T>::ConvertMessage(e))?;

// Todo: Deposit fee(in Ether) to RewardLeger which should cover all of:
// T::RewardLeger::deposit(who, envelope.fee.into())?;
Expand Down Expand Up @@ -246,4 +247,19 @@ pub mod pallet {
Ok(())
}
}

impl<T: Config> Pallet<T> {
pub fn dry_run_message(
message: Message,
proof: Proof,
) -> Result<(Xcm<()>, u128), Error<T>> {
let xcm =
T::MessageConverter::convert(message).map_err(|e| Error::<T>::ConvertMessage(e))?;
let origin_location = Location::new(1, Parachain(1002).into());
let dry_run_result =
pallet_xcm::dry_run_xcm(origin_location, xcm).map_err(Error::<T>::from)?;

Ok((xcm, 0))
}
}
}
9 changes: 3 additions & 6 deletions bridges/snowbridge/pallets/inbound-queue-v2/src/mock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
// SPDX-FileCopyrightText: 2023 Snowfork <[email protected]>
use super::*;

use crate::{self as inbound_queue};
use frame_support::{derive_impl, parameter_types, traits::ConstU32, weights::IdentityFee};
use hex_literal::hex;
use snowbridge_beacon_primitives::{
Expand All @@ -11,15 +12,14 @@ use snowbridge_core::{
inbound::{Log, Proof, VerificationError},
TokenId,
};
use snowbridge_router_primitives::inbound::v2::MessageToXcm;
use sp_core::{H160, H256};
use sp_runtime::{
traits::{IdentifyAccount, IdentityLookup, MaybeEquivalence, Verify},
BuildStorage, FixedU128, MultiSignature,
};
use sp_std::{convert::From, default::Default};
use xcm::{latest::SendXcm, prelude::*};
use snowbridge_router_primitives::inbound::v2::MessageToXcm;
use crate::{self as inbound_queue};

type Block = frame_system::mocking::MockBlock<Test>;

Expand Down Expand Up @@ -158,10 +158,7 @@ impl inbound_queue::Config for Test {
type WeightInfo = ();
type GatewayAddress = GatewayAddress;
type AssetHubParaId = ConstU32<1000>;
type MessageConverter = MessageToXcm<
EthereumNetwork,
InboundQueuePalletInstance,
>;
type MessageConverter = MessageToXcm<EthereumNetwork, InboundQueuePalletInstance>;
#[cfg(feature = "runtime-benchmarks")]
type Helper = Test;
}
Expand Down
16 changes: 8 additions & 8 deletions bridges/snowbridge/pallets/inbound-queue-v2/src/test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,16 +10,16 @@ use sp_runtime::DispatchError;

use crate::{mock::*, Error, Event as InboundQueueEvent};
use codec::DecodeLimit;
use snowbridge_router_primitives::inbound::v2::InboundAsset;
use snowbridge_router_primitives::inbound::v2::{ConvertMessage, InboundAsset};
use sp_core::H256;
use xcm::opaque::latest::{
prelude::{ClearOrigin, ReceiveTeleportedAsset},
Asset, AssetId, Assets,
use xcm::{
opaque::latest::{
prelude::{ClearOrigin, ReceiveTeleportedAsset},
Asset, AssetId, Assets,
},
prelude::{Junction::AccountKey20, *},
VersionedXcm, MAX_XCM_DECODE_DEPTH,
};
use xcm::VersionedXcm;
use xcm::MAX_XCM_DECODE_DEPTH;
use snowbridge_router_primitives::inbound::v2::ConvertMessage;
use xcm::prelude::{Junction::AccountKey20, *};

#[test]
fn test_submit_happy_path() {
Expand Down
3 changes: 3 additions & 0 deletions bridges/snowbridge/primitives/router/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ scale-info = { features = ["derive"], workspace = true }
log = { workspace = true }

frame-support = { workspace = true }
frame-system = { workspace = true }
sp-core = { workspace = true }
sp-io = { workspace = true }
sp-runtime = { workspace = true }
Expand All @@ -37,6 +38,7 @@ default = ["std"]
std = [
"codec/std",
"frame-support/std",
"frame-system/std",
"log/std",
"scale-info/std",
"snowbridge-core/std",
Expand All @@ -50,6 +52,7 @@ std = [
]
runtime-benchmarks = [
"frame-support/runtime-benchmarks",
"frame-system/runtime-benchmarks",
"snowbridge-core/runtime-benchmarks",
"sp-runtime/runtime-benchmarks",
"xcm-builder/runtime-benchmarks",
Expand Down
86 changes: 86 additions & 0 deletions bridges/snowbridge/primitives/router/src/inbound/dry_run.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
// SPDX-License-Identifier: Apache-2.0
// SPDX-FileCopyrightText: 2023 Snowfork <[email protected]>
use crate::inbound::v2::{ConvertMessage, Message};
use codec::{Decode, Encode};
use frame_support::{
dispatch::{GetDispatchInfo, PostDispatchInfo},
Parameter,
};
use scale_info::TypeInfo;
use sp_runtime::{
traits::{Dispatchable, PhantomData},
Weight,
};
use xcm::{
latest::Xcm,
opaque::latest::{ExecuteXcm, Junction, Junction::Parachain, Location},
};
use xcm_builder::InspectMessageQueues;

#[derive(Copy, Clone, Encode, Decode, Eq, PartialEq, Debug, TypeInfo)]
pub enum DryRunError {
/// Message cannot be decoded.
InvalidPayload,
/// An API call is unsupported.
Unimplemented,
/// Converting a versioned data structure from one version to another failed.
VersionedConversionFailed,
}

pub trait DryRunMessage {
fn dry_run_xcm(message: Message) -> Result<Xcm<()>, DryRunError>;
}

pub struct MessageToFeeEstimate<Runtime, Router, RuntimeCall, XcmExecutor, MessageConverter>
where
Runtime: frame_system::Config,
Router: InspectMessageQueues,
RuntimeCall: Parameter
+ GetDispatchInfo
+ Dispatchable<RuntimeOrigin = <Runtime>::RuntimeOrigin, PostInfo = PostDispatchInfo>,
XcmExecutor: ExecuteXcm<<Runtime>::RuntimeCall>,
MessageConverter: ConvertMessage,
{
_phantom: PhantomData<(Runtime, Router, RuntimeCall, XcmExecutor, MessageConverter)>,
}

impl<Runtime, Router, RuntimeCall, XcmExecutor, MessageConverter> DryRunMessage
for MessageToFeeEstimate<Runtime, Router, RuntimeCall, XcmExecutor, MessageConverter>
where
Runtime: frame_system::Config<RuntimeCall = RuntimeCall>,
Router: InspectMessageQueues,
RuntimeCall: Parameter
+ GetDispatchInfo
+ Dispatchable<RuntimeOrigin = <Runtime>::RuntimeOrigin, PostInfo = PostDispatchInfo>,
XcmExecutor: ExecuteXcm<<Runtime>::RuntimeCall>,
MessageConverter: ConvertMessage,
{
fn dry_run_xcm(message: Message) -> Result<Xcm<()>, DryRunError> {
let message_xcm =
MessageConverter::convert(message).map_err(|error| DryRunError::InvalidPayload)?;
let origin_location = Location::new(1, Parachain(1002));

let xcm_program = Xcm::<RuntimeCall>::from(message_xcm.clone().try_into().unwrap());

let origin_location: Location = origin_location
.try_into()
.map_err(|error| DryRunError::VersionedConversionFailed)?;
let xcm: Xcm<RuntimeCall> =
xcm_program.try_into().map_err(|error| DryRunError::VersionedConversionFailed)?;
let mut hash = xcm.using_encoded(sp_io::hashing::blake2_256);
frame_system::Pallet::<Runtime>::reset_events(); // To make sure we only record events from current call.
let result = XcmExecutor::prepare_and_execute(
origin_location,
xcm,
&mut hash,
Weight::MAX, // Max limit available for execution.
Weight::zero(),
);
let forwarded_xcms = Router::get_messages();
let events: Vec<<Runtime as frame_system::Config>::RuntimeEvent> =
frame_system::Pallet::<Runtime>::read_events_no_consensus()
.map(|record| record.event.clone())
.collect();
Ok(vec![].into())
}
}
1 change: 1 addition & 0 deletions bridges/snowbridge/primitives/router/src/inbound/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
// SPDX-FileCopyrightText: 2023 Snowfork <[email protected]>
// SPDX-FileCopyrightText: 2021-2022 Parity Technologies (UK) Ltd.

pub mod dry_run;
pub mod v1;
pub mod v2;
use codec::Encode;
Expand Down
9 changes: 4 additions & 5 deletions bridges/snowbridge/primitives/router/src/inbound/v2.rs
Original file line number Diff line number Diff line change
Expand Up @@ -83,16 +83,15 @@ where
InboundQueuePalletInstance: Get<u8>,
{
fn convert(message: Message) -> Result<Xcm<()>, ConvertMessageError> {
let mut message_xcm : Xcm<()> = Xcm::new();
if message.xcm.len() > 0{
let mut message_xcm: Xcm<()> = Xcm::new();
if message.xcm.len() > 0 {
// Decode xcm
let versioned_xcm = VersionedXcm::<()>::decode_with_depth_limit(
MAX_XCM_DECODE_DEPTH,
&mut message.xcm.as_ref(),
)
.map_err(|_| ConvertMessageError::InvalidVersionedXCM)?;
message_xcm =
versioned_xcm.try_into().map_err(|_| ConvertMessageError::InvalidXCM)?;
.map_err(|_| ConvertMessageError::InvalidVersionedXCM)?;
message_xcm = versioned_xcm.try_into().map_err(|_| ConvertMessageError::InvalidXCM)?;
}

log::debug!(target: LOG_TARGET,"xcm decoded as {:?}", message_xcm);
Expand Down

0 comments on commit b20b728

Please sign in to comment.