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

fix: make timestamps strictly increasing #201

Merged
merged 3 commits into from
Jul 16, 2021
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 14 additions & 1 deletion peer/record.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package peer

import (
"fmt"
"sync/atomic"
"time"

pb "github.com/libp2p/go-libp2p-core/peer/pb"
Expand Down Expand Up @@ -125,9 +126,21 @@ func PeerRecordFromProtobuf(msg *pb.PeerRecord) (*PeerRecord, error) {
return record, nil
}

var 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())
previous := atomic.LoadUint64(&lastTimestamp)
// If the new time is not greater than the last tiemstamp, or if someone else beats us to
// updateing the timestamp, just use last+1.
//
// Technically, last+1 could be before "now". But it's still strictly increasing and close
// enough.
if now <= previous || !atomic.CompareAndSwapUint64(&lastTimestamp, previous, now) {
now = atomic.AddUint64(&lastTimestamp, 1)
}
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
Original file line number Diff line number Diff line change
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) {
last := uint64(0)
Stebalien marked this conversation as resolved.
Show resolved Hide resolved
for i := 0; i < 1000; i++ {
next := TimestampSeq()
if next <= last {
t.Errorf("non-increasing timestampfound: %d <= %d", next, last)
Stebalien marked this conversation as resolved.
Show resolved Hide resolved
}
last = next
}
}