github.com/evdatsion/aphelion-dpos-bft@v0.32.1/config/config.go (about)

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