Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(WIP) : rotate operator key #15494

Closed
wants to merge 54 commits into from
Closed
Show file tree
Hide file tree
Changes from 13 commits
Commits
Show all changes
54 commits
Select commit Hold shift + click to select a range
8f6299f
proto
atheeshp Mar 14, 2023
5f978d8
make proto-gen
atheeshp Mar 14, 2023
a468a05
proto
atheeshp Mar 15, 2023
e2161b5
proto-gen
atheeshp Mar 15, 2023
8dfd0bb
proto
atheeshp Mar 16, 2023
7ec7cac
proto-gen
atheeshp Mar 16, 2023
8fed09a
WIP: operator key
atheeshp Mar 16, 2023
cff75c6
mocks
atheeshp Mar 16, 2023
bcda6c4
Merge branch 'main' of github.com:cosmos/cosmos-sdk into ap/rotate_op…
atheeshp Mar 17, 2023
eb47ea3
Merge branch 'main' of github.com:cosmos/cosmos-sdk into ap/rotate_op…
atheeshp Mar 18, 2023
85ab4ad
proto
atheeshp Mar 18, 2023
ed7e3ed
proto-gen
atheeshp Mar 18, 2023
239a358
set waiting period for operator key rotation
atheeshp Mar 18, 2023
9cf2bda
add delegations by validator index
atheeshp Apr 4, 2023
445b722
refactor: add delegations by validator index
atheeshp Apr 5, 2023
9b3c8b4
Merge branch 'main' of github.com:cosmos/cosmos-sdk into ap/delegatio…
atheeshp Apr 5, 2023
cc1c2ce
nits
atheeshp Apr 5, 2023
71aabc2
update validator delegations query with index
atheeshp Apr 7, 2023
b99b5e8
remove unnecessory tests
atheeshp Apr 7, 2023
dc60199
Merge branch 'main' of github.com:cosmos/cosmos-sdk into ap/delegatio…
atheeshp Apr 7, 2023
d6a4a0c
fix tests
atheeshp Apr 7, 2023
76bc044
remove unnecessary test
atheeshp Apr 7, 2023
6656c62
remove test code
atheeshp Apr 7, 2023
faa45dc
refactor
atheeshp Apr 7, 2023
f96a4b3
Merge branch 'main' of github.com:cosmos/cosmos-sdk into ap/delegatio…
atheeshp Apr 11, 2023
d3f0412
review changes
atheeshp Apr 11, 2023
213ea9a
Merge branch 'main' of github.com:cosmos/cosmos-sdk into ap/delegatio…
atheeshp Apr 12, 2023
58aa3ba
review changes
atheeshp Apr 12, 2023
b03ad16
Merge branch 'main' of github.com:cosmos/cosmos-sdk into ap/delegatio…
atheeshp Apr 12, 2023
4a1ad7f
register migration
atheeshp Apr 12, 2023
64349dd
review changes
atheeshp Apr 13, 2023
7062b56
Merge branch 'main' of github.com:cosmos/cosmos-sdk into ap/delegatio…
atheeshp Apr 14, 2023
697ee7b
keys
atheeshp Apr 14, 2023
a04740a
Merge branch 'main' of github.com:cosmos/cosmos-sdk into ap/delegatio…
atheeshp Apr 17, 2023
07ea2e5
review changes
atheeshp Apr 17, 2023
d07bc41
Merge branch 'main' of github.com:cosmos/cosmos-sdk into ap/delegatio…
atheeshp Apr 18, 2023
8308684
review changes
atheeshp Apr 18, 2023
d655db3
review changes
atheeshp Apr 18, 2023
727e273
review changes
atheeshp Apr 18, 2023
d5f5fea
fix lint
atheeshp Apr 18, 2023
9ada08c
fix lint
atheeshp Apr 18, 2023
c058798
error handling
atheeshp Apr 18, 2023
cc2ee23
Merge branch 'main' into ap/delegations-by-validator
atheeshp Apr 18, 2023
0a70b08
Merge branch 'main' into ap/delegations-by-validator
atheeshp Apr 20, 2023
c3a2c41
review changes
atheeshp Apr 20, 2023
45a84e9
Merge branch 'ap/delegations-by-validator' of github.com:cosmos/cosmo…
atheeshp Apr 20, 2023
be5d46e
Merge branch 'ap/delegations-by-validator' of github.com:cosmos/cosmo…
atheeshp Apr 20, 2023
fed64cc
add key updations
atheeshp Apr 20, 2023
30aa0f1
Merge branch 'main' of github.com:cosmos/cosmos-sdk into ap/rotate_op…
atheeshp Apr 21, 2023
2596e00
updations
atheeshp Apr 21, 2023
066e672
proto-gen
atheeshp Apr 21, 2023
d316acf
fix
atheeshp Apr 25, 2023
43ea5dd
Merge branch 'main' of github.com:cosmos/cosmos-sdk into ap/rotate_op…
atheeshp Apr 25, 2023
590d0ca
Merge branch 'ap/rotate_oper_key' of github.com:cosmos/cosmos-sdk int…
atheeshp Apr 25, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1,647 changes: 1,443 additions & 204 deletions api/cosmos/staking/v1beta1/staking.pulsar.go

Large diffs are not rendered by default.

1,148 changes: 1,057 additions & 91 deletions api/cosmos/staking/v1beta1/tx.pulsar.go

Large diffs are not rendered by default.

45 changes: 45 additions & 0 deletions api/cosmos/staking/v1beta1/tx_grpc.pb.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

27 changes: 27 additions & 0 deletions proto/cosmos/staking/v1beta1/staking.proto
Original file line number Diff line number Diff line change
Expand Up @@ -320,6 +320,12 @@ message Params {
(amino.dont_omitempty) = true,
(cosmos_proto.scalar) = "cosmos.Dec"
];

// key_rotation_fee is fee to be spent when rotating validator's keys(either pubkey or operator key)
cosmos.base.v1beta1.Coin key_rotation_fee = 7 [
(gogoproto.nullable) = false,
(amino.dont_omitempty) = true
];
}

// DelegationResponse is equivalent to Delegation except that it contains a
Expand Down Expand Up @@ -392,3 +398,24 @@ enum Infraction {
message ValidatorUpdates {
repeated tendermint.abci.ValidatorUpdate updates = 1 [(gogoproto.nullable) = false, (amino.dont_omitempty) = true];
}

// OperatorKeyRotationRecord contains a validator's operator key rotation history.
message OperatorKeyRotationRecord {
option (gogoproto.equal) = false;
option (gogoproto.goproto_getters) = false;

// operator_address defines the address of the validator's operator; bech encoded in JSON.
string operator_address = 1 ;

// old_operator_address defines the previous address of the validator's operator; bech encoded in JSON.
string old_operator_address = 2 ;

// height defines the block height at which the rotation event occured.
uint64 height = 3;
}

// RotatedOperatorAddresses contains the array of addresses which rotated their keys
// This is to block the validator's next rotation till unbonding period.
message RotatedOperatorAddresses {
repeated string addresses = 1 [(cosmos_proto.scalar) = "cosmos.AddressString"];
}
26 changes: 26 additions & 0 deletions proto/cosmos/staking/v1beta1/tx.proto
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,12 @@ service Msg {
// parameters.
// Since: cosmos-sdk 0.47
rpc UpdateParams(MsgUpdateParams) returns (MsgUpdateParamsResponse);

// RotateOperatorKey defines an operation for rotating the operator key
// of a validator.
//
// Since: cosmos-sdk 0.48
rpc RotateOperatorKey(MsgRotateOperatorKey) returns (MsgRotateOperatorKeyResponse);
}

// MsgCreateValidator defines a SDK message for creating a new validator.
Expand Down Expand Up @@ -204,3 +210,23 @@ message MsgUpdateParams {
//
// Since: cosmos-sdk 0.47
message MsgUpdateParamsResponse {};

// MsgRotateOperatorKey is the Msg/RotateOperatorKey request type.
//
// Since: cosmos-sdk 0.48
message MsgRotateOperatorKey {
option (cosmos.msg.v1.signer) = "validator_address";
option (amino.name) = "cosmos-sdk/MsgRotateOperatorKey";

option (gogoproto.goproto_getters) = false;
option (gogoproto.equal) = false;

string validator_address = 2 [(cosmos_proto.scalar) = "cosmos.AddressString"];
string new_operator_key = 3;
}

// MsgRotateOperatorKeyResponse defines the response structure for executing a
// MsgRotateOperatorKey message.
//
// Since: cosmos-sdk 0.48
message MsgRotateOperatorKeyResponse {}
46 changes: 46 additions & 0 deletions x/staking/keeper/msg_server.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import (
"github.com/cosmos/cosmos-sdk/telemetry"
sdk "github.com/cosmos/cosmos-sdk/types"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
distrtypes "github.com/cosmos/cosmos-sdk/x/distribution/types"
govtypes "github.com/cosmos/cosmos-sdk/x/gov/types"
"github.com/cosmos/cosmos-sdk/x/staking/types"
)
Expand Down Expand Up @@ -489,3 +490,48 @@ func (k msgServer) UpdateParams(goCtx context.Context, msg *types.MsgUpdateParam

return &types.MsgUpdateParamsResponse{}, nil
}

func (k msgServer) RotateOperatorKey(goCtx context.Context, req *types.MsgRotateOperatorKey) (*types.MsgRotateOperatorKeyResponse, error) {
ctx := sdk.UnwrapSDKContext(goCtx)

curValAddr, err := sdk.ValAddressFromBech32(req.ValidatorAddress)
if err != nil {
return &types.MsgRotateOperatorKeyResponse{}, err
}

validator, found := k.Keeper.GetValidator(ctx, curValAddr)
if found {
return nil, types.ErrOperatorKeyAlreadyUsed
}

// checks if NewPubKey is not duplicated on ValidatorsByConsAddr
newValAddr, err := sdk.ValAddressFromBech32(req.NewOperatorKey)
if err != nil {
return &types.MsgRotateOperatorKeyResponse{}, err
}

_, found = k.Keeper.GetValidator(ctx, newValAddr)
if found {
return nil, types.ErrOperatorKeyAlreadyUsed
}

// checks if the signing account has enough balance to pay KeyRotationFee
// pays KeyRotationFee to community fund
rotationFee := k.OperatorKeyRotationFee(ctx)
sender := sdk.AccAddress(curValAddr)

err = k.Keeper.bankKeeper.SendCoinsFromAccountToModule(ctx, sender, distrtypes.ModuleName, sdk.NewCoins(rotationFee))
if err != nil {
return nil, err
}

validator.OperatorAddress = req.NewOperatorKey
k.SetValidator(ctx, validator)

// Add OperatorKeyRotationRecord for tracking rotations
if err := k.SetOperatorKeyRotationRecord(ctx, curValAddr, newValAddr, ctx.BlockHeight()); err != nil {
return &types.MsgRotateOperatorKeyResponse{}, err
}

return &types.MsgRotateOperatorKeyResponse{}, nil
}
117 changes: 117 additions & 0 deletions x/staking/keeper/operator_key.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
package keeper

import (
"time"

storetypes "cosmossdk.io/store/types"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/x/staking/types"
)

func (k Keeper) GetValidatorOperatorKeyRotationsHistory(ctx sdk.Context,
valAddr sdk.ValAddress) []types.OperatorKeyRotationRecord {

var historyObjs []types.OperatorKeyRotationRecord
store := ctx.KVStore(k.storeKey)

iterator := storetypes.KVStorePrefixIterator(store,
append([]byte(types.ValidatorOperatorKeyRotationRecordKey), valAddr...))
defer iterator.Close()

for ; iterator.Valid(); iterator.Next() {
var history types.OperatorKeyRotationRecord

k.cdc.MustUnmarshal(iterator.Value(), &history)
historyObjs = append(historyObjs, history)
}
return historyObjs
}

func (k Keeper) SetOperatorKeyRotationRecord(ctx sdk.Context, curValAddr, newValAddr sdk.ValAddress, height int64) error {
historyObj := types.OperatorKeyRotationRecord{
OperatorAddress: newValAddr.String(),
OldOperatorAddress: curValAddr.String(),
Height: uint64(ctx.BlockHeight()),
}

store := ctx.KVStore(k.storeKey)
key := types.GetOperKeyRotationHistoryKey(newValAddr, uint64(height))
bz, err := k.cdc.Marshal(&historyObj)

if err != nil {
return err
}

store.Set(key, bz)
k.SetVORQueue(ctx, ctx.BlockTime(), newValAddr)
k.SetVORIndex(ctx, newValAddr)

return nil
}

func (k Keeper) GetVORQueue(ctx sdk.Context, ts time.Time) types.RotatedOperatorAddresses {
var valAddrs types.RotatedOperatorAddresses
store := ctx.KVStore(k.storeKey)
key := types.GetOperatorRotationTimeKey(ts)
bz := store.Get(key)
if bz == nil {
return valAddrs
}
k.cdc.MustUnmarshal(bz, &valAddrs)
return valAddrs
}

func (k Keeper) SetVORQueue(ctx sdk.Context, ts time.Time, valAddr sdk.ValAddress) {
operKeys := k.GetVORQueue(ctx, ts)
operKeys.Addresses = append(operKeys.Addresses, valAddr.String())
key := types.GetOperatorRotationTimeKey(ts)
store := ctx.KVStore(k.storeKey)
bz := k.cdc.MustMarshal(&operKeys)
store.Set(key, bz)
}

func (k Keeper) SetVORIndex(ctx sdk.Context, valAddr sdk.ValAddress) {
store := ctx.KVStore(k.storeKey)
key := types.GetVORIndexKey(valAddr)
store.Set(key, []byte{})
}

func (k Keeper) GetVORIndex(ctx sdk.Context, valAddr sdk.ValAddress) bool {
store := ctx.KVStore(k.storeKey)
key := types.GetVORIndexKey(valAddr)
bz := store.Get(key)
return bz != nil
}

func (k Keeper) UpdateAllMaturedVORRotatedKeys(ctx sdk.Context, maturedTime time.Time) {
maturedRotatedValAddrs := k.GetAllMaturedRotatedKeys(ctx, maturedTime)
for _, valAddrStr := range maturedRotatedValAddrs {
valAddr, err := sdk.ValAddressFromBech32(valAddrStr)
if err != nil {
panic(err)

Check warning

Code scanning / CodeQL

Panic in BeginBock or EndBlock consensus methods

Possible panics in BeginBock- or EndBlock-related consensus methods could cause a chain halt
}

k.deleteVORIndexKey(ctx, valAddr)
}
}

func (k Keeper) GetAllMaturedRotatedKeys(ctx sdk.Context, matureTime time.Time) []string {
store := ctx.KVStore(k.storeKey)
var ValAddresses []string
prefixIterator := storetypes.KVStorePrefixIterator(store, storetypes.InclusiveEndBytes(types.GetOperatorRotationTimeKey(matureTime)))

for ; prefixIterator.Valid(); prefixIterator.Next() {
var operKey types.RotatedOperatorAddresses
k.cdc.MustUnmarshal(prefixIterator.Value(), &operKey)
ValAddresses = append(ValAddresses, operKey.Addresses...)
store.Delete(prefixIterator.Key())
}

return ValAddresses
}

func (k Keeper) deleteVORIndexKey(ctx sdk.Context, valAddr sdk.ValAddress) {
store := ctx.KVStore(k.storeKey)
key := types.GetVORIndexKey(valAddr)
store.Delete(key)
}
10 changes: 10 additions & 0 deletions x/staking/keeper/params.go
Original file line number Diff line number Diff line change
Expand Up @@ -76,3 +76,13 @@ func (k Keeper) GetParams(ctx sdk.Context) (params types.Params) {
k.cdc.MustUnmarshal(bz, &params)
return params
}

// // MaxOperatorKeyRotations - Maximum operator key rotations
// func (k Keeper) MaxOperatorKeyRotations(ctx sdk.Context) (res uint64) {
// return k.GetParams(ctx).MaxOperatorKeyRotations
// }

// OperatorKeyRotationFee - Fee to be paid for rotating a key
func (k Keeper) OperatorKeyRotationFee(ctx sdk.Context) sdk.Coin {
return k.GetParams(ctx).KeyRotationFee
}
2 changes: 2 additions & 0 deletions x/staking/keeper/val_state_change.go
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,8 @@ func (k Keeper) BlockValidatorUpdates(ctx sdk.Context) []abci.ValidatorUpdate {
)
}

k.UpdateAllMaturedVORRotatedKeys(ctx, ctx.BlockHeader().Time)

return validatorUpdates
}

Expand Down
14 changes: 14 additions & 0 deletions x/staking/testutil/expected_keepers_mocks.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions x/staking/types/errors.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,4 +50,6 @@ var (
ErrCommissionLTMinRate = errors.Register(ModuleName, 40, "commission cannot be less than min rate")
ErrUnbondingNotFound = errors.Register(ModuleName, 41, "unbonding operation not found")
ErrUnbondingOnHoldRefCountNegative = errors.Register(ModuleName, 42, "cannot un-hold unbonding operation that is not on hold")
ErrOperatorKeyAlreadyUsed = errors.Register(ModuleName, 43, "operator key is already used for a validator")
ErrMaxOperatorKeyRotationsReached = errors.Register(ModuleName, 44, "exceeding maximum consensus pubkey rotations")
)
Loading