add consensus reactor sleep durations to the config
This commit is contained in:
parent
8355fee16a
commit
ca8c34f966
|
@ -1,5 +1,10 @@
|
|||
# Changelog
|
||||
|
||||
## 0.10.2 (TBD)
|
||||
|
||||
FEATURES:
|
||||
- Add consensus reactor sleep durations to the config
|
||||
|
||||
## 0.10.1 (June 28, 2017)
|
||||
|
||||
FEATURES:
|
||||
|
|
|
@ -5,9 +5,10 @@ import (
|
|||
"path/filepath"
|
||||
"time"
|
||||
|
||||
"github.com/tendermint/tendermint/types"
|
||||
"github.com/tendermint/tendermint/types" // TODO: remove
|
||||
)
|
||||
|
||||
// Config defines the top level configuration for a Tendermint node
|
||||
type Config struct {
|
||||
// Top level options use an anonymous struct
|
||||
BaseConfig `mapstructure:",squash"`
|
||||
|
@ -19,6 +20,7 @@ type Config struct {
|
|||
Consensus *ConsensusConfig `mapstructure:"consensus"`
|
||||
}
|
||||
|
||||
// DefaultConfig returns a default configuration for a Tendermint node
|
||||
func DefaultConfig() *Config {
|
||||
return &Config{
|
||||
BaseConfig: DefaultBaseConfig(),
|
||||
|
@ -29,6 +31,7 @@ func DefaultConfig() *Config {
|
|||
}
|
||||
}
|
||||
|
||||
// TestConfig returns a configuration that can be used for testing
|
||||
func TestConfig() *Config {
|
||||
return &Config{
|
||||
BaseConfig: TestBaseConfig(),
|
||||
|
@ -39,7 +42,7 @@ func TestConfig() *Config {
|
|||
}
|
||||
}
|
||||
|
||||
// Set the RootDir for all Config structs
|
||||
// SetRoot sets the RootDir for all Config structs
|
||||
func (cfg *Config) SetRoot(root string) *Config {
|
||||
cfg.BaseConfig.RootDir = root
|
||||
cfg.RPC.RootDir = root
|
||||
|
@ -52,7 +55,7 @@ func (cfg *Config) SetRoot(root string) *Config {
|
|||
//-----------------------------------------------------------------------------
|
||||
// BaseConfig
|
||||
|
||||
// BaseConfig struct for a Tendermint node
|
||||
// BaseConfig defines the base configuration for a Tendermint node
|
||||
type BaseConfig struct {
|
||||
// The root directory for all data.
|
||||
// This should be set in viper so it can unmarshal into this struct
|
||||
|
@ -102,6 +105,7 @@ type BaseConfig struct {
|
|||
DBPath string `mapstructure:"db_dir"`
|
||||
}
|
||||
|
||||
// DefaultBaseConfig returns a default base configuration for a Tendermint node
|
||||
func DefaultBaseConfig() BaseConfig {
|
||||
return BaseConfig{
|
||||
Genesis: "genesis.json",
|
||||
|
@ -119,6 +123,7 @@ func DefaultBaseConfig() BaseConfig {
|
|||
}
|
||||
}
|
||||
|
||||
// TestBaseConfig returns a base configuration for testing a Tendermint node
|
||||
func TestBaseConfig() BaseConfig {
|
||||
conf := DefaultBaseConfig()
|
||||
conf.ChainID = "tendermint_test"
|
||||
|
@ -128,22 +133,27 @@ func TestBaseConfig() BaseConfig {
|
|||
return conf
|
||||
}
|
||||
|
||||
// GenesisFile returns the full path to the genesis.json file
|
||||
func (b BaseConfig) GenesisFile() string {
|
||||
return rootify(b.Genesis, b.RootDir)
|
||||
}
|
||||
|
||||
// PrivValidatorFile returns the full path to the priv_validator.json file
|
||||
func (b BaseConfig) PrivValidatorFile() string {
|
||||
return rootify(b.PrivValidator, b.RootDir)
|
||||
}
|
||||
|
||||
// DBDir returns the full path to the database directory
|
||||
func (b BaseConfig) DBDir() string {
|
||||
return rootify(b.DBPath, b.RootDir)
|
||||
}
|
||||
|
||||
// DefaultLogLevel returns a default log level of "error"
|
||||
func DefaultLogLevel() string {
|
||||
return "error"
|
||||
}
|
||||
|
||||
// DefaultPackageLogLevels returns a default log level setting so all packages log at "error", while the `state` package logs at "info"
|
||||
func DefaultPackageLogLevels() string {
|
||||
return fmt.Sprintf("state:info,*:%s", DefaultLogLevel())
|
||||
}
|
||||
|
@ -151,6 +161,7 @@ func DefaultPackageLogLevels() string {
|
|||
//-----------------------------------------------------------------------------
|
||||
// RPCConfig
|
||||
|
||||
// RPCConfig defines the configuration options for the Tendermint RPC server
|
||||
type RPCConfig struct {
|
||||
RootDir string `mapstructure:"home"`
|
||||
|
||||
|
@ -165,6 +176,7 @@ type RPCConfig struct {
|
|||
Unsafe bool `mapstructure:"unsafe"`
|
||||
}
|
||||
|
||||
// DefaultRPCConfig returns a default configuration for the RPC server
|
||||
func DefaultRPCConfig() *RPCConfig {
|
||||
return &RPCConfig{
|
||||
ListenAddress: "tcp://0.0.0.0:46657",
|
||||
|
@ -173,6 +185,7 @@ func DefaultRPCConfig() *RPCConfig {
|
|||
}
|
||||
}
|
||||
|
||||
// TestRPCConfig returns a configuration for testing the RPC server
|
||||
func TestRPCConfig() *RPCConfig {
|
||||
conf := DefaultRPCConfig()
|
||||
conf.ListenAddress = "tcp://0.0.0.0:36657"
|
||||
|
@ -184,6 +197,7 @@ func TestRPCConfig() *RPCConfig {
|
|||
//-----------------------------------------------------------------------------
|
||||
// P2PConfig
|
||||
|
||||
// P2PConfig defines the configuration options for the Tendermint peer-to-peer networking layer
|
||||
type P2PConfig struct {
|
||||
RootDir string `mapstructure:"home"`
|
||||
ListenAddress string `mapstructure:"laddr"`
|
||||
|
@ -195,6 +209,7 @@ type P2PConfig struct {
|
|||
MaxNumPeers int `mapstructure:"max_num_peers"`
|
||||
}
|
||||
|
||||
// DefaultP2PConfig returns a default configuration for the peer-to-peer layer
|
||||
func DefaultP2PConfig() *P2PConfig {
|
||||
return &P2PConfig{
|
||||
ListenAddress: "tcp://0.0.0.0:46656",
|
||||
|
@ -204,6 +219,7 @@ func DefaultP2PConfig() *P2PConfig {
|
|||
}
|
||||
}
|
||||
|
||||
// TestP2PConfig returns a configuration for testing the peer-to-peer layer
|
||||
func TestP2PConfig() *P2PConfig {
|
||||
conf := DefaultP2PConfig()
|
||||
conf.ListenAddress = "tcp://0.0.0.0:36656"
|
||||
|
@ -211,6 +227,7 @@ func TestP2PConfig() *P2PConfig {
|
|||
return conf
|
||||
}
|
||||
|
||||
// AddrBookFile returns the full path to the address bool
|
||||
func (p *P2PConfig) AddrBookFile() string {
|
||||
return rootify(p.AddrBook, p.RootDir)
|
||||
}
|
||||
|
@ -218,6 +235,7 @@ func (p *P2PConfig) AddrBookFile() string {
|
|||
//-----------------------------------------------------------------------------
|
||||
// MempoolConfig
|
||||
|
||||
// MempoolConfig defines the configuration options for the Tendermint mempool
|
||||
type MempoolConfig struct {
|
||||
RootDir string `mapstructure:"home"`
|
||||
Recheck bool `mapstructure:"recheck"`
|
||||
|
@ -226,6 +244,7 @@ type MempoolConfig struct {
|
|||
WalPath string `mapstructure:"wal_dir"`
|
||||
}
|
||||
|
||||
// DefaultMempoolConfig returns a default configuration for the Tendermint mempool
|
||||
func DefaultMempoolConfig() *MempoolConfig {
|
||||
return &MempoolConfig{
|
||||
Recheck: true,
|
||||
|
@ -235,6 +254,7 @@ func DefaultMempoolConfig() *MempoolConfig {
|
|||
}
|
||||
}
|
||||
|
||||
// WalDir returns the full path to the mempool's write-ahead log
|
||||
func (m *MempoolConfig) WalDir() string {
|
||||
return rootify(m.WalPath, m.RootDir)
|
||||
}
|
||||
|
@ -242,8 +262,8 @@ func (m *MempoolConfig) WalDir() string {
|
|||
//-----------------------------------------------------------------------------
|
||||
// ConsensusConfig
|
||||
|
||||
// ConsensusConfig holds timeouts and details about the WAL, the block structure,
|
||||
// and timeouts in the consensus protocol.
|
||||
// ConsensusConfig defines the confuguration for the Tendermint consensus service,
|
||||
// including timeouts and details about the WAL and the block structure.
|
||||
type ConsensusConfig struct {
|
||||
RootDir string `mapstructure:"home"`
|
||||
WalPath string `mapstructure:"wal_file"`
|
||||
|
@ -269,46 +289,64 @@ type ConsensusConfig struct {
|
|||
// 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"`
|
||||
|
||||
// Reactor sleep duration parameters are in ms
|
||||
PeerGossipSleepDuration int `mapstructure:"peer_gossip_sleep_duration"`
|
||||
PeerQueryMaj23SleepDuration int `mapstructure:"peer_query_maj23_sleep_duration"`
|
||||
}
|
||||
|
||||
// Wait this long for a proposal
|
||||
// Propose returns the amount of time to wait 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
|
||||
// Prevote returns the amount of time to wait for straggler votes after receiving any +2/3 prevotes
|
||||
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
|
||||
// Precommit returns the amount of time to wait for straggler votes after receiving any +2/3 precommits
|
||||
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
|
||||
// Commit returns the amount of time to wait for straggler votes after receiving +2/3 precommits for a single block (ie. a commit).
|
||||
func (cfg *ConsensusConfig) Commit(t time.Time) time.Time {
|
||||
return t.Add(time.Duration(cfg.TimeoutCommit) * time.Millisecond)
|
||||
}
|
||||
|
||||
// PeerGossipSleep returns the amount of time to sleep if there is nothing to send from the ConsensusReactor
|
||||
func (cfg *ConsensusConfig) PeerGossipSleep() time.Duration {
|
||||
return time.Duration(cfg.PeerGossipSleepDuration) * time.Millisecond
|
||||
}
|
||||
|
||||
// PeerQueryMaj23Sleep returns the amount of time to sleep after each VoteSetMaj23Message is sent in the ConsensusReactor
|
||||
func (cfg *ConsensusConfig) PeerQueryMaj23Sleep() time.Duration {
|
||||
return time.Duration(cfg.PeerQueryMaj23SleepDuration) * time.Millisecond
|
||||
}
|
||||
|
||||
// DefaultConsensusConfig returns a default configuration for the consensus service
|
||||
func DefaultConsensusConfig() *ConsensusConfig {
|
||||
return &ConsensusConfig{
|
||||
WalPath: "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, // TODO: we shouldnt be importing types
|
||||
WalPath: "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, // TODO: we shouldnt be importing types
|
||||
PeerGossipSleepDuration: 100,
|
||||
PeerQueryMaj23SleepDuration: 2000,
|
||||
}
|
||||
}
|
||||
|
||||
// TestConsensusConfig returns a configuration for testing the consensus service
|
||||
func TestConsensusConfig() *ConsensusConfig {
|
||||
config := DefaultConsensusConfig()
|
||||
config.TimeoutPropose = 2000
|
||||
|
@ -322,6 +360,7 @@ func TestConsensusConfig() *ConsensusConfig {
|
|||
return config
|
||||
}
|
||||
|
||||
// WalFile returns the full path to the write-ahead log file
|
||||
func (c *ConsensusConfig) WalFile() string {
|
||||
if c.walFile != "" {
|
||||
return c.walFile
|
||||
|
@ -329,6 +368,7 @@ func (c *ConsensusConfig) WalFile() string {
|
|||
return rootify(c.WalPath, c.RootDir)
|
||||
}
|
||||
|
||||
// SetWalFile sets the path to the write-ahead log file
|
||||
func (c *ConsensusConfig) SetWalFile(walFile string) {
|
||||
c.walFile = walFile
|
||||
}
|
||||
|
|
|
@ -21,9 +21,7 @@ const (
|
|||
VoteChannel = byte(0x22)
|
||||
VoteSetBitsChannel = byte(0x23)
|
||||
|
||||
peerGossipSleepDuration = 100 * time.Millisecond // Time to sleep if there's nothing to send.
|
||||
peerQueryMaj23SleepDuration = 2 * time.Second // Time to sleep after each VoteSetMaj23Message sent
|
||||
maxConsensusMessageSize = 1048576 // 1MB; NOTE: keep in sync with types.PartSet sizes.
|
||||
maxConsensusMessageSize = 1048576 // 1MB; NOTE/TODO: keep in sync with types.PartSet sizes.
|
||||
)
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
@ -413,12 +411,12 @@ OUTER_LOOP:
|
|||
blockMeta := conR.conS.blockStore.LoadBlockMeta(prs.Height)
|
||||
if blockMeta == nil {
|
||||
logger.Error("Failed to load block meta", "peer height", prs.Height, "ourHeight", rs.Height, "blockstoreHeight", conR.conS.blockStore.Height(), "pv", conR.conS.privValidator)
|
||||
time.Sleep(peerGossipSleepDuration)
|
||||
time.Sleep(conR.conS.config.PeerGossipSleep())
|
||||
continue OUTER_LOOP
|
||||
} else if !blockMeta.BlockID.PartsHeader.Equals(prs.ProposalBlockPartsHeader) {
|
||||
logger.Info("Peer ProposalBlockPartsHeader mismatch, sleeping",
|
||||
"peerHeight", prs.Height, "blockPartsHeader", blockMeta.BlockID.PartsHeader, "peerBlockPartsHeader", prs.ProposalBlockPartsHeader)
|
||||
time.Sleep(peerGossipSleepDuration)
|
||||
time.Sleep(conR.conS.config.PeerGossipSleep())
|
||||
continue OUTER_LOOP
|
||||
}
|
||||
// Load the part
|
||||
|
@ -426,7 +424,7 @@ OUTER_LOOP:
|
|||
if part == nil {
|
||||
logger.Error("Could not load part", "index", index,
|
||||
"peerHeight", prs.Height, "blockPartsHeader", blockMeta.BlockID.PartsHeader, "peerBlockPartsHeader", prs.ProposalBlockPartsHeader)
|
||||
time.Sleep(peerGossipSleepDuration)
|
||||
time.Sleep(conR.conS.config.PeerGossipSleep())
|
||||
continue OUTER_LOOP
|
||||
}
|
||||
// Send the part
|
||||
|
@ -441,7 +439,7 @@ OUTER_LOOP:
|
|||
continue OUTER_LOOP
|
||||
} else {
|
||||
//logger.Info("No parts to send in catch-up, sleeping")
|
||||
time.Sleep(peerGossipSleepDuration)
|
||||
time.Sleep(conR.conS.config.PeerGossipSleep())
|
||||
continue OUTER_LOOP
|
||||
}
|
||||
}
|
||||
|
@ -449,7 +447,7 @@ OUTER_LOOP:
|
|||
// If height and round don't match, sleep.
|
||||
if (rs.Height != prs.Height) || (rs.Round != prs.Round) {
|
||||
//logger.Info("Peer Height|Round mismatch, sleeping", "peerHeight", prs.Height, "peerRound", prs.Round, "peer", peer)
|
||||
time.Sleep(peerGossipSleepDuration)
|
||||
time.Sleep(conR.conS.config.PeerGossipSleep())
|
||||
continue OUTER_LOOP
|
||||
}
|
||||
|
||||
|
@ -483,7 +481,7 @@ OUTER_LOOP:
|
|||
}
|
||||
|
||||
// Nothing to do. Sleep.
|
||||
time.Sleep(peerGossipSleepDuration)
|
||||
time.Sleep(conR.conS.config.PeerGossipSleep())
|
||||
continue OUTER_LOOP
|
||||
}
|
||||
}
|
||||
|
@ -581,7 +579,7 @@ OUTER_LOOP:
|
|||
sleeping = 1
|
||||
}
|
||||
|
||||
time.Sleep(peerGossipSleepDuration)
|
||||
time.Sleep(conR.conS.config.PeerGossipSleep())
|
||||
continue OUTER_LOOP
|
||||
}
|
||||
}
|
||||
|
@ -611,7 +609,7 @@ OUTER_LOOP:
|
|||
Type: types.VoteTypePrevote,
|
||||
BlockID: maj23,
|
||||
}})
|
||||
time.Sleep(peerQueryMaj23SleepDuration)
|
||||
time.Sleep(conR.conS.config.PeerQueryMaj23Sleep())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -628,7 +626,7 @@ OUTER_LOOP:
|
|||
Type: types.VoteTypePrecommit,
|
||||
BlockID: maj23,
|
||||
}})
|
||||
time.Sleep(peerQueryMaj23SleepDuration)
|
||||
time.Sleep(conR.conS.config.PeerQueryMaj23Sleep())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -645,7 +643,7 @@ OUTER_LOOP:
|
|||
Type: types.VoteTypePrevote,
|
||||
BlockID: maj23,
|
||||
}})
|
||||
time.Sleep(peerQueryMaj23SleepDuration)
|
||||
time.Sleep(conR.conS.config.PeerQueryMaj23Sleep())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -664,11 +662,11 @@ OUTER_LOOP:
|
|||
Type: types.VoteTypePrecommit,
|
||||
BlockID: commit.BlockID,
|
||||
}})
|
||||
time.Sleep(peerQueryMaj23SleepDuration)
|
||||
time.Sleep(conR.conS.config.PeerQueryMaj23Sleep())
|
||||
}
|
||||
}
|
||||
|
||||
time.Sleep(peerQueryMaj23SleepDuration)
|
||||
time.Sleep(conR.conS.config.PeerQueryMaj23Sleep())
|
||||
|
||||
continue OUTER_LOOP
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue