From 604bf03f3a539f5f27434642bf116c6fa7a3ee0f Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Thu, 4 May 2017 20:07:08 +0200 Subject: [PATCH] Pulled out all config structs (except p2p.PeerConfig) into config package --- config/config.go | 153 +++++++++++++++++++++++++++- config/tendermint/config.go | 122 ---------------------- config/tendermint_test/config.go | 170 ------------------------------- config/toml.go | 129 +++++++++++++++++++++++ consensus/replay_file.go | 4 +- consensus/state.go | 86 +--------------- glide.lock | 9 +- glide.yaml | 1 + mempool/mempool.go | 5 +- mempool/reactor.go | 21 +--- node/node.go | 36 +------ p2p/switch.go | 41 ++------ 12 files changed, 310 insertions(+), 467 deletions(-) delete mode 100644 config/tendermint/config.go delete mode 100644 config/tendermint_test/config.go create mode 100644 config/toml.go diff --git a/config/config.go b/config/config.go index 5f4f28a83..531ef9a50 100644 --- a/config/config.go +++ b/config/config.go @@ -1,7 +1,41 @@ package config -// Config struct for a Tendermint node +import ( + "time" + + "github.com/tendermint/tendermint/types" +) + type Config struct { + // Top level options use an anonymous struct + *BaseConfig `mapstructure:",squash"` + + // Options for services + P2P *P2PConfig `mapstructure:"p2p"` + Mempool *MempoolConfig `mapstructure:"mempool"` + Consensus *ConsensusConfig `mapstructure:"consensus"` +} + +func DefaultConfig(rootDir string) *Config { + return &Config{ + BaseConfig: DefaultBaseConfig(rootDir), + P2P: DefaultP2PConfig(rootDir), + Mempool: DefaultMempoolConfig(rootDir), + Consensus: DefaultConsensusConfig(rootDir), + } +} + +func TestConfig(rootDir string) *Config { + return &Config{ + BaseConfig: DefaultBaseConfig(rootDir), + P2P: DefaultP2PConfig(rootDir), + Mempool: DefaultMempoolConfig(rootDir), + Consensus: TestConsensusConfig(rootDir), + } +} + +// BaseConfig struct for a Tendermint node +type BaseConfig struct { // The ID of the chain to join (should be signed with every transaction and vote) ChainID string `mapstructure:"chain_id"` @@ -53,8 +87,8 @@ type Config struct { GRPCListenAddress string `mapstructure:"grpc_laddr"` } -func NewDefaultConfig(rootDir string) *Config { - return &Config{ +func DefaultBaseConfig(rootDir string) *BaseConfig { + return &BaseConfig{ GenesisFile: rootDir + "/genesis.json", PrivValidatorFile: rootDir + "/priv_validator.json", Moniker: "anonymous", @@ -71,3 +105,116 @@ func NewDefaultConfig(rootDir string) *Config { GRPCListenAddress: "", } } + +type P2PConfig struct { + ListenAddress string `mapstructure:"laddr"` + Seeds string `mapstructure:"seeds"` + SkipUPNP bool `mapstructure:"skip_upnp"` + AddrBookFile string `mapstructure:"addr_book_file"` + AddrBookStrict bool `mapstructure:"addr_book_strict"` + PexReactor bool `mapstructure:"pex_reactor"` + MaxNumPeers int `mapstructure:"max_num_peers"` +} + +func DefaultP2PConfig(rootDir string) *P2PConfig { + return &P2PConfig{ + ListenAddress: "tcp://0.0.0.0:46656", + AddrBookFile: rootDir + "/addrbook.json", + AddrBookStrict: true, + MaxNumPeers: 50, + } +} + +type MempoolConfig struct { + Recheck bool `mapstructure:"recheck"` // true + RecheckEmpty bool `mapstructure:"recheck_empty"` // true + Broadcast bool `mapstructure:"broadcast"` // true + WalDir string `mapstructure:"wal_dir"` // +} + +func DefaultMempoolConfig(rootDir string) *MempoolConfig { + return &MempoolConfig{ + Recheck: true, + RecheckEmpty: true, + Broadcast: true, + WalDir: rootDir + "/data/mempool.wal", + } +} + +// ConsensusConfig holds timeouts and details about the WAL, the block structure, +// and timeouts in the consensus protocol. +type ConsensusConfig struct { + WalFile string `mapstructure:"wal_file"` + WalLight bool `mapstructure:"wal_light"` + + // All timeouts are in ms + TimeoutPropose int `mapstructure:"timeout_propose"` + TimeoutProposeDelta int `mapstructure:"timeout_propose_delta"` + TimeoutPrevote int `mapstructure:"timeout_prevote"` + TimeoutPrevoteDelta int `mapstructure:"timeout_prevote_delta"` + TimeoutPrecommit int `mapstructure:"timeout_precommit"` + TimeoutPrecommitDelta int `mapstructure:"timeout_precommit_delta"` + TimeoutCommit int `mapstructure:"timeout_commit"` + + // Make progress as soon as we have all the precommits (as if TimeoutCommit = 0) + SkipTimeoutCommit bool `mapstructure:"skip_timeout_commit"` + + // BlockSize + MaxBlockSizeTxs int `mapstructure:"max_block_size_txs"` + MaxBlockSizeBytes int `mapstructure:"max_block_size_bytes"` + + // TODO: This probably shouldn't be exposed but it makes it + // easy to write tests for the wal/replay + BlockPartSize int `mapstructure:"block_part_size"` +} + +// Wait this long for a proposal +func (cfg *ConsensusConfig) Propose(round int) time.Duration { + return time.Duration(cfg.TimeoutPropose+cfg.TimeoutProposeDelta*round) * time.Millisecond +} + +// After receiving any +2/3 prevote, wait this long for stragglers +func (cfg *ConsensusConfig) Prevote(round int) time.Duration { + return time.Duration(cfg.TimeoutPrevote+cfg.TimeoutPrevoteDelta*round) * time.Millisecond +} + +// After receiving any +2/3 precommits, wait this long for stragglers +func (cfg *ConsensusConfig) Precommit(round int) time.Duration { + return time.Duration(cfg.TimeoutPrecommit+cfg.TimeoutPrecommitDelta*round) * time.Millisecond +} + +// After receiving +2/3 precommits for a single block (a commit), wait this long for stragglers in the next height's RoundStepNewHeight +func (cfg *ConsensusConfig) Commit(t time.Time) time.Time { + return t.Add(time.Duration(cfg.TimeoutCommit) * time.Millisecond) +} + +func DefaultConsensusConfig(rootDir string) *ConsensusConfig { + return &ConsensusConfig{ + WalFile: rootDir + "/data/cs.wal/wal", + WalLight: false, + TimeoutPropose: 3000, + TimeoutProposeDelta: 500, + TimeoutPrevote: 1000, + TimeoutPrevoteDelta: 500, + TimeoutPrecommit: 1000, + TimeoutPrecommitDelta: 500, + TimeoutCommit: 1000, + SkipTimeoutCommit: false, + MaxBlockSizeTxs: 10000, + MaxBlockSizeBytes: 1, // TODO + BlockPartSize: types.DefaultBlockPartSize, + } +} + +func TestConsensusConfig(rootDir string) *ConsensusConfig { + config := DefaultConsensusConfig(rootDir) + config.TimeoutPropose = 2000 + config.TimeoutProposeDelta = 1 + config.TimeoutPrevote = 10 + config.TimeoutPrevoteDelta = 1 + config.TimeoutPrecommit = 10 + config.TimeoutPrecommitDelta = 1 + config.TimeoutCommit = 10 + config.SkipTimeoutCommit = true + return config +} diff --git a/config/tendermint/config.go b/config/tendermint/config.go deleted file mode 100644 index e6757f5be..000000000 --- a/config/tendermint/config.go +++ /dev/null @@ -1,122 +0,0 @@ -package tendermint - -import ( - "os" - "path" - "strings" - - "github.com/spf13/viper" - cmn "github.com/tendermint/tmlibs/common" -) - -func getTMRoot(rootDir string) string { - if rootDir == "" { - rootDir = os.Getenv("TMHOME") - } - if rootDir == "" { - // deprecated, use TMHOME (TODO: remove in TM 0.11.0) - rootDir = os.Getenv("TMROOT") - } - if rootDir == "" { - rootDir = os.Getenv("HOME") + "/.tendermint" - } - return rootDir -} - -func initTMRoot(rootDir string) { - rootDir = getTMRoot(rootDir) - cmn.EnsureDir(rootDir, 0700) - cmn.EnsureDir(rootDir+"/data", 0700) - - configFilePath := path.Join(rootDir, "config.toml") - - // Write default config file if missing. - if !cmn.FileExists(configFilePath) { - // Ask user for moniker - // moniker := cfg.Prompt("Type hostname: ", "anonymous") - cmn.MustWriteFile(configFilePath, []byte(defaultConfig("anonymous")), 0644) - } -} - -func GetConfig(rootDir string) *viper.Viper { - rootDir = getTMRoot(rootDir) - initTMRoot(rootDir) - - config := viper.New() - config.SetConfigName("config") - config.SetConfigType("toml") - config.AddConfigPath(rootDir) - err := config.ReadInConfig() - if err != nil { - cmn.Exit(cmn.Fmt("Could not read config from directory %v: %v", rootDir, err)) - } - //config.WatchConfig() - - // Set defaults or panic - if config.IsSet("chain.chain_id") { - cmn.Exit("Cannot set 'chain_id' via config.toml") - } - //mapConfig.SetRequired("chain_id") // blows up if you try to use it before setting. - config.SetDefault("moniker", "anonymous") - config.SetDefault("log_level", "info") - config.SetDefault("prof_laddr", "") - config.SetDefault("genesis_file", rootDir+"/genesis.json") - config.SetDefault("proxy_app", "tcp://127.0.0.1:46658") - config.SetDefault("abci", "socket") - config.SetDefault("filter_peers", false) - config.SetDefault("fast_sync", true) - config.SetDefault("priv_validator_file", rootDir+"/priv_validator.json") - config.SetDefault("db_backend", "leveldb") - config.SetDefault("db_dir", rootDir+"/data") - config.SetDefault("rpc_laddr", "tcp://0.0.0.0:46657") - config.SetDefault("grpc_laddr", "") - config.SetDefault("tx_index", "kv") - - config.SetDefault("p2p.laddr", "tcp://0.0.0.0:46656") - config.SetDefault("p2p.seeds", "") - config.SetDefault("p2p.skip_upnp", false) - config.SetDefault("p2p.addrbook_file", rootDir+"/addrbook.json") - config.SetDefault("p2p.addrbook_strict", true) // disable to allow connections locally - config.SetDefault("p2p.pex_reactor", false) // enable for peer exchange - - config.SetDefault("consensus.wal_file", rootDir+"/data/cs.wal/wal") - config.SetDefault("consensus.wal_light", false) - config.SetDefault("consensus.max_block_size_txs", 10000) // max number of txs - config.SetDefault("consensus.block_part_size", 65536) // part size 64K - // all timeouts are in ms - config.SetDefault("consensus.timeout_handshake", 10000) - config.SetDefault("consensus.timeout_propose", 3000) - config.SetDefault("consensus.timeout_propose_delta", 500) - config.SetDefault("consensus.timeout_prevote", 1000) - config.SetDefault("consensus.timeout_prevote_delta", 500) - config.SetDefault("consensus.timeout_precommit", 1000) - config.SetDefault("consensus.timeout_precommit_delta", 500) - config.SetDefault("consensus.timeout_commit", 1000) - // make progress asap (no `timeout_commit`) on full precommit votes - config.SetDefault("consensus.skip_timeout_commit", false) - - config.SetDefault("mempool.recheck", true) - config.SetDefault("mempool.recheck_empty", true) - config.SetDefault("mempool.broadcast", true) - config.SetDefault("mempool.wal_dir", rootDir+"/data/mempool.wal") - - return config -} - -var defaultConfigTmpl = `# This is a TOML config file. -# For more information, see https://github.com/toml-lang/toml - -proxy_app = "tcp://127.0.0.1:46658" -moniker = "__MONIKER__" -node_laddr = "tcp://0.0.0.0:46656" -seeds = "" -fast_sync = true -db_backend = "leveldb" -log_level = "notice" -rpc_laddr = "tcp://0.0.0.0:46657" -` - -func defaultConfig(moniker string) (defaultConfig string) { - defaultConfig = strings.Replace(defaultConfigTmpl, "__MONIKER__", moniker, -1) - return -} diff --git a/config/tendermint_test/config.go b/config/tendermint_test/config.go deleted file mode 100644 index 6eb8f53d8..000000000 --- a/config/tendermint_test/config.go +++ /dev/null @@ -1,170 +0,0 @@ -// Import this in all *_test.go files to initialize ~/.tendermint_test. - -package tendermint_test - -import ( - "fmt" - "os" - "path" - "strings" - - "github.com/spf13/viper" - - . "github.com/tendermint/tmlibs/common" - "github.com/tendermint/tmlibs/logger" -) - -func init() { - // Creates ~/.tendermint_test - EnsureDir(os.Getenv("HOME")+"/.tendermint_test", 0700) -} - -func initTMRoot(rootDir string) { - // Remove ~/.tendermint_test_bak - if FileExists(rootDir + "_bak") { - err := os.RemoveAll(rootDir + "_bak") - if err != nil { - PanicSanity(err.Error()) - } - } - // Move ~/.tendermint_test to ~/.tendermint_test_bak - if FileExists(rootDir) { - err := os.Rename(rootDir, rootDir+"_bak") - if err != nil { - PanicSanity(err.Error()) - } - } - // Create new dir - EnsureDir(rootDir, 0700) - EnsureDir(rootDir+"/data", 0700) - - configFilePath := path.Join(rootDir, "config.toml") - genesisFilePath := path.Join(rootDir, "genesis.json") - privFilePath := path.Join(rootDir, "priv_validator.json") - - // Write default config file if missing. - if !FileExists(configFilePath) { - // Ask user for moniker - MustWriteFile(configFilePath, []byte(defaultConfig("anonymous")), 0644) - } - if !FileExists(genesisFilePath) { - MustWriteFile(genesisFilePath, []byte(defaultGenesis), 0644) - } - // we always overwrite the priv val - MustWriteFile(privFilePath, []byte(defaultPrivValidator), 0644) -} - -func ResetConfig(localPath string) *viper.Viper { - rootDir := os.Getenv("HOME") + "/.tendermint_test/" + localPath - initTMRoot(rootDir) - - config := viper.New() - config.SetConfigName("config") - config.SetConfigType("toml") - config.AddConfigPath(rootDir) - err := config.ReadInConfig() - if err != nil { - Exit(Fmt("Could not read config: %v", err)) - } - //config.WatchConfig() - - // Set defaults or panic - if config.IsSet("chain_id") { - Exit(fmt.Sprintf("Cannot set 'chain_id' via config.toml:\n %v\n %v\n ", config.Get("chain_id"), rootDir)) - } - - config.SetDefault("chain_id", "tendermint_test") - config.SetDefault("genesis_file", rootDir+"/genesis.json") - config.SetDefault("proxy_app", "dummy") - config.SetDefault("abci", "socket") - config.SetDefault("moniker", "anonymous") - config.SetDefault("node_laddr", "tcp://0.0.0.0:36656") - config.SetDefault("fast_sync", false) - config.SetDefault("priv_validator_file", rootDir+"/priv_validator.json") - config.SetDefault("db_backend", "memdb") - config.SetDefault("db_dir", rootDir+"/data") - config.SetDefault("log_level", "info") - config.SetDefault("rpc_laddr", "tcp://0.0.0.0:36657") - config.SetDefault("grpc_laddr", "tcp://0.0.0.0:36658") - config.SetDefault("prof_laddr", "") - config.SetDefault("filter_peers", false) - config.SetDefault("tx_index", "kv") - - config.SetDefault("p2p.laddr", "tcp://0.0.0.0:36656") - config.SetDefault("p2p.skip_upnp", true) - config.SetDefault("p2p.addrbook_file", rootDir+"/addrbook.json") - config.SetDefault("p2p.addrbook_strict", true) // disable to allow connections locally - config.SetDefault("p2p.pex_reactor", false) // enable for peer exchange - - config.SetDefault("consensus.wal_file", rootDir+"/data/cs.wal/wal") - config.SetDefault("consensus.wal_light", false) - config.SetDefault("consensus.max_block_size_txs", 10000) - config.SetDefault("consensus.block_part_size", 65536) // part size 64K - config.SetDefault("consensus.timeout_handshake", 10000) - config.SetDefault("consensus.timeout_propose", 2000) - config.SetDefault("consensus.timeout_propose_delta", 1) - config.SetDefault("consensus.timeout_prevote", 10) - config.SetDefault("consensus.timeout_prevote_delta", 1) - config.SetDefault("consensus.timeout_precommit", 10) - config.SetDefault("consensus.timeout_precommit_delta", 1) - config.SetDefault("consensus.timeout_commit", 10) - config.SetDefault("consensus.skip_timeout_commit", true) - - config.SetDefault("mempool.recheck", true) - config.SetDefault("mempool.recheck_empty", true) - config.SetDefault("mempool.broadcast", true) - config.SetDefault("mempool.wal_dir", "") - - logger.SetLogLevel(config.GetString("log_level")) - - return config -} - -var defaultConfigTmpl = `# This is a TOML config file. -# For more information, see https://github.com/toml-lang/toml - -proxy_app = "dummy" -moniker = "__MONIKER__" -node_laddr = "tcp://0.0.0.0:36656" -seeds = "" -fast_sync = false -db_backend = "memdb" -log_level = "info" -rpc_laddr = "tcp://0.0.0.0:36657" -` - -func defaultConfig(moniker string) (defaultConfig string) { - defaultConfig = strings.Replace(defaultConfigTmpl, "__MONIKER__", moniker, -1) - return -} - -var defaultGenesis = `{ - "genesis_time": "0001-01-01T00:00:00.000Z", - "chain_id": "tendermint_test", - "validators": [ - { - "pub_key": { - "type": "ed25519", - "data":"3B3069C422E19688B45CBFAE7BB009FC0FA1B1EA86593519318B7214853803C8" - }, - "amount": 10, - "name": "" - } - ], - "app_hash": "" -}` - -var defaultPrivValidator = `{ - "address": "D028C9981F7A87F3093672BF0D5B0E2A1B3ED456", - "pub_key": { - "type": "ed25519", - "data": "3B3069C422E19688B45CBFAE7BB009FC0FA1B1EA86593519318B7214853803C8" - }, - "priv_key": { - "type": "ed25519", - "data": "27F82582AEFAE7AB151CFB01C48BB6C1A0DA78F9BDDA979A9F70A84D074EB07D3B3069C422E19688B45CBFAE7BB009FC0FA1B1EA86593519318B7214853803C8" - }, - "last_height": 0, - "last_round": 0, - "last_step": 0 -}` diff --git a/config/toml.go b/config/toml.go new file mode 100644 index 000000000..a9e6ba302 --- /dev/null +++ b/config/toml.go @@ -0,0 +1,129 @@ +package config + +import ( + "os" + "path" + "strings" + + cmn "github.com/tendermint/tmlibs/common" +) + +/****** these are for production settings ***********/ + +func initRoot(rootDir string) { + cmn.EnsureDir(rootDir, 0700) + cmn.EnsureDir(rootDir+"/data", 0700) + + configFilePath := path.Join(rootDir, "config.toml") + + // Write default config file if missing. + if !cmn.FileExists(configFilePath) { + // Ask user for moniker + // moniker := cfg.Prompt("Type hostname: ", "anonymous") + cmn.MustWriteFile(configFilePath, []byte(defaultConfig("anonymous")), 0644) + } +} + +var defaultConfigTmpl = `# This is a TOML config file. +# For more information, see https://github.com/toml-lang/toml + +proxy_app = "tcp://127.0.0.1:46658" +moniker = "__MONIKER__" +node_laddr = "tcp://0.0.0.0:46656" +seeds = "" +fast_sync = true +db_backend = "leveldb" +log_level = "notice" +rpc_laddr = "tcp://0.0.0.0:46657" +` + +func defaultConfig(moniker string) (defaultConfig string) { + defaultConfig = strings.Replace(defaultConfigTmpl, "__MONIKER__", moniker, -1) + return +} + +/****** these are for test settings ***********/ + +func initTestRoot(rootDir string) { + // Remove ~/.tendermint_test_bak + if cmn.FileExists(rootDir + "_bak") { + err := os.RemoveAll(rootDir + "_bak") + if err != nil { + cmn.PanicSanity(err.Error()) + } + } + // Move ~/.tendermint_test to ~/.tendermint_test_bak + if cmn.FileExists(rootDir) { + err := os.Rename(rootDir, rootDir+"_bak") + if err != nil { + cmn.PanicSanity(err.Error()) + } + } + // Create new dir + cmn.EnsureDir(rootDir, 0700) + cmn.EnsureDir(rootDir+"/data", 0700) + + configFilePath := path.Join(rootDir, "config.toml") + genesisFilePath := path.Join(rootDir, "genesis.json") + privFilePath := path.Join(rootDir, "priv_validator.json") + + // Write default config file if missing. + if !cmn.FileExists(configFilePath) { + // Ask user for moniker + cmn.MustWriteFile(configFilePath, []byte(testConfig("anonymous")), 0644) + } + if !cmn.FileExists(genesisFilePath) { + cmn.MustWriteFile(genesisFilePath, []byte(testGenesis), 0644) + } + // we always overwrite the priv val + cmn.MustWriteFile(privFilePath, []byte(testPrivValidator), 0644) +} + +var testConfigTmpl = `# This is a TOML config file. +# For more information, see https://github.com/toml-lang/toml + +proxy_app = "dummy" +moniker = "__MONIKER__" +node_laddr = "tcp://0.0.0.0:36656" +seeds = "" +fast_sync = false +db_backend = "memdb" +log_level = "info" +rpc_laddr = "tcp://0.0.0.0:36657" +` + +func testConfig(moniker string) (testConfig string) { + testConfig = strings.Replace(testConfigTmpl, "__MONIKER__", moniker, -1) + return +} + +var testGenesis = `{ + "genesis_time": "0001-01-01T00:00:00.000Z", + "chain_id": "tendermint_test", + "validators": [ + { + "pub_key": { + "type": "ed25519", + "data":"3B3069C422E19688B45CBFAE7BB009FC0FA1B1EA86593519318B7214853803C8" + }, + "amount": 10, + "name": "" + } + ], + "app_hash": "" +}` + +var testPrivValidator = `{ + "address": "D028C9981F7A87F3093672BF0D5B0E2A1B3ED456", + "pub_key": { + "type": "ed25519", + "data": "3B3069C422E19688B45CBFAE7BB009FC0FA1B1EA86593519318B7214853803C8" + }, + "priv_key": { + "type": "ed25519", + "data": "27F82582AEFAE7AB151CFB01C48BB6C1A0DA78F9BDDA979A9F70A84D074EB07D3B3069C422E19688B45CBFAE7BB009FC0FA1B1EA86593519318B7214853803C8" + }, + "last_height": 0, + "last_round": 0, + "last_step": 0 +}` diff --git a/consensus/replay_file.go b/consensus/replay_file.go index 4e0f40b65..2db228c91 100644 --- a/consensus/replay_file.go +++ b/consensus/replay_file.go @@ -20,7 +20,7 @@ import ( //-------------------------------------------------------- // replay messages interactively or all at once -func RunReplayFile(config *cfg.Config, csConfig *Config, console bool) { +func RunReplayFile(config *cfg.Config, csConfig *cfg.ConsensusConfig, console bool) { consensusState := newConsensusStateForReplay(config, csConfig) if err := consensusState.ReplayFile(csConfig.WalFile, console); err != nil { @@ -235,7 +235,7 @@ func (pb *playback) replayConsoleLoop() int { //-------------------------------------------------------------------------------- // convenience for replay mode -func newConsensusStateForReplay(config *cfg.Config, csConfig *Config) *ConsensusState { +func newConsensusStateForReplay(config *cfg.Config, csConfig *cfg.ConsensusConfig) *ConsensusState { // Get BlockStore blockStoreDB := dbm.NewDB("blockstore", config.DBBackend, config.DBDir) blockStore := bc.NewBlockStore(blockStoreDB) diff --git a/consensus/state.go b/consensus/state.go index e7b6381c2..a565dfdce 100644 --- a/consensus/state.go +++ b/consensus/state.go @@ -9,9 +9,9 @@ import ( "sync" "time" - "github.com/ebuchman/fail-test" - + fail "github.com/ebuchman/fail-test" "github.com/tendermint/go-wire" + cfg "github.com/tendermint/tendermint/config" "github.com/tendermint/tendermint/proxy" sm "github.com/tendermint/tendermint/state" "github.com/tendermint/tendermint/types" @@ -21,84 +21,6 @@ import ( //----------------------------------------------------------------------------- // Config -// Config holds timeouts and details about the WAL, the block structure, -// and timeouts in the consensus protocol. -type Config struct { - WalFile string `mapstructure:"wal_file"` - WalLight bool `mapstructure:"wal_light"` - - // All timeouts are in ms - TimeoutPropose int `mapstructure:"timeout_propose"` - TimeoutProposeDelta int `mapstructure:"timeout_propose_delta"` - TimeoutPrevote int `mapstructure:"timeout_prevote"` - TimeoutPrevoteDelta int `mapstructure:"timeout_prevote_delta"` - TimeoutPrecommit int `mapstructure:"timeout_precommit"` - TimeoutPrecommitDelta int `mapstructure:"timeout_precommit_delta"` - TimeoutCommit int `mapstructure:"timeout_commit"` - - // Make progress as soon as we have all the precommits (as if TimeoutCommit = 0) - SkipTimeoutCommit bool `mapstructure:"skip_timeout_commit"` - - // BlockSize - MaxBlockSizeTxs int `mapstructure:"max_block_size_txs"` - MaxBlockSizeBytes int `mapstructure:"max_block_size_bytes"` - - // TODO: This probably shouldn't be exposed but it makes it - // easy to write tests for the wal/replay - BlockPartSize int `mapstructure:"block_part_size"` -} - -func NewDefaultConfig(rootDir string) *Config { - return &Config{ - WalFile: rootDir + "/data/cs.wal/wal", - WalLight: false, - TimeoutPropose: 3000, - TimeoutProposeDelta: 500, - TimeoutPrevote: 1000, - TimeoutPrevoteDelta: 500, - TimeoutPrecommit: 1000, - TimeoutPrecommitDelta: 500, - TimeoutCommit: 1000, - SkipTimeoutCommit: false, - MaxBlockSizeTxs: 10000, - MaxBlockSizeBytes: 1, // TODO - BlockPartSize: types.DefaultBlockPartSize, - } -} - -func NewTestConfig(rootDir string) *Config { - config := NewDefaultConfig(rootDir) - config.TimeoutPropose = 2000 - config.TimeoutProposeDelta = 1 - config.TimeoutPrevote = 10 - config.TimeoutPrevoteDelta = 1 - config.TimeoutPrecommit = 10 - config.TimeoutPrecommitDelta = 1 - config.TimeoutCommit = 10 - config.SkipTimeoutCommit = true - return config -} - -// Wait this long for a proposal -func (cfg *Config) Propose(round int) time.Duration { - return time.Duration(cfg.TimeoutPropose+cfg.TimeoutProposeDelta*round) * time.Millisecond -} - -// After receiving any +2/3 prevote, wait this long for stragglers -func (cfg *Config) Prevote(round int) time.Duration { - return time.Duration(cfg.TimeoutPrevote+cfg.TimeoutPrevoteDelta*round) * time.Millisecond -} - -// After receiving any +2/3 precommits, wait this long for stragglers -func (cfg *Config) Precommit(round int) time.Duration { - return time.Duration(cfg.TimeoutPrecommit+cfg.TimeoutPrecommitDelta*round) * time.Millisecond -} - -// After receiving +2/3 precommits for a single block (a commit), wait this long for stragglers in the next height's RoundStepNewHeight -func (cfg *Config) Commit(t time.Time) time.Time { - return t.Add(time.Duration(cfg.TimeoutCommit) * time.Millisecond) -} - //----------------------------------------------------------------------------- // Errors @@ -255,7 +177,7 @@ type ConsensusState struct { cmn.BaseService // config details - config *Config + config *cfg.ConsensusConfig privValidator PrivValidator // for signing votes // services for creating and executing blocks @@ -295,7 +217,7 @@ type ConsensusState struct { done chan struct{} } -func NewConsensusState(config *Config, state *sm.State, proxyAppConn proxy.AppConnConsensus, blockStore types.BlockStore, mempool types.Mempool) *ConsensusState { +func NewConsensusState(config *cfg.ConsensusConfig, state *sm.State, proxyAppConn proxy.AppConnConsensus, blockStore types.BlockStore, mempool types.Mempool) *ConsensusState { cs := &ConsensusState{ config: config, proxyAppConn: proxyAppConn, diff --git a/glide.lock b/glide.lock index b78270bd7..0f1426f3d 100644 --- a/glide.lock +++ b/glide.lock @@ -1,5 +1,5 @@ -hash: 6f8962f6ca0e25b8e43bc6e496bd46c9ff3a79dcf789578efeeaee2fffc39c6e -updated: 2017-04-27T19:56:37.342860938-04:00 +hash: 1bdb98b332fc88df3659092ce571b74851f54465c11d91e273a10098dd4d8011 +updated: 2017-05-04T19:50:25.718540841+02:00 imports: - name: github.com/btcsuite/btcd version: 4b348c1d33373d672edd83fc576892d0e46686d2 @@ -56,7 +56,7 @@ imports: - name: github.com/pelletier/go-toml version: 13d49d4606eb801b8f01ae542b4afc4c6ee3d84a - name: github.com/pkg/errors - version: 645ef00459ed84a119197bfb8d8205042c6df63d + version: bfd5150e4e41705ded2129ec33379de1cb90b513 - name: github.com/pmezard/go-difflib version: d8ed2627bdf02c080bf22230dbb337003b7aba2d subpackages: @@ -119,7 +119,7 @@ imports: subpackages: - term - name: github.com/tendermint/merkleeyes - version: ea4dd9c7b773435de26bf59fddf90afd43a07d67 + version: 0fab643ccac1a3f93b90e0e2682a5d1b9d17f8c4 subpackages: - app - client @@ -129,6 +129,7 @@ imports: version: df250b69416a35a943a6e2a92118667e9ef031d4 subpackages: - autofile + - cli - clist - common - db diff --git a/glide.yaml b/glide.yaml index f06a16b3b..238b4ec0c 100644 --- a/glide.yaml +++ b/glide.yaml @@ -31,6 +31,7 @@ import: version: develop subpackages: - autofile + - cli - clist - common - db diff --git a/mempool/mempool.go b/mempool/mempool.go index daf9f6524..6b168897c 100644 --- a/mempool/mempool.go +++ b/mempool/mempool.go @@ -12,6 +12,7 @@ import ( "github.com/tendermint/tmlibs/clist" cmn "github.com/tendermint/tmlibs/common" + cfg "github.com/tendermint/tendermint/config" "github.com/tendermint/tendermint/proxy" "github.com/tendermint/tendermint/types" ) @@ -47,7 +48,7 @@ TODO: Better handle abci client errors. (make it automatically handle connection const cacheSize = 100000 type Mempool struct { - config *Config + config *cfg.MempoolConfig proxyMtx sync.Mutex proxyAppConn proxy.AppConnMempool @@ -66,7 +67,7 @@ type Mempool struct { wal *auto.AutoFile } -func NewMempool(config *Config, proxyAppConn proxy.AppConnMempool) *Mempool { +func NewMempool(config *cfg.MempoolConfig, proxyAppConn proxy.AppConnMempool) *Mempool { mempool := &Mempool{ config: config, proxyAppConn: proxyAppConn, diff --git a/mempool/reactor.go b/mempool/reactor.go index a0e7d518c..169228982 100644 --- a/mempool/reactor.go +++ b/mempool/reactor.go @@ -10,6 +10,7 @@ import ( "github.com/tendermint/go-wire" "github.com/tendermint/tmlibs/clist" + cfg "github.com/tendermint/tendermint/config" "github.com/tendermint/tendermint/p2p" "github.com/tendermint/tendermint/types" ) @@ -21,31 +22,15 @@ const ( peerCatchupSleepIntervalMS = 100 // If peer is behind, sleep this amount ) -type Config struct { - Recheck bool `mapstructure:"recheck"` // true - RecheckEmpty bool `mapstructure:"recheck_empty"` // true - Broadcast bool `mapstructure:"broadcast"` // true - WalDir string `mapstructure:"wal_dir"` // -} - -func NewDefaultConfig(rootDir string) *Config { - return &Config{ - Recheck: true, - RecheckEmpty: true, - Broadcast: true, - WalDir: rootDir + "/data/mempool.wal", - } -} - // MempoolReactor handles mempool tx broadcasting amongst peers. type MempoolReactor struct { p2p.BaseReactor - config *Config + config *cfg.MempoolConfig Mempool *Mempool evsw types.EventSwitch } -func NewMempoolReactor(config *Config, mempool *Mempool) *MempoolReactor { +func NewMempoolReactor(config *cfg.MempoolConfig, mempool *Mempool) *MempoolReactor { memR := &MempoolReactor{ config: config, Mempool: mempool, diff --git a/node/node.go b/node/node.go index e4f945ee3..b206c2ad9 100644 --- a/node/node.go +++ b/node/node.go @@ -7,14 +7,11 @@ import ( "net/http" "strings" - "github.com/spf13/viper" - abci "github.com/tendermint/abci/types" crypto "github.com/tendermint/go-crypto" wire "github.com/tendermint/go-wire" bc "github.com/tendermint/tendermint/blockchain" cfg "github.com/tendermint/tendermint/config" - // tmcfg "github.com/tendermint/tendermint/config/tendermint" "github.com/tendermint/tendermint/consensus" mempl "github.com/tendermint/tendermint/mempool" p2p "github.com/tendermint/tendermint/p2p" @@ -35,38 +32,11 @@ import ( _ "net/http/pprof" ) -type Config struct { - // Top level options use an anonymous struct - cfg.Config `mapstructure:",squash"` - - // Options for services - P2P *p2p.Config `mapstructure:"p2p"` - Mempool *mempl.Config `mapstructure:"mempool"` - Consensus *consensus.Config `mapstructure:"consensus"` -} - -func NewDefaultConfig(rootDir string) *Config { - return &Config{ - Config: *cfg.NewDefaultConfig(rootDir), - P2P: p2p.NewDefaultConfig(rootDir), - Mempool: mempl.NewDefaultConfig(rootDir), - Consensus: consensus.NewDefaultConfig(rootDir), - } -} - -func ConfigFromViper(viperConfig *viper.Viper) *Config { - tmConfig := new(Config) - if err := viperConfig.Unmarshal(tmConfig); err != nil { - panic(err) - } - return tmConfig -} - type Node struct { cmn.BaseService // config - config *Config + config *cfg.Config genesisDoc *types.GenesisDoc // initial validator set privValidator *types.PrivValidator // local node's validator key @@ -87,14 +57,14 @@ type Node struct { txIndexer txindex.TxIndexer } -func NewNodeDefault(config *Config) *Node { +func NewNodeDefault(config *cfg.Config) *Node { // Get PrivValidator privValidator := types.LoadOrGenPrivValidator(config.PrivValidatorFile) return NewNode(config, privValidator, proxy.DefaultClientCreator(config.ProxyApp, config.ABCI, config.DBDir)) } -func NewNode(config *Config, privValidator *types.PrivValidator, clientCreator proxy.ClientCreator) *Node { +func NewNode(config *cfg.Config, privValidator *types.PrivValidator, clientCreator proxy.ClientCreator) *Node { // Get BlockStore blockStoreDB := dbm.NewDB("blockstore", config.DBBackend, config.DBDir) diff --git a/p2p/switch.go b/p2p/switch.go index 49d817f20..9fe001eff 100644 --- a/p2p/switch.go +++ b/p2p/switch.go @@ -9,6 +9,7 @@ import ( crypto "github.com/tendermint/go-crypto" "github.com/tendermint/log15" + cfg "github.com/tendermint/tendermint/config" cmn "github.com/tendermint/tmlibs/common" ) @@ -17,29 +18,6 @@ const ( reconnectInterval = 3 * time.Second ) -// for node.Config -type Config struct { - ListenAddress string `mapstructure:"laddr"` - Seeds string `mapstructure:"seeds"` - SkipUPNP bool `mapstructure:"skip_upnp"` - AddrBookFile string `mapstructure:"addr_book_file"` - AddrBookStrict bool `mapstructure:"addr_book_strict"` - PexReactor bool `mapstructure:"pex_reactor"` - MaxNumPeers int `mapstructure:"max_num_peers"` - - peer *PeerConfig // Not exposed -} - -func NewDefaultConfig(rootDir string) *Config { - return &Config{ - ListenAddress: "tcp://0.0.0.0:46656", - AddrBookFile: rootDir + "/addrbook.json", - AddrBookStrict: true, - MaxNumPeers: 50, - peer: DefaultPeerConfig(), - } -} - type Reactor interface { cmn.Service // Start, Stop @@ -83,7 +61,8 @@ incoming messages are received on the reactor. type Switch struct { cmn.BaseService - config *Config + config *cfg.P2PConfig + peerConfig *PeerConfig listeners []Listener reactors map[string]Reactor chDescs []*ChannelDescriptor @@ -102,10 +81,10 @@ var ( ErrSwitchMaxPeersPerIPRange = errors.New("IP range has too many peers") ) -func NewSwitch(config *Config) *Switch { - config.peer = DefaultPeerConfig() +func NewSwitch(config *cfg.P2PConfig) *Switch { sw := &Switch{ config: config, + peerConfig: DefaultPeerConfig(), reactors: make(map[string]Reactor), chDescs: make([]*ChannelDescriptor, 0), reactorsByCh: make(map[byte]Reactor), @@ -229,7 +208,7 @@ func (sw *Switch) AddPeer(peer *Peer) error { return err } - if err := peer.HandshakeTimeout(sw.nodeInfo, time.Duration(sw.config.peer.HandshakeTimeout*time.Second)); err != nil { + if err := peer.HandshakeTimeout(sw.nodeInfo, time.Duration(sw.peerConfig.HandshakeTimeout*time.Second)); err != nil { return err } @@ -338,7 +317,7 @@ func (sw *Switch) DialPeerWithAddress(addr *NetAddress, persistent bool) (*Peer, sw.dialing.Set(addr.IP.String(), addr) defer sw.dialing.Delete(addr.IP.String()) - peer, err := newOutboundPeerWithConfig(addr, sw.reactorsByCh, sw.chDescs, sw.StopPeerForError, sw.nodePrivKey, sw.config.peer) + peer, err := newOutboundPeerWithConfig(addr, sw.reactorsByCh, sw.chDescs, sw.StopPeerForError, sw.nodePrivKey, sw.peerConfig) if err != nil { log.Info("Failed dialing peer", "address", addr, "error", err) return nil, err @@ -457,7 +436,7 @@ func (sw *Switch) listenerRoutine(l Listener) { } // New inbound connection! - err := sw.addPeerWithConnectionAndConfig(inConn, sw.config.peer) + err := sw.addPeerWithConnectionAndConfig(inConn, sw.peerConfig) if err != nil { log.Notice("Ignoring inbound connection: error while adding peer", "address", inConn.RemoteAddr().String(), "error", err) continue @@ -489,7 +468,7 @@ type SwitchEventDonePeer struct { // If connect==Connect2Switches, the switches will be fully connected. // initSwitch defines how the ith switch should be initialized (ie. with what reactors). // NOTE: panics if any switch fails to start. -func MakeConnectedSwitches(cfg *Config, n int, initSwitch func(int, *Switch) *Switch, connect func([]*Switch, int, int)) []*Switch { +func MakeConnectedSwitches(cfg *cfg.P2PConfig, n int, initSwitch func(int, *Switch) *Switch, connect func([]*Switch, int, int)) []*Switch { switches := make([]*Switch, n) for i := 0; i < n; i++ { switches[i] = makeSwitch(cfg, i, "testing", "123.123.123", initSwitch) @@ -546,7 +525,7 @@ func StartSwitches(switches []*Switch) error { return nil } -func makeSwitch(cfg *Config, i int, network, version string, initSwitch func(int, *Switch) *Switch) *Switch { +func makeSwitch(cfg *cfg.P2PConfig, i int, network, version string, initSwitch func(int, *Switch) *Switch) *Switch { privKey := crypto.GenPrivKeyEd25519() // new switch, add reactors // TODO: let the config be passed in?