Peg clock value to whisper timestamp (#1804)

This commit pegs the clock value to maximum + 120 seconds from the whisper
timestamp.
In this way the we avoid the scenario where a client makes the timestamp
increase arbitrarely.
This commit is contained in:
Andrea Maria Piana 2020-01-20 17:44:32 +01:00 committed by GitHub
parent 93975aa900
commit 456bcfa022
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
24 changed files with 446 additions and 283 deletions

View File

@ -1 +1 @@
0.39.6
0.39.7

View File

@ -18,7 +18,7 @@ require (
github.com/status-im/doubleratchet v3.0.0+incompatible
github.com/status-im/status-go/extkeys v1.0.0
github.com/status-im/status-go/waku v1.0.0
github.com/status-im/status-go/whisper/v6 v6.0.1 // indirect
github.com/status-im/status-go/whisper/v6 v6.0.1
github.com/stretchr/testify v1.4.0
github.com/wealdtech/go-ens/v3 v3.0.9
go.uber.org/zap v1.13.0

View File

@ -27,6 +27,7 @@ github.com/aristanetworks/goarista v0.0.0-20181002214814-33151c4543a7 h1:6TQIK3K
github.com/aristanetworks/goarista v0.0.0-20181002214814-33151c4543a7/go.mod h1:D/tb0zPVXnP7fmsLZjtdUhSsumbK/ij54UXjjVgMGxQ=
github.com/aristanetworks/goarista v0.0.0-20190219163901-728bce664cf5 h1:L0TwgZQo7Mga9im6FvKEZGIvyLE/VG/HI5loz5LpvC0=
github.com/aristanetworks/goarista v0.0.0-20190219163901-728bce664cf5/go.mod h1:D/tb0zPVXnP7fmsLZjtdUhSsumbK/ij54UXjjVgMGxQ=
github.com/aristanetworks/goarista v0.0.0-20191106175434-873d404c7f40 h1:ZdRuixFqR3mfx4FHzclG3COrRgWrYq0VhNgIoYoObcM=
github.com/aristanetworks/goarista v0.0.0-20191106175434-873d404c7f40/go.mod h1:Z4RTxGAuYhPzcq8+EdRM+R8M48Ssle2TsWtwRKa+vns=
github.com/aristanetworks/splunk-hec-go v0.3.3/go.mod h1:1VHO9r17b0K7WmOlLb9nTk/2YanvOEnLMUgsFrxBROc=
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
@ -77,6 +78,7 @@ github.com/edsrzf/mmap-go v1.0.0/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaB
github.com/elastic/gosigar v0.0.0-20180330100440-37f05ff46ffa/go.mod h1:cdorVVzy1fhmEqmtgqkoE3bYtCfSCkVyjTyCIo22xvs=
github.com/elastic/gosigar v0.10.4 h1:6jfw75dsoflhBMRdO6QPzQUgLqUYTsQQQRkkcsHsuPo=
github.com/elastic/gosigar v0.10.4/go.mod h1:cdorVVzy1fhmEqmtgqkoE3bYtCfSCkVyjTyCIo22xvs=
github.com/elastic/gosigar v0.10.5 h1:GzPQ+78RaAb4J63unidA/JavQRKrB6s8IOzN6Ib59jo=
github.com/elastic/gosigar v0.10.5/go.mod h1:cdorVVzy1fhmEqmtgqkoE3bYtCfSCkVyjTyCIo22xvs=
github.com/ethereum/go-ethereum v1.9.2/go.mod h1:PwpWDrCLZrV+tfrhqqF6kPknbISMHaJv9Ln3kPCZLwY=
github.com/fatih/color v1.3.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
@ -139,6 +141,7 @@ github.com/influxdata/influxdb1-client v0.0.0-20190809212627-fc22c7df067e/go.mod
github.com/jackpal/go-nat-pmp v0.0.0-20160603034137-1fa385a6f458/go.mod h1:QPH045xvCAeXUZOxsnwmrtiCoxIr9eob+4orBN1SBKc=
github.com/jackpal/go-nat-pmp v1.0.1 h1:i0LektDkO1QlrTm/cSuP+PyBCDnYvjPLGl4LdWEMiaA=
github.com/jackpal/go-nat-pmp v1.0.1/go.mod h1:QPH045xvCAeXUZOxsnwmrtiCoxIr9eob+4orBN1SBKc=
github.com/jackpal/go-nat-pmp v1.0.2 h1:KzKSgb7qkJvOUTqYl9/Hg/me3pWgBmERKrTGD7BdWus=
github.com/jackpal/go-nat-pmp v1.0.2/go.mod h1:QPH045xvCAeXUZOxsnwmrtiCoxIr9eob+4orBN1SBKc=
github.com/jcmturner/gofork v0.0.0-20190328161633-dc7c13fece03/go.mod h1:MK8+TM0La+2rjBD4jE12Kj1pCCxK7d2LK/UM3ncEo0o=
github.com/jessevdk/go-flags v0.0.0-20141203071132-1679536dcc89/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
@ -226,6 +229,7 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo=
github.com/prometheus/client_golang v1.1.0/go.mod h1:I1FGZT9+L76gKKOs5djB6ezCbFQP1xR9D75/vuwEF3g=
github.com/prometheus/client_golang v1.2.1 h1:JnMpQc6ppsNgw9QPAGF6Dod479itz7lvlsMzzNayLOI=
github.com/prometheus/client_golang v1.2.1/go.mod h1:XMU6Z2MjaRKVu/dC1qupJI9SiNkDYzz3xecMgSW/F+U=
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
@ -233,10 +237,12 @@ github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4 h1:gQz4mCbXsO+nc9n1hCxHcGA3Zx3Eo+UHZoInFGUIXNM=
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
github.com/prometheus/common v0.6.0/go.mod h1:eBmuwkDJBwy6iBfxCBob6t6dR6ENT/y+J+Zk0j9GMYc=
github.com/prometheus/common v0.7.0 h1:L+1lyG48J1zAQXA3RBX/nG/B3gjlHq0zTt2tlbJLyCY=
github.com/prometheus/common v0.7.0/go.mod h1:DjGbpBbp5NYNiECxcL/VnbXCCaQpKd3tt26CguLLsqA=
github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
github.com/prometheus/procfs v0.0.3/go.mod h1:4A/X28fw3Fc593LaREMrKMqOKvUAntwMDaekg4FpcdQ=
github.com/prometheus/procfs v0.0.5 h1:3+auTFlqw+ZaQYJARz6ArODtkaIwtvBTx3N2NehQlL8=
github.com/prometheus/procfs v0.0.5/go.mod h1:4A/X28fw3Fc593LaREMrKMqOKvUAntwMDaekg4FpcdQ=
github.com/prometheus/prometheus v0.0.0-20170814170113-3101606756c5/go.mod h1:oAIUtOny2rjMX0OWN5vPR5/q/twIROJvdqnQKDdil/s=
@ -251,6 +257,7 @@ github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFR
github.com/rs/cors v0.0.0-20160617231935-a62a804a8a00/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU=
github.com/rs/cors v1.6.0 h1:G9tHG9lebljV9mfp9SNPDL36nCDxmo3zTlAf1YgvzmI=
github.com/rs/cors v1.6.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU=
github.com/rs/cors v1.7.0 h1:+88SsELBHx5r+hZ8TCkggzSstaWNbDvThkVK8H6f9ik=
github.com/rs/cors v1.7.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU=
github.com/rs/xhandler v0.0.0-20160618193221-ed27b6fd6521/go.mod h1:RvLn4FgxWubrpZHtQLnOf6EwhN2hEMusxZOhcW9H3UQ=
github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0=
@ -345,6 +352,7 @@ golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn
golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859 h1:R/3boaszxrf1GEUWTVDzSKVwLmSJpwZ1yqXm8j0v2QI=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190912160710-24e19bdeb0f2 h1:4dVFTC832rPn4pomLSz1vA+are2+dU19w1H8OngV7nc=
golang.org/x/net v0.0.0-20190912160710-24e19bdeb0f2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f h1:wMNYb4v58l5UBM7MYRLPG6ZhfOqbKu7X5eyFl8ZhKvA=
@ -353,6 +361,7 @@ golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJ
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190423024810-112230192c58 h1:8gQV6CLnAEikrhgkHFbMAEhagSSnXWGV915qUMm9mrU=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e h1:vcxGaoTs7kV8m5Np9uUNQin4BrLOthgV7252N8V+FwY=
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e h1:o3PsSEY8E4eXWkXrIP9YJALUkVZqzHJT5DOasTyn8Vs=
@ -365,6 +374,8 @@ golang.org/x/sys v0.0.0-20190403152447-81d4e9dc473e/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20190412213103-97732733099d h1:+R4KGOnez64A81RvjARKc4UT5/tI9ujCIVX+P5KiHuI=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190801041406-cbf593c0f2f3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190912141932-bc967efca4b8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191010194322-b09406accb47 h1:/XfQ9z7ib8eEJX2hdgFTZJ/ntt0swNk5oYBziWeTCvY=
golang.org/x/sys v0.0.0-20191010194322-b09406accb47/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=

View File

@ -207,39 +207,39 @@ func oneToOneChatID(publicKey *ecdsa.PublicKey) string {
return types.EncodeHex(crypto.FromECDSAPub(publicKey))
}
func OneToOneFromPublicKey(pk *ecdsa.PublicKey) *Chat {
func OneToOneFromPublicKey(pk *ecdsa.PublicKey, timesource ClockValueTimesource) *Chat {
chatID := types.EncodeHex(crypto.FromECDSAPub(pk))
newChat := CreateOneToOneChat(chatID[:8], pk)
newChat := CreateOneToOneChat(chatID[:8], pk, timesource)
return &newChat
}
func CreateOneToOneChat(name string, publicKey *ecdsa.PublicKey) Chat {
func CreateOneToOneChat(name string, publicKey *ecdsa.PublicKey, timesource ClockValueTimesource) Chat {
return Chat{
ID: oneToOneChatID(publicKey),
Name: name,
Timestamp: int64(timestampInMs()),
Timestamp: int64(timesource.GetCurrentTime()),
Active: true,
ChatType: ChatTypeOneToOne,
}
}
func CreatePublicChat(name string) Chat {
func CreatePublicChat(name string, timesource ClockValueTimesource) Chat {
return Chat{
ID: name,
Name: name,
Active: true,
Timestamp: int64(timestampInMs()),
Timestamp: int64(timesource.GetCurrentTime()),
Color: chatColors[rand.Intn(len(chatColors))],
ChatType: ChatTypePublic,
}
}
func createGroupChat() Chat {
func createGroupChat(timesource ClockValueTimesource) Chat {
return Chat{
Active: true,
Color: chatColors[rand.Intn(len(chatColors))],
Timestamp: int64(timestampInMs()),
Timestamp: int64(timesource.GetCurrentTime()),
ChatType: ChatTypePrivateGroupChat,
}
}
@ -276,11 +276,15 @@ func stringSliceToPublicKeys(slice []string, prefixed bool) ([]*ecdsa.PublicKey,
return result, nil
}
type ClockValueTimesource interface {
GetCurrentTime() uint64
}
// NextClockAndTimestamp returns the next clock value
// and the current timestamp
func (c *Chat) NextClockAndTimestamp() (uint64, uint64) {
func (c *Chat) NextClockAndTimestamp(timesource ClockValueTimesource) (uint64, uint64) {
clock := c.LastClockValue
timestamp := timestampInMs()
timestamp := timesource.GetCurrentTime()
if clock == 0 || clock < timestamp {
clock = timestamp
} else {
@ -289,8 +293,8 @@ func (c *Chat) NextClockAndTimestamp() (uint64, uint64) {
return clock, timestamp
}
func (c *Chat) UpdateFromMessage(message *Message) error {
c.Timestamp = int64(timestampInMs())
func (c *Chat) UpdateFromMessage(message *Message, timesource ClockValueTimesource) error {
c.Timestamp = int64(timesource.GetCurrentTime())
if c.LastClockValue <= message.Clock {
jsonMessage, err := json.Marshal(message)
if err != nil {

View File

@ -3,7 +3,6 @@ package protocol
import (
"crypto/ecdsa"
"encoding/hex"
"strings"
"github.com/status-im/status-go/eth-node/crypto"
"github.com/status-im/status-go/eth-node/types"
@ -33,7 +32,7 @@ type Contact struct {
// ID of the contact. It's a hex-encoded public key (prefixed with 0x).
ID string `json:"id"`
// Ethereum address of the contact
Address string `json:"address"`
Address string `json:"address,omitempty"`
// ENS name of contact
Name string `json:"name,omitempty"`
// EnsVerified whether we verified the name of the contact
@ -88,8 +87,6 @@ func existsInStringSlice(set []string, find string) bool {
}
func buildContact(publicKey *ecdsa.PublicKey) (*Contact, error) {
address := strings.ToLower(crypto.PubkeyToAddress(*publicKey).Hex())
id := "0x" + hex.EncodeToString(crypto.FromECDSAPub(publicKey))
identicon, err := identicon.GenerateBase64(id)
@ -99,7 +96,6 @@ func buildContact(publicKey *ecdsa.PublicKey) (*Contact, error) {
contact := &Contact{
ID: id,
Address: address[2:],
Alias: alias.GenerateFromPublicKey(publicKey),
Identicon: identicon,
}

View File

@ -9,8 +9,8 @@ import (
"github.com/status-im/status-go/protocol/identity/identicon"
)
func extendMessageFromChat(message *Message, chat *Chat, key *ecdsa.PublicKey) error {
clock, timestamp := chat.NextClockAndTimestamp()
func extendMessageFromChat(message *Message, chat *Chat, key *ecdsa.PublicKey, timesource ClockValueTimesource) error {
clock, timestamp := chat.NextClockAndTimestamp(timesource)
message.LocalChatID = chat.ID
message.Clock = clock

View File

@ -33,12 +33,19 @@ func (m *MessageHandler) HandleMembershipUpdate(messageState *ReceivedMessageSta
var group *v1protocol.Group
var err error
logger := m.logger.With(zap.String("site", "HandleMembershipUpdate"))
message, err := v1protocol.MembershipUpdateMessageFromProtobuf(&rawMembershipUpdate)
if err != nil {
return err
}
if err := ValidateMembershipUpdateMessage(message, messageState.Timesource.GetCurrentTime()); err != nil {
logger.Warn("failed to validate message", zap.Error(err))
return err
}
if chat == nil {
if len(message.Events) == 0 {
return errors.New("can't create new group chat without events")
@ -52,7 +59,7 @@ func (m *MessageHandler) HandleMembershipUpdate(messageState *ReceivedMessageSta
if !group.IsMember(contactIDFromPublicKey(&m.identity.PublicKey)) {
return errors.New("can't create a new group chat without us being a member")
}
newChat := createGroupChat()
newChat := createGroupChat(messageState.Timesource)
chat = &newChat
} else {
@ -108,7 +115,7 @@ func (m *MessageHandler) handleCommandMessage(state *ReceivedMessageState, messa
message.WhisperTimestamp = state.CurrentMessageState.WhisperTimestamp
message.PrepareContent()
chat, err := m.matchMessage(message, state.AllChats)
chat, err := m.matchMessage(message, state.AllChats, state.Timesource)
if err != nil {
return err
}
@ -137,7 +144,7 @@ func (m *MessageHandler) handleCommandMessage(state *ReceivedMessageState, messa
message.OutgoingStatus = OutgoingStatusSent
}
err = chat.UpdateFromMessage(message)
err = chat.UpdateFromMessage(message, state.Timesource)
if err != nil {
return err
}
@ -158,7 +165,7 @@ func (m *MessageHandler) handleCommandMessage(state *ReceivedMessageState, messa
func (m *MessageHandler) HandleSyncInstallationContact(state *ReceivedMessageState, message protobuf.SyncInstallationContact) error {
chat, ok := state.AllChats[state.CurrentMessageState.Contact.ID]
if !ok {
chat = OneToOneFromPublicKey(state.CurrentMessageState.PublicKey)
chat = OneToOneFromPublicKey(state.CurrentMessageState.PublicKey, state.Timesource)
// We don't want to show the chat to the user
chat.Active = false
}
@ -205,7 +212,7 @@ func (m *MessageHandler) HandleSyncInstallationPublicChat(state *ReceivedMessage
return nil
}
chat := CreatePublicChat(chatID)
chat := CreatePublicChat(chatID, state.Timesource)
state.AllChats[chat.ID] = &chat
state.ModifiedChats[chat.ID] = true
@ -218,7 +225,7 @@ func (m *MessageHandler) HandleContactUpdate(state *ReceivedMessageState, messag
contact := state.CurrentMessageState.Contact
chat, ok := state.AllChats[contact.ID]
if !ok {
chat = OneToOneFromPublicKey(state.CurrentMessageState.PublicKey)
chat = OneToOneFromPublicKey(state.CurrentMessageState.PublicKey, state.Timesource)
// We don't want to show the chat to the user
chat.Active = false
}
@ -252,7 +259,7 @@ func (m *MessageHandler) HandleContactUpdate(state *ReceivedMessageState, messag
func (m *MessageHandler) HandlePairInstallation(state *ReceivedMessageState, message protobuf.PairInstallation) error {
logger := m.logger.With(zap.String("site", "HandlePairInstallation"))
if err := ValidateReceivedPairInstallation(&message); err != nil {
if err := ValidateReceivedPairInstallation(&message, state.CurrentMessageState.WhisperTimestamp); err != nil {
logger.Warn("failed to validate message", zap.Error(err))
return err
}
@ -276,7 +283,7 @@ func (m *MessageHandler) HandlePairInstallation(state *ReceivedMessageState, mes
func (m *MessageHandler) HandleChatMessage(state *ReceivedMessageState) error {
logger := m.logger.With(zap.String("site", "handleChatMessage"))
if err := ValidateReceivedChatMessage(&state.CurrentMessageState.Message); err != nil {
if err := ValidateReceivedChatMessage(&state.CurrentMessageState.Message, state.CurrentMessageState.WhisperTimestamp); err != nil {
logger.Warn("failed to validate message", zap.Error(err))
return err
}
@ -291,7 +298,7 @@ func (m *MessageHandler) HandleChatMessage(state *ReceivedMessageState) error {
}
receivedMessage.PrepareContent()
chat, err := m.matchMessage(receivedMessage, state.AllChats)
chat, err := m.matchMessage(receivedMessage, state.AllChats, state.Timesource)
if err != nil {
return err
}
@ -319,7 +326,7 @@ func (m *MessageHandler) HandleChatMessage(state *ReceivedMessageState) error {
receivedMessage.OutgoingStatus = OutgoingStatusSent
}
err = chat.UpdateFromMessage(receivedMessage)
err = chat.UpdateFromMessage(receivedMessage, state.Timesource)
if err != nil {
return err
}
@ -339,7 +346,7 @@ func (m *MessageHandler) HandleChatMessage(state *ReceivedMessageState) error {
}
func (m *MessageHandler) HandleRequestAddressForTransaction(messageState *ReceivedMessageState, command protobuf.RequestAddressForTransaction) error {
err := ValidateReceivedRequestAddressForTransaction(&command)
err := ValidateReceivedRequestAddressForTransaction(&command, messageState.CurrentMessageState.WhisperTimestamp)
if err != nil {
return err
}
@ -363,7 +370,7 @@ func (m *MessageHandler) HandleRequestAddressForTransaction(messageState *Receiv
}
func (m *MessageHandler) HandleRequestTransaction(messageState *ReceivedMessageState, command protobuf.RequestTransaction) error {
err := ValidateReceivedRequestTransaction(&command)
err := ValidateReceivedRequestTransaction(&command, messageState.CurrentMessageState.WhisperTimestamp)
if err != nil {
return err
}
@ -388,7 +395,7 @@ func (m *MessageHandler) HandleRequestTransaction(messageState *ReceivedMessageS
}
func (m *MessageHandler) HandleAcceptRequestAddressForTransaction(messageState *ReceivedMessageState, command protobuf.AcceptRequestAddressForTransaction) error {
err := ValidateReceivedAcceptRequestAddressForTransaction(&command)
err := ValidateReceivedAcceptRequestAddressForTransaction(&command, messageState.CurrentMessageState.WhisperTimestamp)
if err != nil {
return err
}
@ -437,7 +444,7 @@ func (m *MessageHandler) HandleAcceptRequestAddressForTransaction(messageState *
}
func (m *MessageHandler) HandleSendTransaction(messageState *ReceivedMessageState, command protobuf.SendTransaction) error {
err := ValidateReceivedSendTransaction(&command)
err := ValidateReceivedSendTransaction(&command, messageState.CurrentMessageState.WhisperTimestamp)
if err != nil {
return err
}
@ -457,7 +464,7 @@ func (m *MessageHandler) HandleSendTransaction(messageState *ReceivedMessageStat
}
func (m *MessageHandler) HandleDeclineRequestAddressForTransaction(messageState *ReceivedMessageState, command protobuf.DeclineRequestAddressForTransaction) error {
err := ValidateReceivedDeclineRequestAddressForTransaction(&command)
err := ValidateReceivedDeclineRequestAddressForTransaction(&command, messageState.CurrentMessageState.WhisperTimestamp)
if err != nil {
return err
}
@ -497,7 +504,7 @@ func (m *MessageHandler) HandleDeclineRequestAddressForTransaction(messageState
}
func (m *MessageHandler) HandleDeclineRequestTransaction(messageState *ReceivedMessageState, command protobuf.DeclineRequestTransaction) error {
err := ValidateReceivedDeclineRequestTransaction(&command)
err := ValidateReceivedDeclineRequestTransaction(&command, messageState.CurrentMessageState.WhisperTimestamp)
if err != nil {
return err
}
@ -536,7 +543,7 @@ func (m *MessageHandler) HandleDeclineRequestTransaction(messageState *ReceivedM
return m.handleCommandMessage(messageState, oldMessage)
}
func (m *MessageHandler) matchMessage(message *Message, chats map[string]*Chat) (*Chat, error) {
func (m *MessageHandler) matchMessage(message *Message, chats map[string]*Chat, timesource ClockValueTimesource) (*Chat, error) {
if message.SigPubKey == nil {
m.logger.Error("public key can't be empty")
return nil, errors.New("received a message with empty public key")
@ -571,7 +578,7 @@ func (m *MessageHandler) matchMessage(message *Message, chats map[string]*Chat)
return nil, errors.Wrap(err, "failed to decode pubkey")
}
newChat := CreateOneToOneChat(chatID[:8], pubKey)
newChat := CreateOneToOneChat(chatID[:8], pubKey, timesource)
chat = &newChat
}
return chat, nil
@ -582,7 +589,7 @@ func (m *MessageHandler) matchMessage(message *Message, chats map[string]*Chat)
chat := chats[chatID]
if chat == nil {
// TODO: this should be a three-word name used in the mobile client
newChat := CreateOneToOneChat(chatID[:8], message.SigPubKey)
newChat := CreateOneToOneChat(chatID[:8], message.SigPubKey, timesource)
chat = &newChat
}
return chat, nil

View File

@ -6,13 +6,41 @@ import (
"strings"
"github.com/status-im/status-go/protocol/protobuf"
"github.com/status-im/status-go/protocol/v1"
)
func ValidateReceivedPairInstallation(message *protobuf.PairInstallation) error {
if message.Clock == 0 {
// maxWhisperDrift is how many milliseconds we allow the clock value to differ
// from whisperTimestamp
const maxWhisperFutureDriftMs uint64 = 120000
func validateClockValue(clock uint64, whisperTimestamp uint64) error {
if clock == 0 {
return errors.New("clock can't be 0")
}
if clock > whisperTimestamp && clock-whisperTimestamp > maxWhisperFutureDriftMs {
return errors.New("clock value too high")
}
return nil
}
func ValidateMembershipUpdateMessage(message *protocol.MembershipUpdateMessage, timeNowMs uint64) error {
for _, e := range message.Events {
if err := validateClockValue(e.ClockValue, timeNowMs); err != nil {
return err
}
}
return nil
}
func ValidateReceivedPairInstallation(message *protobuf.PairInstallation, whisperTimestamp uint64) error {
if err := validateClockValue(message.Clock, whisperTimestamp); err != nil {
return err
}
if len(strings.TrimSpace(message.Name)) == 0 {
return errors.New("name can't be empty")
}
@ -28,9 +56,9 @@ func ValidateReceivedPairInstallation(message *protobuf.PairInstallation) error
return nil
}
func ValidateReceivedSendTransaction(message *protobuf.SendTransaction) error {
if message.Clock == 0 {
return errors.New("clock can't be 0")
func ValidateReceivedSendTransaction(message *protobuf.SendTransaction, whisperTimestamp uint64) error {
if err := validateClockValue(message.Clock, whisperTimestamp); err != nil {
return err
}
if len(strings.TrimSpace(message.TransactionHash)) == 0 {
@ -44,9 +72,9 @@ func ValidateReceivedSendTransaction(message *protobuf.SendTransaction) error {
return nil
}
func ValidateReceivedRequestAddressForTransaction(message *protobuf.RequestAddressForTransaction) error {
if message.Clock == 0 {
return errors.New("clock can't be 0")
func ValidateReceivedRequestAddressForTransaction(message *protobuf.RequestAddressForTransaction, whisperTimestamp uint64) error {
if err := validateClockValue(message.Clock, whisperTimestamp); err != nil {
return err
}
if len(strings.TrimSpace(message.Value)) == 0 {
@ -61,9 +89,9 @@ func ValidateReceivedRequestAddressForTransaction(message *protobuf.RequestAddre
return nil
}
func ValidateReceivedRequestTransaction(message *protobuf.RequestTransaction) error {
if message.Clock == 0 {
return errors.New("clock can't be 0")
func ValidateReceivedRequestTransaction(message *protobuf.RequestTransaction, whisperTimestamp uint64) error {
if err := validateClockValue(message.Clock, whisperTimestamp); err != nil {
return err
}
if len(strings.TrimSpace(message.Value)) == 0 {
@ -82,9 +110,9 @@ func ValidateReceivedRequestTransaction(message *protobuf.RequestTransaction) er
return nil
}
func ValidateReceivedAcceptRequestAddressForTransaction(message *protobuf.AcceptRequestAddressForTransaction) error {
if message.Clock == 0 {
return errors.New("clock can't be 0")
func ValidateReceivedAcceptRequestAddressForTransaction(message *protobuf.AcceptRequestAddressForTransaction, whisperTimestamp uint64) error {
if err := validateClockValue(message.Clock, whisperTimestamp); err != nil {
return err
}
if len(message.Id) == 0 {
@ -98,9 +126,9 @@ func ValidateReceivedAcceptRequestAddressForTransaction(message *protobuf.Accept
return nil
}
func ValidateReceivedDeclineRequestAddressForTransaction(message *protobuf.DeclineRequestAddressForTransaction) error {
if message.Clock == 0 {
return errors.New("clock can't be 0")
func ValidateReceivedDeclineRequestAddressForTransaction(message *protobuf.DeclineRequestAddressForTransaction, whisperTimestamp uint64) error {
if err := validateClockValue(message.Clock, whisperTimestamp); err != nil {
return err
}
if len(message.Id) == 0 {
@ -110,9 +138,9 @@ func ValidateReceivedDeclineRequestAddressForTransaction(message *protobuf.Decli
return nil
}
func ValidateReceivedDeclineRequestTransaction(message *protobuf.DeclineRequestTransaction) error {
if message.Clock == 0 {
return errors.New("clock can't be 0")
func ValidateReceivedDeclineRequestTransaction(message *protobuf.DeclineRequestTransaction, whisperTimestamp uint64) error {
if err := validateClockValue(message.Clock, whisperTimestamp); err != nil {
return err
}
if len(message.Id) == 0 {
@ -122,9 +150,9 @@ func ValidateReceivedDeclineRequestTransaction(message *protobuf.DeclineRequestT
return nil
}
func ValidateReceivedChatMessage(message *protobuf.ChatMessage) error {
if message.Clock == 0 {
return errors.New("clock can't be 0")
func ValidateReceivedChatMessage(message *protobuf.ChatMessage, whisperTimestamp uint64) error {
if err := validateClockValue(message.Clock, whisperTimestamp); err != nil {
return err
}
if message.Timestamp == 0 {

View File

@ -18,13 +18,15 @@ func TestMessageValidatorSuite(t *testing.T) {
func (s *MessageValidatorSuite) TestValidateRequestAddressForTransaction() {
testCases := []struct {
Name string
Valid bool
Message protobuf.RequestAddressForTransaction
Name string
WhisperTimestamp uint64
Valid bool
Message protobuf.RequestAddressForTransaction
}{
{
Name: "valid message",
Valid: true,
Name: "valid message",
WhisperTimestamp: 30,
Valid: true,
Message: protobuf.RequestAddressForTransaction{
Clock: 30,
Value: "0.34",
@ -32,34 +34,47 @@ func (s *MessageValidatorSuite) TestValidateRequestAddressForTransaction() {
},
},
{
Name: "missing clock value",
Valid: false,
Name: "missing clock value",
WhisperTimestamp: 30,
Valid: false,
Message: protobuf.RequestAddressForTransaction{
Value: "0.34",
Contract: "some contract",
},
},
{
Name: "missing value",
Valid: false,
Name: "missing value",
WhisperTimestamp: 30,
Valid: false,
Message: protobuf.RequestAddressForTransaction{
Clock: 30,
Contract: "some contract",
},
},
{
Name: "non number value",
Valid: false,
Name: "non number value",
WhisperTimestamp: 30,
Valid: false,
Message: protobuf.RequestAddressForTransaction{
Clock: 30,
Value: "most definitely not a number",
Contract: "some contract",
},
},
{
Name: "Clock value too high",
WhisperTimestamp: 30,
Valid: false,
Message: protobuf.RequestAddressForTransaction{
Clock: 151000,
Value: "0.34",
Contract: "some contract",
},
},
}
for _, tc := range testCases {
s.Run(tc.Name, func() {
err := ValidateReceivedRequestAddressForTransaction(&tc.Message)
err := ValidateReceivedRequestAddressForTransaction(&tc.Message, tc.WhisperTimestamp)
if tc.Valid {
s.Nil(err)
} else {
@ -72,13 +87,15 @@ func (s *MessageValidatorSuite) TestValidateRequestAddressForTransaction() {
func (s *MessageValidatorSuite) TestValidatePlainTextMessage() {
testCases := []struct {
Name string
Valid bool
Message protobuf.ChatMessage
Name string
WhisperTimestamp uint64
Valid bool
Message protobuf.ChatMessage
}{
{
Name: "A valid message",
Valid: true,
Name: "A valid message",
WhisperTimestamp: 2,
Valid: true,
Message: protobuf.ChatMessage{
ChatId: "a",
Clock: 1,
@ -91,8 +108,9 @@ func (s *MessageValidatorSuite) TestValidatePlainTextMessage() {
},
},
{
Name: "Missing chatId",
Valid: false,
Name: "Missing chatId",
WhisperTimestamp: 2,
Valid: false,
Message: protobuf.ChatMessage{
Clock: 1,
Timestamp: 2,
@ -104,8 +122,9 @@ func (s *MessageValidatorSuite) TestValidatePlainTextMessage() {
},
},
{
Name: "Missing clock",
Valid: false,
Name: "Missing clock",
WhisperTimestamp: 2,
Valid: false,
Message: protobuf.ChatMessage{
ChatId: "a",
Timestamp: 2,
@ -117,8 +136,24 @@ func (s *MessageValidatorSuite) TestValidatePlainTextMessage() {
},
},
{
Name: "Missing timestamp",
Valid: false,
Name: "Clock value too high",
WhisperTimestamp: 2,
Valid: false,
Message: protobuf.ChatMessage{
ChatId: "a",
Clock: 133000,
Timestamp: 1,
Text: "some-text",
ResponseTo: "",
EnsName: "",
MessageType: protobuf.ChatMessage_ONE_TO_ONE,
ContentType: protobuf.ChatMessage_TEXT_PLAIN,
},
},
{
Name: "Missing timestamp",
WhisperTimestamp: 2,
Valid: false,
Message: protobuf.ChatMessage{
ChatId: "a",
Clock: 2,
@ -130,8 +165,9 @@ func (s *MessageValidatorSuite) TestValidatePlainTextMessage() {
},
},
{
Name: "Missing text",
Valid: false,
Name: "Missing text",
WhisperTimestamp: 2,
Valid: false,
Message: protobuf.ChatMessage{
ChatId: "a",
Clock: 2,
@ -143,8 +179,9 @@ func (s *MessageValidatorSuite) TestValidatePlainTextMessage() {
},
},
{
Name: "Blank text",
Valid: false,
Name: "Blank text",
WhisperTimestamp: 2,
Valid: false,
Message: protobuf.ChatMessage{
ChatId: "a",
Text: " \n \t \n ",
@ -157,8 +194,9 @@ func (s *MessageValidatorSuite) TestValidatePlainTextMessage() {
},
},
{
Name: "Unknown MessageType",
Valid: false,
Name: "Unknown MessageType",
WhisperTimestamp: 2,
Valid: false,
Message: protobuf.ChatMessage{
ChatId: "a",
Text: "valid",
@ -171,8 +209,9 @@ func (s *MessageValidatorSuite) TestValidatePlainTextMessage() {
},
},
{
Name: "Unknown ContentType",
Valid: false,
Name: "Unknown ContentType",
WhisperTimestamp: 2,
Valid: false,
Message: protobuf.ChatMessage{
ChatId: "a",
Text: "valid",
@ -185,8 +224,9 @@ func (s *MessageValidatorSuite) TestValidatePlainTextMessage() {
},
},
{
Name: "System message MessageType",
Valid: false,
Name: "System message MessageType",
WhisperTimestamp: 2,
Valid: false,
Message: protobuf.ChatMessage{
ChatId: "a",
Text: "valid",
@ -199,8 +239,9 @@ func (s *MessageValidatorSuite) TestValidatePlainTextMessage() {
},
},
{
Name: "Request address for transaction message type",
Valid: false,
Name: "Request address for transaction message type",
WhisperTimestamp: 2,
Valid: false,
Message: protobuf.ChatMessage{
ChatId: "a",
Text: "valid",
@ -213,8 +254,9 @@ func (s *MessageValidatorSuite) TestValidatePlainTextMessage() {
},
},
{
Name: "Valid emoji only emssage",
Valid: true,
Name: "Valid emoji only emssage",
WhisperTimestamp: 2,
Valid: true,
Message: protobuf.ChatMessage{
ChatId: "a",
Text: ":+1:",
@ -243,8 +285,9 @@ func (s *MessageValidatorSuite) TestValidatePlainTextMessage() {
}
,*/
{
Name: "Valid sticker message",
Valid: true,
Name: "Valid sticker message",
WhisperTimestamp: 2,
Valid: true,
Message: protobuf.ChatMessage{
ChatId: "a",
Text: "valid",
@ -263,8 +306,9 @@ func (s *MessageValidatorSuite) TestValidatePlainTextMessage() {
},
},
{
Name: "Invalid sticker message without Hash",
Valid: false,
Name: "Invalid sticker message without Hash",
WhisperTimestamp: 2,
Valid: false,
Message: protobuf.ChatMessage{
ChatId: "a",
Text: "valid",
@ -282,8 +326,9 @@ func (s *MessageValidatorSuite) TestValidatePlainTextMessage() {
},
},
{
Name: "Invalid sticker message without any content",
Valid: false,
Name: "Invalid sticker message without any content",
WhisperTimestamp: 2,
Valid: false,
Message: protobuf.ChatMessage{
ChatId: "a",
Text: "valid",
@ -299,7 +344,7 @@ func (s *MessageValidatorSuite) TestValidatePlainTextMessage() {
for _, tc := range testCases {
s.Run(tc.Name, func() {
err := ValidateReceivedChatMessage(&tc.Message)
err := ValidateReceivedChatMessage(&tc.Message, tc.WhisperTimestamp)
if tc.Valid {
s.Nil(err)
} else {

View File

@ -283,6 +283,7 @@ func NewMessenger(
// Initialize transport layer.
var transp transport.Transport
if shh, err := node.GetWhisper(nil); err == nil {
transp, err = shhtransp.NewWhisperServiceTransport(
shh,
@ -631,14 +632,14 @@ func (m *Messenger) CreateGroupChatWithMembers(ctx context.Context, name string,
var response MessengerResponse
logger := m.logger.With(zap.String("site", "CreateGroupChatWithMembers"))
logger.Info("Creating group chat", zap.String("name", name), zap.Any("members", members))
chat := createGroupChat()
chat := createGroupChat(m.getTimesource())
group, err := v1protocol.NewGroupWithCreator(name, m.identity)
if err != nil {
return nil, err
}
chat.updateChatFromProtocolGroup(group)
clock, _ := chat.NextClockAndTimestamp()
clock, _ := chat.NextClockAndTimestamp(m.getTimesource())
// Add members
event := v1protocol.NewMembersAddedEvent(members, clock)
event.ChatID = chat.ID
@ -710,7 +711,7 @@ func (m *Messenger) RemoveMemberFromGroupChat(ctx context.Context, chatID string
return nil, err
}
clock, _ := chat.NextClockAndTimestamp()
clock, _ := chat.NextClockAndTimestamp(m.getTimesource())
// Remove member
event := v1protocol.NewMemberRemovedEvent(member, clock)
event.ChatID = chat.ID
@ -767,7 +768,7 @@ func (m *Messenger) AddMembersToGroupChat(ctx context.Context, chatID string, me
return nil, err
}
clock, _ := chat.NextClockAndTimestamp()
clock, _ := chat.NextClockAndTimestamp(m.getTimesource())
// Add members
event := v1protocol.NewMembersAddedEvent(members, clock)
event.ChatID = chat.ID
@ -832,7 +833,7 @@ func (m *Messenger) AddAdminsToGroupChat(ctx context.Context, chatID string, mem
return nil, err
}
clock, _ := chat.NextClockAndTimestamp()
clock, _ := chat.NextClockAndTimestamp(m.getTimesource())
// Add members
event := v1protocol.NewAdminsAddedEvent(members, clock)
event.ChatID = chat.ID
@ -899,7 +900,7 @@ func (m *Messenger) ConfirmJoiningGroup(ctx context.Context, chatID string) (*Me
if err != nil {
return nil, err
}
clock, _ := chat.NextClockAndTimestamp()
clock, _ := chat.NextClockAndTimestamp(m.getTimesource())
event := v1protocol.NewMemberJoinedEvent(
clock,
)
@ -966,7 +967,7 @@ func (m *Messenger) LeaveGroupChat(ctx context.Context, chatID string) (*Messeng
if err != nil {
return nil, err
}
clock, _ := chat.NextClockAndTimestamp()
clock, _ := chat.NextClockAndTimestamp(m.getTimesource())
event := v1protocol.NewMemberRemovedEvent(
contactIDFromPublicKey(&m.identity.PublicKey),
clock,
@ -1146,10 +1147,6 @@ func (m *Messenger) Contacts() []*Contact {
return contacts
}
func timestampInMs() uint64 {
return uint64(time.Now().UnixNano() / int64(time.Millisecond))
}
// ReSendChatMessage pulls a message from the database and sends it again
func (m *Messenger) ReSendChatMessage(ctx context.Context, messageID string) error {
m.mutex.Lock()
@ -1307,7 +1304,7 @@ func (m *Messenger) SendChatMessage(ctx context.Context, message *Message) (*Mes
return nil, errors.New("Chat not found")
}
err := extendMessageFromChat(message, chat, &m.identity.PublicKey)
err := extendMessageFromChat(message, chat, &m.identity.PublicKey, m.getTimesource())
if err != nil {
return nil, err
}
@ -1361,7 +1358,7 @@ func (m *Messenger) SendChatMessage(ctx context.Context, message *Message) (*Mes
return nil, err
}
err = chat.UpdateFromMessage(message)
err = chat.UpdateFromMessage(message, m.getTimesource())
if err != nil {
return nil, err
}
@ -1432,13 +1429,13 @@ func (m *Messenger) sendContactUpdate(ctx context.Context, chatID, ensName, prof
if err != nil {
return nil, err
}
chat = OneToOneFromPublicKey(publicKey)
chat = OneToOneFromPublicKey(publicKey, m.getTimesource())
// We don't want to show the chat to the user
chat.Active = false
}
m.allChats[chat.ID] = chat
clock, _ := chat.NextClockAndTimestamp()
clock, _ := chat.NextClockAndTimestamp(m.getTimesource())
contactUpdate := &protobuf.ContactUpdate{
Clock: clock,
@ -1525,13 +1522,13 @@ func (m *Messenger) SendPairInstallation(ctx context.Context) (*MessengerRespons
chat, ok := m.allChats[chatID]
if !ok {
chat = OneToOneFromPublicKey(&m.identity.PublicKey)
chat = OneToOneFromPublicKey(&m.identity.PublicKey, m.getTimesource())
// We don't want to show the chat to the user
chat.Active = false
}
m.allChats[chat.ID] = chat
clock, _ := chat.NextClockAndTimestamp()
clock, _ := chat.NextClockAndTimestamp(m.getTimesource())
pairMessage := &protobuf.PairInstallation{
Clock: clock,
@ -1573,13 +1570,13 @@ func (m *Messenger) syncPublicChat(ctx context.Context, publicChat *Chat) error
chat, ok := m.allChats[chatID]
if !ok {
chat = OneToOneFromPublicKey(&m.identity.PublicKey)
chat = OneToOneFromPublicKey(&m.identity.PublicKey, m.getTimesource())
// We don't want to show the chat to the user
chat.Active = false
}
m.allChats[chat.ID] = chat
clock, _ := chat.NextClockAndTimestamp()
clock, _ := chat.NextClockAndTimestamp(m.getTimesource())
syncMessage := &protobuf.SyncInstallationPublicChat{
Clock: clock,
@ -1614,13 +1611,13 @@ func (m *Messenger) syncContact(ctx context.Context, contact *Contact) error {
chat, ok := m.allChats[chatID]
if !ok {
chat = OneToOneFromPublicKey(&m.identity.PublicKey)
chat = OneToOneFromPublicKey(&m.identity.PublicKey, m.getTimesource())
// We don't want to show the chat to the user
chat.Active = false
}
m.allChats[chat.ID] = chat
clock, _ := chat.NextClockAndTimestamp()
clock, _ := chat.NextClockAndTimestamp(m.getTimesource())
syncMessage := &protobuf.SyncInstallationContact{
Clock: clock,
@ -1705,6 +1702,8 @@ type ReceivedMessageState struct {
ExistingMessagesMap map[string]bool
// Response to the client
Response *MessengerResponse
// Timesource is a timesource for clock values/timestamps
Timesource ClockValueTimesource
}
func (m *Messenger) handleRetrievedMessages(chatWithMessages map[transport.Filter][]*types.Message) (*MessengerResponse, error) {
@ -1719,6 +1718,7 @@ func (m *Messenger) handleRetrievedMessages(chatWithMessages map[transport.Filte
ModifiedInstallations: m.modifiedInstallations,
ExistingMessagesMap: make(map[string]bool),
Response: &MessengerResponse{},
Timesource: m.getTimesource(),
}
logger := m.logger.With(zap.String("site", "RetrieveAll"))
@ -2111,7 +2111,7 @@ func (m *Messenger) RequestTransaction(ctx context.Context, chatID, value, contr
}
message := &Message{}
err := extendMessageFromChat(message, chat, &m.identity.PublicKey)
err := extendMessageFromChat(message, chat, &m.identity.PublicKey, m.transport)
if err != nil {
return nil, err
}
@ -2157,7 +2157,7 @@ func (m *Messenger) RequestTransaction(ctx context.Context, chatID, value, contr
return nil, err
}
err = chat.UpdateFromMessage(message)
err = chat.UpdateFromMessage(message, m.transport)
if err != nil {
return nil, err
}
@ -2188,7 +2188,7 @@ func (m *Messenger) RequestAddressForTransaction(ctx context.Context, chatID, fr
}
message := &Message{}
err := extendMessageFromChat(message, chat, &m.identity.PublicKey)
err := extendMessageFromChat(message, chat, &m.identity.PublicKey, m.transport)
if err != nil {
return nil, err
}
@ -2233,7 +2233,7 @@ func (m *Messenger) RequestAddressForTransaction(ctx context.Context, chatID, fr
return nil, err
}
err = chat.UpdateFromMessage(message)
err = chat.UpdateFromMessage(message, m.transport)
if err != nil {
return nil, err
}
@ -2274,7 +2274,7 @@ func (m *Messenger) AcceptRequestAddressForTransaction(ctx context.Context, mess
return nil, errors.New("Need to be a one-to-one chat")
}
clock, timestamp := chat.NextClockAndTimestamp()
clock, timestamp := chat.NextClockAndTimestamp(m.transport)
message.Clock = clock
message.WhisperTimestamp = timestamp
message.Timestamp = timestamp
@ -2328,7 +2328,7 @@ func (m *Messenger) AcceptRequestAddressForTransaction(ctx context.Context, mess
return nil, err
}
err = chat.UpdateFromMessage(message)
err = chat.UpdateFromMessage(message, m.transport)
if err != nil {
return nil, err
}
@ -2369,7 +2369,7 @@ func (m *Messenger) DeclineRequestTransaction(ctx context.Context, messageID str
return nil, errors.New("Need to be a one-to-one chat")
}
clock, timestamp := chat.NextClockAndTimestamp()
clock, timestamp := chat.NextClockAndTimestamp(m.transport)
message.Clock = clock
message.WhisperTimestamp = timestamp
message.Timestamp = timestamp
@ -2410,7 +2410,7 @@ func (m *Messenger) DeclineRequestTransaction(ctx context.Context, messageID str
return nil, err
}
err = chat.UpdateFromMessage(message)
err = chat.UpdateFromMessage(message, m.transport)
if err != nil {
return nil, err
}
@ -2451,7 +2451,7 @@ func (m *Messenger) DeclineRequestAddressForTransaction(ctx context.Context, mes
return nil, errors.New("Need to be a one-to-one chat")
}
clock, timestamp := chat.NextClockAndTimestamp()
clock, timestamp := chat.NextClockAndTimestamp(m.transport)
message.Clock = clock
message.WhisperTimestamp = timestamp
message.Timestamp = timestamp
@ -2492,7 +2492,7 @@ func (m *Messenger) DeclineRequestAddressForTransaction(ctx context.Context, mes
return nil, err
}
err = chat.UpdateFromMessage(message)
err = chat.UpdateFromMessage(message, m.transport)
if err != nil {
return nil, err
}
@ -2533,7 +2533,7 @@ func (m *Messenger) AcceptRequestTransaction(ctx context.Context, transactionHas
return nil, errors.New("Need to be a one-to-one chat")
}
clock, timestamp := chat.NextClockAndTimestamp()
clock, timestamp := chat.NextClockAndTimestamp(m.transport)
message.Clock = clock
message.WhisperTimestamp = timestamp
message.Timestamp = timestamp
@ -2591,7 +2591,7 @@ func (m *Messenger) AcceptRequestTransaction(ctx context.Context, transactionHas
return nil, err
}
err = chat.UpdateFromMessage(message)
err = chat.UpdateFromMessage(message, m.transport)
if err != nil {
return nil, err
}
@ -2622,7 +2622,7 @@ func (m *Messenger) SendTransaction(ctx context.Context, chatID, value, contract
}
message := &Message{}
err := extendMessageFromChat(message, chat, &m.identity.PublicKey)
err := extendMessageFromChat(message, chat, &m.identity.PublicKey, m.transport)
if err != nil {
return nil, err
}
@ -2631,7 +2631,7 @@ func (m *Messenger) SendTransaction(ctx context.Context, chatID, value, contract
message.ContentType = protobuf.ChatMessage_TRANSACTION_COMMAND
message.LocalChatID = chatID
clock, timestamp := chat.NextClockAndTimestamp()
clock, timestamp := chat.NextClockAndTimestamp(m.transport)
message.Clock = clock
message.WhisperTimestamp = timestamp
message.Timestamp = timestamp
@ -2672,7 +2672,7 @@ func (m *Messenger) SendTransaction(ctx context.Context, chatID, value, contract
return nil, err
}
err = chat.UpdateFromMessage(message)
err = chat.UpdateFromMessage(message, m.transport)
if err != nil {
return nil, err
}
@ -2716,13 +2716,13 @@ func (m *Messenger) ValidateTransactions(ctx context.Context, addresses []types.
chatID := contactIDFromPublicKey(validationResult.Transaction.From)
chat, ok := m.allChats[chatID]
if !ok {
chat = OneToOneFromPublicKey(validationResult.Transaction.From)
chat = OneToOneFromPublicKey(validationResult.Transaction.From, m.transport)
}
if validationResult.Message != nil {
message = validationResult.Message
} else {
message = &Message{}
err := extendMessageFromChat(message, chat, &m.identity.PublicKey)
err := extendMessageFromChat(message, chat, &m.identity.PublicKey, m.transport)
if err != nil {
return nil, err
}
@ -2733,7 +2733,7 @@ func (m *Messenger) ValidateTransactions(ctx context.Context, addresses []types.
message.LocalChatID = chatID
message.OutgoingStatus = ""
clock, timestamp := chat.NextClockAndTimestamp()
clock, timestamp := chat.NextClockAndTimestamp(m.transport)
message.Clock = clock
message.Timestamp = timestamp
message.WhisperTimestamp = timestamp
@ -2757,7 +2757,7 @@ func (m *Messenger) ValidateTransactions(ctx context.Context, addresses []types.
return nil, err
}
err = chat.UpdateFromMessage(message)
err = chat.UpdateFromMessage(message, m.transport)
if err != nil {
return nil, err
}
@ -2795,3 +2795,7 @@ func (m *Messenger) ValidateTransactions(ctx context.Context, addresses []types.
}
return &response, nil
}
func (m *Messenger) getTimesource() ClockValueTimesource {
return m.transport
}

View File

@ -143,7 +143,7 @@ func (s *MessengerInstallationSuite) TestReceiveInstallation() {
s.Require().Equal(contact.ID, actualContact.ID)
s.Require().True(actualContact.IsAdded())
chat := CreatePublicChat("status")
chat := CreatePublicChat("status", s.m.transport)
err = s.m.SaveChat(&chat)
s.Require().NoError(err)
@ -176,7 +176,7 @@ func (s *MessengerInstallationSuite) TestSyncInstallation() {
s.Require().NoError(err)
// add chat
chat := CreatePublicChat("status")
chat := CreatePublicChat("status", s.m.transport)
err = s.m.SaveChat(&chat)
s.Require().NoError(err)

View File

@ -273,12 +273,13 @@ func (s *MessengerSuite) TestInit() {
}
func buildTestMessage(chat Chat) *Message {
clock, timestamp := chat.NextClockAndTimestamp(&testTimeSource{})
message := &Message{}
message.Text = "text-input-message"
message.ChatId = chat.ID
message.Clock = 2
message.WhisperTimestamp = 10
message.Clock = clock
message.Timestamp = timestamp
message.WhisperTimestamp = clock
message.LocalChatID = chat.ID
message.ContentType = protobuf.ChatMessage_TEXT_PLAIN
switch chat.ChatType {
@ -294,7 +295,7 @@ func buildTestMessage(chat Chat) *Message {
}
func (s *MessengerSuite) TestMarkMessagesSeen() {
chat := CreatePublicChat("test-chat")
chat := CreatePublicChat("test-chat", s.m.transport)
chat.UnviewedMessagesCount = 2
err := s.m.SaveChat(&chat)
s.Require().NoError(err)
@ -317,7 +318,7 @@ func (s *MessengerSuite) TestMarkMessagesSeen() {
}
func (s *MessengerSuite) TestSendPublic() {
chat := CreatePublicChat("test-chat")
chat := CreatePublicChat("test-chat", s.m.transport)
chat.LastClockValue = uint64(100000000000000)
err := s.m.SaveChat(&chat)
s.NoError(err)
@ -346,7 +347,7 @@ func (s *MessengerSuite) TestSendPrivateOneToOne() {
recipientKey, err := crypto.GenerateKey()
s.NoError(err)
pkString := hex.EncodeToString(crypto.FromECDSAPub(&recipientKey.PublicKey))
chat := CreateOneToOneChat(pkString, &recipientKey.PublicKey)
chat := CreateOneToOneChat(pkString, &recipientKey.PublicKey, s.m.transport)
inputMessage := &Message{}
inputMessage.ChatId = chat.ID
@ -432,7 +433,7 @@ func (s *MessengerSuite) TestSendPrivateEmptyGroup() {
// Make sure public messages sent by us are not
func (s *MessengerSuite) TestRetrieveOwnPublic() {
chat := CreatePublicChat("status")
chat := CreatePublicChat("status", s.m.transport)
err := s.m.SaveChat(&chat)
s.NoError(err)
// Right-to-left text
@ -467,11 +468,11 @@ func (s *MessengerSuite) TestRetrieveOwnPublic() {
// Retrieve their public message
func (s *MessengerSuite) TestRetrieveTheirPublic() {
theirMessenger := s.newMessenger(s.shh)
theirChat := CreatePublicChat("status")
theirChat := CreatePublicChat("status", s.m.transport)
err := theirMessenger.SaveChat(&theirChat)
s.Require().NoError(err)
chat := CreatePublicChat("status")
chat := CreatePublicChat("status", s.m.transport)
err = s.m.SaveChat(&chat)
s.Require().NoError(err)
@ -510,11 +511,11 @@ func (s *MessengerSuite) TestRetrieveTheirPublic() {
func (s *MessengerSuite) TestDeletedAtClockValue() {
theirMessenger := s.newMessenger(s.shh)
theirChat := CreatePublicChat("status")
theirChat := CreatePublicChat("status", s.m.transport)
err := theirMessenger.SaveChat(&theirChat)
s.Require().NoError(err)
chat := CreatePublicChat("status")
chat := CreatePublicChat("status", s.m.transport)
err = s.m.SaveChat(&chat)
s.Require().NoError(err)
@ -539,11 +540,11 @@ func (s *MessengerSuite) TestDeletedAtClockValue() {
func (s *MessengerSuite) TestRetrieveBlockedContact() {
theirMessenger := s.newMessenger(s.shh)
theirChat := CreatePublicChat("status")
theirChat := CreatePublicChat("status", s.m.transport)
err := theirMessenger.SaveChat(&theirChat)
s.Require().NoError(err)
chat := CreatePublicChat("status")
chat := CreatePublicChat("status", s.m.transport)
err = s.m.SaveChat(&chat)
s.Require().NoError(err)
@ -553,7 +554,6 @@ func (s *MessengerSuite) TestRetrieveBlockedContact() {
publicKeyHex := "0x" + hex.EncodeToString(crypto.FromECDSAPub(&theirMessenger.identity.PublicKey))
blockedContact := Contact{
ID: publicKeyHex,
Address: "contact-address",
Name: "contact-name",
Photo: "contact-photo",
LastUpdated: 20,
@ -578,11 +578,11 @@ func (s *MessengerSuite) TestRetrieveBlockedContact() {
// Resend their public message, receive only once
func (s *MessengerSuite) TestResendPublicMessage() {
theirMessenger := s.newMessenger(s.shh)
theirChat := CreatePublicChat("status")
theirChat := CreatePublicChat("status", s.m.transport)
err := theirMessenger.SaveChat(&theirChat)
s.Require().NoError(err)
chat := CreatePublicChat("status")
chat := CreatePublicChat("status", s.m.transport)
err = s.m.SaveChat(&chat)
s.Require().NoError(err)
@ -635,11 +635,11 @@ func (s *MessengerSuite) TestResendPublicMessage() {
// Test receiving a message on an existing private chat
func (s *MessengerSuite) TestRetrieveTheirPrivateChatExisting() {
theirMessenger := s.newMessenger(s.shh)
theirChat := CreateOneToOneChat("XXX", &s.privateKey.PublicKey)
theirChat := CreateOneToOneChat("XXX", &s.privateKey.PublicKey, s.m.transport)
err := theirMessenger.SaveChat(&theirChat)
s.Require().NoError(err)
ourChat := CreateOneToOneChat("our-chat", &theirMessenger.identity.PublicKey)
ourChat := CreateOneToOneChat("our-chat", &theirMessenger.identity.PublicKey, s.m.transport)
ourChat.UnviewedMessagesCount = 1
// Make chat inactive
ourChat.Active = false
@ -679,7 +679,7 @@ func (s *MessengerSuite) TestRetrieveTheirPrivateChatExisting() {
// Test receiving a message on an non-existing private chat
func (s *MessengerSuite) TestRetrieveTheirPrivateChatNonExisting() {
theirMessenger := s.newMessenger(s.shh)
chat := CreateOneToOneChat("XXX", &s.privateKey.PublicKey)
chat := CreateOneToOneChat("XXX", &s.privateKey.PublicKey, s.m.transport)
err := theirMessenger.SaveChat(&chat)
s.NoError(err)
@ -718,7 +718,7 @@ func (s *MessengerSuite) TestRetrieveTheirPrivateChatNonExisting() {
// Test receiving a message on an non-existing public chat
func (s *MessengerSuite) TestRetrieveTheirPublicChatNonExisting() {
theirMessenger := s.newMessenger(s.shh)
chat := CreatePublicChat("test-chat")
chat := CreatePublicChat("test-chat", s.m.transport)
err := theirMessenger.SaveChat(&chat)
s.NoError(err)
@ -1093,7 +1093,6 @@ func (s *MessengerSuite) TestBlockContact() {
contact := Contact{
ID: pk,
Address: "contact-address",
Name: "contact-name",
Photo: "contact-photo",
LastUpdated: 20,
@ -1282,7 +1281,6 @@ func (s *MessengerSuite) TestContactPersistence() {
contact := Contact{
ID: "0x0424a68f89ba5fcd5e0640c1e1f591d561fa4125ca4e2a43592bc4123eca10ce064e522c254bb83079ba404327f6eafc01ec90a1444331fe769d3f3a7f90b0dde1",
Address: "contact-address",
Name: "contact-name",
Photo: "contact-photo",
LastUpdated: 20,
@ -1390,7 +1388,6 @@ func (s *MessengerSuite) TestContactPersistenceUpdate() {
contact := Contact{
ID: contactID,
Address: "contact-address",
Name: "contact-name",
Photo: "contact-photo",
LastUpdated: 20,
@ -1482,7 +1479,7 @@ func (s *MessengerSuite) TestDeclineRequestAddressForTransaction() {
theirMessenger := s.newMessenger(s.shh)
theirPkString := types.EncodeHex(crypto.FromECDSAPub(&theirMessenger.identity.PublicKey))
chat := CreateOneToOneChat(theirPkString, &theirMessenger.identity.PublicKey)
chat := CreateOneToOneChat(theirPkString, &theirMessenger.identity.PublicKey, s.m.transport)
err := s.m.SaveChat(&chat)
s.Require().NoError(err)
@ -1579,7 +1576,7 @@ func (s *MessengerSuite) TestSendEthTransaction() {
receiverAddress := crypto.PubkeyToAddress(theirMessenger.identity.PublicKey)
receiverAddressString := strings.ToLower(receiverAddress.Hex())
chat := CreateOneToOneChat(theirPkString, &theirMessenger.identity.PublicKey)
chat := CreateOneToOneChat(theirPkString, &theirMessenger.identity.PublicKey, s.m.transport)
err := s.m.SaveChat(&chat)
s.Require().NoError(err)
@ -1680,7 +1677,7 @@ func (s *MessengerSuite) TestSendTokenTransaction() {
receiverAddress := crypto.PubkeyToAddress(theirMessenger.identity.PublicKey)
receiverAddressString := strings.ToLower(receiverAddress.Hex())
chat := CreateOneToOneChat(theirPkString, &theirMessenger.identity.PublicKey)
chat := CreateOneToOneChat(theirPkString, &theirMessenger.identity.PublicKey, s.m.transport)
err := s.m.SaveChat(&chat)
s.Require().NoError(err)
@ -1779,7 +1776,7 @@ func (s *MessengerSuite) TestAcceptRequestAddressForTransaction() {
myAddress := crypto.PubkeyToAddress(s.m.identity.PublicKey)
chat := CreateOneToOneChat(theirPkString, &theirMessenger.identity.PublicKey)
chat := CreateOneToOneChat(theirPkString, &theirMessenger.identity.PublicKey, s.m.transport)
err := s.m.SaveChat(&chat)
s.Require().NoError(err)
@ -1874,7 +1871,7 @@ func (s *MessengerSuite) TestDeclineRequestTransaction() {
theirMessenger := s.newMessenger(s.shh)
theirPkString := types.EncodeHex(crypto.FromECDSAPub(&theirMessenger.identity.PublicKey))
chat := CreateOneToOneChat(theirPkString, &theirMessenger.identity.PublicKey)
chat := CreateOneToOneChat(theirPkString, &theirMessenger.identity.PublicKey, s.m.transport)
err := s.m.SaveChat(&chat)
s.Require().NoError(err)
@ -1967,7 +1964,7 @@ func (s *MessengerSuite) TestRequestTransaction() {
theirMessenger := s.newMessenger(s.shh)
theirPkString := types.EncodeHex(crypto.FromECDSAPub(&theirMessenger.identity.PublicKey))
chat := CreateOneToOneChat(theirPkString, &theirMessenger.identity.PublicKey)
chat := CreateOneToOneChat(theirPkString, &theirMessenger.identity.PublicKey, s.m.transport)
err := s.m.SaveChat(&chat)
s.Require().NoError(err)
@ -2203,6 +2200,12 @@ func (s *MessageHandlerSuite) TearDownTest() {
_ = s.logger.Sync()
}
type testTimeSource struct{}
func (t *testTimeSource) GetCurrentTime() uint64 {
return uint64(time.Now().Unix())
}
func (s *MessageHandlerSuite) TestRun() {
key1, err := crypto.GenerateKey()
s.Require().NoError(err)
@ -2219,7 +2222,7 @@ func (s *MessageHandlerSuite) TestRun() {
}{
{
Name: "Public chat",
Chat: CreatePublicChat("test-chat"),
Chat: CreatePublicChat("test-chat", &testTimeSource{}),
Message: Message{
ChatMessage: protobuf.ChatMessage{
ChatId: "test-chat",
@ -2231,7 +2234,7 @@ func (s *MessageHandlerSuite) TestRun() {
},
{
Name: "Private message from myself with existing chat",
Chat: CreateOneToOneChat("test-private-chat", &key1.PublicKey),
Chat: CreateOneToOneChat("test-private-chat", &key1.PublicKey, &testTimeSource{}),
Message: Message{
ChatMessage: protobuf.ChatMessage{
ChatId: "test-chat",
@ -2243,7 +2246,7 @@ func (s *MessageHandlerSuite) TestRun() {
},
{
Name: "Private message from other with existing chat",
Chat: CreateOneToOneChat("test-private-chat", &key2.PublicKey),
Chat: CreateOneToOneChat("test-private-chat", &key2.PublicKey, &testTimeSource{}),
Message: Message{
ChatMessage: protobuf.ChatMessage{
ChatId: "test-chat",
@ -2309,7 +2312,7 @@ func (s *MessageHandlerSuite) TestRun() {
s.Empty(message.LocalChatID)
message.ID = strconv.Itoa(idx) // manually set the ID because messages does not go through messageProcessor
chat, err := s.messageHandler.matchMessage(&message, chatsMap)
chat, err := s.messageHandler.matchMessage(&message, chatsMap, &testTimeSource{})
if tc.Error {
s.Require().Error(err)
} else {

View File

@ -16,6 +16,7 @@ type Transport interface {
LeaveGroup(publicKeys []*ecdsa.PublicKey) error
JoinPublic(chatID string) error
LeavePublic(chatID string) error
GetCurrentTime() uint64
SendPublic(ctx context.Context, newMessage *types.NewMessage, chatName string) ([]byte, error)
SendPrivateWithSharedSecret(ctx context.Context, newMessage *types.NewMessage, publicKey *ecdsa.PublicKey, secret []byte) ([]byte, error)

View File

@ -6,6 +6,7 @@ import (
"crypto/ecdsa"
"database/sql"
"sync"
"time"
"github.com/pkg/errors"
"go.uber.org/zap"
@ -360,6 +361,11 @@ func (a *WakuServiceTransport) Track(identifiers [][]byte, hash []byte, newMessa
}
}
// GetCurrentTime returns the current unix timestamp in milliseconds
func (a *WakuServiceTransport) GetCurrentTime() uint64 {
return uint64(a.waku.GetCurrentTime().UnixNano() / int64(time.Millisecond))
}
func (a *WakuServiceTransport) Stop() error {
if a.envelopesMonitor != nil {
a.envelopesMonitor.Stop()

View File

@ -6,6 +6,7 @@ import (
"crypto/ecdsa"
"database/sql"
"sync"
"time"
"github.com/pkg/errors"
"go.uber.org/zap"
@ -360,6 +361,11 @@ func (a *WhisperServiceTransport) Track(identifiers [][]byte, hash []byte, newMe
}
}
// GetCurrentTime returns the current unix timestamp in milliseconds
func (a *WhisperServiceTransport) GetCurrentTime() uint64 {
return uint64(a.shh.GetCurrentTime().UnixNano() / int64(time.Millisecond))
}
func (a *WhisperServiceTransport) Stop() error {
if a.envelopesMonitor != nil {
a.envelopesMonitor.Stop()

View File

@ -207,39 +207,39 @@ func oneToOneChatID(publicKey *ecdsa.PublicKey) string {
return types.EncodeHex(crypto.FromECDSAPub(publicKey))
}
func OneToOneFromPublicKey(pk *ecdsa.PublicKey) *Chat {
func OneToOneFromPublicKey(pk *ecdsa.PublicKey, timesource ClockValueTimesource) *Chat {
chatID := types.EncodeHex(crypto.FromECDSAPub(pk))
newChat := CreateOneToOneChat(chatID[:8], pk)
newChat := CreateOneToOneChat(chatID[:8], pk, timesource)
return &newChat
}
func CreateOneToOneChat(name string, publicKey *ecdsa.PublicKey) Chat {
func CreateOneToOneChat(name string, publicKey *ecdsa.PublicKey, timesource ClockValueTimesource) Chat {
return Chat{
ID: oneToOneChatID(publicKey),
Name: name,
Timestamp: int64(timestampInMs()),
Timestamp: int64(timesource.GetCurrentTime()),
Active: true,
ChatType: ChatTypeOneToOne,
}
}
func CreatePublicChat(name string) Chat {
func CreatePublicChat(name string, timesource ClockValueTimesource) Chat {
return Chat{
ID: name,
Name: name,
Active: true,
Timestamp: int64(timestampInMs()),
Timestamp: int64(timesource.GetCurrentTime()),
Color: chatColors[rand.Intn(len(chatColors))],
ChatType: ChatTypePublic,
}
}
func createGroupChat() Chat {
func createGroupChat(timesource ClockValueTimesource) Chat {
return Chat{
Active: true,
Color: chatColors[rand.Intn(len(chatColors))],
Timestamp: int64(timestampInMs()),
Timestamp: int64(timesource.GetCurrentTime()),
ChatType: ChatTypePrivateGroupChat,
}
}
@ -276,11 +276,15 @@ func stringSliceToPublicKeys(slice []string, prefixed bool) ([]*ecdsa.PublicKey,
return result, nil
}
type ClockValueTimesource interface {
GetCurrentTime() uint64
}
// NextClockAndTimestamp returns the next clock value
// and the current timestamp
func (c *Chat) NextClockAndTimestamp() (uint64, uint64) {
func (c *Chat) NextClockAndTimestamp(timesource ClockValueTimesource) (uint64, uint64) {
clock := c.LastClockValue
timestamp := timestampInMs()
timestamp := timesource.GetCurrentTime()
if clock == 0 || clock < timestamp {
clock = timestamp
} else {
@ -289,8 +293,8 @@ func (c *Chat) NextClockAndTimestamp() (uint64, uint64) {
return clock, timestamp
}
func (c *Chat) UpdateFromMessage(message *Message) error {
c.Timestamp = int64(timestampInMs())
func (c *Chat) UpdateFromMessage(message *Message, timesource ClockValueTimesource) error {
c.Timestamp = int64(timesource.GetCurrentTime())
if c.LastClockValue <= message.Clock {
jsonMessage, err := json.Marshal(message)
if err != nil {

View File

@ -3,7 +3,6 @@ package protocol
import (
"crypto/ecdsa"
"encoding/hex"
"strings"
"github.com/status-im/status-go/eth-node/crypto"
"github.com/status-im/status-go/eth-node/types"
@ -33,7 +32,7 @@ type Contact struct {
// ID of the contact. It's a hex-encoded public key (prefixed with 0x).
ID string `json:"id"`
// Ethereum address of the contact
Address string `json:"address"`
Address string `json:"address,omitempty"`
// ENS name of contact
Name string `json:"name,omitempty"`
// EnsVerified whether we verified the name of the contact
@ -88,8 +87,6 @@ func existsInStringSlice(set []string, find string) bool {
}
func buildContact(publicKey *ecdsa.PublicKey) (*Contact, error) {
address := strings.ToLower(crypto.PubkeyToAddress(*publicKey).Hex())
id := "0x" + hex.EncodeToString(crypto.FromECDSAPub(publicKey))
identicon, err := identicon.GenerateBase64(id)
@ -99,7 +96,6 @@ func buildContact(publicKey *ecdsa.PublicKey) (*Contact, error) {
contact := &Contact{
ID: id,
Address: address[2:],
Alias: alias.GenerateFromPublicKey(publicKey),
Identicon: identicon,
}

View File

@ -9,8 +9,8 @@ import (
"github.com/status-im/status-go/protocol/identity/identicon"
)
func extendMessageFromChat(message *Message, chat *Chat, key *ecdsa.PublicKey) error {
clock, timestamp := chat.NextClockAndTimestamp()
func extendMessageFromChat(message *Message, chat *Chat, key *ecdsa.PublicKey, timesource ClockValueTimesource) error {
clock, timestamp := chat.NextClockAndTimestamp(timesource)
message.LocalChatID = chat.ID
message.Clock = clock

View File

@ -33,12 +33,19 @@ func (m *MessageHandler) HandleMembershipUpdate(messageState *ReceivedMessageSta
var group *v1protocol.Group
var err error
logger := m.logger.With(zap.String("site", "HandleMembershipUpdate"))
message, err := v1protocol.MembershipUpdateMessageFromProtobuf(&rawMembershipUpdate)
if err != nil {
return err
}
if err := ValidateMembershipUpdateMessage(message, messageState.Timesource.GetCurrentTime()); err != nil {
logger.Warn("failed to validate message", zap.Error(err))
return err
}
if chat == nil {
if len(message.Events) == 0 {
return errors.New("can't create new group chat without events")
@ -52,7 +59,7 @@ func (m *MessageHandler) HandleMembershipUpdate(messageState *ReceivedMessageSta
if !group.IsMember(contactIDFromPublicKey(&m.identity.PublicKey)) {
return errors.New("can't create a new group chat without us being a member")
}
newChat := createGroupChat()
newChat := createGroupChat(messageState.Timesource)
chat = &newChat
} else {
@ -108,7 +115,7 @@ func (m *MessageHandler) handleCommandMessage(state *ReceivedMessageState, messa
message.WhisperTimestamp = state.CurrentMessageState.WhisperTimestamp
message.PrepareContent()
chat, err := m.matchMessage(message, state.AllChats)
chat, err := m.matchMessage(message, state.AllChats, state.Timesource)
if err != nil {
return err
}
@ -137,7 +144,7 @@ func (m *MessageHandler) handleCommandMessage(state *ReceivedMessageState, messa
message.OutgoingStatus = OutgoingStatusSent
}
err = chat.UpdateFromMessage(message)
err = chat.UpdateFromMessage(message, state.Timesource)
if err != nil {
return err
}
@ -158,7 +165,7 @@ func (m *MessageHandler) handleCommandMessage(state *ReceivedMessageState, messa
func (m *MessageHandler) HandleSyncInstallationContact(state *ReceivedMessageState, message protobuf.SyncInstallationContact) error {
chat, ok := state.AllChats[state.CurrentMessageState.Contact.ID]
if !ok {
chat = OneToOneFromPublicKey(state.CurrentMessageState.PublicKey)
chat = OneToOneFromPublicKey(state.CurrentMessageState.PublicKey, state.Timesource)
// We don't want to show the chat to the user
chat.Active = false
}
@ -205,7 +212,7 @@ func (m *MessageHandler) HandleSyncInstallationPublicChat(state *ReceivedMessage
return nil
}
chat := CreatePublicChat(chatID)
chat := CreatePublicChat(chatID, state.Timesource)
state.AllChats[chat.ID] = &chat
state.ModifiedChats[chat.ID] = true
@ -218,7 +225,7 @@ func (m *MessageHandler) HandleContactUpdate(state *ReceivedMessageState, messag
contact := state.CurrentMessageState.Contact
chat, ok := state.AllChats[contact.ID]
if !ok {
chat = OneToOneFromPublicKey(state.CurrentMessageState.PublicKey)
chat = OneToOneFromPublicKey(state.CurrentMessageState.PublicKey, state.Timesource)
// We don't want to show the chat to the user
chat.Active = false
}
@ -252,7 +259,7 @@ func (m *MessageHandler) HandleContactUpdate(state *ReceivedMessageState, messag
func (m *MessageHandler) HandlePairInstallation(state *ReceivedMessageState, message protobuf.PairInstallation) error {
logger := m.logger.With(zap.String("site", "HandlePairInstallation"))
if err := ValidateReceivedPairInstallation(&message); err != nil {
if err := ValidateReceivedPairInstallation(&message, state.CurrentMessageState.WhisperTimestamp); err != nil {
logger.Warn("failed to validate message", zap.Error(err))
return err
}
@ -276,7 +283,7 @@ func (m *MessageHandler) HandlePairInstallation(state *ReceivedMessageState, mes
func (m *MessageHandler) HandleChatMessage(state *ReceivedMessageState) error {
logger := m.logger.With(zap.String("site", "handleChatMessage"))
if err := ValidateReceivedChatMessage(&state.CurrentMessageState.Message); err != nil {
if err := ValidateReceivedChatMessage(&state.CurrentMessageState.Message, state.CurrentMessageState.WhisperTimestamp); err != nil {
logger.Warn("failed to validate message", zap.Error(err))
return err
}
@ -291,7 +298,7 @@ func (m *MessageHandler) HandleChatMessage(state *ReceivedMessageState) error {
}
receivedMessage.PrepareContent()
chat, err := m.matchMessage(receivedMessage, state.AllChats)
chat, err := m.matchMessage(receivedMessage, state.AllChats, state.Timesource)
if err != nil {
return err
}
@ -319,7 +326,7 @@ func (m *MessageHandler) HandleChatMessage(state *ReceivedMessageState) error {
receivedMessage.OutgoingStatus = OutgoingStatusSent
}
err = chat.UpdateFromMessage(receivedMessage)
err = chat.UpdateFromMessage(receivedMessage, state.Timesource)
if err != nil {
return err
}
@ -339,7 +346,7 @@ func (m *MessageHandler) HandleChatMessage(state *ReceivedMessageState) error {
}
func (m *MessageHandler) HandleRequestAddressForTransaction(messageState *ReceivedMessageState, command protobuf.RequestAddressForTransaction) error {
err := ValidateReceivedRequestAddressForTransaction(&command)
err := ValidateReceivedRequestAddressForTransaction(&command, messageState.CurrentMessageState.WhisperTimestamp)
if err != nil {
return err
}
@ -363,7 +370,7 @@ func (m *MessageHandler) HandleRequestAddressForTransaction(messageState *Receiv
}
func (m *MessageHandler) HandleRequestTransaction(messageState *ReceivedMessageState, command protobuf.RequestTransaction) error {
err := ValidateReceivedRequestTransaction(&command)
err := ValidateReceivedRequestTransaction(&command, messageState.CurrentMessageState.WhisperTimestamp)
if err != nil {
return err
}
@ -388,7 +395,7 @@ func (m *MessageHandler) HandleRequestTransaction(messageState *ReceivedMessageS
}
func (m *MessageHandler) HandleAcceptRequestAddressForTransaction(messageState *ReceivedMessageState, command protobuf.AcceptRequestAddressForTransaction) error {
err := ValidateReceivedAcceptRequestAddressForTransaction(&command)
err := ValidateReceivedAcceptRequestAddressForTransaction(&command, messageState.CurrentMessageState.WhisperTimestamp)
if err != nil {
return err
}
@ -437,7 +444,7 @@ func (m *MessageHandler) HandleAcceptRequestAddressForTransaction(messageState *
}
func (m *MessageHandler) HandleSendTransaction(messageState *ReceivedMessageState, command protobuf.SendTransaction) error {
err := ValidateReceivedSendTransaction(&command)
err := ValidateReceivedSendTransaction(&command, messageState.CurrentMessageState.WhisperTimestamp)
if err != nil {
return err
}
@ -457,7 +464,7 @@ func (m *MessageHandler) HandleSendTransaction(messageState *ReceivedMessageStat
}
func (m *MessageHandler) HandleDeclineRequestAddressForTransaction(messageState *ReceivedMessageState, command protobuf.DeclineRequestAddressForTransaction) error {
err := ValidateReceivedDeclineRequestAddressForTransaction(&command)
err := ValidateReceivedDeclineRequestAddressForTransaction(&command, messageState.CurrentMessageState.WhisperTimestamp)
if err != nil {
return err
}
@ -497,7 +504,7 @@ func (m *MessageHandler) HandleDeclineRequestAddressForTransaction(messageState
}
func (m *MessageHandler) HandleDeclineRequestTransaction(messageState *ReceivedMessageState, command protobuf.DeclineRequestTransaction) error {
err := ValidateReceivedDeclineRequestTransaction(&command)
err := ValidateReceivedDeclineRequestTransaction(&command, messageState.CurrentMessageState.WhisperTimestamp)
if err != nil {
return err
}
@ -536,7 +543,7 @@ func (m *MessageHandler) HandleDeclineRequestTransaction(messageState *ReceivedM
return m.handleCommandMessage(messageState, oldMessage)
}
func (m *MessageHandler) matchMessage(message *Message, chats map[string]*Chat) (*Chat, error) {
func (m *MessageHandler) matchMessage(message *Message, chats map[string]*Chat, timesource ClockValueTimesource) (*Chat, error) {
if message.SigPubKey == nil {
m.logger.Error("public key can't be empty")
return nil, errors.New("received a message with empty public key")
@ -571,7 +578,7 @@ func (m *MessageHandler) matchMessage(message *Message, chats map[string]*Chat)
return nil, errors.Wrap(err, "failed to decode pubkey")
}
newChat := CreateOneToOneChat(chatID[:8], pubKey)
newChat := CreateOneToOneChat(chatID[:8], pubKey, timesource)
chat = &newChat
}
return chat, nil
@ -582,7 +589,7 @@ func (m *MessageHandler) matchMessage(message *Message, chats map[string]*Chat)
chat := chats[chatID]
if chat == nil {
// TODO: this should be a three-word name used in the mobile client
newChat := CreateOneToOneChat(chatID[:8], message.SigPubKey)
newChat := CreateOneToOneChat(chatID[:8], message.SigPubKey, timesource)
chat = &newChat
}
return chat, nil

View File

@ -6,13 +6,41 @@ import (
"strings"
"github.com/status-im/status-go/protocol/protobuf"
"github.com/status-im/status-go/protocol/v1"
)
func ValidateReceivedPairInstallation(message *protobuf.PairInstallation) error {
if message.Clock == 0 {
// maxWhisperDrift is how many milliseconds we allow the clock value to differ
// from whisperTimestamp
const maxWhisperFutureDriftMs uint64 = 120000
func validateClockValue(clock uint64, whisperTimestamp uint64) error {
if clock == 0 {
return errors.New("clock can't be 0")
}
if clock > whisperTimestamp && clock-whisperTimestamp > maxWhisperFutureDriftMs {
return errors.New("clock value too high")
}
return nil
}
func ValidateMembershipUpdateMessage(message *protocol.MembershipUpdateMessage, timeNowMs uint64) error {
for _, e := range message.Events {
if err := validateClockValue(e.ClockValue, timeNowMs); err != nil {
return err
}
}
return nil
}
func ValidateReceivedPairInstallation(message *protobuf.PairInstallation, whisperTimestamp uint64) error {
if err := validateClockValue(message.Clock, whisperTimestamp); err != nil {
return err
}
if len(strings.TrimSpace(message.Name)) == 0 {
return errors.New("name can't be empty")
}
@ -28,9 +56,9 @@ func ValidateReceivedPairInstallation(message *protobuf.PairInstallation) error
return nil
}
func ValidateReceivedSendTransaction(message *protobuf.SendTransaction) error {
if message.Clock == 0 {
return errors.New("clock can't be 0")
func ValidateReceivedSendTransaction(message *protobuf.SendTransaction, whisperTimestamp uint64) error {
if err := validateClockValue(message.Clock, whisperTimestamp); err != nil {
return err
}
if len(strings.TrimSpace(message.TransactionHash)) == 0 {
@ -44,9 +72,9 @@ func ValidateReceivedSendTransaction(message *protobuf.SendTransaction) error {
return nil
}
func ValidateReceivedRequestAddressForTransaction(message *protobuf.RequestAddressForTransaction) error {
if message.Clock == 0 {
return errors.New("clock can't be 0")
func ValidateReceivedRequestAddressForTransaction(message *protobuf.RequestAddressForTransaction, whisperTimestamp uint64) error {
if err := validateClockValue(message.Clock, whisperTimestamp); err != nil {
return err
}
if len(strings.TrimSpace(message.Value)) == 0 {
@ -61,9 +89,9 @@ func ValidateReceivedRequestAddressForTransaction(message *protobuf.RequestAddre
return nil
}
func ValidateReceivedRequestTransaction(message *protobuf.RequestTransaction) error {
if message.Clock == 0 {
return errors.New("clock can't be 0")
func ValidateReceivedRequestTransaction(message *protobuf.RequestTransaction, whisperTimestamp uint64) error {
if err := validateClockValue(message.Clock, whisperTimestamp); err != nil {
return err
}
if len(strings.TrimSpace(message.Value)) == 0 {
@ -82,9 +110,9 @@ func ValidateReceivedRequestTransaction(message *protobuf.RequestTransaction) er
return nil
}
func ValidateReceivedAcceptRequestAddressForTransaction(message *protobuf.AcceptRequestAddressForTransaction) error {
if message.Clock == 0 {
return errors.New("clock can't be 0")
func ValidateReceivedAcceptRequestAddressForTransaction(message *protobuf.AcceptRequestAddressForTransaction, whisperTimestamp uint64) error {
if err := validateClockValue(message.Clock, whisperTimestamp); err != nil {
return err
}
if len(message.Id) == 0 {
@ -98,9 +126,9 @@ func ValidateReceivedAcceptRequestAddressForTransaction(message *protobuf.Accept
return nil
}
func ValidateReceivedDeclineRequestAddressForTransaction(message *protobuf.DeclineRequestAddressForTransaction) error {
if message.Clock == 0 {
return errors.New("clock can't be 0")
func ValidateReceivedDeclineRequestAddressForTransaction(message *protobuf.DeclineRequestAddressForTransaction, whisperTimestamp uint64) error {
if err := validateClockValue(message.Clock, whisperTimestamp); err != nil {
return err
}
if len(message.Id) == 0 {
@ -110,9 +138,9 @@ func ValidateReceivedDeclineRequestAddressForTransaction(message *protobuf.Decli
return nil
}
func ValidateReceivedDeclineRequestTransaction(message *protobuf.DeclineRequestTransaction) error {
if message.Clock == 0 {
return errors.New("clock can't be 0")
func ValidateReceivedDeclineRequestTransaction(message *protobuf.DeclineRequestTransaction, whisperTimestamp uint64) error {
if err := validateClockValue(message.Clock, whisperTimestamp); err != nil {
return err
}
if len(message.Id) == 0 {
@ -122,9 +150,9 @@ func ValidateReceivedDeclineRequestTransaction(message *protobuf.DeclineRequestT
return nil
}
func ValidateReceivedChatMessage(message *protobuf.ChatMessage) error {
if message.Clock == 0 {
return errors.New("clock can't be 0")
func ValidateReceivedChatMessage(message *protobuf.ChatMessage, whisperTimestamp uint64) error {
if err := validateClockValue(message.Clock, whisperTimestamp); err != nil {
return err
}
if message.Timestamp == 0 {

View File

@ -283,6 +283,7 @@ func NewMessenger(
// Initialize transport layer.
var transp transport.Transport
if shh, err := node.GetWhisper(nil); err == nil {
transp, err = shhtransp.NewWhisperServiceTransport(
shh,
@ -631,14 +632,14 @@ func (m *Messenger) CreateGroupChatWithMembers(ctx context.Context, name string,
var response MessengerResponse
logger := m.logger.With(zap.String("site", "CreateGroupChatWithMembers"))
logger.Info("Creating group chat", zap.String("name", name), zap.Any("members", members))
chat := createGroupChat()
chat := createGroupChat(m.getTimesource())
group, err := v1protocol.NewGroupWithCreator(name, m.identity)
if err != nil {
return nil, err
}
chat.updateChatFromProtocolGroup(group)
clock, _ := chat.NextClockAndTimestamp()
clock, _ := chat.NextClockAndTimestamp(m.getTimesource())
// Add members
event := v1protocol.NewMembersAddedEvent(members, clock)
event.ChatID = chat.ID
@ -710,7 +711,7 @@ func (m *Messenger) RemoveMemberFromGroupChat(ctx context.Context, chatID string
return nil, err
}
clock, _ := chat.NextClockAndTimestamp()
clock, _ := chat.NextClockAndTimestamp(m.getTimesource())
// Remove member
event := v1protocol.NewMemberRemovedEvent(member, clock)
event.ChatID = chat.ID
@ -767,7 +768,7 @@ func (m *Messenger) AddMembersToGroupChat(ctx context.Context, chatID string, me
return nil, err
}
clock, _ := chat.NextClockAndTimestamp()
clock, _ := chat.NextClockAndTimestamp(m.getTimesource())
// Add members
event := v1protocol.NewMembersAddedEvent(members, clock)
event.ChatID = chat.ID
@ -832,7 +833,7 @@ func (m *Messenger) AddAdminsToGroupChat(ctx context.Context, chatID string, mem
return nil, err
}
clock, _ := chat.NextClockAndTimestamp()
clock, _ := chat.NextClockAndTimestamp(m.getTimesource())
// Add members
event := v1protocol.NewAdminsAddedEvent(members, clock)
event.ChatID = chat.ID
@ -899,7 +900,7 @@ func (m *Messenger) ConfirmJoiningGroup(ctx context.Context, chatID string) (*Me
if err != nil {
return nil, err
}
clock, _ := chat.NextClockAndTimestamp()
clock, _ := chat.NextClockAndTimestamp(m.getTimesource())
event := v1protocol.NewMemberJoinedEvent(
clock,
)
@ -966,7 +967,7 @@ func (m *Messenger) LeaveGroupChat(ctx context.Context, chatID string) (*Messeng
if err != nil {
return nil, err
}
clock, _ := chat.NextClockAndTimestamp()
clock, _ := chat.NextClockAndTimestamp(m.getTimesource())
event := v1protocol.NewMemberRemovedEvent(
contactIDFromPublicKey(&m.identity.PublicKey),
clock,
@ -1146,10 +1147,6 @@ func (m *Messenger) Contacts() []*Contact {
return contacts
}
func timestampInMs() uint64 {
return uint64(time.Now().UnixNano() / int64(time.Millisecond))
}
// ReSendChatMessage pulls a message from the database and sends it again
func (m *Messenger) ReSendChatMessage(ctx context.Context, messageID string) error {
m.mutex.Lock()
@ -1307,7 +1304,7 @@ func (m *Messenger) SendChatMessage(ctx context.Context, message *Message) (*Mes
return nil, errors.New("Chat not found")
}
err := extendMessageFromChat(message, chat, &m.identity.PublicKey)
err := extendMessageFromChat(message, chat, &m.identity.PublicKey, m.getTimesource())
if err != nil {
return nil, err
}
@ -1361,7 +1358,7 @@ func (m *Messenger) SendChatMessage(ctx context.Context, message *Message) (*Mes
return nil, err
}
err = chat.UpdateFromMessage(message)
err = chat.UpdateFromMessage(message, m.getTimesource())
if err != nil {
return nil, err
}
@ -1432,13 +1429,13 @@ func (m *Messenger) sendContactUpdate(ctx context.Context, chatID, ensName, prof
if err != nil {
return nil, err
}
chat = OneToOneFromPublicKey(publicKey)
chat = OneToOneFromPublicKey(publicKey, m.getTimesource())
// We don't want to show the chat to the user
chat.Active = false
}
m.allChats[chat.ID] = chat
clock, _ := chat.NextClockAndTimestamp()
clock, _ := chat.NextClockAndTimestamp(m.getTimesource())
contactUpdate := &protobuf.ContactUpdate{
Clock: clock,
@ -1525,13 +1522,13 @@ func (m *Messenger) SendPairInstallation(ctx context.Context) (*MessengerRespons
chat, ok := m.allChats[chatID]
if !ok {
chat = OneToOneFromPublicKey(&m.identity.PublicKey)
chat = OneToOneFromPublicKey(&m.identity.PublicKey, m.getTimesource())
// We don't want to show the chat to the user
chat.Active = false
}
m.allChats[chat.ID] = chat
clock, _ := chat.NextClockAndTimestamp()
clock, _ := chat.NextClockAndTimestamp(m.getTimesource())
pairMessage := &protobuf.PairInstallation{
Clock: clock,
@ -1573,13 +1570,13 @@ func (m *Messenger) syncPublicChat(ctx context.Context, publicChat *Chat) error
chat, ok := m.allChats[chatID]
if !ok {
chat = OneToOneFromPublicKey(&m.identity.PublicKey)
chat = OneToOneFromPublicKey(&m.identity.PublicKey, m.getTimesource())
// We don't want to show the chat to the user
chat.Active = false
}
m.allChats[chat.ID] = chat
clock, _ := chat.NextClockAndTimestamp()
clock, _ := chat.NextClockAndTimestamp(m.getTimesource())
syncMessage := &protobuf.SyncInstallationPublicChat{
Clock: clock,
@ -1614,13 +1611,13 @@ func (m *Messenger) syncContact(ctx context.Context, contact *Contact) error {
chat, ok := m.allChats[chatID]
if !ok {
chat = OneToOneFromPublicKey(&m.identity.PublicKey)
chat = OneToOneFromPublicKey(&m.identity.PublicKey, m.getTimesource())
// We don't want to show the chat to the user
chat.Active = false
}
m.allChats[chat.ID] = chat
clock, _ := chat.NextClockAndTimestamp()
clock, _ := chat.NextClockAndTimestamp(m.getTimesource())
syncMessage := &protobuf.SyncInstallationContact{
Clock: clock,
@ -1705,6 +1702,8 @@ type ReceivedMessageState struct {
ExistingMessagesMap map[string]bool
// Response to the client
Response *MessengerResponse
// Timesource is a timesource for clock values/timestamps
Timesource ClockValueTimesource
}
func (m *Messenger) handleRetrievedMessages(chatWithMessages map[transport.Filter][]*types.Message) (*MessengerResponse, error) {
@ -1719,6 +1718,7 @@ func (m *Messenger) handleRetrievedMessages(chatWithMessages map[transport.Filte
ModifiedInstallations: m.modifiedInstallations,
ExistingMessagesMap: make(map[string]bool),
Response: &MessengerResponse{},
Timesource: m.getTimesource(),
}
logger := m.logger.With(zap.String("site", "RetrieveAll"))
@ -2111,7 +2111,7 @@ func (m *Messenger) RequestTransaction(ctx context.Context, chatID, value, contr
}
message := &Message{}
err := extendMessageFromChat(message, chat, &m.identity.PublicKey)
err := extendMessageFromChat(message, chat, &m.identity.PublicKey, m.transport)
if err != nil {
return nil, err
}
@ -2157,7 +2157,7 @@ func (m *Messenger) RequestTransaction(ctx context.Context, chatID, value, contr
return nil, err
}
err = chat.UpdateFromMessage(message)
err = chat.UpdateFromMessage(message, m.transport)
if err != nil {
return nil, err
}
@ -2188,7 +2188,7 @@ func (m *Messenger) RequestAddressForTransaction(ctx context.Context, chatID, fr
}
message := &Message{}
err := extendMessageFromChat(message, chat, &m.identity.PublicKey)
err := extendMessageFromChat(message, chat, &m.identity.PublicKey, m.transport)
if err != nil {
return nil, err
}
@ -2233,7 +2233,7 @@ func (m *Messenger) RequestAddressForTransaction(ctx context.Context, chatID, fr
return nil, err
}
err = chat.UpdateFromMessage(message)
err = chat.UpdateFromMessage(message, m.transport)
if err != nil {
return nil, err
}
@ -2274,7 +2274,7 @@ func (m *Messenger) AcceptRequestAddressForTransaction(ctx context.Context, mess
return nil, errors.New("Need to be a one-to-one chat")
}
clock, timestamp := chat.NextClockAndTimestamp()
clock, timestamp := chat.NextClockAndTimestamp(m.transport)
message.Clock = clock
message.WhisperTimestamp = timestamp
message.Timestamp = timestamp
@ -2328,7 +2328,7 @@ func (m *Messenger) AcceptRequestAddressForTransaction(ctx context.Context, mess
return nil, err
}
err = chat.UpdateFromMessage(message)
err = chat.UpdateFromMessage(message, m.transport)
if err != nil {
return nil, err
}
@ -2369,7 +2369,7 @@ func (m *Messenger) DeclineRequestTransaction(ctx context.Context, messageID str
return nil, errors.New("Need to be a one-to-one chat")
}
clock, timestamp := chat.NextClockAndTimestamp()
clock, timestamp := chat.NextClockAndTimestamp(m.transport)
message.Clock = clock
message.WhisperTimestamp = timestamp
message.Timestamp = timestamp
@ -2410,7 +2410,7 @@ func (m *Messenger) DeclineRequestTransaction(ctx context.Context, messageID str
return nil, err
}
err = chat.UpdateFromMessage(message)
err = chat.UpdateFromMessage(message, m.transport)
if err != nil {
return nil, err
}
@ -2451,7 +2451,7 @@ func (m *Messenger) DeclineRequestAddressForTransaction(ctx context.Context, mes
return nil, errors.New("Need to be a one-to-one chat")
}
clock, timestamp := chat.NextClockAndTimestamp()
clock, timestamp := chat.NextClockAndTimestamp(m.transport)
message.Clock = clock
message.WhisperTimestamp = timestamp
message.Timestamp = timestamp
@ -2492,7 +2492,7 @@ func (m *Messenger) DeclineRequestAddressForTransaction(ctx context.Context, mes
return nil, err
}
err = chat.UpdateFromMessage(message)
err = chat.UpdateFromMessage(message, m.transport)
if err != nil {
return nil, err
}
@ -2533,7 +2533,7 @@ func (m *Messenger) AcceptRequestTransaction(ctx context.Context, transactionHas
return nil, errors.New("Need to be a one-to-one chat")
}
clock, timestamp := chat.NextClockAndTimestamp()
clock, timestamp := chat.NextClockAndTimestamp(m.transport)
message.Clock = clock
message.WhisperTimestamp = timestamp
message.Timestamp = timestamp
@ -2591,7 +2591,7 @@ func (m *Messenger) AcceptRequestTransaction(ctx context.Context, transactionHas
return nil, err
}
err = chat.UpdateFromMessage(message)
err = chat.UpdateFromMessage(message, m.transport)
if err != nil {
return nil, err
}
@ -2622,7 +2622,7 @@ func (m *Messenger) SendTransaction(ctx context.Context, chatID, value, contract
}
message := &Message{}
err := extendMessageFromChat(message, chat, &m.identity.PublicKey)
err := extendMessageFromChat(message, chat, &m.identity.PublicKey, m.transport)
if err != nil {
return nil, err
}
@ -2631,7 +2631,7 @@ func (m *Messenger) SendTransaction(ctx context.Context, chatID, value, contract
message.ContentType = protobuf.ChatMessage_TRANSACTION_COMMAND
message.LocalChatID = chatID
clock, timestamp := chat.NextClockAndTimestamp()
clock, timestamp := chat.NextClockAndTimestamp(m.transport)
message.Clock = clock
message.WhisperTimestamp = timestamp
message.Timestamp = timestamp
@ -2672,7 +2672,7 @@ func (m *Messenger) SendTransaction(ctx context.Context, chatID, value, contract
return nil, err
}
err = chat.UpdateFromMessage(message)
err = chat.UpdateFromMessage(message, m.transport)
if err != nil {
return nil, err
}
@ -2716,13 +2716,13 @@ func (m *Messenger) ValidateTransactions(ctx context.Context, addresses []types.
chatID := contactIDFromPublicKey(validationResult.Transaction.From)
chat, ok := m.allChats[chatID]
if !ok {
chat = OneToOneFromPublicKey(validationResult.Transaction.From)
chat = OneToOneFromPublicKey(validationResult.Transaction.From, m.transport)
}
if validationResult.Message != nil {
message = validationResult.Message
} else {
message = &Message{}
err := extendMessageFromChat(message, chat, &m.identity.PublicKey)
err := extendMessageFromChat(message, chat, &m.identity.PublicKey, m.transport)
if err != nil {
return nil, err
}
@ -2733,7 +2733,7 @@ func (m *Messenger) ValidateTransactions(ctx context.Context, addresses []types.
message.LocalChatID = chatID
message.OutgoingStatus = ""
clock, timestamp := chat.NextClockAndTimestamp()
clock, timestamp := chat.NextClockAndTimestamp(m.transport)
message.Clock = clock
message.Timestamp = timestamp
message.WhisperTimestamp = timestamp
@ -2757,7 +2757,7 @@ func (m *Messenger) ValidateTransactions(ctx context.Context, addresses []types.
return nil, err
}
err = chat.UpdateFromMessage(message)
err = chat.UpdateFromMessage(message, m.transport)
if err != nil {
return nil, err
}
@ -2795,3 +2795,7 @@ func (m *Messenger) ValidateTransactions(ctx context.Context, addresses []types.
}
return &response, nil
}
func (m *Messenger) getTimesource() ClockValueTimesource {
return m.transport
}

View File

@ -16,6 +16,7 @@ type Transport interface {
LeaveGroup(publicKeys []*ecdsa.PublicKey) error
JoinPublic(chatID string) error
LeavePublic(chatID string) error
GetCurrentTime() uint64
SendPublic(ctx context.Context, newMessage *types.NewMessage, chatName string) ([]byte, error)
SendPrivateWithSharedSecret(ctx context.Context, newMessage *types.NewMessage, publicKey *ecdsa.PublicKey, secret []byte) ([]byte, error)

View File

@ -6,6 +6,7 @@ import (
"crypto/ecdsa"
"database/sql"
"sync"
"time"
"github.com/pkg/errors"
"go.uber.org/zap"
@ -360,6 +361,11 @@ func (a *WakuServiceTransport) Track(identifiers [][]byte, hash []byte, newMessa
}
}
// GetCurrentTime returns the current unix timestamp in milliseconds
func (a *WakuServiceTransport) GetCurrentTime() uint64 {
return uint64(a.waku.GetCurrentTime().UnixNano() / int64(time.Millisecond))
}
func (a *WakuServiceTransport) Stop() error {
if a.envelopesMonitor != nil {
a.envelopesMonitor.Stop()

View File

@ -6,6 +6,7 @@ import (
"crypto/ecdsa"
"database/sql"
"sync"
"time"
"github.com/pkg/errors"
"go.uber.org/zap"
@ -360,6 +361,11 @@ func (a *WhisperServiceTransport) Track(identifiers [][]byte, hash []byte, newMe
}
}
// GetCurrentTime returns the current unix timestamp in milliseconds
func (a *WhisperServiceTransport) GetCurrentTime() uint64 {
return uint64(a.shh.GetCurrentTime().UnixNano() / int64(time.Millisecond))
}
func (a *WhisperServiceTransport) Stop() error {
if a.envelopesMonitor != nil {
a.envelopesMonitor.Stop()