Skip to content
This repository has been archived by the owner on Sep 6, 2022. It is now read-only.

Commit

Permalink
fix: make timestamps strictly increasing (#201)
Browse files Browse the repository at this point in the history
* 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>
  • Loading branch information
Stebalien and marten-seemann committed Jul 16, 2021
1 parent e5b6740 commit ef6e277
Show file tree
Hide file tree
Showing 2 changed files with 29 additions and 1 deletion.
17 changes: 16 additions & 1 deletion peer/record.go
Expand Up @@ -2,6 +2,7 @@ package peer

import (
"fmt"
"sync"
"time"

pb "github.com/libp2p/go-libp2p-core/peer/pb"
Expand Down Expand Up @@ -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.
Expand Down
13 changes: 13 additions & 0 deletions peer/record_test.go
Expand Up @@ -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
}
}

0 comments on commit ef6e277

Please sign in to comment.