62 个版本 (35 个重大更改)

37.0.0 2024年7月18日
36.0.0 2024年7月12日
35.0.0 2024年6月24日
34.0.0 2024年5月24日
2.0.0-alpha.52020年3月24日

#1454 in 神奇豆子

Download history 2158/week @ 2024-04-22 1996/week @ 2024-04-29 1916/week @ 2024-05-06 1706/week @ 2024-05-13 2162/week @ 2024-05-20 2068/week @ 2024-05-27 1969/week @ 2024-06-03 1576/week @ 2024-06-10 1393/week @ 2024-06-17 2491/week @ 2024-06-24 1159/week @ 2024-07-01 1529/week @ 2024-07-08 2626/week @ 2024-07-15 1465/week @ 2024-07-22 1890/week @ 2024-07-29 1652/week @ 2024-08-05

7,706 每月下载量
用于 89 个包 (17 个直接)

Apache-2.0

3MB
54K SLoC

质押模块

质押模块用于管理网络维护者质押的资金。

概述

质押模块是通过选择那些自愿将资金存入的维护者(在某些环境中被称为“权威”而在其他环境中被称为“验证者”)来管理网络维护者质押的资金的方式。存入的资金在正常运营下将获得奖励,但如果质押的维护者被发现未能正确履行其职责,这些资金将面临被“削减”(没收)的风险。

术语

  • 质押:将资金锁定一段时间,使其面临被削减(损失)的风险,以成为网络的奖励维护者。
  • 验证:运行一个节点以积极维护网络的过程,无论是通过产生区块还是保证链的最终性。
  • 提名:将质押资金投入一个或多个验证者背后,以分享他们所获得的任何奖励和惩罚。
  • 质押账户:持有所有者用于质押资金的账户。
  • 控制器账户(正在被弃用):控制所有者质押资金的账户。
  • 时代:一系列会话的(整体)数字,这是验证者集(以及每个验证者的活跃提名者集)重新计算和奖励发放的周期。
  • 削减:通过减少资金对质押者的惩罚。

目标

Substrate NPoS中的质押系统旨在实现以下可能性:

  • 控制冷钱包的资金进行质押。
  • 在不中断实体角色的前提下,提取部分资金或存入更多资金。
  • 以最小的开销在角色(提名者、验证者、空闲)之间切换。

场景

质押

几乎任何与质押模块的交互都需要一个绑定(也称为成为质押者)的过程。要成为绑定的,一个名为质押账户的资金持有账户,该账户持有部分或全部资金,这些资金在质押过程中被冻结。控制器账户,现在由该组件分配给质押账户,负责发出如何使用资金的指示。

账户可以通过bond调用成为一个绑定质押账户。

质押账户可以使用set_controller调用将其关联的控制器账户更新回其质押账户。

注意:由于代理账户的兴起,控制器账户正在被弃用,因此现在无法为质押账户的控制器设置唯一的地址。

任何质押账户对可以处于三种可能的角色之一:Validator(验证者)、Nominator(提名者)和Idle(空闲)(定义在StakerStatus)。有三个相应的指令用于在角色之间切换,分别是:validate(验证)、nominate(提名)和chill(空闲)。

验证

验证者的作用是验证区块或确保其最终性,维护网络的真确性。验证者应避免任何形式的恶意行为和离线。声称有兴趣成为验证者的绑定账户不会立即被选为验证者。相反,它们被宣布为候选人,并可能在下一个时代被选为验证者。选举结果由提名者和他们的投票决定。

账户可以通过validate调用成为一个验证者候选人。

提名

提名者不会直接参与维护网络,相反,它会投票选择一组将被选中的验证者。一旦账户表达了对提名的兴趣,它将在下一轮选举中生效。提名者存入的金额表明其投票的权重。验证者获得的奖励和任何惩罚都会在验证者和其提名者之间共享。这一规则激励提名者尽可能地不为不当行为/离线验证者投票,因为如果投票不佳,提名者也会损失资金。

账户可以通过nominate调用成为提名者。

奖励和惩罚

奖励和惩罚程序是存证模块的核心,旨在鼓励合法行为,同时对任何不当行为或不可用行为进行惩罚。

$HISTORY_DEPTH之前,每个时代的奖励必须通过使用payout_stakers调用进行领取,否则就会变得过于陈旧。当验证者有超过Config::MaxExposurePageSize提名者时,提名者会被分成多个页面,每次调用payout_stakers会按照顺序和升序方式向一个页面的提名者支付奖励。任何账户也可以调用payout_stakers_by_page来明确支付给定页面的奖励。很明显,这意味着每次调用只奖励Config::MaxExposurePageSize的提名者。这是为了限制每个提名者账户修改存储的I/O成本。

惩罚可以在任何时间发生,一旦报告不当行为。一旦确定惩罚,就会从验证者和所有为该验证者投票的提名者的余额中扣除一定数额(从被惩罚实体的存档账户中扣除)。

惩罚逻辑在slashing模块的文档中有更详细的描述。

与惩罚类似,奖励也会在验证者和其相关提名者之间共享。然而,奖励资金并不总是转移到存档账户,并且可以进行配置。有关详细信息,请参阅奖励计算

冷静

最后,上述任何角色都可以选择暂时退后,冷静一下。这意味着如果他们是提名者,将不再被视为投票者;如果他们是验证者,将不再成为下一轮选举的候选人。

账户可以通过chill调用退后。

会话管理

该模块实现了SessionManager特质。这是查询新验证者集的唯一API,并允许一旦这些验证者集的时代结束,就可以对它们进行奖励。

接口

可调用的函数

存证模块的可调用函数使实体能够接受和改变其角色,并附带一些辅助函数来获取/设置模块的元数据。

公共函数

存证模块包含许多公共存储项和(不可变)函数。

用法

示例:通过id奖励验证者

use pallet_staking::{self as staking};

#[frame_support::pallet]
pub mod pallet {
    use super::*;
    use frame_support::pallet_prelude::*;
    use frame_system::pallet_prelude::*;

    #[pallet::pallet]
    pub struct Pallet<T>(_);

    #[pallet::config]
    pub trait Config: frame_system::Config + staking::Config {}

    #[pallet::call]
    impl<T: Config> Pallet<T> {
        /// Reward a validator.
        #[pallet::weight(0)]
        pub fn reward_myself(origin: OriginFor<T>) -> DispatchResult {
            let reported = ensure_signed(origin)?;
            <staking::Pallet<T>>::reward_by_ids(vec![(reported, 10)]);
            Ok(())
        }
    }
}

实现细节

时代支付

收益分配使用在T::RewardCurve中定义的年度通货膨胀曲线来计算,如下所示

staker_payout = yearly_inflation(npos_token_staked / total_tokens) * total_tokens / era_per_year

此收益分配用于在下节中定义的收益分配给质押者

remaining_payout = max_yearly_inflation * total_tokens / era_per_year - staker_payout

剩余的收益将被发送到可配置的端点T::RewardRemainder

收益计算

验证者和提名者在每个时代结束时获得奖励。一个时代的总收益通过时代持续时间和质押率(提名者和验证者质押的总代币数量除以总代币供应量)来计算。这旨在激励达到一个定义的质押率。完整的规范可以在这里找到。

总收益根据每个时代内获得的积分数量在验证者和他们的提名者之间分配。积分通过reward_by_idsreward_by_indices添加到验证者。

Module实现了pallet_authorship::EventHandler以向区块生产者和引用的叔父区块生产者添加奖励积分。

验证者和其提名者的收益分配如下

验证者可以声明一个名为commission的金额,该金额不与提名者共享,并通过其ValidatorPrefs在每个收益分配时扣除。此值从支付给验证者和其提名者的总收益中扣除。剩余部分按比例分配给验证者和所有提名了该验证者的提名者,比例是这些提名者在该验证者背后质押的价值(即,通过Exposure中的ownothers除以total)。

所有获得奖励的实体都有通过Payee存储项(参见set_payee)选择其奖励目的地的选项,可以是以下之一

  • 控制账户(显然)不会增加质押价值。
  • Stash账户,不会增加质押价值。
  • Stash账户,也会增加质押价值。

额外的资金管理操作

已放入Stash的资金可以成为以下操作的靶子

控制器账户可以使用unbond调用释放部分(或全部)的资金。请注意,资金不会立即可用。相反,必须经过由BondingDuration(以时代数量表示)表示的持续时间,资金才能实际取出。一旦BondingDuration结束,就可以使用withdraw_unbonded调用实际提取资金。

请注意,通过unbond预定在将来解锁的资金块数量是有限制的。如果达到此最大值(MAX_UNLOCKING_CHUNKS),则已质押账户必须首先等待成功调用withdraw_unbonded以删除一些块。

选举算法

当前的选举算法基于Phragmén实现。参考实现可以在这里找到。

选举算法除了选举具有最大质押价值和投票的验证者外,还试图以平等的方式将提名者投票分配给候选人。为此,可以应用一个可选的后处理,该处理迭代地规范化提名者的质押价值,直到特定提名者投票之间的总差异小于一个阈值。

创世配置

质押模块依赖于GenesisConfig。该GenesisConfig是可选的,允许设置一些初始质押者。

  • Balances:用于管理质押的价值。
  • Session:用于管理会话。此外,在每个时代结束时,新验证者的列表存储在会话模块的Validators中。

许可:Apache-2.0

依赖项

~19–34MB
~574K SLoC