From 3e413243db3c20941de2306debe7d8c28404f324 Mon Sep 17 00:00:00 2001 From: Marko Date: Mon, 12 Aug 2024 16:19:13 +0200 Subject: [PATCH 1/6] refactor: remove consensus messages (#21248) --- core/app/app.go | 26 ++++---- core/context/context.go | 7 ++- server/v2/appmanager/appmanager.go | 8 +-- server/v2/cometbft/abci.go | 42 ++++++++----- server/v2/cometbft/config.go | 4 +- server/v2/go.mod | 14 +++-- server/v2/go.sum | 29 +++++---- server/v2/stf/stf.go | 36 +++-------- simapp/app.go | 26 ++++++-- simapp/app_config.go | 1 + simapp/v2/app_config.go | 1 + x/consensus/keeper/keeper.go | 60 +++++++++++++++---- x/consensus/module.go | 27 +++++++-- .../proto/cosmos/consensus/v1/query.proto | 1 - .../proto/cosmos/consensus/v1/tx.proto | 1 - 15 files changed, 180 insertions(+), 103 deletions(-) diff --git a/core/app/app.go b/core/app/app.go index 2295b0300835..b377d42cef38 100644 --- a/core/app/app.go +++ b/core/app/app.go @@ -21,26 +21,24 @@ type QueryResponse struct { } type BlockRequest[T transaction.Tx] struct { - Height uint64 - Time time.Time - Hash []byte - ChainId string - AppHash []byte - Txs []T - ConsensusMessages []transaction.Msg + Height uint64 + Time time.Time + Hash []byte + ChainId string + AppHash []byte + Txs []T // IsGenesis indicates if this block is the first block of the chain. IsGenesis bool } type BlockResponse struct { - Apphash []byte - ConsensusMessagesResponse []transaction.Msg - ValidatorUpdates []appmodulev2.ValidatorUpdate - PreBlockEvents []event.Event - BeginBlockEvents []event.Event - TxResults []TxResult - EndBlockEvents []event.Event + Apphash []byte + ValidatorUpdates []appmodulev2.ValidatorUpdate + PreBlockEvents []event.Event + BeginBlockEvents []event.Event + TxResults []TxResult + EndBlockEvents []event.Event } type RequestInitChain struct { diff --git a/core/context/context.go b/core/context/context.go index 6803bd7eb44b..54ed6b46236f 100644 --- a/core/context/context.go +++ b/core/context/context.go @@ -3,12 +3,17 @@ package context type ( execModeKey struct{} cometInfoKey struct{} + initInfoKey struct{} environmentKey struct{} ) var ( - ExecModeKey = execModeKey{} + // ExecModeKey is the context key for setting the execution mode. + ExecModeKey = execModeKey{} + // CometInfoKey is the context key for allowing modules to get CometInfo. CometInfoKey = cometInfoKey{} + // InitInfoKey is the context key for setting consensus params from genesis in the consensus module. + InitInfoKey = initInfoKey{} // EnvironmentContextKey is the context key for the environment. // A caller should not assume the environment is available in each context. diff --git a/server/v2/appmanager/appmanager.go b/server/v2/appmanager/appmanager.go index cef0fc57cce7..66e38a762a18 100644 --- a/server/v2/appmanager/appmanager.go +++ b/server/v2/appmanager/appmanager.go @@ -36,6 +36,7 @@ type AppManager[T transaction.Tx] struct { stf StateTransitionFunction[T] } +// InitGenesis initializes the genesis state of the application. func (a AppManager[T]) InitGenesis( ctx context.Context, blockRequest *appmanager.BlockRequest[T], @@ -65,8 +66,6 @@ func (a AppManager[T]) InitGenesis( return nil, nil, fmt.Errorf("failed to import genesis state: %w", err) } // run block - // TODO: in an ideal world, genesis state is simply an initial state being applied - // unaware of what that state means in relation to every other blockRequest.Txs = genTxs blockResponse, blockZeroState, err := a.stf.DeliverBlock(ctx, blockRequest, genesisState) @@ -75,18 +74,17 @@ func (a AppManager[T]) InitGenesis( } // after executing block 0, we extract the changes and apply them to the genesis state. - blockZeroStateChanges, err := blockZeroState.GetStateChanges() + stateChanges, err := blockZeroState.GetStateChanges() if err != nil { return nil, nil, fmt.Errorf("failed to get block zero state changes: %w", err) } - err = genesisState.ApplyStateChanges(blockZeroStateChanges) + err = genesisState.ApplyStateChanges(stateChanges) if err != nil { return nil, nil, fmt.Errorf("failed to apply block zero state changes to genesis state: %w", err) } return blockResponse, genesisState, err - // consensus server will need to set the version of the store } // ExportGenesis exports the genesis state of the application. diff --git a/server/v2/cometbft/abci.go b/server/v2/cometbft/abci.go index 2fa91216ed85..b7a300b05f5e 100644 --- a/server/v2/cometbft/abci.go +++ b/server/v2/cometbft/abci.go @@ -13,6 +13,7 @@ import ( coreappmgr "cosmossdk.io/core/app" "cosmossdk.io/core/comet" + corecontext "cosmossdk.io/core/context" "cosmossdk.io/core/event" "cosmossdk.io/core/store" "cosmossdk.io/core/transaction" @@ -152,10 +153,23 @@ func (c *Consensus[T]) Info(ctx context.Context, _ *abciproto.InfoRequest) (*abc return nil, err } - // cp, err := c.GetConsensusParams(ctx) - // if err != nil { - // return nil, err - // } + // if height is 0, we dont know the consensus params + var appVersion uint64 = 0 + if version > 0 { + cp, err := c.GetConsensusParams(ctx) + // if the consensus params are not found, we set the app version to 0 + // in the case that the start version is > 0 + if cp == nil || errors.Is(err, errors.New("collections: not found")) { + appVersion = 0 + } else if err != nil { + return nil, err + } else { + appVersion = cp.Version.GetApp() + } + if err != nil { + return nil, err + } + } cid, err := c.store.LastCommitID() if err != nil { @@ -165,7 +179,7 @@ func (c *Consensus[T]) Info(ctx context.Context, _ *abciproto.InfoRequest) (*abc return &abciproto.InfoResponse{ Data: c.appName, Version: c.version, - AppVersion: 0, // TODO fetch consensus params? + AppVersion: appVersion, LastBlockHeight: int64(version), LastBlockAppHash: cid.Hash, }, nil @@ -234,14 +248,15 @@ func (c *Consensus[T]) InitChain(ctx context.Context, req *abciproto.InitChainRe c.initialHeight = 1 } - var consMessages []transaction.Msg if req.ConsensusParams != nil { - consMessages = append(consMessages, &consensustypes.MsgUpdateParams{ + ctx = context.WithValue(ctx, corecontext.InitInfoKey, &consensustypes.MsgUpdateParams{ Authority: c.consensusAuthority, Block: req.ConsensusParams.Block, Evidence: req.ConsensusParams.Evidence, Validator: req.ConsensusParams.Validator, Abci: req.ConsensusParams.Abci, + Synchrony: req.ConsensusParams.Synchrony, + Feature: req.ConsensusParams.Feature, }) } @@ -254,13 +269,12 @@ func (c *Consensus[T]) InitChain(ctx context.Context, req *abciproto.InitChainRe bz := sha256.Sum256([]byte{}) br := &coreappmgr.BlockRequest[T]{ - Height: uint64(req.InitialHeight - 1), - Time: req.Time, - Hash: bz[:], - AppHash: ci.Hash, - ChainId: req.ChainId, - ConsensusMessages: consMessages, - IsGenesis: true, + Height: uint64(req.InitialHeight - 1), + Time: req.Time, + Hash: bz[:], + AppHash: ci.Hash, + ChainId: req.ChainId, + IsGenesis: true, } blockresponse, genesisState, err := c.app.InitGenesis( diff --git a/server/v2/cometbft/config.go b/server/v2/cometbft/config.go index 3f03e383c601..56860a78ddaf 100644 --- a/server/v2/cometbft/config.go +++ b/server/v2/cometbft/config.go @@ -43,14 +43,14 @@ type CfgOption func(*Config) // OverwriteDefaultConfigTomlConfig overwrites the default comet config with the new config. func OverwriteDefaultConfigTomlConfig(newCfg *cmtcfg.Config) CfgOption { return func(cfg *Config) { - cfg.ConfigTomlConfig = newCfg // nolint:ineffassign,staticcheck // We want to overwrite everything + cfg.ConfigTomlConfig = newCfg } } // OverwriteDefaultAppTomlConfig overwrites the default comet config with the new config. func OverwriteDefaultAppTomlConfig(newCfg *AppTomlConfig) CfgOption { return func(cfg *Config) { - cfg.AppTomlConfig = newCfg // nolint:ineffassign,staticcheck // We want to overwrite everything + cfg.AppTomlConfig = newCfg } } diff --git a/server/v2/go.mod b/server/v2/go.mod index d9f90121405a..602ffa6cdfa7 100644 --- a/server/v2/go.mod +++ b/server/v2/go.mod @@ -26,9 +26,9 @@ require ( github.com/golang/protobuf v1.5.4 github.com/gorilla/mux v1.8.1 github.com/grpc-ecosystem/grpc-gateway v1.16.0 - github.com/hashicorp/go-hclog v1.6.2 + github.com/hashicorp/go-hclog v1.6.3 github.com/hashicorp/go-metrics v0.5.3 - github.com/hashicorp/go-plugin v1.6.0 + github.com/hashicorp/go-plugin v1.6.1 github.com/mitchellh/mapstructure v1.5.0 github.com/pelletier/go-toml/v2 v2.2.2 github.com/prometheus/client_golang v1.19.1 @@ -46,8 +46,9 @@ require ( require ( cosmossdk.io/errors/v2 v2.0.0-20240731132947-df72853b3ca5 // indirect - github.com/DataDog/datadog-go v3.2.0+incompatible // indirect + github.com/DataDog/datadog-go v4.8.3+incompatible // indirect github.com/DataDog/zstd v1.5.5 // indirect + github.com/Microsoft/go-winio v0.6.1 // indirect github.com/beorn7/perks v1.0.1 // indirect github.com/cespare/xxhash/v2 v2.3.0 // indirect github.com/cockroachdb/errors v1.11.1 // indirect @@ -60,7 +61,7 @@ require ( github.com/cosmos/ics23/go v0.10.0 // indirect github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect github.com/emicklei/dot v1.6.2 // indirect - github.com/fatih/color v1.15.0 // indirect + github.com/fatih/color v1.17.0 // indirect github.com/fsnotify/fsnotify v1.7.0 // indirect github.com/getsentry/sentry-go v0.27.0 // indirect github.com/gogo/googleapis v1.4.1 // indirect @@ -74,7 +75,7 @@ require ( github.com/hashicorp/yamux v0.1.1 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/jhump/protoreflect v1.15.3 // indirect - github.com/klauspost/compress v1.17.7 // indirect + github.com/klauspost/compress v1.17.8 // indirect github.com/kr/pretty v0.3.1 // indirect github.com/kr/text v0.2.0 // indirect github.com/linxGnu/grocksdb v1.8.14 // indirect @@ -85,6 +86,7 @@ require ( github.com/mitchellh/go-testing-interface v1.14.1 // indirect github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect github.com/oklog/run v1.1.0 // indirect + github.com/onsi/gomega v1.28.1 // indirect github.com/pkg/errors v0.9.1 // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect github.com/prometheus/client_model v0.6.1 // indirect @@ -100,9 +102,11 @@ require ( github.com/tidwall/btree v1.7.0 // indirect go.uber.org/multierr v1.11.0 // indirect golang.org/x/crypto v0.26.0 // indirect + golang.org/x/mod v0.17.0 // indirect golang.org/x/net v0.28.0 // indirect golang.org/x/sys v0.24.0 // indirect golang.org/x/text v0.17.0 // indirect + golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d // indirect google.golang.org/genproto v0.0.0-20240227224415-6ceb2ff114de // indirect google.golang.org/genproto/googleapis/api v0.0.0-20240528184218-531527333157 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20240808171019-573a1156607a // indirect diff --git a/server/v2/go.sum b/server/v2/go.sum index 8b891e449ae8..c87730bfa317 100644 --- a/server/v2/go.sum +++ b/server/v2/go.sum @@ -5,10 +5,13 @@ cosmossdk.io/errors/v2 v2.0.0-20240731132947-df72853b3ca5/go.mod h1:0CuYKkFHxc1v cosmossdk.io/log v1.4.0 h1:Ttt9d6fQ0GlktwhcysOeNiIjixW7l0rYBocmoXOb11k= cosmossdk.io/log v1.4.0/go.mod h1:k08v0Pyq+gCP6phvdI6RCGhLf/r425UT6Rk/m+o74rU= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= -github.com/DataDog/datadog-go v3.2.0+incompatible h1:qSG2N4FghB1He/r2mFrWKCaL7dXCilEuNEeAn20fdD4= github.com/DataDog/datadog-go v3.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ= +github.com/DataDog/datadog-go v4.8.3+incompatible h1:fNGaYSuObuQb5nzeTQqowRAd9bpDIRRV4/gUtIBjh8Q= +github.com/DataDog/datadog-go v4.8.3+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ= github.com/DataDog/zstd v1.5.5 h1:oWf5W7GtOLgp6bciQYDmhHHjdhYkALu6S/5Ni9ZgSvQ= github.com/DataDog/zstd v1.5.5/go.mod h1:g4AWEaM3yOg3HYfnJ3YIawPnVdXJh9QME85blwSAmyw= +github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migciow= +github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= @@ -79,8 +82,8 @@ github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go. github.com/envoyproxy/go-control-plane v0.10.2-0.20220325020618-49ff273808a1/go.mod h1:KJwIaB5Mv44NWtYuAOFCVOjcI94vtpEz2JU/D2v6IjE= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk= -github.com/fatih/color v1.15.0 h1:kOqh6YHBtK8aywxGerMG2Eq3H6Qgoqeo13Bk2Mv/nBs= -github.com/fatih/color v1.15.0/go.mod h1:0h5ZqXfHYED7Bhv2ZJamyIOUej9KtShiJESRwBDUSsw= +github.com/fatih/color v1.17.0 h1:GlRw1BRJxkpqUCBKzKOw098ed57fEsKeNjpTe3cSjK4= +github.com/fatih/color v1.17.0/go.mod h1:YZ7TlrGPkiz6ku9fK3TLD/pl3CpsiFyu8N92HLgmosI= github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8= github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= @@ -148,15 +151,15 @@ github.com/gorilla/mux v1.8.1/go.mod h1:AKf9I4AEqPTmMytcMc0KkNouC66V3BtZ4qD5fmWS github.com/grpc-ecosystem/grpc-gateway v1.16.0 h1:gmcG1KaJ57LophUzW0Hy8NmPhnMZb4M0+kPpLofRdBo= github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= github.com/hashicorp/go-cleanhttp v0.5.0/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= -github.com/hashicorp/go-hclog v1.6.2 h1:NOtoftovWkDheyUM/8JW3QMiXyxJK3uHRK7wV04nD2I= -github.com/hashicorp/go-hclog v1.6.2/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M= +github.com/hashicorp/go-hclog v1.6.3 h1:Qr2kF+eVWjTiYmU7Y31tYlP1h0q/X3Nl3tPGdaB11/k= +github.com/hashicorp/go-hclog v1.6.3/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M= github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= github.com/hashicorp/go-immutable-radix v1.3.1 h1:DKHmCUm2hRBK510BaiZlwvpD40f8bJFeZnpfm2KLowc= github.com/hashicorp/go-immutable-radix v1.3.1/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= github.com/hashicorp/go-metrics v0.5.3 h1:M5uADWMOGCTUNU1YuC4hfknOeHNaX54LDm4oYSucoNE= github.com/hashicorp/go-metrics v0.5.3/go.mod h1:KEjodfebIOuBYSAe/bHTm+HChmKSxAOXPBieMLYozDE= -github.com/hashicorp/go-plugin v1.6.0 h1:wgd4KxHJTVGGqWBq4QPB1i5BZNEx9BR8+OFmHDmTk8A= -github.com/hashicorp/go-plugin v1.6.0/go.mod h1:lBS5MtSSBZk0SHc66KACcjjlU6WzEVP/8pwz68aMkCI= +github.com/hashicorp/go-plugin v1.6.1 h1:P7MR2UP6gNKGPp+y7EZw2kOiq4IR9WiqLvp0XOsVdwI= +github.com/hashicorp/go-plugin v1.6.1/go.mod h1:XPHFku2tFo3o3QKFgSYo+cghcUhw1NA1hZyMK0PWAw0= github.com/hashicorp/go-retryablehttp v0.5.3/go.mod h1:9B5zBasrRhHXnJnui7y6sL7es7NDiJgTc6Er0maI1Xs= github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= github.com/hashicorp/go-uuid v1.0.1 h1:fv1ep09latC32wFoVwnqcnKJGnMSdBanPczbHAYm1BE= @@ -180,8 +183,8 @@ github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7V github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= -github.com/klauspost/compress v1.17.7 h1:ehO88t2UGzQK66LMdE8tibEd1ErmzZjNEqWkjLAKQQg= -github.com/klauspost/compress v1.17.7/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw= +github.com/klauspost/compress v1.17.8 h1:YcnTYrq7MikUT7k0Yb5eceMmALQPYBW/Xltxn0NAMnU= +github.com/klauspost/compress v1.17.8/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= @@ -234,8 +237,8 @@ github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7J github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY= github.com/onsi/gomega v1.19.0/go.mod h1:LY+I3pBVzYsTBU1AnDwOSxaYi9WoWiqgwooUqq9yPro= -github.com/onsi/gomega v1.26.0 h1:03cDLK28U6hWvCAns6NeydX3zIm4SF3ci69ulidS32Q= -github.com/onsi/gomega v1.26.0/go.mod h1:r+zV744Re+DiYCIPRlYOTxn0YkOLcAnW8k1xXdMPGhM= +github.com/onsi/gomega v1.28.1 h1:MijcGUbfYuznzK/5R4CPNoUP/9Xvuo20sXfEm6XxoTA= +github.com/onsi/gomega v1.28.1/go.mod h1:9sxs+SwGrKI0+PWe4Fxa9tFQQBG5xSsSbMXOI8PPpoQ= github.com/pascaldekloe/goe v0.1.0 h1:cBOtyMzM9HTpWjXfbbunk26uA6nG3a8n06Wieeh0MwY= github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= github.com/pelletier/go-toml/v2 v2.2.2 h1:aYUidT7k73Pcl9nb2gScu7NSrKCSHIDE89b3+6Wq+LM= @@ -341,6 +344,8 @@ golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvx golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.17.0 h1:zY54UmvipHiNd+pm+m0x9KhZ9hl1/7QNMyxXbc6ICqA= +golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -425,6 +430,8 @@ golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtn golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d h1:vU5i/LfpvrRCpgM/VPfJLg5KjxD3E+hfT1SH+d9zLwg= +golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= diff --git a/server/v2/stf/stf.go b/server/v2/stf/stf.go index 2231f893b55b..d3cd2405b23b 100644 --- a/server/v2/stf/stf.go +++ b/server/v2/stf/stf.go @@ -106,10 +106,6 @@ func (s STF[T]) DeliverBlock( exCtx := s.makeContext(ctx, appmanager.ConsensusIdentity, newState, internal.ExecModeFinalize) exCtx.setHeaderInfo(hi) - consMessagesResponses, err := s.runConsensusMessages(exCtx, block.ConsensusMessages) - if err != nil { - return nil, nil, fmt.Errorf("failed to execute consensus messages: %w", err) - } // reset events exCtx.events = make([]event.Event, 0) @@ -160,13 +156,12 @@ func (s STF[T]) DeliverBlock( } return &appmanager.BlockResponse{ - Apphash: nil, - ConsensusMessagesResponse: consMessagesResponses, - ValidatorUpdates: valset, - PreBlockEvents: preBlockEvents, - BeginBlockEvents: beginBlockEvents, - TxResults: txResults, - EndBlockEvents: endBlockEvents, + Apphash: nil, + ValidatorUpdates: valset, + PreBlockEvents: preBlockEvents, + BeginBlockEvents: beginBlockEvents, + TxResults: txResults, + EndBlockEvents: endBlockEvents, }, newState, nil } @@ -333,6 +328,7 @@ func (s STF[T]) runTxMsgs( return msgResps, consumed, execCtx.events, nil } +// preBlock executes the pre block logic. func (s STF[T]) preBlock( ctx *executionContext, txs []T, @@ -352,22 +348,7 @@ func (s STF[T]) preBlock( return ctx.events, nil } -func (s STF[T]) runConsensusMessages( - ctx *executionContext, - messages []transaction.Msg, -) ([]transaction.Msg, error) { - responses := make([]transaction.Msg, len(messages)) - for i := range messages { - resp, err := s.msgRouter.InvokeUntyped(ctx, messages[i]) - if err != nil { - return nil, err - } - responses[i] = resp - } - - return responses, nil -} - +// beginBlock executes the begin block logic. func (s STF[T]) beginBlock( ctx *executionContext, ) (beginBlockEvents []event.Event, err error) { @@ -386,6 +367,7 @@ func (s STF[T]) beginBlock( return ctx.events, nil } +// endBlock executes the end block logic. func (s STF[T]) endBlock( ctx *executionContext, ) ([]event.Event, []appmodulev2.ValidatorUpdate, error) { diff --git a/simapp/app.go b/simapp/app.go index 6c2424e29c60..a03a9e69f518 100644 --- a/simapp/app.go +++ b/simapp/app.go @@ -51,6 +51,7 @@ import ( "cosmossdk.io/x/consensus" consensusparamkeeper "cosmossdk.io/x/consensus/keeper" consensusparamtypes "cosmossdk.io/x/consensus/types" + consensustypes "cosmossdk.io/x/consensus/types" distr "cosmossdk.io/x/distribution" distrkeeper "cosmossdk.io/x/distribution/keeper" distrtypes "cosmossdk.io/x/distribution/types" @@ -501,11 +502,26 @@ func NewSimApp( // properly initialized with tokens from genesis accounts. // NOTE: The genutils module must also occur after auth so that it can access the params from auth. genesisModuleOrder := []string{ - accounts.ModuleName, authtypes.ModuleName, banktypes.ModuleName, - distrtypes.ModuleName, stakingtypes.ModuleName, slashingtypes.ModuleName, govtypes.ModuleName, - minttypes.ModuleName, genutiltypes.ModuleName, evidencetypes.ModuleName, authz.ModuleName, - feegrant.ModuleName, nft.ModuleName, group.ModuleName, upgradetypes.ModuleName, - vestingtypes.ModuleName, consensusparamtypes.ModuleName, circuittypes.ModuleName, pooltypes.ModuleName, + consensustypes.ModuleName, + accounts.ModuleName, + authtypes.ModuleName, + banktypes.ModuleName, + distrtypes.ModuleName, + stakingtypes.ModuleName, + slashingtypes.ModuleName, + govtypes.ModuleName, + minttypes.ModuleName, + genutiltypes.ModuleName, + evidencetypes.ModuleName, + authz.ModuleName, + feegrant.ModuleName, + nft.ModuleName, + group.ModuleName, + upgradetypes.ModuleName, + vestingtypes.ModuleName, + consensusparamtypes.ModuleName, + circuittypes.ModuleName, + pooltypes.ModuleName, epochstypes.ModuleName, } app.ModuleManager.SetOrderInitGenesis(genesisModuleOrder...) diff --git a/simapp/app_config.go b/simapp/app_config.go index e92ac2ce03fe..8918475184e1 100644 --- a/simapp/app_config.go +++ b/simapp/app_config.go @@ -149,6 +149,7 @@ var ( // properly initialized with tokens from genesis accounts. // NOTE: The genutils module must also occur after auth so that it can access the params from auth. InitGenesis: []string{ + consensustypes.ModuleName, accounts.ModuleName, authtypes.ModuleName, banktypes.ModuleName, diff --git a/simapp/v2/app_config.go b/simapp/v2/app_config.go index c3e5e0492935..ab54100a3f09 100644 --- a/simapp/v2/app_config.go +++ b/simapp/v2/app_config.go @@ -139,6 +139,7 @@ var ( // properly initialized with tokens from genesis accounts. // NOTE: The genutils module must also occur after auth so that it can access the params from auth. InitGenesis: []string{ + consensustypes.ModuleName, accounts.ModuleName, authtypes.ModuleName, banktypes.ModuleName, diff --git a/x/consensus/keeper/keeper.go b/x/consensus/keeper/keeper.go index 9236f76f8ddb..548bf61d9337 100644 --- a/x/consensus/keeper/keeper.go +++ b/x/consensus/keeper/keeper.go @@ -12,6 +12,7 @@ import ( "cosmossdk.io/collections" "cosmossdk.io/core/appmodule" + corecontext "cosmossdk.io/core/context" "cosmossdk.io/core/event" "cosmossdk.io/x/consensus/exported" "cosmossdk.io/x/consensus/types" @@ -41,6 +42,31 @@ func (k *Keeper) GetAuthority() string { return k.authority } +// InitGenesis initializes the initial state of the module +func (k *Keeper) InitGenesis(ctx context.Context) error { + value, ok := ctx.Value(corecontext.InitInfoKey).(*types.MsgUpdateParams) + if !ok { + // no error for appv1 and appv2 + return nil + } + if value == nil { + // no error for appv1 + return nil + } + + consensusParams, err := value.ToProtoConsensusParams() + if err != nil { + return err + } + + nextParams, err := k.paramCheck(ctx, consensusParams) + if err != nil { + return err + } + + return k.ParamsStore.Set(ctx, nextParams.ToProto()) +} + // Querier var _ types.QueryServer = Keeper{} @@ -69,6 +95,27 @@ func (k Keeper) UpdateParams(ctx context.Context, msg *types.MsgUpdateParams) (* return nil, err } + nextParams, err := k.paramCheck(ctx, consensusParams) + if err != nil { + return nil, err + } + + if err := k.ParamsStore.Set(ctx, nextParams.ToProto()); err != nil { + return nil, err + } + + if err := k.EventService.EventManager(ctx).EmitKV( + "update_consensus_params", + event.NewAttribute("authority", msg.Authority), + event.NewAttribute("parameters", consensusParams.String())); err != nil { + return nil, err + } + + return &types.MsgUpdateParamsResponse{}, nil +} + +// paramCheck validates the consensus params +func (k Keeper) paramCheck(ctx context.Context, consensusParams cmtproto.ConsensusParams) (*cmttypes.ConsensusParams, error) { paramsProto, err := k.ParamsStore.Get(ctx) var params cmttypes.ConsensusParams @@ -92,16 +139,5 @@ func (k Keeper) UpdateParams(ctx context.Context, msg *types.MsgUpdateParams) (* return nil, err } - if err := k.ParamsStore.Set(ctx, nextParams.ToProto()); err != nil { - return nil, err - } - - if err := k.EventService.EventManager(ctx).EmitKV( - "update_consensus_params", - event.NewAttribute("authority", msg.Authority), - event.NewAttribute("parameters", consensusParams.String())); err != nil { - return nil, err - } - - return &types.MsgUpdateParamsResponse{}, nil + return &nextParams, nil } diff --git a/x/consensus/module.go b/x/consensus/module.go index 02504cfcff19..72c04496addc 100644 --- a/x/consensus/module.go +++ b/x/consensus/module.go @@ -2,6 +2,7 @@ package consensus import ( "context" + "encoding/json" gwruntime "github.com/grpc-ecosystem/grpc-gateway/runtime" "google.golang.org/grpc" @@ -25,6 +26,7 @@ var ( _ module.HasGRPCGateway = AppModule{} _ appmodule.AppModule = AppModule{} + _ appmodule.HasGenesis = AppModule{} _ appmodule.HasRegisterInterfaces = AppModule{} ) @@ -42,6 +44,26 @@ func NewAppModule(cdc codec.Codec, keeper keeper.Keeper) AppModule { } } +// InitGenesis performs genesis initialization for the bank module. +func (am AppModule) InitGenesis(ctx context.Context, data json.RawMessage) error { + return am.keeper.InitGenesis(ctx) +} + +// DefaultGenesis returns the default genesis state. (Noop) +func (am AppModule) DefaultGenesis() json.RawMessage { + return nil +} + +// ValidateGenesis validates the genesis state. (Noop) +func (am AppModule) ValidateGenesis(data json.RawMessage) error { + return nil +} + +// ExportGenesis returns the exported genesis state. (Noop) +func (am AppModule) ExportGenesis(ctx context.Context) (json.RawMessage, error) { + return nil, nil +} + // IsAppModule implements the appmodule.AppModule interface. func (AppModule) IsAppModule() {} @@ -75,8 +97,3 @@ func (am AppModule) RegisterServices(registrar grpc.ServiceRegistrar) error { // ConsensusVersion implements HasConsensusVersion. func (AppModule) ConsensusVersion() uint64 { return ConsensusVersion } - -// RegisterConsensusMessages registers the consensus module's messages. -func (am AppModule) RegisterConsensusMessages(builder any) { - // std.RegisterConsensusHandler(builder ,am.keeper.SetParams) // TODO uncomment when api is available -} diff --git a/x/consensus/proto/cosmos/consensus/v1/query.proto b/x/consensus/proto/cosmos/consensus/v1/query.proto index 4841c5aed367..9a84c1909766 100644 --- a/x/consensus/proto/cosmos/consensus/v1/query.proto +++ b/x/consensus/proto/cosmos/consensus/v1/query.proto @@ -4,7 +4,6 @@ package cosmos.consensus.v1; import "google/api/annotations.proto"; import "cometbft/types/v1/params.proto"; -import "cosmos/consensus/v1/consensus.proto"; option go_package = "cosmossdk.io/x/consensus/types"; diff --git a/x/consensus/proto/cosmos/consensus/v1/tx.proto b/x/consensus/proto/cosmos/consensus/v1/tx.proto index afecf31d97b8..d0cdde493a9c 100644 --- a/x/consensus/proto/cosmos/consensus/v1/tx.proto +++ b/x/consensus/proto/cosmos/consensus/v1/tx.proto @@ -6,7 +6,6 @@ import "amino/amino.proto"; import "cosmos_proto/cosmos.proto"; import "cosmos/msg/v1/msg.proto"; import "cometbft/types/v1/params.proto"; -import "cometbft/abci/v1/types.proto"; option go_package = "cosmossdk.io/x/consensus/types"; From 76e1fa30fb352800b3e79e08a76a474bc88b6193 Mon Sep 17 00:00:00 2001 From: Julien Robert Date: Mon, 12 Aug 2024 22:08:36 +0200 Subject: [PATCH 2/6] fix(cosmovisor): fix upgrade detection (#20585) --- .github/workflows/lint.yml | 13 + tools/cosmovisor/CHANGELOG.md | 9 +- tools/cosmovisor/README.md | 37 ++- tools/cosmovisor/args.go | 27 +- tools/cosmovisor/args_test.go | 2 +- tools/cosmovisor/cmd/cosmovisor/init.go | 43 +--- tools/cosmovisor/cmd/cosmovisor/init_test.go | 8 +- tools/cosmovisor/cmd/cosmovisor/main.go | 13 - tools/cosmovisor/cmd/cosmovisor/run.go | 2 +- tools/cosmovisor/go.mod | 4 +- tools/cosmovisor/process.go | 2 +- tools/cosmovisor/process_test.go | 250 +++++++++---------- tools/cosmovisor/scanner.go | 36 ++- 13 files changed, 210 insertions(+), 236 deletions(-) diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 813453c5fb53..1b61aa2b1748 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -40,6 +40,19 @@ jobs: PATTERNS: | **/*.go *.go + !store/** + - name: run linting (short) + if: steps.lint_long.outcome == 'skipped' && env.GIT_DIFF + run: | + make lint + env: + GIT_DIFF: ${{ env.GIT_DIFF }} + LINT_DIFF: 1 + - uses: technote-space/get-diff-action@v6.1.2 + if: steps.lint_long.outcome == 'skipped' + with: + PATTERNS: | + store/** - name: run linting (short) if: steps.lint_long.outcome == 'skipped' && env.GIT_DIFF run: | diff --git a/tools/cosmovisor/CHANGELOG.md b/tools/cosmovisor/CHANGELOG.md index 220fc0745025..3931ccd3a3b2 100644 --- a/tools/cosmovisor/CHANGELOG.md +++ b/tools/cosmovisor/CHANGELOG.md @@ -36,13 +36,11 @@ Ref: https://keepachangelog.com/en/1.0.0/ ## [Unreleased] -## Features - -* [#19764](https://github.com/cosmos/cosmos-sdk/issues/19764) Use config file for cosmovisor configuration. +## v1.6.0 - 2024-08-12 ## Improvements -* [#20573](https://github.com/cosmos/cosmos-sdk/pull/20573) Bump `cosmossdk.io/x/upgrade` to v0.1.3 (including go-getter vulnerability fix) +* Bump `cosmossdk.io/x/upgrade` to v0.1.4 (including go-getter vulnerability fix) * [#19995](https://github.com/cosmos/cosmos-sdk/pull/19995): * `init command` writes the configuration to the config file only at the default path `DAEMON_HOME/cosmovisor/config.toml`. * Provide `--cosmovisor-config` flag with value as args to provide the path to the configuration file in the `run` command. `run --cosmovisor-config (other cmds with flags) ...`. @@ -52,6 +50,9 @@ Ref: https://keepachangelog.com/en/1.0.0/ ## Bug Fixes * [#20062](https://github.com/cosmos/cosmos-sdk/pull/20062) Fixed cosmovisor add-upgrade permissions +* [#20585](https://github.com/cosmos/cosmos-sdk/pull/20585) Always parse stdout and stderr +* [#20585](https://github.com/cosmos/cosmos-sdk/pull/20585) Pass right home to command `status` +* [#20585](https://github.com/cosmos/cosmos-sdk/pull/20585) Fix upgrades applied automatically (check two casing of sync_info) ## v1.5.0 - 2023-07-17 diff --git a/tools/cosmovisor/README.md b/tools/cosmovisor/README.md index 06c7e61c9846..db15ab0a5d64 100644 --- a/tools/cosmovisor/README.md +++ b/tools/cosmovisor/README.md @@ -7,21 +7,22 @@ sidebar_position: 1 `cosmovisor` is a process manager for Cosmos SDK application binaries that automates application binary switch at chain upgrades. It polls the `upgrade-info.json` file that is created by the x/upgrade module at upgrade height, and then can automatically download the new binary, stop the current binary, switch from the old binary to the new one, and finally restart the node with the new binary. -* [Design](#design) -* [Contributing](#contributing) -* [Setup](#setup) - * [Installation](#installation) - * [Command Line Arguments And Environment Variables](#command-line-arguments-and-environment-variables) - * [Folder Layout](#folder-layout) -* [Usage](#usage) - * [Initialization](#initialization) - * [Detecting Upgrades](#detecting-upgrades) - * [Adding Upgrade Binary](#adding-upgrade-binary) - * [Auto-Download](#auto-download) -* [Example: SimApp Upgrade](#example-simapp-upgrade) - * [Chain Setup](#chain-setup) - * [Prepare Cosmovisor and Start the Chain](#prepare-cosmovisor-and-start-the-chain) - * [Update App](#update-app) +* [Cosmovisor](#cosmovisor) + * [Design](#design) + * [Contributing](#contributing) + * [Setup](#setup) + * [Installation](#installation) + * [Command Line Arguments And Environment Variables](#command-line-arguments-and-environment-variables) + * [Folder Layout](#folder-layout) + * [Usage](#usage) + * [Initialization](#initialization) + * [Detecting Upgrades](#detecting-upgrades) + * [Adding Upgrade Binary](#adding-upgrade-binary) + * [Auto-Download](#auto-download) + * [Example: SimApp Upgrade](#example-simapp-upgrade) + * [Chain Setup](#chain-setup) + * [Prepare Cosmovisor and Start the Chain](#prepare-cosmovisor-and-start-the-chain) + * [Update App](#update-app) ## Design @@ -87,11 +88,7 @@ The first argument passed to `cosmovisor` is the action for `cosmovisor` to take All arguments passed to `cosmovisor run` will be passed to the application binary (as a subprocess). `cosmovisor` will return `/dev/stdout` and `/dev/stderr` of the subprocess as its own. For this reason, `cosmovisor run` cannot accept any command-line arguments other than those available to the application binary. -:::warning -Use of `cosmovisor` without one of the action arguments is deprecated. For backwards compatibility, if the first argument is not an action argument, `run` is assumed. However, this fallback might be removed in future versions, so it is recommended that you always provide `run`. -::: - -`cosmovisor` reads its configuration from environment variables: +`cosmovisor` reads its configuration from environment variables, or its configuration file (use `--cosmovisor-config `): * `DAEMON_HOME` is the location where the `cosmovisor/` directory is kept that contains the genesis binary, the upgrade binaries, and any additional auxiliary files associated with each binary (e.g. `$HOME/.gaiad`, `$HOME/.regend`, `$HOME/.simd`, etc.). * `DAEMON_NAME` is the name of the binary itself (e.g. `gaiad`, `regend`, `simd`, etc.). diff --git a/tools/cosmovisor/args.go b/tools/cosmovisor/args.go index 40e2553631b3..be94fbadaf6c 100644 --- a/tools/cosmovisor/args.go +++ b/tools/cosmovisor/args.go @@ -156,12 +156,12 @@ func (cfg *Config) CurrentBin() (string, error) { return binpath, nil } -// GetConfigFromFile will read the configuration from the file at the given path. -// If the file path is not provided, it will try to read the configuration from the ENV variables. +// GetConfigFromFile will read the configuration from the config file at the given path. +// If the file path is not provided, it will read the configuration from the ENV variables. // If a file path is provided and ENV variables are set, they will override the values in the file. func GetConfigFromFile(filePath string) (*Config, error) { if filePath == "" { - return GetConfigFromEnv() + return GetConfigFromEnv(false) } // ensure the file exist @@ -169,18 +169,19 @@ func GetConfigFromFile(filePath string) (*Config, error) { return nil, fmt.Errorf("config not found: at %s : %w", filePath, err) } + v := viper.New() // read the configuration from the file - viper.SetConfigFile(filePath) + v.SetConfigFile(filePath) // load the env variables // if the env variable is set, it will override the value provided by the config - viper.AutomaticEnv() + v.AutomaticEnv() - if err := viper.ReadInConfig(); err != nil { + if err := v.ReadInConfig(); err != nil { return nil, fmt.Errorf("failed to read config file: %w", err) } cfg := &Config{} - if err := viper.Unmarshal(cfg); err != nil { + if err := v.Unmarshal(cfg); err != nil { return nil, fmt.Errorf("failed to unmarshal configuration: %w", err) } @@ -203,7 +204,7 @@ func GetConfigFromFile(filePath string) (*Config, error) { // GetConfigFromEnv will read the environmental variables into a config // and then validate it is reasonable -func GetConfigFromEnv() (*Config, error) { +func GetConfigFromEnv(skipValidate bool) (*Config, error) { var errs []error cfg := &Config{ Home: os.Getenv(EnvHome), @@ -281,9 +282,11 @@ func GetConfigFromEnv() (*Config, error) { errs = append(errs, fmt.Errorf("%s could not be parsed to int: %w", EnvPreupgradeMaxRetries, err)) } - errs = append(errs, cfg.validate()...) - if len(errs) > 0 { - return nil, errors.Join(errs...) + if !skipValidate { + errs = append(errs, cfg.validate()...) + if len(errs) > 0 { + return nil, errors.Join(errs...) + } } return cfg, nil @@ -574,7 +577,7 @@ func (cfg Config) DetailString() string { return sb.String() } -// Export exports the configuration to a file at the given path. +// Export exports the configuration to a file at the cosmovisor root directory. func (cfg Config) Export() (string, error) { // always use the default path path := filepath.Clean(cfg.DefaultCfgPath()) diff --git a/tools/cosmovisor/args_test.go b/tools/cosmovisor/args_test.go index b379720763f0..74b75841ec5d 100644 --- a/tools/cosmovisor/args_test.go +++ b/tools/cosmovisor/args_test.go @@ -769,7 +769,7 @@ func (s *argsTestSuite) TestGetConfigFromEnv() { s.T().Run(tc.name, func(t *testing.T) { s.setEnv(t, &tc.envVals) - cfg, err := GetConfigFromEnv() + cfg, err := GetConfigFromEnv(false) if tc.expectedErrCount == 0 { assert.NoError(t, err) } else if assert.Error(t, err) { diff --git a/tools/cosmovisor/cmd/cosmovisor/init.go b/tools/cosmovisor/cmd/cosmovisor/init.go index 66d99b68032e..5f78e2845c02 100644 --- a/tools/cosmovisor/cmd/cosmovisor/init.go +++ b/tools/cosmovisor/cmd/cosmovisor/init.go @@ -6,7 +6,6 @@ import ( "io" "os" "path/filepath" - "time" "github.com/spf13/cobra" @@ -45,11 +44,18 @@ func InitializeCosmovisor(logger log.Logger, args []string) error { case exeInfo.IsDir(): return errors.New("invalid path to executable: must not be a directory") } - cfg, err := getConfigForInitCmd() + + // skipping validation to not check if directories exist + cfg, err := cosmovisor.GetConfigFromEnv(true) if err != nil { return err } + // process to minimal validation + if err := minConfigValidate(cfg); err != nil { + return err + } + if logger == nil { logger = cfg.Logger(os.Stdout) } @@ -98,37 +104,13 @@ func InitializeCosmovisor(logger log.Logger, args []string) error { if err != nil { return fmt.Errorf("failed to export configuration: %w", err) } - - logger.Info(fmt.Sprintf("config file present at: %s", filePath)) + logger.Info(fmt.Sprintf("cosmovisor config.toml created at: %s", filePath)) return nil } -// getConfigForInitCmd gets just the configuration elements needed to initialize cosmovisor. -func getConfigForInitCmd() (*cosmovisor.Config, error) { +func minConfigValidate(cfg *cosmovisor.Config) error { var errs []error - - // Note: Not using GetConfigFromEnv here because that checks that the directories already exist. - // We also don't care about the rest of the configuration stuff in here. - cfg := &cosmovisor.Config{ - Home: os.Getenv(cosmovisor.EnvHome), - Name: os.Getenv(cosmovisor.EnvName), - } - - var err error - if cfg.ColorLogs, err = cosmovisor.BooleanOption(cosmovisor.EnvColorLogs, true); err != nil { - errs = append(errs, err) - } - - if cfg.TimeFormatLogs, err = cosmovisor.TimeFormatOptionFromEnv(cosmovisor.EnvTimeFormatLogs, time.Kitchen); err != nil { - errs = append(errs, err) - } - - // if backup is not set, use the home directory - if cfg.DataBackupPath == "" { - cfg.DataBackupPath = cfg.Home - } - if len(cfg.Name) == 0 { errs = append(errs, fmt.Errorf("%s is not set", cosmovisor.EnvName)) } @@ -140,10 +122,7 @@ func getConfigForInitCmd() (*cosmovisor.Config, error) { errs = append(errs, fmt.Errorf("%s must be an absolute path", cosmovisor.EnvHome)) } - if len(errs) > 0 { - return cfg, errors.Join(errs...) - } - return cfg, nil + return errors.Join(errs...) } // copyFile copies the file at the given source to the given destination. diff --git a/tools/cosmovisor/cmd/cosmovisor/init_test.go b/tools/cosmovisor/cmd/cosmovisor/init_test.go index 95d971ab08ed..cea1349e3b39 100644 --- a/tools/cosmovisor/cmd/cosmovisor/init_test.go +++ b/tools/cosmovisor/cmd/cosmovisor/init_test.go @@ -502,7 +502,7 @@ func (s *InitTestSuite) TestInitializeCosmovisorValid() { fmt.Sprintf("making sure %q is executable", genBinExe), "checking on the current symlink and creating it if needed", fmt.Sprintf("the current symlink points to: %q", genBinExe), - fmt.Sprintf("config file present at: %s", filepath.Join(env.Home, cosmovisorDirName, cfgFileWithExt)), + fmt.Sprintf("cosmovisor config.toml created at: %s", filepath.Join(env.Home, cosmovisorDirName, cfgFileWithExt)), } s.setEnv(s.T(), env) @@ -555,7 +555,7 @@ func (s *InitTestSuite) TestInitializeCosmovisorValid() { fmt.Sprintf("the %q file already exists", genBinDirExe), fmt.Sprintf("making sure %q is executable", genBinDirExe), fmt.Sprintf("the current symlink points to: %q", genBinDirExe), - fmt.Sprintf("config file present at: %s", filepath.Join(env.Home, cosmovisorDirName, cfgFileWithExt)), + fmt.Sprintf("cosmovisor config.toml created at: %s", filepath.Join(env.Home, cosmovisorDirName, cfgFileWithExt)), } s.setEnv(t, env) @@ -588,7 +588,7 @@ func (s *InitTestSuite) TestInitializeCosmovisorValid() { fmt.Sprintf("copying executable into place: %q", genBinExe), fmt.Sprintf("making sure %q is executable", genBinExe), fmt.Sprintf("the current symlink points to: %q", genBinExe), - fmt.Sprintf("config file present at: %s", filepath.Join(env.Home, cosmovisorDirName, cfgFileWithExt)), + fmt.Sprintf("cosmovisor config.toml created at: %s", filepath.Join(env.Home, cosmovisorDirName, cfgFileWithExt)), } s.setEnv(t, env) @@ -620,7 +620,7 @@ func (s *InitTestSuite) TestInitializeCosmovisorValid() { require.NoError(t, err, "calling InitializeCosmovisor") bufferBz := buffer.Collect() bufferStr := string(bufferBz) - assert.Contains(t, bufferStr, fmt.Sprintf("config file present at: %s", filepath.Join(env.Home, cosmovisorDirName, cfgFileWithExt))) + assert.Contains(t, bufferStr, fmt.Sprintf("cosmovisor config.toml created at: %s", filepath.Join(env.Home, cosmovisorDirName, cfgFileWithExt))) }) } diff --git a/tools/cosmovisor/cmd/cosmovisor/main.go b/tools/cosmovisor/cmd/cosmovisor/main.go index 8ed5a2e9f9ed..294dd66f7165 100644 --- a/tools/cosmovisor/cmd/cosmovisor/main.go +++ b/tools/cosmovisor/cmd/cosmovisor/main.go @@ -6,20 +6,7 @@ import ( ) func main() { - // error logger used only during configuration phase - cfg, _ := getConfigForInitCmd() - logger := cfg.Logger(os.Stderr) - if err := NewRootCmd().ExecuteContext(context.Background()); err != nil { - if errMulti, ok := err.(interface{ Unwrap() []error }); ok { - err := errMulti.Unwrap() - for _, e := range err { - logger.Error("", "error", e) - } - } else { - logger.Error("", "error", err) - } - os.Exit(1) } } diff --git a/tools/cosmovisor/cmd/cosmovisor/run.go b/tools/cosmovisor/cmd/cosmovisor/run.go index 6aa938c7d780..0e1513cf6766 100644 --- a/tools/cosmovisor/cmd/cosmovisor/run.go +++ b/tools/cosmovisor/cmd/cosmovisor/run.go @@ -13,7 +13,7 @@ var runCmd = &cobra.Command{ Use: "run", Short: "Run an APP command.", Long: `Run an APP command. This command is intended to be used by the cosmovisor binary. -Provide cosmovisor config file path in command args or set env variables to load configuration. +Provide '--cosmovisor-config' file path in command args or set env variables to load configuration. `, SilenceUsage: true, DisableFlagParsing: true, diff --git a/tools/cosmovisor/go.mod b/tools/cosmovisor/go.mod index c404d40619b3..fe89a5c39c17 100644 --- a/tools/cosmovisor/go.mod +++ b/tools/cosmovisor/go.mod @@ -1,8 +1,6 @@ module cosmossdk.io/tools/cosmovisor -go 1.22.2 - -toolchain go1.22.4 +go 1.22.4 require ( cosmossdk.io/log v1.4.0 diff --git a/tools/cosmovisor/process.go b/tools/cosmovisor/process.go index dfda812efe49..c288515005fd 100644 --- a/tools/cosmovisor/process.go +++ b/tools/cosmovisor/process.go @@ -28,7 +28,7 @@ type Launcher struct { } func NewLauncher(logger log.Logger, cfg *Config) (Launcher, error) { - fw, err := newUpgradeFileWatcher(cfg, logger) + fw, err := newUpgradeFileWatcher(cfg) if err != nil { return Launcher{}, err } diff --git a/tools/cosmovisor/process_test.go b/tools/cosmovisor/process_test.go index aa587042668c..09658f265cdb 100644 --- a/tools/cosmovisor/process_test.go +++ b/tools/cosmovisor/process_test.go @@ -13,259 +13,244 @@ import ( "time" "github.com/stretchr/testify/require" - "github.com/stretchr/testify/suite" "cosmossdk.io/log" "cosmossdk.io/tools/cosmovisor" upgradetypes "cosmossdk.io/x/upgrade/types" ) -type processTestSuite struct { - suite.Suite -} - -func TestProcessTestSuite(t *testing.T) { - suite.Run(t, new(processTestSuite)) -} - // TestLaunchProcess will try running the script a few times and watch upgrades work properly // and args are passed through -func (s *processTestSuite) TestLaunchProcess() { +func TestLaunchProcess(t *testing.T) { // binaries from testdata/validate directory - require := s.Require() - home := copyTestData(s.T(), "validate") + home := copyTestData(t, "validate") cfg := &cosmovisor.Config{Home: home, Name: "dummyd", PollInterval: 20, UnsafeSkipBackup: true} - logger := log.NewTestLogger(s.T()).With(log.ModuleKey, "cosmosvisor") + logger := log.NewTestLogger(t).With(log.ModuleKey, "cosmosvisor") // should run the genesis binary and produce expected output stdout, stderr := newBuffer(), newBuffer() currentBin, err := cfg.CurrentBin() - require.NoError(err) - require.Equal(cfg.GenesisBin(), currentBin) + require.NoError(t, err) + require.Equal(t, cfg.GenesisBin(), currentBin) launcher, err := cosmovisor.NewLauncher(logger, cfg) - require.NoError(err) + require.NoError(t, err) upgradeFile := cfg.UpgradeInfoFilePath() args := []string{"foo", "bar", "1234", upgradeFile} doUpgrade, err := launcher.Run(args, stdout, stderr) - require.NoError(err) - require.True(doUpgrade) - require.Equal("", stderr.String()) - require.Equal(fmt.Sprintf("Genesis foo bar 1234 %s\nUPGRADE \"chain2\" NEEDED at height: 49: {}\n", upgradeFile), stdout.String()) + require.NoError(t, err) + require.True(t, doUpgrade) + require.Empty(t, stderr.String()) + require.Equal(t, fmt.Sprintf("Genesis foo bar 1234 %s\nUPGRADE \"chain2\" NEEDED at height: 49: {}\n", upgradeFile), stdout.String()) // ensure this is upgraded now and produces new output currentBin, err = cfg.CurrentBin() - require.NoError(err) + require.NoError(t, err) - require.Equal(cfg.UpgradeBin("chain2"), currentBin) + require.Equal(t, cfg.UpgradeBin("chain2"), currentBin) args = []string{"second", "run", "--verbose"} stdout.Reset() stderr.Reset() doUpgrade, err = launcher.Run(args, stdout, stderr) - require.NoError(err) - require.False(doUpgrade) - require.Equal("", stderr.String()) - require.Equal("Chain 2 is live!\nArgs: second run --verbose\nFinished successfully\n", stdout.String()) + require.NoError(t, err) + require.False(t, doUpgrade) + require.Empty(t, stderr.String()) + require.Equal(t, "Chain 2 is live!\nArgs: second run --verbose\nFinished successfully\n", stdout.String()) // ended without other upgrade - require.Equal(cfg.UpgradeBin("chain2"), currentBin) + require.Equal(t, cfg.UpgradeBin("chain2"), currentBin) } // TestPlanDisableRecase will test upgrades without lower case plan names -func (s *processTestSuite) TestPlanDisableRecase() { +func TestPlanDisableRecase(t *testing.T) { // binaries from testdata/validate directory - require := s.Require() - home := copyTestData(s.T(), "norecase") + home := copyTestData(t, "norecase") cfg := &cosmovisor.Config{Home: home, Name: "dummyd", PollInterval: 20, UnsafeSkipBackup: true, DisableRecase: true} - logger := log.NewTestLogger(s.T()).With(log.ModuleKey, "cosmosvisor") + logger := log.NewTestLogger(t).With(log.ModuleKey, "cosmosvisor") // should run the genesis binary and produce expected output stdout, stderr := newBuffer(), newBuffer() currentBin, err := cfg.CurrentBin() - require.NoError(err) - require.Equal(cfg.GenesisBin(), currentBin) + require.NoError(t, err) + require.Equal(t, cfg.GenesisBin(), currentBin) launcher, err := cosmovisor.NewLauncher(logger, cfg) - require.NoError(err) + require.NoError(t, err) upgradeFile := cfg.UpgradeInfoFilePath() args := []string{"foo", "bar", "1234", upgradeFile} doUpgrade, err := launcher.Run(args, stdout, stderr) - require.NoError(err) - require.True(doUpgrade) - require.Equal("", stderr.String()) - require.Equal(fmt.Sprintf("Genesis foo bar 1234 %s\nUPGRADE \"Chain2\" NEEDED at height: 49: {}\n", upgradeFile), stdout.String()) + require.NoError(t, err) + require.True(t, doUpgrade) + require.Empty(t, stderr.String()) + require.Equal(t, fmt.Sprintf("Genesis foo bar 1234 %s\nUPGRADE \"Chain2\" NEEDED at height: 49: {}\n", upgradeFile), stdout.String()) // ensure this is upgraded now and produces new output currentBin, err = cfg.CurrentBin() - require.NoError(err) + require.NoError(t, err) - require.Equal(cfg.UpgradeBin("Chain2"), currentBin) + require.Equal(t, cfg.UpgradeBin("Chain2"), currentBin) args = []string{"second", "run", "--verbose"} stdout.Reset() stderr.Reset() doUpgrade, err = launcher.Run(args, stdout, stderr) - require.NoError(err) - require.False(doUpgrade) - require.Equal("", stderr.String()) - require.Equal("Chain 2 is live!\nArgs: second run --verbose\nFinished successfully\n", stdout.String()) + require.NoError(t, err) + require.False(t, doUpgrade) + require.Empty(t, stderr.String()) + require.Equal(t, "Chain 2 is live!\nArgs: second run --verbose\nFinished successfully\n", stdout.String()) // ended without other upgrade - require.Equal(cfg.UpgradeBin("Chain2"), currentBin) + require.Equal(t, cfg.UpgradeBin("Chain2"), currentBin) } -func (s *processTestSuite) TestLaunchProcessWithRestartDelay() { +func TestLaunchProcessWithRestartDelay(t *testing.T) { // binaries from testdata/validate directory - require := s.Require() - home := copyTestData(s.T(), "validate") + home := copyTestData(t, "validate") cfg := &cosmovisor.Config{Home: home, Name: "dummyd", RestartDelay: 5 * time.Second, PollInterval: 20, UnsafeSkipBackup: true} - logger := log.NewTestLogger(s.T()).With(log.ModuleKey, "cosmosvisor") + logger := log.NewTestLogger(t).With(log.ModuleKey, "cosmosvisor") // should run the genesis binary and produce expected output stdout, stderr := newBuffer(), newBuffer() currentBin, err := cfg.CurrentBin() - require.NoError(err) - require.Equal(cfg.GenesisBin(), currentBin) + require.NoError(t, err) + require.Equal(t, cfg.GenesisBin(), currentBin) launcher, err := cosmovisor.NewLauncher(logger, cfg) - require.NoError(err) + require.NoError(t, err) upgradeFile := cfg.UpgradeInfoFilePath() start := time.Now() doUpgrade, err := launcher.Run([]string{"foo", "bar", "1234", upgradeFile}, stdout, stderr) - require.NoError(err) - require.True(doUpgrade) + require.NoError(t, err) + require.True(t, doUpgrade) // may not be the best way but the fastest way to check we meet the delay // in addition to comparing both the runtime of this test and TestLaunchProcess in addition if time.Since(start) < cfg.RestartDelay { - require.FailNow("restart delay not met") + require.FailNow(t, "restart delay not met") } } // TestPlanShutdownGrace will test upgrades without lower case plan names -func (s *processTestSuite) TestPlanShutdownGrace() { +func TestPlanShutdownGrace(t *testing.T) { // binaries from testdata/validate directory - require := s.Require() - home := copyTestData(s.T(), "dontdie") + home := copyTestData(t, "dontdie") cfg := &cosmovisor.Config{Home: home, Name: "dummyd", PollInterval: 20, UnsafeSkipBackup: true, ShutdownGrace: 2 * time.Second} - logger := log.NewTestLogger(s.T()).With(log.ModuleKey, "cosmosvisor") + logger := log.NewTestLogger(t).With(log.ModuleKey, "cosmosvisor") // should run the genesis binary and produce expected output stdout, stderr := newBuffer(), newBuffer() currentBin, err := cfg.CurrentBin() - require.NoError(err) - require.Equal(cfg.GenesisBin(), currentBin) + require.NoError(t, err) + require.Equal(t, cfg.GenesisBin(), currentBin) launcher, err := cosmovisor.NewLauncher(logger, cfg) - require.NoError(err) + require.NoError(t, err) upgradeFile := cfg.UpgradeInfoFilePath() args := []string{"foo", "bar", "1234", upgradeFile} doUpgrade, err := launcher.Run(args, stdout, stderr) - require.NoError(err) - require.True(doUpgrade) - require.Equal("", stderr.String()) - require.Equal(fmt.Sprintf("Genesis foo bar 1234 %s\nUPGRADE \"Chain2\" NEEDED at height: 49: {}\nWARN Need Flush\nFlushed\n", upgradeFile), stdout.String()) + require.NoError(t, err) + require.True(t, doUpgrade) + require.Empty(t, stderr.String()) + require.Equal(t, fmt.Sprintf("Genesis foo bar 1234 %s\nUPGRADE \"Chain2\" NEEDED at height: 49: {}\nWARN Need Flush\nFlushed\n", upgradeFile), stdout.String()) // ensure this is upgraded now and produces new output currentBin, err = cfg.CurrentBin() - require.NoError(err) + require.NoError(t, err) - require.Equal(cfg.UpgradeBin("chain2"), currentBin) + require.Equal(t, cfg.UpgradeBin("chain2"), currentBin) args = []string{"second", "run", "--verbose"} stdout.Reset() stderr.Reset() doUpgrade, err = launcher.Run(args, stdout, stderr) - require.NoError(err) - require.False(doUpgrade) - require.Equal("", stderr.String()) - require.Equal("Chain 2 is live!\nArgs: second run --verbose\nFinished successfully\n", stdout.String()) + require.NoError(t, err) + require.False(t, doUpgrade) + require.Empty(t, stderr.String()) + require.Equal(t, "Chain 2 is live!\nArgs: second run --verbose\nFinished successfully\n", stdout.String()) // ended without other upgrade - require.Equal(cfg.UpgradeBin("chain2"), currentBin) + require.Equal(t, cfg.UpgradeBin("chain2"), currentBin) } // TestLaunchProcess will try running the script a few times and watch upgrades work properly // and args are passed through -func (s *processTestSuite) TestLaunchProcessWithDownloads() { +func TestLaunchProcessWithDownloads(t *testing.T) { // test case upgrade path (binaries from testdata/download directory): // genesis -> chain2-zip_bin // chain2-zip_bin -> ref_to_chain3-zip_dir.json = (json for the next download instructions) -> chain3-zip_dir // chain3-zip_dir - doesn't upgrade - require := s.Require() - home := copyTestData(s.T(), "download") + home := copyTestData(t, "download") cfg := &cosmovisor.Config{Home: home, Name: "autod", AllowDownloadBinaries: true, PollInterval: 100, UnsafeSkipBackup: true} - logger := log.NewTestLogger(s.T()).With(log.ModuleKey, "cosmovisor") + logger := log.NewTestLogger(t).With(log.ModuleKey, "cosmovisor") upgradeFilename := cfg.UpgradeInfoFilePath() // should run the genesis binary and produce expected output currentBin, err := cfg.CurrentBin() - require.NoError(err) - require.Equal(cfg.GenesisBin(), currentBin) + require.NoError(t, err) + require.Equal(t, cfg.GenesisBin(), currentBin) launcher, err := cosmovisor.NewLauncher(logger, cfg) - require.NoError(err) + require.NoError(t, err) stdout, stderr := newBuffer(), newBuffer() args := []string{"some", "args", upgradeFilename} doUpgrade, err := launcher.Run(args, stdout, stderr) - require.NoError(err) - require.True(doUpgrade) - require.Equal("", stderr.String()) - require.Equal("Genesis autod. Args: some args "+upgradeFilename+"\n"+`ERROR: UPGRADE "chain2" NEEDED at height: 49: zip_binary`+"\n", stdout.String()) + require.NoError(t, err) + require.True(t, doUpgrade) + require.Empty(t, stderr.String()) + require.Equal(t, "Genesis autod. Args: some args "+upgradeFilename+"\n"+`ERROR: UPGRADE "chain2" NEEDED at height: 49: zip_binary`+"\n", stdout.String()) currentBin, err = cfg.CurrentBin() - require.NoError(err) - require.Equal(cfg.UpgradeBin("chain2"), currentBin) + require.NoError(t, err) + require.Equal(t, cfg.UpgradeBin("chain2"), currentBin) // start chain2 stdout.Reset() stderr.Reset() args = []string{"run", "--fast", upgradeFilename} doUpgrade, err = launcher.Run(args, stdout, stderr) - require.NoError(err) + require.NoError(t, err) - require.Equal("", stderr.String()) - require.Equal("Chain 2 from zipped binary\nArgs: run --fast "+upgradeFilename+"\n"+`ERROR: UPGRADE "chain3" NEEDED at height: 936: ref_to_chain3-zip_dir.json module=main`+"\n", stdout.String()) + require.Empty(t, stderr.String()) + require.Equal(t, "Chain 2 from zipped binary\nArgs: run --fast "+upgradeFilename+"\n"+`ERROR: UPGRADE "chain3" NEEDED at height: 936: ref_to_chain3-zip_dir.json module=main`+"\n", stdout.String()) // ended with one more upgrade - require.True(doUpgrade) + require.True(t, doUpgrade) currentBin, err = cfg.CurrentBin() - require.NoError(err) - require.Equal(cfg.UpgradeBin("chain3"), currentBin) + require.NoError(t, err) + require.Equal(t, cfg.UpgradeBin("chain3"), currentBin) // run the last chain args = []string{"end", "--halt", upgradeFilename} stdout.Reset() stderr.Reset() doUpgrade, err = launcher.Run(args, stdout, stderr) - require.NoError(err) - require.False(doUpgrade) - require.Equal("", stderr.String()) - require.Equal("Chain 3 from zipped directory\nArgs: end --halt "+upgradeFilename+"\n", stdout.String()) + require.NoError(t, err) + require.False(t, doUpgrade) + require.Empty(t, stderr.String()) + require.Equal(t, "Chain 3 from zipped directory\nArgs: end --halt "+upgradeFilename+"\n", stdout.String()) // and this doesn't upgrade currentBin, err = cfg.CurrentBin() - require.NoError(err) - require.Equal(cfg.UpgradeBin("chain3"), currentBin) + require.NoError(t, err) + require.Equal(t, cfg.UpgradeBin("chain3"), currentBin) } // TestLaunchProcessWithDownloadsAndMissingPreupgrade will try running the script a few times and watch upgrades work properly // and args are passed through -func (s *processTestSuite) TestLaunchProcessWithDownloadsAndMissingPreupgrade() { +func TestLaunchProcessWithDownloadsAndMissingPreupgrade(t *testing.T) { // test case upgrade path (binaries from testdata/download directory): // genesis -> chain2-zip_bin // chain2-zip_bin -> ref_to_chain3-zip_dir.json = (json for the next download instructions) -> chain3-zip_dir // chain3-zip_dir - doesn't upgrade - require := s.Require() - home := copyTestData(s.T(), "download") + home := copyTestData(t, "download") cfg := &cosmovisor.Config{ Home: home, Name: "autod", @@ -274,34 +259,33 @@ func (s *processTestSuite) TestLaunchProcessWithDownloadsAndMissingPreupgrade() UnsafeSkipBackup: true, CustomPreUpgrade: "missing.sh", } - logger := log.NewTestLogger(s.T()).With(log.ModuleKey, "cosmovisor") + logger := log.NewTestLogger(t).With(log.ModuleKey, "cosmovisor") upgradeFilename := cfg.UpgradeInfoFilePath() // should run the genesis binary and produce expected output currentBin, err := cfg.CurrentBin() - require.NoError(err) - require.Equal(cfg.GenesisBin(), currentBin) + require.NoError(t, err) + require.Equal(t, cfg.GenesisBin(), currentBin) launcher, err := cosmovisor.NewLauncher(logger, cfg) - require.NoError(err) + require.NoError(t, err) // Missing Preupgrade Script stdout, stderr := newBuffer(), newBuffer() args := []string{"some", "args", upgradeFilename} _, err = launcher.Run(args, stdout, stderr) - require.ErrorContains(err, "missing.sh") - require.ErrorIs(err, fs.ErrNotExist) + require.ErrorContains(t, err, "missing.sh") + require.ErrorIs(t, err, fs.ErrNotExist) } // TestLaunchProcessWithDownloadsAndPreupgrade will try running the script a few times and watch upgrades work properly // and args are passed through -func (s *processTestSuite) TestLaunchProcessWithDownloadsAndPreupgrade() { +func TestLaunchProcessWithDownloadsAndPreupgrade(t *testing.T) { // test case upgrade path (binaries from testdata/download directory): // genesis -> chain2-zip_bin // chain2-zip_bin -> ref_to_chain3-zip_dir.json = (json for the next download instructions) -> chain3-zip_dir // chain3-zip_dir - doesn't upgrade - require := s.Require() - home := copyTestData(s.T(), "download") + home := copyTestData(t, "download") cfg := &cosmovisor.Config{ Home: home, Name: "autod", @@ -316,58 +300,58 @@ func (s *processTestSuite) TestLaunchProcessWithDownloadsAndPreupgrade() { // should run the genesis binary and produce expected output currentBin, err := cfg.CurrentBin() - require.NoError(err) - require.Equal(cfg.GenesisBin(), currentBin) + require.NoError(t, err) + require.Equal(t, cfg.GenesisBin(), currentBin) launcher, err := cosmovisor.NewLauncher(logger, cfg) - require.NoError(err) + require.NoError(t, err) stdout, stderr := newBuffer(), newBuffer() args := []string{"some", "args", upgradeFilename} doUpgrade, err := launcher.Run(args, stdout, stderr) - require.NoError(err) - require.True(doUpgrade) - require.Equal("", stderr.String()) - require.Equal("Genesis autod. Args: some args "+upgradeFilename+"\n"+`ERROR: UPGRADE "chain2" NEEDED at height: 49: zip_binary`+"\n", stdout.String()) + require.NoError(t, err) + require.True(t, doUpgrade) + require.Empty(t, stderr.String()) + require.Equal(t, "Genesis autod. Args: some args "+upgradeFilename+"\n"+`ERROR: UPGRADE "chain2" NEEDED at height: 49: zip_binary`+"\n", stdout.String()) currentBin, err = cfg.CurrentBin() - require.NoError(err) - require.Equal(cfg.UpgradeBin("chain2"), currentBin) + require.NoError(t, err) + require.Equal(t, cfg.UpgradeBin("chain2"), currentBin) // should have preupgrade.sh results - require.FileExists(filepath.Join(home, "upgrade_name_chain2_height_49")) + require.FileExists(t, filepath.Join(home, "upgrade_name_chain2_height_49")) // start chain2 stdout.Reset() stderr.Reset() args = []string{"run", "--fast", upgradeFilename} doUpgrade, err = launcher.Run(args, stdout, stderr) - require.NoError(err) + require.NoError(t, err) - require.Equal("", stderr.String()) - require.Equal("Chain 2 from zipped binary\nArgs: run --fast "+upgradeFilename+"\n"+`ERROR: UPGRADE "chain3" NEEDED at height: 936: ref_to_chain3-zip_dir.json module=main`+"\n", stdout.String()) + require.Empty(t, stderr.String()) + require.Equal(t, "Chain 2 from zipped binary\nArgs: run --fast "+upgradeFilename+"\n"+`ERROR: UPGRADE "chain3" NEEDED at height: 936: ref_to_chain3-zip_dir.json module=main`+"\n", stdout.String()) // ended with one more upgrade - require.True(doUpgrade) + require.True(t, doUpgrade) currentBin, err = cfg.CurrentBin() - require.NoError(err) - require.Equal(cfg.UpgradeBin("chain3"), currentBin) + require.NoError(t, err) + require.Equal(t, cfg.UpgradeBin("chain3"), currentBin) // should have preupgrade.sh results - require.FileExists(filepath.Join(home, "upgrade_name_chain3_height_936")) + require.FileExists(t, filepath.Join(home, "upgrade_name_chain3_height_936")) // run the last chain args = []string{"end", "--halt", upgradeFilename} stdout.Reset() stderr.Reset() doUpgrade, err = launcher.Run(args, stdout, stderr) - require.NoError(err) - require.False(doUpgrade) - require.Equal("", stderr.String()) - require.Equal("Chain 3 from zipped directory\nArgs: end --halt "+upgradeFilename+"\n", stdout.String()) + require.NoError(t, err) + require.False(t, doUpgrade) + require.Empty(t, stderr.String()) + require.Equal(t, "Chain 3 from zipped directory\nArgs: end --halt "+upgradeFilename+"\n", stdout.String()) // and this doesn't upgrade currentBin, err = cfg.CurrentBin() - require.NoError(err) - require.Equal(cfg.UpgradeBin("chain3"), currentBin) + require.NoError(t, err) + require.Equal(t, cfg.UpgradeBin("chain3"), currentBin) } // TestSkipUpgrade tests heights that are identified to be skipped and return if upgrade height matches the skip heights diff --git a/tools/cosmovisor/scanner.go b/tools/cosmovisor/scanner.go index 55f9df6e078e..a5bfdf2cc05c 100644 --- a/tools/cosmovisor/scanner.go +++ b/tools/cosmovisor/scanner.go @@ -9,15 +9,16 @@ import ( "path/filepath" "strconv" "strings" + "testing" "time" - "cosmossdk.io/log" upgradetypes "cosmossdk.io/x/upgrade/types" ) type fileWatcher struct { - filename string // full path to a watched file - interval time.Duration + deamonHome string + filename string // full path to a watched file + interval time.Duration currentBin string currentInfo upgradetypes.Plan @@ -30,7 +31,7 @@ type fileWatcher struct { disableRecase bool } -func newUpgradeFileWatcher(cfg *Config, logger log.Logger) (*fileWatcher, error) { +func newUpgradeFileWatcher(cfg *Config) (*fileWatcher, error) { filename := cfg.UpgradeInfoFilePath() if filename == "" { return nil, errors.New("filename undefined") @@ -52,6 +53,7 @@ func newUpgradeFileWatcher(cfg *Config, logger log.Logger) (*fileWatcher, error) } return &fileWatcher{ + deamonHome: cfg.Home, currentBin: bin, filename: filenameAbs, interval: cfg.PollInterval, @@ -111,10 +113,18 @@ func (fw *fileWatcher) CheckUpdate(currentUpgrade upgradetypes.Plan) bool { return false } + // no update if the file already exists and has not been modified if !stat.ModTime().After(fw.lastModTime) { return false } + // if fw.lastModTime.IsZero() { // check https://github.com/cosmos/cosmos-sdk/issues/21086 + // // first initialization or daemon restart while upgrading-info.json exists. + // // it could be that it was just created and not fully written to disk. + // // wait tiniest bit of time to allow the file to be fully written. + // time.Sleep(2 * time.Millisecond) + // } + info, err := parseUpgradeInfoFile(fw.filename, fw.disableRecase) if err != nil { panic(fmt.Errorf("failed to parse upgrade info file: %w", err)) @@ -153,14 +163,11 @@ func (fw *fileWatcher) CheckUpdate(currentUpgrade upgradetypes.Plan) bool { // checkHeight checks if the current block height func (fw *fileWatcher) checkHeight() (int64, error) { - // TODO(@julienrbrt) use `if !testing.Testing()` from Go 1.22 - // The tests from `process_test.go`, which run only on linux, are failing when using `autod` that is a bash script. - // In production, the binary will always be an application with a status command, but in tests it isn't not. - if strings.HasSuffix(os.Args[0], ".test") { + if testing.Testing() { // we cannot test the command in the test environment return 0, nil } - result, err := exec.Command(fw.currentBin, "status").Output() //nolint:gosec // we want to execute the status command + result, err := exec.Command(fw.currentBin, "status", "--home", fw.deamonHome).CombinedOutput() //nolint:gosec // we want to execute the status command if err != nil { return 0, err } @@ -168,6 +175,9 @@ func (fw *fileWatcher) checkHeight() (int64, error) { type response struct { SyncInfo struct { LatestBlockHeight string `json:"latest_block_height"` + } `json:"sync_info"` + AnotherCasingSyncInfo struct { + LatestBlockHeight string `json:"latest_block_height"` } `json:"SyncInfo"` } @@ -176,11 +186,13 @@ func (fw *fileWatcher) checkHeight() (int64, error) { return 0, err } - if resp.SyncInfo.LatestBlockHeight == "" { - return 0, errors.New("latest block height is empty") + if resp.SyncInfo.LatestBlockHeight != "" { + return strconv.ParseInt(resp.SyncInfo.LatestBlockHeight, 10, 64) + } else if resp.AnotherCasingSyncInfo.LatestBlockHeight != "" { + return strconv.ParseInt(resp.AnotherCasingSyncInfo.LatestBlockHeight, 10, 64) } - return strconv.ParseInt(resp.SyncInfo.LatestBlockHeight, 10, 64) + return 0, errors.New("latest block height is empty") } func parseUpgradeInfoFile(filename string, disableRecase bool) (upgradetypes.Plan, error) { From df3b035dd876fff8375beb4380d4cd063361f3fa Mon Sep 17 00:00:00 2001 From: cool-developer <51834436+cool-develope@users.noreply.github.com> Date: Mon, 12 Aug 2024 16:40:28 -0400 Subject: [PATCH 3/6] chore(core/store): Batch interface alias (#21262) --- core/store/store.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/store/store.go b/core/store/store.go index 5a522626d743..164bcca6112e 100644 --- a/core/store/store.go +++ b/core/store/store.go @@ -35,7 +35,7 @@ type KVStore interface { // // As with KVStore, given keys and values should be considered read-only, and must not be modified after // passing them to the batch. -type Batch interface { +type Batch = interface { // Set sets a key/value pair. // CONTRACT: key, value readonly []byte Set(key, value []byte) error From 431b52309c80d43e53f55fd7c833af2ec71bebdf Mon Sep 17 00:00:00 2001 From: Aaron Craelius Date: Mon, 12 Aug 2024 17:04:23 -0400 Subject: [PATCH 4/6] refactor(schema)!: move view interfaces from testing to schema (#21204) --- schema/indexer/indexer.go | 21 ++++--- schema/testing/appdatasim/app_data.go | 7 ++- schema/testing/appdatasim/diff.go | 30 ++++----- .../testdata/app_sim_example_schema.txt | 2 +- .../appdatasim/testdata/diff_example.txt | 10 +-- schema/testing/statesim/app.go | 21 ++++--- schema/testing/statesim/app_diff.go | 52 ++++++++++------ schema/testing/statesim/module.go | 26 +++++--- schema/testing/statesim/module_diff.go | 52 +++++++++------- schema/testing/statesim/object_coll.go | 13 ++-- schema/testing/statesim/object_coll_diff.go | 61 ++++++++++--------- schema/view/app.go | 15 +++++ schema/view/app_data.go | 16 +++++ schema/view/doc.go | 2 + schema/view/module.go | 23 +++++++ schema/view/object.go | 27 ++++++++ 16 files changed, 254 insertions(+), 124 deletions(-) create mode 100644 schema/view/app.go create mode 100644 schema/view/app_data.go create mode 100644 schema/view/doc.go create mode 100644 schema/view/module.go create mode 100644 schema/view/object.go diff --git a/schema/indexer/indexer.go b/schema/indexer/indexer.go index ba3d0db704fa..57ada8bb80c1 100644 --- a/schema/indexer/indexer.go +++ b/schema/indexer/indexer.go @@ -5,6 +5,7 @@ import ( "cosmossdk.io/schema/appdata" "cosmossdk.io/schema/logutil" + "cosmossdk.io/schema/view" ) // Config species the configuration passed to an indexer initialization function. @@ -55,10 +56,11 @@ type InitParams struct { Config Config // Context is the context that the indexer should use to listen for a shutdown signal via Context.Done(). Other - // parameters may also be passed through context from the app if necessary. + // parameters may also be passed through context from the app if necessary. It is expected to be non-nil. Context context.Context - // Logger is a logger the indexer can use to write log messages. + // Logger is a logger the indexer can use to write log messages. It may be nil if the indexer does not need + // to write logs. Logger logutil.Logger } @@ -67,12 +69,13 @@ type InitResult struct { // Listener is the indexer's app data listener. Listener appdata.Listener - // LastBlockPersisted indicates the last block that the indexer persisted (if it is persisting data). It - // should be 0 if the indexer has no data stored and wants to start syncing state. It should be -1 if the indexer - // does not care to persist state at all and is just listening for some other streaming purpose. If the indexer - // has persisted state and has missed some blocks, a runtime error will occur to prevent the indexer from continuing - // in an invalid state. If an indexer starts indexing after a chain's genesis (returning 0), the indexer manager - // will attempt to perform a catch-up sync of state. Historical events will not be replayed, but an accurate + // View is a view of indexed data that indexers can provide. It is optional and may be nil. + // If it is provided it can be used for automated testing and other purposes. + // At indexer start-up, the block number returned by the view will be used to determine the + // starting block for the indexer. If the block number is 0, the indexer manager will attempt + // to perform a catch-up sync of state. Historical events will not be replayed, but an accurate // representation of the current state at the height at which indexing began can be reproduced. - LastBlockPersisted int64 + // If the block number is non-zero but does not match the current chain height, a runtime error + // will occur because this is an unsafe condition that indicates lost data. + View view.AppData } diff --git a/schema/testing/appdatasim/app_data.go b/schema/testing/appdatasim/app_data.go index db82d285de5a..2f6138bfe824 100644 --- a/schema/testing/appdatasim/app_data.go +++ b/schema/testing/appdatasim/app_data.go @@ -9,6 +9,7 @@ import ( "cosmossdk.io/schema" "cosmossdk.io/schema/appdata" "cosmossdk.io/schema/testing/statesim" + "cosmossdk.io/schema/view" ) // Options are the options for creating an app data simulator. @@ -151,11 +152,11 @@ func (a *Simulator) ProcessPacket(packet appdata.Packet) error { } // AppState returns the current app state backing the simulator. -func (a *Simulator) AppState() statesim.AppState { +func (a *Simulator) AppState() view.AppState { return a.state } // BlockNum returns the current block number of the simulator. -func (a *Simulator) BlockNum() uint64 { - return a.blockNum +func (a *Simulator) BlockNum() (uint64, error) { + return a.blockNum, nil } diff --git a/schema/testing/appdatasim/diff.go b/schema/testing/appdatasim/diff.go index 5896331d542a..339419e7d9b8 100644 --- a/schema/testing/appdatasim/diff.go +++ b/schema/testing/appdatasim/diff.go @@ -4,25 +4,15 @@ import ( "fmt" "cosmossdk.io/schema/testing/statesim" + "cosmossdk.io/schema/view" ) -// HasAppData defines an interface for things that hold app data include app state. -// If an indexer implements this then DiffAppData can be used to compare it with -// the Simulator state which also implements this. -type HasAppData interface { - // AppState returns the app state. - AppState() statesim.AppState - - // BlockNum returns the latest block number. - BlockNum() uint64 -} - // DiffAppData compares the app data of two objects that implement HasAppData. // This can be used by indexer to compare their state with the Simulator state // if the indexer implements HasAppData. // It returns a human-readable diff if the app data differs and the empty string // if they are the same. -func DiffAppData(expected, actual HasAppData) string { +func DiffAppData(expected, actual view.AppData) string { res := "" if stateDiff := statesim.DiffAppStates(expected.AppState(), actual.AppState()); stateDiff != "" { @@ -30,8 +20,20 @@ func DiffAppData(expected, actual HasAppData) string { res += stateDiff } - if expected.BlockNum() != actual.BlockNum() { - res += fmt.Sprintf("BlockNum: expected %d, got %d\n", expected.BlockNum(), actual.BlockNum()) + expectedBlock, err := expected.BlockNum() + if err != nil { + res += fmt.Sprintf("ERROR getting expected block num: %s\n", err) + return res + } + + actualBlock, err := actual.BlockNum() + if err != nil { + res += fmt.Sprintf("ERROR getting actual block num: %s\n", err) + return res + } + + if expectedBlock != actualBlock { + res += fmt.Sprintf("BlockNum: expected %d, got %d\n", expectedBlock, actualBlock) } return res diff --git a/schema/testing/appdatasim/testdata/app_sim_example_schema.txt b/schema/testing/appdatasim/testdata/app_sim_example_schema.txt index 32aa613514a2..117d557ba5a4 100644 --- a/schema/testing/appdatasim/testdata/app_sim_example_schema.txt +++ b/schema/testing/appdatasim/testdata/app_sim_example_schema.txt @@ -78,7 +78,7 @@ StartBlock: {6 } OnObjectUpdate: {"ModuleName":"test_cases","Updates":[{"TypeName":"TwoKeys","Key":["A𞥟",981],"Value":null,"Delete":false},{"TypeName":"ManyValues","Key":"ᵕ؏­􏿽A","Value":{"Value1":-317,"Value2":"AA==","Value3":-37.62890625,"Value4":232},"Delete":false}]} OnObjectUpdate: {"ModuleName":"all_kinds","Updates":[{"TypeName":"test_address","Key":"AACHBAjyAgFHOQAABo+PGAK3Bj7TwwBb/wAB3gE=","Value":{"valNotNull":"HBwBHAY6AAKO+UwDKRICAT0lgRRvCRvHFFoNAigBAUEDHoQUfB2qApRB/z41AAubARsBATQg3gCppQMAAQwHAQ=="},"Delete":false}]} OnObjectUpdate: {"ModuleName":"all_kinds","Updates":[{"TypeName":"test_decimal","Key":"9.5E+8","Value":["-2","88111430.0122412446"],"Delete":false}]} -OnObjectUpdate: {"ModuleName":"all_kinds","Updates":[{"TypeName":"test_uint8","Key":7,"Value":null,"Delete":true},{"TypeName":"test_time","Key":"1970-01-01T00:59:59.999999999+01:00","Value":["1970-01-01T01:00:00.000000001+01:00",null],"Delete":false}]} +OnObjectUpdate: {"ModuleName":"all_kinds","Updates":[{"TypeName":"test_uint8","Key":7,"Value":null,"Delete":true},{"TypeName":"test_time","Key":"1969-12-31T18:59:59.999999999-05:00","Value":["1969-12-31T19:00:00.000000001-05:00",null],"Delete":false}]} OnObjectUpdate: {"ModuleName":"test_cases","Updates":[{"TypeName":"RetainDeletions","Key":"൴~𝔶ٞ蹯a_ ᛮ!؋aض©-?","Value":{"Value2":""},"Delete":false}]} OnObjectUpdate: {"ModuleName":"all_kinds","Updates":[{"TypeName":"test_uint8","Key":14,"Value":{"valNotNull":116},"Delete":false},{"TypeName":"test_duration","Key":100403021838,"Value":[1547,null],"Delete":false}]} OnObjectUpdate: {"ModuleName":"all_kinds","Updates":[{"TypeName":"test_int64","Key":-34196421,"Value":[56,224549431],"Delete":false},{"TypeName":"test_bool","Key":true,"Value":{"valNotNull":true,"valNullable":null},"Delete":false}]} diff --git a/schema/testing/appdatasim/testdata/diff_example.txt b/schema/testing/appdatasim/testdata/diff_example.txt index 636e388937ee..fcdd45729de3 100644 --- a/schema/testing/appdatasim/testdata/diff_example.txt +++ b/schema/testing/appdatasim/testdata/diff_example.txt @@ -60,10 +60,10 @@ Module all_kinds Object key=š℠¼々¢~;-Ⱥ!˃a[ʰᾌ?{ᪧ৵%ᾯ¦〈: NOT FOUND Object Collection test_time OBJECT COUNT ERROR: expected 4, got 3 - Object key=1970-01-01 01:00:00.000000005 +0100 CET: NOT FOUND - Object key=1970-01-01 01:00:00.001598687 +0100 CET - valNotNull: expected 1970-01-01 01:00:00.007727197 +0100 CET, got 1970-01-01 01:00:00.034531678 +0100 CET - valNullable: expected 1970-01-01 01:00:00.000000484 +0100 CET, got 1970-01-01 01:00:00.000000033 +0100 CET + Object key=1969-12-31 19:00:00.000000005 -0500 EST: NOT FOUND + Object key=1969-12-31 19:00:00.001598687 -0500 EST + valNotNull: expected 1969-12-31 19:00:00.007727197 -0500 EST, got 1969-12-31 19:00:00.034531678 -0500 EST + valNullable: expected 1969-12-31 19:00:00.000000484 -0500 EST, got 1969-12-31 19:00:00.000000033 -0500 EST Object Collection test_uint16 OBJECT COUNT ERROR: expected 4, got 3 Object key=23712: NOT FOUND @@ -75,5 +75,5 @@ Module all_kinds Object Collection test_uint8 OBJECT COUNT ERROR: expected 3, got 2 Object key=1: NOT FOUND - Module test_cases: NOT FOUND + Module test_cases: actual module NOT FOUND BlockNum: expected 2, got 1 diff --git a/schema/testing/statesim/app.go b/schema/testing/statesim/app.go index 127af5431b9d..c3c7399acc2b 100644 --- a/schema/testing/statesim/app.go +++ b/schema/testing/statesim/app.go @@ -9,6 +9,7 @@ import ( "cosmossdk.io/schema" "cosmossdk.io/schema/appdata" + "cosmossdk.io/schema/view" ) // App is a collection of simulated module states corresponding to an app's schema for testing purposes. @@ -27,7 +28,7 @@ func NewApp(appSchema map[string]schema.ModuleSchema, options Options) *App { } for moduleName, moduleSchema := range appSchema { - moduleState := NewModule(moduleSchema, options) + moduleState := NewModule(moduleName, moduleSchema, options) app.moduleStates.Set(moduleName, moduleState) } @@ -62,7 +63,7 @@ func (a *App) InitializeModule(data appdata.ModuleInitializationData) error { return fmt.Errorf("module %s already initialized", data.ModuleName) } - a.moduleStates.Set(data.ModuleName, NewModule(data.Schema, a.options)) + a.moduleStates.Set(data.ModuleName, NewModule(data.ModuleName, data.Schema, a.options)) return nil } @@ -91,18 +92,22 @@ func (a *App) UpdateGen() *rapid.Generator[appdata.ObjectUpdateData] { } // GetModule returns the module state for the given module name. -func (a *App) GetModule(moduleName string) (ModuleState, bool) { - return a.moduleStates.Get(moduleName) +func (a *App) GetModule(moduleName string) (view.ModuleState, error) { + mod, ok := a.moduleStates.Get(moduleName) + if !ok { + return nil, nil + } + return mod, nil } // Modules iterates over all the module state instances in the app. -func (a *App) Modules(f func(moduleName string, modState ModuleState) bool) { +func (a *App) Modules(f func(modState view.ModuleState, err error) bool) { a.moduleStates.Scan(func(key string, value *Module) bool { - return f(key, value) + return f(value, nil) }) } // NumModules returns the number of modules in the app. -func (a *App) NumModules() int { - return a.moduleStates.Len() +func (a *App) NumModules() (int, error) { + return a.moduleStates.Len(), nil } diff --git a/schema/testing/statesim/app_diff.go b/schema/testing/statesim/app_diff.go index 6dfa222d066a..93735093a7db 100644 --- a/schema/testing/statesim/app_diff.go +++ b/schema/testing/statesim/app_diff.go @@ -1,32 +1,46 @@ package statesim -import "fmt" +import ( + "fmt" -// AppState defines an interface for things that represent application state in schema format. -type AppState interface { - // GetModule returns the module state for the given module name. - GetModule(moduleName string) (ModuleState, bool) - - // Modules iterates over all the module state instances in the app. - Modules(f func(moduleName string, modState ModuleState) bool) - - // NumModules returns the number of modules in the app. - NumModules() int -} + "cosmossdk.io/schema/view" +) // DiffAppStates compares the app state of two objects that implement AppState and returns a string with a diff if they // are different or the empty string if they are the same. -func DiffAppStates(expected, actual AppState) string { +func DiffAppStates(expected, actual view.AppState) string { res := "" - if expected.NumModules() != actual.NumModules() { - res += fmt.Sprintf("MODULE COUNT ERROR: expected %d, got %d\n", expected.NumModules(), actual.NumModules()) + expectNumModules, err := expected.NumModules() + if err != nil { + res += fmt.Sprintf("ERROR getting expected num modules: %s\n", err) + return res + } + + actualNumModules, err := actual.NumModules() + if err != nil { + res += fmt.Sprintf("ERROR getting actual num modules: %s\n", err) + return res + } + + if expectNumModules != actualNumModules { + res += fmt.Sprintf("MODULE COUNT ERROR: expected %d, got %d\n", expectNumModules, actualNumModules) } - expected.Modules(func(moduleName string, expectedMod ModuleState) bool { - actualMod, found := actual.GetModule(moduleName) - if !found { - res += fmt.Sprintf("Module %s: NOT FOUND\n", moduleName) + expected.Modules(func(expectedMod view.ModuleState, err error) bool { + if err != nil { + res += fmt.Sprintf("ERROR getting expected module: %s\n", err) + return true + } + + moduleName := expectedMod.ModuleName() + actualMod, err := actual.GetModule(moduleName) + if err != nil { + res += fmt.Sprintf("ERROR getting actual module: %s\n", err) + return true + } + if actualMod == nil { + res += fmt.Sprintf("Module %s: actual module NOT FOUND\n", moduleName) return true } diff --git a/schema/testing/statesim/module.go b/schema/testing/statesim/module.go index 6a33f19d5817..fd3f70b0fc61 100644 --- a/schema/testing/statesim/module.go +++ b/schema/testing/statesim/module.go @@ -8,17 +8,19 @@ import ( "pgregory.net/rapid" "cosmossdk.io/schema" + "cosmossdk.io/schema/view" ) // Module is a collection of object collections corresponding to a module's schema for testing purposes. type Module struct { + name string moduleSchema schema.ModuleSchema objectCollections *btree.Map[string, *ObjectCollection] updateGen *rapid.Generator[schema.ObjectUpdate] } // NewModule creates a new Module for the given module schema. -func NewModule(moduleSchema schema.ModuleSchema, options Options) *Module { +func NewModule(name string, moduleSchema schema.ModuleSchema, options Options) *Module { objectCollections := &btree.Map[string, *ObjectCollection]{} var objectTypeNames []string @@ -39,6 +41,7 @@ func NewModule(moduleSchema schema.ModuleSchema, options Options) *Module { }) return &Module{ + name: name, moduleSchema: moduleSchema, updateGen: updateGen, objectCollections: objectCollections, @@ -61,24 +64,33 @@ func (o *Module) UpdateGen() *rapid.Generator[schema.ObjectUpdate] { return o.updateGen } +// ModuleName returns the name of the module. +func (o *Module) ModuleName() string { + return o.name +} + // ModuleSchema returns the module schema for the module. func (o *Module) ModuleSchema() schema.ModuleSchema { return o.moduleSchema } // GetObjectCollection returns the object collection for the given object type. -func (o *Module) GetObjectCollection(objectType string) (ObjectCollectionState, bool) { - return o.objectCollections.Get(objectType) +func (o *Module) GetObjectCollection(objectType string) (view.ObjectCollection, error) { + obj, ok := o.objectCollections.Get(objectType) + if !ok { + return nil, nil + } + return obj, nil } // ObjectCollections iterates over all object collections in the module. -func (o *Module) ObjectCollections(f func(value ObjectCollectionState) bool) { +func (o *Module) ObjectCollections(f func(value view.ObjectCollection, err error) bool) { o.objectCollections.Scan(func(key string, value *ObjectCollection) bool { - return f(value) + return f(value, nil) }) } // NumObjectCollections returns the number of object collections in the module. -func (o *Module) NumObjectCollections() int { - return o.objectCollections.Len() +func (o *Module) NumObjectCollections() (int, error) { + return o.objectCollections.Len(), nil } diff --git a/schema/testing/statesim/module_diff.go b/schema/testing/statesim/module_diff.go index 0907f974dfd8..29ee19fb01a9 100644 --- a/schema/testing/statesim/module_diff.go +++ b/schema/testing/statesim/module_diff.go @@ -3,38 +3,44 @@ package statesim import ( "fmt" - "cosmossdk.io/schema" + "cosmossdk.io/schema/view" ) -// ModuleState defines an interface for things that represent module state in schema format. -type ModuleState interface { - // ModuleSchema returns the schema for the module. - ModuleSchema() schema.ModuleSchema - - // GetObjectCollection returns the object collection state for the given object type. - GetObjectCollection(objectType string) (ObjectCollectionState, bool) - - // ObjectCollections iterates over all the object collection states in the module. - ObjectCollections(f func(value ObjectCollectionState) bool) - - // NumObjectCollections returns the number of object collections in the module. - NumObjectCollections() int -} - // DiffModuleStates compares the module state of two objects that implement ModuleState and returns a string with a diff if they // are different or the empty string if they are the same. -func DiffModuleStates(expected, actual ModuleState) string { +func DiffModuleStates(expected, actual view.ModuleState) string { res := "" - if expected.NumObjectCollections() != actual.NumObjectCollections() { - res += fmt.Sprintf("OBJECT COLLECTION COUNT ERROR: expected %d, got %d\n", expected.NumObjectCollections(), actual.NumObjectCollections()) + expectedNumObjectCollections, err := expected.NumObjectCollections() + if err != nil { + res += fmt.Sprintf("ERROR getting expected num object collections: %s\n", err) + return res + } + + actualNumObjectCollections, err := actual.NumObjectCollections() + if err != nil { + res += fmt.Sprintf("ERROR getting actual num object collections: %s\n", err) + return res } - expected.ObjectCollections(func(expectedColl ObjectCollectionState) bool { + if expectedNumObjectCollections != actualNumObjectCollections { + res += fmt.Sprintf("OBJECT COLLECTION COUNT ERROR: expected %d, got %d\n", expectedNumObjectCollections, actualNumObjectCollections) + } + + expected.ObjectCollections(func(expectedColl view.ObjectCollection, err error) bool { + if err != nil { + res += fmt.Sprintf("ERROR getting expected object collection: %s\n", err) + return true + } + objTypeName := expectedColl.ObjectType().Name - actualColl, found := actual.GetObjectCollection(objTypeName) - if !found { - res += fmt.Sprintf("Object Collection %s: NOT FOUND\n", objTypeName) + actualColl, err := actual.GetObjectCollection(objTypeName) + if err != nil { + res += fmt.Sprintf("ERROR getting actual object collection: %s\n", err) + return true + } + if actualColl == nil { + res += fmt.Sprintf("Object Collection %s: actuall collection NOT FOUND\n", objTypeName) return true } diff --git a/schema/testing/statesim/object_coll.go b/schema/testing/statesim/object_coll.go index 56b09fe758b5..8531811de3c3 100644 --- a/schema/testing/statesim/object_coll.go +++ b/schema/testing/statesim/object_coll.go @@ -110,16 +110,17 @@ func (o *ObjectCollection) UpdateGen() *rapid.Generator[schema.ObjectUpdate] { // AllState iterates over the state of the collection by calling the given function with each item in // state represented as an object update. -func (o *ObjectCollection) AllState(f func(schema.ObjectUpdate) bool) { +func (o *ObjectCollection) AllState(f func(schema.ObjectUpdate, error) bool) { o.objects.Scan(func(_ string, v schema.ObjectUpdate) bool { - return f(v) + return f(v, nil) }) } // GetObject returns the object with the given key from the collection represented as an ObjectUpdate // itself. Deletions that are retained are returned as ObjectUpdate's with delete set to true. -func (o *ObjectCollection) GetObject(key any) (update schema.ObjectUpdate, found bool) { - return o.objects.Get(fmtObjectKey(o.objectType, key)) +func (o *ObjectCollection) GetObject(key interface{}) (update schema.ObjectUpdate, found bool, err error) { + update, ok := o.objects.Get(fmtObjectKey(o.objectType, key)) + return update, ok, nil } // ObjectType returns the object type of the collection. @@ -128,8 +129,8 @@ func (o *ObjectCollection) ObjectType() schema.ObjectType { } // Len returns the number of objects in the collection. -func (o *ObjectCollection) Len() int { - return o.objects.Len() +func (o *ObjectCollection) Len() (int, error) { + return o.objects.Len(), nil } func fmtObjectKey(objectType schema.ObjectType, key any) string { diff --git a/schema/testing/statesim/object_coll_diff.go b/schema/testing/statesim/object_coll_diff.go index 0a9be9f222d6..cfd33b0b2a40 100644 --- a/schema/testing/statesim/object_coll_diff.go +++ b/schema/testing/statesim/object_coll_diff.go @@ -6,46 +6,49 @@ import ( "cosmossdk.io/schema" schematesting "cosmossdk.io/schema/testing" + "cosmossdk.io/schema/view" ) -// ObjectCollectionState is the interface for the state of an object collection -// represented by ObjectUpdate's for an ObjectType. ObjectUpdates must not include -// ValueUpdates in the Value field. When ValueUpdates are applied they must be -// converted to individual value or array format depending on the number of fields in -// the value. For collections which retain deletions, ObjectUpdate's with the Delete -// field set to true should be returned with the latest Value still intact. -type ObjectCollectionState interface { - // ObjectType returns the object type for the collection. - ObjectType() schema.ObjectType - - // GetObject returns the object update for the given key if it exists. - GetObject(key any) (update schema.ObjectUpdate, found bool) - - // AllState iterates over the state of the collection by calling the given function with each item in - // state represented as an object update. - AllState(f func(schema.ObjectUpdate) bool) - - // Len returns the number of objects in the collection. - Len() int -} - // DiffObjectCollections compares the object collection state of two objects that implement ObjectCollectionState and returns a string with a diff if they // are different or the empty string if they are the same. -func DiffObjectCollections(expected, actual ObjectCollectionState) string { +func DiffObjectCollections(expected, actual view.ObjectCollection) string { res := "" - if expected.Len() != actual.Len() { - res += fmt.Sprintf("OBJECT COUNT ERROR: expected %d, got %d\n", expected.Len(), actual.Len()) + + expectedNumObjects, err := expected.Len() + if err != nil { + res += fmt.Sprintf("ERROR getting expected num objects: %s\n", err) + return res + } + + actualNumObjects, err := actual.Len() + if err != nil { + res += fmt.Sprintf("ERROR getting actual num objects: %s\n", err) + return res } - expected.AllState(func(expectedUpdate schema.ObjectUpdate) bool { - actualUpdate, found := actual.GetObject(expectedUpdate.Key) + if expectedNumObjects != actualNumObjects { + res += fmt.Sprintf("OBJECT COUNT ERROR: expected %d, got %d\n", expectedNumObjects, actualNumObjects) + } + + expected.AllState(func(expectedUpdate schema.ObjectUpdate, err error) bool { + if err != nil { + res += fmt.Sprintf("ERROR getting expected object: %s\n", err) + return true + } + + keyStr := fmtObjectKey(expected.ObjectType(), expectedUpdate.Key) + actualUpdate, found, err := actual.GetObject(expectedUpdate.Key) + if err != nil { + res += fmt.Sprintf("Object %s: ERROR: %v\n", keyStr, err) + return true + } if !found { - res += fmt.Sprintf("Object %s: NOT FOUND\n", fmtObjectKey(expected.ObjectType(), expectedUpdate.Key)) + res += fmt.Sprintf("Object %s: NOT FOUND\n", keyStr) return true } if expectedUpdate.Delete != actualUpdate.Delete { - res += fmt.Sprintf("Object %s: Deleted mismatch, expected %v, got %v\n", fmtObjectKey(expected.ObjectType(), expectedUpdate.Key), expectedUpdate.Delete, actualUpdate.Delete) + res += fmt.Sprintf("Object %s: Deleted mismatch, expected %v, got %v\n", keyStr, expectedUpdate.Delete, actualUpdate.Delete) } if expectedUpdate.Delete { @@ -55,7 +58,7 @@ func DiffObjectCollections(expected, actual ObjectCollectionState) string { valueDiff := schematesting.DiffObjectValues(expected.ObjectType().ValueFields, expectedUpdate.Value, actualUpdate.Value) if valueDiff != "" { res += "Object " - res += fmtObjectKey(expected.ObjectType(), expectedUpdate.Key) + res += keyStr res += "\n" res += indentAllLines(valueDiff) } diff --git a/schema/view/app.go b/schema/view/app.go new file mode 100644 index 000000000000..80f43b0bd701 --- /dev/null +++ b/schema/view/app.go @@ -0,0 +1,15 @@ +package view + +// AppState defines an interface for things that represent application state in schema format. +type AppState interface { + // GetModule returns the module state for the given module name. If the module does not exist, nil and no error + // should be returned. + GetModule(moduleName string) (ModuleState, error) + + // Modules iterates over all the module state instances in the app. If there is an error getting a module state, + // modState may be nil and err will be non-nil. + Modules(f func(modState ModuleState, err error) bool) + + // NumModules returns the number of modules in the app. + NumModules() (int, error) +} diff --git a/schema/view/app_data.go b/schema/view/app_data.go new file mode 100644 index 000000000000..3de86e421cad --- /dev/null +++ b/schema/view/app_data.go @@ -0,0 +1,16 @@ +package view + +// AppData is an interface which indexer data targets can implement to allow their app data including +// state, blocks, transactions and events to be queried. An app's state and event store can also implement +// this interface to provide an authoritative source of data for comparing with indexed data. +type AppData interface { + // BlockNum indicates the last block that was persisted. It should be 0 if the target has no data + // stored and wants to start syncing state. + // If an indexer starts indexing after a chain's genesis (returning 0), the indexer manager + // will attempt to perform a catch-up sync of state. Historical events will not be replayed, but an accurate + // representation of the current state at the height at which indexing began can be reproduced. + BlockNum() (uint64, error) + + // AppState returns the app state. If the view doesn't persist app state, nil should be returned. + AppState() AppState +} diff --git a/schema/view/doc.go b/schema/view/doc.go new file mode 100644 index 000000000000..e58cbf49eab5 --- /dev/null +++ b/schema/view/doc.go @@ -0,0 +1,2 @@ +// Package view defines interfaces for viewing the data stored in an indexer target or an app's original data store. +package view diff --git a/schema/view/module.go b/schema/view/module.go new file mode 100644 index 000000000000..41893d45b11c --- /dev/null +++ b/schema/view/module.go @@ -0,0 +1,23 @@ +package view + +import "cosmossdk.io/schema" + +// ModuleState defines an interface for things that represent module state in schema format. +type ModuleState interface { + // ModuleName returns the name of the module. + ModuleName() string + + // ModuleSchema returns the schema for the module. + ModuleSchema() schema.ModuleSchema + + // GetObjectCollection returns the object collection for the given object type. If the object collection + // does not exist, nil and no error should be returned + GetObjectCollection(objectType string) (ObjectCollection, error) + + // ObjectCollections iterates over all the object collections in the module. If there is an error getting an object + // collection, objColl may be nil and err will be non-nil. + ObjectCollections(f func(value ObjectCollection, err error) bool) + + // NumObjectCollections returns the number of object collections in the module. + NumObjectCollections() (int, error) +} diff --git a/schema/view/object.go b/schema/view/object.go new file mode 100644 index 000000000000..ac19edd6abb5 --- /dev/null +++ b/schema/view/object.go @@ -0,0 +1,27 @@ +package view + +import "cosmossdk.io/schema" + +// ObjectCollection is the interface for viewing the state of a collection of objects in a module +// represented by ObjectUpdate's for an ObjectType. ObjectUpdates must not include +// ValueUpdates in the Value field. When ValueUpdates are applied they must be +// converted to individual value or array format depending on the number of fields in +// the value. For collections which retain deletions, ObjectUpdate's with the Delete +// field set to true should be returned with the latest Value still intact. +type ObjectCollection interface { + // ObjectType returns the object type for the collection. + ObjectType() schema.ObjectType + + // GetObject returns the object update for the given key if it exists. And error should only be returned + // if there was an error getting the object update. If the object does not exist but there was no error, + // then found should be false and the error should be nil. + GetObject(key interface{}) (update schema.ObjectUpdate, found bool, err error) + + // AllState iterates over the state of the collection by calling the given function with each item in + // state represented as an object update. If there is an error getting an object update, the error will be + // non-nil and the object update should be empty. + AllState(f func(schema.ObjectUpdate, error) bool) + + // Len returns the number of objects in the collection. + Len() (int, error) +} From 1d7f891ea96f69c390aee99cee93fc05f0b9833f Mon Sep 17 00:00:00 2001 From: Tom <54514587+GAtom22@users.noreply.github.com> Date: Tue, 13 Aug 2024 07:03:21 -0300 Subject: [PATCH 5/6] feat(confix): allow customization of migration plan (#21202) Co-authored-by: Hieu Vu <72878483+hieuvubk@users.noreply.github.com> --- tools/confix/CHANGELOG.md | 4 ++++ tools/confix/migrations.go | 22 +++++++++++++++------- 2 files changed, 19 insertions(+), 7 deletions(-) diff --git a/tools/confix/CHANGELOG.md b/tools/confix/CHANGELOG.md index e044193f3029..531daaf7b5c1 100644 --- a/tools/confix/CHANGELOG.md +++ b/tools/confix/CHANGELOG.md @@ -31,6 +31,10 @@ Ref: https://keepachangelog.com/en/1.0.0/ ## [Unreleased] +### Features + +* (confix) [#21202](https://github.com/cosmos/cosmos-sdk/pull/21202) Allow customization of migration `PlanBuilder`. + ## [v0.1.1](https://github.com/cosmos/cosmos-sdk/releases/tag/tools/confix/v0.1.1) - 2023-12-11 * [#18496](https://github.com/cosmos/cosmos-sdk/pull/18496) Remove invalid non SDK config from app.toml migration templates. diff --git a/tools/confix/migrations.go b/tools/confix/migrations.go index 737ed6b822cb..4a500898bc04 100644 --- a/tools/confix/migrations.go +++ b/tools/confix/migrations.go @@ -21,14 +21,18 @@ const ( // MigrationMap defines a mapping from a version to a transformation plan. type MigrationMap map[string]func(from *tomledit.Document, to, planType string) (transform.Plan, *tomledit.Document) +// loadDestConfigFile is the function signature to load the destination version +// configuration toml file. +type loadDestConfigFile func(to, planType string) (*tomledit.Document, error) + var Migrations = MigrationMap{ "v0.45": NoPlan, // Confix supports only the current supported SDK version. So we do not support v0.44 -> v0.45. - "v0.46": PlanBuilder, - "v0.47": PlanBuilder, - "v0.50": PlanBuilder, - "v0.52": PlanBuilder, + "v0.46": defaultPlanBuilder, + "v0.47": defaultPlanBuilder, + "v0.50": defaultPlanBuilder, + "v0.52": defaultPlanBuilder, "v2": V2PlanBuilder, - // "v0.xx.x": PlanBuilder, // add specific migration in case of configuration changes in minor versions + // "v0.xx.x": defaultPlanBuilder, // add specific migration in case of configuration changes in minor versions } type v2KeyChangesMap map[string][]string @@ -53,12 +57,16 @@ var v2KeyChanges = v2KeyChangesMap{ // Add other key mappings as needed } +func defaultPlanBuilder(from *tomledit.Document, to, planType string) (transform.Plan, *tomledit.Document) { + return PlanBuilder(from, to, planType, LoadLocalConfig) +} + // PlanBuilder is a function that returns a transformation plan for a given diff between two files. -func PlanBuilder(from *tomledit.Document, to, planType string) (transform.Plan, *tomledit.Document) { +func PlanBuilder(from *tomledit.Document, to, planType string, loadFn loadDestConfigFile) (transform.Plan, *tomledit.Document) { plan := transform.Plan{} deletedSections := map[string]bool{} - target, err := LoadLocalConfig(to, planType) + target, err := loadFn(to, planType) if err != nil { panic(fmt.Errorf("failed to parse file: %w. This file should have been valid", err)) } From 75db9d77507d64de23c1172d7a1da251e6ee6ce4 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 13 Aug 2024 10:28:01 +0000 Subject: [PATCH 6/6] build(deps): Bump github.com/cosmos/cosmos-sdk from 0.50.8 to 0.50.9 in /tools/confix (#21263) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Julien Robert --- simapp/go.mod | 2 +- simapp/v2/go.mod | 2 +- tests/go.mod | 2 +- tools/confix/go.mod | 9 ++++----- tools/confix/go.sum | 18 ++++++++---------- 5 files changed, 15 insertions(+), 18 deletions(-) diff --git a/simapp/go.mod b/simapp/go.mod index 9a3e05c78a74..ac5032b9a94d 100644 --- a/simapp/go.mod +++ b/simapp/go.mod @@ -31,7 +31,7 @@ require ( cosmossdk.io/x/protocolpool v0.0.0-20230925135524-a1bc045b3190 cosmossdk.io/x/slashing v0.0.0-00010101000000-000000000000 cosmossdk.io/x/staking v0.0.0-20240226161501-23359a0b6d91 - cosmossdk.io/x/tx v0.13.3 + cosmossdk.io/x/tx v0.13.4 cosmossdk.io/x/upgrade v0.0.0-20230613133644-0a778132a60f github.com/cometbft/cometbft v1.0.0-rc1 github.com/cometbft/cometbft/api v1.0.0-rc.1 diff --git a/simapp/v2/go.mod b/simapp/v2/go.mod index 9e2118f0c2fa..e1f174677563 100644 --- a/simapp/v2/go.mod +++ b/simapp/v2/go.mod @@ -63,7 +63,7 @@ require ( cosmossdk.io/x/accounts/defaults/lockup v0.0.0-20240417181816-5e7aae0db1f5 // indirect cosmossdk.io/x/accounts/defaults/multisig v0.0.0-00010101000000-000000000000 // indirect cosmossdk.io/x/epochs v0.0.0-20240522060652-a1ae4c3e0337 // indirect - cosmossdk.io/x/tx v0.13.3 // indirect + cosmossdk.io/x/tx v0.13.4 // indirect filippo.io/edwards25519 v1.1.0 // indirect github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4 // indirect github.com/99designs/keyring v1.2.2 // indirect diff --git a/tests/go.mod b/tests/go.mod index 67c4e9a420f9..9eea02c21ae0 100644 --- a/tests/go.mod +++ b/tests/go.mod @@ -16,7 +16,7 @@ require ( cosmossdk.io/x/feegrant v0.0.0-20230613133644-0a778132a60f cosmossdk.io/x/nft v0.0.0-20230613133644-0a778132a60f cosmossdk.io/x/protocolpool v0.0.0-20230925135524-a1bc045b3190 - cosmossdk.io/x/tx v0.13.3 + cosmossdk.io/x/tx v0.13.4 cosmossdk.io/x/upgrade v0.0.0-20230613133644-0a778132a60f github.com/cometbft/cometbft v1.0.0-rc1 github.com/cosmos/cosmos-db v1.0.2 diff --git a/tools/confix/go.mod b/tools/confix/go.mod index ea40688a794c..1d9fda986f01 100644 --- a/tools/confix/go.mod +++ b/tools/confix/go.mod @@ -3,7 +3,7 @@ module cosmossdk.io/tools/confix go 1.21 require ( - github.com/cosmos/cosmos-sdk v0.50.8 + github.com/cosmos/cosmos-sdk v0.50.9 github.com/creachadair/atomicfile v0.3.4 github.com/creachadair/tomledit v0.0.26 github.com/pelletier/go-toml/v2 v2.2.2 @@ -16,13 +16,13 @@ require ( require ( cosmossdk.io/api v0.7.5 // indirect cosmossdk.io/collections v0.4.0 // indirect - cosmossdk.io/core v0.11.0 // indirect + cosmossdk.io/core v0.11.1 // indirect cosmossdk.io/depinject v1.0.0 // indirect cosmossdk.io/errors v1.0.1 // indirect cosmossdk.io/log v1.4.0 // indirect cosmossdk.io/math v1.3.0 // indirect cosmossdk.io/store v1.1.0 // indirect - cosmossdk.io/x/tx v0.13.3 // indirect + cosmossdk.io/x/tx v0.13.4 // indirect filippo.io/edwards25519 v1.1.0 // indirect github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4 // indirect github.com/99designs/keyring v1.2.1 // indirect @@ -39,7 +39,7 @@ require ( github.com/cockroachdb/pebble v1.1.0 // indirect github.com/cockroachdb/redact v1.1.5 // indirect github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06 // indirect - github.com/cometbft/cometbft v0.38.9 // indirect + github.com/cometbft/cometbft v0.38.10 // indirect github.com/cometbft/cometbft-db v0.9.1 // indirect github.com/cosmos/btcutil v1.0.5 // indirect github.com/cosmos/cosmos-db v1.0.2 // indirect @@ -101,7 +101,6 @@ require ( github.com/kr/pretty v0.3.1 // indirect github.com/kr/text v0.2.0 // indirect github.com/lib/pq v1.10.7 // indirect - github.com/libp2p/go-buffer-pool v0.1.0 // indirect github.com/linxGnu/grocksdb v1.8.14 // indirect github.com/magiconair/properties v1.8.7 // indirect github.com/mattn/go-colorable v0.1.13 // indirect diff --git a/tools/confix/go.sum b/tools/confix/go.sum index 3c86bf1173e5..18d458249637 100644 --- a/tools/confix/go.sum +++ b/tools/confix/go.sum @@ -4,8 +4,8 @@ cosmossdk.io/api v0.7.5 h1:eMPTReoNmGUm8DeiQL9DyM8sYDjEhWzL1+nLbI9DqtQ= cosmossdk.io/api v0.7.5/go.mod h1:IcxpYS5fMemZGqyYtErK7OqvdM0C8kdW3dq8Q/XIG38= cosmossdk.io/collections v0.4.0 h1:PFmwj2W8szgpD5nOd8GWH6AbYNi1f2J6akWXJ7P5t9s= cosmossdk.io/collections v0.4.0/go.mod h1:oa5lUING2dP+gdDquow+QjlF45eL1t4TJDypgGd+tv0= -cosmossdk.io/core v0.11.0 h1:vtIafqUi+1ZNAE/oxLOQQ7Oek2n4S48SWLG8h/+wdbo= -cosmossdk.io/core v0.11.0/go.mod h1:LaTtayWBSoacF5xNzoF8tmLhehqlA9z1SWiPuNC6X1w= +cosmossdk.io/core v0.11.1 h1:h9WfBey7NAiFfIcUhDVNS503I2P2HdZLebJlUIs8LPA= +cosmossdk.io/core v0.11.1/go.mod h1:OJzxcdC+RPrgGF8NJZR2uoQr56tc7gfBKhiKeDO7hH0= cosmossdk.io/depinject v1.0.0 h1:dQaTu6+O6askNXO06+jyeUAnF2/ssKwrrszP9t5q050= cosmossdk.io/depinject v1.0.0/go.mod h1:zxK/h3HgHoA/eJVtiSsoaRaRA2D5U4cJ5thIG4ssbB8= cosmossdk.io/errors v1.0.1 h1:bzu+Kcr0kS/1DuPBtUFdWjzLqyUuCiyHjyJB6srBV/0= @@ -16,8 +16,8 @@ cosmossdk.io/math v1.3.0 h1:RC+jryuKeytIiictDslBP9i1fhkVm6ZDmZEoNP316zE= cosmossdk.io/math v1.3.0/go.mod h1:vnRTxewy+M7BtXBNFybkuhSH4WfedVAAnERHgVFhp3k= cosmossdk.io/store v1.1.0 h1:LnKwgYMc9BInn9PhpTFEQVbL9UK475G2H911CGGnWHk= cosmossdk.io/store v1.1.0/go.mod h1:oZfW/4Fc/zYqu3JmQcQdUJ3fqu5vnYTn3LZFFy8P8ng= -cosmossdk.io/x/tx v0.13.3 h1:Ha4mNaHmxBc6RMun9aKuqul8yHiL78EKJQ8g23Zf73g= -cosmossdk.io/x/tx v0.13.3/go.mod h1:I8xaHv0rhUdIvIdptKIqzYy27+n2+zBVaxO6fscFhys= +cosmossdk.io/x/tx v0.13.4 h1:Eg0PbJgeO0gM8p5wx6xa0fKR7hIV6+8lC56UrsvSo0Y= +cosmossdk.io/x/tx v0.13.4/go.mod h1:BkFqrnGGgW50Y6cwTy+JvgAhiffbGEKW6KF9ufcDpvk= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA= filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4= @@ -125,8 +125,8 @@ github.com/cockroachdb/redact v1.1.5/go.mod h1:BVNblN9mBWFyMyqK1k3AAiSxhvhfK2oOZ github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06 h1:zuQyyAKVxetITBuuhv3BI9cMrmStnpT18zmgmTxunpo= github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06/go.mod h1:7nc4anLGjupUW/PeY5qiNYsdNXj7zopG+eqsS7To5IQ= github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd/go.mod h1:sE/e/2PUdi/liOCUjSTXgM1o87ZssimdTWN964YiIeI= -github.com/cometbft/cometbft v0.38.9 h1:cJBJBG0mPKz+sqelCi/hlfZjadZQGdDNnu6YQ1ZsUHQ= -github.com/cometbft/cometbft v0.38.9/go.mod h1:xOoGZrtUT+A5izWfHSJgl0gYZUE7lu7Z2XIS1vWG/QQ= +github.com/cometbft/cometbft v0.38.10 h1:2ePuglchT+j0Iao+cfmt/nw5U7K2lnGDzXSUPGVdXaU= +github.com/cometbft/cometbft v0.38.10/go.mod h1:jHPx9vQpWzPHEAiYI/7EDKaB1NXhK6o3SArrrY8ExKc= github.com/cometbft/cometbft-db v0.9.1 h1:MIhVX5ja5bXNHF8EYrThkG9F7r9kSfv8BX4LWaxWJ4M= github.com/cometbft/cometbft-db v0.9.1/go.mod h1:iliyWaoV0mRwBJoizElCwwRA9Tf7jZJOURcRZF9m60U= github.com/containerd/continuity v0.3.0 h1:nisirsYROK15TAMVukJOUyGJjz4BNQJBVsNvAXZJ/eg= @@ -143,8 +143,8 @@ github.com/cosmos/cosmos-db v1.0.2 h1:hwMjozuY1OlJs/uh6vddqnk9j7VamLv+0DBlbEXbAK github.com/cosmos/cosmos-db v1.0.2/go.mod h1:Z8IXcFJ9PqKK6BIsVOB3QXtkKoqUOp1vRvPT39kOXEA= 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.50.8 h1:2UJHssUaGHTl4/dFp8xyREKAnfiRU6VVfqtKG9n8w5g= -github.com/cosmos/cosmos-sdk v0.50.8/go.mod h1:Zb+DgHtiByNwgj71IlJBXwOq6dLhtyAq3AgqpXm/jHo= +github.com/cosmos/cosmos-sdk v0.50.9 h1:gt2usjz0H0qW6KwAxWw7ZJ3XU8uDwmhN+hYG3nTLeSg= +github.com/cosmos/cosmos-sdk v0.50.9/go.mod h1:TMH6wpoYBcg7Cp5BEg8fneLr+8XloNQkf2MRNF9V6JE= github.com/cosmos/go-bip39 v1.0.0 h1:pcomnQdrdH22njcAatO0yWojsUnCO3y2tNoV1cb6hHY= github.com/cosmos/go-bip39 v1.0.0/go.mod h1:RNJv0H/pOIVgxw6KS7QeX2a0Uo0aKUlfhZ4xuwvCdJw= github.com/cosmos/gogogateway v1.2.0 h1:Ae/OivNhp8DqBi/sh2A8a1D0y638GpL3tkmLQAiKxTE= @@ -462,8 +462,6 @@ github.com/leodido/go-urn v1.2.1 h1:BqpAaACuzVSgi/VLzGZIobT2z4v53pjosyNd9Yv6n/w= github.com/leodido/go-urn v1.2.1/go.mod h1:zt4jvISO2HfUBqxjfIshjdMTYS56ZS/qv49ictyFfxY= github.com/lib/pq v1.10.7 h1:p7ZhMD+KsSRozJr34udlUrhboJwWAgCg34+/ZZNvZZw= github.com/lib/pq v1.10.7/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= -github.com/libp2p/go-buffer-pool v0.1.0 h1:oK4mSFcQz7cTQIfqbe4MIj9gLW+mnanjyFtc6cdF0Y8= -github.com/libp2p/go-buffer-pool v0.1.0/go.mod h1:N+vh8gMqimBzdKkSMVuydVDq+UV5QTWy5HSiZacSbPg= github.com/lightstep/lightstep-tracer-common/golang/gogo v0.0.0-20190605223551-bc2310a04743/go.mod h1:qklhhLq1aX+mtWk9cPHPzaBjWImj5ULL6C7HFJtXQMM= github.com/lightstep/lightstep-tracer-go v0.18.1/go.mod h1:jlF1pusYV4pidLvZ+XD0UBX0ZE6WURAspgAczcDHrL4= github.com/linxGnu/grocksdb v1.8.14 h1:HTgyYalNwBSG/1qCQUIott44wU5b2Y9Kr3z7SK5OfGQ=