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:
@@ -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
|
||||
|
||||
@@ -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
@@ -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
|
||||
|
||||
@@ -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{}},
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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())
|
||||
}
|
||||
|
||||
@@ -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]))
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
Reference in New Issue
Block a user