github.com/KYVENetwork/cometbft/v38@v38.0.3/config/config.go (about)

     1  package config
     2  
     3  import (
     4  	"encoding/hex"
     5  	"errors"
     6  	"fmt"
     7  	"net/http"
     8  	"os"
     9  	"path/filepath"
    10  	"regexp"
    11  	"time"
    12  
    13  	"github.com/KYVENetwork/cometbft/v38/version"
    14  )
    15  
    16  const (
    17  	// FuzzModeDrop is a mode in which we randomly drop reads/writes, connections or sleep
    18  	FuzzModeDrop = iota
    19  	// FuzzModeDelay is a mode in which we randomly sleep
    20  	FuzzModeDelay
    21  
    22  	// LogFormatPlain is a format for colored text
    23  	LogFormatPlain = "plain"
    24  	// LogFormatJSON is a format for json output
    25  	LogFormatJSON = "json"
    26  
    27  	// DefaultLogLevel defines a default log level as INFO.
    28  	DefaultLogLevel = "info"
    29  
    30  	DefaultTendermintDir = ".cometbft"
    31  	DefaultConfigDir     = "config"
    32  	DefaultDataDir       = "data"
    33  
    34  	DefaultConfigFileName  = "config.toml"
    35  	DefaultGenesisJSONName = "genesis.json"
    36  
    37  	DefaultPrivValKeyName   = "priv_validator_key.json"
    38  	DefaultPrivValStateName = "priv_validator_state.json"
    39  
    40  	DefaultNodeKeyName  = "node_key.json"
    41  	DefaultAddrBookName = "addrbook.json"
    42  
    43  	MempoolTypeFlood = "flood"
    44  	MempoolTypeNop   = "nop"
    45  )
    46  
    47  // NOTE: Most of the structs & relevant comments + the
    48  // default configuration options were used to manually
    49  // generate the config.toml. Please reflect any changes
    50  // made here in the defaultConfigTemplate constant in
    51  // config/toml.go
    52  // NOTE: libs/cli must know to look in the config dir!
    53  var (
    54  	defaultConfigFilePath   = filepath.Join(DefaultConfigDir, DefaultConfigFileName)
    55  	defaultGenesisJSONPath  = filepath.Join(DefaultConfigDir, DefaultGenesisJSONName)
    56  	defaultPrivValKeyPath   = filepath.Join(DefaultConfigDir, DefaultPrivValKeyName)
    57  	defaultPrivValStatePath = filepath.Join(DefaultDataDir, DefaultPrivValStateName)
    58  
    59  	defaultNodeKeyPath  = filepath.Join(DefaultConfigDir, DefaultNodeKeyName)
    60  	defaultAddrBookPath = filepath.Join(DefaultConfigDir, DefaultAddrBookName)
    61  
    62  	minSubscriptionBufferSize     = 100
    63  	defaultSubscriptionBufferSize = 200
    64  
    65  	// taken from https://semver.org/
    66  	semverRegexp = regexp.MustCompile(`^(?P<major>0|[1-9]\d*)\.(?P<minor>0|[1-9]\d*)\.(?P<patch>0|[1-9]\d*)(?:-(?P<prerelease>(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+(?P<buildmetadata>[0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$`)
    67  )
    68  
    69  // Config defines the top level configuration for a CometBFT node
    70  type Config struct {
    71  	// Top level options use an anonymous struct
    72  	BaseConfig `mapstructure:",squash"`
    73  
    74  	// Options for services
    75  	RPC             *RPCConfig             `mapstructure:"rpc"`
    76  	P2P             *P2PConfig             `mapstructure:"p2p"`
    77  	Mempool         *MempoolConfig         `mapstructure:"mempool"`
    78  	StateSync       *StateSyncConfig       `mapstructure:"statesync"`
    79  	BlockSync       *BlockSyncConfig       `mapstructure:"blocksync"`
    80  	Consensus       *ConsensusConfig       `mapstructure:"consensus"`
    81  	Storage         *StorageConfig         `mapstructure:"storage"`
    82  	TxIndex         *TxIndexConfig         `mapstructure:"tx_index"`
    83  	Instrumentation *InstrumentationConfig `mapstructure:"instrumentation"`
    84  }
    85  
    86  // DefaultConfig returns a default configuration for a CometBFT node
    87  func DefaultConfig() *Config {
    88  	return &Config{
    89  		BaseConfig:      DefaultBaseConfig(),
    90  		RPC:             DefaultRPCConfig(),
    91  		P2P:             DefaultP2PConfig(),
    92  		Mempool:         DefaultMempoolConfig(),
    93  		StateSync:       DefaultStateSyncConfig(),
    94  		BlockSync:       DefaultBlockSyncConfig(),
    95  		Consensus:       DefaultConsensusConfig(),
    96  		Storage:         DefaultStorageConfig(),
    97  		TxIndex:         DefaultTxIndexConfig(),
    98  		Instrumentation: DefaultInstrumentationConfig(),
    99  	}
   100  }
   101  
   102  // TestConfig returns a configuration that can be used for testing
   103  func TestConfig() *Config {
   104  	return &Config{
   105  		BaseConfig:      TestBaseConfig(),
   106  		RPC:             TestRPCConfig(),
   107  		P2P:             TestP2PConfig(),
   108  		Mempool:         TestMempoolConfig(),
   109  		StateSync:       TestStateSyncConfig(),
   110  		BlockSync:       TestBlockSyncConfig(),
   111  		Consensus:       TestConsensusConfig(),
   112  		Storage:         TestStorageConfig(),
   113  		TxIndex:         TestTxIndexConfig(),
   114  		Instrumentation: TestInstrumentationConfig(),
   115  	}
   116  }
   117  
   118  // SetRoot sets the RootDir for all Config structs
   119  func (cfg *Config) SetRoot(root string) *Config {
   120  	cfg.BaseConfig.RootDir = root
   121  	cfg.RPC.RootDir = root
   122  	cfg.P2P.RootDir = root
   123  	cfg.Mempool.RootDir = root
   124  	cfg.Consensus.RootDir = root
   125  	return cfg
   126  }
   127  
   128  // ValidateBasic performs basic validation (checking param bounds, etc.) and
   129  // returns an error if any check fails.
   130  func (cfg *Config) ValidateBasic() error {
   131  	if err := cfg.BaseConfig.ValidateBasic(); err != nil {
   132  		return err
   133  	}
   134  	if err := cfg.RPC.ValidateBasic(); err != nil {
   135  		return fmt.Errorf("error in [rpc] section: %w", err)
   136  	}
   137  	if err := cfg.P2P.ValidateBasic(); err != nil {
   138  		return fmt.Errorf("error in [p2p] section: %w", err)
   139  	}
   140  	if err := cfg.Mempool.ValidateBasic(); err != nil {
   141  		return fmt.Errorf("error in [mempool] section: %w", err)
   142  	}
   143  	if err := cfg.StateSync.ValidateBasic(); err != nil {
   144  		return fmt.Errorf("error in [statesync] section: %w", err)
   145  	}
   146  	if err := cfg.BlockSync.ValidateBasic(); err != nil {
   147  		return fmt.Errorf("error in [blocksync] section: %w", err)
   148  	}
   149  	if err := cfg.Consensus.ValidateBasic(); err != nil {
   150  		return fmt.Errorf("error in [consensus] section: %w", err)
   151  	}
   152  	if err := cfg.Instrumentation.ValidateBasic(); err != nil {
   153  		return fmt.Errorf("error in [instrumentation] section: %w", err)
   154  	}
   155  	if !cfg.Consensus.CreateEmptyBlocks && cfg.Mempool.Type == MempoolTypeNop {
   156  		return fmt.Errorf("`nop` mempool does not support create_empty_blocks = false")
   157  	}
   158  	return nil
   159  }
   160  
   161  // CheckDeprecated returns any deprecation warnings. These are printed to the operator on startup
   162  func (cfg *Config) CheckDeprecated() []string {
   163  	var warnings []string
   164  	return warnings
   165  }
   166  
   167  //-----------------------------------------------------------------------------
   168  // BaseConfig
   169  
   170  // BaseConfig defines the base configuration for a CometBFT node
   171  type BaseConfig struct { //nolint: maligned
   172  
   173  	// The version of the CometBFT binary that created
   174  	// or last modified the config file
   175  	Version string `mapstructure:"version"`
   176  
   177  	// The root directory for all data.
   178  	// This should be set in viper so it can unmarshal into this struct
   179  	RootDir string `mapstructure:"home"`
   180  
   181  	// TCP or UNIX socket address of the ABCI application,
   182  	// or the name of an ABCI application compiled in with the CometBFT binary
   183  	ProxyApp string `mapstructure:"proxy_app"`
   184  
   185  	// A custom human readable name for this node
   186  	Moniker string `mapstructure:"moniker"`
   187  
   188  	// Database backend: goleveldb | cleveldb | boltdb | rocksdb
   189  	// * goleveldb (github.com/syndtr/goleveldb - most popular implementation)
   190  	//   - pure go
   191  	//   - stable
   192  	// * cleveldb (uses levigo wrapper)
   193  	//   - fast
   194  	//   - requires gcc
   195  	//   - use cleveldb build tag (go build -tags cleveldb)
   196  	// * boltdb (uses etcd's fork of bolt - github.com/etcd-io/bbolt)
   197  	//   - EXPERIMENTAL
   198  	//   - may be faster is some use-cases (random reads - indexer)
   199  	//   - use boltdb build tag (go build -tags boltdb)
   200  	// * rocksdb (uses github.com/tecbot/gorocksdb)
   201  	//   - EXPERIMENTAL
   202  	//   - requires gcc
   203  	//   - use rocksdb build tag (go build -tags rocksdb)
   204  	// * badgerdb (uses github.com/dgraph-io/badger)
   205  	//   - EXPERIMENTAL
   206  	//   - use badgerdb build tag (go build -tags badgerdb)
   207  	DBBackend string `mapstructure:"db_backend"`
   208  
   209  	// Database directory
   210  	DBPath string `mapstructure:"db_dir"`
   211  
   212  	// Output level for logging
   213  	LogLevel string `mapstructure:"log_level"`
   214  
   215  	// Output format: 'plain' (colored text) or 'json'
   216  	LogFormat string `mapstructure:"log_format"`
   217  
   218  	// Path to the JSON file containing the initial validator set and other meta data
   219  	Genesis string `mapstructure:"genesis_file"`
   220  
   221  	// Path to the JSON file containing the private key to use as a validator in the consensus protocol
   222  	PrivValidatorKey string `mapstructure:"priv_validator_key_file"`
   223  
   224  	// Path to the JSON file containing the last sign state of a validator
   225  	PrivValidatorState string `mapstructure:"priv_validator_state_file"`
   226  
   227  	// TCP or UNIX socket address for CometBFT to listen on for
   228  	// connections from an external PrivValidator process
   229  	PrivValidatorListenAddr string `mapstructure:"priv_validator_laddr"`
   230  
   231  	// A JSON file containing the private key to use for p2p authenticated encryption
   232  	NodeKey string `mapstructure:"node_key_file"`
   233  
   234  	// Mechanism to connect to the ABCI application: socket | grpc
   235  	ABCI string `mapstructure:"abci"`
   236  
   237  	// If true, query the ABCI app on connecting to a new peer
   238  	// so the app can decide if we should keep the connection or not
   239  	FilterPeers bool `mapstructure:"filter_peers"` // false
   240  }
   241  
   242  // DefaultBaseConfig returns a default base configuration for a CometBFT node
   243  func DefaultBaseConfig() BaseConfig {
   244  	return BaseConfig{
   245  		Version:            version.TMCoreSemVer,
   246  		Genesis:            defaultGenesisJSONPath,
   247  		PrivValidatorKey:   defaultPrivValKeyPath,
   248  		PrivValidatorState: defaultPrivValStatePath,
   249  		NodeKey:            defaultNodeKeyPath,
   250  		Moniker:            defaultMoniker,
   251  		ProxyApp:           "tcp://127.0.0.1:26658",
   252  		ABCI:               "socket",
   253  		LogLevel:           DefaultLogLevel,
   254  		LogFormat:          LogFormatPlain,
   255  		FilterPeers:        false,
   256  		DBBackend:          "goleveldb",
   257  		DBPath:             DefaultDataDir,
   258  	}
   259  }
   260  
   261  // TestBaseConfig returns a base configuration for testing a CometBFT node
   262  func TestBaseConfig() BaseConfig {
   263  	cfg := DefaultBaseConfig()
   264  	cfg.ProxyApp = "kvstore"
   265  	cfg.DBBackend = "memdb"
   266  	return cfg
   267  }
   268  
   269  // GenesisFile returns the full path to the genesis.json file
   270  func (cfg BaseConfig) GenesisFile() string {
   271  	return rootify(cfg.Genesis, cfg.RootDir)
   272  }
   273  
   274  // PrivValidatorKeyFile returns the full path to the priv_validator_key.json file
   275  func (cfg BaseConfig) PrivValidatorKeyFile() string {
   276  	return rootify(cfg.PrivValidatorKey, cfg.RootDir)
   277  }
   278  
   279  // PrivValidatorFile returns the full path to the priv_validator_state.json file
   280  func (cfg BaseConfig) PrivValidatorStateFile() string {
   281  	return rootify(cfg.PrivValidatorState, cfg.RootDir)
   282  }
   283  
   284  // NodeKeyFile returns the full path to the node_key.json file
   285  func (cfg BaseConfig) NodeKeyFile() string {
   286  	return rootify(cfg.NodeKey, cfg.RootDir)
   287  }
   288  
   289  // DBDir returns the full path to the database directory
   290  func (cfg BaseConfig) DBDir() string {
   291  	return rootify(cfg.DBPath, cfg.RootDir)
   292  }
   293  
   294  // ValidateBasic performs basic validation (checking param bounds, etc.) and
   295  // returns an error if any check fails.
   296  func (cfg BaseConfig) ValidateBasic() error {
   297  	// version on old config files aren't set so we can't expect it
   298  	// always to exist
   299  	if cfg.Version != "" && !semverRegexp.MatchString(cfg.Version) {
   300  		return fmt.Errorf("invalid version string: %s", cfg.Version)
   301  	}
   302  
   303  	switch cfg.LogFormat {
   304  	case LogFormatPlain, LogFormatJSON:
   305  	default:
   306  		return errors.New("unknown log_format (must be 'plain' or 'json')")
   307  	}
   308  	return nil
   309  }
   310  
   311  //-----------------------------------------------------------------------------
   312  // RPCConfig
   313  
   314  // RPCConfig defines the configuration options for the CometBFT RPC server
   315  type RPCConfig struct {
   316  	RootDir string `mapstructure:"home"`
   317  
   318  	// TCP or UNIX socket address for the RPC server to listen on
   319  	ListenAddress string `mapstructure:"laddr"`
   320  
   321  	// A list of origins a cross-domain request can be executed from.
   322  	// If the special '*' value is present in the list, all origins will be allowed.
   323  	// An origin may contain a wildcard (*) to replace 0 or more characters (i.e.: http://*.domain.com).
   324  	// Only one wildcard can be used per origin.
   325  	CORSAllowedOrigins []string `mapstructure:"cors_allowed_origins"`
   326  
   327  	// A list of methods the client is allowed to use with cross-domain requests.
   328  	CORSAllowedMethods []string `mapstructure:"cors_allowed_methods"`
   329  
   330  	// A list of non simple headers the client is allowed to use with cross-domain requests.
   331  	CORSAllowedHeaders []string `mapstructure:"cors_allowed_headers"`
   332  
   333  	// TCP or UNIX socket address for the gRPC server to listen on
   334  	// NOTE: This server only supports /broadcast_tx_commit
   335  	GRPCListenAddress string `mapstructure:"grpc_laddr"`
   336  
   337  	// Maximum number of simultaneous connections.
   338  	// Does not include RPC (HTTP&WebSocket) connections. See max_open_connections
   339  	// If you want to accept a larger number than the default, make sure
   340  	// you increase your OS limits.
   341  	// 0 - unlimited.
   342  	GRPCMaxOpenConnections int `mapstructure:"grpc_max_open_connections"`
   343  
   344  	// Activate unsafe RPC commands like /dial_persistent_peers and /unsafe_flush_mempool
   345  	Unsafe bool `mapstructure:"unsafe"`
   346  
   347  	// Maximum number of simultaneous connections (including WebSocket).
   348  	// Does not include gRPC connections. See grpc_max_open_connections
   349  	// If you want to accept a larger number than the default, make sure
   350  	// you increase your OS limits.
   351  	// 0 - unlimited.
   352  	// Should be < {ulimit -Sn} - {MaxNumInboundPeers} - {MaxNumOutboundPeers} - {N of wal, db and other open files}
   353  	// 1024 - 40 - 10 - 50 = 924 = ~900
   354  	MaxOpenConnections int `mapstructure:"max_open_connections"`
   355  
   356  	// Maximum number of unique clientIDs that can /subscribe
   357  	// If you're using /broadcast_tx_commit, set to the estimated maximum number
   358  	// of broadcast_tx_commit calls per block.
   359  	MaxSubscriptionClients int `mapstructure:"max_subscription_clients"`
   360  
   361  	// Maximum number of unique queries a given client can /subscribe to
   362  	// If you're using GRPC (or Local RPC client) and /broadcast_tx_commit, set
   363  	// to the estimated maximum number of broadcast_tx_commit calls per block.
   364  	MaxSubscriptionsPerClient int `mapstructure:"max_subscriptions_per_client"`
   365  
   366  	// The number of events that can be buffered per subscription before
   367  	// returning `ErrOutOfCapacity`.
   368  	SubscriptionBufferSize int `mapstructure:"experimental_subscription_buffer_size"`
   369  
   370  	// The maximum number of responses that can be buffered per WebSocket
   371  	// client. If clients cannot read from the WebSocket endpoint fast enough,
   372  	// they will be disconnected, so increasing this parameter may reduce the
   373  	// chances of them being disconnected (but will cause the node to use more
   374  	// memory).
   375  	//
   376  	// Must be at least the same as `SubscriptionBufferSize`, otherwise
   377  	// connections may be dropped unnecessarily.
   378  	WebSocketWriteBufferSize int `mapstructure:"experimental_websocket_write_buffer_size"`
   379  
   380  	// If a WebSocket client cannot read fast enough, at present we may
   381  	// silently drop events instead of generating an error or disconnecting the
   382  	// client.
   383  	//
   384  	// Enabling this parameter will cause the WebSocket connection to be closed
   385  	// instead if it cannot read fast enough, allowing for greater
   386  	// predictability in subscription behavior.
   387  	CloseOnSlowClient bool `mapstructure:"experimental_close_on_slow_client"`
   388  
   389  	// How long to wait for a tx to be committed during /broadcast_tx_commit
   390  	// WARNING: Using a value larger than 10s will result in increasing the
   391  	// global HTTP write timeout, which applies to all connections and endpoints.
   392  	// See https://github.com/tendermint/tendermint/issues/3435
   393  	TimeoutBroadcastTxCommit time.Duration `mapstructure:"timeout_broadcast_tx_commit"`
   394  
   395  	// Maximum size of request body, in bytes
   396  	MaxBodyBytes int64 `mapstructure:"max_body_bytes"`
   397  
   398  	// Maximum size of request header, in bytes
   399  	MaxHeaderBytes int `mapstructure:"max_header_bytes"`
   400  
   401  	// The path to a file containing certificate that is used to create the HTTPS server.
   402  	// Might be either absolute path or path related to CometBFT's config directory.
   403  	//
   404  	// If the certificate is signed by a certificate authority,
   405  	// the certFile should be the concatenation of the server's certificate, any intermediates,
   406  	// and the CA's certificate.
   407  	//
   408  	// NOTE: both tls_cert_file and tls_key_file must be present for CometBFT to create HTTPS server.
   409  	// Otherwise, HTTP server is run.
   410  	TLSCertFile string `mapstructure:"tls_cert_file"`
   411  
   412  	// The path to a file containing matching private key that is used to create the HTTPS server.
   413  	// Might be either absolute path or path related to CometBFT's config directory.
   414  	//
   415  	// NOTE: both tls_cert_file and tls_key_file must be present for CometBFT to create HTTPS server.
   416  	// Otherwise, HTTP server is run.
   417  	TLSKeyFile string `mapstructure:"tls_key_file"`
   418  
   419  	// pprof listen address (https://golang.org/pkg/net/http/pprof)
   420  	// FIXME: This should be moved under the instrumentation section
   421  	PprofListenAddress string `mapstructure:"pprof_laddr"`
   422  }
   423  
   424  // DefaultRPCConfig returns a default configuration for the RPC server
   425  func DefaultRPCConfig() *RPCConfig {
   426  	return &RPCConfig{
   427  		ListenAddress:          "tcp://127.0.0.1:26657",
   428  		CORSAllowedOrigins:     []string{},
   429  		CORSAllowedMethods:     []string{http.MethodHead, http.MethodGet, http.MethodPost},
   430  		CORSAllowedHeaders:     []string{"Origin", "Accept", "Content-Type", "X-Requested-With", "X-Server-Time"},
   431  		GRPCListenAddress:      "",
   432  		GRPCMaxOpenConnections: 900,
   433  
   434  		Unsafe:             false,
   435  		MaxOpenConnections: 900,
   436  
   437  		MaxSubscriptionClients:    100,
   438  		MaxSubscriptionsPerClient: 5,
   439  		SubscriptionBufferSize:    defaultSubscriptionBufferSize,
   440  		TimeoutBroadcastTxCommit:  10 * time.Second,
   441  		WebSocketWriteBufferSize:  defaultSubscriptionBufferSize,
   442  
   443  		MaxBodyBytes:   int64(1000000), // 1MB
   444  		MaxHeaderBytes: 1 << 20,        // same as the net/http default
   445  
   446  		TLSCertFile: "",
   447  		TLSKeyFile:  "",
   448  	}
   449  }
   450  
   451  // TestRPCConfig returns a configuration for testing the RPC server
   452  func TestRPCConfig() *RPCConfig {
   453  	cfg := DefaultRPCConfig()
   454  	cfg.ListenAddress = "tcp://127.0.0.1:36657"
   455  	cfg.GRPCListenAddress = "tcp://127.0.0.1:36658"
   456  	cfg.Unsafe = true
   457  	return cfg
   458  }
   459  
   460  // ValidateBasic performs basic validation (checking param bounds, etc.) and
   461  // returns an error if any check fails.
   462  func (cfg *RPCConfig) ValidateBasic() error {
   463  	if cfg.GRPCMaxOpenConnections < 0 {
   464  		return errors.New("grpc_max_open_connections can't be negative")
   465  	}
   466  	if cfg.MaxOpenConnections < 0 {
   467  		return errors.New("max_open_connections can't be negative")
   468  	}
   469  	if cfg.MaxSubscriptionClients < 0 {
   470  		return errors.New("max_subscription_clients can't be negative")
   471  	}
   472  	if cfg.MaxSubscriptionsPerClient < 0 {
   473  		return errors.New("max_subscriptions_per_client can't be negative")
   474  	}
   475  	if cfg.SubscriptionBufferSize < minSubscriptionBufferSize {
   476  		return fmt.Errorf(
   477  			"experimental_subscription_buffer_size must be >= %d",
   478  			minSubscriptionBufferSize,
   479  		)
   480  	}
   481  	if cfg.WebSocketWriteBufferSize < cfg.SubscriptionBufferSize {
   482  		return fmt.Errorf(
   483  			"experimental_websocket_write_buffer_size must be >= experimental_subscription_buffer_size (%d)",
   484  			cfg.SubscriptionBufferSize,
   485  		)
   486  	}
   487  	if cfg.TimeoutBroadcastTxCommit < 0 {
   488  		return errors.New("timeout_broadcast_tx_commit can't be negative")
   489  	}
   490  	if cfg.MaxBodyBytes < 0 {
   491  		return errors.New("max_body_bytes can't be negative")
   492  	}
   493  	if cfg.MaxHeaderBytes < 0 {
   494  		return errors.New("max_header_bytes can't be negative")
   495  	}
   496  	return nil
   497  }
   498  
   499  // IsCorsEnabled returns true if cross-origin resource sharing is enabled.
   500  func (cfg *RPCConfig) IsCorsEnabled() bool {
   501  	return len(cfg.CORSAllowedOrigins) != 0
   502  }
   503  
   504  func (cfg *RPCConfig) IsPprofEnabled() bool {
   505  	return len(cfg.PprofListenAddress) != 0
   506  }
   507  
   508  func (cfg RPCConfig) KeyFile() string {
   509  	path := cfg.TLSKeyFile
   510  	if filepath.IsAbs(path) {
   511  		return path
   512  	}
   513  	return rootify(filepath.Join(DefaultConfigDir, path), cfg.RootDir)
   514  }
   515  
   516  func (cfg RPCConfig) CertFile() string {
   517  	path := cfg.TLSCertFile
   518  	if filepath.IsAbs(path) {
   519  		return path
   520  	}
   521  	return rootify(filepath.Join(DefaultConfigDir, path), cfg.RootDir)
   522  }
   523  
   524  func (cfg RPCConfig) IsTLSEnabled() bool {
   525  	return cfg.TLSCertFile != "" && cfg.TLSKeyFile != ""
   526  }
   527  
   528  //-----------------------------------------------------------------------------
   529  // P2PConfig
   530  
   531  // P2PConfig defines the configuration options for the CometBFT peer-to-peer networking layer
   532  type P2PConfig struct { //nolint: maligned
   533  	RootDir string `mapstructure:"home"`
   534  
   535  	// Address to listen for incoming connections
   536  	ListenAddress string `mapstructure:"laddr"`
   537  
   538  	// Address to advertise to peers for them to dial
   539  	ExternalAddress string `mapstructure:"external_address"`
   540  
   541  	// Comma separated list of seed nodes to connect to
   542  	// We only use these if we can’t connect to peers in the addrbook
   543  	Seeds string `mapstructure:"seeds"`
   544  
   545  	// Comma separated list of nodes to keep persistent connections to
   546  	PersistentPeers string `mapstructure:"persistent_peers"`
   547  
   548  	// Path to address book
   549  	AddrBook string `mapstructure:"addr_book_file"`
   550  
   551  	// Set true for strict address routability rules
   552  	// Set false for private or local networks
   553  	AddrBookStrict bool `mapstructure:"addr_book_strict"`
   554  
   555  	// Maximum number of inbound peers
   556  	MaxNumInboundPeers int `mapstructure:"max_num_inbound_peers"`
   557  
   558  	// Maximum number of outbound peers to connect to, excluding persistent peers
   559  	MaxNumOutboundPeers int `mapstructure:"max_num_outbound_peers"`
   560  
   561  	// List of node IDs, to which a connection will be (re)established ignoring any existing limits
   562  	UnconditionalPeerIDs string `mapstructure:"unconditional_peer_ids"`
   563  
   564  	// Maximum pause when redialing a persistent peer (if zero, exponential backoff is used)
   565  	PersistentPeersMaxDialPeriod time.Duration `mapstructure:"persistent_peers_max_dial_period"`
   566  
   567  	// Time to wait before flushing messages out on the connection
   568  	FlushThrottleTimeout time.Duration `mapstructure:"flush_throttle_timeout"`
   569  
   570  	// Maximum size of a message packet payload, in bytes
   571  	MaxPacketMsgPayloadSize int `mapstructure:"max_packet_msg_payload_size"`
   572  
   573  	// Rate at which packets can be sent, in bytes/second
   574  	SendRate int64 `mapstructure:"send_rate"`
   575  
   576  	// Rate at which packets can be received, in bytes/second
   577  	RecvRate int64 `mapstructure:"recv_rate"`
   578  
   579  	// Set true to enable the peer-exchange reactor
   580  	PexReactor bool `mapstructure:"pex"`
   581  
   582  	// Seed mode, in which node constantly crawls the network and looks for
   583  	// peers. If another node asks it for addresses, it responds and disconnects.
   584  	//
   585  	// Does not work if the peer-exchange reactor is disabled.
   586  	SeedMode bool `mapstructure:"seed_mode"`
   587  
   588  	// Comma separated list of peer IDs to keep private (will not be gossiped to
   589  	// other peers)
   590  	PrivatePeerIDs string `mapstructure:"private_peer_ids"`
   591  
   592  	// Toggle to disable guard against peers connecting from the same ip.
   593  	AllowDuplicateIP bool `mapstructure:"allow_duplicate_ip"`
   594  
   595  	// Peer connection configuration.
   596  	HandshakeTimeout time.Duration `mapstructure:"handshake_timeout"`
   597  	DialTimeout      time.Duration `mapstructure:"dial_timeout"`
   598  
   599  	// Testing params.
   600  	// Force dial to fail
   601  	TestDialFail bool `mapstructure:"test_dial_fail"`
   602  	// Fuzz connection
   603  	TestFuzz       bool            `mapstructure:"test_fuzz"`
   604  	TestFuzzConfig *FuzzConnConfig `mapstructure:"test_fuzz_config"`
   605  }
   606  
   607  // DefaultP2PConfig returns a default configuration for the peer-to-peer layer
   608  func DefaultP2PConfig() *P2PConfig {
   609  	return &P2PConfig{
   610  		ListenAddress:                "tcp://0.0.0.0:26656",
   611  		ExternalAddress:              "",
   612  		AddrBook:                     defaultAddrBookPath,
   613  		AddrBookStrict:               true,
   614  		MaxNumInboundPeers:           40,
   615  		MaxNumOutboundPeers:          10,
   616  		PersistentPeersMaxDialPeriod: 0 * time.Second,
   617  		FlushThrottleTimeout:         100 * time.Millisecond,
   618  		MaxPacketMsgPayloadSize:      1024,    // 1 kB
   619  		SendRate:                     5120000, // 5 mB/s
   620  		RecvRate:                     5120000, // 5 mB/s
   621  		PexReactor:                   true,
   622  		SeedMode:                     false,
   623  		AllowDuplicateIP:             false,
   624  		HandshakeTimeout:             20 * time.Second,
   625  		DialTimeout:                  3 * time.Second,
   626  		TestDialFail:                 false,
   627  		TestFuzz:                     false,
   628  		TestFuzzConfig:               DefaultFuzzConnConfig(),
   629  	}
   630  }
   631  
   632  // TestP2PConfig returns a configuration for testing the peer-to-peer layer
   633  func TestP2PConfig() *P2PConfig {
   634  	cfg := DefaultP2PConfig()
   635  	cfg.ListenAddress = "tcp://127.0.0.1:36656"
   636  	cfg.FlushThrottleTimeout = 10 * time.Millisecond
   637  	cfg.AllowDuplicateIP = true
   638  	return cfg
   639  }
   640  
   641  // AddrBookFile returns the full path to the address book
   642  func (cfg *P2PConfig) AddrBookFile() string {
   643  	return rootify(cfg.AddrBook, cfg.RootDir)
   644  }
   645  
   646  // ValidateBasic performs basic validation (checking param bounds, etc.) and
   647  // returns an error if any check fails.
   648  func (cfg *P2PConfig) ValidateBasic() error {
   649  	if cfg.MaxNumInboundPeers < 0 {
   650  		return errors.New("max_num_inbound_peers can't be negative")
   651  	}
   652  	if cfg.MaxNumOutboundPeers < 0 {
   653  		return errors.New("max_num_outbound_peers can't be negative")
   654  	}
   655  	if cfg.FlushThrottleTimeout < 0 {
   656  		return errors.New("flush_throttle_timeout can't be negative")
   657  	}
   658  	if cfg.PersistentPeersMaxDialPeriod < 0 {
   659  		return errors.New("persistent_peers_max_dial_period can't be negative")
   660  	}
   661  	if cfg.MaxPacketMsgPayloadSize < 0 {
   662  		return errors.New("max_packet_msg_payload_size can't be negative")
   663  	}
   664  	if cfg.SendRate < 0 {
   665  		return errors.New("send_rate can't be negative")
   666  	}
   667  	if cfg.RecvRate < 0 {
   668  		return errors.New("recv_rate can't be negative")
   669  	}
   670  	return nil
   671  }
   672  
   673  // FuzzConnConfig is a FuzzedConnection configuration.
   674  type FuzzConnConfig struct {
   675  	Mode         int
   676  	MaxDelay     time.Duration
   677  	ProbDropRW   float64
   678  	ProbDropConn float64
   679  	ProbSleep    float64
   680  }
   681  
   682  // DefaultFuzzConnConfig returns the default config.
   683  func DefaultFuzzConnConfig() *FuzzConnConfig {
   684  	return &FuzzConnConfig{
   685  		Mode:         FuzzModeDrop,
   686  		MaxDelay:     3 * time.Second,
   687  		ProbDropRW:   0.2,
   688  		ProbDropConn: 0.00,
   689  		ProbSleep:    0.00,
   690  	}
   691  }
   692  
   693  //-----------------------------------------------------------------------------
   694  // MempoolConfig
   695  
   696  // MempoolConfig defines the configuration options for the CometBFT mempool
   697  //
   698  // Note: Until v0.37 there was a `Version` field to select which implementation
   699  // of the mempool to use. Two versions used to exist: the current, default
   700  // implementation (previously called v0), and a prioritized mempool (v1), which
   701  // was removed (see https://github.com/KYVENetwork/cometbft/v38/issues/260).
   702  type MempoolConfig struct {
   703  	// The type of mempool for this node to use.
   704  	//
   705  	//  Possible types:
   706  	//  - "flood" : concurrent linked list mempool with flooding gossip protocol
   707  	//  (default)
   708  	//  - "nop"   : nop-mempool (short for no operation; the ABCI app is
   709  	//  responsible for storing, disseminating and proposing txs).
   710  	//  "create_empty_blocks=false" is not supported.
   711  	Type string `mapstructure:"type"`
   712  	// RootDir is the root directory for all data. This should be configured via
   713  	// the $CMTHOME env variable or --home cmd flag rather than overriding this
   714  	// struct field.
   715  	RootDir string `mapstructure:"home"`
   716  	// Recheck (default: true) defines whether CometBFT should recheck the
   717  	// validity for all remaining transaction in the mempool after a block.
   718  	// Since a block affects the application state, some transactions in the
   719  	// mempool may become invalid. If this does not apply to your application,
   720  	// you can disable rechecking.
   721  	Recheck bool `mapstructure:"recheck"`
   722  	// Broadcast (default: true) defines whether the mempool should relay
   723  	// transactions to other peers. Setting this to false will stop the mempool
   724  	// from relaying transactions to other peers until they are included in a
   725  	// block. In other words, if Broadcast is disabled, only the peer you send
   726  	// the tx to will see it until it is included in a block.
   727  	Broadcast bool `mapstructure:"broadcast"`
   728  	// WalPath (default: "") configures the location of the Write Ahead Log
   729  	// (WAL) for the mempool. The WAL is disabled by default. To enable, set
   730  	// WalPath to where you want the WAL to be written (e.g.
   731  	// "data/mempool.wal").
   732  	WalPath string `mapstructure:"wal_dir"`
   733  	// Maximum number of transactions in the mempool
   734  	Size int `mapstructure:"size"`
   735  	// Limit the total size of all txs in the mempool.
   736  	// This only accounts for raw transactions (e.g. given 1MB transactions and
   737  	// max_txs_bytes=5MB, mempool will only accept 5 transactions).
   738  	MaxTxsBytes int64 `mapstructure:"max_txs_bytes"`
   739  	// Size of the cache (used to filter transactions we saw earlier) in transactions
   740  	CacheSize int `mapstructure:"cache_size"`
   741  	// Do not remove invalid transactions from the cache (default: false)
   742  	// Set to true if it's not possible for any invalid transaction to become
   743  	// valid again in the future.
   744  	KeepInvalidTxsInCache bool `mapstructure:"keep-invalid-txs-in-cache"`
   745  	// Maximum size of a single transaction
   746  	// NOTE: the max size of a tx transmitted over the network is {max_tx_bytes}.
   747  	MaxTxBytes int `mapstructure:"max_tx_bytes"`
   748  	// Maximum size of a batch of transactions to send to a peer
   749  	// Including space needed by encoding (one varint per transaction).
   750  	// XXX: Unused due to https://github.com/tendermint/tendermint/issues/5796
   751  	MaxBatchBytes int `mapstructure:"max_batch_bytes"`
   752  	// Experimental parameters to limit gossiping txs to up to the specified number of peers.
   753  	// We use two independent upper values for persistent and non-persistent peers.
   754  	// Unconditional peers are not affected by this feature.
   755  	// If we are connected to more than the specified number of persistent peers, only send txs to
   756  	// ExperimentalMaxGossipConnectionsToPersistentPeers of them. If one of those
   757  	// persistent peers disconnects, activate another persistent peer.
   758  	// Similarly for non-persistent peers, with an upper limit of
   759  	// ExperimentalMaxGossipConnectionsToNonPersistentPeers.
   760  	// If set to 0, the feature is disabled for the corresponding group of peers, that is, the
   761  	// number of active connections to that group of peers is not bounded.
   762  	// For non-persistent peers, if enabled, a value of 10 is recommended based on experimental
   763  	// performance results using the default P2P configuration.
   764  	ExperimentalMaxGossipConnectionsToPersistentPeers    int `mapstructure:"experimental_max_gossip_connections_to_persistent_peers"`
   765  	ExperimentalMaxGossipConnectionsToNonPersistentPeers int `mapstructure:"experimental_max_gossip_connections_to_non_persistent_peers"`
   766  }
   767  
   768  // DefaultMempoolConfig returns a default configuration for the CometBFT mempool
   769  func DefaultMempoolConfig() *MempoolConfig {
   770  	return &MempoolConfig{
   771  		Type:      MempoolTypeFlood,
   772  		Recheck:   true,
   773  		Broadcast: true,
   774  		WalPath:   "",
   775  		// Each signature verification takes .5ms, Size reduced until we implement
   776  		// ABCI Recheck
   777  		Size:        5000,
   778  		MaxTxsBytes: 1024 * 1024 * 1024, // 1GB
   779  		CacheSize:   10000,
   780  		MaxTxBytes:  1024 * 1024, // 1MB
   781  		ExperimentalMaxGossipConnectionsToNonPersistentPeers: 0,
   782  		ExperimentalMaxGossipConnectionsToPersistentPeers:    0,
   783  	}
   784  }
   785  
   786  // TestMempoolConfig returns a configuration for testing the CometBFT mempool
   787  func TestMempoolConfig() *MempoolConfig {
   788  	cfg := DefaultMempoolConfig()
   789  	cfg.CacheSize = 1000
   790  	return cfg
   791  }
   792  
   793  // WalDir returns the full path to the mempool's write-ahead log
   794  func (cfg *MempoolConfig) WalDir() string {
   795  	return rootify(cfg.WalPath, cfg.RootDir)
   796  }
   797  
   798  // WalEnabled returns true if the WAL is enabled.
   799  func (cfg *MempoolConfig) WalEnabled() bool {
   800  	return cfg.WalPath != ""
   801  }
   802  
   803  // ValidateBasic performs basic validation (checking param bounds, etc.) and
   804  // returns an error if any check fails.
   805  func (cfg *MempoolConfig) ValidateBasic() error {
   806  	switch cfg.Type {
   807  	case MempoolTypeFlood, MempoolTypeNop:
   808  	case "": // allow empty string to be backwards compatible
   809  	default:
   810  		return fmt.Errorf("unknown mempool type: %q", cfg.Type)
   811  	}
   812  	if cfg.Size < 0 {
   813  		return errors.New("size can't be negative")
   814  	}
   815  	if cfg.MaxTxsBytes < 0 {
   816  		return errors.New("max_txs_bytes can't be negative")
   817  	}
   818  	if cfg.CacheSize < 0 {
   819  		return errors.New("cache_size can't be negative")
   820  	}
   821  	if cfg.MaxTxBytes < 0 {
   822  		return errors.New("max_tx_bytes can't be negative")
   823  	}
   824  	if cfg.ExperimentalMaxGossipConnectionsToPersistentPeers < 0 {
   825  		return errors.New("experimental_max_gossip_connections_to_persistent_peers can't be negative")
   826  	}
   827  	if cfg.ExperimentalMaxGossipConnectionsToNonPersistentPeers < 0 {
   828  		return errors.New("experimental_max_gossip_connections_to_non_persistent_peers can't be negative")
   829  	}
   830  	return nil
   831  }
   832  
   833  //-----------------------------------------------------------------------------
   834  // StateSyncConfig
   835  
   836  // StateSyncConfig defines the configuration for the CometBFT state sync service
   837  type StateSyncConfig struct {
   838  	Enable              bool          `mapstructure:"enable"`
   839  	TempDir             string        `mapstructure:"temp_dir"`
   840  	RPCServers          []string      `mapstructure:"rpc_servers"`
   841  	TrustPeriod         time.Duration `mapstructure:"trust_period"`
   842  	TrustHeight         int64         `mapstructure:"trust_height"`
   843  	TrustHash           string        `mapstructure:"trust_hash"`
   844  	DiscoveryTime       time.Duration `mapstructure:"discovery_time"`
   845  	ChunkRequestTimeout time.Duration `mapstructure:"chunk_request_timeout"`
   846  	ChunkFetchers       int32         `mapstructure:"chunk_fetchers"`
   847  }
   848  
   849  func (cfg *StateSyncConfig) TrustHashBytes() []byte {
   850  	// validated in ValidateBasic, so we can safely panic here
   851  	bytes, err := hex.DecodeString(cfg.TrustHash)
   852  	if err != nil {
   853  		panic(err)
   854  	}
   855  	return bytes
   856  }
   857  
   858  // DefaultStateSyncConfig returns a default configuration for the state sync service
   859  func DefaultStateSyncConfig() *StateSyncConfig {
   860  	return &StateSyncConfig{
   861  		TrustPeriod:         168 * time.Hour,
   862  		DiscoveryTime:       15 * time.Second,
   863  		ChunkRequestTimeout: 10 * time.Second,
   864  		ChunkFetchers:       4,
   865  	}
   866  }
   867  
   868  // TestStateSyncConfig returns a default configuration for the state sync service
   869  func TestStateSyncConfig() *StateSyncConfig {
   870  	return DefaultStateSyncConfig()
   871  }
   872  
   873  // ValidateBasic performs basic validation.
   874  func (cfg *StateSyncConfig) ValidateBasic() error {
   875  	if cfg.Enable {
   876  		if len(cfg.RPCServers) == 0 {
   877  			return errors.New("rpc_servers is required")
   878  		}
   879  
   880  		if len(cfg.RPCServers) < 2 {
   881  			return errors.New("at least two rpc_servers entries is required")
   882  		}
   883  
   884  		for _, server := range cfg.RPCServers {
   885  			if len(server) == 0 {
   886  				return errors.New("found empty rpc_servers entry")
   887  			}
   888  		}
   889  
   890  		if cfg.DiscoveryTime != 0 && cfg.DiscoveryTime < 5*time.Second {
   891  			return errors.New("discovery time must be 0s or greater than five seconds")
   892  		}
   893  
   894  		if cfg.TrustPeriod <= 0 {
   895  			return errors.New("trusted_period is required")
   896  		}
   897  
   898  		if cfg.TrustHeight <= 0 {
   899  			return errors.New("trusted_height is required")
   900  		}
   901  
   902  		if len(cfg.TrustHash) == 0 {
   903  			return errors.New("trusted_hash is required")
   904  		}
   905  
   906  		_, err := hex.DecodeString(cfg.TrustHash)
   907  		if err != nil {
   908  			return fmt.Errorf("invalid trusted_hash: %w", err)
   909  		}
   910  
   911  		if cfg.ChunkRequestTimeout < 5*time.Second {
   912  			return errors.New("chunk_request_timeout must be at least 5 seconds")
   913  		}
   914  
   915  		if cfg.ChunkFetchers <= 0 {
   916  			return errors.New("chunk_fetchers is required")
   917  		}
   918  	}
   919  
   920  	return nil
   921  }
   922  
   923  //-----------------------------------------------------------------------------
   924  // BlockSyncConfig
   925  
   926  // BlockSyncConfig (formerly known as FastSync) defines the configuration for the CometBFT block sync service
   927  type BlockSyncConfig struct {
   928  	Version string `mapstructure:"version"`
   929  }
   930  
   931  // DefaultBlockSyncConfig returns a default configuration for the block sync service
   932  func DefaultBlockSyncConfig() *BlockSyncConfig {
   933  	return &BlockSyncConfig{
   934  		Version: "v0",
   935  	}
   936  }
   937  
   938  // TestBlockSyncConfig returns a default configuration for the block sync.
   939  func TestBlockSyncConfig() *BlockSyncConfig {
   940  	return DefaultBlockSyncConfig()
   941  }
   942  
   943  // ValidateBasic performs basic validation.
   944  func (cfg *BlockSyncConfig) ValidateBasic() error {
   945  	switch cfg.Version {
   946  	case "v0":
   947  		return nil
   948  	case "v1", "v2":
   949  		return fmt.Errorf("blocksync version %s has been deprecated. Please use v0 instead", cfg.Version)
   950  	default:
   951  		return fmt.Errorf("unknown blocksync version %s", cfg.Version)
   952  	}
   953  }
   954  
   955  //-----------------------------------------------------------------------------
   956  // ConsensusConfig
   957  
   958  // ConsensusConfig defines the configuration for the Tendermint consensus algorithm, adopted by CometBFT,
   959  // including timeouts and details about the WAL and the block structure.
   960  type ConsensusConfig struct {
   961  	RootDir string `mapstructure:"home"`
   962  	WalPath string `mapstructure:"wal_file"`
   963  	walFile string // overrides WalPath if set
   964  
   965  	// How long we wait for a proposal block before prevoting nil
   966  	TimeoutPropose time.Duration `mapstructure:"timeout_propose"`
   967  	// How much timeout_propose increases with each round
   968  	TimeoutProposeDelta time.Duration `mapstructure:"timeout_propose_delta"`
   969  	// How long we wait after receiving +2/3 prevotes for “anything” (ie. not a single block or nil)
   970  	TimeoutPrevote time.Duration `mapstructure:"timeout_prevote"`
   971  	// How much the timeout_prevote increases with each round
   972  	TimeoutPrevoteDelta time.Duration `mapstructure:"timeout_prevote_delta"`
   973  	// How long we wait after receiving +2/3 precommits for “anything” (ie. not a single block or nil)
   974  	TimeoutPrecommit time.Duration `mapstructure:"timeout_precommit"`
   975  	// How much the timeout_precommit increases with each round
   976  	TimeoutPrecommitDelta time.Duration `mapstructure:"timeout_precommit_delta"`
   977  	// How long we wait after committing a block, before starting on the new
   978  	// height (this gives us a chance to receive some more precommits, even
   979  	// though we already have +2/3).
   980  	// NOTE: when modifying, make sure to update time_iota_ms genesis parameter
   981  	TimeoutCommit time.Duration `mapstructure:"timeout_commit"`
   982  
   983  	// Make progress as soon as we have all the precommits (as if TimeoutCommit = 0)
   984  	SkipTimeoutCommit bool `mapstructure:"skip_timeout_commit"`
   985  
   986  	// EmptyBlocks mode and possible interval between empty blocks
   987  	CreateEmptyBlocks         bool          `mapstructure:"create_empty_blocks"`
   988  	CreateEmptyBlocksInterval time.Duration `mapstructure:"create_empty_blocks_interval"`
   989  
   990  	// Reactor sleep duration parameters
   991  	PeerGossipSleepDuration     time.Duration `mapstructure:"peer_gossip_sleep_duration"`
   992  	PeerQueryMaj23SleepDuration time.Duration `mapstructure:"peer_query_maj23_sleep_duration"`
   993  
   994  	DoubleSignCheckHeight int64 `mapstructure:"double_sign_check_height"`
   995  }
   996  
   997  // DefaultConsensusConfig returns a default configuration for the consensus service
   998  func DefaultConsensusConfig() *ConsensusConfig {
   999  	return &ConsensusConfig{
  1000  		WalPath:                     filepath.Join(DefaultDataDir, "cs.wal", "wal"),
  1001  		TimeoutPropose:              3000 * time.Millisecond,
  1002  		TimeoutProposeDelta:         500 * time.Millisecond,
  1003  		TimeoutPrevote:              1000 * time.Millisecond,
  1004  		TimeoutPrevoteDelta:         500 * time.Millisecond,
  1005  		TimeoutPrecommit:            1000 * time.Millisecond,
  1006  		TimeoutPrecommitDelta:       500 * time.Millisecond,
  1007  		TimeoutCommit:               1000 * time.Millisecond,
  1008  		SkipTimeoutCommit:           false,
  1009  		CreateEmptyBlocks:           true,
  1010  		CreateEmptyBlocksInterval:   0 * time.Second,
  1011  		PeerGossipSleepDuration:     100 * time.Millisecond,
  1012  		PeerQueryMaj23SleepDuration: 2000 * time.Millisecond,
  1013  		DoubleSignCheckHeight:       int64(0),
  1014  	}
  1015  }
  1016  
  1017  // TestConsensusConfig returns a configuration for testing the consensus service
  1018  func TestConsensusConfig() *ConsensusConfig {
  1019  	cfg := DefaultConsensusConfig()
  1020  	cfg.TimeoutPropose = 40 * time.Millisecond
  1021  	cfg.TimeoutProposeDelta = 1 * time.Millisecond
  1022  	cfg.TimeoutPrevote = 10 * time.Millisecond
  1023  	cfg.TimeoutPrevoteDelta = 1 * time.Millisecond
  1024  	cfg.TimeoutPrecommit = 10 * time.Millisecond
  1025  	cfg.TimeoutPrecommitDelta = 1 * time.Millisecond
  1026  	// NOTE: when modifying, make sure to update time_iota_ms (testGenesisFmt) in toml.go
  1027  	cfg.TimeoutCommit = 10 * time.Millisecond
  1028  	cfg.SkipTimeoutCommit = true
  1029  	cfg.PeerGossipSleepDuration = 5 * time.Millisecond
  1030  	cfg.PeerQueryMaj23SleepDuration = 250 * time.Millisecond
  1031  	cfg.DoubleSignCheckHeight = int64(0)
  1032  	return cfg
  1033  }
  1034  
  1035  // WaitForTxs returns true if the consensus should wait for transactions before entering the propose step
  1036  func (cfg *ConsensusConfig) WaitForTxs() bool {
  1037  	return !cfg.CreateEmptyBlocks || cfg.CreateEmptyBlocksInterval > 0
  1038  }
  1039  
  1040  // Propose returns the amount of time to wait for a proposal
  1041  func (cfg *ConsensusConfig) Propose(round int32) time.Duration {
  1042  	return time.Duration(
  1043  		cfg.TimeoutPropose.Nanoseconds()+cfg.TimeoutProposeDelta.Nanoseconds()*int64(round),
  1044  	) * time.Nanosecond
  1045  }
  1046  
  1047  // Prevote returns the amount of time to wait for straggler votes after receiving any +2/3 prevotes
  1048  func (cfg *ConsensusConfig) Prevote(round int32) time.Duration {
  1049  	return time.Duration(
  1050  		cfg.TimeoutPrevote.Nanoseconds()+cfg.TimeoutPrevoteDelta.Nanoseconds()*int64(round),
  1051  	) * time.Nanosecond
  1052  }
  1053  
  1054  // Precommit returns the amount of time to wait for straggler votes after receiving any +2/3 precommits
  1055  func (cfg *ConsensusConfig) Precommit(round int32) time.Duration {
  1056  	return time.Duration(
  1057  		cfg.TimeoutPrecommit.Nanoseconds()+cfg.TimeoutPrecommitDelta.Nanoseconds()*int64(round),
  1058  	) * time.Nanosecond
  1059  }
  1060  
  1061  // Commit returns the amount of time to wait for straggler votes after receiving +2/3 precommits
  1062  // for a single block (ie. a commit).
  1063  func (cfg *ConsensusConfig) Commit(t time.Time) time.Time {
  1064  	return t.Add(cfg.TimeoutCommit)
  1065  }
  1066  
  1067  // WalFile returns the full path to the write-ahead log file
  1068  func (cfg *ConsensusConfig) WalFile() string {
  1069  	if cfg.walFile != "" {
  1070  		return cfg.walFile
  1071  	}
  1072  	return rootify(cfg.WalPath, cfg.RootDir)
  1073  }
  1074  
  1075  // SetWalFile sets the path to the write-ahead log file
  1076  func (cfg *ConsensusConfig) SetWalFile(walFile string) {
  1077  	cfg.walFile = walFile
  1078  }
  1079  
  1080  // ValidateBasic performs basic validation (checking param bounds, etc.) and
  1081  // returns an error if any check fails.
  1082  func (cfg *ConsensusConfig) ValidateBasic() error {
  1083  	if cfg.TimeoutPropose < 0 {
  1084  		return errors.New("timeout_propose can't be negative")
  1085  	}
  1086  	if cfg.TimeoutProposeDelta < 0 {
  1087  		return errors.New("timeout_propose_delta can't be negative")
  1088  	}
  1089  	if cfg.TimeoutPrevote < 0 {
  1090  		return errors.New("timeout_prevote can't be negative")
  1091  	}
  1092  	if cfg.TimeoutPrevoteDelta < 0 {
  1093  		return errors.New("timeout_prevote_delta can't be negative")
  1094  	}
  1095  	if cfg.TimeoutPrecommit < 0 {
  1096  		return errors.New("timeout_precommit can't be negative")
  1097  	}
  1098  	if cfg.TimeoutPrecommitDelta < 0 {
  1099  		return errors.New("timeout_precommit_delta can't be negative")
  1100  	}
  1101  	if cfg.TimeoutCommit < 0 {
  1102  		return errors.New("timeout_commit can't be negative")
  1103  	}
  1104  	if cfg.CreateEmptyBlocksInterval < 0 {
  1105  		return errors.New("create_empty_blocks_interval can't be negative")
  1106  	}
  1107  	if cfg.PeerGossipSleepDuration < 0 {
  1108  		return errors.New("peer_gossip_sleep_duration can't be negative")
  1109  	}
  1110  	if cfg.PeerQueryMaj23SleepDuration < 0 {
  1111  		return errors.New("peer_query_maj23_sleep_duration can't be negative")
  1112  	}
  1113  	if cfg.DoubleSignCheckHeight < 0 {
  1114  		return errors.New("double_sign_check_height can't be negative")
  1115  	}
  1116  	return nil
  1117  }
  1118  
  1119  //-----------------------------------------------------------------------------
  1120  // StorageConfig
  1121  
  1122  // StorageConfig allows more fine-grained control over certain storage-related
  1123  // behavior.
  1124  type StorageConfig struct {
  1125  	// Set to false to ensure ABCI responses are persisted. ABCI responses are
  1126  	// required for `/block_results` RPC queries, and to reindex events in the
  1127  	// command-line tool.
  1128  	DiscardABCIResponses bool `mapstructure:"discard_abci_responses"`
  1129  }
  1130  
  1131  // DefaultStorageConfig returns the default configuration options relating to
  1132  // CometBFT storage optimization.
  1133  func DefaultStorageConfig() *StorageConfig {
  1134  	return &StorageConfig{
  1135  		DiscardABCIResponses: false,
  1136  	}
  1137  }
  1138  
  1139  // TestStorageConfig returns storage configuration that can be used for
  1140  // testing.
  1141  func TestStorageConfig() *StorageConfig {
  1142  	return &StorageConfig{
  1143  		DiscardABCIResponses: false,
  1144  	}
  1145  }
  1146  
  1147  // -----------------------------------------------------------------------------
  1148  // TxIndexConfig
  1149  // Remember that Event has the following structure:
  1150  // type: [
  1151  //
  1152  //	key: value,
  1153  //	...
  1154  //
  1155  // ]
  1156  //
  1157  // CompositeKeys are constructed by `type.key`
  1158  // TxIndexConfig defines the configuration for the transaction indexer,
  1159  // including composite keys to index.
  1160  type TxIndexConfig struct {
  1161  	// What indexer to use for transactions
  1162  	//
  1163  	// Options:
  1164  	//   1) "null"
  1165  	//   2) "kv" (default) - the simplest possible indexer,
  1166  	//      backed by key-value storage (defaults to levelDB; see DBBackend).
  1167  	//   3) "psql" - the indexer services backed by PostgreSQL.
  1168  	Indexer string `mapstructure:"indexer"`
  1169  
  1170  	// The PostgreSQL connection configuration, the connection format:
  1171  	// postgresql://<user>:<password>@<host>:<port>/<db>?<opts>
  1172  	PsqlConn string `mapstructure:"psql-conn"`
  1173  }
  1174  
  1175  // DefaultTxIndexConfig returns a default configuration for the transaction indexer.
  1176  func DefaultTxIndexConfig() *TxIndexConfig {
  1177  	return &TxIndexConfig{
  1178  		Indexer: "kv",
  1179  	}
  1180  }
  1181  
  1182  // TestTxIndexConfig returns a default configuration for the transaction indexer.
  1183  func TestTxIndexConfig() *TxIndexConfig {
  1184  	return DefaultTxIndexConfig()
  1185  }
  1186  
  1187  //-----------------------------------------------------------------------------
  1188  // InstrumentationConfig
  1189  
  1190  // InstrumentationConfig defines the configuration for metrics reporting.
  1191  type InstrumentationConfig struct {
  1192  	// When true, Prometheus metrics are served under /metrics on
  1193  	// PrometheusListenAddr.
  1194  	// Check out the documentation for the list of available metrics.
  1195  	Prometheus bool `mapstructure:"prometheus"`
  1196  
  1197  	// Address to listen for Prometheus collector(s) connections.
  1198  	PrometheusListenAddr string `mapstructure:"prometheus_listen_addr"`
  1199  
  1200  	// Maximum number of simultaneous connections.
  1201  	// If you want to accept a larger number than the default, make sure
  1202  	// you increase your OS limits.
  1203  	// 0 - unlimited.
  1204  	MaxOpenConnections int `mapstructure:"max_open_connections"`
  1205  
  1206  	// Instrumentation namespace.
  1207  	Namespace string `mapstructure:"namespace"`
  1208  }
  1209  
  1210  // DefaultInstrumentationConfig returns a default configuration for metrics
  1211  // reporting.
  1212  func DefaultInstrumentationConfig() *InstrumentationConfig {
  1213  	return &InstrumentationConfig{
  1214  		Prometheus:           false,
  1215  		PrometheusListenAddr: ":26660",
  1216  		MaxOpenConnections:   3,
  1217  		Namespace:            "cometbft",
  1218  	}
  1219  }
  1220  
  1221  // TestInstrumentationConfig returns a default configuration for metrics
  1222  // reporting.
  1223  func TestInstrumentationConfig() *InstrumentationConfig {
  1224  	return DefaultInstrumentationConfig()
  1225  }
  1226  
  1227  // ValidateBasic performs basic validation (checking param bounds, etc.) and
  1228  // returns an error if any check fails.
  1229  func (cfg *InstrumentationConfig) ValidateBasic() error {
  1230  	if cfg.MaxOpenConnections < 0 {
  1231  		return errors.New("max_open_connections can't be negative")
  1232  	}
  1233  	return nil
  1234  }
  1235  
  1236  func (cfg *InstrumentationConfig) IsPrometheusEnabled() bool {
  1237  	return cfg.Prometheus && cfg.PrometheusListenAddr != ""
  1238  }
  1239  
  1240  //-----------------------------------------------------------------------------
  1241  // Utils
  1242  
  1243  // helper function to make config creation independent of root dir
  1244  func rootify(path, root string) string {
  1245  	if filepath.IsAbs(path) {
  1246  		return path
  1247  	}
  1248  	return filepath.Join(root, path)
  1249  }
  1250  
  1251  //-----------------------------------------------------------------------------
  1252  // Moniker
  1253  
  1254  var defaultMoniker = getDefaultMoniker()
  1255  
  1256  // getDefaultMoniker returns a default moniker, which is the host name. If runtime
  1257  // fails to get the host name, "anonymous" will be returned.
  1258  func getDefaultMoniker() string {
  1259  	moniker, err := os.Hostname()
  1260  	if err != nil {
  1261  		moniker = "anonymous"
  1262  	}
  1263  	return moniker
  1264  }