From 1dde9decd22b327c430038f51c376f06d43107d9 Mon Sep 17 00:00:00 2001 From: Randy Grok <98407738+randygrok@users.noreply.github.com> Date: Fri, 6 Sep 2024 17:56:29 +0200 Subject: [PATCH 1/5] feat: unify version modifier for v2 (#21508) (cherry picked from commit dce0365c234b60b355988e57fa275bf9bd3ea667) # Conflicts: # baseapp/utils_test.go # core/server/app.go # runtime/v2/module.go # server/v2/stf/core_branch_service.go # server/v2/stf/core_branch_service_test.go --- baseapp/baseapp.go | 15 +- baseapp/baseapp_test.go | 1 + baseapp/options.go | 27 ++- baseapp/utils_test.go | 90 ++++++++ core/server/app.go | 59 ++++++ runtime/module.go | 6 - runtime/v2/module.go | 238 ++++++++++++++++++++++ server/v2/stf/core_branch_service.go | 85 ++++++++ server/v2/stf/core_branch_service_test.go | 110 ++++++++++ simapp/CHANGELOG.md | 2 + simapp/app.go | 3 + x/consensus/depinject.go | 39 +++- 12 files changed, 644 insertions(+), 31 deletions(-) create mode 100644 core/server/app.go create mode 100644 runtime/v2/module.go create mode 100644 server/v2/stf/core_branch_service.go create mode 100644 server/v2/stf/core_branch_service_test.go diff --git a/baseapp/baseapp.go b/baseapp/baseapp.go index f2c75f5f5a51..2638cbe60ae7 100644 --- a/baseapp/baseapp.go +++ b/baseapp/baseapp.go @@ -2,6 +2,7 @@ package baseapp import ( "context" + "cosmossdk.io/core/server" "errors" "fmt" "maps" @@ -89,6 +90,7 @@ type BaseApp struct { verifyVoteExt sdk.VerifyVoteExtensionHandler // ABCI VerifyVoteExtension handler prepareCheckStater sdk.PrepareCheckStater // logic to run during commit using the checkState precommiter sdk.Precommiter // logic to run during commit using the deliverState + versionModifier server.VersionModifier // interface to get and set the app version addrPeerFilter sdk.PeerFilter // filter peers by address and port idPeerFilter sdk.PeerFilter // filter peers by node ID @@ -249,18 +251,11 @@ func (app *BaseApp) Name() string { // AppVersion returns the application's protocol version. func (app *BaseApp) AppVersion(ctx context.Context) (uint64, error) { - if app.paramStore == nil { - return 0, errors.New("app.paramStore is nil") + if app.versionModifier == nil { + return 0, errors.New("app.versionModifier is nil") } - cp, err := app.paramStore.Get(ctx) - if err != nil { - return 0, fmt.Errorf("failed to get consensus params: %w", err) - } - if cp.Version == nil { - return 0, nil - } - return cp.Version.App, nil + return app.versionModifier.AppVersion(ctx) } // Version returns the application's version string. diff --git a/baseapp/baseapp_test.go b/baseapp/baseapp_test.go index ecaf6894b400..22b046cf8a63 100644 --- a/baseapp/baseapp_test.go +++ b/baseapp/baseapp_test.go @@ -81,6 +81,7 @@ func NewBaseAppSuite(t *testing.T, opts ...func(*baseapp.BaseApp)) *BaseAppSuite app.SetParamStore(paramStore{db: dbm.NewMemDB()}) app.SetTxDecoder(txConfig.TxDecoder()) app.SetTxEncoder(txConfig.TxEncoder()) + app.SetVersionModifier(newMockedVersionModifier(0)) // mount stores and seal require.Nil(t, app.LoadLatestVersion()) diff --git a/baseapp/options.go b/baseapp/options.go index 431f64b70906..7500e070710c 100644 --- a/baseapp/options.go +++ b/baseapp/options.go @@ -2,6 +2,7 @@ package baseapp import ( "context" + "cosmossdk.io/core/server" "errors" "fmt" "io" @@ -146,22 +147,11 @@ func (app *BaseApp) SetVersion(v string) { // SetAppVersion sets the application's version this is used as part of the // header in blocks and is returned to the consensus engine in EndBlock. func (app *BaseApp) SetAppVersion(ctx context.Context, v uint64) error { - if app.paramStore == nil { - return errors.New("param store must be set to set app version") + if app.versionModifier == nil { + return errors.New("version modifier must be set to set app version") } - cp, err := app.paramStore.Get(ctx) - if err != nil { - return fmt.Errorf("failed to get consensus params: %w", err) - } - if cp.Version == nil { - return errors.New("version is not set in param store") - } - cp.Version.App = v - if err := app.paramStore.Set(ctx, cp); err != nil { - return err - } - return nil + return app.versionModifier.SetAppVersion(ctx, v) } func (app *BaseApp) SetDB(db corestore.KVStoreWithBatch) { @@ -323,6 +313,15 @@ func (app *BaseApp) SetTxEncoder(txEncoder sdk.TxEncoder) { app.txEncoder = txEncoder } +// SetVersionModifier sets the version modifier for the BaseApp that allows to set the app version. +func (app *BaseApp) SetVersionModifier(versionModifier server.VersionModifier) { + if app.sealed { + panic("SetVersionModifier() on sealed BaseApp") + } + + app.versionModifier = versionModifier +} + // SetQueryMultiStore set a alternative MultiStore implementation to support grpc query service. // // Ref: https://github.com/cosmos/cosmos-sdk/issues/13317 diff --git a/baseapp/utils_test.go b/baseapp/utils_test.go index 9a47fde242d7..bb3ca0422e57 100644 --- a/baseapp/utils_test.go +++ b/baseapp/utils_test.go @@ -3,6 +3,7 @@ package baseapp_test import ( "bytes" "context" + "cosmossdk.io/core/server" "encoding/binary" "encoding/json" "errors" @@ -375,3 +376,92 @@ func wonkyMsg(t *testing.T, cfg client.TxConfig, tx signing.Tx) signing.Tx { require.NoError(t, err) return builder.GetTx() } +<<<<<<< HEAD +======= + +type SendServerImpl struct { + gas uint64 +} + +func (s SendServerImpl) Send(ctx context.Context, send *baseapptestutil.MsgSend) (*baseapptestutil.MsgSendResponse, error) { + sdkCtx := sdk.UnwrapSDKContext(ctx) + if send.From == "" { + return nil, errors.New("from address cannot be empty") + } + if send.To == "" { + return nil, errors.New("to address cannot be empty") + } + + _, err := sdk.ParseCoinNormalized(send.Amount) + if err != nil { + return nil, err + } + gas := s.gas + if gas == 0 { + gas = 5 + } + sdkCtx.GasMeter().ConsumeGas(gas, "send test") + return &baseapptestutil.MsgSendResponse{}, nil +} + +type NestedMessgesServerImpl struct { + gas uint64 +} + +func (n NestedMessgesServerImpl) Check(ctx context.Context, message *baseapptestutil.MsgNestedMessages) (*baseapptestutil.MsgCreateNestedMessagesResponse, error) { + sdkCtx := sdk.UnwrapSDKContext(ctx) + cdc := codectestutil.CodecOptions{}.NewCodec() + baseapptestutil.RegisterInterfaces(cdc.InterfaceRegistry()) + + signer, _, err := cdc.GetMsgSigners(message) + if err != nil { + return nil, err + } + if len(signer) != 1 { + return nil, fmt.Errorf("expected 1 signer, got %d", len(signer)) + } + + msgs, err := message.GetMsgs() + if err != nil { + return nil, err + } + + for _, msg := range msgs { + s, _, err := cdc.GetMsgSigners(msg) + if err != nil { + return nil, err + } + if len(s) != 1 { + return nil, fmt.Errorf("expected 1 signer, got %d", len(s)) + } + if !bytes.Equal(signer[0], s[0]) { + return nil, errors.New("signer does not match") + } + + } + + gas := n.gas + if gas == 0 { + gas = 5 + } + sdkCtx.GasMeter().ConsumeGas(gas, "nested messages test") + return nil, nil +} + +func newMockedVersionModifier(startingVersion uint64) server.VersionModifier { + return &mockedVersionModifier{version: startingVersion} +} + +type mockedVersionModifier struct { + version uint64 +} + +func (m *mockedVersionModifier) SetAppVersion(ctx context.Context, u uint64) error { + m.version = u + return nil +} + +func (m *mockedVersionModifier) AppVersion(ctx context.Context) (uint64, error) { + return m.version, nil +} +>>>>>>> dce0365c2 (feat: unify version modifier for v2 (#21508)) diff --git a/core/server/app.go b/core/server/app.go new file mode 100644 index 000000000000..9576fa8825f8 --- /dev/null +++ b/core/server/app.go @@ -0,0 +1,59 @@ +package server + +import ( + "context" + "time" + + appmodulev2 "cosmossdk.io/core/appmodule/v2" + "cosmossdk.io/core/event" + "cosmossdk.io/core/transaction" +) + +// BlockRequest defines the request structure for a block coming from consensus server to the state transition function. +type BlockRequest[T transaction.Tx] struct { + 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 +} + +// BlockResponse defines the response structure for a block coming from the state transition function to consensus server. +type BlockResponse struct { + ValidatorUpdates []appmodulev2.ValidatorUpdate + PreBlockEvents []event.Event + BeginBlockEvents []event.Event + TxResults []TxResult + EndBlockEvents []event.Event +} + +// TxResult defines the result of a transaction execution. +type TxResult struct { + // Events produced by the transaction. + Events []event.Event + // Response messages produced by the transaction. + Resp []transaction.Msg + // Error produced by the transaction. + Error error + // Code produced by the transaction. + // A non-zero code is an error that is either define by the module via the cosmossdk.io/errors/v2 package + // or injected through the antehandler along the execution of the transaction. + Code uint32 + // GasWanted is the maximum units of work we allow this tx to perform. + GasWanted uint64 + // GasUsed is the amount of gas actually consumed. + GasUsed uint64 +} + +// VersionModifier defines the interface fulfilled by BaseApp +// which allows getting and setting its appVersion field. This +// in turn updates the consensus params that are sent to the +// consensus engine in EndBlock +type VersionModifier interface { + SetAppVersion(context.Context, uint64) error + AppVersion(context.Context) (uint64, error) +} diff --git a/runtime/module.go b/runtime/module.go index 2b2a9bb1b9df..95595fc209f8 100644 --- a/runtime/module.go +++ b/runtime/module.go @@ -15,7 +15,6 @@ import ( "cosmossdk.io/core/appmodule" "cosmossdk.io/core/comet" "cosmossdk.io/core/registry" - "cosmossdk.io/core/server" "cosmossdk.io/core/store" "cosmossdk.io/depinject" "cosmossdk.io/depinject/appconfig" @@ -103,7 +102,6 @@ func init() { ProvideEnvironment, ProvideTransientStoreService, ProvideModuleManager, - ProvideAppVersionModifier, ProvideCometService, ), appconfig.Invoke(SetupAppBuilder), @@ -293,10 +291,6 @@ func ProvideTransientStoreService( return transientStoreService{key: storeKey} } -func ProvideAppVersionModifier(app *AppBuilder) server.VersionModifier { - return app.app -} - func ProvideCometService() comet.Service { return NewContextAwareCometInfoService() } diff --git a/runtime/v2/module.go b/runtime/v2/module.go new file mode 100644 index 000000000000..1cda0a577fd4 --- /dev/null +++ b/runtime/v2/module.go @@ -0,0 +1,238 @@ +package runtime + +import ( + "fmt" + "os" + "slices" + + "github.com/cosmos/gogoproto/proto" + "github.com/spf13/viper" + "google.golang.org/grpc" + "google.golang.org/protobuf/reflect/protodesc" + "google.golang.org/protobuf/reflect/protoregistry" + + runtimev2 "cosmossdk.io/api/cosmos/app/runtime/v2" + appv1alpha1 "cosmossdk.io/api/cosmos/app/v1alpha1" + autocliv1 "cosmossdk.io/api/cosmos/autocli/v1" + reflectionv1 "cosmossdk.io/api/cosmos/reflection/v1" + appmodulev2 "cosmossdk.io/core/appmodule/v2" + "cosmossdk.io/core/comet" + "cosmossdk.io/core/registry" + "cosmossdk.io/core/store" + "cosmossdk.io/core/transaction" + "cosmossdk.io/depinject" + "cosmossdk.io/depinject/appconfig" + "cosmossdk.io/log" + "cosmossdk.io/runtime/v2/services" + "cosmossdk.io/server/v2/stf" +) + +var ( + _ appmodulev2.AppModule = appModule[transaction.Tx]{} + _ hasServicesV1 = appModule[transaction.Tx]{} +) + +type appModule[T transaction.Tx] struct { + app *App[T] +} + +func (m appModule[T]) IsOnePerModuleType() {} +func (m appModule[T]) IsAppModule() {} + +func (m appModule[T]) RegisterServices(registar grpc.ServiceRegistrar) error { + autoCliQueryService, err := services.NewAutoCLIQueryService(m.app.moduleManager.modules) + if err != nil { + return err + } + + autocliv1.RegisterQueryServer(registar, autoCliQueryService) + + reflectionSvc, err := services.NewReflectionService() + if err != nil { + return err + } + reflectionv1.RegisterReflectionServiceServer(registar, reflectionSvc) + + return nil +} + +func (m appModule[T]) AutoCLIOptions() *autocliv1.ModuleOptions { + return &autocliv1.ModuleOptions{ + Query: &autocliv1.ServiceCommandDescriptor{ + Service: appv1alpha1.Query_ServiceDesc.ServiceName, + RpcCommandOptions: []*autocliv1.RpcCommandOptions{ + { + RpcMethod: "Config", + Short: "Query the current app config", + }, + }, + SubCommands: map[string]*autocliv1.ServiceCommandDescriptor{ + "autocli": { + Service: autocliv1.Query_ServiceDesc.ServiceName, + RpcCommandOptions: []*autocliv1.RpcCommandOptions{ + { + RpcMethod: "AppOptions", + Short: "Query the custom autocli options", + }, + }, + }, + "reflection": { + Service: reflectionv1.ReflectionService_ServiceDesc.ServiceName, + RpcCommandOptions: []*autocliv1.RpcCommandOptions{ + { + RpcMethod: "FileDescriptors", + Short: "Query the app's protobuf file descriptors", + }, + }, + }, + }, + }, + } +} + +func init() { + appconfig.Register(&runtimev2.Module{}, + appconfig.Provide( + ProvideAppBuilder[transaction.Tx], + ProvideEnvironment[transaction.Tx], + ProvideModuleManager[transaction.Tx], + ProvideCometService, + ), + appconfig.Invoke(SetupAppBuilder), + ) +} + +func ProvideAppBuilder[T transaction.Tx]( + interfaceRegistrar registry.InterfaceRegistrar, + amino registry.AminoRegistrar, +) ( + *AppBuilder[T], + *stf.MsgRouterBuilder, + appmodulev2.AppModule, + protodesc.Resolver, + protoregistry.MessageTypeResolver, +) { + protoFiles := proto.HybridResolver + protoTypes := protoregistry.GlobalTypes + + // At startup, check that all proto annotations are correct. + if err := validateProtoAnnotations(protoFiles); err != nil { + // Once we switch to using protoreflect-based ante handlers, we might + // want to panic here instead of logging a warning. + _, _ = fmt.Fprintln(os.Stderr, err.Error()) + } + + msgRouterBuilder := stf.NewMsgRouterBuilder() + app := &App[T]{ + storeKeys: nil, + interfaceRegistrar: interfaceRegistrar, + amino: amino, + msgRouterBuilder: msgRouterBuilder, + queryRouterBuilder: stf.NewMsgRouterBuilder(), // TODO dedicated query router + GRPCMethodsToMessageMap: map[string]func() proto.Message{}, + } + appBuilder := &AppBuilder[T]{app: app} + + return appBuilder, msgRouterBuilder, appModule[T]{app}, protoFiles, protoTypes +} + +type AppInputs struct { + depinject.In + + Config *runtimev2.Module + AppBuilder *AppBuilder[transaction.Tx] + ModuleManager *MM[transaction.Tx] + InterfaceRegistrar registry.InterfaceRegistrar + LegacyAmino registry.AminoRegistrar + Logger log.Logger + Viper *viper.Viper `optional:"true"` // can be nil in client wiring +} + +func SetupAppBuilder(inputs AppInputs) { + app := inputs.AppBuilder.app + app.config = inputs.Config + app.logger = inputs.Logger + app.moduleManager = inputs.ModuleManager + app.moduleManager.RegisterInterfaces(inputs.InterfaceRegistrar) + app.moduleManager.RegisterLegacyAminoCodec(inputs.LegacyAmino) + + if inputs.Viper != nil { + inputs.AppBuilder.viper = inputs.Viper + } +} + +func ProvideModuleManager[T transaction.Tx]( + logger log.Logger, + config *runtimev2.Module, + modules map[string]appmodulev2.AppModule, +) *MM[T] { + return NewModuleManager[T](logger, config, modules) +} + +// ProvideEnvironment provides the environment for keeper modules, while maintaining backward compatibility and provide services directly as well. +func ProvideEnvironment[T transaction.Tx]( + logger log.Logger, + config *runtimev2.Module, + key depinject.ModuleKey, + appBuilder *AppBuilder[T], +) ( + appmodulev2.Environment, + store.KVStoreService, + store.MemoryStoreService, +) { + var ( + kvService store.KVStoreService = failingStoreService{} + memKvService store.MemoryStoreService = failingStoreService{} + ) + + // skips modules that have no store + if !slices.Contains(config.SkipStoreKeys, key.Name()) { + var kvStoreKey string + storeKeyOverride := storeKeyOverride(config, key.Name()) + if storeKeyOverride != nil { + kvStoreKey = storeKeyOverride.KvStoreKey + } else { + kvStoreKey = key.Name() + } + + registerStoreKey(appBuilder, kvStoreKey) + kvService = stf.NewKVStoreService([]byte(kvStoreKey)) + + memStoreKey := fmt.Sprintf("memory:%s", key.Name()) + registerStoreKey(appBuilder, memStoreKey) + memKvService = stf.NewMemoryStoreService([]byte(memStoreKey)) + } + + env := appmodulev2.Environment{ + Logger: logger, + BranchService: stf.BranchService{}, + EventService: stf.NewEventService(), + GasService: stf.NewGasMeterService(), + HeaderService: stf.HeaderService{}, + QueryRouterService: stf.NewQueryRouterService(), + MsgRouterService: stf.NewMsgRouterService([]byte(key.Name())), + TransactionService: services.NewContextAwareTransactionService(), + KVStoreService: kvService, + MemStoreService: memKvService, + } + + return env, kvService, memKvService +} + +func registerStoreKey[T transaction.Tx](wrapper *AppBuilder[T], key string) { + wrapper.app.storeKeys = append(wrapper.app.storeKeys, key) +} + +func storeKeyOverride(config *runtimev2.Module, moduleName string) *runtimev2.StoreKeyConfig { + for _, cfg := range config.OverrideStoreKeys { + if cfg.ModuleName == moduleName { + return cfg + } + } + + return nil +} + +func ProvideCometService() comet.Service { + return &services.ContextAwareCometInfoService{} +} diff --git a/server/v2/stf/core_branch_service.go b/server/v2/stf/core_branch_service.go new file mode 100644 index 000000000000..5a83dff6be7c --- /dev/null +++ b/server/v2/stf/core_branch_service.go @@ -0,0 +1,85 @@ +package stf + +import ( + "context" + + "cosmossdk.io/core/branch" + "cosmossdk.io/core/store" +) + +type branchFn func(state store.ReaderMap) store.WriterMap + +var _ branch.Service = (*BranchService)(nil) + +type BranchService struct{} + +func (bs BranchService) Execute(ctx context.Context, f func(ctx context.Context) error) error { + exCtx, err := getExecutionCtxFromContext(ctx) + if err != nil { + return err + } + + return bs.execute(exCtx, f) +} + +func (bs BranchService) ExecuteWithGasLimit( + ctx context.Context, + gasLimit uint64, + f func(ctx context.Context) error, +) (gasUsed uint64, err error) { + exCtx, err := getExecutionCtxFromContext(ctx) + if err != nil { + return 0, err + } + + originalGasMeter := exCtx.meter + + exCtx.setGasLimit(gasLimit) + + // execute branched, with predefined gas limit. + err = bs.execute(exCtx, f) + // restore original context + gasUsed = exCtx.meter.Limit() - exCtx.meter.Remaining() + _ = originalGasMeter.Consume(gasUsed, "execute-with-gas-limit") + exCtx.setGasLimit(originalGasMeter.Remaining()) + + return gasUsed, err +} + +func (bs BranchService) execute(ctx *executionContext, f func(ctx context.Context) error) error { + branchedState := ctx.branchFn(ctx.unmeteredState) + meteredBranchedState := ctx.makeGasMeteredStore(ctx.meter, branchedState) + + branchedCtx := &executionContext{ + Context: ctx.Context, + unmeteredState: branchedState, + state: meteredBranchedState, + meter: ctx.meter, + events: nil, + sender: ctx.sender, + headerInfo: ctx.headerInfo, + execMode: ctx.execMode, + branchFn: ctx.branchFn, + makeGasMeter: ctx.makeGasMeter, + makeGasMeteredStore: ctx.makeGasMeteredStore, + msgRouter: ctx.msgRouter, + queryRouter: ctx.queryRouter, + } + + err := f(branchedCtx) + if err != nil { + return err + } + + // apply state changes to original state + if len(branchedCtx.events) != 0 { + ctx.events = append(ctx.events, branchedCtx.events...) + } + + err = applyStateChanges(ctx.state, branchedCtx.unmeteredState) + if err != nil { + return err + } + + return nil +} diff --git a/server/v2/stf/core_branch_service_test.go b/server/v2/stf/core_branch_service_test.go new file mode 100644 index 000000000000..0394ce0f3b1a --- /dev/null +++ b/server/v2/stf/core_branch_service_test.go @@ -0,0 +1,110 @@ +package stf + +import ( + "context" + "errors" + "testing" + + appmodulev2 "cosmossdk.io/core/appmodule/v2" + "cosmossdk.io/server/v2/stf/branch" + "cosmossdk.io/server/v2/stf/gas" + "cosmossdk.io/server/v2/stf/mock" + gogotypes "github.com/cosmos/gogoproto/types" +) + +func TestBranchService(t *testing.T) { + s := &STF[mock.Tx]{ + doPreBlock: func(ctx context.Context, txs []mock.Tx) error { return nil }, + doBeginBlock: func(ctx context.Context) error { + kvSet(t, ctx, "begin-block") + return nil + }, + doEndBlock: func(ctx context.Context) error { + kvSet(t, ctx, "end-block") + return nil + }, + doValidatorUpdate: func(ctx context.Context) ([]appmodulev2.ValidatorUpdate, error) { return nil, nil }, + doTxValidation: func(ctx context.Context, tx mock.Tx) error { + kvSet(t, ctx, "validate") + return nil + }, + postTxExec: func(ctx context.Context, tx mock.Tx, success bool) error { + kvSet(t, ctx, "post-tx-exec") + return nil + }, + branchFn: branch.DefaultNewWriterMap, + makeGasMeter: gas.DefaultGasMeter, + makeGasMeteredState: gas.DefaultWrapWithGasMeter, + } + addMsgHandlerToSTF(t, s, func(ctx context.Context, msg *gogotypes.BoolValue) (*gogotypes.BoolValue, error) { + kvSet(t, ctx, "exec") + return nil, nil + }) + + makeContext := func() *executionContext { + state := mock.DB() + writableState := s.branchFn(state) + ctx := s.makeContext(context.Background(), []byte("cookies"), writableState, 0) + ctx.setGasLimit(1000000) + return ctx + } + + branchService := BranchService{} + + // TODO: add events check + gas limit precision test + + t.Run("ok", func(t *testing.T) { + stfCtx := makeContext() + gasUsed, err := branchService.ExecuteWithGasLimit(stfCtx, 10000, func(ctx context.Context) error { + kvSet(t, ctx, "cookies") + return nil + }) + if err != nil { + t.Errorf("unexpected error: %v", err) + } + if gasUsed == 0 { + t.Error("expected non-zero gasUsed") + } + stateHas(t, stfCtx.state, "cookies") + }) + + t.Run("fail - reverts state", func(t *testing.T) { + stfCtx := makeContext() + originalGas := stfCtx.meter.Remaining() + gasUsed, err := branchService.ExecuteWithGasLimit(stfCtx, 10000, func(ctx context.Context) error { + kvSet(t, ctx, "cookies") + return errors.New("fail") + }) + if err == nil { + t.Error("expected error") + } + if gasUsed == 0 { + t.Error("expected non-zero gasUsed") + } + if stfCtx.meter.Remaining() != originalGas-gasUsed { + t.Error("expected gas to be reverted") + } + + stateNotHas(t, stfCtx.state, "cookies") + }) + + t.Run("fail - out of gas", func(t *testing.T) { + stfCtx := makeContext() + + gasUsed, err := branchService.ExecuteWithGasLimit(stfCtx, 4000, func(ctx context.Context) error { + state, _ := ctx.(*executionContext).state.GetWriter(actorName) + _ = state.Set([]byte("not out of gas"), []byte{}) + return state.Set([]byte("out of gas"), []byte{}) + }) + if err == nil { + t.Error("expected error") + } + if gasUsed == 0 { + t.Error("expected non-zero gasUsed") + } + stateNotHas(t, stfCtx.state, "cookies") + if stfCtx.meter.Limit()-stfCtx.meter.Remaining() != 1000 { + t.Error("expected gas limit precision to be 1000") + } + }) +} diff --git a/simapp/CHANGELOG.md b/simapp/CHANGELOG.md index 5e6dae65ec2b..678870d8b74a 100644 --- a/simapp/CHANGELOG.md +++ b/simapp/CHANGELOG.md @@ -46,6 +46,8 @@ Always refer to the [UPGRADING.md](https://github.com/cosmos/cosmos-sdk/blob/mai * [#20490](https://github.com/cosmos/cosmos-sdk/pull/20490) Refactor simulations to make use of `testutil/sims` instead of `runsims`. * [#19726](https://github.com/cosmos/cosmos-sdk/pull/19726) Update APIs to match CometBFT v1. * [#21466](https://github.com/cosmos/cosmos-sdk/pull/21466) Allow chains to plug in their own public key types in `base.Account` +* [#21508](https://github.com/cosmos/cosmos-sdk/pull/21508) Abstract the way we update the version of the app state in `app.go` using the interface `VersionModifier`. + ## v0.47 to v0.50 diff --git a/simapp/app.go b/simapp/app.go index 2cc114103fc6..6cb7a326cf6d 100644 --- a/simapp/app.go +++ b/simapp/app.go @@ -294,6 +294,9 @@ func NewSimApp( app.ConsensusParamsKeeper = consensusparamkeeper.NewKeeper(appCodec, runtime.NewEnvironment(runtime.NewKVStoreService(keys[consensustypes.StoreKey]), logger.With(log.ModuleKey, "x/consensus")), govModuleAddr) bApp.SetParamStore(app.ConsensusParamsKeeper.ParamsStore) + // set the version modifier + bApp.SetVersionModifier(consensus.ProvideAppVersionModifier(app.ConsensusParamsKeeper)) + // add keepers accountsKeeper, err := accounts.NewKeeper( appCodec, diff --git a/x/consensus/depinject.go b/x/consensus/depinject.go index 127144d91a51..07048b4c8684 100644 --- a/x/consensus/depinject.go +++ b/x/consensus/depinject.go @@ -1,13 +1,14 @@ package consensus import ( + "context" modulev1 "cosmossdk.io/api/cosmos/consensus/module/v1" "cosmossdk.io/core/address" "cosmossdk.io/core/appmodule" + "cosmossdk.io/core/server" "cosmossdk.io/depinject" "cosmossdk.io/depinject/appconfig" "cosmossdk.io/x/consensus/keeper" - "github.com/cosmos/cosmos-sdk/baseapp" "github.com/cosmos/cosmos-sdk/codec" "github.com/cosmos/cosmos-sdk/runtime" @@ -23,6 +24,7 @@ func init() { appconfig.RegisterModule( &modulev1.Module{}, appconfig.Provide(ProvideModule), + appconfig.Provide(ProvideAppVersionModifier), ) } @@ -64,6 +66,7 @@ func ProvideModule(in ModuleInputs) ModuleOutputs { m := NewAppModule(in.Cdc, k) baseappOpt := func(app *baseapp.BaseApp) { app.SetParamStore(k.ParamsStore) + app.SetVersionModifier(versionModifier{Keeper: k}) } return ModuleOutputs{ @@ -72,3 +75,37 @@ func ProvideModule(in ModuleInputs) ModuleOutputs { BaseAppOption: baseappOpt, } } + +type versionModifier struct { + Keeper keeper.Keeper +} + +func (v versionModifier) SetAppVersion(ctx context.Context, version uint64) error { + params, err := v.Keeper.Params(ctx, nil) + if err != nil { + return err + } + + updatedParams := params.Params + updatedParams.Version.App = version + + err = v.Keeper.ParamsStore.Set(ctx, *updatedParams) + if err != nil { + return err + } + + return nil +} + +func (v versionModifier) AppVersion(ctx context.Context) (uint64, error) { + params, err := v.Keeper.Params(ctx, nil) + if err != nil { + return 0, err + } + + return params.Params.Version.GetApp(), nil +} + +func ProvideAppVersionModifier(k keeper.Keeper) server.VersionModifier { + return versionModifier{Keeper: k} +} From 67bf95577da8b60478e7237286b557c69cbc2b60 Mon Sep 17 00:00:00 2001 From: Julien Robert Date: Fri, 6 Sep 2024 18:06:22 +0200 Subject: [PATCH 2/5] updates --- baseapp/utils_test.go | 75 +------ core/server/app.go | 59 ------ runtime/v2/module.go | 238 ---------------------- server/v2/stf/core_branch_service.go | 85 -------- server/v2/stf/core_branch_service_test.go | 110 ---------- simapp/v2/go.mod | 2 +- simapp/v2/go.sum | 4 +- 7 files changed, 5 insertions(+), 568 deletions(-) delete mode 100644 core/server/app.go delete mode 100644 runtime/v2/module.go delete mode 100644 server/v2/stf/core_branch_service.go delete mode 100644 server/v2/stf/core_branch_service_test.go diff --git a/baseapp/utils_test.go b/baseapp/utils_test.go index bb3ca0422e57..96458289c94a 100644 --- a/baseapp/utils_test.go +++ b/baseapp/utils_test.go @@ -3,7 +3,6 @@ package baseapp_test import ( "bytes" "context" - "cosmossdk.io/core/server" "encoding/binary" "encoding/json" "errors" @@ -14,6 +13,8 @@ import ( "testing" "unsafe" + "cosmossdk.io/core/server" + cmtproto "github.com/cometbft/cometbft/api/cometbft/types/v1" dbm "github.com/cosmos/cosmos-db" "github.com/stretchr/testify/require" @@ -376,77 +377,6 @@ func wonkyMsg(t *testing.T, cfg client.TxConfig, tx signing.Tx) signing.Tx { require.NoError(t, err) return builder.GetTx() } -<<<<<<< HEAD -======= - -type SendServerImpl struct { - gas uint64 -} - -func (s SendServerImpl) Send(ctx context.Context, send *baseapptestutil.MsgSend) (*baseapptestutil.MsgSendResponse, error) { - sdkCtx := sdk.UnwrapSDKContext(ctx) - if send.From == "" { - return nil, errors.New("from address cannot be empty") - } - if send.To == "" { - return nil, errors.New("to address cannot be empty") - } - - _, err := sdk.ParseCoinNormalized(send.Amount) - if err != nil { - return nil, err - } - gas := s.gas - if gas == 0 { - gas = 5 - } - sdkCtx.GasMeter().ConsumeGas(gas, "send test") - return &baseapptestutil.MsgSendResponse{}, nil -} - -type NestedMessgesServerImpl struct { - gas uint64 -} - -func (n NestedMessgesServerImpl) Check(ctx context.Context, message *baseapptestutil.MsgNestedMessages) (*baseapptestutil.MsgCreateNestedMessagesResponse, error) { - sdkCtx := sdk.UnwrapSDKContext(ctx) - cdc := codectestutil.CodecOptions{}.NewCodec() - baseapptestutil.RegisterInterfaces(cdc.InterfaceRegistry()) - - signer, _, err := cdc.GetMsgSigners(message) - if err != nil { - return nil, err - } - if len(signer) != 1 { - return nil, fmt.Errorf("expected 1 signer, got %d", len(signer)) - } - - msgs, err := message.GetMsgs() - if err != nil { - return nil, err - } - - for _, msg := range msgs { - s, _, err := cdc.GetMsgSigners(msg) - if err != nil { - return nil, err - } - if len(s) != 1 { - return nil, fmt.Errorf("expected 1 signer, got %d", len(s)) - } - if !bytes.Equal(signer[0], s[0]) { - return nil, errors.New("signer does not match") - } - - } - - gas := n.gas - if gas == 0 { - gas = 5 - } - sdkCtx.GasMeter().ConsumeGas(gas, "nested messages test") - return nil, nil -} func newMockedVersionModifier(startingVersion uint64) server.VersionModifier { return &mockedVersionModifier{version: startingVersion} @@ -464,4 +394,3 @@ func (m *mockedVersionModifier) SetAppVersion(ctx context.Context, u uint64) err func (m *mockedVersionModifier) AppVersion(ctx context.Context) (uint64, error) { return m.version, nil } ->>>>>>> dce0365c2 (feat: unify version modifier for v2 (#21508)) diff --git a/core/server/app.go b/core/server/app.go deleted file mode 100644 index 9576fa8825f8..000000000000 --- a/core/server/app.go +++ /dev/null @@ -1,59 +0,0 @@ -package server - -import ( - "context" - "time" - - appmodulev2 "cosmossdk.io/core/appmodule/v2" - "cosmossdk.io/core/event" - "cosmossdk.io/core/transaction" -) - -// BlockRequest defines the request structure for a block coming from consensus server to the state transition function. -type BlockRequest[T transaction.Tx] struct { - 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 -} - -// BlockResponse defines the response structure for a block coming from the state transition function to consensus server. -type BlockResponse struct { - ValidatorUpdates []appmodulev2.ValidatorUpdate - PreBlockEvents []event.Event - BeginBlockEvents []event.Event - TxResults []TxResult - EndBlockEvents []event.Event -} - -// TxResult defines the result of a transaction execution. -type TxResult struct { - // Events produced by the transaction. - Events []event.Event - // Response messages produced by the transaction. - Resp []transaction.Msg - // Error produced by the transaction. - Error error - // Code produced by the transaction. - // A non-zero code is an error that is either define by the module via the cosmossdk.io/errors/v2 package - // or injected through the antehandler along the execution of the transaction. - Code uint32 - // GasWanted is the maximum units of work we allow this tx to perform. - GasWanted uint64 - // GasUsed is the amount of gas actually consumed. - GasUsed uint64 -} - -// VersionModifier defines the interface fulfilled by BaseApp -// which allows getting and setting its appVersion field. This -// in turn updates the consensus params that are sent to the -// consensus engine in EndBlock -type VersionModifier interface { - SetAppVersion(context.Context, uint64) error - AppVersion(context.Context) (uint64, error) -} diff --git a/runtime/v2/module.go b/runtime/v2/module.go deleted file mode 100644 index 1cda0a577fd4..000000000000 --- a/runtime/v2/module.go +++ /dev/null @@ -1,238 +0,0 @@ -package runtime - -import ( - "fmt" - "os" - "slices" - - "github.com/cosmos/gogoproto/proto" - "github.com/spf13/viper" - "google.golang.org/grpc" - "google.golang.org/protobuf/reflect/protodesc" - "google.golang.org/protobuf/reflect/protoregistry" - - runtimev2 "cosmossdk.io/api/cosmos/app/runtime/v2" - appv1alpha1 "cosmossdk.io/api/cosmos/app/v1alpha1" - autocliv1 "cosmossdk.io/api/cosmos/autocli/v1" - reflectionv1 "cosmossdk.io/api/cosmos/reflection/v1" - appmodulev2 "cosmossdk.io/core/appmodule/v2" - "cosmossdk.io/core/comet" - "cosmossdk.io/core/registry" - "cosmossdk.io/core/store" - "cosmossdk.io/core/transaction" - "cosmossdk.io/depinject" - "cosmossdk.io/depinject/appconfig" - "cosmossdk.io/log" - "cosmossdk.io/runtime/v2/services" - "cosmossdk.io/server/v2/stf" -) - -var ( - _ appmodulev2.AppModule = appModule[transaction.Tx]{} - _ hasServicesV1 = appModule[transaction.Tx]{} -) - -type appModule[T transaction.Tx] struct { - app *App[T] -} - -func (m appModule[T]) IsOnePerModuleType() {} -func (m appModule[T]) IsAppModule() {} - -func (m appModule[T]) RegisterServices(registar grpc.ServiceRegistrar) error { - autoCliQueryService, err := services.NewAutoCLIQueryService(m.app.moduleManager.modules) - if err != nil { - return err - } - - autocliv1.RegisterQueryServer(registar, autoCliQueryService) - - reflectionSvc, err := services.NewReflectionService() - if err != nil { - return err - } - reflectionv1.RegisterReflectionServiceServer(registar, reflectionSvc) - - return nil -} - -func (m appModule[T]) AutoCLIOptions() *autocliv1.ModuleOptions { - return &autocliv1.ModuleOptions{ - Query: &autocliv1.ServiceCommandDescriptor{ - Service: appv1alpha1.Query_ServiceDesc.ServiceName, - RpcCommandOptions: []*autocliv1.RpcCommandOptions{ - { - RpcMethod: "Config", - Short: "Query the current app config", - }, - }, - SubCommands: map[string]*autocliv1.ServiceCommandDescriptor{ - "autocli": { - Service: autocliv1.Query_ServiceDesc.ServiceName, - RpcCommandOptions: []*autocliv1.RpcCommandOptions{ - { - RpcMethod: "AppOptions", - Short: "Query the custom autocli options", - }, - }, - }, - "reflection": { - Service: reflectionv1.ReflectionService_ServiceDesc.ServiceName, - RpcCommandOptions: []*autocliv1.RpcCommandOptions{ - { - RpcMethod: "FileDescriptors", - Short: "Query the app's protobuf file descriptors", - }, - }, - }, - }, - }, - } -} - -func init() { - appconfig.Register(&runtimev2.Module{}, - appconfig.Provide( - ProvideAppBuilder[transaction.Tx], - ProvideEnvironment[transaction.Tx], - ProvideModuleManager[transaction.Tx], - ProvideCometService, - ), - appconfig.Invoke(SetupAppBuilder), - ) -} - -func ProvideAppBuilder[T transaction.Tx]( - interfaceRegistrar registry.InterfaceRegistrar, - amino registry.AminoRegistrar, -) ( - *AppBuilder[T], - *stf.MsgRouterBuilder, - appmodulev2.AppModule, - protodesc.Resolver, - protoregistry.MessageTypeResolver, -) { - protoFiles := proto.HybridResolver - protoTypes := protoregistry.GlobalTypes - - // At startup, check that all proto annotations are correct. - if err := validateProtoAnnotations(protoFiles); err != nil { - // Once we switch to using protoreflect-based ante handlers, we might - // want to panic here instead of logging a warning. - _, _ = fmt.Fprintln(os.Stderr, err.Error()) - } - - msgRouterBuilder := stf.NewMsgRouterBuilder() - app := &App[T]{ - storeKeys: nil, - interfaceRegistrar: interfaceRegistrar, - amino: amino, - msgRouterBuilder: msgRouterBuilder, - queryRouterBuilder: stf.NewMsgRouterBuilder(), // TODO dedicated query router - GRPCMethodsToMessageMap: map[string]func() proto.Message{}, - } - appBuilder := &AppBuilder[T]{app: app} - - return appBuilder, msgRouterBuilder, appModule[T]{app}, protoFiles, protoTypes -} - -type AppInputs struct { - depinject.In - - Config *runtimev2.Module - AppBuilder *AppBuilder[transaction.Tx] - ModuleManager *MM[transaction.Tx] - InterfaceRegistrar registry.InterfaceRegistrar - LegacyAmino registry.AminoRegistrar - Logger log.Logger - Viper *viper.Viper `optional:"true"` // can be nil in client wiring -} - -func SetupAppBuilder(inputs AppInputs) { - app := inputs.AppBuilder.app - app.config = inputs.Config - app.logger = inputs.Logger - app.moduleManager = inputs.ModuleManager - app.moduleManager.RegisterInterfaces(inputs.InterfaceRegistrar) - app.moduleManager.RegisterLegacyAminoCodec(inputs.LegacyAmino) - - if inputs.Viper != nil { - inputs.AppBuilder.viper = inputs.Viper - } -} - -func ProvideModuleManager[T transaction.Tx]( - logger log.Logger, - config *runtimev2.Module, - modules map[string]appmodulev2.AppModule, -) *MM[T] { - return NewModuleManager[T](logger, config, modules) -} - -// ProvideEnvironment provides the environment for keeper modules, while maintaining backward compatibility and provide services directly as well. -func ProvideEnvironment[T transaction.Tx]( - logger log.Logger, - config *runtimev2.Module, - key depinject.ModuleKey, - appBuilder *AppBuilder[T], -) ( - appmodulev2.Environment, - store.KVStoreService, - store.MemoryStoreService, -) { - var ( - kvService store.KVStoreService = failingStoreService{} - memKvService store.MemoryStoreService = failingStoreService{} - ) - - // skips modules that have no store - if !slices.Contains(config.SkipStoreKeys, key.Name()) { - var kvStoreKey string - storeKeyOverride := storeKeyOverride(config, key.Name()) - if storeKeyOverride != nil { - kvStoreKey = storeKeyOverride.KvStoreKey - } else { - kvStoreKey = key.Name() - } - - registerStoreKey(appBuilder, kvStoreKey) - kvService = stf.NewKVStoreService([]byte(kvStoreKey)) - - memStoreKey := fmt.Sprintf("memory:%s", key.Name()) - registerStoreKey(appBuilder, memStoreKey) - memKvService = stf.NewMemoryStoreService([]byte(memStoreKey)) - } - - env := appmodulev2.Environment{ - Logger: logger, - BranchService: stf.BranchService{}, - EventService: stf.NewEventService(), - GasService: stf.NewGasMeterService(), - HeaderService: stf.HeaderService{}, - QueryRouterService: stf.NewQueryRouterService(), - MsgRouterService: stf.NewMsgRouterService([]byte(key.Name())), - TransactionService: services.NewContextAwareTransactionService(), - KVStoreService: kvService, - MemStoreService: memKvService, - } - - return env, kvService, memKvService -} - -func registerStoreKey[T transaction.Tx](wrapper *AppBuilder[T], key string) { - wrapper.app.storeKeys = append(wrapper.app.storeKeys, key) -} - -func storeKeyOverride(config *runtimev2.Module, moduleName string) *runtimev2.StoreKeyConfig { - for _, cfg := range config.OverrideStoreKeys { - if cfg.ModuleName == moduleName { - return cfg - } - } - - return nil -} - -func ProvideCometService() comet.Service { - return &services.ContextAwareCometInfoService{} -} diff --git a/server/v2/stf/core_branch_service.go b/server/v2/stf/core_branch_service.go deleted file mode 100644 index 5a83dff6be7c..000000000000 --- a/server/v2/stf/core_branch_service.go +++ /dev/null @@ -1,85 +0,0 @@ -package stf - -import ( - "context" - - "cosmossdk.io/core/branch" - "cosmossdk.io/core/store" -) - -type branchFn func(state store.ReaderMap) store.WriterMap - -var _ branch.Service = (*BranchService)(nil) - -type BranchService struct{} - -func (bs BranchService) Execute(ctx context.Context, f func(ctx context.Context) error) error { - exCtx, err := getExecutionCtxFromContext(ctx) - if err != nil { - return err - } - - return bs.execute(exCtx, f) -} - -func (bs BranchService) ExecuteWithGasLimit( - ctx context.Context, - gasLimit uint64, - f func(ctx context.Context) error, -) (gasUsed uint64, err error) { - exCtx, err := getExecutionCtxFromContext(ctx) - if err != nil { - return 0, err - } - - originalGasMeter := exCtx.meter - - exCtx.setGasLimit(gasLimit) - - // execute branched, with predefined gas limit. - err = bs.execute(exCtx, f) - // restore original context - gasUsed = exCtx.meter.Limit() - exCtx.meter.Remaining() - _ = originalGasMeter.Consume(gasUsed, "execute-with-gas-limit") - exCtx.setGasLimit(originalGasMeter.Remaining()) - - return gasUsed, err -} - -func (bs BranchService) execute(ctx *executionContext, f func(ctx context.Context) error) error { - branchedState := ctx.branchFn(ctx.unmeteredState) - meteredBranchedState := ctx.makeGasMeteredStore(ctx.meter, branchedState) - - branchedCtx := &executionContext{ - Context: ctx.Context, - unmeteredState: branchedState, - state: meteredBranchedState, - meter: ctx.meter, - events: nil, - sender: ctx.sender, - headerInfo: ctx.headerInfo, - execMode: ctx.execMode, - branchFn: ctx.branchFn, - makeGasMeter: ctx.makeGasMeter, - makeGasMeteredStore: ctx.makeGasMeteredStore, - msgRouter: ctx.msgRouter, - queryRouter: ctx.queryRouter, - } - - err := f(branchedCtx) - if err != nil { - return err - } - - // apply state changes to original state - if len(branchedCtx.events) != 0 { - ctx.events = append(ctx.events, branchedCtx.events...) - } - - err = applyStateChanges(ctx.state, branchedCtx.unmeteredState) - if err != nil { - return err - } - - return nil -} diff --git a/server/v2/stf/core_branch_service_test.go b/server/v2/stf/core_branch_service_test.go deleted file mode 100644 index 0394ce0f3b1a..000000000000 --- a/server/v2/stf/core_branch_service_test.go +++ /dev/null @@ -1,110 +0,0 @@ -package stf - -import ( - "context" - "errors" - "testing" - - appmodulev2 "cosmossdk.io/core/appmodule/v2" - "cosmossdk.io/server/v2/stf/branch" - "cosmossdk.io/server/v2/stf/gas" - "cosmossdk.io/server/v2/stf/mock" - gogotypes "github.com/cosmos/gogoproto/types" -) - -func TestBranchService(t *testing.T) { - s := &STF[mock.Tx]{ - doPreBlock: func(ctx context.Context, txs []mock.Tx) error { return nil }, - doBeginBlock: func(ctx context.Context) error { - kvSet(t, ctx, "begin-block") - return nil - }, - doEndBlock: func(ctx context.Context) error { - kvSet(t, ctx, "end-block") - return nil - }, - doValidatorUpdate: func(ctx context.Context) ([]appmodulev2.ValidatorUpdate, error) { return nil, nil }, - doTxValidation: func(ctx context.Context, tx mock.Tx) error { - kvSet(t, ctx, "validate") - return nil - }, - postTxExec: func(ctx context.Context, tx mock.Tx, success bool) error { - kvSet(t, ctx, "post-tx-exec") - return nil - }, - branchFn: branch.DefaultNewWriterMap, - makeGasMeter: gas.DefaultGasMeter, - makeGasMeteredState: gas.DefaultWrapWithGasMeter, - } - addMsgHandlerToSTF(t, s, func(ctx context.Context, msg *gogotypes.BoolValue) (*gogotypes.BoolValue, error) { - kvSet(t, ctx, "exec") - return nil, nil - }) - - makeContext := func() *executionContext { - state := mock.DB() - writableState := s.branchFn(state) - ctx := s.makeContext(context.Background(), []byte("cookies"), writableState, 0) - ctx.setGasLimit(1000000) - return ctx - } - - branchService := BranchService{} - - // TODO: add events check + gas limit precision test - - t.Run("ok", func(t *testing.T) { - stfCtx := makeContext() - gasUsed, err := branchService.ExecuteWithGasLimit(stfCtx, 10000, func(ctx context.Context) error { - kvSet(t, ctx, "cookies") - return nil - }) - if err != nil { - t.Errorf("unexpected error: %v", err) - } - if gasUsed == 0 { - t.Error("expected non-zero gasUsed") - } - stateHas(t, stfCtx.state, "cookies") - }) - - t.Run("fail - reverts state", func(t *testing.T) { - stfCtx := makeContext() - originalGas := stfCtx.meter.Remaining() - gasUsed, err := branchService.ExecuteWithGasLimit(stfCtx, 10000, func(ctx context.Context) error { - kvSet(t, ctx, "cookies") - return errors.New("fail") - }) - if err == nil { - t.Error("expected error") - } - if gasUsed == 0 { - t.Error("expected non-zero gasUsed") - } - if stfCtx.meter.Remaining() != originalGas-gasUsed { - t.Error("expected gas to be reverted") - } - - stateNotHas(t, stfCtx.state, "cookies") - }) - - t.Run("fail - out of gas", func(t *testing.T) { - stfCtx := makeContext() - - gasUsed, err := branchService.ExecuteWithGasLimit(stfCtx, 4000, func(ctx context.Context) error { - state, _ := ctx.(*executionContext).state.GetWriter(actorName) - _ = state.Set([]byte("not out of gas"), []byte{}) - return state.Set([]byte("out of gas"), []byte{}) - }) - if err == nil { - t.Error("expected error") - } - if gasUsed == 0 { - t.Error("expected non-zero gasUsed") - } - stateNotHas(t, stfCtx.state, "cookies") - if stfCtx.meter.Limit()-stfCtx.meter.Remaining() != 1000 { - t.Error("expected gas limit precision to be 1000") - } - }) -} diff --git a/simapp/v2/go.mod b/simapp/v2/go.mod index 310cf9938de0..d890ce0280d6 100644 --- a/simapp/v2/go.mod +++ b/simapp/v2/go.mod @@ -10,7 +10,7 @@ require ( cosmossdk.io/depinject v1.0.0 cosmossdk.io/log v1.4.1 cosmossdk.io/math v1.3.0 - cosmossdk.io/runtime/v2 v2.0.0-20240905114452-a57b25418a59 // main + cosmossdk.io/runtime/v2 v2.0.0-20240906155629-dce0365c234b // main cosmossdk.io/server/v2 v2.0.0-20240829074658-81a225e6a29b // main cosmossdk.io/server/v2/cometbft v0.0.0-00010101000000-000000000000 cosmossdk.io/store/v2 v2.0.0-20240906090851-36d9b25e8981 // main diff --git a/simapp/v2/go.sum b/simapp/v2/go.sum index ace10a1275a8..9f30c4a3dcab 100644 --- a/simapp/v2/go.sum +++ b/simapp/v2/go.sum @@ -210,8 +210,8 @@ cosmossdk.io/log v1.4.1 h1:wKdjfDRbDyZRuWa8M+9nuvpVYxrEOwbD/CA8hvhU8QM= cosmossdk.io/log v1.4.1/go.mod h1:k08v0Pyq+gCP6phvdI6RCGhLf/r425UT6Rk/m+o74rU= cosmossdk.io/math v1.3.0 h1:RC+jryuKeytIiictDslBP9i1fhkVm6ZDmZEoNP316zE= cosmossdk.io/math v1.3.0/go.mod h1:vnRTxewy+M7BtXBNFybkuhSH4WfedVAAnERHgVFhp3k= -cosmossdk.io/runtime/v2 v2.0.0-20240905114452-a57b25418a59 h1:9p9X7mTme7w0dznm6Zqr5APd7qhakJZx7CqGJyAYtYE= -cosmossdk.io/runtime/v2 v2.0.0-20240905114452-a57b25418a59/go.mod h1:yrRIRz4pLdpntieuC6DrCx+7AZGcy6zVI1kOEYzZTmo= +cosmossdk.io/runtime/v2 v2.0.0-20240906155629-dce0365c234b h1:jxpSMaMYYbkD7Ydt6YgbBev4txSyeSQhJJyMQ9ZNZrs= +cosmossdk.io/runtime/v2 v2.0.0-20240906155629-dce0365c234b/go.mod h1:dS/uElxFZjZUgwEjjRh8qE84OoavL8Yd6gEdUOGtkjQ= cosmossdk.io/schema v0.2.0 h1:UH5CR1DqUq8yP+5Np8PbvG4YX0zAUsTN2Qk6yThmfMk= cosmossdk.io/schema v0.2.0/go.mod h1:RDAhxIeNB4bYqAlF4NBJwRrgtnciMcyyg0DOKnhNZQQ= cosmossdk.io/server/v2 v2.0.0-20240829074658-81a225e6a29b h1:FFixNVq2SbtRlYvr1fB/WikfYTRrA0o/35ImIhhZzrE= From 546a6a4327f285dfc759fa5b35ddea66ba9f5c97 Mon Sep 17 00:00:00 2001 From: Julien Robert Date: Fri, 6 Sep 2024 19:24:47 +0200 Subject: [PATCH 3/5] lint --- baseapp/baseapp.go | 2 +- baseapp/options.go | 3 ++- baseapp/utils_test.go | 3 +-- x/consensus/depinject.go | 2 ++ 4 files changed, 6 insertions(+), 4 deletions(-) diff --git a/baseapp/baseapp.go b/baseapp/baseapp.go index 2638cbe60ae7..2e3640519f9c 100644 --- a/baseapp/baseapp.go +++ b/baseapp/baseapp.go @@ -2,7 +2,6 @@ package baseapp import ( "context" - "cosmossdk.io/core/server" "errors" "fmt" "maps" @@ -18,6 +17,7 @@ import ( "google.golang.org/protobuf/reflect/protoreflect" "cosmossdk.io/core/header" + "cosmossdk.io/core/server" corestore "cosmossdk.io/core/store" errorsmod "cosmossdk.io/errors" "cosmossdk.io/log" diff --git a/baseapp/options.go b/baseapp/options.go index 7500e070710c..abe66049da3c 100644 --- a/baseapp/options.go +++ b/baseapp/options.go @@ -2,12 +2,13 @@ package baseapp import ( "context" - "cosmossdk.io/core/server" "errors" "fmt" "io" "math" + "cosmossdk.io/core/server" + corestore "cosmossdk.io/core/store" "cosmossdk.io/store/metrics" pruningtypes "cosmossdk.io/store/pruning/types" diff --git a/baseapp/utils_test.go b/baseapp/utils_test.go index 96458289c94a..5715d57d134e 100644 --- a/baseapp/utils_test.go +++ b/baseapp/utils_test.go @@ -13,8 +13,6 @@ import ( "testing" "unsafe" - "cosmossdk.io/core/server" - cmtproto "github.com/cometbft/cometbft/api/cometbft/types/v1" dbm "github.com/cosmos/cosmos-db" "github.com/stretchr/testify/require" @@ -22,6 +20,7 @@ import ( runtimev1alpha1 "cosmossdk.io/api/cosmos/app/runtime/v1alpha1" appv1alpha1 "cosmossdk.io/api/cosmos/app/v1alpha1" "cosmossdk.io/core/address" + "cosmossdk.io/core/server" "cosmossdk.io/depinject" "cosmossdk.io/depinject/appconfig" errorsmod "cosmossdk.io/errors" diff --git a/x/consensus/depinject.go b/x/consensus/depinject.go index 07048b4c8684..f5e71717c724 100644 --- a/x/consensus/depinject.go +++ b/x/consensus/depinject.go @@ -2,6 +2,7 @@ package consensus import ( "context" + modulev1 "cosmossdk.io/api/cosmos/consensus/module/v1" "cosmossdk.io/core/address" "cosmossdk.io/core/appmodule" @@ -9,6 +10,7 @@ import ( "cosmossdk.io/depinject" "cosmossdk.io/depinject/appconfig" "cosmossdk.io/x/consensus/keeper" + "github.com/cosmos/cosmos-sdk/baseapp" "github.com/cosmos/cosmos-sdk/codec" "github.com/cosmos/cosmos-sdk/runtime" From 1e0e1546d08bc1c6f24dc9922b4d679ee498cb95 Mon Sep 17 00:00:00 2001 From: Julien Robert Date: Fri, 6 Sep 2024 20:44:58 +0200 Subject: [PATCH 4/5] lint fixes --- baseapp/options.go | 1 - 1 file changed, 1 deletion(-) diff --git a/baseapp/options.go b/baseapp/options.go index abe66049da3c..05962ec06c0a 100644 --- a/baseapp/options.go +++ b/baseapp/options.go @@ -8,7 +8,6 @@ import ( "math" "cosmossdk.io/core/server" - corestore "cosmossdk.io/core/store" "cosmossdk.io/store/metrics" pruningtypes "cosmossdk.io/store/pruning/types" From f4194a9531cb667041400ecd4a3dabc8d634295b Mon Sep 17 00:00:00 2001 From: Julien Robert Date: Fri, 6 Sep 2024 20:48:46 +0200 Subject: [PATCH 5/5] fix upgrades --- x/upgrade/keeper/abci_test.go | 19 +++++++++++++++++++ x/upgrade/keeper/keeper_test.go | 2 ++ 2 files changed, 21 insertions(+) diff --git a/x/upgrade/keeper/abci_test.go b/x/upgrade/keeper/abci_test.go index 5ae0fd23ff7d..200594436f95 100644 --- a/x/upgrade/keeper/abci_test.go +++ b/x/upgrade/keeper/abci_test.go @@ -12,6 +12,7 @@ import ( "cosmossdk.io/core/appmodule" "cosmossdk.io/core/header" + "cosmossdk.io/core/server" coretesting "cosmossdk.io/core/testing" "cosmossdk.io/log" storetypes "cosmossdk.io/store/types" @@ -132,6 +133,7 @@ func setupTest(t *testing.T, height int64, skip map[int64]bool) *TestSuite { s.env = runtime.NewEnvironment(storeService, coretesting.NewNopLogger(), runtime.EnvWithMsgRouterService(s.baseApp.MsgServiceRouter()), runtime.EnvWithQueryRouterService(s.baseApp.GRPCQueryRouter())) s.baseApp.SetParamStore(¶mStore{params: cmtproto.ConsensusParams{Version: &cmtproto.VersionParams{App: 1}}}) + s.baseApp.SetVersionModifier(newMockedVersionModifier(1)) authority, err := addresscodec.NewBech32Codec("cosmos").BytesToString(authtypes.NewModuleAddress(govModuleName)) require.NoError(t, err) @@ -144,6 +146,23 @@ func setupTest(t *testing.T, height int64, skip map[int64]bool) *TestSuite { return &s } +func newMockedVersionModifier(startingVersion uint64) server.VersionModifier { + return &mockedVersionModifier{version: startingVersion} +} + +type mockedVersionModifier struct { + version uint64 +} + +func (m *mockedVersionModifier) SetAppVersion(ctx context.Context, u uint64) error { + m.version = u + return nil +} + +func (m *mockedVersionModifier) AppVersion(ctx context.Context) (uint64, error) { + return m.version, nil +} + func TestRequireFutureBlock(t *testing.T) { s := setupTest(t, 10, map[int64]bool{}) err := s.keeper.ScheduleUpgrade(s.ctx, types.Plan{Name: "test", Height: s.ctx.HeaderInfo().Height - 1}) diff --git a/x/upgrade/keeper/keeper_test.go b/x/upgrade/keeper/keeper_test.go index 0aabb13500b9..d211c8fedcfe 100644 --- a/x/upgrade/keeper/keeper_test.go +++ b/x/upgrade/keeper/keeper_test.go @@ -60,6 +60,8 @@ func (s *KeeperTestSuite) SetupTest() { s.encCfg.TxConfig.TxDecoder(), ) s.baseApp.SetParamStore(¶mStore{params: cmttypes.DefaultConsensusParams().ToProto()}) + s.baseApp.SetVersionModifier(newMockedVersionModifier(0)) + appVersion, err := s.baseApp.AppVersion(context.Background()) s.Require().NoError(err) s.Require().Equal(uint64(0), appVersion)