diff --git a/api/defaults.go b/api/defaults.go index d027fe97d..188e4891e 100644 --- a/api/defaults.go +++ b/api/defaults.go @@ -207,7 +207,7 @@ func buildWalletConfig(request *requests.WalletSecretsConfig) params.WalletConfi return walletConfig } -func defaultNodeConfig(installationID string, request *requests.CreateAccount) (*params.NodeConfig, error) { +func defaultNodeConfig(installationID string, request *requests.CreateAccount, opts ...params.Option) (*params.NodeConfig, error) { // Set mainnet nodeConfig := ¶ms.NodeConfig{} nodeConfig.LogEnabled = request.LogEnabled @@ -335,6 +335,12 @@ func defaultNodeConfig(installationID string, request *requests.CreateAccount) ( nodeConfig.APIModules = request.APIConfig.APIModules } + for _, opt := range opts { + if err := opt(nodeConfig); err != nil { + return nil, err + } + } + return nodeConfig, nil } diff --git a/api/geth_backend.go b/api/geth_backend.go index adef81778..8464992cd 100644 --- a/api/geth_backend.go +++ b/api/geth_backend.go @@ -1302,7 +1302,7 @@ func (b *GethStatusBackend) GetKeyUIDByMnemonic(mnemonic string) (string, error) return info.KeyUID, nil } -func (b *GethStatusBackend) generateOrImportAccount(mnemonic string, customizationColorClock uint64, fetchBackup bool, request *requests.CreateAccount) (*multiaccounts.Account, error) { +func (b *GethStatusBackend) generateOrImportAccount(mnemonic string, customizationColorClock uint64, fetchBackup bool, request *requests.CreateAccount, opts ...params.Option) (*multiaccounts.Account, error) { keystoreDir := keystoreRelativePath b.UpdateRootDataDir(request.BackupDisabledDataDir) @@ -1406,7 +1406,7 @@ func (b *GethStatusBackend) generateOrImportAccount(mnemonic string, customizati //settings.MnemonicWasNotShown = true } - nodeConfig, err := defaultNodeConfig(settings.InstallationID, request) + nodeConfig, err := defaultNodeConfig(settings.InstallationID, request, opts...) if err != nil { return nil, err } @@ -1454,14 +1454,16 @@ func (b *GethStatusBackend) generateOrImportAccount(mnemonic string, customizati return &account, nil } -func (b *GethStatusBackend) CreateAccountAndLogin(request *requests.CreateAccount) (*multiaccounts.Account, error) { +// CreateAccountAndLogin creates a new account and logs in with it. +// NOTE: requests.CreateAccount is used for public, params.Option maybe used for internal usage. +func (b *GethStatusBackend) CreateAccountAndLogin(request *requests.CreateAccount, opts ...params.Option) (*multiaccounts.Account, error) { validation := &requests.CreateAccountValidation{ AllowEmptyDisplayName: false, } if err := request.Validate(validation); err != nil { return nil, err } - return b.generateOrImportAccount("", 1, false, request) + return b.generateOrImportAccount("", 1, false, request, opts...) } func (b *GethStatusBackend) ConvertToRegularAccount(mnemonic string, currPassword string, newPassword string) error { diff --git a/api/messenger_raw_message_resend_test.go b/api/messenger_raw_message_resend_test.go new file mode 100644 index 000000000..73c6dc8fe --- /dev/null +++ b/api/messenger_raw_message_resend_test.go @@ -0,0 +1,389 @@ +package api + +import ( + "context" + "errors" + "path/filepath" + "testing" + "time" + + "go.uber.org/zap" + + "github.com/status-im/status-go/eth-node/types" + m_common "github.com/status-im/status-go/multiaccounts/common" + "github.com/status-im/status-go/params" + "github.com/status-im/status-go/protocol" + "github.com/status-im/status-go/protocol/common" + "github.com/status-im/status-go/protocol/common/shard" + "github.com/status-im/status-go/protocol/communities" + "github.com/status-im/status-go/protocol/protobuf" + "github.com/status-im/status-go/protocol/requests" + "github.com/status-im/status-go/protocol/tt" + "github.com/status-im/status-go/services/utils" + "github.com/status-im/status-go/wakuv2" + + "github.com/stretchr/testify/suite" +) + +type MessengerRawMessageResendTest struct { + suite.Suite + aliceBackend *GethStatusBackend + bobBackend *GethStatusBackend + aliceMessenger *protocol.Messenger + bobMessenger *protocol.Messenger + // add exchangeBootNode to ensure alice and bob can find each other. + // If relying on in the fleet, the test will likely be flaky + exchangeBootNode *wakuv2.Waku +} + +func TestMessengerRawMessageResendTestSuite(t *testing.T) { + suite.Run(t, new(MessengerRawMessageResendTest)) +} + +func (s *MessengerRawMessageResendTest) SetupTest() { + logger, err := zap.NewDevelopment() + s.Require().NoError(err) + + exchangeNodeConfig := &wakuv2.Config{ + Port: 0, + EnableDiscV5: true, + EnablePeerExchangeServer: true, + ClusterID: 16, + UseShardAsDefaultTopic: true, + DefaultShardPubsubTopic: shard.DefaultShardPubsubTopic(), + } + s.exchangeBootNode, err = wakuv2.New("", "", exchangeNodeConfig, logger.Named("pxServerNode"), nil, nil, nil, nil) + s.Require().NoError(err) + s.Require().NoError(s.exchangeBootNode.Start()) + + s.createAliceBobBackendAndLogin() + community := s.createTestCommunity(s.aliceMessenger, protobuf.CommunityPermissions_MANUAL_ACCEPT) + s.addMutualContact() + advertiseCommunityToUserOldWay(&s.Suite, community, s.aliceMessenger, s.bobMessenger) + requestBob := &requests.RequestToJoinCommunity{ + CommunityID: community.ID(), + } + joinOnRequestCommunity(&s.Suite, community, s.aliceMessenger, s.bobMessenger, requestBob) +} + +func (s *MessengerRawMessageResendTest) TearDownTest() { + // Initialize a map to keep track of the operation status. + operationStatus := map[string]bool{ + "Alice Logout": false, + "Bob Logout": false, + "Boot Node Stop": false, + } + + done := make(chan string, 3) // Buffered channel to receive the names of the completed operations + errs := make(chan error, 3) // Channel to receive errs from operations + + // Asynchronously perform operations and report completion or errs. + go func() { + err := s.aliceBackend.Logout() + if err != nil { + errs <- err + } + done <- "Alice Logout" + }() + + go func() { + err := s.bobBackend.Logout() + if err != nil { + errs <- err + } + done <- "Bob Logout" + }() + + go func() { + err := s.exchangeBootNode.Stop() + if err != nil { + errs <- err + } + done <- "Boot Node Stop" + }() + + timeout := time.After(30 * time.Second) + operationsCompleted := 0 + + for operationsCompleted < 3 { + select { + case opName := <-done: + s.T().Logf("%s completed successfully.", opName) + operationStatus[opName] = true + operationsCompleted++ + case err := <-errs: + s.Require().NoError(err) + case <-timeout: + // If a timeout occurs, check which operations have not reported completion. + s.T().Errorf("Timeout occurred, the following operations did not complete in time:") + for opName, completed := range operationStatus { + if !completed { + s.T().Errorf("%s is still pending.", opName) + } + } + s.T().FailNow() + } + } +} + +func (s *MessengerRawMessageResendTest) createAliceBobBackendAndLogin() { + pxServerNodeENR, err := s.exchangeBootNode.GetNodeENRString() + s.Require().NoError(err) + // we don't support multiple logger instances, so just share the log dir + shareLogDir := filepath.Join(s.T().TempDir(), "logs") + s.T().Logf("shareLogDir: %s", shareLogDir) + s.createBackendAndLogin(&s.aliceBackend, &s.aliceMessenger, "alice66", pxServerNodeENR, shareLogDir) + s.createBackendAndLogin(&s.bobBackend, &s.bobMessenger, "bob66", pxServerNodeENR, shareLogDir) +} + +func (s *MessengerRawMessageResendTest) createBackendAndLogin(backend **GethStatusBackend, messenger **protocol.Messenger, displayName, pxServerNodeENR, shareLogDir string) { + *backend = NewGethStatusBackend() + rootDir := filepath.Join(s.T().TempDir()) + s.T().Logf("%s rootDir: %s", displayName, rootDir) + createAccountRequest := s.setCreateAccountRequest(displayName, rootDir, shareLogDir) + _, err := (*backend).CreateAccountAndLogin(createAccountRequest, + params.WithDiscV5BootstrapNodes([]string{pxServerNodeENR}), + // override fleet nodes + params.WithWakuNodes([]string{})) + s.Require().NoError(err) + *messenger = (*backend).Messenger() + s.Require().NotNil(messenger) + _, err = (*messenger).Start() + s.Require().NoError(err) +} + +func (s *MessengerRawMessageResendTest) setCreateAccountRequest(displayName, backupDisabledDataDir, logFilePath string) *requests.CreateAccount { + nameServer := "1.1.1.1" + verifyENSContractAddress := "0x00000000000C2E074eC69A0dFb2997BA6C7d2e1e" + verifyTransactionChainID := int64(1) + verifyURL := "https://eth-archival.rpc.grove.city/v1/3ef2018191814b7e1009b8d9" + logLevel := "DEBUG" + networkID := uint64(1) + password := "qwerty" + return &requests.CreateAccount{ + UpstreamConfig: verifyURL, + WakuV2Nameserver: &nameServer, + VerifyENSContractAddress: &verifyENSContractAddress, + BackupDisabledDataDir: backupDisabledDataDir, + Password: password, + DisplayName: displayName, + LogEnabled: true, + VerifyTransactionChainID: &verifyTransactionChainID, + VerifyTransactionURL: &verifyURL, + VerifyENSURL: &verifyURL, + LogLevel: &logLevel, + LogFilePath: logFilePath, + NetworkID: &networkID, + CustomizationColor: string(m_common.CustomizationColorPrimary), + } +} + +// TestMessageSent tests if ApplicationMetadataMessage_COMMUNITY_REQUEST_TO_JOIN is in state `sent` without resending +func (s *MessengerRawMessageResendTest) TestMessageSent() { + ids, err := s.bobMessenger.RawMessagesIDsByType(protobuf.ApplicationMetadataMessage_COMMUNITY_REQUEST_TO_JOIN) + s.Require().NoError(err) + s.Require().Len(ids, 1) + + err = tt.RetryWithBackOff(func() error { + rawMessage, err := s.bobMessenger.RawMessageByID(ids[0]) + s.Require().NoError(err) + s.Require().NotNil(rawMessage) + if rawMessage.Sent { + return nil + } + return errors.New("raw message should be sent finally") + }) + s.Require().NoError(err) +} + +// TestMessageResend tests if ApplicationMetadataMessage_COMMUNITY_REQUEST_TO_JOIN is resent +func (s *MessengerRawMessageResendTest) TestMessageResend() { + ids, err := s.bobMessenger.RawMessagesIDsByType(protobuf.ApplicationMetadataMessage_COMMUNITY_REQUEST_TO_JOIN) + s.Require().NoError(err) + s.Require().Len(ids, 1) + rawMessage, err := s.bobMessenger.RawMessageByID(ids[0]) + s.Require().NoError(err) + s.Require().NotNil(rawMessage) + s.Require().NoError(s.bobMessenger.UpdateRawMessageSent(rawMessage.ID, false, 0)) + err = tt.RetryWithBackOff(func() error { + rawMessage, err := s.bobMessenger.RawMessageByID(ids[0]) + s.Require().NoError(err) + s.Require().NotNil(rawMessage) + if !rawMessage.Sent { + return errors.New("message ApplicationMetadataMessage_COMMUNITY_REQUEST_TO_JOIN was not resent yet") + } + return nil + }) + s.Require().NoError(err) + + waitOnMessengerResponse(&s.Suite, func(r *protocol.MessengerResponse) error { + if len(r.RequestsToJoinCommunity()) > 0 { + return nil + } + return errors.New("community request to join not received") + }, s.aliceMessenger) +} + +// To be removed in https://github.com/status-im/status-go/issues/4437 +func advertiseCommunityToUserOldWay(s *suite.Suite, community *communities.Community, alice *protocol.Messenger, bob *protocol.Messenger) { + chat := protocol.CreateOneToOneChat(bob.IdentityPublicKeyString(), bob.IdentityPublicKey(), bob.GetTransport()) + + inputMessage := common.NewMessage() + inputMessage.ChatId = chat.ID + inputMessage.Text = "some text" + inputMessage.CommunityID = community.IDString() + + err := alice.SaveChat(chat) + s.Require().NoError(err) + _, err = alice.SendChatMessage(context.Background(), inputMessage) + s.Require().NoError(err) + + // Ensure community is received + response, err := protocol.WaitOnMessengerResponse( + bob, + func(r *protocol.MessengerResponse) bool { + return len(r.Communities()) > 0 + }, + "bob did not receive community request to join", + ) + s.Require().NoError(err) + communityInResponse := response.Communities()[0] + s.Require().Equal(community.ID(), communityInResponse.ID()) +} + +func (s *MessengerRawMessageResendTest) addMutualContact() { + bobPubkey := s.bobMessenger.IdentityPublicKeyCompressed() + bobZQ3ID, err := utils.SerializePublicKey(bobPubkey) + s.Require().NoError(err) + mr, err := s.aliceMessenger.AddContact(context.Background(), &requests.AddContact{ + ID: bobZQ3ID, + DisplayName: "bob666", + }) + s.Require().NoError(err) + s.Require().Len(mr.Messages(), 2) + + var contactRequest *common.Message + waitOnMessengerResponse(&s.Suite, func(r *protocol.MessengerResponse) error { + for _, m := range r.Messages() { + if m.GetContentType() == protobuf.ChatMessage_CONTACT_REQUEST { + contactRequest = m + return nil + } + } + return errors.New("contact request not received") + }, s.bobMessenger) + + mr, err = s.bobMessenger.AcceptContactRequest(context.Background(), &requests.AcceptContactRequest{ + ID: types.FromHex(contactRequest.ID), + }) + s.Require().NoError(err) + s.Require().Len(mr.Contacts, 1) + + waitOnMessengerResponse(&s.Suite, func(r *protocol.MessengerResponse) error { + if len(r.Contacts) > 0 { + return nil + } + return errors.New("contact accepted not received") + }, s.aliceMessenger) +} + +type MessageResponseValidator func(*protocol.MessengerResponse) error + +func waitOnMessengerResponse(s *suite.Suite, fnWait MessageResponseValidator, user *protocol.Messenger) { + _, err := protocol.WaitOnMessengerResponse( + user, + func(r *protocol.MessengerResponse) bool { + err := fnWait(r) + if err != nil { + s.T().Logf("response error: %s", err.Error()) + } + return err == nil + }, + "MessengerResponse data not received", + ) + s.Require().NoError(err) +} + +func requestToJoinCommunity(s *suite.Suite, controlNode *protocol.Messenger, user *protocol.Messenger, request *requests.RequestToJoinCommunity) types.HexBytes { + response, err := user.RequestToJoinCommunity(request) + s.Require().NoError(err) + s.Require().NotNil(response) + s.Require().Len(response.RequestsToJoinCommunity(), 1) + + requestToJoin := response.RequestsToJoinCommunity()[0] + s.Require().Equal(requestToJoin.PublicKey, user.IdentityPublicKeyString()) + + _, err = protocol.WaitOnMessengerResponse( + controlNode, + func(r *protocol.MessengerResponse) bool { + if len(r.RequestsToJoinCommunity()) == 0 { + return false + } + + for _, resultRequest := range r.RequestsToJoinCommunity() { + if resultRequest.PublicKey == user.IdentityPublicKeyString() { + return true + } + } + return false + }, + "control node did not receive community request to join", + ) + s.Require().NoError(err) + + return requestToJoin.ID +} + +func joinOnRequestCommunity(s *suite.Suite, community *communities.Community, controlNode *protocol.Messenger, user *protocol.Messenger, request *requests.RequestToJoinCommunity) { + // Request to join the community + requestToJoinID := requestToJoinCommunity(s, controlNode, user, request) + + // accept join request + acceptRequestToJoin := &requests.AcceptRequestToJoinCommunity{ID: requestToJoinID} + response, err := controlNode.AcceptRequestToJoinCommunity(acceptRequestToJoin) + s.Require().NoError(err) + s.Require().NotNil(response) + + updatedCommunity := response.Communities()[0] + s.Require().NotNil(updatedCommunity) + s.Require().True(updatedCommunity.HasMember(user.IdentityPublicKey())) + + // receive request to join response + _, err = protocol.WaitOnMessengerResponse( + user, + func(r *protocol.MessengerResponse) bool { + return len(r.Communities()) > 0 && r.Communities()[0].HasMember(user.IdentityPublicKey()) + }, + "user did not receive request to join response", + ) + s.Require().NoError(err) + + userCommunity, err := user.GetCommunityByID(community.ID()) + s.Require().NoError(err) + s.Require().True(userCommunity.HasMember(user.IdentityPublicKey())) + + _, err = protocol.WaitOnMessengerResponse( + controlNode, + func(r *protocol.MessengerResponse) bool { + return len(r.Communities()) > 0 && r.Communities()[0].HasMember(user.IdentityPublicKey()) + }, + "control node did not receive request to join response", + ) + s.Require().NoError(err) +} + +func (s *MessengerRawMessageResendTest) createTestCommunity(controlNode *protocol.Messenger, membershipType protobuf.CommunityPermissions_Access) *communities.Community { + description := &requests.CreateCommunity{ + Membership: membershipType, + Name: "status", + Color: "#ffffff", + Description: "status community description", + PinMessageAllMembersEnabled: false, + } + response, err := controlNode.CreateCommunity(description, true) + s.Require().NoError(err) + s.Require().NotNil(response) + s.Require().Len(response.Communities(), 1) + s.Require().Len(response.Chats(), 1) + return response.Communities()[0] +} diff --git a/multiaccounts/settings/sync_protobuf_factories.go b/multiaccounts/settings/sync_protobuf_factories.go index e5b361ddb..ffc473a0e 100644 --- a/multiaccounts/settings/sync_protobuf_factories.go +++ b/multiaccounts/settings/sync_protobuf_factories.go @@ -24,10 +24,10 @@ func buildRawSyncSettingMessage(msg *protobuf.SyncSetting, chatID string) (*comm } return &common.RawMessage{ - LocalChatID: chatID, - Payload: encodedMessage, - MessageType: protobuf.ApplicationMetadataMessage_SYNC_SETTING, - ResendAutomatically: true, + LocalChatID: chatID, + Payload: encodedMessage, + MessageType: protobuf.ApplicationMetadataMessage_SYNC_SETTING, + ResendType: common.ResendTypeDataSync, }, nil } diff --git a/params/config.go b/params/config.go index 6e298f438..cb1dbdf13 100644 --- a/params/config.go +++ b/params/config.go @@ -719,6 +719,20 @@ func WithMailserver() Option { } } +func WithDiscV5BootstrapNodes(nodes []string) Option { + return func(c *NodeConfig) error { + c.ClusterConfig.DiscV5BootstrapNodes = nodes + return nil + } +} + +func WithWakuNodes(nodes []string) Option { + return func(c *NodeConfig) error { + c.ClusterConfig.WakuNodes = nodes + return nil + } +} + // NewNodeConfigWithDefaults creates new node configuration object // with some defaults suitable for adhoc use. func NewNodeConfigWithDefaults(dataDir string, networkID uint64, opts ...Option) (*NodeConfig, error) { diff --git a/protocol/common/message_sender.go b/protocol/common/message_sender.go index c5352b1e0..a7d67801b 100644 --- a/protocol/common/message_sender.go +++ b/protocol/common/message_sender.go @@ -166,7 +166,7 @@ func (s *MessageSender) SendPrivate( // Currently we don't support sending through datasync and setting custom waku fields, // as the datasync interface is not rich enough to propagate that information, so we // would have to add some complexity to handle this. - if rawMessage.ResendAutomatically && (rawMessage.Sender != nil || rawMessage.SkipEncryptionLayer || rawMessage.SendOnPersonalTopic) { + if rawMessage.ResendType == ResendTypeDataSync && (rawMessage.Sender != nil || rawMessage.SkipEncryptionLayer || rawMessage.SendOnPersonalTopic) { return nil, errors.New("setting identity, skip-encryption or personal topic and datasync not supported") } @@ -182,7 +182,7 @@ func (s *MessageSender) SendPrivate( // using the community topic and their key func (s *MessageSender) SendCommunityMessage( ctx context.Context, - rawMessage RawMessage, + rawMessage *RawMessage, ) ([]byte, error) { s.logger.Debug( "sending a community message", @@ -191,7 +191,7 @@ func (s *MessageSender) SendCommunityMessage( ) rawMessage.Sender = s.identity - return s.sendCommunity(ctx, &rawMessage) + return s.sendCommunity(ctx, rawMessage) } // SendPubsubTopicKey sends the protected topic key for a community to a list of recipients @@ -421,7 +421,7 @@ func (s *MessageSender) sendPrivate( // earlier than the scheduled s.notifyOnScheduledMessage(recipient, rawMessage) - if s.datasync != nil && s.featureFlags.Datasync && rawMessage.ResendAutomatically { + if s.datasync != nil && s.featureFlags.Datasync && rawMessage.ResendType == ResendTypeDataSync { // No need to call transport tracking. // It is done in a data sync dispatch step. datasyncID, err := s.addToDataSync(recipient, wrappedMessage) diff --git a/protocol/common/raw_message.go b/protocol/common/raw_message.go index 60d82b518..a784e586a 100644 --- a/protocol/common/raw_message.go +++ b/protocol/common/raw_message.go @@ -14,16 +14,49 @@ const ( KeyExMsgRekey CommKeyExMsgType = 2 ) +// ResendType There are distinct mechanisms for retrying send messages: Datasync supports only direct messages (1-to-1 or private group chats) +// because it requires an acknowledgment (ACK). As implemented, sending a message to a community, where hundreds of +// people receive it, would lead all recipients to attempt sending an ACK, resulting in an excessive number of messages. +// Datasync utilizes ACKs, but community messages do not, to avoid this issue. However, we still aim to retry sending +// community messages if they fail to send or if we are offline. +type ResendType uint8 + +const ( + // ResendTypeNone won't resend + ResendTypeNone ResendType = 0 + // ResendTypeDataSync use DataSync which use MVDS as underlying dependency to resend messages. + // Works only when underlying sending method is MessageSender#SendPrivate. Pls see SendPrivate for more details. + // For usage example, you can find usage with this type value in this project. e.g. Messenger#syncContact + ResendTypeDataSync ResendType = 1 + // ResendTypeRawMessage We have a function, watchExpiredMessages, that monitors the 'raw_messages' table + // and will attempts to resend messages if a previous message sending failed. + ResendTypeRawMessage ResendType = 2 +) + +// ResendMethod defines how to resend a raw message +type ResendMethod uint8 + +const ( + // ResendMethodDynamic determined by logic of Messenger#dispatchMessage, mostly based on chat type + ResendMethodDynamic ResendMethod = 0 + // ResendMethodSendPrivate corresponding function MessageSender#SendPrivate + ResendMethodSendPrivate ResendMethod = 1 + // ResendMethodSendCommunityMessage corresponding function MessageSender#SendCommunityMessage + ResendMethodSendCommunityMessage ResendMethod = 2 +) + // RawMessage represent a sent or received message, kept for being able // to re-send/propagate type RawMessage struct { - ID string - LocalChatID string - LastSent uint64 - SendCount int - Sent bool - ResendAutomatically bool - SkipEncryptionLayer bool // don't wrap message into ProtocolMessage + ID string + LocalChatID string + LastSent uint64 + SendCount int + Sent bool + // don't wrap message into ProtocolMessage. + // when this is true, the message will not be resent via ResendTypeDataSync, but it's possible to + // resend it via ResendTypeRawMessage specified in ResendType + SkipEncryptionLayer bool SendPushNotification bool MessageType protobuf.ApplicationMetadataMessage_Type Payload []byte @@ -38,4 +71,6 @@ type RawMessage struct { BeforeDispatch func(*RawMessage) error HashRatchetGroupID []byte PubsubTopic string + ResendType ResendType + ResendMethod ResendMethod } diff --git a/protocol/common/raw_messages_persistence.go b/protocol/common/raw_messages_persistence.go index 099f1f586..97fcc66bf 100644 --- a/protocol/common/raw_messages_persistence.go +++ b/protocol/common/raw_messages_persistence.go @@ -70,7 +70,10 @@ func (db RawMessagesPersistence) SaveRawMessage(message *RawMessage) error { message.Sent = oldMessage.Sent } } - + var sender []byte + if message.Sender != nil { + sender = crypto.FromECDSA(message.Sender) + } _, err = tx.Exec(` INSERT INTO raw_messages @@ -81,28 +84,41 @@ func (db RawMessagesPersistence) SaveRawMessage(message *RawMessage) error { send_count, sent, message_type, - resend_automatically, recipients, skip_encryption, - send_push_notification, + send_push_notification, skip_group_message_wrap, send_on_personal_topic, - payload + payload, + sender, + community_id, + resend_type, + pubsub_topic, + hash_ratchet_group_id, + community_key_ex_msg_type, + resend_method ) - VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`, + VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`, message.ID, message.LocalChatID, message.LastSent, message.SendCount, message.Sent, message.MessageType, - message.ResendAutomatically, encodedRecipients.Bytes(), message.SkipEncryptionLayer, message.SendPushNotification, message.SkipGroupMessageWrap, message.SendOnPersonalTopic, - message.Payload) + message.Payload, + sender, + message.CommunityID, + message.ResendType, + message.PubsubTopic, + message.HashRatchetGroupID, + message.CommunityKeyExMsgType, + message.ResendMethod, + ) return err } @@ -126,8 +142,8 @@ func (db RawMessagesPersistence) RawMessageByID(id string) (*RawMessage, error) func (db RawMessagesPersistence) rawMessageByID(tx *sql.Tx, id string) (*RawMessage, error) { var rawPubKeys [][]byte var encodedRecipients []byte - var skipGroupMessageWrap sql.NullBool - var sendOnPersonalTopic sql.NullBool + var skipGroupMessageWrap, sendOnPersonalTopic sql.NullBool + var sender []byte message := &RawMessage{} err := tx.QueryRow(` @@ -138,13 +154,19 @@ func (db RawMessagesPersistence) rawMessageByID(tx *sql.Tx, id string) (*RawMess send_count, sent, message_type, - resend_automatically, recipients, skip_encryption, - send_push_notification, + send_push_notification, skip_group_message_wrap, send_on_personal_topic, - payload + payload, + sender, + community_id, + resend_type, + pubsub_topic, + hash_ratchet_group_id, + community_key_ex_msg_type, + resend_method FROM raw_messages WHERE @@ -157,19 +179,25 @@ func (db RawMessagesPersistence) rawMessageByID(tx *sql.Tx, id string) (*RawMess &message.SendCount, &message.Sent, &message.MessageType, - &message.ResendAutomatically, &encodedRecipients, &message.SkipEncryptionLayer, &message.SendPushNotification, &skipGroupMessageWrap, &sendOnPersonalTopic, &message.Payload, + &sender, + &message.CommunityID, + &message.ResendType, + &message.PubsubTopic, + &message.HashRatchetGroupID, + &message.CommunityKeyExMsgType, + &message.ResendMethod, ) if err != nil { return nil, err } - if rawPubKeys != nil { + if encodedRecipients != nil { // Restore recipients decoder := gob.NewDecoder(bytes.NewBuffer(encodedRecipients)) err = decoder.Decode(&rawPubKeys) @@ -177,7 +205,7 @@ func (db RawMessagesPersistence) rawMessageByID(tx *sql.Tx, id string) (*RawMess return nil, err } for _, pkBytes := range rawPubKeys { - pubkey, err := crypto.UnmarshalPubkey(pkBytes) + pubkey, err := crypto.DecompressPubkey(pkBytes) if err != nil { return nil, err } @@ -193,6 +221,12 @@ func (db RawMessagesPersistence) rawMessageByID(tx *sql.Tx, id string) (*RawMess message.SendOnPersonalTopic = sendOnPersonalTopic.Bool } + if sender != nil { + message.Sender, err = crypto.ToECDSA(sender) + if err != nil { + return nil, err + } + } return message, nil } @@ -435,3 +469,8 @@ func (db *RawMessagesPersistence) RemoveMessageSegmentsCompletedOlderThan(timest _, err := db.db.Exec("DELETE FROM message_segments_completed WHERE timestamp < ?", timestamp) return err } + +func (db RawMessagesPersistence) UpdateRawMessageSent(id string, sent bool, lastSent uint64) error { + _, err := db.db.Exec("UPDATE raw_messages SET sent = ?, last_sent = ? WHERE id = ?", sent, lastSent, id) + return err +} diff --git a/protocol/common/raw_messages_persistence_test.go b/protocol/common/raw_messages_persistence_test.go new file mode 100644 index 000000000..eb93b54b9 --- /dev/null +++ b/protocol/common/raw_messages_persistence_test.go @@ -0,0 +1,83 @@ +package common + +import ( + "crypto/ecdsa" + "testing" + "time" + + "github.com/stretchr/testify/require" + + "github.com/status-im/status-go/appdatabase" + "github.com/status-im/status-go/eth-node/crypto" + "github.com/status-im/status-go/protocol/sqlite" + "github.com/status-im/status-go/t/helpers" +) + +func TestSaveRawMessage(t *testing.T) { + db, err := helpers.SetupTestMemorySQLDB(appdatabase.DbInitializer{}) + require.NoError(t, err) + require.NoError(t, sqlite.Migrate(db)) + p := NewRawMessagesPersistence(db) + + pk, err := crypto.GenerateKey() + require.NoError(t, err) + + err = p.SaveRawMessage(&RawMessage{ + ID: "1", + ResendType: ResendTypeRawMessage, + LocalChatID: "", + CommunityID: []byte("c1"), + CommunityKeyExMsgType: KeyExMsgRekey, + Sender: pk, + ResendMethod: ResendMethodSendPrivate, + Recipients: []*ecdsa.PublicKey{pk.Public().(*ecdsa.PublicKey)}, + }) + require.NoError(t, err) + m, err := p.RawMessageByID("1") + require.NoError(t, err) + require.Equal(t, "1", m.ID) + require.Equal(t, ResendTypeRawMessage, m.ResendType) + require.Equal(t, KeyExMsgRekey, m.CommunityKeyExMsgType) + require.Equal(t, "c1", string(m.CommunityID)) + require.Equal(t, pk, m.Sender) + require.Equal(t, ResendMethodSendPrivate, m.ResendMethod) + require.Equal(t, 1, len(m.Recipients)) +} + +func TestUpdateRawMessageSent(t *testing.T) { + db, err := helpers.SetupTestMemorySQLDB(appdatabase.DbInitializer{}) + require.NoError(t, err) + require.NoError(t, sqlite.Migrate(db)) + p := NewRawMessagesPersistence(db) + + pk, err := crypto.GenerateKey() + require.NoError(t, err) + + rawMessageID := "1" + err = p.SaveRawMessage(&RawMessage{ + ID: rawMessageID, + ResendType: ResendTypeRawMessage, + LocalChatID: "", + CommunityID: []byte("c1"), + CommunityKeyExMsgType: KeyExMsgRekey, + Sender: pk, + ResendMethod: ResendMethodSendPrivate, + Recipients: []*ecdsa.PublicKey{pk.Public().(*ecdsa.PublicKey)}, + Sent: true, + LastSent: uint64(time.Now().UnixNano() / int64(time.Millisecond)), + }) + require.NoError(t, err) + + rawMessage, err := p.RawMessageByID(rawMessageID) + require.NoError(t, err) + require.True(t, rawMessage.Sent) + require.Greater(t, rawMessage.LastSent, uint64(0)) + + err = p.UpdateRawMessageSent(rawMessageID, false, 0) + require.NoError(t, err) + + m, err := p.RawMessageByID(rawMessageID) + require.NoError(t, err) + require.False(t, m.Sent) + require.Equal(t, m.LastSent, uint64(0)) +} diff --git a/protocol/communities_key_distributor.go b/protocol/communities_key_distributor.go index 55dcbf698..c0c4d125d 100644 --- a/protocol/communities_key_distributor.go +++ b/protocol/communities_key_distributor.go @@ -97,7 +97,7 @@ func (ckd *CommunitiesKeyDistributorImpl) sendKeyExchangeMessage(community *comm HashRatchetGroupID: hashRatchetGroupID, PubsubTopic: community.PubsubTopic(), // TODO: confirm if it should be sent in community pubsub topic } - _, err := ckd.sender.SendCommunityMessage(context.Background(), rawMessage) + _, err := ckd.sender.SendCommunityMessage(context.Background(), &rawMessage) if err != nil { return err diff --git a/protocol/messenger.go b/protocol/messenger.go index d39c8d8d0..9062b8559 100644 --- a/protocol/messenger.go +++ b/protocol/messenger.go @@ -7,7 +7,6 @@ import ( "database/sql" "encoding/json" "fmt" - "math" "math/rand" "os" "strconv" @@ -678,62 +677,6 @@ func (m *Messenger) processSentMessages(ids []string) error { return nil } -func (m *Messenger) shouldResendMessage(message *common.RawMessage, t common.TimeSource) (bool, error) { - if m.featureFlags.ResendRawMessagesDisabled { - return false, nil - } - //exponential backoff depends on how many attempts to send message already made - power := math.Pow(2, float64(message.SendCount-1)) - backoff := uint64(power) * uint64(m.config.messageResendMinDelay.Milliseconds()) - backoffElapsed := t.GetCurrentTime() > (message.LastSent + backoff) - return backoffElapsed, nil -} - -func (m *Messenger) resendExpiredMessages() error { - if m.connectionState.Offline { - return errors.New("offline") - } - - ids, err := m.persistence.ExpiredMessagesIDs(m.config.messageResendMaxCount) - if err != nil { - return errors.Wrapf(err, "Can't get expired reactions from db") - } - - for _, id := range ids { - rawMessage, err := m.persistence.RawMessageByID(id) - if err != nil { - return errors.Wrapf(err, "Can't get raw message with id %v", id) - } - - chat, ok := m.allChats.Load(rawMessage.LocalChatID) - if !ok { - return ErrChatNotFound - } - - if !(chat.Public() || chat.CommunityChat()) { - return errors.New("Only public chats and community chats messages are resent") - } - - ok, err = m.shouldResendMessage(rawMessage, m.getTimesource()) - if err != nil { - return err - } - - if ok { - err = m.persistence.SaveRawMessage(rawMessage) - if err != nil { - return errors.Wrapf(err, "Can't save raw message marked as non-expired") - } - - err = m.reSendRawMessage(context.Background(), rawMessage.ID) - if err != nil { - return errors.Wrapf(err, "Can't resend expired message with id %v", rawMessage.ID) - } - } - } - return nil -} - func (m *Messenger) ToForeground() { if m.httpServer != nil { m.httpServer.ToForeground() @@ -1613,26 +1556,6 @@ func (m *Messenger) watchCommunitiesToUnmute() { }() } -// watchExpiredMessages regularly checks for expired emojis and invoke their resending -func (m *Messenger) watchExpiredMessages() { - m.logger.Debug("watching expired messages") - go func() { - for { - select { - case <-time.After(time.Second): - if m.Online() { - err := m.resendExpiredMessages() - if err != nil { - m.logger.Debug("failed to resend expired message", zap.Error(err)) - } - } - case <-m.quit: - return - } - } - }() -} - // watchIdentityImageChanges checks for identity images changes and publishes to the contact code when it happens func (m *Messenger) watchIdentityImageChanges() { m.logger.Debug("watching identity image changes") @@ -2112,30 +2035,6 @@ func (m *Messenger) reregisterForPushNotifications() error { return m.pushNotificationClient.Reregister(m.pushNotificationOptions()) } -// pull a message from the database and send it again -func (m *Messenger) reSendRawMessage(ctx context.Context, messageID string) error { - message, err := m.persistence.RawMessageByID(messageID) - if err != nil { - return err - } - - chat, ok := m.allChats.Load(message.LocalChatID) - if !ok { - return errors.New("chat not found") - } - - _, err = m.dispatchMessage(ctx, common.RawMessage{ - LocalChatID: chat.ID, - Payload: message.Payload, - PubsubTopic: message.PubsubTopic, - MessageType: message.MessageType, - Recipients: message.Recipients, - ResendAutomatically: message.ResendAutomatically, - SendCount: message.SendCount, - }) - return err -} - // ReSendChatMessage pulls a message from the database and sends it again func (m *Messenger) ReSendChatMessage(ctx context.Context, messageID string) error { return m.reSendRawMessage(ctx, messageID) @@ -2288,7 +2187,7 @@ func (m *Messenger) dispatchMessage(ctx context.Context, rawMessage common.RawMe rawMessage.HashRatchetGroupID = rawMessage.CommunityID } - id, err = m.sender.SendCommunityMessage(ctx, rawMessage) + id, err = m.sender.SendCommunityMessage(ctx, &rawMessage) if err != nil { return rawMessage, err } @@ -2486,7 +2385,10 @@ func (m *Messenger) sendChatMessage(ctx context.Context, message *common.Message SendPushNotification: m.featureFlags.PushNotifications, Payload: encodedMessage, MessageType: protobuf.ApplicationMetadataMessage_CHAT_MESSAGE, - ResendAutomatically: true, + ResendType: common.ResendTypeRawMessage, + } + if chat.ChatType == ChatTypeOneToOne { + rawMessage.ResendType = common.ResendTypeDataSync } // We want to save the raw message before dispatching it, to avoid race conditions @@ -2699,10 +2601,10 @@ func (m *Messenger) syncProfilePictures(rawMessageHandler RawMessageHandler, ide } rawMessage := common.RawMessage{ - LocalChatID: chat.ID, - Payload: encodedMessage, - MessageType: protobuf.ApplicationMetadataMessage_SYNC_PROFILE_PICTURES, - ResendAutomatically: true, + LocalChatID: chat.ID, + Payload: encodedMessage, + MessageType: protobuf.ApplicationMetadataMessage_SYNC_PROFILE_PICTURES, + ResendType: common.ResendTypeDataSync, } _, err = rawMessageHandler(ctx, rawMessage) @@ -2915,10 +2817,10 @@ func (m *Messenger) syncContactRequestDecision(ctx context.Context, requestID st } rawMessage := common.RawMessage{ - LocalChatID: chat.ID, - Payload: encodedMessage, - MessageType: protobuf.ApplicationMetadataMessage_SYNC_CONTACT_REQUEST_DECISION, - ResendAutomatically: true, + LocalChatID: chat.ID, + Payload: encodedMessage, + MessageType: protobuf.ApplicationMetadataMessage_SYNC_CONTACT_REQUEST_DECISION, + ResendType: common.ResendTypeDataSync, } _, err = rawMessageHandler(ctx, rawMessage) @@ -2976,10 +2878,10 @@ func (m *Messenger) SendPairInstallation(ctx context.Context, rawMessageHandler rawMessageHandler = m.dispatchPairInstallationMessage } _, err = rawMessageHandler(ctx, common.RawMessage{ - LocalChatID: chat.ID, - Payload: encodedMessage, - MessageType: protobuf.ApplicationMetadataMessage_SYNC_PAIR_INSTALLATION, - ResendAutomatically: true, + LocalChatID: chat.ID, + Payload: encodedMessage, + MessageType: protobuf.ApplicationMetadataMessage_SYNC_PAIR_INSTALLATION, + ResendType: common.ResendTypeDataSync, }) if err != nil { return nil, err @@ -3041,10 +2943,10 @@ func (m *Messenger) syncChat(ctx context.Context, chatToSync *Chat, rawMessageHa } rawMessage := common.RawMessage{ - LocalChatID: chat.ID, - Payload: encodedMessage, - MessageType: protobuf.ApplicationMetadataMessage_SYNC_CHAT, - ResendAutomatically: true, + LocalChatID: chat.ID, + Payload: encodedMessage, + MessageType: protobuf.ApplicationMetadataMessage_SYNC_CHAT, + ResendType: common.ResendTypeDataSync, } _, err = rawMessageHandler(ctx, rawMessage) @@ -3074,10 +2976,10 @@ func (m *Messenger) syncClearHistory(ctx context.Context, publicChat *Chat, rawM } rawMessage := common.RawMessage{ - LocalChatID: chat.ID, - Payload: encodedMessage, - MessageType: protobuf.ApplicationMetadataMessage_SYNC_CLEAR_HISTORY, - ResendAutomatically: true, + LocalChatID: chat.ID, + Payload: encodedMessage, + MessageType: protobuf.ApplicationMetadataMessage_SYNC_CLEAR_HISTORY, + ResendType: common.ResendTypeDataSync, } _, err = rawMessageHandler(ctx, rawMessage) @@ -3106,10 +3008,10 @@ func (m *Messenger) syncChatRemoving(ctx context.Context, id string, rawMessageH } rawMessage := common.RawMessage{ - LocalChatID: chat.ID, - Payload: encodedMessage, - MessageType: protobuf.ApplicationMetadataMessage_SYNC_CHAT_REMOVED, - ResendAutomatically: true, + LocalChatID: chat.ID, + Payload: encodedMessage, + MessageType: protobuf.ApplicationMetadataMessage_SYNC_CHAT_REMOVED, + ResendType: common.ResendTypeDataSync, } _, err = rawMessageHandler(ctx, rawMessage) @@ -3140,10 +3042,10 @@ func (m *Messenger) syncContact(ctx context.Context, contact *Contact, rawMessag } rawMessage := common.RawMessage{ - LocalChatID: chat.ID, - Payload: encodedMessage, - MessageType: protobuf.ApplicationMetadataMessage_SYNC_INSTALLATION_CONTACT_V2, - ResendAutomatically: true, + LocalChatID: chat.ID, + Payload: encodedMessage, + MessageType: protobuf.ApplicationMetadataMessage_SYNC_INSTALLATION_CONTACT_V2, + ResendType: common.ResendTypeDataSync, } _, err = rawMessageHandler(ctx, rawMessage) @@ -3221,10 +3123,10 @@ func (m *Messenger) syncCommunity(ctx context.Context, community *communities.Co } rawMessage := common.RawMessage{ - LocalChatID: chat.ID, - Payload: encodedMessage, - MessageType: protobuf.ApplicationMetadataMessage_SYNC_INSTALLATION_COMMUNITY, - ResendAutomatically: true, + LocalChatID: chat.ID, + Payload: encodedMessage, + MessageType: protobuf.ApplicationMetadataMessage_SYNC_INSTALLATION_COMMUNITY, + ResendType: common.ResendTypeDataSync, } _, err = rawMessageHandler(ctx, rawMessage) @@ -3258,10 +3160,10 @@ func (m *Messenger) SyncBookmark(ctx context.Context, bookmark *browsers.Bookmar } rawMessage := common.RawMessage{ - LocalChatID: chat.ID, - Payload: encodedMessage, - MessageType: protobuf.ApplicationMetadataMessage_SYNC_BOOKMARK, - ResendAutomatically: true, + LocalChatID: chat.ID, + Payload: encodedMessage, + MessageType: protobuf.ApplicationMetadataMessage_SYNC_BOOKMARK, + ResendType: common.ResendTypeDataSync, } _, err = rawMessageHandler(ctx, rawMessage) if err != nil { @@ -3331,10 +3233,10 @@ func (m *Messenger) syncEnsUsernameDetail(ctx context.Context, usernameDetail *e _, chat := m.getLastClockWithRelatedChat() rawMessage := common.RawMessage{ - LocalChatID: chat.ID, - Payload: encodedMessage, - MessageType: protobuf.ApplicationMetadataMessage_SYNC_ENS_USERNAME_DETAIL, - ResendAutomatically: true, + LocalChatID: chat.ID, + Payload: encodedMessage, + MessageType: protobuf.ApplicationMetadataMessage_SYNC_ENS_USERNAME_DETAIL, + ResendType: common.ResendTypeDataSync, } _, err = rawMessageHandler(ctx, rawMessage) @@ -3360,10 +3262,10 @@ func (m *Messenger) syncAccountCustomizationColor(ctx context.Context, acc *mult } rawMessage := common.RawMessage{ - LocalChatID: chat.ID, - Payload: encodedMessage, - MessageType: protobuf.ApplicationMetadataMessage_SYNC_ACCOUNT_CUSTOMIZATION_COLOR, - ResendAutomatically: true, + LocalChatID: chat.ID, + Payload: encodedMessage, + MessageType: protobuf.ApplicationMetadataMessage_SYNC_ACCOUNT_CUSTOMIZATION_COLOR, + ResendType: common.ResendTypeDataSync, } _, err = m.dispatchMessage(ctx, rawMessage) @@ -3388,10 +3290,10 @@ func (m *Messenger) SyncTrustedUser(ctx context.Context, publicKey string, ts ve } rawMessage := common.RawMessage{ - LocalChatID: chat.ID, - Payload: encodedMessage, - MessageType: protobuf.ApplicationMetadataMessage_SYNC_TRUSTED_USER, - ResendAutomatically: true, + LocalChatID: chat.ID, + Payload: encodedMessage, + MessageType: protobuf.ApplicationMetadataMessage_SYNC_TRUSTED_USER, + ResendType: common.ResendTypeDataSync, } _, err = rawMessageHandler(ctx, rawMessage) @@ -3427,10 +3329,10 @@ func (m *Messenger) SyncVerificationRequest(ctx context.Context, vr *verificatio } rawMessage := common.RawMessage{ - LocalChatID: chat.ID, - Payload: encodedMessage, - MessageType: protobuf.ApplicationMetadataMessage_SYNC_VERIFICATION_REQUEST, - ResendAutomatically: true, + LocalChatID: chat.ID, + Payload: encodedMessage, + MessageType: protobuf.ApplicationMetadataMessage_SYNC_VERIFICATION_REQUEST, + ResendType: common.ResendTypeDataSync, } _, err = rawMessageHandler(ctx, rawMessage) @@ -4566,10 +4468,10 @@ func (m *Messenger) syncChatMessagesRead(ctx context.Context, chatID string, clo } rawMessage := common.RawMessage{ - LocalChatID: chat.ID, - Payload: encodedMessage, - MessageType: protobuf.ApplicationMetadataMessage_SYNC_CHAT_MESSAGES_READ, - ResendAutomatically: true, + LocalChatID: chat.ID, + Payload: encodedMessage, + MessageType: protobuf.ApplicationMetadataMessage_SYNC_CHAT_MESSAGES_READ, + ResendType: common.ResendTypeDataSync, } _, err = rawMessageHandler(ctx, rawMessage) @@ -4858,11 +4760,15 @@ func (m *Messenger) RequestTransaction(ctx context.Context, chatID, value, contr if err != nil { return nil, err } + resendType := common.ResendTypeRawMessage + if chat.ChatType == ChatTypeOneToOne { + resendType = common.ResendTypeDataSync + } rawMessage, err := m.dispatchMessage(ctx, common.RawMessage{ - LocalChatID: chat.ID, - Payload: encodedMessage, - MessageType: protobuf.ApplicationMetadataMessage_REQUEST_TRANSACTION, - ResendAutomatically: true, + LocalChatID: chat.ID, + Payload: encodedMessage, + MessageType: protobuf.ApplicationMetadataMessage_REQUEST_TRANSACTION, + ResendType: resendType, }) message.CommandParameters = &common.CommandParameters{ @@ -4931,11 +4837,16 @@ func (m *Messenger) RequestAddressForTransaction(ctx context.Context, chatID, fr if err != nil { return nil, err } + + resendType := common.ResendTypeRawMessage + if chat.ChatType == ChatTypeOneToOne { + resendType = common.ResendTypeDataSync + } rawMessage, err := m.dispatchMessage(ctx, common.RawMessage{ - LocalChatID: chat.ID, - Payload: encodedMessage, - MessageType: protobuf.ApplicationMetadataMessage_REQUEST_ADDRESS_FOR_TRANSACTION, - ResendAutomatically: true, + LocalChatID: chat.ID, + Payload: encodedMessage, + MessageType: protobuf.ApplicationMetadataMessage_REQUEST_ADDRESS_FOR_TRANSACTION, + ResendType: resendType, }) message.CommandParameters = &common.CommandParameters{ @@ -5030,11 +4941,15 @@ func (m *Messenger) AcceptRequestAddressForTransaction(ctx context.Context, mess return nil, err } + resendType := common.ResendTypeRawMessage + if chat.ChatType == ChatTypeOneToOne { + resendType = common.ResendTypeDataSync + } rawMessage, err := m.dispatchMessage(ctx, common.RawMessage{ - LocalChatID: chat.ID, - Payload: encodedMessage, - MessageType: protobuf.ApplicationMetadataMessage_ACCEPT_REQUEST_ADDRESS_FOR_TRANSACTION, - ResendAutomatically: true, + LocalChatID: chat.ID, + Payload: encodedMessage, + MessageType: protobuf.ApplicationMetadataMessage_ACCEPT_REQUEST_ADDRESS_FOR_TRANSACTION, + ResendType: resendType, }) if err != nil { @@ -5110,11 +5025,15 @@ func (m *Messenger) DeclineRequestTransaction(ctx context.Context, messageID str return nil, err } + resendType := common.ResendTypeRawMessage + if chat.ChatType == ChatTypeOneToOne { + resendType = common.ResendTypeDataSync + } rawMessage, err := m.dispatchMessage(ctx, common.RawMessage{ - LocalChatID: chat.ID, - Payload: encodedMessage, - MessageType: protobuf.ApplicationMetadataMessage_DECLINE_REQUEST_TRANSACTION, - ResendAutomatically: true, + LocalChatID: chat.ID, + Payload: encodedMessage, + MessageType: protobuf.ApplicationMetadataMessage_DECLINE_REQUEST_TRANSACTION, + ResendType: resendType, }) if err != nil { @@ -5189,11 +5108,15 @@ func (m *Messenger) DeclineRequestAddressForTransaction(ctx context.Context, mes return nil, err } + resendType := common.ResendTypeRawMessage + if chat.ChatType == ChatTypeOneToOne { + resendType = common.ResendTypeDataSync + } rawMessage, err := m.dispatchMessage(ctx, common.RawMessage{ - LocalChatID: chat.ID, - Payload: encodedMessage, - MessageType: protobuf.ApplicationMetadataMessage_DECLINE_REQUEST_ADDRESS_FOR_TRANSACTION, - ResendAutomatically: true, + LocalChatID: chat.ID, + Payload: encodedMessage, + MessageType: protobuf.ApplicationMetadataMessage_DECLINE_REQUEST_ADDRESS_FOR_TRANSACTION, + ResendType: resendType, }) if err != nil { @@ -5283,11 +5206,15 @@ func (m *Messenger) AcceptRequestTransaction(ctx context.Context, transactionHas return nil, err } + resendType := common.ResendTypeRawMessage + if chat.ChatType == ChatTypeOneToOne { + resendType = common.ResendTypeDataSync + } rawMessage, err := m.dispatchMessage(ctx, common.RawMessage{ - LocalChatID: chat.ID, - Payload: encodedMessage, - MessageType: protobuf.ApplicationMetadataMessage_SEND_TRANSACTION, - ResendAutomatically: true, + LocalChatID: chat.ID, + Payload: encodedMessage, + MessageType: protobuf.ApplicationMetadataMessage_SEND_TRANSACTION, + ResendType: resendType, }) if err != nil { @@ -5357,11 +5284,15 @@ func (m *Messenger) SendTransaction(ctx context.Context, chatID, value, contract return nil, err } + resendType := common.ResendTypeRawMessage + if chat.ChatType == ChatTypeOneToOne { + resendType = common.ResendTypeDataSync + } rawMessage, err := m.dispatchMessage(ctx, common.RawMessage{ - LocalChatID: chat.ID, - Payload: encodedMessage, - MessageType: protobuf.ApplicationMetadataMessage_SEND_TRANSACTION, - ResendAutomatically: true, + LocalChatID: chat.ID, + Payload: encodedMessage, + MessageType: protobuf.ApplicationMetadataMessage_SEND_TRANSACTION, + ResendType: resendType, }) if err != nil { @@ -5942,10 +5873,10 @@ func (m *Messenger) syncDeleteForMeMessage(ctx context.Context, rawMessageDispat return err2 } rawMessage := common.RawMessage{ - LocalChatID: chatID, - Payload: encodedMessage, - MessageType: protobuf.ApplicationMetadataMessage_SYNC_DELETE_FOR_ME_MESSAGE, - ResendAutomatically: true, + LocalChatID: chatID, + Payload: encodedMessage, + MessageType: protobuf.ApplicationMetadataMessage_SYNC_DELETE_FOR_ME_MESSAGE, + ResendType: common.ResendTypeDataSync, } _, err2 = rawMessageDispatcher(ctx, rawMessage) if err2 != nil { @@ -5978,10 +5909,10 @@ func (m *Messenger) syncSocialLinks(ctx context.Context, rawMessageDispatcher Ra } rawMessage := common.RawMessage{ - LocalChatID: chat.ID, - Payload: encodedMessage, - MessageType: protobuf.ApplicationMetadataMessage_SYNC_SOCIAL_LINKS, - ResendAutomatically: true, + LocalChatID: chat.ID, + Payload: encodedMessage, + MessageType: protobuf.ApplicationMetadataMessage_SYNC_SOCIAL_LINKS, + ResendType: common.ResendTypeDataSync, } _, err = rawMessageDispatcher(ctx, rawMessage) diff --git a/protocol/messenger_activity_center.go b/protocol/messenger_activity_center.go index 616e6248d..987256054 100644 --- a/protocol/messenger_activity_center.go +++ b/protocol/messenger_activity_center.go @@ -287,9 +287,9 @@ func (m *Messenger) syncActivityCenterReadByIDs(ctx context.Context, ids []types } return m.sendToPairedDevices(ctx, common.RawMessage{ - Payload: encodedMessage, - MessageType: protobuf.ApplicationMetadataMessage_SYNC_ACTIVITY_CENTER_READ, - ResendAutomatically: true, + Payload: encodedMessage, + MessageType: protobuf.ApplicationMetadataMessage_SYNC_ACTIVITY_CENTER_READ, + ResendType: common.ResendTypeDataSync, }) } @@ -305,9 +305,9 @@ func (m *Messenger) syncActivityCenterUnreadByIDs(ctx context.Context, ids []typ } return m.sendToPairedDevices(ctx, common.RawMessage{ - Payload: encodedMessage, - MessageType: protobuf.ApplicationMetadataMessage_SYNC_ACTIVITY_CENTER_UNREAD, - ResendAutomatically: true, + Payload: encodedMessage, + MessageType: protobuf.ApplicationMetadataMessage_SYNC_ACTIVITY_CENTER_UNREAD, + ResendType: common.ResendTypeDataSync, }) } @@ -408,9 +408,9 @@ func (m *Messenger) syncActivityCenterAcceptedByIDs(ctx context.Context, ids []t } return m.sendToPairedDevices(ctx, common.RawMessage{ - Payload: encodedMessage, - MessageType: protobuf.ApplicationMetadataMessage_SYNC_ACTIVITY_CENTER_ACCEPTED, - ResendAutomatically: true, + Payload: encodedMessage, + MessageType: protobuf.ApplicationMetadataMessage_SYNC_ACTIVITY_CENTER_ACCEPTED, + ResendType: common.ResendTypeDataSync, }) } @@ -450,9 +450,9 @@ func (m *Messenger) syncActivityCenterCommunityRequestDecision(ctx context.Conte } return m.sendToPairedDevices(ctx, common.RawMessage{ - Payload: encodedMessage, - MessageType: protobuf.ApplicationMetadataMessage_SYNC_ACTIVITY_CENTER_COMMUNITY_REQUEST_DECISION, - ResendAutomatically: true, + Payload: encodedMessage, + MessageType: protobuf.ApplicationMetadataMessage_SYNC_ACTIVITY_CENTER_COMMUNITY_REQUEST_DECISION, + ResendType: common.ResendTypeDataSync, }) } @@ -530,9 +530,9 @@ func (m *Messenger) syncActivityCenterDeletedByIDs(ctx context.Context, ids []ty } return m.sendToPairedDevices(ctx, common.RawMessage{ - Payload: encodedMessage, - MessageType: protobuf.ApplicationMetadataMessage_SYNC_ACTIVITY_CENTER_DELETED, - ResendAutomatically: true, + Payload: encodedMessage, + MessageType: protobuf.ApplicationMetadataMessage_SYNC_ACTIVITY_CENTER_DELETED, + ResendType: common.ResendTypeDataSync, }) } @@ -556,9 +556,9 @@ func (m *Messenger) syncActivityCenterDismissedByIDs(ctx context.Context, ids [] } return m.sendToPairedDevices(ctx, common.RawMessage{ - Payload: encodedMessage, - MessageType: protobuf.ApplicationMetadataMessage_SYNC_ACTIVITY_CENTER_DISMISSED, - ResendAutomatically: true, + Payload: encodedMessage, + MessageType: protobuf.ApplicationMetadataMessage_SYNC_ACTIVITY_CENTER_DISMISSED, + ResendType: common.ResendTypeDataSync, }) } diff --git a/protocol/messenger_communities.go b/protocol/messenger_communities.go index 1cf226d1c..68d5fa5af 100644 --- a/protocol/messenger_communities.go +++ b/protocol/messenger_communities.go @@ -1300,12 +1300,13 @@ func (m *Messenger) RequestToJoinCommunity(request *requests.RequestToJoinCommun rawMessage := common.RawMessage{ Payload: payload, CommunityID: community.ID(), + ResendType: common.ResendTypeRawMessage, SkipEncryptionLayer: true, MessageType: protobuf.ApplicationMetadataMessage_COMMUNITY_REQUEST_TO_JOIN, PubsubTopic: shard.DefaultNonProtectedPubsubTopic(), } - _, err = m.SendMessageToControlNode(community, rawMessage) + _, err = m.SendMessageToControlNode(community, &rawMessage) if err != nil { return nil, err } @@ -1314,12 +1315,14 @@ func (m *Messenger) RequestToJoinCommunity(request *requests.RequestToJoinCommun privilegedMembers := community.GetFilteredPrivilegedMembers(map[string]struct{}{}) for _, member := range privilegedMembers[protobuf.CommunityMember_ROLE_OWNER] { + rawMessage.Recipients = append(rawMessage.Recipients, member) _, err := m.sender.SendPrivate(context.Background(), member, &rawMessage) if err != nil { return nil, err } } for _, member := range privilegedMembers[protobuf.CommunityMember_ROLE_TOKEN_MASTER] { + rawMessage.Recipients = append(rawMessage.Recipients, member) _, err := m.sender.SendPrivate(context.Background(), member, &rawMessage) if err != nil { return nil, err @@ -1335,6 +1338,7 @@ func (m *Messenger) RequestToJoinCommunity(request *requests.RequestToJoinCommun rawMessage.Payload = payload for _, member := range privilegedMembers[protobuf.CommunityMember_ROLE_ADMIN] { + rawMessage.Recipients = append(rawMessage.Recipients, member) _, err := m.sender.SendPrivate(context.Background(), member, &rawMessage) if err != nil { return nil, err @@ -1342,6 +1346,10 @@ func (m *Messenger) RequestToJoinCommunity(request *requests.RequestToJoinCommun } } + if _, err = m.UpsertRawMessageToWatch(&rawMessage); err != nil { + return nil, err + } + response := &MessengerResponse{} response.AddRequestToJoinCommunity(requestToJoin) response.AddCommunity(community) @@ -1465,9 +1473,10 @@ func (m *Messenger) EditSharedAddressesForCommunity(request *requests.EditShared SkipEncryptionLayer: true, MessageType: protobuf.ApplicationMetadataMessage_COMMUNITY_EDIT_SHARED_ADDRESSES, PubsubTopic: community.PubsubTopic(), // TODO: confirm if it should be sent in community pubsub topic + ResendType: common.ResendTypeRawMessage, } - _, err = m.SendMessageToControlNode(community, rawMessage) + _, err = m.SendMessageToControlNode(community, &rawMessage) if err != nil { return nil, err } @@ -1482,12 +1491,16 @@ func (m *Messenger) EditSharedAddressesForCommunity(request *requests.EditShared continue } for _, member := range members { + rawMessage.Recipients = append(rawMessage.Recipients, member) _, err := m.sender.SendPrivate(context.Background(), member, &rawMessage) if err != nil { return nil, err } } } + if _, err = m.UpsertRawMessageToWatch(&rawMessage); err != nil { + return nil, err + } response := &MessengerResponse{} response.AddCommunity(community) @@ -1630,9 +1643,10 @@ func (m *Messenger) CancelRequestToJoinCommunity(ctx context.Context, request *r SkipEncryptionLayer: true, MessageType: protobuf.ApplicationMetadataMessage_COMMUNITY_CANCEL_REQUEST_TO_JOIN, PubsubTopic: shard.DefaultNonProtectedPubsubTopic(), + ResendType: common.ResendTypeRawMessage, } - _, err = m.SendMessageToControlNode(community, rawMessage) + _, err = m.SendMessageToControlNode(community, &rawMessage) if err != nil { return nil, err } @@ -1643,6 +1657,7 @@ func (m *Messenger) CancelRequestToJoinCommunity(ctx context.Context, request *r privilegedMembers := community.GetPrivilegedMembers() for _, privilegedMember := range privilegedMembers { + rawMessage.Recipients = append(rawMessage.Recipients, privilegedMember) _, err := m.sender.SendPrivate(context.Background(), privilegedMember, &rawMessage) if err != nil { return nil, err @@ -1650,6 +1665,10 @@ func (m *Messenger) CancelRequestToJoinCommunity(ctx context.Context, request *r } } + if _, err = m.UpsertRawMessageToWatch(&rawMessage); err != nil { + return nil, err + } + response := &MessengerResponse{} response.AddCommunity(community) response.AddRequestToJoinCommunity(requestToJoin) @@ -1739,9 +1758,13 @@ func (m *Messenger) acceptRequestToJoinCommunity(requestToJoin *communities.Requ rawMessage := &common.RawMessage{ Payload: payload, Sender: community.PrivateKey(), + CommunityID: community.ID(), SkipEncryptionLayer: true, MessageType: protobuf.ApplicationMetadataMessage_COMMUNITY_REQUEST_TO_JOIN_RESPONSE, PubsubTopic: shard.DefaultNonProtectedPubsubTopic(), + ResendType: common.ResendTypeRawMessage, + ResendMethod: common.ResendMethodSendPrivate, + Recipients: []*ecdsa.PublicKey{pk}, } if community.Encrypted() { @@ -1753,6 +1776,10 @@ func (m *Messenger) acceptRequestToJoinCommunity(requestToJoin *communities.Requ if err != nil { return nil, err } + + if _, err = m.UpsertRawMessageToWatch(rawMessage); err != nil { + return nil, err + } } response := &MessengerResponse{} @@ -1930,12 +1957,17 @@ func (m *Messenger) LeaveCommunity(communityID types.HexBytes) (*MessengerRespon SkipEncryptionLayer: true, MessageType: protobuf.ApplicationMetadataMessage_COMMUNITY_REQUEST_TO_LEAVE, PubsubTopic: community.PubsubTopic(), // TODO: confirm if it should be sent in the community pubsub topic + ResendType: common.ResendTypeRawMessage, } - _, err = m.SendMessageToControlNode(community, rawMessage) + _, err = m.SendMessageToControlNode(community, &rawMessage) if err != nil { return nil, err } + + if _, err = m.UpsertRawMessageToWatch(&rawMessage); err != nil { + return nil, err + } } return mr, nil @@ -2595,7 +2627,7 @@ func (m *Messenger) ReevaluateCommunityMembersPermissions(request *requests.Reev MessageType: protobuf.ApplicationMetadataMessage_COMMUNITY_REEVALUATE_PERMISSIONS_REQUEST, PubsubTopic: community.PubsubTopic(), } - _, err = m.SendMessageToControlNode(community, rawMessage) + _, err = m.SendMessageToControlNode(community, &rawMessage) if err != nil { return nil, err } @@ -2865,10 +2897,10 @@ func (m *Messenger) SendCommunityShardKey(community *communities.Community, pubk } rawMessage := common.RawMessage{ - Recipients: pubkeys, - ResendAutomatically: true, - MessageType: protobuf.ApplicationMetadataMessage_COMMUNITY_SHARD_KEY, - Payload: encodedMessage, + Recipients: pubkeys, + ResendType: common.ResendTypeDataSync, + MessageType: protobuf.ApplicationMetadataMessage_COMMUNITY_SHARD_KEY, + Payload: encodedMessage, } _, err = m.sender.SendPubsubTopicKey(context.Background(), &rawMessage) @@ -3395,6 +3427,9 @@ func (m *Messenger) sendSharedAddressToControlNode(receiver *ecdsa.PublicKey, co SkipEncryptionLayer: true, MessageType: protobuf.ApplicationMetadataMessage_COMMUNITY_REQUEST_TO_JOIN, PubsubTopic: community.PubsubTopic(), // TODO: confirm if it should be sent in community pubsub topic + ResendType: common.ResendTypeRawMessage, + ResendMethod: common.ResendMethodSendPrivate, + Recipients: []*ecdsa.PublicKey{receiver}, } if err = m.communitiesManager.SaveRequestToJoin(requestToJoin); err != nil { @@ -3402,6 +3437,12 @@ func (m *Messenger) sendSharedAddressToControlNode(receiver *ecdsa.PublicKey, co } _, err = m.sender.SendPrivate(context.Background(), receiver, &rawMessage) + if err != nil { + return nil, err + } + + _, err = m.UpsertRawMessageToWatch(&rawMessage) + return requestToJoin, err } @@ -3987,10 +4028,10 @@ func (m *Messenger) SyncCommunitySettings(ctx context.Context, settings *communi } _, err = m.dispatchMessage(ctx, common.RawMessage{ - LocalChatID: chat.ID, - Payload: encodedMessage, - MessageType: protobuf.ApplicationMetadataMessage_SYNC_COMMUNITY_SETTINGS, - ResendAutomatically: true, + LocalChatID: chat.ID, + Payload: encodedMessage, + MessageType: protobuf.ApplicationMetadataMessage_SYNC_COMMUNITY_SETTINGS, + ResendType: common.ResendTypeDataSync, }) if err != nil { return err @@ -4529,11 +4570,20 @@ func (m *Messenger) CreateResponseWithACNotification(communityID string, acType return response, nil } -func (m *Messenger) SendMessageToControlNode(community *communities.Community, rawMessage common.RawMessage) ([]byte, error) { +// SendMessageToControlNode sends a message to the control node of the community. +// use pointer to rawMessage to get the message ID and other updated properties. +func (m *Messenger) SendMessageToControlNode(community *communities.Community, rawMessage *common.RawMessage) ([]byte, error) { if !community.PublicKey().Equal(community.ControlNode()) { - return m.sender.SendPrivate(context.Background(), community.ControlNode(), &rawMessage) + rawMessage.ResendMethod = common.ResendMethodSendPrivate + rawMessage.Recipients = append(rawMessage.Recipients, community.ControlNode()) + return m.sender.SendPrivate(context.Background(), community.ControlNode(), rawMessage) } - + rawMessage.ResendMethod = common.ResendMethodSendCommunityMessage + // Note: There are multiple instances where SendMessageToControlNode is invoked throughout the codebase. + // Additionally, some callers may invoke SendPrivate before SendMessageToControlNode. This could potentially + // lead to a situation where the same raw message is sent using different methods, which, from a code perspective, + // seems erroneous when implementing raw message resending. However, this behavior is intentional and is not considered + // an issue. For a detailed explanation, refer https://github.com/status-im/status-go/pull/4969#issuecomment-2040891184 return m.sender.SendCommunityMessage(context.Background(), rawMessage) } diff --git a/protocol/messenger_communities_sharding_test.go b/protocol/messenger_communities_sharding_test.go index 3e43c532b..3dc314074 100644 --- a/protocol/messenger_communities_sharding_test.go +++ b/protocol/messenger_communities_sharding_test.go @@ -187,10 +187,10 @@ func (s *MessengerCommunitiesShardingSuite) TestIgnoreOutdatedShardKey() { s.Require().NoError(err) rawMessage := common.RawMessage{ - Recipients: []*ecdsa.PublicKey{&s.alice.identity.PublicKey}, - ResendAutomatically: true, - MessageType: protobuf.ApplicationMetadataMessage_COMMUNITY_SHARD_KEY, - Payload: encodedMessage, + Recipients: []*ecdsa.PublicKey{&s.alice.identity.PublicKey}, + ResendType: common.ResendTypeDataSync, + MessageType: protobuf.ApplicationMetadataMessage_COMMUNITY_SHARD_KEY, + Payload: encodedMessage, } _, err = s.owner.sender.SendPubsubTopicKey(context.Background(), &rawMessage) diff --git a/protocol/messenger_contact_verification.go b/protocol/messenger_contact_verification.go index f7d868e39..b0d3328b6 100644 --- a/protocol/messenger_contact_verification.go +++ b/protocol/messenger_contact_verification.go @@ -67,10 +67,10 @@ func (m *Messenger) SendContactVerificationRequest(ctx context.Context, contactI } rawMessage, err := m.dispatchMessage(ctx, common.RawMessage{ - LocalChatID: chat.ID, - Payload: encodedMessage, - MessageType: protobuf.ApplicationMetadataMessage_REQUEST_CONTACT_VERIFICATION, - ResendAutomatically: true, + LocalChatID: chat.ID, + Payload: encodedMessage, + MessageType: protobuf.ApplicationMetadataMessage_REQUEST_CONTACT_VERIFICATION, + ResendType: common.ResendTypeDataSync, }) if err != nil { @@ -232,10 +232,10 @@ func (m *Messenger) CancelVerificationRequest(ctx context.Context, id string) (* } _, err = m.dispatchMessage(ctx, common.RawMessage{ - LocalChatID: chat.ID, - Payload: encodedMessage, - MessageType: protobuf.ApplicationMetadataMessage_CANCEL_CONTACT_VERIFICATION, - ResendAutomatically: true, + LocalChatID: chat.ID, + Payload: encodedMessage, + MessageType: protobuf.ApplicationMetadataMessage_CANCEL_CONTACT_VERIFICATION, + ResendType: common.ResendTypeDataSync, }) if err != nil { @@ -323,10 +323,10 @@ func (m *Messenger) AcceptContactVerificationRequest(ctx context.Context, id str } rawMessage, err := m.dispatchMessage(ctx, common.RawMessage{ - LocalChatID: chat.ID, - Payload: encodedMessage, - MessageType: protobuf.ApplicationMetadataMessage_ACCEPT_CONTACT_VERIFICATION, - ResendAutomatically: true, + LocalChatID: chat.ID, + Payload: encodedMessage, + MessageType: protobuf.ApplicationMetadataMessage_ACCEPT_CONTACT_VERIFICATION, + ResendType: common.ResendTypeDataSync, }) if err != nil { @@ -643,10 +643,10 @@ func (m *Messenger) DeclineContactVerificationRequest(ctx context.Context, id st } _, err = m.dispatchMessage(ctx, common.RawMessage{ - LocalChatID: chat.ID, - Payload: encodedMessage, - MessageType: protobuf.ApplicationMetadataMessage_DECLINE_CONTACT_VERIFICATION, - ResendAutomatically: true, + LocalChatID: chat.ID, + Payload: encodedMessage, + MessageType: protobuf.ApplicationMetadataMessage_DECLINE_CONTACT_VERIFICATION, + ResendType: common.ResendTypeDataSync, }) if err != nil { diff --git a/protocol/messenger_contacts.go b/protocol/messenger_contacts.go index 6c5c6370b..c7bd384e3 100644 --- a/protocol/messenger_contacts.go +++ b/protocol/messenger_contacts.go @@ -319,10 +319,10 @@ func (m *Messenger) updateAcceptedContactRequest(response *MessengerResponse, co return nil, err } _, err = m.dispatchMessage(context.Background(), common.RawMessage{ - LocalChatID: contactRequest.From, - Payload: encodedMessage, - MessageType: protobuf.ApplicationMetadataMessage_ACCEPT_CONTACT_REQUEST, - ResendAutomatically: true, + LocalChatID: contactRequest.From, + Payload: encodedMessage, + MessageType: protobuf.ApplicationMetadataMessage_ACCEPT_CONTACT_REQUEST, + ResendType: common.ResendTypeDataSync, }) if err != nil { return nil, err @@ -1112,10 +1112,10 @@ func (m *Messenger) sendContactUpdate(ctx context.Context, } rawMessage := common.RawMessage{ - LocalChatID: chatID, - Payload: encodedMessage, - MessageType: protobuf.ApplicationMetadataMessage_CONTACT_UPDATE, - ResendAutomatically: true, + LocalChatID: chatID, + Payload: encodedMessage, + MessageType: protobuf.ApplicationMetadataMessage_CONTACT_UPDATE, + ResendType: common.ResendTypeDataSync, } _, err = rawMessageHandler(ctx, rawMessage) @@ -1190,10 +1190,10 @@ func (m *Messenger) sendRetractContactRequest(contact *Contact) error { } _, err = m.dispatchMessage(context.Background(), common.RawMessage{ - LocalChatID: contact.ID, - Payload: encodedMessage, - MessageType: protobuf.ApplicationMetadataMessage_RETRACT_CONTACT_REQUEST, - ResendAutomatically: true, + LocalChatID: contact.ID, + Payload: encodedMessage, + MessageType: protobuf.ApplicationMetadataMessage_RETRACT_CONTACT_REQUEST, + ResendType: common.ResendTypeDataSync, }) if err != nil { return err diff --git a/protocol/messenger_emoji_reactions.go b/protocol/messenger_emoji_reactions.go index 9c945dc05..b63f25670 100644 --- a/protocol/messenger_emoji_reactions.go +++ b/protocol/messenger_emoji_reactions.go @@ -42,7 +42,7 @@ func (m *Messenger) SendEmojiReaction(ctx context.Context, chatID, messageID str MessageType: protobuf.ApplicationMetadataMessage_EMOJI_REACTION, // Don't resend using datasync, that would create quite a lot // of traffic if clicking too eagelry - ResendAutomatically: false, + ResendType: common.ResendTypeNone, }) if err != nil { return nil, err @@ -127,7 +127,7 @@ func (m *Messenger) SendEmojiReactionRetraction(ctx context.Context, emojiReacti MessageType: protobuf.ApplicationMetadataMessage_EMOJI_REACTION, // Don't resend using datasync, that would create quite a lot // of traffic if clicking too eagelry - ResendAutomatically: false, + ResendType: common.ResendTypeNone, }) if err != nil { return nil, err diff --git a/protocol/messenger_group_chat.go b/protocol/messenger_group_chat.go index a607ee0d8..2c084cf86 100644 --- a/protocol/messenger_group_chat.go +++ b/protocol/messenger_group_chat.go @@ -471,10 +471,10 @@ func (m *Messenger) SendGroupChatInvitationRequest(ctx context.Context, chatID s } spec := common.RawMessage{ - LocalChatID: adminPK, - Payload: encodedMessage, - MessageType: protobuf.ApplicationMetadataMessage_GROUP_CHAT_INVITATION, - ResendAutomatically: true, + LocalChatID: adminPK, + Payload: encodedMessage, + MessageType: protobuf.ApplicationMetadataMessage_GROUP_CHAT_INVITATION, + ResendType: common.ResendTypeDataSync, } pkey, err := hex.DecodeString(adminPK[2:]) @@ -539,10 +539,10 @@ func (m *Messenger) SendGroupChatInvitationRejection(ctx context.Context, invita } spec := common.RawMessage{ - LocalChatID: invitationR.From, - Payload: encodedMessage, - MessageType: protobuf.ApplicationMetadataMessage_GROUP_CHAT_INVITATION, - ResendAutomatically: true, + LocalChatID: invitationR.From, + Payload: encodedMessage, + MessageType: protobuf.ApplicationMetadataMessage_GROUP_CHAT_INVITATION, + ResendType: common.ResendTypeDataSync, } pkey, err := hex.DecodeString(invitationR.From[2:]) diff --git a/protocol/messenger_messages.go b/protocol/messenger_messages.go index 288414941..637d68d11 100644 --- a/protocol/messenger_messages.go +++ b/protocol/messenger_messages.go @@ -102,12 +102,16 @@ func (m *Messenger) EditMessage(ctx context.Context, request *requests.EditMessa return nil, err } + resendType := common.ResendTypeRawMessage + if chat.ChatType == ChatTypeOneToOne { + resendType = common.ResendTypeDataSync + } rawMessage := common.RawMessage{ LocalChatID: chat.ID, Payload: encodedMessage, MessageType: protobuf.ApplicationMetadataMessage_EDIT_MESSAGE, SkipGroupMessageWrap: true, - ResendAutomatically: true, + ResendType: resendType, } _, err = m.dispatchMessage(ctx, rawMessage) if err != nil { @@ -231,7 +235,7 @@ func (m *Messenger) DeleteMessageAndSend(ctx context.Context, messageID string) Payload: encodedMessage, MessageType: protobuf.ApplicationMetadataMessage_DELETE_MESSAGE, SkipGroupMessageWrap: true, - ResendAutomatically: true, + ResendType: GetResendTypeForChat(chat), } _, err = m.dispatchMessage(ctx, rawMessage) @@ -350,10 +354,10 @@ func (m *Messenger) DeleteMessageForMeAndSync(ctx context.Context, localChatID s } rawMessage := common.RawMessage{ - LocalChatID: chatID, - Payload: encodedMessage, - MessageType: protobuf.ApplicationMetadataMessage_SYNC_DELETE_FOR_ME_MESSAGE, - ResendAutomatically: true, + LocalChatID: chatID, + Payload: encodedMessage, + MessageType: protobuf.ApplicationMetadataMessage_SYNC_DELETE_FOR_ME_MESSAGE, + ResendType: common.ResendTypeDataSync, } _, err2 = m.dispatchMessage(ctx, rawMessage) return err2 diff --git a/protocol/messenger_pin_messages.go b/protocol/messenger_pin_messages.go index 1732b2068..45df91888 100644 --- a/protocol/messenger_pin_messages.go +++ b/protocol/messenger_pin_messages.go @@ -56,7 +56,7 @@ func (m *Messenger) sendPinMessage(ctx context.Context, message *common.PinMessa Payload: encodedMessage, MessageType: protobuf.ApplicationMetadataMessage_PIN_MESSAGE, SkipGroupMessageWrap: true, - ResendAutomatically: true, + ResendType: GetResendTypeForChat(chat), } _, err = m.dispatchMessage(ctx, rawMessage) if err != nil { diff --git a/protocol/messenger_profile_showcase.go b/protocol/messenger_profile_showcase.go index 61cb3eecc..f7dfc6bbb 100644 --- a/protocol/messenger_profile_showcase.go +++ b/protocol/messenger_profile_showcase.go @@ -758,10 +758,10 @@ func (m *Messenger) syncProfileShowcasePreferences(ctx context.Context, rawMessa _, chat := m.getLastClockWithRelatedChat() rawMessage := common.RawMessage{ - LocalChatID: chat.ID, - Payload: encodedMessage, - MessageType: protobuf.ApplicationMetadataMessage_SYNC_PROFILE_SHOWCASE_PREFERENCES, - ResendAutomatically: true, + LocalChatID: chat.ID, + Payload: encodedMessage, + MessageType: protobuf.ApplicationMetadataMessage_SYNC_PROFILE_SHOWCASE_PREFERENCES, + ResendType: common.ResendTypeDataSync, } _, err = rawMessageHandler(ctx, rawMessage) diff --git a/protocol/messenger_raw_message_resend.go b/protocol/messenger_raw_message_resend.go new file mode 100644 index 000000000..3e0649000 --- /dev/null +++ b/protocol/messenger_raw_message_resend.go @@ -0,0 +1,205 @@ +package protocol + +import ( + "context" + "fmt" + "math" + "time" + + "github.com/status-im/status-go/protocol/protobuf" + + "github.com/pkg/errors" + "go.uber.org/zap" + + "github.com/status-im/status-go/protocol/common" +) + +// watchExpiredMessages regularly checks for expired emojis and invoke their resending +func (m *Messenger) watchExpiredMessages() { + m.logger.Debug("watching expired messages") + go func() { + for { + select { + case <-time.After(time.Second): + if m.Online() { + err := m.resendExpiredMessages() + if err != nil { + m.logger.Debug("failed to resend expired message", zap.Error(err)) + } + } + case <-m.quit: + return + } + } + }() +} + +func (m *Messenger) resendExpiredMessages() error { + if m.connectionState.Offline { + return errors.New("offline") + } + + ids, err := m.persistence.ExpiredMessagesIDs(m.config.messageResendMaxCount) + if err != nil { + return errors.Wrapf(err, "Can't get expired reactions from db") + } + + for _, id := range ids { + message, shouldResend, err := m.processMessageID(id) + if err != nil { + m.logger.Error("Error processing message ID when trying resend raw message", zap.String("id", id), zap.Error(err)) + } else if shouldResend { + m.logger.Debug("Resent raw message", + zap.String("id", id), + zap.Any("message type", message.MessageType), + zap.Int("send count", message.SendCount), + ) + } + } + return nil +} + +func (m *Messenger) processMessageID(id string) (*common.RawMessage, bool, error) { + rawMessage, err := m.persistence.RawMessageByID(id) + if err != nil { + return nil, false, errors.Wrap(err, "Can't get raw message by ID") + } + + shouldResend, err := m.shouldResendMessage(rawMessage, m.getTimesource()) + if err != nil { + m.logger.Error("Can't check if message should be resent", zap.Error(err)) + return rawMessage, false, err + } + + if !shouldResend { + return rawMessage, false, nil + } + + switch rawMessage.ResendMethod { + case common.ResendMethodSendCommunityMessage: + err = m.handleSendCommunityMessage(rawMessage) + case common.ResendMethodSendPrivate: + err = m.handleSendPrivateMessage(rawMessage) + case common.ResendMethodDynamic: + shouldResend, err = m.handleOtherResendMethods(rawMessage) + default: + err = errors.New("Unknown resend method") + } + return rawMessage, shouldResend, err +} + +func (m *Messenger) handleSendCommunityMessage(rawMessage *common.RawMessage) error { + _, err := m.sender.SendCommunityMessage(context.TODO(), rawMessage) + if err != nil { + err = errors.Wrap(err, "Can't resend message with SendCommunityMessage") + } + m.upsertRawMessageToWatch(rawMessage) + return err +} + +func (m *Messenger) handleSendPrivateMessage(rawMessage *common.RawMessage) error { + if len(rawMessage.Recipients) == 0 { + m.logger.Error("No recipients to resend message", zap.String("id", rawMessage.ID)) + m.upsertRawMessageToWatch(rawMessage) + return errors.New("No recipients to resend message with SendPrivate") + } + + var err error + for _, r := range rawMessage.Recipients { + _, err = m.sender.SendPrivate(context.TODO(), r, rawMessage) + if err != nil { + err = errors.Wrap(err, fmt.Sprintf("Can't resend message with SendPrivate to %s", common.PubkeyToHex(r))) + } + } + + m.upsertRawMessageToWatch(rawMessage) + return err +} + +func (m *Messenger) handleOtherResendMethods(rawMessage *common.RawMessage) (bool, error) { + chat, ok := m.allChats.Load(rawMessage.LocalChatID) + if !ok { + m.logger.Error("Can't find chat with id", zap.String("id", rawMessage.LocalChatID)) + return false, nil // Continue with next message if chat not found + } + + if !(chat.Public() || chat.CommunityChat()) { + return false, nil // Only resend for public or community chats + } + + if ok { + err := m.persistence.SaveRawMessage(rawMessage) + if err != nil { + m.logger.Error("Can't save raw message marked as expired", zap.Error(err)) + return true, err + } + } + return true, m.reSendRawMessage(context.Background(), rawMessage.ID) +} + +func (m *Messenger) shouldResendMessage(message *common.RawMessage, t common.TimeSource) (bool, error) { + if m.featureFlags.ResendRawMessagesDisabled { + return false, nil + } + //exponential backoff depends on how many attempts to send message already made + power := math.Pow(2, float64(message.SendCount-1)) + backoff := uint64(power) * uint64(m.config.messageResendMinDelay.Milliseconds()) + backoffElapsed := t.GetCurrentTime() > (message.LastSent + backoff) + return backoffElapsed, nil +} + +// pull a message from the database and send it again +func (m *Messenger) reSendRawMessage(ctx context.Context, messageID string) error { + message, err := m.persistence.RawMessageByID(messageID) + if err != nil { + return err + } + + chat, ok := m.allChats.Load(message.LocalChatID) + if !ok { + return errors.New("chat not found") + } + + _, err = m.dispatchMessage(ctx, common.RawMessage{ + LocalChatID: chat.ID, + Payload: message.Payload, + PubsubTopic: message.PubsubTopic, + MessageType: message.MessageType, + Recipients: message.Recipients, + ResendType: message.ResendType, + SendCount: message.SendCount, + }) + return err +} + +// UpsertRawMessageToWatch insert/update the rawMessage to the database, resend it if necessary. +// relate watch method: Messenger#watchExpiredMessages +func (m *Messenger) UpsertRawMessageToWatch(rawMessage *common.RawMessage) (*common.RawMessage, error) { + rawMessage.SendCount++ + rawMessage.LastSent = m.getTimesource().GetCurrentTime() + err := m.persistence.SaveRawMessage(rawMessage) + if err != nil { + return nil, err + } + return rawMessage, nil +} + +func (m *Messenger) upsertRawMessageToWatch(rawMessage *common.RawMessage) { + _, err := m.UpsertRawMessageToWatch(rawMessage) + if err != nil { + // this is unlikely to happen, but we should log it + m.logger.Error("Can't upsert raw message after SendCommunityMessage", zap.Error(err), zap.String("id", rawMessage.ID)) + } +} + +func (m *Messenger) RawMessagesIDsByType(t protobuf.ApplicationMetadataMessage_Type) ([]string, error) { + return m.persistence.RawMessagesIDsByType(t) +} + +func (m *Messenger) RawMessageByID(id string) (*common.RawMessage, error) { + return m.persistence.RawMessageByID(id) +} + +func (m *Messenger) UpdateRawMessageSent(id string, sent bool, lastSent uint64) error { + return m.persistence.UpdateRawMessageSent(id, sent, lastSent) +} diff --git a/protocol/messenger_saved_address.go b/protocol/messenger_saved_address.go index 9eef49a7d..71689ac42 100644 --- a/protocol/messenger_saved_address.go +++ b/protocol/messenger_saved_address.go @@ -53,10 +53,10 @@ func (m *Messenger) dispatchSyncSavedAddress(ctx context.Context, syncMessage *p } rawMessage := common.RawMessage{ - LocalChatID: chat.ID, - Payload: encodedMessage, - MessageType: protobuf.ApplicationMetadataMessage_SYNC_SAVED_ADDRESS, - ResendAutomatically: true, + LocalChatID: chat.ID, + Payload: encodedMessage, + MessageType: protobuf.ApplicationMetadataMessage_SYNC_SAVED_ADDRESS, + ResendType: common.ResendTypeDataSync, } _, err = rawMessageHandler(ctx, rawMessage) diff --git a/protocol/messenger_status_updates.go b/protocol/messenger_status_updates.go index d7ad0803d..6188a294d 100644 --- a/protocol/messenger_status_updates.go +++ b/protocol/messenger_status_updates.go @@ -65,11 +65,11 @@ func (m *Messenger) sendUserStatus(ctx context.Context, status UserStatus) error contactCodeTopic := transport.ContactCodeTopic(&m.identity.PublicKey) rawMessage := common.RawMessage{ - LocalChatID: contactCodeTopic, - Payload: encodedMessage, - MessageType: protobuf.ApplicationMetadataMessage_STATUS_UPDATE, - ResendAutomatically: true, - Ephemeral: statusUpdate.StatusType == protobuf.StatusUpdate_AUTOMATIC, + LocalChatID: contactCodeTopic, + Payload: encodedMessage, + MessageType: protobuf.ApplicationMetadataMessage_STATUS_UPDATE, + ResendType: common.ResendTypeNone, // does this need to be resent? + Ephemeral: statusUpdate.StatusType == protobuf.StatusUpdate_AUTOMATIC, } _, err = m.sender.SendPublic(ctx, contactCodeTopic, rawMessage) @@ -167,12 +167,12 @@ func (m *Messenger) sendCurrentUserStatusToCommunity(ctx context.Context, commun } rawMessage := common.RawMessage{ - LocalChatID: community.StatusUpdatesChannelID(), - Payload: encodedMessage, - MessageType: protobuf.ApplicationMetadataMessage_STATUS_UPDATE, - ResendAutomatically: true, - Ephemeral: statusUpdate.StatusType == protobuf.StatusUpdate_AUTOMATIC, - PubsubTopic: community.PubsubTopic(), + LocalChatID: community.StatusUpdatesChannelID(), + Payload: encodedMessage, + MessageType: protobuf.ApplicationMetadataMessage_STATUS_UPDATE, + ResendType: common.ResendTypeNone, // does this need to be resent? + Ephemeral: statusUpdate.StatusType == protobuf.StatusUpdate_AUTOMATIC, + PubsubTopic: community.PubsubTopic(), } _, err = m.sender.SendPublic(ctx, rawMessage.LocalChatID, rawMessage) diff --git a/protocol/messenger_util.go b/protocol/messenger_util.go new file mode 100644 index 000000000..d47d3243a --- /dev/null +++ b/protocol/messenger_util.go @@ -0,0 +1,16 @@ +package protocol + +import "github.com/status-im/status-go/protocol/common" + +// GetResendTypeForChat returns the resend type for a chat. +// This function currently infers the ResendType from the chat type. +// However, it is recommended to explicitly determine the ResendType based on +// specific message characteristics to avoid implicit assumptions. This ensures +// that each message dictates its ResendType based on its own properties and +// context, rather than the chat type it is associated with. +func GetResendTypeForChat(chat *Chat) common.ResendType { + if chat.ChatType == ChatTypeOneToOne { + return common.ResendTypeDataSync + } + return common.ResendTypeRawMessage +} diff --git a/protocol/messenger_wallet.go b/protocol/messenger_wallet.go index 04964da8e..6a15e7c68 100644 --- a/protocol/messenger_wallet.go +++ b/protocol/messenger_wallet.go @@ -511,10 +511,10 @@ func (m *Messenger) syncTokenPreferences(rawMessageHandler RawMessageHandler) er } rawMessage := common.RawMessage{ - LocalChatID: chat.ID, - Payload: encodedMessage, - MessageType: protobuf.ApplicationMetadataMessage_SYNC_TOKEN_PREFERENCES, - ResendAutomatically: true, + LocalChatID: chat.ID, + Payload: encodedMessage, + MessageType: protobuf.ApplicationMetadataMessage_SYNC_TOKEN_PREFERENCES, + ResendType: common.ResendTypeDataSync, } _, err = rawMessageHandler(ctx, rawMessage) @@ -608,10 +608,10 @@ func (m *Messenger) syncCollectiblePreferences(rawMessageHandler RawMessageHandl } rawMessage := common.RawMessage{ - LocalChatID: chat.ID, - Payload: encodedMessage, - MessageType: protobuf.ApplicationMetadataMessage_SYNC_COLLECTIBLE_PREFERENCES, - ResendAutomatically: true, + LocalChatID: chat.ID, + Payload: encodedMessage, + MessageType: protobuf.ApplicationMetadataMessage_SYNC_COLLECTIBLE_PREFERENCES, + ResendType: common.ResendTypeDataSync, } _, err = rawMessageHandler(ctx, rawMessage) @@ -655,10 +655,10 @@ func (m *Messenger) syncAccountsPositions(rawMessageHandler RawMessageHandler) e } rawMessage := common.RawMessage{ - LocalChatID: chat.ID, - Payload: encodedMessage, - MessageType: protobuf.ApplicationMetadataMessage_SYNC_ACCOUNTS_POSITIONS, - ResendAutomatically: true, + LocalChatID: chat.ID, + Payload: encodedMessage, + MessageType: protobuf.ApplicationMetadataMessage_SYNC_ACCOUNTS_POSITIONS, + ResendType: common.ResendTypeDataSync, } _, err = rawMessageHandler(ctx, rawMessage) @@ -683,10 +683,10 @@ func (m *Messenger) syncWalletAccount(acc *accounts.Account, rawMessageHandler R } rawMessage := common.RawMessage{ - LocalChatID: chat.ID, - Payload: encodedMessage, - MessageType: protobuf.ApplicationMetadataMessage_SYNC_ACCOUNT, - ResendAutomatically: true, + LocalChatID: chat.ID, + Payload: encodedMessage, + MessageType: protobuf.ApplicationMetadataMessage_SYNC_ACCOUNT, + ResendType: common.ResendTypeDataSync, } _, err = rawMessageHandler(ctx, rawMessage) @@ -703,9 +703,9 @@ func (m *Messenger) syncKeypair(keypair *accounts.Keypair, rawMessageHandler Raw _, chat := m.getLastClockWithRelatedChat() rawMessage := common.RawMessage{ - LocalChatID: chat.ID, - ResendAutomatically: true, - MessageType: protobuf.ApplicationMetadataMessage_SYNC_KEYPAIR, + LocalChatID: chat.ID, + ResendType: common.ResendTypeDataSync, + MessageType: protobuf.ApplicationMetadataMessage_SYNC_KEYPAIR, } message, err := m.prepareSyncKeypairMessage(keypair) diff --git a/protocol/migrations/migrations.go b/protocol/migrations/migrations.go index cbd73ec29..85916eefe 100644 --- a/protocol/migrations/migrations.go +++ b/protocol/migrations/migrations.go @@ -135,6 +135,7 @@ // 1711937186_add_contact_customization_color.up.sql (172B) // 1712745141_hash_ratchet_encrypted_messages_key_id.up.sql (111B) // 1712905223_add_parity_to_message_segments.up.sql (792B) +// 1713169458_update_raw_messages_with_resend_features.up.sql (608B) // README.md (554B) // doc.go (870B) @@ -146,6 +147,7 @@ import ( "crypto/sha256" "fmt" "io" + "io/ioutil" "os" "path/filepath" "strings" @@ -155,7 +157,7 @@ import ( func bindataRead(data []byte, name string) ([]byte, error) { gz, err := gzip.NewReader(bytes.NewBuffer(data)) if err != nil { - return nil, fmt.Errorf("read %q: %w", name, err) + return nil, fmt.Errorf("read %q: %v", name, err) } var buf bytes.Buffer @@ -163,7 +165,7 @@ func bindataRead(data []byte, name string) ([]byte, error) { clErr := gz.Close() if err != nil { - return nil, fmt.Errorf("read %q: %w", name, err) + return nil, fmt.Errorf("read %q: %v", name, err) } if clErr != nil { return nil, err @@ -2904,6 +2906,26 @@ func _1712905223_add_parity_to_message_segmentsUpSql() (*asset, error) { return a, nil } +var __1713169458_update_raw_messages_with_resend_featuresUpSql = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x9c\x90\x3f\x6b\xc3\x30\x10\x47\x77\x7f\x8a\xdb\xd2\x6e\xdd\x33\xc9\xb6\x42\x0d\xaa\x5d\x14\xa5\x64\x3b\x14\xfb\xb0\x45\xa3\xc8\xe8\x0f\x8d\xbf\x7d\x69\x08\x6d\x52\x4a\x89\x33\x4b\xef\xdd\x8f\xc7\x84\xe2\x12\x14\xcb\x05\x07\xaf\x3f\xd0\x52\x08\xba\xa7\x00\xac\x2c\xa1\x68\xc4\xe6\xa5\x86\x40\x87\x8e\x3c\xe4\xa2\xc9\x97\xd9\x2d\x40\xeb\xac\x4d\x07\x13\x27\x34\xdd\x0c\xcc\xd3\xd7\x25\x8c\xd3\x48\x50\xd5\x0a\x4a\xbe\x62\x1b\xa1\xe0\x69\x16\x6e\x29\x0e\xae\xbb\x47\x30\xa6\x5d\x48\x3b\x8c\x6e\x34\x2d\xbc\x31\x59\x3c\x33\xf9\xed\x58\x2c\x6e\x93\x0c\x3a\x0c\xe8\x75\x6c\x07\x8a\xd8\x7b\x97\xc6\x79\x11\x7e\xda\xbd\xd3\x84\x74\x44\x1b\xfa\x3f\x93\x64\xa5\x6c\x5e\xa1\xaa\x4b\xbe\x85\x6a\x05\x7c\x5b\xad\xd5\x1a\x4c\x77\xc4\x73\x08\x9d\xa2\xb3\x3a\x9a\x56\xef\xf7\xd3\x32\x2b\x24\x67\x8a\x9f\x81\x8b\x6f\x27\x77\x53\x5f\x0d\x7a\xb8\x78\x7b\xfc\x67\xf7\x69\xc2\x75\xfe\x5f\x57\x3f\x03\x00\x00\xff\xff\x6e\x3a\xd8\x1f\x60\x02\x00\x00") + +func _1713169458_update_raw_messages_with_resend_featuresUpSqlBytes() ([]byte, error) { + return bindataRead( + __1713169458_update_raw_messages_with_resend_featuresUpSql, + "1713169458_update_raw_messages_with_resend_features.up.sql", + ) +} + +func _1713169458_update_raw_messages_with_resend_featuresUpSql() (*asset, error) { + bytes, err := _1713169458_update_raw_messages_with_resend_featuresUpSqlBytes() + if err != nil { + return nil, err + } + + info := bindataFileInfo{name: "1713169458_update_raw_messages_with_resend_features.up.sql", size: 608, mode: os.FileMode(0644), modTime: time.Unix(1700000000, 0)} + a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x67, 0x9b, 0x64, 0x54, 0x62, 0x84, 0x6, 0x98, 0x6d, 0x80, 0x67, 0xf2, 0x7e, 0x75, 0x1e, 0xd8, 0x3f, 0x8, 0xc5, 0xcc, 0x48, 0xe6, 0xe0, 0x22, 0x42, 0x9, 0xe4, 0x5d, 0xbf, 0xd3, 0x58, 0x8a}} + return a, nil +} + var _readmeMd = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x54\x91\xc1\xce\xd3\x30\x10\x84\xef\x7e\x8a\x91\x7a\x01\xa9\x2a\x8f\xc0\x0d\x71\x82\x03\x48\x1c\xc9\x36\x9e\x36\x96\x1c\x6f\xf0\xae\x93\xe6\xed\x91\xa3\xc2\xdf\xff\x66\xed\xd8\x33\xdf\x78\x4f\xa7\x13\xbe\xea\x06\x57\x6c\x35\x39\x31\xa7\x7b\x15\x4f\x5a\xec\x73\x08\xbf\x08\x2d\x79\x7f\x4a\x43\x5b\x86\x17\xfd\x8c\x21\xea\x56\x5e\x47\x90\x4a\x14\x75\x48\xde\x64\x37\x2c\x6a\x96\xae\x99\x48\x05\xf6\x27\x77\x13\xad\x08\xae\x8a\x51\xe7\x25\xf3\xf1\xa9\x9f\xf9\x58\x58\x2c\xad\xbc\xe0\x8b\x56\xf0\x21\x5d\xeb\x4c\x95\xb3\xae\x84\x60\xd4\xdc\xe6\x82\x5d\x1b\x36\x6d\x39\x62\x92\xf5\xb8\x11\xdb\x92\xd3\x28\xce\xe0\x13\xe1\x72\xcd\x3c\x63\xd4\x65\x87\xae\xac\xe8\xc3\x28\x2e\x67\x44\x66\x3a\x21\x25\xa2\x72\xac\x14\x67\xbc\x84\x9f\x53\x32\x8c\x52\x70\x25\x56\xd6\xfd\x8d\x05\x37\xad\x30\x9d\x9f\xa6\x86\x0f\xcd\x58\x7f\xcf\x34\x93\x3b\xed\x90\x9f\xa4\x1f\xcf\x30\x85\x4d\x07\x58\xaf\x7f\x25\xc4\x9d\xf3\x72\x64\x84\xd0\x7f\xf9\x9b\x3a\x2d\x84\xef\x85\x48\x66\x8d\xd8\x88\x9b\x8c\x8c\x98\x5b\xf6\x74\x14\x4e\x33\x0d\xc9\xe0\x93\x38\xda\x12\xc5\x69\xbd\xe4\xf0\x2e\x7a\x78\x07\x1c\xfe\x13\x9f\x91\x29\x31\x95\x7b\x7f\x62\x59\x37\xb4\xe5\x5e\x25\xfe\x33\xee\xd5\x53\x71\xd6\xda\x3a\xd8\xcb\xde\x2e\xf8\xa1\x90\x55\x53\x0c\xc7\xaa\x0d\xe9\x76\x14\x29\x1c\x7b\x68\xdd\x2f\xe1\x6f\x00\x00\x00\xff\xff\x3c\x0a\xc2\xfe\x2a\x02\x00\x00") func readmeMdBytes() ([]byte, error) { @@ -3035,159 +3057,292 @@ func AssetNames() []string { // _bindata is a table, holding each asset generator, mapped to its name. var _bindata = map[string]func() (*asset, error){ - "000001_init.down.db.sql": _000001_initDownDbSql, - "000001_init.up.db.sql": _000001_initUpDbSql, - "000002_add_last_ens_clock_value.up.sql": _000002_add_last_ens_clock_valueUpSql, - "1586358095_add_replace.up.sql": _1586358095_add_replaceUpSql, - "1588665364_add_image_data.up.sql": _1588665364_add_image_dataUpSql, - "1589365189_add_pow_target.up.sql": _1589365189_add_pow_targetUpSql, - "1591277220_add_index_messages.up.sql": _1591277220_add_index_messagesUpSql, - "1593087212_add_mute_chat_and_raw_message_fields.up.sql": _1593087212_add_mute_chat_and_raw_message_fieldsUpSql, - "1595862781_add_audio_data.up.sql": _1595862781_add_audio_dataUpSql, - "1595865249_create_emoji_reactions_table.up.sql": _1595865249_create_emoji_reactions_tableUpSql, - "1596805115_create_group_chat_invitations_table.up.sql": _1596805115_create_group_chat_invitations_tableUpSql, - "1597322655_add_invitation_admin_chat_field.up.sql": _1597322655_add_invitation_admin_chat_fieldUpSql, - "1597757544_add_nickname.up.sql": _1597757544_add_nicknameUpSql, - "1598955122_add_mentions.up.sql": _1598955122_add_mentionsUpSql, - "1599641390_add_emoji_reactions_index.up.sql": _1599641390_add_emoji_reactions_indexUpSql, - "1599720851_add_seen_index_remove_long_messages.up.sql": _1599720851_add_seen_index_remove_long_messagesUpSql, - "1603198582_add_profile_chat_field.up.sql": _1603198582_add_profile_chat_fieldUpSql, - "1603816533_add_links.up.sql": _1603816533_add_linksUpSql, - "1603888149_create_chat_identity_last_published_table.up.sql": _1603888149_create_chat_identity_last_published_tableUpSql, - "1605075346_add_communities.up.sql": _1605075346_add_communitiesUpSql, - "1610117927_add_message_cache.up.sql": _1610117927_add_message_cacheUpSql, - "1610959908_add_dont_wrap_to_raw_messages.up.sql": _1610959908_add_dont_wrap_to_raw_messagesUpSql, - "1610960912_add_send_on_personal_topic.up.sql": _1610960912_add_send_on_personal_topicUpSql, - "1612870480_add_datasync_id.up.sql": _1612870480_add_datasync_idUpSql, - "1614152139_add_communities_request_to_join.up.sql": _1614152139_add_communities_request_to_joinUpSql, - "1615374373_add_confirmations.up.sql": _1615374373_add_confirmationsUpSql, - "1617694931_add_notification_center.up.sql": _1617694931_add_notification_centerUpSql, - "1618923660_create_pin_messages.up.sql": _1618923660_create_pin_messagesUpSql, - "1619094007_add_joined_chat_field.up.sql": _1619094007_add_joined_chat_fieldUpSql, - "1619099821_add_last_synced_field.up.sql": _1619099821_add_last_synced_fieldUpSql, - "1621933219_add_mentioned.up.sql": _1621933219_add_mentionedUpSql, - "1622010048_add_unviewed_mentions_count.up.sql": _1622010048_add_unviewed_mentions_countUpSql, - "1622061278_add_message_activity_center_notification_field.up.sql": _1622061278_add_message_activity_center_notification_fieldUpSql, - "1622464518_set_synced_to_from.up.sql": _1622464518_set_synced_to_fromUpSql, - "1622464519_add_chat_description.up.sql": _1622464519_add_chat_descriptionUpSql, - "1622622253_add_pinned_by_to_pin_messages.up.sql": _1622622253_add_pinned_by_to_pin_messagesUpSql, - "1623938329_add_author_activity_center_notification_field.up.sql": _1623938329_add_author_activity_center_notification_fieldUpSql, - "1623938330_add_edit_messages.up.sql": _1623938330_add_edit_messagesUpSql, - "1624978434_add_muted_community.up.sql": _1624978434_add_muted_communityUpSql, - "1625018910_add_repply_message_activity_center_notification_field.up.sql": _1625018910_add_repply_message_activity_center_notification_fieldUpSql, - "1625762506_add_deleted_messages.up.sql": _1625762506_add_deleted_messagesUpSql, - "1627388946_add_communities_synced_at.up.sql": _1627388946_add_communities_synced_atUpSql, - "1628280060_create-usermessages-index.sql": _1628280060_createUsermessagesIndexSql, - "1632303896_modify_contacts_table.up.sql": _1632303896_modify_contacts_tableUpSql, - "1633349838_add_emoji_column_in_chats.up.sql": _1633349838_add_emoji_column_in_chatsUpSql, - "1634831235_add_highlight_column_in_chats.up.sql": _1634831235_add_highlight_column_in_chatsUpSql, - "1634896007_add_last_updated_locally_and_removed.up.sql": _1634896007_add_last_updated_locally_and_removedUpSql, - "1635840039_add_clock_read_at_column_in_chats.up.sql": _1635840039_add_clock_read_at_column_in_chatsUpSql, - "1637852321_add_received_invitation_admin_column_in_chats.up.sql": _1637852321_add_received_invitation_admin_column_in_chatsUpSql, - "1645034601_display_name.up.sql": _1645034601_display_nameUpSql, - "1645034602_add_mutual_contact_request.up.sql": _1645034602_add_mutual_contact_requestUpSql, - "1650373957_add_contact_request_state.up.sql": _1650373957_add_contact_request_stateUpSql, - "1656958989_contact_verification.up.sql": _1656958989_contact_verificationUpSql, - "1658236268_add_discord_message_authors_table.up.sql": _1658236268_add_discord_message_authors_tableUpSql, - "1659619997_add_discord_messages_table.up.sql": _1659619997_add_discord_messages_tableUpSql, - "1660226788_create_chat_identity_social_links.up.sql": _1660226788_create_chat_identity_social_linksUpSql, - "1660226789_add_walletconnectsessions_table.up.sql": _1660226789_add_walletconnectsessions_tableUpSql, - "1661242854_add_communities_requests_to_leave.up.sql": _1661242854_add_communities_requests_to_leaveUpSql, - "1662044232_add_chat_image.up.sql": _1662044232_add_chat_imageUpSql, - "1662106895_add_chat_first_message_timestamp.up.sql": _1662106895_add_chat_first_message_timestampUpSql, - "1662723928_add_discord_author_image_fields.up.sql": _1662723928_add_discord_author_image_fieldsUpSql, - "1664195977_add_deleted_for_mes.up.sql": _1664195977_add_deleted_for_mesUpSql, - "1664367420_add_discord_attachments_table.up.sql": _1664367420_add_discord_attachments_tableUpSql, - "1665079662_add_spectated_column_in_communities.up.sql": _1665079662_add_spectated_column_in_communitiesUpSql, - "1665479047_add_community_id_in_notifications.up.sql": _1665479047_add_community_id_in_notificationsUpSql, - "1665484435_add_encrypted_messages.up.sql": _1665484435_add_encrypted_messagesUpSql, - "1665560200_add_contact_verification_individual.up.sql": _1665560200_add_contact_verification_individualUpSql, - "1670921937_add_album_id.up.sql": _1670921937_add_album_idUpSql, - "1673373000_add_replied.up.sql": _1673373000_add_repliedUpSql, - "1673428910_add_image_width_height.up.sql": _1673428910_add_image_width_heightUpSql, - "1674210659_add_contact_request_local_clock.up.sql": _1674210659_add_contact_request_local_clockUpSql, - "1675212323_add_deleted_by.up.sql": _1675212323_add_deleted_byUpSql, - "1675247084_add_activity_center_states.up.sql": _1675247084_add_activity_center_statesUpSql, - "1675272329_fix_protocol_migration.up.sql": _1675272329_fix_protocol_migrationUpSql, - "1676998418_fix_activity_center_migration.up.sql": _1676998418_fix_activity_center_migrationUpSql, - "1677278861_add_deleted_column_to_activity_center_notifications_table.up.sql": _1677278861_add_deleted_column_to_activity_center_notifications_tableUpSql, - "1677486338_add_community_tokens_table.up.sql": _1677486338_add_community_tokens_tableUpSql, - "1678292329_add_collapsed_categories.up.sql": _1678292329_add_collapsed_categoriesUpSql, - "1678800760_add_index_to_raw_messages.up.sql": _1678800760_add_index_to_raw_messagesUpSql, - "1678877478_add_communities_requests_to_join_revealed_addresses_table.up.sql": _1678877478_add_communities_requests_to_join_revealed_addresses_tableUpSql, - "1679326850_add_community_token_owners.up.sql": _1679326850_add_community_token_ownersUpSql, - "1680011500_add_album_images_count.up.sql": _1680011500_add_album_images_countUpSql, - "1680114896_add_index_on_album_id.up.sql": _1680114896_add_index_on_album_idUpSql, - "1681655289_add_mute_till.up.sql": _1681655289_add_mute_tillUpSql, - "1681934966_add_index_response_to.up.sql": _1681934966_add_index_response_toUpSql, - "1682528339_add_index_user_messages_unseen.up.sql": _1682528339_add_index_user_messages_unseenUpSql, - "1683707289_recreate_deleted_for_mes.up.sql": _1683707289_recreate_deleted_for_mesUpSql, - "1683725607_mark_discord_messages_as_seen.up.sql": _1683725607_mark_discord_messages_as_seenUpSql, - "1684174617_add_url_previews_to_user_messages.up.sql": _1684174617_add_url_previews_to_user_messagesUpSql, - "1684175608_add_token_balances.up.sql": _1684175608_add_token_balancesUpSql, - "1684979808_sync_activity_center_notifications.up.sql": _1684979808_sync_activity_center_notificationsUpSql, - "1685383829_add_communities_mute_till.up.sql": _1685383829_add_communities_mute_tillUpSql, - "1685964183_add_chainids_to_revealed_addresses.up.sql": _1685964183_add_chainids_to_revealed_addressesUpSql, - "1687370421_add_communities_muted_till_new.up.sql": _1687370421_add_communities_muted_till_newUpSql, - "1687416607_add_communities_check_channel_permission_responses_table.up.sql": _1687416607_add_communities_check_channel_permission_responses_tableUpSql, - "1687856939_add_community_tokens_decimals.up.sql": _1687856939_add_community_tokens_decimalsUpSql, - "1687959987_modify_community_tokens_supply_as_string.up.sql": _1687959987_modify_community_tokens_supply_as_stringUpSql, - "1689258900_add_airdrop_address_to_revealed_addresses.up.sql": _1689258900_add_airdrop_address_to_revealed_addressesUpSql, - "1689266326_create_communities_events_table.up.sql": _1689266326_create_communities_events_tableUpSql, - "1689931300_add_community_tokens_deployer_and_priv_level.up.sql": _1689931300_add_community_tokens_deployer_and_priv_levelUpSql, - "1693311881_add_unfurled_links_to_message_edits.up.sql": _1693311881_add_unfurled_links_to_message_editsUpSql, - "1693311981_community_shard.up.sql": _1693311981_community_shardUpSql, - "1695331492_add_status_link_previews.up.sql": _1695331492_add_status_link_previewsUpSql, - "1695918296_add_validated_at.up.sql": _1695918296_add_validated_atUpSql, - "1697699419_community_control_node_sync.up.sql": _1697699419_community_control_node_syncUpSql, - "1698137561_add_profile_showcase_tables.up.sql": _1698137561_add_profile_showcase_tablesUpSql, - "1698137562_fix_encryption_key_id.up.sql": _1698137562_fix_encryption_key_idUpSql, - "1698414646_add_padding.up.sql": _1698414646_add_paddingUpSql, - "1698746210_add_signature_to_revealed_addresses.up.sql": _1698746210_add_signature_to_revealed_addressesUpSql, - "1699041816_profile_showcase_contacts.up.sql": _1699041816_profile_showcase_contactsUpSql, - "1699554099_message_segments.up.sql": _1699554099_message_segmentsUpSql, - "1700044186_message_segments_timestamp.up.sql": _1700044186_message_segments_timestampUpSql, - "1700044187_curated_communities.up.sql": _1700044187_curated_communitiesUpSql, - "1700820989_add_resend_automatically_index.up.sql": _1700820989_add_resend_automatically_indexUpSql, - "1702996953_add_communities_shards_table.up.sql": _1702996953_add_communities_shards_tableUpSql, - "1704489636_add_album_images.up.sql": _1704489636_add_album_imagesUpSql, - "1704821941_add_joined_at_for_community.up.sql": _1704821941_add_joined_at_for_communityUpSql, - "1704832511_add_last_opened_at_for_communities.up.sql": _1704832511_add_last_opened_at_for_communitiesUpSql, - "1704832512_add_peersyncing.up.sql": _1704832512_add_peersyncingUpSql, - "1706028033_profile_showcase_address_and_community.up.sql": _1706028033_profile_showcase_address_and_communityUpSql, - "1706520870_add_bridge_messages_table.up.sql": _1706520870_add_bridge_messages_tableUpSql, - "1706520871_add_community_description_cache.up.sql": _1706520871_add_community_description_cacheUpSql, - "1707749393_add_community_grants.up.sql": _1707749393_add_community_grantsUpSql, - "1707841194_add_profile_showcase_preferences.up.sql": _1707841194_add_profile_showcase_preferencesUpSql, - "1708062699_activity_data.up.sql": _1708062699_activity_dataUpSql, - "1708423707_applied_community_events.up.sql": _1708423707_applied_community_eventsUpSql, - "1708440786_profile_showcase_social_links.up.sql": _1708440786_profile_showcase_social_linksUpSql, - "1709805967_simplify_profile_showcase_preferences.up.sql": _1709805967_simplify_profile_showcase_preferencesUpSql, - "1709828431_add_community_description_cache.up.sql": _1709828431_add_community_description_cacheUpSql, - "1710331283_add_bio_to_contacts.up.sql": _1710331283_add_bio_to_contactsUpSql, - "1710331284_hash_ratchet_encrypted_messages_key_id.up.sql": _1710331284_hash_ratchet_encrypted_messages_key_idUpSql, - "1711389881_add_profile_showcase_community_grant.up.sql": _1711389881_add_profile_showcase_community_grantUpSql, - "1711937186_add_contact_customization_color.up.sql": _1711937186_add_contact_customization_colorUpSql, - "1712745141_hash_ratchet_encrypted_messages_key_id.up.sql": _1712745141_hash_ratchet_encrypted_messages_key_idUpSql, - "1712905223_add_parity_to_message_segments.up.sql": _1712905223_add_parity_to_message_segmentsUpSql, - "README.md": readmeMd, - "doc.go": docGo, -} + "000001_init.down.db.sql": _000001_initDownDbSql, -// AssetDebug is true if the assets were built with the debug flag enabled. -const AssetDebug = false + "000001_init.up.db.sql": _000001_initUpDbSql, + + "000002_add_last_ens_clock_value.up.sql": _000002_add_last_ens_clock_valueUpSql, + + "1586358095_add_replace.up.sql": _1586358095_add_replaceUpSql, + + "1588665364_add_image_data.up.sql": _1588665364_add_image_dataUpSql, + + "1589365189_add_pow_target.up.sql": _1589365189_add_pow_targetUpSql, + + "1591277220_add_index_messages.up.sql": _1591277220_add_index_messagesUpSql, + + "1593087212_add_mute_chat_and_raw_message_fields.up.sql": _1593087212_add_mute_chat_and_raw_message_fieldsUpSql, + + "1595862781_add_audio_data.up.sql": _1595862781_add_audio_dataUpSql, + + "1595865249_create_emoji_reactions_table.up.sql": _1595865249_create_emoji_reactions_tableUpSql, + + "1596805115_create_group_chat_invitations_table.up.sql": _1596805115_create_group_chat_invitations_tableUpSql, + + "1597322655_add_invitation_admin_chat_field.up.sql": _1597322655_add_invitation_admin_chat_fieldUpSql, + + "1597757544_add_nickname.up.sql": _1597757544_add_nicknameUpSql, + + "1598955122_add_mentions.up.sql": _1598955122_add_mentionsUpSql, + + "1599641390_add_emoji_reactions_index.up.sql": _1599641390_add_emoji_reactions_indexUpSql, + + "1599720851_add_seen_index_remove_long_messages.up.sql": _1599720851_add_seen_index_remove_long_messagesUpSql, + + "1603198582_add_profile_chat_field.up.sql": _1603198582_add_profile_chat_fieldUpSql, + + "1603816533_add_links.up.sql": _1603816533_add_linksUpSql, + + "1603888149_create_chat_identity_last_published_table.up.sql": _1603888149_create_chat_identity_last_published_tableUpSql, + + "1605075346_add_communities.up.sql": _1605075346_add_communitiesUpSql, + + "1610117927_add_message_cache.up.sql": _1610117927_add_message_cacheUpSql, + + "1610959908_add_dont_wrap_to_raw_messages.up.sql": _1610959908_add_dont_wrap_to_raw_messagesUpSql, + + "1610960912_add_send_on_personal_topic.up.sql": _1610960912_add_send_on_personal_topicUpSql, + + "1612870480_add_datasync_id.up.sql": _1612870480_add_datasync_idUpSql, + + "1614152139_add_communities_request_to_join.up.sql": _1614152139_add_communities_request_to_joinUpSql, + + "1615374373_add_confirmations.up.sql": _1615374373_add_confirmationsUpSql, + + "1617694931_add_notification_center.up.sql": _1617694931_add_notification_centerUpSql, + + "1618923660_create_pin_messages.up.sql": _1618923660_create_pin_messagesUpSql, + + "1619094007_add_joined_chat_field.up.sql": _1619094007_add_joined_chat_fieldUpSql, + + "1619099821_add_last_synced_field.up.sql": _1619099821_add_last_synced_fieldUpSql, + + "1621933219_add_mentioned.up.sql": _1621933219_add_mentionedUpSql, + + "1622010048_add_unviewed_mentions_count.up.sql": _1622010048_add_unviewed_mentions_countUpSql, + + "1622061278_add_message_activity_center_notification_field.up.sql": _1622061278_add_message_activity_center_notification_fieldUpSql, + + "1622464518_set_synced_to_from.up.sql": _1622464518_set_synced_to_fromUpSql, + + "1622464519_add_chat_description.up.sql": _1622464519_add_chat_descriptionUpSql, + + "1622622253_add_pinned_by_to_pin_messages.up.sql": _1622622253_add_pinned_by_to_pin_messagesUpSql, + + "1623938329_add_author_activity_center_notification_field.up.sql": _1623938329_add_author_activity_center_notification_fieldUpSql, + + "1623938330_add_edit_messages.up.sql": _1623938330_add_edit_messagesUpSql, + + "1624978434_add_muted_community.up.sql": _1624978434_add_muted_communityUpSql, + + "1625018910_add_repply_message_activity_center_notification_field.up.sql": _1625018910_add_repply_message_activity_center_notification_fieldUpSql, + + "1625762506_add_deleted_messages.up.sql": _1625762506_add_deleted_messagesUpSql, + + "1627388946_add_communities_synced_at.up.sql": _1627388946_add_communities_synced_atUpSql, + + "1628280060_create-usermessages-index.sql": _1628280060_createUsermessagesIndexSql, + + "1632303896_modify_contacts_table.up.sql": _1632303896_modify_contacts_tableUpSql, + + "1633349838_add_emoji_column_in_chats.up.sql": _1633349838_add_emoji_column_in_chatsUpSql, + + "1634831235_add_highlight_column_in_chats.up.sql": _1634831235_add_highlight_column_in_chatsUpSql, + + "1634896007_add_last_updated_locally_and_removed.up.sql": _1634896007_add_last_updated_locally_and_removedUpSql, + + "1635840039_add_clock_read_at_column_in_chats.up.sql": _1635840039_add_clock_read_at_column_in_chatsUpSql, + + "1637852321_add_received_invitation_admin_column_in_chats.up.sql": _1637852321_add_received_invitation_admin_column_in_chatsUpSql, + + "1645034601_display_name.up.sql": _1645034601_display_nameUpSql, + + "1645034602_add_mutual_contact_request.up.sql": _1645034602_add_mutual_contact_requestUpSql, + + "1650373957_add_contact_request_state.up.sql": _1650373957_add_contact_request_stateUpSql, + + "1656958989_contact_verification.up.sql": _1656958989_contact_verificationUpSql, + + "1658236268_add_discord_message_authors_table.up.sql": _1658236268_add_discord_message_authors_tableUpSql, + + "1659619997_add_discord_messages_table.up.sql": _1659619997_add_discord_messages_tableUpSql, + + "1660226788_create_chat_identity_social_links.up.sql": _1660226788_create_chat_identity_social_linksUpSql, + + "1660226789_add_walletconnectsessions_table.up.sql": _1660226789_add_walletconnectsessions_tableUpSql, + + "1661242854_add_communities_requests_to_leave.up.sql": _1661242854_add_communities_requests_to_leaveUpSql, + + "1662044232_add_chat_image.up.sql": _1662044232_add_chat_imageUpSql, + + "1662106895_add_chat_first_message_timestamp.up.sql": _1662106895_add_chat_first_message_timestampUpSql, + + "1662723928_add_discord_author_image_fields.up.sql": _1662723928_add_discord_author_image_fieldsUpSql, + + "1664195977_add_deleted_for_mes.up.sql": _1664195977_add_deleted_for_mesUpSql, + + "1664367420_add_discord_attachments_table.up.sql": _1664367420_add_discord_attachments_tableUpSql, + + "1665079662_add_spectated_column_in_communities.up.sql": _1665079662_add_spectated_column_in_communitiesUpSql, + + "1665479047_add_community_id_in_notifications.up.sql": _1665479047_add_community_id_in_notificationsUpSql, + + "1665484435_add_encrypted_messages.up.sql": _1665484435_add_encrypted_messagesUpSql, + + "1665560200_add_contact_verification_individual.up.sql": _1665560200_add_contact_verification_individualUpSql, + + "1670921937_add_album_id.up.sql": _1670921937_add_album_idUpSql, + + "1673373000_add_replied.up.sql": _1673373000_add_repliedUpSql, + + "1673428910_add_image_width_height.up.sql": _1673428910_add_image_width_heightUpSql, + + "1674210659_add_contact_request_local_clock.up.sql": _1674210659_add_contact_request_local_clockUpSql, + + "1675212323_add_deleted_by.up.sql": _1675212323_add_deleted_byUpSql, + + "1675247084_add_activity_center_states.up.sql": _1675247084_add_activity_center_statesUpSql, + + "1675272329_fix_protocol_migration.up.sql": _1675272329_fix_protocol_migrationUpSql, + + "1676998418_fix_activity_center_migration.up.sql": _1676998418_fix_activity_center_migrationUpSql, + + "1677278861_add_deleted_column_to_activity_center_notifications_table.up.sql": _1677278861_add_deleted_column_to_activity_center_notifications_tableUpSql, + + "1677486338_add_community_tokens_table.up.sql": _1677486338_add_community_tokens_tableUpSql, + + "1678292329_add_collapsed_categories.up.sql": _1678292329_add_collapsed_categoriesUpSql, + + "1678800760_add_index_to_raw_messages.up.sql": _1678800760_add_index_to_raw_messagesUpSql, + + "1678877478_add_communities_requests_to_join_revealed_addresses_table.up.sql": _1678877478_add_communities_requests_to_join_revealed_addresses_tableUpSql, + + "1679326850_add_community_token_owners.up.sql": _1679326850_add_community_token_ownersUpSql, + + "1680011500_add_album_images_count.up.sql": _1680011500_add_album_images_countUpSql, + + "1680114896_add_index_on_album_id.up.sql": _1680114896_add_index_on_album_idUpSql, + + "1681655289_add_mute_till.up.sql": _1681655289_add_mute_tillUpSql, + + "1681934966_add_index_response_to.up.sql": _1681934966_add_index_response_toUpSql, + + "1682528339_add_index_user_messages_unseen.up.sql": _1682528339_add_index_user_messages_unseenUpSql, + + "1683707289_recreate_deleted_for_mes.up.sql": _1683707289_recreate_deleted_for_mesUpSql, + + "1683725607_mark_discord_messages_as_seen.up.sql": _1683725607_mark_discord_messages_as_seenUpSql, + + "1684174617_add_url_previews_to_user_messages.up.sql": _1684174617_add_url_previews_to_user_messagesUpSql, + + "1684175608_add_token_balances.up.sql": _1684175608_add_token_balancesUpSql, + + "1684979808_sync_activity_center_notifications.up.sql": _1684979808_sync_activity_center_notificationsUpSql, + + "1685383829_add_communities_mute_till.up.sql": _1685383829_add_communities_mute_tillUpSql, + + "1685964183_add_chainids_to_revealed_addresses.up.sql": _1685964183_add_chainids_to_revealed_addressesUpSql, + + "1687370421_add_communities_muted_till_new.up.sql": _1687370421_add_communities_muted_till_newUpSql, + + "1687416607_add_communities_check_channel_permission_responses_table.up.sql": _1687416607_add_communities_check_channel_permission_responses_tableUpSql, + + "1687856939_add_community_tokens_decimals.up.sql": _1687856939_add_community_tokens_decimalsUpSql, + + "1687959987_modify_community_tokens_supply_as_string.up.sql": _1687959987_modify_community_tokens_supply_as_stringUpSql, + + "1689258900_add_airdrop_address_to_revealed_addresses.up.sql": _1689258900_add_airdrop_address_to_revealed_addressesUpSql, + + "1689266326_create_communities_events_table.up.sql": _1689266326_create_communities_events_tableUpSql, + + "1689931300_add_community_tokens_deployer_and_priv_level.up.sql": _1689931300_add_community_tokens_deployer_and_priv_levelUpSql, + + "1693311881_add_unfurled_links_to_message_edits.up.sql": _1693311881_add_unfurled_links_to_message_editsUpSql, + + "1693311981_community_shard.up.sql": _1693311981_community_shardUpSql, + + "1695331492_add_status_link_previews.up.sql": _1695331492_add_status_link_previewsUpSql, + + "1695918296_add_validated_at.up.sql": _1695918296_add_validated_atUpSql, + + "1697699419_community_control_node_sync.up.sql": _1697699419_community_control_node_syncUpSql, + + "1698137561_add_profile_showcase_tables.up.sql": _1698137561_add_profile_showcase_tablesUpSql, + + "1698137562_fix_encryption_key_id.up.sql": _1698137562_fix_encryption_key_idUpSql, + + "1698414646_add_padding.up.sql": _1698414646_add_paddingUpSql, + + "1698746210_add_signature_to_revealed_addresses.up.sql": _1698746210_add_signature_to_revealed_addressesUpSql, + + "1699041816_profile_showcase_contacts.up.sql": _1699041816_profile_showcase_contactsUpSql, + + "1699554099_message_segments.up.sql": _1699554099_message_segmentsUpSql, + + "1700044186_message_segments_timestamp.up.sql": _1700044186_message_segments_timestampUpSql, + + "1700044187_curated_communities.up.sql": _1700044187_curated_communitiesUpSql, + + "1700820989_add_resend_automatically_index.up.sql": _1700820989_add_resend_automatically_indexUpSql, + + "1702996953_add_communities_shards_table.up.sql": _1702996953_add_communities_shards_tableUpSql, + + "1704489636_add_album_images.up.sql": _1704489636_add_album_imagesUpSql, + + "1704821941_add_joined_at_for_community.up.sql": _1704821941_add_joined_at_for_communityUpSql, + + "1704832511_add_last_opened_at_for_communities.up.sql": _1704832511_add_last_opened_at_for_communitiesUpSql, + + "1704832512_add_peersyncing.up.sql": _1704832512_add_peersyncingUpSql, + + "1706028033_profile_showcase_address_and_community.up.sql": _1706028033_profile_showcase_address_and_communityUpSql, + + "1706520870_add_bridge_messages_table.up.sql": _1706520870_add_bridge_messages_tableUpSql, + + "1706520871_add_community_description_cache.up.sql": _1706520871_add_community_description_cacheUpSql, + + "1707749393_add_community_grants.up.sql": _1707749393_add_community_grantsUpSql, + + "1707841194_add_profile_showcase_preferences.up.sql": _1707841194_add_profile_showcase_preferencesUpSql, + + "1708062699_activity_data.up.sql": _1708062699_activity_dataUpSql, + + "1708423707_applied_community_events.up.sql": _1708423707_applied_community_eventsUpSql, + + "1708440786_profile_showcase_social_links.up.sql": _1708440786_profile_showcase_social_linksUpSql, + + "1709805967_simplify_profile_showcase_preferences.up.sql": _1709805967_simplify_profile_showcase_preferencesUpSql, + + "1709828431_add_community_description_cache.up.sql": _1709828431_add_community_description_cacheUpSql, + + "1710331283_add_bio_to_contacts.up.sql": _1710331283_add_bio_to_contactsUpSql, + + "1710331284_hash_ratchet_encrypted_messages_key_id.up.sql": _1710331284_hash_ratchet_encrypted_messages_key_idUpSql, + + "1711389881_add_profile_showcase_community_grant.up.sql": _1711389881_add_profile_showcase_community_grantUpSql, + + "1711937186_add_contact_customization_color.up.sql": _1711937186_add_contact_customization_colorUpSql, + + "1712745141_hash_ratchet_encrypted_messages_key_id.up.sql": _1712745141_hash_ratchet_encrypted_messages_key_idUpSql, + + "1712905223_add_parity_to_message_segments.up.sql": _1712905223_add_parity_to_message_segmentsUpSql, + + "1713169458_update_raw_messages_with_resend_features.up.sql": _1713169458_update_raw_messages_with_resend_featuresUpSql, + + "README.md": readmeMd, + + "doc.go": docGo, +} // AssetDir returns the file names below a certain // directory embedded in the file by go-bindata. // For example if you run go-bindata on data/... and data contains the // following hierarchy: -// -// data/ -// foo.txt -// img/ -// a.png -// b.png -// +// data/ +// foo.txt +// img/ +// a.png +// b.png // then AssetDir("data") would return []string{"foo.txt", "img"}, // AssetDir("data/img") would return []string{"a.png", "b.png"}, // AssetDir("foo.txt") and AssetDir("notexist") would return an error, and @@ -3220,143 +3375,144 @@ type bintree struct { } var _bintree = &bintree{nil, map[string]*bintree{ - "000001_init.down.db.sql": {_000001_initDownDbSql, map[string]*bintree{}}, - "000001_init.up.db.sql": {_000001_initUpDbSql, map[string]*bintree{}}, - "000002_add_last_ens_clock_value.up.sql": {_000002_add_last_ens_clock_valueUpSql, map[string]*bintree{}}, - "1586358095_add_replace.up.sql": {_1586358095_add_replaceUpSql, map[string]*bintree{}}, - "1588665364_add_image_data.up.sql": {_1588665364_add_image_dataUpSql, map[string]*bintree{}}, - "1589365189_add_pow_target.up.sql": {_1589365189_add_pow_targetUpSql, map[string]*bintree{}}, - "1591277220_add_index_messages.up.sql": {_1591277220_add_index_messagesUpSql, map[string]*bintree{}}, - "1593087212_add_mute_chat_and_raw_message_fields.up.sql": {_1593087212_add_mute_chat_and_raw_message_fieldsUpSql, map[string]*bintree{}}, - "1595862781_add_audio_data.up.sql": {_1595862781_add_audio_dataUpSql, map[string]*bintree{}}, - "1595865249_create_emoji_reactions_table.up.sql": {_1595865249_create_emoji_reactions_tableUpSql, map[string]*bintree{}}, - "1596805115_create_group_chat_invitations_table.up.sql": {_1596805115_create_group_chat_invitations_tableUpSql, map[string]*bintree{}}, - "1597322655_add_invitation_admin_chat_field.up.sql": {_1597322655_add_invitation_admin_chat_fieldUpSql, map[string]*bintree{}}, - "1597757544_add_nickname.up.sql": {_1597757544_add_nicknameUpSql, map[string]*bintree{}}, - "1598955122_add_mentions.up.sql": {_1598955122_add_mentionsUpSql, map[string]*bintree{}}, - "1599641390_add_emoji_reactions_index.up.sql": {_1599641390_add_emoji_reactions_indexUpSql, map[string]*bintree{}}, - "1599720851_add_seen_index_remove_long_messages.up.sql": {_1599720851_add_seen_index_remove_long_messagesUpSql, map[string]*bintree{}}, - "1603198582_add_profile_chat_field.up.sql": {_1603198582_add_profile_chat_fieldUpSql, map[string]*bintree{}}, - "1603816533_add_links.up.sql": {_1603816533_add_linksUpSql, map[string]*bintree{}}, - "1603888149_create_chat_identity_last_published_table.up.sql": {_1603888149_create_chat_identity_last_published_tableUpSql, map[string]*bintree{}}, - "1605075346_add_communities.up.sql": {_1605075346_add_communitiesUpSql, map[string]*bintree{}}, - "1610117927_add_message_cache.up.sql": {_1610117927_add_message_cacheUpSql, map[string]*bintree{}}, - "1610959908_add_dont_wrap_to_raw_messages.up.sql": {_1610959908_add_dont_wrap_to_raw_messagesUpSql, map[string]*bintree{}}, - "1610960912_add_send_on_personal_topic.up.sql": {_1610960912_add_send_on_personal_topicUpSql, map[string]*bintree{}}, - "1612870480_add_datasync_id.up.sql": {_1612870480_add_datasync_idUpSql, map[string]*bintree{}}, - "1614152139_add_communities_request_to_join.up.sql": {_1614152139_add_communities_request_to_joinUpSql, map[string]*bintree{}}, - "1615374373_add_confirmations.up.sql": {_1615374373_add_confirmationsUpSql, map[string]*bintree{}}, - "1617694931_add_notification_center.up.sql": {_1617694931_add_notification_centerUpSql, map[string]*bintree{}}, - "1618923660_create_pin_messages.up.sql": {_1618923660_create_pin_messagesUpSql, map[string]*bintree{}}, - "1619094007_add_joined_chat_field.up.sql": {_1619094007_add_joined_chat_fieldUpSql, map[string]*bintree{}}, - "1619099821_add_last_synced_field.up.sql": {_1619099821_add_last_synced_fieldUpSql, map[string]*bintree{}}, - "1621933219_add_mentioned.up.sql": {_1621933219_add_mentionedUpSql, map[string]*bintree{}}, - "1622010048_add_unviewed_mentions_count.up.sql": {_1622010048_add_unviewed_mentions_countUpSql, map[string]*bintree{}}, - "1622061278_add_message_activity_center_notification_field.up.sql": {_1622061278_add_message_activity_center_notification_fieldUpSql, map[string]*bintree{}}, - "1622464518_set_synced_to_from.up.sql": {_1622464518_set_synced_to_fromUpSql, map[string]*bintree{}}, - "1622464519_add_chat_description.up.sql": {_1622464519_add_chat_descriptionUpSql, map[string]*bintree{}}, - "1622622253_add_pinned_by_to_pin_messages.up.sql": {_1622622253_add_pinned_by_to_pin_messagesUpSql, map[string]*bintree{}}, - "1623938329_add_author_activity_center_notification_field.up.sql": {_1623938329_add_author_activity_center_notification_fieldUpSql, map[string]*bintree{}}, - "1623938330_add_edit_messages.up.sql": {_1623938330_add_edit_messagesUpSql, map[string]*bintree{}}, - "1624978434_add_muted_community.up.sql": {_1624978434_add_muted_communityUpSql, map[string]*bintree{}}, - "1625018910_add_repply_message_activity_center_notification_field.up.sql": {_1625018910_add_repply_message_activity_center_notification_fieldUpSql, map[string]*bintree{}}, - "1625762506_add_deleted_messages.up.sql": {_1625762506_add_deleted_messagesUpSql, map[string]*bintree{}}, - "1627388946_add_communities_synced_at.up.sql": {_1627388946_add_communities_synced_atUpSql, map[string]*bintree{}}, - "1628280060_create-usermessages-index.sql": {_1628280060_createUsermessagesIndexSql, map[string]*bintree{}}, - "1632303896_modify_contacts_table.up.sql": {_1632303896_modify_contacts_tableUpSql, map[string]*bintree{}}, - "1633349838_add_emoji_column_in_chats.up.sql": {_1633349838_add_emoji_column_in_chatsUpSql, map[string]*bintree{}}, - "1634831235_add_highlight_column_in_chats.up.sql": {_1634831235_add_highlight_column_in_chatsUpSql, map[string]*bintree{}}, - "1634896007_add_last_updated_locally_and_removed.up.sql": {_1634896007_add_last_updated_locally_and_removedUpSql, map[string]*bintree{}}, - "1635840039_add_clock_read_at_column_in_chats.up.sql": {_1635840039_add_clock_read_at_column_in_chatsUpSql, map[string]*bintree{}}, - "1637852321_add_received_invitation_admin_column_in_chats.up.sql": {_1637852321_add_received_invitation_admin_column_in_chatsUpSql, map[string]*bintree{}}, - "1645034601_display_name.up.sql": {_1645034601_display_nameUpSql, map[string]*bintree{}}, - "1645034602_add_mutual_contact_request.up.sql": {_1645034602_add_mutual_contact_requestUpSql, map[string]*bintree{}}, - "1650373957_add_contact_request_state.up.sql": {_1650373957_add_contact_request_stateUpSql, map[string]*bintree{}}, - "1656958989_contact_verification.up.sql": {_1656958989_contact_verificationUpSql, map[string]*bintree{}}, - "1658236268_add_discord_message_authors_table.up.sql": {_1658236268_add_discord_message_authors_tableUpSql, map[string]*bintree{}}, - "1659619997_add_discord_messages_table.up.sql": {_1659619997_add_discord_messages_tableUpSql, map[string]*bintree{}}, - "1660226788_create_chat_identity_social_links.up.sql": {_1660226788_create_chat_identity_social_linksUpSql, map[string]*bintree{}}, - "1660226789_add_walletconnectsessions_table.up.sql": {_1660226789_add_walletconnectsessions_tableUpSql, map[string]*bintree{}}, - "1661242854_add_communities_requests_to_leave.up.sql": {_1661242854_add_communities_requests_to_leaveUpSql, map[string]*bintree{}}, - "1662044232_add_chat_image.up.sql": {_1662044232_add_chat_imageUpSql, map[string]*bintree{}}, - "1662106895_add_chat_first_message_timestamp.up.sql": {_1662106895_add_chat_first_message_timestampUpSql, map[string]*bintree{}}, - "1662723928_add_discord_author_image_fields.up.sql": {_1662723928_add_discord_author_image_fieldsUpSql, map[string]*bintree{}}, - "1664195977_add_deleted_for_mes.up.sql": {_1664195977_add_deleted_for_mesUpSql, map[string]*bintree{}}, - "1664367420_add_discord_attachments_table.up.sql": {_1664367420_add_discord_attachments_tableUpSql, map[string]*bintree{}}, - "1665079662_add_spectated_column_in_communities.up.sql": {_1665079662_add_spectated_column_in_communitiesUpSql, map[string]*bintree{}}, - "1665479047_add_community_id_in_notifications.up.sql": {_1665479047_add_community_id_in_notificationsUpSql, map[string]*bintree{}}, - "1665484435_add_encrypted_messages.up.sql": {_1665484435_add_encrypted_messagesUpSql, map[string]*bintree{}}, - "1665560200_add_contact_verification_individual.up.sql": {_1665560200_add_contact_verification_individualUpSql, map[string]*bintree{}}, - "1670921937_add_album_id.up.sql": {_1670921937_add_album_idUpSql, map[string]*bintree{}}, - "1673373000_add_replied.up.sql": {_1673373000_add_repliedUpSql, map[string]*bintree{}}, - "1673428910_add_image_width_height.up.sql": {_1673428910_add_image_width_heightUpSql, map[string]*bintree{}}, - "1674210659_add_contact_request_local_clock.up.sql": {_1674210659_add_contact_request_local_clockUpSql, map[string]*bintree{}}, - "1675212323_add_deleted_by.up.sql": {_1675212323_add_deleted_byUpSql, map[string]*bintree{}}, - "1675247084_add_activity_center_states.up.sql": {_1675247084_add_activity_center_statesUpSql, map[string]*bintree{}}, - "1675272329_fix_protocol_migration.up.sql": {_1675272329_fix_protocol_migrationUpSql, map[string]*bintree{}}, - "1676998418_fix_activity_center_migration.up.sql": {_1676998418_fix_activity_center_migrationUpSql, map[string]*bintree{}}, - "1677278861_add_deleted_column_to_activity_center_notifications_table.up.sql": {_1677278861_add_deleted_column_to_activity_center_notifications_tableUpSql, map[string]*bintree{}}, - "1677486338_add_community_tokens_table.up.sql": {_1677486338_add_community_tokens_tableUpSql, map[string]*bintree{}}, - "1678292329_add_collapsed_categories.up.sql": {_1678292329_add_collapsed_categoriesUpSql, map[string]*bintree{}}, - "1678800760_add_index_to_raw_messages.up.sql": {_1678800760_add_index_to_raw_messagesUpSql, map[string]*bintree{}}, - "1678877478_add_communities_requests_to_join_revealed_addresses_table.up.sql": {_1678877478_add_communities_requests_to_join_revealed_addresses_tableUpSql, map[string]*bintree{}}, - "1679326850_add_community_token_owners.up.sql": {_1679326850_add_community_token_ownersUpSql, map[string]*bintree{}}, - "1680011500_add_album_images_count.up.sql": {_1680011500_add_album_images_countUpSql, map[string]*bintree{}}, - "1680114896_add_index_on_album_id.up.sql": {_1680114896_add_index_on_album_idUpSql, map[string]*bintree{}}, - "1681655289_add_mute_till.up.sql": {_1681655289_add_mute_tillUpSql, map[string]*bintree{}}, - "1681934966_add_index_response_to.up.sql": {_1681934966_add_index_response_toUpSql, map[string]*bintree{}}, - "1682528339_add_index_user_messages_unseen.up.sql": {_1682528339_add_index_user_messages_unseenUpSql, map[string]*bintree{}}, - "1683707289_recreate_deleted_for_mes.up.sql": {_1683707289_recreate_deleted_for_mesUpSql, map[string]*bintree{}}, - "1683725607_mark_discord_messages_as_seen.up.sql": {_1683725607_mark_discord_messages_as_seenUpSql, map[string]*bintree{}}, - "1684174617_add_url_previews_to_user_messages.up.sql": {_1684174617_add_url_previews_to_user_messagesUpSql, map[string]*bintree{}}, - "1684175608_add_token_balances.up.sql": {_1684175608_add_token_balancesUpSql, map[string]*bintree{}}, - "1684979808_sync_activity_center_notifications.up.sql": {_1684979808_sync_activity_center_notificationsUpSql, map[string]*bintree{}}, - "1685383829_add_communities_mute_till.up.sql": {_1685383829_add_communities_mute_tillUpSql, map[string]*bintree{}}, - "1685964183_add_chainids_to_revealed_addresses.up.sql": {_1685964183_add_chainids_to_revealed_addressesUpSql, map[string]*bintree{}}, - "1687370421_add_communities_muted_till_new.up.sql": {_1687370421_add_communities_muted_till_newUpSql, map[string]*bintree{}}, - "1687416607_add_communities_check_channel_permission_responses_table.up.sql": {_1687416607_add_communities_check_channel_permission_responses_tableUpSql, map[string]*bintree{}}, - "1687856939_add_community_tokens_decimals.up.sql": {_1687856939_add_community_tokens_decimalsUpSql, map[string]*bintree{}}, - "1687959987_modify_community_tokens_supply_as_string.up.sql": {_1687959987_modify_community_tokens_supply_as_stringUpSql, map[string]*bintree{}}, - "1689258900_add_airdrop_address_to_revealed_addresses.up.sql": {_1689258900_add_airdrop_address_to_revealed_addressesUpSql, map[string]*bintree{}}, - "1689266326_create_communities_events_table.up.sql": {_1689266326_create_communities_events_tableUpSql, map[string]*bintree{}}, - "1689931300_add_community_tokens_deployer_and_priv_level.up.sql": {_1689931300_add_community_tokens_deployer_and_priv_levelUpSql, map[string]*bintree{}}, - "1693311881_add_unfurled_links_to_message_edits.up.sql": {_1693311881_add_unfurled_links_to_message_editsUpSql, map[string]*bintree{}}, - "1693311981_community_shard.up.sql": {_1693311981_community_shardUpSql, map[string]*bintree{}}, - "1695331492_add_status_link_previews.up.sql": {_1695331492_add_status_link_previewsUpSql, map[string]*bintree{}}, - "1695918296_add_validated_at.up.sql": {_1695918296_add_validated_atUpSql, map[string]*bintree{}}, - "1697699419_community_control_node_sync.up.sql": {_1697699419_community_control_node_syncUpSql, map[string]*bintree{}}, - "1698137561_add_profile_showcase_tables.up.sql": {_1698137561_add_profile_showcase_tablesUpSql, map[string]*bintree{}}, - "1698137562_fix_encryption_key_id.up.sql": {_1698137562_fix_encryption_key_idUpSql, map[string]*bintree{}}, - "1698414646_add_padding.up.sql": {_1698414646_add_paddingUpSql, map[string]*bintree{}}, - "1698746210_add_signature_to_revealed_addresses.up.sql": {_1698746210_add_signature_to_revealed_addressesUpSql, map[string]*bintree{}}, - "1699041816_profile_showcase_contacts.up.sql": {_1699041816_profile_showcase_contactsUpSql, map[string]*bintree{}}, - "1699554099_message_segments.up.sql": {_1699554099_message_segmentsUpSql, map[string]*bintree{}}, - "1700044186_message_segments_timestamp.up.sql": {_1700044186_message_segments_timestampUpSql, map[string]*bintree{}}, - "1700044187_curated_communities.up.sql": {_1700044187_curated_communitiesUpSql, map[string]*bintree{}}, - "1700820989_add_resend_automatically_index.up.sql": {_1700820989_add_resend_automatically_indexUpSql, map[string]*bintree{}}, - "1702996953_add_communities_shards_table.up.sql": {_1702996953_add_communities_shards_tableUpSql, map[string]*bintree{}}, - "1704489636_add_album_images.up.sql": {_1704489636_add_album_imagesUpSql, map[string]*bintree{}}, - "1704821941_add_joined_at_for_community.up.sql": {_1704821941_add_joined_at_for_communityUpSql, map[string]*bintree{}}, - "1704832511_add_last_opened_at_for_communities.up.sql": {_1704832511_add_last_opened_at_for_communitiesUpSql, map[string]*bintree{}}, - "1704832512_add_peersyncing.up.sql": {_1704832512_add_peersyncingUpSql, map[string]*bintree{}}, - "1706028033_profile_showcase_address_and_community.up.sql": {_1706028033_profile_showcase_address_and_communityUpSql, map[string]*bintree{}}, - "1706520870_add_bridge_messages_table.up.sql": {_1706520870_add_bridge_messages_tableUpSql, map[string]*bintree{}}, - "1706520871_add_community_description_cache.up.sql": {_1706520871_add_community_description_cacheUpSql, map[string]*bintree{}}, - "1707749393_add_community_grants.up.sql": {_1707749393_add_community_grantsUpSql, map[string]*bintree{}}, - "1707841194_add_profile_showcase_preferences.up.sql": {_1707841194_add_profile_showcase_preferencesUpSql, map[string]*bintree{}}, - "1708062699_activity_data.up.sql": {_1708062699_activity_dataUpSql, map[string]*bintree{}}, - "1708423707_applied_community_events.up.sql": {_1708423707_applied_community_eventsUpSql, map[string]*bintree{}}, - "1708440786_profile_showcase_social_links.up.sql": {_1708440786_profile_showcase_social_linksUpSql, map[string]*bintree{}}, - "1709805967_simplify_profile_showcase_preferences.up.sql": {_1709805967_simplify_profile_showcase_preferencesUpSql, map[string]*bintree{}}, - "1709828431_add_community_description_cache.up.sql": {_1709828431_add_community_description_cacheUpSql, map[string]*bintree{}}, - "1710331283_add_bio_to_contacts.up.sql": {_1710331283_add_bio_to_contactsUpSql, map[string]*bintree{}}, - "1710331284_hash_ratchet_encrypted_messages_key_id.up.sql": {_1710331284_hash_ratchet_encrypted_messages_key_idUpSql, map[string]*bintree{}}, - "1711389881_add_profile_showcase_community_grant.up.sql": {_1711389881_add_profile_showcase_community_grantUpSql, map[string]*bintree{}}, - "1711937186_add_contact_customization_color.up.sql": {_1711937186_add_contact_customization_colorUpSql, map[string]*bintree{}}, - "1712745141_hash_ratchet_encrypted_messages_key_id.up.sql": {_1712745141_hash_ratchet_encrypted_messages_key_idUpSql, map[string]*bintree{}}, - "1712905223_add_parity_to_message_segments.up.sql": {_1712905223_add_parity_to_message_segmentsUpSql, map[string]*bintree{}}, - "README.md": {readmeMd, map[string]*bintree{}}, - "doc.go": {docGo, map[string]*bintree{}}, + "000001_init.down.db.sql": &bintree{_000001_initDownDbSql, map[string]*bintree{}}, + "000001_init.up.db.sql": &bintree{_000001_initUpDbSql, map[string]*bintree{}}, + "000002_add_last_ens_clock_value.up.sql": &bintree{_000002_add_last_ens_clock_valueUpSql, map[string]*bintree{}}, + "1586358095_add_replace.up.sql": &bintree{_1586358095_add_replaceUpSql, map[string]*bintree{}}, + "1588665364_add_image_data.up.sql": &bintree{_1588665364_add_image_dataUpSql, map[string]*bintree{}}, + "1589365189_add_pow_target.up.sql": &bintree{_1589365189_add_pow_targetUpSql, map[string]*bintree{}}, + "1591277220_add_index_messages.up.sql": &bintree{_1591277220_add_index_messagesUpSql, map[string]*bintree{}}, + "1593087212_add_mute_chat_and_raw_message_fields.up.sql": &bintree{_1593087212_add_mute_chat_and_raw_message_fieldsUpSql, map[string]*bintree{}}, + "1595862781_add_audio_data.up.sql": &bintree{_1595862781_add_audio_dataUpSql, map[string]*bintree{}}, + "1595865249_create_emoji_reactions_table.up.sql": &bintree{_1595865249_create_emoji_reactions_tableUpSql, map[string]*bintree{}}, + "1596805115_create_group_chat_invitations_table.up.sql": &bintree{_1596805115_create_group_chat_invitations_tableUpSql, map[string]*bintree{}}, + "1597322655_add_invitation_admin_chat_field.up.sql": &bintree{_1597322655_add_invitation_admin_chat_fieldUpSql, map[string]*bintree{}}, + "1597757544_add_nickname.up.sql": &bintree{_1597757544_add_nicknameUpSql, map[string]*bintree{}}, + "1598955122_add_mentions.up.sql": &bintree{_1598955122_add_mentionsUpSql, map[string]*bintree{}}, + "1599641390_add_emoji_reactions_index.up.sql": &bintree{_1599641390_add_emoji_reactions_indexUpSql, map[string]*bintree{}}, + "1599720851_add_seen_index_remove_long_messages.up.sql": &bintree{_1599720851_add_seen_index_remove_long_messagesUpSql, map[string]*bintree{}}, + "1603198582_add_profile_chat_field.up.sql": &bintree{_1603198582_add_profile_chat_fieldUpSql, map[string]*bintree{}}, + "1603816533_add_links.up.sql": &bintree{_1603816533_add_linksUpSql, map[string]*bintree{}}, + "1603888149_create_chat_identity_last_published_table.up.sql": &bintree{_1603888149_create_chat_identity_last_published_tableUpSql, map[string]*bintree{}}, + "1605075346_add_communities.up.sql": &bintree{_1605075346_add_communitiesUpSql, map[string]*bintree{}}, + "1610117927_add_message_cache.up.sql": &bintree{_1610117927_add_message_cacheUpSql, map[string]*bintree{}}, + "1610959908_add_dont_wrap_to_raw_messages.up.sql": &bintree{_1610959908_add_dont_wrap_to_raw_messagesUpSql, map[string]*bintree{}}, + "1610960912_add_send_on_personal_topic.up.sql": &bintree{_1610960912_add_send_on_personal_topicUpSql, map[string]*bintree{}}, + "1612870480_add_datasync_id.up.sql": &bintree{_1612870480_add_datasync_idUpSql, map[string]*bintree{}}, + "1614152139_add_communities_request_to_join.up.sql": &bintree{_1614152139_add_communities_request_to_joinUpSql, map[string]*bintree{}}, + "1615374373_add_confirmations.up.sql": &bintree{_1615374373_add_confirmationsUpSql, map[string]*bintree{}}, + "1617694931_add_notification_center.up.sql": &bintree{_1617694931_add_notification_centerUpSql, map[string]*bintree{}}, + "1618923660_create_pin_messages.up.sql": &bintree{_1618923660_create_pin_messagesUpSql, map[string]*bintree{}}, + "1619094007_add_joined_chat_field.up.sql": &bintree{_1619094007_add_joined_chat_fieldUpSql, map[string]*bintree{}}, + "1619099821_add_last_synced_field.up.sql": &bintree{_1619099821_add_last_synced_fieldUpSql, map[string]*bintree{}}, + "1621933219_add_mentioned.up.sql": &bintree{_1621933219_add_mentionedUpSql, map[string]*bintree{}}, + "1622010048_add_unviewed_mentions_count.up.sql": &bintree{_1622010048_add_unviewed_mentions_countUpSql, map[string]*bintree{}}, + "1622061278_add_message_activity_center_notification_field.up.sql": &bintree{_1622061278_add_message_activity_center_notification_fieldUpSql, map[string]*bintree{}}, + "1622464518_set_synced_to_from.up.sql": &bintree{_1622464518_set_synced_to_fromUpSql, map[string]*bintree{}}, + "1622464519_add_chat_description.up.sql": &bintree{_1622464519_add_chat_descriptionUpSql, map[string]*bintree{}}, + "1622622253_add_pinned_by_to_pin_messages.up.sql": &bintree{_1622622253_add_pinned_by_to_pin_messagesUpSql, map[string]*bintree{}}, + "1623938329_add_author_activity_center_notification_field.up.sql": &bintree{_1623938329_add_author_activity_center_notification_fieldUpSql, map[string]*bintree{}}, + "1623938330_add_edit_messages.up.sql": &bintree{_1623938330_add_edit_messagesUpSql, map[string]*bintree{}}, + "1624978434_add_muted_community.up.sql": &bintree{_1624978434_add_muted_communityUpSql, map[string]*bintree{}}, + "1625018910_add_repply_message_activity_center_notification_field.up.sql": &bintree{_1625018910_add_repply_message_activity_center_notification_fieldUpSql, map[string]*bintree{}}, + "1625762506_add_deleted_messages.up.sql": &bintree{_1625762506_add_deleted_messagesUpSql, map[string]*bintree{}}, + "1627388946_add_communities_synced_at.up.sql": &bintree{_1627388946_add_communities_synced_atUpSql, map[string]*bintree{}}, + "1628280060_create-usermessages-index.sql": &bintree{_1628280060_createUsermessagesIndexSql, map[string]*bintree{}}, + "1632303896_modify_contacts_table.up.sql": &bintree{_1632303896_modify_contacts_tableUpSql, map[string]*bintree{}}, + "1633349838_add_emoji_column_in_chats.up.sql": &bintree{_1633349838_add_emoji_column_in_chatsUpSql, map[string]*bintree{}}, + "1634831235_add_highlight_column_in_chats.up.sql": &bintree{_1634831235_add_highlight_column_in_chatsUpSql, map[string]*bintree{}}, + "1634896007_add_last_updated_locally_and_removed.up.sql": &bintree{_1634896007_add_last_updated_locally_and_removedUpSql, map[string]*bintree{}}, + "1635840039_add_clock_read_at_column_in_chats.up.sql": &bintree{_1635840039_add_clock_read_at_column_in_chatsUpSql, map[string]*bintree{}}, + "1637852321_add_received_invitation_admin_column_in_chats.up.sql": &bintree{_1637852321_add_received_invitation_admin_column_in_chatsUpSql, map[string]*bintree{}}, + "1645034601_display_name.up.sql": &bintree{_1645034601_display_nameUpSql, map[string]*bintree{}}, + "1645034602_add_mutual_contact_request.up.sql": &bintree{_1645034602_add_mutual_contact_requestUpSql, map[string]*bintree{}}, + "1650373957_add_contact_request_state.up.sql": &bintree{_1650373957_add_contact_request_stateUpSql, map[string]*bintree{}}, + "1656958989_contact_verification.up.sql": &bintree{_1656958989_contact_verificationUpSql, map[string]*bintree{}}, + "1658236268_add_discord_message_authors_table.up.sql": &bintree{_1658236268_add_discord_message_authors_tableUpSql, map[string]*bintree{}}, + "1659619997_add_discord_messages_table.up.sql": &bintree{_1659619997_add_discord_messages_tableUpSql, map[string]*bintree{}}, + "1660226788_create_chat_identity_social_links.up.sql": &bintree{_1660226788_create_chat_identity_social_linksUpSql, map[string]*bintree{}}, + "1660226789_add_walletconnectsessions_table.up.sql": &bintree{_1660226789_add_walletconnectsessions_tableUpSql, map[string]*bintree{}}, + "1661242854_add_communities_requests_to_leave.up.sql": &bintree{_1661242854_add_communities_requests_to_leaveUpSql, map[string]*bintree{}}, + "1662044232_add_chat_image.up.sql": &bintree{_1662044232_add_chat_imageUpSql, map[string]*bintree{}}, + "1662106895_add_chat_first_message_timestamp.up.sql": &bintree{_1662106895_add_chat_first_message_timestampUpSql, map[string]*bintree{}}, + "1662723928_add_discord_author_image_fields.up.sql": &bintree{_1662723928_add_discord_author_image_fieldsUpSql, map[string]*bintree{}}, + "1664195977_add_deleted_for_mes.up.sql": &bintree{_1664195977_add_deleted_for_mesUpSql, map[string]*bintree{}}, + "1664367420_add_discord_attachments_table.up.sql": &bintree{_1664367420_add_discord_attachments_tableUpSql, map[string]*bintree{}}, + "1665079662_add_spectated_column_in_communities.up.sql": &bintree{_1665079662_add_spectated_column_in_communitiesUpSql, map[string]*bintree{}}, + "1665479047_add_community_id_in_notifications.up.sql": &bintree{_1665479047_add_community_id_in_notificationsUpSql, map[string]*bintree{}}, + "1665484435_add_encrypted_messages.up.sql": &bintree{_1665484435_add_encrypted_messagesUpSql, map[string]*bintree{}}, + "1665560200_add_contact_verification_individual.up.sql": &bintree{_1665560200_add_contact_verification_individualUpSql, map[string]*bintree{}}, + "1670921937_add_album_id.up.sql": &bintree{_1670921937_add_album_idUpSql, map[string]*bintree{}}, + "1673373000_add_replied.up.sql": &bintree{_1673373000_add_repliedUpSql, map[string]*bintree{}}, + "1673428910_add_image_width_height.up.sql": &bintree{_1673428910_add_image_width_heightUpSql, map[string]*bintree{}}, + "1674210659_add_contact_request_local_clock.up.sql": &bintree{_1674210659_add_contact_request_local_clockUpSql, map[string]*bintree{}}, + "1675212323_add_deleted_by.up.sql": &bintree{_1675212323_add_deleted_byUpSql, map[string]*bintree{}}, + "1675247084_add_activity_center_states.up.sql": &bintree{_1675247084_add_activity_center_statesUpSql, map[string]*bintree{}}, + "1675272329_fix_protocol_migration.up.sql": &bintree{_1675272329_fix_protocol_migrationUpSql, map[string]*bintree{}}, + "1676998418_fix_activity_center_migration.up.sql": &bintree{_1676998418_fix_activity_center_migrationUpSql, map[string]*bintree{}}, + "1677278861_add_deleted_column_to_activity_center_notifications_table.up.sql": &bintree{_1677278861_add_deleted_column_to_activity_center_notifications_tableUpSql, map[string]*bintree{}}, + "1677486338_add_community_tokens_table.up.sql": &bintree{_1677486338_add_community_tokens_tableUpSql, map[string]*bintree{}}, + "1678292329_add_collapsed_categories.up.sql": &bintree{_1678292329_add_collapsed_categoriesUpSql, map[string]*bintree{}}, + "1678800760_add_index_to_raw_messages.up.sql": &bintree{_1678800760_add_index_to_raw_messagesUpSql, map[string]*bintree{}}, + "1678877478_add_communities_requests_to_join_revealed_addresses_table.up.sql": &bintree{_1678877478_add_communities_requests_to_join_revealed_addresses_tableUpSql, map[string]*bintree{}}, + "1679326850_add_community_token_owners.up.sql": &bintree{_1679326850_add_community_token_ownersUpSql, map[string]*bintree{}}, + "1680011500_add_album_images_count.up.sql": &bintree{_1680011500_add_album_images_countUpSql, map[string]*bintree{}}, + "1680114896_add_index_on_album_id.up.sql": &bintree{_1680114896_add_index_on_album_idUpSql, map[string]*bintree{}}, + "1681655289_add_mute_till.up.sql": &bintree{_1681655289_add_mute_tillUpSql, map[string]*bintree{}}, + "1681934966_add_index_response_to.up.sql": &bintree{_1681934966_add_index_response_toUpSql, map[string]*bintree{}}, + "1682528339_add_index_user_messages_unseen.up.sql": &bintree{_1682528339_add_index_user_messages_unseenUpSql, map[string]*bintree{}}, + "1683707289_recreate_deleted_for_mes.up.sql": &bintree{_1683707289_recreate_deleted_for_mesUpSql, map[string]*bintree{}}, + "1683725607_mark_discord_messages_as_seen.up.sql": &bintree{_1683725607_mark_discord_messages_as_seenUpSql, map[string]*bintree{}}, + "1684174617_add_url_previews_to_user_messages.up.sql": &bintree{_1684174617_add_url_previews_to_user_messagesUpSql, map[string]*bintree{}}, + "1684175608_add_token_balances.up.sql": &bintree{_1684175608_add_token_balancesUpSql, map[string]*bintree{}}, + "1684979808_sync_activity_center_notifications.up.sql": &bintree{_1684979808_sync_activity_center_notificationsUpSql, map[string]*bintree{}}, + "1685383829_add_communities_mute_till.up.sql": &bintree{_1685383829_add_communities_mute_tillUpSql, map[string]*bintree{}}, + "1685964183_add_chainids_to_revealed_addresses.up.sql": &bintree{_1685964183_add_chainids_to_revealed_addressesUpSql, map[string]*bintree{}}, + "1687370421_add_communities_muted_till_new.up.sql": &bintree{_1687370421_add_communities_muted_till_newUpSql, map[string]*bintree{}}, + "1687416607_add_communities_check_channel_permission_responses_table.up.sql": &bintree{_1687416607_add_communities_check_channel_permission_responses_tableUpSql, map[string]*bintree{}}, + "1687856939_add_community_tokens_decimals.up.sql": &bintree{_1687856939_add_community_tokens_decimalsUpSql, map[string]*bintree{}}, + "1687959987_modify_community_tokens_supply_as_string.up.sql": &bintree{_1687959987_modify_community_tokens_supply_as_stringUpSql, map[string]*bintree{}}, + "1689258900_add_airdrop_address_to_revealed_addresses.up.sql": &bintree{_1689258900_add_airdrop_address_to_revealed_addressesUpSql, map[string]*bintree{}}, + "1689266326_create_communities_events_table.up.sql": &bintree{_1689266326_create_communities_events_tableUpSql, map[string]*bintree{}}, + "1689931300_add_community_tokens_deployer_and_priv_level.up.sql": &bintree{_1689931300_add_community_tokens_deployer_and_priv_levelUpSql, map[string]*bintree{}}, + "1693311881_add_unfurled_links_to_message_edits.up.sql": &bintree{_1693311881_add_unfurled_links_to_message_editsUpSql, map[string]*bintree{}}, + "1693311981_community_shard.up.sql": &bintree{_1693311981_community_shardUpSql, map[string]*bintree{}}, + "1695331492_add_status_link_previews.up.sql": &bintree{_1695331492_add_status_link_previewsUpSql, map[string]*bintree{}}, + "1695918296_add_validated_at.up.sql": &bintree{_1695918296_add_validated_atUpSql, map[string]*bintree{}}, + "1697699419_community_control_node_sync.up.sql": &bintree{_1697699419_community_control_node_syncUpSql, map[string]*bintree{}}, + "1698137561_add_profile_showcase_tables.up.sql": &bintree{_1698137561_add_profile_showcase_tablesUpSql, map[string]*bintree{}}, + "1698137562_fix_encryption_key_id.up.sql": &bintree{_1698137562_fix_encryption_key_idUpSql, map[string]*bintree{}}, + "1698414646_add_padding.up.sql": &bintree{_1698414646_add_paddingUpSql, map[string]*bintree{}}, + "1698746210_add_signature_to_revealed_addresses.up.sql": &bintree{_1698746210_add_signature_to_revealed_addressesUpSql, map[string]*bintree{}}, + "1699041816_profile_showcase_contacts.up.sql": &bintree{_1699041816_profile_showcase_contactsUpSql, map[string]*bintree{}}, + "1699554099_message_segments.up.sql": &bintree{_1699554099_message_segmentsUpSql, map[string]*bintree{}}, + "1700044186_message_segments_timestamp.up.sql": &bintree{_1700044186_message_segments_timestampUpSql, map[string]*bintree{}}, + "1700044187_curated_communities.up.sql": &bintree{_1700044187_curated_communitiesUpSql, map[string]*bintree{}}, + "1700820989_add_resend_automatically_index.up.sql": &bintree{_1700820989_add_resend_automatically_indexUpSql, map[string]*bintree{}}, + "1702996953_add_communities_shards_table.up.sql": &bintree{_1702996953_add_communities_shards_tableUpSql, map[string]*bintree{}}, + "1704489636_add_album_images.up.sql": &bintree{_1704489636_add_album_imagesUpSql, map[string]*bintree{}}, + "1704821941_add_joined_at_for_community.up.sql": &bintree{_1704821941_add_joined_at_for_communityUpSql, map[string]*bintree{}}, + "1704832511_add_last_opened_at_for_communities.up.sql": &bintree{_1704832511_add_last_opened_at_for_communitiesUpSql, map[string]*bintree{}}, + "1704832512_add_peersyncing.up.sql": &bintree{_1704832512_add_peersyncingUpSql, map[string]*bintree{}}, + "1706028033_profile_showcase_address_and_community.up.sql": &bintree{_1706028033_profile_showcase_address_and_communityUpSql, map[string]*bintree{}}, + "1706520870_add_bridge_messages_table.up.sql": &bintree{_1706520870_add_bridge_messages_tableUpSql, map[string]*bintree{}}, + "1706520871_add_community_description_cache.up.sql": &bintree{_1706520871_add_community_description_cacheUpSql, map[string]*bintree{}}, + "1707749393_add_community_grants.up.sql": &bintree{_1707749393_add_community_grantsUpSql, map[string]*bintree{}}, + "1707841194_add_profile_showcase_preferences.up.sql": &bintree{_1707841194_add_profile_showcase_preferencesUpSql, map[string]*bintree{}}, + "1708062699_activity_data.up.sql": &bintree{_1708062699_activity_dataUpSql, map[string]*bintree{}}, + "1708423707_applied_community_events.up.sql": &bintree{_1708423707_applied_community_eventsUpSql, map[string]*bintree{}}, + "1708440786_profile_showcase_social_links.up.sql": &bintree{_1708440786_profile_showcase_social_linksUpSql, map[string]*bintree{}}, + "1709805967_simplify_profile_showcase_preferences.up.sql": &bintree{_1709805967_simplify_profile_showcase_preferencesUpSql, map[string]*bintree{}}, + "1709828431_add_community_description_cache.up.sql": &bintree{_1709828431_add_community_description_cacheUpSql, map[string]*bintree{}}, + "1710331283_add_bio_to_contacts.up.sql": &bintree{_1710331283_add_bio_to_contactsUpSql, map[string]*bintree{}}, + "1710331284_hash_ratchet_encrypted_messages_key_id.up.sql": &bintree{_1710331284_hash_ratchet_encrypted_messages_key_idUpSql, map[string]*bintree{}}, + "1711389881_add_profile_showcase_community_grant.up.sql": &bintree{_1711389881_add_profile_showcase_community_grantUpSql, map[string]*bintree{}}, + "1711937186_add_contact_customization_color.up.sql": &bintree{_1711937186_add_contact_customization_colorUpSql, map[string]*bintree{}}, + "1712745141_hash_ratchet_encrypted_messages_key_id.up.sql": &bintree{_1712745141_hash_ratchet_encrypted_messages_key_idUpSql, map[string]*bintree{}}, + "1712905223_add_parity_to_message_segments.up.sql": &bintree{_1712905223_add_parity_to_message_segmentsUpSql, map[string]*bintree{}}, + "1713169458_update_raw_messages_with_resend_features.up.sql": &bintree{_1713169458_update_raw_messages_with_resend_featuresUpSql, map[string]*bintree{}}, + "README.md": &bintree{readmeMd, map[string]*bintree{}}, + "doc.go": &bintree{docGo, map[string]*bintree{}}, }} // RestoreAsset restores an asset under the given directory. @@ -3373,7 +3529,7 @@ func RestoreAsset(dir, name string) error { if err != nil { return err } - err = os.WriteFile(_filePath(dir, name), data, info.Mode()) + err = ioutil.WriteFile(_filePath(dir, name), data, info.Mode()) if err != nil { return err } diff --git a/protocol/migrations/sqlite/1713169458_update_raw_messages_with_resend_features.up.sql b/protocol/migrations/sqlite/1713169458_update_raw_messages_with_resend_features.up.sql new file mode 100644 index 000000000..d0b775cc9 --- /dev/null +++ b/protocol/migrations/sqlite/1713169458_update_raw_messages_with_resend_features.up.sql @@ -0,0 +1,11 @@ +ALTER TABLE raw_messages ADD COLUMN sender BLOB; +ALTER TABLE raw_messages ADD COLUMN community_id BLOB; +ALTER TABLE raw_messages ADD COLUMN resend_type INT DEFAULT 0; +ALTER TABLE raw_messages ADD COLUMN resend_method INT DEFAULT 0; +ALTER TABLE raw_messages ADD COLUMN pubsub_topic VARCHAR DEFAULT ''; +ALTER TABLE raw_messages ADD COLUMN hash_ratchet_group_id BLOB; +ALTER TABLE raw_messages ADD COLUMN community_key_ex_msg_type INT DEFAULT 0; + +DROP INDEX IF EXISTS idx_resend_automatically; +CREATE INDEX idx_resend_type ON raw_messages(resend_type); +ALTER TABLE raw_messages DROP COLUMN resend_automatically; diff --git a/protocol/persistence.go b/protocol/persistence.go index 6c1c3ce27..5f0d768c9 100644 --- a/protocol/persistence.go +++ b/protocol/persistence.go @@ -924,9 +924,10 @@ func (db sqlitePersistence) ExpiredMessagesIDs(maxSendCount int) ([]string, erro FROM raw_messages WHERE - (message_type IN (?, ?) OR resend_automatically) AND sent = ? AND send_count <= ?`, + (message_type IN (?, ?) OR resend_type=?) AND sent = ? AND send_count <= ?`, protobuf.ApplicationMetadataMessage_CHAT_MESSAGE, protobuf.ApplicationMetadataMessage_EMOJI_REACTION, + common.ResendTypeRawMessage, false, maxSendCount) if err != nil { diff --git a/protocol/persistence_test.go b/protocol/persistence_test.go index 82fe74a82..c19c31e18 100644 --- a/protocol/persistence_test.go +++ b/protocol/persistence_test.go @@ -780,7 +780,6 @@ func TestDontOverwriteSentStatus(t *testing.T) { require.NoError(t, err) rawMessage.Sent = false - rawMessage.ResendAutomatically = true err = p.SaveRawMessage(rawMessage) require.NoError(t, err) @@ -788,7 +787,6 @@ func TestDontOverwriteSentStatus(t *testing.T) { require.NoError(t, err) require.True(t, m.Sent) - require.True(t, m.ResendAutomatically) } func TestPersistenceEmojiReactions(t *testing.T) { diff --git a/wakuv2/waku.go b/wakuv2/waku.go index 60fc25fa6..cb3b25500 100644 --- a/wakuv2/waku.go +++ b/wakuv2/waku.go @@ -313,6 +313,13 @@ func (w *Waku) SubscribeToConnStatusChanges() *types.ConnStatusSubscription { return subscription } +func (w *Waku) GetNodeENRString() (string, error) { + if w.node == nil { + return "", errors.New("node not initialized") + } + return w.node.ENR().String(), nil +} + func (w *Waku) getDiscV5BootstrapNodes(ctx context.Context, addresses []string) ([]*enode.Node, error) { wg := sync.WaitGroup{} mu := sync.Mutex{}