Skip to content

Commit

Permalink
add simple rtt estimator
Browse files Browse the repository at this point in the history
Signed-off-by: Roman Khimov <roman@nspcc.ru>
  • Loading branch information
roman-khimov committed Dec 25, 2024
1 parent 279e52e commit 62f5a64
Show file tree
Hide file tree
Showing 4 changed files with 37 additions and 0 deletions.
4 changes: 4 additions & 0 deletions context.go
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,9 @@ type Context[H Hash] struct {
lastBlockTime time.Time // Wall clock time of when the last block was first seen (used for timer adjustments).
lastBlockIndex uint32
lastBlockView byte

prepareSentTime time.Time
rttEstimates rtt
}

// N returns total number of validators.
Expand Down Expand Up @@ -236,6 +239,7 @@ func (c *Context[H]) PreBlock() PreBlock[H] {

func (c *Context[H]) reset(view byte, ts uint64) {
c.MyIndex = -1
c.prepareSentTime = time.Time{}
c.lastBlockTimestamp = ts

if view == 0 {
Expand Down
5 changes: 5 additions & 0 deletions dbft.go
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,7 @@ func (d *DBFT[H]) initializeConsensus(view byte, ts uint64) {
var ts = d.Timer.Now()
var diff = ts.Sub(d.lastBlockTime)
timeout -= diff
timeout -= d.rttEstimates.avg
timeout = max(0, timeout)
}
d.changeTimer(timeout)
Expand Down Expand Up @@ -482,6 +483,10 @@ func (d *DBFT[H]) onPrepareResponse(msg ConsensusPayload[H]) {
}
}

if d.IsPrimary() && !d.prepareSentTime.IsZero() && !d.recovering {
d.rttEstimates.addTime(time.Since(d.prepareSentTime))
}

d.extendTimer(2)

if !d.Context.WatchOnly() && !d.CommitSent() && (!d.isAntiMEVExtensionEnabled() || !d.PreCommitSent()) && d.RequestSentOrReceived() {
Expand Down
26 changes: 26 additions & 0 deletions rtt.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package dbft

import (
"time"
)

const rttLength = 7 * 10

type rtt struct {
times [rttLength]time.Duration
idx int
avg time.Duration
}

func (r *rtt) addTime(new time.Duration) {
var old = r.times[r.idx]

if old != 0 {
new = min(new, 2*old) // Too long delays should be normalized, we don't want to overshoot.
}

Check warning on line 20 in rtt.go

View check run for this annotation

Codecov / codecov/patch

rtt.go#L19-L20

Added lines #L19 - L20 were not covered by tests

r.avg = r.avg + (new-old)/time.Duration(len(r.times))
r.avg = max(0, r.avg) // Can't be less than zero.
r.times[r.idx] = new
r.idx = (r.idx + 1) % len(r.times)
}
2 changes: 2 additions & 0 deletions send.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ func (d *DBFT[H]) sendPrepareRequest() {
d.PreparationPayloads[d.MyIndex] = msg
d.broadcast(msg)

d.prepareSentTime = d.Timer.Now()

delay := d.SecondsPerBlock << (d.ViewNumber + 1)
if d.ViewNumber == 0 {
delay -= d.SecondsPerBlock
Expand Down

0 comments on commit 62f5a64

Please sign in to comment.