From ccdc39e1dc562274bbd720c6458b3ce26cf1ab0f Mon Sep 17 00:00:00 2001 From: Steven Allen Date: Fri, 16 Jul 2021 14:18:57 -0700 Subject: [PATCH] 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. --- peer/record.go | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/peer/record.go b/peer/record.go index 3968fc2..95c8f6c 100644 --- a/peer/record.go +++ b/peer/record.go @@ -2,6 +2,7 @@ package peer import ( "fmt" + "sync/atomic" "time" pb "github.com/libp2p/go-libp2p-core/peer/pb" @@ -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.