refactor(server)!: continue server v1 removal (#23238)
This commit is contained in:
parent
597c176900
commit
c5b3033b3a
@ -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.
|
||||
|
||||
@ -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"`
|
||||
}
|
||||
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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,
|
||||
) {
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
}
|
||||
@ -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)
|
||||
}
|
||||
@ -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")
|
||||
|
||||
@ -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
2
go.mod
@ -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
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
|
||||
@ -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 {
|
||||
|
||||
@ -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.
|
||||
|
||||
@ -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) {
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
}
|
||||
@ -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
|
||||
}
|
||||
@ -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 }}
|
||||
@ -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)
|
||||
}
|
||||
@ -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
|
||||
}
|
||||
@ -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"
|
||||
)
|
||||
@ -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
|
||||
@ -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
|
||||
}
|
||||
@ -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")
|
||||
}
|
||||
}
|
||||
@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -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}
|
||||
}
|
||||
@ -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
|
||||
}
|
||||
}
|
||||
@ -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}
|
||||
}
|
||||
@ -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)
|
||||
}
|
||||
@ -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)
|
||||
}
|
||||
@ -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)}
|
||||
}
|
||||
@ -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")
|
||||
}
|
||||
@ -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
|
||||
}
|
||||
@ -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)
|
||||
}
|
||||
@ -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)
|
||||
)
|
||||
@ -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)
|
||||
|
||||
@ -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) {
|
||||
@ -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) {
|
||||
|
||||
@ -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,
|
||||
}
|
||||
|
||||
@ -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.
|
||||
|
||||
@ -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 {
|
||||
|
||||
@ -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)
|
||||
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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))
|
||||
|
||||
@ -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
|
||||
}
|
||||
@ -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{
|
||||
|
||||
@ -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))
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
package server
|
||||
package cli
|
||||
|
||||
import (
|
||||
"errors"
|
||||
@ -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))
|
||||
|
||||
@ -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{}
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user