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

x/staking: skip HistoricalInfo in simulations #5949

Merged
merged 13 commits into from
Apr 7, 2020
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@ types (eg. keys) to the `auth` module internal amino codec.
* (rest) [\#5906](https://github.com/cosmos/cosmos-sdk/pull/5906) Fix an issue that make some REST calls panic when sending
invalid or incomplete requests.
* (x/genutil) [\#5938](https://github.com/cosmos/cosmos-sdk/pull/5938) Fix `InitializeNodeValidatorFiles` error handling.
* (x/staking) [\#5949](https://github.com/cosmos/cosmos-sdk/pull/5949) Add `HistoricalInfo` to staking `GenesisState` for import and export.

### State Machine Breaking

Expand Down
6 changes: 6 additions & 0 deletions x/staking/genesis.go
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,10 @@ func InitGenesis(
supplyKeeper.SetModuleAccount(ctx, notBondedPool)
}

for _, hi := range data.HistoricalInfos {
keeper.SetHistoricalInfo(ctx, hi.Header.GetHeight(), hi)
}

// don't need to run Tendermint updates if we exported
if data.Exported {
for _, lv := range data.LastValidatorPowers {
Expand Down Expand Up @@ -148,6 +152,7 @@ func ExportGenesis(ctx sdk.Context, keeper Keeper) types.GenesisState {
lastTotalPower := keeper.GetLastTotalPower(ctx)
validators := keeper.GetAllValidators(ctx)
delegations := keeper.GetAllDelegations(ctx)
historicalInfos := keeper.GetAllHistoricalInfo(ctx)
var unbondingDelegations []types.UnbondingDelegation
keeper.IterateUnbondingDelegations(ctx, func(_ int64, ubd types.UnbondingDelegation) (stop bool) {
unbondingDelegations = append(unbondingDelegations, ubd)
Expand All @@ -172,6 +177,7 @@ func ExportGenesis(ctx sdk.Context, keeper Keeper) types.GenesisState {
Delegations: delegations,
UnbondingDelegations: unbondingDelegations,
Redelegations: redelegations,
HistoricalInfos: historicalInfos,
fedekunze marked this conversation as resolved.
Show resolved Hide resolved
Exported: true,
}
}
Expand Down
8 changes: 8 additions & 0 deletions x/staking/genesis_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,15 @@ func TestInitGenesis(t *testing.T) {
validators[1].Tokens = valTokens
validators[1].DelegatorShares = valTokens.ToDec()

header1 := abci.Header{ChainID: "gaia", Height: 10}
header2 := abci.Header{ChainID: "gaia", Height: 11}
header3 := abci.Header{ChainID: "gaia", Height: 12}
hist1 := types.HistoricalInfo{Header: header1, Valset: validators}
hist2 := types.HistoricalInfo{Header: header2, Valset: validators}
hist3 := types.HistoricalInfo{Header: header3, Valset: validators}

genesisState := types.NewGenesisState(params, validators, delegations)
genesisState.HistoricalInfos = []types.HistoricalInfo{hist1, hist2, hist3}
vals := staking.InitGenesis(ctx, app.StakingKeeper, app.AccountKeeper, app.BankKeeper, app.SupplyKeeper, genesisState)

actualGenesis := staking.ExportGenesis(ctx, app.StakingKeeper)
Expand Down
26 changes: 26 additions & 0 deletions x/staking/keeper/historical_info.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,32 @@ func (k Keeper) DeleteHistoricalInfo(ctx sdk.Context, height int64) {
store.Delete(key)
}

// IterateHistoricalInfo provides an interator over all stored HistoricalInfo
// objects. For each HistoricalInfo object, cb will be called. If the cb returns
// true, the iterator will close and stop.
func (k Keeper) IterateHistoricalInfo(ctx sdk.Context, cb func(types.HistoricalInfo) bool) {
store := ctx.KVStore(k.storeKey)
iterator := sdk.KVStorePrefixIterator(store, types.HistoricalInfoKey)
defer iterator.Close()

for ; iterator.Valid(); iterator.Next() {
histInfo := types.MustUnmarshalHistoricalInfo(k.cdc, iterator.Value())
if cb(histInfo) {
break
}
}
}

// GetAllHistoricalInfo returns all stored HistoricalInfo objects.
func (k Keeper) GetAllHistoricalInfo(ctx sdk.Context) []types.HistoricalInfo {
var infos []types.HistoricalInfo
k.IterateHistoricalInfo(ctx, func(histInfo types.HistoricalInfo) bool {
infos = append(infos, histInfo)
return false
})
return infos
}

// TrackHistoricalInfo saves the latest historical-info and deletes the oldest
// heights that are below pruning height
func (k Keeper) TrackHistoricalInfo(ctx sdk.Context) {
Expand Down
29 changes: 29 additions & 0 deletions x/staking/keeper/historical_info_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -114,3 +114,32 @@ func TestTrackHistoricalInfo(t *testing.T) {
require.False(t, found, "GetHistoricalInfo did not prune first prune height")
require.Equal(t, types.HistoricalInfo{}, recv, "GetHistoricalInfo at height 5 is not empty after prune")
}

func TestGetAllHistoricalInfo(t *testing.T) {
_, app, ctx := createTestInput()

addrDels := simapp.AddTestAddrsIncremental(app, ctx, 50, sdk.NewInt(0))
addrVals := simapp.ConvertAddrsToValAddrs(addrDels)

valSet := []types.Validator{
types.NewValidator(addrVals[0], PKs[0], types.Description{}),
types.NewValidator(addrVals[1], PKs[1], types.Description{}),
}

header1 := abci.Header{ChainID: "HelloChain", Height: 10}
header2 := abci.Header{ChainID: "HelloChain", Height: 11}
header3 := abci.Header{ChainID: "HelloChain", Height: 12}

hist1 := types.HistoricalInfo{Header: header1, Valset: valSet}
hist2 := types.HistoricalInfo{Header: header2, Valset: valSet}
hist3 := types.HistoricalInfo{Header: header3, Valset: valSet}

expHistInfos := []types.HistoricalInfo{hist1, hist2, hist3}

for i, hi := range expHistInfos {
app.StakingKeeper.SetHistoricalInfo(ctx, int64(10+i), hi)
}

infos := app.StakingKeeper.GetAllHistoricalInfo(ctx)
require.Equal(t, expHistInfos, infos)
}
1 change: 1 addition & 0 deletions x/staking/keeper/keeper.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ func NewKeeper(
cdc codec.Marshaler, key sdk.StoreKey, bk types.BankKeeper, sk types.SupplyKeeper, ps paramtypes.Subspace,
) Keeper {

// set KeyTable if it has not already been set
if !ps.HasKeyTable() {
ps = ps.WithKeyTable(ParamKeyTable())
}
Expand Down
6 changes: 6 additions & 0 deletions x/staking/simulation/decoder.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,12 @@ func DecodeStore(cdc *codec.Codec, kvA, kvB tmkv.Pair) string {
cdc.MustUnmarshalBinaryBare(kvB.Value, &redB)
return fmt.Sprintf("%v\n%v", redA, redB)

case bytes.Equal(kvA.Key[:1], types.HistoricalInfoKey):
var histInfoA, histInfoB types.HistoricalInfo
cdc.MustUnmarshalBinaryBare(kvA.Value, &histInfoA)
cdc.MustUnmarshalBinaryBare(kvB.Value, &histInfoB)
return fmt.Sprintf("%v\n%v", histInfoA, histInfoB)

default:
panic(fmt.Sprintf("invalid staking key prefix %X", kvA.Key[:1]))
}
Expand Down
4 changes: 4 additions & 0 deletions x/staking/simulation/decoder_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (

"github.com/stretchr/testify/require"

abci "github.com/tendermint/tendermint/abci/types"
"github.com/tendermint/tendermint/crypto/ed25519"
tmkv "github.com/tendermint/tendermint/libs/kv"

Expand Down Expand Up @@ -38,6 +39,7 @@ func TestDecodeStore(t *testing.T) {
del := types.NewDelegation(delAddr1, valAddr1, sdk.OneDec())
ubd := types.NewUnbondingDelegation(delAddr1, valAddr1, 15, bondTime, sdk.OneInt())
red := types.NewRedelegation(delAddr1, valAddr1, valAddr1, 12, bondTime, sdk.OneInt(), sdk.OneDec())
histInfo := types.NewHistoricalInfo(abci.Header{ChainID: "gaia", Height: 10, Time: bondTime}, types.Validators{val})

kvPairs := tmkv.Pairs{
tmkv.Pair{Key: types.LastTotalPowerKey, Value: cdc.MustMarshalBinaryBare(sdk.OneInt())},
Expand All @@ -46,6 +48,7 @@ func TestDecodeStore(t *testing.T) {
tmkv.Pair{Key: types.GetDelegationKey(delAddr1, valAddr1), Value: cdc.MustMarshalBinaryBare(del)},
tmkv.Pair{Key: types.GetUBDKey(delAddr1, valAddr1), Value: cdc.MustMarshalBinaryBare(ubd)},
tmkv.Pair{Key: types.GetREDKey(delAddr1, valAddr1, valAddr1), Value: cdc.MustMarshalBinaryBare(red)},
tmkv.Pair{Key: types.GetHistoricalInfoKey(10), Value: cdc.MustMarshalBinaryBare(histInfo)},
tmkv.Pair{Key: []byte{0x99}, Value: []byte{0x99}},
}

Expand All @@ -59,6 +62,7 @@ func TestDecodeStore(t *testing.T) {
{"Delegation", fmt.Sprintf("%v\n%v", del, del)},
{"UnbondingDelegation", fmt.Sprintf("%v\n%v", ubd, ubd)},
{"Redelegation", fmt.Sprintf("%v\n%v", red, red)},
{"HistoricalInfo", fmt.Sprintf("%v\n%v", histInfo, histInfo)},
{"other", ""},
}
for i, tt := range tests {
Expand Down
1 change: 1 addition & 0 deletions x/staking/types/genesis.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ type GenesisState struct {
Delegations Delegations `json:"delegations" yaml:"delegations"`
UnbondingDelegations []UnbondingDelegation `json:"unbonding_delegations" yaml:"unbonding_delegations"`
Redelegations []Redelegation `json:"redelegations" yaml:"redelegations"`
HistoricalInfos []HistoricalInfo `json:"historical_infos" yaml:"historical_infos"`
Exported bool `json:"exported" yaml:"exported"`
}

Expand Down