refactor for sdk update

- register crypto types

- fix app codec

eager config and cli init

[wip] fix app cli

[wip] new msg handler registration (bonds)

clean up module autocli: use <> for required positional args

system tests

- registry

[wip] system tests fix, refactor

registry tests

TransferCoinsToModuleAccount: clarify function
This commit is contained in:
Roy Crihfield 2024-10-27 19:54:43 +08:00
parent 8ccf602c63
commit 72a93dec2f
31 changed files with 1201 additions and 666 deletions

View File

@ -7,6 +7,8 @@ LACONIC_BINARY = laconicd
BRANCH := $(shell git rev-parse --abbrev-ref HEAD) BRANCH := $(shell git rev-parse --abbrev-ref HEAD)
COMMIT := $(shell git log -1 --format='%H') COMMIT := $(shell git log -1 --format='%H')
COSMOS_BUILD_OPTIONS := v2
# don't override user values # don't override user values
ifeq (,$(VERSION)) ifeq (,$(VERSION))
VERSION := $(shell git describe --exact-match 2>/dev/null) VERSION := $(shell git describe --exact-match 2>/dev/null)
@ -106,3 +108,7 @@ test-e2e:
test-unit: test-unit:
go test ./utils/... ./cmd/... -mod=readonly -test.v go test ./utils/... ./cmd/... -mod=readonly -test.v
test-system: build
test -d ./tests/system/binaries || ln -sf $(BUILDDIR) ./tests/system/binaries
go test ./tests/system -test.v -timeout 10m

View File

@ -2,22 +2,16 @@ package app
import ( import (
_ "embed" _ "embed"
"os" "fmt"
"path/filepath"
"github.com/spf13/viper"
coreserver "cosmossdk.io/core/server"
"cosmossdk.io/core/transaction" "cosmossdk.io/core/transaction"
"cosmossdk.io/depinject" "cosmossdk.io/depinject"
"cosmossdk.io/depinject/appconfig" "cosmossdk.io/depinject/appconfig"
"cosmossdk.io/log"
"cosmossdk.io/runtime/v2" "cosmossdk.io/runtime/v2"
server "cosmossdk.io/server/v2"
serverstore "cosmossdk.io/server/v2/store" serverstore "cosmossdk.io/server/v2/store"
"cosmossdk.io/store/v2" "cosmossdk.io/store/v2"
"cosmossdk.io/store/v2/root" "cosmossdk.io/store/v2/root"
// crypto/keys/ed25519/keys.pb.go:123
coreserver "cosmossdk.io/core/server"
bankkeeper "cosmossdk.io/x/bank/keeper" bankkeeper "cosmossdk.io/x/bank/keeper"
consensuskeeper "cosmossdk.io/x/consensus/keeper" consensuskeeper "cosmossdk.io/x/consensus/keeper"
distrkeeper "cosmossdk.io/x/distribution/keeper" distrkeeper "cosmossdk.io/x/distribution/keeper"
@ -32,12 +26,15 @@ import (
"github.com/cosmos/cosmos-sdk/client" "github.com/cosmos/cosmos-sdk/client"
"github.com/cosmos/cosmos-sdk/codec" "github.com/cosmos/cosmos-sdk/codec"
codectypes "github.com/cosmos/cosmos-sdk/codec/types" codectypes "github.com/cosmos/cosmos-sdk/codec/types"
"github.com/cosmos/cosmos-sdk/types/module" "github.com/cosmos/cosmos-sdk/std"
authkeeper "github.com/cosmos/cosmos-sdk/x/auth/keeper" authkeeper "github.com/cosmos/cosmos-sdk/x/auth/keeper"
_ "cosmossdk.io/api/cosmos/tx/config/v1" // import for side-effects _ "cosmossdk.io/api/cosmos/tx/config/v1" // import for side-effects
_ "cosmossdk.io/x/accounts" // import for side-effects _ "cosmossdk.io/x/accounts" // import for side-effects
_ "cosmossdk.io/x/bank" // import for side-effects _ "cosmossdk.io/x/bank" // import for side-effects
// _ "cosmossdk.io/x/bank/v2" // import for side-effects
_ "cosmossdk.io/runtime/v2/services" // import for side-effects
_ "cosmossdk.io/x/consensus" // import for side-effects _ "cosmossdk.io/x/consensus" // import for side-effects
_ "cosmossdk.io/x/distribution" // import for side-effects _ "cosmossdk.io/x/distribution" // import for side-effects
_ "cosmossdk.io/x/gov" // import for side-effects _ "cosmossdk.io/x/gov" // import for side-effects
@ -54,21 +51,21 @@ import (
_ "github.com/cosmos/cosmos-sdk/x/auth/tx/config" // import for side-effects _ "github.com/cosmos/cosmos-sdk/x/auth/tx/config" // import for side-effects
) )
// DefaultNodeHome default home directories for the application daemon
var DefaultNodeHome string
//go:embed app.yaml
var AppConfigYAML []byte
var ( var (
_ server.AppI[transaction.Tx] = (*LaconicApp)(nil) //go:embed app.yaml
AppConfigYAML []byte
)
type (
Tx = transaction.Tx
AppBuilder = runtime.AppBuilder[Tx]
) )
// LaconicApp extends an ABCI application, but with most of its parameters exported. // LaconicApp extends an ABCI application, but with most of its parameters exported.
// They are exported for convenience in creating helper functions, as object // They are exported for convenience in creating helper functions, as object
// capabilities aren't needed for testing. // capabilities aren't needed for testing.
type LaconicApp struct { type LaconicApp[T Tx] struct {
*runtime.App[transaction.Tx] *runtime.App[T]
// legacyAmino *codec.LegacyAmino // legacyAmino *codec.LegacyAmino
appCodec codec.Codec appCodec codec.Codec
txConfig client.TxConfig txConfig client.TxConfig
@ -89,23 +86,6 @@ type LaconicApp struct {
BondKeeper *bondkeeper.Keeper BondKeeper *bondkeeper.Keeper
RegistryKeeper registrykeeper.Keeper RegistryKeeper registrykeeper.Keeper
OnboardingKeeper *onboardingkeeper.Keeper OnboardingKeeper *onboardingkeeper.Keeper
// simulation manager
sm *module.SimulationManager
}
type (
AppTx = transaction.Tx
AppBuilder = runtime.AppBuilder[AppTx]
)
func init() {
userHomeDir, err := os.UserHomeDir()
if err != nil {
panic(err)
}
DefaultNodeHome = filepath.Join(userHomeDir, ".laconicd")
} }
// AppConfig returns the default app config. // AppConfig returns the default app config.
@ -122,50 +102,46 @@ func AppConfig() depinject.Config {
codec.ProvideInterfaceRegistry, codec.ProvideInterfaceRegistry,
codec.ProvideAddressCodec, codec.ProvideAddressCodec,
codec.ProvideProtoCodec, codec.ProvideProtoCodec,
codec.ProvideLegacyAmino, codec.ProvideLegacyAmino, // note: needed by ProvideAppBuilder (runtime/v2)
ProvideRootStoreConfig,
// // inject desired account types:
// basedepinject.ProvideAccount,
// multisigdepinject.ProvideAccount,
// lockupdepinject.ProvideAllLockupAccounts,
// // provide base account options
// basedepinject.ProvideSecp256K1PubKey,
),
depinject.Invoke(
std.RegisterInterfaces,
// std.RegisterLegacyAminoCodec,
), ),
) )
} }
// NewLaconicApp returns a reference to an initialized LaconicApp. // NewLaconicApp returns a reference to an initialized LaconicApp.
func NewLaconicApp( func NewLaconicApp[T Tx](
logger log.Logger, config depinject.Config,
// db corestore.KVStoreWithBatch, outputs ...any,
// traceStore io.Writer, ) (*LaconicApp[T], error) {
viper *viper.Viper,
loadLatest bool,
// appOpts server.AppOptions, // TODO migrate?
appBuilderOpts ...runtime.AppBuilderOption[AppTx],
) (*LaconicApp, error) {
var ( var (
app LaconicApp app LaconicApp[T]
appBuilder *AppBuilder appBuilder *runtime.AppBuilder[T]
storeBuilder root.Builder storeBuilder root.Builder
err error err error
) )
logfile := "/Users/roy/vulcanize/dump/laconic-debug/app_depinject.log" outputs = append(outputs,
if err := depinject.InjectDebug(
// depinject.Debug(),
depinject.DebugOptions(
depinject.FileLogger(logfile),
),
depinject.Configs(
AppConfig(),
depinject.Supply(
logger,
// appOpts,
),
),
&appBuilder,
&storeBuilder, &storeBuilder,
&appBuilder,
&app.appCodec, &app.appCodec,
// &app.legacyAmino, // &app.legacyAmino,
&app.txConfig, &app.txConfig,
&app.interfaceRegistry, &app.interfaceRegistry,
&app.StakingKeeper,
&app.AccountKeeper, &app.AccountKeeper,
&app.BankKeeper, &app.BankKeeper,
&app.StakingKeeper,
&app.SlashingKeeper, &app.SlashingKeeper,
&app.DistrKeeper, &app.DistrKeeper,
&app.GovKeeper, &app.GovKeeper,
@ -174,76 +150,46 @@ func NewLaconicApp(
&app.BondKeeper, &app.BondKeeper,
&app.RegistryKeeper, &app.RegistryKeeper,
&app.OnboardingKeeper, &app.OnboardingKeeper,
)
if err = depinject.Inject(
depinject.Configs(AppConfig(), config),
outputs...,
); err != nil { ); err != nil {
return nil, err return nil, err
} }
// store/v2 follows a slightly more eager config life cycle than server components // // TODO: db config correct?
storeConfig, err := serverstore.UnmarshalConfig(viper.AllSettings()) // // TODO: store tracer injection?
app.App, err = appBuilder.Build()
if err != nil { if err != nil {
panic(err)
}
app.store, err = storeBuilder.Build(logger, storeConfig)
if err != nil {
panic(err)
}
// TODO: db config correct?
// TODO: store tracer injection?
if app.App, err = appBuilder.Build(appBuilderOpts...); err != nil {
return nil, err return nil, err
} }
// TODO app.store = storeBuilder.Get()
// // register streaming services if app.store == nil {
// if err := app.RegisterStreamingServices(appOpts, app.kvStoreKeys()); err != nil { return nil, fmt.Errorf("store builder did not return a db")
// return nil, err }
// }
/**** Module Options ****/ // TODO: review streaming services
// create the simulation manager and define the order of the modules for deterministic simulations // Note: upgrade handlers are registered here in simapp
// NOTE: this is not required for apps that don't use the simulator for fuzz testing transactions
app.sm = module.NewSimulationManagerFromAppModules(
app.ModuleManager().Modules(),
make(map[string]module.AppModuleSimulation, 0))
app.sm.RegisterStoreDecoders()
// TODO: remove
if loadLatest {
if err = app.LoadLatest(); err != nil { if err = app.LoadLatest(); err != nil {
return nil, err return nil, err
} }
}
return &app, nil return &app, nil
} }
// // LegacyAmino returns LaconicApp's amino codec. func (app *LaconicApp[T]) InterfaceRegistry() coreserver.InterfaceRegistry {
// func (app *LaconicApp) LegacyAmino() *codec.LegacyAmino {
// return app.legacyAmino
// }
func (app *LaconicApp) InterfaceRegistry() coreserver.InterfaceRegistry {
return app.interfaceRegistry return app.interfaceRegistry
} }
// GetKey returns the KVStoreKey for the provided store key. // GetKey returns the KVStoreKey for the provided store key.
func (app *LaconicApp) Store() store.RootStore { func (app *LaconicApp[T]) Store() store.RootStore {
return app.store return app.store
} }
// func (app *LaconicApp) kvStoreKeys() map[string]*store.KVStoreKey { func ProvideRootStoreConfig(config runtime.GlobalConfig) (*root.Config, error) {
// keys := make(map[string]*store.KVStoreKey) return serverstore.UnmarshalConfig(config)
// for _, k := range app.GetStoreKeys() {
// if kv, ok := k.(*storetypes.KVStoreKey); ok {
// keys[kv.Name()] = kv
// }
// }
// return keys
// }
// SimulationManager implements the SimulationApp interface
func (app *LaconicApp) SimulationManager() *module.SimulationManager {
return app.sm
} }

View File

@ -13,7 +13,7 @@ import (
// file. // file.
// This is a demonstation of how to export a genesis file. Export may need extended at // This is a demonstation of how to export a genesis file. Export may need extended at
// the user discretion for cleaning the genesis state at the end provided with jailAllowedAddrs // the user discretion for cleaning the genesis state at the end provided with jailAllowedAddrs
func (app *LaconicApp) ExportAppStateAndValidators( func (app *LaconicApp[T]) ExportAppStateAndValidators(
jailAllowedAddrs []string, jailAllowedAddrs []string,
) (v2.ExportedApp, error) { ) (v2.ExportedApp, error) {
ctx := context.Background() ctx := context.Background()

View File

@ -1,14 +1,15 @@
package cmd package cmd
import ( import (
"context" "io"
"fmt"
"github.com/spf13/cobra" "github.com/spf13/cobra"
"github.com/spf13/viper"
corectx "cosmossdk.io/core/context" "cosmossdk.io/client/v2/offchain"
coreserver "cosmossdk.io/core/server"
"cosmossdk.io/core/transaction"
"cosmossdk.io/log" "cosmossdk.io/log"
runtimev2 "cosmossdk.io/runtime/v2"
serverv2 "cosmossdk.io/server/v2" serverv2 "cosmossdk.io/server/v2"
"cosmossdk.io/server/v2/api/grpc" "cosmossdk.io/server/v2/api/grpc"
"cosmossdk.io/server/v2/api/rest" "cosmossdk.io/server/v2/api/rest"
@ -18,78 +19,142 @@ import (
confixcmd "cosmossdk.io/tools/confix/cmd" confixcmd "cosmossdk.io/tools/confix/cmd"
"github.com/cosmos/cosmos-sdk/client" "github.com/cosmos/cosmos-sdk/client"
"github.com/cosmos/cosmos-sdk/client/config"
"github.com/cosmos/cosmos-sdk/client/debug" "github.com/cosmos/cosmos-sdk/client/debug"
"github.com/cosmos/cosmos-sdk/client/keys" "github.com/cosmos/cosmos-sdk/client/keys"
"github.com/cosmos/cosmos-sdk/server"
sdk "github.com/cosmos/cosmos-sdk/types" sdk "github.com/cosmos/cosmos-sdk/types"
authcmd "github.com/cosmos/cosmos-sdk/x/auth/client/cli" authcmd "github.com/cosmos/cosmos-sdk/x/auth/client/cli"
"github.com/cosmos/cosmos-sdk/x/genutil" "github.com/cosmos/cosmos-sdk/x/genutil"
genutilcli "github.com/cosmos/cosmos-sdk/x/genutil/client/cli" genutilcli "github.com/cosmos/cosmos-sdk/x/genutil/client/cli"
genutiltypes "github.com/cosmos/cosmos-sdk/x/genutil/types" genutiltypes "github.com/cosmos/cosmos-sdk/x/genutil/types"
genutilv2 "github.com/cosmos/cosmos-sdk/x/genutil/v2"
genutilv2cli "github.com/cosmos/cosmos-sdk/x/genutil/v2/cli" genutilv2cli "github.com/cosmos/cosmos-sdk/x/genutil/v2/cli"
"git.vdb.to/cerc-io/laconicd/app" "git.vdb.to/cerc-io/laconicd/app"
"git.vdb.to/cerc-io/laconicd/utils" "git.vdb.to/cerc-io/laconicd/utils"
) )
func initRootCmd(rootCmd *cobra.Command, txConfig client.TxConfig, moduleManager moduleManager) { // CommandDependencies is a struct that contains all the dependencies needed to initialize the root command.
// an alternative design could fetch these even later from the command context
type CommandDependencies[T app.Tx] struct {
GlobalConfig coreserver.ConfigMap
TxConfig client.TxConfig
ModuleManager *runtimev2.MM[T]
LaconicApp *app.LaconicApp[T]
Consensus serverv2.ServerComponent[T]
}
func InitRootCmd[T app.Tx](
rootCmd *cobra.Command,
logger log.Logger,
deps CommandDependencies[T],
) (serverv2.ConfigWriter, error) {
cfg := sdk.GetConfig() cfg := sdk.GetConfig()
cfg.Seal() cfg.Seal()
rootCmd.AddCommand( rootCmd.AddCommand(
genutilcli.InitCmd(moduleManager), genutilcli.InitCmd(deps.ModuleManager),
genesisCommand(deps.ModuleManager, deps.LaconicApp),
NewTestnetCmd(deps.ModuleManager),
debug.Cmd(), debug.Cmd(),
confixcmd.ConfigCommand(), confixcmd.ConfigCommand(),
NewTestnetCmd(moduleManager),
// TODO
// pruning.Cmd(newApp),
// snapshot.Cmd(newApp),
)
if err := serverv2.AddCommands(
rootCmd,
newApp,
initServerConfig(),
cometbft.New(
utils.GenericTxDecoder[app.AppTx]{txConfig},
initCometOptions[app.AppTx](),
initCometConfig(),
),
grpc.New[app.AppTx](),
serverstore.New[app.AppTx](),
telemetry.New[app.AppTx](),
rest.New[app.AppTx](),
// serverv2.StartCmdOptions[*app.LaconicApp]{
// PostSetup: func(
// _ *app.LaconicApp,
// svrCtx *server.Context,
// clientCtx client.Context,
// ctx context.Context,
// g *errgroup.Group,
// ) error {
// g.Go(func() error {
// return gql.Server(ctx, clientCtx, svrCtx.Logger.With("module", "gql-server"))
// })
// return nil
// },
// },
); err != nil {
panic(err)
}
// add keybase, auxiliary RPC, query, genesis, and tx child commands // add keybase, auxiliary RPC, query, genesis, and tx child commands
rootCmd.AddCommand(
server.StatusCommand(),
genutilv2cli.Commands(
moduleManager.Modules()[genutiltypes.ModuleName].(genutil.AppModule),
moduleManager,
appExport),
queryCommand(), queryCommand(),
txCommand(), txCommand(),
keys.Commands(), keys.Commands(),
offchain.OffChain(),
) )
// TODO
// pruning.Cmd(newApp),
// snapshot.Cmd(newApp),
// build CLI skeleton for initial config parsing or a client application invocation
if deps.LaconicApp == nil {
if deps.Consensus == nil {
deps.Consensus = cometbft.NewWithConfigOptions[T](initCometConfig())
}
return serverv2.AddCommands[T](
rootCmd,
logger,
io.NopCloser(nil),
deps.GlobalConfig,
initServerConfig(),
deps.Consensus,
&grpc.Server[T]{},
&serverstore.Server[T]{},
&telemetry.Server[T]{},
&rest.Server[T]{},
)
}
// build full app!
app := deps.LaconicApp
grpcServer, err := grpc.New[T](logger, app.InterfaceRegistry(), app.QueryHandlers(), app.Query, deps.GlobalConfig)
if err != nil {
return nil, err
}
// store component (not a server)
storeComponent, err := serverstore.New[T](app.Store(), deps.GlobalConfig)
if err != nil {
return nil, err
}
restServer, err := rest.New(logger, app.App.AppManager, deps.GlobalConfig)
if err != nil {
return nil, err
}
// consensus component
if deps.Consensus == nil {
deps.Consensus, err = cometbft.New(
logger,
app.Name(),
app.Store(),
app.App.AppManager,
app.App.QueryHandlers(),
app.App.SchemaDecoderResolver(),
&utils.GenericTxDecoder[T]{deps.TxConfig},
deps.GlobalConfig,
initCometOptions[T](),
)
if err != nil {
return nil, err
}
}
telemetryServer, err := telemetry.New[T](deps.GlobalConfig, logger)
if err != nil {
return nil, err
}
// wire server commands
return serverv2.AddCommands[T](
rootCmd,
logger,
app,
deps.GlobalConfig,
initServerConfig(),
deps.Consensus,
grpcServer,
storeComponent,
telemetryServer,
restServer,
)
}
// genesisCommand builds genesis-related `simd genesis` command.
func genesisCommand[T app.Tx](
moduleManager *runtimev2.MM[T],
app *app.LaconicApp[T],
) *cobra.Command {
var genTxValidator func([]transaction.Msg) error
if moduleManager != nil {
genTxValidator = moduleManager.Modules()[genutiltypes.ModuleName].(genutil.AppModule).GenTxValidator()
}
cmd := genutilv2cli.Commands(
genTxValidator,
moduleManager,
app,
)
return cmd
} }
func queryCommand() *cobra.Command { func queryCommand() *cobra.Command {
@ -103,11 +168,11 @@ func queryCommand() *cobra.Command {
} }
cmd.AddCommand( cmd.AddCommand(
server.QueryBlockCmd(), cometbft.QueryBlockCmd(),
cometbft.QueryBlocksCmd(),
cometbft.QueryBlockResultsCmd(),
authcmd.QueryTxsByEventsCmd(), authcmd.QueryTxsByEventsCmd(),
server.QueryBlocksCmd(),
authcmd.QueryTxCmd(), authcmd.QueryTxCmd(),
server.QueryBlockResultsCmd(),
) )
return cmd return cmd
@ -137,102 +202,29 @@ func txCommand() *cobra.Command {
return cmd return cmd
} }
func newApp(logger log.Logger, viper *viper.Viper) serverv2.AppI[app.AppTx] { func RootCommandPersistentPreRun(clientCtx client.Context) func(*cobra.Command, []string) error {
// viper.Set(serverv2.FlagHome, app.DefaultNodeHome) return func(cmd *cobra.Command, args []string) error {
lacapp, err := app.NewLaconicApp(logger, viper, true) // set the default command outputs
cmd.SetOut(cmd.OutOrStdout())
cmd.SetErr(cmd.ErrOrStderr())
clientCtx = clientCtx.WithCmdContext(cmd.Context())
clientCtx, err := client.ReadPersistentCommandFlags(clientCtx, cmd.Flags())
if err != nil { if err != nil {
panic(err) return err
}
return serverv2.AppI[app.AppTx](lacapp)
} }
// appExport creates a new simapp (optionally at a given height) and exports state. customClientTemplate, customClientConfig := initClientConfig()
func appExport( clientCtx, err = config.CreateClientConfig(
ctx context.Context, clientCtx, customClientTemplate, customClientConfig)
height int64,
jailAllowedAddrs []string,
) (genutilv2.ExportedApp, error) {
value := ctx.Value(corectx.ViperContextKey)
viper, ok := value.(*viper.Viper)
if !ok {
return genutilv2.ExportedApp{},
fmt.Errorf("incorrect viper type %T: expected *viper.Viper in context", value)
}
value = ctx.Value(corectx.LoggerContextKey)
logger, ok := value.(log.Logger)
if !ok {
return genutilv2.ExportedApp{},
fmt.Errorf("incorrect logger type %T: expected log.Logger in context", value)
}
// overwrite the FlagInvCheckPeriod
viper.Set(server.FlagInvCheckPeriod, 1)
viper.Set(serverv2.FlagHome, app.DefaultNodeHome)
lacapp, err := app.NewLaconicApp(logger, viper, false)
if err != nil { if err != nil {
return genutilv2.ExportedApp{}, err return err
}
if height != -1 {
err = lacapp.LoadHeight(uint64(height))
} else {
err = lacapp.LoadLatest()
}
if err != nil {
return genutilv2.ExportedApp{}, err
} }
return lacapp.ExportAppStateAndValidators(jailAllowedAddrs) if err = client.SetCmdClientContextHandler(clientCtx, cmd); err != nil {
return err
} }
// // appExport creates a new app (optionally at a given height) and exports state. return nil
// func appExport( }
// logger log.Logger, }
// db corestore.KVStoreWithBatch,
// traceStore io.Writer,
// height int64,
// forZeroHeight bool,
// jailAllowedAddrs []string,
// appOpts servertypes.AppOptions,
// modulesToExport []string,
// ) (genutilv2.ExportedApp, error) {
// var (
// laconicApp *app.LaconicApp
// err error
// )
// // this check is necessary as we use the flag in x/upgrade.
// // we can exit more gracefully by checking the flag here.
// homePath, ok := appOpts.Get(flags.FlagHome).(string)
// if !ok || homePath == "" {
// return servertypes.ExportedApp{}, errors.New("application home not set")
// }
// viperAppOpts, ok := appOpts.(*viper.Viper)
// if !ok {
// return servertypes.ExportedApp{}, errors.New("appOpts is not viper.Viper")
// }
// // overwrite the FlagInvCheckPeriod
// viperAppOpts.Set(server.FlagInvCheckPeriod, 1)
// appOpts = viperAppOpts
// if height != -1 {
// laconicApp, err = app.NewLaconicApp(logger, db, false)
// if err != nil {
// return servertypes.ExportedApp{}, err
// }
// if err := laconicApp.LoadHeight(uint64(height)); err != nil {
// return servertypes.ExportedApp{}, err
// }
// } else {
// panic("height cannot be < 0")
// laconicApp, err = app.NewLaconicApp(logger, db, true)
// if err != nil {
// return servertypes.ExportedApp{}, err
// }
// }
// return laconicApp.ExportAppStateAndValidators(forZeroHeight, jailAllowedAddrs, modulesToExport)
// }

View File

@ -1,65 +1,28 @@
package cmd package cmd
import ( import (
"strings"
"time" "time"
cmtcfg "github.com/cometbft/cometbft/config" cmtcfg "github.com/cometbft/cometbft/config"
"cosmossdk.io/core/transaction"
serverv2 "cosmossdk.io/server/v2" serverv2 "cosmossdk.io/server/v2"
"cosmossdk.io/server/v2/cometbft" "cosmossdk.io/server/v2/cometbft"
sdk "github.com/cosmos/cosmos-sdk/types"
clientconfig "github.com/cosmos/cosmos-sdk/client/config" "cosmossdk.io/core/transaction"
"github.com/cosmos/cosmos-sdk/crypto/keyring"
) )
// initAppConfig helps to override default client config template and configs. // initAppConfig helps to override default client config template and configs.
// return "", nil if no custom configuration is required for the application. // return "", nil if no custom configuration is required for the application.
func initClientConfig() (string, interface{}) { func initClientConfig() (string, interface{}) {
type GasConfig struct { // customClientConfigTemplate, customClientConfig
GasAdjustment float64 `mapstructure:"gas-adjustment"` return "", nil
}
type CustomClientConfig struct {
clientconfig.Config `mapstructure:",squash"`
GasConfig GasConfig `mapstructure:"gas"`
}
// Optionally allow the chain developer to overwrite the SDK's default client config.
clientCfg := clientconfig.DefaultConfig()
// The SDK's default keyring backend is set to "os".
// This is more secure than "test" and is the recommended value.
//
// In simapp, we set the default keyring backend to test, as SimApp is meant
// to be an example and testing application.
clientCfg.KeyringBackend = keyring.BackendTest
// Now we set the custom config default values.
customClientConfig := CustomClientConfig{
Config: *clientCfg,
GasConfig: GasConfig{
GasAdjustment: 1.5,
},
}
// The default SDK app template is defined in serverconfig.DefaultConfigTemplate.
// We append the custom config template to the default one.
// And we set the default config to the custom app template.
customClientConfigTemplate := clientconfig.DefaultClientConfigTemplate + strings.TrimSpace(`
# This is default the gas adjustment factor used in tx commands.
# It can be overwritten by the --gas-adjustment flag in each tx command.
gas-adjustment = {{ .GasConfig.GasAdjustment }}
`)
return customClientConfigTemplate, customClientConfig
} }
// Allow the chain developer to overwrite the server default app toml config. // Allow the chain developer to overwrite the server default app toml config.
func initServerConfig() serverv2.ServerConfig { func initServerConfig() serverv2.ServerConfig {
serverCfg := serverv2.DefaultServerConfig() serverCfg := serverv2.DefaultServerConfig()
serverCfg.MinGasPrices = "0" + sdk.DefaultBondDenom
// The server's default minimum gas price is set to "0stake" inside // The server's default minimum gas price is set to "0stake" inside
// app.toml. However, the chain developer can set a default app.toml value for their // app.toml. However, the chain developer can set a default app.toml value for their
// validators here. Please update value based on chain denom. // validators here. Please update value based on chain denom.
@ -79,9 +42,11 @@ func initCometConfig() cometbft.CfgOption {
cfg := cmtcfg.DefaultConfig() cfg := cmtcfg.DefaultConfig()
// display only warn logs by default except for p2p and state // display only warn logs by default except for p2p and state
// better default logging
cfg.LogLevel = "*:warn,server:info,p2p:info,state:info" cfg.LogLevel = "*:warn,server:info,p2p:info,state:info"
cfg.LogLevel += ",auction:info,bond:info,registry:info,gql-server:info"
// increase block timeout // increase block timeout
cfg.Consensus.TimeoutCommit = 5 * time.Second cfg.Consensus.TimeoutCommit = 3 * time.Second
// overwrite default pprof listen address // overwrite default pprof listen address
cfg.RPC.PprofListenAddress = "localhost:6060" cfg.RPC.PprofListenAddress = "localhost:6060"

View File

@ -0,0 +1,71 @@
package cmd
import (
"os"
clientv2keyring "cosmossdk.io/client/v2/autocli/keyring"
"cosmossdk.io/core/address"
runtime "cosmossdk.io/runtime/v2"
serverv2 "cosmossdk.io/server/v2"
"github.com/cosmos/cosmos-sdk/client"
"github.com/cosmos/cosmos-sdk/client/config"
"github.com/cosmos/cosmos-sdk/codec"
codectypes "github.com/cosmos/cosmos-sdk/codec/types"
"github.com/cosmos/cosmos-sdk/crypto/keyring"
"github.com/cosmos/cosmos-sdk/x/auth/types"
)
func ProvideClientContext(
configMap runtime.GlobalConfig,
appCodec codec.Codec,
interfaceRegistry codectypes.InterfaceRegistry,
txConfig client.TxConfig,
// legacyAmino registry.AminoRegistrar,
addressCodec address.Codec,
validatorAddressCodec address.ValidatorAddressCodec,
consensusAddressCodec address.ConsensusAddressCodec,
) client.Context {
var err error
homeDir, ok := configMap[serverv2.FlagHome].(string)
if !ok {
panic("server.ConfigMap must contain a string value for serverv2.FlagHome")
}
clientCtx := client.Context{}.
WithCodec(appCodec).
WithInterfaceRegistry(interfaceRegistry).
WithTxConfig(txConfig).
// WithLegacyAmino(amino).
WithInput(os.Stdin).
WithAccountRetriever(types.AccountRetriever{}).
WithAddressCodec(addressCodec).
WithValidatorAddressCodec(validatorAddressCodec).
WithConsensusAddressCodec(consensusAddressCodec).
WithHomeDir(homeDir).
WithViper(EnvPrefix) // env variable prefix
// Read the config to overwrite the default values with the values from the config file
customClientTemplate, customClientConfig := initClientConfig()
clientCtx, err = config.CreateClientConfig(clientCtx, customClientTemplate, customClientConfig)
if err != nil {
panic(err)
}
// // Workaround: Unset clientCtx.HomeDir and clientCtx.KeyringDir from depinject clientCtx as they
// // are given precedence over the CLI args (--home flag) in some commands
// // TODO: Implement proper fix
// clientCtx.HomeDir = ""
// clientCtx.KeyringDir = ""
return clientCtx
}
func ProvideKeyring(clientCtx client.Context, addressCodec address.Codec) (clientv2keyring.Keyring, error) {
kb, err := client.NewKeyringFromBackend(clientCtx, clientCtx.Keyring.Backend())
if err != nil {
return nil, err
}
return keyring.NewAutoCLIKeyring(kb, addressCodec)
}

View File

@ -1,181 +1,123 @@
package cmd package cmd
import ( import (
"fmt" "errors"
"os"
"time"
cmtcfg "github.com/cometbft/cometbft/config"
"github.com/spf13/cobra" "github.com/spf13/cobra"
"github.com/spf13/pflag"
autocliv1 "cosmossdk.io/api/cosmos/autocli/v1"
"cosmossdk.io/client/v2/autocli" "cosmossdk.io/client/v2/autocli"
clientv2keyring "cosmossdk.io/client/v2/autocli/keyring"
"cosmossdk.io/core/address"
"cosmossdk.io/core/transaction"
"cosmossdk.io/depinject" "cosmossdk.io/depinject"
"cosmossdk.io/log" "cosmossdk.io/log"
runtime "cosmossdk.io/runtime/v2" runtime "cosmossdk.io/runtime/v2"
serverv2 "cosmossdk.io/server/v2"
"github.com/cosmos/cosmos-sdk/client" "github.com/cosmos/cosmos-sdk/client"
"github.com/cosmos/cosmos-sdk/client/config" 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/crypto/keyring"
"github.com/cosmos/cosmos-sdk/server"
serverconfig "github.com/cosmos/cosmos-sdk/server/config"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/types/tx/signing"
"github.com/cosmos/cosmos-sdk/x/auth/tx"
txmodule "github.com/cosmos/cosmos-sdk/x/auth/tx/config"
"github.com/cosmos/cosmos-sdk/x/auth/types"
"git.vdb.to/cerc-io/laconicd/app" "git.vdb.to/cerc-io/laconicd/app"
"git.vdb.to/cerc-io/laconicd/gql"
) )
const EnvPrefix = "LACONIC" const (
// EnvPrefix is the environment variable prefix for the application
EnvPrefix = "LACONIC"
type moduleManager = *runtime.MM[transaction.Tx] // DefaultNodeHome is the default data directory name for the application
DefaultNodeHome = ".laconicd"
// NewRootCmd creates a new root command for laconicd. It is called once in the
// main function.
func NewRootCmd() *cobra.Command {
var (
txConfigOpts tx.ConfigOptions
autoCliOpts autocli.AppOptions
moduleManager moduleManager
clientCtx client.Context
) )
if err := depinject.InjectDebug( func NewRootCmd[T app.Tx](
depinject.Debug(), args ...string,
depinject.Configs( ) (*cobra.Command, error) {
app.AppConfig(), rootCommand := &cobra.Command{
depinject.Supply(
log.NewNopLogger(),
),
depinject.Provide(
ProvideClientContext,
ProvideKeyring,
),
),
&txConfigOpts,
&autoCliOpts,
&moduleManager,
&clientCtx,
); err != nil {
panic(err)
}
rootCmd := &cobra.Command{
Use: "laconicd", Use: "laconicd",
Short: "Laconic Daemon", SilenceErrors: true,
PersistentPreRunE: func(cmd *cobra.Command, _ []string) error {
// set the default command outputs
cmd.SetOut(cmd.OutOrStdout())
cmd.SetErr(cmd.ErrOrStderr())
clientCtx = clientCtx.WithCmdContext(cmd.Context()).WithViper(EnvPrefix)
clientCtx, err := client.ReadPersistentCommandFlags(clientCtx, cmd.Flags())
if err != nil {
return err
} }
configWriter, err := InitRootCmd(rootCommand, log.NewNopLogger(), CommandDependencies[T]{})
clientCtx, err = config.CreateClientConfig(clientCtx, "", nil)
if err != nil { if err != nil {
return err return nil, err
} }
factory, err := serverv2.NewCommandFactory(
// sign mode textual is only available in online mode serverv2.WithConfigWriter(configWriter),
if !clientCtx.Offline { serverv2.WithStdDefaultHomeDir(DefaultNodeHome),
// This needs to happen after initializing the client context so the RPC client is set serverv2.WithLoggerFactory(serverv2.NewLogger),
txConfigOpts.EnabledSignModes = append(txConfigOpts.EnabledSignModes, signing.SignMode_SIGN_MODE_TEXTUAL)
txConfigOpts.TextualCoinMetadataQueryFn = txmodule.NewGRPCCoinMetadataQueryFn(clientCtx)
txConfigWithTextual, err := tx.NewTxConfigWithOptions(
codec.NewProtoCodec(clientCtx.InterfaceRegistry),
txConfigOpts,
) )
if err != nil {
return err
}
clientCtx = clientCtx.WithTxConfig(txConfigWithTextual)
}
if err := client.SetCmdClientContextHandler(clientCtx, cmd); err != nil {
return err
}
// overwrite the minimum gas price from the app configuration
srvCfg := serverconfig.DefaultConfig()
srvCfg.MinGasPrices = fmt.Sprintf("0%s", sdk.DefaultBondDenom)
// overwrite the block timeout
cmtCfg := cmtcfg.DefaultConfig()
// TODO use FinalizeBlockResponse.next_block_delay
cmtCfg.Consensus.TimeoutCommit = 3 * time.Second
cmtCfg.LogLevel = "*:error,p2p:info,state:info,auction:info,bond:info,registry:info,gql-server:info" // better default logging
return server.InterceptConfigsPreRunHandler(cmd, serverconfig.DefaultConfigTemplate, srvCfg, cmtCfg)
},
}
initRootCmd(rootCmd, clientCtx.TxConfig, moduleManager)
if err := autoCliOpts.EnhanceRootCommand(rootCmd); err != nil {
panic(err)
}
// Add flags for GQL server.
rootCmd = gql.AddGQLFlags(rootCmd)
return rootCmd
}
func ProvideClientContext(
appCodec codec.Codec,
interfaceRegistry codectypes.InterfaceRegistry,
txConfig client.TxConfig,
// legacyAmino registry.AminoRegistrar,
addressCodec address.Codec,
validatorAddressCodec address.ValidatorAddressCodec,
consensusAddressCodec address.ConsensusAddressCodec,
) client.Context {
var err error
clientCtx := client.Context{}.
WithCodec(appCodec).
WithInterfaceRegistry(interfaceRegistry).
WithTxConfig(txConfig).
// WithLegacyAmino(amino).
WithInput(os.Stdin).
WithAccountRetriever(types.AccountRetriever{}).
WithAddressCodec(addressCodec).
WithValidatorAddressCodec(validatorAddressCodec).
WithConsensusAddressCodec(consensusAddressCodec).
WithHomeDir(app.DefaultNodeHome).
WithViper(EnvPrefix) // env variable prefix
// Read the config to overwrite the default values with the values from the config file
clientCtx, err = config.CreateClientConfig(clientCtx, "", nil)
if err != nil {
panic(err)
}
// Workaround: Unset clientCtx.HomeDir and clientCtx.KeyringDir from depinject clientCtx as they
// are given precedence over the CLI args (--home flag) in some commands
// TODO: Implement proper fix
clientCtx.HomeDir = ""
clientCtx.KeyringDir = ""
return clientCtx
}
func ProvideKeyring(clientCtx client.Context, addressCodec address.Codec) (clientv2keyring.Keyring, error) {
kb, err := client.NewKeyringFromBackend(clientCtx, clientCtx.Keyring.Backend())
if err != nil { if err != nil {
return nil, err return nil, err
} }
return keyring.NewAutoCLIKeyring(kb, addressCodec) nodeCmds := nodeservice.NewNodeCommands()
autoCLIModuleOpts := make(map[string]*autocliv1.ModuleOptions)
autoCLIModuleOpts[nodeCmds.Name()] = nodeCmds.AutoCLIOptions()
autoCliOpts, err := autocli.NewAppOptionsFromConfig(
depinject.Configs(app.AppConfig(), depinject.Supply(runtime.GlobalConfig{})),
autoCLIModuleOpts,
)
if err != nil {
return nil, err
}
if err = autoCliOpts.EnhanceRootCommand(rootCommand); err != nil {
return nil, err
}
subCommand, configMap, logger, err := factory.ParseCommand(rootCommand, args)
if err != nil {
if errors.Is(err, pflag.ErrHelp) {
return rootCommand, nil
}
return nil, err
}
var (
moduleManager *runtime.MM[T]
clientCtx client.Context
laconic *app.LaconicApp[T]
depinjectConfig = depinject.Configs(
depinject.Supply(logger, runtime.GlobalConfig(configMap)),
depinject.Provide(ProvideClientContext),
)
)
if serverv2.IsAppRequired(subCommand) {
// server construction
laconic, err = app.NewLaconicApp[T](depinjectConfig, &autoCliOpts, &moduleManager, &clientCtx)
if err != nil {
return nil, err
}
} else {
// client construction
if err = depinject.Inject(
depinject.Configs(
app.AppConfig(),
depinjectConfig,
),
&autoCliOpts, &moduleManager, &clientCtx,
); err != nil {
return nil, err
}
}
commandDeps := CommandDependencies[T]{
GlobalConfig: configMap,
TxConfig: clientCtx.TxConfig,
ModuleManager: moduleManager,
LaconicApp: laconic,
}
rootCommand = &cobra.Command{
Use: "laconicd",
Short: "Laconic Daemon",
SilenceErrors: true,
PersistentPreRunE: RootCommandPersistentPreRun(clientCtx),
}
factory.EnhanceRootCommand(rootCommand)
_, err = InitRootCmd(rootCommand, logger, commandDeps)
if err != nil {
return nil, err
}
autoCliOpts.ModuleOptions = autoCLIModuleOpts
if err := autoCliOpts.EnhanceRootCommand(rootCommand); err != nil {
return nil, err
}
return rootCommand, nil
} }

View File

@ -0,0 +1,67 @@
package cmd_test
import (
"bytes"
"fmt"
"testing"
"github.com/stretchr/testify/require"
"github.com/cosmos/cosmos-sdk/client/flags"
"github.com/cosmos/cosmos-sdk/x/genutil/client/cli"
"git.vdb.to/cerc-io/laconicd/app"
"git.vdb.to/cerc-io/laconicd/cmd/laconicd/cmd"
)
func TestInitCmd(t *testing.T) {
args := []string{
"init", // Test the init cmd
"laconicd-test", // Moniker
fmt.Sprintf("--%s=%s", cli.FlagOverwrite, "true"), // Overwrite genesis.json, in case it already exists
}
rootCmd, err := cmd.NewRootCmd[app.Tx](args...)
require.NoError(t, err)
rootCmd.SetArgs(args)
require.NoError(t, rootCmd.Execute())
}
func TestHomeFlagRegistration(t *testing.T) {
homeDir := "/tmp/foo"
args := []string{
"query",
fmt.Sprintf("--%s", flags.FlagHome),
homeDir,
}
rootCmd, err := cmd.NewRootCmd[app.Tx](args...)
require.NoError(t, err)
rootCmd.SetArgs(args)
require.NoError(t, rootCmd.Execute())
result, err := rootCmd.Flags().GetString(flags.FlagHome)
require.NoError(t, err)
require.Equal(t, result, homeDir)
}
func TestHelpRequested(t *testing.T) {
argz := [][]string{
{"query", "--help"},
{"query", "tx", "-h"},
{"--help"},
{"start", "-h"},
}
for _, args := range argz {
rootCmd, err := cmd.NewRootCmd[app.Tx](args...)
require.NoError(t, err)
var out bytes.Buffer
rootCmd.SetArgs(args)
rootCmd.SetOut(&out)
require.NoError(t, rootCmd.Execute())
require.Contains(t, out.String(), args[0])
require.Contains(t, out.String(), "--help")
require.Contains(t, out.String(), "Usage:")
}
}

View File

@ -37,8 +37,6 @@ import (
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
"github.com/cosmos/cosmos-sdk/x/genutil" "github.com/cosmos/cosmos-sdk/x/genutil"
genutiltypes "github.com/cosmos/cosmos-sdk/x/genutil/types" genutiltypes "github.com/cosmos/cosmos-sdk/x/genutil/types"
"git.vdb.to/cerc-io/laconicd/utils"
) )
var ( var (
@ -74,6 +72,14 @@ func addTestnetFlagsToCmd(cmd *cobra.Command) {
cmd.Flags().String(flags.FlagChainID, "", "genesis file chain-id, if left blank will be randomly created") cmd.Flags().String(flags.FlagChainID, "", "genesis file chain-id, if left blank will be randomly created")
cmd.Flags().String(serverv2.FlagMinGasPrices, fmt.Sprintf("0.000006%s", sdk.DefaultBondDenom), "Minimum gas prices to accept for transactions; All fees in a tx must meet this minimum (e.g. 0.01photino,0.001stake)") cmd.Flags().String(serverv2.FlagMinGasPrices, fmt.Sprintf("0.000006%s", sdk.DefaultBondDenom), "Minimum gas prices to accept for transactions; All fees in a tx must meet this minimum (e.g. 0.01photino,0.001stake)")
cmd.Flags().String(flags.FlagKeyType, string(hd.Secp256k1Type), "Key signing algorithm to generate keys for") cmd.Flags().String(flags.FlagKeyType, string(hd.Secp256k1Type), "Key signing algorithm to generate keys for")
cmd.Flags().String(flagNodeDirPrefix, "node", "Prefix for the name of per-validator subdirectories (to be number-suffixed like node0, node1, ...)")
cmd.Flags().String(flagNodeDaemonHome, "laconicd", "Home directory of the node's daemon configuration")
cmd.Flags().String(flagStartingIPAddress, "192.168.0.1", "Starting IP address (192.168.0.1 results in persistent peers list ID0@192.168.0.1:46656, ID1@192.168.0.2:46656, ...)")
cmd.Flags().String(flagListenIPAddress, "127.0.0.1", "TCP or UNIX socket IP address for the RPC server to listen on")
cmd.Flags().String(flags.FlagKeyringBackend, flags.DefaultKeyringBackend, "Select keyring's backend (os|file|test)")
cmd.Flags().Duration(flagCommitTimeout, 5*time.Second, "Time to wait after a block commit before starting on the new height")
cmd.Flags().Bool(flagSingleHost, false, "Cluster runs on a single host machine with different ports")
cmd.Flags().String(flagStakingDenom, sdk.DefaultBondDenom, "Default staking token denominator")
} }
// NewTestnetCmd creates a root testnet command with subcommands to run an in-process testnet or initialize // NewTestnetCmd creates a root testnet command with subcommands to run an in-process testnet or initialize
@ -139,15 +145,6 @@ Example:
} }
addTestnetFlagsToCmd(cmd) addTestnetFlagsToCmd(cmd)
cmd.Flags().String(flagNodeDirPrefix, "node", "Prefix for the name of per-validator subdirectories (to be number-suffixed like node0, node1, ...)")
cmd.Flags().String(flagNodeDaemonHome, "laconicd", "Home directory of the node's daemon configuration")
cmd.Flags().String(flagStartingIPAddress, "192.168.0.1", "Starting IP address (192.168.0.1 results in persistent peers list ID0@192.168.0.1:46656, ID1@192.168.0.2:46656, ...)")
cmd.Flags().String(flagListenIPAddress, "127.0.0.1", "TCP or UNIX socket IP address for the RPC server to listen on")
cmd.Flags().String(flags.FlagKeyringBackend, flags.DefaultKeyringBackend, "Select keyring's backend (os|file|test)")
cmd.Flags().Duration(flagCommitTimeout, 5*time.Second, "Time to wait after a block commit before starting on the new height")
cmd.Flags().Bool(flagSingleHost, false, "Cluster runs on a single host machine with different ports")
cmd.Flags().String(flagStakingDenom, sdk.DefaultBondDenom, "Default staking token denominator")
return cmd return cmd
} }
@ -327,15 +324,10 @@ func initTestnetFiles[T transaction.Tx](
serverCfg := serverv2.DefaultServerConfig() serverCfg := serverv2.DefaultServerConfig()
serverCfg.MinGasPrices = args.minGasPrices serverCfg.MinGasPrices = args.minGasPrices
// Write server config cometServer := cometbft.NewWithConfigOptions[T](cometbft.OverwriteDefaultConfigTomlConfig(nodeConfig))
cometServer := cometbft.New[T]( storeServer := &store.Server[T]{}
utils.GenericTxDecoder[T]{clientCtx.TxConfig}, grpcServer := grpc.NewWithConfigOptions[T](grpc.OverwriteDefaultConfig(grpcConfig))
cometbft.ServerOptions[T]{}, server := serverv2.NewServer[T](serverCfg, cometServer, storeServer, grpcServer)
cometbft.OverwriteDefaultConfigTomlConfig(nodeConfig),
)
storeServer := store.New[T]()
grpcServer := grpc.New[T](grpc.OverwriteDefaultConfig(grpcConfig))
server := serverv2.NewServer[T](serverCfg, cometServer, grpcServer, storeServer)
err = server.WriteConfig(filepath.Join(nodeDir, "config")) err = server.WriteConfig(filepath.Join(nodeDir, "config"))
if err != nil { if err != nil {
return err return err

View File

@ -6,7 +6,6 @@ import (
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
svrcmd "cosmossdk.io/server/v2"
"github.com/cosmos/cosmos-sdk/client/flags" "github.com/cosmos/cosmos-sdk/client/flags"
"github.com/cosmos/cosmos-sdk/crypto/keyring" "github.com/cosmos/cosmos-sdk/crypto/keyring"
@ -15,12 +14,13 @@ import (
) )
func TestInitTestFilesCmd(t *testing.T) { func TestInitTestFilesCmd(t *testing.T) {
rootCmd := cmd.NewRootCmd() args := []string{
rootCmd.SetArgs([]string{
"testnet", // Test the testnet init-files command "testnet", // Test the testnet init-files command
"init-files", "init-files",
fmt.Sprintf("--%s=%s", flags.FlagKeyringBackend, keyring.BackendTest), // Set keyring-backend to test fmt.Sprintf("--%s=%s", flags.FlagKeyringBackend, keyring.BackendTest), // Set keyring-backend to test
}) }
rootCmd, err := cmd.NewRootCmd[app.Tx](args...)
require.NoError(t, svrcmd.Execute(rootCmd, "", app.DefaultNodeHome)) require.NoError(t, err)
rootCmd.SetArgs(args)
require.NoError(t, rootCmd.Execute())
} }

View File

@ -1,28 +0,0 @@
package main_test
import (
"fmt"
"testing"
"github.com/stretchr/testify/require"
svrcmd "cosmossdk.io/server/v2"
"github.com/cosmos/cosmos-sdk/client/flags"
"github.com/cosmos/cosmos-sdk/x/genutil/client/cli"
"git.vdb.to/cerc-io/laconicd/app"
"git.vdb.to/cerc-io/laconicd/cmd/laconicd/cmd"
)
func TestInitCmd(t *testing.T) {
rootCmd := cmd.NewRootCmd()
rootCmd.SetArgs([]string{
"init", // Test the init cmd
"localtestnet", // Moniker
fmt.Sprintf("--%s=%s", cli.FlagOverwrite, "true"), // Overwrite genesis.json, in case it already exists
fmt.Sprintf("--%s=%s", flags.FlagChainID, "laconic_9000-1"),
})
err := svrcmd.Execute(rootCmd, "", app.DefaultNodeHome)
require.NoError(t, err)
}

View File

@ -1,22 +1,31 @@
package main package main
import ( import (
"errors"
"fmt" "fmt"
"os" "os"
"git.vdb.to/cerc-io/laconicd/app" "git.vdb.to/cerc-io/laconicd/app"
"git.vdb.to/cerc-io/laconicd/cmd/laconicd/cmd" "git.vdb.to/cerc-io/laconicd/cmd/laconicd/cmd"
clientv2helpers "cosmossdk.io/client/v2/helpers"
serverv2 "cosmossdk.io/server/v2"
_ "git.vdb.to/cerc-io/laconicd/app/params" // import for side-effects _ "git.vdb.to/cerc-io/laconicd/app/params" // import for side-effects
) )
func main() { func main() {
rootCmd := cmd.NewRootCmd() // reproduce default cobra behavior so that eager parsing of flags is possible.
if err := serverv2.Execute(rootCmd, clientv2helpers.EnvPrefix, app.DefaultNodeHome); err != nil { // see: https://github.com/spf13/cobra/blob/e94f6d0dd9a5e5738dca6bce03c4b1207ffbc0ec/command.go#L1082
fmt.Fprintln(rootCmd.OutOrStderr(), err) args := os.Args[1:]
rootCmd, err := cmd.NewRootCmd[app.Tx](args...)
if err != nil {
if _, pErr := fmt.Fprintln(os.Stderr, err); pErr != nil {
panic(errors.Join(err, pErr))
}
os.Exit(1)
}
if err = rootCmd.Execute(); err != nil {
if _, pErr := fmt.Fprintln(rootCmd.OutOrStderr(), err); pErr != nil {
panic(errors.Join(err, pErr))
}
os.Exit(1) os.Exit(1)
} }
} }

47
go.mod
View File

@ -15,9 +15,9 @@ replace (
require ( require (
cosmossdk.io/api v0.7.6 cosmossdk.io/api v0.7.6
cosmossdk.io/client/v2 v2.0.0-beta.1 cosmossdk.io/client/v2 v2.0.0-beta.1
cosmossdk.io/collections v0.4.0 cosmossdk.io/collections v0.4.1-0.20241104084251-838f1557af0a
cosmossdk.io/core v1.0.0-alpha.5 cosmossdk.io/core v1.0.0-alpha.5.0.20241108140525-43e28b43ad7a
cosmossdk.io/depinject v1.0.0 cosmossdk.io/depinject v1.1.0
cosmossdk.io/errors v1.0.1 cosmossdk.io/errors v1.0.1
cosmossdk.io/log v1.4.1 cosmossdk.io/log v1.4.1
cosmossdk.io/math v1.3.0 cosmossdk.io/math v1.3.0
@ -46,13 +46,17 @@ require (
github.com/ipld/go-ipld-prime v0.21.0 github.com/ipld/go-ipld-prime v0.21.0
github.com/rs/cors v1.11.1 github.com/rs/cors v1.11.1
github.com/spf13/cobra v1.8.1 github.com/spf13/cobra v1.8.1
github.com/spf13/pflag v1.0.5
github.com/spf13/viper v1.19.0 github.com/spf13/viper v1.19.0
github.com/statechannels/go-nitro v0.1.2 github.com/statechannels/go-nitro v0.1.2
github.com/stretchr/testify v1.9.0 github.com/stretchr/testify v1.9.0
github.com/tidwall/gjson v1.14.4
github.com/tidwall/sjson v1.2.5
github.com/vektah/gqlparser/v2 v2.5.11 github.com/vektah/gqlparser/v2 v2.5.11
golang.org/x/sync v0.8.0 // indirect go.uber.org/mock v0.5.0
google.golang.org/genproto/googleapis/api v0.0.0-20240814211410-ddb44dafa142 golang.org/x/sync v0.9.0 // indirect
google.golang.org/grpc v1.67.1 google.golang.org/genproto/googleapis/api v0.0.0-20240903143218-8af14fe29dc1
google.golang.org/grpc v1.68.0
google.golang.org/protobuf v1.35.1 google.golang.org/protobuf v1.35.1
gopkg.in/yaml.v3 v3.0.1 gopkg.in/yaml.v3 v3.0.1
) )
@ -61,6 +65,9 @@ require (
cosmossdk.io/server/v2/appmanager v0.0.0-20240802110823-cffeedff643d cosmossdk.io/server/v2/appmanager v0.0.0-20240802110823-cffeedff643d
cosmossdk.io/server/v2/stf v0.0.0-20240708142107-25e99c54bac1 cosmossdk.io/server/v2/stf v0.0.0-20240708142107-25e99c54bac1
cosmossdk.io/x/accounts v1.0.0-alpha.4 cosmossdk.io/x/accounts v1.0.0-alpha.4
cosmossdk.io/x/accounts/defaults/base v0.0.0-00010101000000-000000000000
cosmossdk.io/x/accounts/defaults/lockup v0.0.0-00010101000000-000000000000
cosmossdk.io/x/accounts/defaults/multisig v0.0.0-00010101000000-000000000000
cosmossdk.io/x/bank v1.0.0-alpha.4 cosmossdk.io/x/bank v1.0.0-alpha.4
cosmossdk.io/x/consensus v0.0.0-20241007000829-38662ecb209f cosmossdk.io/x/consensus v0.0.0-20241007000829-38662ecb209f
cosmossdk.io/x/distribution v0.0.0-20241007000829-38662ecb209f cosmossdk.io/x/distribution v0.0.0-20241007000829-38662ecb209f
@ -69,15 +76,12 @@ require (
cosmossdk.io/x/protocolpool v1.0.0-alpha.4 cosmossdk.io/x/protocolpool v1.0.0-alpha.4
cosmossdk.io/x/slashing v0.0.0-20241007000829-38662ecb209f cosmossdk.io/x/slashing v0.0.0-20241007000829-38662ecb209f
cosmossdk.io/x/staking v1.0.0-alpha.4 cosmossdk.io/x/staking v1.0.0-alpha.4
github.com/tidwall/gjson v1.14.4
github.com/tidwall/sjson v1.2.5
go.uber.org/mock v0.5.0
) )
require ( require (
buf.build/gen/go/cometbft/cometbft/protocolbuffers/go v1.35.1-20240701160653-fedbb9acfd2f.1 // indirect buf.build/gen/go/cometbft/cometbft/protocolbuffers/go v1.35.1-20240701160653-fedbb9acfd2f.1 // indirect
buf.build/gen/go/cosmos/gogo-proto/protocolbuffers/go v1.35.1-20240130113600-88ef6483f90f.1 // indirect buf.build/gen/go/cosmos/gogo-proto/protocolbuffers/go v1.35.1-20240130113600-88ef6483f90f.1 // indirect
cosmossdk.io/core/testing v0.0.0-20240923163230-04da382a9f29 // indirect cosmossdk.io/core/testing v0.0.0 // indirect
cosmossdk.io/errors/v2 v2.0.0-20240731132947-df72853b3ca5 // indirect cosmossdk.io/errors/v2 v2.0.0-20240731132947-df72853b3ca5 // indirect
cosmossdk.io/schema v0.3.1-0.20241010135032-192601639cac // indirect cosmossdk.io/schema v0.3.1-0.20241010135032-192601639cac // indirect
cosmossdk.io/x/epochs v0.0.0-20240522060652-a1ae4c3e0337 // indirect cosmossdk.io/x/epochs v0.0.0-20240522060652-a1ae4c3e0337 // indirect
@ -107,7 +111,7 @@ require (
github.com/cosmos/btcutil v1.0.5 // indirect github.com/cosmos/btcutil v1.0.5 // indirect
github.com/cosmos/crypto v0.1.2 // indirect github.com/cosmos/crypto v0.1.2 // indirect
github.com/cosmos/gogogateway v1.2.0 // indirect github.com/cosmos/gogogateway v1.2.0 // indirect
github.com/cosmos/iavl v1.3.0 // indirect github.com/cosmos/iavl v1.3.1 // indirect
github.com/cosmos/ics23/go v0.11.0 // indirect github.com/cosmos/ics23/go v0.11.0 // indirect
github.com/cosmos/ledger-cosmos-go v0.13.3 // indirect github.com/cosmos/ledger-cosmos-go v0.13.3 // indirect
github.com/creachadair/atomicfile v0.3.5 // indirect github.com/creachadair/atomicfile v0.3.5 // indirect
@ -122,7 +126,7 @@ require (
github.com/emicklei/dot v1.6.2 // indirect github.com/emicklei/dot v1.6.2 // indirect
github.com/fatih/color v1.18.0 // indirect github.com/fatih/color v1.18.0 // indirect
github.com/felixge/httpsnoop v1.0.4 // indirect github.com/felixge/httpsnoop v1.0.4 // indirect
github.com/fsnotify/fsnotify v1.7.0 // indirect github.com/fsnotify/fsnotify v1.8.0 // indirect
github.com/getsentry/sentry-go v0.27.0 // indirect github.com/getsentry/sentry-go v0.27.0 // indirect
github.com/go-kit/kit v0.13.0 // indirect github.com/go-kit/kit v0.13.0 // indirect
github.com/go-kit/log v0.2.1 // indirect github.com/go-kit/log v0.2.1 // indirect
@ -204,7 +208,6 @@ require (
github.com/spaolacci/murmur3 v1.1.0 // indirect github.com/spaolacci/murmur3 v1.1.0 // indirect
github.com/spf13/afero v1.11.0 // indirect github.com/spf13/afero v1.11.0 // indirect
github.com/spf13/cast v1.7.0 // indirect github.com/spf13/cast v1.7.0 // indirect
github.com/spf13/pflag v1.0.5 // indirect
github.com/subosito/gotenv v1.6.0 // indirect github.com/subosito/gotenv v1.6.0 // indirect
github.com/supranational/blst v0.3.13 // indirect github.com/supranational/blst v0.3.13 // indirect
github.com/syndtr/goleveldb v1.0.1-0.20220721030215-126854af5e6d // indirect github.com/syndtr/goleveldb v1.0.1-0.20220721030215-126854af5e6d // indirect
@ -219,14 +222,14 @@ require (
go.etcd.io/bbolt v1.4.0-alpha.0.0.20240404170359-43604f3112c5 // indirect go.etcd.io/bbolt v1.4.0-alpha.0.0.20240404170359-43604f3112c5 // indirect
go.opencensus.io v0.24.0 // indirect go.opencensus.io v0.24.0 // indirect
go.uber.org/multierr v1.11.0 // indirect go.uber.org/multierr v1.11.0 // indirect
golang.org/x/crypto v0.28.0 // indirect golang.org/x/crypto v0.29.0 // indirect
golang.org/x/exp v0.0.0-20240531132922-fd00a4e0eefc // indirect golang.org/x/exp v0.0.0-20240531132922-fd00a4e0eefc // indirect
golang.org/x/net v0.30.0 // indirect golang.org/x/net v0.30.0 // indirect
golang.org/x/sys v0.26.0 // indirect golang.org/x/sys v0.27.0 // indirect
golang.org/x/term v0.25.0 // indirect golang.org/x/term v0.26.0 // indirect
golang.org/x/text v0.19.0 // indirect golang.org/x/text v0.20.0 // indirect
google.golang.org/genproto v0.0.0-20240227224415-6ceb2ff114de // indirect google.golang.org/genproto v0.0.0-20240227224415-6ceb2ff114de // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20241021214115-324edc3d5d38 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20241104194629-dd2ea8efbc28 // indirect
gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/ini.v1 v1.67.0 // indirect
gotest.tools/v3 v3.5.1 // indirect gotest.tools/v3 v3.5.1 // indirect
lukechampine.com/blake3 v1.2.1 // indirect lukechampine.com/blake3 v1.2.1 // indirect
@ -256,6 +259,8 @@ replace (
// cosmossdk.io/core => ../cosmos-sdk/core // cosmossdk.io/core => ../cosmos-sdk/core
cosmossdk.io/api => ../cosmos-sdk/api cosmossdk.io/api => ../cosmos-sdk/api
cosmossdk.io/client/v2 => ../cosmos-sdk/client/v2 cosmossdk.io/client/v2 => ../cosmos-sdk/client/v2
cosmossdk.io/core/testing => ../cosmos-sdk/core/testing
cosmossdk.io/depinject => ../cosmos-sdk/depinject
cosmossdk.io/runtime/v2 => ../cosmos-sdk/runtime/v2 cosmossdk.io/runtime/v2 => ../cosmos-sdk/runtime/v2
cosmossdk.io/server/v2 => ../cosmos-sdk/server/v2 cosmossdk.io/server/v2 => ../cosmos-sdk/server/v2
cosmossdk.io/server/v2/appmanager => ../cosmos-sdk/server/v2/appmanager cosmossdk.io/server/v2/appmanager => ../cosmos-sdk/server/v2/appmanager
@ -265,6 +270,9 @@ replace (
cosmossdk.io/store/v2 => ../cosmos-sdk/store/v2 cosmossdk.io/store/v2 => ../cosmos-sdk/store/v2
cosmossdk.io/tests/systemtests => ../cosmos-sdk/tests/systemtests cosmossdk.io/tests/systemtests => ../cosmos-sdk/tests/systemtests
cosmossdk.io/x/accounts => ../cosmos-sdk/x/accounts cosmossdk.io/x/accounts => ../cosmos-sdk/x/accounts
cosmossdk.io/x/accounts/defaults/base => ../cosmos-sdk/x/accounts/defaults/base
cosmossdk.io/x/accounts/defaults/lockup => ../cosmos-sdk/x/accounts/defaults/lockup
cosmossdk.io/x/accounts/defaults/multisig => ../cosmos-sdk/x/accounts/defaults/multisig
cosmossdk.io/x/bank => ../cosmos-sdk/x/bank cosmossdk.io/x/bank => ../cosmos-sdk/x/bank
cosmossdk.io/x/consensus => ../cosmos-sdk/x/consensus cosmossdk.io/x/consensus => ../cosmos-sdk/x/consensus
cosmossdk.io/x/distribution => ../cosmos-sdk/x/distribution cosmossdk.io/x/distribution => ../cosmos-sdk/x/distribution
@ -276,7 +284,10 @@ replace (
cosmossdk.io/x/slashing => ../cosmos-sdk/x/slashing cosmossdk.io/x/slashing => ../cosmos-sdk/x/slashing
cosmossdk.io/x/staking => ../cosmos-sdk/x/staking cosmossdk.io/x/staking => ../cosmos-sdk/x/staking
cosmossdk.io/x/tx => ../cosmos-sdk/x/tx cosmossdk.io/x/tx => ../cosmos-sdk/x/tx
github.com/cometbft/cometbft => ../cometbft github.com/cometbft/cometbft => ../cometbft
github.com/cosmos/cosmos-sdk => ../cosmos-sdk github.com/cosmos/cosmos-sdk => ../cosmos-sdk
github.com/cosmos/cosmos-sdk/tests => ../cosmos-sdk/tests github.com/cosmos/cosmos-sdk/tests => ../cosmos-sdk/tests
) )
replace google.golang.org/protobuf => /Users/roy/clone/protobuf-go

74
go.sum
View File

@ -4,14 +4,10 @@ buf.build/gen/go/cosmos/gogo-proto/protocolbuffers/go v1.35.1-20240130113600-88e
buf.build/gen/go/cosmos/gogo-proto/protocolbuffers/go v1.35.1-20240130113600-88ef6483f90f.1/go.mod h1:zqi/LZjZhyvjCMTEVIwAf5VRlkLduuCfqmZxgoormq0= buf.build/gen/go/cosmos/gogo-proto/protocolbuffers/go v1.35.1-20240130113600-88ef6483f90f.1/go.mod h1:zqi/LZjZhyvjCMTEVIwAf5VRlkLduuCfqmZxgoormq0=
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
cosmossdk.io/collections v0.4.0 h1:PFmwj2W8szgpD5nOd8GWH6AbYNi1f2J6akWXJ7P5t9s= cosmossdk.io/collections v0.4.1-0.20241104084251-838f1557af0a h1:9DxUD+82dO3c+R3XqwW+a7i4nVLiN6I0g2rp2rLOh7E=
cosmossdk.io/collections v0.4.0/go.mod h1:oa5lUING2dP+gdDquow+QjlF45eL1t4TJDypgGd+tv0= cosmossdk.io/collections v0.4.1-0.20241104084251-838f1557af0a/go.mod h1:DcD++Yfcq0OFtM3CJNYLIBjfZ+4DEyeJ/AUk6gkwlOE=
cosmossdk.io/core v1.0.0-alpha.5 h1:McjYXAQ6XcT20v2uHyH7PhoWH8V+mebzfVFqT3GinsI= cosmossdk.io/core v1.0.0-alpha.5.0.20241108140525-43e28b43ad7a h1:iN3KJqxjdsIxHDKOFjQ6GQpQNYwcqnhVR9jkuwU7bDA=
cosmossdk.io/core v1.0.0-alpha.5/go.mod h1:3u9cWq1FAVtiiCrDPpo4LhR+9V6k/ycSG4/Y/tREWCY= cosmossdk.io/core v1.0.0-alpha.5.0.20241108140525-43e28b43ad7a/go.mod h1:3u9cWq1FAVtiiCrDPpo4LhR+9V6k/ycSG4/Y/tREWCY=
cosmossdk.io/core/testing v0.0.0-20240923163230-04da382a9f29 h1:NxxUo0GMJUbIuVg0R70e3cbn9eFTEuMr7ev1AFvypdY=
cosmossdk.io/core/testing v0.0.0-20240923163230-04da382a9f29/go.mod h1:8s2tPeJtSiQuoyPmr2Ag7meikonISO4Fv4MoO8+ORrs=
cosmossdk.io/depinject v1.0.0 h1:dQaTu6+O6askNXO06+jyeUAnF2/ssKwrrszP9t5q050=
cosmossdk.io/depinject v1.0.0/go.mod h1:zxK/h3HgHoA/eJVtiSsoaRaRA2D5U4cJ5thIG4ssbB8=
cosmossdk.io/errors v1.0.1 h1:bzu+Kcr0kS/1DuPBtUFdWjzLqyUuCiyHjyJB6srBV/0= cosmossdk.io/errors v1.0.1 h1:bzu+Kcr0kS/1DuPBtUFdWjzLqyUuCiyHjyJB6srBV/0=
cosmossdk.io/errors v1.0.1/go.mod h1:MeelVSZThMi4bEakzhhhE/CKqVv3nOJDA25bIqRDu/U= cosmossdk.io/errors v1.0.1/go.mod h1:MeelVSZThMi4bEakzhhhE/CKqVv3nOJDA25bIqRDu/U=
cosmossdk.io/errors/v2 v2.0.0-20240731132947-df72853b3ca5 h1:IQNdY2kB+k+1OM2DvqFG1+UgeU1JzZrWtwuWzI3ZfwA= cosmossdk.io/errors/v2 v2.0.0-20240731132947-df72853b3ca5 h1:IQNdY2kB+k+1OM2DvqFG1+UgeU1JzZrWtwuWzI3ZfwA=
@ -144,8 +140,8 @@ github.com/cosmos/gogogateway v1.2.0/go.mod h1:iQpLkGWxYcnCdz5iAdLcRBSw3h7NXeOkZ
github.com/cosmos/gogoproto v1.4.2/go.mod h1:cLxOsn1ljAHSV527CHOtaIP91kK6cCrZETRBrkzItWU= github.com/cosmos/gogoproto v1.4.2/go.mod h1:cLxOsn1ljAHSV527CHOtaIP91kK6cCrZETRBrkzItWU=
github.com/cosmos/gogoproto v1.7.0 h1:79USr0oyXAbxg3rspGh/m4SWNyoz/GLaAh0QlCe2fro= github.com/cosmos/gogoproto v1.7.0 h1:79USr0oyXAbxg3rspGh/m4SWNyoz/GLaAh0QlCe2fro=
github.com/cosmos/gogoproto v1.7.0/go.mod h1:yWChEv5IUEYURQasfyBW5ffkMHR/90hiHgbNgrtp4j0= github.com/cosmos/gogoproto v1.7.0/go.mod h1:yWChEv5IUEYURQasfyBW5ffkMHR/90hiHgbNgrtp4j0=
github.com/cosmos/iavl v1.3.0 h1:Ezaxt8aPA3kbkhsfyqwenChGLQwHDAIif3tG9x1FMV8= github.com/cosmos/iavl v1.3.1 h1:+W1G2uSUtJMqMGpwz/fKiwZxY2DDT/9/0hyNLm6Geu0=
github.com/cosmos/iavl v1.3.0/go.mod h1:T6SfBcyhulVIY2G/ZtAtQm/QiJvsuhIos52V4dWYk88= github.com/cosmos/iavl v1.3.1/go.mod h1:T6SfBcyhulVIY2G/ZtAtQm/QiJvsuhIos52V4dWYk88=
github.com/cosmos/ics23/go v0.11.0 h1:jk5skjT0TqX5e5QJbEnwXIS2yI2vnmLOgpQPeM5RtnU= github.com/cosmos/ics23/go v0.11.0 h1:jk5skjT0TqX5e5QJbEnwXIS2yI2vnmLOgpQPeM5RtnU=
github.com/cosmos/ics23/go v0.11.0/go.mod h1:A8OjxPE67hHST4Icw94hOxxFEJMBG031xIGF/JHNIY0= github.com/cosmos/ics23/go v0.11.0/go.mod h1:A8OjxPE67hHST4Icw94hOxxFEJMBG031xIGF/JHNIY0=
github.com/cosmos/ledger-cosmos-go v0.13.3 h1:7ehuBGuyIytsXbd4MP43mLeoN2LTOEnk5nvue4rK+yM= github.com/cosmos/ledger-cosmos-go v0.13.3 h1:7ehuBGuyIytsXbd4MP43mLeoN2LTOEnk5nvue4rK+yM=
@ -210,8 +206,8 @@ github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHk
github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0=
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA= github.com/fsnotify/fsnotify v1.8.0 h1:dAwr6QBTBZIkG8roQaJjGof0pp0EeF+tNV7YBP3F/8M=
github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM= github.com/fsnotify/fsnotify v1.8.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0=
github.com/getsentry/sentry-go v0.27.0 h1:Pv98CIbtB3LkMWmXi4Joa5OOcwbmnX88sF5qbK3r3Ps= github.com/getsentry/sentry-go v0.27.0 h1:Pv98CIbtB3LkMWmXi4Joa5OOcwbmnX88sF5qbK3r3Ps=
github.com/getsentry/sentry-go v0.27.0/go.mod h1:lc76E2QywIyW8WuBnwl8Lc4bkmQH4+w1gwTf25trprY= github.com/getsentry/sentry-go v0.27.0/go.mod h1:lc76E2QywIyW8WuBnwl8Lc4bkmQH4+w1gwTf25trprY=
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
@ -257,11 +253,6 @@ github.com/golang/protobuf v1.3.0/go.mod h1:Qd/q+1AKNOZr9uGQzbzCmRO6sUih6GTPZv6a
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs=
github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=
github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8=
github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
@ -277,7 +268,6 @@ github.com/google/btree v1.1.3/go.mod h1:qOPhT0dTNdNzV6Z/lhRX0YXUafgPLFUh+gZMl76
github.com/google/flatbuffers v2.0.8+incompatible h1:ivUb1cGomAB101ZM1T0nOiWz9pSrTMoa9+EiY7igmkM= github.com/google/flatbuffers v2.0.8+incompatible h1:ivUb1cGomAB101ZM1T0nOiWz9pSrTMoa9+EiY7igmkM=
github.com/google/flatbuffers v2.0.8+incompatible/go.mod h1:1AeVuKshWv4vARoZatz6mlQ0JxURH0Kv5+zNeJKJCa8= github.com/google/flatbuffers v2.0.8+incompatible/go.mod h1:1AeVuKshWv4vARoZatz6mlQ0JxURH0Kv5+zNeJKJCa8=
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
@ -628,8 +618,8 @@ golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8U
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20200728195943-123391ffb6de/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200728195943-123391ffb6de/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.28.0 h1:GBDwsMXVQi34v5CCYUm2jkJvu4cbtru2U4TN2PSyQnw= golang.org/x/crypto v0.29.0 h1:L5SG1JTTXupVV3n6sUqMTeWbjAyfPwoda2DLX8J8FrQ=
golang.org/x/crypto v0.28.0/go.mod h1:rmgy+3RHxRZMyY0jjAJShp2zgEdOqj2AO7U0pYmeQ7U= golang.org/x/crypto v0.29.0/go.mod h1:+F4F4N5hv6v38hfeYwTdx20oUvLLc+QfrE9Ax9HtgRg=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20240531132922-fd00a4e0eefc h1:O9NuF4s+E/PvMIy+9IUZB9znFwUIXEWSstNjek6VpVg= golang.org/x/exp v0.0.0-20240531132922-fd00a4e0eefc h1:O9NuF4s+E/PvMIy+9IUZB9znFwUIXEWSstNjek6VpVg=
golang.org/x/exp v0.0.0-20240531132922-fd00a4e0eefc/go.mod h1:XtvwrStGgqGPLc4cjQfWqZHG1YFdYs6swckp8vpsjnc= golang.org/x/exp v0.0.0-20240531132922-fd00a4e0eefc/go.mod h1:XtvwrStGgqGPLc4cjQfWqZHG1YFdYs6swckp8vpsjnc=
@ -675,8 +665,8 @@ golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJ
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ= golang.org/x/sync v0.9.0 h1:fEo0HyrW1GIgZdpbhCRO0PkJajUS5H9IFUztCgEo2jQ=
golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sync v0.9.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
@ -716,12 +706,12 @@ golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.26.0 h1:KHjCJyddX0LoSTb3J+vWpupP9p0oznkqVk/IfjymZbo= golang.org/x/sys v0.27.0 h1:wBqf8DvsY9Y/2P8gAfPDEYNuS30J4lPHJxXSb/nJZ+s=
golang.org/x/sys v0.26.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.27.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.25.0 h1:WtHI/ltw4NvSUig5KARz9h521QvRC8RmF/cuYqifU24= golang.org/x/term v0.26.0 h1:WEQa6V3Gja/BhNxg540hBip/kkaYtRg3cxg4oXSw4AU=
golang.org/x/term v0.25.0/go.mod h1:RPyXicDX+6vLxogjjRxjgD2TKtmAO6NZBsBRfrOLu7M= golang.org/x/term v0.26.0/go.mod h1:Si5m1o57C5nBNQo5z1iq+XDijt21BDBDp2bK0QI8e3E=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
@ -729,8 +719,8 @@ golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ= golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ=
golang.org/x/text v0.19.0 h1:kTxAhCbGbxhK0IwgSKiMO5awPoDQ0RpfiVYBfK860YM= golang.org/x/text v0.20.0 h1:gK/Kv2otX8gz+wn7Rmb3vT96ZwuoxnQlY+HlJVj7Qug=
golang.org/x/text v0.19.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= golang.org/x/text v0.20.0/go.mod h1:D4IsuqiFMhST5bX19pQ9ikHC2GsaKyk/oF+pn3ducp4=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
@ -759,10 +749,10 @@ google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEY
google.golang.org/genproto v0.0.0-20220314164441-57ef72a4c106/go.mod h1:hAL49I2IFola2sVEjAn7MEwsja0xp51I0tlGAf9hz4E= google.golang.org/genproto v0.0.0-20220314164441-57ef72a4c106/go.mod h1:hAL49I2IFola2sVEjAn7MEwsja0xp51I0tlGAf9hz4E=
google.golang.org/genproto v0.0.0-20240227224415-6ceb2ff114de h1:F6qOa9AZTYJXOUEr4jDysRDLrm4PHePlge4v4TGAlxY= google.golang.org/genproto v0.0.0-20240227224415-6ceb2ff114de h1:F6qOa9AZTYJXOUEr4jDysRDLrm4PHePlge4v4TGAlxY=
google.golang.org/genproto v0.0.0-20240227224415-6ceb2ff114de/go.mod h1:VUhTRKeHn9wwcdrk73nvdC9gF178Tzhmt/qyaFcPLSo= google.golang.org/genproto v0.0.0-20240227224415-6ceb2ff114de/go.mod h1:VUhTRKeHn9wwcdrk73nvdC9gF178Tzhmt/qyaFcPLSo=
google.golang.org/genproto/googleapis/api v0.0.0-20240814211410-ddb44dafa142 h1:wKguEg1hsxI2/L3hUYrpo1RVi48K+uTyzKqprwLXsb8= google.golang.org/genproto/googleapis/api v0.0.0-20240903143218-8af14fe29dc1 h1:hjSy6tcFQZ171igDaN5QHOw2n6vx40juYbC/x67CEhc=
google.golang.org/genproto/googleapis/api v0.0.0-20240814211410-ddb44dafa142/go.mod h1:d6be+8HhtEtucleCbxpPW9PA9XwISACu8nvpPqF0BVo= google.golang.org/genproto/googleapis/api v0.0.0-20240903143218-8af14fe29dc1/go.mod h1:qpvKtACPCQhAdu3PyQgV4l3LMXZEtft7y8QcarRsp9I=
google.golang.org/genproto/googleapis/rpc v0.0.0-20241021214115-324edc3d5d38 h1:zciRKQ4kBpFgpfC5QQCVtnnNAcLIqweL7plyZRQHVpI= google.golang.org/genproto/googleapis/rpc v0.0.0-20241104194629-dd2ea8efbc28 h1:XVhgTWWV3kGQlwJHR3upFWZeTsei6Oks1apkZSeonIE=
google.golang.org/genproto/googleapis/rpc v0.0.0-20241021214115-324edc3d5d38/go.mod h1:GX3210XPVPUjJbTUbvwI8f2IpZDMZuPJWDzDuebbviI= google.golang.org/genproto/googleapis/rpc v0.0.0-20241104194629-dd2ea8efbc28/go.mod h1:GX3210XPVPUjJbTUbvwI8f2IpZDMZuPJWDzDuebbviI=
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY=
@ -773,24 +763,8 @@ google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv
google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
google.golang.org/grpc v1.45.0/go.mod h1:lN7owxKUQEqMfSyQikvvk5tf/6zMPsrK+ONuO11+0rQ= google.golang.org/grpc v1.45.0/go.mod h1:lN7owxKUQEqMfSyQikvvk5tf/6zMPsrK+ONuO11+0rQ=
google.golang.org/grpc v1.49.0/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI= google.golang.org/grpc v1.49.0/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI=
google.golang.org/grpc v1.67.1 h1:zWnc1Vrcno+lHZCOofnIMvycFcc0QRGIzm9dhnDX68E= google.golang.org/grpc v1.68.0 h1:aHQeeJbo8zAkAa3pRzrVjZlbz6uSfeOXlJNQM0RAbz0=
google.golang.org/grpc v1.67.1/go.mod h1:1gLDyUQU7CTLJI90u3nXZ9ekeghjeM7pTDZlqFNg2AA= google.golang.org/grpc v1.68.0/go.mod h1:fmSPC5AsjSBCK54MyHRx48kpOti1/jRfOlwEWywNjWA=
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE=
google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=
google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
google.golang.org/protobuf v1.35.1 h1:m3LfL6/Ca+fqnjnlqQXNpFPABW1UD7mjh8KO2mKFytA=
google.golang.org/protobuf v1.35.1/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=

View File

@ -81,7 +81,7 @@ func NewTestNetworkFixture() network.TestFixture {
} }
abci, err := setUpConsensus( abci, err := setUpConsensus(
val.GetLogger(), 100_000, mempool.NoOpMempool[laconicApp.AppTx]{}, val.GetLogger(), 100_000, mempool.NoOpMempool[laconicApp.Tx]{},
dir, val.GetClientCtx().TxConfig) dir, val.GetClientCtx().TxConfig)
if err != nil { if err != nil {
panic(fmt.Errorf("failed to build ABCI app: %w", err)) panic(fmt.Errorf("failed to build ABCI app: %w", err))

27
tests/system/cli.go Normal file
View File

@ -0,0 +1,27 @@
package system
import (
"path/filepath"
"testing"
"github.com/stretchr/testify/assert"
"cosmossdk.io/tests/systemtests"
)
func NewCLIWrapper(t *testing.T, sut *SystemUnderTest, verbose bool, fees string) *systemtests.CLIWrapper {
t.Helper()
return systemtests.NewCLIWrapperX(
t,
sut.execBinary,
sut.rpcAddr,
sut.chainID,
sut.AwaitNextBlock,
sut.nodesCount,
filepath.Join(WorkDir, sut.outputDir),
fees,
verbose,
assert.NoError,
true,
)
}

151
tests/system/events.go Normal file
View File

@ -0,0 +1,151 @@
package system
import (
"context"
"testing"
"time"
"github.com/cometbft/cometbft/libs/sync"
client "github.com/cometbft/cometbft/rpc/client/http"
ctypes "github.com/cometbft/cometbft/rpc/core/types"
"github.com/stretchr/testify/require"
)
// EventListener watches for events on the chain
type EventListener struct {
t *testing.T
client *client.HTTP
}
var DefaultWaitTime = 30 * time.Second
type (
CleanupFn func()
EventConsumer func(e ctypes.ResultEvent) (more bool)
)
// NewEventListener event listener
func NewEventListener(t *testing.T, rpcAddr string) *EventListener {
t.Helper()
httpClient, err := client.New(rpcAddr)
require.NoError(t, err)
require.NoError(t, httpClient.Start())
return &EventListener{client: httpClient, t: t}
}
// Subscribe to receive events for a topic. Does not block.
// For query syntax See https://docs.cosmos.network/master/core/events.html#subscribing-to-events
func (l *EventListener) Subscribe(query string, cb EventConsumer) func() {
ctx, done := context.WithCancel(context.Background())
l.t.Cleanup(done)
eventsChan, err := l.client.WSEvents.Subscribe(ctx, "testing", query)
require.NoError(l.t, err)
cleanup := func() {
ctx, _ := context.WithTimeout(ctx, DefaultWaitTime) //nolint:govet // used in cleanup only
go l.client.WSEvents.Unsubscribe(ctx, "testing", query) //nolint:errcheck // used by tests only
done()
}
go func() {
for e := range eventsChan {
if !cb(e) {
return
}
}
}()
return cleanup
}
// AwaitQuery blocks and waits for a single result or timeout. This can be used with `broadcast-mode=async`.
// For query syntax See https://docs.cosmos.network/master/core/events.html#subscribing-to-events
func (l *EventListener) AwaitQuery(query string, optMaxWaitTime ...time.Duration) *ctypes.ResultEvent {
c, result := CaptureSingleEventConsumer()
maxWaitTime := DefaultWaitTime
if len(optMaxWaitTime) != 0 {
maxWaitTime = optMaxWaitTime[0]
}
cleanupFn := l.Subscribe(query, TimeoutConsumer(l.t, maxWaitTime, c))
l.t.Cleanup(cleanupFn)
return result
}
// TimeoutConsumer is an event consumer decorator with a max wait time. Panics when wait time exceeded without
// a result returned
func TimeoutConsumer(t *testing.T, maxWaitTime time.Duration, next EventConsumer) EventConsumer {
t.Helper()
ctx, done := context.WithCancel(context.Background())
t.Cleanup(done)
timeout := time.NewTimer(maxWaitTime)
timedOut := make(chan struct{}, 1)
go func() {
select {
case <-ctx.Done():
case <-timeout.C:
timedOut <- struct{}{}
close(timedOut)
}
}()
return func(e ctypes.ResultEvent) (more bool) {
select {
case <-timedOut:
t.Fatalf("Timeout waiting for new events %s", maxWaitTime)
return false
default:
timeout.Reset(maxWaitTime)
result := next(e)
if !result {
done()
}
return result
}
}
}
// CaptureSingleEventConsumer consumes one event. No timeout
func CaptureSingleEventConsumer() (EventConsumer, *ctypes.ResultEvent) {
var result ctypes.ResultEvent
return func(e ctypes.ResultEvent) (more bool) {
return false
}, &result
}
// CaptureAllEventsConsumer is an `EventConsumer` that captures all events until `done()` is called to stop or timeout happens.
// The consumer works async in the background and returns all the captured events when `done()` is called.
// This can be used to verify that certain events have happened.
// Example usage:
//
// c, done := CaptureAllEventsConsumer(t)
// query := `tm.event='Tx'`
// cleanupFn := l.Subscribe(query, c)
// t.Cleanup(cleanupFn)
//
// // do something in your test that create events
//
// assert.Len(t, done(), 1) // then verify your assumption
func CaptureAllEventsConsumer(t *testing.T, optMaxWaitTime ...time.Duration) (c EventConsumer, done func() []ctypes.ResultEvent) {
t.Helper()
maxWaitTime := DefaultWaitTime
if len(optMaxWaitTime) != 0 {
maxWaitTime = optMaxWaitTime[0]
}
var (
mu sync.Mutex
capturedEvents []ctypes.ResultEvent
exit bool
)
collectEventsConsumer := func(e ctypes.ResultEvent) (more bool) {
mu.Lock()
defer mu.Unlock()
if exit {
return false
}
capturedEvents = append(capturedEvents, e)
return true
}
return TimeoutConsumer(t, maxWaitTime, collectEventsConsumer), func() []ctypes.ResultEvent {
mu.Lock()
defer mu.Unlock()
exit = true
return capturedEvents
}
}

View File

@ -0,0 +1,7 @@
package system
import "testing"
func TestMain(m *testing.M) {
RunTests(m)
}

View File

@ -0,0 +1,234 @@
package system
import (
"encoding/json"
"fmt"
"os"
"path/filepath"
"testing"
"time"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/tidwall/gjson"
"github.com/tidwall/sjson"
"cosmossdk.io/math"
"cosmossdk.io/tests/systemtests"
"github.com/cosmos/cosmos-sdk/client/flags"
"github.com/cosmos/cosmos-sdk/codec"
codectypes "github.com/cosmos/cosmos-sdk/codec/types"
sdk "github.com/cosmos/cosmos-sdk/types"
bondtypes "git.vdb.to/cerc-io/laconicd/x/bond"
registrytypes "git.vdb.to/cerc-io/laconicd/x/registry"
)
var recordFilePath = "../data/examples/service_provider_example.yml"
func init() {
var err error
if recordFilePath, err = filepath.Abs(recordFilePath); err != nil {
panic(err)
}
if _, err = os.Stat(recordFilePath); err != nil {
panic(err)
}
}
type systemTestSuite struct {
t *testing.T
fees string
}
type registryTestSuite struct {
*systemTestSuite
accountName string
accountAddress string
bondDenom string
bondId string
}
func newSystemTestSuite(t *testing.T, fees string) *systemTestSuite {
return &systemTestSuite{
t: t,
fees: fees,
}
}
func (s *systemTestSuite) cli() *systemtests.CLIWrapper {
return NewCLIWrapper(s.t, sut, verbose, s.fees)
}
func (s *systemTestSuite) SubTest(name string, f func(t *systemTestSuite)) {
s.t.Run(name, func(t *testing.T) {
subsuite := newSystemTestSuite(t, s.fees)
f(subsuite)
})
}
// run manually:
// go test ./tests/system -test.v -timeout 10m --verbose --nodes-count 1 -run TestRegistrySetRecord
func TestRegistrySetRecord(t *testing.T) {
s := setupSuite(t)
testCases := []struct {
name string
args []string
err bool
}{
{
"request with invalid payload file arg",
[]string{"bad-file", s.bondId},
true,
},
{
"success",
append([]string{recordFilePath, s.bondId}, s.commonTxFlags()...),
false,
},
}
for _, tc := range testCases {
s.SubTest(fmt.Sprintf("Case %s", tc.name), func(s *systemTestSuite) {
cli := s.cli()
cmd := append([]string{"tx", "registry", "set"}, tc.args...)
if tc.err {
cli := cli.WithRunErrorMatcher(assert.Error)
_ = cli.RunCommandWithArgs(cmd...)
} else {
txhash := cli.Run(cmd...)
systemtests.RequireTxSuccess(s.t, txhash)
}
})
}
}
func setupSuite(t *testing.T) *registryTestSuite {
sut.ResetChain(t)
accountName := "node0"
bondDenom := sdk.DefaultBondDenom
var accountAddress string
s := newSystemTestSuite(t, "3"+bondDenom)
registry := codectypes.NewInterfaceRegistry()
// codec.RegisterInterfaces(registry)
cdc := codec.NewProtoCodec(registry)
sut.ModifyGenesisJSON(t, func(genesis []byte) []byte {
accountAddress = s.cli().GetKeyAddr(accountName)
// update registry genesis params
var regState registrytypes.GenesisState
rawSupply := gjson.Get(string(genesis), "app_state.registry").String()
require.NoError(t, cdc.UnmarshalJSON([]byte(rawSupply), &regState))
updateParams(&regState.Params, bondDenom)
regStateBz, err := cdc.MarshalJSON(&regState)
require.NoError(t, err)
genesis, err = sjson.SetRawBytes(genesis, "app_state.registry", regStateBz)
require.NoError(t, err)
return genesis
})
sut.StartChain(t)
rts := registryTestSuite{
systemTestSuite: s,
accountName: accountName,
accountAddress: accountAddress,
bondDenom: bondDenom,
}
rts.bondId = createBond(&rts)
return &rts
}
func createBond(s *registryTestSuite) string {
cli := s.cli()
cmd := []string{
"tx", "bond", "create",
fmt.Sprintf("1000000%s", s.bondDenom),
"--from", s.accountName,
}
txhash := cli.Run(cmd...)
systemtests.RequireTxSuccess(s.t, txhash)
raw := cli.CustomQuery("q", "bond", "list")
var queryResponse bondtypes.QueryBondsResponse
require.NoError(s.t, json.Unmarshal([]byte(raw), &queryResponse))
bonds := queryResponse.GetBonds()
require.NotEmpty(s.t, bonds)
return bonds[0].GetId()
}
func reserveName(s *registryTestSuite, authorityName string) {
cli := s.cli()
cmd := []string{
"tx", "registry", "reserve-authority",
authorityName,
s.accountAddress,
}
txhash := cli.Run(cmd...)
systemtests.RequireTxSuccess(s.t, txhash)
}
func createNameRecord(s *registryTestSuite, authorityName string) {
cli := s.cli()
// reserve name authority
cmd := []string{
"tx", "registry", "reserve-authority",
authorityName,
s.accountAddress,
}
txhash := cli.Run(cmd...)
systemtests.RequireTxSuccess(s.t, txhash)
// add bond-id to name authority
cmd = []string{
"tx", "registry", "authority-bond",
authorityName, s.bondId,
}
txhash = cli.Run(cmd...)
systemtests.RequireTxSuccess(s.t, txhash)
cmd = []string{
"tx", "registry", "set-name",
fmt.Sprintf("lrn://%s/", authorityName),
"test_hello_cid",
}
txhash = cli.Run(cmd...)
systemtests.RequireTxSuccess(s.t, txhash)
}
func createRecord(s *registryTestSuite, bondId string) {
cmd := []string{
"tx", "registry", "set",
recordFilePath, bondId,
}
txhash := s.cli().Run(cmd...)
systemtests.RequireTxSuccess(s.t, txhash)
}
func updateParams(params *registrytypes.Params, bondDenom string) {
params.RecordRent = sdk.NewCoin(bondDenom, math.NewInt(1000))
params.RecordRentDuration = 10 * time.Second
params.AuthorityRent = sdk.NewCoin(bondDenom, math.NewInt(1000))
params.AuthorityGracePeriod = 10 * time.Second
params.AuthorityAuctionCommitFee = sdk.NewCoin(bondDenom, math.NewInt(100))
params.AuthorityAuctionRevealFee = sdk.NewCoin(bondDenom, math.NewInt(100))
params.AuthorityAuctionMinimumBid = sdk.NewCoin(bondDenom, math.NewInt(500))
}
func (s registryTestSuite) commonTxFlags() []string {
return []string{
fmt.Sprintf("--%s=%s", flags.FlagFrom, s.accountName),
// fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
// fmt.Sprintf("--%s=json", flags.FlagOutput),
// fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastSync),
// fmt.Sprintf("--%s=%s", flags.FlagFees, fmt.Sprintf("3%s", s.bondDenom)),
}
}

133
tests/system/test_runner.go Normal file
View File

@ -0,0 +1,133 @@
package system
import (
"flag"
"fmt"
"os"
"os/exec"
"strconv"
"strings"
"testing"
"time"
sdk "github.com/cosmos/cosmos-sdk/types"
)
var (
sut *SystemUnderTest
verbose bool
execBinaryName = "laconicd"
// block time (commit timeout) should match what the testnet command generates
blockTime = time.Second
)
func RunTests(m *testing.M) {
waitTime := flag.Duration("wait-time", DefaultWaitTime, "time to wait for chain events")
nodesCount := flag.Int("nodes-count", 4, "number of nodes in the cluster")
// blockTime := flag.Duration("block-time", 1000*time.Millisecond, "block creation time")
// execBinary := flag.String("binary", "simd", "executable binary for server/ client side")
// bech32Prefix := flag.String("bech32", "cosmos", "bech32 prefix to be used with addresses")
flag.BoolVar(&verbose, "verbose", false, "verbose output")
flag.Parse()
// fail fast on most common setup issue
requireEnoughFileHandlers(*nodesCount + 1) // +1 as tests may start another node
dir, err := os.Getwd()
if err != nil {
panic(err)
}
WorkDir = dir
if verbose {
println("Work dir: ", WorkDir)
}
initSDKConfig("laconic")
DefaultWaitTime = *waitTime
// if *execBinary == "" {
// panic("executable binary name must not be empty")
// }
// sdk systemtests expects this to be set for v2 server/runtime
os.Setenv("COSMOS_BUILD_OPTIONS", "v2")
sut = NewSystemUnderTest(execBinaryName, verbose, *nodesCount, blockTime)
sut.SetupChain() // setup chain and keyring
// run tests
exitCode := m.Run()
// postprocess
sut.StopChain()
if verbose || exitCode != 0 {
sut.PrintBuffer()
printResultFlag(exitCode == 0)
}
os.Exit(exitCode)
}
func GetSystemUnderTest() *SystemUnderTest {
return sut
}
func IsVerbose() bool {
return verbose
}
func GetExecutableName() string {
return execBinaryName
}
// requireEnoughFileHandlers uses `ulimit`
func requireEnoughFileHandlers(nodesCount int) {
ulimit, err := exec.LookPath("ulimit")
if err != nil || ulimit == "" { // skip when not available
return
}
cmd := exec.Command(ulimit, "-n")
cmd.Dir = WorkDir
out, err := cmd.CombinedOutput()
if err != nil {
panic(fmt.Sprintf("unexpected error :%#+v, output: %s", err, string(out)))
}
fileDescrCount, err := strconv.Atoi(strings.Trim(string(out), " \t\n"))
if err != nil {
panic(fmt.Sprintf("unexpected error :%#+v, output: %s", err, string(out)))
}
expFH := nodesCount * 260 // random number that worked on my box
if fileDescrCount < expFH {
panic(fmt.Sprintf("Fail fast. Insufficient setup. Run 'ulimit -n %d'", expFH))
}
}
func initSDKConfig(bech32Prefix string) {
config := sdk.GetConfig()
config.SetBech32PrefixForAccount(bech32Prefix, bech32Prefix+sdk.PrefixPublic)
config.SetBech32PrefixForValidator(bech32Prefix+sdk.PrefixValidator+sdk.PrefixOperator, bech32Prefix+sdk.PrefixValidator+sdk.PrefixOperator+sdk.PrefixPublic)
config.SetBech32PrefixForConsensusNode(bech32Prefix+sdk.PrefixValidator+sdk.PrefixConsensus, bech32Prefix+sdk.PrefixValidator+sdk.PrefixConsensus+sdk.PrefixPublic)
}
const (
successFlag = `
___ _ _ ___ ___ ___ ___ ___
/ __| | | |/ __/ __/ _ \/ __/ __|
\__ \ |_| | (_| (_| __/\__ \__ \
|___/\__,_|\___\___\___||___/___/`
failureFlag = `
__ _ _ _
/ _| (_) | | |
| |_ __ _ _| | ___ __| |
| _/ _| | | |/ _ \/ _| |
| || (_| | | | __/ (_| |
|_| \__,_|_|_|\___|\__,_|`
)
func printResultFlag(ok bool) {
if ok {
fmt.Println(successFlag)
} else {
fmt.Println(failureFlag)
}
}

View File

@ -29,7 +29,7 @@ func (am AppModule) AutoCLIOptions() *autocliv1.ModuleOptions {
}, },
{ {
RpcMethod: "GetAuction", RpcMethod: "GetAuction",
Use: "get [auction-id]", Use: "get <auction-id>",
Short: "Get auction info by auction id", Short: "Get auction info by auction id",
PositionalArgs: []*autocliv1.PositionalArgDescriptor{ PositionalArgs: []*autocliv1.PositionalArgDescriptor{
{ProtoField: "id"}, {ProtoField: "id"},
@ -37,7 +37,7 @@ func (am AppModule) AutoCLIOptions() *autocliv1.ModuleOptions {
}, },
{ {
RpcMethod: "AuctionsByOwner", RpcMethod: "AuctionsByOwner",
Use: "by-owner [owner-address]", Use: "by-owner <owner-address>",
Short: "Get auctions list by owner / creator address", Short: "Get auctions list by owner / creator address",
PositionalArgs: []*autocliv1.PositionalArgDescriptor{ PositionalArgs: []*autocliv1.PositionalArgDescriptor{
{ProtoField: "owner_address"}, {ProtoField: "owner_address"},
@ -45,7 +45,7 @@ func (am AppModule) AutoCLIOptions() *autocliv1.ModuleOptions {
}, },
{ {
RpcMethod: "GetBid", RpcMethod: "GetBid",
Use: "get-bid [auction-id] [bidder]", Use: "get-bid <auction-id> <bidder>",
Short: "Get auction bid by auction id and bidder", Short: "Get auction bid by auction id and bidder",
PositionalArgs: []*autocliv1.PositionalArgDescriptor{ PositionalArgs: []*autocliv1.PositionalArgDescriptor{
{ProtoField: "auction_id"}, {ProtoField: "auction_id"},
@ -54,7 +54,7 @@ func (am AppModule) AutoCLIOptions() *autocliv1.ModuleOptions {
}, },
{ {
RpcMethod: "GetBids", RpcMethod: "GetBids",
Use: "get-bids [auction-id]", Use: "get-bids <auction-id>",
Short: "Get all auction bids", Short: "Get all auction bids",
PositionalArgs: []*autocliv1.PositionalArgDescriptor{ PositionalArgs: []*autocliv1.PositionalArgDescriptor{
{ProtoField: "auction_id"}, {ProtoField: "auction_id"},
@ -62,7 +62,7 @@ func (am AppModule) AutoCLIOptions() *autocliv1.ModuleOptions {
}, },
{ {
RpcMethod: "AuctionsByBidder", RpcMethod: "AuctionsByBidder",
Use: "by-bidder [bidder]", Use: "by-bidder <bidder>",
Short: "Get auctions list by bidder", Short: "Get auctions list by bidder",
PositionalArgs: []*autocliv1.PositionalArgDescriptor{ PositionalArgs: []*autocliv1.PositionalArgDescriptor{
{ProtoField: "bidder_address"}, {ProtoField: "bidder_address"},
@ -81,7 +81,7 @@ func (am AppModule) AutoCLIOptions() *autocliv1.ModuleOptions {
RpcCommandOptions: []*autocliv1.RpcCommandOptions{ RpcCommandOptions: []*autocliv1.RpcCommandOptions{
{ {
RpcMethod: "CreateAuction", RpcMethod: "CreateAuction",
Use: "create [commits-duration] [reveals-duration] [commit-fee] [reveal-fee]", Use: "create <commits-duration> <reveals-duration> <commit-fee> <reveal-fee>",
Short: "Create an auction", Short: "Create an auction",
PositionalArgs: []*autocliv1.PositionalArgDescriptor{ PositionalArgs: []*autocliv1.PositionalArgDescriptor{
{ProtoField: "commits_duration"}, {ProtoField: "commits_duration"},

View File

@ -14,7 +14,7 @@ import (
// Used in e2e tests // Used in e2e tests
func NewCreateBondCmd() *cobra.Command { func NewCreateBondCmd() *cobra.Command {
cmd := &cobra.Command{ cmd := &cobra.Command{
Use: "create [amount]", Use: "create <amount>",
Short: "Create bond.", Short: "Create bond.",
Args: cobra.ExactArgs(1), Args: cobra.ExactArgs(1),
RunE: func(cmd *cobra.Command, args []string) error { RunE: func(cmd *cobra.Command, args []string) error {

View File

@ -172,7 +172,7 @@ func (k Keeper) GetBondById(ctx context.Context, id string) (bondtypes.Bond, err
bond, err := k.Bonds.Get(ctx, id) bond, err := k.Bonds.Get(ctx, id)
if err != nil { if err != nil {
if errors.Is(err, collections.ErrNotFound) { if errors.Is(err, collections.ErrNotFound) {
return bondtypes.Bond{}, errorsmod.Wrap(sdkerrors.ErrInvalidRequest, "Bond not found.") err = errorsmod.Wrap(sdkerrors.ErrInvalidRequest, "Bond not found")
} }
return bondtypes.Bond{}, err return bondtypes.Bond{}, err
} }
@ -397,8 +397,8 @@ func (k Keeper) getMaxBondAmount(ctx context.Context) (sdk.Coins, error) {
return sdk.NewCoins(maxBondAmount), nil return sdk.NewCoins(maxBondAmount), nil
} }
// TransferCoinsToModuleAccount moves funds from the bonds module account to another module account. // TransferRentToModuleAccount sends rent from a bond to a module account.
func (k Keeper) TransferCoinsToModuleAccount(ctx context.Context, id, moduleAccount string, coins sdk.Coins) error { func (k Keeper) TransferRentToModuleAccount(ctx context.Context, id, moduleAccount string, rent sdk.Coins) error {
if has, err := k.HasBond(ctx, id); !has { if has, err := k.HasBond(ctx, id); !has {
if err != nil { if err != nil {
return err return err
@ -412,15 +412,14 @@ func (k Keeper) TransferCoinsToModuleAccount(ctx context.Context, id, moduleAcco
} }
// Deduct rent from bond. // Deduct rent from bond.
updatedBalance, isNeg := bond.Balance.SafeSub(coins...) updatedBalance, isNeg := bond.Balance.SafeSub(rent...)
if isNeg { if isNeg {
// Check if bond has sufficient funds. // Check if bond has sufficient funds.
return errorsmod.Wrap(sdkerrors.ErrInsufficientFunds, "Insufficient funds.") return errorsmod.Wrap(sdkerrors.ErrInsufficientFunds, "Insufficient funds.")
} }
// Move funds from bond module to record rent module. // Move funds from bond module to record rent module.
err = k.bankKeeper.SendCoinsFromModuleToModule(ctx, bondtypes.ModuleName, moduleAccount, coins) err = k.bankKeeper.SendCoinsFromModuleToModule(ctx, bondtypes.ModuleName, moduleAccount, rent)
if err != nil { if err != nil {
return errorsmod.Wrap(sdkerrors.ErrInvalidRequest, "Error transferring funds.") return errorsmod.Wrap(sdkerrors.ErrInvalidRequest, "Error transferring funds.")
} }

View File

@ -11,18 +11,17 @@ import (
"git.vdb.to/cerc-io/laconicd/x/bond" "git.vdb.to/cerc-io/laconicd/x/bond"
) )
var _ bond.MsgServer = msgServer{} type msgHandlers struct {
type msgServer struct {
k *Keeper k *Keeper
} }
// NewMsgServerImpl returns an implementation of the module MsgServer interface. // NewHandlers returns an implementation of the module MsgServer interface.
func NewMsgServerImpl(keeper *Keeper) bond.MsgServer { func NewHandlers(keeper *Keeper) msgHandlers {
return &msgServer{k: keeper} return msgHandlers{k: keeper}
} }
func (ms msgServer) CreateBond(c context.Context, msg *bond.MsgCreateBond) (*bond.MsgCreateBondResponse, error) { func (ms msgHandlers) CreateBond(c context.Context, msg *bond.MsgCreateBond) (*bond.MsgCreateBondResponse, error) {
panic("handlers.CreateBond is definitely called")
if err := msg.ValidateBasic(); err != nil { if err := msg.ValidateBasic(); err != nil {
return nil, err return nil, err
} }
@ -60,7 +59,7 @@ func (ms msgServer) CreateBond(c context.Context, msg *bond.MsgCreateBond) (*bon
} }
// RefillBond implements bond.MsgServer. // RefillBond implements bond.MsgServer.
func (ms msgServer) RefillBond(c context.Context, msg *bond.MsgRefillBond) (*bond.MsgRefillBondResponse, error) { func (ms msgHandlers) RefillBond(c context.Context, msg *bond.MsgRefillBond) (*bond.MsgRefillBondResponse, error) {
if err := msg.ValidateBasic(); err != nil { if err := msg.ValidateBasic(); err != nil {
return nil, err return nil, err
} }
@ -99,7 +98,7 @@ func (ms msgServer) RefillBond(c context.Context, msg *bond.MsgRefillBond) (*bon
} }
// WithdrawBond implements bond.MsgServer. // WithdrawBond implements bond.MsgServer.
func (ms msgServer) WithdrawBond(c context.Context, msg *bond.MsgWithdrawBond) (*bond.MsgWithdrawBondResponse, error) { func (ms msgHandlers) WithdrawBond(c context.Context, msg *bond.MsgWithdrawBond) (*bond.MsgWithdrawBondResponse, error) {
if err := msg.ValidateBasic(); err != nil { if err := msg.ValidateBasic(); err != nil {
return nil, err return nil, err
} }
@ -138,7 +137,7 @@ func (ms msgServer) WithdrawBond(c context.Context, msg *bond.MsgWithdrawBond) (
} }
// CancelBond implements bond.MsgServer. // CancelBond implements bond.MsgServer.
func (ms msgServer) CancelBond(c context.Context, msg *bond.MsgCancelBond) (*bond.MsgCancelBondResponse, error) { func (ms msgHandlers) CancelBond(c context.Context, msg *bond.MsgCancelBond) (*bond.MsgCancelBondResponse, error) {
if err := msg.ValidateBasic(); err != nil { if err := msg.ValidateBasic(); err != nil {
return nil, err return nil, err
} }
@ -176,7 +175,7 @@ func (ms msgServer) CancelBond(c context.Context, msg *bond.MsgCancelBond) (*bon
} }
// UpdateParams defines a method to perform updation of module params. // UpdateParams defines a method to perform updation of module params.
func (ms msgServer) UpdateParams(c context.Context, msg *bond.MsgUpdateParams) (*bond.MsgUpdateParamsResponse, error) { func (ms msgHandlers) UpdateParams(c context.Context, msg *bond.MsgUpdateParams) (*bond.MsgUpdateParamsResponse, error) {
if ms.k.authority != msg.Authority { if ms.k.authority != msg.Authority {
return nil, errorsmod.Wrapf(govtypes.ErrInvalidSigner, "invalid authority; expected %s, got %s", ms.k.authority, msg.Authority) return nil, errorsmod.Wrapf(govtypes.ErrInvalidSigner, "invalid authority; expected %s, got %s", ms.k.authority, msg.Authority)
} }

View File

@ -9,19 +9,17 @@ import (
bondtypes "git.vdb.to/cerc-io/laconicd/x/bond" bondtypes "git.vdb.to/cerc-io/laconicd/x/bond"
) )
var _ bondtypes.QueryServer = queryServer{} type queryHandlers struct {
type queryServer struct {
k *Keeper k *Keeper
} }
// NewQueryServerImpl returns an implementation of the module QueryServer. // NewQueryHandlers returns an implementation of the module QueryServer.
func NewQueryServerImpl(k *Keeper) bondtypes.QueryServer { func NewQueryHandlers(k *Keeper) bondtypes.QueryServer {
return queryServer{k} return queryHandlers{k}
} }
// Params implements bond.QueryServer. // Params implements bond.QueryServer.
func (qs queryServer) Params(ctx context.Context, _ *bondtypes.QueryParamsRequest) (*bondtypes.QueryParamsResponse, error) { func (qs queryHandlers) Params(ctx context.Context, _ *bondtypes.QueryParamsRequest) (*bondtypes.QueryParamsResponse, error) {
params, err := qs.k.GetParams(ctx) params, err := qs.k.GetParams(ctx)
if err != nil { if err != nil {
return nil, err return nil, err
@ -31,7 +29,7 @@ func (qs queryServer) Params(ctx context.Context, _ *bondtypes.QueryParamsReques
} }
// Bonds implements bond.QueryServer. // Bonds implements bond.QueryServer.
func (qs queryServer) Bonds(ctx context.Context, _ *bondtypes.QueryBondsRequest) (*bondtypes.QueryBondsResponse, error) { func (qs queryHandlers) Bonds(ctx context.Context, _ *bondtypes.QueryBondsRequest) (*bondtypes.QueryBondsResponse, error) {
resp, err := qs.k.ListBonds(ctx) resp, err := qs.k.ListBonds(ctx)
if err != nil { if err != nil {
return nil, err return nil, err
@ -41,7 +39,7 @@ func (qs queryServer) Bonds(ctx context.Context, _ *bondtypes.QueryBondsRequest)
} }
// GetBondById implements bond.QueryServer. // GetBondById implements bond.QueryServer.
func (qs queryServer) GetBondById(ctx context.Context, req *bondtypes.QueryGetBondByIdRequest) (*bondtypes.QueryGetBondByIdResponse, error) { func (qs queryHandlers) GetBondById(ctx context.Context, req *bondtypes.QueryGetBondByIdRequest) (*bondtypes.QueryGetBondByIdResponse, error) {
bondId := req.GetId() bondId := req.GetId()
if len(bondId) == 0 { if len(bondId) == 0 {
return nil, errorsmod.Wrap(sdkerrors.ErrInvalidRequest, "bond id required") return nil, errorsmod.Wrap(sdkerrors.ErrInvalidRequest, "bond id required")
@ -56,7 +54,7 @@ func (qs queryServer) GetBondById(ctx context.Context, req *bondtypes.QueryGetBo
} }
// GetBondsByOwner implements bond.QueryServer. // GetBondsByOwner implements bond.QueryServer.
func (qs queryServer) GetBondsByOwner( func (qs queryHandlers) GetBondsByOwner(
ctx context.Context, ctx context.Context,
req *bondtypes.QueryGetBondsByOwnerRequest, req *bondtypes.QueryGetBondsByOwnerRequest,
) (*bondtypes.QueryGetBondsByOwnerResponse, error) { ) (*bondtypes.QueryGetBondsByOwnerResponse, error) {
@ -76,7 +74,7 @@ func (qs queryServer) GetBondsByOwner(
} }
// GetBondModuleBalance implements bond.QueryServer. // GetBondModuleBalance implements bond.QueryServer.
func (qs queryServer) GetBondModuleBalance( func (qs queryHandlers) GetBondModuleBalance(
ctx context.Context, ctx context.Context,
_ *bondtypes.QueryGetBondModuleBalanceRequest, _ *bondtypes.QueryGetBondModuleBalanceRequest,
) (*bondtypes.QueryGetBondModuleBalanceResponse, error) { ) (*bondtypes.QueryGetBondModuleBalanceResponse, error) {

View File

@ -29,7 +29,7 @@ func (am AppModule) AutoCLIOptions() *autocliv1.ModuleOptions {
}, },
{ {
RpcMethod: "GetBondById", RpcMethod: "GetBondById",
Use: "get [bond-id]", Use: "get <bond-id>",
Short: "Get bond info by bond id", Short: "Get bond info by bond id",
PositionalArgs: []*autocliv1.PositionalArgDescriptor{ PositionalArgs: []*autocliv1.PositionalArgDescriptor{
{ProtoField: "id"}, {ProtoField: "id"},
@ -37,7 +37,7 @@ func (am AppModule) AutoCLIOptions() *autocliv1.ModuleOptions {
}, },
{ {
RpcMethod: "GetBondsByOwner", RpcMethod: "GetBondsByOwner",
Use: "by-owner [owner-address]", Use: "by-owner <owner-address>",
Short: "Get bonds list by owner address", Short: "Get bonds list by owner address",
PositionalArgs: []*autocliv1.PositionalArgDescriptor{ PositionalArgs: []*autocliv1.PositionalArgDescriptor{
{ProtoField: "owner"}, {ProtoField: "owner"},
@ -56,7 +56,7 @@ func (am AppModule) AutoCLIOptions() *autocliv1.ModuleOptions {
RpcCommandOptions: []*autocliv1.RpcCommandOptions{ RpcCommandOptions: []*autocliv1.RpcCommandOptions{
{ {
RpcMethod: "CreateBond", RpcMethod: "CreateBond",
Use: "create [amount]", Use: "create <amount>",
Short: "Create bond", Short: "Create bond",
PositionalArgs: []*autocliv1.PositionalArgDescriptor{ PositionalArgs: []*autocliv1.PositionalArgDescriptor{
{ProtoField: "coins"}, {ProtoField: "coins"},
@ -64,7 +64,7 @@ func (am AppModule) AutoCLIOptions() *autocliv1.ModuleOptions {
}, },
{ {
RpcMethod: "RefillBond", RpcMethod: "RefillBond",
Use: "refill [bond-id] [amount]", Use: "refill <bond-id> <amount>",
Short: "Refill bond", Short: "Refill bond",
PositionalArgs: []*autocliv1.PositionalArgDescriptor{ PositionalArgs: []*autocliv1.PositionalArgDescriptor{
{ProtoField: "id"}, {ProtoField: "id"},
@ -73,7 +73,7 @@ func (am AppModule) AutoCLIOptions() *autocliv1.ModuleOptions {
}, },
{ {
RpcMethod: "WithdrawBond", RpcMethod: "WithdrawBond",
Use: "withdraw [bond-id] [amount]", Use: "withdraw <bond-id> <amount>",
Short: "Withdraw amount from bond", Short: "Withdraw amount from bond",
PositionalArgs: []*autocliv1.PositionalArgDescriptor{ PositionalArgs: []*autocliv1.PositionalArgDescriptor{
{ProtoField: "id"}, {ProtoField: "id"},
@ -82,7 +82,7 @@ func (am AppModule) AutoCLIOptions() *autocliv1.ModuleOptions {
}, },
{ {
RpcMethod: "CancelBond", RpcMethod: "CancelBond",
Use: "cancel [bond-id]", Use: "cancel <bond-id>",
Short: "Cancel bond", Short: "Cancel bond",
PositionalArgs: []*autocliv1.PositionalArgDescriptor{ PositionalArgs: []*autocliv1.PositionalArgDescriptor{
{ProtoField: "id"}, {ProtoField: "id"},

View File

@ -5,15 +5,19 @@ import (
"encoding/json" "encoding/json"
"fmt" "fmt"
gwruntime "github.com/grpc-ecosystem/grpc-gateway/runtime"
"github.com/spf13/cobra"
// "google.golang.org/grpc"
appmodule "cosmossdk.io/core/appmodule/v2" appmodule "cosmossdk.io/core/appmodule/v2"
"cosmossdk.io/core/registry" "cosmossdk.io/core/registry"
"github.com/cosmos/cosmos-sdk/client" "github.com/cosmos/cosmos-sdk/client"
"github.com/cosmos/cosmos-sdk/codec" "github.com/cosmos/cosmos-sdk/codec"
sdk "github.com/cosmos/cosmos-sdk/types" sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/types/module" "github.com/cosmos/cosmos-sdk/types/module"
gwruntime "github.com/grpc-ecosystem/grpc-gateway/runtime"
"git.vdb.to/cerc-io/laconicd/x/bond" "git.vdb.to/cerc-io/laconicd/x/bond"
"git.vdb.to/cerc-io/laconicd/x/bond/client/cli"
"git.vdb.to/cerc-io/laconicd/x/bond/keeper" "git.vdb.to/cerc-io/laconicd/x/bond/keeper"
) )
@ -22,9 +26,11 @@ var (
_ appmodule.HasGenesis = AppModule{} _ appmodule.HasGenesis = AppModule{}
_ appmodule.HasConsensusVersion = AppModule{} _ appmodule.HasConsensusVersion = AppModule{}
_ appmodule.HasRegisterInterfaces = AppModule{} _ appmodule.HasRegisterInterfaces = AppModule{}
// _ appmodule.HasMsgHandlers = AppModule{}
_ appmodule.HasQueryHandlers = AppModule{}
_ module.HasGRPCGateway = AppModule{} _ module.HasGRPCGateway = AppModule{}
_ module.HasServices = AppModule{} // _ module.HasServices = AppModule{}
_ module.HasInvariants = AppModule{} _ module.HasInvariants = AppModule{}
// _ module.HasAminoCodec = AppModule{} // TODO // _ module.HasAminoCodec = AppModule{} // TODO
) )
@ -111,16 +117,50 @@ func (am AppModule) ExportGenesis(ctx context.Context) (json.RawMessage, error)
return am.cdc.MustMarshalJSON(gs), nil return am.cdc.MustMarshalJSON(gs), nil
} }
// module.HasServices // // module.HasServices
func (am AppModule) RegisterServices(cfg module.Configurator) { // func (am AppModule) RegisterServices(registrar grpc.ServiceRegistrar) error {
// Register servers // bond.RegisterMsgServer(registrar, keeper.NewHandlers(am.keeper))
bond.RegisterMsgServer(cfg.MsgServer(), keeper.NewMsgServerImpl(am.keeper)) // bond.RegisterQueryServer(registrar, keeper.NewQueryHandlers(am.keeper))
bond.RegisterQueryServer(cfg.QueryServer(), keeper.NewQueryServerImpl(am.keeper)) // return nil
} // }
// module.HasInvariants // module.HasInvariants
func (am AppModule) RegisterInvariants(ir sdk.InvariantRegistry) { func (am AppModule) RegisterInvariants(ir sdk.InvariantRegistry) {
keeper.RegisterInvariants(ir, am.keeper) keeper.RegisterInvariants(ir, am.keeper)
} }
// RegisterMsgHandlers registers the message handlers for the bond module.
func (am AppModule) RegisterMsgHandlers(router appmodule.MsgRouter) {
handlers := keeper.NewHandlers(am.keeper)
appmodule.RegisterMsgHandler(router, handlers.CreateBond)
appmodule.RegisterMsgHandler(router, handlers.RefillBond)
appmodule.RegisterMsgHandler(router, handlers.WithdrawBond)
appmodule.RegisterMsgHandler(router, handlers.CancelBond)
appmodule.RegisterMsgHandler(router, handlers.UpdateParams)
}
// RegisterQueryHandlers registers the query handlers for the bond module.
func (am AppModule) RegisterQueryHandlers(router appmodule.QueryRouter) {
handlers := keeper.NewQueryHandlers(am.keeper)
appmodule.RegisterMsgHandler(router, handlers.Params)
appmodule.RegisterMsgHandler(router, handlers.Bonds)
appmodule.RegisterMsgHandler(router, handlers.GetBondById)
appmodule.RegisterMsgHandler(router, handlers.GetBondsByOwner)
appmodule.RegisterMsgHandler(router, handlers.GetBondModuleBalance)
}
// GetTxCmd returns the root tx command for the bank/v2 module.
// TODO: Remove & use autocli
func (AppModule) GetTxCmd() *cobra.Command {
return cli.NewTxCmd()
}
// GetQueryCmd returns the root query command for the bank/v2 module.
// TODO: Remove & use autocli
func (AppModule) GetQueryCmd() *cobra.Command {
return cli.GetQueryCmd()
}

View File

@ -20,7 +20,7 @@ func (am AppModule) AutoCLIOptions() *autocliv1.ModuleOptions {
}, },
{ {
RpcMethod: "GetParticipantByAddress", RpcMethod: "GetParticipantByAddress",
Use: "get-by-address [address]", Use: "get-by-address <address>",
Short: "Get participant by address", Short: "Get participant by address",
PositionalArgs: []*autocliv1.PositionalArgDescriptor{ PositionalArgs: []*autocliv1.PositionalArgDescriptor{
{ProtoField: "address"}, {ProtoField: "address"},
@ -28,7 +28,7 @@ func (am AppModule) AutoCLIOptions() *autocliv1.ModuleOptions {
}, },
{ {
RpcMethod: "GetParticipantByNitroAddress", RpcMethod: "GetParticipantByNitroAddress",
Use: "get-by-nitro-address [nitro_address]", Use: "get-by-nitro-address <nitro-address>",
Short: "Get participant by nitro address", Short: "Get participant by nitro address",
PositionalArgs: []*autocliv1.PositionalArgDescriptor{ PositionalArgs: []*autocliv1.PositionalArgDescriptor{
{ProtoField: "nitro_address"}, {ProtoField: "nitro_address"},
@ -42,7 +42,7 @@ func (am AppModule) AutoCLIOptions() *autocliv1.ModuleOptions {
RpcCommandOptions: []*autocliv1.RpcCommandOptions{ RpcCommandOptions: []*autocliv1.RpcCommandOptions{
{ {
RpcMethod: "OnboardParticipant", RpcMethod: "OnboardParticipant",
Use: "enroll [eth_payload] [eth_signature] [role] [kyc_id]", Use: "enroll <eth-payload> <eth-signature> <role> <kyc-id>",
Short: "Enroll a testnet validator", Short: "Enroll a testnet validator",
PositionalArgs: []*autocliv1.PositionalArgDescriptor{ PositionalArgs: []*autocliv1.PositionalArgDescriptor{
{ProtoField: "eth_payload"}, {ProtoField: "eth_payload"},

View File

@ -440,7 +440,7 @@ func (k Keeper) processRecord(ctx context.Context, record *registrytypes.Readabl
} }
rent := params.RecordRent rent := params.RecordRent
if err = k.bondKeeper.TransferCoinsToModuleAccount( if err = k.bondKeeper.TransferRentToModuleAccount(
ctx, record.BondId, registrytypes.RecordRentModuleAccountName, sdk.NewCoins(rent), ctx, record.BondId, registrytypes.RecordRentModuleAccountName, sdk.NewCoins(rent),
); err != nil { ); err != nil {
return err return err
@ -721,7 +721,7 @@ func (k Keeper) tryTakeRecordRent(ctx context.Context, record registrytypes.Reco
} }
rent := params.RecordRent rent := params.RecordRent
sdkErr := k.bondKeeper.TransferCoinsToModuleAccount(ctx, record.BondId, registrytypes.RecordRentModuleAccountName, sdk.NewCoins(rent)) sdkErr := k.bondKeeper.TransferRentToModuleAccount(ctx, record.BondId, registrytypes.RecordRentModuleAccountName, sdk.NewCoins(rent))
if sdkErr != nil { if sdkErr != nil {
// Insufficient funds, mark record as deleted. // Insufficient funds, mark record as deleted.
record.Deleted = true record.Deleted = true

View File

@ -622,7 +622,7 @@ func (k Keeper) tryTakeAuthorityRent(ctx context.Context, name string, authority
} }
rent := params.AuthorityRent rent := params.AuthorityRent
sdkErr := k.bondKeeper.TransferCoinsToModuleAccount(ctx, authority.BondId, registrytypes.AuthorityRentModuleAccountName, sdk.NewCoins(rent)) sdkErr := k.bondKeeper.TransferRentToModuleAccount(ctx, authority.BondId, registrytypes.AuthorityRentModuleAccountName, sdk.NewCoins(rent))
if sdkErr != nil { if sdkErr != nil {
// Insufficient funds, mark authority as expired. // Insufficient funds, mark authority as expired.
authority.Status = registrytypes.AuthorityExpired authority.Status = registrytypes.AuthorityExpired

View File

@ -29,7 +29,7 @@ func (am AppModule) AutoCLIOptions() *autocliv1.ModuleOptions {
}, },
{ {
RpcMethod: "GetRecord", RpcMethod: "GetRecord",
Use: "get [record-id]", Use: "get <record-id>",
Short: "Get record info by record id", Short: "Get record info by record id",
PositionalArgs: []*autocliv1.PositionalArgDescriptor{ PositionalArgs: []*autocliv1.PositionalArgDescriptor{
{ProtoField: "id"}, {ProtoField: "id"},
@ -37,7 +37,7 @@ func (am AppModule) AutoCLIOptions() *autocliv1.ModuleOptions {
}, },
{ {
RpcMethod: "GetRecordsByBondId", RpcMethod: "GetRecordsByBondId",
Use: "get-records-by-bond-id [bond-id]", Use: "get-records-by-bond-id <bond-id>",
Short: "Get records by bond id", Short: "Get records by bond id",
PositionalArgs: []*autocliv1.PositionalArgDescriptor{ PositionalArgs: []*autocliv1.PositionalArgDescriptor{
{ProtoField: "id"}, {ProtoField: "id"},
@ -45,7 +45,7 @@ func (am AppModule) AutoCLIOptions() *autocliv1.ModuleOptions {
}, },
{ {
RpcMethod: "Whois", RpcMethod: "Whois",
Use: "whois [name]", Use: "whois <name>",
Short: "Get name authority info", Short: "Get name authority info",
PositionalArgs: []*autocliv1.PositionalArgDescriptor{ PositionalArgs: []*autocliv1.PositionalArgDescriptor{
{ProtoField: "name"}, {ProtoField: "name"},
@ -71,7 +71,7 @@ func (am AppModule) AutoCLIOptions() *autocliv1.ModuleOptions {
}, },
{ {
RpcMethod: "LookupLrn", RpcMethod: "LookupLrn",
Use: "lookup [lrn]", Use: "lookup <lrn>",
Short: "Get naming info for LRN", Short: "Get naming info for LRN",
PositionalArgs: []*autocliv1.PositionalArgDescriptor{ PositionalArgs: []*autocliv1.PositionalArgDescriptor{
{ProtoField: "lrn"}, {ProtoField: "lrn"},
@ -79,7 +79,7 @@ func (am AppModule) AutoCLIOptions() *autocliv1.ModuleOptions {
}, },
{ {
RpcMethod: "ResolveLrn", RpcMethod: "ResolveLrn",
Use: "resolve [lrn]", Use: "resolve <lrn>",
Short: "Resolve LRN to record", Short: "Resolve LRN to record",
PositionalArgs: []*autocliv1.PositionalArgDescriptor{ PositionalArgs: []*autocliv1.PositionalArgDescriptor{
{ProtoField: "lrn"}, {ProtoField: "lrn"},
@ -98,7 +98,7 @@ func (am AppModule) AutoCLIOptions() *autocliv1.ModuleOptions {
RpcCommandOptions: []*autocliv1.RpcCommandOptions{ RpcCommandOptions: []*autocliv1.RpcCommandOptions{
{ {
RpcMethod: "RenewRecord", RpcMethod: "RenewRecord",
Use: "renew-record [record-id]", Use: "renew-record <record-id>",
Short: "Renew (expired) record", Short: "Renew (expired) record",
PositionalArgs: []*autocliv1.PositionalArgDescriptor{ PositionalArgs: []*autocliv1.PositionalArgDescriptor{
{ProtoField: "record_id"}, {ProtoField: "record_id"},
@ -106,7 +106,7 @@ func (am AppModule) AutoCLIOptions() *autocliv1.ModuleOptions {
}, },
{ {
RpcMethod: "ReserveAuthority", RpcMethod: "ReserveAuthority",
Use: "reserve-authority [name] [owner]", Use: "reserve-authority <name> <owner>",
Short: "Reserve authority name", Short: "Reserve authority name",
PositionalArgs: []*autocliv1.PositionalArgDescriptor{ PositionalArgs: []*autocliv1.PositionalArgDescriptor{
{ProtoField: "name"}, {ProtoField: "name"},
@ -115,7 +115,7 @@ func (am AppModule) AutoCLIOptions() *autocliv1.ModuleOptions {
}, },
{ {
RpcMethod: "SetAuthorityBond", RpcMethod: "SetAuthorityBond",
Use: "authority-bond [name] [bond-id]", Use: "authority-bond <name> <bond-id>",
Short: "Associate authority with bond", Short: "Associate authority with bond",
PositionalArgs: []*autocliv1.PositionalArgDescriptor{ PositionalArgs: []*autocliv1.PositionalArgDescriptor{
{ProtoField: "name"}, {ProtoField: "name"},
@ -124,7 +124,7 @@ func (am AppModule) AutoCLIOptions() *autocliv1.ModuleOptions {
}, },
{ {
RpcMethod: "SetName", RpcMethod: "SetName",
Use: "set-name [lrn] [cid]", Use: "set-name <lrn> <cid>",
Short: "Set LRN to CID mapping", Short: "Set LRN to CID mapping",
PositionalArgs: []*autocliv1.PositionalArgDescriptor{ PositionalArgs: []*autocliv1.PositionalArgDescriptor{
{ProtoField: "lrn"}, {ProtoField: "lrn"},
@ -133,7 +133,7 @@ func (am AppModule) AutoCLIOptions() *autocliv1.ModuleOptions {
}, },
{ {
RpcMethod: "DeleteName", RpcMethod: "DeleteName",
Use: "delete-name [lrn]", Use: "delete-name <lrn>",
Short: "Delete LRN", Short: "Delete LRN",
PositionalArgs: []*autocliv1.PositionalArgDescriptor{ PositionalArgs: []*autocliv1.PositionalArgDescriptor{
{ProtoField: "lrn"}, {ProtoField: "lrn"},
@ -141,7 +141,7 @@ func (am AppModule) AutoCLIOptions() *autocliv1.ModuleOptions {
}, },
{ {
RpcMethod: "AssociateBond", RpcMethod: "AssociateBond",
Use: "associate-bond [record-id] [bond-id]", Use: "associate-bond <record-id> <bond-id>",
Short: "Associate record with a bond", Short: "Associate record with a bond",
PositionalArgs: []*autocliv1.PositionalArgDescriptor{ PositionalArgs: []*autocliv1.PositionalArgDescriptor{
{ProtoField: "record_id"}, {ProtoField: "record_id"},
@ -150,7 +150,7 @@ func (am AppModule) AutoCLIOptions() *autocliv1.ModuleOptions {
}, },
{ {
RpcMethod: "DissociateBond", RpcMethod: "DissociateBond",
Use: "dissociate-bond [record-id]", Use: "dissociate-bond <record-id>",
Short: "Dissociate record from (existing) bond", Short: "Dissociate record from (existing) bond",
PositionalArgs: []*autocliv1.PositionalArgDescriptor{ PositionalArgs: []*autocliv1.PositionalArgDescriptor{
{ProtoField: "record_id"}, {ProtoField: "record_id"},
@ -158,7 +158,7 @@ func (am AppModule) AutoCLIOptions() *autocliv1.ModuleOptions {
}, },
{ {
RpcMethod: "DissociateRecords", RpcMethod: "DissociateRecords",
Use: "dissociate-records [bond-id]", Use: "dissociate-records <bond-id>",
Short: "Dissociate all records from a bond", Short: "Dissociate all records from a bond",
PositionalArgs: []*autocliv1.PositionalArgDescriptor{ PositionalArgs: []*autocliv1.PositionalArgDescriptor{
{ProtoField: "bond_id"}, {ProtoField: "bond_id"},
@ -166,7 +166,7 @@ func (am AppModule) AutoCLIOptions() *autocliv1.ModuleOptions {
}, },
{ {
RpcMethod: "ReassociateRecords", RpcMethod: "ReassociateRecords",
Use: "reassociate-records [old-bond-id] [new-bond-id]", Use: "reassociate-records <old-bond-id> <new-bond-id>",
Short: "Re-associate all records from an old to a new bond", Short: "Re-associate all records from an old to a new bond",
PositionalArgs: []*autocliv1.PositionalArgDescriptor{ PositionalArgs: []*autocliv1.PositionalArgDescriptor{
{ProtoField: "old_bond_id"}, {ProtoField: "old_bond_id"},