github.com/okex/exchain@v1.8.0/libs/tendermint/config/config.go (about)

     1  package config
     2  
     3  import (
     4  	"fmt"
     5  	"net/http"
     6  	"os"
     7  	"path/filepath"
     8  	"time"
     9  
    10  	"github.com/okex/exchain/libs/tendermint/types"
    11  
    12  	"github.com/pkg/errors"
    13  )
    14  
    15  const (
    16  	// FuzzModeDrop is a mode in which we randomly drop reads/writes, connections or sleep
    17  	FuzzModeDrop = iota
    18  	// FuzzModeDelay is a mode in which we randomly sleep
    19  	FuzzModeDelay
    20  
    21  	// LogFormatPlain is a format for colored text
    22  	LogFormatPlain = "plain"
    23  	// LogFormatJSON is a format for json output
    24  	LogFormatJSON = "json"
    25  )
    26  
    27  // NOTE: Most of the structs & relevant comments + the
    28  // default configuration options were used to manually
    29  // generate the config.toml. Please reflect any changes
    30  // made here in the defaultConfigTemplate constant in
    31  // config/toml.go
    32  // NOTE: libs/cli must know to look in the config dir!
    33  var (
    34  	DefaultTendermintDir = ".tendermint"
    35  	defaultConfigDir     = "config"
    36  	defaultDataDir       = "data"
    37  
    38  	defaultConfigFileName  = "config.toml"
    39  	defaultGenesisJSONName = "genesis.json"
    40  
    41  	defaultPrivValKeyName   = "priv_validator_key.json"
    42  	defaultPrivValStateName = "priv_validator_state.json"
    43  
    44  	defaultNodeKeyName  = "node_key.json"
    45  	defaultAddrBookName = "addrbook.json"
    46  
    47  	defaultConfigFilePath   = filepath.Join(defaultConfigDir, defaultConfigFileName)
    48  	defaultGenesisJSONPath  = filepath.Join(defaultConfigDir, defaultGenesisJSONName)
    49  	defaultPrivValKeyPath   = filepath.Join(defaultConfigDir, defaultPrivValKeyName)
    50  	defaultPrivValStatePath = filepath.Join(defaultDataDir, defaultPrivValStateName)
    51  
    52  	defaultNodeKeyPath  = filepath.Join(defaultConfigDir, defaultNodeKeyName)
    53  	defaultAddrBookPath = filepath.Join(defaultConfigDir, defaultAddrBookName)
    54  
    55  	DefaultLogPath     = os.ExpandEnv("$HOME/.exchaind")
    56  	defaultLogFileName = "exchaind.log"
    57  	defaultLogFile     = filepath.Join(DefaultLogPath, defaultLogFileName)
    58  )
    59  
    60  var (
    61  	oldPrivVal     = "priv_validator.json"
    62  	oldPrivValPath = filepath.Join(defaultConfigDir, oldPrivVal)
    63  )
    64  
    65  // Config defines the top level configuration for a Tendermint node
    66  type Config struct {
    67  	// Top level options use an anonymous struct
    68  	BaseConfig `mapstructure:",squash"`
    69  
    70  	// Options for services
    71  	RPC             *RPCConfig             `mapstructure:"rpc"`
    72  	P2P             *P2PConfig             `mapstructure:"p2p"`
    73  	Mempool         *MempoolConfig         `mapstructure:"mempool"`
    74  	FastSync        *FastSyncConfig        `mapstructure:"fastsync"`
    75  	Consensus       *ConsensusConfig       `mapstructure:"consensus"`
    76  	TxIndex         *TxIndexConfig         `mapstructure:"tx_index"`
    77  	Instrumentation *InstrumentationConfig `mapstructure:"instrumentation"`
    78  	GRPC            GRPCConfig             `mapstructure:"grpc"`
    79  }
    80  
    81  // DefaultConfig returns a default configuration for a Tendermint node
    82  func DefaultConfig() *Config {
    83  	return &Config{
    84  		BaseConfig:      DefaultBaseConfig(),
    85  		RPC:             DefaultRPCConfig(),
    86  		P2P:             DefaultP2PConfig(),
    87  		Mempool:         DefaultMempoolConfig(),
    88  		FastSync:        DefaultFastSyncConfig(),
    89  		Consensus:       DefaultConsensusConfig(),
    90  		TxIndex:         DefaultTxIndexConfig(),
    91  		Instrumentation: DefaultInstrumentationConfig(),
    92  		GRPC:            DefaultGRPCConfig(),
    93  	}
    94  }
    95  
    96  // TestConfig returns a configuration that can be used for testing
    97  func TestConfig() *Config {
    98  	return &Config{
    99  		BaseConfig:      TestBaseConfig(),
   100  		RPC:             TestRPCConfig(),
   101  		P2P:             TestP2PConfig(),
   102  		Mempool:         TestMempoolConfig(),
   103  		FastSync:        TestFastSyncConfig(),
   104  		Consensus:       TestConsensusConfig(),
   105  		TxIndex:         TestTxIndexConfig(),
   106  		Instrumentation: TestInstrumentationConfig(),
   107  	}
   108  }
   109  
   110  // SetRoot sets the RootDir for all Config structs
   111  func (cfg *Config) SetRoot(root string) *Config {
   112  	cfg.BaseConfig.RootDir = root
   113  	cfg.RPC.RootDir = root
   114  	cfg.P2P.RootDir = root
   115  	cfg.Mempool.RootDir = root
   116  	cfg.Consensus.RootDir = root
   117  
   118  	// exchain change LogFile base on cfg.BaseConfig.RootDir
   119  	if root != DefaultLogPath && cfg.BaseConfig.LogFile == defaultLogFile {
   120  		cfg.BaseConfig.LogFile = filepath.Join(root, defaultLogFileName)
   121  	}
   122  	return cfg
   123  }
   124  
   125  // ValidateBasic performs basic validation (checking param bounds, etc.) and
   126  // returns an error if any check fails.
   127  func (cfg *Config) ValidateBasic() error {
   128  	if err := cfg.BaseConfig.ValidateBasic(); err != nil {
   129  		return err
   130  	}
   131  	if err := cfg.RPC.ValidateBasic(); err != nil {
   132  		return errors.Wrap(err, "Error in [rpc] section")
   133  	}
   134  	if err := cfg.P2P.ValidateBasic(); err != nil {
   135  		return errors.Wrap(err, "Error in [p2p] section")
   136  	}
   137  	if err := cfg.Mempool.ValidateBasic(); err != nil {
   138  		return errors.Wrap(err, "Error in [mempool] section")
   139  	}
   140  	if err := cfg.FastSync.ValidateBasic(); err != nil {
   141  		return errors.Wrap(err, "Error in [fastsync] section")
   142  	}
   143  	if err := cfg.Consensus.ValidateBasic(); err != nil {
   144  		return errors.Wrap(err, "Error in [consensus] section")
   145  	}
   146  	return errors.Wrap(
   147  		cfg.Instrumentation.ValidateBasic(),
   148  		"Error in [instrumentation] section",
   149  	)
   150  }
   151  
   152  //-----------------------------------------------------------------------------
   153  // BaseConfig
   154  
   155  // BaseConfig defines the base configuration for a Tendermint node
   156  type BaseConfig struct { //nolint: maligned
   157  	// chainID is unexposed and immutable but here for convenience
   158  	chainID string
   159  
   160  	// The root directory for all data.
   161  	// This should be set in viper so it can unmarshal into this struct
   162  	RootDir string `mapstructure:"home"`
   163  
   164  	// TCP or UNIX socket address of the ABCI application,
   165  	// or the name of an ABCI application compiled in with the Tendermint binary
   166  	ProxyApp string `mapstructure:"proxy_app"`
   167  
   168  	// A custom human readable name for this node
   169  	Moniker string `mapstructure:"moniker"`
   170  
   171  	// If this node is many blocks behind the tip of the chain, FastSync
   172  	// allows them to catchup quickly by downloading blocks in parallel
   173  	// and verifying their commits
   174  	FastSyncMode bool `mapstructure:"fast_sync"`
   175  
   176  	// AutoFastSync allows this node switches from consensus mode to fast-sync mode automatically
   177  	// when it is many blocks behind the tip of the chain.
   178  	AutoFastSync bool `mapstructure:"auto_fast_sync"`
   179  
   180  	// Database backend: goleveldb | cleveldb | boltdb | rocksdb
   181  	// * goleveldb (github.com/syndtr/goleveldb - most popular implementation)
   182  	//   - pure go
   183  	//   - stable
   184  	// * cleveldb (uses levigo wrapper)
   185  	//   - fast
   186  	//   - requires gcc
   187  	//   - use cleveldb build tag (go build -tags cleveldb)
   188  	// * boltdb (uses etcd's fork of bolt - github.com/etcd-io/bbolt)
   189  	//   - EXPERIMENTAL
   190  	//   - may be faster is some use-cases (random reads - indexer)
   191  	//   - use boltdb build tag (go build -tags boltdb)
   192  	// * rocksdb (uses github.com/tecbot/gorocksdb)
   193  	//   - EXPERIMENTAL
   194  	//   - requires gcc
   195  	//   - use rocksdb build tag (go build -tags rocksdb)
   196  	DBBackend string `mapstructure:"db_backend"`
   197  
   198  	// Database directory
   199  	DBPath string `mapstructure:"db_dir"`
   200  
   201  	// Output level for logging
   202  	LogLevel string `mapstructure:"log_level"`
   203  
   204  	// Output format: 'plain' (colored text) or 'json'
   205  	LogFormat string `mapstructure:"log_format"`
   206  
   207  	// Path to the JSON file containing the initial validator set and other meta data
   208  	Genesis string `mapstructure:"genesis_file"`
   209  
   210  	// Path to the JSON file containing the private key to use as a validator in the consensus protocol
   211  	PrivValidatorKey string `mapstructure:"priv_validator_key_file"`
   212  
   213  	// Path to the JSON file containing the last sign state of a validator
   214  	PrivValidatorState string `mapstructure:"priv_validator_state_file"`
   215  
   216  	// TCP or UNIX socket address for Tendermint to listen on for
   217  	// connections from an external PrivValidator process
   218  	PrivValidatorListenAddr string `mapstructure:"priv_validator_laddr"`
   219  
   220  	// A JSON file containing the private key to use for p2p authenticated encryption
   221  	NodeKey string `mapstructure:"node_key_file"`
   222  
   223  	// Mechanism to connect to the ABCI application: socket | grpc
   224  	ABCI string `mapstructure:"abci"`
   225  
   226  	// TCP or UNIX socket address for the profiling server to listen on
   227  	ProfListenAddress string `mapstructure:"prof_laddr"`
   228  
   229  	// If true, query the ABCI app on connecting to a new peer
   230  	// so the app can decide if we should keep the connection or not
   231  	FilterPeers bool `mapstructure:"filter_peers"` // false
   232  
   233  	// Logging file directory
   234  	LogFile string `mapstructure:"log_file"`
   235  
   236  	// Logging stdout
   237  	LogStdout bool `mapstructure:"log_stdout"`
   238  }
   239  
   240  // DefaultBaseConfig returns a default base configuration for a Tendermint node
   241  func DefaultBaseConfig() BaseConfig {
   242  	return BaseConfig{
   243  		Genesis:            defaultGenesisJSONPath,
   244  		PrivValidatorKey:   defaultPrivValKeyPath,
   245  		PrivValidatorState: defaultPrivValStatePath,
   246  		NodeKey:            defaultNodeKeyPath,
   247  		Moniker:            defaultMoniker,
   248  		ProxyApp:           "tcp://127.0.0.1:26658",
   249  		ABCI:               "socket",
   250  		LogLevel:           DefaultPackageLogLevels(),
   251  		LogFormat:          LogFormatPlain,
   252  		FastSyncMode:       true,
   253  		AutoFastSync:       true,
   254  		FilterPeers:        false,
   255  		DBBackend:          types.DBBackend,
   256  		DBPath:             "data",
   257  		LogFile:            defaultLogFile,
   258  		LogStdout:          true,
   259  		ProfListenAddress:  "localhost:6060",
   260  	}
   261  }
   262  
   263  // TestBaseConfig returns a base configuration for testing a Tendermint node
   264  func TestBaseConfig() BaseConfig {
   265  	cfg := DefaultBaseConfig()
   266  	cfg.chainID = "tendermint_test"
   267  	cfg.ProxyApp = "kvstore"
   268  	cfg.FastSyncMode = false
   269  	cfg.AutoFastSync = false
   270  	cfg.DBBackend = "memdb"
   271  	return cfg
   272  }
   273  
   274  func (cfg BaseConfig) ChainID() string {
   275  	return cfg.chainID
   276  }
   277  
   278  // GenesisFile returns the full path to the genesis.json file
   279  func (cfg BaseConfig) GenesisFile() string {
   280  	return rootify(cfg.Genesis, cfg.RootDir)
   281  }
   282  
   283  // PrivValidatorKeyFile returns the full path to the priv_validator_key.json file
   284  func (cfg BaseConfig) PrivValidatorKeyFile() string {
   285  	return rootify(cfg.PrivValidatorKey, cfg.RootDir)
   286  }
   287  
   288  // PrivValidatorFile returns the full path to the priv_validator_state.json file
   289  func (cfg BaseConfig) PrivValidatorStateFile() string {
   290  	return rootify(cfg.PrivValidatorState, cfg.RootDir)
   291  }
   292  
   293  // NodeKeyFile returns the full path to the node_key.json file
   294  func (cfg BaseConfig) NodeKeyFile() string {
   295  	return rootify(cfg.NodeKey, cfg.RootDir)
   296  }
   297  
   298  // DBDir returns the full path to the database directory
   299  func (cfg BaseConfig) DBDir() string {
   300  	return rootify(cfg.DBPath, cfg.RootDir)
   301  }
   302  
   303  // ValidateBasic performs basic validation (checking param bounds, etc.) and
   304  // returns an error if any check fails.
   305  func (cfg BaseConfig) ValidateBasic() error {
   306  	switch cfg.LogFormat {
   307  	case LogFormatPlain, LogFormatJSON:
   308  	default:
   309  		return errors.New("unknown log_format (must be 'plain' or 'json')")
   310  	}
   311  	return nil
   312  }
   313  
   314  // DefaultLogLevel returns a default log level of "error"
   315  func DefaultLogLevel() string {
   316  	return "error"
   317  }
   318  
   319  // DefaultPackageLogLevels returns a default log level setting so all packages
   320  // log at "error", while the `state` and `main` packages log at "info"
   321  func DefaultPackageLogLevels() string {
   322  	return fmt.Sprintf("main:info,iavl:info,*:%s", DefaultLogLevel())
   323  }
   324  
   325  //-----------------------------------------------------------------------------
   326  // RPCConfig
   327  
   328  // RPCConfig defines the configuration options for the Tendermint RPC server
   329  type RPCConfig struct {
   330  	RootDir string `mapstructure:"home"`
   331  
   332  	// TCP or UNIX socket address for the RPC server to listen on
   333  	ListenAddress string `mapstructure:"laddr"`
   334  
   335  	// A list of origins a cross-domain request can be executed from.
   336  	// If the special '*' value is present in the list, all origins will be allowed.
   337  	// An origin may contain a wildcard (*) to replace 0 or more characters (i.e.: http://*.domain.com).
   338  	// Only one wildcard can be used per origin.
   339  	CORSAllowedOrigins []string `mapstructure:"cors_allowed_origins"`
   340  
   341  	// A list of methods the client is allowed to use with cross-domain requests.
   342  	CORSAllowedMethods []string `mapstructure:"cors_allowed_methods"`
   343  
   344  	// A list of non simple headers the client is allowed to use with cross-domain requests.
   345  	CORSAllowedHeaders []string `mapstructure:"cors_allowed_headers"`
   346  
   347  	// TCP or UNIX socket address for the gRPC server to listen on
   348  	// NOTE: This server only supports /broadcast_tx_commit
   349  	GRPCListenAddress string `mapstructure:"grpc_laddr"`
   350  
   351  	// Maximum number of simultaneous connections.
   352  	// Does not include RPC (HTTP&WebSocket) connections. See max_open_connections
   353  	// If you want to accept a larger number than the default, make sure
   354  	// you increase your OS limits.
   355  	// 0 - unlimited.
   356  	GRPCMaxOpenConnections int `mapstructure:"grpc_max_open_connections"`
   357  
   358  	// Activate unsafe RPC commands like /dial_persistent_peers and /unsafe_flush_mempool
   359  	Unsafe bool `mapstructure:"unsafe"`
   360  
   361  	// Maximum number of simultaneous connections (including WebSocket).
   362  	// Does not include gRPC connections. See grpc_max_open_connections
   363  	// If you want to accept a larger number than the default, make sure
   364  	// you increase your OS limits.
   365  	// 0 - unlimited.
   366  	// Should be < {ulimit -Sn} - {MaxNumInboundPeers} - {MaxNumOutboundPeers} - {N of wal, db and other open files}
   367  	// 1024 - 40 - 10 - 50 = 924 = ~900
   368  	MaxOpenConnections int `mapstructure:"max_open_connections"`
   369  
   370  	// Maximum number of unique clientIDs that can /subscribe
   371  	// If you're using /broadcast_tx_commit, set to the estimated maximum number
   372  	// of broadcast_tx_commit calls per block.
   373  	MaxSubscriptionClients int `mapstructure:"max_subscription_clients"`
   374  
   375  	// Maximum number of unique queries a given client can /subscribe to
   376  	// If you're using GRPC (or Local RPC client) and /broadcast_tx_commit, set
   377  	// to the estimated maximum number of broadcast_tx_commit calls per block.
   378  	MaxSubscriptionsPerClient int `mapstructure:"max_subscriptions_per_client"`
   379  
   380  	// How long to wait for a tx to be committed during /broadcast_tx_commit
   381  	// WARNING: Using a value larger than 10s will result in increasing the
   382  	// global HTTP write timeout, which applies to all connections and endpoints.
   383  	// See https://github.com/tendermint/tendermint/issues/3435
   384  	TimeoutBroadcastTxCommit time.Duration `mapstructure:"timeout_broadcast_tx_commit"`
   385  
   386  	// Maximum size of request body, in bytes
   387  	MaxBodyBytes int64 `mapstructure:"max_body_bytes"`
   388  
   389  	// Maximum size of request header, in bytes
   390  	MaxHeaderBytes int `mapstructure:"max_header_bytes"`
   391  
   392  	// The path to a file containing certificate that is used to create the HTTPS server.
   393  	// Migth be either absolute path or path related to tendermint's config directory.
   394  	//
   395  	// If the certificate is signed by a certificate authority,
   396  	// the certFile should be the concatenation of the server's certificate, any intermediates,
   397  	// and the CA's certificate.
   398  	//
   399  	// NOTE: both tls_cert_file and tls_key_file must be present for Tendermint to create HTTPS server.
   400  	// Otherwise, HTTP server is run.
   401  	TLSCertFile string `mapstructure:"tls_cert_file"`
   402  
   403  	// The path to a file containing matching private key that is used to create the HTTPS server.
   404  	// Migth be either absolute path or path related to tendermint's config directory.
   405  	//
   406  	// NOTE: both tls_cert_file and tls_key_file must be present for Tendermint to create HTTPS server.
   407  	// Otherwise, HTTP server is run.
   408  	TLSKeyFile string `mapstructure:"tls_key_file"`
   409  }
   410  
   411  // DefaultRPCConfig returns a default configuration for the RPC server
   412  func DefaultRPCConfig() *RPCConfig {
   413  	return &RPCConfig{
   414  		ListenAddress:          "tcp://0.0.0.0:26657",
   415  		CORSAllowedOrigins:     []string{},
   416  		CORSAllowedMethods:     []string{http.MethodHead, http.MethodGet, http.MethodPost},
   417  		CORSAllowedHeaders:     []string{"Origin", "Accept", "Content-Type", "X-Requested-With", "X-Server-Time"},
   418  		GRPCListenAddress:      "",
   419  		GRPCMaxOpenConnections: 900,
   420  
   421  		Unsafe:             false,
   422  		MaxOpenConnections: 900,
   423  
   424  		MaxSubscriptionClients:    100,
   425  		MaxSubscriptionsPerClient: 1000,
   426  		TimeoutBroadcastTxCommit:  10 * time.Second,
   427  
   428  		MaxBodyBytes:   int64(1000000), // 1MB
   429  		MaxHeaderBytes: 1 << 20,        // same as the net/http default
   430  
   431  		TLSCertFile: "",
   432  		TLSKeyFile:  "",
   433  	}
   434  }
   435  
   436  // TestRPCConfig returns a configuration for testing the RPC server
   437  func TestRPCConfig() *RPCConfig {
   438  	cfg := DefaultRPCConfig()
   439  	cfg.ListenAddress = "tcp://127.0.0.1:36657"
   440  	cfg.GRPCListenAddress = "tcp://127.0.0.1:36658"
   441  	cfg.Unsafe = true
   442  	return cfg
   443  }
   444  
   445  // ValidateBasic performs basic validation (checking param bounds, etc.) and
   446  // returns an error if any check fails.
   447  func (cfg *RPCConfig) ValidateBasic() error {
   448  	if cfg.GRPCMaxOpenConnections < 0 {
   449  		return errors.New("grpc_max_open_connections can't be negative")
   450  	}
   451  	if cfg.MaxOpenConnections < 0 {
   452  		return errors.New("max_open_connections can't be negative")
   453  	}
   454  	if cfg.MaxSubscriptionClients < 0 {
   455  		return errors.New("max_subscription_clients can't be negative")
   456  	}
   457  	if cfg.MaxSubscriptionsPerClient < 0 {
   458  		return errors.New("max_subscriptions_per_client can't be negative")
   459  	}
   460  	if cfg.TimeoutBroadcastTxCommit < 0 {
   461  		return errors.New("timeout_broadcast_tx_commit can't be negative")
   462  	}
   463  	if cfg.MaxBodyBytes < 0 {
   464  		return errors.New("max_body_bytes can't be negative")
   465  	}
   466  	if cfg.MaxHeaderBytes < 0 {
   467  		return errors.New("max_header_bytes can't be negative")
   468  	}
   469  	return nil
   470  }
   471  
   472  // IsCorsEnabled returns true if cross-origin resource sharing is enabled.
   473  func (cfg *RPCConfig) IsCorsEnabled() bool {
   474  	return len(cfg.CORSAllowedOrigins) != 0
   475  }
   476  
   477  func (cfg RPCConfig) KeyFile() string {
   478  	path := cfg.TLSKeyFile
   479  	if filepath.IsAbs(path) {
   480  		return path
   481  	}
   482  	return rootify(filepath.Join(defaultConfigDir, path), cfg.RootDir)
   483  }
   484  
   485  func (cfg RPCConfig) CertFile() string {
   486  	path := cfg.TLSCertFile
   487  	if filepath.IsAbs(path) {
   488  		return path
   489  	}
   490  	return rootify(filepath.Join(defaultConfigDir, path), cfg.RootDir)
   491  }
   492  
   493  func (cfg RPCConfig) IsTLSEnabled() bool {
   494  	return cfg.TLSCertFile != "" && cfg.TLSKeyFile != ""
   495  }
   496  
   497  //-----------------------------------------------------------------------------
   498  // P2PConfig
   499  
   500  // P2PConfig defines the configuration options for the Tendermint peer-to-peer networking layer
   501  type P2PConfig struct { //nolint: maligned
   502  	RootDir string `mapstructure:"home"`
   503  
   504  	// Address to listen for incoming connections
   505  	ListenAddress string `mapstructure:"laddr"`
   506  
   507  	// Address to advertise to peers for them to dial
   508  	ExternalAddress string `mapstructure:"external_address"`
   509  
   510  	// Comma separated list of seed nodes to connect to
   511  	// We only use these if we can’t connect to peers in the addrbook
   512  	Seeds string `mapstructure:"seeds"`
   513  
   514  	// Comma separated list of nodes to keep persistent connections to
   515  	PersistentPeers string `mapstructure:"persistent_peers"`
   516  
   517  	// UPNP port forwarding
   518  	UPNP bool `mapstructure:"upnp"`
   519  
   520  	// Path to address book
   521  	AddrBook string `mapstructure:"addr_book_file"`
   522  
   523  	// Set true for strict address routability rules
   524  	// Set false for private or local networks
   525  	AddrBookStrict bool `mapstructure:"addr_book_strict"`
   526  
   527  	// Maximum number of inbound peers
   528  	MaxNumInboundPeers int `mapstructure:"max_num_inbound_peers"`
   529  
   530  	// Maximum number of outbound peers to connect to, excluding persistent peers
   531  	MaxNumOutboundPeers int `mapstructure:"max_num_outbound_peers"`
   532  
   533  	// List of node IDs, to which a connection will be (re)established ignoring any existing limits
   534  	UnconditionalPeerIDs string `mapstructure:"unconditional_peer_ids"`
   535  
   536  	// Maximum pause when redialing a persistent peer (if zero, exponential backoff is used)
   537  	PersistentPeersMaxDialPeriod time.Duration `mapstructure:"persistent_peers_max_dial_period"`
   538  
   539  	// Time to wait before flushing messages out on the connection
   540  	FlushThrottleTimeout time.Duration `mapstructure:"flush_throttle_timeout"`
   541  
   542  	// Maximum size of a message packet payload, in bytes
   543  	MaxPacketMsgPayloadSize int `mapstructure:"max_packet_msg_payload_size"`
   544  
   545  	// Rate at which packets can be sent, in bytes/second
   546  	SendRate int64 `mapstructure:"send_rate"`
   547  
   548  	// Rate at which packets can be received, in bytes/second
   549  	RecvRate int64 `mapstructure:"recv_rate"`
   550  
   551  	// Set true to enable the peer-exchange reactor
   552  	PexReactor bool `mapstructure:"pex"`
   553  
   554  	// Seed mode, in which node constantly crawls the network and looks for
   555  	// peers. If another node asks it for addresses, it responds and disconnects.
   556  	//
   557  	// Does not work if the peer-exchange reactor is disabled.
   558  	SeedMode bool `mapstructure:"seed_mode"`
   559  
   560  	// Comma separated list of peer IDs to keep private (will not be gossiped to
   561  	// other peers)
   562  	PrivatePeerIDs string `mapstructure:"private_peer_ids"`
   563  
   564  	// Toggle to disable guard against peers connecting from the same ip.
   565  	AllowDuplicateIP bool `mapstructure:"allow_duplicate_ip"`
   566  
   567  	// Peer connection configuration.
   568  	HandshakeTimeout time.Duration `mapstructure:"handshake_timeout"`
   569  	DialTimeout      time.Duration `mapstructure:"dial_timeout"`
   570  
   571  	// Testing params.
   572  	// Force dial to fail
   573  	TestDialFail bool `mapstructure:"test_dial_fail"`
   574  	// FUzz connection
   575  	TestFuzz       bool            `mapstructure:"test_fuzz"`
   576  	TestFuzzConfig *FuzzConnConfig `mapstructure:"test_fuzz_config"`
   577  }
   578  
   579  // DefaultP2PConfig returns a default configuration for the peer-to-peer layer
   580  func DefaultP2PConfig() *P2PConfig {
   581  	return &P2PConfig{
   582  		ListenAddress:                "tcp://0.0.0.0:26656",
   583  		ExternalAddress:              "",
   584  		UPNP:                         false,
   585  		AddrBook:                     defaultAddrBookPath,
   586  		AddrBookStrict:               true,
   587  		MaxNumInboundPeers:           40,
   588  		MaxNumOutboundPeers:          10,
   589  		PersistentPeersMaxDialPeriod: 0 * time.Second,
   590  		FlushThrottleTimeout:         100 * time.Millisecond,
   591  		MaxPacketMsgPayloadSize:      1024,    // 1 kB
   592  		SendRate:                     5120000, // 5 mB/s
   593  		RecvRate:                     5120000, // 5 mB/s
   594  		PexReactor:                   true,
   595  		SeedMode:                     false,
   596  		AllowDuplicateIP:             false,
   597  		HandshakeTimeout:             20 * time.Second,
   598  		DialTimeout:                  3 * time.Second,
   599  		TestDialFail:                 false,
   600  		TestFuzz:                     false,
   601  		TestFuzzConfig:               DefaultFuzzConnConfig(),
   602  	}
   603  }
   604  
   605  // TestP2PConfig returns a configuration for testing the peer-to-peer layer
   606  func TestP2PConfig() *P2PConfig {
   607  	cfg := DefaultP2PConfig()
   608  	cfg.ListenAddress = "tcp://127.0.0.1:36656"
   609  	cfg.FlushThrottleTimeout = 10 * time.Millisecond
   610  	cfg.AllowDuplicateIP = true
   611  	return cfg
   612  }
   613  
   614  // AddrBookFile returns the full path to the address book
   615  func (cfg *P2PConfig) AddrBookFile() string {
   616  	return rootify(cfg.AddrBook, cfg.RootDir)
   617  }
   618  
   619  // ValidateBasic performs basic validation (checking param bounds, etc.) and
   620  // returns an error if any check fails.
   621  func (cfg *P2PConfig) ValidateBasic() error {
   622  	if cfg.MaxNumInboundPeers < 0 {
   623  		return errors.New("max_num_inbound_peers can't be negative")
   624  	}
   625  	if cfg.MaxNumOutboundPeers < 0 {
   626  		return errors.New("max_num_outbound_peers can't be negative")
   627  	}
   628  	if cfg.FlushThrottleTimeout < 0 {
   629  		return errors.New("flush_throttle_timeout can't be negative")
   630  	}
   631  	if cfg.PersistentPeersMaxDialPeriod < 0 {
   632  		return errors.New("persistent_peers_max_dial_period can't be negative")
   633  	}
   634  	if cfg.MaxPacketMsgPayloadSize < 0 {
   635  		return errors.New("max_packet_msg_payload_size can't be negative")
   636  	}
   637  	if cfg.SendRate < 0 {
   638  		return errors.New("send_rate can't be negative")
   639  	}
   640  	if cfg.RecvRate < 0 {
   641  		return errors.New("recv_rate can't be negative")
   642  	}
   643  	return nil
   644  }
   645  
   646  // FuzzConnConfig is a FuzzedConnection configuration.
   647  type FuzzConnConfig struct {
   648  	Mode         int
   649  	MaxDelay     time.Duration
   650  	ProbDropRW   float64
   651  	ProbDropConn float64
   652  	ProbSleep    float64
   653  }
   654  
   655  // DefaultFuzzConnConfig returns the default config.
   656  func DefaultFuzzConnConfig() *FuzzConnConfig {
   657  	return &FuzzConnConfig{
   658  		Mode:         FuzzModeDrop,
   659  		MaxDelay:     3 * time.Second,
   660  		ProbDropRW:   0.2,
   661  		ProbDropConn: 0.00,
   662  		ProbSleep:    0.00,
   663  	}
   664  }
   665  
   666  //-----------------------------------------------------------------------------
   667  // MempoolConfig
   668  
   669  // MempoolConfig defines the configuration options for the Tendermint mempool
   670  type MempoolConfig struct {
   671  	RootDir                    string   `mapstructure:"home"`
   672  	Sealed                     bool     `mapstructure:"sealed"`
   673  	Recheck                    bool     `mapstructure:"recheck"`
   674  	Broadcast                  bool     `mapstructure:"broadcast"`
   675  	Size                       int      `mapstructure:"size"`
   676  	MaxTxsBytes                int64    `mapstructure:"max_txs_bytes"`
   677  	CacheSize                  int      `mapstructure:"cache_size"`
   678  	MaxTxBytes                 int      `mapstructure:"max_tx_bytes"`
   679  	MaxTxNumPerBlock           int64    `mapstructure:"max_tx_num_per_block"`
   680  	EnableDeleteMinGPTx        bool     `mapstructure:"enable_delete_min_gp_tx"`
   681  	MaxGasUsedPerBlock         int64    `mapstructure:"max_gas_used_per_block"`
   682  	SortTxByGp                 bool     `mapstructure:"sort_tx_by_gp"`
   683  	ForceRecheckGap            int64    `mapstructure:"force_recheck_gap"`
   684  	TxPriceBump                uint64   `mapstructure:"tx_price_bump"`
   685  	EnablePendingPool          bool     `mapstructure:"enable_pending_pool"`
   686  	PendingPoolSize            int      `mapstructure:"pending_pool_size"`
   687  	PendingPoolPeriod          int      `mapstructure:"pending_pool_period"`
   688  	PendingPoolReserveBlocks   int      `mapstructure:"pending_pool_reserve_blocks"`
   689  	PendingPoolMaxTxPerAddress int      `mapstructure:"pending_pool_max_tx_per_address"`
   690  	NodeKeyWhitelist           []string `mapstructure:"node_key_whitelist"`
   691  	PendingRemoveEvent         bool     `mapstructure:"pending_remove_event"`
   692  }
   693  
   694  // DefaultMempoolConfig returns a default configuration for the Tendermint mempool
   695  func DefaultMempoolConfig() *MempoolConfig {
   696  	return &MempoolConfig{
   697  		Recheck:   false,
   698  		Broadcast: true,
   699  		// Each signature verification takes .5ms, Size reduced until we implement
   700  		// ABCI Recheck
   701  		Size:                       200_000,            // exchain memory pool size(max tx num)
   702  		MaxTxsBytes:                1024 * 1024 * 1024, // 1GB
   703  		CacheSize:                  300_000,
   704  		MaxTxBytes:                 1024 * 1024, // 1MB
   705  		MaxTxNumPerBlock:           300,
   706  		EnableDeleteMinGPTx:        false,
   707  		MaxGasUsedPerBlock:         -1,
   708  		SortTxByGp:                 true,
   709  		ForceRecheckGap:            2000,
   710  		TxPriceBump:                10,
   711  		EnablePendingPool:          false,
   712  		PendingPoolSize:            50000,
   713  		PendingPoolPeriod:          3,
   714  		PendingPoolReserveBlocks:   100,
   715  		PendingPoolMaxTxPerAddress: 100,
   716  		NodeKeyWhitelist:           []string{},
   717  		PendingRemoveEvent:         false,
   718  	}
   719  }
   720  
   721  // TestMempoolConfig returns a configuration for testing the Tendermint mempool
   722  func TestMempoolConfig() *MempoolConfig {
   723  	cfg := DefaultMempoolConfig()
   724  	cfg.CacheSize = 1000
   725  	return cfg
   726  }
   727  
   728  // GetNodeKeyWhitelist first use the DynamicConfig to get secondly backup to
   729  // the config file
   730  func (cfg *MempoolConfig) GetNodeKeyWhitelist() []string {
   731  	keys := DynamicConfig.GetNodeKeyWhitelist()
   732  	if len(keys) != 0 {
   733  		return keys
   734  	}
   735  	return cfg.NodeKeyWhitelist
   736  }
   737  
   738  // ValidateBasic performs basic validation (checking param bounds, etc.) and
   739  // returns an error if any check fails.
   740  func (cfg *MempoolConfig) ValidateBasic() error {
   741  	if cfg.Size < 0 {
   742  		return errors.New("size can't be negative")
   743  	}
   744  	if cfg.MaxTxsBytes < 0 {
   745  		return errors.New("max_txs_bytes can't be negative")
   746  	}
   747  	if cfg.CacheSize < 0 {
   748  		return errors.New("cache_size can't be negative")
   749  	}
   750  	if cfg.MaxTxBytes < 0 {
   751  		return errors.New("max_tx_bytes can't be negative")
   752  	}
   753  	if cfg.MaxTxNumPerBlock < 0 {
   754  		return errors.New("max_tx_num_per_block can't be negative")
   755  	}
   756  	if cfg.ForceRecheckGap <= 0 {
   757  		return errors.New("force_recheck_gap can't be negative or zero")
   758  	}
   759  	return nil
   760  }
   761  
   762  //-----------------------------------------------------------------------------
   763  // FastSyncConfig
   764  
   765  // FastSyncConfig defines the configuration for the Tendermint fast sync service
   766  type FastSyncConfig struct {
   767  	Version string `mapstructure:"version"`
   768  }
   769  
   770  // DefaultFastSyncConfig returns a default configuration for the fast sync service
   771  func DefaultFastSyncConfig() *FastSyncConfig {
   772  	return &FastSyncConfig{
   773  		Version: "v0",
   774  	}
   775  }
   776  
   777  // TestFastSyncConfig returns a default configuration for the fast sync.
   778  func TestFastSyncConfig() *FastSyncConfig {
   779  	return DefaultFastSyncConfig()
   780  }
   781  
   782  // ValidateBasic performs basic validation.
   783  func (cfg *FastSyncConfig) ValidateBasic() error {
   784  	switch cfg.Version {
   785  	case "v0":
   786  		return nil
   787  	case "v1":
   788  		return nil
   789  	case "v2":
   790  		return nil
   791  	default:
   792  		return fmt.Errorf("unknown fastsync version %s", cfg.Version)
   793  	}
   794  }
   795  
   796  //-----------------------------------------------------------------------------
   797  // ConsensusConfig
   798  
   799  // ConsensusConfig defines the configuration for the Tendermint consensus service,
   800  // including timeouts and details about the WAL and the block structure.
   801  type ConsensusConfig struct {
   802  	RootDir string `mapstructure:"home"`
   803  	WalPath string `mapstructure:"wal_file"`
   804  	walFile string // overrides WalPath if set
   805  
   806  	TimeoutPropose        time.Duration `mapstructure:"timeout_propose"`
   807  	TimeoutProposeDelta   time.Duration `mapstructure:"timeout_propose_delta"`
   808  	TimeoutPrevote        time.Duration `mapstructure:"timeout_prevote"`
   809  	TimeoutPrevoteDelta   time.Duration `mapstructure:"timeout_prevote_delta"`
   810  	TimeoutPrecommit      time.Duration `mapstructure:"timeout_precommit"`
   811  	TimeoutPrecommitDelta time.Duration `mapstructure:"timeout_precommit_delta"`
   812  	TimeoutCommit         time.Duration `mapstructure:"timeout_commit"`
   813  	TimeoutConsensus      time.Duration `mapstructure:"timeout_consensus"`
   814  	Waiting               bool          `mapstructure:"waiting"`
   815  
   816  	// Make progress as soon as we have all the precommits (as if TimeoutCommit = 0)
   817  	SkipTimeoutCommit bool `mapstructure:"skip_timeout_commit"`
   818  
   819  	// EmptyBlocks mode and possible interval between empty blocks
   820  	CreateEmptyBlocks         bool          `mapstructure:"create_empty_blocks"`
   821  	CreateEmptyBlocksInterval time.Duration `mapstructure:"create_empty_blocks_interval"`
   822  	TimeoutToFastSync         time.Duration `mapstructure:"switch_to_fast_sync_interval"`
   823  
   824  	// Reactor sleep duration parameters
   825  	PeerGossipSleepDuration     time.Duration `mapstructure:"peer_gossip_sleep_duration"`
   826  	PeerQueryMaj23SleepDuration time.Duration `mapstructure:"peer_query_maj23_sleep_duration"`
   827  }
   828  
   829  // DefaultConsensusConfig returns a default configuration for the consensus service
   830  func DefaultConsensusConfig() *ConsensusConfig {
   831  	return &ConsensusConfig{
   832  		WalPath:                     filepath.Join(defaultDataDir, "cs.wal", "wal"),
   833  		TimeoutPropose:              3000 * time.Millisecond,
   834  		TimeoutProposeDelta:         500 * time.Millisecond,
   835  		TimeoutPrevote:              1000 * time.Millisecond,
   836  		TimeoutPrevoteDelta:         500 * time.Millisecond,
   837  		TimeoutPrecommit:            1000 * time.Millisecond,
   838  		TimeoutPrecommitDelta:       500 * time.Millisecond,
   839  		TimeoutCommit:               types.TimeoutCommit * time.Millisecond,
   840  		TimeoutConsensus:            1000 * time.Millisecond,
   841  		SkipTimeoutCommit:           false,
   842  		CreateEmptyBlocks:           true,
   843  		CreateEmptyBlocksInterval:   0 * time.Second,
   844  		TimeoutToFastSync:           30 * time.Second,
   845  		PeerGossipSleepDuration:     100 * time.Millisecond,
   846  		PeerQueryMaj23SleepDuration: 2000 * time.Millisecond,
   847  		Waiting:                     true,
   848  	}
   849  }
   850  
   851  // TestConsensusConfig returns a configuration for testing the consensus service
   852  func TestConsensusConfig() *ConsensusConfig {
   853  	cfg := DefaultConsensusConfig()
   854  	cfg.TimeoutPropose = 40 * time.Millisecond
   855  	cfg.TimeoutProposeDelta = 1 * time.Millisecond
   856  	cfg.TimeoutPrevote = 10 * time.Millisecond
   857  	cfg.TimeoutPrevoteDelta = 1 * time.Millisecond
   858  	cfg.TimeoutPrecommit = 10 * time.Millisecond
   859  	cfg.TimeoutPrecommitDelta = 1 * time.Millisecond
   860  	cfg.TimeoutCommit = 10 * time.Millisecond
   861  	cfg.TimeoutConsensus = 60 * time.Millisecond
   862  	cfg.SkipTimeoutCommit = true
   863  	cfg.TimeoutToFastSync = 30 * time.Second
   864  	cfg.PeerGossipSleepDuration = 5 * time.Millisecond
   865  	cfg.PeerQueryMaj23SleepDuration = 250 * time.Millisecond
   866  	return cfg
   867  }
   868  
   869  // WaitForTxs returns true if the consensus should wait for transactions before entering the propose step
   870  func (cfg *ConsensusConfig) WaitForTxs() bool {
   871  	return !cfg.CreateEmptyBlocks || cfg.CreateEmptyBlocksInterval > 0
   872  }
   873  
   874  // Propose returns the amount of time to wait for a proposal
   875  func (cfg *ConsensusConfig) Propose(round int) time.Duration {
   876  	return time.Duration(
   877  		DynamicConfig.GetCsTimeoutPropose().Nanoseconds()+DynamicConfig.GetCsTimeoutProposeDelta().Nanoseconds()*int64(round),
   878  	) * time.Nanosecond
   879  }
   880  
   881  // Prevote returns the amount of time to wait for straggler votes after receiving any +2/3 prevotes
   882  func (cfg *ConsensusConfig) Prevote(round int) time.Duration {
   883  	return time.Duration(
   884  		DynamicConfig.GetCsTimeoutPrevote().Nanoseconds()+DynamicConfig.GetCsTimeoutPrevoteDelta().Nanoseconds()*int64(round),
   885  	) * time.Nanosecond
   886  }
   887  
   888  // Precommit returns the amount of time to wait for straggler votes after receiving any +2/3 precommits
   889  func (cfg *ConsensusConfig) Precommit(round int) time.Duration {
   890  	return time.Duration(
   891  		DynamicConfig.GetCsTimeoutPrecommit().Nanoseconds()+DynamicConfig.GetCsTimeoutPrecommitDelta().Nanoseconds()*int64(round),
   892  	) * time.Nanosecond
   893  }
   894  
   895  // Commit returns the amount of time to wait for straggler votes after receiving +2/3 precommits
   896  // for a single block (ie. a commit).
   897  func (cfg *ConsensusConfig) Commit(t time.Time) time.Time {
   898  	return t.Add(DynamicConfig.GetCsTimeoutCommit())
   899  }
   900  
   901  // WalFile returns the full path to the write-ahead log file
   902  func (cfg *ConsensusConfig) WalFile() string {
   903  	if cfg.walFile != "" {
   904  		return cfg.walFile
   905  	}
   906  	return rootify(cfg.WalPath, cfg.RootDir)
   907  }
   908  
   909  // SetWalFile sets the path to the write-ahead log file
   910  func (cfg *ConsensusConfig) SetWalFile(walFile string) {
   911  	cfg.walFile = walFile
   912  }
   913  
   914  // ValidateBasic performs basic validation (checking param bounds, etc.) and
   915  // returns an error if any check fails.
   916  func (cfg *ConsensusConfig) ValidateBasic() error {
   917  	if cfg.TimeoutPropose < 0 {
   918  		return errors.New("timeout_propose can't be negative")
   919  	}
   920  	if cfg.TimeoutProposeDelta < 0 {
   921  		return errors.New("timeout_propose_delta can't be negative")
   922  	}
   923  	if cfg.TimeoutPrevote < 0 {
   924  		return errors.New("timeout_prevote can't be negative")
   925  	}
   926  	if cfg.TimeoutPrevoteDelta < 0 {
   927  		return errors.New("timeout_prevote_delta can't be negative")
   928  	}
   929  	if cfg.TimeoutPrecommit < 0 {
   930  		return errors.New("timeout_precommit can't be negative")
   931  	}
   932  	if cfg.TimeoutPrecommitDelta < 0 {
   933  		return errors.New("timeout_precommit_delta can't be negative")
   934  	}
   935  	if cfg.TimeoutCommit < 0 {
   936  		return errors.New("timeout_commit can't be negative")
   937  	}
   938  	if cfg.TimeoutConsensus < 0 {
   939  		return errors.New("timeout_consensus can't be negative")
   940  	}
   941  	if cfg.CreateEmptyBlocksInterval < 0 {
   942  		return errors.New("create_empty_blocks_interval can't be negative")
   943  	}
   944  	if cfg.TimeoutToFastSync < 0 {
   945  		return errors.New("timeout_to_fast_sync can't be negative")
   946  	}
   947  	if cfg.PeerGossipSleepDuration < 0 {
   948  		return errors.New("peer_gossip_sleep_duration can't be negative")
   949  	}
   950  	if cfg.PeerQueryMaj23SleepDuration < 0 {
   951  		return errors.New("peer_query_maj23_sleep_duration can't be negative")
   952  	}
   953  	return nil
   954  }
   955  
   956  //-----------------------------------------------------------------------------
   957  // TxIndexConfig
   958  // Remember that Event has the following structure:
   959  // type: [
   960  //  key: value,
   961  //  ...
   962  // ]
   963  //
   964  // CompositeKeys are constructed by `type.key`
   965  // TxIndexConfig defines the configuration for the transaction indexer,
   966  // including composite keys to index.
   967  type TxIndexConfig struct {
   968  	// What indexer to use for transactions
   969  	//
   970  	// Options:
   971  	//   1) "null"
   972  	//   2) "kv" (default) - the simplest possible indexer,
   973  	//      backed by key-value storage (defaults to levelDB; see DBBackend).
   974  	Indexer string `mapstructure:"indexer"`
   975  
   976  	// Comma-separated list of compositeKeys to index (by default the only key is "tx.hash")
   977  	//
   978  	// You can also index transactions by height by adding "tx.height" key here.
   979  	//
   980  	// It's recommended to index only a subset of keys due to possible memory
   981  	// bloat. This is, of course, depends on the indexer's DB and the volume of
   982  	// transactions.
   983  	IndexKeys string `mapstructure:"index_keys"`
   984  
   985  	// When set to true, tells indexer to index all compositeKeys (predefined keys:
   986  	// "tx.hash", "tx.height" and all keys from DeliverTx responses).
   987  	//
   988  	// Note this may be not desirable (see the comment above). IndexKeys has a
   989  	// precedence over IndexAllKeys (i.e. when given both, IndexKeys will be
   990  	// indexed).
   991  	IndexAllKeys bool `mapstructure:"index_all_keys"`
   992  }
   993  
   994  // DefaultTxIndexConfig returns a default configuration for the transaction indexer.
   995  func DefaultTxIndexConfig() *TxIndexConfig {
   996  	return &TxIndexConfig{
   997  		Indexer:      "kv",
   998  		IndexKeys:    "",
   999  		IndexAllKeys: false,
  1000  	}
  1001  }
  1002  
  1003  // TestTxIndexConfig returns a default configuration for the transaction indexer.
  1004  func TestTxIndexConfig() *TxIndexConfig {
  1005  	return DefaultTxIndexConfig()
  1006  }
  1007  
  1008  //-----------------------------------------------------------------------------
  1009  // InstrumentationConfig
  1010  
  1011  // InstrumentationConfig defines the configuration for metrics reporting.
  1012  type InstrumentationConfig struct {
  1013  	// When true, Prometheus metrics are served under /metrics on
  1014  	// PrometheusListenAddr.
  1015  	// Check out the documentation for the list of available metrics.
  1016  	Prometheus bool `mapstructure:"prometheus"`
  1017  
  1018  	// Address to listen for Prometheus collector(s) connections.
  1019  	PrometheusListenAddr string `mapstructure:"prometheus_listen_addr"`
  1020  
  1021  	// Maximum number of simultaneous connections.
  1022  	// If you want to accept a larger number than the default, make sure
  1023  	// you increase your OS limits.
  1024  	// 0 - unlimited.
  1025  	MaxOpenConnections int `mapstructure:"max_open_connections"`
  1026  
  1027  	// Instrumentation namespace.
  1028  	Namespace string `mapstructure:"namespace"`
  1029  }
  1030  
  1031  // DefaultInstrumentationConfig returns a default configuration for metrics
  1032  // reporting.
  1033  func DefaultInstrumentationConfig() *InstrumentationConfig {
  1034  	return &InstrumentationConfig{
  1035  		Prometheus:           true,
  1036  		PrometheusListenAddr: ":26660",
  1037  		MaxOpenConnections:   3,
  1038  		Namespace:            "tendermint",
  1039  	}
  1040  }
  1041  
  1042  // TestInstrumentationConfig returns a default configuration for metrics
  1043  // reporting.
  1044  func TestInstrumentationConfig() *InstrumentationConfig {
  1045  	return DefaultInstrumentationConfig()
  1046  }
  1047  
  1048  // ValidateBasic performs basic validation (checking param bounds, etc.) and
  1049  // returns an error if any check fails.
  1050  func (cfg *InstrumentationConfig) ValidateBasic() error {
  1051  	if cfg.MaxOpenConnections < 0 {
  1052  		return errors.New("max_open_connections can't be negative")
  1053  	}
  1054  	return nil
  1055  }
  1056  
  1057  //-----------------------------------------------------------------------------
  1058  // Utils
  1059  
  1060  // helper function to make config creation independent of root dir
  1061  func rootify(path, root string) string {
  1062  	if filepath.IsAbs(path) {
  1063  		return path
  1064  	}
  1065  	return filepath.Join(root, path)
  1066  }
  1067  
  1068  //-----------------------------------------------------------------------------
  1069  // Moniker
  1070  
  1071  var defaultMoniker = getDefaultMoniker()
  1072  
  1073  // getDefaultMoniker returns a default moniker, which is the host name. If runtime
  1074  // fails to get the host name, "anonymous" will be returned.
  1075  func getDefaultMoniker() string {
  1076  	moniker, err := os.Hostname()
  1077  	if err != nil {
  1078  		moniker = "anonymous"
  1079  	}
  1080  	return moniker
  1081  }