Skip to content

Commit

Permalink
change val's consensus pubkey
Browse files Browse the repository at this point in the history
  • Loading branch information
ylsGit committed Aug 22, 2024
1 parent a5e5127 commit 65c4e04
Show file tree
Hide file tree
Showing 16 changed files with 162 additions and 23 deletions.
20 changes: 14 additions & 6 deletions app/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,9 @@ import (
icacontroller "github.com/okex/exchain/libs/ibc-go/modules/apps/27-interchain-accounts/controller"
icahost "github.com/okex/exchain/libs/ibc-go/modules/apps/27-interchain-accounts/host"
"github.com/okex/exchain/libs/ibc-go/modules/apps/common"
"github.com/okex/exchain/x/icamauth"

ibccommon "github.com/okex/exchain/libs/ibc-go/modules/core/common"
"github.com/okex/exchain/x/icamauth"
paramstypes "github.com/okex/exchain/x/params/types"

icacontrollertypes "github.com/okex/exchain/libs/ibc-go/modules/apps/27-interchain-accounts/controller/types"
icahosttypes "github.com/okex/exchain/libs/ibc-go/modules/apps/27-interchain-accounts/host/types"
Expand Down Expand Up @@ -773,10 +773,7 @@ func NewOKExChainApp(
tmos.Exit(fmt.Sprintf("failed initialize pinned codes %s", err))
}

if err := app.ParamsKeeper.ApplyEffectiveUpgrade(ctx); err != nil {
tmos.Exit(fmt.Sprintf("failed apply effective upgrade height info: %s", err))
}

app.InitUpgrade(ctx)
app.WasmKeeper.UpdateGasRegister(ctx)
}

Expand All @@ -793,6 +790,17 @@ func NewOKExChainApp(
return app
}

func (app *OKExChainApp) InitUpgrade(ctx sdk.Context) {
// Claim before ApplyEffectiveUpgrade
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))
}
}

func (app *OKExChainApp) SetOption(req abci.RequestSetOption) (res abci.ResponseSetOption) {
if req.Key == "CheckChainID" {
if err := okexchain.IsValidateChainIdWithGenesisHeight(req.Value); err != nil {
Expand Down
19 changes: 17 additions & 2 deletions libs/tendermint/types/milestone.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,9 @@ var (
MILESTONE_VENUS5_HEIGHT string
milestoneVenus5Height int64

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 @@ -112,7 +115,7 @@ func SetupTestNetEnvironment(pruneH int64) {
milestoneVenus1Height = TestNetVeneus1Height
}

//depracate homstead signer support
// depracate homstead signer support
func HigherThanMercury(height int64) bool {
if milestoneMercuryHeight == 0 {
// milestoneMercuryHeight not enabled
Expand All @@ -128,7 +131,7 @@ func HigherThanVenus(height int64) bool {
return height >= milestoneVenusHeight
}

//use MPT storage model to replace IAVL storage model
// use MPT storage model to replace IAVL storage model
func HigherThanMars(height int64) bool {
if milestoneMarsHeight == 0 {
return false
Expand Down Expand Up @@ -304,3 +307,15 @@ func GetVenus5Height() int64 {

// =========== Venus4 ===============
// ==================================

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

func InitMilestoneVenus8Height(h int64) {
milestoneVenus8Height = h
}
4 changes: 4 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,9 @@ 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
15 changes: 15 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,10 @@ 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())
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
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
Loading

0 comments on commit 65c4e04

Please sign in to comment.