github.com/fibonacci-chain/fbc@v0.0.0-20231124064014-c7636198c1e9/libs/cosmos-sdk/docs/architecture/adr-016-validator-consensus-key-rotation.md (about)

     1  # ADR 016: Validator Consensus Key Rotation
     2  
     3  ## Changelog
     4  
     5  - 2019 Oct 23: Initial draft
     6  - 2019 Nov 28: Add key rotation fee
     7  
     8  ## Context
     9  
    10  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. https://github.com/tendermint/tendermint/issues/1136). So, we suggest one of the simplest form of validator consensus key rotation implementation mostly onto Cosmos-SDK. 
    11  
    12  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.
    13  
    14  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.
    15  
    16  ## Decision
    17  
    18  ### Pseudo procedure for consensus key rotation
    19  
    20  - create new random consensus key.
    21  - create and broadcast a transaction with a `MsgRotateConsPubKey` that states the new consensus key is now coupled with the validator operator with signature from the validator's operator key.
    22  - old consensus key becomes unable to participate on consensus immediately after the update of key mapping state on-chain.
    23  - start validating with new consensus key.
    24  - validators using HSM and KMS should update the consensus key in HSM to use the new rotated key after the height `h` when `MsgRotateConsPubKey` committed to the blockchain.
    25  
    26  
    27  ### Considerations
    28  
    29  - consensus key mapping information management strategy
    30      - store history of each key mapping changes in the kvstore.
    31      - the state machine can search corresponding consensus key paired with given validator operator for any arbitrary height in a recent unbonding period.
    32      - the state machine does not need any historical mapping information which is past more than unbonding period.
    33  - key rotation costs related to LCD and IBC
    34      - LCD and IBC will have traffic/computation burden when there exists frequent power changes
    35      - In current Tendermint design, consensus key rotations are seen as power changes from LCD or IBC perspective
    36      - 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 
    37  - limits
    38      - a validator cannot rotate its consensus key more than `MaxConsPubKeyRotations` time for any unbonding period, to prevent spam.
    39      - parameters can be decided by governance and stored in genesis file.
    40  - key rotation fee
    41      - a validator should pay `KeyRotationFee` to rotate the consensus key which is calculated as below
    42      - `KeyRotationFee` = (max(`VotingPowerPercentage` * 100, 1) * `InitialKeyRotationFee`) * 2^(number of rotations in `ConsPubKeyRotationHistory` in recent unbonding period)
    43  - evidence module
    44      - 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.
    45  - abci.ValidatorUpdate
    46      - tendermint already has ability to change a consensus key by ABCI communication(`ValidatorUpdate`).
    47      - validator consensus key update can be done via creating new + delete old by change the power to zero.
    48      - therefore, we expect we even do not need to change tendermint codebase at all to implement this feature.
    49  - new genesis parameters in `staking` module
    50      - `MaxConsPubKeyRotations` : 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)
    51      - `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)
    52  
    53  
    54  ### Workflow
    55  
    56  1. The validator generates a new consensus keypair.
    57  2. The validator generates and signs a `MsgRotateConsPubKey` tx with their operator key and new ConsPubKey
    58  
    59      ```go
    60      type MsgRotateConsPubKey struct {
    61          ValidatorAddress  sdk.ValAddress
    62          NewPubKey         crypto.PubKey
    63      }
    64      ```
    65  
    66  3. `handleMsgRotateConsPubKey` gets `MsgRotateConsPubKey`, calls `RotateConsPubKey` with emits event
    67  4. `RotateConsPubKey` 
    68      - checks if `NewPubKey` is not duplicated on `ValidatorsByConsAddr`
    69      - checks if the validator is does not exceed parameter `MaxConsPubKeyRotations` by iterating `ConsPubKeyRotationHistory`
    70      - checks if the signing account has enough balance to pay `KeyRotationFee`
    71      - pays `KeyRotationFee` to community fund
    72      - overwrites `NewPubKey` in `validator.ConsPubKey`
    73      - deletes old `ValidatorByConsAddr`
    74      - `SetValidatorByConsAddr` for `NewPubKey`
    75      - Add `ConsPubKeyRotationHistory` for tracking rotation
    76  
    77      ```go
    78      type ConsPubKeyRotationHistory struct {
    79          OperatorAddress         sdk.ValAddress
    80          OldConsPubKey           crypto.PubKey
    81          NewConsPubKey           crypto.PubKey
    82          RotatedHeight           int64
    83      }
    84      ```
    85  
    86  5. `ApplyAndReturnValidatorSetUpdates` checks if there is `ConsPubKeyRotationHistory` with `ConsPubKeyRotationHistory.RotatedHeight == ctx.BlockHeight()` and if so, generates 2 `ValidatorUpdate` , one for a remove validator and one for create new validator 
    87  
    88      ```go
    89      abci.ValidatorUpdate{
    90          PubKey: tmtypes.TM2PB.PubKey(OldConsPubKey),
    91          Power:  0,
    92      }
    93  
    94      abci.ValidatorUpdate{
    95          PubKey: tmtypes.TM2PB.PubKey(NewConsPubKey),
    96          Power:  v.ConsensusPower(),
    97      }
    98      ```
    99  
   100  6. at `previousVotes` Iteration logic of `AllocateTokens`,  `previousVote` using `OldConsPubKey` match up with `ConsPubKeyRotationHistory`, and replace validator for token allocation
   101  7. Migrate `ValidatorSigningInfo` and `ValidatorMissedBlockBitArray` from `OldConsPubKey` to `NewConsPubKey`
   102  - Note : All above features shall be implemented in `staking` module.
   103  
   104  ## Status
   105  
   106  Proposed
   107  
   108  ## Consequences
   109  
   110  ### Positive
   111  
   112  - Validators can immediately or periodically rotate their consensus key to have better security policy
   113  - improved security against Long-Range attacks (https://nearprotocol.com/blog/long-range-attacks-and-a-new-fork-choice-rule) given a validator throws away the old consensus key(s)
   114  
   115  ### Negative
   116  
   117  - Slash module needs more computation because it needs to lookup corresponding consensus key of validators for each height
   118  - frequent key rotations will make light client bisection less efficient
   119  
   120  ### Neutral
   121  
   122  ## References
   123  
   124  - on tendermint repo : https://github.com/tendermint/tendermint/issues/1136
   125  - on cosmos-sdk repo : https://github.com/cosmos/cosmos-sdk/issues/5231
   126  - about multiple consensus keys : https://github.com/tendermint/tendermint/issues/1758#issuecomment-545291698