From 9ce62b28517317314848acfb4f2b6dce499807dc Mon Sep 17 00:00:00 2001 From: Julien Robert Date: Thu, 19 Dec 2024 16:00:37 +0100 Subject: [PATCH] test: investigate test failure due to wal log (#22679) (cherry picked from commit a9c1149155e498a41f4b68a5694027a3f3f9f059) # Conflicts: # server/v2/api/telemetry/config.go # server/v2/stf/stf_test.go # server/v2/store/commands.go # server/v2/store/snapshot.go # server/v2/testdata/app.toml # store/v2/db/pebbledb.go # systemtests/CHANGELOG.md # systemtests/system.go # systemtests/testnet_init.go # tests/go.mod # tests/systemtests/go.mod # tests/systemtests/go.sum # x/accounts/go.mod # x/authz/go.mod # x/bank/go.mod # x/staking/go.mod --- client/pruning/main.go | 4 +- client/snapshot/export.go | 8 +- client/snapshot/list.go | 5 + client/snapshot/restore.go | 7 +- client/v2/go.mod | 2 +- client/v2/go.sum | 4 +- go.mod | 2 +- go.sum | 4 +- server/cmt_cmds.go | 4 +- server/v2/api/telemetry/config.go | 61 ++ server/v2/cometbft/go.sum | 4 +- server/v2/stf/stf_test.go | 512 +++++++++++++++ server/v2/store/commands.go | 87 +++ server/v2/store/snapshot.go | 420 ++++++++++++ server/v2/testdata/app.toml | 42 ++ simapp/go.mod | 2 +- simapp/go.sum | 4 +- simapp/v2/go.mod | 2 +- simapp/v2/go.sum | 4 +- store/v2/db/pebbledb.go | 314 +++++++++ systemtests/CHANGELOG.md | 57 ++ systemtests/system.go | 987 ++++++++++++++++++++++++++++ systemtests/testnet_init.go | 228 +++++++ tests/go.mod | 5 + tests/go.sum | 4 +- tests/systemtests/export_test.go | 22 +- tests/systemtests/go.mod | 5 + tests/systemtests/go.sum | 7 + tests/systemtests/snapshots_test.go | 23 +- tools/benchmark/go.sum | 4 +- tools/confix/data/v2-app.toml | 2 +- x/accounts/defaults/base/go.mod | 2 +- x/accounts/defaults/base/go.sum | 4 +- x/accounts/defaults/lockup/go.sum | 4 +- x/accounts/defaults/multisig/go.mod | 2 +- x/accounts/defaults/multisig/go.sum | 4 +- x/accounts/go.mod | 5 + x/accounts/go.sum | 4 +- x/authz/go.mod | 26 + x/authz/go.sum | 4 +- x/bank/go.mod | 24 + x/bank/go.sum | 4 +- x/circuit/go.mod | 2 +- x/circuit/go.sum | 4 +- x/consensus/go.mod | 2 +- x/consensus/go.sum | 4 +- x/distribution/go.mod | 2 +- x/distribution/go.sum | 4 +- x/epochs/go.mod | 2 +- x/epochs/go.sum | 4 +- x/evidence/go.mod | 2 +- x/evidence/go.sum | 4 +- x/feegrant/go.mod | 2 +- x/feegrant/go.sum | 4 +- x/gov/go.mod | 2 +- x/gov/go.sum | 4 +- x/group/go.mod | 2 +- x/group/go.sum | 4 +- x/mint/go.mod | 2 +- x/mint/go.sum | 4 +- x/nft/go.mod | 2 +- x/nft/go.sum | 4 +- x/params/go.sum | 4 +- x/protocolpool/go.mod | 2 +- x/protocolpool/go.sum | 4 +- x/slashing/go.mod | 2 +- x/slashing/go.sum | 4 +- x/staking/go.mod | 5 + x/staking/go.sum | 4 +- x/upgrade/go.mod | 2 +- x/upgrade/go.sum | 4 +- 71 files changed, 2894 insertions(+), 116 deletions(-) create mode 100644 server/v2/api/telemetry/config.go create mode 100644 server/v2/stf/stf_test.go create mode 100644 server/v2/store/commands.go create mode 100644 server/v2/store/snapshot.go create mode 100644 server/v2/testdata/app.toml create mode 100644 store/v2/db/pebbledb.go create mode 100644 systemtests/CHANGELOG.md create mode 100644 systemtests/system.go create mode 100644 systemtests/testnet_init.go diff --git a/client/pruning/main.go b/client/pruning/main.go index 0168308ea325..cc50bc612ca4 100644 --- a/client/pruning/main.go +++ b/client/pruning/main.go @@ -10,10 +10,10 @@ import ( "github.com/spf13/viper" corestore "cosmossdk.io/core/store" - "cosmossdk.io/log" pruningtypes "cosmossdk.io/store/pruning/types" "cosmossdk.io/store/rootmulti" + "github.com/cosmos/cosmos-sdk/client" "github.com/cosmos/cosmos-sdk/client/flags" "github.com/cosmos/cosmos-sdk/server" servertypes "github.com/cosmos/cosmos-sdk/server/types" @@ -78,7 +78,7 @@ Supported app-db-backend types include 'goleveldb', 'rocksdb', 'pebbledb'.`, // in our test, it's important to close db explicitly for pebbledb to write to disk. defer db.Close() - logger := log.NewLogger(cmd.OutOrStdout()) + logger := client.GetLoggerFromCmd(cmd) app := appCreator(logger, db, nil, vp) cms := app.CommitMultiStore() diff --git a/client/snapshot/export.go b/client/snapshot/export.go index 30f573676d33..42ec84b32d86 100644 --- a/client/snapshot/export.go +++ b/client/snapshot/export.go @@ -3,9 +3,8 @@ package snapshot import ( "github.com/spf13/cobra" - "cosmossdk.io/log" - "github.com/cosmos/cosmos-sdk/client" + "github.com/cosmos/cosmos-sdk/client/flags" "github.com/cosmos/cosmos-sdk/server" servertypes "github.com/cosmos/cosmos-sdk/server/types" ) @@ -17,20 +16,19 @@ func ExportSnapshotCmd[T servertypes.Application](appCreator servertypes.AppCrea Short: "Export app state to snapshot store", Args: cobra.NoArgs, RunE: func(cmd *cobra.Command, args []string) error { - cfg := client.GetConfigFromCmd(cmd) viper := client.GetViperFromCmd(cmd) + logger := client.GetLoggerFromCmd(cmd) height, err := cmd.Flags().GetInt64("height") if err != nil { return err } - home := cfg.RootDir + home := viper.GetString(flags.FlagHome) db, err := openDB(home, server.GetAppDBBackend(viper)) if err != nil { return err } - logger := log.NewLogger(cmd.OutOrStdout()) app := appCreator(logger, db, nil, viper) if height == 0 { diff --git a/client/snapshot/list.go b/client/snapshot/list.go index 43ff31cfd4ac..1d564c44f5cc 100644 --- a/client/snapshot/list.go +++ b/client/snapshot/list.go @@ -23,6 +23,11 @@ var ListSnapshotsCmd = &cobra.Command{ if err != nil { return fmt.Errorf("failed to list snapshots: %w", err) } + + if len(snapshots) == 0 { + cmd.Println("no snapshots found") + } + for _, snapshot := range snapshots { cmd.Println("height:", snapshot.Height, "format:", snapshot.Format, "chunks:", snapshot.Chunks) } diff --git a/client/snapshot/restore.go b/client/snapshot/restore.go index 3cb6e4154e25..db32801bf10e 100644 --- a/client/snapshot/restore.go +++ b/client/snapshot/restore.go @@ -8,9 +8,9 @@ import ( "github.com/spf13/cobra" corestore "cosmossdk.io/core/store" - "cosmossdk.io/log" "github.com/cosmos/cosmos-sdk/client" + "github.com/cosmos/cosmos-sdk/client/flags" "github.com/cosmos/cosmos-sdk/server" servertypes "github.com/cosmos/cosmos-sdk/server/types" ) @@ -23,8 +23,8 @@ func RestoreSnapshotCmd[T servertypes.Application](appCreator servertypes.AppCre Long: "Restore app state from local snapshot", Args: cobra.ExactArgs(2), RunE: func(cmd *cobra.Command, args []string) error { - cfg := client.GetConfigFromCmd(cmd) viper := client.GetViperFromCmd(cmd) + logger := client.GetLoggerFromCmd(cmd) height, err := strconv.ParseUint(args[0], 10, 64) if err != nil { @@ -35,12 +35,11 @@ func RestoreSnapshotCmd[T servertypes.Application](appCreator servertypes.AppCre return err } - home := cfg.RootDir + home := viper.GetString(flags.FlagHome) db, err := openDB(home, server.GetAppDBBackend(viper)) if err != nil { return err } - logger := log.NewLogger(cmd.OutOrStdout()) app := appCreator(logger, db, nil, viper) sm := app.SnapshotManager() diff --git a/client/v2/go.mod b/client/v2/go.mod index 66557847cb5d..3d4da2cf41c1 100644 --- a/client/v2/go.mod +++ b/client/v2/go.mod @@ -61,7 +61,7 @@ require ( github.com/cometbft/cometbft-db v1.0.1 // indirect github.com/cometbft/cometbft/api v1.0.0 github.com/cosmos/btcutil v1.0.5 // indirect - github.com/cosmos/cosmos-db v1.1.0 // indirect + github.com/cosmos/cosmos-db v1.1.1 // indirect github.com/cosmos/go-bip39 v1.0.0 github.com/cosmos/gogogateway v1.2.0 // indirect github.com/cosmos/gogoproto v1.7.0 diff --git a/client/v2/go.sum b/client/v2/go.sum index 794a902122a8..456e6b5a4014 100644 --- a/client/v2/go.sum +++ b/client/v2/go.sum @@ -127,8 +127,8 @@ github.com/containerd/continuity v0.3.0/go.mod h1:wJEAIwKOm/pBZuBd0JmeTvnLquTB1A github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= github.com/cosmos/btcutil v1.0.5 h1:t+ZFcX77LpKtDBhjucvnOH8C2l2ioGsBNEQ3jef8xFk= github.com/cosmos/btcutil v1.0.5/go.mod h1:IyB7iuqZMJlthe2tkIFL33xPyzbFYP0XVdS8P5lUPis= -github.com/cosmos/cosmos-db v1.1.0 h1:KLHNVQ73h7vawXTpj9UJ7ZR2IXv51tsEHkQJJ9EBDzI= -github.com/cosmos/cosmos-db v1.1.0/go.mod h1:t7c4A6cfGdpUwwVxrQ0gQLeRQqGUBJu0yvE4F/26REg= +github.com/cosmos/cosmos-db v1.1.1 h1:FezFSU37AlBC8S98NlSagL76oqBRWq/prTPvFcEJNCM= +github.com/cosmos/cosmos-db v1.1.1/go.mod h1:AghjcIPqdhSLP/2Z0yha5xPH3nLnskz81pBx3tcVSAw= github.com/cosmos/cosmos-proto v1.0.0-beta.5 h1:eNcayDLpip+zVLRLYafhzLvQlSmyab+RC5W7ZfmxJLA= github.com/cosmos/cosmos-proto v1.0.0-beta.5/go.mod h1:hQGLpiIUloJBMdQMMWb/4wRApmI9hjHH05nefC0Ojec= github.com/cosmos/cosmos-sdk v0.52.0-rc.1 h1:HgHOUYbxvjvyiX5CQF4eLT0u1wvjxajwgClOGzAmNoQ= diff --git a/go.mod b/go.mod index 18a446197444..ead61d7bd464 100644 --- a/go.mod +++ b/go.mod @@ -22,7 +22,7 @@ require ( github.com/cometbft/cometbft v1.0.0 github.com/cometbft/cometbft/api v1.0.0 github.com/cosmos/btcutil v1.0.5 - github.com/cosmos/cosmos-db v1.1.0 + github.com/cosmos/cosmos-db v1.1.1 github.com/cosmos/cosmos-proto v1.0.0-beta.5 github.com/cosmos/go-bip39 v1.0.0 github.com/cosmos/gogogateway v1.2.0 diff --git a/go.sum b/go.sum index 18d2fc8adcf0..521f3076a532 100644 --- a/go.sum +++ b/go.sum @@ -118,8 +118,8 @@ github.com/containerd/continuity v0.3.0/go.mod h1:wJEAIwKOm/pBZuBd0JmeTvnLquTB1A github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= github.com/cosmos/btcutil v1.0.5 h1:t+ZFcX77LpKtDBhjucvnOH8C2l2ioGsBNEQ3jef8xFk= github.com/cosmos/btcutil v1.0.5/go.mod h1:IyB7iuqZMJlthe2tkIFL33xPyzbFYP0XVdS8P5lUPis= -github.com/cosmos/cosmos-db v1.1.0 h1:KLHNVQ73h7vawXTpj9UJ7ZR2IXv51tsEHkQJJ9EBDzI= -github.com/cosmos/cosmos-db v1.1.0/go.mod h1:t7c4A6cfGdpUwwVxrQ0gQLeRQqGUBJu0yvE4F/26REg= +github.com/cosmos/cosmos-db v1.1.1 h1:FezFSU37AlBC8S98NlSagL76oqBRWq/prTPvFcEJNCM= +github.com/cosmos/cosmos-db v1.1.1/go.mod h1:AghjcIPqdhSLP/2Z0yha5xPH3nLnskz81pBx3tcVSAw= github.com/cosmos/cosmos-proto v1.0.0-beta.5 h1:eNcayDLpip+zVLRLYafhzLvQlSmyab+RC5W7ZfmxJLA= github.com/cosmos/cosmos-proto v1.0.0-beta.5/go.mod h1:hQGLpiIUloJBMdQMMWb/4wRApmI9hjHH05nefC0Ojec= github.com/cosmos/go-bip39 v1.0.0 h1:pcomnQdrdH22njcAatO0yWojsUnCO3y2tNoV1cb6hHY= diff --git a/server/cmt_cmds.go b/server/cmt_cmds.go index 2aa5d0ca55c5..3a388e980b73 100644 --- a/server/cmt_cmds.go +++ b/server/cmt_cmds.go @@ -16,8 +16,6 @@ import ( "github.com/spf13/cobra" "sigs.k8s.io/yaml" - "cosmossdk.io/log" - "github.com/cosmos/cosmos-sdk/client" "github.com/cosmos/cosmos-sdk/client/flags" "github.com/cosmos/cosmos-sdk/client/rpc" @@ -370,7 +368,7 @@ func BootstrapStateCmd[T types.Application](appCreator types.AppCreator[T]) *cob Example: "bootstrap-state --height 1000000", RunE: func(cmd *cobra.Command, args []string) error { serverCtx := GetServerContextFromCmd(cmd) - logger := log.NewLogger(cmd.OutOrStdout()) + logger := client.GetLoggerFromCmd(cmd) cfg := serverCtx.Config height, err := cmd.Flags().GetInt64("height") diff --git a/server/v2/api/telemetry/config.go b/server/v2/api/telemetry/config.go new file mode 100644 index 000000000000..277b030c8a33 --- /dev/null +++ b/server/v2/api/telemetry/config.go @@ -0,0 +1,61 @@ +package telemetry + +func DefaultConfig() *Config { + return &Config{ + Enable: true, + Address: "localhost:7180", + ServiceName: "", + EnableHostname: false, + EnableHostnameLabel: false, + EnableServiceLabel: false, + PrometheusRetentionTime: 0, + GlobalLabels: nil, + MetricsSink: "", + StatsdAddr: "", + DatadogHostname: "", + } +} + +type Config struct { + // Enable enables the application telemetry functionality. When enabled, + // an in-memory sink is also enabled by default. Operators may also enabled + // other sinks such as Prometheus. + Enable bool `mapstructure:"enable" toml:"enable" comment:"Enable enables the application telemetry functionality. When enabled, an in-memory sink is also enabled by default. Operators may also enabled other sinks such as Prometheus."` + + // Address defines the API server to listen on + Address string `mapstructure:"address" toml:"address" comment:"Address defines the metrics server address to bind to."` + + // Prefixed with keys to separate services + ServiceName string `mapstructure:"service-name" toml:"service-name" comment:"Prefixed with keys to separate services."` + + // Enable prefixing gauge values with hostname + EnableHostname bool `mapstructure:"enable-hostname" toml:"enable-hostname" comment:"Enable prefixing gauge values with hostname."` + + // Enable adding hostname to labels + EnableHostnameLabel bool `mapstructure:"enable-hostname-label" toml:"enable-hostname-label" comment:"Enable adding hostname to labels."` + + // Enable adding service to labels + EnableServiceLabel bool `mapstructure:"enable-service-label" toml:"enable-service-label" comment:"Enable adding service to labels."` + + // PrometheusRetentionTime, when positive, enables a Prometheus metrics sink. + // It defines the retention duration in seconds. + PrometheusRetentionTime int64 `mapstructure:"prometheus-retention-time" toml:"prometheus-retention-time" comment:"PrometheusRetentionTime, when positive, enables a Prometheus metrics sink. It defines the retention duration in seconds."` + + // GlobalLabels defines a global set of name/value label tuples applied to all + // metrics emitted using the wrapper functions defined in telemetry package. + // + // Example: + // [["chain_id", "cosmoshub-1"]] + GlobalLabels [][]string `mapstructure:"global-labels" toml:"global-labels" comment:"GlobalLabels defines a global set of name/value label tuples applied to all metrics emitted using the wrapper functions defined in telemetry package.\n Example:\n [[\"chain_id\", \"cosmoshub-1\"]]"` + + // MetricsSink defines the type of metrics backend to use. + MetricsSink string `mapstructure:"type" toml:"metrics-sink" comment:"MetricsSink defines the type of metrics backend to use. Default is in memory"` + + // StatsdAddr defines the address of a statsd server to send metrics to. + // Only utilized if MetricsSink is set to "statsd" or "dogstatsd". + StatsdAddr string `mapstructure:"statsd-addr" toml:"stats-addr" comment:"StatsdAddr defines the address of a statsd server to send metrics to. Only utilized if MetricsSink is set to \"statsd\" or \"dogstatsd\"."` + + // DatadogHostname defines the hostname to use when emitting metrics to + // Datadog. Only utilized if MetricsSink is set to "dogstatsd". + DatadogHostname string `mapstructure:"datadog-hostname" toml:"data-dog-hostname" comment:"DatadogHostname defines the hostname to use when emitting metrics to Datadog. Only utilized if MetricsSink is set to \"dogstatsd\"."` +} diff --git a/server/v2/cometbft/go.sum b/server/v2/cometbft/go.sum index 8984a60f743c..8fd658acd1c0 100644 --- a/server/v2/cometbft/go.sum +++ b/server/v2/cometbft/go.sum @@ -133,8 +133,8 @@ github.com/containerd/continuity v0.3.0/go.mod h1:wJEAIwKOm/pBZuBd0JmeTvnLquTB1A github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= github.com/cosmos/btcutil v1.0.5 h1:t+ZFcX77LpKtDBhjucvnOH8C2l2ioGsBNEQ3jef8xFk= github.com/cosmos/btcutil v1.0.5/go.mod h1:IyB7iuqZMJlthe2tkIFL33xPyzbFYP0XVdS8P5lUPis= -github.com/cosmos/cosmos-db v1.1.0 h1:KLHNVQ73h7vawXTpj9UJ7ZR2IXv51tsEHkQJJ9EBDzI= -github.com/cosmos/cosmos-db v1.1.0/go.mod h1:t7c4A6cfGdpUwwVxrQ0gQLeRQqGUBJu0yvE4F/26REg= +github.com/cosmos/cosmos-db v1.1.1 h1:FezFSU37AlBC8S98NlSagL76oqBRWq/prTPvFcEJNCM= +github.com/cosmos/cosmos-db v1.1.1/go.mod h1:AghjcIPqdhSLP/2Z0yha5xPH3nLnskz81pBx3tcVSAw= github.com/cosmos/cosmos-proto v1.0.0-beta.5 h1:eNcayDLpip+zVLRLYafhzLvQlSmyab+RC5W7ZfmxJLA= github.com/cosmos/cosmos-proto v1.0.0-beta.5/go.mod h1:hQGLpiIUloJBMdQMMWb/4wRApmI9hjHH05nefC0Ojec= github.com/cosmos/cosmos-sdk v0.52.0-rc.1 h1:HgHOUYbxvjvyiX5CQF4eLT0u1wvjxajwgClOGzAmNoQ= diff --git a/server/v2/stf/stf_test.go b/server/v2/stf/stf_test.go new file mode 100644 index 000000000000..bb42ed3094ae --- /dev/null +++ b/server/v2/stf/stf_test.go @@ -0,0 +1,512 @@ +package stf + +import ( + "context" + "crypto/sha256" + "errors" + "strings" + "testing" + "time" + + gogotypes "github.com/cosmos/gogoproto/types" + + appmodulev2 "cosmossdk.io/core/appmodule/v2" + "cosmossdk.io/core/event" + coregas "cosmossdk.io/core/gas" + "cosmossdk.io/core/server" + "cosmossdk.io/core/store" + "cosmossdk.io/core/transaction" + "cosmossdk.io/schema/appdata" + "cosmossdk.io/server/v2/stf/branch" + "cosmossdk.io/server/v2/stf/gas" + "cosmossdk.io/server/v2/stf/mock" +) + +const senderAddr = "sender" + +func addMsgHandlerToSTF[T any, PT interface { + *T + transaction.Msg +}, + U any, UT interface { + *U + transaction.Msg + }]( + t *testing.T, + stf *STF[mock.Tx], + handler func(ctx context.Context, msg PT) (UT, error), +) { + t.Helper() + msgRouterBuilder := NewMsgRouterBuilder() + err := msgRouterBuilder.RegisterHandler( + msgTypeURL(PT(new(T))), + func(ctx context.Context, msg transaction.Msg) (msgResp transaction.Msg, err error) { + typedReq := msg.(PT) + typedResp, err := handler(ctx, typedReq) + if err != nil { + return nil, err + } + + return typedResp, nil + }, + ) + if err != nil { + t.Errorf("Failed to register handler: %v", err) + } + + msgRouter, err := msgRouterBuilder.build() + if err != nil { + t.Errorf("Failed to build message router: %v", err) + } + stf.msgRouter = msgRouter +} + +func TestSTF(t *testing.T) { + state := mock.DB() + mockTx := mock.Tx{ + Sender: []byte(senderAddr), + Msg: &gogotypes.BoolValue{Value: true}, + GasLimit: 100_000, + } + + sum := sha256.Sum256([]byte("test-hash")) + + s := &STF[mock.Tx]{ + doPreBlock: func(ctx context.Context, txs []mock.Tx) error { + ctx.(*executionContext).events = append(ctx.(*executionContext).events, event.NewEvent("pre-block")) + return nil + }, + doBeginBlock: func(ctx context.Context) error { + kvSet(t, ctx, "begin-block") + ctx.(*executionContext).events = append(ctx.(*executionContext).events, event.NewEvent("begin-block")) + return nil + }, + doEndBlock: func(ctx context.Context) error { + kvSet(t, ctx, "end-block") + ctx.(*executionContext).events = append(ctx.(*executionContext).events, event.NewEvent("end-block")) + return nil + }, + doValidatorUpdate: func(ctx context.Context) ([]appmodulev2.ValidatorUpdate, error) { + ctx.(*executionContext).events = append(ctx.(*executionContext).events, event.NewEvent("validator-update")) + return nil, nil + }, + doTxValidation: func(ctx context.Context, tx mock.Tx) error { + kvSet(t, ctx, "validate") + ctx.(*executionContext).events = append( + ctx.(*executionContext).events, + event.NewEvent("validate-tx", event.NewAttribute(senderAddr, string(tx.Sender))), + event.NewEvent( + "validate-tx", + event.NewAttribute(senderAddr, string(tx.Sender)), + event.NewAttribute("index", "2"), + ), + ) + return nil + }, + postTxExec: func(ctx context.Context, tx mock.Tx, success bool) error { + kvSet(t, ctx, "post-tx-exec") + ctx.(*executionContext).events = append( + ctx.(*executionContext).events, + event.NewEvent("post-tx-exec", event.NewAttribute(senderAddr, string(tx.Sender))), + event.NewEvent( + "post-tx-exec", + event.NewAttribute(senderAddr, string(tx.Sender)), + event.NewAttribute("index", "2"), + ), + ) + return nil + }, + branchFn: branch.DefaultNewWriterMap, + makeGasMeter: gas.DefaultGasMeter, + makeGasMeteredState: gas.DefaultWrapWithGasMeter, + } + + addMsgHandlerToSTF(t, s, func(ctx context.Context, msg *gogotypes.BoolValue) (*gogotypes.BoolValue, error) { + kvSet(t, ctx, "exec") + ctx.(*executionContext).events = append( + ctx.(*executionContext).events, + event.NewEvent("handle-msg", event.NewAttribute("msg", msg.String())), + event.NewEvent( + "handle-msg", + event.NewAttribute("msg", msg.String()), + event.NewAttribute("index", "2"), + ), + ) + return nil, nil + }) + + t.Run("begin and end block", func(t *testing.T) { + _, newState, err := s.DeliverBlock(context.Background(), &server.BlockRequest[mock.Tx]{ + Height: uint64(1), + Time: time.Date(2024, 2, 3, 18, 23, 0, 0, time.UTC), + AppHash: sum[:], + Hash: sum[:], + }, state) + if err != nil { + t.Errorf("DeliverBlock error: %v", err) + } + stateHas(t, newState, "begin-block") + stateHas(t, newState, "end-block") + }) + + t.Run("basic tx", func(t *testing.T) { + result, newState, err := s.DeliverBlock(context.Background(), &server.BlockRequest[mock.Tx]{ + Height: uint64(1), + Time: time.Date(2024, 2, 3, 18, 23, 0, 0, time.UTC), + AppHash: sum[:], + Hash: sum[:], + Txs: []mock.Tx{mockTx}, + }, state) + if err != nil { + t.Errorf("DeliverBlock error: %v", err) + } + stateHas(t, newState, "validate") + stateHas(t, newState, "exec") + stateHas(t, newState, "post-tx-exec") + + if len(result.TxResults) != 1 { + t.Errorf("Expected 1 TxResult, got %d", len(result.TxResults)) + } + txResult := result.TxResults[0] + if txResult.GasUsed == 0 { + t.Errorf("GasUsed should not be zero") + } + if txResult.GasWanted != mockTx.GasLimit { + t.Errorf("Expected GasWanted to be %d, got %d", mockTx.GasLimit, txResult.GasWanted) + } + + // Check PreBlockEvents + preBlockEvents := result.PreBlockEvents + if len(preBlockEvents) != 1 { + t.Fatalf("Expected 1 PreBlockEvent, got %d", len(preBlockEvents)) + } + if preBlockEvents[0].Type != "pre-block" { + t.Errorf("Expected PreBlockEvent Type 'pre-block', got %s", preBlockEvents[0].Type) + } + if preBlockEvents[0].BlockStage != appdata.PreBlockStage { + t.Errorf("Expected PreBlockStage %d, got %d", appdata.PreBlockStage, preBlockEvents[0].BlockStage) + } + if preBlockEvents[0].EventIndex != 1 { + t.Errorf("Expected PreBlockEventIndex 1, got %d", preBlockEvents[0].EventIndex) + } + // Check BeginBlockEvents + beginBlockEvents := result.BeginBlockEvents + if len(beginBlockEvents) != 1 { + t.Fatalf("Expected 1 BeginBlockEvent, got %d", len(beginBlockEvents)) + } + if beginBlockEvents[0].Type != "begin-block" { + t.Errorf("Expected BeginBlockEvent Type 'begin-block', got %s", beginBlockEvents[0].Type) + } + if beginBlockEvents[0].BlockStage != appdata.BeginBlockStage { + t.Errorf("Expected BeginBlockStage %d, got %d", appdata.BeginBlockStage, beginBlockEvents[0].BlockStage) + } + if beginBlockEvents[0].EventIndex != 1 { + t.Errorf("Expected BeginBlockEventIndex 1, got %d", beginBlockEvents[0].EventIndex) + } + // Check EndBlockEvents + endBlockEvents := result.EndBlockEvents + if len(endBlockEvents) != 2 { + t.Fatalf("Expected 2 EndBlockEvents, got %d", len(endBlockEvents)) + } + if endBlockEvents[0].Type != "end-block" { + t.Errorf("Expected EndBlockEvent Type 'end-block', got %s", endBlockEvents[0].Type) + } + if endBlockEvents[1].Type != "validator-update" { + t.Errorf("Expected EndBlockEvent Type 'validator-update', got %s", endBlockEvents[1].Type) + } + if endBlockEvents[1].BlockStage != appdata.EndBlockStage { + t.Errorf("Expected EndBlockStage %d, got %d", appdata.EndBlockStage, endBlockEvents[1].BlockStage) + } + if endBlockEvents[0].EventIndex != 1 { + t.Errorf("Expected EndBlockEventIndex 1, got %d", endBlockEvents[0].EventIndex) + } + if endBlockEvents[1].EventIndex != 2 { + t.Errorf("Expected EndBlockEventIndex 2, got %d", endBlockEvents[1].EventIndex) + } + // check TxEvents + events := txResult.Events + if len(events) != 7 { + t.Fatalf("Expected 7 TxEvents, got %d", len(events)) + } + + const message = "message" + for i, event := range events { + if event.BlockStage != appdata.TxProcessingStage { + t.Errorf("Expected BlockStage %d, got %d", appdata.TxProcessingStage, event.BlockStage) + } + if event.TxIndex != 1 { + t.Errorf("Expected TxIndex 1, got %d", event.TxIndex) + } + if event.EventIndex != int32(i%2+1) && + (event.Type == message && event.EventIndex != 3) { // special case for message event type as it happens in the msg handling flow + t.Errorf("Expected EventIndex %d, got %d", i%2+1, event.EventIndex) + } + + attrs, err := event.Attributes() + if err != nil { + t.Fatalf("Error getting event attributes: %v", err) + } + if len(attrs) < 1 || len(attrs) > 2 { + t.Errorf("Expected 1 or 2 attributes, got %d", len(attrs)) + } + + if len(attrs) == 2 && event.Type != message { + if attrs[1].Key != "index" || attrs[1].Value != "2" { + t.Errorf("Expected attribute key 'index' and value '2', got key '%s' and value '%s'", attrs[1].Key, attrs[1].Value) + } + } + switch i { + case 0, 1: + if event.Type != "validate-tx" { + t.Errorf("Expected event type 'validate-tx', got %s", event.Type) + } + if event.MsgIndex != 0 { + t.Errorf("Expected MsgIndex 0, got %d", event.MsgIndex) + } + if attrs[0].Key != senderAddr || attrs[0].Value != senderAddr { + t.Errorf("Expected sender attribute key 'sender' and value 'sender', got key '%s' and value '%s'", attrs[0].Key, attrs[0].Value) + } + case 2, 3: + if event.Type != "handle-msg" { + t.Errorf("Expected event type 'handle-msg', got %s", event.Type) + } + if event.MsgIndex != 1 { + t.Errorf("Expected MsgIndex 1, got %d", event.MsgIndex) + } + if attrs[0].Key != "msg" || attrs[0].Value != "&BoolValue{Value:true,XXX_unrecognized:[],}" { + t.Errorf("Expected msg attribute with value '&BoolValue{Value:true,XXX_unrecognized:[],}', got '%s'", attrs[0].Value) + } + case 4: + if event.Type != message { + t.Errorf("Expected event type 'message', got %s", event.Type) + } + + if event.MsgIndex != 1 { + t.Errorf("Expected MsgIndex 1, got %d", event.MsgIndex) + } + + if attrs[0].Key != "action" || attrs[0].Value != "/google.protobuf.BoolValue" { + t.Errorf("Expected msg attribute with value '/google.protobuf.BoolValue', got '%s'", attrs[0].Value) + } + case 5, 6: + if event.Type != "post-tx-exec" { + t.Errorf("Expected event type 'post-tx-exec', got %s", event.Type) + } + if event.MsgIndex != -1 { + t.Errorf("Expected MsgIndex -1, got %d", event.MsgIndex) + } + if attrs[0].Key != senderAddr || attrs[0].Value != senderAddr { + t.Errorf("Expected sender attribute key 'sender' and value 'sender', got key '%s' and value '%s'", attrs[0].Key, attrs[0].Value) + } + } + } + }) + + t.Run("exec tx out of gas", func(t *testing.T) { + s := s.clone() + + mockTx := mock.Tx{ + Sender: []byte(senderAddr), + Msg: &gogotypes.BoolValue{Value: true}, // msg does not matter at all because our handler does nothing. + GasLimit: 0, // NO GAS! + } + + // this handler will propagate the storage error back, we expect + // out of gas immediately at tx validation level. + s.doTxValidation = func(ctx context.Context, tx mock.Tx) error { + w, err := ctx.(*executionContext).state.GetWriter(actorName) + if err != nil { + t.Errorf("GetWriter error: %v", err) + } + err = w.Set([]byte("gas_failure"), []byte{}) + if err == nil { + t.Error("Expected error, got nil") + } + return err + } + + result, newState, err := s.DeliverBlock(context.Background(), &server.BlockRequest[mock.Tx]{ + Height: uint64(1), + Time: time.Date(2024, 2, 3, 18, 23, 0, 0, time.UTC), + AppHash: sum[:], + Hash: sum[:], + Txs: []mock.Tx{mockTx}, + }, state) + if err != nil { + t.Errorf("DeliverBlock error: %v", err) + } + stateNotHas(t, newState, "gas_failure") // assert during out of gas no state changes leaked. + if !errors.Is(result.TxResults[0].Error, coregas.ErrOutOfGas) { + t.Errorf("Expected ErrOutOfGas, got %v", result.TxResults[0].Error) + } + }) + + t.Run("fail exec tx", func(t *testing.T) { + // update the stf to fail on the handler + s := s.clone() + addMsgHandlerToSTF(t, &s, func(ctx context.Context, msg *gogotypes.BoolValue) (*gogotypes.BoolValue, error) { + return nil, errors.New("failure") + }) + + blockResult, newState, err := s.DeliverBlock(context.Background(), &server.BlockRequest[mock.Tx]{ + Height: uint64(1), + Time: time.Date(2024, 2, 3, 18, 23, 0, 0, time.UTC), + AppHash: sum[:], + Hash: sum[:], + Txs: []mock.Tx{mockTx}, + }, state) + if err != nil { + t.Errorf("DeliverBlock error: %v", err) + } + if !strings.Contains(blockResult.TxResults[0].Error.Error(), "failure") { + t.Errorf("Expected error to contain 'failure', got %v", blockResult.TxResults[0].Error) + } + stateHas(t, newState, "begin-block") + stateHas(t, newState, "end-block") + stateHas(t, newState, "validate") + stateNotHas(t, newState, "exec") + stateHas(t, newState, "post-tx-exec") + }) + + t.Run("tx is success but post tx failed", func(t *testing.T) { + s := s.clone() + s.postTxExec = func(ctx context.Context, tx mock.Tx, success bool) error { + return errors.New("post tx failure") + } + blockResult, newState, err := s.DeliverBlock(context.Background(), &server.BlockRequest[mock.Tx]{ + Height: uint64(1), + Time: time.Date(2024, 2, 3, 18, 23, 0, 0, time.UTC), + AppHash: sum[:], + Hash: sum[:], + Txs: []mock.Tx{mockTx}, + }, state) + if err != nil { + t.Errorf("DeliverBlock error: %v", err) + } + if !strings.Contains(blockResult.TxResults[0].Error.Error(), "post tx failure") { + t.Errorf("Expected error to contain 'post tx failure', got %v", blockResult.TxResults[0].Error) + } + stateHas(t, newState, "begin-block") + stateHas(t, newState, "end-block") + stateHas(t, newState, "validate") + stateNotHas(t, newState, "exec") + stateNotHas(t, newState, "post-tx-exec") + }) + + t.Run("tx failed and post tx failed", func(t *testing.T) { + s := s.clone() + addMsgHandlerToSTF(t, &s, func(ctx context.Context, msg *gogotypes.BoolValue) (*gogotypes.BoolValue, error) { + return nil, errors.New("exec failure") + }) + s.postTxExec = func(ctx context.Context, tx mock.Tx, success bool) error { return errors.New("post tx failure") } + blockResult, newState, err := s.DeliverBlock(context.Background(), &server.BlockRequest[mock.Tx]{ + Height: uint64(1), + Time: time.Date(2024, 2, 3, 18, 23, 0, 0, time.UTC), + AppHash: sum[:], + Hash: sum[:], + Txs: []mock.Tx{mockTx}, + }, state) + if err != nil { + t.Errorf("DeliverBlock error: %v", err) + } + if !strings.Contains(blockResult.TxResults[0].Error.Error(), "exec failure\npost tx failure") { + t.Errorf("Expected error to contain 'exec failure\npost tx failure', got %v", blockResult.TxResults[0].Error) + } + stateHas(t, newState, "begin-block") + stateHas(t, newState, "end-block") + stateHas(t, newState, "validate") + stateNotHas(t, newState, "exec") + stateNotHas(t, newState, "post-tx-exec") + }) + + t.Run("fail validate tx", func(t *testing.T) { + // update stf to fail on the validation step + s := s.clone() + s.doTxValidation = func(ctx context.Context, tx mock.Tx) error { return errors.New("failure") } + blockResult, newState, err := s.DeliverBlock(context.Background(), &server.BlockRequest[mock.Tx]{ + Height: uint64(1), + Time: time.Date(2024, 2, 3, 18, 23, 0, 0, time.UTC), + AppHash: sum[:], + Hash: sum[:], + Txs: []mock.Tx{mockTx}, + }, state) + if err != nil { + t.Errorf("DeliverBlock error: %v", err) + } + if !strings.Contains(blockResult.TxResults[0].Error.Error(), "failure") { + t.Errorf("Expected error to contain 'failure', got %v", blockResult.TxResults[0].Error) + } + stateHas(t, newState, "begin-block") + stateHas(t, newState, "end-block") + stateNotHas(t, newState, "validate") + stateNotHas(t, newState, "exec") + }) + + t.Run("test validate tx with exec mode", func(t *testing.T) { + // update stf to fail on the validation step + s := s.clone() + s.doTxValidation = func(ctx context.Context, tx mock.Tx) error { + if ctx.(*executionContext).execMode == transaction.ExecModeCheck { + return errors.New("failure") + } + return nil + } + // test ValidateTx as it validates with check execMode + res := s.ValidateTx(context.Background(), state, mockTx.GasLimit, mockTx) + if res.Error == nil { + t.Error("Expected error, got nil") + } + + // test validate tx with exec mode as finalize + _, _, err := s.validateTx(context.Background(), s.branchFn(state), mockTx.GasLimit, + mockTx, transaction.ExecModeFinalize) + if err != nil { + t.Errorf("validateTx error: %v", err) + } + }) +} + +var actorName = []byte("cookies") + +func kvSet(t *testing.T, ctx context.Context, v string) { + t.Helper() + state, err := ctx.(*executionContext).state.GetWriter(actorName) + if err != nil { + t.Errorf("Set error: %v", err) + } else { + err = state.Set([]byte(v), []byte(v)) + if err != nil { + t.Errorf("Set error: %v", err) + } + } +} + +func stateHas(t *testing.T, accountState store.ReaderMap, key string) { + t.Helper() + state, err := accountState.GetReader(actorName) + if err != nil { + t.Errorf("GetReader error: %v", err) + } + has, err := state.Has([]byte(key)) + if err != nil { + t.Errorf("Has error: %v", err) + } + if !has { + t.Errorf("State did not have key: %s", key) + } +} + +func stateNotHas(t *testing.T, accountState store.ReaderMap, key string) { + t.Helper() + state, err := accountState.GetReader(actorName) + if err != nil { + t.Errorf("GetReader error: %v", err) + } + has, err := state.Has([]byte(key)) + if err != nil { + t.Errorf("Has error: %v", err) + } + if has { + t.Errorf("State was not supposed to have key: %s", key) + } +} diff --git a/server/v2/store/commands.go b/server/v2/store/commands.go new file mode 100644 index 000000000000..efb6b9b7b66b --- /dev/null +++ b/server/v2/store/commands.go @@ -0,0 +1,87 @@ +package store + +import ( + "fmt" + + "github.com/spf13/cobra" + "github.com/spf13/viper" + + "cosmossdk.io/log" + serverv2 "cosmossdk.io/server/v2" + storev2 "cosmossdk.io/store/v2" + "cosmossdk.io/store/v2/root" +) + +// PrunesCmd implements the default command for pruning app history states. +func (s *Server[T]) PrunesCmd() *cobra.Command { + cmd := &cobra.Command{ + Use: "prune [pruning-method]", + Short: "Prune app history states by keeping the recent heights and deleting old heights", + Long: `Prune app history states by keeping the recent heights and deleting old heights. +The pruning option is provided via the 'pruning' argument or alternatively with '--pruning-keep-recent' + +- default: the last 362880 states are kept +- nothing: all historic states will be saved, nothing will be deleted (i.e. archiving node) +- everything: 2 latest states will be kept +- custom: allow pruning options to be manually specified through 'pruning-keep-recent' + +Note: When the --app-db-backend flag is not specified, the default backend type is 'goleveldb'. +Supported app-db-backend types include 'goleveldb', 'rocksdb', 'pebbledb'.`, + Example: fmt.Sprintf("%s prune custom --pruning-keep-recent 100 --app-db-backend 'goleveldb'", ""), + Args: cobra.RangeArgs(0, 1), + RunE: func(cmd *cobra.Command, args []string) error { + // bind flags to the Context's Viper so we can get pruning options. + vp := serverv2.GetViperFromCmd(cmd) + if err := vp.BindPFlags(cmd.Flags()); err != nil { + return err + } + if err := vp.BindPFlags(cmd.PersistentFlags()); err != nil { + return err + } + logger := serverv2.GetLoggerFromCmd(cmd) + + rootStore, opts, err := createRootStore(vp, logger) + if err != nil { + return fmt.Errorf("can not create root store %w", err) + } + + latestHeight, err := rootStore.GetLatestVersion() + if err != nil { + return err + } + + // valid heights should be greater than 0. + if latestHeight <= 0 { + return fmt.Errorf("the database has no valid heights to prune, the latest height: %v", latestHeight) + } + + diff := latestHeight - opts.SCPruningOption.KeepRecent + cmd.Printf("pruning heights up to %v\n", diff) + + err = rootStore.Prune(latestHeight) + if err != nil { + return err + } + + cmd.Println("successfully pruned the application root multi stores") + return nil + }, + } + + cmd.Flags().String(FlagAppDBBackend, "", "The type of database for application and snapshots databases") + cmd.Flags().Uint64(FlagKeepRecent, 0, "Number of recent heights to keep on disk (ignored if pruning is not 'custom')") + + return cmd +} + +func createRootStore(v *viper.Viper, logger log.Logger) (storev2.RootStore, root.Options, error) { + storeConfig, err := UnmarshalConfig(v.AllSettings()) + if err != nil { + return nil, root.Options{}, fmt.Errorf("failed to unmarshal config: %w", err) + } + store, err := root.NewBuilder().Build(logger, storeConfig) + if err != nil { + return nil, root.Options{}, fmt.Errorf("failed to create store backend: %w", err) + } + return store, storeConfig.Options, nil +} diff --git a/server/v2/store/snapshot.go b/server/v2/store/snapshot.go new file mode 100644 index 000000000000..0fa2b67c708e --- /dev/null +++ b/server/v2/store/snapshot.go @@ -0,0 +1,420 @@ +package store + +import ( + "archive/tar" + "bytes" + "compress/gzip" + "errors" + "fmt" + "io" + "os" + "path/filepath" + "reflect" + "strconv" + + "github.com/spf13/cobra" + "github.com/spf13/viper" + + "cosmossdk.io/log" + serverv2 "cosmossdk.io/server/v2" + storev2 "cosmossdk.io/store/v2" + "cosmossdk.io/store/v2/snapshots" + "cosmossdk.io/store/v2/snapshots/types" +) + +const SnapshotFileName = "_snapshot" + +// ExportSnapshotCmd exports app state to snapshot store. +func (s *Server[T]) ExportSnapshotCmd() *cobra.Command { + cmd := &cobra.Command{ + Use: "export", + Short: "Export app state to snapshot store", + Args: cobra.NoArgs, + RunE: func(cmd *cobra.Command, args []string) error { + v := serverv2.GetViperFromCmd(cmd) + + height, err := cmd.Flags().GetInt64("height") + if err != nil { + return err + } + + logger := serverv2.GetLoggerFromCmd(cmd) + rootStore, _, err := createRootStore(v, logger) + if err != nil { + return err + } + if height == 0 { + lastCommitId, err := rootStore.LastCommitID() + if err != nil { + return err + } + height = int64(lastCommitId.Version) + } + + cmd.Printf("Exporting snapshot for height %d\n", height) + + sm, err := createSnapshotsManager(cmd, v, logger, rootStore) + if err != nil { + return err + } + + snapshot, err := sm.Create(uint64(height)) + if err != nil { + return err + } + + cmd.Printf("Snapshot created at height %d, format %d, chunks %d\n", snapshot.Height, snapshot.Format, snapshot.Chunks) + return nil + }, + } + + addSnapshotFlagsToCmd(cmd) + cmd.Flags().Int64("height", 0, "Height to export, default to latest state height") + + return cmd +} + +// RestoreSnapshotCmd returns a command to restore a snapshot +func (s *Server[T]) RestoreSnapshotCmd() *cobra.Command { + cmd := &cobra.Command{ + Use: "restore ", + Short: "Restore app state from local snapshot", + Long: "Restore app state from local snapshot", + Args: cobra.ExactArgs(2), + RunE: func(cmd *cobra.Command, args []string) error { + v := serverv2.GetViperFromCmd(cmd) + logger := serverv2.GetLoggerFromCmd(cmd) + + height, err := strconv.ParseUint(args[0], 10, 64) + if err != nil { + return err + } + format, err := strconv.ParseUint(args[1], 10, 32) + if err != nil { + return err + } + + rootStore, _, err := createRootStore(v, logger) + if err != nil { + return fmt.Errorf("failed to create root store: %w", err) + } + sm, err := createSnapshotsManager(cmd, v, logger, rootStore) + if err != nil { + return err + } + + return sm.RestoreLocalSnapshot(height, uint32(format)) + }, + } + + addSnapshotFlagsToCmd(cmd) + + return cmd +} + +// ListSnapshotsCmd returns the command to list local snapshots +func (s *Server[T]) ListSnapshotsCmd() *cobra.Command { + cmd := &cobra.Command{ + Use: "list", + Short: "List local snapshots", + RunE: func(cmd *cobra.Command, args []string) error { + v := serverv2.GetViperFromCmd(cmd) + snapshotStore, err := snapshots.NewStore(filepath.Join(v.GetString(serverv2.FlagHome), "data", "snapshots")) + if err != nil { + return err + } + snapshots, err := snapshotStore.List() + if err != nil { + return fmt.Errorf("failed to list snapshots: %w", err) + } + + if len(snapshots) == 0 { + cmd.Println("no snapshots found") + } + + for _, snapshot := range snapshots { + cmd.Println("height:", snapshot.Height, "format:", snapshot.Format, "chunks:", snapshot.Chunks) + } + + return nil + }, + } + + return cmd +} + +// DeleteSnapshotCmd returns the command to delete a local snapshot +func (s *Server[T]) DeleteSnapshotCmd() *cobra.Command { + return &cobra.Command{ + Use: "delete ", + Short: "Delete a local snapshot", + Args: cobra.ExactArgs(2), + RunE: func(cmd *cobra.Command, args []string) error { + v := serverv2.GetViperFromCmd(cmd) + + height, err := strconv.ParseUint(args[0], 10, 64) + if err != nil { + return err + } + format, err := strconv.ParseUint(args[1], 10, 32) + if err != nil { + return err + } + + snapshotStore, err := snapshots.NewStore(filepath.Join(v.GetString(serverv2.FlagHome), "data", "snapshots")) + if err != nil { + return err + } + + return snapshotStore.Delete(height, uint32(format)) + }, + } +} + +// DumpArchiveCmd returns a command to dump the snapshot as portable archive format +func (s *Server[T]) DumpArchiveCmd() *cobra.Command { + cmd := &cobra.Command{ + Use: "dump ", + Short: "Dump the snapshot as portable archive format", + Args: cobra.ExactArgs(2), + RunE: func(cmd *cobra.Command, args []string) error { + v := serverv2.GetViperFromCmd(cmd) + snapshotStore, err := snapshots.NewStore(filepath.Join(v.GetString(serverv2.FlagHome), "data", "snapshots")) + if err != nil { + return err + } + + output, err := cmd.Flags().GetString("output") + if err != nil { + return err + } + + height, err := strconv.ParseUint(args[0], 10, 64) + if err != nil { + return err + } + format, err := strconv.ParseUint(args[1], 10, 32) + if err != nil { + return err + } + + if output == "" { + output = fmt.Sprintf("%d-%d.tar.gz", height, format) + } + + snapshot, err := snapshotStore.Get(height, uint32(format)) + if err != nil { + return err + } + + if snapshot == nil { + return errors.New("snapshot doesn't exist") + } + + bz, err := snapshot.Marshal() + if err != nil { + return err + } + + fp, err := os.Create(output) + if err != nil { + return err + } + defer fp.Close() + + // since the chunk files are already compressed, we just use fastest compression here + gzipWriter, err := gzip.NewWriterLevel(fp, gzip.BestSpeed) + if err != nil { + return err + } + tarWriter := tar.NewWriter(gzipWriter) + if err := tarWriter.WriteHeader(&tar.Header{ + Name: SnapshotFileName, + Mode: 0o644, + Size: int64(len(bz)), + }); err != nil { + return fmt.Errorf("failed to write snapshot header to tar: %w", err) + } + if _, err := tarWriter.Write(bz); err != nil { + return fmt.Errorf("failed to write snapshot to tar: %w", err) + } + + for i := uint32(0); i < snapshot.Chunks; i++ { + path := snapshotStore.PathChunk(height, uint32(format), i) + tarName := strconv.FormatUint(uint64(i), 10) + if err := processChunk(tarWriter, path, tarName); err != nil { + return err + } + } + + if err := tarWriter.Close(); err != nil { + return fmt.Errorf("failed to close tar writer: %w", err) + } + + if err := gzipWriter.Close(); err != nil { + return fmt.Errorf("failed to close gzip writer: %w", err) + } + + return fp.Close() + }, + } + + cmd.Flags().StringP("output", "o", "", "output file") + + return cmd +} + +// LoadArchiveCmd load a portable archive format snapshot into snapshot store +func (s *Server[T]) LoadArchiveCmd() *cobra.Command { + return &cobra.Command{ + Use: "load ", + Short: "Load a snapshot archive file (.tar.gz) into snapshot store", + Args: cobra.ExactArgs(1), + RunE: func(cmd *cobra.Command, args []string) error { + v := serverv2.GetViperFromCmd(cmd) + snapshotStore, err := snapshots.NewStore(filepath.Join(v.GetString(serverv2.FlagHome), "data", "snapshots")) + if err != nil { + return err + } + + path := args[0] + fp, err := os.Open(path) + if err != nil { + return fmt.Errorf("failed to open archive file: %w", err) + } + reader, err := gzip.NewReader(fp) + if err != nil { + return fmt.Errorf("failed to create gzip reader: %w", err) + } + + var snapshot types.Snapshot + tr := tar.NewReader(reader) + + hdr, err := tr.Next() + if err != nil { + return fmt.Errorf("failed to read snapshot file header: %w", err) + } + if hdr.Name != SnapshotFileName { + return fmt.Errorf("invalid archive, expect file: snapshot, got: %s", hdr.Name) + } + bz, err := io.ReadAll(tr) + if err != nil { + return fmt.Errorf("failed to read snapshot file: %w", err) + } + if err := snapshot.Unmarshal(bz); err != nil { + return fmt.Errorf("failed to unmarshal snapshot: %w", err) + } + + // make sure the channel is unbuffered, because the tar reader can't do concurrency + chunks := make(chan io.ReadCloser) + quitChan := make(chan *types.Snapshot) + go func() { + defer close(quitChan) + + savedSnapshot, err := snapshotStore.Save(snapshot.Height, snapshot.Format, chunks) + if err != nil { + cmd.Println("failed to save snapshot", err) + return + } + quitChan <- savedSnapshot + }() + + for i := uint32(0); i < snapshot.Chunks; i++ { + hdr, err = tr.Next() + if err != nil { + if errors.Is(err, io.EOF) { + break + } + return err + } + + if hdr.Name != strconv.FormatInt(int64(i), 10) { + return fmt.Errorf("invalid archive, expect file: %d, got: %s", i, hdr.Name) + } + + bz, err := io.ReadAll(tr) + if err != nil { + return fmt.Errorf("failed to read chunk file: %w", err) + } + chunks <- io.NopCloser(bytes.NewReader(bz)) + } + close(chunks) + + savedSnapshot := <-quitChan + if savedSnapshot == nil { + return errors.New("failed to save snapshot") + } + + if !reflect.DeepEqual(&snapshot, savedSnapshot) { + _ = snapshotStore.Delete(snapshot.Height, snapshot.Format) + return errors.New("invalid archive, the saved snapshot is not equal to the original one") + } + + return nil + }, + } +} + +func createSnapshotsManager( + cmd *cobra.Command, v *viper.Viper, logger log.Logger, store storev2.Backend, +) (*snapshots.Manager, error) { + home := v.GetString(serverv2.FlagHome) + snapshotStore, err := snapshots.NewStore(filepath.Join(home, "data", "snapshots")) + if err != nil { + return nil, err + } + var interval, keepRecent uint64 + // if flag was not passed, use as 0. + if cmd.Flags().Changed(FlagKeepRecent) { + keepRecent, err = cmd.Flags().GetUint64(FlagKeepRecent) + if err != nil { + return nil, err + } + } + if cmd.Flags().Changed(FlagInterval) { + interval, err = cmd.Flags().GetUint64(FlagInterval) + if err != nil { + return nil, err + } + } + + sm := snapshots.NewManager( + snapshotStore, + snapshots.NewSnapshotOptions(interval, uint32(keepRecent)), + store.GetStateCommitment().(snapshots.CommitSnapshotter), + nil, + logger) + return sm, nil +} + +func addSnapshotFlagsToCmd(cmd *cobra.Command) { + cmd.Flags().Uint64(FlagKeepRecent, 0, "KeepRecent defines how many snapshots to keep in heights") + cmd.Flags().Uint64(FlagInterval, 0, "Interval defines at which heights the snapshot is taken") +} + +func processChunk(tarWriter *tar.Writer, path, tarName string) error { + file, err := os.Open(path) + if err != nil { + return fmt.Errorf("failed to open chunk file %s: %w", path, err) + } + defer file.Close() + + st, err := file.Stat() + if err != nil { + return fmt.Errorf("failed to stat chunk file %s: %w", path, err) + } + + if err := tarWriter.WriteHeader(&tar.Header{ + Name: tarName, + Mode: 0o644, + Size: st.Size(), + }); err != nil { + return fmt.Errorf("failed to write chunk header to tar: %w", err) + } + + if _, err := io.Copy(tarWriter, file); err != nil { + return fmt.Errorf("failed to write chunk to tar: %w", err) + } + + return nil +} diff --git a/server/v2/testdata/app.toml b/server/v2/testdata/app.toml new file mode 100644 index 000000000000..348b057cd5d7 --- /dev/null +++ b/server/v2/testdata/app.toml @@ -0,0 +1,42 @@ +[grpc] +# Enable defines if the gRPC server should be enabled. +enable = false +# Address defines the gRPC server address to bind to. +address = 'localhost:9090' +# MaxRecvMsgSize defines the max message size in bytes the server can receive. +# The default value is 10MB. +max-recv-msg-size = 10485760 +# MaxSendMsgSize defines the max message size in bytes the server can send. +# The default value is math.MaxInt32. +max-send-msg-size = 2147483647 + +[mock-server-1] +# Mock field +mock_field = 'default' +# Mock field two +mock_field_two = 1 + +[server] +# minimum-gas-prices defines the price which a validator is willing to accept for processing a transaction. A transaction's fees must meet the minimum of any denomination specified in this config (e.g. 0.25token1;0.0001token2). +minimum-gas-prices = '0stake' + +[store] +# The type of database for application and snapshots databases. +app-db-backend = 'goleveldb' + +[store.options] +# State commitment database type. Currently we support: "iavl" and "iavl-v2" +sc-type = 'iavl' + +# Pruning options for state commitment +[store.options.sc-pruning-option] +# Number of recent heights to keep on disk. +keep-recent = 2 +# Height interval at which pruned heights are removed from disk. +interval = 100 + +[store.options.iavl-config] +# CacheSize set the size of the iavl tree cache. +cache-size = 100000 +# If true, the tree will work like no fast storage and always not upgrade fast storage. +skip-fast-storage-upgrade = true diff --git a/simapp/go.mod b/simapp/go.mod index 5ada223b5b37..087d41316886 100644 --- a/simapp/go.mod +++ b/simapp/go.mod @@ -90,7 +90,7 @@ require ( github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06 // indirect github.com/cometbft/cometbft-db v1.0.1 // indirect github.com/cosmos/btcutil v1.0.5 // indirect - github.com/cosmos/cosmos-db v1.1.0 // indirect + github.com/cosmos/cosmos-db v1.1.1 // indirect github.com/cosmos/cosmos-proto v1.0.0-beta.5 // indirect github.com/cosmos/go-bip39 v1.0.0 // indirect github.com/cosmos/gogogateway v1.2.0 // indirect diff --git a/simapp/go.sum b/simapp/go.sum index 2e0a011043e2..cfb1627799eb 100644 --- a/simapp/go.sum +++ b/simapp/go.sum @@ -375,8 +375,8 @@ github.com/containerd/continuity v0.3.0/go.mod h1:wJEAIwKOm/pBZuBd0JmeTvnLquTB1A github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= github.com/cosmos/btcutil v1.0.5 h1:t+ZFcX77LpKtDBhjucvnOH8C2l2ioGsBNEQ3jef8xFk= github.com/cosmos/btcutil v1.0.5/go.mod h1:IyB7iuqZMJlthe2tkIFL33xPyzbFYP0XVdS8P5lUPis= -github.com/cosmos/cosmos-db v1.1.0 h1:KLHNVQ73h7vawXTpj9UJ7ZR2IXv51tsEHkQJJ9EBDzI= -github.com/cosmos/cosmos-db v1.1.0/go.mod h1:t7c4A6cfGdpUwwVxrQ0gQLeRQqGUBJu0yvE4F/26REg= +github.com/cosmos/cosmos-db v1.1.1 h1:FezFSU37AlBC8S98NlSagL76oqBRWq/prTPvFcEJNCM= +github.com/cosmos/cosmos-db v1.1.1/go.mod h1:AghjcIPqdhSLP/2Z0yha5xPH3nLnskz81pBx3tcVSAw= github.com/cosmos/cosmos-proto v1.0.0-beta.5 h1:eNcayDLpip+zVLRLYafhzLvQlSmyab+RC5W7ZfmxJLA= github.com/cosmos/cosmos-proto v1.0.0-beta.5/go.mod h1:hQGLpiIUloJBMdQMMWb/4wRApmI9hjHH05nefC0Ojec= github.com/cosmos/go-bip39 v1.0.0 h1:pcomnQdrdH22njcAatO0yWojsUnCO3y2tNoV1cb6hHY= diff --git a/simapp/v2/go.mod b/simapp/v2/go.mod index 76d9e1b7a8b0..8d16f6b36309 100644 --- a/simapp/v2/go.mod +++ b/simapp/v2/go.mod @@ -93,7 +93,7 @@ require ( github.com/cometbft/cometbft-db v1.0.1 // indirect github.com/cometbft/cometbft/api v1.0.0 // indirect github.com/cosmos/btcutil v1.0.5 // indirect - github.com/cosmos/cosmos-db v1.1.0 // indirect + github.com/cosmos/cosmos-db v1.1.1 // indirect github.com/cosmos/cosmos-proto v1.0.0-beta.5 // indirect github.com/cosmos/go-bip39 v1.0.0 // indirect github.com/cosmos/gogogateway v1.2.0 // indirect diff --git a/simapp/v2/go.sum b/simapp/v2/go.sum index 8098757ca48d..52b167e13209 100644 --- a/simapp/v2/go.sum +++ b/simapp/v2/go.sum @@ -387,8 +387,8 @@ github.com/containerd/continuity v0.3.0/go.mod h1:wJEAIwKOm/pBZuBd0JmeTvnLquTB1A github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= github.com/cosmos/btcutil v1.0.5 h1:t+ZFcX77LpKtDBhjucvnOH8C2l2ioGsBNEQ3jef8xFk= github.com/cosmos/btcutil v1.0.5/go.mod h1:IyB7iuqZMJlthe2tkIFL33xPyzbFYP0XVdS8P5lUPis= -github.com/cosmos/cosmos-db v1.1.0 h1:KLHNVQ73h7vawXTpj9UJ7ZR2IXv51tsEHkQJJ9EBDzI= -github.com/cosmos/cosmos-db v1.1.0/go.mod h1:t7c4A6cfGdpUwwVxrQ0gQLeRQqGUBJu0yvE4F/26REg= +github.com/cosmos/cosmos-db v1.1.1 h1:FezFSU37AlBC8S98NlSagL76oqBRWq/prTPvFcEJNCM= +github.com/cosmos/cosmos-db v1.1.1/go.mod h1:AghjcIPqdhSLP/2Z0yha5xPH3nLnskz81pBx3tcVSAw= github.com/cosmos/cosmos-proto v1.0.0-beta.5 h1:eNcayDLpip+zVLRLYafhzLvQlSmyab+RC5W7ZfmxJLA= github.com/cosmos/cosmos-proto v1.0.0-beta.5/go.mod h1:hQGLpiIUloJBMdQMMWb/4wRApmI9hjHH05nefC0Ojec= github.com/cosmos/go-bip39 v1.0.0 h1:pcomnQdrdH22njcAatO0yWojsUnCO3y2tNoV1cb6hHY= diff --git a/store/v2/db/pebbledb.go b/store/v2/db/pebbledb.go new file mode 100644 index 000000000000..c4eb2c0122bf --- /dev/null +++ b/store/v2/db/pebbledb.go @@ -0,0 +1,314 @@ +package db + +import ( + "bytes" + "errors" + "fmt" + "path/filepath" + "slices" + + "github.com/cockroachdb/pebble" + "github.com/spf13/cast" + + coreserver "cosmossdk.io/core/server" + corestore "cosmossdk.io/core/store" + storeerrors "cosmossdk.io/store/v2/errors" +) + +var _ corestore.KVStoreWithBatch = (*PebbleDB)(nil) + +// PebbleDB implements `corestore.KVStoreWithBatch` using PebbleDB as the underlying storage engine. +// It is used for only store v2 migration, since some clients use PebbleDB as +// the IAVL v0/v1 backend. +type PebbleDB struct { + storage *pebble.DB +} + +func NewPebbleDB(name, dataDir string) (*PebbleDB, error) { + return NewPebbleDBWithOpts(name, dataDir, nil) +} + +func NewPebbleDBWithOpts(name, dataDir string, opts coreserver.DynamicConfig) (*PebbleDB, error) { + do := &pebble.Options{ + Logger: &fatalLogger{}, // pebble info logs are messing up the logs (not a cosmossdk.io/log logger) + MaxConcurrentCompactions: func() int { return 3 }, // default 1 + } + + do.EnsureDefaults() + + if opts != nil { + files := cast.ToInt(opts.Get("maxopenfiles")) + if files > 0 { + do.MaxOpenFiles = files + } + } + dbPath := filepath.Join(dataDir, name+DBFileSuffix) + db, err := pebble.Open(dbPath, do) + if err != nil { + return nil, fmt.Errorf("failed to open PebbleDB: %w", err) + } + + return &PebbleDB{storage: db}, nil +} + +func (db *PebbleDB) Close() error { + err := db.storage.Close() + db.storage = nil + return err +} + +func (db *PebbleDB) Get(key []byte) ([]byte, error) { + if len(key) == 0 { + return nil, storeerrors.ErrKeyEmpty + } + + bz, closer, err := db.storage.Get(key) + if err != nil { + if errors.Is(err, pebble.ErrNotFound) { + // in case of a fresh database + return nil, nil + } + + return nil, fmt.Errorf("failed to perform PebbleDB read: %w", err) + } + + if len(bz) == 0 { + return nil, closer.Close() + } + + return bz, closer.Close() +} + +func (db *PebbleDB) Has(key []byte) (bool, error) { + bz, err := db.Get(key) + if err != nil { + return false, err + } + + return bz != nil, nil +} + +func (db *PebbleDB) Set(key, value []byte) error { + if len(key) == 0 { + return storeerrors.ErrKeyEmpty + } + if value == nil { + return storeerrors.ErrValueNil + } + + return db.storage.Set(key, value, &pebble.WriteOptions{Sync: false}) +} + +func (db *PebbleDB) Delete(key []byte) error { + if len(key) == 0 { + return storeerrors.ErrKeyEmpty + } + + return db.storage.Delete(key, &pebble.WriteOptions{Sync: false}) +} + +func (db *PebbleDB) Iterator(start, end []byte) (corestore.Iterator, error) { + if (start != nil && len(start) == 0) || (end != nil && len(end) == 0) { + return nil, storeerrors.ErrKeyEmpty + } + + itr, err := db.storage.NewIter(&pebble.IterOptions{LowerBound: start, UpperBound: end}) + if err != nil { + return nil, fmt.Errorf("failed to create PebbleDB iterator: %w", err) + } + + return newPebbleDBIterator(itr, start, end, false), nil +} + +func (db *PebbleDB) ReverseIterator(start, end []byte) (corestore.Iterator, error) { + if (start != nil && len(start) == 0) || (end != nil && len(end) == 0) { + return nil, storeerrors.ErrKeyEmpty + } + + itr, err := db.storage.NewIter(&pebble.IterOptions{LowerBound: start, UpperBound: end}) + if err != nil { + return nil, fmt.Errorf("failed to create PebbleDB iterator: %w", err) + } + + return newPebbleDBIterator(itr, start, end, true), nil +} + +func (db *PebbleDB) NewBatch() corestore.Batch { + return &pebbleDBBatch{ + db: db, + batch: db.storage.NewBatch(), + } +} + +func (db *PebbleDB) NewBatchWithSize(size int) corestore.Batch { + return &pebbleDBBatch{ + db: db, + batch: db.storage.NewBatchWithSize(size), + } +} + +var _ corestore.Iterator = (*pebbleDBIterator)(nil) + +type pebbleDBIterator struct { + source *pebble.Iterator + start []byte + end []byte + valid bool + reverse bool +} + +func newPebbleDBIterator(src *pebble.Iterator, start, end []byte, reverse bool) *pebbleDBIterator { + // move the underlying PebbleDB cursor to the first key + var valid bool + if reverse { + if end == nil { + valid = src.Last() + } else { + valid = src.SeekLT(end) + } + } else { + valid = src.First() + } + + return &pebbleDBIterator{ + source: src, + start: start, + end: end, + valid: valid, + reverse: reverse, + } +} + +func (itr *pebbleDBIterator) Domain() (start, end []byte) { + return itr.start, itr.end +} + +func (itr *pebbleDBIterator) Valid() bool { + // once invalid, forever invalid + if !itr.valid || !itr.source.Valid() { + itr.valid = false + return itr.valid + } + + // if source has error, consider it invalid + if err := itr.source.Error(); err != nil { + itr.valid = false + return itr.valid + } + + // if key is at the end or past it, consider it invalid + if end := itr.end; end != nil { + if bytes.Compare(end, itr.Key()) <= 0 { + itr.valid = false + return itr.valid + } + } + + return true +} + +func (itr *pebbleDBIterator) Key() []byte { + itr.assertIsValid() + return slices.Clone(itr.source.Key()) +} + +func (itr *pebbleDBIterator) Value() []byte { + itr.assertIsValid() + return slices.Clone(itr.source.Value()) +} + +func (itr *pebbleDBIterator) Next() { + itr.assertIsValid() + + if itr.reverse { + itr.valid = itr.source.Prev() + } else { + itr.valid = itr.source.Next() + } +} + +func (itr *pebbleDBIterator) Error() error { + return itr.source.Error() +} + +func (itr *pebbleDBIterator) Close() error { + err := itr.source.Close() + itr.source = nil + itr.valid = false + + return err +} + +func (itr *pebbleDBIterator) assertIsValid() { + if !itr.valid { + panic("pebbleDB iterator is invalid") + } +} + +var _ corestore.Batch = (*pebbleDBBatch)(nil) + +type pebbleDBBatch struct { + db *PebbleDB + batch *pebble.Batch +} + +func (b *pebbleDBBatch) Set(key, value []byte) error { + if len(key) == 0 { + return storeerrors.ErrKeyEmpty + } + if value == nil { + return storeerrors.ErrValueNil + } + if b.batch == nil { + return storeerrors.ErrBatchClosed + } + + return b.batch.Set(key, value, nil) +} + +func (b *pebbleDBBatch) Delete(key []byte) error { + if len(key) == 0 { + return storeerrors.ErrKeyEmpty + } + if b.batch == nil { + return storeerrors.ErrBatchClosed + } + + return b.batch.Delete(key, nil) +} + +func (b *pebbleDBBatch) Write() error { + err := b.batch.Commit(&pebble.WriteOptions{Sync: false}) + if err != nil { + return fmt.Errorf("failed to write PebbleDB batch: %w", err) + } + + return nil +} + +func (b *pebbleDBBatch) WriteSync() error { + err := b.batch.Commit(&pebble.WriteOptions{Sync: true}) + if err != nil { + return fmt.Errorf("failed to write PebbleDB batch: %w", err) + } + + return nil +} + +func (b *pebbleDBBatch) Close() error { + return b.batch.Close() +} + +func (b *pebbleDBBatch) GetByteSize() (int, error) { + return b.batch.Len(), nil +} + +type fatalLogger struct { + pebble.Logger +} + +func (*fatalLogger) Fatalf(format string, args ...interface{}) { + pebble.DefaultLogger.Fatalf(format, args...) +} + +func (*fatalLogger) Infof(format string, args ...interface{}) {} diff --git a/systemtests/CHANGELOG.md b/systemtests/CHANGELOG.md new file mode 100644 index 000000000000..736ef5c24881 --- /dev/null +++ b/systemtests/CHANGELOG.md @@ -0,0 +1,57 @@ + + +# Changelog + +## [Unreleased] + +## [v1.0.0] - 2024-12-19 + +* [#22849](https://github.com/cosmos/cosmos-sdk/pull/22849) Avoid telemetry server conflicts on port 7180 + +## [v1.0.0-rc.4] - 2024-12-10 + +* [#22810](https://github.com/cosmos/cosmos-sdk/pull/22810) Avoid HTTP server conflicts on port 8080 + +## [v1.0.0-rc.3] - 2024-12-05 + +* [#22774](https://github.com/cosmos/cosmos-sdk/pull/22774) Add greater than or equal support in Rest test suite + +## [v1.0.0-rc.2] - 2024-11-26 + +* [#22577](https://github.com/cosmos/cosmos-sdk/pull/22577) Support invalid RPC response for CometBFT v1 + +## [v1.0.0-rc.1] - 2024-11-26 + +* [#22578](https://github.com/cosmos/cosmos-sdk/pull/22578) Extract system test framework diff --git a/systemtests/system.go b/systemtests/system.go new file mode 100644 index 000000000000..ccbc9e05f5a4 --- /dev/null +++ b/systemtests/system.go @@ -0,0 +1,987 @@ +package systemtests + +import ( + "bufio" + "bytes" + "container/ring" + "context" + "fmt" + "io" + "maps" + "os" + "os/exec" + "path/filepath" + "regexp" + "strings" + "sync/atomic" + "syscall" + "testing" + "time" + + "github.com/cometbft/cometbft/libs/sync" + client "github.com/cometbft/cometbft/rpc/client/http" + ctypes "github.com/cometbft/cometbft/rpc/core/types" + tmtypes "github.com/cometbft/cometbft/types" + "github.com/creachadair/tomledit" + "github.com/stretchr/testify/require" + "github.com/tidwall/sjson" + + "github.com/cosmos/cosmos-sdk/server" + sdk "github.com/cosmos/cosmos-sdk/types" +) + +var ( + // WorkDir is the directory where tests are executed. Path should be relative to this dir + WorkDir string + + // ExecBinaryUnversionedRegExp regular expression to extract the unversioned binary name + ExecBinaryUnversionedRegExp = regexp.MustCompile(`^(\w+)-?.*$`) + + MaxGas = 10_000_000 + // DefaultApiPort is the port for the node to interact with + DefaultApiPort = 1317 + DefaultRpcPort = 26657 + DefaultTelemetryPort = 7180 + DefaultRestPort = 8080 + DefaultGrpcPort = 9090 + DefaultP2PPort = 16656 +) + +type TestnetInitializer interface { + Initialize() +} + +// SystemUnderTest blockchain provisioning +type SystemUnderTest struct { + execBinary string + blockListener *EventListener + currentHeight atomic.Int64 + outputDir string + testnetInitializer TestnetInitializer + + // blockTime is the expected/desired block time. This is not going to be very precise + // since Tendermint consensus does not allow specifying it directly. + blockTime time.Duration + rpcAddr string + apiAddr string + initialNodesCount int + nodesCount int + minGasPrice string + cleanupFn []CleanupFn + outBuff *ring.Ring + errBuff *ring.Ring + out io.Writer + verbose bool + ChainStarted bool + projectName string + dirty bool // requires full reset when marked dirty + + pidsLock sync.RWMutex + pids map[int]struct{} + chainID string +} + +func NewSystemUnderTest(execBinary string, verbose bool, nodesCount int, blockTime time.Duration, initer ...TestnetInitializer) *SystemUnderTest { + if execBinary == "" { + panic("executable binary name must not be empty") + } + nameTokens := ExecBinaryUnversionedRegExp.FindAllString(execBinary, 1) + if len(nameTokens) == 0 || nameTokens[0] == "" { + panic("failed to parse project name from binary") + } + + execBinary = filepath.Join(WorkDir, "binaries", execBinary) + s := &SystemUnderTest{ + chainID: "testing", + execBinary: execBinary, + outputDir: "./testnet", + blockTime: blockTime, + rpcAddr: "tcp://localhost:26657", + apiAddr: fmt.Sprintf("http://localhost:%d", DefaultApiPort), + initialNodesCount: nodesCount, + outBuff: ring.New(100), + errBuff: ring.New(100), + out: os.Stdout, + verbose: verbose, + minGasPrice: fmt.Sprintf("0.000001%s", sdk.DefaultBondDenom), + projectName: nameTokens[0], + pids: make(map[int]struct{}, nodesCount), + } + if len(initer) > 0 { + s.testnetInitializer = initer[0] + } else { + s.testnetInitializer = NewSingleHostTestnetCmdInitializer(execBinary, WorkDir, s.chainID, s.outputDir, s.initialNodesCount, s.minGasPrice, s.CommitTimeout(), s.Log) + } + return s +} + +// SetExecBinary sets the executable binary for the system under test. +func (s *SystemUnderTest) SetExecBinary(binary string) { + s.execBinary = binary +} + +// ExecBinary returns the path of the binary executable associated with the SystemUnderTest instance. +func (s *SystemUnderTest) ExecBinary() string { + return s.execBinary +} + +// SetTestnetInitializer sets the initializer for the testnet configuration. +func (s *SystemUnderTest) SetTestnetInitializer(testnetInitializer TestnetInitializer) { + s.testnetInitializer = testnetInitializer +} + +// TestnetInitializer returns the testnet initializer associated with the SystemUnderTest. +func (s *SystemUnderTest) TestnetInitializer() TestnetInitializer { + return s.testnetInitializer +} + +// CommitTimeout returns the max time to wait for a commit. Default to 90% of block time +func (s *SystemUnderTest) CommitTimeout() time.Duration { + // The commit timeout is a lower bound for the block time. We try to set it to a level that allows us to reach the expected block time. + return time.Duration((int64(s.blockTime) * 90) / 100) // leave 10% for all other operations +} + +func (s *SystemUnderTest) SetupChain() { + s.Logf("Setup chain: %s\n", s.outputDir) + if err := os.RemoveAll(filepath.Join(WorkDir, s.outputDir)); err != nil { + panic(err.Error()) + } + s.testnetInitializer.Initialize() + s.nodesCount = s.initialNodesCount + + // modify genesis with system test defaults + src := filepath.Join(WorkDir, s.nodePath(0), "config", "genesis.json") + genesisBz, err := os.ReadFile(src) // #nosec G304 + if err != nil { + panic(fmt.Sprintf("failed to load genesis: %s", err)) + } + + genesisBz, err = sjson.SetRawBytes(genesisBz, "consensus.params.block.max_gas", []byte(fmt.Sprintf(`"%d"`, MaxGas))) + if err != nil { + panic(fmt.Sprintf("failed to set block max gas: %s", err)) + } + s.withEachNodeHome(func(i int, home string) { + if err := saveGenesis(home, genesisBz); err != nil { + panic(err) + } + }) + + // backup genesis + dest := filepath.Join(WorkDir, s.nodePath(0), "config", "genesis.json.orig") + MustCopyFile(src, dest) + // backup keyring + src = filepath.Join(WorkDir, s.nodePath(0), "keyring-test") + dest = filepath.Join(WorkDir, s.outputDir, "keyring-test") + MustCopyFilesInDir(src, dest) +} + +func (s *SystemUnderTest) StartChain(t *testing.T, xargs ...string) { + t.Helper() + s.Log("Start chain\n") + s.ChainStarted = true + s.startNodesAsync(t, append([]string{"start", "--log_level=info", "--log_no_color"}, xargs...)...) + + s.AwaitNodeUp(t, s.rpcAddr) + + t.Log("Start new block listener") + s.blockListener = NewEventListener(t, s.rpcAddr) + s.cleanupFn = append(s.cleanupFn, + s.blockListener.Subscribe("tm.event='NewBlock'", func(e ctypes.ResultEvent) (more bool) { + newBlock, ok := e.Data.(tmtypes.EventDataNewBlock) + require.True(t, ok, "unexpected type %T", e.Data) + s.currentHeight.Store(newBlock.Block.Height) + return true + }), + ) + s.AwaitNextBlock(t, 4e9) +} + +// MarkDirty whole chain will be reset when marked dirty +func (s *SystemUnderTest) MarkDirty() { + s.dirty = true +} + +// IsDirty true when non default genesis or other state modification were applied that might create incompatibility for tests +func (s *SystemUnderTest) IsDirty() bool { + return s.dirty +} + +// watchLogs stores stdout/stderr in a file and in a ring buffer to output the last n lines on test error +func (s *SystemUnderTest) watchLogs(node int, cmd *exec.Cmd) { + logfile, err := os.Create(filepath.Join(WorkDir, s.outputDir, fmt.Sprintf("node%d.out", node))) + if err != nil { + panic(fmt.Sprintf("open logfile error %#+v", err)) + } + + errReader, err := cmd.StderrPipe() + if err != nil { + panic(fmt.Sprintf("stderr reader error %#+v", err)) + } + stopRingBuffer := make(chan struct{}) + go appendToBuf(io.TeeReader(errReader, logfile), s.errBuff, stopRingBuffer) + + outReader, err := cmd.StdoutPipe() + if err != nil { + panic(fmt.Sprintf("stdout reader error %#+v", err)) + } + go appendToBuf(io.TeeReader(outReader, logfile), s.outBuff, stopRingBuffer) + s.cleanupFn = append(s.cleanupFn, func() { + close(stopRingBuffer) + _ = logfile.Close() + }) +} + +func appendToBuf(r io.Reader, b *ring.Ring, stop <-chan struct{}) { + scanner := bufio.NewScanner(r) + for scanner.Scan() { + select { + case <-stop: + return + default: + } + text := scanner.Text() + // filter out noise + if isLogNoise(text) { + continue + } + b.Value = text + b = b.Next() + } +} + +func isLogNoise(text string) bool { + for _, v := range []string{ + "\x1b[36mmodule=\x1b[0mrpc-server", // "module=rpc-server", + } { + if strings.Contains(text, v) { + return true + } + } + return false +} + +// AwaitUpgradeInfo blocks util an upgrade info file is persisted to disk +func (s *SystemUnderTest) AwaitUpgradeInfo(t *testing.T) { + t.Helper() + var found bool + for !found { + s.withEachNodeHome(func(i int, home string) { + _, err := os.Stat(filepath.Join(s.nodePath(0), "data", "upgrade-info.json")) + switch { + case err == nil: + found = true + case !os.IsNotExist(err): + t.Fatal(err.Error()) + } + }) + time.Sleep(s.blockTime / 2) + } +} + +func (s *SystemUnderTest) AwaitChainStopped() { + for s.anyNodeRunning() { + time.Sleep(s.blockTime) + } +} + +// AwaitNodeUp ensures the node is running +func (s *SystemUnderTest) AwaitNodeUp(t *testing.T, rpcAddr string) { + t.Helper() + t.Logf("Await node is up: %s", rpcAddr) + timeout := DefaultWaitTime + ctx, done := context.WithTimeout(context.Background(), timeout) + defer done() + + started := make(chan struct{}) + go func() { // query for a non empty block on status page + t.Logf("Checking node status: %s\n", rpcAddr) + for { + con, err := client.New(rpcAddr, "/websocket") + if err != nil || con.Start() != nil { + time.Sleep(time.Second) + continue + } + result, err := con.Status(ctx) + if err != nil || result.SyncInfo.LatestBlockHeight < 1 { + _ = con.Stop() + continue + } + t.Logf("Node started. Current block: %d\n", result.SyncInfo.LatestBlockHeight) + _ = con.Stop() + started <- struct{}{} + } + }() + select { + case <-started: + case <-ctx.Done(): + require.NoError(t, ctx.Err()) + case <-time.NewTimer(timeout).C: + t.Fatalf("timeout waiting for node start: %s", timeout) + } +} + +// StopChain stops the system under test and executes all registered cleanup callbacks +func (s *SystemUnderTest) StopChain() { + s.Log("Stop chain\n") + if !s.ChainStarted { + return + } + + for _, c := range s.cleanupFn { + c() + } + s.cleanupFn = nil + // send SIGTERM + s.withEachPid(func(p *os.Process) { + go func() { + if err := p.Signal(syscall.SIGTERM); err != nil { + s.Logf("failed to stop node with pid %d: %s\n", p.Pid, err) + } + }() + }) + // give some final time to shut down + s.withEachPid(func(p *os.Process) { + time.Sleep(200 * time.Millisecond) + }) + // goodbye + for ; s.anyNodeRunning(); time.Sleep(100 * time.Millisecond) { + s.withEachPid(func(p *os.Process) { + s.Logf("killing node %d\n", p.Pid) + if err := p.Kill(); err != nil { + s.Logf("failed to kill node with pid %d: %s\n", p.Pid, err) + } + }) + } + s.ChainStarted = false +} + +func (s *SystemUnderTest) withEachPid(cb func(p *os.Process)) { + s.pidsLock.RLock() + pids := maps.Keys(s.pids) + s.pidsLock.RUnlock() + + for pid := range pids { + p, err := os.FindProcess(pid) + if err != nil { + continue + } + cb(p) + } +} + +// PrintBuffer prints the chain logs to the console +func (s *SystemUnderTest) PrintBuffer() { + s.outBuff.Do(func(v interface{}) { + if v != nil { + _, _ = fmt.Fprintf(s.out, "out> %s\n", v) + } + }) + fmt.Fprint(s.out, "8< chain err -----------------------------------------\n") + s.errBuff.Do(func(v interface{}) { + if v != nil { + _, _ = fmt.Fprintf(s.out, "err> %s\n", v) + } + }) +} + +// AwaitNBlocks blocks until the current height + n block is reached. An optional timeout parameter can be passed to abort early +func (s *SystemUnderTest) AwaitNBlocks(t *testing.T, n int64, timeout ...time.Duration) { + t.Helper() + s.AwaitBlockHeight(t, s.CurrentHeight()+n, timeout...) +} + +// AwaitBlockHeight blocks until the target height is reached. An optional timeout parameter can be passed to abort early +func (s *SystemUnderTest) AwaitBlockHeight(t *testing.T, targetHeight int64, timeout ...time.Duration) { + t.Helper() + require.Greater(t, targetHeight, s.currentHeight.Load()) + var maxWaitTime time.Duration + if len(timeout) != 0 { + maxWaitTime = timeout[0] + } else { + maxWaitTime = time.Duration(targetHeight-s.currentHeight.Load()+3) * s.blockTime + } + abort := time.NewTimer(maxWaitTime).C + for { + select { + case <-abort: + t.Fatalf("Timeout - block %d not reached within %s", targetHeight, maxWaitTime) + return + default: + if current := s.AwaitNextBlock(t); current >= targetHeight { + return + } + } + } +} + +// AwaitNextBlock is a first class function that any caller can use to ensure a new block was minted. +// Returns the new height +func (s *SystemUnderTest) AwaitNextBlock(t *testing.T, timeout ...time.Duration) int64 { + t.Helper() + maxWaitTime := s.blockTime * 3 + if len(timeout) != 0 { // optional argument to overwrite default timeout + maxWaitTime = timeout[0] + } + done := make(chan int64) + go func() { + for start, current := s.currentHeight.Load(), s.currentHeight.Load(); current == start; current = s.currentHeight.Load() { + time.Sleep(s.blockTime) + } + done <- s.currentHeight.Load() + close(done) + }() + select { + case v := <-done: + return v + case <-time.NewTimer(maxWaitTime).C: + t.Fatalf("Timeout - no block within %s", maxWaitTime) + return -1 + } +} + +// ResetDirtyChain reset chain when non default setup or state (dirty) +func (s *SystemUnderTest) ResetDirtyChain(t *testing.T) { + t.Helper() + if s.IsDirty() { + s.ResetChain(t) + } +} + +// ResetChain stops and clears all nodes state via 'unsafe-reset-all' +func (s *SystemUnderTest) ResetChain(t *testing.T) { + t.Helper() + t.Log("Reset chain") + s.StopChain() + restoreOriginalGenesis(t, s) + restoreOriginalKeyring(t, s) + s.resetBuffers() + + // remove all additional nodes + for i := s.initialNodesCount; i < s.nodesCount; i++ { + _ = os.RemoveAll(filepath.Join(WorkDir, s.nodePath(i))) + _ = os.Remove(filepath.Join(WorkDir, s.outputDir, fmt.Sprintf("node%d.out", i))) + } + s.nodesCount = s.initialNodesCount + + // reset all validator nodes + s.ForEachNodeExecAndWait(t, []string{"comet", "unsafe-reset-all"}) + s.currentHeight.Store(0) + s.dirty = false +} + +// ModifyGenesisCLI executes the CLI commands to modify the genesis +func (s *SystemUnderTest) ModifyGenesisCLI(t *testing.T, cmds ...[]string) { + t.Helper() + s.ForEachNodeExecAndWait(t, cmds...) + s.MarkDirty() +} + +type GenesisMutator func([]byte) []byte + +// ModifyGenesisJSON resets the chain and executes the callbacks to update the json representation +// The mutator callbacks after each other receive the genesis as raw bytes and return the updated genesis for the next. +// example: +// +// return func(genesis []byte) []byte { +// val, _ := json.Marshal(sdk.NewDecCoins(fees...)) +// state, _ := sjson.SetRawBytes(genesis, "app_state.globalfee.params.minimum_gas_prices", val) +// return state +// } +func (s *SystemUnderTest) ModifyGenesisJSON(t *testing.T, mutators ...GenesisMutator) { + t.Helper() + s.ResetChain(t) + s.modifyGenesisJSON(t, mutators...) +} + +// modify json without enforcing a reset +func (s *SystemUnderTest) modifyGenesisJSON(t *testing.T, mutators ...GenesisMutator) { + t.Helper() + require.Empty(t, s.currentHeight.Load(), "forced chain reset required") + current, err := os.ReadFile(filepath.Join(WorkDir, s.nodePath(0), "config", "genesis.json")) + require.NoError(t, err) + for _, m := range mutators { + current = m(current) + } + out := StoreTempFile(t, current) + defer os.Remove(out.Name()) + s.setGenesis(t, out.Name()) + s.MarkDirty() +} + +// ReadGenesisJSON returns current genesis.json content as raw string +func (s *SystemUnderTest) ReadGenesisJSON(t *testing.T) string { + t.Helper() + content, err := os.ReadFile(filepath.Join(WorkDir, s.nodePath(0), "config", "genesis.json")) + require.NoError(t, err) + return string(content) +} + +// setGenesis copy genesis file to all nodes +func (s *SystemUnderTest) setGenesis(t *testing.T, srcPath string) { + t.Helper() + in, err := os.Open(srcPath) + require.NoError(t, err) + defer in.Close() + var buf bytes.Buffer + + _, err = io.Copy(&buf, in) + require.NoError(t, err) + + s.withEachNodeHome(func(i int, home string) { + require.NoError(t, saveGenesis(home, buf.Bytes())) + }) +} + +func saveGenesis(home string, content []byte) error { + out, err := os.Create(filepath.Join(WorkDir, home, "config", "genesis.json")) + if err != nil { + return fmt.Errorf("out file: %w", err) + } + defer out.Close() + + if _, err = io.Copy(out, bytes.NewReader(content)); err != nil { + return fmt.Errorf("write out file: %w", err) + } + + if err = out.Close(); err != nil { + return fmt.Errorf("close out file: %w", err) + } + return nil +} + +// ForEachNodeExecAndWait runs the given app executable commands for all cluster nodes synchronously +// The commands output is returned for each node. +func (s *SystemUnderTest) ForEachNodeExecAndWait(t *testing.T, cmds ...[]string) [][]string { + t.Helper() + result := make([][]string, s.nodesCount) + s.withEachNodeHome(func(i int, home string) { + result[i] = make([]string, len(cmds)) + for j, xargs := range cmds { + xargs = append(xargs, "--home", home) + s.Logf("Execute `%s %s`\n", s.execBinary, strings.Join(xargs, " ")) + out := MustRunShellCmd(t, s.execBinary, xargs...) + s.Logf("Result: %s\n", out) + result[i][j] = out + } + }) + return result +} + +func MustRunShellCmd(t *testing.T, cmd string, args ...string) string { + t.Helper() + out, err := RunShellCmd(cmd, args...) + require.NoError(t, err) + return out +} + +func RunShellCmd(cmd string, args ...string) (string, error) { + c := exec.Command( //nolint:gosec // used by tests only + locateExecutable(cmd), + args..., + ) + c.Dir = WorkDir + out, err := c.Output() + if err != nil { + return string(out), fmt.Errorf("run `%s %s`: out: %s: %w", cmd, strings.Join(args, " "), string(out), err) + } + return string(out), nil +} + +// startNodesAsync runs the given app cli command for all cluster nodes and returns without waiting +func (s *SystemUnderTest) startNodesAsync(t *testing.T, xargs ...string) { + t.Helper() + s.withEachNodeHome(func(i int, home string) { + args := append(xargs, "--home="+home) + s.Logf("Execute `%s %s`\n", s.execBinary, strings.Join(args, " ")) + cmd := exec.Command( //nolint:gosec // used by tests only + locateExecutable(s.execBinary), + args..., + ) + cmd.Dir = WorkDir + s.watchLogs(i, cmd) + require.NoError(t, cmd.Start(), "node %d", i) + s.Logf("Node started: %d\n", cmd.Process.Pid) + + // cleanup when stopped + s.awaitProcessCleanup(cmd) + }) +} + +// tracks the PID in state with a go routine waiting for the shutdown completion to unregister +func (s *SystemUnderTest) awaitProcessCleanup(cmd *exec.Cmd) { + pid := cmd.Process.Pid + s.pidsLock.Lock() + s.pids[pid] = struct{}{} + s.pidsLock.Unlock() + go func() { + _ = cmd.Wait() // blocks until shutdown + s.Logf("Node stopped: %d\n", pid) + s.pidsLock.Lock() + delete(s.pids, pid) + s.pidsLock.Unlock() + }() +} + +func (s *SystemUnderTest) withEachNodeHome(cb func(i int, home string)) { + for i := 0; i < s.nodesCount; i++ { + cb(i, s.nodePath(i)) + } +} + +// NodeDir returns the workdir and path to the node home folder. +func (s *SystemUnderTest) NodeDir(i int) string { + return filepath.Join(WorkDir, s.nodePath(i)) +} + +// nodePath returns the path of the node within the work dir. not absolute +func (s *SystemUnderTest) nodePath(i int) string { + return NodePath(i, s.outputDir, s.projectName) +} + +func NodePath(n int, outputDir, name string) string { + return fmt.Sprintf("%s/node%d/%s", outputDir, n, name) +} + +func (s *SystemUnderTest) Log(msg string) { + if s.verbose { + _, _ = fmt.Fprint(s.out, msg) + } +} + +func (s *SystemUnderTest) Logf(msg string, args ...interface{}) { + s.Log(fmt.Sprintf(msg, args...)) +} + +func (s *SystemUnderTest) RPCClient(t *testing.T) RPCClient { + t.Helper() + return NewRPCClient(t, s.rpcAddr) +} + +func (s *SystemUnderTest) APIAddress() string { + return s.apiAddr +} + +func (s *SystemUnderTest) AllPeers(t *testing.T) []string { + t.Helper() + result := make([]string, s.nodesCount) + for i, n := range s.AllNodes(t) { + result[i] = n.PeerAddr() + } + return result +} + +func (s *SystemUnderTest) AllNodes(t *testing.T) []Node { + t.Helper() + return AllNodes(t, s) +} + +func AllNodes(t *testing.T, s *SystemUnderTest) []Node { + t.Helper() + result := make([]Node, s.nodesCount) + outs := s.ForEachNodeExecAndWait(t, []string{"comet", "show-node-id"}) + ip := "127.0.0.1" + if false { // is there still a use case for external ip? + var err error + ip, err = server.ExternalIP() + require.NoError(t, err) + } + for i, out := range outs { + result[i] = Node{ + ID: strings.TrimSpace(out[0]), + IP: ip, + RPCPort: 26657 + i, // as defined in testnet command + P2PPort: 16656 + i, // as defined in testnet command + } + } + return result +} + +func (s *SystemUnderTest) resetBuffers() { + s.outBuff = ring.New(100) + s.errBuff = ring.New(100) +} + +// AddFullnode starts a new fullnode that connects to the existing chain but is not a validator. +func (s *SystemUnderTest) AddFullnode(t *testing.T, beforeStart ...func(nodeNumber int, nodePath string)) Node { + t.Helper() + s.MarkDirty() + s.nodesCount++ + nodeNumber := s.nodesCount - 1 + nodePath := s.nodePath(nodeNumber) + _ = os.RemoveAll(nodePath) // drop any legacy path, just in case + + // prepare new node + moniker := fmt.Sprintf("node%d", nodeNumber) + args := []string{"init", moniker, "--home=" + nodePath, "--overwrite"} + s.Logf("Execute `%s %s`\n", s.execBinary, strings.Join(args, " ")) + cmd := exec.Command( //nolint:gosec // used by tests only + locateExecutable(s.execBinary), + args..., + ) + cmd.Dir = WorkDir + s.watchLogs(nodeNumber, cmd) + require.NoError(t, cmd.Run(), "failed to start node with id %d", nodeNumber) + require.NoError(t, saveGenesis(nodePath, []byte(s.ReadGenesisJSON(t)))) + + configPath := filepath.Join(WorkDir, nodePath, "config") + + // start node + allNodes := s.AllNodes(t) + node := allNodes[len(allNodes)-1] + // quick hack: copy config and overwrite by start params + for _, tomlFile := range []string{"config.toml", "app.toml"} { + configFile := filepath.Join(configPath, tomlFile) + _ = os.Remove(configFile) + _ = MustCopyFile(filepath.Join(WorkDir, s.nodePath(0), "config", tomlFile), configFile) + if tomlFile == "app.toml" && IsV2() { + file := filepath.Join(WorkDir, s.nodePath(nodeNumber), "config", tomlFile) + EditToml(file, func(doc *tomledit.Document) { + SetValue(doc, fmt.Sprintf("%s:%d", node.IP, DefaultApiPort+nodeNumber), "grpc-gateway", "address") + SetValue(doc, fmt.Sprintf("%s:%d", node.IP, DefaultRestPort+nodeNumber), "rest", "address") + SetValue(doc, fmt.Sprintf("%s:%d", node.IP, DefaultTelemetryPort+nodeNumber), "telemetry", "address") + }) + } + } + peers := make([]string, len(allNodes)-1) + for i, n := range allNodes[0 : len(allNodes)-1] { + peers[i] = n.PeerAddr() + } + for _, c := range beforeStart { + c(nodeNumber, nodePath) + } + args = []string{ + "start", + "--p2p.persistent_peers=" + strings.Join(peers, ","), + fmt.Sprintf("--p2p.laddr=tcp://localhost:%d", node.P2PPort), + fmt.Sprintf("--rpc.laddr=tcp://localhost:%d", node.RPCPort), + fmt.Sprintf("--grpc.address=localhost:%d", DefaultGrpcPort+nodeNumber), + "--p2p.pex=false", + "--moniker=" + moniker, + "--log_level=info", + "--log_no_color", + "--home", nodePath, + } + s.Logf("Execute `%s %s`\n", s.execBinary, strings.Join(args, " ")) + cmd = exec.Command( //nolint:gosec // used by tests only + locateExecutable(s.execBinary), + args..., + ) + cmd.Dir = WorkDir + s.watchLogs(nodeNumber, cmd) + require.NoError(t, cmd.Start(), "node %d", nodeNumber) + s.awaitProcessCleanup(cmd) + return node +} + +// NewEventListener constructor for Eventlistener with system rpc address +func (s *SystemUnderTest) NewEventListener(t *testing.T) *EventListener { + t.Helper() + return NewEventListener(t, s.rpcAddr) +} + +// is any process let running? +func (s *SystemUnderTest) anyNodeRunning() bool { + s.pidsLock.RLock() + defer s.pidsLock.RUnlock() + return len(s.pids) != 0 +} + +func (s *SystemUnderTest) CurrentHeight() int64 { + return s.currentHeight.Load() +} + +// NodesCount returns the number of node instances used +func (s *SystemUnderTest) NodesCount() int { + return s.nodesCount +} + +func (s *SystemUnderTest) BlockTime() time.Duration { + return s.blockTime +} + +type Node struct { + ID string + IP string + RPCPort int + P2PPort int +} + +func (n Node) PeerAddr() string { + return fmt.Sprintf("%s@%s:%d", n.ID, n.IP, n.P2PPort) +} + +func (n Node) RPCAddr() string { + return fmt.Sprintf("tcp://%s:%d", n.IP, n.RPCPort) +} + +// locateExecutable looks up the binary on the OS path. +func locateExecutable(file string) string { + if strings.TrimSpace(file) == "" { + panic("executable binary name must not be empty") + } + path, err := exec.LookPath(file) + if err != nil { + panic(fmt.Sprintf("unexpected error with file %q: %s", file, err.Error())) + } + if path == "" { + panic(fmt.Sprintf("%q not found", file)) + } + return path +} + +// EventListener watches for events on the chain +type EventListener struct { + t *testing.T + client *client.HTTP +} + +// NewEventListener event listener +func NewEventListener(t *testing.T, rpcAddr string) *EventListener { + t.Helper() + httpClient, err := client.New(rpcAddr, "/websocket") + require.NoError(t, err) + require.NoError(t, httpClient.Start()) + return &EventListener{client: httpClient, t: t} +} + +var DefaultWaitTime = 30 * time.Second + +type ( + CleanupFn func() + EventConsumer func(e ctypes.ResultEvent) (more bool) +) + +// Subscribe to receive events for a topic. Does not block. +// For query syntax See https://docs.cosmos.network/master/core/events.html#subscribing-to-events +func (l *EventListener) Subscribe(query string, cb EventConsumer) func() { + ctx, done := context.WithCancel(context.Background()) + l.t.Cleanup(done) + eventsChan, err := l.client.WSEvents.Subscribe(ctx, "testing", query) + require.NoError(l.t, err) + cleanup := func() { + ctx, _ := context.WithTimeout(ctx, DefaultWaitTime) //nolint:govet // used in cleanup only + go l.client.WSEvents.Unsubscribe(ctx, "testing", query) //nolint:errcheck // used by tests only + done() + } + go func() { + for e := range eventsChan { + if !cb(e) { + return + } + } + }() + return cleanup +} + +// AwaitQuery blocks and waits for a single result or timeout. This can be used with `broadcast-mode=async`. +// For query syntax See https://docs.cosmos.network/master/core/events.html#subscribing-to-events +func (l *EventListener) AwaitQuery(query string, optMaxWaitTime ...time.Duration) *ctypes.ResultEvent { + c, result := CaptureSingleEventConsumer() + maxWaitTime := DefaultWaitTime + if len(optMaxWaitTime) != 0 { + maxWaitTime = optMaxWaitTime[0] + } + cleanupFn := l.Subscribe(query, TimeoutConsumer(l.t, maxWaitTime, c)) + l.t.Cleanup(cleanupFn) + return result +} + +// TimeoutConsumer is an event consumer decorator with a max wait time. Panics when wait time exceeded without +// a result returned +func TimeoutConsumer(t *testing.T, maxWaitTime time.Duration, next EventConsumer) EventConsumer { + t.Helper() + ctx, done := context.WithCancel(context.Background()) + t.Cleanup(done) + timeout := time.NewTimer(maxWaitTime) + timedOut := make(chan struct{}, 1) + go func() { + select { + case <-ctx.Done(): + case <-timeout.C: + timedOut <- struct{}{} + close(timedOut) + } + }() + return func(e ctypes.ResultEvent) (more bool) { + select { + case <-timedOut: + t.Fatalf("Timeout waiting for new events %s", maxWaitTime) + return false + default: + timeout.Reset(maxWaitTime) + result := next(e) + if !result { + done() + } + return result + } + } +} + +// CaptureSingleEventConsumer consumes one event. No timeout +func CaptureSingleEventConsumer() (EventConsumer, *ctypes.ResultEvent) { + var result ctypes.ResultEvent + return func(e ctypes.ResultEvent) (more bool) { + return false + }, &result +} + +// CaptureAllEventsConsumer is an `EventConsumer` that captures all events until `done()` is called to stop or timeout happens. +// The consumer works async in the background and returns all the captured events when `done()` is called. +// This can be used to verify that certain events have happened. +// Example usage: +// +// c, done := CaptureAllEventsConsumer(t) +// query := `tm.event='Tx'` +// cleanupFn := l.Subscribe(query, c) +// t.Cleanup(cleanupFn) +// +// // do something in your test that create events +// +// assert.Len(t, done(), 1) // then verify your assumption +func CaptureAllEventsConsumer(t *testing.T, optMaxWaitTime ...time.Duration) (c EventConsumer, done func() []ctypes.ResultEvent) { + t.Helper() + maxWaitTime := DefaultWaitTime + if len(optMaxWaitTime) != 0 { + maxWaitTime = optMaxWaitTime[0] + } + var ( + mu sync.Mutex + capturedEvents []ctypes.ResultEvent + exit bool + ) + collectEventsConsumer := func(e ctypes.ResultEvent) (more bool) { + mu.Lock() + defer mu.Unlock() + if exit { + return false + } + capturedEvents = append(capturedEvents, e) + return true + } + + return TimeoutConsumer(t, maxWaitTime, collectEventsConsumer), func() []ctypes.ResultEvent { + mu.Lock() + defer mu.Unlock() + exit = true + return capturedEvents + } +} + +// restoreOriginalGenesis replace nodes genesis by the one created on setup +func restoreOriginalGenesis(t *testing.T, s *SystemUnderTest) { + t.Helper() + src := filepath.Join(WorkDir, s.nodePath(0), "config", "genesis.json.orig") + s.setGenesis(t, src) +} + +// restoreOriginalKeyring replaces test keyring with original +func restoreOriginalKeyring(t *testing.T, s *SystemUnderTest) { + t.Helper() + dest := filepath.Join(WorkDir, s.outputDir, "keyring-test") + require.NoError(t, os.RemoveAll(dest)) + for i := 0; i < s.initialNodesCount; i++ { + src := filepath.Join(WorkDir, s.nodePath(i), "keyring-test") + MustCopyFilesInDir(src, dest) + } +} diff --git a/systemtests/testnet_init.go b/systemtests/testnet_init.go new file mode 100644 index 000000000000..1e7b41378220 --- /dev/null +++ b/systemtests/testnet_init.go @@ -0,0 +1,228 @@ +package systemtests + +import ( + "fmt" + "os" + "path/filepath" + "strconv" + "strings" + "time" + + "github.com/cometbft/cometbft/p2p" + "github.com/creachadair/tomledit" + "github.com/creachadair/tomledit/parser" +) + +// IsV2 checks if the tests run with simapp v2 +func IsV2() bool { + buildOptions := os.Getenv("COSMOS_BUILD_OPTIONS") + return strings.Contains(buildOptions, "v2") +} + +// SingleHostTestnetCmdInitializer default testnet cmd that supports the --single-host param +type SingleHostTestnetCmdInitializer struct { + execBinary string + workDir string + chainID string + outputDir string + initialNodesCount int + minGasPrice string + commitTimeout time.Duration + log func(string) +} + +// NewSingleHostTestnetCmdInitializer constructor +func NewSingleHostTestnetCmdInitializer( + execBinary, workDir, chainID, outputDir string, + initialNodesCount int, + minGasPrice string, + commitTimeout time.Duration, + log func(string), +) *SingleHostTestnetCmdInitializer { + return &SingleHostTestnetCmdInitializer{ + execBinary: execBinary, + workDir: workDir, + chainID: chainID, + outputDir: outputDir, + initialNodesCount: initialNodesCount, + minGasPrice: minGasPrice, + commitTimeout: commitTimeout, + log: log, + } +} + +// InitializerWithBinary creates new SingleHostTestnetCmdInitializer from sut with given binary +func InitializerWithBinary(binary string, sut *SystemUnderTest) TestnetInitializer { + return NewSingleHostTestnetCmdInitializer( + binary, + WorkDir, + sut.chainID, + sut.outputDir, + sut.initialNodesCount, + sut.minGasPrice, + sut.CommitTimeout(), + sut.Log, + ) +} + +func (s SingleHostTestnetCmdInitializer) Initialize() { + args := []string{ + "testnet", + "init-files", + "--chain-id=" + s.chainID, + "--output-dir=" + s.outputDir, + "--validator-count=" + strconv.Itoa(s.initialNodesCount), + "--keyring-backend=test", + "--commit-timeout=" + s.commitTimeout.String(), + "--single-host", + } + + if IsV2() { + args = append(args, "--server.minimum-gas-prices="+s.minGasPrice) + } else { + args = append(args, "--minimum-gas-prices="+s.minGasPrice) + } + + s.log(fmt.Sprintf("+++ %s %s\n", s.execBinary, strings.Join(args, " "))) + out, err := RunShellCmd(s.execBinary, args...) + if err != nil { + panic(err) + } + s.log(out) +} + +// ModifyConfigYamlInitializer testnet cmd prior to --single-host param. Modifies the toml files. +type ModifyConfigYamlInitializer struct { + execBinary string + workDir string + chainID string + outputDir string + initialNodesCount int + minGasPrice string + commitTimeout time.Duration + log func(string) + projectName string +} + +func NewModifyConfigYamlInitializer(exec string, s *SystemUnderTest) *ModifyConfigYamlInitializer { + return &ModifyConfigYamlInitializer{ + execBinary: exec, + workDir: WorkDir, + chainID: s.chainID, + outputDir: s.outputDir, + initialNodesCount: s.initialNodesCount, + minGasPrice: s.minGasPrice, + commitTimeout: s.CommitTimeout(), + log: s.Log, + projectName: s.projectName, + } +} + +func (s ModifyConfigYamlInitializer) Initialize() { + // init with legacy testnet command + args := []string{ + "testnet", + "init-files", + "--chain-id=" + s.chainID, + "--output-dir=" + s.outputDir, + "--v=" + strconv.Itoa(s.initialNodesCount), + "--keyring-backend=test", + } + + if IsV2() { + args = append(args, "--server.minimum-gas-prices="+s.minGasPrice) + } else { + args = append(args, "--minimum-gas-prices="+s.minGasPrice) + } + + s.log(fmt.Sprintf("+++ %s %s\n", s.execBinary, strings.Join(args, " "))) + + out, err := RunShellCmd(s.execBinary, args...) + if err != nil { + panic(err) + } + s.log(out) + + nodeAddresses := make([]string, s.initialNodesCount) + for i := 0; i < s.initialNodesCount; i++ { + nodeDir := filepath.Join(WorkDir, NodePath(i, s.outputDir, s.projectName), "config") + id := string(mustV(p2p.LoadNodeKey(filepath.Join(nodeDir, "node_key.json"))).ID()) + nodeAddresses[i] = fmt.Sprintf("%s@127.0.0.1:%d", id, DefaultP2PPort+i) + } + + // then update configs + for i := 0; i < s.initialNodesCount; i++ { + nodeDir := filepath.Join(WorkDir, NodePath(i, s.outputDir, s.projectName), "config") + nodeNumber := i + EditToml(filepath.Join(nodeDir, "config.toml"), func(doc *tomledit.Document) { + UpdatePort(doc, DefaultRpcPort+i, "rpc", "laddr") + UpdatePort(doc, DefaultP2PPort+i, "p2p", "laddr") + SetBool(doc, false, "p2p", "addr_book_strict") + SetBool(doc, false, "p2p", "pex") + SetBool(doc, true, "p2p", "allow_duplicate_ip") + peers := make([]string, s.initialNodesCount) + copy(peers, nodeAddresses[0:nodeNumber]) + copy(peers[nodeNumber:], nodeAddresses[nodeNumber+1:]) + SetValue(doc, strings.Join(peers, ","), "p2p", "persistent_peers") + SetValue(doc, s.commitTimeout.String(), "consensus", "timeout_commit") + SetValue(doc, "goleveldb", "db_backend") + }) + EditToml(filepath.Join(nodeDir, "app.toml"), func(doc *tomledit.Document) { + UpdatePort(doc, DefaultApiPort+i, "api", "address") + UpdatePort(doc, DefaultGrpcPort+i, "grpc", "address") + }) + } +} + +func EditToml(filename string, f func(doc *tomledit.Document)) { + tomlFile := mustV(os.OpenFile(filename, os.O_RDWR, 0o600)) + defer tomlFile.Close() + doc := mustV(tomledit.Parse(tomlFile)) + f(doc) + mustV(tomlFile.Seek(0, 0)) // reset the cursor to the beginning of the file + must(tomlFile.Truncate(0)) + must(tomledit.Format(tomlFile, doc)) +} + +func SetBool(doc *tomledit.Document, newVal bool, xpath ...string) { + e := doc.First(xpath...) + if e == nil { + panic(fmt.Sprintf("not found: %v", xpath)) + } + e.Value = parser.MustValue(strconv.FormatBool(newVal)) +} + +func SetValue(doc *tomledit.Document, newVal string, xpath ...string) { + e := doc.First(xpath...) + if e == nil { + panic(fmt.Sprintf("not found: %v", xpath)) + } + e.Value = parser.MustValue(fmt.Sprintf("%q", newVal)) +} + +func UpdatePort(doc *tomledit.Document, newPort int, xpath ...string) { + e := doc.First(xpath...) + if e == nil { + panic(fmt.Sprintf("not found: %v", xpath)) + } + data := e.Value.X.String() + pos := strings.LastIndexAny(data, ":") + if pos == -1 { + panic("column not found") + } + data = data[0:pos+1] + strconv.Itoa(newPort) + e.Value = parser.MustValue(data + "\"") +} + +// mustV same as must but with value returned +func mustV[T any](r T, err error) T { + must(err) + return r +} + +// must simple panic on error for fluent calls +func must(err error) { + if err != nil { + panic(err) + } +} diff --git a/tests/go.mod b/tests/go.mod index 22aabbf400e2..bb3c3e673a3a 100644 --- a/tests/go.mod +++ b/tests/go.mod @@ -49,7 +49,12 @@ require ( cosmossdk.io/x/slashing v0.2.0-rc.1 cosmossdk.io/x/staking v0.2.0-rc.1 github.com/cometbft/cometbft/api v1.0.0 +<<<<<<< HEAD github.com/cosmos/cosmos-db v1.1.0 // indirect +======= + github.com/cosmos/cosmos-db v1.1.1 + github.com/gogo/protobuf v1.3.2 // indirect +>>>>>>> a9c114915 (test: investigate test failure due to wal log (#22679)) github.com/google/go-cmp v0.6.0 github.com/google/gofuzz v1.2.0 github.com/jhump/protoreflect v1.17.0 diff --git a/tests/go.sum b/tests/go.sum index d35d8ff90e7c..9002ba65b1d3 100644 --- a/tests/go.sum +++ b/tests/go.sum @@ -337,8 +337,8 @@ github.com/containerd/continuity v0.3.0/go.mod h1:wJEAIwKOm/pBZuBd0JmeTvnLquTB1A github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= github.com/cosmos/btcutil v1.0.5 h1:t+ZFcX77LpKtDBhjucvnOH8C2l2ioGsBNEQ3jef8xFk= github.com/cosmos/btcutil v1.0.5/go.mod h1:IyB7iuqZMJlthe2tkIFL33xPyzbFYP0XVdS8P5lUPis= -github.com/cosmos/cosmos-db v1.1.0 h1:KLHNVQ73h7vawXTpj9UJ7ZR2IXv51tsEHkQJJ9EBDzI= -github.com/cosmos/cosmos-db v1.1.0/go.mod h1:t7c4A6cfGdpUwwVxrQ0gQLeRQqGUBJu0yvE4F/26REg= +github.com/cosmos/cosmos-db v1.1.1 h1:FezFSU37AlBC8S98NlSagL76oqBRWq/prTPvFcEJNCM= +github.com/cosmos/cosmos-db v1.1.1/go.mod h1:AghjcIPqdhSLP/2Z0yha5xPH3nLnskz81pBx3tcVSAw= github.com/cosmos/cosmos-proto v1.0.0-beta.5 h1:eNcayDLpip+zVLRLYafhzLvQlSmyab+RC5W7ZfmxJLA= github.com/cosmos/cosmos-proto v1.0.0-beta.5/go.mod h1:hQGLpiIUloJBMdQMMWb/4wRApmI9hjHH05nefC0Ojec= github.com/cosmos/go-bip39 v1.0.0 h1:pcomnQdrdH22njcAatO0yWojsUnCO3y2tNoV1cb6hHY= diff --git a/tests/systemtests/export_test.go b/tests/systemtests/export_test.go index bd50457cb234..279bb7f00a9a 100644 --- a/tests/systemtests/export_test.go +++ b/tests/systemtests/export_test.go @@ -6,7 +6,6 @@ import ( "fmt" "os" "path/filepath" - "strings" "testing" "github.com/stretchr/testify/assert" @@ -44,6 +43,7 @@ func TestChainExportImport(t *testing.T) { }) systest.Sut.StartChain(t) systest.Sut.AwaitNBlocks(t, 2) + systest.Sut.StopChain() } func TestExportCmd_WithHeight(t *testing.T) { @@ -62,22 +62,16 @@ func TestExportCmd_WithHeight(t *testing.T) { args []string expZeroHeight bool }{ - {"should export correct height", []string{"genesis", "export", "--home", systest.Sut.NodeDir(0), "--log_level=disabled"}, false}, - {"should export correct height with --height", []string{"genesis", "export", "--height=5", "--home", systest.Sut.NodeDir(0), "--log_level=disabled"}, false}, - {"should export height 0 with --for-zero-height", []string{"genesis", "export", "--for-zero-height=true", "--home", systest.Sut.NodeDir(0), "--log_level=disabled"}, true}, + {"should export correct height", []string{"genesis", "export", "--home", systest.Sut.NodeDir(0), disabledLog}, false}, + {"should export correct height with --height", []string{"genesis", "export", "--height=5", "--home", systest.Sut.NodeDir(0), disabledLog}, false}, + {"should export height 0 with --for-zero-height", []string{"genesis", "export", "--for-zero-height=true", "--home", systest.Sut.NodeDir(0), disabledLog}, true}, } for _, tc := range testCases { - res := cli.RunCommandWithArgs(tc.args...) - // PebbleDB logs are printed directly to stderr. - // Cosmos-DB and Store/v2 do not provide a way to override the logger. - // This isn't problematic in a real-world scenario, but it makes it hard to test the output. - // https://github.com/cockroachdb/pebble/blob/v1.1.2/internal/base/logger.go#L26-L40 - // We trim the output to get the JSON part only - if i := strings.Index(res, "{"); i > 0 { - res = res[i:] - } - + res := cli. + WithRunErrorsIgnored(). + WithRunSingleOutput(). // pebbledb prints logs to stderr, we cannot override the logger in store/v2 and cosmos-db. This isn't problematic in a real-world scenario, but it makes it hard to test the output + RunCommandWithArgs(tc.args...) height := gjson.Get(res, "initial_height").Int() if tc.expZeroHeight { require.Equal(t, height, int64(0)) diff --git a/tests/systemtests/go.mod b/tests/systemtests/go.mod index ad47ff371aca..42272f8435aa 100644 --- a/tests/systemtests/go.mod +++ b/tests/systemtests/go.mod @@ -4,6 +4,7 @@ go 1.23.1 require ( cosmossdk.io/math v1.4.0 +<<<<<<< HEAD cosmossdk.io/systemtests v1.0.0-rc.4 github.com/cosmos/cosmos-sdk v0.50.6 github.com/cosmos/gogogateway v1.2.0 // indirect @@ -24,6 +25,10 @@ require ( github.com/tidwall/sjson v1.2.5 google.golang.org/genproto v0.0.0-20240227224415-6ceb2ff114de // indirect google.golang.org/grpc v1.68.1 // indirect +======= + cosmossdk.io/systemtests v1.0.0-rc.4.0.20241219115822-5bebfb028815 + github.com/cosmos/cosmos-sdk v0.50.11 +>>>>>>> a9c114915 (test: investigate test failure due to wal log (#22679)) ) require ( diff --git a/tests/systemtests/go.sum b/tests/systemtests/go.sum index 1e2a4677226c..1dda2048fa75 100644 --- a/tests/systemtests/go.sum +++ b/tests/systemtests/go.sum @@ -14,10 +14,17 @@ cosmossdk.io/log v1.5.0 h1:dVdzPJW9kMrnAYyMf1duqacoidB9uZIl+7c6z0mnq0g= cosmossdk.io/log v1.5.0/go.mod h1:Tr46PUJjiUthlwQ+hxYtUtPn4D/oCZXAkYevBeh5+FI= cosmossdk.io/math v1.4.0 h1:XbgExXFnXmF/CccPPEto40gOO7FpWu9yWNAZPN3nkNQ= cosmossdk.io/math v1.4.0/go.mod h1:O5PkD4apz2jZs4zqFdTr16e1dcaQCc5z6lkEnrrppuk= +<<<<<<< HEAD cosmossdk.io/store v1.1.0 h1:LnKwgYMc9BInn9PhpTFEQVbL9UK475G2H911CGGnWHk= cosmossdk.io/store v1.1.0/go.mod h1:oZfW/4Fc/zYqu3JmQcQdUJ3fqu5vnYTn3LZFFy8P8ng= cosmossdk.io/systemtests v1.0.0-rc.4 h1:AbVrPlkNFadArOsDReeCKXhVITW3Hzv6BDBcAwMIE8s= cosmossdk.io/systemtests v1.0.0-rc.4/go.mod h1:RfkegSDKIEx0XdMenpmubgnJm3PtaRTAYkXvV2uJGMw= +======= +cosmossdk.io/store v1.1.1 h1:NA3PioJtWDVU7cHHeyvdva5J/ggyLDkyH0hGHl2804Y= +cosmossdk.io/store v1.1.1/go.mod h1:8DwVTz83/2PSI366FERGbWSH7hL6sB7HbYp8bqksNwM= +cosmossdk.io/systemtests v1.0.0-rc.4.0.20241219115822-5bebfb028815 h1:ilHcBaGJrYhEKC2gO+DVBmWOPNt1VUWNQz3g7/9X4Ow= +cosmossdk.io/systemtests v1.0.0-rc.4.0.20241219115822-5bebfb028815/go.mod h1:tTDdBl9wnIyP4L1Gi1/GXD1onPfaAOsscWCw7JUuJ/A= +>>>>>>> a9c114915 (test: investigate test failure due to wal log (#22679)) cosmossdk.io/x/tx v1.0.0-alpha.3 h1:+55/JFH5QRqnFhOI2heH3DKsaNL0RpXcJOQNzUvHiaQ= cosmossdk.io/x/tx v1.0.0-alpha.3/go.mod h1:h4pQ/j6Gfu8goB1R3Jbl4qY4RjYVNAsoylcleTXdSRg= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= diff --git a/tests/systemtests/snapshots_test.go b/tests/systemtests/snapshots_test.go index 3377e55fb7af..6fae39749eb4 100644 --- a/tests/systemtests/snapshots_test.go +++ b/tests/systemtests/snapshots_test.go @@ -12,8 +12,10 @@ import ( systest "cosmossdk.io/systemtests" ) +const disabledLog = "--log_level=disabled" + func TestSnapshots(t *testing.T) { - t.Skip("Skip snapshots test, flaky due to pebbledb logs on CI") + t.Skip("Not persisting properly on CI") systest.Sut.ResetChain(t) cli := systest.NewCLIWrapper(t, systest.Sut, systest.Verbose) @@ -38,28 +40,25 @@ func TestSnapshots(t *testing.T) { } // export snapshot at height 5 - res := cli.RunCommandWithArgs(command, "export", "--height=5", fmt.Sprintf("--home=%s", node0Dir)) + res := cli.RunCommandWithArgs(command, "export", "--height=5", fmt.Sprintf("--home=%s", node0Dir), disabledLog) require.Contains(t, res, "Snapshot created at height 5") require.DirExists(t, fmt.Sprintf("%s/data/snapshots/5/3", node0Dir)) // Check snapshots list - res = cli. - WithRunErrorsIgnored(). - WithRunSingleOutput(). // pebbledb prints logs to stderr, we cannot override the logger in store/v2 and cosmos-db. This isn't problematic in a real-world scenario, but it makes it hard to test the output. - RunCommandWithArgs(command, "list", fmt.Sprintf("--home=%s", node0Dir)) + res = cli.RunCommandWithArgs(command, "list", fmt.Sprintf("--home=%s", node0Dir), disabledLog) require.Contains(t, res, "height: 5") // Dump snapshot - res = cli.RunCommandWithArgs(command, "dump", "5", "3", fmt.Sprintf("--home=%s", node0Dir), fmt.Sprintf("--output=%s/5-3.tar.gz", node0Dir)) + res = cli.RunCommandWithArgs(command, "dump", "5", "3", fmt.Sprintf("--home=%s", node0Dir), fmt.Sprintf("--output=%s/5-3.tar.gz", node0Dir), disabledLog) // Check if output file exist require.FileExists(t, fmt.Sprintf("%s/5-3.tar.gz", node0Dir)) // Delete snapshots - res = cli.RunCommandWithArgs(command, "delete", "5", "3", fmt.Sprintf("--home=%s", node0Dir)) + res = cli.RunCommandWithArgs(command, "delete", "5", "3", fmt.Sprintf("--home=%s", node0Dir), disabledLog) require.NoDirExists(t, fmt.Sprintf("%s/data/snapshots/5/3", node0Dir)) // Load snapshot from file - res = cli.RunCommandWithArgs(command, "load", fmt.Sprintf("%s/5-3.tar.gz", node0Dir), fmt.Sprintf("--home=%s", node0Dir)) + res = cli.RunCommandWithArgs(command, "load", fmt.Sprintf("%s/5-3.tar.gz", node0Dir), fmt.Sprintf("--home=%s", node0Dir), disabledLog) require.DirExists(t, fmt.Sprintf("%s/data/snapshots/5/3", node0Dir)) // Restore from snapshots @@ -73,14 +72,14 @@ func TestSnapshots(t *testing.T) { require.NoError(t, os.RemoveAll(fmt.Sprintf("%s/data/ss", node0Dir))) } - res = cli.RunCommandWithArgs(command, "restore", "5", "3", fmt.Sprintf("--home=%s", node0Dir)) + res = cli.RunCommandWithArgs(command, "restore", "5", "3", fmt.Sprintf("--home=%s", node0Dir), disabledLog) for _, dir := range restoreableDirs { require.DirExists(t, dir) } } func TestPrune(t *testing.T) { - t.Skip("Skip snapshots test, flaky due to pebbledb logs on CI") + t.Skip("Not persisting properly on CI") systest.Sut.ResetChain(t) cli := systest.NewCLIWrapper(t, systest.Sut, systest.Verbose) @@ -102,6 +101,6 @@ func TestPrune(t *testing.T) { } else { command = []string{"prune", "everything"} } - res := cli.RunCommandWithArgs(append(command, fmt.Sprintf("--home=%s", node0Dir))...) + res := cli.RunCommandWithArgs(append(command, fmt.Sprintf("--home=%s", node0Dir), disabledLog)...) require.Contains(t, res, "successfully pruned the application root multi stores") } diff --git a/tools/benchmark/go.sum b/tools/benchmark/go.sum index 05a7bc99f6cd..009ec84d06a8 100644 --- a/tools/benchmark/go.sum +++ b/tools/benchmark/go.sum @@ -102,8 +102,8 @@ github.com/cometbft/cometbft/api v1.0.0/go.mod h1:EkQiqVSu/p2ebrZEnB2z6Re7r8XNe/ github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= github.com/cosmos/btcutil v1.0.5 h1:t+ZFcX77LpKtDBhjucvnOH8C2l2ioGsBNEQ3jef8xFk= github.com/cosmos/btcutil v1.0.5/go.mod h1:IyB7iuqZMJlthe2tkIFL33xPyzbFYP0XVdS8P5lUPis= -github.com/cosmos/cosmos-db v1.1.0 h1:KLHNVQ73h7vawXTpj9UJ7ZR2IXv51tsEHkQJJ9EBDzI= -github.com/cosmos/cosmos-db v1.1.0/go.mod h1:t7c4A6cfGdpUwwVxrQ0gQLeRQqGUBJu0yvE4F/26REg= +github.com/cosmos/cosmos-db v1.1.1 h1:FezFSU37AlBC8S98NlSagL76oqBRWq/prTPvFcEJNCM= +github.com/cosmos/cosmos-db v1.1.1/go.mod h1:AghjcIPqdhSLP/2Z0yha5xPH3nLnskz81pBx3tcVSAw= github.com/cosmos/cosmos-proto v1.0.0-beta.5 h1:eNcayDLpip+zVLRLYafhzLvQlSmyab+RC5W7ZfmxJLA= github.com/cosmos/cosmos-proto v1.0.0-beta.5/go.mod h1:hQGLpiIUloJBMdQMMWb/4wRApmI9hjHH05nefC0Ojec= github.com/cosmos/cosmos-sdk v0.52.0-rc.1 h1:HgHOUYbxvjvyiX5CQF4eLT0u1wvjxajwgClOGzAmNoQ= diff --git a/tools/confix/data/v2-app.toml b/tools/confix/data/v2-app.toml index 7d136a84c2c6..51c1e3298dfe 100644 --- a/tools/confix/data/v2-app.toml +++ b/tools/confix/data/v2-app.toml @@ -86,7 +86,7 @@ skip-fast-storage-upgrade = true # Enable enables the application telemetry functionality. When enabled, an in-memory sink is also enabled by default. Operators may also enabled other sinks such as Prometheus. enable = true # Address defines the metrics server address to bind to. -address = 'localhost:1327' +address = 'localhost:7180' # Prefixed with keys to separate services. service-name = '' # Enable prefixing gauge values with hostname. diff --git a/x/accounts/defaults/base/go.mod b/x/accounts/defaults/base/go.mod index b869d2d88ece..a65131b5146b 100644 --- a/x/accounts/defaults/base/go.mod +++ b/x/accounts/defaults/base/go.mod @@ -50,7 +50,7 @@ require ( github.com/cometbft/cometbft-db v1.0.1 // indirect github.com/cometbft/cometbft/api v1.0.0 // indirect github.com/cosmos/btcutil v1.0.5 // indirect - github.com/cosmos/cosmos-db v1.1.0 // indirect + github.com/cosmos/cosmos-db v1.1.1 // indirect github.com/cosmos/cosmos-proto v1.0.0-beta.5 // indirect github.com/cosmos/go-bip39 v1.0.0 // indirect github.com/cosmos/gogogateway v1.2.0 // indirect diff --git a/x/accounts/defaults/base/go.sum b/x/accounts/defaults/base/go.sum index e37065c4f2f6..d74d22b37607 100644 --- a/x/accounts/defaults/base/go.sum +++ b/x/accounts/defaults/base/go.sum @@ -123,8 +123,8 @@ github.com/containerd/continuity v0.3.0/go.mod h1:wJEAIwKOm/pBZuBd0JmeTvnLquTB1A github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= github.com/cosmos/btcutil v1.0.5 h1:t+ZFcX77LpKtDBhjucvnOH8C2l2ioGsBNEQ3jef8xFk= github.com/cosmos/btcutil v1.0.5/go.mod h1:IyB7iuqZMJlthe2tkIFL33xPyzbFYP0XVdS8P5lUPis= -github.com/cosmos/cosmos-db v1.1.0 h1:KLHNVQ73h7vawXTpj9UJ7ZR2IXv51tsEHkQJJ9EBDzI= -github.com/cosmos/cosmos-db v1.1.0/go.mod h1:t7c4A6cfGdpUwwVxrQ0gQLeRQqGUBJu0yvE4F/26REg= +github.com/cosmos/cosmos-db v1.1.1 h1:FezFSU37AlBC8S98NlSagL76oqBRWq/prTPvFcEJNCM= +github.com/cosmos/cosmos-db v1.1.1/go.mod h1:AghjcIPqdhSLP/2Z0yha5xPH3nLnskz81pBx3tcVSAw= github.com/cosmos/cosmos-proto v1.0.0-beta.5 h1:eNcayDLpip+zVLRLYafhzLvQlSmyab+RC5W7ZfmxJLA= github.com/cosmos/cosmos-proto v1.0.0-beta.5/go.mod h1:hQGLpiIUloJBMdQMMWb/4wRApmI9hjHH05nefC0Ojec= github.com/cosmos/cosmos-sdk v0.52.0-rc.1 h1:HgHOUYbxvjvyiX5CQF4eLT0u1wvjxajwgClOGzAmNoQ= diff --git a/x/accounts/defaults/lockup/go.sum b/x/accounts/defaults/lockup/go.sum index 4884a40f652e..8b4445b976dd 100644 --- a/x/accounts/defaults/lockup/go.sum +++ b/x/accounts/defaults/lockup/go.sum @@ -106,8 +106,8 @@ github.com/cometbft/cometbft/api v1.0.0/go.mod h1:EkQiqVSu/p2ebrZEnB2z6Re7r8XNe/ github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= github.com/cosmos/btcutil v1.0.5 h1:t+ZFcX77LpKtDBhjucvnOH8C2l2ioGsBNEQ3jef8xFk= github.com/cosmos/btcutil v1.0.5/go.mod h1:IyB7iuqZMJlthe2tkIFL33xPyzbFYP0XVdS8P5lUPis= -github.com/cosmos/cosmos-db v1.1.0 h1:KLHNVQ73h7vawXTpj9UJ7ZR2IXv51tsEHkQJJ9EBDzI= -github.com/cosmos/cosmos-db v1.1.0/go.mod h1:t7c4A6cfGdpUwwVxrQ0gQLeRQqGUBJu0yvE4F/26REg= +github.com/cosmos/cosmos-db v1.1.1 h1:FezFSU37AlBC8S98NlSagL76oqBRWq/prTPvFcEJNCM= +github.com/cosmos/cosmos-db v1.1.1/go.mod h1:AghjcIPqdhSLP/2Z0yha5xPH3nLnskz81pBx3tcVSAw= github.com/cosmos/cosmos-proto v1.0.0-beta.5 h1:eNcayDLpip+zVLRLYafhzLvQlSmyab+RC5W7ZfmxJLA= github.com/cosmos/cosmos-proto v1.0.0-beta.5/go.mod h1:hQGLpiIUloJBMdQMMWb/4wRApmI9hjHH05nefC0Ojec= github.com/cosmos/cosmos-sdk v0.52.0-rc.1 h1:HgHOUYbxvjvyiX5CQF4eLT0u1wvjxajwgClOGzAmNoQ= diff --git a/x/accounts/defaults/multisig/go.mod b/x/accounts/defaults/multisig/go.mod index 372332dc8c6f..808fed61bc32 100644 --- a/x/accounts/defaults/multisig/go.mod +++ b/x/accounts/defaults/multisig/go.mod @@ -50,7 +50,7 @@ require ( github.com/cometbft/cometbft-db v1.0.1 // indirect github.com/cometbft/cometbft/api v1.0.0 // indirect github.com/cosmos/btcutil v1.0.5 // indirect - github.com/cosmos/cosmos-db v1.1.0 // indirect + github.com/cosmos/cosmos-db v1.1.1 // indirect github.com/cosmos/go-bip39 v1.0.0 // indirect github.com/cosmos/gogogateway v1.2.0 // indirect github.com/cosmos/iavl v1.3.4 // indirect diff --git a/x/accounts/defaults/multisig/go.sum b/x/accounts/defaults/multisig/go.sum index e37065c4f2f6..d74d22b37607 100644 --- a/x/accounts/defaults/multisig/go.sum +++ b/x/accounts/defaults/multisig/go.sum @@ -123,8 +123,8 @@ github.com/containerd/continuity v0.3.0/go.mod h1:wJEAIwKOm/pBZuBd0JmeTvnLquTB1A github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= github.com/cosmos/btcutil v1.0.5 h1:t+ZFcX77LpKtDBhjucvnOH8C2l2ioGsBNEQ3jef8xFk= github.com/cosmos/btcutil v1.0.5/go.mod h1:IyB7iuqZMJlthe2tkIFL33xPyzbFYP0XVdS8P5lUPis= -github.com/cosmos/cosmos-db v1.1.0 h1:KLHNVQ73h7vawXTpj9UJ7ZR2IXv51tsEHkQJJ9EBDzI= -github.com/cosmos/cosmos-db v1.1.0/go.mod h1:t7c4A6cfGdpUwwVxrQ0gQLeRQqGUBJu0yvE4F/26REg= +github.com/cosmos/cosmos-db v1.1.1 h1:FezFSU37AlBC8S98NlSagL76oqBRWq/prTPvFcEJNCM= +github.com/cosmos/cosmos-db v1.1.1/go.mod h1:AghjcIPqdhSLP/2Z0yha5xPH3nLnskz81pBx3tcVSAw= github.com/cosmos/cosmos-proto v1.0.0-beta.5 h1:eNcayDLpip+zVLRLYafhzLvQlSmyab+RC5W7ZfmxJLA= github.com/cosmos/cosmos-proto v1.0.0-beta.5/go.mod h1:hQGLpiIUloJBMdQMMWb/4wRApmI9hjHH05nefC0Ojec= github.com/cosmos/cosmos-sdk v0.52.0-rc.1 h1:HgHOUYbxvjvyiX5CQF4eLT0u1wvjxajwgClOGzAmNoQ= diff --git a/x/accounts/go.mod b/x/accounts/go.mod index aeedf9b7ad19..c84f8e300b4b 100644 --- a/x/accounts/go.mod +++ b/x/accounts/go.mod @@ -23,8 +23,13 @@ require ( github.com/bytedance/sonic/loader v0.2.1 // indirect github.com/cloudwego/base64x v0.1.4 // indirect github.com/cloudwego/iasm v0.2.0 // indirect +<<<<<<< HEAD github.com/cockroachdb/fifo v0.0.0-20240816210425-c5d0cb0b6fc0 // indirect github.com/cosmos/cosmos-db v1.1.0 // indirect +======= + github.com/cockroachdb/fifo v0.0.0-20240606204812-0bbfbd93a7ce // indirect + github.com/cosmos/cosmos-db v1.1.1 // indirect +>>>>>>> a9c114915 (test: investigate test failure due to wal log (#22679)) github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0 // indirect github.com/dgraph-io/ristretto/v2 v2.0.0 // indirect github.com/google/uuid v1.6.0 // indirect diff --git a/x/accounts/go.sum b/x/accounts/go.sum index 712fad4822ab..dd6fe9ff026d 100644 --- a/x/accounts/go.sum +++ b/x/accounts/go.sum @@ -121,8 +121,8 @@ github.com/containerd/continuity v0.3.0/go.mod h1:wJEAIwKOm/pBZuBd0JmeTvnLquTB1A github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= github.com/cosmos/btcutil v1.0.5 h1:t+ZFcX77LpKtDBhjucvnOH8C2l2ioGsBNEQ3jef8xFk= github.com/cosmos/btcutil v1.0.5/go.mod h1:IyB7iuqZMJlthe2tkIFL33xPyzbFYP0XVdS8P5lUPis= -github.com/cosmos/cosmos-db v1.1.0 h1:KLHNVQ73h7vawXTpj9UJ7ZR2IXv51tsEHkQJJ9EBDzI= -github.com/cosmos/cosmos-db v1.1.0/go.mod h1:t7c4A6cfGdpUwwVxrQ0gQLeRQqGUBJu0yvE4F/26REg= +github.com/cosmos/cosmos-db v1.1.1 h1:FezFSU37AlBC8S98NlSagL76oqBRWq/prTPvFcEJNCM= +github.com/cosmos/cosmos-db v1.1.1/go.mod h1:AghjcIPqdhSLP/2Z0yha5xPH3nLnskz81pBx3tcVSAw= github.com/cosmos/cosmos-proto v1.0.0-beta.5 h1:eNcayDLpip+zVLRLYafhzLvQlSmyab+RC5W7ZfmxJLA= github.com/cosmos/cosmos-proto v1.0.0-beta.5/go.mod h1:hQGLpiIUloJBMdQMMWb/4wRApmI9hjHH05nefC0Ojec= github.com/cosmos/cosmos-sdk v0.52.0-rc.1 h1:HgHOUYbxvjvyiX5CQF4eLT0u1wvjxajwgClOGzAmNoQ= diff --git a/x/authz/go.mod b/x/authz/go.mod index 907553940432..1d1da4a07130 100644 --- a/x/authz/go.mod +++ b/x/authz/go.mod @@ -170,4 +170,30 @@ require ( sigs.k8s.io/yaml v1.4.0 // indirect ) +<<<<<<< HEAD replace github.com/cosmos/cosmos-sdk => github.com/cosmos/cosmos-sdk v0.52.0-rc.1 +======= +require cosmossdk.io/core/testing v0.0.1 + +require ( + github.com/bytedance/sonic v1.12.6 // indirect + github.com/bytedance/sonic/loader v0.2.1 // indirect + github.com/cloudwego/base64x v0.1.4 // indirect + github.com/cloudwego/iasm v0.2.0 // indirect + github.com/cockroachdb/fifo v0.0.0-20240606204812-0bbfbd93a7ce // indirect + github.com/cosmos/cosmos-db v1.1.1 // indirect + github.com/dgraph-io/ristretto/v2 v2.0.0 // indirect + github.com/google/uuid v1.6.0 // indirect + github.com/klauspost/cpuid/v2 v2.2.9 // indirect + github.com/twitchyliquid64/golang-asm v0.15.1 // indirect + golang.org/x/arch v0.12.0 // indirect +) + +replace github.com/cosmos/cosmos-sdk => ../../. + +// TODO remove post spinning out all modules +replace ( + cosmossdk.io/x/bank => ../bank + cosmossdk.io/x/staking => ../staking +) +>>>>>>> a9c114915 (test: investigate test failure due to wal log (#22679)) diff --git a/x/authz/go.sum b/x/authz/go.sum index 712fad4822ab..dd6fe9ff026d 100644 --- a/x/authz/go.sum +++ b/x/authz/go.sum @@ -121,8 +121,8 @@ github.com/containerd/continuity v0.3.0/go.mod h1:wJEAIwKOm/pBZuBd0JmeTvnLquTB1A github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= github.com/cosmos/btcutil v1.0.5 h1:t+ZFcX77LpKtDBhjucvnOH8C2l2ioGsBNEQ3jef8xFk= github.com/cosmos/btcutil v1.0.5/go.mod h1:IyB7iuqZMJlthe2tkIFL33xPyzbFYP0XVdS8P5lUPis= -github.com/cosmos/cosmos-db v1.1.0 h1:KLHNVQ73h7vawXTpj9UJ7ZR2IXv51tsEHkQJJ9EBDzI= -github.com/cosmos/cosmos-db v1.1.0/go.mod h1:t7c4A6cfGdpUwwVxrQ0gQLeRQqGUBJu0yvE4F/26REg= +github.com/cosmos/cosmos-db v1.1.1 h1:FezFSU37AlBC8S98NlSagL76oqBRWq/prTPvFcEJNCM= +github.com/cosmos/cosmos-db v1.1.1/go.mod h1:AghjcIPqdhSLP/2Z0yha5xPH3nLnskz81pBx3tcVSAw= github.com/cosmos/cosmos-proto v1.0.0-beta.5 h1:eNcayDLpip+zVLRLYafhzLvQlSmyab+RC5W7ZfmxJLA= github.com/cosmos/cosmos-proto v1.0.0-beta.5/go.mod h1:hQGLpiIUloJBMdQMMWb/4wRApmI9hjHH05nefC0Ojec= github.com/cosmos/cosmos-sdk v0.52.0-rc.1 h1:HgHOUYbxvjvyiX5CQF4eLT0u1wvjxajwgClOGzAmNoQ= diff --git a/x/bank/go.mod b/x/bank/go.mod index b17be441b9a8..18c7873bf040 100644 --- a/x/bank/go.mod +++ b/x/bank/go.mod @@ -169,4 +169,28 @@ require ( sigs.k8s.io/yaml v1.4.0 // indirect ) +<<<<<<< HEAD replace github.com/cosmos/cosmos-sdk => github.com/cosmos/cosmos-sdk v0.52.0-rc.1 +======= +require cosmossdk.io/schema v1.0.0 + +require ( + github.com/bytedance/sonic v1.12.6 // indirect + github.com/bytedance/sonic/loader v0.2.1 // indirect + github.com/cloudwego/base64x v0.1.4 // indirect + github.com/cloudwego/iasm v0.2.0 // indirect + github.com/cockroachdb/fifo v0.0.0-20240606204812-0bbfbd93a7ce // indirect + github.com/cosmos/cosmos-db v1.1.1 // indirect + github.com/dgraph-io/ristretto/v2 v2.0.0 // indirect + github.com/google/uuid v1.6.0 // indirect + github.com/klauspost/cpuid/v2 v2.2.9 // indirect + github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect + github.com/twitchyliquid64/golang-asm v0.15.1 // indirect + golang.org/x/arch v0.12.0 // indirect +) + +replace github.com/cosmos/cosmos-sdk => ../../. + +// TODO remove post spinning out all modules +replace cosmossdk.io/x/staking => ../staking +>>>>>>> a9c114915 (test: investigate test failure due to wal log (#22679)) diff --git a/x/bank/go.sum b/x/bank/go.sum index 8d37aecd7ea3..f1c7a308087c 100644 --- a/x/bank/go.sum +++ b/x/bank/go.sum @@ -119,8 +119,8 @@ github.com/containerd/continuity v0.3.0/go.mod h1:wJEAIwKOm/pBZuBd0JmeTvnLquTB1A github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= github.com/cosmos/btcutil v1.0.5 h1:t+ZFcX77LpKtDBhjucvnOH8C2l2ioGsBNEQ3jef8xFk= github.com/cosmos/btcutil v1.0.5/go.mod h1:IyB7iuqZMJlthe2tkIFL33xPyzbFYP0XVdS8P5lUPis= -github.com/cosmos/cosmos-db v1.1.0 h1:KLHNVQ73h7vawXTpj9UJ7ZR2IXv51tsEHkQJJ9EBDzI= -github.com/cosmos/cosmos-db v1.1.0/go.mod h1:t7c4A6cfGdpUwwVxrQ0gQLeRQqGUBJu0yvE4F/26REg= +github.com/cosmos/cosmos-db v1.1.1 h1:FezFSU37AlBC8S98NlSagL76oqBRWq/prTPvFcEJNCM= +github.com/cosmos/cosmos-db v1.1.1/go.mod h1:AghjcIPqdhSLP/2Z0yha5xPH3nLnskz81pBx3tcVSAw= github.com/cosmos/cosmos-proto v1.0.0-beta.5 h1:eNcayDLpip+zVLRLYafhzLvQlSmyab+RC5W7ZfmxJLA= github.com/cosmos/cosmos-proto v1.0.0-beta.5/go.mod h1:hQGLpiIUloJBMdQMMWb/4wRApmI9hjHH05nefC0Ojec= github.com/cosmos/cosmos-sdk v0.52.0-rc.1 h1:HgHOUYbxvjvyiX5CQF4eLT0u1wvjxajwgClOGzAmNoQ= diff --git a/x/circuit/go.mod b/x/circuit/go.mod index aab9bc0a54a0..ae364666e52d 100644 --- a/x/circuit/go.mod +++ b/x/circuit/go.mod @@ -51,7 +51,7 @@ require ( github.com/cometbft/cometbft-db v1.0.1 // indirect github.com/cometbft/cometbft/api v1.0.0 // indirect github.com/cosmos/btcutil v1.0.5 // indirect - github.com/cosmos/cosmos-db v1.1.0 // indirect + github.com/cosmos/cosmos-db v1.1.1 // indirect github.com/cosmos/cosmos-proto v1.0.0-beta.5 // indirect github.com/cosmos/go-bip39 v1.0.0 // indirect github.com/cosmos/gogogateway v1.2.0 // indirect diff --git a/x/circuit/go.sum b/x/circuit/go.sum index 712fad4822ab..dd6fe9ff026d 100644 --- a/x/circuit/go.sum +++ b/x/circuit/go.sum @@ -121,8 +121,8 @@ github.com/containerd/continuity v0.3.0/go.mod h1:wJEAIwKOm/pBZuBd0JmeTvnLquTB1A github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= github.com/cosmos/btcutil v1.0.5 h1:t+ZFcX77LpKtDBhjucvnOH8C2l2ioGsBNEQ3jef8xFk= github.com/cosmos/btcutil v1.0.5/go.mod h1:IyB7iuqZMJlthe2tkIFL33xPyzbFYP0XVdS8P5lUPis= -github.com/cosmos/cosmos-db v1.1.0 h1:KLHNVQ73h7vawXTpj9UJ7ZR2IXv51tsEHkQJJ9EBDzI= -github.com/cosmos/cosmos-db v1.1.0/go.mod h1:t7c4A6cfGdpUwwVxrQ0gQLeRQqGUBJu0yvE4F/26REg= +github.com/cosmos/cosmos-db v1.1.1 h1:FezFSU37AlBC8S98NlSagL76oqBRWq/prTPvFcEJNCM= +github.com/cosmos/cosmos-db v1.1.1/go.mod h1:AghjcIPqdhSLP/2Z0yha5xPH3nLnskz81pBx3tcVSAw= github.com/cosmos/cosmos-proto v1.0.0-beta.5 h1:eNcayDLpip+zVLRLYafhzLvQlSmyab+RC5W7ZfmxJLA= github.com/cosmos/cosmos-proto v1.0.0-beta.5/go.mod h1:hQGLpiIUloJBMdQMMWb/4wRApmI9hjHH05nefC0Ojec= github.com/cosmos/cosmos-sdk v0.52.0-rc.1 h1:HgHOUYbxvjvyiX5CQF4eLT0u1wvjxajwgClOGzAmNoQ= diff --git a/x/consensus/go.mod b/x/consensus/go.mod index e0560d304595..5a25cec04486 100644 --- a/x/consensus/go.mod +++ b/x/consensus/go.mod @@ -52,7 +52,7 @@ require ( github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06 // indirect github.com/cometbft/cometbft-db v1.0.1 // indirect github.com/cosmos/btcutil v1.0.5 // indirect - github.com/cosmos/cosmos-db v1.1.0 // indirect + github.com/cosmos/cosmos-db v1.1.1 // indirect github.com/cosmos/go-bip39 v1.0.0 // indirect github.com/cosmos/gogogateway v1.2.0 // indirect github.com/cosmos/iavl v1.3.4 // indirect diff --git a/x/consensus/go.sum b/x/consensus/go.sum index 69bd869db09d..521aadcf9d71 100644 --- a/x/consensus/go.sum +++ b/x/consensus/go.sum @@ -121,8 +121,8 @@ github.com/containerd/continuity v0.3.0/go.mod h1:wJEAIwKOm/pBZuBd0JmeTvnLquTB1A github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= github.com/cosmos/btcutil v1.0.5 h1:t+ZFcX77LpKtDBhjucvnOH8C2l2ioGsBNEQ3jef8xFk= github.com/cosmos/btcutil v1.0.5/go.mod h1:IyB7iuqZMJlthe2tkIFL33xPyzbFYP0XVdS8P5lUPis= -github.com/cosmos/cosmos-db v1.1.0 h1:KLHNVQ73h7vawXTpj9UJ7ZR2IXv51tsEHkQJJ9EBDzI= -github.com/cosmos/cosmos-db v1.1.0/go.mod h1:t7c4A6cfGdpUwwVxrQ0gQLeRQqGUBJu0yvE4F/26REg= +github.com/cosmos/cosmos-db v1.1.1 h1:FezFSU37AlBC8S98NlSagL76oqBRWq/prTPvFcEJNCM= +github.com/cosmos/cosmos-db v1.1.1/go.mod h1:AghjcIPqdhSLP/2Z0yha5xPH3nLnskz81pBx3tcVSAw= github.com/cosmos/cosmos-proto v1.0.0-beta.5 h1:eNcayDLpip+zVLRLYafhzLvQlSmyab+RC5W7ZfmxJLA= github.com/cosmos/cosmos-proto v1.0.0-beta.5/go.mod h1:hQGLpiIUloJBMdQMMWb/4wRApmI9hjHH05nefC0Ojec= github.com/cosmos/cosmos-sdk v0.52.0-rc.1 h1:HgHOUYbxvjvyiX5CQF4eLT0u1wvjxajwgClOGzAmNoQ= diff --git a/x/distribution/go.mod b/x/distribution/go.mod index d9b31c88a3cc..776a913cebdd 100644 --- a/x/distribution/go.mod +++ b/x/distribution/go.mod @@ -56,7 +56,7 @@ require ( github.com/cometbft/cometbft-db v1.0.1 // indirect github.com/cometbft/cometbft/api v1.0.0 // indirect github.com/cosmos/btcutil v1.0.5 // indirect - github.com/cosmos/cosmos-db v1.1.0 // indirect + github.com/cosmos/cosmos-db v1.1.1 // indirect github.com/cosmos/go-bip39 v1.0.0 // indirect github.com/cosmos/gogogateway v1.2.0 // indirect github.com/cosmos/iavl v1.3.4 // indirect diff --git a/x/distribution/go.sum b/x/distribution/go.sum index 712fad4822ab..dd6fe9ff026d 100644 --- a/x/distribution/go.sum +++ b/x/distribution/go.sum @@ -121,8 +121,8 @@ github.com/containerd/continuity v0.3.0/go.mod h1:wJEAIwKOm/pBZuBd0JmeTvnLquTB1A github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= github.com/cosmos/btcutil v1.0.5 h1:t+ZFcX77LpKtDBhjucvnOH8C2l2ioGsBNEQ3jef8xFk= github.com/cosmos/btcutil v1.0.5/go.mod h1:IyB7iuqZMJlthe2tkIFL33xPyzbFYP0XVdS8P5lUPis= -github.com/cosmos/cosmos-db v1.1.0 h1:KLHNVQ73h7vawXTpj9UJ7ZR2IXv51tsEHkQJJ9EBDzI= -github.com/cosmos/cosmos-db v1.1.0/go.mod h1:t7c4A6cfGdpUwwVxrQ0gQLeRQqGUBJu0yvE4F/26REg= +github.com/cosmos/cosmos-db v1.1.1 h1:FezFSU37AlBC8S98NlSagL76oqBRWq/prTPvFcEJNCM= +github.com/cosmos/cosmos-db v1.1.1/go.mod h1:AghjcIPqdhSLP/2Z0yha5xPH3nLnskz81pBx3tcVSAw= github.com/cosmos/cosmos-proto v1.0.0-beta.5 h1:eNcayDLpip+zVLRLYafhzLvQlSmyab+RC5W7ZfmxJLA= github.com/cosmos/cosmos-proto v1.0.0-beta.5/go.mod h1:hQGLpiIUloJBMdQMMWb/4wRApmI9hjHH05nefC0Ojec= github.com/cosmos/cosmos-sdk v0.52.0-rc.1 h1:HgHOUYbxvjvyiX5CQF4eLT0u1wvjxajwgClOGzAmNoQ= diff --git a/x/epochs/go.mod b/x/epochs/go.mod index d16599e9a9a7..6d3d8ed4bdb0 100644 --- a/x/epochs/go.mod +++ b/x/epochs/go.mod @@ -52,7 +52,7 @@ require ( github.com/cometbft/cometbft-db v1.0.1 // indirect github.com/cometbft/cometbft/api v1.0.0 // indirect github.com/cosmos/btcutil v1.0.5 // indirect - github.com/cosmos/cosmos-db v1.1.0 // indirect + github.com/cosmos/cosmos-db v1.1.1 // indirect github.com/cosmos/go-bip39 v1.0.0 // indirect github.com/cosmos/gogogateway v1.2.0 // indirect github.com/cosmos/iavl v1.3.4 // indirect diff --git a/x/epochs/go.sum b/x/epochs/go.sum index 69bd869db09d..521aadcf9d71 100644 --- a/x/epochs/go.sum +++ b/x/epochs/go.sum @@ -121,8 +121,8 @@ github.com/containerd/continuity v0.3.0/go.mod h1:wJEAIwKOm/pBZuBd0JmeTvnLquTB1A github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= github.com/cosmos/btcutil v1.0.5 h1:t+ZFcX77LpKtDBhjucvnOH8C2l2ioGsBNEQ3jef8xFk= github.com/cosmos/btcutil v1.0.5/go.mod h1:IyB7iuqZMJlthe2tkIFL33xPyzbFYP0XVdS8P5lUPis= -github.com/cosmos/cosmos-db v1.1.0 h1:KLHNVQ73h7vawXTpj9UJ7ZR2IXv51tsEHkQJJ9EBDzI= -github.com/cosmos/cosmos-db v1.1.0/go.mod h1:t7c4A6cfGdpUwwVxrQ0gQLeRQqGUBJu0yvE4F/26REg= +github.com/cosmos/cosmos-db v1.1.1 h1:FezFSU37AlBC8S98NlSagL76oqBRWq/prTPvFcEJNCM= +github.com/cosmos/cosmos-db v1.1.1/go.mod h1:AghjcIPqdhSLP/2Z0yha5xPH3nLnskz81pBx3tcVSAw= github.com/cosmos/cosmos-proto v1.0.0-beta.5 h1:eNcayDLpip+zVLRLYafhzLvQlSmyab+RC5W7ZfmxJLA= github.com/cosmos/cosmos-proto v1.0.0-beta.5/go.mod h1:hQGLpiIUloJBMdQMMWb/4wRApmI9hjHH05nefC0Ojec= github.com/cosmos/cosmos-sdk v0.52.0-rc.1 h1:HgHOUYbxvjvyiX5CQF4eLT0u1wvjxajwgClOGzAmNoQ= diff --git a/x/evidence/go.mod b/x/evidence/go.mod index f53d57e04b74..3bd652ac8f80 100644 --- a/x/evidence/go.mod +++ b/x/evidence/go.mod @@ -55,7 +55,7 @@ require ( github.com/cometbft/cometbft-db v1.0.1 // indirect github.com/cometbft/cometbft/api v1.0.0 // indirect github.com/cosmos/btcutil v1.0.5 // indirect - github.com/cosmos/cosmos-db v1.1.0 // indirect + github.com/cosmos/cosmos-db v1.1.1 // indirect github.com/cosmos/go-bip39 v1.0.0 // indirect github.com/cosmos/gogogateway v1.2.0 // indirect github.com/cosmos/iavl v1.3.4 // indirect diff --git a/x/evidence/go.sum b/x/evidence/go.sum index 712fad4822ab..dd6fe9ff026d 100644 --- a/x/evidence/go.sum +++ b/x/evidence/go.sum @@ -121,8 +121,8 @@ github.com/containerd/continuity v0.3.0/go.mod h1:wJEAIwKOm/pBZuBd0JmeTvnLquTB1A github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= github.com/cosmos/btcutil v1.0.5 h1:t+ZFcX77LpKtDBhjucvnOH8C2l2ioGsBNEQ3jef8xFk= github.com/cosmos/btcutil v1.0.5/go.mod h1:IyB7iuqZMJlthe2tkIFL33xPyzbFYP0XVdS8P5lUPis= -github.com/cosmos/cosmos-db v1.1.0 h1:KLHNVQ73h7vawXTpj9UJ7ZR2IXv51tsEHkQJJ9EBDzI= -github.com/cosmos/cosmos-db v1.1.0/go.mod h1:t7c4A6cfGdpUwwVxrQ0gQLeRQqGUBJu0yvE4F/26REg= +github.com/cosmos/cosmos-db v1.1.1 h1:FezFSU37AlBC8S98NlSagL76oqBRWq/prTPvFcEJNCM= +github.com/cosmos/cosmos-db v1.1.1/go.mod h1:AghjcIPqdhSLP/2Z0yha5xPH3nLnskz81pBx3tcVSAw= github.com/cosmos/cosmos-proto v1.0.0-beta.5 h1:eNcayDLpip+zVLRLYafhzLvQlSmyab+RC5W7ZfmxJLA= github.com/cosmos/cosmos-proto v1.0.0-beta.5/go.mod h1:hQGLpiIUloJBMdQMMWb/4wRApmI9hjHH05nefC0Ojec= github.com/cosmos/cosmos-sdk v0.52.0-rc.1 h1:HgHOUYbxvjvyiX5CQF4eLT0u1wvjxajwgClOGzAmNoQ= diff --git a/x/feegrant/go.mod b/x/feegrant/go.mod index 58c0cb4fbfcb..e628ce97884f 100644 --- a/x/feegrant/go.mod +++ b/x/feegrant/go.mod @@ -60,7 +60,7 @@ require ( github.com/cometbft/cometbft-db v1.0.1 // indirect github.com/cometbft/cometbft/api v1.0.0 // indirect github.com/cosmos/btcutil v1.0.5 // indirect - github.com/cosmos/cosmos-db v1.1.0 // indirect + github.com/cosmos/cosmos-db v1.1.1 // indirect github.com/cosmos/go-bip39 v1.0.0 // indirect github.com/cosmos/gogogateway v1.2.0 // indirect github.com/cosmos/iavl v1.3.4 // indirect diff --git a/x/feegrant/go.sum b/x/feegrant/go.sum index 1325a124a61f..1b137835f745 100644 --- a/x/feegrant/go.sum +++ b/x/feegrant/go.sum @@ -133,8 +133,8 @@ github.com/containerd/continuity v0.3.0/go.mod h1:wJEAIwKOm/pBZuBd0JmeTvnLquTB1A github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= github.com/cosmos/btcutil v1.0.5 h1:t+ZFcX77LpKtDBhjucvnOH8C2l2ioGsBNEQ3jef8xFk= github.com/cosmos/btcutil v1.0.5/go.mod h1:IyB7iuqZMJlthe2tkIFL33xPyzbFYP0XVdS8P5lUPis= -github.com/cosmos/cosmos-db v1.1.0 h1:KLHNVQ73h7vawXTpj9UJ7ZR2IXv51tsEHkQJJ9EBDzI= -github.com/cosmos/cosmos-db v1.1.0/go.mod h1:t7c4A6cfGdpUwwVxrQ0gQLeRQqGUBJu0yvE4F/26REg= +github.com/cosmos/cosmos-db v1.1.1 h1:FezFSU37AlBC8S98NlSagL76oqBRWq/prTPvFcEJNCM= +github.com/cosmos/cosmos-db v1.1.1/go.mod h1:AghjcIPqdhSLP/2Z0yha5xPH3nLnskz81pBx3tcVSAw= github.com/cosmos/cosmos-proto v1.0.0-beta.5 h1:eNcayDLpip+zVLRLYafhzLvQlSmyab+RC5W7ZfmxJLA= github.com/cosmos/cosmos-proto v1.0.0-beta.5/go.mod h1:hQGLpiIUloJBMdQMMWb/4wRApmI9hjHH05nefC0Ojec= github.com/cosmos/cosmos-sdk v0.52.0-rc.1 h1:HgHOUYbxvjvyiX5CQF4eLT0u1wvjxajwgClOGzAmNoQ= diff --git a/x/gov/go.mod b/x/gov/go.mod index 3ed30ff673ca..539c5ae8dbd5 100644 --- a/x/gov/go.mod +++ b/x/gov/go.mod @@ -61,7 +61,7 @@ require ( github.com/cometbft/cometbft-db v1.0.1 // indirect github.com/cometbft/cometbft/api v1.0.0 // indirect github.com/cosmos/btcutil v1.0.5 // indirect - github.com/cosmos/cosmos-db v1.1.0 // indirect + github.com/cosmos/cosmos-db v1.1.1 // indirect github.com/cosmos/go-bip39 v1.0.0 // indirect github.com/cosmos/gogogateway v1.2.0 // indirect github.com/cosmos/iavl v1.3.4 // indirect diff --git a/x/gov/go.sum b/x/gov/go.sum index 9f8428dbcd8a..2b7be0b0e217 100644 --- a/x/gov/go.sum +++ b/x/gov/go.sum @@ -131,8 +131,8 @@ github.com/containerd/continuity v0.3.0/go.mod h1:wJEAIwKOm/pBZuBd0JmeTvnLquTB1A github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= github.com/cosmos/btcutil v1.0.5 h1:t+ZFcX77LpKtDBhjucvnOH8C2l2ioGsBNEQ3jef8xFk= github.com/cosmos/btcutil v1.0.5/go.mod h1:IyB7iuqZMJlthe2tkIFL33xPyzbFYP0XVdS8P5lUPis= -github.com/cosmos/cosmos-db v1.1.0 h1:KLHNVQ73h7vawXTpj9UJ7ZR2IXv51tsEHkQJJ9EBDzI= -github.com/cosmos/cosmos-db v1.1.0/go.mod h1:t7c4A6cfGdpUwwVxrQ0gQLeRQqGUBJu0yvE4F/26REg= +github.com/cosmos/cosmos-db v1.1.1 h1:FezFSU37AlBC8S98NlSagL76oqBRWq/prTPvFcEJNCM= +github.com/cosmos/cosmos-db v1.1.1/go.mod h1:AghjcIPqdhSLP/2Z0yha5xPH3nLnskz81pBx3tcVSAw= github.com/cosmos/cosmos-proto v1.0.0-beta.5 h1:eNcayDLpip+zVLRLYafhzLvQlSmyab+RC5W7ZfmxJLA= github.com/cosmos/cosmos-proto v1.0.0-beta.5/go.mod h1:hQGLpiIUloJBMdQMMWb/4wRApmI9hjHH05nefC0Ojec= github.com/cosmos/cosmos-sdk v0.52.0-rc.1 h1:HgHOUYbxvjvyiX5CQF4eLT0u1wvjxajwgClOGzAmNoQ= diff --git a/x/group/go.mod b/x/group/go.mod index ca7b1059867f..4e7d018954f7 100644 --- a/x/group/go.mod +++ b/x/group/go.mod @@ -62,7 +62,7 @@ require ( github.com/cometbft/cometbft-db v1.0.1 // indirect github.com/cometbft/cometbft/api v1.0.0 // indirect github.com/cosmos/btcutil v1.0.5 // indirect - github.com/cosmos/cosmos-db v1.1.0 // indirect + github.com/cosmos/cosmos-db v1.1.1 // indirect github.com/cosmos/go-bip39 v1.0.0 // indirect github.com/cosmos/gogogateway v1.2.0 // indirect github.com/cosmos/iavl v1.3.4 // indirect diff --git a/x/group/go.sum b/x/group/go.sum index e590888ef619..d3f7a02d1b4e 100644 --- a/x/group/go.sum +++ b/x/group/go.sum @@ -135,8 +135,8 @@ github.com/containerd/continuity v0.3.0/go.mod h1:wJEAIwKOm/pBZuBd0JmeTvnLquTB1A github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= github.com/cosmos/btcutil v1.0.5 h1:t+ZFcX77LpKtDBhjucvnOH8C2l2ioGsBNEQ3jef8xFk= github.com/cosmos/btcutil v1.0.5/go.mod h1:IyB7iuqZMJlthe2tkIFL33xPyzbFYP0XVdS8P5lUPis= -github.com/cosmos/cosmos-db v1.1.0 h1:KLHNVQ73h7vawXTpj9UJ7ZR2IXv51tsEHkQJJ9EBDzI= -github.com/cosmos/cosmos-db v1.1.0/go.mod h1:t7c4A6cfGdpUwwVxrQ0gQLeRQqGUBJu0yvE4F/26REg= +github.com/cosmos/cosmos-db v1.1.1 h1:FezFSU37AlBC8S98NlSagL76oqBRWq/prTPvFcEJNCM= +github.com/cosmos/cosmos-db v1.1.1/go.mod h1:AghjcIPqdhSLP/2Z0yha5xPH3nLnskz81pBx3tcVSAw= github.com/cosmos/cosmos-proto v1.0.0-beta.5 h1:eNcayDLpip+zVLRLYafhzLvQlSmyab+RC5W7ZfmxJLA= github.com/cosmos/cosmos-proto v1.0.0-beta.5/go.mod h1:hQGLpiIUloJBMdQMMWb/4wRApmI9hjHH05nefC0Ojec= github.com/cosmos/cosmos-sdk v0.52.0-rc.1 h1:HgHOUYbxvjvyiX5CQF4eLT0u1wvjxajwgClOGzAmNoQ= diff --git a/x/mint/go.mod b/x/mint/go.mod index b17632174284..ae12af2c408f 100644 --- a/x/mint/go.mod +++ b/x/mint/go.mod @@ -166,7 +166,7 @@ require ( github.com/cloudwego/iasm v0.2.0 // indirect github.com/cockroachdb/fifo v0.0.0-20240816210425-c5d0cb0b6fc0 // indirect github.com/cometbft/cometbft/api v1.0.0 // indirect - github.com/cosmos/cosmos-db v1.1.0 // indirect + github.com/cosmos/cosmos-db v1.1.1 // indirect github.com/dgraph-io/ristretto/v2 v2.0.0 // indirect github.com/google/uuid v1.6.0 // indirect github.com/klauspost/cpuid/v2 v2.2.9 // indirect diff --git a/x/mint/go.sum b/x/mint/go.sum index a76c061fe252..864d9d26e017 100644 --- a/x/mint/go.sum +++ b/x/mint/go.sum @@ -123,8 +123,8 @@ github.com/containerd/continuity v0.3.0/go.mod h1:wJEAIwKOm/pBZuBd0JmeTvnLquTB1A github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= github.com/cosmos/btcutil v1.0.5 h1:t+ZFcX77LpKtDBhjucvnOH8C2l2ioGsBNEQ3jef8xFk= github.com/cosmos/btcutil v1.0.5/go.mod h1:IyB7iuqZMJlthe2tkIFL33xPyzbFYP0XVdS8P5lUPis= -github.com/cosmos/cosmos-db v1.1.0 h1:KLHNVQ73h7vawXTpj9UJ7ZR2IXv51tsEHkQJJ9EBDzI= -github.com/cosmos/cosmos-db v1.1.0/go.mod h1:t7c4A6cfGdpUwwVxrQ0gQLeRQqGUBJu0yvE4F/26REg= +github.com/cosmos/cosmos-db v1.1.1 h1:FezFSU37AlBC8S98NlSagL76oqBRWq/prTPvFcEJNCM= +github.com/cosmos/cosmos-db v1.1.1/go.mod h1:AghjcIPqdhSLP/2Z0yha5xPH3nLnskz81pBx3tcVSAw= github.com/cosmos/cosmos-proto v1.0.0-beta.5 h1:eNcayDLpip+zVLRLYafhzLvQlSmyab+RC5W7ZfmxJLA= github.com/cosmos/cosmos-proto v1.0.0-beta.5/go.mod h1:hQGLpiIUloJBMdQMMWb/4wRApmI9hjHH05nefC0Ojec= github.com/cosmos/cosmos-sdk v0.52.0-rc.1 h1:HgHOUYbxvjvyiX5CQF4eLT0u1wvjxajwgClOGzAmNoQ= diff --git a/x/nft/go.mod b/x/nft/go.mod index 201ad0ea006f..5ff229fe4abd 100644 --- a/x/nft/go.mod +++ b/x/nft/go.mod @@ -53,7 +53,7 @@ require ( github.com/cometbft/cometbft-db v1.0.1 // indirect github.com/cometbft/cometbft/api v1.0.0 // indirect github.com/cosmos/btcutil v1.0.5 // indirect - github.com/cosmos/cosmos-db v1.1.0 // indirect + github.com/cosmos/cosmos-db v1.1.1 // indirect github.com/cosmos/go-bip39 v1.0.0 // indirect github.com/cosmos/gogogateway v1.2.0 // indirect github.com/cosmos/iavl v1.3.4 // indirect diff --git a/x/nft/go.sum b/x/nft/go.sum index 712fad4822ab..dd6fe9ff026d 100644 --- a/x/nft/go.sum +++ b/x/nft/go.sum @@ -121,8 +121,8 @@ github.com/containerd/continuity v0.3.0/go.mod h1:wJEAIwKOm/pBZuBd0JmeTvnLquTB1A github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= github.com/cosmos/btcutil v1.0.5 h1:t+ZFcX77LpKtDBhjucvnOH8C2l2ioGsBNEQ3jef8xFk= github.com/cosmos/btcutil v1.0.5/go.mod h1:IyB7iuqZMJlthe2tkIFL33xPyzbFYP0XVdS8P5lUPis= -github.com/cosmos/cosmos-db v1.1.0 h1:KLHNVQ73h7vawXTpj9UJ7ZR2IXv51tsEHkQJJ9EBDzI= -github.com/cosmos/cosmos-db v1.1.0/go.mod h1:t7c4A6cfGdpUwwVxrQ0gQLeRQqGUBJu0yvE4F/26REg= +github.com/cosmos/cosmos-db v1.1.1 h1:FezFSU37AlBC8S98NlSagL76oqBRWq/prTPvFcEJNCM= +github.com/cosmos/cosmos-db v1.1.1/go.mod h1:AghjcIPqdhSLP/2Z0yha5xPH3nLnskz81pBx3tcVSAw= github.com/cosmos/cosmos-proto v1.0.0-beta.5 h1:eNcayDLpip+zVLRLYafhzLvQlSmyab+RC5W7ZfmxJLA= github.com/cosmos/cosmos-proto v1.0.0-beta.5/go.mod h1:hQGLpiIUloJBMdQMMWb/4wRApmI9hjHH05nefC0Ojec= github.com/cosmos/cosmos-sdk v0.52.0-rc.1 h1:HgHOUYbxvjvyiX5CQF4eLT0u1wvjxajwgClOGzAmNoQ= diff --git a/x/params/go.sum b/x/params/go.sum index abb06fde52c7..f4b3788b35b9 100644 --- a/x/params/go.sum +++ b/x/params/go.sum @@ -113,8 +113,8 @@ github.com/cometbft/cometbft/api v1.0.0/go.mod h1:EkQiqVSu/p2ebrZEnB2z6Re7r8XNe/ github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= github.com/cosmos/btcutil v1.0.5 h1:t+ZFcX77LpKtDBhjucvnOH8C2l2ioGsBNEQ3jef8xFk= github.com/cosmos/btcutil v1.0.5/go.mod h1:IyB7iuqZMJlthe2tkIFL33xPyzbFYP0XVdS8P5lUPis= -github.com/cosmos/cosmos-db v1.1.0 h1:KLHNVQ73h7vawXTpj9UJ7ZR2IXv51tsEHkQJJ9EBDzI= -github.com/cosmos/cosmos-db v1.1.0/go.mod h1:t7c4A6cfGdpUwwVxrQ0gQLeRQqGUBJu0yvE4F/26REg= +github.com/cosmos/cosmos-db v1.1.1 h1:FezFSU37AlBC8S98NlSagL76oqBRWq/prTPvFcEJNCM= +github.com/cosmos/cosmos-db v1.1.1/go.mod h1:AghjcIPqdhSLP/2Z0yha5xPH3nLnskz81pBx3tcVSAw= github.com/cosmos/cosmos-proto v1.0.0-beta.5 h1:eNcayDLpip+zVLRLYafhzLvQlSmyab+RC5W7ZfmxJLA= github.com/cosmos/cosmos-proto v1.0.0-beta.5/go.mod h1:hQGLpiIUloJBMdQMMWb/4wRApmI9hjHH05nefC0Ojec= github.com/cosmos/cosmos-sdk v0.52.0-rc.1 h1:HgHOUYbxvjvyiX5CQF4eLT0u1wvjxajwgClOGzAmNoQ= diff --git a/x/protocolpool/go.mod b/x/protocolpool/go.mod index f88ddff01f14..496895c8a760 100644 --- a/x/protocolpool/go.mod +++ b/x/protocolpool/go.mod @@ -55,7 +55,7 @@ require ( github.com/cometbft/cometbft-db v1.0.1 // indirect github.com/cometbft/cometbft/api v1.0.0 // indirect github.com/cosmos/btcutil v1.0.5 // indirect - github.com/cosmos/cosmos-db v1.1.0 // indirect + github.com/cosmos/cosmos-db v1.1.1 // indirect github.com/cosmos/go-bip39 v1.0.0 // indirect github.com/cosmos/gogogateway v1.2.0 // indirect github.com/cosmos/iavl v1.3.4 // indirect diff --git a/x/protocolpool/go.sum b/x/protocolpool/go.sum index 712fad4822ab..dd6fe9ff026d 100644 --- a/x/protocolpool/go.sum +++ b/x/protocolpool/go.sum @@ -121,8 +121,8 @@ github.com/containerd/continuity v0.3.0/go.mod h1:wJEAIwKOm/pBZuBd0JmeTvnLquTB1A github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= github.com/cosmos/btcutil v1.0.5 h1:t+ZFcX77LpKtDBhjucvnOH8C2l2ioGsBNEQ3jef8xFk= github.com/cosmos/btcutil v1.0.5/go.mod h1:IyB7iuqZMJlthe2tkIFL33xPyzbFYP0XVdS8P5lUPis= -github.com/cosmos/cosmos-db v1.1.0 h1:KLHNVQ73h7vawXTpj9UJ7ZR2IXv51tsEHkQJJ9EBDzI= -github.com/cosmos/cosmos-db v1.1.0/go.mod h1:t7c4A6cfGdpUwwVxrQ0gQLeRQqGUBJu0yvE4F/26REg= +github.com/cosmos/cosmos-db v1.1.1 h1:FezFSU37AlBC8S98NlSagL76oqBRWq/prTPvFcEJNCM= +github.com/cosmos/cosmos-db v1.1.1/go.mod h1:AghjcIPqdhSLP/2Z0yha5xPH3nLnskz81pBx3tcVSAw= github.com/cosmos/cosmos-proto v1.0.0-beta.5 h1:eNcayDLpip+zVLRLYafhzLvQlSmyab+RC5W7ZfmxJLA= github.com/cosmos/cosmos-proto v1.0.0-beta.5/go.mod h1:hQGLpiIUloJBMdQMMWb/4wRApmI9hjHH05nefC0Ojec= github.com/cosmos/cosmos-sdk v0.52.0-rc.1 h1:HgHOUYbxvjvyiX5CQF4eLT0u1wvjxajwgClOGzAmNoQ= diff --git a/x/slashing/go.mod b/x/slashing/go.mod index ec593bf1dae9..ff9875605486 100644 --- a/x/slashing/go.mod +++ b/x/slashing/go.mod @@ -56,7 +56,7 @@ require ( github.com/cometbft/cometbft-db v1.0.1 // indirect github.com/cometbft/cometbft/api v1.0.0 // indirect github.com/cosmos/btcutil v1.0.5 // indirect - github.com/cosmos/cosmos-db v1.1.0 // indirect + github.com/cosmos/cosmos-db v1.1.1 // indirect github.com/cosmos/go-bip39 v1.0.0 // indirect github.com/cosmos/gogogateway v1.2.0 // indirect github.com/cosmos/iavl v1.3.4 // indirect diff --git a/x/slashing/go.sum b/x/slashing/go.sum index 6e4b8e315e0b..9aad1c48fd12 100644 --- a/x/slashing/go.sum +++ b/x/slashing/go.sum @@ -123,8 +123,8 @@ github.com/containerd/continuity v0.3.0/go.mod h1:wJEAIwKOm/pBZuBd0JmeTvnLquTB1A github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= github.com/cosmos/btcutil v1.0.5 h1:t+ZFcX77LpKtDBhjucvnOH8C2l2ioGsBNEQ3jef8xFk= github.com/cosmos/btcutil v1.0.5/go.mod h1:IyB7iuqZMJlthe2tkIFL33xPyzbFYP0XVdS8P5lUPis= -github.com/cosmos/cosmos-db v1.1.0 h1:KLHNVQ73h7vawXTpj9UJ7ZR2IXv51tsEHkQJJ9EBDzI= -github.com/cosmos/cosmos-db v1.1.0/go.mod h1:t7c4A6cfGdpUwwVxrQ0gQLeRQqGUBJu0yvE4F/26REg= +github.com/cosmos/cosmos-db v1.1.1 h1:FezFSU37AlBC8S98NlSagL76oqBRWq/prTPvFcEJNCM= +github.com/cosmos/cosmos-db v1.1.1/go.mod h1:AghjcIPqdhSLP/2Z0yha5xPH3nLnskz81pBx3tcVSAw= github.com/cosmos/cosmos-proto v1.0.0-beta.5 h1:eNcayDLpip+zVLRLYafhzLvQlSmyab+RC5W7ZfmxJLA= github.com/cosmos/cosmos-proto v1.0.0-beta.5/go.mod h1:hQGLpiIUloJBMdQMMWb/4wRApmI9hjHH05nefC0Ojec= github.com/cosmos/cosmos-sdk v0.52.0-rc.1 h1:HgHOUYbxvjvyiX5CQF4eLT0u1wvjxajwgClOGzAmNoQ= diff --git a/x/staking/go.mod b/x/staking/go.mod index 5c0c704f69e1..cfd79ec1a529 100644 --- a/x/staking/go.mod +++ b/x/staking/go.mod @@ -168,6 +168,11 @@ require ( github.com/bytedance/sonic/loader v0.2.1 // indirect github.com/cloudwego/base64x v0.1.4 // indirect github.com/cloudwego/iasm v0.2.0 // indirect +<<<<<<< HEAD +======= + github.com/cockroachdb/fifo v0.0.0-20240606204812-0bbfbd93a7ce // indirect + github.com/cosmos/cosmos-db v1.1.1 // indirect +>>>>>>> a9c114915 (test: investigate test failure due to wal log (#22679)) github.com/dgraph-io/ristretto/v2 v2.0.0 // indirect github.com/klauspost/cpuid/v2 v2.2.9 // indirect github.com/twitchyliquid64/golang-asm v0.15.1 // indirect diff --git a/x/staking/go.sum b/x/staking/go.sum index 812b25eef1e6..0dfc480fdcf3 100644 --- a/x/staking/go.sum +++ b/x/staking/go.sum @@ -119,8 +119,8 @@ github.com/containerd/continuity v0.3.0/go.mod h1:wJEAIwKOm/pBZuBd0JmeTvnLquTB1A github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= github.com/cosmos/btcutil v1.0.5 h1:t+ZFcX77LpKtDBhjucvnOH8C2l2ioGsBNEQ3jef8xFk= github.com/cosmos/btcutil v1.0.5/go.mod h1:IyB7iuqZMJlthe2tkIFL33xPyzbFYP0XVdS8P5lUPis= -github.com/cosmos/cosmos-db v1.1.0 h1:KLHNVQ73h7vawXTpj9UJ7ZR2IXv51tsEHkQJJ9EBDzI= -github.com/cosmos/cosmos-db v1.1.0/go.mod h1:t7c4A6cfGdpUwwVxrQ0gQLeRQqGUBJu0yvE4F/26REg= +github.com/cosmos/cosmos-db v1.1.1 h1:FezFSU37AlBC8S98NlSagL76oqBRWq/prTPvFcEJNCM= +github.com/cosmos/cosmos-db v1.1.1/go.mod h1:AghjcIPqdhSLP/2Z0yha5xPH3nLnskz81pBx3tcVSAw= github.com/cosmos/cosmos-proto v1.0.0-beta.5 h1:eNcayDLpip+zVLRLYafhzLvQlSmyab+RC5W7ZfmxJLA= github.com/cosmos/cosmos-proto v1.0.0-beta.5/go.mod h1:hQGLpiIUloJBMdQMMWb/4wRApmI9hjHH05nefC0Ojec= github.com/cosmos/cosmos-sdk v0.52.0-rc.1 h1:HgHOUYbxvjvyiX5CQF4eLT0u1wvjxajwgClOGzAmNoQ= diff --git a/x/upgrade/go.mod b/x/upgrade/go.mod index 4e1a9e3db20e..df3ff1533cd3 100644 --- a/x/upgrade/go.mod +++ b/x/upgrade/go.mod @@ -71,7 +71,7 @@ require ( github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06 // indirect github.com/cometbft/cometbft-db v1.0.1 // indirect github.com/cosmos/btcutil v1.0.5 // indirect - github.com/cosmos/cosmos-db v1.1.0 // indirect + github.com/cosmos/cosmos-db v1.1.1 // indirect github.com/cosmos/go-bip39 v1.0.0 // indirect github.com/cosmos/gogogateway v1.2.0 // indirect github.com/cosmos/iavl v1.3.4 // indirect diff --git a/x/upgrade/go.sum b/x/upgrade/go.sum index cb1fce816444..b2c398b83d16 100644 --- a/x/upgrade/go.sum +++ b/x/upgrade/go.sum @@ -333,8 +333,8 @@ github.com/containerd/continuity v0.3.0/go.mod h1:wJEAIwKOm/pBZuBd0JmeTvnLquTB1A github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= github.com/cosmos/btcutil v1.0.5 h1:t+ZFcX77LpKtDBhjucvnOH8C2l2ioGsBNEQ3jef8xFk= github.com/cosmos/btcutil v1.0.5/go.mod h1:IyB7iuqZMJlthe2tkIFL33xPyzbFYP0XVdS8P5lUPis= -github.com/cosmos/cosmos-db v1.1.0 h1:KLHNVQ73h7vawXTpj9UJ7ZR2IXv51tsEHkQJJ9EBDzI= -github.com/cosmos/cosmos-db v1.1.0/go.mod h1:t7c4A6cfGdpUwwVxrQ0gQLeRQqGUBJu0yvE4F/26REg= +github.com/cosmos/cosmos-db v1.1.1 h1:FezFSU37AlBC8S98NlSagL76oqBRWq/prTPvFcEJNCM= +github.com/cosmos/cosmos-db v1.1.1/go.mod h1:AghjcIPqdhSLP/2Z0yha5xPH3nLnskz81pBx3tcVSAw= github.com/cosmos/cosmos-proto v1.0.0-beta.5 h1:eNcayDLpip+zVLRLYafhzLvQlSmyab+RC5W7ZfmxJLA= github.com/cosmos/cosmos-proto v1.0.0-beta.5/go.mod h1:hQGLpiIUloJBMdQMMWb/4wRApmI9hjHH05nefC0Ojec= github.com/cosmos/cosmos-sdk v0.52.0-rc.1 h1:HgHOUYbxvjvyiX5CQF4eLT0u1wvjxajwgClOGzAmNoQ=