Skip to content

Commit

Permalink
feat(server/v2): add min gas price and check with tx fee (cosmos#21173)
Browse files Browse the repository at this point in the history
Co-authored-by: Julien Robert <[email protected]>
  • Loading branch information
akhilkumarpilli and julienrbrt authored Aug 29, 2024
1 parent 78de1a2 commit 81a225e
Show file tree
Hide file tree
Showing 17 changed files with 222 additions and 79 deletions.
3 changes: 2 additions & 1 deletion server/v2/commands.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,13 +38,14 @@ func AddCommands[T transaction.Tx](
rootCmd *cobra.Command,
newApp AppCreator[T],
logger log.Logger,
serverCfg ServerConfig,
components ...ServerComponent[T],
) error {
if len(components) == 0 {
return errors.New("no components provided")
}

server := NewServer(logger, components...)
server := NewServer(logger, serverCfg, components...)
originalPersistentPreRunE := rootCmd.PersistentPreRunE
rootCmd.PersistentPreRunE = func(cmd *cobra.Command, args []string) error {
// set the default command outputs
Expand Down
12 changes: 12 additions & 0 deletions server/v2/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,18 @@ import (
"github.com/spf13/viper"
)

// ServerConfig defines configuration for the server component.
type ServerConfig struct {
MinGasPrices string `mapstructure:"minimum-gas-prices" toml:"minimum-gas-prices" comment:"minimum-gas-prices defines the price which a validator is willing to accept for processing a transaction. A transaction's fees must meet the minimum of any denomination specified in this config (e.g. 0.25token1;0.0001token2)."`
}

// DefaultServerConfig returns the default config of server component
func DefaultServerConfig() ServerConfig {
return ServerConfig{
MinGasPrices: "0stake",
}
}

// ReadConfig returns a viper instance of the config file
func ReadConfig(configPath string) (*viper.Viper, error) {
v := viper.New()
Expand Down
10 changes: 10 additions & 0 deletions server/v2/flags.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,16 @@
// Package serverv2 defines constants for server configuration flags and output formats.
package serverv2

import "fmt"

// start flags are prefixed with the server name
// this allows viper to properly bind the flags
func prefix(f string) string {
return fmt.Sprintf("%s.%s", serverName, f)
}

var FlagMinGasPrices = prefix("minimum-gas-prices")

const (
// FlagHome specifies the home directory flag.
FlagHome = "home"
Expand Down
38 changes: 37 additions & 1 deletion server/v2/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,25 +56,32 @@ type CLIConfig struct {
Txs []*cobra.Command
}

const (
serverName = "server"
)

var _ ServerComponent[transaction.Tx] = (*Server[transaction.Tx])(nil)

type Server[T transaction.Tx] struct {
logger log.Logger
components []ServerComponent[T]
config ServerConfig
}

func NewServer[T transaction.Tx](
logger log.Logger,
config ServerConfig,
components ...ServerComponent[T],
) *Server[T] {
return &Server[T]{
logger: logger,
config: config,
components: components,
}
}

func (s *Server[T]) Name() string {
return "server"
return serverName
}

// Start starts all components concurrently.
Expand Down Expand Up @@ -151,9 +158,19 @@ func (s *Server[T]) CLICommands() CLIConfig {
return commands
}

// Config returns config of the server component
func (s *Server[T]) Config() ServerConfig {
return s.config
}

// Configs returns all configs of all server components.
func (s *Server[T]) Configs() map[string]any {
cfgs := make(map[string]any)

// add server component config
cfgs[s.Name()] = s.config

// add other components' config
for _, mod := range s.components {
if configmod, ok := mod.(HasConfig); ok {
cfg := configmod.Config()
Expand All @@ -164,9 +181,22 @@ func (s *Server[T]) Configs() map[string]any {
return cfgs
}

func (s *Server[T]) StartCmdFlags() *pflag.FlagSet {
flags := pflag.NewFlagSet(s.Name(), pflag.ExitOnError)
flags.String(FlagMinGasPrices, "", "Minimum gas prices to accept for transactions; Any fee in a tx must meet this minimum (e.g. 0.01photino;0.0001stake)")
return flags
}

// Init initializes all server components with the provided application, configuration, and logger.
// It returns an error if any component fails to initialize.
func (s *Server[T]) Init(appI AppI[T], v *viper.Viper, logger log.Logger) error {
cfg := s.config
if v != nil {
if err := UnmarshalSubConfig(v, s.Name(), &cfg); err != nil {
return fmt.Errorf("failed to unmarshal config: %w", err)
}
}

var components []ServerComponent[T]
for _, mod := range s.components {
mod := mod
Expand All @@ -177,6 +207,7 @@ func (s *Server[T]) Init(appI AppI[T], v *viper.Viper, logger log.Logger) error
components = append(components, mod)
}

s.config = cfg
s.components = components
return nil
}
Expand Down Expand Up @@ -217,6 +248,11 @@ func (s *Server[T]) WriteConfig(configPath string) error {
// StartFlags returns all flags of all server components.
func (s *Server[T]) StartFlags() []*pflag.FlagSet {
flags := []*pflag.FlagSet{}

// add server component flags
flags = append(flags, s.StartCmdFlags())

// add other components' start cmd flags
for _, mod := range s.components {
if startmod, ok := mod.(HasStartFlags); ok {
flags = append(flags, startmod.StartCmdFlags())
Expand Down
1 change: 1 addition & 0 deletions server/v2/server_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ func TestServer(t *testing.T) {

server := serverv2.NewServer(
logger,
serverv2.DefaultServerConfig(),
grpcServer,
mockServer,
)
Expand Down
4 changes: 4 additions & 0 deletions server/v2/testdata/app.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,10 @@ max-recv-msg-size = 10485760
# The default value is math.MaxInt32.
max-send-msg-size = 2147483647

[server]
# minimum-gas-prices defines the price which a validator is willing to accept for processing a transaction. A transaction's fees must meet the minimum of any denomination specified in this config (e.g. 0.25token1;0.0001token2).
minimum-gas-prices = '0stake'

[store]
# The type of database for application and snapshots databases.
app-db-backend = 'goleveldb'
Expand Down
1 change: 1 addition & 0 deletions simapp/v2/simdv2/cmd/commands.go
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ func initRootCmd[T transaction.Tx](
rootCmd,
newApp,
logger,
initServerConfig(),
cometbft.New(&genericTxDecoder[T]{txConfig}, cometbft.DefaultServerOptions[T]()),
grpc.New[T](),
store.New[T](newApp),
Expand Down
19 changes: 19 additions & 0 deletions simapp/v2/simdv2/cmd/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ package cmd
import (
"strings"

serverv2 "cosmossdk.io/server/v2"

clientconfig "github.com/cosmos/cosmos-sdk/client/config"
"github.com/cosmos/cosmos-sdk/crypto/keyring"
)
Expand Down Expand Up @@ -49,3 +51,20 @@ gas-adjustment = {{ .GasConfig.GasAdjustment }}

return customClientConfigTemplate, customClientConfig
}

// Allow the chain developer to overwrite the server default app toml config.
func initServerConfig() serverv2.ServerConfig {
serverCfg := serverv2.DefaultServerConfig()
// 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
// validators here. Please update value based on chain denom.
//
// In summary:
// - if you set serverCfg.MinGasPrices value, validators CAN tweak their
// own app.toml to override, or use this default value.
//
// In simapp, we set the min gas prices to 0.
serverCfg.MinGasPrices = "0stake"

return serverCfg
}
10 changes: 6 additions & 4 deletions simapp/v2/simdv2/cmd/testnet.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,6 @@ import (
)

var (
flagMinGasPrices = "minimum-gas-prices"
flagNodeDirPrefix = "node-dir-prefix"
flagNumValidators = "validator-count"
flagOutputDir = "output-dir"
Expand Down Expand Up @@ -72,7 +71,7 @@ func addTestnetFlagsToCmd(cmd *cobra.Command) {
cmd.Flags().IntP(flagNumValidators, "n", 4, "Number of validators to initialize the testnet with")
cmd.Flags().StringP(flagOutputDir, "o", "./.testnets", "Directory to store initialization data for the testnet")
cmd.Flags().String(flags.FlagChainID, "", "genesis file chain-id, if left blank will be randomly created")
cmd.Flags().String(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")

// support old flags name for backwards compatibility
Expand Down Expand Up @@ -129,7 +128,7 @@ Example:
args.outputDir, _ = cmd.Flags().GetString(flagOutputDir)
args.keyringBackend, _ = cmd.Flags().GetString(flags.FlagKeyringBackend)
args.chainID, _ = cmd.Flags().GetString(flags.FlagChainID)
args.minGasPrices, _ = cmd.Flags().GetString(flagMinGasPrices)
args.minGasPrices, _ = cmd.Flags().GetString(serverv2.FlagMinGasPrices)
args.nodeDirPrefix, _ = cmd.Flags().GetString(flagNodeDirPrefix)
args.nodeDaemonHome, _ = cmd.Flags().GetString(flagNodeDaemonHome)
args.startingIPAddress, _ = cmd.Flags().GetString(flagStartingIPAddress)
Expand Down Expand Up @@ -337,6 +336,9 @@ func initTestnetFiles[T transaction.Tx](
return err
}

serverCfg := serverv2.DefaultServerConfig()
serverCfg.MinGasPrices = args.minGasPrices

// Write server config
cometServer := cometbft.New[T](
&genericTxDecoder[T]{clientCtx.TxConfig},
Expand All @@ -345,7 +347,7 @@ func initTestnetFiles[T transaction.Tx](
)
storeServer := store.New[T](newApp)
grpcServer := grpc.New[T](grpc.OverwriteDefaultConfig(grpcConfig))
server := serverv2.NewServer(log.NewNopLogger(), cometServer, grpcServer, storeServer)
server := serverv2.NewServer(log.NewNopLogger(), serverCfg, cometServer, grpcServer, storeServer)
err = server.WriteConfig(filepath.Join(nodeDir, "config"))
if err != nil {
return err
Expand Down
1 change: 0 additions & 1 deletion tests/systemtests/staking_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ import (
)

func TestStakeUnstake(t *testing.T) {
t.Skip("The fee deduction is not yet implemented in v2")
// Scenario:
// delegate tokens to validator
// undelegate some tokens
Expand Down
4 changes: 4 additions & 0 deletions tools/confix/data/v2-app.toml
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,10 @@ max-recv-msg-size = 10485760
# The default value is math.MaxInt32.
max-send-msg-size = 2147483647

[server]
# minimum-gas-prices defines the price which a validator is willing to accept for processing a transaction. A transaction's fees must meet the minimum of any denomination specified in this config (e.g. 0.25token1;0.0001token2).
minimum-gas-prices = '0stake'

[store]
# The type of database for application and snapshots databases.
app-db-backend = 'goleveldb'
Expand Down
11 changes: 6 additions & 5 deletions tools/confix/migrations.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,11 +39,12 @@ type v2KeyChangesMap map[string][]string

// list all the keys which are need to be modified in v2
var v2KeyChanges = v2KeyChangesMap{
"min-retain-blocks": []string{"comet.min-retain-blocks"},
"index-events": []string{"comet.index-events"},
"halt-height": []string{"comet.halt-height"},
"halt-time": []string{"comet.halt-time"},
"app-db-backend": []string{"store.app-db-backend"},
"minimum-gas-prices": []string{"server.minimum-gas-prices"},
"min-retain-blocks": []string{"comet.min-retain-blocks"},
"index-events": []string{"comet.index-events"},
"halt-height": []string{"comet.halt-height"},
"halt-time": []string{"comet.halt-time"},
"app-db-backend": []string{"store.app-db-backend"},
"pruning-keep-recent": []string{
"store.options.ss-pruning-option.keep-recent",
"store.options.sc-pruning-option.keep-recent",
Expand Down
Loading

0 comments on commit 81a225e

Please sign in to comment.