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 }