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;
}

关键组件说明

  1. xcm_procedural宏#[xcm_message_handler]宏用于标记XCM消息处理trait,自动生成必要的实现代码。

  2. XCM消息处理handle_xcm_message函数是处理XCM消息的核心,可以自定义处理逻辑。

  3. 存储:示例中存储了最后接收到的XCM消息,便于调试和验证。

  4. 事件系统:当XCM消息处理完成时,会发出相应事件。

使用场景

此示例展示了如何:

  • 接收并处理XCM消息
  • 解析XCM消息内容
  • 响应跨链请求
  • 与Substrate框架集成

注意事项

  1. 需要确保runtime已正确配置XCM支持
  2. 根据实际业务需求调整消息处理逻辑
  3. 考虑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();
}

注意事项

  1. 确保使用的xcm-procedural版本与Substrate版本兼容
  2. XCM消息执行可能需要目标链的支持
  3. 跨链操作通常需要支付费用,确保账户有足够余额
  4. 权重计算应准确以避免执行失败

通过xcm-procedural库,开发者可以更简洁高效地构建和处理XCM消息,实现复杂的跨链交互功能。

回到顶部