fix(sims): Minor fixes (#24095)

Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
Co-authored-by: Alex | Interchain Labs <alex@interchainlabs.io>
This commit is contained in:
Alexander Peters 2025-03-25 18:45:55 +01:00 committed by GitHub
parent 5254d57c5b
commit 7827aee97b
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 53 additions and 36 deletions

View File

@ -264,7 +264,7 @@ endif
test-sim-nondeterminism:
@echo "Running non-determinism test..."
@cd ${CURRENT_DIR}/simapp && go test -mod=readonly -timeout=30m -tags='sims' -run TestAppStateDeterminism \
@cd ${CURRENT_DIR}/simapp && go test -failfast -mod=readonly -timeout=30m -tags='sims' -run TestAppStateDeterminism \
-NumBlocks=100 -BlockSize=200 -Period=0
# Requires an exported plugin. See store/streaming/README.md for documentation.
@ -278,39 +278,39 @@ test-sim-nondeterminism:
# make test-sim-nondeterminism-streaming
test-sim-nondeterminism-streaming:
@echo "Running non-determinism-streaming test..."
@cd ${CURRENT_DIR}/simapp && go test -mod=readonly -timeout=30m -tags='sims' -run TestAppStateDeterminism \
@cd ${CURRENT_DIR}/simapp && go test -failfast -mod=readonly -timeout=30m -tags='sims' -run TestAppStateDeterminism \
-NumBlocks=100 -BlockSize=200 -Period=0 -EnableStreaming=true
test-sim-custom-genesis-fast:
@echo "Running custom genesis simulation..."
@echo "By default, ${HOME}/.simapp/config/genesis.json will be used."
@cd ${CURRENT_DIR}/simapp && go test -mod=readonly -timeout=30m -tags='sims' -run TestFullAppSimulation -Genesis=${HOME}/.simapp/config/genesis.json \
@cd ${CURRENT_DIR}/simapp && go test -failfast -mod=readonly -timeout=30m -tags='sims' -run TestFullAppSimulation -Genesis=${HOME}/.simapp/config/genesis.json \
-NumBlocks=100 -BlockSize=200 -Seed=99 -Period=5 -SigverifyTx=false
test-sim-import-export:
@echo "Running application import/export simulation. This may take several minutes..."
@cd ${CURRENT_DIR}/simapp && go test -mod=readonly -timeout 20m -tags='sims' -run TestAppImportExport \
@cd ${CURRENT_DIR}/simapp && go test -failfast -mod=readonly -timeout 20m -tags='sims' -run TestAppImportExport \
-NumBlocks=50 -Period=5
test-sim-after-import:
@echo "Running application simulation-after-import. This may take several minutes..."
@cd ${CURRENT_DIR}/simapp && go test -mod=readonly -timeout 30m -tags='sims' -run TestAppSimulationAfterImport \
@cd ${CURRENT_DIR}/simapp && go test -failfast -mod=readonly -timeout 30m -tags='sims' -run TestAppSimulationAfterImport \
-NumBlocks=50 -Period=5
test-sim-custom-genesis-multi-seed:
@echo "Running multi-seed custom genesis simulation..."
@echo "By default, ${HOME}/.simapp/config/genesis.json will be used."
@cd ${CURRENT_DIR}/simapp && go test -mod=readonly -timeout 30m -tags='sims' -run TestFullAppSimulation -Genesis=${HOME}/.simapp/config/genesis.json \
@cd ${CURRENT_DIR}/simapp && go test -failfast -mod=readonly -timeout 30m -tags='sims' -run TestFullAppSimulation -Genesis=${HOME}/.simapp/config/genesis.json \
-NumBlocks=400 -Period=5
test-sim-multi-seed-long:
@echo "Running long multi-seed application simulation. This may take awhile!"
@cd ${CURRENT_DIR}/simapp && go test -mod=readonly -timeout=1h -tags='sims' -run TestFullAppSimulation \
@cd ${CURRENT_DIR}/simapp && go test -failfast -mod=readonly -timeout=1h -tags='sims' -run TestFullAppSimulation \
-NumBlocks=500 -Period=50
test-sim-multi-seed-short:
@echo "Running short multi-seed application simulation. This may take awhile!"
@cd ${CURRENT_DIR}/simapp && go test -mod=readonly -timeout 30m -tags='sims' -run TestFullAppSimulation \
@cd ${CURRENT_DIR}/simapp && go test -failfast -mod=readonly -timeout 30m -tags='sims' -run TestFullAppSimulation \
-NumBlocks=50 -Period=10
.PHONY: \
@ -331,12 +331,12 @@ SIM_COMMIT ?= true
test-sim-fuzz:
@echo "Running application fuzz for numBlocks=2, blockSize=20. This may take awhile!"
#ld flags are a quick fix to make it work on current osx
@cd ${CURRENT_DIR}/simapp && go test -mod=readonly -json -tags='sims' -ldflags="-extldflags=-Wl,-ld_classic" -timeout=60m -fuzztime=60m -run=^$$ -fuzz=FuzzFullAppSimulation -GenesisTime=1714720615 -NumBlocks=2 -BlockSize=20
@cd ${CURRENT_DIR}/simapp && go test -failfast -mod=readonly -json -tags='sims' -ldflags="-extldflags=-Wl,-ld_classic" -timeout=60m -fuzztime=60m -run=^$$ -fuzz=FuzzFullAppSimulation -GenesisTime=1714720615 -NumBlocks=2 -BlockSize=20
#? test-sim-benchmark: Run benchmark test for simapp
test-sim-benchmark:
@echo "Running application benchmark for numBlocks=$(SIM_NUM_BLOCKS), blockSize=$(SIM_BLOCK_SIZE). This may take awhile!"
@cd ${CURRENT_DIR}/simapp && go test -mod=readonly -tags='sims' -run=^$$ $(.) -bench ^BenchmarkFullAppSimulation$$ \
@cd ${CURRENT_DIR}/simapp && go test -failfast -mod=readonly -tags='sims' -run=^$$ $(.) -bench ^BenchmarkFullAppSimulation$$ \
-NumBlocks=$(SIM_NUM_BLOCKS) -BlockSize=$(SIM_BLOCK_SIZE) -Commit=$(SIM_COMMIT) -Seed=57 -timeout 30m
# Requires an exported plugin. See store/streaming/README.md for documentation.
@ -350,12 +350,12 @@ test-sim-benchmark:
# make test-sim-benchmark-streaming
test-sim-benchmark-streaming:
@echo "Running application benchmark for numBlocks=$(SIM_NUM_BLOCKS), blockSize=$(SIM_BLOCK_SIZE). This may take awhile!"
@cd ${CURRENT_DIR}/simapp && go test -mod=readonly -run=^$$ $(.) -bench ^BenchmarkFullAppSimulation$$ \
@cd ${CURRENT_DIR}/simapp && go test -failfast -mod=readonly -run=^$$ $(.) -bench ^BenchmarkFullAppSimulation$$ \
-NumBlocks=$(SIM_NUM_BLOCKS) -BlockSize=$(SIM_BLOCK_SIZE) -Commit=$(SIM_COMMIT) -timeout 24h -EnableStreaming=true
test-sim-profile:
@echo "Running application benchmark for numBlocks=$(SIM_NUM_BLOCKS), blockSize=$(SIM_BLOCK_SIZE). This may take awhile!"
@cd ${CURRENT_DIR}/simapp && go test -mod=readonly -benchmem -run=^$$ $(.) -bench ^BenchmarkFullAppSimulation$$ \
@cd ${CURRENT_DIR}/simapp && go test -failfast -mod=readonly -benchmem -run=^$$ $(.) -bench ^BenchmarkFullAppSimulation$$ \
-NumBlocks=$(SIM_NUM_BLOCKS) -BlockSize=$(SIM_BLOCK_SIZE) -Commit=$(SIM_COMMIT) -timeout 24h -cpuprofile cpu.out -memprofile mem.out
# Requires an exported plugin. See store/streaming/README.md for documentation.
@ -369,7 +369,7 @@ test-sim-profile:
# make test-sim-profile-streaming
test-sim-profile-streaming:
@echo "Running application benchmark for numBlocks=$(SIM_NUM_BLOCKS), blockSize=$(SIM_BLOCK_SIZE). This may take awhile!"
@cd ${CURRENT_DIR}/simapp && go test -mod=readonly -benchmem -run=^$$ $(.) -bench ^BenchmarkFullAppSimulation$$ \
@cd ${CURRENT_DIR}/simapp && go test -failfast -mod=readonly -benchmem -run=^$$ $(.) -bench ^BenchmarkFullAppSimulation$$ \
-NumBlocks=$(SIM_NUM_BLOCKS) -BlockSize=$(SIM_BLOCK_SIZE) -Commit=$(SIM_COMMIT) -timeout 24h -cpuprofile cpu.out -memprofile mem.out -EnableStreaming=true
.PHONY: test-sim-profile test-sim-benchmark test-sim-fuzz

View File

@ -51,6 +51,12 @@ func (app *BaseApp) SimTxFinalizeBlock(txEncoder sdk.TxEncoder, tx sdk.Tx) (sdk.
return gasInfo, result, err
}
// SimWriteState is an entrypoint for simulations only. They are not executed during the normal ABCI finalize
// block step but later. Therefor an extra call to the root multi-store (app.cms) is required to write the changes.
func (app *BaseApp) SimWriteState() {
app.finalizeBlockState.ms.Write()
}
// NewContextLegacy returns a new sdk.Context with the provided header
func (app *BaseApp) NewContextLegacy(isCheckTx bool, header cmtproto.Header) sdk.Context {
if isCheckTx {

View File

@ -180,7 +180,7 @@ func TestAppStateDeterminism(t *testing.T) {
"streaming.abci.stop-node-on-err": true,
}
others := appOpts
appOpts = sims.AppOptionsFn(func(k string) any {
appOpts = appOptionsFn(func(k string) any {
if v, ok := m[k]; ok {
return v
}
@ -262,6 +262,19 @@ func AssertEqualStores(t *testing.T, app, newApp ComparableStoreApp, storeDecode
}
}
// appOptionsFn is an adapter to the single method AppOptions interface
type appOptionsFn func(string) any
func (f appOptionsFn) Get(k string) any {
return f(k)
}
// FauxMerkleModeOpt returns a BaseApp option to use a dbStoreAdapter instead of
// an IAVLStore for faster simulation speed.
func FauxMerkleModeOpt(bapp *baseapp.BaseApp) {
bapp.SetFauxMerkleMode()
}
func FuzzFullAppSimulation(f *testing.F) {
f.Fuzz(func(t *testing.T, rawSeed []byte) {
if len(rawSeed) < 8 {

View File

@ -3,6 +3,7 @@ package sims
import (
"fmt"
"io"
"os"
"path/filepath"
"strings"
"testing"
@ -49,6 +50,7 @@ type SimulationApp interface {
SetNotSigverifyTx()
GetBaseApp() *baseapp.BaseApp
TxConfig() client.TxConfig
Close() error
}
// Run is a helper function that runs a simulation test with the given parameters.
@ -141,6 +143,7 @@ func RunWithSeeds[T SimulationApp](
for _, step := range postRunActions {
step(t, testInstance)
}
require.NoError(t, app.Close())
})
}
}
@ -174,6 +177,8 @@ func NewSimulationAppInstance[T SimulationApp](
) TestInstance[T] {
t.Helper()
workDir := t.TempDir()
require.NoError(t, os.Mkdir(filepath.Join(workDir, "data"), 0o755))
dbDir := filepath.Join(workDir, "leveldb-app-sim")
var logger log.Logger
if cli.FlagVerboseValue {
@ -186,7 +191,7 @@ func NewSimulationAppInstance[T SimulationApp](
db, err := dbm.NewDB("Simulation", dbm.BackendType(tCfg.DBBackend), dbDir)
require.NoError(t, err)
t.Cleanup(func() {
require.NoError(t, db.Close())
_ = db.Close() // ensure db is closed
})
appOptions := make(simtestutil.AppOptionsMap)
appOptions[flags.FlagHome] = workDir
@ -220,16 +225,3 @@ func WriteToDebugLog(logger log.Logger) io.Writer {
return len(p), nil
})
}
// AppOptionsFn is an adapter to the single method AppOptions interface
type AppOptionsFn func(string) any
func (f AppOptionsFn) Get(k string) any {
return f(k)
}
// FauxMerkleModeOpt returns a BaseApp option to use a dbStoreAdapter instead of
// an IAVLStore for faster simulation speed.
func FauxMerkleModeOpt(bapp *baseapp.BaseApp) {
bapp.SetFauxMerkleMode()
}

View File

@ -243,6 +243,7 @@ func SimulateFromSeedX(
proposerAddress = validators.randomProposer(r)
if config.Commit {
app.SimWriteState()
if _, err := app.Commit(); err != nil {
return params, fmt.Errorf("commit failed at height %d: %w", blockHeight, err)
}
@ -342,10 +343,10 @@ func createBlockSimulator(tb testing.TB, printProgress bool, w io.Writer, params
if err != nil {
logWriter.PrintLogs()
tb.Fatalf(`error on block %d/%d, operation (%d/%d) from x/%s:
tb.Fatalf(`error on block %d/%d, operation (%d/%d) from x/%s for msg %q:
%v
Comment: %s`,
header.Height, config.NumBlocks, opCount, blocksize, opMsg.Route, err, opMsg.Comment)
header.Height, config.NumBlocks, opCount, blocksize, opMsg.Route, opMsg.Name, err, opMsg.Comment)
}
queueOperations(operationQueue, timeOperationQueue, futureOps)

View File

@ -90,20 +90,20 @@ func SimulateMsgUnjail(
consAddr, err := validator.GetConsAddr()
if err != nil {
return simtypes.NoOpMsg(types.ModuleName, msgType, "unable to get validator consensus key"), nil, err
return simtypes.NoOpMsg(types.ModuleName, msgType, "unable to get validator consensus key"), nil, nil
}
info, err := k.GetValidatorSigningInfo(ctx, consAddr)
if err != nil {
return simtypes.NoOpMsg(types.ModuleName, msgType, "unable to find validator signing info"), nil, err // skip
return simtypes.NoOpMsg(types.ModuleName, msgType, "unable to find validator signing info"), nil, nil
}
selfDel, err := sk.Delegation(ctx, simAccount.Address, bz)
if err != nil {
return simtypes.NoOpMsg(types.ModuleName, msgType, "unable to get self delegation"), nil, err
return simtypes.NoOpMsg(types.ModuleName, msgType, "unable to get self delegation"), nil, nil
}
if selfDel == nil {
return simtypes.NoOpMsg(types.ModuleName, msgType, "self delegation is nil"), nil, nil // skip
return simtypes.NoOpMsg(types.ModuleName, msgType, "self delegation is nil"), nil, nil
}
account := ak.GetAccount(ctx, sdk.AccAddress(bz))
@ -111,7 +111,7 @@ func SimulateMsgUnjail(
fees, err := simtypes.RandomFees(r, ctx, spendable)
if err != nil {
return simtypes.NoOpMsg(types.ModuleName, msgType, "unable to generate fees"), nil, err
return simtypes.NoOpMsg(types.ModuleName, msgType, "unable to generate fees"), nil, nil
}
msg := types.NewMsgUnjail(validator.GetOperator())
@ -139,6 +139,7 @@ func SimulateMsgUnjail(
// - self delegation too low
if info.Tombstoned ||
ctx.BlockHeader().Time.Before(info.JailedUntil) ||
selfDel.GetShares().IsNil() ||
validator.TokensFromShares(selfDel.GetShares()).TruncateInt().LT(validator.GetMinSelfDelegation()) {
if res != nil && err == nil {
if info.Tombstoned {
@ -147,7 +148,8 @@ func SimulateMsgUnjail(
if ctx.BlockHeader().Time.Before(info.JailedUntil) {
return simtypes.NewOperationMsg(msg, true, ""), nil, errors.New("validator unjailed while validator still in jail period")
}
if validator.TokensFromShares(selfDel.GetShares()).TruncateInt().LT(validator.GetMinSelfDelegation()) {
if selfDel.GetShares().IsNil() ||
validator.TokensFromShares(selfDel.GetShares()).TruncateInt().LT(validator.GetMinSelfDelegation()) {
return simtypes.NewOperationMsg(msg, true, ""), nil, errors.New("validator unjailed even though self-delegation too low")
}
}

View File

@ -649,6 +649,9 @@ func SimulateMsgBeginRedelegate(
if redAmt.IsZero() {
return simtypes.NoOpMsg(types.ModuleName, msgType, "amount is zero"), nil, nil
}
if totalBond.Sub(redAmt).IsZero() {
return simtypes.NoOpMsg(types.ModuleName, msgType, "can not redelegate all"), nil, nil
}
// check if the shares truncate to zero
shares, err := srcVal.SharesFromTokens(redAmt)