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

[R4R] Upgrade splitting validator address #109

Merged
merged 1 commit into from
Apr 4, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
63 changes: 60 additions & 3 deletions types/upgrade.go
Original file line number Diff line number Diff line change
@@ -1,17 +1,22 @@
package types

import "fmt"

var UpgradeMgr = NewUpgradeManager(UpgradeConfig{})

const UpgradeLimitAddressLength = "UpgradeLimitAddressLength" // limit address length to 20 bytes
const UpgradeSeparateValAddrName = "UpgradeSeparateValAddr"

var MainNetConfig = UpgradeConfig{
map[string]int64{
UpgradeLimitAddressLength: 554000,
HeightMap: map[string]int64{
UpgradeLimitAddressLength: 554000,
UpgradeSeparateValAddrName: 1000000,
},
}

type UpgradeConfig struct {
HeightMap map[string]int64
HeightMap map[string]int64
BeginBlockers map[int64][]func(ctx Context)
}

type UpgradeManager struct {
Expand Down Expand Up @@ -39,6 +44,33 @@ func (mgr *UpgradeManager) GetHeight() int64 {
return mgr.Height
}

// run in every ABCI BeginBlock.
func (mgr *UpgradeManager) BeginBlocker(ctx Context) {
if endBlockers, ok := mgr.Config.BeginBlockers[mgr.GetHeight()]; ok {
for _, endBlocker := range endBlockers {
endBlocker(ctx)
}
}
}

func (mgr *UpgradeManager) RegisterBeginBlocker(name string, beginBlocker func(Context)) {
height := mgr.GetUpgradeHeight(name)
if height == 0 {
panic(fmt.Errorf("no UpgradeHeight found for %s", name))
}

if mgr.Config.BeginBlockers == nil {
mgr.Config.BeginBlockers = make(map[int64][]func(ctx Context))
}

if beginBlockers, ok := mgr.Config.BeginBlockers[height]; ok {
beginBlockers = append(beginBlockers, beginBlocker)
mgr.Config.BeginBlockers[height] = beginBlockers
} else {
mgr.Config.BeginBlockers[height] = []func(Context){beginBlocker}
}
}

func (mgr *UpgradeManager) AddUpgradeHeight(name string, height int64) {
if mgr.Config.HeightMap == nil {
mgr.Config.HeightMap = map[string]int64{}
Expand Down Expand Up @@ -72,6 +104,31 @@ func IsUpgrade(name string) bool {
return UpgradeMgr.GetHeight() >= upgradeHeight
}

func Upgrade(name string, before func(), in func(), after func()) {
// if no special logic for the UpgradeHeight, than apply the `after` logic
if in == nil {
in = after
}

if IsUpgradeHeight(name) {
if in != nil {
in()
}
} else if IsUpgrade(name) {
if after != nil {
after()
}
} else {
if before != nil {
before()
}
}
}

func UpgradeSeparateValAddresses(before func(), after func()) {
Upgrade(UpgradeSeparateValAddrName, before, nil, after)
}

func IsLimitAddressLengthUpgrade() bool {
return IsUpgrade(UpgradeLimitAddressLength)
}
11 changes: 8 additions & 3 deletions x/stake/client/cli/query.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,10 @@ func GetCmdQueryValidator(storeName string, cdc *codec.Codec) *cobra.Command {
return fmt.Errorf("No validator found with address %s", args[0])
}

validator := types.MustUnmarshalValidator(cdc, addr, res)
validator, err := types.UnmarshalValidator(cdc, res)
if err != nil {
return err
}

switch viper.Get(cli.OutputFlag) {
case "text":
Expand Down Expand Up @@ -81,8 +84,10 @@ func GetCmdQueryValidators(storeName string, cdc *codec.Codec) *cobra.Command {
// parse out the validators
var validators []stake.Validator
for _, kv := range resKVs {
addr := kv.Key[1:]
validator := types.MustUnmarshalValidator(cdc, addr, kv.Value)
validator, err := types.UnmarshalValidator(cdc, kv.Value)
if err != nil {
return err
}
validators = append(validators, validator)
}

Expand Down
3 changes: 2 additions & 1 deletion x/stake/keeper/keeper.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ package keeper
import (
"github.com/cosmos/cosmos-sdk/codec"
sdk "github.com/cosmos/cosmos-sdk/types"

"github.com/cosmos/cosmos-sdk/x/bank"
"github.com/cosmos/cosmos-sdk/x/params"
"github.com/cosmos/cosmos-sdk/x/stake/types"
Expand Down Expand Up @@ -32,6 +31,8 @@ func NewKeeper(cdc *codec.Codec, key, tkey sdk.StoreKey, ck bank.Keeper, paramst
hooks: nil,
codespace: codespace,
}

sdk.UpgradeMgr.RegisterBeginBlocker(sdk.UpgradeSeparateValAddrName, keeper.FixValidatorFeeAddr)
return keeper
}

Expand Down
60 changes: 60 additions & 0 deletions x/stake/keeper/validator.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,66 @@ type cachedValidator struct {
var validatorCache = make(map[string]cachedValidator, 500)
var validatorCacheList = list.New()

func (k Keeper) FixValidatorFeeAddr(ctx sdk.Context) {
store := ctx.KVStore(k.storeKey)
iterator := sdk.KVStorePrefixIterator(store, ValidatorsKey)
defer iterator.Close()

allValidators := make([]types.Validator, 0, 11)
for ; iterator.Valid(); iterator.Next() {
addr := iterator.Key()[1:]
// use the old logic to unmarshal it
if validator, err := types.UnmarshalValidatorDeprecated(k.cdc, addr, iterator.Value()); err != nil {
panic(err)
} else {
allValidators = append(allValidators, validator)
}
}

// "tbnb13nj6strryvnqud5tqchkltwaatqr9awrxdlk8q",
// "tbnb1lyjatx8jed40afe75t744hkvj0559xrvv4rle3",
// "tbnb1snyg4ttdyckluwzphm4eh43uv5sw5ys5x9gxuj",
// "tbnb1kem52fk9w43hemgqgjft8q76xesv0uypzcncjx",
// "tbnb1hvcnlrflp2sgzvyrzqgtpsvqxrahhtrlsa4r4p",
// "tbnb10da4lqdtp8yeahr2n2s88unmc2qn4czgnlr9u7",
// "tbnb1xmdk54cuytnfgv6krzj2fnr9t55l94hnxdwe72",
// "tbnb1f02de8sxjcznu5qejuzll0cmuxxzwq4yd4lghw",
// "tbnb18arl8klkum0fpke8hyuucxu44wrhwdyg23nlsc",
// "tbnb1zwuz8qklekm4vfwtkswu6nhhs2ghevn2dzqq85",
// "tbnb1q7cc8e2nn39frppdzkqnzdy2f0pf664deg4zkq",
feeAddressesHex := []string{
"8CE5A82C6323260E368B062F6FADDDEAC032F5C3",
"F925D598F2CB6AFEA73EA2FD5ADECC93E942986C",
"84C88AAD6D262DFE3841BEEB9BD63C6520EA1214",
"B6774526C575637CED004492B383DA3660C7F081",
"BB313F8D3F0AA08130831010B0C18030FB7BAC7F",
"7B7B5F81AB09C99EDC6A9AA073F27BC2813AE048",
"36DB6A571C22E694335618A4A4CC655D29F2D6F3",
"4BD4DC9E0696053E50199705FFBF1BE18C2702A4",
"3F47F3DBF6E6DE90DB27B939CC1B95AB87773488",
"13B82382DFCDB75625CBB41DCD4EF782917CB26A",
"07B183E5539C4A91842D158131348A4BC29D6AAD",
}

for i, val := range allValidators {
if i < 11 {
aa, err := sdk.AccAddressFromHex(feeAddressesHex[i])
if err != nil {
panic(err)
}
// create the fee account
if sdkErr := k.bankKeeper.SetCoins(ctx, aa, nil); sdkErr != nil {
panic(sdkErr)
}
val.FeeAddr = aa
} else {
val.FeeAddr = sdk.AccAddress(val.OperatorAddr)
}
// use the new logic to Marshal and store it.
k.SetValidator(ctx, val)
}
}

// get a single validator
func (k Keeper) GetValidator(ctx sdk.Context, addr sdk.ValAddress) (validator types.Validator, found bool) {
store := ctx.KVStore(k.storeKey)
Expand Down
57 changes: 37 additions & 20 deletions x/stake/types/validator.go
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,6 @@ func NewValidatorWithFeeAddr(feeAddr sdk.AccAddress, operator sdk.ValAddress, pu

// what's kept in the store value
type validatorValue struct {
FeeAddr sdk.AccAddress
ConsPubKey crypto.PubKey
Jailed bool
Status sdk.BondStatus
Expand All @@ -80,34 +79,47 @@ type validatorValue struct {

// return the redelegation without fields contained within the key for the store
func MustMarshalValidator(cdc *codec.Codec, validator Validator) []byte {
val := validatorValue{
FeeAddr: validator.FeeAddr,
ConsPubKey: validator.ConsPubKey,
Jailed: validator.Jailed,
Status: validator.Status,
Tokens: validator.Tokens,
DelegatorShares: validator.DelegatorShares,
Description: validator.Description,
BondHeight: validator.BondHeight,
BondIntraTxCounter: validator.BondIntraTxCounter,
UnbondingHeight: validator.UnbondingHeight,
UnbondingMinTime: validator.UnbondingMinTime,
Commission: validator.Commission,
}
return cdc.MustMarshalBinaryLengthPrefixed(val)
var res []byte
sdk.UpgradeSeparateValAddresses(func() {
val := validatorValue{
ConsPubKey: validator.ConsPubKey,
Jailed: validator.Jailed,
Status: validator.Status,
Tokens: validator.Tokens,
DelegatorShares: validator.DelegatorShares,
Description: validator.Description,
BondHeight: validator.BondHeight,
BondIntraTxCounter: validator.BondIntraTxCounter,
UnbondingHeight: validator.UnbondingHeight,
UnbondingMinTime: validator.UnbondingMinTime,
Commission: validator.Commission,
}
res = cdc.MustMarshalBinaryLengthPrefixed(val)
}, func() {
res = cdc.MustMarshalBinaryLengthPrefixed(validator)
})

return res
}

// unmarshal a redelegation from a store key and value
func MustUnmarshalValidator(cdc *codec.Codec, operatorAddr, value []byte) Validator {
validator, err := UnmarshalValidator(cdc, operatorAddr, value)
var validator Validator
var err error
sdk.UpgradeSeparateValAddresses(func() {
validator, err = UnmarshalValidatorDeprecated(cdc, operatorAddr, value)
}, func() {
validator, err = UnmarshalValidator(cdc, value)
})

if err != nil {
panic(err)
}
return validator
}

// unmarshal a redelegation from a store key and value
func UnmarshalValidator(cdc *codec.Codec, operatorAddr, value []byte) (validator Validator, err error) {
// !!!DEPRECATED, would be called only before the UpgradeHeight
func UnmarshalValidatorDeprecated(cdc *codec.Codec, operatorAddr, value []byte) (validator Validator, err error) {
if len(operatorAddr) != sdk.AddrLen {
err = fmt.Errorf("%v", ErrBadValidatorAddr(DefaultCodespace).Data())
return
Expand All @@ -119,7 +131,7 @@ func UnmarshalValidator(cdc *codec.Codec, operatorAddr, value []byte) (validator
}

return Validator{
FeeAddr: storeValue.FeeAddr,
FeeAddr: sdk.AccAddress(operatorAddr),
OperatorAddr: operatorAddr,
ConsPubKey: storeValue.ConsPubKey,
Jailed: storeValue.Jailed,
Expand All @@ -135,6 +147,11 @@ func UnmarshalValidator(cdc *codec.Codec, operatorAddr, value []byte) (validator
}, nil
}

func UnmarshalValidator(cdc *codec.Codec, value []byte) (validator Validator, err error) {
err = cdc.UnmarshalBinaryLengthPrefixed(value, &validator)
return validator, err
}

// HumanReadableString returns a human readable string representation of a
// validator. An error is returned if the operator or the operator's public key
// cannot be converted to Bech32 format.
Expand Down