Skip to content
Snippets Groups Projects
Commit 12f3c10e authored by benjamin's avatar benjamin
Browse files

adjusted timestamp handling - they are added to messages and will be used if...

adjusted timestamp handling - they are added to messages and will be used if they are within -5/+2 seconds of the round they are carried in, otherwise the old mutateTimestamp system is used
parent 73696112
No related branches found
No related tags found
3 merge requests!510Release,!419rewrote the health tracker to both consider if there are waiting rounds and...,!340Project/channels
......@@ -15,6 +15,7 @@ import (
"gitlab.com/elixxir/crypto/channel"
"gitlab.com/elixxir/primitives/states"
"gitlab.com/xx_network/primitives/id"
"time"
)
// adminListener adheres to the [broadcast.ListenerFunc] interface and is used
......@@ -54,8 +55,10 @@ func (al *adminListener) Listen(payload []byte,
return
}
// Modify the timestamp to reduce the chance message order will be ambiguous
ts := mutateTimestamp(round.Timestamps[states.QUEUED], msgID)
// Replace the timestamp on the message if it is outside of the
// allowable range
ts := vetTimestamp(time.Unix(0, cm.LocalTimestamp),
round.Timestamps[states.QUEUED], msgID)
// Submit the message to the event model for listening
if uuid, err := al.trigger(al.chID, cm, ts, msgID, receptionID,
......
......@@ -18,10 +18,28 @@ const (
// arise due to cofactors with the message ID when doing the modulo
tenMsInNs = 10000019
halfTenMsInNs = tenMsInNs / 2
beforeGrace = 5 * time.Second
afterGrace = 2 * time.Second
)
var tenMsInNsLargeInt = large.NewInt(tenMsInNs)
// vetTimestamp determines which timestamp to use for a message. It will
// use the local timestamp provided in the message as long as it is within 5
// seconds before the round and 2 second after the round. Otherwise, it will
// use the round timestamp via mutateTimestamp
func vetTimestamp(localTS, ts time.Time, msgID channel.MessageID) time.Time {
before := ts.Add(-beforeGrace)
after := ts.Add(afterGrace)
if localTS.Before(before) || localTS.After(after) {
return mutateTimestamp(ts, msgID)
}
return localTS
}
// mutateTimestamp is used to modify the the timestamps on all messages in a
// deterministic manner. This is because message ordering is done by timestamp
// and the timestamps come from the rounds, which means multiple messages can
......
......@@ -53,3 +53,77 @@ func TestMutateTimestampDeltaAverage(t *testing.T) {
t.Fatal()
}
}
const generationRange = beforeGrace + afterGrace
// TestVetTimestamp_Happy tests that when the localTS is within
// the allowed range, it is unmodified
func TestVetTimestamp_Happy(t *testing.T) {
samples := 10000
rng := rand.New(rand.NewSource(netTime.Now().UnixNano()))
for i := 0; i < samples; i++ {
now := time.Now()
tested := now.Add(-beforeGrace).Add(time.Duration(rng.Int63()) % generationRange)
var msgID channel.MessageID
rng.Read(msgID[:])
result := vetTimestamp(tested, now, msgID)
if !tested.Equal(result) {
t.Errorf("Timestamp was molested unexpectedly")
}
}
}
// TestVetTimestamp_Happy tests that when the localTS is less than
// the allowed time period it is replaced
func TestVetTimestamp_BeforePeriod(t *testing.T) {
samples := 10000
rng := rand.New(rand.NewSource(netTime.Now().UnixNano()))
for i := 0; i < samples; i++ {
now := time.Now()
tested := now.Add(-beforeGrace).Add(-time.Duration(rng.Int63()) % (100000 * time.Hour))
var msgID channel.MessageID
rng.Read(msgID[:])
result := vetTimestamp(tested, now, msgID)
if tested.Equal(result) {
t.Errorf("Timestamp was unmolested unexpectedly")
}
}
}
// TestVetTimestamp_Happy tests that when the localTS is greater than
// the allowed time period it is replaced
func TestVetTimestamp_AfterPeriod(t *testing.T) {
samples := 10000
rng := rand.New(rand.NewSource(netTime.Now().UnixNano()))
for i := 0; i < samples; i++ {
now := time.Now()
tested := now.Add(afterGrace).Add(-time.Duration(rng.Int63()) % (100000 * time.Hour))
var msgID channel.MessageID
rng.Read(msgID[:])
result := vetTimestamp(tested, now, msgID)
if tested.Equal(result) {
t.Errorf("Timestamp was unmolested unexpectedly")
}
}
}
......@@ -17,6 +17,7 @@ import (
"gitlab.com/elixxir/crypto/rsa"
"gitlab.com/xx_network/primitives/id"
"gitlab.com/xx_network/primitives/id/ephemeral"
"gitlab.com/xx_network/primitives/netTime"
"google.golang.org/protobuf/proto"
"time"
)
......@@ -55,6 +56,7 @@ func (m *manager) SendGeneric(channelID *id.ID, messageType MessageType,
Payload: msg,
Nickname: nickname,
Nonce: make([]byte, messageNonceSize),
LocalTimestamp: netTime.Now().UnixNano(),
}
// Generate random nonce to be used for message ID generation. This makes it
......@@ -75,7 +77,7 @@ func (m *manager) SendGeneric(channelID *id.ID, messageType MessageType,
ECCPublicKey: m.me.PubKey,
}
//Note: we are not checking check if message is too long before trying to
//Note: we are not checking if message is too long before trying to
//find a round
//Build the function pointer that will build the message
......@@ -150,6 +152,7 @@ func (m *manager) SendAdminGeneric(privKey rsa.PrivateKey, channelID *id.ID,
Payload: msg,
Nickname: AdminUsername,
Nonce: make([]byte, messageNonceSize),
LocalTimestamp: netTime.Now().UnixNano(),
}
// Generate random nonce to be used for message ID generation. This makes it
......
......@@ -14,6 +14,7 @@ import (
"gitlab.com/elixxir/client/cmix/rounds"
"gitlab.com/elixxir/primitives/states"
"gitlab.com/xx_network/primitives/id"
"time"
)
// the userListener adheres to the [broadcast.ListenerFunc] interface and is
......@@ -64,8 +65,9 @@ func (ul *userListener) Listen(payload []byte,
return
}
// Modify the timestamp to reduce the chance message order will be ambiguous
ts := mutateTimestamp(round.Timestamps[states.QUEUED], msgID)
// Replace the timestamp on the message if it is outside of the
// allowable range
ts := vetTimestamp(time.Unix(0, cm.LocalTimestamp), round.Timestamps[states.QUEUED], msgID)
//TODO: Processing of the message relative to admin commands will be here
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please to comment