refactor(server)!: continue server v1 removal (#23238)

This commit is contained in:
Julien Robert 2025-01-08 13:18:19 +01:00 committed by GitHub
parent 597c176900
commit c5b3033b3a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
50 changed files with 183 additions and 3218 deletions

View File

@ -61,6 +61,15 @@ Every module contains its own CHANGELOG.md. Please refer to the module you are i
* (x/params) [#22995](https://github.com/cosmos/cosmos-sdk/pull/22995) Remove `x/params`. Migrate to the new params system introduced in `v0.47` as demonstrated [here](https://github.com/cosmos/cosmos-sdk/blob/main/UPGRADING.md#xparams).
* (testutil) [#22392](https://github.com/cosmos/cosmos-sdk/pull/22392) Remove `testutil/network` package. Use the integration framework or systemtests framework instead.
#### Removal of v1 components
This subsection lists the API breaking changes that are [part of the removal of v1 components](https://github.com/cosmos/cosmos-sdk/issues/22904). The v1 components were deprecated in `v0.52` and are now removed.
* (simapp) [#23009](https://github.com/cosmos/cosmos-sdk/pull/23009) Simapp has been removed. Check-out Simapp/v2 instead.
* (server) [#23018](https://github.com/cosmos/cosmos-sdk/pull/23018) [#23238](https://github.com/cosmos/cosmos-sdk/pull/23238) The server package has been removed. Use server/v2 instead
* (x/genutil) [#23238](https://github.com/cosmos/cosmos-sdk/pull/23238) Genutil commands specific to a baseapp chain have been deleted.
* (client) [#22904](https://github.com/cosmos/cosmos-sdk/issues/22904) v1 specific client commands have been removed.
### Deprecated
* (modules) [#22994](https://github.com/cosmos/cosmos-sdk/pull/22994) Deprecate `Invariants` and associated methods.

View File

@ -1833,7 +1833,7 @@ type ListImplementationsRequest struct {
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
// interface_name defines the interface to query the implementations for.
// interface_name defines the interface to query the implementations.
InterfaceName string `protobuf:"bytes,1,opt,name=interface_name,json=interfaceName,proto3" json:"interface_name,omitempty"`
}

View File

@ -29,7 +29,6 @@ import (
"github.com/cosmos/cosmos-sdk/baseapp/oe"
"github.com/cosmos/cosmos-sdk/codec"
codectypes "github.com/cosmos/cosmos-sdk/codec/types"
servertypes "github.com/cosmos/cosmos-sdk/server/types"
"github.com/cosmos/cosmos-sdk/telemetry"
sdk "github.com/cosmos/cosmos-sdk/types"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
@ -58,8 +57,6 @@ const (
execModeFinalize // Finalize a block proposal
)
var _ servertypes.ABCI = (*BaseApp)(nil)
// BaseApp reflects the ABCI application implementation.
type BaseApp struct {
// initialized on creation

View File

@ -12,6 +12,7 @@ import (
abci "github.com/cometbft/cometbft/api/cometbft/abci/v1"
"github.com/spf13/cast"
"cosmossdk.io/core/server"
"cosmossdk.io/log"
"cosmossdk.io/schema"
"cosmossdk.io/schema/appdata"
@ -21,7 +22,6 @@ import (
storetypes "cosmossdk.io/store/types"
"github.com/cosmos/cosmos-sdk/client/flags"
servertypes "github.com/cosmos/cosmos-sdk/server/types"
sdk "github.com/cosmos/cosmos-sdk/types"
)
@ -60,7 +60,7 @@ func (app *BaseApp) EnableIndexer(indexerOpts interface{}, keys map[string]*stor
}
// RegisterStreamingServices registers streaming services with the BaseApp.
func (app *BaseApp) RegisterStreamingServices(appOpts servertypes.AppOptions, keys map[string]*storetypes.KVStoreKey) error {
func (app *BaseApp) RegisterStreamingServices(appOpts server.DynamicConfig, keys map[string]*storetypes.KVStoreKey) error {
// register streaming services
streamingCfg := cast.ToStringMap(appOpts.Get(StreamingTomlKey))
for service := range streamingCfg {
@ -83,7 +83,7 @@ func (app *BaseApp) RegisterStreamingServices(appOpts servertypes.AppOptions, ke
// registerStreamingPlugin registers streaming plugins with the BaseApp.
func (app *BaseApp) registerStreamingPlugin(
appOpts servertypes.AppOptions,
appOpts server.DynamicConfig,
keys map[string]*storetypes.KVStoreKey,
streamingPlugin interface{},
) error {
@ -98,7 +98,7 @@ func (app *BaseApp) registerStreamingPlugin(
// registerABCIListenerPlugin registers plugins that implement the ABCIListener interface.
func (app *BaseApp) registerABCIListenerPlugin(
appOpts servertypes.AppOptions,
appOpts server.DynamicConfig,
keys map[string]*storetypes.KVStoreKey,
abciListener storetypes.ABCIListener,
) {

View File

@ -83,6 +83,7 @@ const (
FlagTip = "tip"
FlagAux = "aux"
FlagInitHeight = "initial-height"
FlagInvCheckPeriod = "inv-check-period"
// FlagOutput is the flag to set the output format.
// This differs from FlagOutputDocument that is used to set the output file.
FlagOutput = "output"
@ -90,6 +91,7 @@ const (
FlagLogLevel = "log_level"
FlagLogFormat = "log_format"
FlagLogNoColor = "log_no_color"
FlagTrace = "trace"
)
// List of supported output formats

View File

@ -1,65 +0,0 @@
package node
import (
"context"
gogogrpc "github.com/cosmos/gogoproto/grpc"
"github.com/grpc-ecosystem/grpc-gateway/runtime"
"github.com/cosmos/cosmos-sdk/client"
"github.com/cosmos/cosmos-sdk/server/config"
sdk "github.com/cosmos/cosmos-sdk/types"
)
// RegisterNodeService registers the node gRPC service on the provided gRPC router.
func RegisterNodeService(clientCtx client.Context, server gogogrpc.Server, cfg config.Config) {
RegisterServiceServer(server, NewQueryServer(clientCtx, cfg))
}
// RegisterGRPCGatewayRoutes mounts the node gRPC service's GRPC-gateway routes
// on the given mux object.
func RegisterGRPCGatewayRoutes(clientConn gogogrpc.ClientConn, mux *runtime.ServeMux) {
_ = RegisterServiceHandlerClient(context.Background(), mux, NewServiceClient(clientConn))
}
var _ ServiceServer = queryServer{}
type queryServer struct {
clientCtx client.Context
cfg config.Config
}
func NewQueryServer(clientCtx client.Context, cfg config.Config) ServiceServer {
return queryServer{
clientCtx: clientCtx,
cfg: cfg,
}
}
func (s queryServer) Config(ctx context.Context, _ *ConfigRequest) (*ConfigResponse, error) {
sdkCtx := sdk.UnwrapSDKContext(ctx)
return &ConfigResponse{
MinimumGasPrice: sdkCtx.MinGasPrices().String(),
PruningKeepRecent: s.cfg.PruningKeepRecent,
PruningInterval: s.cfg.PruningInterval,
HaltHeight: s.cfg.HaltHeight,
}, nil
}
func (s queryServer) Status(ctx context.Context, _ *StatusRequest) (*StatusResponse, error) {
sdkCtx := sdk.UnwrapSDKContext(ctx)
blockTime := sdkCtx.HeaderInfo().Time
return &StatusResponse{
// TODO: Get earliest version from store.
//
// Ref: ...
// EarliestStoreHeight: sdkCtx.MultiStore(),
Height: uint64(sdkCtx.BlockHeight()),
Timestamp: &blockTime,
AppHash: sdkCtx.BlockHeader().AppHash,
ValidatorHash: sdkCtx.BlockHeader().NextValidatorsHash,
}, nil
}

View File

@ -1,28 +0,0 @@
package node
import (
"testing"
"github.com/stretchr/testify/require"
"github.com/cosmos/cosmos-sdk/client"
"github.com/cosmos/cosmos-sdk/server/config"
sdk "github.com/cosmos/cosmos-sdk/types"
)
func TestServiceServer_Config(t *testing.T) {
defaultCfg := config.DefaultConfig()
defaultCfg.PruningKeepRecent = "2000"
defaultCfg.PruningInterval = "10"
defaultCfg.HaltHeight = 100
svr := NewQueryServer(client.Context{}, *defaultCfg)
ctx := sdk.Context{}.WithMinGasPrices(sdk.NewDecCoins(sdk.NewInt64DecCoin("stake", 15)))
resp, err := svr.Config(ctx, &ConfigRequest{})
require.NoError(t, err)
require.NotNil(t, resp)
require.Equal(t, ctx.MinGasPrices().String(), resp.MinimumGasPrice)
require.Equal(t, defaultCfg.PruningKeepRecent, resp.PruningKeepRecent)
require.Equal(t, defaultCfg.PruningInterval, resp.PruningInterval)
require.Equal(t, defaultCfg.HaltHeight, resp.HaltHeight)
}

View File

@ -300,12 +300,12 @@ type ReflectionServiceServer interface {
ListImplementations(context.Context, *ListImplementationsRequest) (*ListImplementationsResponse, error)
}
// UnimplementedReflectionServiceServer can be embedded to have forward-compatible implementations.
// UnimplementedReflectionServiceServer can be embedded to have forward compatible implementations.
type UnimplementedReflectionServiceServer struct {
}
func (*UnimplementedReflectionServiceServer) ListAllInterfaces(ctx context.Context, req *ListAllInterfacesRequest) (*ListAllInterfacesResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method ListAllInterfaces is not implemented")
return nil, status.Errorf(codes.Unimplemented, "method ListAllInterfaces not implemented")
}
func (*UnimplementedReflectionServiceServer) ListImplementations(ctx context.Context, req *ListImplementationsRequest) (*ListImplementationsResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method ListImplementations not implemented")

View File

@ -3870,7 +3870,7 @@ type MsgRequest struct {
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
// u32 is an uint32
// u32 is a uint32
U32 uint32 `protobuf:"varint,1,opt,name=u32,proto3" json:"u32,omitempty"`
U64 uint64 `protobuf:"varint,2,opt,name=u64,proto3" json:"u64,omitempty"`
Str string `protobuf:"bytes,3,opt,name=str,proto3" json:"str,omitempty"`

2
go.mod
View File

@ -41,7 +41,6 @@ require (
github.com/muesli/termenv v0.15.2
github.com/prometheus/client_golang v1.20.5
github.com/prometheus/common v0.61.0
github.com/rs/zerolog v1.33.0
github.com/spf13/cast v1.7.1
github.com/spf13/cobra v1.8.1
github.com/spf13/pflag v1.0.5
@ -136,6 +135,7 @@ require (
github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 // indirect
github.com/rivo/uniseg v0.2.0 // indirect
github.com/rogpeppe/go-internal v1.13.1 // indirect
github.com/rs/zerolog v1.33.0 // indirect
github.com/sagikazarmark/locafero v0.4.0 // indirect
github.com/sagikazarmark/slog-shim v0.1.0 // indirect
github.com/sasha-s/go-deadlock v0.3.5 // indirect

View File

@ -33,7 +33,7 @@ message ListAllInterfacesResponse {
// ListImplementationsRequest is the request type of the ListImplementations
// RPC.
message ListImplementationsRequest {
// interface_name defines the interface to query the implementations for.
// interface_name defines the interface to query the implementations.
string interface_name = 1;
}

View File

@ -18,13 +18,8 @@ import (
"github.com/cosmos/cosmos-sdk/baseapp"
"github.com/cosmos/cosmos-sdk/client"
"github.com/cosmos/cosmos-sdk/client/grpc/cmtservice"
nodeservice "github.com/cosmos/cosmos-sdk/client/grpc/node"
"github.com/cosmos/cosmos-sdk/codec"
codectypes "github.com/cosmos/cosmos-sdk/codec/types"
"github.com/cosmos/cosmos-sdk/server"
"github.com/cosmos/cosmos-sdk/server/config"
servertypes "github.com/cosmos/cosmos-sdk/server/types"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/types/module"
"github.com/cosmos/cosmos-sdk/x/auth/ante/unorderedtx"
@ -221,22 +216,6 @@ func (a *App) RegisterTxService(clientCtx client.Context) {
authtx.RegisterTxService(a.GRPCQueryRouter(), clientCtx, a.Simulate, a.interfaceRegistry)
}
// RegisterTendermintService implements the Application.RegisterTendermintService method.
func (a *App) RegisterTendermintService(clientCtx client.Context) {
cmtApp := server.NewCometABCIWrapper(a)
cmtservice.RegisterTendermintService(
clientCtx,
a.GRPCQueryRouter(),
a.interfaceRegistry,
cmtApp.Query,
)
}
// RegisterNodeService registers the node gRPC service on the app gRPC router.
func (a *App) RegisterNodeService(clientCtx client.Context, cfg config.Config) {
nodeservice.RegisterNodeService(clientCtx, a.GRPCQueryRouter(), cfg)
}
// Configurator returns the app's configurator.
func (a *App) Configurator() module.Configurator { //nolint:staticcheck // SA1019: Configurator is deprecated but still used in runtime v1.
return a.configurator
@ -288,8 +267,6 @@ func (a *App) UnsafeFindStoreKey(storeKey string) storetypes.StoreKey {
return a.storeKeys[i]
}
var _ servertypes.Application = &App{}
// hasServicesV1 is the interface for registering service in baseapp Cosmos SDK.
// This API is part of core/appmodule but commented out for dependencies.
type hasServicesV1 interface {

View File

@ -8,12 +8,12 @@ import (
"github.com/spf13/cast"
"cosmossdk.io/core/server"
corestore "cosmossdk.io/core/store"
storetypes "cosmossdk.io/store/types"
"github.com/cosmos/cosmos-sdk/baseapp"
"github.com/cosmos/cosmos-sdk/client/flags"
servertypes "github.com/cosmos/cosmos-sdk/server/types"
"github.com/cosmos/cosmos-sdk/types/module"
"github.com/cosmos/cosmos-sdk/version"
"github.com/cosmos/cosmos-sdk/x/auth/ante/unorderedtx"
@ -25,7 +25,7 @@ import (
type AppBuilder struct {
app *App
appOptions servertypes.AppOptions
appOptions server.DynamicConfig
}
// DefaultGenesis returns a default genesis from the registered modules.

View File

@ -15,6 +15,7 @@ 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"
@ -24,7 +25,6 @@ import (
"github.com/cosmos/cosmos-sdk/baseapp"
"github.com/cosmos/cosmos-sdk/codec"
codectypes "github.com/cosmos/cosmos-sdk/codec/types"
servertypes "github.com/cosmos/cosmos-sdk/server/types"
"github.com/cosmos/cosmos-sdk/std"
"github.com/cosmos/cosmos-sdk/types/module"
"github.com/cosmos/cosmos-sdk/types/msgservice"
@ -161,7 +161,7 @@ type AppInputs struct {
BaseAppOptions []BaseAppOption
InterfaceRegistry codectypes.InterfaceRegistry
LegacyAmino registry.AminoRegistrar
AppOptions servertypes.AppOptions `optional:"true"` // can be nil in client wiring
AppOptions server.DynamicConfig `optional:"true"` // can be nil in client wiring
}
func SetupAppBuilder(inputs AppInputs) {

View File

@ -1,9 +1,11 @@
package runtime
import (
abci "github.com/cometbft/cometbft/api/cometbft/abci/v1"
"encoding/json"
abci "github.com/cometbft/cometbft/api/cometbft/abci/v1"
cmtproto "github.com/cometbft/cometbft/api/cometbft/types/v1"
"github.com/cosmos/cosmos-sdk/server/types"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/types/module"
)
@ -29,7 +31,20 @@ type AppI interface {
LoadHeight(height int64) error
// ExportAppStateAndValidators exports the state of the application for a genesis file.
ExportAppStateAndValidators(forZeroHeight bool, jailAllowedAddrs, modulesToExport []string) (types.ExportedApp, error)
ExportAppStateAndValidators(forZeroHeight bool, jailAllowedAddrs, modulesToExport []string) (ExportedApp, error)
}
// ExportedApp represents an exported app state, along with
// validators, consensus params and latest app height.
type ExportedApp struct {
// AppState is the application state as JSON.
AppState json.RawMessage
// Validators is the exported validator set.
Validators []sdk.GenesisValidator
// Height is the app's latest block height.
Height int64
// ConsensusParams are the exported consensus params for ABCI.
ConsensusParams cmtproto.ConsensusParams
}
// AppSimI implements the common methods for a Cosmos SDK-based application

View File

@ -1,48 +0,0 @@
package cmd
import (
"context"
"strings"
"github.com/rs/zerolog"
"github.com/spf13/cobra"
"github.com/spf13/viper"
"github.com/cosmos/cosmos-sdk/client"
"github.com/cosmos/cosmos-sdk/client/flags"
"github.com/cosmos/cosmos-sdk/server"
)
// Execute executes the root command of an application. It handles creating a
// server context object with the appropriate server and client objects injected
// into the underlying stdlib Context. It also handles adding core CLI flags,
// specifically the logging flags. It returns an error upon execution failure.
func Execute(rootCmd *cobra.Command, envPrefix, defaultHome string) error {
// Create and set a client.Context on the command's Context. During the pre-run
// of the root command, a default initialized client.Context is provided to
// seed child command execution with values such as AccountRetriever, Keyring,
// and a CometBFT RPC. This requires the use of a pointer reference when
// getting and setting the client.Context. Ideally, we utilize
// https://github.com/spf13/cobra/pull/1118.
ctx := CreateExecuteContext(context.Background())
rootCmd.PersistentFlags().String(flags.FlagLogLevel, zerolog.InfoLevel.String(), "The logging level (trace|debug|info|warn|error|fatal|panic|disabled or '*:<level>,<key>:<level>')")
rootCmd.PersistentFlags().String(flags.FlagLogFormat, "plain", "The logging format (json|plain)")
rootCmd.PersistentFlags().Bool(flags.FlagLogNoColor, false, "Disable colored logs")
rootCmd.PersistentFlags().StringP(flags.FlagHome, "", defaultHome, "directory for config and data")
rootCmd.PersistentFlags().Bool(server.FlagTrace, false, "print out full stack trace on errors")
// update the global viper with the root command's configuration
viper.SetEnvPrefix(envPrefix)
viper.SetEnvKeyReplacer(strings.NewReplacer(".", "_", "-", "_"))
viper.AutomaticEnv()
return rootCmd.ExecuteContext(ctx)
}
// CreateExecuteContext returns a base Context with server and client context
// values initialized.
func CreateExecuteContext(ctx context.Context) context.Context {
ctx = context.WithValue(ctx, client.ClientContextKey, &client.Context{})
return ctx
}

View File

@ -1,282 +0,0 @@
package config
import (
"fmt"
"math"
"github.com/spf13/viper"
pruningtypes "cosmossdk.io/store/pruning/types"
"github.com/cosmos/cosmos-sdk/telemetry"
sdk "github.com/cosmos/cosmos-sdk/types"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
)
const (
defaultMinGasPrices = ""
// DefaultAPIAddress defines the default address to bind the API server to.
DefaultAPIAddress = "tcp://localhost:1317"
// DefaultGRPCAddress defines the default address to bind the gRPC server to.
DefaultGRPCAddress = "localhost:9090"
// DefaultGRPCMaxRecvMsgSize defines the default gRPC max message size in
// bytes the server can receive.
DefaultGRPCMaxRecvMsgSize = 1024 * 1024 * 10
// DefaultGRPCMaxSendMsgSize defines the default gRPC max message size in
// bytes the server can send.
DefaultGRPCMaxSendMsgSize = math.MaxInt32
)
// BaseConfig defines the server's basic configuration
type BaseConfig struct {
// The minimum gas prices a validator is willing to accept for processing a
// transaction. A transaction's fees must meet the minimum of any denomination
// specified in this config (e.g. 0.25token1;0.0001token2).
MinGasPrices string `mapstructure:"minimum-gas-prices"`
// The maximum amount of gas a grpc/Rest query may consume.
// If set to 0, it is unbounded.
QueryGasLimit uint64 `mapstructure:"query-gas-limit"`
Pruning string `mapstructure:"pruning"`
PruningKeepRecent string `mapstructure:"pruning-keep-recent"`
PruningInterval string `mapstructure:"pruning-interval"`
// HaltHeight contains a non-zero block height at which a node will gracefully
// halt and shutdown that can be used to assist upgrades and testing.
//
// Note: Commitment of state will be attempted on the corresponding block.
HaltHeight uint64 `mapstructure:"halt-height"`
// HaltTime contains a non-zero minimum block time (in Unix seconds) at which
// a node will gracefully halt and shutdown that can be used to assist
// upgrades and testing.
//
// Note: Commitment of state will be attempted on the corresponding block.
HaltTime uint64 `mapstructure:"halt-time"`
// MinRetainBlocks defines the minimum block height offset from the current
// block being committed, such that blocks past this offset may be pruned
// from CometBFT. It is used as part of the process of determining the
// ResponseCommit.RetainHeight value during ABCI Commit. A value of 0 indicates
// that no blocks should be pruned.
//
// This configuration value is only responsible for pruning CometBFT blocks.
// It has no bearing on application state pruning which is determined by the
// "pruning-*" configurations.
//
// Note: CometBFT block pruning is dependent on this parameter in conjunction
// with the unbonding (safety threshold) period, state pruning and state sync
// snapshot parameters to determine the correct minimum value of
// ResponseCommit.RetainHeight.
MinRetainBlocks uint64 `mapstructure:"min-retain-blocks"`
// InterBlockCache enables inter-block caching.
InterBlockCache bool `mapstructure:"inter-block-cache"`
// IndexEvents defines the set of events in the form {eventType}.{attributeKey},
// which informs CometBFT what to index. If empty, all events will be indexed.
IndexEvents []string `mapstructure:"index-events"`
// IavlCacheSize set the size of the iavl tree cache.
IAVLCacheSize uint64 `mapstructure:"iavl-cache-size"`
// IAVLDisableFastNode enables or disables the fast sync node.
IAVLDisableFastNode bool `mapstructure:"iavl-disable-fastnode"`
// AppDBBackend defines the type of Database to use for the application and snapshots databases.
// An empty string indicates that the CometBFT config's DBBackend value should be used.
AppDBBackend string `mapstructure:"app-db-backend"`
}
// APIConfig defines the API listener configuration.
type APIConfig struct {
// Enable defines if the API server should be enabled.
Enable bool `mapstructure:"enable"`
// Swagger defines if swagger documentation should automatically be registered.
Swagger bool `mapstructure:"swagger"`
// EnableUnsafeCORS defines if CORS should be enabled (unsafe - use it at your own risk)
EnableUnsafeCORS bool `mapstructure:"enabled-unsafe-cors"`
// Address defines the API server to listen on
Address string `mapstructure:"address"`
// MaxOpenConnections defines the number of maximum open connections
MaxOpenConnections uint `mapstructure:"max-open-connections"`
// RPCReadTimeout defines the CometBFT RPC read timeout (in seconds)
RPCReadTimeout uint `mapstructure:"rpc-read-timeout"`
// RPCWriteTimeout defines the CometBFT RPC write timeout (in seconds)
RPCWriteTimeout uint `mapstructure:"rpc-write-timeout"`
// RPCMaxBodyBytes defines the CometBFT maximum request body (in bytes)
RPCMaxBodyBytes uint `mapstructure:"rpc-max-body-bytes"`
// TODO: TLS/Proxy configuration.
//
// Ref: https://github.com/cosmos/cosmos-sdk/issues/6420
}
// GRPCConfig defines configuration for the gRPC server.
type GRPCConfig struct {
// Enable defines if the gRPC server should be enabled.
Enable bool `mapstructure:"enable"`
// Address defines the API server to listen on
Address string `mapstructure:"address"`
// MaxRecvMsgSize defines the max message size in bytes the server can receive.
// The default value is 10MB.
MaxRecvMsgSize int `mapstructure:"max-recv-msg-size"`
// MaxSendMsgSize defines the max message size in bytes the server can send.
// The default value is math.MaxInt32.
MaxSendMsgSize int `mapstructure:"max-send-msg-size"`
}
// StateSyncConfig defines the state sync snapshot configuration.
type StateSyncConfig struct {
// SnapshotInterval sets the interval at which state sync snapshots are taken.
// 0 disables snapshots.
SnapshotInterval uint64 `mapstructure:"snapshot-interval"`
// SnapshotKeepRecent sets the number of recent state sync snapshots to keep.
// 0 keeps all snapshots.
SnapshotKeepRecent uint32 `mapstructure:"snapshot-keep-recent"`
}
// MempoolConfig defines the configurations for the SDK built-in app-side mempool
// implementations.
type MempoolConfig struct {
// MaxTxs defines the behavior of the mempool. A negative value indicates
// the mempool is disabled entirely, zero indicates that the mempool is
// unbounded in how many txs it may contain, and a positive value indicates
// the maximum amount of txs it may contain.
MaxTxs int `mapstructure:"max-txs"`
}
// State Streaming configuration
type (
// StreamingConfig defines application configuration for external streaming services
StreamingConfig struct {
ABCI ABCIListenerConfig `mapstructure:"abci"`
}
// ABCIListenerConfig defines application configuration for ABCIListener streaming service
ABCIListenerConfig struct {
Keys []string `mapstructure:"keys"`
Plugin string `mapstructure:"plugin"`
StopNodeOnErr bool `mapstructure:"stop-node-on-err"`
}
)
// Config defines the server's top level configuration
type Config struct {
BaseConfig `mapstructure:",squash"`
// Telemetry defines the application telemetry configuration
Telemetry telemetry.Config `mapstructure:"telemetry"`
API APIConfig `mapstructure:"api"`
GRPC GRPCConfig `mapstructure:"grpc"`
StateSync StateSyncConfig `mapstructure:"state-sync"`
Streaming StreamingConfig `mapstructure:"streaming"`
Mempool MempoolConfig `mapstructure:"mempool"`
}
// SetMinGasPrices sets the validator's minimum gas prices.
func (c *Config) SetMinGasPrices(gasPrices sdk.DecCoins) {
c.MinGasPrices = gasPrices.String()
}
// GetMinGasPrices returns the validator's minimum gas prices based on the set configuration.
func (c *Config) GetMinGasPrices() sdk.DecCoins {
if c.MinGasPrices == "" {
return sdk.DecCoins{}
}
gasPrices, err := sdk.ParseDecCoins(c.MinGasPrices)
if err != nil {
panic(fmt.Sprintf("invalid minimum gas prices: %v", err))
}
return gasPrices
}
// DefaultConfig returns server's default configuration.
func DefaultConfig() *Config {
return &Config{
BaseConfig: BaseConfig{
MinGasPrices: defaultMinGasPrices,
QueryGasLimit: 0,
InterBlockCache: true,
Pruning: pruningtypes.PruningOptionDefault,
PruningKeepRecent: "0",
PruningInterval: "0",
MinRetainBlocks: 0,
IndexEvents: make([]string, 0),
IAVLCacheSize: 781250,
IAVLDisableFastNode: false,
AppDBBackend: "",
},
Telemetry: telemetry.Config{
Enabled: false,
GlobalLabels: [][]string{},
},
API: APIConfig{
Enable: false,
Swagger: false,
Address: DefaultAPIAddress,
MaxOpenConnections: 1000,
RPCReadTimeout: 10,
RPCMaxBodyBytes: 1000000,
},
GRPC: GRPCConfig{
Enable: true,
Address: DefaultGRPCAddress,
MaxRecvMsgSize: DefaultGRPCMaxRecvMsgSize,
MaxSendMsgSize: DefaultGRPCMaxSendMsgSize,
},
StateSync: StateSyncConfig{
SnapshotInterval: 0,
SnapshotKeepRecent: 2,
},
Streaming: StreamingConfig{
ABCI: ABCIListenerConfig{
Keys: []string{},
StopNodeOnErr: true,
},
},
Mempool: MempoolConfig{
MaxTxs: -1,
},
}
}
// GetConfig returns a fully parsed Config object.
func GetConfig(v *viper.Viper) (Config, error) {
conf := DefaultConfig()
if err := v.Unmarshal(conf); err != nil {
return Config{}, fmt.Errorf("error extracting app config: %w", err)
}
return *conf, nil
}
// ValidateBasic returns an error if min-gas-prices field is empty in BaseConfig. Otherwise, it returns nil.
func (c Config) ValidateBasic() error {
if c.BaseConfig.MinGasPrices == "" {
return sdkerrors.ErrAppConfig.Wrap("set min gas price in app.toml or flag or env variable")
}
if c.Pruning == pruningtypes.PruningOptionEverything && c.StateSync.SnapshotInterval > 0 {
return sdkerrors.ErrAppConfig.Wrapf(
"cannot enable state sync snapshots with '%s' pruning setting", pruningtypes.PruningOptionEverything,
)
}
return nil
}

View File

@ -1,226 +0,0 @@
# This is a TOML config file.
# For more information, see https://github.com/toml-lang/toml
###############################################################################
### Base Configuration ###
###############################################################################
# The minimum gas prices a validator is willing to accept for processing a
# transaction. A transaction's fees must meet the minimum of any denomination
# specified in this config (e.g. 0.25token1,0.0001token2).
minimum-gas-prices = "{{ .BaseConfig.MinGasPrices }}"
# The maximum gas a query coming over rest/grpc may consume.
# If this is set to zero, the query can consume an unbounded amount of gas.
query-gas-limit = "{{ .BaseConfig.QueryGasLimit }}"
# default: the last 362880 states are kept, pruning at 10 block intervals
# nothing: all historic states will be saved, nothing will be deleted (i.e. archiving node)
# everything: 2 latest states will be kept; pruning at 10 block intervals.
# custom: allow pruning options to be manually specified through 'pruning-keep-recent', and 'pruning-interval'
pruning = "{{ .BaseConfig.Pruning }}"
# These are applied if and only if the pruning strategy is custom.
pruning-keep-recent = "{{ .BaseConfig.PruningKeepRecent }}"
pruning-interval = "{{ .BaseConfig.PruningInterval }}"
# HaltHeight contains a non-zero block height at which a node will gracefully
# halt and shutdown that can be used to assist upgrades and testing.
#
# Note: Commitment of state will be attempted on the corresponding block.
halt-height = {{ .BaseConfig.HaltHeight }}
# HaltTime contains a non-zero minimum block time (in Unix seconds) at which
# a node will gracefully halt and shutdown that can be used to assist upgrades
# and testing.
#
# Note: Commitment of state will be attempted on the corresponding block.
halt-time = {{ .BaseConfig.HaltTime }}
# MinRetainBlocks defines the minimum block height offset from the current
# block being committed, such that all blocks past this offset are pruned
# from CometBFT. It is used as part of the process of determining the
# ResponseCommit.RetainHeight value during ABCI Commit. A value of 0 indicates
# that no blocks should be pruned.
#
# This configuration value is only responsible for pruning CometBFT blocks.
# It has no bearing on application state pruning which is determined by the
# "pruning-*" configurations.
#
# Note: CometBFT block pruning is dependent on this parameter in conjunction
# with the unbonding (safety threshold) period, state pruning and state sync
# snapshot parameters to determine the correct minimum value of
# ResponseCommit.RetainHeight.
min-retain-blocks = {{ .BaseConfig.MinRetainBlocks }}
# InterBlockCache enables inter-block caching.
inter-block-cache = {{ .BaseConfig.InterBlockCache }}
# IndexEvents defines the set of events in the form {eventType}.{attributeKey},
# which informs CometBFT what to index. If empty, all events will be indexed.
#
# Example:
# ["message.sender", "message.recipient"]
index-events = [{{ range .BaseConfig.IndexEvents }}{{ printf "%q, " . }}{{end}}]
# IavlCacheSize set the size of the iavl tree cache (in number of nodes).
iavl-cache-size = {{ .BaseConfig.IAVLCacheSize }}
# IAVLDisableFastNode enables or disables the fast node feature of IAVL.
# Default is false.
iavl-disable-fastnode = {{ .BaseConfig.IAVLDisableFastNode }}
# AppDBBackend defines the database backend type to use for the application and snapshots DBs.
# An empty string indicates that a fallback will be used.
# The fallback is the db_backend value set in CometBFT's config.toml.
app-db-backend = "{{ .BaseConfig.AppDBBackend }}"
###############################################################################
### Telemetry Configuration ###
###############################################################################
[telemetry]
# Prefixed with keys to separate services.
service-name = "{{ .Telemetry.ServiceName }}"
# Enabled enables the application telemetry functionality. When enabled,
# an in-memory sink is also enabled by default. Operators may also enabled
# other sinks such as Prometheus.
enabled = {{ .Telemetry.Enabled }}
# Enable prefixing gauge values with hostname.
enable-hostname = {{ .Telemetry.EnableHostname }}
# Enable adding hostname to labels.
enable-hostname-label = {{ .Telemetry.EnableHostnameLabel }}
# Enable adding service to labels.
enable-service-label = {{ .Telemetry.EnableServiceLabel }}
# PrometheusRetentionTime, when positive, enables a Prometheus metrics sink.
prometheus-retention-time = {{ .Telemetry.PrometheusRetentionTime }}
# GlobalLabels defines a global set of name/value label tuples applied to all
# metrics emitted using the wrapper functions defined in telemetry package.
#
# Example:
# [["chain_id", "cosmoshub-1"]]
global-labels = [{{ range $k, $v := .Telemetry.GlobalLabels }}
["{{index $v 0 }}", "{{ index $v 1}}"],{{ end }}
]
# MetricsSink defines the type of metrics sink to use.
metrics-sink = "{{ .Telemetry.MetricsSink }}"
# StatsdAddr defines the address of a statsd server to send metrics to.
# Only utilized if MetricsSink is set to "statsd" or "dogstatsd".
statsd-addr = "{{ .Telemetry.StatsdAddr }}"
# DatadogHostname defines the hostname to use when emitting metrics to
# Datadog. Only utilized if MetricsSink is set to "dogstatsd".
datadog-hostname = "{{ .Telemetry.DatadogHostname }}"
###############################################################################
### API Configuration ###
###############################################################################
[api]
# Enable defines if the API server should be enabled.
enable = {{ .API.Enable }}
# Swagger defines if swagger documentation should automatically be registered.
swagger = {{ .API.Swagger }}
# Address defines the API server to listen on.
address = "{{ .API.Address }}"
# MaxOpenConnections defines the number of maximum open connections.
max-open-connections = {{ .API.MaxOpenConnections }}
# RPCReadTimeout defines the CometBFT RPC read timeout (in seconds).
rpc-read-timeout = {{ .API.RPCReadTimeout }}
# RPCWriteTimeout defines the CometBFT RPC write timeout (in seconds).
rpc-write-timeout = {{ .API.RPCWriteTimeout }}
# RPCMaxBodyBytes defines the CometBFT maximum request body (in bytes).
rpc-max-body-bytes = {{ .API.RPCMaxBodyBytes }}
# EnableUnsafeCORS defines if CORS should be enabled (unsafe - use it at your own risk).
enabled-unsafe-cors = {{ .API.EnableUnsafeCORS }}
###############################################################################
### gRPC Configuration ###
###############################################################################
[grpc]
# Enable defines if the gRPC server should be enabled.
enable = {{ .GRPC.Enable }}
# Address defines the gRPC server address to bind to.
address = "{{ .GRPC.Address }}"
# MaxRecvMsgSize defines the max message size in bytes the server can receive.
# The default value is 10MB.
max-recv-msg-size = "{{ .GRPC.MaxRecvMsgSize }}"
# MaxSendMsgSize defines the max message size in bytes the server can send.
# The default value is math.MaxInt32.
max-send-msg-size = "{{ .GRPC.MaxSendMsgSize }}"
###############################################################################
### State Sync Configuration ###
###############################################################################
# State sync snapshots allow other nodes to rapidly join the network without replaying historical
# blocks, instead downloading and applying a snapshot of the application state at a given height.
[state-sync]
# snapshot-interval specifies the block interval at which local state sync snapshots are
# taken (0 to disable).
snapshot-interval = {{ .StateSync.SnapshotInterval }}
# snapshot-keep-recent specifies the number of recent snapshots to keep and serve (0 to keep all).
snapshot-keep-recent = {{ .StateSync.SnapshotKeepRecent }}
###############################################################################
### State Streaming ###
###############################################################################
# Streaming allows nodes to stream state to external systems.
[streaming]
# streaming.abci specifies the configuration for the ABCI Listener streaming service.
[streaming.abci]
# List of kv store keys to stream out via gRPC.
# The store key names MUST match the module's StoreKey name.
#
# Example:
# ["acc", "bank", "gov", "staking", "mint"[,...]]
# ["*"] to expose all keys.
keys = [{{ range .Streaming.ABCI.Keys }}{{ printf "%q, " . }}{{end}}]
# The plugin name used for streaming via gRPC.
# Streaming is only enabled if this is set.
# Supported plugins: abci
plugin = "{{ .Streaming.ABCI.Plugin }}"
# stop-node-on-err specifies whether to stop the node on message delivery error.
stop-node-on-err = {{ .Streaming.ABCI.StopNodeOnErr }}
###############################################################################
### Mempool ###
###############################################################################
[mempool]
# Setting max-txs to 0 will allow for a unbounded amount of transactions in the mempool.
# Setting max_txs to negative 1 (-1) will disable transactions from being inserted into the mempool (no-op mempool).
# Setting max_txs to a positive number (> 0) will limit the number of transactions in the mempool, by the specified amount.
#
# Note, this configuration only applies to SDK built-in app-side mempool
# implementations.
max-txs = {{ .Mempool.MaxTxs }}

View File

@ -1,293 +0,0 @@
package config
import (
"bytes"
"os"
"path/filepath"
"testing"
"github.com/spf13/viper"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
pruningtypes "cosmossdk.io/store/pruning/types"
sdk "github.com/cosmos/cosmos-sdk/types"
)
func TestDefaultConfig(t *testing.T) {
cfg := DefaultConfig()
require.True(t, cfg.GetMinGasPrices().IsZero())
}
func TestGetAndSetMinimumGas(t *testing.T) {
cfg := DefaultConfig()
// Test case 1: Single coin
input := sdk.DecCoins{sdk.NewInt64DecCoin("foo", 5)}
cfg.SetMinGasPrices(input)
require.Equal(t, "5.000000000000000000foo", cfg.MinGasPrices)
require.EqualValues(t, cfg.GetMinGasPrices(), input)
// Test case 2: Multiple coins
input = sdk.DecCoins{sdk.NewInt64DecCoin("bar", 1), sdk.NewInt64DecCoin("foo", 5)}
cfg.SetMinGasPrices(input)
require.Equal(t, "1.000000000000000000bar,5.000000000000000000foo", cfg.MinGasPrices)
require.EqualValues(t, cfg.GetMinGasPrices(), input)
// Test case 4: Empty DecCoins
input = sdk.DecCoins{}
cfg.SetMinGasPrices(input)
require.Equal(t, "", cfg.MinGasPrices)
require.EqualValues(t, cfg.GetMinGasPrices(), input)
// Test case 5: Invalid string (should panic)
cfg.MinGasPrices = "invalid,gas,prices"
require.Panics(t, func() {
cfg.GetMinGasPrices()
}, "GetMinGasPrices should panic with invalid input")
}
func TestIndexEventsMarshalling(t *testing.T) {
expectedIn := `index-events = ["key1", "key2", ]` + "\n"
cfg := DefaultConfig()
cfg.IndexEvents = []string{"key1", "key2"}
var buffer bytes.Buffer
err := configTemplate.Execute(&buffer, cfg)
require.NoError(t, err, "executing template")
actual := buffer.String()
require.Contains(t, actual, expectedIn, "config file contents")
}
func TestStreamingConfig(t *testing.T) {
cfg := Config{
Streaming: StreamingConfig{
ABCI: ABCIListenerConfig{
Keys: []string{"one", "two"},
Plugin: "plugin-A",
StopNodeOnErr: false,
},
},
}
testDir := t.TempDir()
cfgFile := filepath.Join(testDir, "app.toml")
err := WriteConfigFile(cfgFile, &cfg)
require.NoError(t, err)
cfgFileBz, err := os.ReadFile(cfgFile)
require.NoError(t, err, "reading %s", cfgFile)
cfgFileContents := string(cfgFileBz)
t.Logf("Config file contents: %s:\n%s", cfgFile, cfgFileContents)
expectedLines := []string{
`keys = ["one", "two", ]`,
`plugin = "plugin-A"`,
`stop-node-on-err = false`,
}
for _, line := range expectedLines {
assert.Contains(t, cfgFileContents, line+"\n", "config file contents")
}
vpr := viper.New()
vpr.SetConfigFile(cfgFile)
err = vpr.ReadInConfig()
require.NoError(t, err, "reading config file into viper")
var actual Config
err = vpr.Unmarshal(&actual)
require.NoError(t, err, "vpr.Unmarshal")
assert.Equal(t, cfg.Streaming, actual.Streaming, "Streaming")
}
func TestParseStreaming(t *testing.T) {
expectedKeys := `keys = ["*", ]` + "\n"
expectedPlugin := `plugin = "abci_v1"` + "\n"
expectedStopNodeOnErr := `stop-node-on-err = true` + "\n"
cfg := DefaultConfig()
cfg.Streaming.ABCI.Keys = []string{"*"}
cfg.Streaming.ABCI.Plugin = "abci_v1"
cfg.Streaming.ABCI.StopNodeOnErr = true
var buffer bytes.Buffer
err := configTemplate.Execute(&buffer, cfg)
require.NoError(t, err, "executing template")
actual := buffer.String()
require.Contains(t, actual, expectedKeys, "config file contents")
require.Contains(t, actual, expectedPlugin, "config file contents")
require.Contains(t, actual, expectedStopNodeOnErr, "config file contents")
}
func TestReadConfig(t *testing.T) {
cfg := DefaultConfig()
tmpFile := filepath.Join(t.TempDir(), "config")
err := WriteConfigFile(tmpFile, cfg)
require.NoError(t, err)
v := viper.New()
otherCfg, err := GetConfig(v)
require.NoError(t, err)
require.Equal(t, *cfg, otherCfg)
}
func TestIndexEventsWriteRead(t *testing.T) {
expected := []string{"key3", "key4"}
// Create config with two IndexEvents entries, and write it to a file.
confFile := filepath.Join(t.TempDir(), "app.toml")
conf := DefaultConfig()
conf.IndexEvents = expected
err := WriteConfigFile(confFile, conf)
require.NoError(t, err)
// read the file into Viper
vpr := viper.New()
vpr.SetConfigFile(confFile)
err = vpr.ReadInConfig()
require.NoError(t, err, "reading config file into viper")
// Check that the raw viper value is correct.
actualRaw := vpr.GetStringSlice("index-events")
require.Equal(t, expected, actualRaw, "viper's index events")
// Check that it is parsed into the config correctly.
cfg, perr := ParseConfig(vpr)
require.NoError(t, perr, "parsing config")
actual := cfg.IndexEvents
require.Equal(t, expected, actual, "config value")
}
func TestGlobalLabelsEventsMarshalling(t *testing.T) {
expectedIn := `global-labels = [
["labelname1", "labelvalue1"],
["labelname2", "labelvalue2"],
]`
cfg := DefaultConfig()
cfg.Telemetry.GlobalLabels = [][]string{{"labelname1", "labelvalue1"}, {"labelname2", "labelvalue2"}}
var buffer bytes.Buffer
err := configTemplate.Execute(&buffer, cfg)
require.NoError(t, err, "executing template")
actual := buffer.String()
require.Contains(t, actual, expectedIn, "config file contents")
}
func TestGlobalLabelsWriteRead(t *testing.T) {
expected := [][]string{{"labelname3", "labelvalue3"}, {"labelname4", "labelvalue4"}}
expectedRaw := make([]interface{}, len(expected))
for i, exp := range expected {
pair := make([]interface{}, len(exp))
for j, s := range exp {
pair[j] = s
}
expectedRaw[i] = pair
}
// Create config with two GlobalLabels entries, and write it to a file.
confFile := filepath.Join(t.TempDir(), "app.toml")
conf := DefaultConfig()
conf.Telemetry.GlobalLabels = expected
err := WriteConfigFile(confFile, conf)
require.NoError(t, err)
// Read that file into viper.
vpr := viper.New()
vpr.SetConfigFile(confFile)
rerr := vpr.ReadInConfig()
require.NoError(t, rerr, "reading config file into viper")
// Check that the raw viper value is correct.
actualRaw := vpr.Get("telemetry.global-labels")
require.Equal(t, expectedRaw, actualRaw, "viper value")
// Check that it is parsed into the config correctly.
cfg, perr := ParseConfig(vpr)
require.NoError(t, perr, "parsing config")
actual := cfg.Telemetry.GlobalLabels
require.Equal(t, expected, actual, "config value")
}
func TestSetConfigTemplate(t *testing.T) {
conf := DefaultConfig()
var initBuffer, setBuffer bytes.Buffer
// Use the configTemplate defined during init() to create a config string.
ierr := configTemplate.Execute(&initBuffer, conf)
require.NoError(t, ierr, "initial configTemplate.Execute")
expected := initBuffer.String()
// Set the template to the default one.
initTmpl := configTemplate
require.NotPanics(t, func() {
_ = SetConfigTemplate(DefaultConfigTemplate)
}, "SetConfigTemplate")
setTmpl := configTemplate
require.NotSame(t, initTmpl, setTmpl, "configTemplate after set")
// Create the string again and make sure it's the same.
serr := configTemplate.Execute(&setBuffer, conf)
require.NoError(t, serr, "after SetConfigTemplate, configTemplate.Execute")
actual := setBuffer.String()
require.Equal(t, expected, actual, "resulting config strings")
}
func TestAppConfig(t *testing.T) {
appConfigFile := filepath.Join(t.TempDir(), "app.toml")
defer func() {
_ = os.Remove(appConfigFile)
}()
defAppConfig := DefaultConfig()
require.NoError(t, SetConfigTemplate(DefaultConfigTemplate))
require.NoError(t, WriteConfigFile(appConfigFile, defAppConfig))
v := viper.New()
v.SetConfigFile(appConfigFile)
require.NoError(t, v.ReadInConfig())
appCfg := new(Config)
require.NoError(t, v.Unmarshal(appCfg))
require.EqualValues(t, appCfg, defAppConfig)
}
func TestValidateBasic(t *testing.T) {
cfg := DefaultConfig()
// Test case 1: Valid MinGasPrices
cfg.MinGasPrices = "0.01stake"
err := cfg.ValidateBasic()
require.NoError(t, err)
// Test case 2: Default configuration (MinGasPrices is empty)
cfg.MinGasPrices = ""
err = cfg.ValidateBasic()
require.Error(t, err)
require.Contains(t, err.Error(), "set min gas price in app.toml or flag or env variable")
// Test case 3: Invalid pruning and state sync combination
cfg = DefaultConfig()
cfg.MinGasPrices = "0.01stake"
cfg.Pruning = pruningtypes.PruningOptionEverything
cfg.StateSync.SnapshotInterval = 1000
err = cfg.ValidateBasic()
require.Error(t, err)
require.Contains(t, err.Error(), "cannot enable state sync snapshots with 'everything' pruning setting")
}
func TestGetConfig(t *testing.T) {
v := viper.New()
v.Set("minimum-gas-prices", "0.01stake")
v.Set("api.enable", true)
v.Set("grpc.max-recv-msg-size", 5*1024*1024)
cfg, err := GetConfig(v)
require.NoError(t, err)
require.Equal(t, "0.01stake", cfg.MinGasPrices)
require.True(t, cfg.API.Enable)
require.Equal(t, 5*1024*1024, cfg.GRPC.MaxRecvMsgSize)
}

View File

@ -1,61 +0,0 @@
package config
import (
"bytes"
_ "embed"
"fmt"
"os"
"text/template"
"github.com/spf13/viper"
)
//go:embed config.toml.tpl
var DefaultConfigTemplate string
var configTemplate *template.Template
func init() {
var err error
tmpl := template.New("appConfigFileTemplate")
if configTemplate, err = tmpl.Parse(DefaultConfigTemplate); err != nil {
panic(err)
}
}
// ParseConfig retrieves the default environment configuration for the application.
func ParseConfig(v *viper.Viper) (*Config, error) {
conf := DefaultConfig()
err := v.Unmarshal(conf)
return conf, err
}
// SetConfigTemplate sets the custom app config template for the application.
func SetConfigTemplate(customTemplate string) error {
var err error
tmpl := template.New("appConfigFileTemplate")
if configTemplate, err = tmpl.Parse(customTemplate); err != nil {
return err
}
return nil
}
// WriteConfigFile renders config using the template and writes it to configFilePath.
func WriteConfigFile(configFilePath string, config interface{}) error {
var buffer bytes.Buffer
if err := configTemplate.Execute(&buffer, config); err != nil {
return err
}
if err := os.WriteFile(configFilePath, buffer.Bytes(), 0o600); err != nil {
return fmt.Errorf("failed to write file: %w", err)
}
return nil
}

View File

@ -1,57 +0,0 @@
package server
const (
// CometBFT full-node start flags
flagWithComet = "with-comet"
flagAddress = "address"
flagTransport = "transport"
flagTraceStore = "trace-store"
flagCPUProfile = "cpu-profile"
FlagMinGasPrices = "minimum-gas-prices"
FlagQueryGasLimit = "query-gas-limit"
FlagHaltHeight = "halt-height"
FlagHaltTime = "halt-time"
FlagInterBlockCache = "inter-block-cache"
FlagUnsafeSkipUpgrades = "unsafe-skip-upgrades"
FlagTrace = "trace"
FlagInvCheckPeriod = "inv-check-period"
FlagPruning = "pruning"
FlagPruningKeepRecent = "pruning-keep-recent"
FlagPruningInterval = "pruning-interval"
FlagIndexEvents = "index-events"
FlagMinRetainBlocks = "min-retain-blocks"
FlagIAVLCacheSize = "iavl-cache-size"
FlagDisableIAVLFastNode = "iavl-disable-fastnode"
FlagIAVLSyncPruning = "iavl-sync-pruning"
FlagShutdownGrace = "shutdown-grace"
// state sync-related flags
FlagStateSyncSnapshotInterval = "state-sync.snapshot-interval"
FlagStateSyncSnapshotKeepRecent = "state-sync.snapshot-keep-recent"
// api-related flags
FlagAPIEnable = "api.enable"
FlagAPISwagger = "api.swagger"
FlagAPIAddress = "api.address"
FlagAPIMaxOpenConnections = "api.max-open-connections"
FlagRPCReadTimeout = "api.rpc-read-timeout"
FlagRPCWriteTimeout = "api.rpc-write-timeout"
FlagRPCMaxBodyBytes = "api.rpc-max-body-bytes"
FlagAPIEnableUnsafeCORS = "api.enabled-unsafe-cors"
// mempool flags
FlagMempoolMaxTxs = "mempool.max-txs"
// testnet keys
KeyIsTestnet = "is-testnet"
KeyNewChainID = "new-chain-ID"
KeyNewOpAddr = "new-operator-addr"
KeyNewValAddr = "new-validator-addr"
KeyUserPubKey = "user-pub-key"
KeyTriggerTestnetUpgrade = "trigger-testnet-upgrade"
)

View File

@ -1,5 +0,0 @@
// Package gogoreflection implements gRPC reflection for gogoproto consumers
// the normal reflection library does not work as it points to a different
// singleton registry. The API and codebase is taken from the official gRPC
// reflection repository.
package gogoreflection

View File

@ -1,75 +0,0 @@
package gogoreflection
import (
"reflect"
_ "github.com/cosmos/cosmos-proto" // look above
_ "github.com/cosmos/gogoproto/gogoproto" // required so it does register the gogoproto file descriptor
gogoproto "github.com/cosmos/gogoproto/proto"
"github.com/golang/protobuf/proto" //nolint:staticcheck // migrate in a future pr
)
func getFileDescriptor(filePath string) []byte {
// Since we got well known descriptors which are not registered into gogoproto
// registry but are instead registered into the proto one, we need to check both.
fd := gogoproto.FileDescriptor(filePath)
if len(fd) != 0 {
return fd
}
return proto.FileDescriptor(filePath) //nolint:staticcheck // keep for backward compatibility
}
func getMessageType(name string) reflect.Type {
typ := gogoproto.MessageType(name)
if typ != nil {
return typ
}
return proto.MessageType(name) //nolint:staticcheck // keep for backward compatibility
}
func getExtension(extID int32, m proto.Message) *gogoproto.ExtensionDesc {
// check first in gogoproto registry
for id, desc := range gogoproto.RegisteredExtensions(m) {
if id == extID {
return desc
}
}
// check into proto registry
for id, desc := range proto.RegisteredExtensions(m) { //nolint:staticcheck // keep for backward compatibility
if id == extID {
return &gogoproto.ExtensionDesc{
ExtendedType: desc.ExtendedType,
ExtensionType: desc.ExtensionType,
Field: desc.Field,
Name: desc.Name,
Tag: desc.Tag,
Filename: desc.Filename,
}
}
}
return nil
}
func getExtensionsNumbers(m proto.Message) []int32 {
gogoProtoExts := gogoproto.RegisteredExtensions(m)
out := make([]int32, 0, len(gogoProtoExts))
for id := range gogoProtoExts {
out = append(out, id)
}
if len(out) != 0 {
return out
}
protoExts := proto.RegisteredExtensions(m) //nolint:staticcheck // kept for backwards compatibility
out = make([]int32, 0, len(protoExts))
for id := range protoExts {
out = append(out, id)
}
return out
}

View File

@ -1,22 +0,0 @@
package gogoreflection
import (
"testing"
"google.golang.org/protobuf/runtime/protoimpl"
)
func TestRegistrationFix(t *testing.T) {
res := getFileDescriptor("gogoproto/gogo.proto")
rawDesc, err := decompress(res)
if err != nil {
t.Fatal(err)
}
fd := protoimpl.DescBuilder{
RawDescriptor: rawDesc,
}.Build()
if fd.File.Extensions().Len() == 0 {
t.Fatal("unexpected parsing")
}
}

View File

@ -1,473 +0,0 @@
// Copyright 2016 gRPC authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// Package gogoreflection implements server reflection service.
//
// The service implemented is defined in:
// https://github.com/grpc/grpc/blob/master/src/proto/grpc/reflection/v1alpha/reflection.proto.
//
// To register server reflection on a gRPC server:
//
// import "google.golang.org/grpc/reflection"
//
// s := grpc.NewServer()
// pb.RegisterYourOwnServer(s, &server{})
//
// // Register reflection service on gRPC server.
// reflection.Register(s)
//
// s.Serve(lis)
package gogoreflection
import (
"bytes"
"compress/gzip"
"errors"
"fmt"
"io"
"log"
"reflect"
"sort"
"sync"
//nolint: staticcheck // keep this import for backward compatibility
"github.com/golang/protobuf/proto"
dpb "github.com/golang/protobuf/protoc-gen-go/descriptor"
"google.golang.org/grpc"
"google.golang.org/grpc/codes"
rpb "google.golang.org/grpc/reflection/grpc_reflection_v1alpha"
"google.golang.org/grpc/status"
)
type serverReflectionServer struct {
rpb.UnimplementedServerReflectionServer
s *grpc.Server
initSymbols sync.Once
serviceNames []string
symbols map[string]*dpb.FileDescriptorProto // map of fully-qualified names to files
}
// Register registers the server reflection service on the given gRPC server.
func Register(s *grpc.Server) {
rpb.RegisterServerReflectionServer(s, &serverReflectionServer{
s: s,
})
}
// protoMessage is used for type assertion on proto messages.
// Generated proto message implements function Descriptor(), but Descriptor()
// is not part of interface proto.Message. This interface is needed to
// call Descriptor().
type protoMessage interface {
Descriptor() ([]byte, []int)
}
func (s *serverReflectionServer) getSymbols() (svcNames []string, symbolIndex map[string]*dpb.FileDescriptorProto) {
s.initSymbols.Do(func() {
serviceInfo := s.s.GetServiceInfo()
s.symbols = map[string]*dpb.FileDescriptorProto{}
s.serviceNames = make([]string, 0, len(serviceInfo))
processed := map[string]struct{}{}
for svc, info := range serviceInfo {
s.serviceNames = append(s.serviceNames, svc)
fdenc, ok := parseMetadata(info.Metadata)
if !ok {
continue
}
fd, err := decodeFileDesc(fdenc)
if err != nil {
continue
}
s.processFile(fd, processed)
}
sort.Strings(s.serviceNames)
})
return s.serviceNames, s.symbols
}
func (s *serverReflectionServer) processFile(fd *dpb.FileDescriptorProto, processed map[string]struct{}) {
filename := fd.GetName()
if _, ok := processed[filename]; ok {
return
}
processed[filename] = struct{}{}
prefix := fd.GetPackage()
for _, msg := range fd.MessageType {
s.processMessage(fd, prefix, msg)
}
for _, en := range fd.EnumType {
s.processEnum(fd, prefix, en)
}
for _, ext := range fd.Extension {
s.processField(fd, prefix, ext)
}
for _, svc := range fd.Service {
svcName := fqn(prefix, svc.GetName())
s.symbols[svcName] = fd
for _, meth := range svc.Method {
name := fqn(svcName, meth.GetName())
s.symbols[name] = fd
}
}
for _, dep := range fd.Dependency {
fdenc := getFileDescriptor(dep)
fdDep, err := decodeFileDesc(fdenc)
if err != nil {
continue
}
s.processFile(fdDep, processed)
}
}
func (s *serverReflectionServer) processMessage(fd *dpb.FileDescriptorProto, prefix string, msg *dpb.DescriptorProto) {
msgName := fqn(prefix, msg.GetName())
s.symbols[msgName] = fd
for _, nested := range msg.NestedType {
s.processMessage(fd, msgName, nested)
}
for _, en := range msg.EnumType {
s.processEnum(fd, msgName, en)
}
for _, ext := range msg.Extension {
s.processField(fd, msgName, ext)
}
for _, fld := range msg.Field {
s.processField(fd, msgName, fld)
}
for _, oneof := range msg.OneofDecl {
oneofName := fqn(msgName, oneof.GetName())
s.symbols[oneofName] = fd
}
}
func (s *serverReflectionServer) processEnum(fd *dpb.FileDescriptorProto, prefix string, en *dpb.EnumDescriptorProto) {
enName := fqn(prefix, en.GetName())
s.symbols[enName] = fd
for _, val := range en.Value {
valName := fqn(enName, val.GetName())
s.symbols[valName] = fd
}
}
func (s *serverReflectionServer) processField(fd *dpb.FileDescriptorProto, prefix string, fld *dpb.FieldDescriptorProto) {
fldName := fqn(prefix, fld.GetName())
s.symbols[fldName] = fd
}
func fqn(prefix, name string) string {
if prefix == "" {
return name
}
return prefix + "." + name
}
// fileDescForType gets the file descriptor for the given type.
// The given type should be a proto message.
func (s *serverReflectionServer) fileDescForType(st reflect.Type) (*dpb.FileDescriptorProto, error) {
m, ok := reflect.Zero(reflect.PointerTo(st)).Interface().(protoMessage)
if !ok {
return nil, fmt.Errorf("failed to create message from type: %v", st)
}
enc, _ := m.Descriptor()
return decodeFileDesc(enc)
}
// decodeFileDesc does decompression and unmarshalling on the given
// file descriptor byte slice.
func decodeFileDesc(enc []byte) (*dpb.FileDescriptorProto, error) {
raw, err := decompress(enc)
if err != nil {
return nil, fmt.Errorf("failed to decompress enc: %w", err)
}
fd := new(dpb.FileDescriptorProto)
if err := proto.Unmarshal(raw, fd); err != nil {
return nil, fmt.Errorf("bad descriptor: %w", err)
}
return fd, nil
}
// decompress does gzip decompression.
func decompress(b []byte) ([]byte, error) {
r, err := gzip.NewReader(bytes.NewReader(b))
if err != nil {
return nil, fmt.Errorf("bad gzipped descriptor: %w", err)
}
out, err := io.ReadAll(r)
if err != nil {
return nil, fmt.Errorf("bad gzipped descriptor: %w", err)
}
return out, nil
}
func typeForName(name string) (reflect.Type, error) {
pt := getMessageType(name)
if pt == nil {
return nil, fmt.Errorf("unknown type: %q", name)
}
st := pt.Elem()
return st, nil
}
func fileDescContainingExtension(st reflect.Type, ext int32) (*dpb.FileDescriptorProto, error) {
m, ok := reflect.Zero(reflect.PointerTo(st)).Interface().(proto.Message)
if !ok {
return nil, fmt.Errorf("failed to create message from type: %v", st)
}
extDesc := getExtension(ext, m)
if extDesc == nil {
return nil, fmt.Errorf("failed to find registered extension for extension number %v", ext)
}
return decodeFileDesc(getFileDescriptor(extDesc.Filename))
}
func (s *serverReflectionServer) allExtensionNumbersForType(st reflect.Type) ([]int32, error) {
m, ok := reflect.Zero(reflect.PointerTo(st)).Interface().(proto.Message)
if !ok {
return nil, fmt.Errorf("failed to create message from type: %v", st)
}
out := getExtensionsNumbers(m)
return out, nil
}
// fileDescWithDependencies returns a slice of serialized fileDescriptors in
// wire format ([]byte). The fileDescriptors will include fd and all the
// transitive dependencies of fd with names not in sentFileDescriptors.
func fileDescWithDependencies(fd *dpb.FileDescriptorProto, sentFileDescriptors map[string]bool) ([][]byte, error) {
r := [][]byte{}
queue := []*dpb.FileDescriptorProto{fd}
for len(queue) > 0 {
currentfd := queue[0]
queue = queue[1:]
if sent := sentFileDescriptors[currentfd.GetName()]; len(r) == 0 || !sent {
sentFileDescriptors[currentfd.GetName()] = true
currentfdEncoded, err := proto.Marshal(currentfd)
if err != nil {
return nil, err
}
r = append(r, currentfdEncoded)
}
for _, dep := range currentfd.Dependency {
fdenc := getFileDescriptor(dep)
fdDep, err := decodeFileDesc(fdenc)
if err != nil {
continue
}
queue = append(queue, fdDep)
}
}
return r, nil
}
// fileDescEncodingByFilename finds the file descriptor for given filename,
// finds all of its previously unsent transitive dependencies, does marshaling
// on them, and returns the marshaled result.
func (s *serverReflectionServer) fileDescEncodingByFilename(name string, sentFileDescriptors map[string]bool) ([][]byte, error) {
enc := getFileDescriptor(name)
if enc == nil {
return nil, fmt.Errorf("unknown file: %v", name)
}
fd, err := decodeFileDesc(enc)
if err != nil {
return nil, err
}
return fileDescWithDependencies(fd, sentFileDescriptors)
}
// parseMetadata finds the file descriptor bytes specified meta.
// For SupportPackageIsVersion4, m is the name of the proto file, we
// call proto.FileDescriptor to get the byte slice.
// For SupportPackageIsVersion3, m is a byte slice itself.
func parseMetadata(meta interface{}) ([]byte, bool) {
// Check if meta is the file name.
if fileNameForMeta, ok := meta.(string); ok {
return getFileDescriptor(fileNameForMeta), true
}
// Check if meta is the byte slice.
if enc, ok := meta.([]byte); ok {
return enc, true
}
return nil, false
}
// fileDescEncodingContainingSymbol finds the file descriptor containing the
// given symbol, finds all of its previously unsent transitive dependencies,
// does marshaling on them, and returns the marshaled result. The given symbol
// can be a type, a service or a method.
func (s *serverReflectionServer) fileDescEncodingContainingSymbol(name string, sentFileDescriptors map[string]bool) ([][]byte, error) {
_, symbols := s.getSymbols()
fd := symbols[name]
if fd == nil {
// Check if it's a type name that was not present in the
// transitive dependencies of the registered services.
if st, err := typeForName(name); err == nil {
fd, err = s.fileDescForType(st)
if err != nil {
return nil, err
}
}
}
if fd == nil {
return nil, fmt.Errorf("unknown symbol: %v", name)
}
return fileDescWithDependencies(fd, sentFileDescriptors)
}
// fileDescEncodingContainingExtension finds the file descriptor containing
// given extension, finds all of its previously unsent transitive dependencies,
// does marshaling on them, and returns the marshaled result.
func (s *serverReflectionServer) fileDescEncodingContainingExtension(typeName string, extNum int32, sentFileDescriptors map[string]bool) ([][]byte, error) {
st, err := typeForName(typeName)
if err != nil {
return nil, err
}
fd, err := fileDescContainingExtension(st, extNum)
if err != nil {
return nil, err
}
return fileDescWithDependencies(fd, sentFileDescriptors)
}
// allExtensionNumbersForTypeName returns all extension numbers for the given type.
func (s *serverReflectionServer) allExtensionNumbersForTypeName(name string) ([]int32, error) {
st, err := typeForName(name)
if err != nil {
return nil, err
}
extNums, err := s.allExtensionNumbersForType(st)
if err != nil {
return nil, err
}
return extNums, nil
}
// ServerReflectionInfo is the reflection service handler.
func (s *serverReflectionServer) ServerReflectionInfo(stream rpb.ServerReflection_ServerReflectionInfoServer) error {
sentFileDescriptors := make(map[string]bool)
for {
in, err := stream.Recv()
if errors.Is(err, io.EOF) {
return nil
}
if err != nil {
return err
}
out := &rpb.ServerReflectionResponse{ //nolint:staticcheck // SA1019: we want to keep using v1alpha
ValidHost: in.Host, //nolint:staticcheck // SA1019: we want to keep using v1alpha
OriginalRequest: in,
}
switch req := in.MessageRequest.(type) {
case *rpb.ServerReflectionRequest_FileByFilename:
b, err := s.fileDescEncodingByFilename(req.FileByFilename, sentFileDescriptors) //nolint:staticcheck // SA1019: we want to keep using v1alpha
if err != nil {
out.MessageResponse = &rpb.ServerReflectionResponse_ErrorResponse{
ErrorResponse: &rpb.ErrorResponse{ //nolint:staticcheck // SA1019: we want to keep using v1alpha
ErrorCode: int32(codes.NotFound),
ErrorMessage: err.Error(),
},
}
} else {
out.MessageResponse = &rpb.ServerReflectionResponse_FileDescriptorResponse{
FileDescriptorResponse: &rpb.FileDescriptorResponse{FileDescriptorProto: b}, //nolint:staticcheck // SA1019: we want to keep using v1alpha
}
}
case *rpb.ServerReflectionRequest_FileContainingSymbol:
b, err := s.fileDescEncodingContainingSymbol(req.FileContainingSymbol, sentFileDescriptors) //nolint:staticcheck // SA1019: we want to keep using v1alpha
if err != nil {
out.MessageResponse = &rpb.ServerReflectionResponse_ErrorResponse{
ErrorResponse: &rpb.ErrorResponse{ //nolint:staticcheck // SA1019: we want to keep using v1alpha
ErrorCode: int32(codes.NotFound),
ErrorMessage: err.Error(),
},
}
} else {
out.MessageResponse = &rpb.ServerReflectionResponse_FileDescriptorResponse{
FileDescriptorResponse: &rpb.FileDescriptorResponse{FileDescriptorProto: b}, //nolint:staticcheck // SA1019: we want to keep using v1alpha
}
}
case *rpb.ServerReflectionRequest_FileContainingExtension:
typeName := req.FileContainingExtension.ContainingType //nolint:staticcheck // SA1019: we want to keep using v1alpha
extNum := req.FileContainingExtension.ExtensionNumber //nolint:staticcheck // SA1019: we want to keep using v1alpha
b, err := s.fileDescEncodingContainingExtension(typeName, extNum, sentFileDescriptors)
if err != nil {
out.MessageResponse = &rpb.ServerReflectionResponse_ErrorResponse{
ErrorResponse: &rpb.ErrorResponse{ //nolint:staticcheck // SA1019: we want to keep using v1alpha
ErrorCode: int32(codes.NotFound),
ErrorMessage: err.Error(),
},
}
} else {
out.MessageResponse = &rpb.ServerReflectionResponse_FileDescriptorResponse{
FileDescriptorResponse: &rpb.FileDescriptorResponse{FileDescriptorProto: b}, //nolint:staticcheck // SA1019: we want to keep using v1alpha
}
}
case *rpb.ServerReflectionRequest_AllExtensionNumbersOfType:
extNums, err := s.allExtensionNumbersForTypeName(req.AllExtensionNumbersOfType) //nolint:staticcheck // SA1019: we want to keep using v1alpha
if err != nil {
out.MessageResponse = &rpb.ServerReflectionResponse_ErrorResponse{
ErrorResponse: &rpb.ErrorResponse{ //nolint:staticcheck // SA1019: we want to keep using v1alpha
ErrorCode: int32(codes.NotFound),
ErrorMessage: err.Error(),
},
}
log.Printf("OH NO: %s", err)
} else {
out.MessageResponse = &rpb.ServerReflectionResponse_AllExtensionNumbersResponse{
AllExtensionNumbersResponse: &rpb.ExtensionNumberResponse{ //nolint:staticcheck // SA1019: we want to keep using v1alpha
BaseTypeName: req.AllExtensionNumbersOfType, //nolint:staticcheck // SA1019: we want to keep using v1alpha
ExtensionNumber: extNums,
},
}
}
case *rpb.ServerReflectionRequest_ListServices:
svcNames, _ := s.getSymbols()
serviceResponses := make([]*rpb.ServiceResponse, len(svcNames)) //nolint:staticcheck // SA1019: we want to keep using v1alpha
for i, n := range svcNames {
serviceResponses[i] = &rpb.ServiceResponse{ //nolint:staticcheck // SA1019: we want to keep using v1alpha
Name: n,
}
}
out.MessageResponse = &rpb.ServerReflectionResponse_ListServicesResponse{
ListServicesResponse: &rpb.ListServiceResponse{ //nolint:staticcheck // SA1019: we want to keep using v1alpha
Service: serviceResponses,
},
}
default:
return status.Errorf(codes.InvalidArgument, "invalid MessageRequest: %v", in.MessageRequest)
}
if err := stream.Send(out); err != nil {
return err
}
}
}

View File

@ -1,197 +0,0 @@
package v2alpha1
import (
"context"
"errors"
"fmt"
"github.com/cosmos/gogoproto/proto"
"google.golang.org/grpc"
codectypes "github.com/cosmos/cosmos-sdk/codec/types"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/types/tx"
)
type Config struct {
SigningModes map[string]int32
ChainID string
InterfaceRegistry codectypes.InterfaceRegistry
}
// Register registers the cosmos sdk reflection service
// to the provided *grpc.Server given a Config
func Register(srv *grpc.Server, conf Config) error {
reflectionServer, err := newReflectionServiceServer(srv, conf)
if err != nil {
return err
}
RegisterReflectionServiceServer(srv, reflectionServer)
return nil
}
type reflectionServiceServer struct {
desc *AppDescriptor
}
func (r reflectionServiceServer) GetAuthnDescriptor(_ context.Context, _ *GetAuthnDescriptorRequest) (*GetAuthnDescriptorResponse, error) {
return &GetAuthnDescriptorResponse{Authn: r.desc.Authn}, nil
}
func (r reflectionServiceServer) GetChainDescriptor(_ context.Context, _ *GetChainDescriptorRequest) (*GetChainDescriptorResponse, error) {
return &GetChainDescriptorResponse{Chain: r.desc.Chain}, nil
}
func (r reflectionServiceServer) GetCodecDescriptor(_ context.Context, _ *GetCodecDescriptorRequest) (*GetCodecDescriptorResponse, error) {
return &GetCodecDescriptorResponse{Codec: r.desc.Codec}, nil
}
func (r reflectionServiceServer) GetConfigurationDescriptor(_ context.Context, _ *GetConfigurationDescriptorRequest) (*GetConfigurationDescriptorResponse, error) {
return nil, errors.New("this endpoint has been deprecated, please see auth/Bech32Prefix for the data you are seeking")
}
func (r reflectionServiceServer) GetQueryServicesDescriptor(_ context.Context, _ *GetQueryServicesDescriptorRequest) (*GetQueryServicesDescriptorResponse, error) {
return &GetQueryServicesDescriptorResponse{Queries: r.desc.QueryServices}, nil
}
func (r reflectionServiceServer) GetTxDescriptor(_ context.Context, _ *GetTxDescriptorRequest) (*GetTxDescriptorResponse, error) {
return &GetTxDescriptorResponse{Tx: r.desc.Tx}, nil
}
func newReflectionServiceServer(grpcSrv *grpc.Server, conf Config) (reflectionServiceServer, error) {
// set chain descriptor
chainDescriptor := &ChainDescriptor{Id: conf.ChainID}
// set codec descriptor
codecDescriptor, err := newCodecDescriptor(conf.InterfaceRegistry)
if err != nil {
return reflectionServiceServer{}, fmt.Errorf("unable to create codec descriptor: %w", err)
}
// set query service descriptor
queryServiceDescriptor := newQueryServiceDescriptor(grpcSrv)
// set deliver descriptor
txDescriptor, err := newTxDescriptor(conf.InterfaceRegistry)
if err != nil {
return reflectionServiceServer{}, fmt.Errorf("unable to create deliver descriptor: %w", err)
}
authnDescriptor := newAuthnDescriptor(conf.SigningModes)
desc := &AppDescriptor{
Authn: authnDescriptor,
Chain: chainDescriptor,
Codec: codecDescriptor,
QueryServices: queryServiceDescriptor,
Tx: txDescriptor,
}
ifaceList := make([]string, len(desc.Codec.Interfaces))
ifaceImplementers := make(map[string][]string, len(desc.Codec.Interfaces))
for i, iface := range desc.Codec.Interfaces {
ifaceList[i] = iface.Fullname
impls := make([]string, len(iface.InterfaceImplementers))
for j, impl := range iface.InterfaceImplementers {
impls[j] = impl.TypeUrl
}
ifaceImplementers[iface.Fullname] = impls
}
return reflectionServiceServer{
desc: desc,
}, nil
}
// newCodecDescriptor describes the codec given the codectypes.InterfaceRegistry
func newCodecDescriptor(ir codectypes.InterfaceRegistry) (*CodecDescriptor, error) {
registeredInterfaces := ir.ListAllInterfaces()
interfaceDescriptors := make([]*InterfaceDescriptor, len(registeredInterfaces))
for i, iface := range registeredInterfaces {
implementers := ir.ListImplementations(iface)
interfaceImplementers := make([]*InterfaceImplementerDescriptor, len(implementers))
for j, implementer := range implementers {
pb, err := ir.Resolve(implementer)
if err != nil {
return nil, fmt.Errorf("unable to resolve implementing type %s for interface %s", implementer, iface)
}
pbName := proto.MessageName(pb)
if pbName == "" {
return nil, fmt.Errorf("unable to get proto name for implementing type %s for interface %s", implementer, iface)
}
interfaceImplementers[j] = &InterfaceImplementerDescriptor{
Fullname: pbName,
TypeUrl: implementer,
}
}
interfaceDescriptors[i] = &InterfaceDescriptor{
Fullname: iface,
// NOTE(fdymylja): this could be filled, but it won't be filled as of now
// doing this would require us to fully rebuild in a (dependency) transitive way the proto
// registry of the supported proto.Messages for the application, this could be easily
// done if we weren't relying on gogoproto which does not allow us to iterate over the
// registry. Achieving this right now would mean to start slowly building descriptors
// getting their files dependencies, building those dependencies then rebuilding the
// descriptor builder. It's too much work as of now.
InterfaceAcceptingMessages: nil,
InterfaceImplementers: interfaceImplementers,
}
}
return &CodecDescriptor{
Interfaces: interfaceDescriptors,
}, nil
}
func newQueryServiceDescriptor(srv *grpc.Server) *QueryServicesDescriptor {
svcInfo := srv.GetServiceInfo()
queryServices := make([]*QueryServiceDescriptor, 0, len(svcInfo))
for name, info := range svcInfo {
methods := make([]*QueryMethodDescriptor, len(info.Methods))
for i, svcMethod := range info.Methods {
methods[i] = &QueryMethodDescriptor{
Name: svcMethod.Name,
FullQueryPath: fmt.Sprintf("/%s/%s", name, svcMethod.Name),
}
}
queryServices = append(queryServices, &QueryServiceDescriptor{
Fullname: name,
Methods: methods,
})
}
return &QueryServicesDescriptor{QueryServices: queryServices}
}
func newTxDescriptor(ir codectypes.InterfaceRegistry) (*TxDescriptor, error) {
// get base tx type name
txPbName := proto.MessageName(&tx.Tx{})
if txPbName == "" {
return nil, errors.New("unable to get *tx.Tx protobuf name")
}
// get msgs
sdkMsgImplementers := ir.ListImplementations(sdk.MsgInterfaceProtoName)
msgsDesc := make([]*MsgDescriptor, 0, len(sdkMsgImplementers))
// process sdk.Msg
for _, msgTypeURL := range sdkMsgImplementers {
msgsDesc = append(msgsDesc, &MsgDescriptor{
MsgTypeUrl: msgTypeURL,
})
}
return &TxDescriptor{
Fullname: txPbName,
Msgs: msgsDesc,
}, nil
}
func newAuthnDescriptor(signingModes map[string]int32) *AuthnDescriptor {
signModesDesc := make([]*SigningModeDescriptor, 0, len(signingModes))
for i, m := range signingModes {
signModesDesc = append(signModesDesc, &SigningModeDescriptor{
Name: i,
Number: m,
// NOTE(fdymylja): this cannot be filled as of now, auth and the sdk itself don't support as of now
// a service which allows to get authentication metadata for the provided sign mode.
AuthnInfoProviderMethodFullname: "",
})
}
return &AuthnDescriptor{SignModes: signModesDesc}
}

View File

@ -1,105 +0,0 @@
package grpc
import (
"context"
"fmt"
"net"
gogogrpcserver "github.com/cosmos/gogoproto/grpc"
"google.golang.org/grpc"
"cosmossdk.io/log"
"github.com/cosmos/cosmos-sdk/client"
"github.com/cosmos/cosmos-sdk/codec"
"github.com/cosmos/cosmos-sdk/server/config"
"github.com/cosmos/cosmos-sdk/server/grpc/gogoreflection"
reflection "github.com/cosmos/cosmos-sdk/server/grpc/reflection/v2alpha1"
_ "github.com/cosmos/cosmos-sdk/types/tx/amino" // Import amino.proto file for reflection
)
// NewGRPCServer returns a correctly configured and initialized gRPC server.
// Note, the caller is responsible for starting the server. See StartGRPCServer.
func NewGRPCServer(clientCtx client.Context, app interface{ RegisterGRPCServer(gogogrpcserver.Server) }, cfg config.GRPCConfig) (*grpc.Server, error) {
maxSendMsgSize := cfg.MaxSendMsgSize
if maxSendMsgSize == 0 {
maxSendMsgSize = config.DefaultGRPCMaxSendMsgSize
}
maxRecvMsgSize := cfg.MaxRecvMsgSize
if maxRecvMsgSize == 0 {
maxRecvMsgSize = config.DefaultGRPCMaxRecvMsgSize
}
grpcSrv := grpc.NewServer(
grpc.ForceServerCodec(codec.NewProtoCodec(clientCtx.InterfaceRegistry).GRPCCodec()),
grpc.MaxSendMsgSize(maxSendMsgSize),
grpc.MaxRecvMsgSize(maxRecvMsgSize),
)
app.RegisterGRPCServer(grpcSrv)
// Reflection allows consumers to build dynamic clients that can write to any
// Cosmos SDK application without relying on application packages at compile
// time.
err := reflection.Register(grpcSrv, reflection.Config{
SigningModes: func() map[string]int32 {
supportedModes := clientCtx.TxConfig.SignModeHandler().SupportedModes()
modes := make(map[string]int32, len(supportedModes))
for _, m := range supportedModes {
modes[m.String()] = (int32)(m)
}
return modes
}(),
ChainID: clientCtx.ChainID,
InterfaceRegistry: clientCtx.InterfaceRegistry,
})
if err != nil {
return nil, fmt.Errorf("failed to register reflection service: %w", err)
}
// Reflection allows external clients to see what services and methods
// the gRPC server exposes.
gogoreflection.Register(grpcSrv)
return grpcSrv, nil
}
// StartGRPCServer starts the provided gRPC server on the address specified in cfg.
//
// Note, this creates a blocking process if the server is started successfully.
// Otherwise, an error is returned. The caller is expected to provide a Context
// that is properly canceled or closed to indicate the server should be stopped.
func StartGRPCServer(ctx context.Context, logger log.Logger, cfg config.GRPCConfig, grpcSrv *grpc.Server) error {
listener, err := net.Listen("tcp", cfg.Address)
if err != nil {
return fmt.Errorf("failed to listen on address %s: %w", cfg.Address, err)
}
errCh := make(chan error)
// Start the gRPC in an external goroutine as Serve is blocking and will return
// an error upon failure, which we'll send on the error channel that will be
// consumed by the for block below.
go func() {
logger.Info("starting gRPC server...", "address", cfg.Address)
errCh <- grpcSrv.Serve(listener)
}()
// Start a blocking select to wait for an indication to stop the server or that
// the server failed to start properly.
select {
case <-ctx.Done():
// The calling process canceled or closed the provided context, so we must
// gracefully stop the gRPC server.
logger.Info("stopping gRPC server...", "address", cfg.Address)
grpcSrv.GracefulStop()
return nil
case err := <-errCh:
logger.Error("failed to start gRPC server", "err", err)
return err
}
}

View File

@ -1,23 +0,0 @@
package server
import (
cmtlog "github.com/cometbft/cometbft/libs/log"
"cosmossdk.io/log"
)
var _ cmtlog.Logger = (*CometLoggerWrapper)(nil)
// CometLoggerWrapper provides a wrapper around a cosmossdk.io/log instance.
// It implements CometBFT's Logger interface.
type CometLoggerWrapper struct {
log.Logger
}
// With returns a new wrapped logger with additional context provided by a set
// of key/value tuples. The number of tuples must be even and the key of the
// tuple must be a string.
func (cmt CometLoggerWrapper) With(keyVals ...interface{}) cmtlog.Logger {
logger := cmt.Logger.With(keyVals...)
return CometLoggerWrapper{logger}
}

View File

@ -1,220 +0,0 @@
package mock
import (
"context"
"encoding/json"
"errors"
"fmt"
"path/filepath"
abci "github.com/cometbft/cometbft/api/cometbft/abci/v1"
dbm "github.com/cosmos/cosmos-db"
"google.golang.org/grpc"
"google.golang.org/protobuf/proto"
"google.golang.org/protobuf/reflect/protodesc"
"google.golang.org/protobuf/reflect/protoregistry"
"google.golang.org/protobuf/types/descriptorpb"
"cosmossdk.io/log"
storetypes "cosmossdk.io/store/types"
bam "github.com/cosmos/cosmos-sdk/baseapp"
"github.com/cosmos/cosmos-sdk/codec"
"github.com/cosmos/cosmos-sdk/codec/testutil"
servertypes "github.com/cosmos/cosmos-sdk/server/types"
sdk "github.com/cosmos/cosmos-sdk/types"
genutiltypes "github.com/cosmos/cosmos-sdk/x/genutil/types"
)
// NewApp creates a simple mock kvstore app for testing. It should work
// similar to a real app. Make sure rootDir is empty before running the test,
// in order to guarantee consistent results.
func NewApp(rootDir string, logger log.Logger) (servertypes.ABCI, error) {
db, err := dbm.NewGoLevelDB("mock", filepath.Join(rootDir, "data"), nil)
if err != nil {
return nil, err
}
capKeyMainStore := storetypes.NewKVStoreKey("main")
baseApp := bam.NewBaseApp("kvstore", logger, db, decodeTx)
baseApp.MountStores(capKeyMainStore)
baseApp.SetInitChainer(InitChainer(capKeyMainStore))
interfaceRegistry := testutil.CodecOptions{}.NewInterfaceRegistry()
interfaceRegistry.RegisterImplementations((*sdk.Msg)(nil), &KVStoreTx{})
baseApp.SetInterfaceRegistry(interfaceRegistry)
router := bam.NewMsgServiceRouter()
router.SetInterfaceRegistry(interfaceRegistry)
newDesc := &grpc.ServiceDesc{
ServiceName: "Test",
Methods: []grpc.MethodDesc{
{
MethodName: "Test",
Handler: MsgTestHandler,
},
},
}
router.RegisterService(newDesc, &MsgServerImpl{capKeyMainStore})
baseApp.SetMsgServiceRouter(router)
if err := baseApp.LoadLatestVersion(); err != nil {
return nil, err
}
return baseApp, nil
}
// KVStoreHandler is a simple handler that takes KVStoreTx and writes
// them to the db.
func KVStoreHandler(storeKey storetypes.StoreKey) bam.MsgServiceHandler {
return func(ctx sdk.Context, msg sdk.Msg) (*sdk.Result, error) {
dTx, ok := msg.(*KVStoreTx)
if !ok {
return nil, errors.New("KVStoreHandler should only receive KVStoreTx")
}
key := dTx.key
value := dTx.value
store := ctx.KVStore(storeKey)
store.Set(key, value)
return &sdk.Result{
Log: fmt.Sprintf("set %s=%s", key, value),
}, nil
}
}
// KV is a basic kv structure
type KV struct {
Key string `json:"key"`
Value string `json:"value"`
}
// GenesisJSON what genesis JSON is formatted as
type GenesisJSON struct {
Values []KV `json:"values"`
}
// InitChainer returns a function that can initialize the chain
// with key/value pairs
func InitChainer(key storetypes.StoreKey) func(sdk.Context, *abci.InitChainRequest) (*abci.InitChainResponse, error) {
return func(ctx sdk.Context, req *abci.InitChainRequest) (*abci.InitChainResponse, error) {
stateJSON := req.AppStateBytes
genesisState := new(GenesisJSON)
err := json.Unmarshal(stateJSON, genesisState)
if err != nil {
return &abci.InitChainResponse{}, err
}
for _, val := range genesisState.Values {
store := ctx.KVStore(key)
store.Set([]byte(val.Key), []byte(val.Value))
}
return &abci.InitChainResponse{}, nil
}
}
// AppGenState can be passed into InitCmd, returns a static string of a few
// key-values that can be parsed by InitChainer
func AppGenState(_ *codec.LegacyAmino, _ genutiltypes.AppGenesis, _ []json.RawMessage) (appState json.RawMessage, err error) {
appState = json.RawMessage(`{
"values": [
{
"key": "hello",
"value": "goodbye"
},
{
"key": "foo",
"value": "bar"
}
]
}`)
return
}
// AppGenStateEmpty returns an empty transaction state for mocking.
func AppGenStateEmpty(_ *codec.LegacyAmino, _ genutiltypes.AppGenesis, _ []json.RawMessage) (appState json.RawMessage, err error) {
appState = json.RawMessage(``)
return
}
// MsgServer manually write the handlers for this custom message
type MsgServer interface {
Test(ctx context.Context, msg *KVStoreTx) (*sdk.Result, error)
}
type MsgServerImpl struct {
capKeyMainStore *storetypes.KVStoreKey
}
func MsgTestHandler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(KVStoreTx)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(MsgServer).Test(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/KVStoreTx",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(MsgServer).Test(ctx, req.(*KVStoreTx))
}
return interceptor(ctx, in, info, handler)
}
func (m MsgServerImpl) Test(ctx context.Context, msg *KVStoreTx) (*sdk.Result, error) {
return KVStoreHandler(m.capKeyMainStore)(sdk.UnwrapSDKContext(ctx), msg)
}
func init() {
err := registerFauxDescriptor()
if err != nil {
panic(err)
}
}
func registerFauxDescriptor() error {
fauxDescriptor, err := protodesc.NewFile(&descriptorpb.FileDescriptorProto{
Name: proto.String("faux_proto/test.proto"),
Dependency: nil,
PublicDependency: nil,
WeakDependency: nil,
MessageType: []*descriptorpb.DescriptorProto{
{
Name: proto.String("KVStoreTx"),
},
},
EnumType: nil,
Service: []*descriptorpb.ServiceDescriptorProto{
{
Name: proto.String("Test"),
Method: []*descriptorpb.MethodDescriptorProto{
{
Name: proto.String("Test"),
InputType: proto.String("KVStoreTx"),
OutputType: proto.String("KVStoreTx"),
},
},
},
},
Extension: nil,
Options: nil,
SourceCodeInfo: nil,
Syntax: nil,
Edition: nil,
}, nil)
if err != nil {
return err
}
return protoregistry.GlobalFiles.RegisterFile(fauxDescriptor)
}

View File

@ -1,99 +0,0 @@
package mock
import (
"context"
"math/rand"
"testing"
"time"
abci "github.com/cometbft/cometbft/api/cometbft/abci/v1"
"github.com/stretchr/testify/require"
"cosmossdk.io/log"
servertypes "github.com/cosmos/cosmos-sdk/server/types"
simtypes "github.com/cosmos/cosmos-sdk/types/simulation"
genutiltypes "github.com/cosmos/cosmos-sdk/x/genutil/types"
)
// SetupApp initializes a new application,
// failing t if initialization fails.
func SetupApp(t *testing.T) servertypes.ABCI {
t.Helper()
logger := log.NewTestLogger(t)
rootDir := t.TempDir()
app, err := NewApp(rootDir, logger)
require.NoError(t, err)
return app
}
func TestInitApp(t *testing.T) {
app := SetupApp(t)
appState, err := AppGenState(nil, genutiltypes.AppGenesis{}, nil)
require.NoError(t, err)
req := abci.InitChainRequest{
AppStateBytes: appState,
}
res, err := app.InitChain(&req)
require.NoError(t, err)
_, err = app.FinalizeBlock(&abci.FinalizeBlockRequest{
Hash: res.AppHash,
Height: 1,
})
require.NoError(t, err)
_, err = app.Commit()
require.NoError(t, err)
// make sure we can query these values
query := abci.QueryRequest{
Path: "/store/main/key",
Data: []byte("foo"),
}
qres, err := app.Query(context.Background(), &query)
require.NoError(t, err)
require.Equal(t, uint32(0), qres.Code, qres.Log)
require.Equal(t, []byte("bar"), qres.Value)
}
func TestDeliverTx(t *testing.T) {
app := SetupApp(t)
key := "my-special-key"
value := "top-secret-data!!"
r := rand.New(rand.NewSource(time.Now().UnixNano()))
randomAccounts := simtypes.RandomAccounts(r, 1)
tx := NewTx(key, value, randomAccounts[0].Address)
txBytes := tx.GetSignBytes()
res, err := app.FinalizeBlock(&abci.FinalizeBlockRequest{
Hash: []byte("apphash"),
Height: 1,
Txs: [][]byte{txBytes},
})
require.NoError(t, err)
require.NotEmpty(t, res.AppHash)
_, err = app.Commit()
require.NoError(t, err)
// make sure we can query these values
query := abci.QueryRequest{
Path: "/store/main/key",
Data: []byte(key),
}
qres, err := app.Query(context.Background(), &query)
require.NoError(t, err)
require.Equal(t, uint32(0), qres.Code, qres.Log)
require.Equal(t, []byte(value), qres.Value)
}

View File

@ -1,245 +0,0 @@
package mock
import (
"io"
protoio "github.com/cosmos/gogoproto/io"
corestore "cosmossdk.io/core/store"
"cosmossdk.io/store/metrics"
pruningtypes "cosmossdk.io/store/pruning/types"
snapshottypes "cosmossdk.io/store/snapshots/types"
storetypes "cosmossdk.io/store/types"
)
var _ storetypes.MultiStore = multiStore{}
type multiStore struct {
kv map[storetypes.StoreKey]kvStore
}
func (ms multiStore) CacheMultiStore() storetypes.CacheMultiStore {
panic("not implemented")
}
func (ms multiStore) CacheMultiStoreWithVersion(_ int64) (storetypes.CacheMultiStore, error) {
panic("not implemented")
}
func (ms multiStore) CacheWrap() storetypes.CacheWrap {
panic("not implemented")
}
func (ms multiStore) CacheWrapWithTrace(_ io.Writer, _ storetypes.TraceContext) storetypes.CacheWrap {
panic("not implemented")
}
func (ms multiStore) CacheWrapWithListeners(_ storetypes.StoreKey, _ []storetypes.MemoryListener) storetypes.CacheWrap {
panic("not implemented")
}
func (ms multiStore) TracingEnabled() bool {
panic("not implemented")
}
func (ms multiStore) SetTracingContext(tc storetypes.TraceContext) storetypes.MultiStore {
panic("not implemented")
}
func (ms multiStore) SetTracer(w io.Writer) storetypes.MultiStore {
panic("not implemented")
}
func (ms multiStore) AddListeners(keys []storetypes.StoreKey) {
panic("not implemented")
}
func (ms multiStore) SetMetrics(metrics.StoreMetrics) {
panic("not implemented")
}
func (ms multiStore) ListeningEnabled(key storetypes.StoreKey) bool {
panic("not implemented")
}
func (ms multiStore) PopStateCache() []*storetypes.StoreKVPair {
panic("not implemented")
}
func (ms multiStore) Commit() storetypes.CommitID {
panic("not implemented")
}
func (ms multiStore) LastCommitID() storetypes.CommitID {
panic("not implemented")
}
func (ms multiStore) SetPruning(opts pruningtypes.PruningOptions) {
panic("not implemented")
}
func (ms multiStore) GetPruning() pruningtypes.PruningOptions {
panic("not implemented")
}
func (ms multiStore) GetCommitKVStore(key storetypes.StoreKey) storetypes.CommitKVStore {
panic("not implemented")
}
func (ms multiStore) GetCommitStore(key storetypes.StoreKey) storetypes.CommitStore {
panic("not implemented")
}
func (ms multiStore) MountStoreWithDB(key storetypes.StoreKey, typ storetypes.StoreType, db corestore.KVStoreWithBatch) {
ms.kv[key] = kvStore{store: make(map[string][]byte)}
}
func (ms multiStore) LoadLatestVersion() error {
return nil
}
func (ms multiStore) LoadLatestVersionAndUpgrade(upgrades *storetypes.StoreUpgrades) error {
return nil
}
func (ms multiStore) LoadVersionAndUpgrade(ver int64, upgrades *storetypes.StoreUpgrades) error {
panic("not implemented")
}
func (ms multiStore) LoadVersion(ver int64) error {
panic("not implemented")
}
func (ms multiStore) GetKVStore(key storetypes.StoreKey) storetypes.KVStore {
return ms.kv[key]
}
func (ms multiStore) GetStore(key storetypes.StoreKey) storetypes.Store {
panic("not implemented")
}
func (ms multiStore) GetStoreType() storetypes.StoreType {
panic("not implemented")
}
func (ms multiStore) PruneSnapshotHeight(height int64) {
panic("not implemented")
}
func (ms multiStore) SetSnapshotInterval(snapshotInterval uint64) {
panic("not implemented")
}
func (ms multiStore) SetInterBlockCache(_ storetypes.MultiStorePersistentCache) {
panic("not implemented")
}
func (ms multiStore) SetIAVLCacheSize(size int) {
panic("not implemented")
}
func (ms multiStore) SetIAVLDisableFastNode(disable bool) {
panic("not implemented")
}
func (ms multiStore) SetIAVLSyncPruning(syncPruning bool) {
panic("not implemented")
}
func (ms multiStore) SetInitialVersion(version int64) error {
panic("not implemented")
}
func (ms multiStore) Snapshot(height uint64, protoWriter protoio.Writer) error {
panic("not implemented")
}
func (ms multiStore) Restore(
height uint64, format uint32, protoReader protoio.Reader,
) (snapshottypes.SnapshotItem, error) {
panic("not implemented")
}
func (ms multiStore) RollbackToVersion(version int64) error {
panic("not implemented")
}
func (ms multiStore) LatestVersion() int64 {
panic("not implemented")
}
func (ms multiStore) WorkingHash() []byte {
panic("not implemented")
}
var _ storetypes.KVStore = kvStore{}
type kvStore struct {
store map[string][]byte
}
func (kv kvStore) CacheWrap() storetypes.CacheWrap {
panic("not implemented")
}
func (kv kvStore) CacheWrapWithTrace(w io.Writer, tc storetypes.TraceContext) storetypes.CacheWrap {
panic("not implemented")
}
func (kv kvStore) CacheWrapWithListeners(_ storetypes.StoreKey, _ []storetypes.MemoryListener) storetypes.CacheWrap {
panic("not implemented")
}
func (kv kvStore) GetStoreType() storetypes.StoreType {
panic("not implemented")
}
func (kv kvStore) Get(key []byte) []byte {
v, ok := kv.store[string(key)]
if !ok {
return nil
}
return v
}
func (kv kvStore) Has(key []byte) bool {
_, ok := kv.store[string(key)]
return ok
}
func (kv kvStore) Set(key, value []byte) {
storetypes.AssertValidKey(key)
kv.store[string(key)] = value
}
func (kv kvStore) Delete(key []byte) {
delete(kv.store, string(key))
}
func (kv kvStore) Prefix(prefix []byte) storetypes.KVStore {
panic("not implemented")
}
func (kv kvStore) Gas(meter storetypes.GasMeter, config storetypes.GasConfig) storetypes.KVStore {
panic("not implemented")
}
func (kv kvStore) Iterator(start, end []byte) storetypes.Iterator {
panic("not implemented")
}
func (kv kvStore) ReverseIterator(start, end []byte) storetypes.Iterator {
panic("not implemented")
}
func (kv kvStore) SubspaceIterator(prefix []byte) storetypes.Iterator {
panic("not implemented")
}
func (kv kvStore) ReverseSubspaceIterator(prefix []byte) storetypes.Iterator {
panic("not implemented")
}
func NewCommitMultiStore() storetypes.CommitMultiStore {
return multiStore{kv: make(map[storetypes.StoreKey]kvStore)}
}

View File

@ -1,35 +0,0 @@
package mock
import (
"testing"
"github.com/stretchr/testify/require"
coretesting "cosmossdk.io/core/testing"
storetypes "cosmossdk.io/store/types"
)
func TestStore(t *testing.T) {
db := coretesting.NewMemDB()
cms := NewCommitMultiStore()
key := storetypes.NewKVStoreKey("test")
cms.MountStoreWithDB(key, storetypes.StoreTypeIAVL, db)
err := cms.LoadLatestVersion()
require.Nil(t, err)
store := cms.GetKVStore(key)
require.NotNil(t, store)
k := []byte("hello")
v := []byte("world")
require.False(t, store.Has(k))
store.Set(k, v)
require.True(t, store.Has(k))
require.Equal(t, v, store.Get(k))
store.Delete(k)
require.False(t, store.Has(k))
require.Panics(t, func() { store.Set([]byte(""), v) }, "setting an empty key should panic")
require.Panics(t, func() { store.Set(nil, v) }, "setting a nil key should panic")
}

View File

@ -1,163 +0,0 @@
package mock
import (
"bytes"
"fmt"
"google.golang.org/protobuf/reflect/protoreflect"
bankv1beta1 "cosmossdk.io/api/cosmos/bank/v1beta1"
"cosmossdk.io/core/transaction"
errorsmod "cosmossdk.io/errors"
cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"
sdk "github.com/cosmos/cosmos-sdk/types"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
txsigning "github.com/cosmos/cosmos-sdk/types/tx/signing"
"github.com/cosmos/cosmos-sdk/x/auth/signing"
)
// KVStoreTx is an sdk.Tx which is its own sdk.Msg.
type KVStoreTx struct {
key []byte
value []byte
bytes []byte
address sdk.AccAddress
}
// testPubKey is a dummy implementation of PubKey used for testing.
type testPubKey struct {
address sdk.AccAddress
}
func (t testPubKey) Reset() { panic("not implemented") }
func (t testPubKey) String() string { panic("not implemented") }
func (t testPubKey) ProtoMessage() { panic("not implemented") }
func (t testPubKey) Address() cryptotypes.Address { return t.address.Bytes() }
func (t testPubKey) Bytes() []byte { panic("not implemented") }
func (t testPubKey) VerifySignature(msg, sig []byte) bool { panic("not implemented") }
func (t testPubKey) Equals(key cryptotypes.PubKey) bool { panic("not implemented") }
func (t testPubKey) Type() string { panic("not implemented") }
func (msg *KVStoreTx) GetSignaturesV2() (res []txsigning.SignatureV2, err error) {
res = append(res, txsigning.SignatureV2{
PubKey: testPubKey{address: msg.address},
Data: nil,
Sequence: 1,
})
return res, nil
}
func (msg *KVStoreTx) VerifySignature(msgByte, sig []byte) bool {
panic("implement me")
}
func (msg *KVStoreTx) Address() cryptotypes.Address {
panic("implement me")
}
func (msg *KVStoreTx) Bytes() []byte {
panic("implement me")
}
func (msg *KVStoreTx) Equals(key cryptotypes.PubKey) bool {
panic("implement me")
}
// dummy implementation of proto.Message
func (msg *KVStoreTx) Reset() {}
func (msg *KVStoreTx) String() string { return "TODO" }
func (msg *KVStoreTx) ProtoMessage() {}
var (
_ sdk.Tx = &KVStoreTx{}
_ sdk.Msg = &KVStoreTx{}
_ signing.SigVerifiableTx = &KVStoreTx{}
_ cryptotypes.PubKey = &KVStoreTx{}
_ cryptotypes.PubKey = &testPubKey{}
)
func NewTx(key, value string, accAddress sdk.AccAddress) *KVStoreTx {
bytes := fmt.Sprintf("%s=%s=%s", key, value, accAddress)
return &KVStoreTx{
key: []byte(key),
value: []byte(value),
bytes: []byte(bytes),
address: accAddress,
}
}
func (msg *KVStoreTx) Hash() [32]byte {
return [32]byte{}
}
func (msg *KVStoreTx) GetGasLimit() (uint64, error) {
return 0, nil
}
func (msg *KVStoreTx) GetMessages() ([]transaction.Msg, error) {
return nil, nil
}
func (msg *KVStoreTx) GetSenders() ([][]byte, error) {
return nil, nil
}
func (msg *KVStoreTx) Type() string {
return "kvstore_tx"
}
func (msg *KVStoreTx) GetMsgs() []sdk.Msg {
return []sdk.Msg{msg}
}
func (msg *KVStoreTx) GetReflectMessages() ([]protoreflect.Message, error) {
return []protoreflect.Message{(&bankv1beta1.MsgSend{FromAddress: msg.address.String()}).ProtoReflect()}, nil // this is a hack for tests
}
func (msg *KVStoreTx) GetSignBytes() []byte {
return msg.bytes
}
// ValidateBasic should the app be calling this? or only handlers?
func (msg *KVStoreTx) ValidateBasic() error {
return nil
}
func (msg *KVStoreTx) GetSigners() ([][]byte, error) {
return nil, nil
}
func (msg *KVStoreTx) GetPubKeys() ([]cryptotypes.PubKey, error) { panic("GetPubKeys not implemented") }
// takes raw transaction bytes and decodes them into an sdk.Tx. An sdk.Tx has
// all the signatures and can be used to authenticate.
func decodeTx(txBytes []byte) (sdk.Tx, error) {
var tx sdk.Tx
split := bytes.Split(txBytes, []byte("="))
switch len(split) {
case 1:
k := split[0]
tx = &KVStoreTx{k, k, txBytes, nil}
case 2:
k, v := split[0], split[1]
tx = &KVStoreTx{k, v, txBytes, nil}
case 3:
k, v, addr := split[0], split[1], split[2]
tx = &KVStoreTx{k, v, txBytes, addr}
default:
return nil, errorsmod.Wrap(sdkerrors.ErrTxDecode, "too many '='")
}
return tx, nil
}

View File

@ -1,49 +0,0 @@
package types
import (
"context"
abci "github.com/cometbft/cometbft/api/cometbft/abci/v1"
)
// ABCI is an interface that enables any finite, deterministic state machine
// to be driven by a blockchain-based replication engine via the ABCI.
type ABCI interface {
// Info/Query Connection
// Info returns application info
Info(*abci.InfoRequest) (*abci.InfoResponse, error)
// Query returns application state
Query(context.Context, *abci.QueryRequest) (*abci.QueryResponse, error)
// Mempool Connection
// CheckTx validate a tx for the mempool
CheckTx(*abci.CheckTxRequest) (*abci.CheckTxResponse, error)
// Consensus Connection
// InitChain Initialize blockchain w validators/other info from CometBFT
InitChain(*abci.InitChainRequest) (*abci.InitChainResponse, error)
PrepareProposal(*abci.PrepareProposalRequest) (*abci.PrepareProposalResponse, error)
ProcessProposal(*abci.ProcessProposalRequest) (*abci.ProcessProposalResponse, error)
// FinalizeBlock deliver the decided block with its txs to the Application
FinalizeBlock(*abci.FinalizeBlockRequest) (*abci.FinalizeBlockResponse, error)
// ExtendVote create application specific vote extension
ExtendVote(context.Context, *abci.ExtendVoteRequest) (*abci.ExtendVoteResponse, error)
// VerifyVoteExtension verify application's vote extension data
VerifyVoteExtension(*abci.VerifyVoteExtensionRequest) (*abci.VerifyVoteExtensionResponse, error)
// Commit the state and return the application Merkle root hash
Commit() (*abci.CommitResponse, error)
// State Sync Connection
// ListSnapshots list available snapshots
ListSnapshots(*abci.ListSnapshotsRequest) (*abci.ListSnapshotsResponse, error)
// OfferSnapshot offer a snapshot to the application
OfferSnapshot(*abci.OfferSnapshotRequest) (*abci.OfferSnapshotResponse, error)
// LoadSnapshotChunk load a snapshot chunk
LoadSnapshotChunk(*abci.LoadSnapshotChunkRequest) (*abci.LoadSnapshotChunkResponse, error)
// ApplySnapshotChunk apply a snapshot chunk
ApplySnapshotChunk(*abci.ApplySnapshotChunkRequest) (*abci.ApplySnapshotChunkResponse, error)
}

View File

@ -1,95 +0,0 @@
package types
import (
"encoding/json"
"io"
cmtproto "github.com/cometbft/cometbft/api/cometbft/types/v1"
cmtcrypto "github.com/cometbft/cometbft/crypto"
"github.com/cosmos/gogoproto/grpc"
"cosmossdk.io/core/server"
corestore "cosmossdk.io/core/store"
"cosmossdk.io/log"
"cosmossdk.io/store/snapshots"
storetypes "cosmossdk.io/store/types"
"github.com/cosmos/cosmos-sdk/client"
"github.com/cosmos/cosmos-sdk/server/config"
sdk "github.com/cosmos/cosmos-sdk/types"
)
type (
// AppOptions defines an interface that is passed into an application
// constructor, typically used to set BaseApp options that are either supplied
// via config file or through CLI arguments/flags. The underlying implementation
// is defined by the server package and is typically implemented via a Viper
// literal defined on the server Context. Note, casting Get calls may not yield
// the expected types and could result in type assertion errors. It is recommend
// to either use the cast package or perform manual conversion for safety.
AppOptions = server.DynamicConfig
// Application defines an application interface that wraps abci.Application.
// The interface defines the necessary contracts to be implemented in order
// to fully bootstrap and start an application.
Application interface {
ABCI
// RegisterGRPCServer registers gRPC services directly with the gRPC
// server.
RegisterGRPCServer(grpc.Server)
// RegisterTxService registers the gRPC Query service for tx (such as tx
// simulation, fetching txs by hash...).
RegisterTxService(client.Context)
// RegisterTendermintService registers the gRPC Query service for CometBFT queries.
RegisterTendermintService(client.Context)
// RegisterNodeService registers the node gRPC Query service.
RegisterNodeService(client.Context, config.Config)
// CommitMultiStore return the multistore instance
CommitMultiStore() storetypes.CommitMultiStore
// SnapshotManager return the snapshot manager
SnapshotManager() *snapshots.Manager
// ValidatorKeyProvider returns a function that generates a validator key
ValidatorKeyProvider() func() (cmtcrypto.PrivKey, error)
// Close is called in start cmd to gracefully cleanup resources.
// Must be safe to be called multiple times.
Close() error
}
// AppCreator is a function that allows us to lazily initialize an
// application using various configurations.
AppCreator[T Application] func(log.Logger, corestore.KVStoreWithBatch, io.Writer, AppOptions) T
// ExportedApp represents an exported app state, along with
// validators, consensus params and latest app height.
ExportedApp struct {
// AppState is the application state as JSON.
AppState json.RawMessage
// Validators is the exported validator set.
Validators []sdk.GenesisValidator
// Height is the app's latest block height.
Height int64
// ConsensusParams are the exported consensus params for ABCI.
ConsensusParams cmtproto.ConsensusParams
}
// AppExporter is a function that dumps all app state to
// JSON-serializable structure and returns the current validator set.
AppExporter func(
logger log.Logger,
db corestore.KVStoreWithBatch,
traceWriter io.Writer,
height int64,
forZeroHeight bool,
jailAllowedAddrs []string,
opts AppOptions,
modulesToExport []string,
) (ExportedApp, error)
)

View File

@ -11,6 +11,7 @@ import (
dbm "github.com/cosmos/cosmos-db"
"github.com/stretchr/testify/require"
"cosmossdk.io/core/server"
corestore "cosmossdk.io/core/store"
"cosmossdk.io/log"
@ -19,8 +20,6 @@ import (
"github.com/cosmos/cosmos-sdk/client/flags"
"github.com/cosmos/cosmos-sdk/codec"
"github.com/cosmos/cosmos-sdk/runtime"
"github.com/cosmos/cosmos-sdk/server"
servertypes "github.com/cosmos/cosmos-sdk/server/types"
simtestutil "github.com/cosmos/cosmos-sdk/testutil/sims"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/types/module"
@ -77,7 +76,7 @@ func Run[T SimulationApp](
db corestore.KVStoreWithBatch,
traceStore io.Writer,
loadLatest bool,
appOpts servertypes.AppOptions,
appOpts server.DynamicConfig,
baseAppOptions ...func(*baseapp.BaseApp),
) T,
setupStateFactory func(app T) SimStateFactory,
@ -103,7 +102,7 @@ func RunWithSeeds[T SimulationApp](
db corestore.KVStoreWithBatch,
traceStore io.Writer,
loadLatest bool,
appOpts servertypes.AppOptions,
appOpts server.DynamicConfig,
baseAppOptions ...func(*baseapp.BaseApp),
) T,
setupStateFactory func(app T) SimStateFactory,
@ -123,7 +122,7 @@ func RunWithSeedsAndRandAcc[T SimulationApp](
db corestore.KVStoreWithBatch,
traceStore io.Writer,
loadLatest bool,
appOpts servertypes.AppOptions,
appOpts server.DynamicConfig,
baseAppOptions ...func(*baseapp.BaseApp),
) T,
setupStateFactory func(app T) SimStateFactory,
@ -153,7 +152,7 @@ func RunWithSeedsAndRandAcc[T SimulationApp](
func RunWithSeed[T SimulationApp](
tb testing.TB,
cfg simtypes.Config,
appFactory func(logger log.Logger, db corestore.KVStoreWithBatch, traceStore io.Writer, loadLatest bool, appOpts servertypes.AppOptions, baseAppOptions ...func(*baseapp.BaseApp)) T,
appFactory func(logger log.Logger, db corestore.KVStoreWithBatch, traceStore io.Writer, loadLatest bool, appOpts server.DynamicConfig, baseAppOptions ...func(*baseapp.BaseApp)) T,
setupStateFactory func(app T) SimStateFactory,
seed int64,
fuzzSeed []byte,
@ -167,7 +166,7 @@ func RunWithSeed[T SimulationApp](
func RunWithSeedAndRandAcc[T SimulationApp](
tb testing.TB,
cfg simtypes.Config,
appFactory func(logger log.Logger, db corestore.KVStoreWithBatch, traceStore io.Writer, loadLatest bool, appOpts servertypes.AppOptions, baseAppOptions ...func(*baseapp.BaseApp)) T,
appFactory func(logger log.Logger, db corestore.KVStoreWithBatch, traceStore io.Writer, loadLatest bool, appOpts server.DynamicConfig, baseAppOptions ...func(*baseapp.BaseApp)) T,
setupStateFactory func(app T) SimStateFactory,
seed int64,
fuzzSeed []byte,
@ -330,7 +329,7 @@ func prepareWeightedOps(
func NewSimulationAppInstance[T SimulationApp](
tb testing.TB,
tCfg simtypes.Config,
appFactory func(logger log.Logger, db corestore.KVStoreWithBatch, traceStore io.Writer, loadLatest bool, appOpts servertypes.AppOptions, baseAppOptions ...func(*baseapp.BaseApp)) T,
appFactory func(logger log.Logger, db corestore.KVStoreWithBatch, traceStore io.Writer, loadLatest bool, appOpts server.DynamicConfig, baseAppOptions ...func(*baseapp.BaseApp)) T,
) TestInstance[T] {
tb.Helper()
workDir := tb.TempDir()
@ -350,7 +349,7 @@ func NewSimulationAppInstance[T SimulationApp](
})
appOptions := make(simtestutil.AppOptionsMap)
appOptions[flags.FlagHome] = workDir
appOptions[server.FlagInvCheckPeriod] = cli.FlagPeriodValue
appOptions[flags.FlagInvCheckPeriod] = cli.FlagPeriodValue
opts := []func(*baseapp.BaseApp){baseapp.SetChainID(tCfg.ChainID)}
if tCfg.FauxMerkle {
opts = append(opts, FauxMerkleModeOpt)

View File

@ -1,20 +1,14 @@
package server
package genutil
import (
"context"
abci "github.com/cometbft/cometbft/abci/types"
abciproto "github.com/cometbft/cometbft/api/cometbft/abci/v1"
servertypes "github.com/cosmos/cosmos-sdk/server/types"
"github.com/cosmos/cosmos-sdk/runtime"
)
type cometABCIWrapper struct {
app servertypes.ABCI
}
func NewCometABCIWrapper(app servertypes.ABCI) abci.Application {
return cometABCIWrapper{app: app}
app *runtime.App
}
func (w cometABCIWrapper) Info(_ context.Context, req *abciproto.InfoRequest) (*abciproto.InfoResponse, error) {

View File

@ -1,12 +1,9 @@
package genutil
import (
"bytes"
"context"
"fmt"
"io"
"net"
"os"
"testing"
"time"
@ -15,7 +12,11 @@ import (
"github.com/stretchr/testify/require"
corectx "cosmossdk.io/core/context"
"cosmossdk.io/depinject"
"cosmossdk.io/log"
_ "cosmossdk.io/x/accounts"
_ "cosmossdk.io/x/bank"
_ "cosmossdk.io/x/consensus"
"cosmossdk.io/x/staking"
"github.com/cosmos/cosmos-sdk/client"
@ -24,16 +25,16 @@ import (
"github.com/cosmos/cosmos-sdk/codec/types"
cryptocodec "github.com/cosmos/cosmos-sdk/crypto/codec"
"github.com/cosmos/cosmos-sdk/crypto/keys/ed25519"
"github.com/cosmos/cosmos-sdk/server"
servercmtlog "github.com/cosmos/cosmos-sdk/server/log"
"github.com/cosmos/cosmos-sdk/server/mock"
"github.com/cosmos/cosmos-sdk/testutil"
"github.com/cosmos/cosmos-sdk/testutil/configurator"
simtestutil "github.com/cosmos/cosmos-sdk/testutil/sims"
genutilhelpers "github.com/cosmos/cosmos-sdk/testutil/x/genutil"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/types/module"
"github.com/cosmos/cosmos-sdk/x/genutil"
genutilcli "github.com/cosmos/cosmos-sdk/x/genutil/client/cli"
genutiltypes "github.com/cosmos/cosmos-sdk/x/genutil/types"
_ "github.com/cosmos/cosmos-sdk/x/validate"
)
var testMbm = module.NewManager(
@ -159,76 +160,88 @@ func TestInitDefaultBondDenom(t *testing.T) {
}
func TestEmptyState(t *testing.T) {
home := t.TempDir()
logger := log.NewNopLogger()
viper := viper.New()
// TODO: rewrite for v2: https://github.com/cosmos/cosmos-sdk/issues/20799
err := writeAndTrackDefaultConfig(viper, home)
require.NoError(t, err)
interfaceRegistry := types.NewInterfaceRegistry()
marshaler := codec.NewProtoCodec(interfaceRegistry)
clientCtx := client.Context{}.
WithCodec(marshaler).
WithLegacyAmino(makeAminoCodec()).
WithHomeDir(home)
// home := t.TempDir()
// logger := log.NewNopLogger()
// viper := viper.New()
ctx := context.Background()
ctx = context.WithValue(ctx, client.ClientContextKey, &clientCtx)
ctx = context.WithValue(ctx, corectx.ViperContextKey, viper)
ctx = context.WithValue(ctx, corectx.LoggerContextKey, logger)
// err := writeAndTrackDefaultConfig(viper, home)
// require.NoError(t, err)
// interfaceRegistry := types.NewInterfaceRegistry()
// marshaler := codec.NewProtoCodec(interfaceRegistry)
// clientCtx := client.Context{}.
// WithCodec(marshaler).
// WithLegacyAmino(makeAminoCodec()).
// WithHomeDir(home)
cmd := genutilcli.InitCmd(testMbm)
cmd.SetArgs([]string{"appnode-test"})
// ctx := context.Background()
// ctx = context.WithValue(ctx, client.ClientContextKey, &clientCtx)
// ctx = context.WithValue(ctx, corectx.ViperContextKey, viper)
// ctx = context.WithValue(ctx, corectx.LoggerContextKey, logger)
require.NoError(t, cmd.ExecuteContext(ctx))
// cmd := genutilcli.InitCmd(testMbm)
// cmd.SetArgs([]string{"appnode-test"})
old := os.Stdout
r, w, _ := os.Pipe()
os.Stdout = w
// require.NoError(t, cmd.ExecuteContext(ctx))
cmd = genutilcli.ExportCmd(nil)
require.NoError(t, cmd.ExecuteContext(ctx))
// old := os.Stdout
// r, w, _ := os.Pipe()
// os.Stdout = w
outC := make(chan string)
go func() {
var buf bytes.Buffer
_, err := io.Copy(&buf, r)
require.NoError(t, err)
// cmd = genutilcli.ExportCmd(nil)
// require.NoError(t, cmd.ExecuteContext(ctx))
outC <- buf.String()
}()
// outC := make(chan string)
// go func() {
// var buf bytes.Buffer
// _, err := io.Copy(&buf, r)
// require.NoError(t, err)
w.Close()
os.Stdout = old
out := <-outC
// outC <- buf.String()
// }()
require.Contains(t, out, "genesis_time")
require.Contains(t, out, "chain_id")
require.Contains(t, out, "consensus")
require.Contains(t, out, "app_hash")
require.Contains(t, out, "app_state")
// w.Close()
// os.Stdout = old
// out := <-outC
// require.Contains(t, out, "genesis_time")
// require.Contains(t, out, "chain_id")
// require.Contains(t, out, "consensus")
// require.Contains(t, out, "app_hash")
// require.Contains(t, out, "app_state")
}
func TestStartStandAlone(t *testing.T) {
home := t.TempDir()
logger := log.NewNopLogger()
interfaceRegistry := types.NewInterfaceRegistry()
marshaler := codec.NewProtoCodec(interfaceRegistry)
err := genutilhelpers.ExecInitCmd(testMbm, home, marshaler)
require.NoError(t, err)
app, err := mock.NewApp(home, logger)
app, err := simtestutil.SetupWithConfiguration(
depinject.Configs(
configurator.NewAppConfig(
configurator.AccountsModule(),
configurator.AuthModule(),
configurator.StakingModule(),
configurator.TxModule(),
configurator.ValidateModule(),
configurator.ConsensusModule(),
configurator.BankModule(),
),
depinject.Supply(log.NewNopLogger()),
), simtestutil.DefaultStartUpConfig())
require.NoError(t, err)
svrAddr, _, closeFn, err := freeTCPAddr()
require.NoError(t, err)
require.NoError(t, closeFn())
cmtApp := server.NewCometABCIWrapper(app)
cmtApp := cometABCIWrapper{app}
svr, err := abci_server.NewServer(svrAddr, "socket", cmtApp)
require.NoError(t, err, "error creating listener")
svr.SetLogger(servercmtlog.CometLoggerWrapper{Logger: logger.With("module", "abci-server")})
err = svr.Start()
require.NoError(t, err)
@ -253,51 +266,53 @@ func TestInitNodeValidatorFiles(t *testing.T) {
}
func TestInitConfig(t *testing.T) {
home := t.TempDir()
logger := log.NewNopLogger()
viper := viper.New()
// TODO: rewrite for v2: https://github.com/cosmos/cosmos-sdk/issues/20799
err := writeAndTrackDefaultConfig(viper, home)
require.NoError(t, err)
interfaceRegistry := types.NewInterfaceRegistry()
marshaler := codec.NewProtoCodec(interfaceRegistry)
clientCtx := client.Context{}.
WithCodec(marshaler).
WithLegacyAmino(makeAminoCodec()).
WithChainID("foo"). // add chain-id to clientCtx
WithHomeDir(home)
// home := t.TempDir()
// logger := log.NewNopLogger()
// viper := viper.New()
ctx := context.Background()
ctx = context.WithValue(ctx, client.ClientContextKey, &clientCtx)
ctx = context.WithValue(ctx, corectx.ViperContextKey, viper)
ctx = context.WithValue(ctx, corectx.LoggerContextKey, logger)
// err := writeAndTrackDefaultConfig(viper, home)
// require.NoError(t, err)
// interfaceRegistry := types.NewInterfaceRegistry()
// marshaler := codec.NewProtoCodec(interfaceRegistry)
// clientCtx := client.Context{}.
// WithCodec(marshaler).
// WithLegacyAmino(makeAminoCodec()).
// WithChainID("foo"). // add chain-id to clientCtx
// WithHomeDir(home)
cmd := genutilcli.InitCmd(testMbm)
cmd.SetArgs([]string{"testnode"})
// ctx := context.Background()
// ctx = context.WithValue(ctx, client.ClientContextKey, &clientCtx)
// ctx = context.WithValue(ctx, corectx.ViperContextKey, viper)
// ctx = context.WithValue(ctx, corectx.LoggerContextKey, logger)
err = cmd.ExecuteContext(ctx)
require.NoError(t, err)
// cmd := genutilcli.InitCmd(testMbm)
// cmd.SetArgs([]string{"testnode"})
old := os.Stdout
r, w, _ := os.Pipe()
os.Stdout = w
// err = cmd.ExecuteContext(ctx)
// require.NoError(t, err)
cmd = genutilcli.ExportCmd(nil)
require.NoError(t, cmd.ExecuteContext(ctx))
// old := os.Stdout
// r, w, _ := os.Pipe()
// os.Stdout = w
outC := make(chan string)
go func() {
var buf bytes.Buffer
_, err := io.Copy(&buf, r)
require.NoError(t, err)
outC <- buf.String()
}()
// cmd = genutilcli.ExportCmd(nil)
// require.NoError(t, cmd.ExecuteContext(ctx))
w.Close()
os.Stdout = old
out := <-outC
// outC := make(chan string)
// go func() {
// var buf bytes.Buffer
// _, err := io.Copy(&buf, r)
// require.NoError(t, err)
// outC <- buf.String()
// }()
require.Contains(t, out, "\"chain_id\": \"foo\"")
// w.Close()
// os.Stdout = old
// out := <-outC
// require.Contains(t, out, "\"chain_id\": \"foo\"")
}
func TestInitWithHeight(t *testing.T) {

View File

@ -11,6 +11,7 @@ import (
cmtjson "github.com/cometbft/cometbft/libs/json"
cmttypes "github.com/cometbft/cometbft/types"
"cosmossdk.io/core/server"
corestore "cosmossdk.io/core/store"
coretesting "cosmossdk.io/core/testing"
"cosmossdk.io/depinject"
@ -24,7 +25,6 @@ import (
cryptocodec "github.com/cosmos/cosmos-sdk/crypto/codec"
"github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1"
"github.com/cosmos/cosmos-sdk/runtime"
servertypes "github.com/cosmos/cosmos-sdk/server/types"
"github.com/cosmos/cosmos-sdk/testutil/mock"
sdk "github.com/cosmos/cosmos-sdk/types"
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
@ -312,7 +312,7 @@ func (m AppOptionsMap) GetString(key string) string {
return v.(string)
}
func NewAppOptionsWithFlagHome(homePath string) servertypes.AppOptions {
func NewAppOptionsWithFlagHome(homePath string) server.DynamicConfig {
return AppOptionsMap{
flags.FlagHome: homePath,
}

View File

@ -31,6 +31,8 @@ Ref: https://keepachangelog.com/en/1.0.0/
## [Unreleased]
* [#23238](https://github.com/cosmos/cosmos-sdk/pull/23238) Loosen `app.toml` validation for consistency between baseapp chains and v2 chains.
## [v0.2.0-rc.1](https://github.com/cosmos/cosmos-sdk/releases/tag/tools/confix/v0.2.0-rc.1) - 2024-12-18
* [#21052](https://github.com/cosmos/cosmos-sdk/pull/21052) Add a migration to v2 config.

View File

@ -14,7 +14,6 @@ import (
"github.com/spf13/viper"
clientcfg "github.com/cosmos/cosmos-sdk/client/config"
srvcfg "github.com/cosmos/cosmos-sdk/server/config"
)
// Upgrade reads the configuration file at configPath and applies any
@ -43,11 +42,8 @@ func Upgrade(ctx context.Context, plan transform.Plan, doc *tomledit.Document, c
return fmt.Errorf("formatting config: %w", err)
}
// ignore validation for serverv2 by checking any default field found in doc
isServerV2 := doc.First(strings.Split("store.options.sc-pruning-option", ".")...) != nil
// allow to skip validation
if !skipValidate && !isServerV2 {
if !skipValidate {
// verify that file is valid after applying fixes
if err := CheckValid(configPath, buf.Bytes()); err != nil {
return fmt.Errorf("updated config is invalid: %w", err)
@ -76,14 +72,8 @@ func CheckValid(fileName string, data []byte) error {
switch {
case strings.HasSuffix(fileName, AppConfig):
var cfg srvcfg.Config
if err := v.Unmarshal(&cfg); err != nil {
return fmt.Errorf("failed to unmarshal as server config: %w", err)
}
if err := cfg.ValidateBasic(); err != nil {
return fmt.Errorf("server config invalid: %w", err)
}
// no validation of server config as v1 and v2 configs are both valid.
// any app.toml is simply considered as a server config.
case strings.HasSuffix(fileName, ClientConfig):
var cfg clientcfg.ClientConfig
if err := v.Unmarshal(&cfg); err != nil {

View File

@ -35,9 +35,6 @@ func TestCheckValid(t *testing.T) {
err = confix.CheckValid("client.toml", []byte{})
assert.Error(t, err, "client config invalid: chain-id is empty")
err = confix.CheckValid("app.toml", []byte{})
assert.ErrorContains(t, err, "server config invalid")
err = confix.CheckValid("app.toml", mustReadConfig(t, "data/v0.45-app.toml"))
assert.NilError(t, err)

View File

@ -19,7 +19,6 @@ import (
addresscodec "github.com/cosmos/cosmos-sdk/codec/address"
codectestutil "github.com/cosmos/cosmos-sdk/codec/testutil"
"github.com/cosmos/cosmos-sdk/crypto/keyring"
svrcmd "github.com/cosmos/cosmos-sdk/server/cmd"
"github.com/cosmos/cosmos-sdk/testutil"
clitestutil "github.com/cosmos/cosmos-sdk/testutil/cli"
sdk "github.com/cosmos/cosmos-sdk/types"
@ -120,14 +119,12 @@ func (s *CLITestSuite) TestTxInitCmd() {
for _, tc := range testCases {
s.Run(tc.name, func() {
ctx := svrcmd.CreateExecuteContext(context.Background())
var args []string
args = append(args, tc.accountType)
args = append(args, tc.jsonMsg)
args = append(args, tc.extraArgs...)
cmd.SetContext(ctx)
cmd.SetContext(context.WithValue(context.Background(), client.ClientContextKey, &client.Context{}))
cmd.SetArgs(args)
out, err := clitestutil.ExecTestCLICmd(s.clientCtx, cmd, args)

View File

@ -17,7 +17,6 @@ import (
addresscodec "github.com/cosmos/cosmos-sdk/codec/address"
codectestutil "github.com/cosmos/cosmos-sdk/codec/testutil"
"github.com/cosmos/cosmos-sdk/crypto/keyring"
svrcmd "github.com/cosmos/cosmos-sdk/server/cmd"
"github.com/cosmos/cosmos-sdk/testutil"
clitestutil "github.com/cosmos/cosmos-sdk/testutil/cli"
sdk "github.com/cosmos/cosmos-sdk/types"
@ -149,15 +148,13 @@ func (s *CLITestSuite) TestMultiSendTxCmd() {
for _, tc := range testCases {
s.Run(tc.name, func() {
ctx := svrcmd.CreateExecuteContext(context.Background())
var args []string
args = append(args, tc.from)
args = append(args, tc.to...)
args = append(args, tc.amount.String())
args = append(args, tc.extraArgs...)
cmd.SetContext(ctx)
cmd.SetContext(context.WithValue(context.Background(), client.ClientContextKey, &client.Context{}))
cmd.SetArgs(args)
s.Require().NoError(client.SetCmdClientContextHandler(tc.ctxGen(), cmd))

View File

@ -1,149 +0,0 @@
package cli
import (
"bytes"
"encoding/json"
"fmt"
"io"
"os"
"path/filepath"
dbm "github.com/cosmos/cosmos-db"
"github.com/spf13/cast"
"github.com/spf13/cobra"
corestore "cosmossdk.io/core/store"
"github.com/cosmos/cosmos-sdk/client"
"github.com/cosmos/cosmos-sdk/client/flags"
servertypes "github.com/cosmos/cosmos-sdk/server/types"
"github.com/cosmos/cosmos-sdk/version"
genutiltypes "github.com/cosmos/cosmos-sdk/x/genutil/types"
)
const (
flagTraceStore = "trace-store"
flagHeight = "height"
flagForZeroHeight = "for-zero-height"
flagJailAllowedAddrs = "jail-allowed-addrs"
flagModulesToExport = "modules-to-export"
)
// ExportCmd dumps app state to JSON.
func ExportCmd(appExporter servertypes.AppExporter) *cobra.Command {
cmd := &cobra.Command{
Use: "export",
Short: "Export state to JSON",
Args: cobra.NoArgs,
RunE: func(cmd *cobra.Command, _ []string) error {
config := client.GetConfigFromCmd(cmd)
viper := client.GetViperFromCmd(cmd)
logger := client.GetLoggerFromCmd(cmd)
if _, err := os.Stat(config.GenesisFile()); os.IsNotExist(err) {
return err
}
db, err := openDB(config.RootDir, getAppDBBackend(viper))
if err != nil {
return err
}
if appExporter == nil {
if _, err := fmt.Fprintln(cmd.ErrOrStderr(), "WARNING: App exporter not defined. Returning genesis file."); err != nil {
return err
}
// Open file in read-only mode so we can copy it to stdout.
// It is possible that the genesis file is large,
// so we don't need to read it all into memory
// before we stream it out.
f, err := os.OpenFile(config.GenesisFile(), os.O_RDONLY, 0)
if err != nil {
return err
}
defer f.Close()
if _, err := io.Copy(cmd.OutOrStdout(), f); err != nil {
return err
}
return nil
}
height, _ := cmd.Flags().GetInt64(flagHeight)
forZeroHeight, _ := cmd.Flags().GetBool(flagForZeroHeight)
jailAllowedAddrs, _ := cmd.Flags().GetStringSlice(flagJailAllowedAddrs)
modulesToExport, _ := cmd.Flags().GetStringSlice(flagModulesToExport)
outputDocument, _ := cmd.Flags().GetString(flags.FlagOutputDocument)
exported, err := appExporter(logger, db, nil, height, forZeroHeight, jailAllowedAddrs, viper, modulesToExport)
if err != nil {
return fmt.Errorf("error exporting state: %w", err)
}
appGenesis, err := genutiltypes.AppGenesisFromFile(config.GenesisFile())
if err != nil {
return err
}
// set current binary version
appGenesis.AppName = version.AppName
appGenesis.AppVersion = version.Version
appGenesis.AppState = exported.AppState
appGenesis.InitialHeight = exported.Height
appGenesis.Consensus = genutiltypes.NewConsensusGenesis(exported.ConsensusParams, exported.Validators)
out, err := json.Marshal(appGenesis)
if err != nil {
return err
}
if outputDocument == "" {
// Copy the entire genesis file to stdout.
_, err := io.Copy(cmd.OutOrStdout(), bytes.NewReader(out))
return err
}
if err = appGenesis.SaveAs(outputDocument); err != nil {
return err
}
return nil
},
}
cmd.Flags().Int64(flagHeight, -1, "Export state from a particular height (-1 means latest height)")
cmd.Flags().Bool(flagForZeroHeight, false, "Export state to start at height zero (perform preproccessing)")
cmd.Flags().StringSlice(flagJailAllowedAddrs, []string{}, "Comma-separated list of operator addresses of jailed validators to unjail")
cmd.Flags().StringSlice(flagModulesToExport, []string{}, "Comma-separated list of modules to export. If empty, will export all modules")
cmd.Flags().String(flags.FlagOutputDocument, "", "Exported state is written to the given file instead of STDOUT")
return cmd
}
// OpenDB opens the application database using the appropriate driver.
func openDB(rootDir string, backendType dbm.BackendType) (corestore.KVStoreWithBatch, error) {
dataDir := filepath.Join(rootDir, "data")
return dbm.NewDB("application", backendType, dataDir)
}
// GetAppDBBackend gets the backend type to use for the application DBs.
func getAppDBBackend(opts servertypes.AppOptions) dbm.BackendType {
rv := cast.ToString(opts.Get("app-db-backend"))
if len(rv) == 0 {
rv = cast.ToString(opts.Get("db_backend"))
}
// Cosmos SDK has migrated to cosmos-db which does not support all the backends which tm-db supported
if rv == "cleveldb" || rv == "badgerdb" || rv == "boltdb" {
panic(fmt.Sprintf("invalid app-db-backend %q, use %q, %q, %q instead", rv, dbm.GoLevelDBBackend, dbm.PebbleDBBackend, dbm.RocksDBBackend))
}
if len(rv) != 0 {
return dbm.BackendType(rv)
}
return dbm.GoLevelDBBackend
}

View File

@ -18,7 +18,6 @@ import (
"github.com/cosmos/cosmos-sdk/client/flags"
"github.com/cosmos/cosmos-sdk/client/tx"
"github.com/cosmos/cosmos-sdk/crypto/keyring"
"github.com/cosmos/cosmos-sdk/server"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/version"
authclient "github.com/cosmos/cosmos-sdk/x/auth/client"
@ -33,7 +32,7 @@ type genesisMM interface {
// GenTxCmd builds the application's gentx command.
func GenTxCmd(genMM genesisMM, genBalIterator types.GenesisBalancesIterator) *cobra.Command {
ipDefault, _ := server.ExternalIP()
ipDefault, _ := ExternalIP()
fsCreateValidator, defaultsDesc := cli.CreateValidatorMsgFlagSet(ipDefault)
cmd := &cobra.Command{

View File

@ -17,7 +17,6 @@ import (
"github.com/cosmos/cosmos-sdk/client/flags"
codectestutil "github.com/cosmos/cosmos-sdk/codec/testutil"
"github.com/cosmos/cosmos-sdk/crypto/keyring"
svrcmd "github.com/cosmos/cosmos-sdk/server/cmd"
clitestutil "github.com/cosmos/cosmos-sdk/testutil/cli"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/types/module"
@ -116,10 +115,9 @@ func (s *CLITestSuite) TestGenTxCmd() {
s.Run(tc.name, func() {
clientCtx := s.clientCtx
ctx := svrcmd.CreateExecuteContext(context.Background())
cmd := cli.GenTxCmd(module.NewManager(), banktypes.GenesisBalancesIterator{})
cmd.SetContext(ctx)
cmd.SetContext(context.WithValue(context.Background(), client.ClientContextKey, &client.Context{}))
cmd.SetArgs(tc.args)
s.Require().NoError(client.SetCmdClientContextHandler(clientCtx, cmd))

View File

@ -1,4 +1,4 @@
package server
package cli
import (
"errors"

View File

@ -23,7 +23,6 @@ import (
codectestutil "github.com/cosmos/cosmos-sdk/codec/testutil"
"github.com/cosmos/cosmos-sdk/crypto/hd"
"github.com/cosmos/cosmos-sdk/crypto/keyring"
svrcmd "github.com/cosmos/cosmos-sdk/server/cmd"
"github.com/cosmos/cosmos-sdk/testutil"
clitestutil "github.com/cosmos/cosmos-sdk/testutil/cli"
sdk "github.com/cosmos/cosmos-sdk/types"
@ -221,8 +220,7 @@ func (s *CLITestSuite) TestTxCreateGroup() {
for _, tc := range testCases {
s.Run(tc.name, func() {
ctx := svrcmd.CreateExecuteContext(context.Background())
cmd.SetContext(ctx)
cmd.SetContext(context.WithValue(context.Background(), client.ClientContextKey, &client.Context{}))
cmd.SetArgs(tc.args)
s.Require().NoError(client.SetCmdClientContextHandler(s.baseCtx, cmd))
@ -335,9 +333,7 @@ func (s *CLITestSuite) TestTxUpdateGroupMembers() {
for _, tc := range testCases {
s.Run(tc.name, func() {
ctx := svrcmd.CreateExecuteContext(context.Background())
cmd.SetContext(ctx)
cmd.SetContext(context.WithValue(context.Background(), client.ClientContextKey, &client.Context{}))
cmd.SetArgs(tc.args)
s.Require().NoError(client.SetCmdClientContextHandler(s.baseCtx, cmd))
@ -457,9 +453,7 @@ func (s *CLITestSuite) TestTxCreateGroupWithPolicy() {
}
for _, tc := range testCases {
s.Run(tc.name, func() {
ctx := svrcmd.CreateExecuteContext(context.Background())
cmd.SetContext(ctx)
cmd.SetContext(context.WithValue(context.Background(), client.ClientContextKey, &client.Context{}))
cmd.SetArgs(tc.args)
s.Require().NoError(client.SetCmdClientContextHandler(s.baseCtx, cmd))
@ -592,9 +586,7 @@ func (s *CLITestSuite) TestTxCreateGroupPolicy() {
for _, tc := range testCases {
s.Run(tc.name, func() {
ctx := svrcmd.CreateExecuteContext(context.Background())
cmd.SetContext(ctx)
cmd.SetContext(context.WithValue(context.Background(), client.ClientContextKey, &client.Context{}))
cmd.SetArgs(tc.args)
s.Require().NoError(client.SetCmdClientContextHandler(s.baseCtx, cmd))
@ -697,9 +689,7 @@ func (s *CLITestSuite) TestTxUpdateGroupPolicyDecisionPolicy() {
for _, tc := range testCases {
s.Run(tc.name, func() {
ctx := svrcmd.CreateExecuteContext(context.Background())
cmd.SetContext(ctx)
cmd.SetContext(context.WithValue(context.Background(), client.ClientContextKey, &client.Context{}))
cmd.SetArgs(tc.args)
s.Require().NoError(client.SetCmdClientContextHandler(s.baseCtx, cmd))
@ -799,9 +789,7 @@ func (s *CLITestSuite) TestTxSubmitProposal() {
for _, tc := range testCases {
s.Run(tc.name, func() {
ctx := svrcmd.CreateExecuteContext(context.Background())
cmd.SetContext(ctx)
cmd.SetContext(context.WithValue(context.Background(), client.ClientContextKey, &client.Context{}))
cmd.SetArgs(tc.args)
s.Require().NoError(client.SetCmdClientContextHandler(s.baseCtx, cmd))

View File

@ -14,14 +14,18 @@ import (
"github.com/cosmos/cosmos-sdk/client/flags"
"github.com/cosmos/cosmos-sdk/codec"
"github.com/cosmos/cosmos-sdk/server"
"github.com/cosmos/cosmos-sdk/types/module"
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
)
// flagUnsafeSkipUpgradesV2 is a custom flag that allows the user to skip upgrades
// It is used in a v2 chain.
const flagUnsafeSkipUpgradesV2 = "server.unsafe-skip-upgrades"
const (
// flagUnsafeSkipUpgrades is a custom flag that allows the user to skip upgrades
// It is used in a baseapp chain.
flagUnsafeSkipUpgrades = "unsafe-skip-upgrades"
// flagUnsafeSkipUpgradesV2 is a custom flag that allows the user to skip upgrades
// It is used in a v2 chain.
flagUnsafeSkipUpgradesV2 = "server.unsafe-skip-upgrades"
)
var _ depinject.OnePerModuleType = AppModule{}
@ -39,9 +43,9 @@ func ProvideConfig(key depinject.OwnModuleKey) coreserver.ModuleConfigMap {
return coreserver.ModuleConfigMap{
Module: depinject.ModuleKey(key).Name(),
Config: coreserver.ConfigMap{
server.FlagUnsafeSkipUpgrades: []int{},
flagUnsafeSkipUpgradesV2: []int{},
flags.FlagHome: "",
flagUnsafeSkipUpgrades: []int{},
flagUnsafeSkipUpgradesV2: []int{},
flags.FlagHome: "",
},
}
}
@ -73,7 +77,7 @@ func ProvideModule(in ModuleInputs) ModuleOutputs {
skipUpgrades, ok := in.ConfigMap[flagUnsafeSkipUpgradesV2] // check v2
if !ok || skipUpgrades == nil {
skipUpgrades, ok = in.ConfigMap[server.FlagUnsafeSkipUpgrades] // check v1
skipUpgrades, ok = in.ConfigMap[flagUnsafeSkipUpgrades] // check v1
if !ok || skipUpgrades == nil {
skipUpgrades = []int{}
}