Skip to content

Commit

Permalink
x
Browse files Browse the repository at this point in the history
(cherry picked from commit 84cb36b3beaf80b2ad61cd1010156d96c38d24a6)
  • Loading branch information
alpe committed Jul 12, 2024
1 parent ab6400f commit e87b5c6
Show file tree
Hide file tree
Showing 123 changed files with 3,560 additions and 9,331 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -63,3 +63,4 @@ debug_container.log
*.synctex.gz
/x/genutil/config/priv_validator_key.json
/x/genutil/data/priv_validator_state.json
simapp/simapp.test
6 changes: 6 additions & 0 deletions baseapp/test_helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,12 @@ func (app *BaseApp) SimDeliver(txEncoder sdk.TxEncoder, tx sdk.Tx) (sdk.GasInfo,
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 {
Expand Down
29 changes: 1 addition & 28 deletions scripts/build/simulations.mk
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ test-sim-multi-seed-long:
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 \
-NumBlocks=50 -Period=10
-NumBlocks=50 -Period=10 -FauxMerkle=true

test-sim-benchmark-invariants:
@echo "Running simulation invariant benchmarks..."
Expand Down Expand Up @@ -85,39 +85,12 @@ test-sim-benchmark:
@cd ${CURRENT_DIR}/simapp && go test -mod=readonly -tags='sims' -run=^$$ $(.) -bench ^BenchmarkFullAppSimulation$$ \
-Enabled=true -NumBlocks=$(SIM_NUM_BLOCKS) -BlockSize=$(SIM_BLOCK_SIZE) -Commit=$(SIM_COMMIT) -timeout 24h

# Requires an exported plugin. See store/streaming/README.md for documentation.
#
# example:
# export COSMOS_SDK_ABCI_V1=<path-to-plugin-binary>
# make test-sim-benchmark-streaming
#
# Using the built-in examples:
# export COSMOS_SDK_ABCI_V1=<path-to-sdk>/store/streaming/abci/examples/file/file
# 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 -tags='sims' -run=^$$ $(.) -bench ^BenchmarkFullAppSimulation$$ \
-Enabled=true -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 -tags='sims' -benchmem -run=^$$ $(.) -bench ^BenchmarkFullAppSimulation$$ \
-Enabled=true -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.
#
# example:
# export COSMOS_SDK_ABCI_V1=<path-to-plugin-binary>
# make test-sim-profile-streaming
#
# Using the built-in examples:
# export COSMOS_SDK_ABCI_V1=<path-to-sdk>/store/streaming/abci/examples/file/file
# 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 -tags='sims' -benchmem -run=^$$ $(.) -bench ^BenchmarkFullAppSimulation$$ \
-Enabled=true -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

#? benchmark: Run benchmark tests
Expand Down
10 changes: 5 additions & 5 deletions simapp/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -442,15 +442,15 @@ func NewSimApp(
auth.NewAppModule(appCodec, app.AuthKeeper, app.AccountsKeeper, authsims.RandomGenesisAccounts),
vesting.NewAppModule(app.AuthKeeper, app.BankKeeper),
bank.NewAppModule(appCodec, app.BankKeeper, app.AuthKeeper),
feegrantmodule.NewAppModule(appCodec, app.AuthKeeper, app.BankKeeper, app.FeeGrantKeeper, app.interfaceRegistry),
feegrantmodule.NewAppModule(appCodec, app.FeeGrantKeeper, app.interfaceRegistry),
gov.NewAppModule(appCodec, &app.GovKeeper, app.AuthKeeper, app.BankKeeper, app.PoolKeeper),
mint.NewAppModule(appCodec, app.MintKeeper, app.AuthKeeper, nil),
slashing.NewAppModule(appCodec, app.SlashingKeeper, app.AuthKeeper, app.BankKeeper, app.StakingKeeper, app.interfaceRegistry, cometService),
distr.NewAppModule(appCodec, app.DistrKeeper, app.AuthKeeper, app.BankKeeper, app.StakingKeeper, app.PoolKeeper),
staking.NewAppModule(appCodec, app.StakingKeeper, app.AuthKeeper, app.BankKeeper),
distr.NewAppModule(appCodec, app.DistrKeeper, app.StakingKeeper),
staking.NewAppModule(appCodec, app.StakingKeeper),
upgrade.NewAppModule(app.UpgradeKeeper),
evidence.NewAppModule(appCodec, app.EvidenceKeeper, cometService),
authzmodule.NewAppModule(appCodec, app.AuthzKeeper, app.AuthKeeper, app.BankKeeper, app.interfaceRegistry),
authzmodule.NewAppModule(appCodec, app.AuthzKeeper, app.interfaceRegistry),
groupmodule.NewAppModule(appCodec, app.GroupKeeper, app.AuthKeeper, app.BankKeeper, app.interfaceRegistry),
nftmodule.NewAppModule(appCodec, app.NFTKeeper, app.AuthKeeper, app.BankKeeper, app.interfaceRegistry),
consensus.NewAppModule(appCodec, app.ConsensusParamsKeeper),
Expand Down Expand Up @@ -533,7 +533,7 @@ func NewSimApp(
overrideModules := map[string]module.AppModuleSimulation{
authtypes.ModuleName: auth.NewAppModule(app.appCodec, app.AuthKeeper, app.AccountsKeeper, authsims.RandomGenesisAccounts),
}
app.sm = module.NewSimulationManagerFromAppModules(app.ModuleManager.Modules, overrideModules)
app.sm = module.NewSimulationManagerFromAppModules(app.AuthKeeper, app.BankKeeper, app.ModuleManager.Modules, overrideModules)

// create, start, and load the unordered tx manager
utxDataDir := filepath.Join(homePath, "data")
Expand Down
2 changes: 1 addition & 1 deletion simapp/app_di.go
Original file line number Diff line number Diff line change
Expand Up @@ -277,7 +277,7 @@ func NewSimApp(
overrideModules := map[string]module.AppModuleSimulation{
authtypes.ModuleName: auth.NewAppModule(app.appCodec, app.AuthKeeper, &app.AccountsKeeper, authsims.RandomGenesisAccounts),
}
app.sm = module.NewSimulationManagerFromAppModules(app.ModuleManager.Modules, overrideModules)
app.sm = module.NewSimulationManagerFromAppModules(app.AuthKeeper, app.BankKeeper, app.ModuleManager.Modules, overrideModules)

app.sm.RegisterStoreDecoders()

Expand Down
69 changes: 1 addition & 68 deletions simapp/sim_bench_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,33 +3,13 @@
package simapp

import (
"os"
"testing"

"github.com/cosmos/cosmos-sdk/testutils/sims"

"cosmossdk.io/core/log"

flag "github.com/spf13/pflag"
"github.com/spf13/viper"
"github.com/stretchr/testify/require"

"github.com/cosmos/cosmos-sdk/baseapp"
"github.com/cosmos/cosmos-sdk/client/flags"
"github.com/cosmos/cosmos-sdk/server"
simtestutil "github.com/cosmos/cosmos-sdk/testutil/sims"
simtypes "github.com/cosmos/cosmos-sdk/types/simulation"
"github.com/cosmos/cosmos-sdk/x/simulation"
simcli "github.com/cosmos/cosmos-sdk/x/simulation/client/cli"
)

var FlagEnableBenchStreamingValue bool

// Get flags every time the simulator is run
func init() {
flag.BoolVar(&FlagEnableBenchStreamingValue, "EnableStreaming", false, "Enable streaming service")
}

// Profile with:
// /usr/local/go/bin/go test -benchmem -run=^$ cosmossdk.io/simapp -bench ^BenchmarkFullAppSimulation$ -Commit=true -cpuprofile cpu.out
func BenchmarkFullAppSimulation(b *testing.B) {
Expand All @@ -38,52 +18,5 @@ func BenchmarkFullAppSimulation(b *testing.B) {
config := simcli.NewConfigFromFlags()
config.ChainID = sims.SimAppChainID

db, dir, logger, skip, err := simtestutil.SetupSimulation(config, "goleveldb-app-sim", "Simulation", simcli.FlagVerboseValue, simcli.FlagEnabledValue)
if err != nil {
b.Fatalf("simulation setup failed: %s", err.Error())
}

if skip {
b.Skip("skipping benchmark application simulation")
}

defer func() {
require.NoError(b, db.Close())
require.NoError(b, os.RemoveAll(dir))
}()

appOptions := viper.New()
appOptions.SetDefault(flags.FlagHome, DefaultNodeHome)
appOptions.SetDefault(server.FlagInvCheckPeriod, simcli.FlagPeriodValue)

app := NewSimApp(logger, db, nil, true, appOptions, interBlockCacheOpt(), baseapp.SetChainID(sims.SimAppChainID))

// run randomized simulation
simParams, simErr := simulation.SimulateFromSeedX(
b,
log.NewNopLogger(),
os.Stdout,
app.BaseApp,
simtestutil.AppStateFn(app.AppCodec(), app.AuthKeeper.AddressCodec(), app.StakingKeeper.ValidatorAddressCodec(), app.SimulationManager(), app.DefaultGenesis()),
simtypes.RandomAccounts,
simtestutil.SimulationOperations(app, app.AppCodec(), config, app.txConfig),
BlockedAddresses(),
config,
app.AppCodec(),
app.txConfig.SigningContext().AddressCodec(),
&simulation.DummyLogWriter{},
)

// export state and simParams before the simulation error is checked
if err = simtestutil.CheckExportSimulation(app, config, simParams); err != nil {
b.Fatal(err)
}

if simErr != nil {
b.Fatal(simErr)
}

if config.Commit {
simtestutil.PrintStats(db)
}
sims.RunWithSeed(b, config, NewSimApp, setupStateFactory, 1, nil)
}
59 changes: 27 additions & 32 deletions simapp/sim_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (
"strings"
"sync"
"testing"
"time"

"cosmossdk.io/log"
"cosmossdk.io/store"
Expand Down Expand Up @@ -63,12 +64,12 @@ func setupStateFactory(app *SimApp) sims.SimStateFactory {
}

var (
exportAllModules = []string{}
exportWithValidatorSet = []string{}
exportAllModules []string
exportWithValidatorSet []string
)

func TestAppImportExport(t *testing.T) {
sims.Run(t, NewSimApp, setupStateFactory, func(t *testing.T, ti sims.TestInstance[*SimApp]) {
sims.Run(t, NewSimApp, setupStateFactory, func(t testing.TB, ti sims.TestInstance[*SimApp]) {
app := ti.App
t.Log("exporting genesis...\n")
exported, err := app.ExportAppStateAndValidators(false, exportWithValidatorSet, exportAllModules)
Expand Down Expand Up @@ -110,40 +111,34 @@ func TestAppImportExport(t *testing.T) {
// set up a new node instance, Init chain from exported genesis
// run new instance for n blocks
func TestAppSimulationAfterImport(t *testing.T) {
sims.Run(t, NewSimApp, setupStateFactory, func(t *testing.T, ti sims.TestInstance[*SimApp]) {
sims.Run(t, NewSimApp, setupStateFactory, func(t testing.TB, ti sims.TestInstance[*SimApp]) {
app := ti.App
t.Log("exporting genesis...\n")
exported, err := app.ExportAppStateAndValidators(false, exportWithValidatorSet, exportAllModules)
require.NoError(t, err)

t.Log("importing genesis...\n")
newTestInstance := sims.NewSimulationAppInstance(t, ti.Cfg, NewSimApp)
newApp := newTestInstance.App
_, err = newApp.InitChain(&abci.InitChainRequest{
AppStateBytes: exported.AppState,
ChainId: sims.SimAppChainID,
})
if IsEmptyValidatorSetErr(err) {
t.Skip("Skipping simulation as all validators have been unbonded")
return
importGenesisStateFactory := func(app *SimApp) sims.SimStateFactory {
return sims.SimStateFactory{
Codec: app.AppCodec(),
AppStateFn: func(r *rand.Rand, accs []simtypes.Account, config simtypes.Config) (json.RawMessage, []simtypes.Account, string, time.Time) {
_, err = app.InitChain(&abci.InitChainRequest{
AppStateBytes: exported.AppState,
ChainId: sims.SimAppChainID,
})
if IsEmptyValidatorSetErr(err) {
t.Skip("Skipping simulation as all validators have been unbonded")
return nil, nil, "", time.Time{}
}
acc, err := simtestutil.AccountsFromAppState(app.AppCodec(), exported.AppState)
require.NoError(t, err)
genesisTimestamp := time.Unix(config.GenesisTime, 0)
return exported.AppState, acc, config.ChainID, genesisTimestamp
},
BlockedAddr: BlockedAddresses(),
}
}
require.NoError(t, err)
newStateFactory := setupStateFactory(newApp)
_, err = simulation.SimulateFromSeedX(
t,
newTestInstance.AppLogger,
sims.WriteToDebugLog(newTestInstance.AppLogger),
newApp.BaseApp,
newStateFactory.AppStateFn,
simtypes.RandomAccounts,
simtestutil.SimulationOperations(newApp, newApp.AppCodec(), newTestInstance.Cfg, newApp.TxConfig()),
newStateFactory.BlockedAddr,
newTestInstance.Cfg,
newStateFactory.Codec,
newApp.TxConfig().SigningContext().AddressCodec(),
ti.ExecLogWriter,
)
require.NoError(t, err)
sims.RunWithSeed(t, ti.Cfg, NewSimApp, importGenesisStateFactory, ti.Cfg.Seed, ti.Cfg.FuzzSeed)
})
}

Expand Down Expand Up @@ -189,7 +184,7 @@ func TestAppStateDeterminism(t *testing.T) {
var mx sync.Mutex
appHashResults := make(map[int64][][]byte)
appSimLogger := make(map[int64][]simulation.LogWriter)
captureAndCheckHash := func(t *testing.T, ti sims.TestInstance[*SimApp]) {
captureAndCheckHash := func(t testing.TB, ti sims.TestInstance[*SimApp]) {
seed, appHash := ti.Cfg.Seed, ti.App.LastCommitID().Hash
mx.Lock()
otherHashes, execWriters := appHashResults[seed], appSimLogger[seed]
Expand Down Expand Up @@ -225,7 +220,7 @@ type ComparableStoreApp interface {
GetStoreKeys() []storetypes.StoreKey
}

func AssertEqualStores(t *testing.T, app ComparableStoreApp, newApp ComparableStoreApp, storeDecoders simtypes.StoreDecoderRegistry, skipPrefixes map[string][][]byte) {
func AssertEqualStores(t testing.TB, app ComparableStoreApp, newApp ComparableStoreApp, storeDecoders simtypes.StoreDecoderRegistry, skipPrefixes map[string][][]byte) {
ctxA := app.NewContextLegacy(true, cmtproto.Header{Height: app.LastBlockHeight()})
ctxB := newApp.NewContextLegacy(true, cmtproto.Header{Height: app.LastBlockHeight()})

Expand Down
90 changes: 90 additions & 0 deletions simsx/delivery.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
package simsx

import (
"context"
"fmt"
"math/rand"

"github.com/cosmos/cosmos-sdk/client"
cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"
"github.com/cosmos/cosmos-sdk/testutil/sims"
sdk "github.com/cosmos/cosmos-sdk/types"
simtypes "github.com/cosmos/cosmos-sdk/types/simulation"
)

type (
// AppEntrypoint is an alias to the simtype interface
AppEntrypoint = simtypes.AppEntrypoint

AccountSource interface {
GetAccount(ctx context.Context, addr sdk.AccAddress) sdk.AccountI
}
// SimDeliveryResultHandler processes the delivery response error. Some sims are supposed to fail and expect an error.
// An unhandled error returned indicates a failure
SimDeliveryResultHandler func(error) error
)

// DeliverSimsMsg delivers a simulation message by creating and signing a mock transaction,
// then delivering it to the application through the specified entrypoint. It returns a legacy
// operation message representing the result of the delivery.
//
// The function takes the following parameters:
// - reporter: SimulationReporter - Interface for reporting the result of the delivery
// - r: *rand.Rand - Random number generator used for creating the mock transaction
// - app: AppEntrypoint - Entry point for delivering the simulation transaction to the application
// - txGen: client.TxConfig - Configuration for generating transactions
// - ak: AccountSource - Source for retrieving accounts
// - msg: sdk.Msg - The simulation message to be delivered
// - ctx: sdk.Context - The simulation context
// - chainID: string - The chain ID
// - senders: ...SimAccount - Accounts from which to send the simulation message
//
// The function returns a simtypes.OperationMsg, which is a legacy representation of the result
// of the delivery.
func DeliverSimsMsg(
ctx sdk.Context,
reporter SimulationReporter,
app AppEntrypoint,
r *rand.Rand,
txGen client.TxConfig,
ak AccountSource,
chainID string,
msg sdk.Msg,
deliveryResultHandler SimDeliveryResultHandler,
senders ...SimAccount,
) simtypes.OperationMsg {
if reporter.IsSkipped() {
return reporter.ToLegacyOperationMsg()
}
accountNumbers := make([]uint64, len(senders))
sequenceNumbers := make([]uint64, len(senders))
for i := 0; i < len(senders); i++ {
acc := ak.GetAccount(ctx, senders[i].Address)
accountNumbers[i] = acc.GetAccountNumber()
sequenceNumbers[i] = acc.GetSequence()
}

fees := senders[0].LiquidBalance().RandFees()
tx, err := sims.GenSignedMockTx(
r,
txGen,
[]sdk.Msg{msg},
fees,
sims.DefaultGenTxGas,
chainID,
accountNumbers,
sequenceNumbers,
Collect(senders, func(a SimAccount) cryptotypes.PrivKey { return a.PrivKey })...,
)
if err != nil {
reporter.Fail(err, "encoding TX")
return reporter.ToLegacyOperationMsg()
}
_, _, err = app.SimDeliver(txGen.TxEncoder(), tx)
if err2 := deliveryResultHandler(err); err2 != nil {
reporter.Fail(err2, fmt.Sprintf("delivering tx with msgs: %#v", tx.GetMsgs()))
return reporter.ToLegacyOperationMsg()
}
reporter.Success(msg)
return reporter.ToLegacyOperationMsg()
}
Loading

0 comments on commit e87b5c6

Please sign in to comment.