Substrate运行时获取验证人集合报错,需实现手续费分配至验证人
Substrate手续费分配给验证人:错误修正与实现
代码中的核心问题
- 泛型参数不匹配:代码里用了
session::Module::<T>::validators(),但当前定义的泛型参数是R,两者不对应。 - 缺少Session Pallet的约束:
where语句里没添加pallet_session::Config,导致无法调用Session模块的验证人查询方法。 - 未实现验证人分配逻辑:仅获取了验证人集合,但没完成手续费拆分、分配给每个验证人的核心逻辑。
修正后的完整实现
use frame_support::{traits::OnUnbalanced, pallet_prelude::*}; use pallet_balances::NegativeImbalance; use pallet_session; pub struct DealWithFees<R>(sp_std::marker::PhantomData<R>); impl<R> OnUnbalanced<NegativeImbalance<R>> for DealWithFees<R> where R: pallet_balances::Config + pallet_authorship::Config + pallet_session::Config, <R as pallet_session::Config>::ValidatorId: Into<<R as frame_system::Config>::AccountId>, { fn on_unbalanceds<B>(mut fees_then_tips: impl Iterator<Item = NegativeImbalance<R>>) { if let Some(fees) = fees_then_tips.next() { let total_fees = fees.peek(); let validators = pallet_session::Pallet::<R>::validators(); let validator_count = validators.len() as u128; if validator_count > 0 { // 计算每个验证人基础份额,处理余数避免精度丢失 let per_validator_amount = total_fees / validator_count; let mut remaining = total_fees % validator_count; // 遍历验证人完成分配 for validator in validators { let account_id = validator.into(); let mut amount = per_validator_amount; if remaining > 0 { amount += 1; remaining -= 1; } // 转换余额类型并完成转账 let imbalance = NegativeImbalance::<R>::new(amount).reverse(); <pallet_balances::Pallet<R>>::resolve_creating(&account_id, imbalance); } } // 小费部分保留原逻辑全部分配给出块作者 if let Some(tips) = fees_then_tips.next() { <pallet_authorship::ToAuthor<R> as OnUnbalanced<_>>::on_unbalanced(tips); } } } }
关键说明
- 泛型约束补充:新增
pallet_session::Config以获取验证人数据,同时确保验证人ID可转换为系统账户ID,满足转账要求。 - 分配逻辑优化:采用平均分配+余数补全的方式,保证手续费全部分配完毕,无精度损失。
- 余额处理规范:通过
reverse()将负余额转为正向余额,再用resolve_creating完成验证人账户的余额增加操作。
内容的提问来源于stack exchange,提问作者Muhammad Zaryab Rafique
相关产品推荐
相关产品推荐

