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