mirror of
https://github.com/fluencelabs/tendermint
synced 2025-04-24 22:32:15 +00:00
Removed MinValidTime Round0 exception; WiggleR -> WiggleDelta
This commit is contained in:
parent
b4120e25ff
commit
4ec86eea39
@ -396,9 +396,9 @@ type ConsensusConfig struct {
|
||||
PeerQueryMaj23SleepDuration int `mapstructure:"peer_query_maj23_sleep_duration"`
|
||||
|
||||
// Block time parameters in milliseconds
|
||||
BlockTimeIota int `mapstructure:"blocktime_iota"`
|
||||
BlockTimeWiggle int `mapstructure:"blocktime_wiggle"`
|
||||
BlockTimeWiggleR float64 `mapstructure:"blocktime_wiggle_r"`
|
||||
BlockTimeIota int `mapstructure:"blocktime_iota"`
|
||||
BlockTimeWiggle int `mapstructure:"blocktime_wiggle"`
|
||||
BlockTimeWiggleDelta int `mapstructure:"blocktime_wiggle_delta"`
|
||||
}
|
||||
|
||||
// DefaultConsensusConfig returns a default configuration for the consensus service
|
||||
@ -421,7 +421,7 @@ func DefaultConsensusConfig() *ConsensusConfig {
|
||||
PeerQueryMaj23SleepDuration: 2000,
|
||||
BlockTimeIota: 10,
|
||||
BlockTimeWiggle: 20000,
|
||||
BlockTimeWiggleR: 0.05,
|
||||
BlockTimeWiggleDelta: 1000,
|
||||
}
|
||||
}
|
||||
|
||||
@ -487,27 +487,19 @@ func (cfg *ConsensusConfig) PeerQueryMaj23Sleep() time.Duration {
|
||||
|
||||
// BlockTimeMinValidTime returns the minimum acceptable block time, as part
|
||||
// of "subjective time validity". See the BFT time spec.
|
||||
func (cfg *ConsensusConfig) BlockTimeMinValidTime(lastBlockTime, now time.Time, round int) time.Time {
|
||||
var minValidTime time.Time = lastBlockTime.Add(time.Duration(cfg.BlockTimeIota) * time.Millisecond)
|
||||
if round == 0 {
|
||||
wiggleAgo := now.Add(-1 * time.Duration(cfg.BlockTimeWiggle) * time.Millisecond)
|
||||
if wiggleAgo.After(minValidTime) {
|
||||
minValidTime = wiggleAgo
|
||||
}
|
||||
} else {
|
||||
// For all subsequent rounds, we accept any block > last_block_time+iota.
|
||||
}
|
||||
return minValidTime
|
||||
func (cfg *ConsensusConfig) BlockTimeMinValidTime(lastBlockTime time.Time) time.Time {
|
||||
return lastBlockTime.
|
||||
Add(time.Duration(cfg.BlockTimeIota) * time.Millisecond)
|
||||
}
|
||||
|
||||
// BlockTimeMaxValidTime returns the maximum acceptable block time, as part
|
||||
// of "subjective time validity". See the BFT time spec.
|
||||
func (cfg *ConsensusConfig) BlockTimeMaxValidTime(lastBlockTime, now time.Time, round int) time.Time {
|
||||
func (cfg *ConsensusConfig) BlockTimeMaxValidTime(now time.Time, round int) time.Time {
|
||||
return now.
|
||||
Add(time.Duration(cfg.BlockTimeWiggle) * time.Millisecond).
|
||||
Add(
|
||||
time.Duration(
|
||||
float64(cfg.BlockTimeWiggle)*cfg.BlockTimeWiggleR*float64(round),
|
||||
int64(cfg.BlockTimeWiggleDelta)*int64(round),
|
||||
) * time.Millisecond,
|
||||
)
|
||||
}
|
||||
|
@ -945,7 +945,7 @@ func (cs *ConsensusState) defaultDoPrevote(height int64, round int) {
|
||||
// See the BFT time spec.
|
||||
lastBlockTime := cs.state.LastBlockTime
|
||||
now := time.Now().Round(0).UTC()
|
||||
minValidTime := cs.config.BlockTimeMinValidTime(lastBlockTime, now, round)
|
||||
minValidTime := cs.config.BlockTimeMinValidTime(lastBlockTime)
|
||||
if cs.ProposalBlock.Time.Before(minValidTime) {
|
||||
logger.Info("enterPrevote: ProposalBlock time too low",
|
||||
"blockTime", cs.ProposalBlock.Time,
|
||||
@ -953,7 +953,7 @@ func (cs *ConsensusState) defaultDoPrevote(height int64, round int) {
|
||||
cs.signAddVote(types.VoteTypePrevote, nil, types.PartSetHeader{})
|
||||
return
|
||||
}
|
||||
maxValidTime := cs.config.BlockTimeMaxValidTime(lastBlockTime, now, round)
|
||||
maxValidTime := cs.config.BlockTimeMaxValidTime(now, round)
|
||||
if maxValidTime.Before(cs.ProposalBlock.Time) {
|
||||
logger.Info("enterPrevote: ProposalBlock time too high",
|
||||
"blockTime", cs.ProposalBlock.Time,
|
||||
|
@ -13,55 +13,49 @@ a header H1 for height h1 and a header H2 for height `h2 = h1 + 1`, `H1.Time < H
|
||||
Beyond satisfying time monotinicity, Tendermint also checks the following
|
||||
property, but only when signing a prevote for a block:
|
||||
|
||||
- **Subjective Time Validity**: Time is greater than MinValidTime(last_block_time,
|
||||
now, round) and less than or equal to MaxValidTime(last_block_time, now), where:
|
||||
- **Subjective Time Validity**: Time is greater than MinValidTime(last_block_time) and less than or equal to MaxValidTime(now, round), where:
|
||||
|
||||
```go
|
||||
// wiggle and iota are provided by consensus config.
|
||||
func MinValidTime(last_block_time, now time.Time, round int) time.Time {
|
||||
var minValidTime time.Time = last_block_time.Add(iota)
|
||||
if round == 0 {
|
||||
minValidTime = maxTime(minValidTime, now.Add(-1*wiggle)
|
||||
} else {
|
||||
// For all subsequent rounds, we accept any block > last_block_time+iota.
|
||||
}
|
||||
return minValidTime
|
||||
// iota provided by consensus config.
|
||||
func MinValidTime(last_block_time) time.Time {
|
||||
return lastBlockTime.
|
||||
Add(time.Duration(iota) * time.Millisecond)
|
||||
}
|
||||
|
||||
// wiggle and wiggle_r are provided by consensus config.
|
||||
func MaxValidTime(last_block_time, now time.Time, round int) time.Time {
|
||||
// wiggle and wiggle_delta are provided by consensus config.
|
||||
func MaxValidTime(now time.Time, round int) time.Time {
|
||||
return now.
|
||||
Add(wiggle).
|
||||
Add(wiggle*wiggle_r*round)
|
||||
Add(time.Duration(wiggle) * time.Millisecond).
|
||||
Add(
|
||||
time.Duration(
|
||||
wiggle_delta*float64(round),
|
||||
) * time.Millisecond,
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
For `MinValidTime`, we only accept recent blocks (`wiggle`) on the first
|
||||
round. This has the effect of slightly slowing down the blockchain (requiring
|
||||
at least two rounds of consensus instead of one) progressively as more validator
|
||||
clocks get off sync from each other. Blocks that are significantly older than
|
||||
`now` can still be valid (except in round 0), which allows for the re-proposing of older proposals.
|
||||
The blockchain's time "eventually" catches up over block heights to a reasonably recent time as long as
|
||||
time-correct validators' proposals are committed in a timely fashion (i.e. less than 1/3
|
||||
are Byzantine) TODO: Quantify "eventually" as a function of % of time-correct
|
||||
validators.
|
||||
For `MinValidTime`, we accept any block that is at least `iota` greater than
|
||||
the last block time. Blocks that are significantly older than the current time
|
||||
can still be valid, which allows for the re-proposing of older proposals.
|
||||
|
||||
For `MaxValidTime`, we accept blocks where the block time is greater than `now`
|
||||
plus some threshold that increases linearly with the round number.
|
||||
The purpose of `wiggle_r` is for graceful degredation when +2/3 validators
|
||||
*aren't* within `wiggle` of each other but are otherwise non-Byzantine in all other respects.
|
||||
Consider an example with 100 equally weighted validators, where 33 are Byzantine,
|
||||
and one of the remaining 67 validators has a faulty clock that causes it to drift
|
||||
back more than `wiggle` from the other 66. If the 33 Byzantine
|
||||
validators were to withhold their votes, no block would produce a Polka until the
|
||||
drifting one becomes the proposer!
|
||||
For `MaxValidTime`, we accept block times greater than `now` plus some
|
||||
threshold that increases linearly with the round number. The purpose of
|
||||
`wiggle_delta` is for graceful degredation when +2/3 validators *aren't* within
|
||||
`wiggle` of each other but are otherwise non-Byzantine in all other respects.
|
||||
|
||||
NOTE: `wiggle_r` could be set to something like 0.05 (e.g. if `wiggle` were 20s, `wiggle*wiggle_r` would be 1s.)
|
||||
`wiggle*wiggle_r` should probably be less than `timeout_propose_delta` to prevent unnecessary
|
||||
forward time-jumps in cases where higher rounds are reached due to factors
|
||||
other than network performance -- for example, where the network is performant
|
||||
but several proposers were absent in a row. `wiggle_r` could theoretically be set to 0
|
||||
if it can be assumed that +2/3 (by voting power) of correct validators' clocks are within `wiggle` of each other.
|
||||
Consider an example with 100 equally weighted validators, where 33 are
|
||||
Byzantine, and one of the remaining 67 validators has a faulty clock that
|
||||
causes it to drift back more than `wiggle` from the other 66. Without
|
||||
`wiggle_delta`, if the 33 Byzantine validators were to withhold their votes, no
|
||||
block would produce a Polka until the drifting one becomes the proposer.
|
||||
|
||||
NOTE: `wiggle_delta` should probably be less than `timeout_propose_delta` to
|
||||
prevent unnecessary forward time-jumps in cases where higher rounds are reached
|
||||
due to factors other than network performance -- for example, where the network
|
||||
is performant but several proposers were absent in a row. `wiggle_delta` could
|
||||
theoretically be set to 0 if it can be assumed that +2/3 (by voting power) of
|
||||
correct validators' clocks are within `wiggle` of each other.
|
||||
|
||||
Subjective time validity is ignored when a Polka or Commit is found, allowing
|
||||
consensus to progress locally even when the subjective time requirements are not satisfied.
|
||||
consensus to progress locally even when the subjective time requirements are
|
||||
not satisfied.
|
||||
|
Loading…
x
Reference in New Issue
Block a user