make Messenger.Timesource public (#1837)
This commit is contained in:
parent
e1dee26ba9
commit
d27a507e0d
|
@ -160,6 +160,33 @@ func (c *Chat) updateChatFromProtocolGroup(g *v1protocol.Group) {
|
|||
c.MembershipUpdates = g.Events()
|
||||
}
|
||||
|
||||
// NextClockAndTimestamp returns the next clock value
|
||||
// and the current timestamp
|
||||
func (c *Chat) NextClockAndTimestamp(timesource TimeSource) (uint64, uint64) {
|
||||
clock := c.LastClockValue
|
||||
timestamp := timesource.GetCurrentTime()
|
||||
if clock == 0 || clock < timestamp {
|
||||
clock = timestamp
|
||||
} else {
|
||||
clock = clock + 1
|
||||
}
|
||||
return clock, timestamp
|
||||
}
|
||||
|
||||
func (c *Chat) UpdateFromMessage(message *Message, timesource TimeSource) error {
|
||||
c.Timestamp = int64(timesource.GetCurrentTime())
|
||||
if c.LastClockValue <= message.Clock {
|
||||
jsonMessage, err := json.Marshal(message)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
c.LastClockValue = message.Clock
|
||||
c.LastMessage = jsonMessage
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// ChatMembershipUpdate represent an event on membership of the chat
|
||||
type ChatMembershipUpdate struct {
|
||||
// Unique identifier for the event
|
||||
|
@ -207,14 +234,14 @@ func oneToOneChatID(publicKey *ecdsa.PublicKey) string {
|
|||
return types.EncodeHex(crypto.FromECDSAPub(publicKey))
|
||||
}
|
||||
|
||||
func OneToOneFromPublicKey(pk *ecdsa.PublicKey, timesource ClockValueTimesource) *Chat {
|
||||
func OneToOneFromPublicKey(pk *ecdsa.PublicKey, timesource TimeSource) *Chat {
|
||||
chatID := types.EncodeHex(crypto.FromECDSAPub(pk))
|
||||
newChat := CreateOneToOneChat(chatID[:8], pk, timesource)
|
||||
|
||||
return &newChat
|
||||
}
|
||||
|
||||
func CreateOneToOneChat(name string, publicKey *ecdsa.PublicKey, timesource ClockValueTimesource) Chat {
|
||||
func CreateOneToOneChat(name string, publicKey *ecdsa.PublicKey, timesource TimeSource) Chat {
|
||||
return Chat{
|
||||
ID: oneToOneChatID(publicKey),
|
||||
Name: name,
|
||||
|
@ -224,7 +251,7 @@ func CreateOneToOneChat(name string, publicKey *ecdsa.PublicKey, timesource Cloc
|
|||
}
|
||||
}
|
||||
|
||||
func CreatePublicChat(name string, timesource ClockValueTimesource) Chat {
|
||||
func CreatePublicChat(name string, timesource TimeSource) Chat {
|
||||
return Chat{
|
||||
ID: name,
|
||||
Name: name,
|
||||
|
@ -235,7 +262,7 @@ func CreatePublicChat(name string, timesource ClockValueTimesource) Chat {
|
|||
}
|
||||
}
|
||||
|
||||
func createGroupChat(timesource ClockValueTimesource) Chat {
|
||||
func CreateGroupChat(timesource TimeSource) Chat {
|
||||
return Chat{
|
||||
Active: true,
|
||||
Color: chatColors[rand.Intn(len(chatColors))],
|
||||
|
@ -276,37 +303,6 @@ 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(timesource ClockValueTimesource) (uint64, uint64) {
|
||||
clock := c.LastClockValue
|
||||
timestamp := timesource.GetCurrentTime()
|
||||
if clock == 0 || clock < timestamp {
|
||||
clock = timestamp
|
||||
} else {
|
||||
clock = clock + 1
|
||||
}
|
||||
return clock, timestamp
|
||||
}
|
||||
|
||||
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 {
|
||||
return err
|
||||
}
|
||||
|
||||
c.LastClockValue = message.Clock
|
||||
c.LastMessage = jsonMessage
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func stringSliceContains(slice []string, item string) bool {
|
||||
for _, s := range slice {
|
||||
if s == item {
|
||||
|
|
|
@ -9,7 +9,7 @@ import (
|
|||
"github.com/status-im/status-go/protocol/identity/identicon"
|
||||
)
|
||||
|
||||
func extendMessageFromChat(message *Message, chat *Chat, key *ecdsa.PublicKey, timesource ClockValueTimesource) error {
|
||||
func extendMessageFromChat(message *Message, chat *Chat, key *ecdsa.PublicKey, timesource TimeSource) error {
|
||||
clock, timestamp := chat.NextClockAndTimestamp(timesource)
|
||||
|
||||
message.LocalChatID = chat.ID
|
||||
|
|
|
@ -59,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(messageState.Timesource)
|
||||
newChat := CreateGroupChat(messageState.Timesource)
|
||||
chat = &newChat
|
||||
|
||||
} else {
|
||||
|
@ -550,7 +550,7 @@ func (m *MessageHandler) HandleDeclineRequestTransaction(messageState *ReceivedM
|
|||
return m.handleCommandMessage(messageState, oldMessage)
|
||||
}
|
||||
|
||||
func (m *MessageHandler) matchMessage(message *Message, chats map[string]*Chat, timesource ClockValueTimesource) (*Chat, error) {
|
||||
func (m *MessageHandler) matchMessage(message *Message, chats map[string]*Chat, timesource TimeSource) (*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")
|
||||
|
|
|
@ -126,6 +126,8 @@ type config struct {
|
|||
|
||||
type Option func(*config) error
|
||||
|
||||
// WithSystemMessagesTranslations is required for Group Chats which are currently disabled.
|
||||
// nolint: unused
|
||||
func WithSystemMessagesTranslations(t map[protobuf.MembershipUpdateEvent_EventType]string) Option {
|
||||
return func(c *config) error {
|
||||
c.systemMessagesTranslations = t
|
||||
|
@ -629,7 +631,7 @@ 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(m.getTimesource())
|
||||
chat := CreateGroupChat(m.getTimesource())
|
||||
group, err := v1protocol.NewGroupWithCreator(name, m.identity)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -1699,8 +1701,8 @@ type ReceivedMessageState struct {
|
|||
ExistingMessagesMap map[string]bool
|
||||
// Response to the client
|
||||
Response *MessengerResponse
|
||||
// Timesource is a timesource for clock values/timestamps
|
||||
Timesource ClockValueTimesource
|
||||
// Timesource is a time source for clock values/timestamps.
|
||||
Timesource TimeSource
|
||||
}
|
||||
|
||||
func (m *Messenger) handleRetrievedMessages(chatWithMessages map[transport.Filter][]*types.Message) (*MessengerResponse, error) {
|
||||
|
@ -2806,6 +2808,10 @@ func (m *Messenger) ValidateTransactions(ctx context.Context, addresses []types.
|
|||
return &response, nil
|
||||
}
|
||||
|
||||
func (m *Messenger) getTimesource() ClockValueTimesource {
|
||||
func (m *Messenger) getTimesource() TimeSource {
|
||||
return m.transport
|
||||
}
|
||||
|
||||
func (m *Messenger) Timesource() TimeSource {
|
||||
return m.getTimesource()
|
||||
}
|
||||
|
|
|
@ -0,0 +1,12 @@
|
|||
package protocol
|
||||
|
||||
// TimeSource provides a unified way of getting the current time.
|
||||
// The intention is to always use a synchronized time source
|
||||
// between all components of the protocol.
|
||||
//
|
||||
// This is required by Whisper and Waku protocols
|
||||
// which rely on a fact that all peers
|
||||
// have a synchronized time source.
|
||||
type TimeSource interface {
|
||||
GetCurrentTime() uint64
|
||||
}
|
|
@ -160,6 +160,33 @@ func (c *Chat) updateChatFromProtocolGroup(g *v1protocol.Group) {
|
|||
c.MembershipUpdates = g.Events()
|
||||
}
|
||||
|
||||
// NextClockAndTimestamp returns the next clock value
|
||||
// and the current timestamp
|
||||
func (c *Chat) NextClockAndTimestamp(timesource TimeSource) (uint64, uint64) {
|
||||
clock := c.LastClockValue
|
||||
timestamp := timesource.GetCurrentTime()
|
||||
if clock == 0 || clock < timestamp {
|
||||
clock = timestamp
|
||||
} else {
|
||||
clock = clock + 1
|
||||
}
|
||||
return clock, timestamp
|
||||
}
|
||||
|
||||
func (c *Chat) UpdateFromMessage(message *Message, timesource TimeSource) error {
|
||||
c.Timestamp = int64(timesource.GetCurrentTime())
|
||||
if c.LastClockValue <= message.Clock {
|
||||
jsonMessage, err := json.Marshal(message)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
c.LastClockValue = message.Clock
|
||||
c.LastMessage = jsonMessage
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// ChatMembershipUpdate represent an event on membership of the chat
|
||||
type ChatMembershipUpdate struct {
|
||||
// Unique identifier for the event
|
||||
|
@ -207,14 +234,14 @@ func oneToOneChatID(publicKey *ecdsa.PublicKey) string {
|
|||
return types.EncodeHex(crypto.FromECDSAPub(publicKey))
|
||||
}
|
||||
|
||||
func OneToOneFromPublicKey(pk *ecdsa.PublicKey, timesource ClockValueTimesource) *Chat {
|
||||
func OneToOneFromPublicKey(pk *ecdsa.PublicKey, timesource TimeSource) *Chat {
|
||||
chatID := types.EncodeHex(crypto.FromECDSAPub(pk))
|
||||
newChat := CreateOneToOneChat(chatID[:8], pk, timesource)
|
||||
|
||||
return &newChat
|
||||
}
|
||||
|
||||
func CreateOneToOneChat(name string, publicKey *ecdsa.PublicKey, timesource ClockValueTimesource) Chat {
|
||||
func CreateOneToOneChat(name string, publicKey *ecdsa.PublicKey, timesource TimeSource) Chat {
|
||||
return Chat{
|
||||
ID: oneToOneChatID(publicKey),
|
||||
Name: name,
|
||||
|
@ -224,7 +251,7 @@ func CreateOneToOneChat(name string, publicKey *ecdsa.PublicKey, timesource Cloc
|
|||
}
|
||||
}
|
||||
|
||||
func CreatePublicChat(name string, timesource ClockValueTimesource) Chat {
|
||||
func CreatePublicChat(name string, timesource TimeSource) Chat {
|
||||
return Chat{
|
||||
ID: name,
|
||||
Name: name,
|
||||
|
@ -235,7 +262,7 @@ func CreatePublicChat(name string, timesource ClockValueTimesource) Chat {
|
|||
}
|
||||
}
|
||||
|
||||
func createGroupChat(timesource ClockValueTimesource) Chat {
|
||||
func CreateGroupChat(timesource TimeSource) Chat {
|
||||
return Chat{
|
||||
Active: true,
|
||||
Color: chatColors[rand.Intn(len(chatColors))],
|
||||
|
@ -276,37 +303,6 @@ 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(timesource ClockValueTimesource) (uint64, uint64) {
|
||||
clock := c.LastClockValue
|
||||
timestamp := timesource.GetCurrentTime()
|
||||
if clock == 0 || clock < timestamp {
|
||||
clock = timestamp
|
||||
} else {
|
||||
clock = clock + 1
|
||||
}
|
||||
return clock, timestamp
|
||||
}
|
||||
|
||||
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 {
|
||||
return err
|
||||
}
|
||||
|
||||
c.LastClockValue = message.Clock
|
||||
c.LastMessage = jsonMessage
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func stringSliceContains(slice []string, item string) bool {
|
||||
for _, s := range slice {
|
||||
if s == item {
|
||||
|
|
|
@ -9,7 +9,7 @@ import (
|
|||
"github.com/status-im/status-go/protocol/identity/identicon"
|
||||
)
|
||||
|
||||
func extendMessageFromChat(message *Message, chat *Chat, key *ecdsa.PublicKey, timesource ClockValueTimesource) error {
|
||||
func extendMessageFromChat(message *Message, chat *Chat, key *ecdsa.PublicKey, timesource TimeSource) error {
|
||||
clock, timestamp := chat.NextClockAndTimestamp(timesource)
|
||||
|
||||
message.LocalChatID = chat.ID
|
||||
|
|
|
@ -59,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(messageState.Timesource)
|
||||
newChat := CreateGroupChat(messageState.Timesource)
|
||||
chat = &newChat
|
||||
|
||||
} else {
|
||||
|
@ -550,7 +550,7 @@ func (m *MessageHandler) HandleDeclineRequestTransaction(messageState *ReceivedM
|
|||
return m.handleCommandMessage(messageState, oldMessage)
|
||||
}
|
||||
|
||||
func (m *MessageHandler) matchMessage(message *Message, chats map[string]*Chat, timesource ClockValueTimesource) (*Chat, error) {
|
||||
func (m *MessageHandler) matchMessage(message *Message, chats map[string]*Chat, timesource TimeSource) (*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")
|
||||
|
|
|
@ -126,6 +126,8 @@ type config struct {
|
|||
|
||||
type Option func(*config) error
|
||||
|
||||
// WithSystemMessagesTranslations is required for Group Chats which are currently disabled.
|
||||
// nolint: unused
|
||||
func WithSystemMessagesTranslations(t map[protobuf.MembershipUpdateEvent_EventType]string) Option {
|
||||
return func(c *config) error {
|
||||
c.systemMessagesTranslations = t
|
||||
|
@ -629,7 +631,7 @@ 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(m.getTimesource())
|
||||
chat := CreateGroupChat(m.getTimesource())
|
||||
group, err := v1protocol.NewGroupWithCreator(name, m.identity)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -1699,8 +1701,8 @@ type ReceivedMessageState struct {
|
|||
ExistingMessagesMap map[string]bool
|
||||
// Response to the client
|
||||
Response *MessengerResponse
|
||||
// Timesource is a timesource for clock values/timestamps
|
||||
Timesource ClockValueTimesource
|
||||
// Timesource is a time source for clock values/timestamps.
|
||||
Timesource TimeSource
|
||||
}
|
||||
|
||||
func (m *Messenger) handleRetrievedMessages(chatWithMessages map[transport.Filter][]*types.Message) (*MessengerResponse, error) {
|
||||
|
@ -2806,6 +2808,10 @@ func (m *Messenger) ValidateTransactions(ctx context.Context, addresses []types.
|
|||
return &response, nil
|
||||
}
|
||||
|
||||
func (m *Messenger) getTimesource() ClockValueTimesource {
|
||||
func (m *Messenger) getTimesource() TimeSource {
|
||||
return m.transport
|
||||
}
|
||||
|
||||
func (m *Messenger) Timesource() TimeSource {
|
||||
return m.getTimesource()
|
||||
}
|
||||
|
|
|
@ -0,0 +1,12 @@
|
|||
package protocol
|
||||
|
||||
// TimeSource provides a unified way of getting the current time.
|
||||
// The intention is to always use a synchronized time source
|
||||
// between all components of the protocol.
|
||||
//
|
||||
// This is required by Whisper and Waku protocols
|
||||
// which rely on a fact that all peers
|
||||
// have a synchronized time source.
|
||||
type TimeSource interface {
|
||||
GetCurrentTime() uint64
|
||||
}
|
Loading…
Reference in New Issue