CreateEmptyBlocks and CreateEmptyBlocksInterval
This commit is contained in:
parent
fb47ca6d35
commit
37f1390473
|
@ -3,7 +3,8 @@
|
|||
## 0.10.3 (TBD)
|
||||
|
||||
FEATURES:
|
||||
- New `--consensus.no_empty_blocks` flag prevents the creation of blocks until there are transactions available
|
||||
- New `--consensus.create_empty_blocks` flag; when set to false, only creates blocks when there are txs or when the AppHash changes
|
||||
- New `consensus.create_empty_blocks_interval` config option; when greater than 0, will create an empty block after waiting that many seconds
|
||||
|
||||
## 0.10.2 (July 10, 2017)
|
||||
|
||||
|
|
|
@ -47,7 +47,7 @@ func AddNodeFlags(cmd *cobra.Command) {
|
|||
cmd.Flags().Bool("p2p.pex", config.P2P.PexReactor, "Enable Peer-Exchange (dev feature)")
|
||||
|
||||
// consensus flags
|
||||
cmd.Flags().Bool("consensus.no_empty_blocks", config.Consensus.NoEmptyBlocks, "Only produce blocks when there are txs and when the AppHash changes")
|
||||
cmd.Flags().Bool("consensus.create_empty_blocks", config.Consensus.CreateEmptyBlocks, "Set this to false to only produce blocks when there are txs or when the AppHash changes")
|
||||
}
|
||||
|
||||
// Users wishing to:
|
||||
|
|
|
@ -301,9 +301,12 @@ type ConsensusConfig struct {
|
|||
SkipTimeoutCommit bool `mapstructure:"skip_timeout_commit"`
|
||||
|
||||
// BlockSize
|
||||
MaxBlockSizeTxs int `mapstructure:"max_block_size_txs"`
|
||||
MaxBlockSizeBytes int `mapstructure:"max_block_size_bytes"`
|
||||
NoEmptyBlocks bool `mapstructure:"no_empty_blocks"`
|
||||
MaxBlockSizeTxs int `mapstructure:"max_block_size_txs"`
|
||||
MaxBlockSizeBytes int `mapstructure:"max_block_size_bytes"`
|
||||
|
||||
// EmptyBlocks mode and possible interval between empty blocks in seconds
|
||||
CreateEmptyBlocks bool `mapstructure:"create_empty_blocks"`
|
||||
CreateEmptyBlocksInterval int `mapstructure:"create_empty_blocks_interval"`
|
||||
|
||||
// TODO: This probably shouldn't be exposed but it makes it
|
||||
// easy to write tests for the wal/replay
|
||||
|
@ -314,6 +317,16 @@ type ConsensusConfig struct {
|
|||
PeerQueryMaj23SleepDuration int `mapstructure:"peer_query_maj23_sleep_duration"`
|
||||
}
|
||||
|
||||
// WaitForTxs returns true if the consensus should wait for transactions before entering the propose step
|
||||
func (cfg *ConsensusConfig) WaitForTxs() bool {
|
||||
return !cfg.CreateEmptyBlocks || cfg.CreateEmptyBlocksInterval > 0
|
||||
}
|
||||
|
||||
// EmptyBlocks returns the amount of time to wait before proposing an empty block or starting the propose timer if there are no txs available
|
||||
func (cfg *ConsensusConfig) EmptyBlocks() time.Duration {
|
||||
return time.Duration(cfg.CreateEmptyBlocksInterval) * time.Second
|
||||
}
|
||||
|
||||
// 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
|
||||
|
@ -359,7 +372,8 @@ func DefaultConsensusConfig() *ConsensusConfig {
|
|||
SkipTimeoutCommit: false,
|
||||
MaxBlockSizeTxs: 10000,
|
||||
MaxBlockSizeBytes: 1, // TODO
|
||||
NoEmptyBlocks: false,
|
||||
CreateEmptyBlocks: true,
|
||||
CreateEmptyBlocksInterval: 0,
|
||||
BlockPartSize: types.DefaultBlockPartSize, // TODO: we shouldnt be importing types
|
||||
PeerGossipSleepDuration: 100,
|
||||
PeerQueryMaj23SleepDuration: 2000,
|
||||
|
|
|
@ -242,7 +242,7 @@ func newConsensusStateWithConfig(thisConfig *cfg.Config, state *sm.State, pv *ty
|
|||
// Make Mempool
|
||||
mempool := mempl.NewMempool(thisConfig.Mempool, proxyAppConnMem, 0)
|
||||
mempool.SetLogger(log.TestingLogger().With("module", "mempool"))
|
||||
if thisConfig.Consensus.NoEmptyBlocks {
|
||||
if thisConfig.Consensus.WaitForTxs() {
|
||||
mempool.EnableTxsAvailable()
|
||||
}
|
||||
|
||||
|
|
|
@ -17,7 +17,7 @@ func init() {
|
|||
|
||||
func TestNoProgressUntilTxsAvailable(t *testing.T) {
|
||||
config := ResetConfig("consensus_mempool_txs_available_test")
|
||||
config.Consensus.NoEmptyBlocks = true
|
||||
config.Consensus.CreateEmptyBlocks = false
|
||||
state, privVals := randGenesisState(1, false, 10)
|
||||
cs := newConsensusStateWithConfig(config, state, privVals[0], NewCounterApplication())
|
||||
cs.mempool.EnableTxsAvailable()
|
||||
|
@ -36,7 +36,7 @@ func TestNoProgressUntilTxsAvailable(t *testing.T) {
|
|||
|
||||
func TestProgressInHigherRound(t *testing.T) {
|
||||
config := ResetConfig("consensus_mempool_txs_available_test")
|
||||
config.Consensus.NoEmptyBlocks = true
|
||||
config.Consensus.CreateEmptyBlocks = false
|
||||
state, privVals := randGenesisState(1, false, 10)
|
||||
cs := newConsensusStateWithConfig(config, state, privVals[0], NewCounterApplication())
|
||||
cs.mempool.EnableTxsAvailable()
|
||||
|
|
|
@ -718,6 +718,8 @@ func (cs *ConsensusState) handleTimeout(ti timeoutInfo, rs RoundState) {
|
|||
// NewRound event fired from enterNewRound.
|
||||
// XXX: should we fire timeout here (for timeout commit)?
|
||||
cs.enterNewRound(ti.Height, 0)
|
||||
case RoundStepNewRound:
|
||||
cs.enterPropose(ti.Height, 0)
|
||||
case RoundStepPropose:
|
||||
types.FireEventTimeoutPropose(cs.evsw, cs.RoundStateEvent())
|
||||
cs.enterPrevote(ti.Height, ti.Round)
|
||||
|
@ -790,8 +792,11 @@ func (cs *ConsensusState) enterNewRound(height int, round int) {
|
|||
// Wait for txs to be available in the mempool
|
||||
// before we enterPropose in round 0. If the last block changed the app hash,
|
||||
// we may need an empty "proof" block, and enterPropose immediately.
|
||||
waitForTxs := cs.config.NoEmptyBlocks && round == 0 && !cs.needProofBlock(height)
|
||||
waitForTxs := cs.config.WaitForTxs() && round == 0 && !cs.needProofBlock(height)
|
||||
if waitForTxs {
|
||||
if cs.config.CreateEmptyBlocksInterval > 0 {
|
||||
cs.scheduleTimeout(cs.config.EmptyBlocks(), height, round, RoundStepNewRound)
|
||||
}
|
||||
go cs.proposalHeartbeat(height, round)
|
||||
} else {
|
||||
cs.enterPropose(height, round)
|
||||
|
@ -841,8 +846,9 @@ func (cs *ConsensusState) proposalHeartbeat(height, round int) {
|
|||
}
|
||||
}
|
||||
|
||||
// Enter (!NoEmptyBlocks): from enterNewRound(height,round)
|
||||
// Enter (NoEmptyBlocks) : after enterNewRound(height,round), once txs are in the mempool
|
||||
// Enter (CreateEmptyBlocks): from enterNewRound(height,round)
|
||||
// Enter (CreateEmptyBlocks, CreateEmptyBlocksInterval > 0 ): after enterNewRound(height,round), after timeout of CreateEmptyBlocksInterval
|
||||
// Enter (!CreateEmptyBlocks) : after enterNewRound(height,round), once txs are in the mempool
|
||||
func (cs *ConsensusState) enterPropose(height int, round int) {
|
||||
if cs.Height != height || round < cs.Round || (cs.Round == round && RoundStepPropose <= cs.Step) {
|
||||
cs.Logger.Debug(cmn.Fmt("enterPropose(%v/%v): Invalid args. Current step: %v/%v/%v", height, round, cs.Height, cs.Round, cs.Step))
|
||||
|
|
|
@ -142,7 +142,7 @@ func NewNode(config *cfg.Config, privValidator *types.PrivValidator, clientCreat
|
|||
mempoolReactor := mempl.NewMempoolReactor(config.Mempool, mempool)
|
||||
mempoolReactor.SetLogger(mempoolLogger)
|
||||
|
||||
if config.Consensus.NoEmptyBlocks {
|
||||
if config.Consensus.WaitForTxs() {
|
||||
mempool.EnableTxsAvailable()
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue