diff --git a/VERSION b/VERSION index e5d9eb181..0c1df6ae2 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -0.39.6 +0.39.7 diff --git a/eth-node/go.mod b/eth-node/go.mod index 6531f17c1..770aa0f4f 100644 --- a/eth-node/go.mod +++ b/eth-node/go.mod @@ -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 diff --git a/eth-node/go.sum b/eth-node/go.sum index 24c52124a..c5823f8b7 100644 --- a/eth-node/go.sum +++ b/eth-node/go.sum @@ -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= diff --git a/protocol/chat.go b/protocol/chat.go index 08988daca..4c2c687a8 100644 --- a/protocol/chat.go +++ b/protocol/chat.go @@ -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 { diff --git a/protocol/contact.go b/protocol/contact.go index fdbe8158e..a12bc12c8 100644 --- a/protocol/contact.go +++ b/protocol/contact.go @@ -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, } diff --git a/protocol/message_builder.go b/protocol/message_builder.go index 2c4f48882..da2e11060 100644 --- a/protocol/message_builder.go +++ b/protocol/message_builder.go @@ -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 diff --git a/protocol/message_handler.go b/protocol/message_handler.go index 5e0e28693..7cda081db 100644 --- a/protocol/message_handler.go +++ b/protocol/message_handler.go @@ -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 diff --git a/protocol/message_validator.go b/protocol/message_validator.go index 682cc6047..cd2fe7ee0 100644 --- a/protocol/message_validator.go +++ b/protocol/message_validator.go @@ -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 { diff --git a/protocol/message_validator_test.go b/protocol/message_validator_test.go index e3688ee7e..a0843dafb 100644 --- a/protocol/message_validator_test.go +++ b/protocol/message_validator_test.go @@ -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 { diff --git a/protocol/messenger.go b/protocol/messenger.go index 1a5d5871d..4baec271e 100644 --- a/protocol/messenger.go +++ b/protocol/messenger.go @@ -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 +} diff --git a/protocol/messenger_installations_test.go b/protocol/messenger_installations_test.go index 0a712119e..29e89a381 100644 --- a/protocol/messenger_installations_test.go +++ b/protocol/messenger_installations_test.go @@ -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) diff --git a/protocol/messenger_test.go b/protocol/messenger_test.go index 357605617..72939b6b3 100644 --- a/protocol/messenger_test.go +++ b/protocol/messenger_test.go @@ -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 { diff --git a/protocol/transport/transport.go b/protocol/transport/transport.go index 9ec4c55db..6a75fe546 100644 --- a/protocol/transport/transport.go +++ b/protocol/transport/transport.go @@ -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) diff --git a/protocol/transport/waku/waku_service.go b/protocol/transport/waku/waku_service.go index 57b319382..92adec1af 100644 --- a/protocol/transport/waku/waku_service.go +++ b/protocol/transport/waku/waku_service.go @@ -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() diff --git a/protocol/transport/whisper/whisper_service.go b/protocol/transport/whisper/whisper_service.go index 38bc3a0a2..2c54c367e 100644 --- a/protocol/transport/whisper/whisper_service.go +++ b/protocol/transport/whisper/whisper_service.go @@ -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() diff --git a/vendor/github.com/status-im/status-go/protocol/chat.go b/vendor/github.com/status-im/status-go/protocol/chat.go index 08988daca..4c2c687a8 100644 --- a/vendor/github.com/status-im/status-go/protocol/chat.go +++ b/vendor/github.com/status-im/status-go/protocol/chat.go @@ -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 { diff --git a/vendor/github.com/status-im/status-go/protocol/contact.go b/vendor/github.com/status-im/status-go/protocol/contact.go index fdbe8158e..a12bc12c8 100644 --- a/vendor/github.com/status-im/status-go/protocol/contact.go +++ b/vendor/github.com/status-im/status-go/protocol/contact.go @@ -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, } diff --git a/vendor/github.com/status-im/status-go/protocol/message_builder.go b/vendor/github.com/status-im/status-go/protocol/message_builder.go index 2c4f48882..da2e11060 100644 --- a/vendor/github.com/status-im/status-go/protocol/message_builder.go +++ b/vendor/github.com/status-im/status-go/protocol/message_builder.go @@ -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 diff --git a/vendor/github.com/status-im/status-go/protocol/message_handler.go b/vendor/github.com/status-im/status-go/protocol/message_handler.go index 5e0e28693..7cda081db 100644 --- a/vendor/github.com/status-im/status-go/protocol/message_handler.go +++ b/vendor/github.com/status-im/status-go/protocol/message_handler.go @@ -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 diff --git a/vendor/github.com/status-im/status-go/protocol/message_validator.go b/vendor/github.com/status-im/status-go/protocol/message_validator.go index 682cc6047..cd2fe7ee0 100644 --- a/vendor/github.com/status-im/status-go/protocol/message_validator.go +++ b/vendor/github.com/status-im/status-go/protocol/message_validator.go @@ -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 { diff --git a/vendor/github.com/status-im/status-go/protocol/messenger.go b/vendor/github.com/status-im/status-go/protocol/messenger.go index 1a5d5871d..4baec271e 100644 --- a/vendor/github.com/status-im/status-go/protocol/messenger.go +++ b/vendor/github.com/status-im/status-go/protocol/messenger.go @@ -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 +} diff --git a/vendor/github.com/status-im/status-go/protocol/transport/transport.go b/vendor/github.com/status-im/status-go/protocol/transport/transport.go index 9ec4c55db..6a75fe546 100644 --- a/vendor/github.com/status-im/status-go/protocol/transport/transport.go +++ b/vendor/github.com/status-im/status-go/protocol/transport/transport.go @@ -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) diff --git a/vendor/github.com/status-im/status-go/protocol/transport/waku/waku_service.go b/vendor/github.com/status-im/status-go/protocol/transport/waku/waku_service.go index 57b319382..92adec1af 100644 --- a/vendor/github.com/status-im/status-go/protocol/transport/waku/waku_service.go +++ b/vendor/github.com/status-im/status-go/protocol/transport/waku/waku_service.go @@ -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() diff --git a/vendor/github.com/status-im/status-go/protocol/transport/whisper/whisper_service.go b/vendor/github.com/status-im/status-go/protocol/transport/whisper/whisper_service.go index 38bc3a0a2..2c54c367e 100644 --- a/vendor/github.com/status-im/status-go/protocol/transport/whisper/whisper_service.go +++ b/vendor/github.com/status-im/status-go/protocol/transport/whisper/whisper_service.go @@ -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()