在 Polkadot Runtime 中添加多个 Pallet 实例实战指南

原文作者:PaperMoon团队

Polkadot SDK 提供的 Parachain Template 为自定义平行链开发奠定了坚实基础。通常情况下,一个 Pallet 在 Runtime 中只会被实例化一次。

但在某些复杂业务场景下,我们可能希望:

• 复用同一个 Pallet 的逻辑

• 运行多个配置不同的实例

• 分别承担不同职责

例如:

• 创建多个治理委员会

• 实现多套代币系统

• 区分技术委员会与社区议会

为此,Polkadot SDK 提供了 可实例化 Pallet(Instantiable Pallet)机制,允许同一个 Pallet 在 Runtime 中运行多个相互独立的实例。

本文将以 pallet-collective 为例,系统讲解如何配置和使用多个 Pallet 实例。

通过本文,你将学会:

✅ 识别可实例化 Pallet

✅ 理解实例泛型机制

✅ 为同一 Pallet 配置多个实例

✅ 注册多个实例到 Runtime

✅ 本地运行并验证

✅ 使用 Polkadot.js 测试多实例独立性

准备工作

开始前,请确保你已经具备:

• 可正常运行的 Polkadot SDK 开发环境

• 成功集成过普通 Pallet 的经验

• 熟悉 Runtime 基本结构

什么是可实例化 Pallet?

  1. Instantiable Pallet 设计原理

并非所有 Pallet 都支持多实例。

支持多实例的 Pallet 会在定义中包含额外的泛型参数 I:

复制代码
#[pallet::pallet]
pub struct Pallet<T, I = ()>(PhantomData<(T, I)>);

含义说明:

参数 作用
T Runtime 配置类型
I 实例标识类型

其中:

• I 用于区分不同实例

• 默认为 (),表示单实例

• 多实例时必须显式指定

  1. 实例泛型的作用机制

实例参数 I 会贯穿整个 Pallet 结构:

模块 表现形式
Config Config
Storage 按实例命名空间隔离
Event Event<T, I>
Call Call<T, I>

因此:

👉 不同实例拥有完全独立的状态空间

👉 互不干扰

👉 逻辑复用,数据隔离

添加 pallet-collective 依赖

  1. 修改 Cargo.toml

打开:

复制代码
runtime/Cargo.toml

添加 feature:

复制代码
polkadot-sdk = { workspace = true, features = [
    "pallet-collective",
    "cumulus-pallet-aura-ext",
    "cumulus-pallet-session-benchmarking",
], default-features = false }
  1. 启用 std 特性

在 [features] 中确认:

复制代码
[features]
default = ["std"]

std = [
    "codec/std",
    "cumulus-pallet-parachain-system/std",
    "log/std",
    "polkadot-sdk/std",
    "scale-info/std",
]

避免 Native 编译失败。

理解 pallet-collective 的 Config Trait

Collective 的 Config 定义如下:

复制代码
pub trait Config<I: 'static = ()>: frame_system::Config {
    type RuntimeOrigin;
    type Proposal;
    type RuntimeEvent;
    type MotionDuration;
    type MaxProposals;
    type MaxMembers;
    type DefaultVote;
    type SetMembersOrigin;
    type WeightInfo;
    type MaxProposalWeight;
    type DisapproveOrigin;
    type KillOrigin;
    type Consideration;
}

该配置支持:

• 成员管理

• 提案投票

• 治理执行

• 权重控制

• 押金机制

是 Polkadot 治理体系的核心模块之一。

定义公共参数

在配置实例前,先定义公共参数。

打开:

复制代码
runtime/src/configs/mod.rs

添加:

复制代码
parameter_types! {
    pub const MotionDuration: BlockNumber = 24 * HOURS;
    pub const MaxProposals: u32 = 100;
    pub const MaxMembers: u32 = 100;

    pub MaxProposalWeight: Weight =
        Perbill::from_percent(50) *
        RuntimeBlockWeights::get().max_block;
}

说明:

参数 含义
MotionDuration 投票时长
MaxProposals 最大提案数
MaxMembers 最大成员数
MaxProposalWeight 最大权重

引入实例类型

Polkadot 提供了标准实例标识:

复制代码
use frame_support::instances::{Instance1, Instance2};

特点:

• 官方提供

• 自动生成唯一类型

• 推荐使用

• 避免冲突

配置第一个实例(技术委员会)

在 runtime/src/configs/mod.rs 中添加:

复制代码
/// Configure the Technical Committee collective
impl pallet_collective::Config<Instance1> for Runtime {
    type RuntimeOrigin = RuntimeOrigin;
    type Proposal = RuntimeCall;
    type RuntimeEvent = RuntimeEvent;

    type MotionDuration = MotionDuration;
    type MaxProposals = MaxProposals;
    type MaxMembers = MaxMembers;

    type DefaultVote =
        pallet_collective::MoreThanMajorityThenPrimeDefaultVote;

    type SetMembersOrigin = EnsureRoot<AccountId>;

    type WeightInfo =
        pallet_collective::weights::SubstrateWeight<Runtime>;

    type MaxProposalWeight = MaxProposalWeight;

    type DisapproveOrigin = EnsureRoot<Self::AccountId>;
    type KillOrigin = EnsureRoot<Self::AccountId>;

    type Consideration = ();
}

配置第二个实例(理事会)

继续添加:

复制代码
/// Configure the Council collective
impl pallet_collective::Config<Instance2> for Runtime {
    type RuntimeOrigin = RuntimeOrigin;
    type Proposal = RuntimeCall;
    type RuntimeEvent = RuntimeEvent;

    type MotionDuration = MotionDuration;
    type MaxProposals = MaxProposals;
    type MaxMembers = MaxMembers;

    type DefaultVote =
        pallet_collective::MoreThanMajorityThenPrimeDefaultVote;

    type SetMembersOrigin = EnsureRoot<AccountId>;

    type WeightInfo =
        pallet_collective::weights::SubstrateWeight<Runtime>;

    type MaxProposalWeight = MaxProposalWeight;

    type DisapproveOrigin = EnsureRoot<Self::AccountId>;
    type KillOrigin = EnsureRoot<Self::AccountId>;

    type Consideration = ();
}

可按需区分配置参数。

注册多个实例到 Runtime

打开:

复制代码
runtime/src/lib.rs

在 runtime 宏中添加:

复制代码
#[runtime::pallet_index(50)]
pub type TechnicalCommittee = pallet_collective<Instance1>;

#[runtime::pallet_index(51)]
pub type Council = pallet_collective<Instance2>;

示例结构:

复制代码
#[runtime::pallet_index(0)]
pub type System = frame_system;

// ...

#[runtime::pallet_index(50)]
pub type TechnicalCommittee = pallet_collective<Instance1>;

#[runtime::pallet_index(51)]
pub type Council = pallet_collective<Instance2>;

注意:

项目 要求
pallet_index 唯一
实例参数 必须填写
命名 建议语义化

编译验证

执行:

复制代码
cargo build --release

检查:

✅ Trait 实现完整

✅ Index 无冲突

✅ Feature 正确

✅ 依赖无缺失

本地运行测试

  1. 生成 Chain Spec

    chain-spec-builder create -t development
    --relay-chain paseo
    --para-id 1000
    --runtime ./target/release/wbuild/parachain-template-runtime/parachain_template_runtime.compact.compressed.wasm
    named-preset development

  2. 启动节点

    polkadot-omni-node --chain ./chain_spec.json --dev

确认正常出块。

Polkadot.js 验证多实例

  1. 连接节点

    ws://127.0.0.1:9944

  2. 查看 Extrinsics

路径:

复制代码
Developer → Extrinsics

应看到:

• technicalCommittee

• council

  1. 支持的方法

常见方法:

• propose

• vote

• close

• setMembers

两个实例完全独立。

验证实例隔离性

进入:

复制代码
Developer → Chain State

分别查询:

复制代码
technicalCommittee > members()
council > members()

确认:

✅ 存储隔离

✅ 投票独立

✅ 并行运行

✅ 不互相影响

典型应用场景

多实例最常见用途:

场景 实现方式
技术委员会 Instance1
社区治理 Instance2
财务委员会 Instance3
审计委员会 Instance4

一个 Pallet → 多个组织体系。

总结

本文完整演示了:

复制代码
依赖 → 参数 → 实例 → Config → 注册 → 编译 → 运行 → 验证

掌握后,你可以:

✅ 构建多治理体系

✅ 实现权限分层

✅ 复用核心逻辑

✅ 提升系统可维护性

这是中高级 Runtime 设计的重要能力。

原文链接:https://docs.polkadot.com/parachains/customize-runtime/add-pallet-instances/

相关推荐
Evand J1 小时前
TDOA(到达时间差)的GDOP和CRLB计算的MATLAB例程,论文复现,附参考文献。GDOP:几何精度因子&CRLB:克拉美罗下界
开发语言·matlab·tdoa·crlb·gdop
野犬寒鸦1 小时前
从零起步学习并发编程 || 第七章:ThreadLocal深层解析及常见问题解决方案
java·服务器·开发语言·jvm·后端·学习
云姜.1 小时前
java抽象类和接口
java·开发语言
带刺的坐椅1 小时前
Claude Code Skills,Google A2A Skills,Solon AI Skills 有什么区别?
java·ai·solon·a2a·claudecode·skills
认真的薛薛2 小时前
数据库-sql语句
数据库·sql·oracle
xyq20242 小时前
Pandas 安装指南
开发语言
爱学英语的程序员2 小时前
面试官:你了解过哪些数据库?
java·数据库·spring boot·sql·mysql·mybatis
xixixin_2 小时前
【JavaScript 】从 || 到??:JavaScript 空值处理的最佳实践升级
开发语言·javascript·ecmascript
m0_736919102 小时前
C++中的委托构造函数
开发语言·c++·算法