Skip to content

Commit

Permalink
feat: change default commit timeout to 500ms (#380)
Browse files Browse the repository at this point in the history
  • Loading branch information
johnletey authored Jun 20, 2024
1 parent 40e9390 commit fad3a7d
Show file tree
Hide file tree
Showing 3 changed files with 193 additions and 1 deletion.
1 change: 1 addition & 0 deletions .changelog/unreleased/features/380-fast-blocks.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
- Update the default `commit_timeout` to `500ms` to improve block time. ([#380](https://github.com/noble-assets/noble/pull/380))
4 changes: 3 additions & 1 deletion cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,9 @@ func NewRootCmd(

customAppTemplate, customAppConfig := initAppConfig()

if err := server.InterceptConfigsPreRunHandler(cmd, customAppTemplate, customAppConfig); err != nil {
// We have copied InterceptConfigsPreRunHandler from the Cosmos SDK
// so that we can override the default commit timeout to 500 milliseconds.
if err := InterceptConfigsPreRunHandler(cmd, customAppTemplate, customAppConfig); err != nil {
return err
}

Expand Down
189 changes: 189 additions & 0 deletions cmd/util.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,189 @@
package cmd

import (
"fmt"
"github.com/cosmos/cosmos-sdk/client/flags"
"github.com/cosmos/cosmos-sdk/server"
"github.com/cosmos/cosmos-sdk/server/config"
"github.com/rs/zerolog"
"github.com/spf13/cobra"
"github.com/spf13/pflag"
"github.com/spf13/viper"
tmcfg "github.com/tendermint/tendermint/config"
"io"
"os"
"path"
"path/filepath"
"strings"
"time"
)

func bindFlags(basename string, cmd *cobra.Command, v *viper.Viper) (err error) {
defer func() {
recover()
}()

cmd.Flags().VisitAll(func(f *pflag.Flag) {
// Environment variables can't have dashes in them, so bind them to their equivalent
// keys with underscores, e.g. --favorite-color to STING_FAVORITE_COLOR
err = v.BindEnv(f.Name, fmt.Sprintf("%s_%s", basename, strings.ToUpper(strings.ReplaceAll(f.Name, "-", "_"))))
if err != nil {
panic(err)
}

err = v.BindPFlag(f.Name, f)
if err != nil {
panic(err)
}

// Apply the viper config value to the flag when the flag is not set and viper has a value
if !f.Changed && v.IsSet(f.Name) {
val := v.Get(f.Name)
err = cmd.Flags().Set(f.Name, fmt.Sprintf("%v", val))
if err != nil {
panic(err)
}
}
})

return
}

// InterceptConfigsPreRunHandler performs a pre-run function for the root daemon
// application command. It will create a Viper literal and a default server
// Context. The server Tendermint configuration will either be read and parsed
// or created and saved to disk, where the server Context is updated to reflect
// the Tendermint configuration. It takes custom app config template and config
// settings to create a custom Tendermint configuration. If the custom template
// is empty, it uses default-template provided by the server. The Viper literal
// is used to read and parse the application configuration. Command handlers can
// fetch the server Context to get the Tendermint configuration or to get access
// to Viper.
func InterceptConfigsPreRunHandler(cmd *cobra.Command, customAppConfigTemplate string, customAppConfig interface{}) error {
serverCtx := server.NewDefaultContext()

// Get the executable name and configure the viper instance so that environmental
// variables are checked based off that name. The underscore character is used
// as a separator
executableName, err := os.Executable()
if err != nil {
return err
}

basename := path.Base(executableName)

// Configure the viper instance
serverCtx.Viper.BindPFlags(cmd.Flags())
serverCtx.Viper.BindPFlags(cmd.PersistentFlags())
serverCtx.Viper.SetEnvPrefix(basename)
serverCtx.Viper.SetEnvKeyReplacer(strings.NewReplacer(".", "_", "-", "_"))
serverCtx.Viper.AutomaticEnv()

// intercept configuration files, using both Viper instances separately
config, err := interceptConfigs(serverCtx.Viper, customAppConfigTemplate, customAppConfig)
if err != nil {
return err
}

// return value is a tendermint configuration object
serverCtx.Config = config
if err = bindFlags(basename, cmd, serverCtx.Viper); err != nil {
return err
}

var logWriter io.Writer
if strings.ToLower(serverCtx.Viper.GetString(flags.FlagLogFormat)) == tmcfg.LogFormatPlain {
logWriter = zerolog.ConsoleWriter{Out: os.Stderr}
} else {
logWriter = os.Stderr
}

logLvlStr := serverCtx.Viper.GetString(flags.FlagLogLevel)
logLvl, err := zerolog.ParseLevel(logLvlStr)
if err != nil {
return fmt.Errorf("failed to parse log level (%s): %w", logLvlStr, err)
}

serverCtx.Logger = server.ZeroLogWrapper{zerolog.New(logWriter).Level(logLvl).With().Timestamp().Logger()}

return server.SetCmdServerContext(cmd, serverCtx)
}

// interceptConfigs parses and updates a Tendermint configuration file or
// creates a new one and saves it. It also parses and saves the application
// configuration file. The Tendermint configuration file is parsed given a root
// Viper object, whereas the application is parsed with the private package-aware
// viperCfg object.
func interceptConfigs(rootViper *viper.Viper, customAppTemplate string, customConfig interface{}) (*tmcfg.Config, error) {
rootDir := rootViper.GetString(flags.FlagHome)
configPath := filepath.Join(rootDir, "config")
tmCfgFile := filepath.Join(configPath, "config.toml")

conf := tmcfg.DefaultConfig()

switch _, err := os.Stat(tmCfgFile); {
case os.IsNotExist(err):
tmcfg.EnsureRoot(rootDir)

if err = conf.ValidateBasic(); err != nil {
return nil, fmt.Errorf("error in config file: %v", err)
}

conf.RPC.PprofListenAddress = "localhost:6060"
conf.P2P.RecvRate = 5120000
conf.P2P.SendRate = 5120000
conf.Consensus.TimeoutCommit = 500 * time.Millisecond // NOBLE
tmcfg.WriteConfigFile(tmCfgFile, conf)

case err != nil:
return nil, err

default:
rootViper.SetConfigType("toml")
rootViper.SetConfigName("config")
rootViper.AddConfigPath(configPath)

if err := rootViper.ReadInConfig(); err != nil {
return nil, fmt.Errorf("failed to read in %s: %w", tmCfgFile, err)
}
}

// Read into the configuration whatever data the viper instance has for it.
// This may come from the configuration file above but also any of the other
// sources viper uses.
if err := rootViper.Unmarshal(conf); err != nil {
return nil, err
}

conf.SetRoot(rootDir)

appCfgFilePath := filepath.Join(configPath, "app.toml")
if _, err := os.Stat(appCfgFilePath); os.IsNotExist(err) {
if customAppTemplate != "" {
config.SetConfigTemplate(customAppTemplate)

if err = rootViper.Unmarshal(&customConfig); err != nil {
return nil, fmt.Errorf("failed to parse %s: %w", appCfgFilePath, err)
}

config.WriteConfigFile(appCfgFilePath, customConfig)
} else {
appConf, err := config.ParseConfig(rootViper)
if err != nil {
return nil, fmt.Errorf("failed to parse %s: %w", appCfgFilePath, err)
}

config.WriteConfigFile(appCfgFilePath, appConf)
}
}

rootViper.SetConfigType("toml")
rootViper.SetConfigName("app")
rootViper.AddConfigPath(configPath)

if err := rootViper.MergeInConfig(); err != nil {
return nil, fmt.Errorf("failed to merge configuration: %w", err)
}

return conf, nil
}

0 comments on commit fad3a7d

Please sign in to comment.