资讯详情

Substrate Collective Pallet 深度解析:理事会治理中的多成员投票、提案动议与 Prime 默认投票机制

📅 2026/9/27 8:45:57 | 华诺云谱 👁 阅读
Substrate Collective Pallet 深度解析:理事会治理中的多成员投票、提案动议与 Prime 默认投票机制
区块链开发框架后端【免费下载链接】substrateSubstrate: The platform for blockchain innovators项目地址https://gitcode.com/gh_mirrors/su/substrate点击查看免费下载本文围绕 frame/collective/README.md 展开系统讲解 Substrate 中pallet-collective的核心设计两种成员来源、两类默认投票策略、提案动议motion从提出到执行的完整生命周期并结合仓库源码与真实运行时配置给出可落地的治理实践方案。读完本文你将掌握如何在 Substrate 运行时中接入并配置理事会 / 技术委员会理解提案门槛threshold、Prime 成员与弃权票的交互规则并能读懂相关测试用例与权重估算逻辑。一、Collective 是什么把一组账户的“集体意愿”变成可执行调用在 Substrate 生态中pallet-collective是一个经典的多签治理原语它把一组AccountId成员组织成一个集体成员可以通过两个专用 Origin发起 dispatch 调用从而让“集体的意志”可被链上执行。它的典型应用场景是理事会Council与技术委员会Technical Committee——例如节点示例运行时中Council、TechnicalCommittee、AllianceMotion都是通过实例化pallet_collective得到的见 bin/node/runtime/src/lib.rs。Council: pallet_collective::Instance1, TechnicalCommittee: pallet_collective::Instance2, AllianceMotion: pallet_collective::Instance3,每个实例拥有独立的成员集合、独立的投票状态、独立的存储因此可以在同一个链上同时存在多个互不干扰的集体。两个专用 Origin定义在 frame/collective/src/lib.rs 的RawOrigin枚举中Members(MemberCount, MemberCount)该调用已被集体的一定数量成员认可参数为认可人数, 总席位数Member(AccountId)该调用已被单个成员认可。这两个 Origin 是其他 pallet如 Democracy、Treasury、Elections授权给集体代行治理权限的桥梁。例如在节点运行时中EnsureProportionAtLeastAccountId, CouncilCollective, 3, 4被用作外部多数提案的授权来源bin/node/runtime/src/lib.rs表示“需要 ≥3/4 的理事会成员认可”。二、成员从哪里来set_members直接设置与ChangeMembers间接管理README 明确指出集体成员有两种提供方式直接方式调用 Root 可调用的set_members函数间接方式由其他 pallet 实现ChangeMemberstrait 来维护成员集合。2.1 直接方式set_membersset_members是pallet-collective的call_index(0)调用frame/collective/src/lib.rs签名如下pub fn set_members( origin: OriginForT, new_members: VecT::AccountId, prime: OptionT::AccountId, old_count: MemberCount, ) - DispatchResultWithPostInfonew_members新成员列表建议调用方提供排序后的列表pallet 内部也会再次sort()prime可选的 Prime 成员old_count存储中旧成员数量的上界用于权重估算调用来源必须满足SetMembersOrigin在运行时中通常配置为EnsureRoot即只有 Root 或经由治理授权的来源可以设置成员。实现细节值得注意若prime提供但不是成员返回Error::PrimeAccountNotMember若new_members超过MaxMembers只打 error 日志、不拒绝执行——这正是 README 强调的“pallet 假设成员数不超过MaxMembers用于权重计算但不在set_members中强制”内部走ChangeMembers::set_members_sorted更新成员并清空 Prime见change_members_sorted中Prime::T, I::kill()。2.2 间接方式ChangeMemberstraitChangeMembers由frame_support提供pallet-collective为它实现了三个方法frame/collective/src/lib.rschange_members_sorted(incoming, outgoing, new)更新成员列表从所有进行中的动议投票里剔除已离任成员并重置 Primeset_prime(prime)设置 Primeget_prime()读取 Prime。典型用法是选举 pallet节点运行时中pallet_elections_phragmen::Config的type ChangeMembers Council、type InitializeMembers Councilbin/node/runtime/src/lib.rs即理事会成员由 Phragmén 选举产生当选/离任时自动回调 collective 更新成员。README 中的 WARNING 在此得到印证set_members与外部成员管理逻辑必须保持同步否则会“成员集合与治理逻辑脱节”。此外InitializeMemberstrait 的initialize_members会在genesis 阶段初始化成员要求存储中尚无成员否则断言AlreadyInitialized并自动排序frame/collective/src/lib.rs。genesis 配置GenesisConfig.members还校验了“不能包含重复账户”和“数量不能超过MaxMembers”frame/collective/src/lib.rs。三、Prime 成员与两种默认投票策略当投票期结束后仍存在**弃权票abstentions**时Prime 成员与DefaultVote策略共同决定这些弃权票如何被“补齐”。该机制由DefaultVotetrait 抽象frame/collective/src/lib.rsfn default_vote( prime_vote: Optionbool, yes_votes: MemberCount, no_votes: MemberCount, len: MemberCount, ) - bool;仓库内置两种实现策略行为源码位置PrimeDefaultVote直接以 Prime 的投票作为弃权票的默认票若未设置 Prime则默认按“反对”unwrap_or(false)处理frame/collective/src/lib.rsMoreThanMajorityThenPrimeDefaultVote先判断“赞成票是否超过全体过半yes_votes * 2 len”若过半则弃权默认投赞成否则退回 Prime 投票frame/collective/src/lib.rs节点运行时的理事会与技术委员会均采用PrimeDefaultVotebin/node/runtime/src/lib.rs。README 中“如果未达阈值且无 Prime则动议被直接丢弃而不执行”的语义正是PrimeDefaultVote在无 Prime 时返回false弃权计为反对的体现。四、动议Motion的完整生命周期提案 → 投票 → 关闭 → 执行README 描述了动议的核心流程下面结合源码逐步拆解核心逻辑集中在 frame/collective/src/lib.rs。4.1 提出proposeproposecall_index(2)要求发起人是成员参数为pub fn propose( origin: OriginForT, #[pallet::compact] threshold: MemberCount, proposal: BoxT as ConfigI::Proposal, #[pallet::compact] length_bound: u32, )threshold 2时不进入投票直接执行do_propose_execute动议以RawOrigin::Members(1, seats)的 Origin 被 dispatchthreshold 2时进入投票do_propose_proposed写入四类存储Proposals当前活动动议哈希的BoundedVecProposalOf哈希 → 具体调用ProposalCount全局计数器单调递增Voting哈希 →Votes { index, threshold, ayes, nays, end }frame/collective/src/lib.rs其中end 当前区块号 MotionDuration。同时校验动议编码长度 ≤length_bound否则WrongProposalLength动议权重 ≤MaxProposalWeight否则WrongProposalWeight哈希不能重复否则DuplicateProposal活动动议数不能超过MaxProposals否则TooManyProposals。测试用例limit_active_proposals验证了连续提出MaxProposals个动议后第MaxProposals 1个会被TooManyProposals拒绝frame/collective/src/tests.rs。4.2 投票vote成员通过votecall_index(3)投出赞成/反对pub fn vote( origin: OriginForT, proposal: T::Hash, #[pallet::compact] index: ProposalIndex, approve: bool, )do_vote内部frame/collective/src/lib.rs校验动议存在ProposalMissing且index匹配WrongIndex同一次动议中每位成员只保留一个有效票重复投同样的票报DuplicateVote改投则从对侧列表swap_remove移出再插入新侧返回“是否该成员在该动议上的首投”——首投免交易费Pays::No改投/重复投票收费Pays::Yes此行为被测试motions_all_first_vote_free_works覆盖frame/collective/src/tests.rs。4.3 关闭close与三种结局动议的关闭由closecall_index(6)完成任何签名账户都可以调用。其核心逻辑do_closeframe/collective/src/lib.rs分三种情况提前通过yes_votes threshold时立即关闭校验proposal_weight_bound与length_bound后执行提案Pays::Yes提前否决seats - no_votes threshold即使剩余所有成员都投赞成也无法达标时立即关闭并移除动议Pays::No豁免费用投票期结束后的结算block_number voting.end前调用会报TooEarly测试close_works验证了这一点见 frame/collective/src/tests.rs。此时取 Prime 的投票若 Prime 在 ayes 中则Some(true)调用T::DefaultVote::default_vote(prime_vote, yes_votes, no_votes, seats)计算弃权票的默认方向把弃权票数加到对应一侧abstentions seats - (yes_votes no_votes)重新计算approved yes_votes threshold通过则执行提案do_approve_proposal以RawOrigin::Members(yes_votes, seats)分发发Approved、Executed事件不通过则do_disapprove_proposal移除动议并发Disapproved事件。close还要求调用者提供proposal_weight_bound执行提案的权重上界与length_bound存储长度上界validate_and_get_proposal通过storage::read直接读取存储长度进行校验frame/collective/src/lib.rs。4.4 其他调用executecall_index(1)成员以MemberOrigin直接执行一个提案跳过投票disapprove_proposalcall_index(5)Root 专用无论动议当前处于什么状态都直接否决并移除ensure_root校验。五、存储结构与错误处理5.1 五块核心存储存储项类型说明ProposalsStorageValueBoundedVecHash, MaxProposals活动动议哈希列表受MaxProposals约束ProposalOfStorageMapHash, Proposal哈希 → 提案调用VotingStorageMapHash, Votes哈希 → 投票状态threshold / ayes / nays / endProposalCountStorageValueu32动议计数器只增不减MembersStorageValueVecAccountId当前成员按值排序存储PrimeStorageValueAccountId当前 Prime 成员定义见 frame/collective/src/lib.rs。5.2 错误枚举Error共 11 个变体frame/collective/src/lib.rsNotMember、DuplicateProposal、ProposalMissing、WrongIndex、DuplicateVote、AlreadyInitialized、TooEarly、TooManyProposals、WrongProposalWeight、WrongProposalLength、PrimeAccountNotMember。各错误的触发条件均已在前文对应流程中说明。5.3 事件Event——动议的可观察轨迹每次动议操作都会产生链上事件Proposed、Voted、Approved、Disapproved、Executed、MemberExecuted、Closedframe/collective/src/lib.rs。测试中对事件序列的断言如close_with_prime_works期望Proposed → Voted → Closed → Approved → Executedframe/collective/src/tests.rs展示了完整的状态机流转可用于索引器与治理 UI 的开发。六、Origin 组合器把集体意志授权给其他模块README 强调“通过两个专用 Origin 派发调用”而pallet-collective还导出了四个EnsureOrigin实现供其他 pallet 作为Config中的授权来源frame/collective/src/lib.rs组合器语义EnsureMemberAccountId, IOrigin 必须是单个成员返回该成员账户EnsureMembersAccountId, I, NOrigin 必须获得至少 N 位成员认可EnsureProportionMoreThanAccountId, I, N, D认可比例 N/DEnsureProportionAtLeastAccountId, I, N, D认可比例≥ N/D节点运行时大量使用这些组合器例如理事会3/4多数用于ExternalMajorityOriginbin/node/runtime/src/lib.rs1/2用于FastTrackOrigin2/3用于VetoOrigin等bin/node/runtime/src/lib.rs。这说明了 collective 在整条链治理栈中的“枢纽”地位选举产生成员成员通过动议形成 OriginOrigin 再驱动民主、国库等模块的执行。七、在运行时中接入 Collective参数配置实战参考节点运行时bin/node/runtime/src/lib.rs配置一个理事会实例需要完成三步。第一步声明实例与参数parameter_types! { pub const CouncilMotionDuration: BlockNumber 5 * DAYS; pub const CouncilMaxProposals: u32 100; pub const CouncilMaxMembers: u32 100; } type CouncilCollective pallet_collective::Instance1;第二步实现pallet_collective::Configimpl pallet_collective::ConfigCouncilCollective for Runtime { type RuntimeOrigin RuntimeOrigin; type Proposal RuntimeCall; // 提案类型运行时全部调用 type RuntimeEvent RuntimeEvent; type MotionDuration CouncilMotionDuration; // 投票期5 天 type MaxProposals CouncilMaxProposals; // 并行活动动议上限100 type MaxMembers CouncilMaxMembers; // 成员上限100用于权重估算 type DefaultVote pallet_collective::PrimeDefaultVote; type WeightInfo pallet_collective::weights::SubstrateWeightRuntime; type SetMembersOrigin EnsureRootSelf::AccountId; // 只有 Root 可设成员 type MaxProposalWeight MaxCollectivesProposalWeight; }第三步注册进construct_runtime!Council: pallet_collective::Instance1,各配置项的要点MotionDuration动议最短投票窗口任何成员都不得在窗口结束前强制结算除非已提前达标MaxProposals同时存在的活动动议数量上限超出报TooManyProposalsMaxMembers仅用于权重估算pallet 本身不在set_members/change_members_sorted中强制执行README 明确说明这一点测试与运行时也通过const_assert!(DesiredMembers::get() CouncilMaxMembers::get())保证选举人数不超过该上限bin/node/runtime/src/lib.rsSetMembersOrigin控制谁能直接改成员示例中为EnsureRootMaxProposalWeight可提出/执行提案的重量上限防止动议携带超重调用WeightInfo每个 extrinsic 的基准权重由 frame/collective/src/benchmarking.rs 生成注意 README 与代码注释均提示修改MaxMembers后需重新跑基准并更新权重set_members的权重复杂度为O(MP N)close的权重在四种关闭路径中取max再累加提案执行权重。若采用“选举产生成员”的间接模式还需把pallet_collective实例作为选举 pallet 的ChangeMembers/InitializeMembers例如type ChangeMembers Councilbin/node/runtime/src/lib.rs。八、运行测试与验证pallet-collective自带 1500 行单元测试frame/collective/src/tests.rs覆盖以下关键行为可作为理解与验证实现的入口initialize_members_sorts_members成员初始化后自动排序set_members_with_prime_works设置 Prime、校验PrimeAccountNotMemberclose_works投票期内提前close报TooEarly期后结算产生Closed Disapproved事件close_with_voting_prime_worksPrime 投了赞成时弃权票按 Prime 方向补齐并执行提案close_with_no_prime_but_majority_worksMoreThanMajorityThenPrimeDefaultVote下即使无 Prime 也可由过半赞成票推动通过removal_of_old_voters_votes_works成员变动后离任成员在投票列表中被剔除proposal_weight_limit_works(_on_approve)提案权重上界校验与“否决路径忽略权重校验”的行为limit_active_proposals活动动议数量上限校验。每个测试经由build_and_execute运行后还会调用do_try_state()做一致性校验try-runtime特性frame/collective/src/lib.rs包括Proposals/ProposalOf哈希一一对应、票数总和不超过MaxMembers、动议索引唯一、成员有序且不超过上限、Prime 必须是成员等不变量。迁移逻辑则维护在 frame/collective/src/migrations当前存储版本为 v4见STORAGE_VERSION StorageVersion::new(4)。九、设计要点小结成员管理双轨制Root 直设set_members与外部模块回调ChangeMembers并存注意同步一致性MaxMembers是软约束它服务于权重估算而非运行时强制治理上需由上层如选举 pallet 的上限断言兜底Prime 是弃权票的“方向盘”PrimeDefaultVote下 Prime 缺席则默认反对MoreThanMajorityThenPrimeDefaultVote下可先看整体多数再回落 Prime动议可提前结算只要“赞成已达标”或“反对已无法挽回”任何账户都可提前close无需等待MotionDuration结束首投免费用鼓励成员尽早表态改投则收取费用抑制反复横跳实例化复用同一 pallet 通过Instance1/2/3可在一条链上承载理事会、技术委员会、联盟治理等多个集体互不干扰。通过 frame/collective/README.md、frame/collective/src/lib.rs 与 bin/node/runtime/src/lib.rs 三者的对照阅读开发者可以完整掌握从“成员集合 → 动议投票 → Origin 授权 → 跨模块治理执行”的整条链路并将其复用到自定义 Substrate 链的治理设计中。赞分享区块链开发框架后端【免费下载链接】substrateSubstrate: The platform for blockchain innovators项目地址https://gitcode.com/gh_mirrors/su/substrate点击查看免费下载相关推荐Substrate Democracy Pallet 深度解析从提案入队到公投投票的链上治理机制Substrate Democracy Pallet 深度解析从提案入队到公投投票的链上治理机制 导读 Democracy Pallet 是 Substrat区块链开发框架后端Substrate 成员管理 Pallet 深度解析用 pallet-membership 管理 Collective 成员与 Prime MemberSubstrate 成员管理 Pallet 深度解析用 pallet membership 管理 Collective 成员与 Prime Member 导读区块链开发框架后端Apereo CAS 项目管理委员会PMC治理机制全解析成员结构、投票规则与提名流程Apereo CAS 项目管理委员会PMC治理机制全解析成员结构、投票规则与提名流程 Apereo CAS 作为一个由志愿者驱动的大型开源单点登录SSO后端认证鉴权单点登录创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
📝

华诺云谱内容团队

资深建站顾问 · 行业研究员

10年+企业数字化服务经验,专注智能建站、SEO优化与品牌营销,持续输出建站技巧、行业洞察与营销干货,已帮助5000+企业实现数字化增长。

你可能需要的服务

订阅华诺云谱资讯周报

每周一封,精选建站技巧、SEO与营销干货,直达邮箱。已有 8,000+ 企业主订阅,助你少走弯路。

↑