Skip to content

Commit

Permalink
Merge remote-tracking branch 'ron/outbound-queue-v2' into inbound-que…
Browse files Browse the repository at this point in the history
…ue-v2
  • Loading branch information
claravanstaden committed Nov 5, 2024
2 parents 41170b3 + 0e27a22 commit 2250d9b
Show file tree
Hide file tree
Showing 12 changed files with 114 additions and 13 deletions.
6 changes: 6 additions & 0 deletions Cargo.lock

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

11 changes: 11 additions & 0 deletions bridges/snowbridge/pallets/outbound-queue-v2/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,10 @@ snowbridge-core = { features = ["serde"], workspace = true }
ethabi = { workspace = true }
hex-literal = { workspace = true, default-features = true }
snowbridge-merkle-tree = { workspace = true }
snowbridge-router-primitives = { workspace = true }
xcm = { workspace = true }
xcm-executor = { workspace = true }
xcm-builder = { workspace = true }

[dev-dependencies]
pallet-message-queue = { workspace = true }
Expand All @@ -57,11 +61,15 @@ std = [
"serde/std",
"snowbridge-core/std",
"snowbridge-merkle-tree/std",
"snowbridge-router-primitives/std",
"sp-arithmetic/std",
"sp-core/std",
"sp-io/std",
"sp-runtime/std",
"sp-std/std",
"xcm-builder/std",
"xcm-executor/std",
"xcm/std",
]
runtime-benchmarks = [
"bridge-hub-common/runtime-benchmarks",
Expand All @@ -71,7 +79,10 @@ runtime-benchmarks = [
"frame-system/runtime-benchmarks",
"pallet-message-queue/runtime-benchmarks",
"snowbridge-core/runtime-benchmarks",
"snowbridge-router-primitives/runtime-benchmarks",
"sp-runtime/runtime-benchmarks",
"xcm-builder/runtime-benchmarks",
"xcm-executor/runtime-benchmarks",
]
try-runtime = [
"frame-support/try-runtime",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,19 +16,23 @@ targets = ["x86_64-unknown-linux-gnu"]

[dependencies]
codec = { features = ["derive"], workspace = true }
scale-info = { features = ["derive"], workspace = true }
sp-std = { workspace = true }
sp-api = { workspace = true }
frame-support = { workspace = true }
snowbridge-core = { workspace = true }
snowbridge-merkle-tree = { workspace = true }
xcm = { workspace = true }

[features]
default = ["std"]
std = [
"codec/std",
"frame-support/std",
"scale-info/std",
"snowbridge-core/std",
"snowbridge-merkle-tree/std",
"sp-api/std",
"sp-std/std",
"xcm/std",
]
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,12 @@
#![cfg_attr(not(feature = "std"), no_std)]

use frame_support::traits::tokens::Balance as BalanceT;
use snowbridge_core::outbound::{
v2::{Fee, InboundMessage},
DryRunError,
};
use snowbridge_merkle_tree::MerkleProof;
use xcm::prelude::Xcm;

sp_api::decl_runtime_apis! {
pub trait OutboundQueueApiV2<Balance> where Balance: BalanceT
Expand All @@ -12,5 +17,7 @@ sp_api::decl_runtime_apis! {
/// The merkle root is stored in the block header as a
/// `sp_runtime::generic::DigestItem::Other`
fn prove_message(leaf_index: u64) -> Option<MerkleProof>;

fn dry_run(xcm: Xcm<()>) -> Result<(InboundMessage,Fee<Balance>),DryRunError>;
}
}
46 changes: 46 additions & 0 deletions bridges/snowbridge/pallets/outbound-queue-v2/src/api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,22 @@
use crate::{Config, MessageLeaves};
use frame_support::storage::StorageStreamIter;
use snowbridge_core::{
outbound::{
v2::{CommandWrapper, Fee, GasMeter, InboundMessage, Message},
DryRunError,
},
AgentIdOf,
};
use snowbridge_merkle_tree::{merkle_proof, MerkleProof};
use snowbridge_router_primitives::outbound::v2::XcmConverter;
use sp_core::Get;
use sp_std::vec::Vec;
use xcm::{
latest::Location,
prelude::{Parachain, Xcm},
};
use xcm_executor::traits::ConvertLocation;

pub fn prove_message<T>(leaf_index: u64) -> Option<MerkleProof>
where
Expand All @@ -17,3 +32,34 @@ where
merkle_proof::<<T as Config>::Hashing, _>(MessageLeaves::<T>::stream_iter(), leaf_index);
Some(proof)
}

pub fn dry_run<T>(xcm: Xcm<()>) -> Result<(InboundMessage, Fee<T::Balance>), DryRunError>
where
T: Config,
{
let mut converter = XcmConverter::<T::ConvertAssetId, ()>::new(
&xcm,
T::EthereumNetwork::get(),
AgentIdOf::convert_location(&Location::new(1, Parachain(1000)))
.ok_or(DryRunError::ConvertFailed)?,
);

let message: Message = converter.convert().map_err(|_| DryRunError::ConvertFailed)?;

let fee = Fee::from(crate::Pallet::<T>::calculate_local_fee());

let commands: Vec<CommandWrapper> = message
.commands
.into_iter()
.map(|command| CommandWrapper {
kind: command.index(),
gas: T::GasMeter::maximum_dispatch_gas_used_at_most(&command),
payload: command.abi_encode(),
})
.collect();

let committed_message =
InboundMessage { origin: message.origin.0.to_vec(), nonce: 0, commands };

Ok((committed_message, fee))
}
10 changes: 9 additions & 1 deletion bridges/snowbridge/pallets/outbound-queue-v2/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ use frame_support::{
use snowbridge_core::{
inbound::Message as DeliveryMessage,
outbound::v2::{CommandWrapper, Fee, GasMeter, InboundMessage, Message},
BasicOperatingMode, RewardLedger,
BasicOperatingMode, RewardLedger, TokenId,
};
use snowbridge_merkle_tree::merkle_root;
use sp_core::H256;
Expand All @@ -133,6 +133,10 @@ use alloy_sol_types::SolValue;

use sp_runtime::traits::TrailingZeroInput;

use sp_runtime::traits::MaybeEquivalence;

use xcm::prelude::{Location, NetworkId};

#[frame_support::pallet]
pub mod pallet {
use super::*;
Expand Down Expand Up @@ -180,6 +184,10 @@ pub mod pallet {

/// Reward leger
type RewardLedger: RewardLedger<<Self as frame_system::Config>::AccountId, Self::Balance>;

type ConvertAssetId: MaybeEquivalence<TokenId, Location>;

type EthereumNetwork: Get<NetworkId>;
}

#[pallet::event]
Expand Down
4 changes: 4 additions & 0 deletions bridges/snowbridge/pallets/outbound-queue-v2/src/mock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,8 @@ parameter_types! {
multiplier: FixedU128::from_rational(4, 3),
};
pub const GatewayAddress: H160 = H160(GATEWAY_ADDRESS);
pub EthereumNetwork: NetworkId = NetworkId::Ethereum { chain_id: 11155111 };

}

pub const DOT: u128 = 10_000_000_000;
Expand All @@ -108,6 +110,8 @@ impl crate::Config for Test {
type WeightToFee = IdentityFee<u128>;
type WeightInfo = ();
type RewardLedger = ();
type ConvertAssetId = ();
type EthereumNetwork = EthereumNetwork;
}

fn setup() {
Expand Down
5 changes: 5 additions & 0 deletions bridges/snowbridge/primitives/core/src/outbound/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,3 +29,8 @@ pub trait SendMessageFeeProvider {
/// The local component of the message processing fees in native currency
fn local_fee() -> Self::Balance;
}

#[derive(Copy, Clone, Encode, Decode, Eq, PartialEq, Debug, TypeInfo)]
pub enum DryRunError {
ConvertFailed,
}
24 changes: 13 additions & 11 deletions bridges/snowbridge/primitives/router/src/outbound/v2.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,10 @@ use frame_support::{
};
use snowbridge_core::{
outbound::v2::{Command, Message, SendMessage},
AgentId, TokenId, TokenIdOf,
AgentId, TokenId, TokenIdOf, TokenIdOf as LocationIdOf,
};
use sp_core::{H160, H256};
use sp_runtime::traits::{BlakeTwo256, Hash, MaybeEquivalence};
use sp_runtime::traits::MaybeEquivalence;
use sp_std::{iter::Peekable, marker::PhantomData, prelude::*};
use xcm::prelude::*;
use xcm_builder::{CreateMatcher, ExporterFor, MatchXcm};
Expand Down Expand Up @@ -163,7 +163,7 @@ where

/// Errors that can be thrown to the pattern matching step.
#[derive(PartialEq, Debug)]
enum XcmConverterError {
pub enum XcmConverterError {
UnexpectedEndOfXcm,
EndOfXcmMessageExpected,
WithdrawAssetExpected,
Expand All @@ -181,6 +181,7 @@ enum XcmConverterError {
UnexpectedInstruction,
TooManyCommands,
AliasOriginExpected,
InvalidOrigin,
}

macro_rules! match_expression {
Expand All @@ -192,7 +193,7 @@ macro_rules! match_expression {
};
}

struct XcmConverter<'a, ConvertAssetId, Call> {
pub struct XcmConverter<'a, ConvertAssetId, Call> {
iter: Peekable<Iter<'a, Instruction<Call>>>,
message: Vec<Instruction<Call>>,
ethereum_network: NetworkId,
Expand All @@ -203,7 +204,7 @@ impl<'a, ConvertAssetId, Call> XcmConverter<'a, ConvertAssetId, Call>
where
ConvertAssetId: MaybeEquivalence<TokenId, Location>,
{
fn new(message: &'a Xcm<Call>, ethereum_network: NetworkId, agent_id: AgentId) -> Self {
pub fn new(message: &'a Xcm<Call>, ethereum_network: NetworkId, agent_id: AgentId) -> Self {
Self {
message: message.clone().inner().into(),
iter: message.inner().iter().peekable(),
Expand All @@ -213,7 +214,7 @@ where
}
}

fn convert(&mut self) -> Result<Message, XcmConverterError> {
pub fn convert(&mut self) -> Result<Message, XcmConverterError> {
let result = match self.jump_to() {
// PNA
Ok(ReserveAssetDeposited { .. }) => self.send_native_tokens_message(),
Expand Down Expand Up @@ -251,8 +252,9 @@ where
.ok_or(WithdrawAssetExpected)?;

// Check AliasOrigin.
let origin = match_expression!(self.next()?, AliasOrigin(origin), origin)
let origin_loc = match_expression!(self.next()?, AliasOrigin(origin), origin)
.ok_or(AliasOriginExpected)?;
let origin = LocationIdOf::convert_location(&origin_loc).ok_or(InvalidOrigin)?;

let (deposit_assets, beneficiary) = match_expression!(
self.next()?,
Expand Down Expand Up @@ -304,8 +306,7 @@ where

let message = Message {
id: (*topic_id).into(),
// Todo: Use DescribeLocation
origin: BlakeTwo256::hash_of(origin),
origin,
fee: fee_amount,
commands: BoundedVec::try_from(vec![Command::UnlockNativeToken {
agent_id: self.agent_id,
Expand Down Expand Up @@ -351,8 +352,9 @@ where
.ok_or(ReserveAssetDepositedExpected)?;

// Check AliasOrigin.
let origin = match_expression!(self.next()?, AliasOrigin(origin), origin)
let origin_loc = match_expression!(self.next()?, AliasOrigin(origin), origin)
.ok_or(AliasOriginExpected)?;
let origin = LocationIdOf::convert_location(&origin_loc).ok_or(InvalidOrigin)?;

let (deposit_assets, beneficiary) = match_expression!(
self.next()?,
Expand Down Expand Up @@ -404,7 +406,7 @@ where
let topic_id = match_expression!(self.next()?, SetTopic(id), id).ok_or(SetTopicExpected)?;

let message = Message {
origin: BlakeTwo256::hash_of(origin),
origin,
fee: fee_amount,
id: (*topic_id).into(),
commands: BoundedVec::try_from(vec![Command::MintForeignToken {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,8 @@ impl snowbridge_pallet_outbound_queue_v2::Config for Runtime {
type GatewayAddress = EthereumGatewayAddress;
type WeightInfo = crate::weights::snowbridge_pallet_outbound_queue_v2::WeightInfo<Runtime>;
type RewardLedger = ();
type ConvertAssetId = EthereumSystem;
type EthereumNetwork = EthereumNetwork;
}

#[cfg(any(feature = "std", feature = "fast-runtime", feature = "runtime-benchmarks", test))]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,10 @@ use xcm::VersionedLocation;

use westend_runtime_constants::system_parachain::{ASSET_HUB_ID, BRIDGE_HUB_ID};

use snowbridge_core::outbound::v2::{Fee as FeeV2, InboundMessage};

use snowbridge_core::outbound::DryRunError;

/// The address format for describing accounts.
pub type Address = MultiAddress<AccountId, ()>;

Expand Down Expand Up @@ -904,6 +908,9 @@ impl_runtime_apis! {
fn prove_message(leaf_index: u64) -> Option<snowbridge_merkle_tree::MerkleProof> {
snowbridge_pallet_outbound_queue_v2::api::prove_message::<Runtime>(leaf_index)
}
fn dry_run(xcm: Xcm<()>) -> Result<(InboundMessage,FeeV2<Balance>),DryRunError> {
snowbridge_pallet_outbound_queue_v2::api::dry_run::<Runtime>(xcm)
}
}

impl snowbridge_system_runtime_api::ControlApi<Block> for Runtime {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,6 @@ use xcm_builder::{
SiblingParachainAsNative, SiblingParachainConvertsVia, SignedAccountId32AsNative,
SignedToAccountId32, SovereignSignedViaLocation, TakeWeightCredit, TrailingSetTopicAsId,
UsingComponents, WeightInfoBounds, WithComputedOrigin, WithUniqueTopic,
XcmFeeManagerFromComponents,
};
use xcm_executor::{
traits::{FeeManager, FeeReason, FeeReason::Export},
Expand Down

0 comments on commit 2250d9b

Please sign in to comment.