Rust跨链通信库cumulus-pallet-xcmp-queue的使用,实现Substrate平行链间高效消息传递

Rust跨链通信库cumulus-pallet-xcmp-queue的使用,实现Substrate平行链间高效消息传递

安装

在项目目录中运行以下Cargo命令:

cargo add cumulus-pallet-xcmp-queue

或者在Cargo.toml中添加以下行:

cumulus-pallet-xcmp-queue = "0.22.0"

使用示例

以下是一个使用cumulus-pallet-xcmp-queue实现平行链间消息传递的完整示例:

use frame_support::{parameter_types, traits::Everything};
use frame_system::EnsureRoot;
use cumulus_pallet_xcmp_queue::{Config, XcmpQueue};

parameter_types! {
    pub const QueueConfig: Config = Config {
        // 设置消息队列大小
        max_message_size: 1024,
        // 设置最大未确认消息数
        max_unconfirmed_messages: 100,
        // 设置消息队列权重限制
        weight_limit: 10_000_000,
    };
}

impl Config for Runtime {
    type Event = Event;
    type XcmExecutor = xcm_executor::XcmExecutor<xcm_config::XcmConfig>;
    type ChannelInfo = ParachainSystem;
    type ControllerOrigin = EnsureRoot<AccountId>;
    type WeightInfo = ();
    type PriceForSiblingDelivery = ();
}

// 在runtime中集成XCMP队列
construct_runtime!(
    pub enum Runtime where
        Block = Block,
        NodeBlock = opaque::Block,
        UncheckedExtrinsic = UncheckedExtrinsic,
    {
        // 其他pallet...
        XcmpQueue: cumulus_pallet_xcmp_queue::{Pallet, Call, Storage, Event<T>},
    }
);

完整示例代码

以下是更完整的XCMP队列实现示例,包含消息发送和接收逻辑:

// runtime/src/lib.rs

use frame_support::{
    construct_runtime, parameter_types,
    traits::{Everything, IsType},
    weights::Weight,
};
use frame_system::EnsureRoot;
use xcm::latest::prelude::*;
use xcm_builder::LocationInverter;
use xcm_executor::XcmExecutor;

// 1. 定义XCMP配置
parameter_types! {
    pub const RelayLocation: MultiLocation = MultiLocation::parent();
    pub const MaxAssetsIntoHolding: u32 = 64;
    pub const UnitWeightCost: Weight = Weight::from_parts(10, 10);
    pub const MaxInstructions: u32 = 100;
}

// 2. 配置XCM执行器
pub type XcmRouter = (
    xcm_builder::LocalOriginToLocation,  // 本地origin转换
    xcm_builder::XcmRouter,              // 路由
);

pub type XcmConfig = xcm_builder::XcmConfig<
    XcmRouter,                           // 路由
    parachain_runtime::RuntimeCall,      // runtime调用
    XcmExecutor<xcm_config::XcmConfig>,  // XCM执行器
    AccountId,                           // 账户ID类型
>;

// 3. 配置XCMP队列
parameter_types! {
    pub const QueueConfig: cumulus_pallet_xcmp_queue::Config = 
        cumulus_pallet_xcmp_queue::Config {
            max_message_size: 1024,          // 最大消息大小
            max_unconfirmed_messages: 100,   // 最大未确认消息数
            weight_limit: 10_000_000,        // 权重限制
        };
}

impl cumulus_pallet_xcmp_queue::Config for Runtime {
    type Event = Event;
    type XcmExecutor = XcmExecutor<XcmConfig>;
    type ChannelInfo = ParachainSystem;      // 通道信息来自parachain系统
    type ControllerOrigin = EnsureRoot<AccountId>; // 控制origin为root
    type WeightInfo = ();
    type PriceForSiblingDelivery = ();
}

// 4. 在runtime中集成
construct_runtime!(
    pub enum Runtime where
        Block = Block,
        NodeBlock = opaque::Block,
        UncheckedExtrinsic = UncheckedExtrinsic,
    {
        System: frame_system,
        // ... 其他pallets
        XcmpQueue: cumulus_pallet_xcmp_queue::{Pallet, Call, Storage, Event<T>},
    }
);

// 5. 发送XCMP消息示例
fn send_xcmp_message(
    dest: ParaId,           // 目标平行链ID
    message: Vec<u8>,       // 要发送的消息
) -> DispatchResult {
    let location = MultiLocation::new(1, X1(Parachain(dest.into())));
    let message = Xcm(vec![
        Transact {
            origin_kind: OriginKind::SovereignAccount,
            require_weight_at_most: 1_000_000_000,
            call: message.into(),
        }
    ]);
    
    XcmPallet::send_xcm(location, message)?;
    Ok(())
}

功能说明

cumulus-pallet-xcmp-queue提供了以下主要功能:

  1. 跨链消息队列管理:处理平行链之间的XCMP消息队列
  2. 消息过滤:可以根据自定义规则过滤消息
  3. 权重控制:限制消息处理所占用的计算资源
  4. 安全机制:防止消息队列溢出和资源耗尽

注意事项

  1. 使用前需要确保平行链已正确配置XCMP协议
  2. 消息大小和队列限制应根据实际网络条件调整
  3. 需要为XCMP消息处理预留足够的计算资源

该库是Substrate平行链实现跨链通信的核心组件之一,由Parity团队维护,采用Apache 2.0许可证。


1 回复

cumulus-pallet-xcmp-queue: Substrate平行链间高效消息传递

完整示例

以下是基于提供内容的完整Demo示例,展示如何在Substrate平行链中配置和使用XCMP队列:

// 1. 引入必要的依赖
use frame_support::{parameter_types, traits::EnqueueMessage};
use xcm::latest::prelude::*;
use xcm_executor::XcmExecutor;
use xcm_builder::XcmOriginToTransactDispatchOrigin;

// 2. 定义运行时配置
pub struct Runtime;

// 3. 定义参数类型
parameter_types! {
    pub const MaxXcmpQueueDepth: u32 = 100;
    pub const MaxInboundXcmpMessageSize: u32 = 1024;
}

// 4. 实现xcmp-queue配置
impl cumulus_pallet_xcmp_queue::Config for Runtime {
    type RuntimeEvent = RuntimeEvent;
    type XcmExecutor = XcmExecutor<xcm_config::XcmConfig>;
    type ChannelInfo = ParachainSystem;
    type VersionWrapper = ();
    type ExecuteOverweightOrigin = frame_system::EnsureRoot<AccountId>;
    type ControllerOrigin = frame_system::EnsureRoot<AccountId>;
    type ControllerOriginConverter = XcmOriginToTransactDispatchOrigin;
    type WeightInfo = ();
    type MaxInboundXcmpMessageSize = MaxInboundXcmpMessageSize;
    type MaxXcmpQueueDepth = MaxXcmpQueueDepth;
}

// 5. 在construct_runtime宏中添加pallet
construct_runtime!(
    pub enum Runtime where
        Block = Block,
        NodeBlock = opaque::Block,
        UncheckedExtrinsic = UncheckedExtrinsic,
    {
        // 其他pallet...
        XcmpQueue: cumulus_pallet_xcmp_queue::{Pallet, Call, Storage, Event<T>},
    }
);

// 6. 发送XCMP消息的函数示例
pub fn send_xcmp_message() {
    // 构建XCM消息
    let message = Xcm(vec![
        // 从发送方账户提取100个原生Token
        WithdrawAsset((Here, 100u128).into()),
        // 购买执行时间
        BuyExecution {
            fees: (Here, 100u128).into(),
            weight_limit: Unlimited,
        },
        // 将资产存入目标链上的ALICE账户
        DepositAsset {
            assets: All.into(),
            max_assets: 1,
            beneficiary: MultiLocation::new(
                1,
                X1(AccountId32 {
                    network: None,
                    id: ALICE.into(),
                }),
            ),
        },
    ]);

    // 发送到目标平行链(ID为2000)
    let dest = Parachain(2000).into();
    let _ = XcmpQueue::send_xcm(dest, message)
        .map_err(|e| log::error!("Failed to send XCM message: {:?}", e));
}

// 7. 处理积压消息的函数示例
pub fn service_overweight_messages() {
    // 手动执行积压的消息
    let _ = XcmpQueue::service_overweight(
        RuntimeOrigin::root(),
        1u64,     // 消息索引
        100000u64 // 权重限制
    );
}

示例说明

  1. 运行时集成:完整展示了如何在运行时中集成xcmp-queue pallet,包括配置trait的实现和construct_runtime宏的使用。

  2. 消息发送:提供了完整的XCMP消息构建和发送示例,包含资产转移的典型用例。

  3. 积压处理:展示了如何手动处理积压的XCMP消息。

  4. 参数配置:包含了队列深度和消息大小的限制配置。

最佳实践建议

  1. 在真实环境中,应该根据实际需求调整MaxXcmpQueueDepthMaxInboundXcmpMessageSize参数。

  2. 建议为ExecuteOverweightOriginControllerOrigin设置适当的权限控制,而不仅仅是EnsureRoot

  3. 在实际应用中应该添加更完善的错误处理和日志记录。

  4. 对于生产环境,建议实现监控机制来跟踪队列深度和消息处理状态。

回到顶部