Browse Source

fix: make timestamps strictly increasing (#201)

* fix: make timestamps strictly increasing

On Linux, this is almost always the case. Windows, however, doesn't have
nanosecond accuracy.

We make the timestamp sequence numbers strictly increasing by returning
the last timestamp + 1 where necessary.

* apply code review

Co-authored-by: Marten Seemann <martenseemann@gmail.com>

* use a lock

Co-authored-by: Marten Seemann <martenseemann@gmail.com>
pull/1683/head
Steven Allen 3 years ago
committed by GitHub
parent
commit
def12fc22a
  1. 17
      core/peer/record.go
  2. 13
      core/peer/record_test.go

17
core/peer/record.go

@ -2,6 +2,7 @@ package peer
import (
"fmt"
"sync"
"time"
pb "github.com/libp2p/go-libp2p-core/peer/pb"
@ -125,9 +126,23 @@ func PeerRecordFromProtobuf(msg *pb.PeerRecord) (*PeerRecord, error) {
return record, nil
}
var (
lastTimestampMu sync.Mutex
lastTimestamp uint64
)
// TimestampSeq is a helper to generate a timestamp-based sequence number for a PeerRecord.
func TimestampSeq() uint64 {
return uint64(time.Now().UnixNano())
now := uint64(time.Now().UnixNano())
lastTimestampMu.Lock()
defer lastTimestampMu.Unlock()
// Not all clocks are strictly increasing, but we need these sequence numbers to be strictly
// increasing.
if now <= lastTimestamp {
now = lastTimestamp + 1
}
lastTimestamp = now
return now
}
// Domain is used when signing and validating PeerRecords contained in Envelopes.

13
core/peer/record_test.go

@ -52,3 +52,16 @@ func TestSignedPeerRecordFromEnvelope(t *testing.T) {
}
})
}
// This is pretty much guaranteed to pass on Linux no matter how we implement it, but Windows has
// low clock precision. This makes sure we never get a duplicate.
func TestTimestampSeq(t *testing.T) {
var last uint64
for i := 0; i < 1000; i++ {
next := TimestampSeq()
if next <= last {
t.Errorf("non-increasing timestamp found: %d <= %d", next, last)
}
last = next
}
}

Loading…
Cancel
Save