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()
|
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
|
// ChatMembershipUpdate represent an event on membership of the chat
|
||||||
type ChatMembershipUpdate struct {
|
type ChatMembershipUpdate struct {
|
||||||
// Unique identifier for the event
|
// Unique identifier for the event
|
||||||
|
@ -207,14 +234,14 @@ func oneToOneChatID(publicKey *ecdsa.PublicKey) string {
|
||||||
return types.EncodeHex(crypto.FromECDSAPub(publicKey))
|
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))
|
chatID := types.EncodeHex(crypto.FromECDSAPub(pk))
|
||||||
newChat := CreateOneToOneChat(chatID[:8], pk, timesource)
|
newChat := CreateOneToOneChat(chatID[:8], pk, timesource)
|
||||||
|
|
||||||
return &newChat
|
return &newChat
|
||||||
}
|
}
|
||||||
|
|
||||||
func CreateOneToOneChat(name string, publicKey *ecdsa.PublicKey, timesource ClockValueTimesource) Chat {
|
func CreateOneToOneChat(name string, publicKey *ecdsa.PublicKey, timesource TimeSource) Chat {
|
||||||
return Chat{
|
return Chat{
|
||||||
ID: oneToOneChatID(publicKey),
|
ID: oneToOneChatID(publicKey),
|
||||||
Name: name,
|
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{
|
return Chat{
|
||||||
ID: name,
|
ID: name,
|
||||||
Name: 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{
|
return Chat{
|
||||||
Active: true,
|
Active: true,
|
||||||
Color: chatColors[rand.Intn(len(chatColors))],
|
Color: chatColors[rand.Intn(len(chatColors))],
|
||||||
|
@ -276,37 +303,6 @@ func stringSliceToPublicKeys(slice []string, prefixed bool) ([]*ecdsa.PublicKey,
|
||||||
return result, nil
|
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 {
|
func stringSliceContains(slice []string, item string) bool {
|
||||||
for _, s := range slice {
|
for _, s := range slice {
|
||||||
if s == item {
|
if s == item {
|
||||||
|
|
|
@ -9,7 +9,7 @@ import (
|
||||||
"github.com/status-im/status-go/protocol/identity/identicon"
|
"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)
|
clock, timestamp := chat.NextClockAndTimestamp(timesource)
|
||||||
|
|
||||||
message.LocalChatID = chat.ID
|
message.LocalChatID = chat.ID
|
||||||
|
|
|
@ -59,7 +59,7 @@ func (m *MessageHandler) HandleMembershipUpdate(messageState *ReceivedMessageSta
|
||||||
if !group.IsMember(contactIDFromPublicKey(&m.identity.PublicKey)) {
|
if !group.IsMember(contactIDFromPublicKey(&m.identity.PublicKey)) {
|
||||||
return errors.New("can't create a new group chat without us being a member")
|
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
|
chat = &newChat
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
@ -550,7 +550,7 @@ func (m *MessageHandler) HandleDeclineRequestTransaction(messageState *ReceivedM
|
||||||
return m.handleCommandMessage(messageState, oldMessage)
|
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 {
|
if message.SigPubKey == nil {
|
||||||
m.logger.Error("public key can't be empty")
|
m.logger.Error("public key can't be empty")
|
||||||
return nil, errors.New("received a message with empty public key")
|
return nil, errors.New("received a message with empty public key")
|
||||||
|
|
|
@ -126,6 +126,8 @@ type config struct {
|
||||||
|
|
||||||
type Option func(*config) error
|
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 {
|
func WithSystemMessagesTranslations(t map[protobuf.MembershipUpdateEvent_EventType]string) Option {
|
||||||
return func(c *config) error {
|
return func(c *config) error {
|
||||||
c.systemMessagesTranslations = t
|
c.systemMessagesTranslations = t
|
||||||
|
@ -629,7 +631,7 @@ func (m *Messenger) CreateGroupChatWithMembers(ctx context.Context, name string,
|
||||||
var response MessengerResponse
|
var response MessengerResponse
|
||||||
logger := m.logger.With(zap.String("site", "CreateGroupChatWithMembers"))
|
logger := m.logger.With(zap.String("site", "CreateGroupChatWithMembers"))
|
||||||
logger.Info("Creating group chat", zap.String("name", name), zap.Any("members", members))
|
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)
|
group, err := v1protocol.NewGroupWithCreator(name, m.identity)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -1699,8 +1701,8 @@ type ReceivedMessageState struct {
|
||||||
ExistingMessagesMap map[string]bool
|
ExistingMessagesMap map[string]bool
|
||||||
// Response to the client
|
// Response to the client
|
||||||
Response *MessengerResponse
|
Response *MessengerResponse
|
||||||
// Timesource is a timesource for clock values/timestamps
|
// Timesource is a time source for clock values/timestamps.
|
||||||
Timesource ClockValueTimesource
|
Timesource TimeSource
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *Messenger) handleRetrievedMessages(chatWithMessages map[transport.Filter][]*types.Message) (*MessengerResponse, error) {
|
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
|
return &response, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *Messenger) getTimesource() ClockValueTimesource {
|
func (m *Messenger) getTimesource() TimeSource {
|
||||||
return m.transport
|
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()
|
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
|
// ChatMembershipUpdate represent an event on membership of the chat
|
||||||
type ChatMembershipUpdate struct {
|
type ChatMembershipUpdate struct {
|
||||||
// Unique identifier for the event
|
// Unique identifier for the event
|
||||||
|
@ -207,14 +234,14 @@ func oneToOneChatID(publicKey *ecdsa.PublicKey) string {
|
||||||
return types.EncodeHex(crypto.FromECDSAPub(publicKey))
|
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))
|
chatID := types.EncodeHex(crypto.FromECDSAPub(pk))
|
||||||
newChat := CreateOneToOneChat(chatID[:8], pk, timesource)
|
newChat := CreateOneToOneChat(chatID[:8], pk, timesource)
|
||||||
|
|
||||||
return &newChat
|
return &newChat
|
||||||
}
|
}
|
||||||
|
|
||||||
func CreateOneToOneChat(name string, publicKey *ecdsa.PublicKey, timesource ClockValueTimesource) Chat {
|
func CreateOneToOneChat(name string, publicKey *ecdsa.PublicKey, timesource TimeSource) Chat {
|
||||||
return Chat{
|
return Chat{
|
||||||
ID: oneToOneChatID(publicKey),
|
ID: oneToOneChatID(publicKey),
|
||||||
Name: name,
|
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{
|
return Chat{
|
||||||
ID: name,
|
ID: name,
|
||||||
Name: 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{
|
return Chat{
|
||||||
Active: true,
|
Active: true,
|
||||||
Color: chatColors[rand.Intn(len(chatColors))],
|
Color: chatColors[rand.Intn(len(chatColors))],
|
||||||
|
@ -276,37 +303,6 @@ func stringSliceToPublicKeys(slice []string, prefixed bool) ([]*ecdsa.PublicKey,
|
||||||
return result, nil
|
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 {
|
func stringSliceContains(slice []string, item string) bool {
|
||||||
for _, s := range slice {
|
for _, s := range slice {
|
||||||
if s == item {
|
if s == item {
|
||||||
|
|
|
@ -9,7 +9,7 @@ import (
|
||||||
"github.com/status-im/status-go/protocol/identity/identicon"
|
"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)
|
clock, timestamp := chat.NextClockAndTimestamp(timesource)
|
||||||
|
|
||||||
message.LocalChatID = chat.ID
|
message.LocalChatID = chat.ID
|
||||||
|
|
|
@ -59,7 +59,7 @@ func (m *MessageHandler) HandleMembershipUpdate(messageState *ReceivedMessageSta
|
||||||
if !group.IsMember(contactIDFromPublicKey(&m.identity.PublicKey)) {
|
if !group.IsMember(contactIDFromPublicKey(&m.identity.PublicKey)) {
|
||||||
return errors.New("can't create a new group chat without us being a member")
|
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
|
chat = &newChat
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
@ -550,7 +550,7 @@ func (m *MessageHandler) HandleDeclineRequestTransaction(messageState *ReceivedM
|
||||||
return m.handleCommandMessage(messageState, oldMessage)
|
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 {
|
if message.SigPubKey == nil {
|
||||||
m.logger.Error("public key can't be empty")
|
m.logger.Error("public key can't be empty")
|
||||||
return nil, errors.New("received a message with empty public key")
|
return nil, errors.New("received a message with empty public key")
|
||||||
|
|
|
@ -126,6 +126,8 @@ type config struct {
|
||||||
|
|
||||||
type Option func(*config) error
|
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 {
|
func WithSystemMessagesTranslations(t map[protobuf.MembershipUpdateEvent_EventType]string) Option {
|
||||||
return func(c *config) error {
|
return func(c *config) error {
|
||||||
c.systemMessagesTranslations = t
|
c.systemMessagesTranslations = t
|
||||||
|
@ -629,7 +631,7 @@ func (m *Messenger) CreateGroupChatWithMembers(ctx context.Context, name string,
|
||||||
var response MessengerResponse
|
var response MessengerResponse
|
||||||
logger := m.logger.With(zap.String("site", "CreateGroupChatWithMembers"))
|
logger := m.logger.With(zap.String("site", "CreateGroupChatWithMembers"))
|
||||||
logger.Info("Creating group chat", zap.String("name", name), zap.Any("members", members))
|
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)
|
group, err := v1protocol.NewGroupWithCreator(name, m.identity)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -1699,8 +1701,8 @@ type ReceivedMessageState struct {
|
||||||
ExistingMessagesMap map[string]bool
|
ExistingMessagesMap map[string]bool
|
||||||
// Response to the client
|
// Response to the client
|
||||||
Response *MessengerResponse
|
Response *MessengerResponse
|
||||||
// Timesource is a timesource for clock values/timestamps
|
// Timesource is a time source for clock values/timestamps.
|
||||||
Timesource ClockValueTimesource
|
Timesource TimeSource
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *Messenger) handleRetrievedMessages(chatWithMessages map[transport.Filter][]*types.Message) (*MessengerResponse, error) {
|
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
|
return &response, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *Messenger) getTimesource() ClockValueTimesource {
|
func (m *Messenger) getTimesource() TimeSource {
|
||||||
return m.transport
|
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