变更记录
- 2019 年 10 月 23 日:初始草案
- 2019 年 11 月 28 日:添加密钥轮换费用
背景
出于更安全的验证人密钥管理策略考虑(例如:链接),验证人共识密钥轮换功能已经被讨论和请求了很长时间。因此,我们建议采用一种主要在 Cosmos SDK 中实现的、最简单形式的验证人共识密钥轮换方案。 我们不需要对 Tendermint 中的共识逻辑做任何更新,因为 Tendermint 并不维护共识密钥与验证人操作员密钥之间的映射信息。这意味着,从 Tendermint 的视角看,验证人的一次共识密钥轮换只是将一个共识密钥替换为另一个。 另外需要注意的是,本 ADR 只包含最简单形式的共识密钥轮换,并未考虑多共识密钥的概念。多共识密钥的概念仍应作为 Tendermint 和 Cosmos SDK 的长期目标。决策
共识密钥轮换的伪流程
- 创建新的随机共识密钥。
- 创建并广播一笔带有
MsgRotateConsPubKey的交易,声明新的共识密钥现在通过验证人操作员密钥签名,与该验证人操作员绑定。 - 在链上密钥映射状态更新后,旧的共识密钥立即失去参与共识的能力。
- 开始使用新的共识密钥进行验证。
- 使用 HSM 和 KMS 的验证人应在
MsgRotateConsPubKey提交到区块链后的高度h之后,在 HSM 中更新共识密钥以使用新轮换的密钥。
考量
- 共识密钥映射信息的管理策略
- 在 kvstore 中存储每次密钥映射变更的历史记录。
- 状态机可以在最近一个解绑期内,为任意高度查询与给定验证人操作员对应的共识密钥。
- 对于早于解绑期的历史映射信息,状态机不再需要。
- 与 LCD 和 IBC 相关的密钥轮换成本
- 当频繁发生投票权重变更时,LCD 和 IBC 会承担流量和计算负担。
- 在当前 Tendermint 设计中,从 LCD 或 IBC 的视角看,共识密钥轮换会被视为投票权重变更。
- 因此,为了尽量减少不必要的频繁密钥轮换行为,我们限制了最近一个解绑期内的最大轮换次数,并引入了指数递增的轮换费用。
- 限制
- 为防止垃圾交易,验证人在任意一个解绑期内轮换其共识密钥的次数不能超过
MaxConsPubKeyRotations。 - 参数可以由治理决定,并存储在 genesis 文件中。
- 为防止垃圾交易,验证人在任意一个解绑期内轮换其共识密钥的次数不能超过
- 密钥轮换费用
- 验证人在轮换共识密钥时应支付
KeyRotationFee,其计算方式如下。 KeyRotationFee= (max(VotingPowerPercentage100, 1)InitialKeyRotationFee) * 2^(最近一个解绑期内ConsPubKeyRotationHistory中的轮换次数)
- 验证人在轮换共识密钥时应支付
- evidence 模块
- evidence 模块可以通过 slashing keeper 查询任意高度对应的共识密钥,从而判断给定高度应使用哪个共识密钥。
abci.ValidatorUpdate- Tendermint 已经具备通过 ABCI 通信(
ValidatorUpdate)变更共识密钥的能力。 - 通过将旧验证人的权重改为零,再新增一个新验证人并删除旧验证人,即可完成验证人共识密钥更新。
- 因此,我们预计甚至完全不需要修改 Tendermint 代码库就能实现该功能。
- Tendermint 已经具备通过 ABCI 通信(
staking模块中的新 genesis 参数MaxConsPubKeyRotations:验证人在最近一个解绑期内最多可执行的轮换次数。建议默认值为 10(第 11 次密钥轮换将被拒绝)。InitialKeyRotationFee:最近一个解绑期内尚未发生过密钥轮换时的初始密钥轮换费用。建议默认值为 1atom(最近一个解绑期内第一次密钥轮换收取 1atom 费用)。
工作流
- 验证人生成一个新的共识密钥对。
-
验证人使用其操作员密钥和新的 ConsPubKey 生成并签名一笔
MsgRotateConsPubKey交易。 -
handleMsgRotateConsPubKey获取MsgRotateConsPubKey,调用RotateConsPubKey并发出事件。 -
RotateConsPubKey- 检查
NewPubKey是否未在ValidatorsByConsAddr中重复出现。 - 通过遍历
ConsPubKeyRotationHistory,检查该验证人是否未超过参数MaxConsPubKeyRotations的限制。 - 检查签名账户余额是否足以支付
KeyRotationFee。 - 将
KeyRotationFee支付到社区资金池。 - 覆盖
validator.ConsPubKey中的NewPubKey。 - 删除旧的
ValidatorByConsAddr。 - 为
NewPubKey执行SetValidatorByConsAddr。 - 添加
ConsPubKeyRotationHistory以跟踪轮换记录。
- 检查
-
ApplyAndReturnValidatorSetUpdates检查是否存在满足ConsPubKeyRotationHistory.RotatedHeight == ctx.BlockHeight()的ConsPubKeyRotationHistory;如果存在,则生成 2 个ValidatorUpdate,一个用于移除旧验证人,另一个用于创建新验证人。 -
在
AllocateTokens的previousVotes迭代逻辑中,使用OldConsPubKey的previousVote与ConsPubKeyRotationHistory匹配,并替换用于代币分配的验证人。 -
将
ValidatorSigningInfo和ValidatorMissedBlockBitArray从OldConsPubKey迁移到NewConsPubKey。
- 注意:以上所有功能都应在
staking模块中实现。
状态
提议中后果
正面影响
- 验证人可以立即或定期轮换其共识密钥,从而获得更好的安全策略。
- 如果验证人丢弃旧的共识密钥,则能更好地抵御长程攻击。
负面影响
- Slash 模块需要更多计算,因为它需要为每个高度查找验证人对应的共识密钥。
- 频繁的密钥轮换会降低轻客户端二分查找的效率。
中性影响
参考
Changelog
- 2019 Oct 23: Initial draft
- 2019 Nov 28: Add key rotation fee
Context
Validator consensus key rotation feature has been discussed and requested for a long time, for the sake of safer validator key management policy (e.g. Link). So, we suggest one of the simplest form of validator consensus key rotation implementation mostly onto Cosmos SDK. We don’t need to make any update on consensus logic in Tendermint because Tendermint does not have any mapping information of consensus key and validator operator key, meaning that from Tendermint point of view, a consensus key rotation of a validator is simply a replacement of a consensus key to another. Also, it should be noted that this ADR includes only the simplest form of consensus key rotation without considering multiple consensus keys concept. Such multiple consensus keys concept shall remain a long term goal of Tendermint and Cosmos SDK.Decision
Pseudo procedure for consensus key rotation
- create new random consensus key.
- create and broadcast a transaction with a
MsgRotateConsPubKeythat states the new consensus key is now coupled with the validator operator with signature from the validator’s operator key. - old consensus key becomes unable to participate on consensus immediately after the update of key mapping state on-chain.
- start validating with new consensus key.
- validators using HSM and KMS should update the consensus key in HSM to use the new rotated key after the height
hwhenMsgRotateConsPubKeycommitted to the blockchain.
Considerations
- consensus key mapping information management strategy
- store history of each key mapping changes in the kvstore.
- the state machine can search corresponding consensus key paired with given validator operator for any arbitrary height in a recent unbonding period.
- the state machine does not need any historical mapping information which is past more than unbonding period.
- key rotation costs related to LCD and IBC
- LCD and IBC will have traffic/computation burden when there exists frequent power changes
- In current Tendermint design, consensus key rotations are seen as power changes from LCD or IBC perspective
- Therefore, to minimize unnecessary frequent key rotation behavior, we limited maximum number of rotation in recent unbonding period and also applied exponentially increasing rotation fee
- limits
- a validator cannot rotate its consensus key more than
MaxConsPubKeyRotationstime for any unbonding period, to prevent spam. - parameters can be decided by governance and stored in genesis file.
- a validator cannot rotate its consensus key more than
- key rotation fee
- a validator should pay
KeyRotationFeeto rotate the consensus key which is calculated as below KeyRotationFee= (max(VotingPowerPercentage100, 1)InitialKeyRotationFee) * 2^(number of rotations inConsPubKeyRotationHistoryin recent unbonding period)
- a validator should pay
- evidence module
- evidence module can search corresponding consensus key for any height from slashing keeper so that it can decide which consensus key is supposed to be used for given height.
- abci.ValidatorUpdate
- tendermint already has ability to change a consensus key by ABCI communication(
ValidatorUpdate). - validator consensus key update can be done via creating new + delete old by change the power to zero.
- therefore, we expect we even do not need to change tendermint codebase at all to implement this feature.
- tendermint already has ability to change a consensus key by ABCI communication(
- new genesis parameters in
stakingmoduleMaxConsPubKeyRotations: maximum number of rotation can be executed by a validator in recent unbonding period. default value 10 is suggested(11th key rotation will be rejected)InitialKeyRotationFee: the initial key rotation fee when no key rotation has happened in recent unbonding period. default value 1atom is suggested(1atom fee for the first key rotation in recent unbonding period)
Workflow
- The validator generates a new consensus keypair.
-
The validator generates and signs a
MsgRotateConsPubKeytx with their operator key and new ConsPubKey -
handleMsgRotateConsPubKeygetsMsgRotateConsPubKey, callsRotateConsPubKeywith emits event -
RotateConsPubKey- checks if
NewPubKeyis not duplicated onValidatorsByConsAddr - checks if the validator is does not exceed parameter
MaxConsPubKeyRotationsby iteratingConsPubKeyRotationHistory - checks if the signing account has enough balance to pay
KeyRotationFee - pays
KeyRotationFeeto community fund - overwrites
NewPubKeyinvalidator.ConsPubKey - deletes old
ValidatorByConsAddr SetValidatorByConsAddrforNewPubKey- Add
ConsPubKeyRotationHistoryfor tracking rotation
- checks if
-
ApplyAndReturnValidatorSetUpdateschecks if there isConsPubKeyRotationHistorywithConsPubKeyRotationHistory.RotatedHeight == ctx.BlockHeight()and if so, generates 2ValidatorUpdate, one for a remove validator and one for create new validator -
at
previousVotesIteration logic ofAllocateTokens,previousVoteusingOldConsPubKeymatch up withConsPubKeyRotationHistory, and replace validator for token allocation -
Migrate
ValidatorSigningInfoandValidatorMissedBlockBitArrayfromOldConsPubKeytoNewConsPubKey
- Note : All above features shall be implemented in
stakingmodule.
Status
ProposedConsequences
Positive
- Validators can immediately or periodically rotate their consensus key to have better security policy
- improved security against Long-Range attacks given a validator throws away the old consensus key(s)
Negative
- Slash module needs more computation because it needs to lookup corresponding consensus key of validators for each height
- frequent key rotations will make light client bisection less efficient