From 258a9121c351e76cbb81fe7d9ace4220ba7fb01c Mon Sep 17 00:00:00 2001 From: Tomas Zemanovic Date: Thu, 10 Jun 2021 14:52:35 +0200 Subject: [PATCH] update tendermint config (#897) * update db_backend config * update log_level config * update tx_index config * config - remove `prof_laddr` * config - add mempool options * fixup! config - add mempool options * config - add p2p options * config - add RPC options * fixup! config - add p2p options * config - add statesync and fastsync options * config - add consensus option * fixup! config - add p2p options * update CHANGELOG * fixup! update log_level config * tests - update sample config.toml * fixup! config - add p2p options * fixup! config - add statesync and fastsync options * update config tests * update docstrings lint * Revert "update CHANGELOG" This reverts commit 51413292a8da1677f52a700997ec13b813a37688. * update changelog * fixup! update changelog --- .../bug-fixes/897-outdated-config.md | 1 + tendermint/src/config.rs | 175 +++++++++++++---- tendermint/tests/config.rs | 12 +- tendermint/tests/support/config/config.toml | 182 ++++++++++++++---- 4 files changed, 290 insertions(+), 80 deletions(-) create mode 100644 .changelog/unreleased/bug-fixes/897-outdated-config.md diff --git a/.changelog/unreleased/bug-fixes/897-outdated-config.md b/.changelog/unreleased/bug-fixes/897-outdated-config.md new file mode 100644 index 000000000..59da8f279 --- /dev/null +++ b/.changelog/unreleased/bug-fixes/897-outdated-config.md @@ -0,0 +1 @@ +- `[tendermint]` Update TendermintConfig for Tendermint v.0.34.x ([#897](https://github.com/informalsystems/tendermint-rs/issues/897)) \ No newline at end of file diff --git a/tendermint/src/config.rs b/tendermint/src/config.rs index 6de2d1ab5..5d21dc381 100644 --- a/tendermint/src/config.rs +++ b/tendermint/src/config.rs @@ -12,7 +12,6 @@ mod priv_validator_key; pub use self::{node_key::NodeKey, priv_validator_key::PrivValidatorKey}; use crate::{ - abci::tag, error::{Error, Kind}, genesis::Genesis, net, node, Moniker, Timeout, @@ -41,7 +40,7 @@ pub struct TendermintConfig { /// and verifying their commits pub fast_sync: bool, - /// Database backend: `leveldb | memdb | cleveldb` + /// Database backend: `goleveldb | cleveldb | boltdb | rocksdb | badgerdb` pub db_backend: DbBackend, /// Database directory @@ -75,10 +74,6 @@ pub struct TendermintConfig { /// Mechanism to connect to the ABCI application: socket | grpc pub abci: AbciMode, - /// TCP or UNIX socket address for the profiling server to listen on - #[serde(deserialize_with = "deserialize_optional_value")] - pub prof_laddr: Option, - /// If `true`, query the ABCI app on connecting to a new peer /// so the app can decide if we should keep the connection or not pub filter_peers: bool, @@ -100,6 +95,12 @@ pub struct TendermintConfig { /// instrumentation configuration options pub instrumentation: InstrumentationConfig, + + /// statesync configuration options + pub statesync: StatesyncConfig, + + /// fastsync configuration options + pub fastsync: FastsyncConfig, } impl TendermintConfig { @@ -144,35 +145,50 @@ impl TendermintConfig { /// Database backend #[derive(Copy, Clone, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)] pub enum DbBackend { - /// LevelDB backend - #[serde(rename = "leveldb")] - LevelDb, - - /// MemDB backend - #[serde(rename = "memdb")] - MemDb, + /// GoLevelDB backend + #[serde(rename = "goleveldb")] + GoLevelDb, /// CLevelDB backend #[serde(rename = "cleveldb")] CLevelDb, + + /// BoltDB backend + #[serde(rename = "boltdb")] + BoltDb, + + /// RocksDB backend + #[serde(rename = "rocksdb")] + RocksDb, + + /// BadgerDB backend + #[serde(rename = "badgerdb")] + BadgerDb, } /// Loglevel configuration #[derive(Clone, Debug, Eq, PartialEq)] -pub struct LogLevel(BTreeMap); +pub struct LogLevel { + /// A global log level + pub global: Option, + components: BTreeMap, +} impl LogLevel { - /// Get the setting for the given key + /// Get the setting for the given key. If not found, returns the global setting, if any. pub fn get(&self, key: S) -> Option<&str> where S: AsRef, { - self.0.get(key.as_ref()).map(AsRef::as_ref) + self.components + .get(key.as_ref()) + .or_else(|| self.global.as_ref()) + .map(AsRef::as_ref) } - /// Iterate over the levels + /// Iterate over the levels. This doesn't include the global setting, if any. pub fn iter(&self) -> LogLevelIter<'_> { - self.0.iter() + self.components.iter() } } @@ -183,33 +199,43 @@ impl FromStr for LogLevel { type Err = Error; fn from_str(s: &str) -> Result { - let mut levels = BTreeMap::new(); + let mut global = None; + let mut components = BTreeMap::new(); for level in s.split(',') { let parts = level.split(':').collect::>(); - if parts.len() != 2 { + if parts.len() == 1 { + global = Some(parts[0].to_owned()); + continue; + } else if parts.len() != 2 { fail!(Kind::Parse, "error parsing log level: {}", level); } let key = parts[0].to_owned(); let value = parts[1].to_owned(); - if levels.insert(key, value).is_some() { + if components.insert(key, value).is_some() { fail!(Kind::Parse, "duplicate log level setting for: {}", level); } } - Ok(LogLevel(levels)) + Ok(LogLevel { global, components }) } } impl fmt::Display for LogLevel { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - for (i, (k, v)) in self.0.iter().enumerate() { + if let Some(global) = &self.global { + write!(f, "{}", global)?; + if !self.components.is_empty() { + write!(f, ",")?; + } + } + for (i, (k, v)) in self.components.iter().enumerate() { write!(f, "{}:{}", k, v)?; - if i < self.0.len() - 1 { + if i < self.components.len() - 1 { write!(f, ",")?; } } @@ -298,6 +324,12 @@ pub struct RpcConfig { /// How long to wait for a tx to be committed during `/broadcast_tx_commit`. pub timeout_broadcast_tx_commit: Timeout, + /// Maximum size of request body, in bytes + pub max_body_bytes: u64, + + /// Maximum size of request header, in bytes + pub max_header_bytes: u64, + /// The name of a file containing certificate that is used to create the HTTPS server. #[serde(deserialize_with = "deserialize_optional_value")] pub tls_cert_file: Option, @@ -305,6 +337,10 @@ pub struct RpcConfig { /// The name of a file containing matching private key that is used to create the HTTPS server. #[serde(deserialize_with = "deserialize_optional_value")] pub tls_key_file: Option, + + /// pprof listen address + #[serde(deserialize_with = "deserialize_optional_value")] + pub pprof_laddr: Option, } /// Origin hosts allowed with CORS requests to the RPC API @@ -401,6 +437,16 @@ pub struct P2PConfig { /// Maximum number of outbound peers to connect to, excluding persistent peers pub max_num_outbound_peers: u64, + /// List of node IDs, to which a connection will be (re)established ignoring any existing limits + #[serde( + serialize_with = "serialize_comma_separated_list", + deserialize_with = "deserialize_comma_separated_list" + )] + pub unconditional_peer_ids: Vec, + + /// Maximum pause when redialing a persistent peer (if zero, exponential backoff is used) + pub persistent_peers_max_dial_period: Timeout, + /// Time to wait before flushing messages out on the connection pub flush_throttle_timeout: Timeout, @@ -462,6 +508,21 @@ pub struct MempoolConfig { /// Size of the cache (used to filter transactions we saw earlier) in transactions pub cache_size: u64, + + /// Do not remove invalid transactions from the cache (default: false) + /// Set to true if it's not possible for any invalid transaction to become valid + /// again in the future. + #[serde(rename = "keep-invalid-txs-in-cache")] + pub keep_invalid_txs_in_cache: bool, + + /// Maximum size of a single transaction. + /// NOTE: the max size of a tx transmitted over the network is {max-tx-bytes}. + pub max_tx_bytes: u64, + + /// Maximum size of a batch of transactions to send to a peer + /// Including space needed by encoding (one varint per transaction). + /// XXX: Unused due to + pub max_batch_bytes: u64, } /// consensus configuration options @@ -491,6 +552,12 @@ pub struct ConsensusConfig { /// Commit timeout pub timeout_commit: Timeout, + /// How many blocks to look back to check existence of the node's consensus votes before joining consensus + /// When non-zero, the node will panic upon restart + /// if the same consensus key was used to sign {double-sign-check-height} last blocks. + /// So, validators should stop the state machine, wait for some blocks, and then restart the state machine to avoid panic. + pub double_sign_check_height: u64, + /// Make progress as soon as we have all the precommits (as if TimeoutCommit = 0) pub skip_timeout_commit: bool, @@ -513,18 +580,6 @@ pub struct TxIndexConfig { /// What indexer to use for transactions #[serde(default)] pub indexer: TxIndexer, - - /// Comma-separated list of tags to index (by default the only tag is `tx.hash`) - // TODO(tarcieri): switch to `tendermint::abci::Tag` - #[serde( - serialize_with = "serialize_comma_separated_list", - deserialize_with = "deserialize_comma_separated_list" - )] - pub index_tags: Vec, - - /// When set to true, tells indexer to index all tags (predefined tags: - /// `tx.hash`, `tx.height` and all tags from DeliverTx responses). - pub index_all_tags: bool, } /// What indexer to use for transactions @@ -565,6 +620,54 @@ pub struct InstrumentationConfig { pub namespace: String, } +/// statesync configuration options +#[derive(Clone, Debug, Deserialize, Serialize)] +pub struct StatesyncConfig { + /// State sync rapidly bootstraps a new node by discovering, fetching, and restoring a state machine + /// snapshot from peers instead of fetching and replaying historical blocks. Requires some peers in + /// the network to take and serve state machine snapshots. State sync is not attempted if the node + /// has any local state (LastBlockHeight > 0). The node will have a truncated block history, + /// starting from the height of the snapshot. + pub enable: bool, + + /// RPC servers (comma-separated) for light client verification of the synced state machine and + /// retrieval of state data for node bootstrapping. Also needs a trusted height and corresponding + /// header hash obtained from a trusted source, and a period during which validators can be trusted. + /// + /// For Cosmos SDK-based chains, trust-period should usually be about 2/3 of the unbonding time (~2 + /// weeks) during which they can be financially punished (slashed) for misbehavior. + #[serde( + serialize_with = "serialize_comma_separated_list", + deserialize_with = "deserialize_comma_separated_list" + )] + pub rpc_servers: Vec, + + /// Trust height. See `rpc_servers` above. + pub trust_height: u64, + + /// Trust hash. See `rpc_servers` above. + pub trust_hash: String, + + /// Trust period. See `rpc_servers` above. + pub trust_period: String, + + /// Time to spend discovering snapshots before initiating a restore. + pub discovery_time: Timeout, + + /// Temporary directory for state sync snapshot chunks, defaults to the OS tempdir (typically /tmp). + /// Will create a new, randomly named directory within, and remove it when done. + pub temp_dir: String, +} + +/// fastsync configuration options +#[derive(Clone, Debug, Deserialize, Serialize)] +pub struct FastsyncConfig { + /// Fast Sync version to use: + /// 1) "v0" (default) - the legacy fast sync implementation + /// 2) "v2" - complete redesign of v0, optimized for testability & readability + pub version: String, +} + /// Rate at which bytes can be sent/received #[derive(Copy, Clone, Debug, Deserialize, Serialize)] pub struct TransferRate(u64); diff --git a/tendermint/tests/config.rs b/tendermint/tests/config.rs index 712f3443e..3c86ec6cf 100644 --- a/tendermint/tests/config.rs +++ b/tendermint/tests/config.rs @@ -26,11 +26,12 @@ mod files { ); assert_eq!(config.moniker.as_ref(), "technodrome"); assert!(config.fast_sync); - assert_eq!(config.db_backend, DbBackend::LevelDb); + assert_eq!(config.db_backend, DbBackend::GoLevelDb); assert_eq!(config.db_dir, PathBuf::from("data")); + assert_eq!(config.log_level.global, Some("info".to_string())); assert_eq!(config.log_level.get("main"), Some("info")); assert_eq!(config.log_level.get("state"), Some("info")); - assert_eq!(config.log_level.get("*"), Some("error")); + assert_eq!(config.log_level.get("*"), Some("info")); assert_eq!(config.log_format, LogFormat::Plain); assert_eq!(config.genesis_file, PathBuf::from("config/genesis.json")); assert_eq!( @@ -44,10 +45,6 @@ mod files { assert_eq!(config.priv_validator_laddr, None); assert_eq!(config.node_key_file, PathBuf::from("config/node_key.json")); assert_eq!(config.abci, AbciMode::Socket); - assert_eq!( - config.prof_laddr, - Some("tcp://localhost:6060".parse::().unwrap()) - ); assert!(!config.filter_peers); // rpc server configuration options @@ -188,9 +185,6 @@ mod files { let tx_index = &config.tx_index; assert_eq!(tx_index.indexer, TxIndexer::Kv); - assert_eq!(tx_index.index_tags.len(), 1); - assert_eq!(tx_index.index_tags[0].as_ref(), "tx.height"); - assert!(tx_index.index_all_tags); // instrumentation configuration options diff --git a/tendermint/tests/support/config/config.toml b/tendermint/tests/support/config/config.toml index d65d0be62..d13022e5a 100644 --- a/tendermint/tests/support/config/config.toml +++ b/tendermint/tests/support/config/config.toml @@ -1,7 +1,14 @@ # This is a TOML config file. # For more information, see https://github.com/toml-lang/toml -##### main base config options ##### +# NOTE: Any path below can be absolute (e.g. "/var/myawesomeapp/data") or +# relative to the home directory (e.g. "data"). The home directory is +# "$HOME/.tendermint" by default, but could be changed via $TMHOME env variable +# or --home cmd flag. + +####################################################################### +### Main Base Config Options ### +####################################################################### # TCP or UNIX socket address of the ABCI application, # or the name of an ABCI application compiled in with the Tendermint binary @@ -15,14 +22,32 @@ moniker = "technodrome" # and verifying their commits fast_sync = true -# Database backend: leveldb | memdb | cleveldb -db_backend = "leveldb" +# Database backend: goleveldb | cleveldb | boltdb | rocksdb | badgerdb +# * goleveldb (github.com/syndtr/goleveldb - most popular implementation) +# - pure go +# - stable +# * cleveldb (uses levigo wrapper) +# - fast +# - requires gcc +# - use cleveldb build tag (go build -tags cleveldb) +# * boltdb (uses etcd's fork of bolt - github.com/etcd-io/bbolt) +# - EXPERIMENTAL +# - may be faster is some use-cases (random reads - indexer) +# - use boltdb build tag (go build -tags boltdb) +# * rocksdb (uses github.com/tecbot/gorocksdb) +# - EXPERIMENTAL +# - requires gcc +# - use rocksdb build tag (go build -tags rocksdb) +# * badgerdb (uses github.com/dgraph-io/badger) +# - EXPERIMENTAL +# - use badgerdb build tag (go build -tags badgerdb) +db_backend = "goleveldb" # Database directory db_dir = "data" # Output level for logging, including package level options -log_level = "main:info,state:info,*:error" +log_level = "info" # Output format: 'plain' (colored text) or 'json' log_format = "plain" @@ -48,16 +73,18 @@ node_key_file = "config/node_key.json" # Mechanism to connect to the ABCI application: socket | grpc abci = "socket" -# TCP or UNIX socket address for the profiling server to listen on -prof_laddr = "localhost:6060" - # If true, query the ABCI app on connecting to a new peer # so the app can decide if we should keep the connection or not filter_peers = false -##### advanced configuration options ##### -##### rpc server configuration options ##### +####################################################################### +### Advanced Configuration Options ### +####################################################################### + +####################################################### +### RPC Server Configuration Options ### +####################################################### [rpc] # TCP or UNIX socket address for the RPC server to listen on @@ -115,18 +142,33 @@ max_subscriptions_per_client = 5 # See https://github.com/tendermint/tendermint/issues/3435 timeout_broadcast_tx_commit = "10s" -# The name of a file containing certificate that is used to create the HTTPS server. +# Maximum size of request body, in bytes +max_body_bytes = 1000000 + +# Maximum size of request header, in bytes +max_header_bytes = 1048576 + +# The path to a file containing certificate that is used to create the HTTPS server. +# Might be either absolute path or path related to Tendermint's config directory. # If the certificate is signed by a certificate authority, # the certFile should be the concatenation of the server's certificate, any intermediates, # and the CA's certificate. -# NOTE: both tls_cert_file and tls_key_file must be present for Tendermint to create HTTPS server. Otherwise, HTTP server is run. +# NOTE: both tls_cert_file and tls_key_file must be present for Tendermint to create HTTPS server. +# Otherwise, HTTP server is run. tls_cert_file = "" -# The name of a file containing matching private key that is used to create the HTTPS server. -# NOTE: both tls_cert_file and tls_key_file must be present for Tendermint to create HTTPS server. Otherwise, HTTP server is run. +# The path to a file containing matching private key that is used to create the HTTPS server. +# Might be either absolute path or path related to Tendermint's config directory. +# NOTE: both tls-cert-file and tls-key-file must be present for Tendermint to create HTTPS server. +# Otherwise, HTTP server is run. tls_key_file = "" -##### peer to peer configuration options ##### +# pprof listen address (https://golang.org/pkg/net/http/pprof) +pprof_laddr = "" + +####################################################### +### P2P Configuration Options ### +####################################################### [p2p] # Address to listen for incoming connections @@ -160,6 +202,12 @@ max_num_inbound_peers = 40 # Maximum number of outbound peers to connect to, excluding persistent peers max_num_outbound_peers = 10 +# List of node IDs, to which a connection will be (re)established ignoring any existing limits +unconditional_peer_ids = "" + +# Maximum pause when redialing a persistent peer (if zero, exponential backoff is used) +persistent_peers_max_dial_period = "0s" + # Time to wait before flushing messages out on the connection flush_throttle_timeout = "100ms" @@ -191,7 +239,9 @@ allow_duplicate_ip = false handshake_timeout = "20s" dial_timeout = "3s" -##### mempool configuration options ##### +####################################################### +### Mempool Configuration Option ### +####################################################### [mempool] recheck = true @@ -209,19 +259,90 @@ max_txs_bytes = 1073741824 # Size of the cache (used to filter transactions we saw earlier) in transactions cache_size = 10000 -##### consensus configuration options ##### +# Do not remove invalid transactions from the cache (default: false) +# Set to true if it's not possible for any invalid transaction to become valid +# again in the future. +keep-invalid-txs-in-cache = false + +# Maximum size of a single transaction. +# NOTE: the max size of a tx transmitted over the network is {max_tx_bytes}. +max_tx_bytes = 1048576 + +# Maximum size of a batch of transactions to send to a peer +# Including space needed by encoding (one varint per transaction). +# XXX: Unused due to https://github.com/tendermint/tendermint/issues/5796 +max_batch_bytes = 0 + +####################################################### +### State Sync Configuration Options ### +####################################################### +[statesync] +# State sync rapidly bootstraps a new node by discovering, fetching, and restoring a state machine +# snapshot from peers instead of fetching and replaying historical blocks. Requires some peers in +# the network to take and serve state machine snapshots. State sync is not attempted if the node +# has any local state (LastBlockHeight > 0). The node will have a truncated block history, +# starting from the height of the snapshot. +enable = false + +# RPC servers (comma-separated) for light client verification of the synced state machine and +# retrieval of state data for node bootstrapping. Also needs a trusted height and corresponding +# header hash obtained from a trusted source, and a period during which validators can be trusted. +# +# For Cosmos SDK-based chains, trust_period should usually be about 2/3 of the unbonding time (~2 +# weeks) during which they can be financially punished (slashed) for misbehavior. +rpc_servers = "" +trust_height = 0 +trust_hash = "" +trust_period = "168h0m0s" + +# Time to spend discovering snapshots before initiating a restore. +discovery_time = "15s" + +# Temporary directory for state sync snapshot chunks, defaults to the OS tempdir (typically /tmp). +# Will create a new, randomly named directory within, and remove it when done. +temp_dir = "" + +####################################################### +### Fast Sync Configuration Connections ### +####################################################### +[fastsync] + +# Fast Sync version to use: +# 1) "v0" (default) - the legacy fast sync implementation +# 2) "v1" - refactor of v0 version for better testability +# 2) "v2" - complete redesign of v0, optimized for testability & readability +version = "v0" + +####################################################### +### Consensus Configuration Options ### +####################################################### [consensus] wal_file = "data/cs.wal/wal" +# How long we wait for a proposal block before prevoting nil timeout_propose = "3s" +# How much timeout_propose increases with each round timeout_propose_delta = "500ms" +# How long we wait after receiving +2/3 prevotes for “anything” (ie. not a single block or nil) timeout_prevote = "1s" +# How much the timeout_prevote increases with each round timeout_prevote_delta = "500ms" +# How long we wait after receiving +2/3 precommits for “anything” (ie. not a single block or nil) timeout_precommit = "1s" +# How much the timeout_precommit increases with each round timeout_precommit_delta = "500ms" +# How long we wait after committing a block, before starting on the new +# height (this gives us a chance to receive some more precommits, even +# though we already have +2/3). timeout_commit = "5s" +# How many blocks to look back to check existence of the node's consensus votes before joining consensus +# When non-zero, the node will panic upon restart +# if the same consensus key was used to sign {double_sign_check_height} last blocks. +# So, validators should stop the state machine, wait for some blocks, and then restart the state machine to avoid panic. +double_sign_check_height = 0 + # Make progress as soon as we have all the precommits (as if TimeoutCommit = 0) skip_timeout_commit = false @@ -233,34 +354,25 @@ create_empty_blocks_interval = "0s" peer_gossip_sleep_duration = "100ms" peer_query_maj23_sleep_duration = "2s" -##### transactions indexer configuration options ##### +####################################################### +### Transaction Indexer Configuration Options ### +####################################################### [tx_index] # What indexer to use for transactions # +# The application will set which txs to index. In some cases a node operator will be able +# to decide which txs to index based on configuration set in the application. +# # Options: # 1) "null" # 2) "kv" (default) - the simplest possible indexer, backed by key-value storage (defaults to levelDB; see DBBackend). +# - When "kv" is chosen "tx.height" and "tx.hash" will always be indexed. indexer = "kv" -# Comma-separated list of tags to index (by default the only tag is "tx.hash") -# -# You can also index transactions by height by adding "tx.height" tag here. -# -# It's recommended to index only a subset of tags due to possible memory -# bloat. This is, of course, depends on the indexer's DB and the volume of -# transactions. -index_tags = "tx.height" - -# When set to true, tells indexer to index all tags (predefined tags: -# "tx.hash", "tx.height" and all tags from DeliverTx responses). -# -# Note this may be not desirable (see the comment above). IndexTags has a -# precedence over IndexAllTags (i.e. when given both, IndexTags will be -# indexed). -index_all_tags = true - -##### instrumentation configuration options ##### +####################################################### +### Instrumentation Configuration Options ### +####################################################### [instrumentation] # When true, Prometheus metrics are served under /metrics on