diff --git a/Cargo.lock b/Cargo.lock index 71d6eab4a6e..ac7cba187b3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -8078,12 +8078,15 @@ dependencies = [ "frame-benchmarking", "frame-support", "frame-system", + "pallet-xcm", "parity-scale-codec", "scale-info", "serde", "sp-core", "sp-io", "sp-runtime", + "sp-std", + "xcm", ] [[package]] diff --git a/parachain-template/node/src/chain_spec.rs b/parachain-template/node/src/chain_spec.rs index b37468f184e..187186ef234 100644 --- a/parachain-template/node/src/chain_spec.rs +++ b/parachain-template/node/src/chain_spec.rs @@ -156,7 +156,7 @@ pub fn local_testnet_config() -> ChainSpec { get_account_id_from_seed::("Eve//stash"), get_account_id_from_seed::("Ferdie//stash"), ], - 1000.into(), + 1001.into(), ) }, // Bootnodes @@ -172,7 +172,7 @@ pub fn local_testnet_config() -> ChainSpec { // Extensions Extensions { relay_chain: "rococo-local".into(), // You MUST set this to the correct network! - para_id: 1000, + para_id: 1001, }, ) } diff --git a/parachain-template/pallets/template/Cargo.toml b/parachain-template/pallets/template/Cargo.toml index 1ccdc6622ba..1abe5394c57 100644 --- a/parachain-template/pallets/template/Cargo.toml +++ b/parachain-template/pallets/template/Cargo.toml @@ -19,6 +19,10 @@ scale-info = { version = "2.2.0", default-features = false, features = ["derive" frame-benchmarking = { git = "https://github.com/paritytech/substrate", default-features = false, optional = true, branch = "master" } frame-support = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" } frame-system = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" } +sp-std = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "master" } + +pallet-xcm = { git = "https://github.com/paritytech/polkadot", default-features = false , branch = "master" } +xcm = { git = "https://github.com/paritytech/polkadot", default-features = false , branch = "master" } [dev-dependencies] serde = { version = "1.0.163" } @@ -37,5 +41,8 @@ std = [ "frame-benchmarking/std", "frame-support/std", "frame-system/std", + "sp-std/std", + "pallet-xcm/std", + "xcm/std", ] -try-runtime = [ "frame-support/try-runtime" ] +try-runtime = [ "frame-support/try-runtime", "pallet-xcm/try-runtime" ] diff --git a/parachain-template/pallets/template/src/lib.rs b/parachain-template/pallets/template/src/lib.rs index 5f3252bfc3a..911896d15d4 100644 --- a/parachain-template/pallets/template/src/lib.rs +++ b/parachain-template/pallets/template/src/lib.rs @@ -18,10 +18,12 @@ mod benchmarking; pub mod pallet { use frame_support::{dispatch::DispatchResultWithPostInfo, pallet_prelude::*}; use frame_system::pallet_prelude::*; + use sp_std::boxed::Box; + use xcm::{v3::prelude::*, VersionedMultiLocation, VersionedXcm}; /// Configure the pallet by specifying the parameters and types on which it depends. #[pallet::config] - pub trait Config: frame_system::Config { + pub trait Config: frame_system::Config + pallet_xcm::Config { /// Because this pallet emits events, it depends on the runtime's definition of an event. type RuntimeEvent: From> + IsType<::RuntimeEvent>; } @@ -45,6 +47,8 @@ pub mod pallet { /// Event documentation should end with an array that provides descriptive names for event /// parameters. [something, who] SomethingStored(u32, T::AccountId), + /// XCM message sent. \[to, message\] + Sent { from: T::AccountId, to: MultiLocation, message: Xcm<()> }, } // Errors inform users that something went wrong. @@ -54,6 +58,15 @@ pub mod pallet { NoneValue, /// Errors should have helpful documentation associated with them. StorageOverflow, + /// The message and destination combination was not recognized as being + /// reachable. + Unreachable, + /// The message and destination was recognized as being reachable but + /// the operation could not be completed. + SendFailure, + /// The version of the `Versioned` value used is not able to be + /// interpreted. + BadVersion, } #[pallet::hooks] @@ -102,5 +115,27 @@ pub mod pallet { }, } } + + /// Send an XCM message as parachain sovereign. + #[pallet::call_index(2)] + #[pallet::weight(Weight::from_parts(100_000_000, 0))] + pub fn send_xcm( + origin: OriginFor, + dest: Box, + message: Box>, + ) -> DispatchResult { + let who = ensure_signed(origin)?; + let dest = MultiLocation::try_from(*dest).map_err(|()| Error::::BadVersion)?; + let message: Xcm<()> = (*message).try_into().map_err(|()| Error::::BadVersion)?; + + pallet_xcm::Pallet::::send_xcm(Here, dest, message.clone()).map_err( + |e| match e { + SendError::Unroutable => Error::::Unreachable, + _ => Error::::SendFailure, + }, + )?; + Self::deposit_event(Event::Sent { from: who, to: dest, message }); + Ok(()) + } } } diff --git a/parachains/pallets/bridge-transfer/src/impls.rs b/parachains/pallets/bridge-transfer/src/impls.rs index 9eb0e6cfcac..8f993482ab9 100644 --- a/parachains/pallets/bridge-transfer/src/impls.rs +++ b/parachains/pallets/bridge-transfer/src/impls.rs @@ -43,8 +43,12 @@ impl Pallet { pub(crate) fn ensure_reachable_remote_destination( remote_destination: MultiLocation, ) -> Result> { + log::info!(target: LOG_TARGET, "Checking destination"); let devolved = ensure_is_remote(T::UniversalLocation::get(), remote_destination) - .map_err(|_| Error::::UnsupportedDestination)?; + .map_err(|e| { + log::error!(target: LOG_TARGET, "Is not global consenus: {:?}", e); + Error::::UnsupportedDestination + })?; let (remote_network, _) = devolved; T::BridgedDestinationValidator::ensure_destination(remote_network, remote_destination) diff --git a/parachains/runtimes/assets/asset-hub-kusama/src/xcm_config.rs b/parachains/runtimes/assets/asset-hub-kusama/src/xcm_config.rs index 12ad726a544..52dcfa3d253 100644 --- a/parachains/runtimes/assets/asset-hub-kusama/src/xcm_config.rs +++ b/parachains/runtimes/assets/asset-hub-kusama/src/xcm_config.rs @@ -542,8 +542,8 @@ pub mod bridging { // The Registry contract for the bridge which is also the origin for reserves and the prefix of all assets. pub EthereumGatewayLocation: MultiLocation = EthereumLocation::get() .pushed_with_interior( - AccountKey20 { - network: None, + AccountKey20 { + network: None, key: hex_literal::hex!("EDa338E4dC46038493b885327842fD3E301CaB39"), } ).unwrap(); diff --git a/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/lib.rs b/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/lib.rs index 9c9e5797bda..aaec18c20c2 100644 --- a/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/lib.rs +++ b/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/lib.rs @@ -55,10 +55,6 @@ use snowbridge_inbound_queue::BenchmarkHelper; use snowbridge_beacon_primitives::CompactExecutionHeader; #[cfg(feature = "runtime-benchmarks")] use sp_core::H256; -#[cfg(feature = "runtime-benchmarks")] -use xcm_builder::EnsureXcmOrigin; -#[cfg(feature = "runtime-benchmarks")] -use crate::xcm_config::LocalOriginToLocation; use frame_support::{ construct_runtime, @@ -73,7 +69,6 @@ use frame_system::{ EnsureRoot, }; -#[cfg(not(feature = "runtime-benchmarks"))] use pallet_xcm::EnsureXcm; pub use sp_consensus_aura::sr25519::AuthorityId as AuraId; @@ -100,7 +95,7 @@ use crate::{ WithBridgeHubRococoMessageBridge, }, constants::fee::WeightToFee, - xcm_config::XcmRouter, + xcm_config::{AllowSiblingsOnly, XcmRouter}, }; use bridge_runtime_common::{ messages::{source::TargetHeaderChainAdapter, target::SourceHeaderChainAdapter}, @@ -689,12 +684,8 @@ impl snowbridge_control::Config for Runtime { type AgentHashedDescription = AgentHashedDescription; type UniversalLocation = UniversalLocation; type RelayLocation = RelayLocation; - - #[cfg(feature = "runtime-benchmarks")] - type CreateAgentOrigin = EnsureXcmOrigin; - - #[cfg(not(feature = "runtime-benchmarks"))] - type CreateAgentOrigin = EnsureXcm; + type AgentOrigin = EnsureXcm; + type ChannelOrigin = EnsureXcm; } // Create the runtime by composing the FRAME pallets that were previously configured. diff --git a/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/weights/snowbridge_control.rs b/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/weights/snowbridge_control.rs index ca0480834b3..5f679d24ddf 100644 --- a/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/weights/snowbridge_control.rs +++ b/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/weights/snowbridge_control.rs @@ -79,4 +79,49 @@ impl snowbridge_control::WeightInfo for WeightInfo { .saturating_add(T::DbWeight::get().reads(5)) .saturating_add(T::DbWeight::get().writes(4)) } + + /// Todo: update with benchmarked + fn create_channel() -> Weight { + // Proof Size summary in bytes: + // Measured: `84` + // Estimated: `3517` + // Minimum execution time: 34_000_000 picoseconds. + Weight::from_parts(35_000_000, 0) + .saturating_add(Weight::from_parts(0, 3517)) + .saturating_add(T::DbWeight::get().reads(5)) + .saturating_add(T::DbWeight::get().writes(4)) + } + + fn update_channel() -> Weight { + // Proof Size summary in bytes: + // Measured: `84` + // Estimated: `3517` + // Minimum execution time: 34_000_000 picoseconds. + Weight::from_parts(35_000_000, 0) + .saturating_add(Weight::from_parts(0, 3517)) + .saturating_add(T::DbWeight::get().reads(5)) + .saturating_add(T::DbWeight::get().writes(4)) + } + + fn set_operating_mode() -> Weight { + // Proof Size summary in bytes: + // Measured: `84` + // Estimated: `3517` + // Minimum execution time: 34_000_000 picoseconds. + Weight::from_parts(35_000_000, 0) + .saturating_add(Weight::from_parts(0, 3517)) + .saturating_add(T::DbWeight::get().reads(5)) + .saturating_add(T::DbWeight::get().writes(4)) + } + + fn transfer_native_from_agent() -> Weight { + // Proof Size summary in bytes: + // Measured: `84` + // Estimated: `3517` + // Minimum execution time: 34_000_000 picoseconds. + Weight::from_parts(35_000_000, 0) + .saturating_add(Weight::from_parts(0, 3517)) + .saturating_add(T::DbWeight::get().reads(5)) + .saturating_add(T::DbWeight::get().writes(4)) + } } diff --git a/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/xcm_config.rs b/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/xcm_config.rs index f99cafa9da7..48b497465bd 100644 --- a/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/xcm_config.rs +++ b/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/xcm_config.rs @@ -49,6 +49,7 @@ use xcm_executor::{ traits::{ExportXcm, WithOriginFilter}, XcmExecutor, }; +use xcm_executor::traits::{FeeManager, FeeReason}; parameter_types! { pub const RelayLocation: MultiLocation = MultiLocation::parent(); @@ -217,12 +218,9 @@ impl Contains for SafeCallFilter { | snowbridge_inbound_queue::Call::set_gateway { .. } | snowbridge_inbound_queue::Call::set_operating_mode { .. }, ) | RuntimeCall::EthereumOutboundQueue( - snowbridge_outbound_queue::Call::set_owner { .. } - | snowbridge_outbound_queue::Call::set_operating_mode { .. }, - ) | RuntimeCall::EthereumControl( - snowbridge_control::Call::upgrade { .. } - | snowbridge_control::Call::create_agent { .. }, - ) + snowbridge_outbound_queue::Call::set_owner { .. } | + snowbridge_outbound_queue::Call::set_operating_mode { .. }, + ) | RuntimeCall::EthereumControl(..) ) } } @@ -255,6 +253,17 @@ pub type Barrier = TrailingSetTopicAsId< >; pub struct XcmConfig; + +impl FeeManager for XcmConfig { + fn is_waived(origin: Option<&MultiLocation>, r: FeeReason) -> bool { + todo!() + } + + fn handle_fee(fee: MultiAssets) { + todo!() + } +} + impl xcm_executor::Config for XcmConfig { type RuntimeCall = RuntimeCall; type XcmSender = XcmRouter; @@ -411,3 +420,14 @@ impl ExportXcm for BridgeHubRococoOrBridgeHubWococoSwitchExporter { } } } + +/// [`Contains`] implementation that allows multiLocation from sibling chains only +pub struct AllowSiblingsOnly; +impl Contains for AllowSiblingsOnly { + fn contains(l: &MultiLocation) -> bool { + match l { + MultiLocation { parents: 1, interior: X1(Parachain(_)) } => true, + _ => false, + } + } +}