x/staking: skip HistoricalInfo in simulations (#5949)

* x/staking: import and export HistoricalInfo

* staking/types: add HistoricalInfo to GenesisState

* changelog

* add staking module to app BeginBlockers

* remove JSON files

* address comments from review

* add HistoricalInfoKey to skipped prefixes

* fix DiffKVStores

* rm JSON
This commit is contained in:
Federico Kunze
2020-04-07 22:33:30 +00:00
committed by GitHub
parent 7b21c54359
commit 7325692550
13 changed files with 80 additions and 23 deletions
+3 -3
View File
@@ -51,7 +51,7 @@ jobs:
with:
path: ~/go/bin
key: ${{ runner.os }}-go-runsim-binary
- name: test nondeterminism
- name: test-sim-nondeterminism
run: |
make test-sim-nondeterminism
@@ -97,9 +97,9 @@ jobs:
with:
path: ~/go/bin
key: ${{ runner.os }}-go-runsim-binary
- name: test after import
- name: test-sim-after-import
run: |
make test-sim-import-export
make test-sim-after-import
test-sim-multi-seed-short:
runs-on: ubuntu-latest
+1
View File
@@ -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) Skip staking `HistoricalInfoKey` in simulations as headers are not exported.
* (x/auth) [\#5950](https://github.com/cosmos/cosmos-sdk/pull/5950) Fix `IncrementSequenceDecorator` to use is `IsReCheckTx` instead of `IsCheckTx` to allow account sequence incrementing.
### State Machine Breaking
+1 -1
View File
@@ -236,7 +236,7 @@ func NewSimApp(
// During begin block slashing happens after distr.BeginBlocker so that
// there is nothing left over in the validator fee pool, so as to keep the
// CanWithdrawInvariant invariant.
app.mm.SetOrderBeginBlockers(upgrade.ModuleName, mint.ModuleName, distr.ModuleName, slashing.ModuleName, evidence.ModuleName)
app.mm.SetOrderBeginBlockers(upgrade.ModuleName, mint.ModuleName, distr.ModuleName, slashing.ModuleName, evidence.ModuleName, staking.ModuleName)
app.mm.SetOrderEndBlockers(crisis.ModuleName, gov.ModuleName, staking.ModuleName)
// NOTE: The genutils moodule must occur after staking so that pools are
+1
View File
@@ -148,6 +148,7 @@ func TestAppImportExport(t *testing.T) {
{app.keys[staking.StoreKey], newApp.keys[staking.StoreKey],
[][]byte{
staking.UnbondingQueueKey, staking.RedelegationQueueKey, staking.ValidatorQueueKey,
staking.HistoricalInfoKey,
}}, // ordering may change but it doesn't matter
{app.keys[slashing.StoreKey], newApp.keys[slashing.StoreKey], [][]byte{}},
{app.keys[mint.StoreKey], newApp.keys[mint.StoreKey], [][]byte{}},
+4 -7
View File
@@ -38,20 +38,17 @@ func DiffKVStores(a KVStore, b KVStore, prefixesToSkip [][]byte) (kvAs, kvBs []t
kvB = tmkv.Pair{Key: iterB.Key(), Value: iterB.Value()}
iterB.Next()
}
if !bytes.Equal(kvA.Key, kvB.Key) {
kvAs = append(kvAs, kvA)
kvBs = append(kvBs, kvB)
continue // no need to compare the value
}
compareValue := true
for _, prefix := range prefixesToSkip {
// Skip value comparison if we matched a prefix
if bytes.Equal(kvA.Key[:len(prefix)], prefix) {
if bytes.HasPrefix(kvA.Key, prefix) || bytes.HasPrefix(kvB.Key, prefix) {
compareValue = false
break
}
}
if compareValue && !bytes.Equal(kvA.Value, kvB.Value) {
if compareValue && (!bytes.Equal(kvA.Key, kvB.Key) || !bytes.Equal(kvA.Value, kvB.Value)) {
kvAs = append(kvAs, kvA)
kvBs = append(kvBs, kvB)
}
-1
View File
@@ -12,7 +12,6 @@ const (
DefaultParamspace = keeper.DefaultParamspace
ModuleName = types.ModuleName
StoreKey = types.StoreKey
TStoreKey = types.TStoreKey
QuerierRoute = types.QuerierRoute
RouterKey = types.RouterKey
DefaultUnbondingTime = types.DefaultUnbondingTime
+4 -8
View File
@@ -144,10 +144,6 @@ func InitGenesis(
// GenesisState will contain the pool, params, validators, and bonds found in
// the keeper.
func ExportGenesis(ctx sdk.Context, keeper Keeper) types.GenesisState {
params := keeper.GetParams(ctx)
lastTotalPower := keeper.GetLastTotalPower(ctx)
validators := keeper.GetAllValidators(ctx)
delegations := keeper.GetAllDelegations(ctx)
var unbondingDelegations []types.UnbondingDelegation
keeper.IterateUnbondingDelegations(ctx, func(_ int64, ubd types.UnbondingDelegation) (stop bool) {
unbondingDelegations = append(unbondingDelegations, ubd)
@@ -165,11 +161,11 @@ func ExportGenesis(ctx sdk.Context, keeper Keeper) types.GenesisState {
})
return types.GenesisState{
Params: params,
LastTotalPower: lastTotalPower,
Params: keeper.GetParams(ctx),
LastTotalPower: keeper.GetLastTotalPower(ctx),
LastValidatorPowers: lastValidatorPowers,
Validators: validators,
Delegations: delegations,
Validators: keeper.GetAllValidators(ctx),
Delegations: keeper.GetAllDelegations(ctx),
UnbondingDelegations: unbondingDelegations,
Redelegations: redelegations,
Exported: true,
+26
View File
@@ -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) {
+29
View File
@@ -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
View File
@@ -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())
}
+6
View File
@@ -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]))
}
+4
View File
@@ -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"
@@ -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())},
@@ -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}},
}
@@ -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 {
-3
View File
@@ -15,9 +15,6 @@ const (
// StoreKey is the string store representation
StoreKey = ModuleName
// TStoreKey is the string transient store representation
TStoreKey = "transient_" + ModuleName
// QuerierRoute is the querier route for the staking module
QuerierRoute = ModuleName