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

change val's consensus pubkey #3312

Open
wants to merge 15 commits into
base: dev
Choose a base branch
from
4 changes: 4 additions & 0 deletions app/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -810,6 +810,10 @@ func (app *OKExChainApp) InitUpgrade(ctx sdk.Context) {
app.WasmKeeper.UpdateMilestone(ctx, "wasm_v1", info.EffectiveHeight)
})

app.ParamsKeeper.ClaimReadyForUpgrade(tmtypes.MILESTONE_VENUS8_NAME, func(info paramstypes.UpgradeInfo) {
tmtypes.InitMilestoneVenus8Height(int64(info.EffectiveHeight))
})

if err := app.ParamsKeeper.ApplyEffectiveUpgrade(ctx); err != nil {
tmos.Exit(fmt.Sprintf("failed apply effective upgrade height info: %s", err))
}
Expand Down
15 changes: 15 additions & 0 deletions libs/tendermint/types/milestone.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,9 @@ var (
MILESTONE_VENUS7_NAME = "venus7"
milestoneVenus7Height int64 = 0

MILESTONE_VENUS8_NAME = "venus8"
milestoneVenus8Height int64 = 0

// note: it stores the earlies height of the node,and it is used by cli
nodePruneHeight int64

Expand Down Expand Up @@ -354,3 +357,15 @@ func GetVenus7Height() int64 {

// =========== Venus7 ===============
// ==================================

// change val's pubkey
func HigherThanVenus8(h int64) bool {
if milestoneVenus8Height == 0 {
return false
}
return h > milestoneVenus8Height
}

func InitMilestoneVenus8Height(h int64) {
milestoneVenus8Height = h
}
5 changes: 5 additions & 0 deletions x/distribution/keeper/hooks.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package keeper

import (
sdk "github.com/okex/exchain/libs/cosmos-sdk/types"
"github.com/okex/exchain/libs/tendermint/crypto"

"github.com/okex/exchain/x/distribution/types"
stakingtypes "github.com/okex/exchain/x/staking/types"
Expand All @@ -23,6 +24,10 @@ func (h Hooks) AfterValidatorCreated(ctx sdk.Context, valAddr sdk.ValAddress) {
h.k.initializeValidator(ctx, val)
}

func (h Hooks) AfterValidatorPubkeyChanged(ctx sdk.Context, oldAddress sdk.ConsAddress, newAddress sdk.ConsAddress, newPubkey crypto.PubKey) {

}

// AfterValidatorRemoved cleans up for after validator is removed
func (h Hooks) AfterValidatorRemoved(ctx sdk.Context, _ sdk.ConsAddress, valAddr sdk.ValAddress) {
if h.k.CheckDistributionProposalValid(ctx) {
Expand Down
14 changes: 14 additions & 0 deletions x/slashing/internal/keeper/hooks.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,17 @@ func (k Keeper) AfterValidatorRemoved(ctx sdk.Context, address sdk.ConsAddress)
k.modifyValidatorStatus(ctx, address, types.Destroyed)
}

func (k Keeper) AfterValidatorPubkeyChanged(ctx sdk.Context, oldAddress sdk.ConsAddress, newAddress sdk.ConsAddress, newPubkey crypto.PubKey) {
k.deleteAddrPubkeyRelation(ctx, crypto.Address(oldAddress))
signingInfo, found := k.GetValidatorSigningInfo(ctx, oldAddress)
k.modifyValidatorStatus(ctx, oldAddress, types.Destroyed)

k.AddPubkey(ctx, newPubkey)
if found {
k.SetValidatorSigningInfo(ctx, newAddress, signingInfo)
}
}

func (k Keeper) AfterValidatorDestroyed(ctx sdk.Context, valAddr sdk.ValAddress) {
validator := k.sk.Validator(ctx, valAddr)
if validator != nil {
Expand Down Expand Up @@ -76,6 +87,9 @@ func (h Hooks) AfterValidatorCreated(ctx sdk.Context, valAddr sdk.ValAddress) {
h.k.AfterValidatorCreated(ctx, valAddr)
}

func (h Hooks) AfterValidatorPubkeyChanged(ctx sdk.Context, oldAddress sdk.ConsAddress, newAddress sdk.ConsAddress, newPubkey crypto.PubKey) {
h.k.AfterValidatorPubkeyChanged(ctx, oldAddress, newAddress, newPubkey)
}
func (h Hooks) AfterValidatorDestroyed(ctx sdk.Context, _ sdk.ConsAddress, valAddr sdk.ValAddress) {
h.k.AfterValidatorDestroyed(ctx, valAddr)
}
Expand Down
3 changes: 2 additions & 1 deletion x/slashing/internal/keeper/infractions.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@ func (k Keeper) HandleValidatorSignature(ctx sdk.Context, addr crypto.Address, p
// fetch the validator public key
consAddr := sdk.ConsAddress(addr)
if _, err := k.GetPubkey(ctx, addr); err != nil {
panic(fmt.Sprintf("Validator consensus-address %s not found", consAddr))
// ignore this panic, now we can change the validator's pub key
//panic(fmt.Sprintf("Validator consensus-address %s not found", consAddr))
}

// fetch signing info
Expand Down
1 change: 1 addition & 0 deletions x/staking/alias.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ var (
RegisterCodec = types.RegisterCodec
NewCommission = types.NewCommission
ErrNoValidatorFound = types.ErrNoValidatorFound
ErrPubkeyEqual = types.ErrPubkeyEqual
ErrValidatorOwnerExists = types.ErrValidatorOwnerExists
ErrValidatorPubKeyExists = types.ErrValidatorPubKeyExists
ErrValidatorPubKeyTypeNotSupported = types.ErrValidatorPubKeyTypeNotSupported
Expand Down
41 changes: 33 additions & 8 deletions x/staking/handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -165,15 +165,40 @@ func handleMsgEditValidator(ctx sdk.Context, msg types.MsgEditValidator, k keepe
return nil, ErrNoValidatorFound(msg.ValidatorAddress.String())
}

// replace all editable fields (clients should autofill existing values)
description, err := validator.Description.UpdateDescription(msg.Description)
if err != nil {
return nil, err
}

validator.Description = description
pk, err := types.GetConsPubKeyBech32(msg.Details)
if err == nil && tmtypes.HigherThanVenus8(ctx.BlockHeight()) {
if validator.ConsPubKey.Equals(pk) {
return nil, ErrPubkeyEqual(pk.Address().String())
}
if _, found := k.GetValidatorByConsAddr(ctx, sdk.GetConsAddress(pk)); found {
return nil, ErrValidatorPubKeyExists()
}
if ctx.ConsensusParams() != nil {
tmPubKey := tmtypes.TM2PB.PubKey(pk)
if !StringInSlice(tmPubKey.Type, ctx.ConsensusParams().Validator.PubKeyTypes) {
return nil, ErrValidatorPubKeyTypeNotSupported(tmPubKey.Type,
ctx.ConsensusParams().Validator.PubKeyTypes)
}
}
k.SetChangePubkey(ctx, validator.OperatorAddress, validator.GetConsPubKey())
ylsGit marked this conversation as resolved.
Show resolved Hide resolved
oldConsAddr := validator.GetConsAddr()

validator.ConsPubKey = pk
newConsAddr := validator.GetConsAddr()
k.SetValidator(ctx, validator)
k.SetValidatorByConsAddr(ctx, validator)
k.DeleteValidatorByConsAddr(ctx, oldConsAddr)
k.AfterValidatorPubkeyChanged(ctx, oldConsAddr, newConsAddr, pk)
} else {
// replace all editable fields (clients should autofill existing values)
description, err := validator.Description.UpdateDescription(msg.Description)
if err != nil {
return nil, err
}

k.SetValidator(ctx, validator)
validator.Description = description
k.SetValidator(ctx, validator)
}

ctx.EventManager().EmitEvents(sdk.Events{
sdk.NewEvent(types.EventTypeEditValidator,
Expand Down
7 changes: 7 additions & 0 deletions x/staking/keeper/hooks.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package keeper

import (
sdk "github.com/okex/exchain/libs/cosmos-sdk/types"
"github.com/okex/exchain/libs/tendermint/crypto"
"github.com/okex/exchain/x/staking/types"
)

Expand All @@ -15,6 +16,12 @@ func (k Keeper) AfterValidatorCreated(ctx sdk.Context, valAddr sdk.ValAddress) {
}
}

func (k Keeper) AfterValidatorPubkeyChanged(ctx sdk.Context, oldAddress sdk.ConsAddress, newAddress sdk.ConsAddress, newPubkey crypto.PubKey) {
if k.hooks != nil {
k.hooks.AfterValidatorPubkeyChanged(ctx, oldAddress, newAddress, newPubkey)
}
}

// BeforeValidatorModified - call hook if registered
func (k Keeper) BeforeValidatorModified(ctx sdk.Context, valAddr sdk.ValAddress) {
if k.hooks != nil {
Expand Down
6 changes: 4 additions & 2 deletions x/staking/keeper/test_common.go
Original file line number Diff line number Diff line change
Expand Up @@ -315,8 +315,10 @@ func SimpleCheckValidator(t *testing.T, ctx sdk.Context, stkKeeper Keeper, vaAdd
// mockDistributionKeeper is supported to test Hooks
type mockDistributionKeeper struct{}

func (dk mockDistributionKeeper) Hooks() types.StakingHooks { return dk }
func (dk mockDistributionKeeper) AfterValidatorCreated(ctx sdk.Context, valAddr sdk.ValAddress) {}
func (dk mockDistributionKeeper) Hooks() types.StakingHooks { return dk }
func (dk mockDistributionKeeper) AfterValidatorCreated(ctx sdk.Context, valAddr sdk.ValAddress) {}
func (dk mockDistributionKeeper) AfterValidatorPubkeyChanged(ctx sdk.Context, oldAddress sdk.ConsAddress, newAddress sdk.ConsAddress, newPubkey crypto.PubKey) {
}
func (dk mockDistributionKeeper) BeforeValidatorModified(ctx sdk.Context, valAddr sdk.ValAddress) {}
func (dk mockDistributionKeeper) AfterValidatorRemoved(ctx sdk.Context, consAddr sdk.ConsAddress, valAddr sdk.ValAddress) {
}
Expand Down
10 changes: 10 additions & 0 deletions x/staking/keeper/val_state_change.go
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,16 @@ func (k Keeper) ApplyAndReturnValidatorSetUpdates(ctx sdk.Context) (updates []ab
k.SetLastValidatorPower(ctx, valAddr, newPower)
}

// change val node key
ylsGit marked this conversation as resolved.
Show resolved Hide resolved
if pk, found := k.GetChangePubkey(ctx, validator.OperatorAddress); found {
oldVal := types.Validator{ConsPubKey: pk}
// delete old pubkey
updates = append(updates, oldVal.ABCIValidatorUpdateZero())
// add new pubkey
updates = append(updates, validator.ABCIValidatorUpdateByShares())
k.DeleteChangePubkey(ctx, validator.OperatorAddress)
}

// validator still in the validator set, so delete from the copy
delete(last, valAddrBytes)

Expand Down
30 changes: 30 additions & 0 deletions x/staking/keeper/validator.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ import (
"time"

sdk "github.com/okex/exchain/libs/cosmos-sdk/types"
"github.com/okex/exchain/libs/tendermint/crypto"
cryptoAmino "github.com/okex/exchain/libs/tendermint/crypto/encoding/amino"
"github.com/okex/exchain/x/staking/types"
)

Expand Down Expand Up @@ -54,13 +56,41 @@ func (k Keeper) SetValidator(ctx sdk.Context, validator types.Validator) {
store.Set(types.GetValidatorKey(validator.OperatorAddress), bz)
}

func (k Keeper) SetChangePubkey(ctx sdk.Context, addr sdk.ValAddress, pubkey crypto.PubKey) {
store := ctx.KVStore(k.storeKey)
store.Set(types.GetValidatorChangePubkeyKey(addr), pubkey.Bytes())
}

func (k Keeper) DeleteChangePubkey(ctx sdk.Context, addr sdk.ValAddress) {
store := ctx.KVStore(k.storeKey)
store.Delete(types.GetValidatorChangePubkeyKey(addr))
}

func (k Keeper) GetChangePubkey(ctx sdk.Context, addr sdk.ValAddress) (pubkey crypto.PubKey, found bool) {
store := ctx.KVStore(k.storeKey)
value := store.Get(types.GetValidatorChangePubkeyKey(addr))
if value == nil {
return nil, false
}
pk, err := cryptoAmino.PubKeyFromBytes(value)
if err != nil {
panic(err)
}
return pk, true
}

// SetValidatorByConsAddr sets the operator address with the key of validator consensus pubkey
func (k Keeper) SetValidatorByConsAddr(ctx sdk.Context, validator types.Validator) {
store := ctx.KVStore(k.storeKey)
consAddr := sdk.ConsAddress(validator.ConsPubKey.Address())
store.Set(types.GetValidatorByConsAddrKey(consAddr), validator.OperatorAddress)
}

func (k Keeper) DeleteValidatorByConsAddr(ctx sdk.Context, consAddr sdk.ConsAddress) {
store := ctx.KVStore(k.storeKey)
store.Delete(types.GetValidatorByConsAddrKey(consAddr))
}

// SetValidatorByPowerIndex sets the power index key of an unjailed validator
func (k Keeper) SetValidatorByPowerIndex(ctx sdk.Context, validator types.Validator) {
// jailed validators are not kept in the power index
Expand Down
11 changes: 9 additions & 2 deletions x/staking/types/errors.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,17 +58,24 @@ const (
CodeNoDelegatorExisted uint32 = 67044
CodeTargetValsDuplicate uint32 = 67045
CodeAlreadyBound uint32 = 67046

CodePubkeyEqual uint32 = 67047
)

var (
ErrInvalidHistoricalInfo = sdkerrors.Register(ModuleName, 144, "invalid historical info")
ErrNoHistoricalInfo = sdkerrors.Register(ModuleName, 145, "no historical info found")
ErrInvalidHistoricalInfo = sdkerrors.Register(ModuleName, 144, "invalid historical info")
ErrNoHistoricalInfo = sdkerrors.Register(ModuleName, 145, "no historical info found")
)

// ErrNoValidatorFound returns an error when a validator doesn't exist
func ErrNoValidatorFound(valAddr string) sdk.EnvelopedErr {
return sdk.EnvelopedErr{Err: sdkerrors.New(DefaultCodespace, CodeNoValidatorFound, fmt.Sprintf("validator %s does not exist", valAddr))}
}

func ErrPubkeyEqual(pubkey string) sdk.EnvelopedErr {
return sdk.EnvelopedErr{Err: sdkerrors.New(DefaultCodespace, CodePubkeyEqual, fmt.Sprintf("validator pubkey %s does exist", pubkey))}
}

// ErrInvalidDelegation returns an error when the delegation is invalid
func ErrInvalidDelegation(delegator string) sdk.EnvelopedErr {
return sdk.EnvelopedErr{Err: sdkerrors.New(DefaultCodespace, CodeInvalidDelegation,
Expand Down
2 changes: 2 additions & 0 deletions x/staking/types/expected_keepers.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
sdk "github.com/okex/exchain/libs/cosmos-sdk/types"
authexported "github.com/okex/exchain/libs/cosmos-sdk/x/auth/exported"
supplyexported "github.com/okex/exchain/libs/cosmos-sdk/x/supply/exported"
"github.com/okex/exchain/libs/tendermint/crypto"
stakingexported "github.com/okex/exchain/x/staking/exported"
)

Expand Down Expand Up @@ -74,6 +75,7 @@ type ValidatorSet interface {
type StakingHooks interface {
// Must be called when a validator is created
AfterValidatorCreated(ctx sdk.Context, valAddr sdk.ValAddress)
AfterValidatorPubkeyChanged(ctx sdk.Context, oldAddress sdk.ConsAddress, newAddress sdk.ConsAddress, newPubkey crypto.PubKey)
// Must be called when a validator's state changes
BeforeValidatorModified(ctx sdk.Context, valAddr sdk.ValAddress)
// Must be called when a validator is deleted
Expand Down
7 changes: 7 additions & 0 deletions x/staking/types/hooks.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package types

import (
sdk "github.com/okex/exchain/libs/cosmos-sdk/types"
"github.com/okex/exchain/libs/tendermint/crypto"
)

// MultiStakingHooks combines multiple staking hooks, all hook functions are run in array sequence
Expand All @@ -20,6 +21,12 @@ func (h MultiStakingHooks) AfterValidatorCreated(ctx sdk.Context, valAddr sdk.Va
}
}

func (h MultiStakingHooks) AfterValidatorPubkeyChanged(ctx sdk.Context, oldAddress sdk.ConsAddress, newAddress sdk.ConsAddress, newPubkey crypto.PubKey) {
for i := range h {
h[i].AfterValidatorPubkeyChanged(ctx, oldAddress, newAddress, newPubkey)
}
}

// BeforeValidatorModified handles the hooks before the validator modified
func (h MultiStakingHooks) BeforeValidatorModified(ctx sdk.Context, valAddr sdk.ValAddress) {
for i := range h {
Expand Down
7 changes: 6 additions & 1 deletion x/staking/types/keys.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ const (
RouterKey = ModuleName
)

//nolint
// nolint
var (
// Keys for store prefixes
// Last* values are constant during a block.
Expand All @@ -40,6 +40,7 @@ var (
ValidatorsKey = []byte{0x21} // prefix for each key to a validator
ValidatorsByConsAddrKey = []byte{0x22} // prefix for each key to a validator index, by pubkey
ValidatorsByPowerIndexKey = []byte{0x23} // prefix for each key to a validator index, sorted by power
ValChangePubkeyKey = []byte{0x24}

ValidatorQueueKey = []byte{0x43} // prefix for the timestamps in validator queue

Expand Down Expand Up @@ -67,6 +68,10 @@ func GetValidatorByConsAddrKey(addr sdk.ConsAddress) []byte {
return append(ValidatorsByConsAddrKey, addr.Bytes()...)
}

func GetValidatorChangePubkeyKey(operatorAddr sdk.ValAddress) []byte {
return append(ValChangePubkeyKey, operatorAddr.Bytes()...)
}

// AddressFromLastValidatorPowerKey gets the validator operator address from LastValidatorPowerKey
func AddressFromLastValidatorPowerKey(key []byte) []byte {
return key[1:] // remove prefix bytes
Expand Down
2 changes: 1 addition & 1 deletion x/staking/types/msg.go
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,7 @@ func (msg MsgEditValidator) ValidateBasic() error {
}

if msg.Description == (Description{}) {
return ErrNilValidatorAddr()
return ErrDescriptionIsEmpty()
}

return nil
Expand Down
Loading