Rust跨链消息处理库xcm-procedural的使用:XCM(Cross-Consensus Messaging)程序宏与Substrate框架集成开发
Rust跨链消息处理库xcm-procedural的使用:XCM(Cross-Consensus Messaging)程序宏与Substrate框架集成开发
安装
在项目目录中运行以下Cargo命令:
cargo add xcm-procedural
或者在Cargo.toml中添加以下行:
xcm-procedural = "11.0.2"
完整示例代码
以下是XCM程序宏与Substrate框架集成开发的完整示例:
use xcm_procedural::*;
use frame_support::{decl_module, decl_storage, dispatch::DispatchResult};
use sp_std::prelude::*;
// 使用xcm_procedural宏定义XCM消息处理器
#[xcm_message_handler]
pub trait XcmMessageHandler {
/// 处理传入的XCM消息
fn handle_xcm_message(origin: &MultiLocation, message: Xcm<()>) -> DispatchResult;
}
// 定义模块配置
pub trait Config: frame_system::Config {
type Event: From<Event<Self>> + Into<<Self as frame_system::Config>::Event>;
}
// 定义存储项
decl_storage! {
trait Store for Module<T: Config> as XcmExample {
// 存储最后接收到的XCM消息
LastReceivedXcm get(fn last_received_xcm): Option<Xcm<()>>;
}
}
// 定义模块
decl_module! {
pub struct Module<T: Config> for enum Call where origin: T::Origin {
type Error = sp_runtime::DispatchError;
fn deposit_event() = default;
// XCM消息处理函数
#[weight = 10_000]
pub fn process_xcm_message(
origin,
message: Xcm<()>,
) -> DispatchResult {
let sender = ensure_signed(origin)?;
// 存储接收到的消息
LastReceivedXcm::put(message.clone());
// 处理XCM消息
Self::handle_xcm_message(&MultiLocation::here(), message)?;
Self::deposit_event(Event::XcmMessageProcessed(sender));
Ok(())
}
}
}
// 实现XCM消息处理器
impl<T: Config> XcmMessageHandler for Module<T> {
fn handle_xcm_message(origin: &MultiLocation, message: Xcm<()>) -> DispatchResult {
// 在这里实现自定义XCM消息处理逻辑
log::info!("Received XCM message from {:?}: {:?}", origin, message);
// 示例:检查消息是否包含转账指令
if let Some(TransferAsset { assets, .. }) = message.0.first() {
log::info!("XCM transfer detected: {:?}", assets);
}
Ok(())
}
}
// 定义事件
#[frame_support::pallet]
pub mod pallet {
#[pallet::event]
#[pallet::generate_deposit(pub(super) fn deposit_event)]
pub enum Event<T: Config> {
/// XCM消息已处理
XcmMessageProcessed(T::AccountId),
}
}
// 配置runtime
impl pallet_xcm_example::Config for Runtime {
type Event = Event;
}
关键组件说明
-
xcm_procedural宏:
#[xcm_message_handler]
宏用于标记XCM消息处理trait,自动生成必要的实现代码。 -
XCM消息处理:
handle_xcm_message
函数是处理XCM消息的核心,可以自定义处理逻辑。 -
存储:示例中存储了最后接收到的XCM消息,便于调试和验证。
-
事件系统:当XCM消息处理完成时,会发出相应事件。
使用场景
此示例展示了如何:
- 接收并处理XCM消息
- 解析XCM消息内容
- 响应跨链请求
- 与Substrate框架集成
注意事项
- 需要确保runtime已正确配置XCM支持
- 根据实际业务需求调整消息处理逻辑
- 考虑XCM执行权重和费用计算
1 回复
Rust跨链消息处理库xcm-procedural的使用指南
概述
xcm-procedural是一个用于处理XCM(跨共识消息)的Rust程序宏库,专为Substrate区块链框架设计。它简化了XCM消息的构建和处理过程,使开发者能够更高效地实现跨链通信功能。
主要特性
- 提供声明式宏简化XCM消息构建
- 支持Substrate框架集成
- 类型安全的XCM消息构造
- 减少样板代码
完整示例代码
以下是结合内容中所有示例的完整demo代码:
// 1. 添加依赖到Cargo.toml
/*
[dependencies]
xcm-procedural = { version = "0.9" }
xcm = { version = "0.9" }
*/
// 2. 基本用法示例
use xcm_procedural::{xcm, xcm_execute};
fn basic_xcm_example() {
// 构建XCM消息
let message = xcm!(
WithdrawAsset((Here, 100u128).into()), // 从本地链提取100个原生代币
BuyExecution { // 购买执行时间
fees: (Here, 1u128).into(), // 支付1个代币作为费用
weight_limit: Unlimited, // 不限制执行权重
},
DepositAsset { // 存入资产
assets: All.into(), // 所有资产
max_assets: 1, // 最多1种资产
beneficiary: AccountId32 { // 受益人账户
network: Any, // 任何网络
id: [1u8; 32].into(), // 账户ID
}.into(),
}
);
// 执行XCM消息
xcm_execute!(message);
}
// 3. 与Substrate集成示例
use frame_support::{pallet_prelude::*, traits::Currency};
use xcm_procedural::{xcm, xcm_send};
#[frame_support::pallet]
pub mod pallet {
use super::*;
#[pallet::config]
pub trait Config: frame_system::Config {
type Currency: Currency<Self::AccountId>;
}
#[pallet::pallet]
pub struct Pallet<T>(_);
#[pallet::call]
impl<T: Config> Pallet<T> {
#[pallet::weight(10_000)]
pub fn send_xcm_message(origin: OriginFor<T>) -> DispatchResult {
let sender = ensure_signed(origin)?;
// 构建XCM消息
let message = xcm!(
ReserveAssetDeposited((Parent, 100u128).into()), // 使用预留的100个父链代币
ClearOrigin, // 清除原始发送者
DepositAsset { // 存入资产
assets: All.into(),
max_assets: 1,
beneficiary: AccountId32 {
network: Any,
id: [2u8; 32].into(),
}.into(),
}
);
// 发送到父链
xcm_send!(Parent, message);
Ok(())
}
}
}
// 4. 处理传入的XCM消息
use xcm_procedural::{xcm_execute, Xcm};
pub fn handle_incoming_xcm(message: Xcm<()>) -> Result<(), &'static str> {
xcm_execute!(message);
Ok(())
}
// 5. 高级用法 - 自定义XCM指令
use xcm_procedural::{xcm, custom_xcm_instruction};
custom_xcm_instruction!(
MyCustomInstruction { // 自定义指令
param1: u32, // 参数1
param2: Vec<u8>, // 参数2
}
);
fn custom_instruction_example() {
let message = xcm!(
WithdrawAsset((Here, 100u128).into()),
MyCustomInstruction { // 使用自定义指令
param1: 42,
param2: b"custom_data".to_vec(),
},
DepositAsset {
assets: All.into(),
max_assets: 1,
beneficiary: AccountId32 {
network: Any,
id: [3u8; 32].into(),
}.into(),
}
);
}
// 6. 权重计算示例
use xcm_procedural::{xcm, xcm_weight};
fn weight_calculation_example() {
let message = xcm!(
WithdrawAsset((Here, 100u128).into()),
BuyExecution {
fees: (Here, 1u128).into(),
weight_limit: Limited(1_000_000), // 限制执行权重
}
);
let weight = xcm_weight!(message);
println!("预估XCM执行权重: {}", weight);
}
fn main() {
basic_xcm_example();
weight_calculation_example();
}
注意事项
- 确保使用的xcm-procedural版本与Substrate版本兼容
- XCM消息执行可能需要目标链的支持
- 跨链操作通常需要支付费用,确保账户有足够余额
- 权重计算应准确以避免执行失败
通过xcm-procedural库,开发者可以更简洁高效地构建和处理XCM消息,实现复杂的跨链交互功能。