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.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
15 changes: 14 additions & 1 deletion peer/record.go
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
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
}
}