Merge branch 'bug/saved-mailserver-topics' into develop

This commit is contained in:
Andrea Maria Piana 2021-01-26 12:42:14 +01:00
commit f73fb9c3f6
No known key found for this signature in database
GPG Key ID: AA6CCA6DE0E06424
142 changed files with 5718 additions and 5586 deletions

View File

@ -1 +1 @@
0.68.8
0.69.0

View File

@ -400,6 +400,60 @@ func (b *GethStatusBackend) StartNodeWithAccount(acc multiaccounts.Account, pass
return err
}
func (b *GethStatusBackend) ExportUnencryptedDatabase(acc multiaccounts.Account, password, directory string) error {
b.mu.Lock()
defer b.mu.Unlock()
if b.appDB != nil {
return nil
}
if len(b.rootDataDir) == 0 {
return errors.New("root datadir wasn't provided")
}
// Migrate file path to fix issue https://github.com/status-im/status-go/issues/2027
oldPath := filepath.Join(b.rootDataDir, fmt.Sprintf("app-%x.sql", acc.KeyUID))
newPath := filepath.Join(b.rootDataDir, fmt.Sprintf("%s.db", acc.KeyUID))
_, err := os.Stat(oldPath)
if err == nil {
err := os.Rename(oldPath, newPath)
if err != nil {
return err
}
// rename journals as well, but ignore errors
_ = os.Rename(oldPath+"-shm", newPath+"-shm")
_ = os.Rename(oldPath+"-wal", newPath+"-wal")
}
err = appdatabase.DecryptDatabase(newPath, directory, password)
if err != nil {
b.log.Error("failed to initialize db", "err", err)
return err
}
return nil
}
func (b *GethStatusBackend) ImportUnencryptedDatabase(acc multiaccounts.Account, password, databasePath string) error {
b.mu.Lock()
defer b.mu.Unlock()
if b.appDB != nil {
return nil
}
if len(b.rootDataDir) == 0 {
return errors.New("root datadir wasn't provided")
}
path := filepath.Join(b.rootDataDir, fmt.Sprintf("%s.db", acc.KeyUID))
err := appdatabase.EncryptDatabase(databasePath, path, password)
if err != nil {
b.log.Error("failed to initialize db", "err", err)
return err
}
return nil
}
func (b *GethStatusBackend) SaveAccountAndStartNodeWithKey(acc multiaccounts.Account, password string, settings accounts.Settings, nodecfg *params.NodeConfig, subaccs []accounts.Account, keyHex string) error {
err := b.SaveAccount(acc)
if err != nil {

View File

@ -19,3 +19,15 @@ func InitializeDB(path, password string) (*sql.DB, error) {
}
return db, nil
}
// DecryptDatabase creates an unencrypted copy of the database and copies it
// over to the given directory
func DecryptDatabase(oldPath, newPath, password string) error {
return sqlite.DecryptDB(oldPath, newPath, password)
}
// EncryptDatabase creates an encrypted copy of the database and copies it to the
// user path
func EncryptDatabase(oldPath, newPath, password string) error {
return sqlite.EncryptDB(oldPath, newPath, password)
}

View File

@ -356,7 +356,7 @@ func _0008_add_push_notificationsUpSql() (*asset, error) {
return nil, err
}
info := bindataFileInfo{name: "0008_add_push_notifications.up.sql", size: 349, mode: os.FileMode(0644), modTime: time.Unix(1609934130, 0)}
info := bindataFileInfo{name: "0008_add_push_notifications.up.sql", size: 349, mode: os.FileMode(0644), modTime: time.Unix(1611588835, 0)}
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x5a, 0x0, 0xbf, 0xd0, 0xdd, 0xcd, 0x73, 0xe0, 0x7c, 0x56, 0xef, 0xdc, 0x57, 0x61, 0x94, 0x64, 0x70, 0xb9, 0xfa, 0xa1, 0x2a, 0x36, 0xc, 0x2f, 0xf8, 0x95, 0xa, 0x57, 0x3e, 0x7a, 0xd7, 0x12}}
return a, nil
}
@ -376,7 +376,7 @@ func _0009_enable_sending_push_notificationsDownSql() (*asset, error) {
return nil, err
}
info := bindataFileInfo{name: "0009_enable_sending_push_notifications.down.sql", size: 49, mode: os.FileMode(0644), modTime: time.Unix(1609934130, 0)}
info := bindataFileInfo{name: "0009_enable_sending_push_notifications.down.sql", size: 49, mode: os.FileMode(0644), modTime: time.Unix(1611588835, 0)}
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xe9, 0xae, 0x1b, 0x41, 0xcb, 0x9c, 0x2c, 0x93, 0xc6, 0x2a, 0x77, 0x3, 0xb9, 0x51, 0xe0, 0x68, 0x68, 0x0, 0xf7, 0x5b, 0xb3, 0x1e, 0x94, 0x44, 0xba, 0x9c, 0xd0, 0x3b, 0x80, 0x21, 0x6f, 0xb5}}
return a, nil
}
@ -396,7 +396,7 @@ func _0009_enable_sending_push_notificationsUpSql() (*asset, error) {
return nil, err
}
info := bindataFileInfo{name: "0009_enable_sending_push_notifications.up.sql", size: 49, mode: os.FileMode(0644), modTime: time.Unix(1609934130, 0)}
info := bindataFileInfo{name: "0009_enable_sending_push_notifications.up.sql", size: 49, mode: os.FileMode(0644), modTime: time.Unix(1611588835, 0)}
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x1b, 0x80, 0xe4, 0x9c, 0xc8, 0xb8, 0xd5, 0xef, 0xce, 0x74, 0x9b, 0x7b, 0xdd, 0xa, 0x99, 0x1e, 0xef, 0x7f, 0xb8, 0x99, 0x84, 0x4, 0x0, 0x6b, 0x1d, 0x2c, 0xa, 0xf8, 0x2c, 0x4f, 0xb5, 0x44}}
return a, nil
}
@ -416,7 +416,7 @@ func _0010_add_block_mentionsDownSql() (*asset, error) {
return nil, err
}
info := bindataFileInfo{name: "0010_add_block_mentions.down.sql", size: 83, mode: os.FileMode(0644), modTime: time.Unix(1609934130, 0)}
info := bindataFileInfo{name: "0010_add_block_mentions.down.sql", size: 83, mode: os.FileMode(0644), modTime: time.Unix(1611588835, 0)}
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x6d, 0x9e, 0x27, 0x1e, 0xba, 0x9f, 0xca, 0xae, 0x98, 0x2e, 0x6e, 0xe3, 0xdd, 0xac, 0x73, 0x34, 0x4e, 0x69, 0x92, 0xb5, 0xf6, 0x9, 0xab, 0x50, 0x35, 0xd, 0xee, 0xeb, 0x3e, 0xcc, 0x7e, 0xce}}
return a, nil
}
@ -436,7 +436,7 @@ func _0010_add_block_mentionsUpSql() (*asset, error) {
return nil, err
}
info := bindataFileInfo{name: "0010_add_block_mentions.up.sql", size: 89, mode: os.FileMode(0644), modTime: time.Unix(1609934130, 0)}
info := bindataFileInfo{name: "0010_add_block_mentions.up.sql", size: 89, mode: os.FileMode(0644), modTime: time.Unix(1611588835, 0)}
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xd7, 0x23, 0x85, 0xa2, 0xb5, 0xb6, 0xb4, 0x3f, 0xdc, 0x4e, 0xff, 0xe2, 0x6b, 0x66, 0x68, 0x5e, 0xb2, 0xb4, 0x14, 0xb2, 0x1b, 0x4d, 0xb1, 0xce, 0xf7, 0x6, 0x58, 0xa7, 0xaf, 0x93, 0x3f, 0x25}}
return a, nil
}
@ -456,7 +456,7 @@ func _0011_allow_webview_permission_requestsDownSql() (*asset, error) {
return nil, err
}
info := bindataFileInfo{name: "0011_allow_webview_permission_requests.down.sql", size: 0, mode: os.FileMode(0644), modTime: time.Unix(1609934130, 0)}
info := bindataFileInfo{name: "0011_allow_webview_permission_requests.down.sql", size: 0, mode: os.FileMode(0644), modTime: time.Unix(1611588835, 0)}
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xe3, 0xb0, 0xc4, 0x42, 0x98, 0xfc, 0x1c, 0x14, 0x9a, 0xfb, 0xf4, 0xc8, 0x99, 0x6f, 0xb9, 0x24, 0x27, 0xae, 0x41, 0xe4, 0x64, 0x9b, 0x93, 0x4c, 0xa4, 0x95, 0x99, 0x1b, 0x78, 0x52, 0xb8, 0x55}}
return a, nil
}
@ -476,7 +476,7 @@ func _0011_allow_webview_permission_requestsUpSql() (*asset, error) {
return nil, err
}
info := bindataFileInfo{name: "0011_allow_webview_permission_requests.up.sql", size: 88, mode: os.FileMode(0644), modTime: time.Unix(1609934130, 0)}
info := bindataFileInfo{name: "0011_allow_webview_permission_requests.up.sql", size: 88, mode: os.FileMode(0644), modTime: time.Unix(1611588835, 0)}
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x43, 0x5f, 0x22, 0x4c, 0x98, 0x1d, 0xc6, 0xf4, 0x89, 0xaf, 0xf4, 0x44, 0xba, 0xf8, 0x28, 0xa7, 0xb5, 0xb9, 0xf0, 0xf2, 0xcb, 0x5, 0x59, 0x7a, 0xc, 0xdf, 0xd3, 0x38, 0xa4, 0xb8, 0x98, 0xc2}}
return a, nil
}
@ -496,7 +496,7 @@ func _0012_pending_transactionsDownSql() (*asset, error) {
return nil, err
}
info := bindataFileInfo{name: "0012_pending_transactions.down.sql", size: 33, mode: os.FileMode(0644), modTime: time.Unix(1609934130, 0)}
info := bindataFileInfo{name: "0012_pending_transactions.down.sql", size: 33, mode: os.FileMode(0644), modTime: time.Unix(1611588835, 0)}
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x7e, 0x41, 0xfe, 0x5c, 0xd8, 0xc3, 0x29, 0xfd, 0x31, 0x78, 0x99, 0x7a, 0xeb, 0x17, 0x62, 0x88, 0x41, 0xb3, 0xe7, 0xb5, 0x5, 0x0, 0x90, 0xa1, 0x7, 0x1a, 0x23, 0x88, 0x81, 0xba, 0x56, 0x9d}}
return a, nil
}
@ -516,7 +516,7 @@ func _0012_pending_transactionsUpSql() (*asset, error) {
return nil, err
}
info := bindataFileInfo{name: "0012_pending_transactions.up.sql", size: 321, mode: os.FileMode(0644), modTime: time.Unix(1609934130, 0)}
info := bindataFileInfo{name: "0012_pending_transactions.up.sql", size: 321, mode: os.FileMode(0644), modTime: time.Unix(1611588835, 0)}
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xd, 0x17, 0xff, 0xd7, 0xa7, 0x49, 0x1e, 0x7b, 0x34, 0x63, 0x7c, 0x53, 0xaa, 0x6b, 0x2d, 0xc8, 0xe0, 0x82, 0x21, 0x90, 0x3a, 0x94, 0xf1, 0xa6, 0xe4, 0x70, 0xe5, 0x85, 0x1a, 0x48, 0x25, 0xb}}
return a, nil
}
@ -536,7 +536,7 @@ func _0013_favouritesDownSql() (*asset, error) {
return nil, err
}
info := bindataFileInfo{name: "0013_favourites.down.sql", size: 23, mode: os.FileMode(0644), modTime: time.Unix(1609934130, 0)}
info := bindataFileInfo{name: "0013_favourites.down.sql", size: 23, mode: os.FileMode(0644), modTime: time.Unix(1611588835, 0)}
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x32, 0xf8, 0x55, 0x13, 0x4f, 0x4a, 0x19, 0x83, 0x9c, 0xda, 0x34, 0xb8, 0x3, 0x54, 0x82, 0x1e, 0x99, 0x36, 0x6b, 0x42, 0x3, 0xf6, 0x43, 0xde, 0xe6, 0x32, 0xb6, 0xdf, 0xe2, 0x59, 0x8c, 0x84}}
return a, nil
}
@ -556,7 +556,7 @@ func _0013_favouritesUpSql() (*asset, error) {
return nil, err
}
info := bindataFileInfo{name: "0013_favourites.up.sql", size: 132, mode: os.FileMode(0644), modTime: time.Unix(1609934130, 0)}
info := bindataFileInfo{name: "0013_favourites.up.sql", size: 132, mode: os.FileMode(0644), modTime: time.Unix(1611588835, 0)}
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xbe, 0x1, 0x27, 0x38, 0x76, 0xf5, 0xcb, 0x61, 0xda, 0x5b, 0xce, 0xd9, 0x8b, 0x18, 0x77, 0x61, 0x84, 0xe7, 0x22, 0xe2, 0x13, 0x99, 0xab, 0x32, 0xbc, 0xbe, 0xed, 0x1f, 0x2f, 0xb0, 0xe4, 0x8d}}
return a, nil
}
@ -576,7 +576,7 @@ func _0014_add_use_mailserversDownSql() (*asset, error) {
return nil, err
}
info := bindataFileInfo{name: "0014_add_use_mailservers.down.sql", size: 0, mode: os.FileMode(0644), modTime: time.Unix(1609934130, 0)}
info := bindataFileInfo{name: "0014_add_use_mailservers.down.sql", size: 0, mode: os.FileMode(0644), modTime: time.Unix(1611588835, 0)}
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xe3, 0xb0, 0xc4, 0x42, 0x98, 0xfc, 0x1c, 0x14, 0x9a, 0xfb, 0xf4, 0xc8, 0x99, 0x6f, 0xb9, 0x24, 0x27, 0xae, 0x41, 0xe4, 0x64, 0x9b, 0x93, 0x4c, 0xa4, 0x95, 0x99, 0x1b, 0x78, 0x52, 0xb8, 0x55}}
return a, nil
}
@ -596,7 +596,7 @@ func _0014_add_use_mailserversUpSql() (*asset, error) {
return nil, err
}
info := bindataFileInfo{name: "0014_add_use_mailservers.up.sql", size: 111, mode: os.FileMode(0644), modTime: time.Unix(1609934130, 0)}
info := bindataFileInfo{name: "0014_add_use_mailservers.up.sql", size: 111, mode: os.FileMode(0644), modTime: time.Unix(1611588835, 0)}
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xc9, 0xba, 0x65, 0xbf, 0x1b, 0xc9, 0x6d, 0x45, 0xf2, 0xf5, 0x30, 0x7c, 0xc1, 0xde, 0xb8, 0xe3, 0x3f, 0xa9, 0x2f, 0x9f, 0xea, 0x1, 0x29, 0x29, 0x65, 0xe7, 0x38, 0xab, 0xa4, 0x62, 0xf, 0xd0}}
return a, nil
}
@ -616,7 +616,7 @@ func _0015_link_previewsDownSql() (*asset, error) {
return nil, err
}
info := bindataFileInfo{name: "0015_link_previews.down.sql", size: 0, mode: os.FileMode(0644), modTime: time.Unix(1609934130, 0)}
info := bindataFileInfo{name: "0015_link_previews.down.sql", size: 0, mode: os.FileMode(0644), modTime: time.Unix(1611588835, 0)}
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xe3, 0xb0, 0xc4, 0x42, 0x98, 0xfc, 0x1c, 0x14, 0x9a, 0xfb, 0xf4, 0xc8, 0x99, 0x6f, 0xb9, 0x24, 0x27, 0xae, 0x41, 0xe4, 0x64, 0x9b, 0x93, 0x4c, 0xa4, 0x95, 0x99, 0x1b, 0x78, 0x52, 0xb8, 0x55}}
return a, nil
}
@ -636,7 +636,7 @@ func _0015_link_previewsUpSql() (*asset, error) {
return nil, err
}
info := bindataFileInfo{name: "0015_link_previews.up.sql", size: 203, mode: os.FileMode(0644), modTime: time.Unix(1609934130, 0)}
info := bindataFileInfo{name: "0015_link_previews.up.sql", size: 203, mode: os.FileMode(0644), modTime: time.Unix(1611588835, 0)}
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xb1, 0xf7, 0x38, 0x25, 0xa6, 0xfc, 0x6b, 0x9, 0xe4, 0xd9, 0xbf, 0x58, 0x7b, 0x80, 0xd8, 0x48, 0x63, 0xde, 0xa5, 0x5e, 0x30, 0xa3, 0xeb, 0x68, 0x8e, 0x6a, 0x9f, 0xfd, 0xf4, 0x46, 0x41, 0x34}}
return a, nil
}
@ -656,7 +656,7 @@ func _0016_local_notifications_preferencesDownSql() (*asset, error) {
return nil, err
}
info := bindataFileInfo{name: "0016_local_notifications_preferences.down.sql", size: 43, mode: os.FileMode(0644), modTime: time.Unix(1609934130, 0)}
info := bindataFileInfo{name: "0016_local_notifications_preferences.down.sql", size: 43, mode: os.FileMode(0644), modTime: time.Unix(1611588835, 0)}
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xe0, 0x50, 0xc7, 0xdd, 0x53, 0x9c, 0x5d, 0x1e, 0xb5, 0x71, 0x25, 0x50, 0x58, 0xcf, 0x6d, 0xbe, 0x5a, 0x8, 0x12, 0xc9, 0x13, 0xd, 0x9a, 0x3d, 0x4b, 0x7a, 0x2f, 0x1b, 0xe5, 0x23, 0x52, 0x78}}
return a, nil
}
@ -676,7 +676,7 @@ func _0016_local_notifications_preferencesUpSql() (*asset, error) {
return nil, err
}
info := bindataFileInfo{name: "0016_local_notifications_preferences.up.sql", size: 204, mode: os.FileMode(0644), modTime: time.Unix(1609934130, 0)}
info := bindataFileInfo{name: "0016_local_notifications_preferences.up.sql", size: 204, mode: os.FileMode(0644), modTime: time.Unix(1611588835, 0)}
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x3f, 0x3a, 0x16, 0x25, 0xdf, 0xba, 0x62, 0xd3, 0x81, 0x73, 0xc, 0x10, 0x85, 0xbc, 0x8d, 0xe, 0x1d, 0x62, 0xcb, 0xb, 0x6d, 0x8c, 0x4f, 0x63, 0x5f, 0xe2, 0xd, 0xc5, 0x46, 0xa8, 0x35, 0x5b}}
return a, nil
}
@ -696,7 +696,7 @@ func _0017_bookmarksDownSql() (*asset, error) {
return nil, err
}
info := bindataFileInfo{name: "0017_bookmarks.down.sql", size: 22, mode: os.FileMode(0644), modTime: time.Unix(1609934130, 0)}
info := bindataFileInfo{name: "0017_bookmarks.down.sql", size: 22, mode: os.FileMode(0644), modTime: time.Unix(1611588835, 0)}
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x9a, 0x13, 0x2a, 0x44, 0xb0, 0x3, 0x18, 0x63, 0xb8, 0x33, 0xda, 0x3a, 0xeb, 0xb8, 0xcb, 0xd1, 0x98, 0x29, 0xa7, 0xf0, 0x6, 0x9d, 0xc9, 0x62, 0xe7, 0x89, 0x7f, 0x77, 0xaf, 0xec, 0x6b, 0x8f}}
return a, nil
}
@ -716,7 +716,7 @@ func _0017_bookmarksUpSql() (*asset, error) {
return nil, err
}
info := bindataFileInfo{name: "0017_bookmarks.up.sql", size: 147, mode: os.FileMode(0644), modTime: time.Unix(1609934130, 0)}
info := bindataFileInfo{name: "0017_bookmarks.up.sql", size: 147, mode: os.FileMode(0644), modTime: time.Unix(1611588835, 0)}
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xbc, 0x47, 0xe1, 0xe3, 0xd8, 0xc6, 0x4, 0x6d, 0x5f, 0x2f, 0xa, 0x51, 0xa6, 0x8c, 0x6a, 0xe0, 0x3d, 0x8c, 0x91, 0x47, 0xbc, 0x1, 0x75, 0x46, 0x92, 0x2, 0x18, 0x6e, 0xe3, 0x4f, 0x18, 0x57}}
return a, nil
}
@ -736,7 +736,7 @@ func _0018_profile_pictures_visibilityUpSql() (*asset, error) {
return nil, err
}
info := bindataFileInfo{name: "0018_profile_pictures_visibility.up.sql", size: 84, mode: os.FileMode(0644), modTime: time.Unix(1610715642, 0)}
info := bindataFileInfo{name: "0018_profile_pictures_visibility.up.sql", size: 84, mode: os.FileMode(0644), modTime: time.Unix(1611588835, 0)}
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xc9, 0xe3, 0xc5, 0xec, 0x83, 0x55, 0x45, 0x57, 0x7a, 0xaa, 0xd2, 0xa7, 0x59, 0xa7, 0x87, 0xef, 0x63, 0x19, 0x9c, 0x46, 0x9c, 0xc5, 0x32, 0x89, 0xa4, 0x68, 0x70, 0xd8, 0x83, 0x43, 0xa4, 0x72}}
return a, nil
}

View File

@ -8,7 +8,7 @@ import (
"github.com/status-im/status-go/waku"
wakucommon "github.com/status-im/status-go/waku/common"
"github.com/status-im/status-go/whisper/v6"
"github.com/status-im/status-go/whisper"
)
type Bridge struct {

View File

@ -14,7 +14,7 @@ import (
"github.com/status-im/status-go/waku"
wakucommon "github.com/status-im/status-go/waku/common"
"github.com/status-im/status-go/whisper/v6"
"github.com/status-im/status-go/whisper"
)
func TestEnvelopesBeingIdentical(t *testing.T) {

View File

@ -31,7 +31,6 @@ import (
"github.com/status-im/status-go/params"
"github.com/status-im/status-go/profiling"
"github.com/status-im/status-go/protocol"
localnotifications "github.com/status-im/status-go/services/local-notifications"
)
const (
@ -242,7 +241,7 @@ func main() {
// This will start the push notification server as well as
// the config is set to Enabled
err = messenger.Start()
_, err = messenger.Start()
if err != nil {
logger.Error("failed to start messenger", "error", err)
return
@ -400,13 +399,11 @@ func retrieveMessagesLoop(messenger *protocol.Messenger, tick time.Duration, can
for {
select {
case <-ticker.C:
mr, err := messenger.RetrieveAll()
_, err := messenger.RetrieveAll()
if err != nil {
logger.Error("failed to retrieve raw messages", "err", err)
continue
}
localnotifications.SendMessageNotifications(mr.Notifications)
case <-cancel:
return
}

17
cmd/topics/main.go Normal file
View File

@ -0,0 +1,17 @@
package main
import (
"encoding/hex"
"fmt"
"github.com/status-im/status-go/protocol/transport"
)
func main() {
for i := 0; i < 5001; i++ {
topic := fmt.Sprintf("contact-discovery-%d", i)
topicBytes := "0x" + hex.EncodeToString(transport.ToTopic(topic))
fmt.Printf("%s - %s\n", topic, topicBytes)
}
}

View File

@ -6,7 +6,7 @@ import (
"github.com/ethereum/go-ethereum/rlp"
"github.com/status-im/status-go/eth-node/types"
waku "github.com/status-im/status-go/waku/common"
"github.com/status-im/status-go/whisper/v6"
"github.com/status-im/status-go/whisper"
)
type whisperEnvelope struct {

View File

@ -3,7 +3,7 @@ package gethbridge
import (
"github.com/status-im/status-go/eth-node/types"
waku "github.com/status-im/status-go/waku/common"
"github.com/status-im/status-go/whisper/v6"
"github.com/status-im/status-go/whisper"
)
// NewWhisperEnvelopeErrorWrapper returns a types.EnvelopeError object that mimics Geth's EnvelopeError

View File

@ -4,7 +4,7 @@ import (
"github.com/status-im/status-go/eth-node/types"
"github.com/status-im/status-go/waku"
wakucommon "github.com/status-im/status-go/waku/common"
"github.com/status-im/status-go/whisper/v6"
"github.com/status-im/status-go/whisper"
)
// NewWhisperEnvelopeEventWrapper returns a types.EnvelopeEvent object that mimics Geth's EnvelopeEvent

View File

@ -3,7 +3,7 @@ package gethbridge
import (
"github.com/status-im/status-go/eth-node/types"
"github.com/status-im/status-go/waku"
"github.com/status-im/status-go/whisper/v6"
"github.com/status-im/status-go/whisper"
)
// NewWhisperMailServerResponseWrapper returns a types.MailServerResponse object that mimics Geth's MailServerResponse

View File

@ -13,7 +13,7 @@ import (
gethens "github.com/status-im/status-go/eth-node/bridge/geth/ens"
"github.com/status-im/status-go/eth-node/types"
enstypes "github.com/status-im/status-go/eth-node/types/ens"
"github.com/status-im/status-go/whisper/v6"
"github.com/status-im/status-go/whisper"
)
type gethNodeWrapper struct {

View File

@ -6,7 +6,7 @@ import (
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/status-im/status-go/eth-node/types"
"github.com/status-im/status-go/whisper/v6"
"github.com/status-im/status-go/whisper"
)
type gethPublicWhisperAPIWrapper struct {

View File

@ -2,7 +2,7 @@ package gethbridge
import (
"github.com/status-im/status-go/eth-node/types"
"github.com/status-im/status-go/whisper/v6"
"github.com/status-im/status-go/whisper"
)
// NewGethSyncEventResponseWrapper returns a types.SyncEventResponse object that mimics Geth's SyncEventResponse

View File

@ -2,7 +2,7 @@ package gethbridge
import (
"github.com/status-im/status-go/eth-node/types"
"github.com/status-im/status-go/whisper/v6"
"github.com/status-im/status-go/whisper"
)
// GetGethSyncMailRequestFrom converts a whisper SyncMailRequest struct from a SyncMailRequest struct

View File

@ -144,6 +144,10 @@ func (w *gethWakuWrapper) Unsubscribe(id string) error {
return w.waku.Unsubscribe(id)
}
func (w *gethWakuWrapper) UnsubscribeMany(ids []string) error {
return w.waku.UnsubscribeMany(ids)
}
func (w *gethWakuWrapper) createFilterWrapper(id string, keyAsym *ecdsa.PrivateKey, keySym []byte, pow float64, topics [][]byte) (types.Filter, error) {
return NewWakuFilterWrapper(&wakucommon.Filter{
KeyAsym: keyAsym,

View File

@ -5,7 +5,7 @@ import (
"time"
"github.com/status-im/status-go/eth-node/types"
"github.com/status-im/status-go/whisper/v6"
"github.com/status-im/status-go/whisper"
)
type gethWhisperWrapper struct {
@ -148,6 +148,10 @@ func (w *gethWhisperWrapper) Unsubscribe(id string) error {
return w.whisper.Unsubscribe(id)
}
func (w *gethWhisperWrapper) UnsubscribeMany(ids []string) error {
return w.whisper.UnsubscribeMany(ids)
}
func (w *gethWhisperWrapper) createFilterWrapper(id string, keyAsym *ecdsa.PrivateKey, keySym []byte, pow float64, topics [][]byte) (types.Filter, error) {
return NewWhisperFilterWrapper(&whisper.Filter{
KeyAsym: keyAsym,

View File

@ -40,6 +40,7 @@ type Waku interface {
Subscribe(opts *SubscriptionOptions) (string, error)
GetFilter(id string) Filter
Unsubscribe(id string) error
UnsubscribeMany(ids []string) error
// RequestHistoricMessages sends a message with p2pRequestCode to a specific peer,
// which is known to implement MailServer interface, and is supposed to process this

View File

@ -42,6 +42,7 @@ type Whisper interface {
Subscribe(opts *SubscriptionOptions) (string, error)
GetFilter(id string) Filter
Unsubscribe(id string) error
UnsubscribeMany(ids []string) error
// RequestHistoricMessages sends a message with p2pRequestCode to a specific peer,
// which is known to implement MailServer interface, and is supposed to process this

2
go.mod
View File

@ -63,7 +63,6 @@ require (
github.com/status-im/migrate/v4 v4.6.2-status.2
github.com/status-im/rendezvous v1.3.0
github.com/status-im/status-go/extkeys v1.1.2
github.com/status-im/status-go/whisper/v6 v6.2.6
github.com/status-im/tcp-shaker v0.0.0-20191114194237-215893130501
github.com/stretchr/testify v1.5.1
github.com/syndtr/goleveldb v1.0.0
@ -74,6 +73,7 @@ require (
go.uber.org/zap v1.13.0
golang.org/x/crypto v0.0.0-20191122220453-ac88ee75c92c
golang.org/x/image v0.0.0-20200927104501-e162460cd6b5
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e
golang.org/x/text v0.3.3 // indirect
golang.org/x/time v0.0.0-20191024005414-555d28b269f0 // indirect
golang.org/x/tools v0.0.0-20200211045251-2de505fc5306 // indirect

15
go.sum
View File

@ -76,8 +76,6 @@ github.com/cespare/cp v1.1.1 h1:nCb6ZLdB7NRaqsm91JtQTAme2SKJzXVsdPIPkyJr1MU=
github.com/cespare/cp v1.1.1/go.mod h1:SOGHArjBr4JWaSDEVpWpo/hNg6RoKrls6Oh40hiwW+s=
github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko=
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
github.com/cespare/xxhash/v2 v2.1.0 h1:yTUvW7Vhb89inJ+8irsUqiWjh8iT6sQPZiQzI6ReGkA=
github.com/cespare/xxhash/v2 v2.1.0/go.mod h1:dgIUBU3pDso/gPgZ1osOZ0iQf77oPR28Tjxl5dIMyVM=
github.com/cespare/xxhash/v2 v2.1.1 h1:6MnRN8NT7+YBpUIWxHtefFZOKTAPgGjpQSxqLNn0+qY=
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
@ -302,7 +300,6 @@ github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht
github.com/jmoiron/sqlx v1.2.0/go.mod h1:1FEQNm3xlJgrMD+FBdI9+xvCksHtbpVBBw5dYhBSsks=
github.com/jrick/logrotate v1.0.0/go.mod h1:LNinyqDIJnpAur+b8yyulnQw/wDuN1+BYKlTRt3OuAQ=
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
github.com/julienschmidt/httprouter v0.0.0-20170430222011-975b5c4c7c21/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
@ -584,8 +581,6 @@ github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXP
github.com/prometheus/client_golang v0.9.2/go.mod h1:OsXs2jCmiKlQ1lTBmv21f2mNfw4xf/QclQDMrYNZzcM=
github.com/prometheus/client_golang v0.9.3-0.20190127221311-3c4408c8b829/go.mod h1:p2iRAGwDERtqlqzRXnrOVns+ignqQo//hLXqYxZYVNs=
github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo=
github.com/prometheus/client_golang v1.2.1 h1:JnMpQc6ppsNgw9QPAGF6Dod479itz7lvlsMzzNayLOI=
github.com/prometheus/client_golang v1.2.1/go.mod h1:XMU6Z2MjaRKVu/dC1qupJI9SiNkDYzz3xecMgSW/F+U=
github.com/prometheus/client_golang v1.5.0 h1:Ctq0iGpCmr3jeP77kbF2UxgvRwzWWz+4Bh9/vJTyg1A=
github.com/prometheus/client_golang v1.5.0/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU=
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
@ -598,16 +593,12 @@ github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6T
github.com/prometheus/common v0.0.0-20181126121408-4724e9255275/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro=
github.com/prometheus/common v0.2.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
github.com/prometheus/common v0.7.0 h1:L+1lyG48J1zAQXA3RBX/nG/B3gjlHq0zTt2tlbJLyCY=
github.com/prometheus/common v0.7.0/go.mod h1:DjGbpBbp5NYNiECxcL/VnbXCCaQpKd3tt26CguLLsqA=
github.com/prometheus/common v0.9.1 h1:KOMtN28tlbam3/7ZKEYKHhKoJZYYj3gMH4uc62x7X7U=
github.com/prometheus/common v0.9.1/go.mod h1:yhUN8i9wzaXS3w1O07YhxHEBxD+W35wd8bs7vj7HSQ4=
github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
github.com/prometheus/procfs v0.0.0-20181204211112-1dc9a6cbc91a/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
github.com/prometheus/procfs v0.0.5 h1:3+auTFlqw+ZaQYJARz6ArODtkaIwtvBTx3N2NehQlL8=
github.com/prometheus/procfs v0.0.5/go.mod h1:4A/X28fw3Fc593LaREMrKMqOKvUAntwMDaekg4FpcdQ=
github.com/prometheus/procfs v0.0.8 h1:+fpWZdT24pJBiqJdAwYBjPSk+5YmQzYNPYzQsdzLkt8=
github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A=
github.com/prometheus/prometheus v0.0.0-20170814170113-3101606756c5/go.mod h1:oAIUtOny2rjMX0OWN5vPR5/q/twIROJvdqnQKDdil/s=
@ -675,8 +666,6 @@ github.com/status-im/resize v0.0.0-20201215164250-7c6d9f0d3088/go.mod h1:+92j1tN
github.com/status-im/status-go/extkeys v1.0.0/go.mod h1:GdqJbrcpkNm5ZsSCpp+PdMxnXx+OcRBdm3PI0rs1FpU=
github.com/status-im/status-go/extkeys v1.1.2 h1:FSjARgDathJ3rIapJt851LsIXP9Oyuu2M2jPJKuzloU=
github.com/status-im/status-go/extkeys v1.1.2/go.mod h1:hCmFzb2jiiVF2voZKYbzuhOQiHHCmyLJsZJXrFFg7BY=
github.com/status-im/status-go/whisper/v6 v6.2.6 h1:xELIv/8QB9CQlJjChnCPt4COWOFmgsc2kl03Y3Dspmo=
github.com/status-im/status-go/whisper/v6 v6.2.6/go.mod h1:csqMoPMkCPW1NJO56HJzNTWAl9UMdetnQzkPbPjsAC4=
github.com/status-im/tcp-shaker v0.0.0-20191114194237-215893130501 h1:oa0KU5jJRNtXaM/P465MhvSFo/HM2O8qi2DDuPcd7ro=
github.com/status-im/tcp-shaker v0.0.0-20191114194237-215893130501/go.mod h1:RYo/itke1oU5k/6sj9DNM3QAwtE5rZSgg5JnkOv83hk=
github.com/steakknife/bloomfilter v0.0.0-20180922174646-6819c0d2a570 h1:gIlAHnH1vJb5vwEjIp5kBj/eu99p/bl0Ay2goiPe5xE=
@ -685,9 +674,8 @@ github.com/steakknife/hamming v0.0.0-20180906055917-c99c65617cd3 h1:njlZPzLwU639
github.com/steakknife/hamming v0.0.0-20180906055917-c99c65617cd3/go.mod h1:hpGUWaI9xL8pRQCTXQgocU38Qw1g0Us7n5PxxTwTCYU=
github.com/stephens2424/writerset v1.0.2/go.mod h1:aS2JhsMn6eA7e82oNmW4rfsgAOp9COBTTl8mzkwADnc=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.1.1 h1:2vfRuCMp5sSVIDSqO8oNnWJq7mPa6KVP3iPIwFBuy8A=
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.2.0 h1:Hbg2NidpLE8veEBkEZTL3CvlkUIVzuU9jDplZO54c48=
github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE=
github.com/stretchr/testify v0.0.0-20170809224252-890a5c3458b4/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
@ -834,7 +822,6 @@ golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20190626221950-04f50cda93cb/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190922100055-0a153f010e69/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191010194322-b09406accb47/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191025090151-53bf42e6b339/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191113165036-4c7a9d0fe056 h1:dHtDnRWQtSx0Hjq9kvKFpBh9uPPKfQN70NZZmvssGwk=
golang.org/x/sys v0.0.0-20191113165036-4c7a9d0fe056/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=

View File

@ -12,7 +12,7 @@ import (
"github.com/ethereum/go-ethereum/rlp"
"github.com/status-im/status-go/eth-node/types"
"github.com/status-im/status-go/whisper/v6"
"github.com/status-im/status-go/whisper"
)
func TestCleaner(t *testing.T) {

View File

@ -37,7 +37,7 @@ import (
"github.com/status-im/status-go/params"
"github.com/status-im/status-go/waku"
wakucommon "github.com/status-im/status-go/waku/common"
"github.com/status-im/status-go/whisper/v6"
"github.com/status-im/status-go/whisper"
)
const (

View File

@ -13,7 +13,7 @@ import (
"github.com/ethereum/go-ethereum/rlp"
"github.com/status-im/status-go/eth-node/types"
"github.com/status-im/status-go/whisper/v6"
"github.com/status-im/status-go/whisper"
)
type LevelDB struct {

View File

@ -20,7 +20,7 @@ import (
"github.com/ethereum/go-ethereum/rlp"
"github.com/status-im/status-go/eth-node/types"
"github.com/status-im/status-go/whisper/v6"
"github.com/status-im/status-go/whisper"
)
type PostgresDB struct {

View File

@ -18,7 +18,7 @@ import (
gethbridge "github.com/status-im/status-go/eth-node/bridge/geth"
"github.com/status-im/status-go/eth-node/crypto"
"github.com/status-im/status-go/eth-node/types"
"github.com/status-im/status-go/whisper/v6"
"github.com/status-im/status-go/whisper"
)
func TestPostgresDB_BuildIteratorWithBloomFilter(t *testing.T) {

View File

@ -35,7 +35,7 @@ import (
"github.com/status-im/status-go/eth-node/types"
"github.com/status-im/status-go/params"
"github.com/status-im/status-go/whisper/v6"
"github.com/status-im/status-go/whisper"
)
const powRequirement = 0.00001

View File

@ -628,3 +628,31 @@ func MultiformatDeserializePublicKey(key, outBase string) string {
return pk
}
// ExportUnencryptedDatabase exports the database unencrypted to the given path
func ExportUnencryptedDatabase(accountData, password, databasePath string) string {
var account multiaccounts.Account
err := json.Unmarshal([]byte(accountData), &account)
if err != nil {
return makeJSONResponse(err)
}
err = statusBackend.ExportUnencryptedDatabase(account, password, databasePath)
if err != nil {
return makeJSONResponse(err)
}
return makeJSONResponse(nil)
}
// ImportUnencryptedDatabase imports the database unencrypted to the given directory
func ImportUnencryptedDatabase(accountData, password, databasePath string) string {
var account multiaccounts.Account
err := json.Unmarshal([]byte(accountData), &account)
if err != nil {
return makeJSONResponse(err)
}
err = statusBackend.ImportUnencryptedDatabase(account, password, databasePath)
if err != nil {
return makeJSONResponse(err)
}
return makeJSONResponse(nil)
}

View File

@ -130,7 +130,7 @@ func _1605007189_identity_imagesDownSql() (*asset, error) {
return nil, err
}
info := bindataFileInfo{name: "1605007189_identity_images.down.sql", size: 29, mode: os.FileMode(0644), modTime: time.Unix(1609934130, 0)}
info := bindataFileInfo{name: "1605007189_identity_images.down.sql", size: 29, mode: os.FileMode(0644), modTime: time.Unix(1611588835, 0)}
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x2f, 0xcf, 0xa7, 0xae, 0xd5, 0x4f, 0xcd, 0x14, 0x63, 0x9, 0xbe, 0x39, 0x49, 0x18, 0x96, 0xb2, 0xa3, 0x8, 0x7d, 0x41, 0xdb, 0x50, 0x5d, 0xf5, 0x4d, 0xa2, 0xd, 0x8f, 0x57, 0x79, 0x77, 0x67}}
return a, nil
}
@ -150,7 +150,7 @@ func _1605007189_identity_imagesUpSql() (*asset, error) {
return nil, err
}
info := bindataFileInfo{name: "1605007189_identity_images.up.sql", size: 268, mode: os.FileMode(0644), modTime: time.Unix(1609934130, 0)}
info := bindataFileInfo{name: "1605007189_identity_images.up.sql", size: 268, mode: os.FileMode(0644), modTime: time.Unix(1611588835, 0)}
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x50, 0xb6, 0xc1, 0x5c, 0x76, 0x72, 0x6b, 0x22, 0x34, 0xdc, 0x96, 0xdc, 0x2b, 0xfd, 0x2d, 0xbe, 0xcc, 0x1e, 0xd4, 0x5, 0x93, 0xd, 0xc2, 0x51, 0xf3, 0x1a, 0xef, 0x2b, 0x26, 0xa4, 0xeb, 0x65}}
return a, nil
}
@ -170,7 +170,7 @@ func _1606224181_drop_photo_path_from_accountsDownSql() (*asset, error) {
return nil, err
}
info := bindataFileInfo{name: "1606224181_drop_photo_path_from_accounts.down.sql", size: 892, mode: os.FileMode(0644), modTime: time.Unix(1609934130, 0)}
info := bindataFileInfo{name: "1606224181_drop_photo_path_from_accounts.down.sql", size: 892, mode: os.FileMode(0644), modTime: time.Unix(1611588835, 0)}
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x90, 0x24, 0x17, 0x7, 0x80, 0x93, 0x6f, 0x8d, 0x5d, 0xaa, 0x8c, 0x79, 0x15, 0x5d, 0xb3, 0x19, 0xd7, 0xd8, 0x39, 0xf9, 0x3a, 0x63, 0x8f, 0x81, 0x15, 0xb6, 0xd6, 0x9a, 0x37, 0xa8, 0x8e, 0x9b}}
return a, nil
}
@ -190,7 +190,7 @@ func _1606224181_drop_photo_path_from_accountsUpSql() (*asset, error) {
return nil, err
}
info := bindataFileInfo{name: "1606224181_drop_photo_path_from_accounts.up.sql", size: 866, mode: os.FileMode(0644), modTime: time.Unix(1609934130, 0)}
info := bindataFileInfo{name: "1606224181_drop_photo_path_from_accounts.up.sql", size: 866, mode: os.FileMode(0644), modTime: time.Unix(1611588835, 0)}
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xff, 0x4c, 0x97, 0xee, 0xef, 0x82, 0xb8, 0x6c, 0x71, 0xbb, 0x50, 0x7b, 0xe6, 0xd9, 0x22, 0x31, 0x7c, 0x1a, 0xfe, 0x91, 0x28, 0xf6, 0x6, 0x36, 0xe, 0xb1, 0xf1, 0xc8, 0x25, 0xac, 0x7e, 0xd6}}
return a, nil
}

View File

@ -41,7 +41,7 @@ import (
"github.com/status-im/status-go/services/wakuext"
"github.com/status-im/status-go/services/wallet"
"github.com/status-im/status-go/waku"
"github.com/status-im/status-go/whisper/v6"
"github.com/status-im/status-go/whisper"
)
// tickerResolution is the delta to check blockchain sync progress.

View File

@ -40,7 +40,7 @@ import (
"github.com/status-im/status-go/timesource"
"github.com/status-im/status-go/waku"
wakucommon "github.com/status-im/status-go/waku/common"
"github.com/status-im/status-go/whisper/v6"
"github.com/status-im/status-go/whisper"
)
// Errors related to node and services creation.

View File

@ -8,7 +8,7 @@ import (
"github.com/stretchr/testify/require"
"github.com/status-im/status-go/params"
"github.com/status-im/status-go/whisper/v6"
"github.com/status-im/status-go/whisper"
)
func TestWhisperLightModeEnabledSetsEmptyBloomFilter(t *testing.T) {

View File

@ -17,7 +17,7 @@ import (
gethnode "github.com/ethereum/go-ethereum/node"
"github.com/ethereum/go-ethereum/p2p"
"github.com/status-im/status-go/whisper/v6"
"github.com/status-im/status-go/whisper"
"github.com/stretchr/testify/require"

View File

@ -24,7 +24,7 @@ import (
"github.com/status-im/status-go/protocol/pushnotificationserver"
"github.com/status-im/status-go/static"
wakucommon "github.com/status-im/status-go/waku/common"
"github.com/status-im/status-go/whisper/v6"
"github.com/status-im/status-go/whisper"
)
// ----------

View File

@ -22,7 +22,7 @@ import (
"github.com/status-im/status-go/discovery"
"github.com/status-im/status-go/params"
"github.com/status-im/status-go/signal"
"github.com/status-im/status-go/whisper/v6"
"github.com/status-im/status-go/whisper"
)
type PeerPoolSimulationSuite struct {

View File

@ -16,7 +16,7 @@ import (
"github.com/status-im/status-go/params"
"github.com/status-im/status-go/t/helpers"
"github.com/status-im/status-go/whisper/v6"
"github.com/status-im/status-go/whisper"
)
type TopicPoolSuite struct {

View File

@ -18,6 +18,7 @@ type ChatEntity interface {
GetSigPubKey() *ecdsa.PublicKey
GetProtobuf() proto.Message
GetGrant() []byte
WrapGroupMessage() bool
SetMessageType(messageType protobuf.MessageType)
}

View File

@ -392,3 +392,8 @@ func (m *Message) GetProtobuf() proto.Message {
func (m *Message) SetMessageType(messageType protobuf.MessageType) {
m.MessageType = messageType
}
// WrapGroupMessage indicates whether we should wrap this in membership information
func (m *Message) WrapGroupMessage() bool {
return true
}

View File

@ -140,8 +140,8 @@ func (p *MessageProcessor) 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.SkipEncryption) {
return nil, errors.New("setting identity, skip-encryption and datasync not supported")
if rawMessage.ResendAutomatically && (rawMessage.Sender != nil || rawMessage.SkipEncryption || rawMessage.SendOnPersonalTopic) {
return nil, errors.New("setting identity, skip-encryption or personal topic and datasync not supported")
}
// Set sender identity if not specified
@ -216,7 +216,7 @@ func (p *MessageProcessor) sendPrivate(
} else if rawMessage.SkipEncryption {
// When SkipEncryption is set we don't pass the message to the encryption layer
messageIDs := [][]byte{messageID}
hash, newMessage, err := p.sendPrivateRawMessage(ctx, recipient, wrappedMessage, messageIDs)
hash, newMessage, err := p.sendPrivateRawMessage(ctx, rawMessage, recipient, wrappedMessage, messageIDs)
if err != nil {
p.logger.Error("failed to send a private message", zap.Error(err))
return nil, errors.Wrap(err, "failed to send a message spec")
@ -284,16 +284,10 @@ func (p *MessageProcessor) SendPairInstallation(
return messageID, nil
}
// EncodeMembershipUpdate takes a group and an optional chat message and returns the protobuf representation to be sent on the wire.
// All the events in a group are encoded and added to the payload
func (p *MessageProcessor) EncodeMembershipUpdate(
group *v1protocol.Group,
func (p *MessageProcessor) encodeMembershipUpdate(
message v1protocol.MembershipUpdateMessage,
chatEntity ChatEntity,
) ([]byte, error) {
message := v1protocol.MembershipUpdateMessage{
ChatID: group.ChatID(),
Events: group.Events(),
}
if chatEntity != nil {
chatEntityProtobuf := chatEntity.GetProtobuf()
@ -314,6 +308,33 @@ func (p *MessageProcessor) EncodeMembershipUpdate(
return encodedMessage, nil
}
// EncodeMembershipUpdate takes a group and an optional chat message and returns the protobuf representation to be sent on the wire.
// All the events in a group are encoded and added to the payload
func (p *MessageProcessor) EncodeMembershipUpdate(
group *v1protocol.Group,
chatEntity ChatEntity,
) ([]byte, error) {
message := v1protocol.MembershipUpdateMessage{
ChatID: group.ChatID(),
Events: group.Events(),
}
return p.encodeMembershipUpdate(message, chatEntity)
}
// EncodeAbridgedMembershipUpdate takes a group and an optional chat message and returns the protobuf representation to be sent on the wire.
// Only the events relevant to the sender are encoded
func (p *MessageProcessor) EncodeAbridgedMembershipUpdate(
group *v1protocol.Group,
chatEntity ChatEntity,
) ([]byte, error) {
message := v1protocol.MembershipUpdateMessage{
ChatID: group.ChatID(),
Events: group.AbridgedEvents(&p.identity.PublicKey),
}
return p.encodeMembershipUpdate(message, chatEntity)
}
// SendPublic takes encoded data, encrypts it and sends through the wire.
func (p *MessageProcessor) SendPublic(
ctx context.Context,
@ -548,15 +569,21 @@ func (p *MessageProcessor) sendDataSync(ctx context.Context, publicKey *ecdsa.Pu
}
// sendPrivateRawMessage sends a message not wrapped in an encryption layer
func (p *MessageProcessor) sendPrivateRawMessage(ctx context.Context, publicKey *ecdsa.PublicKey, payload []byte, messageIDs [][]byte) ([]byte, *types.NewMessage, error) {
func (p *MessageProcessor) sendPrivateRawMessage(ctx context.Context, rawMessage *RawMessage, publicKey *ecdsa.PublicKey, payload []byte, messageIDs [][]byte) ([]byte, *types.NewMessage, error) {
newMessage := &types.NewMessage{
TTL: whisperTTL,
Payload: payload,
PowTarget: calculatePoW(payload),
PowTime: whisperPoWTime,
}
var hash []byte
var err error
hash, err := p.transport.SendPrivateWithPartitioned(ctx, newMessage, publicKey)
if rawMessage.SendOnPersonalTopic {
hash, err = p.transport.SendPrivateOnPersonalTopic(ctx, newMessage, publicKey)
} else {
hash, err = p.transport.SendPrivateWithPartitioned(ctx, newMessage, publicKey)
}
if err != nil {
return nil, nil, err
}

View File

@ -21,7 +21,7 @@ import (
"github.com/status-im/status-go/protocol/sqlite"
transport "github.com/status-im/status-go/protocol/transport/whisper"
v1protocol "github.com/status-im/status-go/protocol/v1"
"github.com/status-im/status-go/whisper/v6"
"github.com/status-im/status-go/whisper"
)
func TestMessageProcessorSuite(t *testing.T) {

View File

@ -21,4 +21,6 @@ type RawMessage struct {
Payload []byte
Sender *ecdsa.PrivateKey
Recipients []*ecdsa.PublicKey
SkipGroupMessageWrap bool
SendOnPersonalTopic bool
}

View File

@ -46,8 +46,10 @@ func (s *MessengerCommunitiesSuite) SetupTest() {
s.bob = s.newMessenger()
s.alice = s.newMessenger()
s.Require().NoError(s.bob.Start())
s.Require().NoError(s.alice.Start())
_, err := s.bob.Start()
s.Require().NoError(err)
_, err = s.alice.Start()
s.Require().NoError(err)
}
func (s *MessengerCommunitiesSuite) TearDownTest() {
@ -144,9 +146,6 @@ func (s *MessengerCommunitiesSuite) TestRetrieveCommunity() {
}
func (s *MessengerCommunitiesSuite) TestJoinCommunity() {
// start alice and enable sending push notifications
s.Require().NoError(s.alice.Start())
description := &protobuf.CommunityDescription{
Permissions: &protobuf.CommunityPermissions{
Access: protobuf.CommunityPermissions_NO_MEMBERSHIP,

View File

@ -76,3 +76,8 @@ func (e EmojiReaction) MarshalJSON() ([]byte, error) {
return json.Marshal(item)
}
// WrapGroupMessage indicates whether we should wrap this in membership information
func (e EmojiReaction) WrapGroupMessage() bool {
return false
}

View File

@ -1,9 +0,0 @@
package protocol
import "github.com/status-im/status-go/protocol/common"
type MessageNotificationBody struct {
Message *common.Message `json:"message"`
Contact *Contact `json:"contact"`
Chat *Chat `json:"chat"`
}

View File

@ -483,16 +483,6 @@ func (m *MessageHandler) HandleChatMessage(state *ReceivedMessageState) error {
// Add to response
state.Response.Messages = append(state.Response.Messages, receivedMessage)
// Create notification body to be eventually passed to `localnotifications.SendMessageNotifications()`
state.Response.Notifications = append(
state.Response.Notifications,
MessageNotificationBody{
Message: receivedMessage,
Contact: contact,
Chat: chat,
},
)
return nil
}

View File

@ -43,6 +43,7 @@ import (
wakutransp "github.com/status-im/status-go/protocol/transport/waku"
shhtransp "github.com/status-im/status-go/protocol/transport/whisper"
v1protocol "github.com/status-im/status-go/protocol/v1"
"github.com/status-im/status-go/services/mailservers"
)
type chatContext string
@ -98,6 +99,7 @@ type Messenger struct {
database *sql.DB
multiAccounts *multiaccounts.Database
account *multiaccounts.Account
mailserversDatabase *mailservers.Database
quit chan struct{}
mutex sync.Mutex
@ -298,10 +300,10 @@ func NewMessenger(
verifyTransactionClient: c.verifyTransactionClient,
database: database,
multiAccounts: c.multiAccount,
mailserversDatabase: c.mailserversDatabase,
account: c.account,
quit: make(chan struct{}),
shutdownTasks: []func() error{
database.Close,
pushNotificationClient.Stop,
communitiesManager.Stop,
encryptionProtocol.Stop,
@ -311,6 +313,7 @@ func NewMessenger(
// Currently this often fails, seems like it's safe to ignore them
// https://github.com/uber-go/zap/issues/328
func() error { _ = logger.Sync; return nil },
database.Close,
},
logger: logger,
}
@ -392,12 +395,12 @@ func (m *Messenger) resendExpiredEmojiReactions() error {
return nil
}
func (m *Messenger) Start() error {
func (m *Messenger) Start() (*MessengerResponse, error) {
m.logger.Info("starting messenger", zap.String("identity", types.EncodeHex(crypto.FromECDSAPub(&m.identity.PublicKey))))
// Start push notification server
if m.pushNotificationServer != nil {
if err := m.pushNotificationServer.Start(); err != nil {
return err
return nil, err
}
}
@ -406,7 +409,7 @@ func (m *Messenger) Start() error {
m.handlePushNotificationClientRegistrations(m.pushNotificationClient.SubscribeToRegistrations())
if err := m.pushNotificationClient.Start(); err != nil {
return err
return nil, err
}
}
@ -415,13 +418,13 @@ func (m *Messenger) Start() error {
subscriptions, err := m.encryptor.Start(m.identity)
if err != nil {
return err
return nil, err
}
// handle stored shared secrets
err = m.handleSharedSecrets(subscriptions.SharedSecrets)
if err != nil {
return err
return nil, err
}
m.handleEncryptionLayerSubscriptions(subscriptions)
@ -430,7 +433,49 @@ func (m *Messenger) Start() error {
m.watchConnectionChange()
m.watchExpiredEmojis()
m.watchIdentityImageChanges()
return nil
if err := m.cleanTopics(); err != nil {
return nil, err
}
response := &MessengerResponse{Filters: m.transport.Filters()}
if m.mailserversDatabase != nil {
mailserverTopics, err := m.mailserversDatabase.Topics()
if err != nil {
return nil, err
}
response.MailserverTopics = mailserverTopics
mailserverRanges, err := m.mailserversDatabase.ChatRequestRanges()
if err != nil {
return nil, err
}
response.MailserverRanges = mailserverRanges
mailservers, err := m.mailserversDatabase.Mailservers()
if err != nil {
return nil, err
}
response.Mailservers = mailservers
}
return response, nil
}
// cleanTopics remove any topic that does not have a Listen flag set
func (m *Messenger) cleanTopics() error {
if m.mailserversDatabase == nil {
return nil
}
var filters []*transport.Filter
for _, f := range m.transport.Filters() {
if f.Listen && !f.Ephemeral {
filters = append(filters, f)
}
}
m.logger.Debug("keeping topics", zap.Any("filters", filters))
return m.mailserversDatabase.SetTopics(filters)
}
// handle connection change is called each time we go from offline/online or viceversa
@ -1033,8 +1078,12 @@ func (m *Messenger) Init() error {
// Shutdown takes care of ensuring a clean shutdown of Messenger
func (m *Messenger) Shutdown() (err error) {
for _, task := range m.shutdownTasks {
close(m.quit)
for i, task := range m.shutdownTasks {
m.logger.Debug("running shutdown task", zap.Int("n", i))
if tErr := task(); tErr != nil {
m.logger.Info("shutdown task failed", zap.Error(tErr))
if err == nil {
// First error appeared.
err = tErr
@ -1045,7 +1094,6 @@ func (m *Messenger) Shutdown() (err error) {
}
}
}
close(m.quit)
return
}
@ -2271,8 +2319,10 @@ func (m *Messenger) dispatchMessage(ctx context.Context, spec common.RawMessage)
case ChatTypePrivateGroupChat:
logger.Debug("sending group message", zap.String("chatName", chat.Name))
if spec.Recipients == nil {
// Chat messages are only dispatched to users who joined
if spec.MessageType == protobuf.ApplicationMetadataMessage_CHAT_MESSAGE {
// Anything that is not a membership update message is only dispatched to joined users
// NOTE: I think here it might make sense to always invite to joined users apart from the
// initial message
if spec.MessageType != protobuf.ApplicationMetadataMessage_MEMBERSHIP_UPDATE_MESSAGE {
spec.Recipients, err = chat.JoinedMembersAsPublicKeys()
if err != nil {
return nil, err
@ -2285,6 +2335,7 @@ func (m *Messenger) dispatchMessage(ctx context.Context, spec common.RawMessage)
}
}
}
hasPairedDevices := m.hasPairedDevices()
if !hasPairedDevices {
@ -2299,8 +2350,10 @@ func (m *Messenger) dispatchMessage(ctx context.Context, spec common.RawMessage)
spec.Recipients = spec.Recipients[:n]
}
spec.MessageType = protobuf.ApplicationMetadataMessage_MEMBERSHIP_UPDATE_MESSAGE
// We always wrap in group information
// We skip wrapping in some cases (emoji reactions for example)
if !spec.SkipGroupMessageWrap {
spec.MessageType = protobuf.ApplicationMetadataMessage_MEMBERSHIP_UPDATE_MESSAGE
}
id, err = m.processor.SendGroup(ctx, spec.Recipients, spec)
if err != nil {
return nil, err
@ -4390,9 +4443,10 @@ func (m *Messenger) SendEmojiReaction(ctx context.Context, chatID, messageID str
}
_, err = m.dispatchMessage(ctx, common.RawMessage{
LocalChatID: chatID,
Payload: encodedMessage,
MessageType: protobuf.ApplicationMetadataMessage_EMOJI_REACTION,
LocalChatID: chatID,
Payload: encodedMessage,
SkipGroupMessageWrap: true,
MessageType: protobuf.ApplicationMetadataMessage_EMOJI_REACTION,
// Don't resend using datasync, that would create quite a lot
// of traffic if clicking too eagelry
ResendAutomatically: false,
@ -4467,9 +4521,10 @@ func (m *Messenger) SendEmojiReactionRetraction(ctx context.Context, emojiReacti
// Send the marshalled EmojiReactionRetraction protobuf
_, err = m.dispatchMessage(ctx, common.RawMessage{
LocalChatID: emojiR.GetChatId(),
Payload: encodedMessage,
MessageType: protobuf.ApplicationMetadataMessage_EMOJI_REACTION,
LocalChatID: emojiR.GetChatId(),
Payload: encodedMessage,
SkipGroupMessageWrap: true,
MessageType: protobuf.ApplicationMetadataMessage_EMOJI_REACTION,
// Don't resend using datasync, that would create quite a lot
// of traffic if clicking too eagelry
ResendAutomatically: false,
@ -4524,15 +4579,22 @@ func (m *Messenger) encodeChatEntity(chat *Chat, message common.ChatEntity) ([]b
case ChatTypePrivateGroupChat:
message.SetMessageType(protobuf.MessageType_PRIVATE_GROUP)
l.Debug("sending group message", zap.String("chatName", chat.Name))
if !message.WrapGroupMessage() {
encodedMessage, err = proto.Marshal(message.GetProtobuf())
if err != nil {
return nil, err
}
} else {
group, err := newProtocolGroupFromChat(chat)
if err != nil {
return nil, err
}
group, err := newProtocolGroupFromChat(chat)
if err != nil {
return nil, err
}
encodedMessage, err = m.processor.EncodeMembershipUpdate(group, message)
if err != nil {
return nil, err
encodedMessage, err = m.processor.EncodeAbridgedMembershipUpdate(group, message)
if err != nil {
return nil, err
}
}
default:

View File

@ -11,6 +11,7 @@ import (
"github.com/status-im/status-go/protocol/pushnotificationclient"
"github.com/status-im/status-go/protocol/pushnotificationserver"
"github.com/status-im/status-go/protocol/transport"
"github.com/status-im/status-go/services/mailservers"
)
type config struct {
@ -28,10 +29,11 @@ type config struct {
// A path to a database or a database instance is required.
// The database instance has a higher priority.
dbConfig dbConfig
db *sql.DB
multiAccount *multiaccounts.Database
account *multiaccounts.Account
dbConfig dbConfig
db *sql.DB
multiAccount *multiaccounts.Database
mailserversDatabase *mailservers.Database
account *multiaccounts.Account
verifyTransactionClient EthClient
@ -94,6 +96,13 @@ func WithMultiAccounts(ma *multiaccounts.Database) Option {
}
}
func WithMailserversDatabase(ma *mailservers.Database) Option {
return func(c *config) error {
c.mailserversDatabase = ma
return nil
}
}
func WithAccount(acc *multiaccounts.Account) Option {
return func(c *config) error {
c.account = acc

View File

@ -40,7 +40,8 @@ func (s *MessengerContactUpdateSuite) SetupTest() {
s.m = s.newMessenger(s.shh)
s.privateKey = s.m.identity
s.Require().NoError(s.m.Start())
_, err := s.m.Start()
s.Require().NoError(err)
}
func (s *MessengerContactUpdateSuite) TearDownTest() {
@ -62,7 +63,8 @@ func (s *MessengerContactUpdateSuite) TestReceiveContactUpdate() {
contactID := types.EncodeHex(crypto.FromECDSAPub(&s.m.identity.PublicKey))
theirMessenger := s.newMessenger(s.shh)
s.Require().NoError(theirMessenger.Start())
_, err := theirMessenger.Start()
s.Require().NoError(err)
theirContactID := types.EncodeHex(crypto.FromECDSAPub(&theirMessenger.identity.PublicKey))
response, err := theirMessenger.SendContactUpdate(context.Background(), contactID, theirName, theirPicture)
@ -124,7 +126,8 @@ func (s *MessengerContactUpdateSuite) TestAddContact() {
contactID := types.EncodeHex(crypto.FromECDSAPub(&s.m.identity.PublicKey))
theirMessenger := s.newMessenger(s.shh)
s.Require().NoError(theirMessenger.Start())
_, err := theirMessenger.Start()
s.Require().NoError(err)
response, err := theirMessenger.AddContact(context.Background(), contactID)
s.Require().NoError(err)

View File

@ -44,7 +44,8 @@ func (s *MessengerEmojiSuite) SetupTest() {
s.m = s.newMessenger(s.shh)
s.privateKey = s.m.identity
s.Require().NoError(s.m.Start())
_, err := s.m.Start()
s.Require().NoError(err)
}
func (s *MessengerEmojiSuite) TearDownTest() {
@ -147,7 +148,8 @@ func (s *MessengerEmojiSuite) TestSendEmoji() {
func (s *MessengerEmojiSuite) TestEmojiPrivateGroup() {
bob := s.m
alice := s.newMessenger(s.shh)
s.Require().NoError(alice.Start())
_, err := alice.Start()
s.Require().NoError(err)
response, err := bob.CreateGroupChatWithMembers(context.Background(), "test", []string{})
s.NoError(err)

View File

@ -47,7 +47,8 @@ func (s *MessengerInstallationSuite) SetupTest() {
s.m = s.newMessenger(s.shh)
s.privateKey = s.m.identity
// We start the messenger in order to receive installations
s.Require().NoError(s.m.Start())
_, err := s.m.Start()
s.Require().NoError(err)
}
func (s *MessengerInstallationSuite) TearDownTest() {

View File

@ -41,7 +41,8 @@ func (s *MessengerMuteSuite) SetupTest() {
s.m = s.newMessenger(s.shh)
s.privateKey = s.m.identity
s.Require().NoError(s.m.Start())
_, err := s.m.Start()
s.Require().NoError(err)
}
func (s *MessengerMuteSuite) TearDownTest() {

View File

@ -5,6 +5,7 @@ import (
"github.com/status-im/status-go/protocol/communities"
"github.com/status-im/status-go/protocol/encryption/multidevice"
"github.com/status-im/status-go/protocol/transport"
"github.com/status-im/status-go/services/mailservers"
)
type MessengerResponse struct {
@ -19,13 +20,13 @@ type MessengerResponse struct {
CommunityChanges []*communities.CommunityChanges `json:"communitiesChanges,omitempty"`
Filters []*transport.Filter `json:"filters,omitempty"`
RemovedFilters []*transport.Filter `json:"removedFilters,omitempty"`
// Notifications a list of MessageNotificationBody derived from received messages that are useful to notify the user about
Notifications []MessageNotificationBody `json:"notifications"`
Mailservers []mailservers.Mailserver `json:"mailservers,omitempty"`
MailserverTopics []mailservers.MailserverTopic `json:"mailserverTopics,omitempty"`
MailserverRanges []mailservers.ChatRequestRange `json:"mailserverRanges,omitempty"`
}
func (m *MessengerResponse) IsEmpty() bool {
return len(m.Chats)+len(m.Messages)+len(m.Contacts)+len(m.Installations)+len(m.Invitations)+len(m.EmojiReactions)+len(m.Communities)+len(m.CommunityChanges)+len(m.Filters)+len(m.RemovedFilters)+len(m.RemovedChats)+len(m.Notifications) == 0
return len(m.Chats)+len(m.Messages)+len(m.Contacts)+len(m.Installations)+len(m.Invitations)+len(m.EmojiReactions)+len(m.Communities)+len(m.CommunityChanges)+len(m.Filters)+len(m.RemovedFilters)+len(m.RemovedChats)+len(m.MailserverTopics)+len(m.Mailservers)+len(m.MailserverRanges) == 0
}
// Merge takes another response and appends the new Chats & new Messages and replaces

View File

@ -109,7 +109,8 @@ func (s *MessengerSuite) SetupTest() {
s.m = s.newMessenger(s.shh)
s.privateKey = s.m.identity
s.Require().NoError(s.m.Start())
_, err := s.m.Start()
s.Require().NoError(err)
}
func newMessengerWithKey(shh types.Waku, privateKey *ecdsa.PrivateKey, logger *zap.Logger, extraOptions []Option) (*Messenger, error) {
@ -150,7 +151,7 @@ func newMessengerWithKey(shh types.Waku, privateKey *ecdsa.PrivateKey, logger *z
return nil, err
}
err = m.Start()
_, err = m.Start()
if err != nil {
return nil, err
}
@ -560,9 +561,10 @@ func (s *MessengerSuite) TestRetrieveOwnPublic() {
// Retrieve their public message
func (s *MessengerSuite) TestRetrieveTheirPublic() {
theirMessenger := s.newMessenger(s.shh)
s.Require().NoError(theirMessenger.Start())
_, err := theirMessenger.Start()
s.Require().NoError(err)
theirChat := CreatePublicChat("status", s.m.transport)
err := theirMessenger.SaveChat(&theirChat)
err = theirMessenger.SaveChat(&theirChat)
s.Require().NoError(err)
chat := CreatePublicChat("status", s.m.transport)
@ -602,9 +604,10 @@ func (s *MessengerSuite) TestRetrieveTheirPublic() {
func (s *MessengerSuite) TestDeletedAtClockValue() {
theirMessenger := s.newMessenger(s.shh)
s.Require().NoError(theirMessenger.Start())
_, err := theirMessenger.Start()
s.Require().NoError(err)
theirChat := CreatePublicChat("status", s.m.transport)
err := theirMessenger.SaveChat(&theirChat)
err = theirMessenger.SaveChat(&theirChat)
s.Require().NoError(err)
chat := CreatePublicChat("status", s.m.transport)
@ -633,9 +636,10 @@ func (s *MessengerSuite) TestDeletedAtClockValue() {
func (s *MessengerSuite) TestRetrieveBlockedContact() {
theirMessenger := s.newMessenger(s.shh)
s.Require().NoError(theirMessenger.Start())
_, err := theirMessenger.Start()
s.Require().NoError(err)
theirChat := CreatePublicChat("status", s.m.transport)
err := theirMessenger.SaveChat(&theirChat)
err = theirMessenger.SaveChat(&theirChat)
s.Require().NoError(err)
chat := CreatePublicChat("status", s.m.transport)
@ -671,9 +675,10 @@ func (s *MessengerSuite) TestRetrieveBlockedContact() {
// Resend their public message, receive only once
func (s *MessengerSuite) TestResendPublicMessage() {
theirMessenger := s.newMessenger(s.shh)
s.Require().NoError(theirMessenger.Start())
_, err := theirMessenger.Start()
s.Require().NoError(err)
theirChat := CreatePublicChat("status", s.m.transport)
err := theirMessenger.SaveChat(&theirChat)
err = theirMessenger.SaveChat(&theirChat)
s.Require().NoError(err)
chat := CreatePublicChat("status", s.m.transport)
@ -725,9 +730,10 @@ func (s *MessengerSuite) TestResendPublicMessage() {
// Test receiving a message on an existing private chat
func (s *MessengerSuite) TestRetrieveTheirPrivateChatExisting() {
theirMessenger := s.newMessenger(s.shh)
s.Require().NoError(theirMessenger.Start())
_, err := theirMessenger.Start()
s.Require().NoError(err)
theirChat := CreateOneToOneChat("XXX", &s.privateKey.PublicKey, s.m.transport)
err := theirMessenger.SaveChat(&theirChat)
err = theirMessenger.SaveChat(&theirChat)
s.Require().NoError(err)
ourChat := CreateOneToOneChat("our-chat", &theirMessenger.identity.PublicKey, s.m.transport)
@ -767,9 +773,10 @@ func (s *MessengerSuite) TestRetrieveTheirPrivateChatExisting() {
// Test receiving a message on an non-existing private chat
func (s *MessengerSuite) TestRetrieveTheirPrivateChatNonExisting() {
theirMessenger := s.newMessenger(s.shh)
s.Require().NoError(theirMessenger.Start())
_, err := theirMessenger.Start()
s.Require().NoError(err)
chat := CreateOneToOneChat("XXX", &s.privateKey.PublicKey, s.m.transport)
err := theirMessenger.SaveChat(&chat)
err = theirMessenger.SaveChat(&chat)
s.NoError(err)
inputMessage := buildTestMessage(chat)
@ -804,9 +811,10 @@ func (s *MessengerSuite) TestRetrieveTheirPrivateChatNonExisting() {
// Test receiving a message on an non-existing public chat
func (s *MessengerSuite) TestRetrieveTheirPublicChatNonExisting() {
theirMessenger := s.newMessenger(s.shh)
s.Require().NoError(theirMessenger.Start())
_, err := theirMessenger.Start()
s.Require().NoError(err)
chat := CreatePublicChat("test-chat", s.m.transport)
err := theirMessenger.SaveChat(&chat)
err = theirMessenger.SaveChat(&chat)
s.NoError(err)
inputMessage := buildTestMessage(chat)
@ -829,8 +837,9 @@ func (s *MessengerSuite) TestRetrieveTheirPublicChatNonExisting() {
func (s *MessengerSuite) TestRetrieveTheirPrivateGroupChat() {
var response *MessengerResponse
theirMessenger := s.newMessenger(s.shh)
s.Require().NoError(theirMessenger.Start())
response, err := s.m.CreateGroupChatWithMembers(context.Background(), "id", []string{})
_, err := theirMessenger.Start()
s.Require().NoError(err)
response, err = s.m.CreateGroupChatWithMembers(context.Background(), "id", []string{})
s.NoError(err)
s.Require().Len(response.Chats, 1)
@ -891,8 +900,9 @@ func (s *MessengerSuite) TestRetrieveTheirPrivateGroupChat() {
func (s *MessengerSuite) TestChangeNameGroupChat() {
var response *MessengerResponse
theirMessenger := s.newMessenger(s.shh)
s.Require().NoError(theirMessenger.Start())
response, err := s.m.CreateGroupChatWithMembers(context.Background(), "old-name", []string{})
_, err := theirMessenger.Start()
s.Require().NoError(err)
response, err = s.m.CreateGroupChatWithMembers(context.Background(), "old-name", []string{})
s.NoError(err)
s.Require().Len(response.Chats, 1)
@ -945,8 +955,9 @@ func (s *MessengerSuite) TestChangeNameGroupChat() {
func (s *MessengerSuite) TestReInvitedToGroupChat() {
var response *MessengerResponse
theirMessenger := s.newMessenger(s.shh)
s.Require().NoError(theirMessenger.Start())
response, err := s.m.CreateGroupChatWithMembers(context.Background(), "old-name", []string{})
_, err := theirMessenger.Start()
s.Require().NoError(err)
response, err = s.m.CreateGroupChatWithMembers(context.Background(), "old-name", []string{})
s.NoError(err)
s.Require().Len(response.Chats, 1)
@ -1512,11 +1523,12 @@ func (s *MessengerSuite) TestDeclineRequestAddressForTransaction() {
value := testValue
contract := testContract
theirMessenger := s.newMessenger(s.shh)
s.Require().NoError(theirMessenger.Start())
_, err := theirMessenger.Start()
s.Require().NoError(err)
theirPkString := types.EncodeHex(crypto.FromECDSAPub(&theirMessenger.identity.PublicKey))
chat := CreateOneToOneChat(theirPkString, &theirMessenger.identity.PublicKey, s.m.transport)
err := s.m.SaveChat(&chat)
err = s.m.SaveChat(&chat)
s.Require().NoError(err)
myAddress := crypto.PubkeyToAddress(s.m.identity.PublicKey)
@ -1603,14 +1615,15 @@ func (s *MessengerSuite) TestSendEthTransaction() {
contract := testContract
theirMessenger := s.newMessenger(s.shh)
s.Require().NoError(theirMessenger.Start())
_, err := theirMessenger.Start()
s.Require().NoError(err)
theirPkString := types.EncodeHex(crypto.FromECDSAPub(&theirMessenger.identity.PublicKey))
receiverAddress := crypto.PubkeyToAddress(theirMessenger.identity.PublicKey)
receiverAddressString := strings.ToLower(receiverAddress.Hex())
chat := CreateOneToOneChat(theirPkString, &theirMessenger.identity.PublicKey, s.m.transport)
err := s.m.SaveChat(&chat)
err = s.m.SaveChat(&chat)
s.Require().NoError(err)
transactionHash := testTransactionHash
@ -1706,14 +1719,15 @@ func (s *MessengerSuite) TestSendTokenTransaction() {
contract := testContract
theirMessenger := s.newMessenger(s.shh)
s.Require().NoError(theirMessenger.Start())
_, err := theirMessenger.Start()
s.Require().NoError(err)
theirPkString := types.EncodeHex(crypto.FromECDSAPub(&theirMessenger.identity.PublicKey))
receiverAddress := crypto.PubkeyToAddress(theirMessenger.identity.PublicKey)
receiverAddressString := strings.ToLower(receiverAddress.Hex())
chat := CreateOneToOneChat(theirPkString, &theirMessenger.identity.PublicKey, s.m.transport)
err := s.m.SaveChat(&chat)
err = s.m.SaveChat(&chat)
s.Require().NoError(err)
transactionHash := testTransactionHash
@ -1808,13 +1822,14 @@ func (s *MessengerSuite) TestAcceptRequestAddressForTransaction() {
value := testValue
contract := testContract
theirMessenger := s.newMessenger(s.shh)
s.Require().NoError(theirMessenger.Start())
_, err := theirMessenger.Start()
s.Require().NoError(err)
theirPkString := types.EncodeHex(crypto.FromECDSAPub(&theirMessenger.identity.PublicKey))
myAddress := crypto.PubkeyToAddress(s.m.identity.PublicKey)
chat := CreateOneToOneChat(theirPkString, &theirMessenger.identity.PublicKey, s.m.transport)
err := s.m.SaveChat(&chat)
err = s.m.SaveChat(&chat)
s.Require().NoError(err)
response, err := s.m.RequestAddressForTransaction(context.Background(), theirPkString, myAddress.Hex(), value, contract)
@ -1902,11 +1917,12 @@ func (s *MessengerSuite) TestDeclineRequestTransaction() {
receiverAddress := crypto.PubkeyToAddress(s.m.identity.PublicKey)
receiverAddressString := strings.ToLower(receiverAddress.Hex())
theirMessenger := s.newMessenger(s.shh)
s.Require().NoError(theirMessenger.Start())
_, err := theirMessenger.Start()
s.Require().NoError(err)
theirPkString := types.EncodeHex(crypto.FromECDSAPub(&theirMessenger.identity.PublicKey))
chat := CreateOneToOneChat(theirPkString, &theirMessenger.identity.PublicKey, s.m.transport)
err := s.m.SaveChat(&chat)
err = s.m.SaveChat(&chat)
s.Require().NoError(err)
response, err := s.m.RequestTransaction(context.Background(), theirPkString, value, contract, receiverAddressString)
@ -1991,11 +2007,12 @@ func (s *MessengerSuite) TestRequestTransaction() {
receiverAddress := crypto.PubkeyToAddress(s.m.identity.PublicKey)
receiverAddressString := strings.ToLower(receiverAddress.Hex())
theirMessenger := s.newMessenger(s.shh)
s.Require().NoError(theirMessenger.Start())
_, err := theirMessenger.Start()
s.Require().NoError(err)
theirPkString := types.EncodeHex(crypto.FromECDSAPub(&theirMessenger.identity.PublicKey))
chat := CreateOneToOneChat(theirPkString, &theirMessenger.identity.PublicKey, s.m.transport)
err := s.m.SaveChat(&chat)
err = s.m.SaveChat(&chat)
s.Require().NoError(err)
response, err := s.m.RequestTransaction(context.Background(), theirPkString, value, contract, receiverAddressString)

View File

@ -21,6 +21,8 @@
// 1603888149_create_chat_identity_last_published_table.up.sql (407B)
// 1605075346_add_communities.up.sql (6.971kB)
// 1610117927_add_message_cache.up.sql (142B)
// 1610959908_add_dont_wrap_to_raw_messages.up.sql (83B)
// 1610960912_add_send_on_personal_topic.up.sql (82B)
// README.md (554B)
// doc.go (850B)
@ -166,7 +168,7 @@ func _1586358095_add_replaceUpSql() (*asset, error) {
return nil, err
}
info := bindataFileInfo{name: "1586358095_add_replace.up.sql", size: 224, mode: os.FileMode(0644), modTime: time.Unix(1610007618, 0)}
info := bindataFileInfo{name: "1586358095_add_replace.up.sql", size: 224, mode: os.FileMode(0644), modTime: time.Unix(1611588719, 0)}
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xd2, 0xb3, 0xa9, 0xc7, 0x7f, 0x9d, 0x8f, 0x43, 0x8c, 0x9e, 0x58, 0x8d, 0x44, 0xbc, 0xfa, 0x6b, 0x5f, 0x3f, 0x5a, 0xbe, 0xe8, 0xb1, 0x16, 0xf, 0x91, 0x2a, 0xa0, 0x71, 0xbb, 0x8d, 0x6b, 0xcb}}
return a, nil
}
@ -186,7 +188,7 @@ func _1588665364_add_image_dataUpSql() (*asset, error) {
return nil, err
}
info := bindataFileInfo{name: "1588665364_add_image_data.up.sql", size: 186, mode: os.FileMode(0644), modTime: time.Unix(1610007618, 0)}
info := bindataFileInfo{name: "1588665364_add_image_data.up.sql", size: 186, mode: os.FileMode(0644), modTime: time.Unix(1611588719, 0)}
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xd6, 0xc6, 0x35, 0xb4, 0x4c, 0x39, 0x96, 0x29, 0x30, 0xda, 0xf4, 0x8f, 0xcb, 0xf1, 0x9f, 0x84, 0xdc, 0x88, 0xd4, 0xd5, 0xbc, 0xb6, 0x5b, 0x46, 0x78, 0x67, 0x76, 0x1a, 0x5, 0x36, 0xdc, 0xe5}}
return a, nil
}
@ -206,7 +208,7 @@ func _1589365189_add_pow_targetUpSql() (*asset, error) {
return nil, err
}
info := bindataFileInfo{name: "1589365189_add_pow_target.up.sql", size: 66, mode: os.FileMode(0644), modTime: time.Unix(1610007618, 0)}
info := bindataFileInfo{name: "1589365189_add_pow_target.up.sql", size: 66, mode: os.FileMode(0644), modTime: time.Unix(1611588719, 0)}
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x4e, 0x3a, 0xe2, 0x2e, 0x7d, 0xaf, 0xbb, 0xcc, 0x21, 0xa1, 0x7a, 0x41, 0x9a, 0xd0, 0xbb, 0xa9, 0xc8, 0x35, 0xf9, 0x32, 0x34, 0x46, 0x44, 0x9a, 0x86, 0x40, 0x7c, 0xb9, 0x23, 0xc7, 0x3, 0x3f}}
return a, nil
}
@ -226,7 +228,7 @@ func _1591277220_add_index_messagesUpSql() (*asset, error) {
return nil, err
}
info := bindataFileInfo{name: "1591277220_add_index_messages.up.sql", size: 240, mode: os.FileMode(0644), modTime: time.Unix(1610007618, 0)}
info := bindataFileInfo{name: "1591277220_add_index_messages.up.sql", size: 240, mode: os.FileMode(0644), modTime: time.Unix(1611588719, 0)}
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x9c, 0xfe, 0xbe, 0xd5, 0xb8, 0x8f, 0xdd, 0xef, 0xbb, 0xa8, 0xad, 0x7f, 0xed, 0x5b, 0x5b, 0x2f, 0xe6, 0x82, 0x27, 0x78, 0x1f, 0xb9, 0x57, 0xdc, 0x8, 0xc2, 0xb2, 0xa9, 0x9a, 0x4, 0xe1, 0x7a}}
return a, nil
}
@ -246,7 +248,7 @@ func _1593087212_add_mute_chat_and_raw_message_fieldsUpSql() (*asset, error) {
return nil, err
}
info := bindataFileInfo{name: "1593087212_add_mute_chat_and_raw_message_fields.up.sql", size: 215, mode: os.FileMode(0644), modTime: time.Unix(1610007618, 0)}
info := bindataFileInfo{name: "1593087212_add_mute_chat_and_raw_message_fields.up.sql", size: 215, mode: os.FileMode(0644), modTime: time.Unix(1611588835, 0)}
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x73, 0x99, 0x61, 0xd1, 0xaa, 0xb4, 0xbf, 0xaf, 0xd7, 0x20, 0x17, 0x40, 0xf9, 0x2, 0xfb, 0xcc, 0x40, 0x2a, 0xd, 0x86, 0x36, 0x30, 0x88, 0x89, 0x25, 0x80, 0x42, 0xb0, 0x5b, 0xe9, 0x73, 0x78}}
return a, nil
}
@ -266,7 +268,7 @@ func _1595862781_add_audio_dataUpSql() (*asset, error) {
return nil, err
}
info := bindataFileInfo{name: "1595862781_add_audio_data.up.sql", size: 246, mode: os.FileMode(0644), modTime: time.Unix(1610007618, 0)}
info := bindataFileInfo{name: "1595862781_add_audio_data.up.sql", size: 246, mode: os.FileMode(0644), modTime: time.Unix(1611588835, 0)}
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xae, 0xd2, 0xee, 0x55, 0xfb, 0x36, 0xa4, 0x92, 0x66, 0xe, 0x81, 0x62, 0x1e, 0x7a, 0x69, 0xa, 0xd5, 0x4b, 0xa5, 0x6a, 0x8d, 0x1d, 0xce, 0xf3, 0x3e, 0xc0, 0x5f, 0x9c, 0x66, 0x1b, 0xb4, 0xed}}
return a, nil
}
@ -286,7 +288,7 @@ func _1595865249_create_emoji_reactions_tableUpSql() (*asset, error) {
return nil, err
}
info := bindataFileInfo{name: "1595865249_create_emoji_reactions_table.up.sql", size: 300, mode: os.FileMode(0644), modTime: time.Unix(1610007618, 0)}
info := bindataFileInfo{name: "1595865249_create_emoji_reactions_table.up.sql", size: 300, mode: os.FileMode(0644), modTime: time.Unix(1611588835, 0)}
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x3e, 0xc5, 0x43, 0x5c, 0x3d, 0x53, 0x43, 0x2c, 0x1a, 0xa5, 0xb6, 0xbf, 0x7, 0x4, 0x5a, 0x3e, 0x40, 0x8b, 0xa4, 0x57, 0x12, 0x58, 0xbc, 0x42, 0xe2, 0xc3, 0xde, 0x76, 0x98, 0x80, 0xe2, 0xbe}}
return a, nil
}
@ -306,7 +308,7 @@ func _1596805115_create_group_chat_invitations_tableUpSql() (*asset, error) {
return nil, err
}
info := bindataFileInfo{name: "1596805115_create_group_chat_invitations_table.up.sql", size: 231, mode: os.FileMode(0644), modTime: time.Unix(1610007618, 0)}
info := bindataFileInfo{name: "1596805115_create_group_chat_invitations_table.up.sql", size: 231, mode: os.FileMode(0644), modTime: time.Unix(1611588835, 0)}
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x6d, 0xb1, 0x14, 0x6d, 0x54, 0x28, 0x67, 0xc3, 0x23, 0x6a, 0xfc, 0x80, 0xdf, 0x9e, 0x4c, 0x35, 0x36, 0xf, 0xf8, 0xf3, 0x5f, 0xae, 0xad, 0xb, 0xc1, 0x51, 0x8e, 0x17, 0x7, 0xe5, 0x7f, 0x91}}
return a, nil
}
@ -326,7 +328,7 @@ func _1597322655_add_invitation_admin_chat_fieldUpSql() (*asset, error) {
return nil, err
}
info := bindataFileInfo{name: "1597322655_add_invitation_admin_chat_field.up.sql", size: 54, mode: os.FileMode(0644), modTime: time.Unix(1610007618, 0)}
info := bindataFileInfo{name: "1597322655_add_invitation_admin_chat_field.up.sql", size: 54, mode: os.FileMode(0644), modTime: time.Unix(1611588835, 0)}
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xa9, 0x7a, 0xa0, 0xf2, 0xdb, 0x13, 0x91, 0x91, 0xa8, 0x34, 0x1a, 0xa1, 0x49, 0x68, 0xd5, 0xae, 0x2c, 0xd8, 0xd5, 0xea, 0x8f, 0x8c, 0xc7, 0x2, 0x4e, 0x58, 0x2c, 0x3a, 0x14, 0xd4, 0x4f, 0x2c}}
return a, nil
}
@ -346,7 +348,7 @@ func _1597757544_add_nicknameUpSql() (*asset, error) {
return nil, err
}
info := bindataFileInfo{name: "1597757544_add_nickname.up.sql", size: 52, mode: os.FileMode(0644), modTime: time.Unix(1610007618, 0)}
info := bindataFileInfo{name: "1597757544_add_nickname.up.sql", size: 52, mode: os.FileMode(0644), modTime: time.Unix(1611588835, 0)}
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xf4, 0xa2, 0x64, 0x50, 0xc5, 0x4, 0xb9, 0x8b, 0xd1, 0x18, 0x9b, 0xc3, 0x91, 0x36, 0x2a, 0x1f, 0xc3, 0x6c, 0x2d, 0x92, 0xf8, 0x5e, 0xff, 0xb1, 0x59, 0x61, 0x2, 0x1c, 0xe1, 0x85, 0x90, 0xa4}}
return a, nil
}
@ -366,7 +368,7 @@ func _1598955122_add_mentionsUpSql() (*asset, error) {
return nil, err
}
info := bindataFileInfo{name: "1598955122_add_mentions.up.sql", size: 52, mode: os.FileMode(0644), modTime: time.Unix(1610007618, 0)}
info := bindataFileInfo{name: "1598955122_add_mentions.up.sql", size: 52, mode: os.FileMode(0644), modTime: time.Unix(1611588835, 0)}
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x8d, 0x22, 0x17, 0x92, 0xd2, 0x11, 0x4e, 0x7, 0x93, 0x9a, 0x55, 0xfd, 0xb, 0x97, 0xc4, 0x63, 0x6a, 0x81, 0x97, 0xcd, 0xb2, 0xf8, 0x4b, 0x5f, 0x3c, 0xfa, 0x3a, 0x38, 0x53, 0x10, 0xed, 0x9d}}
return a, nil
}
@ -386,7 +388,7 @@ func _1599641390_add_emoji_reactions_indexUpSql() (*asset, error) {
return nil, err
}
info := bindataFileInfo{name: "1599641390_add_emoji_reactions_index.up.sql", size: 126, mode: os.FileMode(0644), modTime: time.Unix(1610007618, 0)}
info := bindataFileInfo{name: "1599641390_add_emoji_reactions_index.up.sql", size: 126, mode: os.FileMode(0644), modTime: time.Unix(1611588835, 0)}
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xf9, 0xd8, 0xdc, 0xa7, 0xb, 0x92, 0x7a, 0x61, 0x37, 0x24, 0x1c, 0x77, 0x5e, 0xe, 0x7e, 0xfc, 0x9f, 0x98, 0x7b, 0x65, 0xe7, 0xf9, 0x71, 0x57, 0x89, 0x2d, 0x90, 0x1b, 0xf6, 0x5e, 0x37, 0xe8}}
return a, nil
}
@ -406,7 +408,7 @@ func _1599720851_add_seen_index_remove_long_messagesUpSql() (*asset, error) {
return nil, err
}
info := bindataFileInfo{name: "1599720851_add_seen_index_remove_long_messages.up.sql", size: 150, mode: os.FileMode(0644), modTime: time.Unix(1610007618, 0)}
info := bindataFileInfo{name: "1599720851_add_seen_index_remove_long_messages.up.sql", size: 150, mode: os.FileMode(0644), modTime: time.Unix(1611588835, 0)}
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x24, 0x1c, 0xc4, 0x78, 0x91, 0xc7, 0xeb, 0xfe, 0xc8, 0xa0, 0xd8, 0x13, 0x27, 0x97, 0xc8, 0x96, 0x56, 0x97, 0x33, 0x2c, 0x1e, 0x16, 0x8a, 0xd3, 0x49, 0x99, 0x3, 0xe9, 0xbb, 0xc4, 0x5, 0x3c}}
return a, nil
}
@ -426,7 +428,7 @@ func _1603198582_add_profile_chat_fieldUpSql() (*asset, error) {
return nil, err
}
info := bindataFileInfo{name: "1603198582_add_profile_chat_field.up.sql", size: 45, mode: os.FileMode(0644), modTime: time.Unix(1610007618, 0)}
info := bindataFileInfo{name: "1603198582_add_profile_chat_field.up.sql", size: 45, mode: os.FileMode(0644), modTime: time.Unix(1611588835, 0)}
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xaa, 0xca, 0xe, 0x46, 0xa0, 0x9, 0x9d, 0x47, 0x57, 0xe9, 0xfb, 0x17, 0xeb, 0x9c, 0xf6, 0xb8, 0x1d, 0xe9, 0xd, 0x0, 0xd5, 0xe5, 0xd8, 0x9e, 0x60, 0xa, 0xbf, 0x32, 0x2c, 0x52, 0x7f, 0x6a}}
return a, nil
}
@ -446,7 +448,7 @@ func _1603816533_add_linksUpSql() (*asset, error) {
return nil, err
}
info := bindataFileInfo{name: "1603816533_add_links.up.sql", size: 48, mode: os.FileMode(0644), modTime: time.Unix(1610007618, 0)}
info := bindataFileInfo{name: "1603816533_add_links.up.sql", size: 48, mode: os.FileMode(0644), modTime: time.Unix(1611588835, 0)}
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xc9, 0x24, 0xd6, 0x1d, 0xa, 0x83, 0x1e, 0x4d, 0xf, 0xae, 0x4d, 0x8c, 0x51, 0x32, 0xa8, 0x37, 0xb0, 0x14, 0xfb, 0x32, 0x34, 0xc8, 0xc, 0x4e, 0x5b, 0xc5, 0x15, 0x65, 0x73, 0x0, 0x0, 0x1d}}
return a, nil
}
@ -466,7 +468,7 @@ func _1603888149_create_chat_identity_last_published_tableUpSql() (*asset, error
return nil, err
}
info := bindataFileInfo{name: "1603888149_create_chat_identity_last_published_table.up.sql", size: 407, mode: os.FileMode(0644), modTime: time.Unix(1610007618, 0)}
info := bindataFileInfo{name: "1603888149_create_chat_identity_last_published_table.up.sql", size: 407, mode: os.FileMode(0644), modTime: time.Unix(1611588835, 0)}
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x7f, 0x9, 0xf, 0xfb, 0xdb, 0x3c, 0x86, 0x70, 0x82, 0xda, 0x10, 0x25, 0xe2, 0x4e, 0x40, 0x45, 0xab, 0x8b, 0x1c, 0x91, 0x7c, 0xf1, 0x70, 0x2e, 0x81, 0xf3, 0x71, 0x45, 0xda, 0xe2, 0xa4, 0x57}}
return a, nil
}
@ -486,7 +488,7 @@ func _1605075346_add_communitiesUpSql() (*asset, error) {
return nil, err
}
info := bindataFileInfo{name: "1605075346_add_communities.up.sql", size: 6971, mode: os.FileMode(0644), modTime: time.Unix(1610638422, 0)}
info := bindataFileInfo{name: "1605075346_add_communities.up.sql", size: 6971, mode: os.FileMode(0644), modTime: time.Unix(1611588835, 0)}
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x1f, 0x64, 0xea, 0xb4, 0xae, 0x9e, 0xdb, 0x9, 0x58, 0xb6, 0x5c, 0x7a, 0x50, 0xc5, 0xfe, 0x93, 0x5d, 0x36, 0x85, 0x5d, 0x6a, 0xba, 0xc9, 0x7e, 0x84, 0xd7, 0xbf, 0x2a, 0x53, 0xf3, 0x97, 0xf1}}
return a, nil
}
@ -506,11 +508,51 @@ func _1610117927_add_message_cacheUpSql() (*asset, error) {
return nil, err
}
info := bindataFileInfo{name: "1610117927_add_message_cache.up.sql", size: 142, mode: os.FileMode(0644), modTime: time.Unix(1610715642, 0)}
info := bindataFileInfo{name: "1610117927_add_message_cache.up.sql", size: 142, mode: os.FileMode(0644), modTime: time.Unix(1611588835, 0)}
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x34, 0xf1, 0xf0, 0x82, 0x79, 0x28, 0x19, 0xc2, 0x39, 0x6a, 0xa5, 0x96, 0x59, 0x23, 0xa0, 0xed, 0x60, 0x58, 0x86, 0x9, 0xb9, 0xad, 0xfb, 0xa, 0xe3, 0x47, 0x6e, 0xa1, 0x18, 0xe8, 0x39, 0x2c}}
return a, nil
}
var __1610959908_add_dont_wrap_to_raw_messagesUpSql = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x72\xf4\x09\x71\x0d\x52\x08\x71\x74\xf2\x71\x55\x28\x4a\x2c\x8f\xcf\x4d\x2d\x2e\x4e\x4c\x4f\x2d\x56\x70\x74\x71\x51\x70\xf6\xf7\x09\xf5\xf5\x53\x28\xce\xce\x2c\x88\x4f\x2f\xca\x2f\x2d\x80\x49\xc7\x97\x17\x25\x16\x28\x38\xf9\xfb\xfb\xb8\x3a\xfa\x29\xb8\xb8\xba\x39\x86\xfa\x84\x28\xb8\x39\xfa\x04\xbb\x5a\x73\x01\x02\x00\x00\xff\xff\x3c\x1f\xd3\xe4\x53\x00\x00\x00")
func _1610959908_add_dont_wrap_to_raw_messagesUpSqlBytes() ([]byte, error) {
return bindataRead(
__1610959908_add_dont_wrap_to_raw_messagesUpSql,
"1610959908_add_dont_wrap_to_raw_messages.up.sql",
)
}
func _1610959908_add_dont_wrap_to_raw_messagesUpSql() (*asset, error) {
bytes, err := _1610959908_add_dont_wrap_to_raw_messagesUpSqlBytes()
if err != nil {
return nil, err
}
info := bindataFileInfo{name: "1610959908_add_dont_wrap_to_raw_messages.up.sql", size: 83, mode: os.FileMode(0644), modTime: time.Unix(1611646365, 0)}
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x71, 0x2, 0x9a, 0xca, 0xd4, 0x38, 0x44, 0x30, 0x2b, 0xa8, 0x27, 0x32, 0x63, 0x53, 0x22, 0x60, 0x59, 0x84, 0x23, 0x96, 0x77, 0xf0, 0x56, 0xd7, 0x94, 0xe0, 0x95, 0x28, 0x6, 0x1d, 0x4e, 0xb1}}
return a, nil
}
var __1610960912_add_send_on_personal_topicUpSql = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x04\xc0\xc1\x0a\x82\x21\x0c\x07\xf0\x7b\x4f\xf1\x7f\x8f\x4e\x33\xe7\x69\x29\x94\x9e\x87\xd4\x88\xa0\x54\x5c\xd0\xeb\x7f\x3f\x92\xca\x37\x54\x0a\xc2\xd8\xfd\xaf\x5f\x73\xef\x2f\x73\x50\x8c\xb8\x14\x69\xd7\x0c\xb7\xf1\xd4\x39\x74\xd9\xf6\x39\xfa\x47\x7f\x73\xbd\x1f\x08\xa5\x08\x53\x46\xe4\x44\x4d\x2a\x12\xc9\x9d\xcf\xa7\x23\x00\x00\xff\xff\x14\x1b\x69\x22\x52\x00\x00\x00")
func _1610960912_add_send_on_personal_topicUpSqlBytes() ([]byte, error) {
return bindataRead(
__1610960912_add_send_on_personal_topicUpSql,
"1610960912_add_send_on_personal_topic.up.sql",
)
}
func _1610960912_add_send_on_personal_topicUpSql() (*asset, error) {
bytes, err := _1610960912_add_send_on_personal_topicUpSqlBytes()
if err != nil {
return nil, err
}
info := bindataFileInfo{name: "1610960912_add_send_on_personal_topic.up.sql", size: 82, mode: os.FileMode(0644), modTime: time.Unix(1611646381, 0)}
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x77, 0xac, 0x2f, 0xc4, 0xd, 0xa7, 0x1b, 0x37, 0x30, 0xc2, 0x68, 0xee, 0xde, 0x54, 0x5e, 0xbf, 0x3f, 0xa0, 0xd6, 0xc6, 0x9f, 0xd4, 0x34, 0x12, 0x76, 0x1e, 0x66, 0x4a, 0xfc, 0xf, 0xee, 0xc9}}
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) {
@ -526,7 +568,7 @@ func readmeMd() (*asset, error) {
return nil, err
}
info := bindataFileInfo{name: "README.md", size: 554, mode: os.FileMode(0644), modTime: time.Unix(1610638422, 0)}
info := bindataFileInfo{name: "README.md", size: 554, mode: os.FileMode(0644), modTime: time.Unix(1611588835, 0)}
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x1c, 0x6e, 0xfb, 0xcc, 0x81, 0x94, 0x4d, 0x8c, 0xa0, 0x3b, 0x5, 0xb0, 0x18, 0xd6, 0xbb, 0xb3, 0x79, 0xc8, 0x8f, 0xff, 0xc1, 0x10, 0xf9, 0xf, 0x20, 0x1b, 0x4a, 0x74, 0x96, 0x42, 0xd7, 0xa8}}
return a, nil
}
@ -546,7 +588,7 @@ func docGo() (*asset, error) {
return nil, err
}
info := bindataFileInfo{name: "doc.go", size: 850, mode: os.FileMode(0644), modTime: time.Unix(1610007618, 0)}
info := bindataFileInfo{name: "doc.go", size: 850, mode: os.FileMode(0644), modTime: time.Unix(1611588719, 0)}
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xa0, 0xcc, 0x41, 0xe1, 0x61, 0x12, 0x97, 0xe, 0x36, 0x8c, 0xa7, 0x9e, 0xe0, 0x6e, 0x59, 0x9e, 0xee, 0xd5, 0x4a, 0xcf, 0x1e, 0x60, 0xd6, 0xc3, 0x3a, 0xc9, 0x6c, 0xf2, 0x86, 0x5a, 0xb4, 0x1e}}
return a, nil
}
@ -684,6 +726,10 @@ var _bindata = map[string]func() (*asset, error){
"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,
"README.md": readmeMd,
"doc.go": docGo,
@ -751,8 +797,10 @@ var _bintree = &bintree{nil, 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{}},
"README.md": &bintree{readmeMd, map[string]*bintree{}},
"doc.go": &bintree{docGo, 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{}},
"README.md": &bintree{readmeMd, map[string]*bintree{}},
"doc.go": &bintree{docGo, map[string]*bintree{}},
}}
// RestoreAsset restores an asset under the given directory.

View File

@ -0,0 +1 @@
ALTER TABLE raw_messages ADD COLUMN skip_group_message_wrap BOOLEAN DEFAULT FALSE;

View File

@ -0,0 +1 @@
ALTER TABLE raw_messages ADD COLUMN send_on_personal_topic BOOLEAN DEFAULT FALSE;

View File

@ -590,10 +590,12 @@ func (db sqlitePersistence) SaveRawMessage(message *common.RawMessage) error {
resend_automatically,
recipients,
skip_encryption,
send_push_notification,
send_push_notification,
skip_group_message_wrap,
send_on_personal_topic,
payload
)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
message.ID,
message.LocalChatID,
message.LastSent,
@ -604,6 +606,8 @@ func (db sqlitePersistence) SaveRawMessage(message *common.RawMessage) error {
encodedRecipients.Bytes(),
message.SkipEncryption,
message.SendPushNotification,
message.SkipGroupMessageWrap,
message.SendOnPersonalTopic,
message.Payload)
return err
}
@ -611,6 +615,8 @@ func (db sqlitePersistence) SaveRawMessage(message *common.RawMessage) error {
func (db sqlitePersistence) RawMessageByID(id string) (*common.RawMessage, error) {
var rawPubKeys [][]byte
var encodedRecipients []byte
var skipGroupMessageWrap sql.NullBool
var sendOnPersonalTopic sql.NullBool
message := &common.RawMessage{}
err := db.db.QueryRow(`
@ -624,7 +630,9 @@ func (db sqlitePersistence) RawMessageByID(id string) (*common.RawMessage, error
resend_automatically,
recipients,
skip_encryption,
send_push_notification,
send_push_notification,
skip_group_message_wrap,
send_on_personal_topic,
payload
FROM
raw_messages
@ -642,24 +650,36 @@ func (db sqlitePersistence) RawMessageByID(id string) (*common.RawMessage, error
&encodedRecipients,
&message.SkipEncryption,
&message.SendPushNotification,
&skipGroupMessageWrap,
&sendOnPersonalTopic,
&message.Payload,
)
if err != nil {
return nil, err
}
// Restore recipients
decoder := gob.NewDecoder(bytes.NewBuffer(encodedRecipients))
err = decoder.Decode(&rawPubKeys)
if err != nil {
return nil, err
}
for _, pkBytes := range rawPubKeys {
pubkey, err := crypto.UnmarshalPubkey(pkBytes)
if rawPubKeys != nil {
// Restore recipients
decoder := gob.NewDecoder(bytes.NewBuffer(encodedRecipients))
err = decoder.Decode(&rawPubKeys)
if err != nil {
return nil, err
}
message.Recipients = append(message.Recipients, pubkey)
for _, pkBytes := range rawPubKeys {
pubkey, err := crypto.UnmarshalPubkey(pkBytes)
if err != nil {
return nil, err
}
message.Recipients = append(message.Recipients, pubkey)
}
}
if skipGroupMessageWrap.Valid {
message.SkipGroupMessageWrap = skipGroupMessageWrap.Bool
}
if sendOnPersonalTopic.Valid {
message.SendOnPersonalTopic = sendOnPersonalTopic.Bool
}
return message, nil

View File

@ -52,7 +52,8 @@ func (s *MessengerPushNotificationSuite) SetupTest() {
s.m = s.newMessenger(s.shh)
s.privateKey = s.m.identity
s.Require().NoError(s.m.Start())
_, err := s.m.Start()
s.Require().NoError(err)
}
func (s *MessengerPushNotificationSuite) TearDownTest() {
@ -97,7 +98,8 @@ func (s *MessengerPushNotificationSuite) TestReceivePushNotification() {
alice := s.newMessenger(s.shh)
// start alice and enable sending push notifications
s.Require().NoError(alice.Start())
_, err = alice.Start()
s.Require().NoError(err)
s.Require().NoError(alice.EnableSendingPushNotifications())
bobInstallationIDs := []string{bob1.installationID, bob2.installationID}
@ -124,6 +126,15 @@ func (s *MessengerPushNotificationSuite) TestReceivePushNotification() {
if !registered {
return errors.New("not registered")
}
bobServers, err := bob1.GetPushNotificationsServers()
if err != nil {
return err
}
if len(bobServers) == 0 {
return errors.New("not registered")
}
return nil
})
// Make sure we receive it
@ -155,6 +166,15 @@ func (s *MessengerPushNotificationSuite) TestReceivePushNotification() {
if !registered {
return errors.New("not registered")
}
bobServers, err := bob2.GetPushNotificationsServers()
if err != nil {
return err
}
if len(bobServers) == 0 {
return errors.New("not registered")
}
return nil
})
// Make sure we receive it
@ -262,7 +282,8 @@ func (s *MessengerPushNotificationSuite) TestReceivePushNotificationFromContactO
alice := s.newMessenger(s.shh)
// start alice and enable push notifications
s.Require().NoError(alice.Start())
_, err = alice.Start()
s.Require().NoError(err)
s.Require().NoError(alice.EnableSendingPushNotifications())
bobInstallationIDs := []string{bob.installationID}
@ -304,6 +325,15 @@ func (s *MessengerPushNotificationSuite) TestReceivePushNotificationFromContactO
if !registered {
return errors.New("not registered")
}
bobServers, err := bob.GetPushNotificationsServers()
if err != nil {
return err
}
if len(bobServers) == 0 {
return errors.New("not registered")
}
return nil
})
// Make sure we receive it
@ -395,9 +425,11 @@ func (s *MessengerPushNotificationSuite) TestReceivePushNotificationRetries() {
alice := s.newMessenger(s.shh)
// another contact to invalidate the token
frank := s.newMessenger(s.shh)
s.Require().NoError(frank.Start())
_, err = frank.Start()
s.Require().NoError(err)
// start alice and enable push notifications
s.Require().NoError(alice.Start())
_, err = alice.Start()
s.Require().NoError(err)
s.Require().NoError(alice.EnableSendingPushNotifications())
bobInstallationIDs := []string{bob.installationID}
@ -449,6 +481,15 @@ func (s *MessengerPushNotificationSuite) TestReceivePushNotificationRetries() {
if !registered {
return errors.New("not registered")
}
bobServers, err := bob.GetPushNotificationsServers()
if err != nil {
return err
}
if len(bobServers) == 0 {
return errors.New("not registered")
}
return nil
})
// Make sure we receive it
@ -611,7 +652,8 @@ func (s *MessengerPushNotificationSuite) TestContactCode() {
alice := s.newMessenger(s.shh)
// start alice and enable sending push notifications
s.Require().NoError(alice.Start())
_, err = alice.Start()
s.Require().NoError(err)
s.Require().NoError(alice.EnableSendingPushNotifications())
// Register bob1
@ -637,6 +679,15 @@ func (s *MessengerPushNotificationSuite) TestContactCode() {
if !registered {
return errors.New("not registered")
}
bobServers, err := bob1.GetPushNotificationsServers()
if err != nil {
return err
}
if len(bobServers) == 0 {
return errors.New("not registered")
}
return nil
})
// Make sure we receive it
@ -662,7 +713,8 @@ func (s *MessengerPushNotificationSuite) TestReceivePushNotificationMention() {
alice := s.newMessenger(s.shh)
// start alice and enable sending push notifications
s.Require().NoError(alice.Start())
_, err = alice.Start()
s.Require().NoError(err)
s.Require().NoError(alice.EnableSendingPushNotifications())
bobInstallationIDs := []string{bob.installationID}
@ -703,6 +755,16 @@ func (s *MessengerPushNotificationSuite) TestReceivePushNotificationMention() {
if !registered {
return errors.New("not registered")
}
bobServers, err := bob.GetPushNotificationsServers()
if err != nil {
return err
}
if len(bobServers) == 0 {
return errors.New("not registered")
}
return nil
})
// Make sure we receive it

View File

@ -1267,6 +1267,9 @@ func (c *Client) registerWithServer(registration *protobuf.PushNotificationRegis
rawMessage := common.RawMessage{
Payload: encryptedRegistration,
MessageType: protobuf.ApplicationMetadataMessage_PUSH_NOTIFICATION_REGISTRATION,
// We send on personal topic to avoid a lot of traffic on the partitioned topic
SendOnPersonalTopic: true,
SkipEncryption: true,
}
_, err = c.messageProcessor.SendPrivate(context.Background(), server.PublicKey, rawMessage)

View File

@ -90,7 +90,7 @@ func _1593601729_initial_schemaDownSql() (*asset, error) {
return nil, err
}
info := bindataFileInfo{name: "1593601729_initial_schema.down.sql", size: 144, mode: os.FileMode(0644), modTime: time.Unix(1609934130, 0)}
info := bindataFileInfo{name: "1593601729_initial_schema.down.sql", size: 144, mode: os.FileMode(0644), modTime: time.Unix(1611588835, 0)}
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xa, 0x95, 0x55, 0x64, 0x38, 0x40, 0x16, 0xbf, 0x8b, 0x1c, 0x18, 0xb4, 0xc5, 0x7f, 0xd0, 0xb8, 0xf0, 0x3c, 0xa2, 0x82, 0xf8, 0x8d, 0x5a, 0xd3, 0xb6, 0x6e, 0xa3, 0xb4, 0xc, 0x9, 0x33, 0x0}}
return a, nil
}
@ -110,7 +110,7 @@ func _1593601729_initial_schemaUpSql() (*asset, error) {
return nil, err
}
info := bindataFileInfo{name: "1593601729_initial_schema.up.sql", size: 1773, mode: os.FileMode(0644), modTime: time.Unix(1609934130, 0)}
info := bindataFileInfo{name: "1593601729_initial_schema.up.sql", size: 1773, mode: os.FileMode(0644), modTime: time.Unix(1611588835, 0)}
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x4e, 0x1e, 0x5, 0x35, 0x9, 0xb2, 0x2d, 0x6f, 0x33, 0x63, 0xa2, 0x7a, 0x5b, 0xd2, 0x2d, 0xcb, 0x79, 0x7e, 0x6, 0xb4, 0x9d, 0x35, 0xd8, 0x9b, 0x55, 0xe5, 0xf8, 0x44, 0xca, 0xa6, 0xf3, 0xd3}}
return a, nil
}
@ -130,7 +130,7 @@ func _1597909626_add_server_typeDownSql() (*asset, error) {
return nil, err
}
info := bindataFileInfo{name: "1597909626_add_server_type.down.sql", size: 0, mode: os.FileMode(0644), modTime: time.Unix(1609934130, 0)}
info := bindataFileInfo{name: "1597909626_add_server_type.down.sql", size: 0, mode: os.FileMode(0644), modTime: time.Unix(1611588835, 0)}
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xe3, 0xb0, 0xc4, 0x42, 0x98, 0xfc, 0x1c, 0x14, 0x9a, 0xfb, 0xf4, 0xc8, 0x99, 0x6f, 0xb9, 0x24, 0x27, 0xae, 0x41, 0xe4, 0x64, 0x9b, 0x93, 0x4c, 0xa4, 0x95, 0x99, 0x1b, 0x78, 0x52, 0xb8, 0x55}}
return a, nil
}
@ -150,7 +150,7 @@ func _1597909626_add_server_typeUpSql() (*asset, error) {
return nil, err
}
info := bindataFileInfo{name: "1597909626_add_server_type.up.sql", size: 145, mode: os.FileMode(0644), modTime: time.Unix(1609934130, 0)}
info := bindataFileInfo{name: "1597909626_add_server_type.up.sql", size: 145, mode: os.FileMode(0644), modTime: time.Unix(1611588835, 0)}
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xc8, 0x3f, 0xe0, 0xe7, 0x57, 0x0, 0x5d, 0x60, 0xf3, 0x55, 0x64, 0x71, 0x80, 0x3c, 0xca, 0x8, 0x61, 0xb5, 0x3c, 0xe, 0xa1, 0xe4, 0x61, 0xd1, 0x4e, 0xd8, 0xb2, 0x55, 0xdd, 0x87, 0x62, 0x9b}}
return a, nil
}
@ -170,7 +170,7 @@ func _1599053776_add_chat_id_and_typeDownSql() (*asset, error) {
return nil, err
}
info := bindataFileInfo{name: "1599053776_add_chat_id_and_type.down.sql", size: 0, mode: os.FileMode(0644), modTime: time.Unix(1609934130, 0)}
info := bindataFileInfo{name: "1599053776_add_chat_id_and_type.down.sql", size: 0, mode: os.FileMode(0644), modTime: time.Unix(1611588835, 0)}
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xe3, 0xb0, 0xc4, 0x42, 0x98, 0xfc, 0x1c, 0x14, 0x9a, 0xfb, 0xf4, 0xc8, 0x99, 0x6f, 0xb9, 0x24, 0x27, 0xae, 0x41, 0xe4, 0x64, 0x9b, 0x93, 0x4c, 0xa4, 0x95, 0x99, 0x1b, 0x78, 0x52, 0xb8, 0x55}}
return a, nil
}
@ -190,7 +190,7 @@ func _1599053776_add_chat_id_and_typeUpSql() (*asset, error) {
return nil, err
}
info := bindataFileInfo{name: "1599053776_add_chat_id_and_type.up.sql", size: 264, mode: os.FileMode(0644), modTime: time.Unix(1609934130, 0)}
info := bindataFileInfo{name: "1599053776_add_chat_id_and_type.up.sql", size: 264, mode: os.FileMode(0644), modTime: time.Unix(1611588835, 0)}
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xea, 0x7a, 0xf9, 0xc4, 0xa2, 0x96, 0x2e, 0xf9, 0x8f, 0x7, 0xf1, 0x1e, 0x73, 0x8a, 0xa6, 0x3a, 0x13, 0x4, 0x73, 0x82, 0x83, 0xb, 0xe3, 0xb5, 0x3b, 0x7e, 0xd, 0x23, 0xce, 0x98, 0xd4, 0xdc}}
return a, nil
}
@ -210,7 +210,7 @@ func docGo() (*asset, error) {
return nil, err
}
info := bindataFileInfo{name: "doc.go", size: 382, mode: os.FileMode(0644), modTime: time.Unix(1609934130, 0)}
info := bindataFileInfo{name: "doc.go", size: 382, mode: os.FileMode(0644), modTime: time.Unix(1611588835, 0)}
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xc0, 0x2f, 0x1e, 0x64, 0x9, 0x93, 0xe4, 0x8b, 0xf2, 0x98, 0x5a, 0x45, 0xe2, 0x80, 0x88, 0x67, 0x7a, 0x2d, 0xd7, 0x4b, 0xd1, 0x73, 0xb6, 0x6d, 0x15, 0xc2, 0x0, 0x34, 0xcd, 0xa0, 0xdb, 0x20}}
return a, nil
}

View File

@ -88,7 +88,7 @@ func _1593601728_initial_schemaDownSql() (*asset, error) {
return nil, err
}
info := bindataFileInfo{name: "1593601728_initial_schema.down.sql", size: 200, mode: os.FileMode(0644), modTime: time.Unix(1609934130, 0)}
info := bindataFileInfo{name: "1593601728_initial_schema.down.sql", size: 200, mode: os.FileMode(0644), modTime: time.Unix(1611588835, 0)}
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x88, 0x8a, 0x61, 0x81, 0x57, 0x45, 0x9b, 0x97, 0x9b, 0x1f, 0xf6, 0x94, 0x8a, 0x20, 0xb3, 0x2b, 0xff, 0x69, 0x49, 0xf4, 0x58, 0xcc, 0xd0, 0x55, 0xcc, 0x9a, 0x8b, 0xb6, 0x7f, 0x29, 0x53, 0xc1}}
return a, nil
}
@ -108,7 +108,7 @@ func _1593601728_initial_schemaUpSql() (*asset, error) {
return nil, err
}
info := bindataFileInfo{name: "1593601728_initial_schema.up.sql", size: 675, mode: os.FileMode(0644), modTime: time.Unix(1609934130, 0)}
info := bindataFileInfo{name: "1593601728_initial_schema.up.sql", size: 675, mode: os.FileMode(0644), modTime: time.Unix(1611588835, 0)}
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xfd, 0x61, 0x90, 0x79, 0xd9, 0x14, 0x65, 0xe9, 0x96, 0x53, 0x17, 0x33, 0x54, 0xeb, 0x8b, 0x5d, 0x95, 0x99, 0x10, 0x36, 0x58, 0xdd, 0xb2, 0xbf, 0x45, 0xd9, 0xbb, 0xc4, 0x92, 0xe, 0xce, 0x2}}
return a, nil
}
@ -128,7 +128,7 @@ func _1598419937_add_push_notifications_tableDownSql() (*asset, error) {
return nil, err
}
info := bindataFileInfo{name: "1598419937_add_push_notifications_table.down.sql", size: 51, mode: os.FileMode(0644), modTime: time.Unix(1609934130, 0)}
info := bindataFileInfo{name: "1598419937_add_push_notifications_table.down.sql", size: 51, mode: os.FileMode(0644), modTime: time.Unix(1611588835, 0)}
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xc, 0x98, 0xc8, 0x30, 0x45, 0x5b, 0xc5, 0x7d, 0x13, 0x5d, 0xe7, 0xc8, 0x23, 0x43, 0xf7, 0xdc, 0x9c, 0xe2, 0xdd, 0x63, 0xf0, 0xb7, 0x16, 0x40, 0xc, 0xda, 0xb9, 0x16, 0x70, 0x2b, 0x5a, 0x7e}}
return a, nil
}
@ -148,7 +148,7 @@ func _1598419937_add_push_notifications_tableUpSql() (*asset, error) {
return nil, err
}
info := bindataFileInfo{name: "1598419937_add_push_notifications_table.up.sql", size: 104, mode: os.FileMode(0644), modTime: time.Unix(1609934130, 0)}
info := bindataFileInfo{name: "1598419937_add_push_notifications_table.up.sql", size: 104, mode: os.FileMode(0644), modTime: time.Unix(1611588835, 0)}
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x2, 0x3e, 0xef, 0xf, 0xc2, 0xdf, 0xbc, 0x99, 0x7a, 0xc2, 0xd3, 0x64, 0x4f, 0x4c, 0x7e, 0xfc, 0x2e, 0x8c, 0xa7, 0x54, 0xd3, 0x4d, 0x25, 0x98, 0x41, 0xbc, 0xea, 0xd7, 0x2, 0xc1, 0xd0, 0x52}}
return a, nil
}
@ -168,7 +168,7 @@ func docGo() (*asset, error) {
return nil, err
}
info := bindataFileInfo{name: "doc.go", size: 382, mode: os.FileMode(0644), modTime: time.Unix(1609934130, 0)}
info := bindataFileInfo{name: "doc.go", size: 382, mode: os.FileMode(0644), modTime: time.Unix(1611588835, 0)}
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xc0, 0x2f, 0x1e, 0x64, 0x9, 0x93, 0xe4, 0x8b, 0xf2, 0x98, 0x5a, 0x45, 0xe2, 0x80, 0x88, 0x67, 0x7a, 0x2d, 0xd7, 0x4b, 0xd1, 0x73, 0xb6, 0x6d, 0x15, 0xc2, 0x0, 0x34, 0xcd, 0xa0, 0xdb, 0x20}}
return a, nil
}

View File

@ -23,6 +23,8 @@ type Filter struct {
Negotiated bool `json:"negotiated"`
// Listen is whether we are actually listening for messages on this chat, or the filter is only created in order to be able to post on the topic
Listen bool `json:"listen"`
// Ephemeral indicates that this is an ephemeral filter
Ephemeral bool `json:"ephemeral"`
}
func (c *Filter) IsPublic() bool {

View File

@ -37,6 +37,7 @@ type FiltersService interface {
Subscribe(opts *types.SubscriptionOptions) (string, error)
Unsubscribe(id string) error
UnsubscribeMany(ids []string) error
}
type FiltersManager struct {
@ -230,6 +231,33 @@ func (s *FiltersManager) Remove(filters ...*Filter) error {
return nil
}
// Remove remove all the filters associated with a chat/identity
func (s *FiltersManager) RemoveNoListenFilters() error {
s.mutex.Lock()
defer s.mutex.Unlock()
var filterIDs []string
var filters []*Filter
for _, f := range filters {
if !f.Listen {
filterIDs = append(filterIDs, f.FilterID)
filters = append(filters, f)
}
}
if err := s.service.UnsubscribeMany(filterIDs); err != nil {
return err
}
for _, filter := range filters {
if filter.SymKeyID != "" {
s.service.DeleteSymKey(filter.SymKeyID)
}
delete(s.filters, filter.ChatID)
}
return nil
}
// Remove remove all the filters associated with a chat/identity
func (s *FiltersManager) RemoveFilterByChatID(chatID string) (*Filter, error) {
s.mutex.Lock()
@ -250,18 +278,20 @@ func (s *FiltersManager) RemoveFilterByChatID(chatID string) (*Filter, error) {
// LoadPartitioned creates a filter for a partitioned topic.
func (s *FiltersManager) LoadPartitioned(publicKey *ecdsa.PublicKey, identity *ecdsa.PrivateKey, listen bool) (*Filter, error) {
return s.loadPartitioned(publicKey, identity, listen)
return s.loadPartitioned(publicKey, identity, listen, false)
}
func (s *FiltersManager) loadMyPartitioned() (*Filter, error) {
return s.loadPartitioned(&s.privateKey.PublicKey, s.privateKey, true)
// LoadEphemeral creates a filter for a partitioned/personal topic.
func (s *FiltersManager) LoadEphemeral(publicKey *ecdsa.PublicKey, identity *ecdsa.PrivateKey, listen bool) (*Filter, error) {
return s.loadPartitioned(publicKey, identity, listen, true)
}
func (s *FiltersManager) loadPartitioned(publicKey *ecdsa.PublicKey, identity *ecdsa.PrivateKey, listen bool) (*Filter, error) {
// LoadPersonal creates a filter for a personal topic.
func (s *FiltersManager) LoadPersonal(publicKey *ecdsa.PublicKey, identity *ecdsa.PrivateKey, listen bool) (*Filter, error) {
s.mutex.Lock()
defer s.mutex.Unlock()
chatID := PartitionedTopic(publicKey)
chatID := PersonalDiscoveryTopic(publicKey)
if _, ok := s.filters[chatID]; ok {
return s.filters[chatID], nil
}
@ -284,6 +314,42 @@ func (s *FiltersManager) loadPartitioned(publicKey *ecdsa.PublicKey, identity *e
s.filters[chatID] = chat
return chat, nil
}
func (s *FiltersManager) loadMyPartitioned() (*Filter, error) {
return s.loadPartitioned(&s.privateKey.PublicKey, s.privateKey, true, false)
}
func (s *FiltersManager) loadPartitioned(publicKey *ecdsa.PublicKey, identity *ecdsa.PrivateKey, listen, ephemeral bool) (*Filter, error) {
s.mutex.Lock()
defer s.mutex.Unlock()
chatID := PartitionedTopic(publicKey)
if _, ok := s.filters[chatID]; ok {
return s.filters[chatID], nil
}
// We set up a filter so we can publish,
// but we discard envelopes if listen is false.
filter, err := s.addAsymmetric(chatID, identity, listen)
if err != nil {
return nil, err
}
chat := &Filter{
ChatID: chatID,
FilterID: filter.FilterID,
Topic: filter.Topic,
Identity: PublicKeyToStr(publicKey),
Listen: listen,
Ephemeral: ephemeral,
OneToOne: true,
}
s.filters[chatID] = chat
return chat, nil
}

View File

@ -16,7 +16,7 @@ import (
"go.uber.org/zap"
"github.com/status-im/status-go/eth-node/crypto"
"github.com/status-im/status-go/whisper/v6"
"github.com/status-im/status-go/whisper"
)
type testKeysPersistence struct {

View File

@ -76,6 +76,6 @@ func (c *ProcessedMessageIDsCache) Add(ids []string, timestamp uint64) (err erro
}
func (c *ProcessedMessageIDsCache) Clean(timestamp uint64) error {
_, err := c.db.Exec(`REMOVE FROM transport_message_cache WHERE timestamp < ?`, timestamp)
_, err := c.db.Exec(`DELETE FROM transport_message_cache WHERE timestamp < ?`, timestamp)
return err
}

View File

@ -22,6 +22,7 @@ type Transport interface {
SendPublic(ctx context.Context, newMessage *types.NewMessage, chatName string) ([]byte, error)
SendPrivateWithSharedSecret(ctx context.Context, newMessage *types.NewMessage, publicKey *ecdsa.PublicKey, secret []byte) ([]byte, error)
SendPrivateWithPartitioned(ctx context.Context, newMessage *types.NewMessage, publicKey *ecdsa.PublicKey) ([]byte, error)
SendPrivateOnPersonalTopic(ctx context.Context, newMessage *types.NewMessage, publicKey *ecdsa.PublicKey) ([]byte, error)
SendMessagesRequest(
ctx context.Context,
peerID []byte,

View File

@ -71,6 +71,7 @@ type Transport struct {
mailservers []string
envelopesMonitor *EnvelopesMonitor
quit chan struct{}
}
// NewTransport returns a new Transport.
@ -106,6 +107,7 @@ func NewTransport(
api: api,
cache: transport.NewProcessedMessageIDsCache(db),
envelopesMonitor: envelopesMonitor,
quit: make(chan struct{}),
keysManager: &wakuServiceKeysManager{
waku: waku,
privateKey: privateKey,
@ -122,6 +124,8 @@ func NewTransport(
}
}
t.cleanFiltersLoop()
return t, nil
}
@ -217,6 +221,10 @@ func (a *Transport) RetrieveRawAll() (map[transport.Filter][]*types.Message, err
allFilters := a.filters.Filters()
for _, filter := range allFilters {
// Don't pull from filters we don't listen to
if !filter.Listen {
continue
}
msgs, err := a.api.GetFilterMessages(filter.FilterID)
if err != nil {
a.logger.Warn("failed to fetch messages", zap.Error(err))
@ -305,8 +313,24 @@ func (a *Transport) SendPrivateWithPartitioned(ctx context.Context, newMessage *
return a.api.Post(ctx, *newMessage)
}
func (a *Transport) SendPrivateOnPersonalTopic(ctx context.Context, newMessage *types.NewMessage, publicKey *ecdsa.PublicKey) ([]byte, error) {
if err := a.addSig(newMessage); err != nil {
return nil, err
}
filter, err := a.filters.LoadPersonal(publicKey, a.keysManager.privateKey, false)
if err != nil {
return nil, err
}
newMessage.Topic = filter.Topic
newMessage.PublicKey = crypto.FromECDSAPub(publicKey)
return a.api.Post(ctx, *newMessage)
}
func (a *Transport) LoadKeyFilters(key *ecdsa.PrivateKey) (*transport.Filter, error) {
return a.filters.LoadPartitioned(&key.PublicKey, key, true)
return a.filters.LoadEphemeral(&key.PublicKey, key, true)
}
func (a *Transport) SendPrivateOnDiscovery(ctx context.Context, newMessage *types.NewMessage, publicKey *ecdsa.PublicKey) ([]byte, error) {
@ -326,6 +350,10 @@ func (a *Transport) SendPrivateOnDiscovery(ctx context.Context, newMessage *type
return a.api.Post(ctx, *newMessage)
}
func (a *Transport) cleanFilters() error {
return a.filters.RemoveNoListenFilters()
}
func (a *Transport) addSig(newMessage *types.NewMessage) error {
sigID, err := a.keysManager.AddOrGetKeyPair(a.keysManager.privateKey)
if err != nil {
@ -351,12 +379,38 @@ func (a *Transport) MaxMessageSize() uint32 {
}
func (a *Transport) Stop() error {
close(a.quit)
if a.envelopesMonitor != nil {
a.envelopesMonitor.Stop()
}
return nil
}
// cleanFiltersLoop cleans up the topic we create for the only purpose
// of sending messages.
// Whenever we send a message we also need to listen to that particular topic
// but in case of asymettric topics, we are not interested in listening to them.
// We therefore periodically clean them up so we don't receive unnecessary data.
func (a *Transport) cleanFiltersLoop() {
ticker := time.NewTicker(5 * time.Minute)
go func() {
for {
select {
case <-a.quit:
ticker.Stop()
return
case <-ticker.C:
err := a.cleanFilters()
if err != nil {
a.logger.Error("failed to clean up topics", zap.Error(err))
}
}
}
}()
}
// RequestHistoricMessages requests historic messages for all registered filters.
func (a *Transport) SendMessagesRequest(
ctx context.Context,

View File

@ -335,6 +335,22 @@ func (a *Transport) SendPrivateWithPartitioned(ctx context.Context, newMessage *
return a.shhAPI.Post(ctx, *newMessage)
}
func (a *Transport) SendPrivateOnPersonalTopic(ctx context.Context, newMessage *types.NewMessage, publicKey *ecdsa.PublicKey) ([]byte, error) {
if err := a.addSig(newMessage); err != nil {
return nil, err
}
filter, err := a.filters.LoadPersonal(publicKey, a.keysManager.privateKey, false)
if err != nil {
return nil, err
}
newMessage.Topic = filter.Topic
newMessage.PublicKey = crypto.FromECDSAPub(publicKey)
return a.shhAPI.Post(ctx, *newMessage)
}
func (a *Transport) SendPrivateOnDiscovery(ctx context.Context, newMessage *types.NewMessage, publicKey *ecdsa.PublicKey) ([]byte, error) {
if err := a.addSig(newMessage); err != nil {
return nil, err

View File

@ -42,7 +42,7 @@ func MembershipUpdateEventFromProtobuf(chatID string, raw []byte) (*MembershipUp
return nil, errors.Wrap(err, "failed to extract signature")
}
from := types.EncodeHex(crypto.FromECDSAPub(publicKey))
from := publicKeyToString(publicKey)
err = proto.Unmarshal(encodedEvent, &decodedEvent)
if err != nil {
@ -147,7 +147,7 @@ func (u *MembershipUpdateEvent) Sign(key *ecdsa.PrivateKey) error {
return err
}
u.Signature = signature
u.From = types.EncodeHex(crypto.FromECDSAPub(&key.PublicKey))
u.From = publicKeyToString(&key.PublicKey)
return nil
}
@ -241,7 +241,7 @@ type Group struct {
}
func groupChatID(creator *ecdsa.PublicKey) string {
return uuid.New().String() + "-" + types.EncodeHex(crypto.FromECDSAPub(creator))
return uuid.New().String() + "-" + publicKeyToString(creator)
}
func NewGroupWithEvents(chatID string, events []MembershipUpdateEvent) (*Group, error) {
@ -314,6 +314,78 @@ func (g Group) Events() []MembershipUpdateEvent {
return g.events
}
func isInSlice(m string, set []string) bool {
for _, k := range set {
if k == m {
return true
}
}
return false
}
// AbridgedEvents returns the minimum set of events for a user to publish a post
func (g Group) AbridgedEvents(publicKey *ecdsa.PublicKey) []MembershipUpdateEvent {
var events []MembershipUpdateEvent
var nameChangedEventFound bool
var joinedEventFound bool
memberID := publicKeyToString(publicKey)
var addedEventFound bool
nextInChain := memberID
// Iterate in reverse
for i := len(g.events) - 1; i >= 0; i-- {
event := g.events[i]
switch event.Type {
case protobuf.MembershipUpdateEvent_CHAT_CREATED:
events = append(events, event)
case protobuf.MembershipUpdateEvent_NAME_CHANGED:
if nameChangedEventFound {
continue
}
events = append(events, event)
nameChangedEventFound = true
case protobuf.MembershipUpdateEvent_MEMBERS_ADDED:
// If we already have an added event
// or the user is not in slice, ignore
if addedEventFound {
continue
}
areWeTheTarget := isInSlice(nextInChain, event.Members)
// If it's us, and we have been added by the creator, no more work to do, this is authoritative
if areWeTheTarget && g.events[0].From == event.From {
addedEventFound = true
events = append(events, event)
} else if areWeTheTarget {
// if it's us and we haven't been added by the creator, we follow the history of whoever invited us
nextInChain = event.From
events = append(events, event)
}
case protobuf.MembershipUpdateEvent_MEMBER_JOINED:
if joinedEventFound || event.From != memberID {
continue
}
joinedEventFound = true
events = append(events, event)
case protobuf.MembershipUpdateEvent_ADMINS_ADDED:
if isInSlice(nextInChain, event.Members) {
events = append(events, event)
}
}
}
// Reverse events
for i, j := 0, len(events)-1; i < j; i, j = i+1, j-1 {
events[i], events[j] = events[j], events[i]
}
return events
}
func (g Group) Members() []string {
return g.members.List()
}

View File

@ -324,3 +324,171 @@ func TestMembershipUpdateEventEqual(t *testing.T) {
u2.Signature = []byte("different-signature")
require.False(t, u1.Equal(u2))
}
func TestAbridgedEvents(t *testing.T) {
var clock uint64 = 0
creator, err := crypto.GenerateKey()
require.NoError(t, err)
creatorID := publicKeyToString(&creator.PublicKey)
member1, err := crypto.GenerateKey()
require.NoError(t, err)
member1ID := publicKeyToString(&member1.PublicKey)
member2, err := crypto.GenerateKey()
require.NoError(t, err)
member2ID := publicKeyToString(&member2.PublicKey)
member3, err := crypto.GenerateKey()
require.NoError(t, err)
member3ID := publicKeyToString(&member3.PublicKey)
member4, err := crypto.GenerateKey()
require.NoError(t, err)
member4ID := publicKeyToString(&member4.PublicKey)
g, err := NewGroupWithCreator("name-0", clock, creator)
require.NoError(t, err)
clock++
// Full events is only a single one
require.Len(t, g.Events(), 1)
// same as abridged
require.Len(t, g.AbridgedEvents(&creator.PublicKey), 1)
// We change name of the chat
nameChangedEvent1 := NewNameChangedEvent("name-1", clock)
nameChangedEvent1.From = creatorID
nameChangedEvent1.ChatID = g.chatID
err = g.ProcessEvent(nameChangedEvent1)
require.NoError(t, err)
clock++
// We change name of the chat again
nameChangedEvent2 := NewNameChangedEvent("name-2", clock)
nameChangedEvent2.From = creatorID
nameChangedEvent2.ChatID = g.chatID
err = g.ProcessEvent(nameChangedEvent2)
require.NoError(t, err)
clock++
// Full events is 3 events
require.Len(t, g.Events(), 3)
// While abridged should exclude the first name-1 event
require.Len(t, g.AbridgedEvents(&creator.PublicKey), 2)
require.Equal(t, g.AbridgedEvents(&creator.PublicKey)[1].Name, "name-2")
// Add a new member
newMemberEvent1 := NewMembersAddedEvent([]string{member1ID}, clock)
newMemberEvent1.From = creatorID
newMemberEvent1.ChatID = g.chatID
err = g.ProcessEvent(newMemberEvent1)
require.NoError(t, err)
clock++
// Full events is 4 events
require.Len(t, g.Events(), 4)
// While abridged, given we are the creator, we only take 2 events and ignore
// the member created event
require.Len(t, g.AbridgedEvents(&creator.PublicKey), 2)
require.Equal(t, g.AbridgedEvents(&creator.PublicKey)[1].Name, "name-2")
// While abridged, given we are the new member, we take 3 events
// that are relevant to us
require.Len(t, g.AbridgedEvents(&member1.PublicKey), 3)
require.Equal(t, g.AbridgedEvents(&member1.PublicKey)[1].Name, "name-2")
require.Equal(t, g.AbridgedEvents(&member1.PublicKey)[2].Members, []string{member1ID})
// We join the chat
joinedEvent1 := NewMemberJoinedEvent(clock)
joinedEvent1.From = member1ID
joinedEvent1.ChatID = g.chatID
err = g.ProcessEvent(joinedEvent1)
require.NoError(t, err)
clock++
// Full events is 5 events
require.Len(t, g.Events(), 5)
// While abridged, given we are the creator, we only take 2 events and ignore
// the member created event
require.Len(t, g.AbridgedEvents(&creator.PublicKey), 2)
require.Equal(t, g.AbridgedEvents(&creator.PublicKey)[1].Name, "name-2")
// While abridged, given we are the new member, we take 4 events
// that are relevant to us
require.Len(t, g.AbridgedEvents(&member1.PublicKey), 4)
// Next is the tricky case, a user that has been invited by someone
// made an admin. We need to follow the history of admins so
// that whoever receives the message can see that Creator-> Invited A -> Made A admin -> A Invited B
// Creator makes member1 Admin
addedAdminEvent1 := NewAdminsAddedEvent([]string{member1ID}, clock)
addedAdminEvent1.From = creatorID
addedAdminEvent1.ChatID = g.chatID
err = g.ProcessEvent(addedAdminEvent1)
require.NoError(t, err)
clock++
// member1 adds member2
newMemberEvent2 := NewMembersAddedEvent([]string{member2ID}, clock)
newMemberEvent2.From = member1ID
newMemberEvent2.ChatID = g.chatID
err = g.ProcessEvent(newMemberEvent2)
require.NoError(t, err)
clock++
// member1 makes member2 admin
addedAdminEvent2 := NewAdminsAddedEvent([]string{member2ID}, clock)
addedAdminEvent2.From = member1ID
addedAdminEvent2.ChatID = g.chatID
err = g.ProcessEvent(addedAdminEvent2)
require.NoError(t, err)
clock++
// member2 adds member3
newMemberEvent3 := NewMembersAddedEvent([]string{member3ID}, clock)
newMemberEvent3.From = member2ID
newMemberEvent3.ChatID = g.chatID
err = g.ProcessEvent(newMemberEvent3)
require.NoError(t, err)
clock++
// member1 makes member3 admin
addedAdminEvent3 := NewAdminsAddedEvent([]string{member3ID}, clock)
addedAdminEvent3.From = member1ID
addedAdminEvent3.ChatID = g.chatID
err = g.ProcessEvent(addedAdminEvent3)
require.NoError(t, err)
clock++
// member3 adds member4
newMemberEvent4 := NewMembersAddedEvent([]string{member4ID}, clock)
newMemberEvent4.From = member3ID
newMemberEvent4.ChatID = g.chatID
err = g.ProcessEvent(newMemberEvent4)
require.NoError(t, err)
// Now we check that the history has been correctly followed
// Full events is 4 events
require.Len(t, g.Events(), 11)
// While abridged, given we are the creator, we only take 2 events and ignore
// the member created event
require.Len(t, g.AbridgedEvents(&creator.PublicKey), 2)
require.Equal(t, g.AbridgedEvents(&creator.PublicKey)[1].Name, "name-2")
// While abridged, given we are the new member, we take 3 events
// that are relevant to us
require.Len(t, g.AbridgedEvents(&member4.PublicKey), 9)
// We build a group from the abridged events
group, err := NewGroupWithEvents(g.chatID, g.AbridgedEvents(&member4.PublicKey))
require.NoError(t, err)
// Make sure the chatID, name is the same
require.Equal(t, g.name, group.name)
require.Equal(t, g.chatID, group.chatID)
// Make sure that user 4 is a member
require.True(t, group.IsMember(member4ID))
}

View File

@ -395,7 +395,7 @@ func (api *PublicAPI) ChatMessages(chatID, cursor string, limit int) (*Applicati
}, nil
}
func (api *PublicAPI) StartMessenger() error {
func (api *PublicAPI) StartMessenger() (*protocol.MessengerResponse, error) {
return api.service.StartMessenger()
}

View File

@ -31,7 +31,7 @@ import (
"github.com/status-im/status-go/protocol/pushnotificationserver"
"github.com/status-im/status-go/protocol/transport"
"github.com/status-im/status-go/services/ext/mailservers"
localnotifications "github.com/status-im/status-go/services/local-notifications"
mailserversDB "github.com/status-im/status-go/services/mailservers"
"github.com/status-im/status-go/services/wallet"
"github.com/status-im/status-go/signal"
@ -170,17 +170,17 @@ func (s *Service) InitProtocol(identity *ecdsa.PrivateKey, db *sql.DB, multiAcco
return messenger.Init()
}
func (s *Service) StartMessenger() error {
func (s *Service) StartMessenger() (*protocol.MessengerResponse, error) {
// Start a loop that retrieves all messages and propagates them to status-react.
s.cancelMessenger = make(chan struct{})
err := s.messenger.Start()
response, err := s.messenger.Start()
if err != nil {
return err
return nil, err
}
go s.retrieveMessagesLoop(time.Second, s.cancelMessenger)
go s.verifyTransactionLoop(30*time.Second, s.cancelMessenger)
go s.verifyENSLoop(30*time.Second, s.cancelMessenger)
return nil
return response, nil
}
func (s *Service) retrieveMessagesLoop(tick time.Duration, cancel <-chan struct{}) {
@ -197,7 +197,6 @@ func (s *Service) retrieveMessagesLoop(tick time.Duration, cancel <-chan struct{
}
if !response.IsEmpty() {
PublisherSignalHandler{}.NewMessages(response)
localnotifications.SendMessageNotifications(response.Notifications)
}
case <-cancel:
return
@ -427,6 +426,7 @@ func (s *Service) Stop() error {
if s.messenger != nil {
if err := s.messenger.Shutdown(); err != nil {
log.Error("failed to stop messenger", "err", err)
return err
}
}
@ -470,6 +470,7 @@ func buildMessengerOptions(
protocol.WithPushNotifications(),
protocol.WithDatabase(db),
protocol.WithMultiAccounts(multiAccounts),
protocol.WithMailserversDatabase(mailserversDB.NewDB(db)),
protocol.WithAccount(account),
protocol.WithEnvelopesMonitorConfig(envelopesMonitorConfig),
protocol.WithOnNegotiatedFilters(onNegotiatedFilters),

View File

@ -2,8 +2,6 @@ package localnotifications
import (
"database/sql"
"encoding/json"
"fmt"
"math/big"
"sync"
@ -15,7 +13,6 @@ import (
"github.com/ethereum/go-ethereum/rpc"
"github.com/status-im/status-go/eth-node/types"
"github.com/status-im/status-go/multiaccounts/accounts"
"github.com/status-im/status-go/protocol"
"github.com/status-im/status-go/services/wallet"
"github.com/status-im/status-go/signal"
)
@ -24,24 +21,12 @@ type PushCategory string
type transactionState string
type NotificationType string
const walletDeeplinkPrefix = "status-im://wallet/"
const (
walletDeeplinkPrefix = "status-im://wallet/"
failed transactionState = "failed"
inbound transactionState = "inbound"
outbound transactionState = "outbound"
CategoryTransaction PushCategory = "transaction"
CategoryMessage PushCategory = "newMessage"
TypeTransaction NotificationType = "transaction"
TypeMessage NotificationType = "message"
)
var (
marshalTypeMismatchErr = "notification type mismatch, expected '%s', Body could not be marshalled into this type"
)
type notificationBody struct {
@ -57,23 +42,9 @@ type notificationBody struct {
}
type Notification struct {
ID common.Hash `json:"id"`
Platform float32 `json:"platform,omitempty"`
Body interface{}
BodyType NotificationType `json:"bodyType"`
Category PushCategory `json:"category,omitempty"`
Deeplink string `json:"deepLink,omitempty"`
Image string `json:"imageUrl,omitempty"`
IsScheduled bool `json:"isScheduled,omitempty"`
ScheduledTime string `json:"scheduleTime,omitempty"`
}
// notificationAlias is an interim struct used for json un/marshalling
type notificationAlias struct {
ID common.Hash `json:"id"`
Platform float32 `json:"platform,omitempty"`
Body json.RawMessage `json:"body"`
BodyType NotificationType `json:"bodyType"`
Body notificationBody `json:"body"`
Category PushCategory `json:"category,omitempty"`
Deeplink string `json:"deepLink,omitempty"`
Image string `json:"imageUrl,omitempty"`
@ -131,94 +102,6 @@ func NewService(appDB *sql.DB, network uint64) *Service {
}
}
func (n *Notification) MarshalJSON() ([]byte, error) {
var body json.RawMessage
var err error
switch n.BodyType {
case TypeTransaction:
if nb, ok := n.Body.(notificationBody); ok {
body, err = json.Marshal(nb)
if err != nil {
return nil, err
}
} else {
return nil, fmt.Errorf(marshalTypeMismatchErr, n.BodyType)
}
case TypeMessage:
if nmb, ok := n.Body.(protocol.MessageNotificationBody); ok {
body, err = json.Marshal(nmb)
if err != nil {
return nil, err
}
} else {
return nil, fmt.Errorf(marshalTypeMismatchErr, n.BodyType)
}
default:
return nil, fmt.Errorf("unknown NotificationType '%s'", n.BodyType)
}
alias := notificationAlias{
n.ID,
n.Platform,
body,
n.BodyType,
n.Category,
n.Deeplink,
n.Image,
n.IsScheduled,
n.ScheduledTime,
}
return json.Marshal(alias)
}
func (n *Notification) UnmarshalJSON(data []byte) error {
var alias notificationAlias
err := json.Unmarshal(data, &alias)
if err != nil {
return err
}
n.BodyType = alias.BodyType
n.Category = alias.Category
n.Platform = alias.Platform
n.ID = alias.ID
n.Image = alias.Image
n.Deeplink = alias.Deeplink
n.IsScheduled = alias.IsScheduled
n.ScheduledTime = alias.ScheduledTime
switch n.BodyType {
case TypeTransaction:
return n.unmarshalAndAttachBody(alias.Body, &notificationBody{})
case TypeMessage:
return n.unmarshalAndAttachBody(alias.Body, &protocol.MessageNotificationBody{})
default:
return fmt.Errorf("unknown NotificationType '%s'", n.BodyType)
}
}
func (n *Notification) unmarshalAndAttachBody(body json.RawMessage, bodyStruct interface{}) error {
err := json.Unmarshal(body, &bodyStruct)
if err != nil {
return err
}
n.Body = bodyStruct
return nil
}
func pushMessages(ns []*Notification) {
for _, n := range ns {
pushMessage(n)
}
}
func pushMessage(notification *Notification) {
log.Info("Pushing a new push notification", "info", notification)
signal.SendLocalNotifications(notification)
@ -271,11 +154,10 @@ func (s *Service) buildTransactionNotification(rawTransfer wallet.Transfer) *Not
}
return &Notification{
BodyType: TypeTransaction,
ID: transfer.ID,
Body: body,
Deeplink: deeplink,
Category: CategoryTransaction,
Category: "transaction",
}
}
@ -473,19 +355,3 @@ func (s *Service) Protocols() []p2p.Protocol {
func (s *Service) IsStarted() bool {
return s.started
}
func SendMessageNotifications(mnb []protocol.MessageNotificationBody) {
var ns []*Notification
for _, n := range mnb {
ns = append(ns, &Notification{
Body: n,
BodyType: TypeMessage,
Category: CategoryMessage,
Deeplink: "", // TODO find what if any Deeplink should be used here
Image: "", // TODO do we want to attach any image data contained on the MessageBody{}?
})
}
// sends notifications messages to the OS level application
pushMessages(ns)
}

View File

@ -120,7 +120,7 @@ func TestTransactionNotification(t *testing.T) {
require.NoError(t, utils.Eventually(func() error {
if signalEvent == nil {
return fmt.Errorf("signal was not handled")
return fmt.Errorf("Signal was not handled")
}
notification := struct {
Type string
@ -130,10 +130,10 @@ func TestTransactionNotification(t *testing.T) {
require.NoError(t, json.Unmarshal(signalEvent, &notification))
if notification.Type != "local-notifications" {
return fmt.Errorf("wrong signal was sent")
return fmt.Errorf("Wrong signal was sent")
}
if notification.Event.Body.(*notificationBody).To != header.Address {
return fmt.Errorf("transaction to address is wrong")
if notification.Event.Body.To != header.Address {
return fmt.Errorf("Transaction to address is wrong")
}
return nil
}, 2*time.Second, 100*time.Millisecond))

View File

@ -43,6 +43,10 @@ func (a *API) AddMailserverTopic(ctx context.Context, topic MailserverTopic) err
return a.db.AddTopic(topic)
}
func (a *API) AddMailserverTopics(ctx context.Context, topics []MailserverTopic) error {
return a.db.AddTopics(topics)
}
func (a *API) GetMailserverTopics(ctx context.Context) ([]MailserverTopic, error) {
return a.db.Topics()
}
@ -55,6 +59,10 @@ func (a *API) AddChatRequestRange(ctx context.Context, req ChatRequestRange) err
return a.db.AddChatRequestRange(req)
}
func (a *API) AddChatRequestRanges(ctx context.Context, reqs []ChatRequestRange) error {
return a.db.AddChatRequestRanges(reqs)
}
func (a *API) GetChatRequestRanges(ctx context.Context) ([]ChatRequestRange, error) {
return a.db.ChatRequestRanges()
}

View File

@ -9,6 +9,8 @@ import (
"github.com/stretchr/testify/require"
"github.com/status-im/status-go/appdatabase"
"github.com/status-im/status-go/eth-node/types"
"github.com/status-im/status-go/protocol/transport"
)
func setupTestDB(t *testing.T) (*Database, func()) {
@ -56,6 +58,51 @@ func TestAddGetDeleteMailserver(t *testing.T) {
require.NoError(t, err)
}
func TestTopic(t *testing.T) {
db, close := setupTestDB(t)
defer close()
topicA := "0x61000000"
topicD := "0x64000000"
topic1 := MailserverTopic{Topic: topicA, LastRequest: 1}
topic2 := MailserverTopic{Topic: "0x6200000", LastRequest: 2}
topic3 := MailserverTopic{Topic: "0x6300000", LastRequest: 3}
require.NoError(t, db.AddTopic(topic1))
require.NoError(t, db.AddTopic(topic2))
require.NoError(t, db.AddTopic(topic3))
topics, err := db.Topics()
require.NoError(t, err)
require.Len(t, topics, 3)
filters := []*transport.Filter{
// Existing topic, is not updated
{Topic: types.BytesToTopic([]byte{0x61})},
// Non existing topic is not inserted
{
Discovery: true,
Negotiated: true,
Topic: types.BytesToTopic([]byte{0x64}),
},
}
require.NoError(t, db.SetTopics(filters))
topics, err = db.Topics()
require.NoError(t, err)
require.Len(t, topics, 2)
require.Equal(t, topics[0].Topic, topicA)
require.Equal(t, topics[0].LastRequest, 1)
require.Equal(t, topics[0].Topic, topicA)
require.Equal(t, topics[0].LastRequest, 1)
require.Equal(t, topics[1].Topic, topicD)
require.NotEmpty(t, topics[1].LastRequest)
require.True(t, topics[1].Negotiated)
require.True(t, topics[1].Discovery)
}
func TestAddGetDeleteMailserverRequestGap(t *testing.T) {
db, close := setupTestDB(t)
defer close()

View File

@ -7,6 +7,9 @@ import (
"errors"
"fmt"
"strings"
"time"
"github.com/status-im/status-go/protocol/transport"
)
type Mailserver struct {
@ -210,6 +213,7 @@ func (d *Database) DeleteGapsByChatID(chatID string) error {
}
func (d *Database) AddTopic(topic MailserverTopic) error {
chatIDs := sqlStringSlice(topic.ChatIDs)
_, err := d.db.Exec(`INSERT OR REPLACE INTO mailserver_topics(
topic,
@ -227,6 +231,42 @@ func (d *Database) AddTopic(topic MailserverTopic) error {
return err
}
func (d *Database) AddTopics(topics []MailserverTopic) (err error) {
var tx *sql.Tx
tx, err = d.db.Begin()
if err != nil {
return
}
defer func() {
if err == nil {
err = tx.Commit()
return
}
_ = tx.Rollback()
}()
for _, topic := range topics {
chatIDs := sqlStringSlice(topic.ChatIDs)
_, err = tx.Exec(`INSERT OR REPLACE INTO mailserver_topics(
topic,
chat_ids,
last_request,
discovery,
negotiated
) VALUES (?, ?, ?,?,?)`,
topic.Topic,
chatIDs,
topic.LastRequest,
topic.Discovery,
topic.Negotiated,
)
if err != nil {
return
}
}
return
}
func (d *Database) Topics() ([]MailserverTopic, error) {
var result []MailserverTopic
@ -262,6 +302,58 @@ func (d *Database) DeleteTopic(topic string) error {
return err
}
// SetTopics deletes all topics excepts the one set, or upsert those if
// missing
func (d *Database) SetTopics(filters []*transport.Filter) (err error) {
var tx *sql.Tx
tx, err = d.db.Begin()
if err != nil {
return err
}
defer func() {
if err == nil {
err = tx.Commit()
return
}
_ = tx.Rollback()
}()
if len(filters) == 0 {
return nil
}
topicsArgs := make([]interface{}, 0, len(filters))
for _, filter := range filters {
topicsArgs = append(topicsArgs, filter.Topic.String())
}
inVector := strings.Repeat("?, ", len(filters)-1) + "?"
// Delete topics
query := "DELETE FROM mailserver_topics WHERE topic NOT IN (" + inVector + ")" // nolint: gosec
_, err = tx.Exec(query, topicsArgs...)
// Default to now - 1.day
lastRequest := (time.Now().Add(-24 * time.Hour)).Unix()
// Insert if not existing
for _, filter := range filters {
// fetch
var topic string
err = tx.QueryRow(`SELECT topic FROM mailserver_topics WHERE topic = ?`, filter.Topic.String()).Scan(&topic)
if err != nil && err != sql.ErrNoRows {
return
} else if err == sql.ErrNoRows {
// we insert the topic
_, err = tx.Exec(`INSERT INTO mailserver_topics(topic,last_request,discovery,negotiated) VALUES (?,?,?,?)`, filter.Topic.String(), lastRequest, filter.Discovery, filter.Negotiated)
}
if err != nil {
return
}
}
return
}
func (d *Database) AddChatRequestRange(req ChatRequestRange) error {
_, err := d.db.Exec(`INSERT OR REPLACE INTO mailserver_chat_request_ranges(
chat_id,
@ -275,6 +367,37 @@ func (d *Database) AddChatRequestRange(req ChatRequestRange) error {
return err
}
func (d *Database) AddChatRequestRanges(reqs []ChatRequestRange) (err error) {
var tx *sql.Tx
tx, err = d.db.Begin()
if err != nil {
return err
}
defer func() {
if err == nil {
err = tx.Commit()
return
}
_ = tx.Rollback()
}()
for _, req := range reqs {
_, err = tx.Exec(`INSERT OR REPLACE INTO mailserver_chat_request_ranges(
chat_id,
lowest_request_from,
highest_request_to
) VALUES (?, ?, ?)`,
req.ChatID,
req.LowestRequestFrom,
req.HighestRequestTo,
)
if err != nil {
return
}
}
return
}
func (d *Database) ChatRequestRanges() ([]ChatRequestRange, error) {
var result []ChatRequestRange

View File

@ -15,7 +15,7 @@ import (
gethbridge "github.com/status-im/status-go/eth-node/bridge/geth"
"github.com/status-im/status-go/eth-node/types"
"github.com/status-im/status-go/services/ext"
"github.com/status-im/status-go/whisper/v6"
"github.com/status-im/status-go/whisper"
)
const (

View File

@ -14,7 +14,7 @@ import (
"github.com/status-im/status-go/services/shhext"
"github.com/status-im/status-go/services/wakuext"
"github.com/status-im/status-go/waku"
"github.com/status-im/status-go/whisper/v6"
"github.com/status-im/status-go/whisper"
)
func TestShhextAndWakuextInSingleNode(t *testing.T) {

View File

@ -4,6 +4,7 @@ import (
"database/sql"
"errors"
"fmt"
"os"
_ "github.com/mutecomm/go-sqlcipher" // We require go sqlcipher that overrides default implementation
)
@ -18,6 +19,55 @@ const (
WALMode = "wal"
)
// DecryptDB completely removes the encryption from the db
func DecryptDB(oldPath, newPath, key string) error {
db, err := openDB(oldPath, key)
if err != nil {
return err
}
_, err = db.Exec(`ATTACH DATABASE '` + newPath + `' AS plaintext KEY ''`)
if err != nil {
return err
}
_, err = db.Exec(`SELECT sqlcipher_export('plaintext')`)
if err != nil {
return err
}
_, err = db.Exec(`DETACH DATABASE plaintext`)
return err
}
// EncryptDB takes a plaintext database and adds encryption
func EncryptDB(unencryptedPath, encryptedPath, key string) error {
_ = os.Remove(encryptedPath)
db, err := OpenUnecryptedDB(unencryptedPath)
if err != nil {
return err
}
_, err = db.Exec(`ATTACH DATABASE '` + encryptedPath + `' AS encrypted KEY '` + key + `'`)
if err != nil {
return err
}
_, err = db.Exec(fmt.Sprintf("PRAGMA encrypted.kdf_iter = '%d'", kdfIterationsNumber))
if err != nil {
return err
}
_, err = db.Exec(`SELECT sqlcipher_export('encrypted')`)
if err != nil {
return err
}
_, err = db.Exec(`DETACH DATABASE encrypted`)
return err
}
func openDB(path, key string) (*sql.DB, error) {
db, err := sql.Open("sqlite3", path)
if err != nil {

View File

@ -97,7 +97,7 @@ func ConfigReadmeMd() (*asset, error) {
return nil, err
}
info := bindataFileInfo{name: "../config/README.md", size: 3153, mode: os.FileMode(0644), modTime: time.Unix(1609934130, 0)}
info := bindataFileInfo{name: "../config/README.md", size: 3153, mode: os.FileMode(0644), modTime: time.Unix(1611588835, 0)}
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x84, 0xf1, 0x44, 0x5b, 0x33, 0xe5, 0xfa, 0xe6, 0x38, 0x77, 0x19, 0x91, 0x6e, 0xd8, 0x8e, 0x8d, 0xaa, 0x32, 0xb2, 0x8b, 0xf9, 0x4f, 0x3, 0xe, 0xc0, 0xca, 0x5e, 0x5d, 0xec, 0x37, 0x1d, 0xc3}}
return a, nil
}
@ -117,7 +117,7 @@ func ConfigCliFleetEthProdJson() (*asset, error) {
return nil, err
}
info := bindataFileInfo{name: "../config/cli/fleet-eth.prod.json", size: 4925, mode: os.FileMode(0644), modTime: time.Unix(1609934130, 0)}
info := bindataFileInfo{name: "../config/cli/fleet-eth.prod.json", size: 4925, mode: os.FileMode(0644), modTime: time.Unix(1611588835, 0)}
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x97, 0x5a, 0x72, 0x64, 0x6b, 0xee, 0xe6, 0x97, 0xda, 0xe8, 0x53, 0x7c, 0x33, 0x25, 0x27, 0x55, 0xa8, 0xe0, 0x9a, 0xc2, 0x16, 0xcf, 0xc0, 0x91, 0x8a, 0xbc, 0x98, 0x5, 0xe5, 0x63, 0x83, 0x77}}
return a, nil
}
@ -137,7 +137,7 @@ func ConfigCliFleetEthStagingJson() (*asset, error) {
return nil, err
}
info := bindataFileInfo{name: "../config/cli/fleet-eth.staging.json", size: 2307, mode: os.FileMode(0644), modTime: time.Unix(1609934130, 0)}
info := bindataFileInfo{name: "../config/cli/fleet-eth.staging.json", size: 2307, mode: os.FileMode(0644), modTime: time.Unix(1611588835, 0)}
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xa, 0x55, 0x35, 0x5e, 0xf5, 0x90, 0x37, 0x0, 0xe4, 0x45, 0x8c, 0x19, 0x77, 0x14, 0xa0, 0x94, 0x1c, 0x9b, 0x78, 0xa7, 0x2e, 0x58, 0x45, 0x1b, 0xba, 0xf3, 0xfb, 0x62, 0x87, 0x97, 0xf8, 0x96}}
return a, nil
}
@ -157,7 +157,7 @@ func ConfigCliFleetEthTestJson() (*asset, error) {
return nil, err
}
info := bindataFileInfo{name: "../config/cli/fleet-eth.test.json", size: 2315, mode: os.FileMode(0644), modTime: time.Unix(1609934130, 0)}
info := bindataFileInfo{name: "../config/cli/fleet-eth.test.json", size: 2315, mode: os.FileMode(0644), modTime: time.Unix(1611588835, 0)}
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x7, 0x92, 0x14, 0x26, 0xa6, 0x12, 0xb1, 0x0, 0x2d, 0xbe, 0x9a, 0xb7, 0x55, 0xdb, 0xfc, 0x1f, 0x75, 0xe, 0xc2, 0x2b, 0xad, 0xfe, 0x44, 0x78, 0x2e, 0x7f, 0x8, 0x7f, 0xd1, 0x9e, 0x11, 0x2c}}
return a, nil
}

View File

@ -18,7 +18,7 @@ import (
"github.com/status-im/status-go/params"
"github.com/status-im/status-go/services/ext"
"github.com/status-im/status-go/services/nodebridge"
"github.com/status-im/status-go/whisper/v6"
"github.com/status-im/status-go/whisper"
)
const (

View File

@ -10,7 +10,7 @@ import (
"github.com/ethereum/go-ethereum/node"
"github.com/status-im/status-go/whisper/v6"
"github.com/status-im/status-go/whisper"
)
// TestSendMessages sends messages to a peer.

View File

@ -9,7 +9,7 @@ import (
"github.com/ethereum/go-ethereum/p2p/enode"
"github.com/ethereum/go-ethereum/p2p/nat"
"github.com/status-im/status-go/whisper/v6"
"github.com/status-im/status-go/whisper"
)
var (

View File

@ -11,7 +11,7 @@ import (
"github.com/status-im/status-go/node"
"github.com/status-im/status-go/params"
"github.com/status-im/status-go/whisper/v6"
"github.com/status-im/status-go/whisper"
"github.com/stretchr/testify/suite"

View File

@ -15,7 +15,7 @@ import (
"github.com/status-im/status-go/signal"
"github.com/status-im/status-go/t/utils"
"github.com/status-im/status-go/transactions"
"github.com/status-im/status-go/whisper/v6"
"github.com/status-im/status-go/whisper"
)
// StatusNodeTestSuite defines a test suite with StatusNode.

View File

@ -1,604 +0,0 @@
// Copyright 2016 The go-ethereum Authors
// This file is part of the go-ethereum library.
//
// The go-ethereum library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// The go-ethereum library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
package whisper
import (
"context"
"crypto/ecdsa"
"errors"
"fmt"
"sync"
"time"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/p2p/enode"
"github.com/ethereum/go-ethereum/rpc"
)
// List of errors
var (
ErrSymAsym = errors.New("specify either a symmetric or an asymmetric key")
ErrInvalidSymmetricKey = errors.New("invalid symmetric key")
ErrInvalidPublicKey = errors.New("invalid public key")
ErrInvalidSigningPubKey = errors.New("invalid signing public key")
ErrTooLowPoW = errors.New("message rejected, PoW too low")
ErrNoTopics = errors.New("missing topic(s)")
)
// PublicWhisperAPI provides the whisper RPC service that can be
// use publicly without security implications.
type PublicWhisperAPI struct {
w *Whisper
mu sync.Mutex
lastUsed map[string]time.Time // keeps track when a filter was polled for the last time.
}
// NewPublicWhisperAPI create a new RPC whisper service.
func NewPublicWhisperAPI(w *Whisper) *PublicWhisperAPI {
api := &PublicWhisperAPI{
w: w,
lastUsed: make(map[string]time.Time),
}
return api
}
// Version returns the Whisper sub-protocol version.
func (api *PublicWhisperAPI) Version(ctx context.Context) string {
return ProtocolVersionStr
}
// Info contains diagnostic information.
type Info struct {
Memory int `json:"memory"` // Memory size of the floating messages in bytes.
Messages int `json:"messages"` // Number of floating messages.
MinPow float64 `json:"minPow"` // Minimal accepted PoW
MaxMessageSize uint32 `json:"maxMessageSize"` // Maximum accepted message size
}
// Info returns diagnostic information about the whisper node.
func (api *PublicWhisperAPI) Info(ctx context.Context) Info {
stats := api.w.Stats()
return Info{
Memory: stats.memoryUsed,
Messages: len(api.w.messageQueue) + len(api.w.p2pMsgQueue),
MinPow: api.w.MinPow(),
MaxMessageSize: api.w.MaxMessageSize(),
}
}
// SetMaxMessageSize sets the maximum message size that is accepted.
// Upper limit is defined by MaxMessageSize.
func (api *PublicWhisperAPI) SetMaxMessageSize(ctx context.Context, size uint32) (bool, error) {
return true, api.w.SetMaxMessageSize(size)
}
// SetMinPoW sets the minimum PoW, and notifies the peers.
func (api *PublicWhisperAPI) SetMinPoW(ctx context.Context, pow float64) (bool, error) {
return true, api.w.SetMinimumPoW(pow)
}
// SetBloomFilter sets the new value of bloom filter, and notifies the peers.
func (api *PublicWhisperAPI) SetBloomFilter(ctx context.Context, bloom hexutil.Bytes) (bool, error) {
return true, api.w.SetBloomFilter(bloom)
}
// MarkTrustedPeer marks a peer trusted, which will allow it to send historic (expired) messages.
// Note: This function is not adding new nodes, the node needs to exists as a peer.
func (api *PublicWhisperAPI) MarkTrustedPeer(ctx context.Context, url string) (bool, error) {
n, err := enode.Parse(enode.ValidSchemes, url)
if err != nil {
return false, err
}
return true, api.w.AllowP2PMessagesFromPeer(n.ID().Bytes())
}
// NewKeyPair generates a new public and private key pair for message decryption and encryption.
// It returns an ID that can be used to refer to the keypair.
func (api *PublicWhisperAPI) NewKeyPair(ctx context.Context) (string, error) {
return api.w.NewKeyPair()
}
// AddPrivateKey imports the given private key.
func (api *PublicWhisperAPI) AddPrivateKey(ctx context.Context, privateKey hexutil.Bytes) (string, error) {
key, err := crypto.ToECDSA(privateKey)
if err != nil {
return "", err
}
return api.w.AddKeyPair(key)
}
// DeleteKeyPair removes the key with the given key if it exists.
func (api *PublicWhisperAPI) DeleteKeyPair(ctx context.Context, key string) (bool, error) {
if ok := api.w.DeleteKeyPair(key); ok {
return true, nil
}
return false, fmt.Errorf("key pair %s not found", key)
}
// HasKeyPair returns an indication if the node has a key pair that is associated with the given id.
func (api *PublicWhisperAPI) HasKeyPair(ctx context.Context, id string) bool {
return api.w.HasKeyPair(id)
}
// GetPublicKey returns the public key associated with the given key. The key is the hex
// encoded representation of a key in the form specified in section 4.3.6 of ANSI X9.62.
func (api *PublicWhisperAPI) GetPublicKey(ctx context.Context, id string) (hexutil.Bytes, error) {
key, err := api.w.GetPrivateKey(id)
if err != nil {
return hexutil.Bytes{}, err
}
return crypto.FromECDSAPub(&key.PublicKey), nil
}
// GetPrivateKey returns the private key associated with the given key. The key is the hex
// encoded representation of a key in the form specified in section 4.3.6 of ANSI X9.62.
func (api *PublicWhisperAPI) GetPrivateKey(ctx context.Context, id string) (hexutil.Bytes, error) {
key, err := api.w.GetPrivateKey(id)
if err != nil {
return hexutil.Bytes{}, err
}
return crypto.FromECDSA(key), nil
}
// NewSymKey generate a random symmetric key.
// It returns an ID that can be used to refer to the key.
// Can be used encrypting and decrypting messages where the key is known to both parties.
func (api *PublicWhisperAPI) NewSymKey(ctx context.Context) (string, error) {
return api.w.GenerateSymKey()
}
// AddSymKey import a symmetric key.
// It returns an ID that can be used to refer to the key.
// Can be used encrypting and decrypting messages where the key is known to both parties.
func (api *PublicWhisperAPI) AddSymKey(ctx context.Context, key hexutil.Bytes) (string, error) {
return api.w.AddSymKeyDirect([]byte(key))
}
// GenerateSymKeyFromPassword derive a key from the given password, stores it, and returns its ID.
func (api *PublicWhisperAPI) GenerateSymKeyFromPassword(ctx context.Context, passwd string) (string, error) {
return api.w.AddSymKeyFromPassword(passwd)
}
// HasSymKey returns an indication if the node has a symmetric key associated with the given key.
func (api *PublicWhisperAPI) HasSymKey(ctx context.Context, id string) bool {
return api.w.HasSymKey(id)
}
// GetSymKey returns the symmetric key associated with the given id.
func (api *PublicWhisperAPI) GetSymKey(ctx context.Context, id string) (hexutil.Bytes, error) {
return api.w.GetSymKey(id)
}
// DeleteSymKey deletes the symmetric key that is associated with the given id.
func (api *PublicWhisperAPI) DeleteSymKey(ctx context.Context, id string) bool {
return api.w.DeleteSymKey(id)
}
// MakeLightClient turns the node into light client, which does not forward
// any incoming messages, and sends only messages originated in this node.
func (api *PublicWhisperAPI) MakeLightClient(ctx context.Context) bool {
api.w.SetLightClientMode(true)
return api.w.LightClientMode()
}
// CancelLightClient cancels light client mode.
func (api *PublicWhisperAPI) CancelLightClient(ctx context.Context) bool {
api.w.SetLightClientMode(false)
return !api.w.LightClientMode()
}
//go:generate gencodec -type NewMessage -field-override newMessageOverride -out gen_newmessage_json.go
// NewMessage represents a new whisper message that is posted through the RPC.
type NewMessage struct {
SymKeyID string `json:"symKeyID"`
PublicKey []byte `json:"pubKey"`
Sig string `json:"sig"`
TTL uint32 `json:"ttl"`
Topic TopicType `json:"topic"`
Payload []byte `json:"payload"`
Padding []byte `json:"padding"`
PowTime uint32 `json:"powTime"`
PowTarget float64 `json:"powTarget"`
TargetPeer string `json:"targetPeer"`
}
type newMessageOverride struct {
PublicKey hexutil.Bytes
Payload hexutil.Bytes
Padding hexutil.Bytes
}
// Post posts a message on the Whisper network.
// returns the hash of the message in case of success.
func (api *PublicWhisperAPI) Post(ctx context.Context, req NewMessage) (hexutil.Bytes, error) {
var (
symKeyGiven = len(req.SymKeyID) > 0
pubKeyGiven = len(req.PublicKey) > 0
err error
)
// user must specify either a symmetric or an asymmetric key
if (symKeyGiven && pubKeyGiven) || (!symKeyGiven && !pubKeyGiven) {
return nil, ErrSymAsym
}
params := &MessageParams{
TTL: req.TTL,
Payload: req.Payload,
Padding: req.Padding,
WorkTime: req.PowTime,
PoW: req.PowTarget,
Topic: req.Topic,
}
// Set key that is used to sign the message
if len(req.Sig) > 0 {
if params.Src, err = api.w.GetPrivateKey(req.Sig); err != nil {
return nil, err
}
}
// Set symmetric key that is used to encrypt the message
if symKeyGiven {
if params.Topic == (TopicType{}) { // topics are mandatory with symmetric encryption
return nil, ErrNoTopics
}
if params.KeySym, err = api.w.GetSymKey(req.SymKeyID); err != nil {
return nil, err
}
if !validateDataIntegrity(params.KeySym, aesKeyLength) {
return nil, ErrInvalidSymmetricKey
}
}
// Set asymmetric key that is used to encrypt the message
if pubKeyGiven {
if params.Dst, err = crypto.UnmarshalPubkey(req.PublicKey); err != nil {
return nil, ErrInvalidPublicKey
}
}
// encrypt and sent message
whisperMsg, err := NewSentMessage(params)
if err != nil {
return nil, err
}
var result []byte
env, err := whisperMsg.Wrap(params, api.w.GetCurrentTime())
if err != nil {
return nil, err
}
// send to specific node (skip PoW check)
if len(req.TargetPeer) > 0 {
n, err := enode.Parse(enode.ValidSchemes, req.TargetPeer)
if err != nil {
return nil, fmt.Errorf("failed to parse target peer: %s", err)
}
err = api.w.SendP2PMessage(n.ID().Bytes(), env)
if err == nil {
hash := env.Hash()
result = hash[:]
}
return result, err
}
// ensure that the message PoW meets the node's minimum accepted PoW
if req.PowTarget < api.w.MinPow() {
return nil, ErrTooLowPoW
}
err = api.w.Send(env)
if err == nil {
hash := env.Hash()
result = hash[:]
}
return result, err
}
// UninstallFilter is alias for Unsubscribe
func (api *PublicWhisperAPI) UninstallFilter(id string) {
api.w.Unsubscribe(id)
}
// Unsubscribe disables and removes an existing filter.
func (api *PublicWhisperAPI) Unsubscribe(id string) {
api.w.Unsubscribe(id)
}
//go:generate gencodec -type Criteria -field-override criteriaOverride -out gen_criteria_json.go
// Criteria holds various filter options for inbound messages.
type Criteria struct {
SymKeyID string `json:"symKeyID"`
PrivateKeyID string `json:"privateKeyID"`
Sig []byte `json:"sig"`
MinPow float64 `json:"minPow"`
Topics []TopicType `json:"topics"`
AllowP2P bool `json:"allowP2P"`
}
type criteriaOverride struct {
Sig hexutil.Bytes
}
// Messages set up a subscription that fires events when messages arrive that match
// the given set of criteria.
func (api *PublicWhisperAPI) Messages(ctx context.Context, crit Criteria) (*rpc.Subscription, error) {
var (
symKeyGiven = len(crit.SymKeyID) > 0
pubKeyGiven = len(crit.PrivateKeyID) > 0
err error
)
// ensure that the RPC connection supports subscriptions
notifier, supported := rpc.NotifierFromContext(ctx)
if !supported {
return nil, rpc.ErrNotificationsUnsupported
}
// user must specify either a symmetric or an asymmetric key
if (symKeyGiven && pubKeyGiven) || (!symKeyGiven && !pubKeyGiven) {
return nil, ErrSymAsym
}
filter := Filter{
PoW: crit.MinPow,
Messages: api.w.NewMessageStore(),
AllowP2P: crit.AllowP2P,
}
if len(crit.Sig) > 0 {
if filter.Src, err = crypto.UnmarshalPubkey(crit.Sig); err != nil {
return nil, ErrInvalidSigningPubKey
}
}
for i, bt := range crit.Topics {
if len(bt) == 0 || len(bt) > 4 {
return nil, fmt.Errorf("subscribe: topic %d has wrong size: %d", i, len(bt))
}
filter.Topics = append(filter.Topics, bt[:])
}
// listen for message that are encrypted with the given symmetric key
if symKeyGiven {
if len(filter.Topics) == 0 {
return nil, ErrNoTopics
}
key, err := api.w.GetSymKey(crit.SymKeyID)
if err != nil {
return nil, err
}
if !validateDataIntegrity(key, aesKeyLength) {
return nil, ErrInvalidSymmetricKey
}
filter.KeySym = key
filter.SymKeyHash = crypto.Keccak256Hash(filter.KeySym)
}
// listen for messages that are encrypted with the given public key
if pubKeyGiven {
filter.KeyAsym, err = api.w.GetPrivateKey(crit.PrivateKeyID)
if err != nil || filter.KeyAsym == nil {
return nil, ErrInvalidPublicKey
}
}
id, err := api.w.Subscribe(&filter)
if err != nil {
return nil, err
}
// create subscription and start waiting for message events
rpcSub := notifier.CreateSubscription()
go func() {
// for now poll internally, refactor whisper internal for channel support
ticker := time.NewTicker(250 * time.Millisecond)
defer ticker.Stop()
for {
select {
case <-ticker.C:
if filter := api.w.GetFilter(id); filter != nil {
for _, rpcMessage := range toMessage(filter.Retrieve()) {
if err := notifier.Notify(rpcSub.ID, rpcMessage); err != nil {
log.Error("Failed to send notification", "err", err)
}
}
}
case <-rpcSub.Err():
api.w.Unsubscribe(id)
return
case <-notifier.Closed():
api.w.Unsubscribe(id)
return
}
}
}()
return rpcSub, nil
}
//go:generate gencodec -type Message -field-override messageOverride -out gen_message_json.go
// Message is the RPC representation of a whisper message.
type Message struct {
Sig []byte `json:"sig,omitempty"`
TTL uint32 `json:"ttl"`
Timestamp uint32 `json:"timestamp"`
Topic TopicType `json:"topic"`
Payload []byte `json:"payload"`
Padding []byte `json:"padding"`
PoW float64 `json:"pow"`
Hash []byte `json:"hash"`
Dst []byte `json:"recipientPublicKey,omitempty"`
P2P bool `json:"bool,omitempty"`
}
type messageOverride struct {
Sig hexutil.Bytes
Payload hexutil.Bytes
Padding hexutil.Bytes
Hash hexutil.Bytes
Dst hexutil.Bytes
}
// ToWhisperMessage converts an internal message into an API version.
func ToWhisperMessage(message *ReceivedMessage) *Message {
msg := Message{
Payload: message.Payload,
Padding: message.Padding,
Timestamp: message.Sent,
TTL: message.TTL,
PoW: message.PoW,
Hash: message.EnvelopeHash.Bytes(),
Topic: message.Topic,
P2P: message.P2P,
}
if message.Dst != nil {
b := crypto.FromECDSAPub(message.Dst)
if b != nil {
msg.Dst = b
}
}
if isMessageSigned(message.Raw[0]) {
b := crypto.FromECDSAPub(message.SigToPubKey())
if b != nil {
msg.Sig = b
}
}
return &msg
}
// toMessage converts a set of messages to its RPC representation.
func toMessage(messages []*ReceivedMessage) []*Message {
msgs := make([]*Message, len(messages))
for i, msg := range messages {
msgs[i] = ToWhisperMessage(msg)
}
return msgs
}
// GetFilterMessages returns the messages that match the filter criteria and
// are received between the last poll and now.
func (api *PublicWhisperAPI) GetFilterMessages(id string) ([]*Message, error) {
api.mu.Lock()
f := api.w.GetFilter(id)
if f == nil {
api.mu.Unlock()
return nil, fmt.Errorf("filter not found")
}
api.lastUsed[id] = time.Now()
api.mu.Unlock()
receivedMessages := f.Retrieve()
messages := make([]*Message, 0, len(receivedMessages))
for _, msg := range receivedMessages {
messages = append(messages, ToWhisperMessage(msg))
}
return messages, nil
}
// DeleteMessageFilter deletes a filter.
func (api *PublicWhisperAPI) DeleteMessageFilter(id string) (bool, error) {
api.mu.Lock()
defer api.mu.Unlock()
delete(api.lastUsed, id)
return true, api.w.Unsubscribe(id)
}
// NewMessageFilter creates a new filter that can be used to poll for
// (new) messages that satisfy the given criteria.
func (api *PublicWhisperAPI) NewMessageFilter(req Criteria) (string, error) {
var (
src *ecdsa.PublicKey
keySym []byte
keyAsym *ecdsa.PrivateKey
topics [][]byte
symKeyGiven = len(req.SymKeyID) > 0
asymKeyGiven = len(req.PrivateKeyID) > 0
err error
)
// user must specify either a symmetric or an asymmetric key
if (symKeyGiven && asymKeyGiven) || (!symKeyGiven && !asymKeyGiven) {
return "", ErrSymAsym
}
if len(req.Sig) > 0 {
if src, err = crypto.UnmarshalPubkey(req.Sig); err != nil {
return "", ErrInvalidSigningPubKey
}
}
if symKeyGiven {
if keySym, err = api.w.GetSymKey(req.SymKeyID); err != nil {
return "", err
}
if !validateDataIntegrity(keySym, aesKeyLength) {
return "", ErrInvalidSymmetricKey
}
}
if asymKeyGiven {
if keyAsym, err = api.w.GetPrivateKey(req.PrivateKeyID); err != nil {
return "", err
}
}
if len(req.Topics) > 0 {
topics = make([][]byte, len(req.Topics))
for i, topic := range req.Topics {
topics[i] = make([]byte, TopicLength)
copy(topics[i], topic[:])
}
}
f := &Filter{
Src: src,
KeySym: keySym,
KeyAsym: keyAsym,
PoW: req.MinPow,
AllowP2P: req.AllowP2P,
Topics: topics,
Messages: api.w.NewMessageStore(),
}
id, err := api.w.Subscribe(f)
if err != nil {
return "", err
}
api.mu.Lock()
api.lastUsed[id] = time.Now()
api.mu.Unlock()
return id, nil
}

View File

@ -1,32 +0,0 @@
// Copyright 2017 The go-ethereum Authors
// This file is part of the go-ethereum library.
//
// The go-ethereum library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// The go-ethereum library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
package whisper
// Config represents the configuration state of a whisper node.
type Config struct {
MaxMessageSize uint32 `toml:",omitempty"`
MinimumAcceptedPOW float64 `toml:",omitempty"`
RestrictConnectionBetweenLightClients bool `toml:",omitempty"`
DisableConfirmations bool `toml:",omitempty"`
}
// DefaultConfig represents (shocker!) the default configuration.
var DefaultConfig = Config{
MaxMessageSize: DefaultMaxMessageSize,
MinimumAcceptedPOW: DefaultMinimumPoW,
RestrictConnectionBetweenLightClients: true,
}

View File

@ -1,273 +0,0 @@
// Copyright 2016 The go-ethereum Authors
// This file is part of the go-ethereum library.
//
// The go-ethereum library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// The go-ethereum library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
/*
Package whisper implements the Whisper protocol (version 6).
Whisper combines aspects of both DHTs and datagram messaging systems (e.g. UDP).
As such it may be likened and compared to both, not dissimilar to the
matter/energy duality (apologies to physicists for the blatant abuse of a
fundamental and beautiful natural principle).
Whisper is a pure identity-based messaging system. Whisper provides a low-level
(non-application-specific) but easily-accessible API without being based upon
or prejudiced by the low-level hardware attributes and characteristics,
particularly the notion of singular endpoints.
*/
// Contains the Whisper protocol constant definitions
package whisper
import (
"errors"
"fmt"
"time"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/rlp"
)
// Whisper protocol parameters
const (
ProtocolVersion = uint64(6) // Protocol version number
ProtocolVersionStr = "6.0" // The same, as a string
ProtocolName = "shh" // Nickname of the protocol in geth
// whisper protocol message codes, according to EIP-627
statusCode = 0 // used by whisper protocol
messagesCode = 1 // normal whisper message
powRequirementCode = 2 // PoW requirement
bloomFilterExCode = 3 // bloom filter exchange
batchAcknowledgedCode = 11 // confirmation that batch of envelopes was received
messageResponseCode = 12 // includes confirmation for delivery and information about errors
rateLimitingCode = 20 // includes peer's rate limiting settings
p2pSyncRequestCode = 123 // used to sync envelopes between two mail servers
p2pSyncResponseCode = 124 // used to sync envelopes between two mail servers
p2pRequestCompleteCode = 125 // peer-to-peer message, used by Dapp protocol
p2pRequestCode = 126 // peer-to-peer message, used by Dapp protocol
p2pMessageCode = 127 // peer-to-peer message (to be consumed by the peer, but not forwarded any further)
NumberOfMessageCodes = 128
SizeMask = byte(3) // mask used to extract the size of payload size field from the flags
signatureFlag = byte(4)
TopicLength = 4 // in bytes
signatureLength = crypto.SignatureLength // in bytes
aesKeyLength = 32 // in bytes
aesNonceLength = 12 // in bytes; for more info please see cipher.gcmStandardNonceSize & aesgcm.NonceSize()
keyIDSize = 32 // in bytes
BloomFilterSize = 64 // in bytes
flagsLength = 1
EnvelopeHeaderLength = 20
MaxMessageSize = uint32(10 * 1024 * 1024) // maximum accepted size of a message.
DefaultMaxMessageSize = uint32(1024 * 1024)
DefaultMinimumPoW = 0.2
padSizeLimit = 256 // just an arbitrary number, could be changed without breaking the protocol
messageQueueLimit = 1024
expirationCycle = time.Second
transmissionCycle = 300 * time.Millisecond
DefaultTTL = 50 // seconds
DefaultSyncAllowance = 10 // seconds
MaxLimitInSyncMailRequest = 1000
EnvelopeTimeNotSynced uint = iota + 1
EnvelopeOtherError
MaxLimitInMessagesRequest = 1000
)
// MailServer represents a mail server, capable of
// archiving the old messages for subsequent delivery
// to the peers. Any implementation must ensure that both
// functions are thread-safe. Also, they must return ASAP.
// DeliverMail should use directMessagesCode for delivery,
// in order to bypass the expiry checks.
type MailServer interface {
Archive(env *Envelope)
DeliverMail(peerID []byte, req *Envelope) // DEPRECATED; user Deliver instead
Deliver(peerID []byte, req MessagesRequest)
SyncMail(peerID []byte, req SyncMailRequest) error
}
// MessagesRequest contains details of a request of historic messages.
type MessagesRequest struct {
// ID of the request. The current implementation requires ID to be 32-byte array,
// however, it's not enforced for future implementation.
ID []byte `json:"id"`
// From is a lower bound of time range.
From uint32 `json:"from"`
// To is a upper bound of time range.
To uint32 `json:"to"`
// Limit determines the number of messages sent by the mail server
// for the current paginated request.
Limit uint32 `json:"limit"`
// Cursor is used as starting point for paginated requests.
Cursor []byte `json:"cursor"`
// Bloom is a filter to match requested messages.
Bloom []byte `json:"bloom"`
}
func (r MessagesRequest) Validate() error {
if len(r.ID) != common.HashLength {
return errors.New("invalid 'ID', expected a 32-byte slice")
}
if r.From > r.To {
return errors.New("invalid 'From' value which is greater than To")
}
if r.Limit > MaxLimitInMessagesRequest {
return fmt.Errorf("invalid 'Limit' value, expected value lower than %d", MaxLimitInMessagesRequest)
}
if len(r.Bloom) == 0 {
return errors.New("invalid 'Bloom' provided")
}
return nil
}
// SyncMailRequest contains details which envelopes should be synced
// between Mail Servers.
type SyncMailRequest struct {
// Lower is a lower bound of time range for which messages are requested.
Lower uint32
// Upper is a lower bound of time range for which messages are requested.
Upper uint32
// Bloom is a bloom filter to filter envelopes.
Bloom []byte
// Limit is the max number of envelopes to return.
Limit uint32
// Cursor is used for pagination of the results.
Cursor []byte
}
// Validate checks request's fields if they are valid.
func (r SyncMailRequest) Validate() error {
if r.Limit == 0 {
return errors.New("invalid 'Limit' value, expected value greater than 0")
}
if r.Limit > MaxLimitInSyncMailRequest {
return fmt.Errorf("invalid 'Limit' value, expected value lower than %d", MaxLimitInSyncMailRequest)
}
if r.Lower > r.Upper {
return errors.New("invalid 'Lower' value, can't be greater than 'Upper'")
}
return nil
}
// SyncResponse is a struct representing a response sent to the peer
// asking for syncing archived envelopes.
type SyncResponse struct {
Envelopes []*Envelope
Cursor []byte
Final bool // if true it means all envelopes were processed
Error string
}
// RawSyncResponse is a struct representing a response sent to the peer
// asking for syncing archived envelopes.
type RawSyncResponse struct {
Envelopes []rlp.RawValue
Cursor []byte
Final bool // if true it means all envelopes were processed
Error string
}
// MessagesResponse sent as a response after processing batch of envelopes.
type MessagesResponse struct {
// Hash is a hash of all envelopes sent in the single batch.
Hash common.Hash
// Per envelope error.
Errors []EnvelopeError
}
// EnvelopeError code and optional description of the error.
type EnvelopeError struct {
Hash common.Hash
Code uint
Description string
}
// MultiVersionResponse allows to decode response into chosen version.
type MultiVersionResponse struct {
Version uint
Response rlp.RawValue
}
// DecodeResponse1 decodes response into first version of the messages response.
func (m MultiVersionResponse) DecodeResponse1() (resp MessagesResponse, err error) {
return resp, rlp.DecodeBytes(m.Response, &resp)
}
// Version1MessageResponse first version of the message response.
type Version1MessageResponse struct {
Version uint
Response MessagesResponse
}
// NewMessagesResponse returns instane of the version messages response.
func NewMessagesResponse(batch common.Hash, errors []EnvelopeError) Version1MessageResponse {
return Version1MessageResponse{
Version: 1,
Response: MessagesResponse{
Hash: batch,
Errors: errors,
},
}
}
// ErrorToEnvelopeError converts common golang error into EnvelopeError with a code.
func ErrorToEnvelopeError(hash common.Hash, err error) EnvelopeError {
code := EnvelopeOtherError
switch err.(type) {
case TimeSyncError:
code = EnvelopeTimeNotSynced
}
return EnvelopeError{
Hash: hash,
Code: code,
Description: err.Error(),
}
}
// RateLimits contains information about rate limit settings.
// It is exchanged using rateLimitingCode packet or in the handshake.
type RateLimits struct {
IPLimits uint64 // messages per second from a single IP (default 0, no limits)
PeerIDLimits uint64 // messages per second from a single peer ID (default 0, no limits)
TopicLimits uint64 // messages per second from a single topic (default 0, no limits)
}
func (r RateLimits) IsZero() bool {
return r == (RateLimits{})
}

View File

@ -1,280 +0,0 @@
// Copyright 2016 The go-ethereum Authors
// This file is part of the go-ethereum library.
//
// The go-ethereum library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// The go-ethereum library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
// Contains the Whisper protocol Envelope element.
package whisper
import (
"crypto/ecdsa"
"encoding/binary"
"fmt"
gmath "math"
"math/big"
"time"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/crypto/ecies"
"github.com/ethereum/go-ethereum/rlp"
)
// Envelope represents a clear-text data packet to transmit through the Whisper
// network. Its contents may or may not be encrypted and signed.
type Envelope struct {
Expiry uint32
TTL uint32
Topic TopicType
Data []byte
Nonce uint64
pow float64 // Message-specific PoW as described in the Whisper specification.
// the following variables should not be accessed directly, use the corresponding function instead: Hash(), Bloom()
hash common.Hash // Cached hash of the envelope to avoid rehashing every time.
bloom []byte
}
// size returns the size of envelope as it is sent (i.e. public fields only)
func (e *Envelope) size() int {
return EnvelopeHeaderLength + len(e.Data)
}
// rlpWithoutNonce returns the RLP encoded envelope contents, except the nonce.
func (e *Envelope) rlpWithoutNonce() []byte {
res, _ := rlp.EncodeToBytes([]interface{}{e.Expiry, e.TTL, e.Topic, e.Data})
return res
}
// NewEnvelope wraps a Whisper message with expiration and destination data
// included into an envelope for network forwarding.
func NewEnvelope(ttl uint32, topic TopicType, msg *sentMessage, now time.Time) *Envelope {
env := Envelope{
Expiry: uint32(now.Add(time.Second * time.Duration(ttl)).Unix()),
TTL: ttl,
Topic: topic,
Data: msg.Raw,
Nonce: 0,
}
return &env
}
// Seal closes the envelope by spending the requested amount of time as a proof
// of work on hashing the data.
func (e *Envelope) Seal(options *MessageParams) error {
if options.PoW == 0 {
// PoW is not required
return nil
}
var target, bestLeadingZeros int
if options.PoW < 0 {
// target is not set - the function should run for a period
// of time specified in WorkTime param. Since we can predict
// the execution time, we can also adjust Expiry.
e.Expiry += options.WorkTime
} else {
target = e.powToFirstBit(options.PoW)
}
rlp := e.rlpWithoutNonce()
buf := make([]byte, len(rlp)+8)
copy(buf, rlp)
asAnInt := new(big.Int)
finish := time.Now().Add(time.Duration(options.WorkTime) * time.Second).UnixNano()
for nonce := uint64(0); time.Now().UnixNano() < finish; {
for i := 0; i < 1024; i++ {
binary.BigEndian.PutUint64(buf[len(rlp):], nonce)
h := crypto.Keccak256(buf)
asAnInt.SetBytes(h)
leadingZeros := 256 - asAnInt.BitLen()
if leadingZeros > bestLeadingZeros {
e.Nonce, bestLeadingZeros = nonce, leadingZeros
if target > 0 && bestLeadingZeros >= target {
return nil
}
}
nonce++
}
}
if target > 0 && bestLeadingZeros < target {
return fmt.Errorf("failed to reach the PoW target, specified pow time (%d seconds) was insufficient", options.WorkTime)
}
return nil
}
// PoW computes (if necessary) and returns the proof of work target
// of the envelope.
func (e *Envelope) PoW() float64 {
if e.pow == 0 {
e.calculatePoW(0)
}
return e.pow
}
func (e *Envelope) calculatePoW(diff uint32) {
rlp := e.rlpWithoutNonce()
buf := make([]byte, len(rlp)+8)
copy(buf, rlp)
binary.BigEndian.PutUint64(buf[len(rlp):], e.Nonce)
powHash := new(big.Int).SetBytes(crypto.Keccak256(buf))
leadingZeroes := 256 - powHash.BitLen()
x := gmath.Pow(2, float64(leadingZeroes))
x /= float64(len(rlp))
x /= float64(e.TTL + diff)
e.pow = x
}
func (e *Envelope) powToFirstBit(pow float64) int {
x := pow
x *= float64(e.size())
x *= float64(e.TTL)
bits := gmath.Log2(x)
bits = gmath.Ceil(bits)
res := int(bits)
if res < 1 {
res = 1
}
return res
}
// Hash returns the SHA3 hash of the envelope, calculating it if not yet done.
func (e *Envelope) Hash() common.Hash {
if (e.hash == common.Hash{}) {
encoded, _ := rlp.EncodeToBytes(e)
e.hash = crypto.Keccak256Hash(encoded)
}
return e.hash
}
// DecodeRLP decodes an Envelope from an RLP data stream.
func (e *Envelope) DecodeRLP(s *rlp.Stream) error {
raw, err := s.Raw()
if err != nil {
return err
}
// The decoding of Envelope uses the struct fields but also needs
// to compute the hash of the whole RLP-encoded envelope. This
// type has the same structure as Envelope but is not an
// rlp.Decoder (does not implement DecodeRLP function).
// Only public members will be encoded.
type rlpenv Envelope
if err := rlp.DecodeBytes(raw, (*rlpenv)(e)); err != nil {
return err
}
e.hash = crypto.Keccak256Hash(raw)
return nil
}
// OpenAsymmetric tries to decrypt an envelope, potentially encrypted with a particular key.
func (e *Envelope) OpenAsymmetric(key *ecdsa.PrivateKey) (*ReceivedMessage, error) {
message := &ReceivedMessage{Raw: e.Data}
err := message.decryptAsymmetric(key)
switch err {
case nil:
return message, nil
case ecies.ErrInvalidPublicKey: // addressed to somebody else
return nil, err
default:
return nil, fmt.Errorf("unable to open envelope, decrypt failed: %v", err)
}
}
// OpenSymmetric tries to decrypt an envelope, potentially encrypted with a particular key.
func (e *Envelope) OpenSymmetric(key []byte) (msg *ReceivedMessage, err error) {
msg = &ReceivedMessage{Raw: e.Data}
err = msg.decryptSymmetric(key)
if err != nil {
msg = nil
}
return msg, err
}
// Open tries to decrypt an envelope, and populates the message fields in case of success.
func (e *Envelope) Open(watcher *Filter) (msg *ReceivedMessage) {
if watcher == nil {
return nil
}
// The API interface forbids filters doing both symmetric and asymmetric encryption.
if watcher.expectsAsymmetricEncryption() && watcher.expectsSymmetricEncryption() {
return nil
}
if watcher.expectsAsymmetricEncryption() {
msg, _ = e.OpenAsymmetric(watcher.KeyAsym)
if msg != nil {
msg.Dst = &watcher.KeyAsym.PublicKey
}
} else if watcher.expectsSymmetricEncryption() {
msg, _ = e.OpenSymmetric(watcher.KeySym)
if msg != nil {
msg.SymKeyHash = crypto.Keccak256Hash(watcher.KeySym)
}
}
if msg != nil {
ok := msg.ValidateAndParse()
if !ok {
return nil
}
msg.Topic = e.Topic
msg.PoW = e.PoW()
msg.TTL = e.TTL
msg.Sent = e.Expiry - e.TTL
msg.EnvelopeHash = e.Hash()
}
return msg
}
// Bloom maps 4-bytes Topic into 64-byte bloom filter with 3 bits set (at most).
func (e *Envelope) Bloom() []byte {
if e.bloom == nil {
e.bloom = TopicToBloom(e.Topic)
}
return e.bloom
}
// TopicToBloom converts the topic (4 bytes) to the bloom filter (64 bytes)
func TopicToBloom(topic TopicType) []byte {
b := make([]byte, BloomFilterSize)
var index [3]int
for j := 0; j < 3; j++ {
index[j] = int(topic[j])
if (topic[3] & (1 << uint(j))) != 0 {
index[j] += 256
}
}
for j := 0; j < 3; j++ {
byteIndex := index[j] / 8
bitIndex := index[j] % 8
b[byteIndex] = (1 << uint(bitIndex))
}
return b
}
// GetEnvelope retrieves an envelope from the message queue by its hash.
// It returns nil if the envelope can not be found.
func (w *Whisper) GetEnvelope(hash common.Hash) *Envelope {
w.poolMu.RLock()
defer w.poolMu.RUnlock()
return w.envelopes[hash]
}

View File

@ -1,53 +0,0 @@
package whisper
import (
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/p2p/enode"
)
// EventType used to define known envelope events.
type EventType string
const (
// EventEnvelopeSent fires when envelope was sent to a peer.
EventEnvelopeSent EventType = "envelope.sent"
// EventEnvelopeExpired fires when envelop expired
EventEnvelopeExpired EventType = "envelope.expired"
// EventEnvelopeReceived is sent once envelope was received from a peer.
// EventEnvelopeReceived must be sent to the feed even if envelope was previously in the cache.
// And event, ideally, should contain information about peer that sent envelope to us.
EventEnvelopeReceived EventType = "envelope.received"
// EventBatchAcknowledged is sent when batch of envelopes was acknowledged by a peer.
EventBatchAcknowledged EventType = "batch.acknowleged"
// EventEnvelopeAvailable fires when envelop is available for filters
EventEnvelopeAvailable EventType = "envelope.available"
// EventMailServerRequestSent fires when such request is sent.
EventMailServerRequestSent EventType = "mailserver.request.sent"
// EventMailServerRequestCompleted fires after mailserver sends all the requested messages
EventMailServerRequestCompleted EventType = "mailserver.request.completed"
// EventMailServerRequestExpired fires after mailserver the request TTL ends.
// This event is independent and concurrent to EventMailServerRequestCompleted.
// Request should be considered as expired only if expiry event was received first.
EventMailServerRequestExpired EventType = "mailserver.request.expired"
// EventMailServerEnvelopeArchived fires after an envelope has been archived
EventMailServerEnvelopeArchived EventType = "mailserver.envelope.archived"
// EventMailServerSyncFinished fires when the sync of messages is finished.
EventMailServerSyncFinished EventType = "mailserver.sync.finished"
)
// EnvelopeEvent used for envelopes events.
type EnvelopeEvent struct {
Event EventType
Topic TopicType
Hash common.Hash
Batch common.Hash
Peer enode.ID
Data interface{}
}
// SyncEventResponse is a response from the Mail Server
// form which the peer received envelopes.
type SyncEventResponse struct {
Cursor []byte
Error string
}

View File

@ -1,294 +0,0 @@
// Copyright 2016 The go-ethereum Authors
// This file is part of the go-ethereum library.
//
// The go-ethereum library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// The go-ethereum library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
package whisper
import (
"crypto/ecdsa"
"fmt"
"sync"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/log"
)
// MessageStore defines interface for temporary message store.
type MessageStore interface {
Add(*ReceivedMessage) error
Pop() ([]*ReceivedMessage, error)
}
// NewMemoryMessageStore returns pointer to an instance of the MemoryMessageStore.
func NewMemoryMessageStore() *MemoryMessageStore {
return &MemoryMessageStore{
messages: map[common.Hash]*ReceivedMessage{},
}
}
// MemoryMessageStore stores massages in memory hash table.
type MemoryMessageStore struct {
mu sync.Mutex
messages map[common.Hash]*ReceivedMessage
}
// Add adds message to store.
func (store *MemoryMessageStore) Add(msg *ReceivedMessage) error {
store.mu.Lock()
defer store.mu.Unlock()
if _, exist := store.messages[msg.EnvelopeHash]; !exist {
store.messages[msg.EnvelopeHash] = msg
}
return nil
}
// Pop returns all available messages and cleans the store.
func (store *MemoryMessageStore) Pop() ([]*ReceivedMessage, error) {
store.mu.Lock()
defer store.mu.Unlock()
all := make([]*ReceivedMessage, 0, len(store.messages))
for hash, msg := range store.messages {
delete(store.messages, hash)
all = append(all, msg)
}
return all, nil
}
// Filter represents a Whisper message filter
type Filter struct {
Src *ecdsa.PublicKey // Sender of the message
KeyAsym *ecdsa.PrivateKey // Private Key of recipient
KeySym []byte // Key associated with the Topic
Topics [][]byte // Topics to filter messages with
PoW float64 // Proof of work as described in the Whisper spec
AllowP2P bool // Indicates whether this filter is interested in direct peer-to-peer messages
SymKeyHash common.Hash // The Keccak256Hash of the symmetric key, needed for optimization
id string // unique identifier
Messages MessageStore
mutex sync.RWMutex
}
// Filters represents a collection of filters
type Filters struct {
watchers map[string]*Filter
topicMatcher map[TopicType]map[*Filter]struct{} // map a topic to the filters that are interested in being notified when a message matches that topic
allTopicsMatcher map[*Filter]struct{} // list all the filters that will be notified of a new message, no matter what its topic is
whisper *Whisper
mutex sync.RWMutex
}
// NewFilters returns a newly created filter collection
func NewFilters(w *Whisper) *Filters {
return &Filters{
watchers: make(map[string]*Filter),
topicMatcher: make(map[TopicType]map[*Filter]struct{}),
allTopicsMatcher: make(map[*Filter]struct{}),
whisper: w,
}
}
// Install will add a new filter to the filter collection
func (fs *Filters) Install(watcher *Filter) (string, error) {
if watcher.KeySym != nil && watcher.KeyAsym != nil {
return "", fmt.Errorf("filters must choose between symmetric and asymmetric keys")
}
id, err := GenerateRandomID()
if err != nil {
return "", err
}
fs.mutex.Lock()
defer fs.mutex.Unlock()
if fs.watchers[id] != nil {
return "", fmt.Errorf("failed to generate unique ID")
}
if watcher.expectsSymmetricEncryption() {
watcher.SymKeyHash = crypto.Keccak256Hash(watcher.KeySym)
}
watcher.id = id
fs.watchers[id] = watcher
fs.addTopicMatcher(watcher)
return id, err
}
// Uninstall will remove a filter whose id has been specified from
// the filter collection
func (fs *Filters) Uninstall(id string) bool {
fs.mutex.Lock()
defer fs.mutex.Unlock()
if fs.watchers[id] != nil {
fs.removeFromTopicMatchers(fs.watchers[id])
delete(fs.watchers, id)
return true
}
return false
}
// addTopicMatcher adds a filter to the topic matchers.
// If the filter's Topics array is empty, it will be tried on every topic.
// Otherwise, it will be tried on the topics specified.
func (fs *Filters) addTopicMatcher(watcher *Filter) {
if len(watcher.Topics) == 0 {
fs.allTopicsMatcher[watcher] = struct{}{}
} else {
for _, t := range watcher.Topics {
topic := BytesToTopic(t)
if fs.topicMatcher[topic] == nil {
fs.topicMatcher[topic] = make(map[*Filter]struct{})
}
fs.topicMatcher[topic][watcher] = struct{}{}
}
}
}
// removeFromTopicMatchers removes a filter from the topic matchers
func (fs *Filters) removeFromTopicMatchers(watcher *Filter) {
delete(fs.allTopicsMatcher, watcher)
for _, topic := range watcher.Topics {
delete(fs.topicMatcher[BytesToTopic(topic)], watcher)
}
}
// getWatchersByTopic returns a slice containing the filters that
// match a specific topic
func (fs *Filters) getWatchersByTopic(topic TopicType) []*Filter {
res := make([]*Filter, 0, len(fs.allTopicsMatcher))
for watcher := range fs.allTopicsMatcher {
res = append(res, watcher)
}
for watcher := range fs.topicMatcher[topic] {
res = append(res, watcher)
}
return res
}
// Get returns a filter from the collection with a specific ID
func (fs *Filters) Get(id string) *Filter {
fs.mutex.RLock()
defer fs.mutex.RUnlock()
return fs.watchers[id]
}
// NotifyWatchers notifies any filter that has declared interest
// for the envelope's topic.
func (fs *Filters) NotifyWatchers(env *Envelope, p2pMessage bool) {
var msg *ReceivedMessage
fs.mutex.RLock()
defer fs.mutex.RUnlock()
candidates := fs.getWatchersByTopic(env.Topic)
for _, watcher := range candidates {
if p2pMessage && !watcher.AllowP2P {
log.Trace(fmt.Sprintf("msg [%x], filter [%s]: p2p messages are not allowed", env.Hash(), watcher.id))
continue
}
var match bool
if msg != nil {
match = watcher.MatchMessage(msg)
} else {
match = watcher.MatchEnvelope(env)
if match {
msg = env.Open(watcher)
if msg == nil {
log.Trace("processing message: failed to open", "message", env.Hash().Hex(), "filter", watcher.id)
}
} else {
log.Trace("processing message: does not match", "message", env.Hash().Hex(), "filter", watcher.id)
}
}
if match && msg != nil {
msg.P2P = p2pMessage
log.Trace("processing message: decrypted", "hash", env.Hash().Hex())
if watcher.Src == nil || IsPubKeyEqual(msg.Src, watcher.Src) {
watcher.Trigger(msg)
}
}
}
}
func (f *Filter) expectsAsymmetricEncryption() bool {
return f.KeyAsym != nil
}
func (f *Filter) expectsSymmetricEncryption() bool {
return f.KeySym != nil
}
// Trigger adds a yet-unknown message to the filter's list of
// received messages.
func (f *Filter) Trigger(msg *ReceivedMessage) {
err := f.Messages.Add(msg)
if err != nil {
log.Error("failed to add msg into the filters store", "hash", msg.EnvelopeHash, "error", err)
}
}
// Retrieve will return the list of all received messages associated
// to a filter.
func (f *Filter) Retrieve() []*ReceivedMessage {
msgs, err := f.Messages.Pop()
if err != nil {
log.Error("failed to retrieve messages from filter store", "error", err)
return nil
}
return msgs
}
// MatchMessage checks if the filter matches an already decrypted
// message (i.e. a Message that has already been handled by
// MatchEnvelope when checked by a previous filter).
// Topics are not checked here, since this is done by topic matchers.
func (f *Filter) MatchMessage(msg *ReceivedMessage) bool {
if f.PoW > 0 && msg.PoW < f.PoW {
return false
}
if f.expectsAsymmetricEncryption() && msg.isAsymmetricEncryption() {
return IsPubKeyEqual(&f.KeyAsym.PublicKey, msg.Dst)
} else if f.expectsSymmetricEncryption() && msg.isSymmetricEncryption() {
return f.SymKeyHash == msg.SymKeyHash
}
return false
}
// MatchEnvelope checks if it's worth decrypting the message. If
// it returns `true`, client code is expected to attempt decrypting
// the message and subsequently call MatchMessage.
// Topics are not checked here, since this is done by topic matchers.
func (f *Filter) MatchEnvelope(envelope *Envelope) bool {
return f.PoW <= 0 || envelope.pow >= f.PoW
}
// IsPubKeyEqual checks that two public keys are equal
func IsPubKeyEqual(a, b *ecdsa.PublicKey) bool {
if !ValidatePublicKey(a) {
return false
} else if !ValidatePublicKey(b) {
return false
}
// the curve is always the same, just compare the points
return a.X.Cmp(b.X) == 0 && a.Y.Cmp(b.Y) == 0
}

View File

@ -1,14 +0,0 @@
// +build gofuzz
package whisper
func Fuzz(data []byte) int {
if len(data) < 2 {
return -1
}
msg := &ReceivedMessage{Raw: data}
msg.ValidateAndParse()
return 0
}

View File

@ -1,66 +0,0 @@
// Code generated by github.com/fjl/gencodec. DO NOT EDIT.
package whisper
import (
"encoding/json"
"github.com/ethereum/go-ethereum/common/hexutil"
)
var _ = (*criteriaOverride)(nil)
// MarshalJSON marshals type Criteria to a json string
func (c Criteria) MarshalJSON() ([]byte, error) {
type Criteria struct {
SymKeyID string `json:"symKeyID"`
PrivateKeyID string `json:"privateKeyID"`
Sig hexutil.Bytes `json:"sig"`
MinPow float64 `json:"minPow"`
Topics []TopicType `json:"topics"`
AllowP2P bool `json:"allowP2P"`
}
var enc Criteria
enc.SymKeyID = c.SymKeyID
enc.PrivateKeyID = c.PrivateKeyID
enc.Sig = c.Sig
enc.MinPow = c.MinPow
enc.Topics = c.Topics
enc.AllowP2P = c.AllowP2P
return json.Marshal(&enc)
}
// UnmarshalJSON unmarshals type Criteria to a json string
func (c *Criteria) UnmarshalJSON(input []byte) error {
type Criteria struct {
SymKeyID *string `json:"symKeyID"`
PrivateKeyID *string `json:"privateKeyID"`
Sig *hexutil.Bytes `json:"sig"`
MinPow *float64 `json:"minPow"`
Topics []TopicType `json:"topics"`
AllowP2P *bool `json:"allowP2P"`
}
var dec Criteria
if err := json.Unmarshal(input, &dec); err != nil {
return err
}
if dec.SymKeyID != nil {
c.SymKeyID = *dec.SymKeyID
}
if dec.PrivateKeyID != nil {
c.PrivateKeyID = *dec.PrivateKeyID
}
if dec.Sig != nil {
c.Sig = *dec.Sig
}
if dec.MinPow != nil {
c.MinPow = *dec.MinPow
}
if dec.Topics != nil {
c.Topics = dec.Topics
}
if dec.AllowP2P != nil {
c.AllowP2P = *dec.AllowP2P
}
return nil
}

View File

@ -1,84 +0,0 @@
// Code generated by github.com/fjl/gencodec. DO NOT EDIT.
package whisper
import (
"encoding/json"
"github.com/ethereum/go-ethereum/common/hexutil"
)
var _ = (*messageOverride)(nil)
// MarshalJSON marshals type Message to a json string
func (m Message) MarshalJSON() ([]byte, error) {
type Message struct {
Sig hexutil.Bytes `json:"sig,omitempty"`
TTL uint32 `json:"ttl"`
Timestamp uint32 `json:"timestamp"`
Topic TopicType `json:"topic"`
Payload hexutil.Bytes `json:"payload"`
Padding hexutil.Bytes `json:"padding"`
PoW float64 `json:"pow"`
Hash hexutil.Bytes `json:"hash"`
Dst hexutil.Bytes `json:"recipientPublicKey,omitempty"`
}
var enc Message
enc.Sig = m.Sig
enc.TTL = m.TTL
enc.Timestamp = m.Timestamp
enc.Topic = m.Topic
enc.Payload = m.Payload
enc.Padding = m.Padding
enc.PoW = m.PoW
enc.Hash = m.Hash
enc.Dst = m.Dst
return json.Marshal(&enc)
}
// UnmarshalJSON unmarshals type Message to a json string
func (m *Message) UnmarshalJSON(input []byte) error {
type Message struct {
Sig *hexutil.Bytes `json:"sig,omitempty"`
TTL *uint32 `json:"ttl"`
Timestamp *uint32 `json:"timestamp"`
Topic *TopicType `json:"topic"`
Payload *hexutil.Bytes `json:"payload"`
Padding *hexutil.Bytes `json:"padding"`
PoW *float64 `json:"pow"`
Hash *hexutil.Bytes `json:"hash"`
Dst *hexutil.Bytes `json:"recipientPublicKey,omitempty"`
}
var dec Message
if err := json.Unmarshal(input, &dec); err != nil {
return err
}
if dec.Sig != nil {
m.Sig = *dec.Sig
}
if dec.TTL != nil {
m.TTL = *dec.TTL
}
if dec.Timestamp != nil {
m.Timestamp = *dec.Timestamp
}
if dec.Topic != nil {
m.Topic = *dec.Topic
}
if dec.Payload != nil {
m.Payload = *dec.Payload
}
if dec.Padding != nil {
m.Padding = *dec.Padding
}
if dec.PoW != nil {
m.PoW = *dec.PoW
}
if dec.Hash != nil {
m.Hash = *dec.Hash
}
if dec.Dst != nil {
m.Dst = *dec.Dst
}
return nil
}

View File

@ -1,90 +0,0 @@
// Code generated by github.com/fjl/gencodec. DO NOT EDIT.
package whisper
import (
"encoding/json"
"github.com/ethereum/go-ethereum/common/hexutil"
)
var _ = (*newMessageOverride)(nil)
// MarshalJSON marshals type NewMessage to a json string
func (n NewMessage) MarshalJSON() ([]byte, error) {
type NewMessage struct {
SymKeyID string `json:"symKeyID"`
PublicKey hexutil.Bytes `json:"pubKey"`
Sig string `json:"sig"`
TTL uint32 `json:"ttl"`
Topic TopicType `json:"topic"`
Payload hexutil.Bytes `json:"payload"`
Padding hexutil.Bytes `json:"padding"`
PowTime uint32 `json:"powTime"`
PowTarget float64 `json:"powTarget"`
TargetPeer string `json:"targetPeer"`
}
var enc NewMessage
enc.SymKeyID = n.SymKeyID
enc.PublicKey = n.PublicKey
enc.Sig = n.Sig
enc.TTL = n.TTL
enc.Topic = n.Topic
enc.Payload = n.Payload
enc.Padding = n.Padding
enc.PowTime = n.PowTime
enc.PowTarget = n.PowTarget
enc.TargetPeer = n.TargetPeer
return json.Marshal(&enc)
}
// UnmarshalJSON unmarshals type NewMessage to a json string
func (n *NewMessage) UnmarshalJSON(input []byte) error {
type NewMessage struct {
SymKeyID *string `json:"symKeyID"`
PublicKey *hexutil.Bytes `json:"pubKey"`
Sig *string `json:"sig"`
TTL *uint32 `json:"ttl"`
Topic *TopicType `json:"topic"`
Payload *hexutil.Bytes `json:"payload"`
Padding *hexutil.Bytes `json:"padding"`
PowTime *uint32 `json:"powTime"`
PowTarget *float64 `json:"powTarget"`
TargetPeer *string `json:"targetPeer"`
}
var dec NewMessage
if err := json.Unmarshal(input, &dec); err != nil {
return err
}
if dec.SymKeyID != nil {
n.SymKeyID = *dec.SymKeyID
}
if dec.PublicKey != nil {
n.PublicKey = *dec.PublicKey
}
if dec.Sig != nil {
n.Sig = *dec.Sig
}
if dec.TTL != nil {
n.TTL = *dec.TTL
}
if dec.Topic != nil {
n.Topic = *dec.Topic
}
if dec.Payload != nil {
n.Payload = *dec.Payload
}
if dec.Padding != nil {
n.Padding = *dec.Padding
}
if dec.PowTime != nil {
n.PowTime = *dec.PowTime
}
if dec.PowTarget != nil {
n.PowTarget = *dec.PowTarget
}
if dec.TargetPeer != nil {
n.TargetPeer = *dec.TargetPeer
}
return nil
}

View File

@ -1,20 +0,0 @@
module github.com/status-im/status-go/whisper/v6
go 1.13
replace github.com/ethereum/go-ethereum v1.9.5 => github.com/status-im/go-ethereum v1.9.5-status.7
require (
github.com/deckarep/golang-set v0.0.0-20180603214616-504e848d77ea
github.com/ethereum/go-ethereum v1.9.5
github.com/gorilla/websocket v1.4.1 // indirect
github.com/prometheus/client_golang v1.2.1
github.com/steakknife/bloomfilter v0.0.0-20180922174646-6819c0d2a570 // indirect
github.com/steakknife/hamming v0.0.0-20180906055917-c99c65617cd3 // indirect
github.com/stretchr/objx v0.2.0 // indirect
github.com/stretchr/testify v1.3.0
github.com/syndtr/goleveldb v0.0.0-20181128100959-b001fa50d6b2
github.com/tsenart/tb v0.0.0-20181025101425-0d2499c8b6e9
golang.org/x/crypto v0.0.0-20191119213627-4f8c1d86b1ba
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4
)

View File

@ -1,216 +0,0 @@
bazil.org/fuse v0.0.0-20160811212531-371fbbdaa898/go.mod h1:Xbm+BRKSBEpa4q4hTSxohYNQpsxXPbPry4JJWOB3LB8=
github.com/Azure/azure-pipeline-go v0.0.0-20180607212504-7571e8eb0876/go.mod h1:XA1kFWRVhSK+KNFiOhfv83Fv8L9achrP7OxIzeTn1Yg=
github.com/Azure/azure-storage-blob-go v0.0.0-20180712005634-eaae161d9d5e/go.mod h1:x2mtS6O3mnMEZOJp7d7oldh8IvatBrMfReiyQ+cKgKY=
github.com/StackExchange/wmi v0.0.0-20180116203802-5d049714c4a6 h1:fLjPD/aNc3UIOA6tDi6QXUemppXK3P9BI7mr2hd6gx8=
github.com/StackExchange/wmi v0.0.0-20180116203802-5d049714c4a6/go.mod h1:3eOhrUMpNV+6aFIbp5/iudMxNCF27Vw2OZgy4xEx0Fg=
github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII=
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
github.com/allegro/bigcache v0.0.0-20190218064605-e24eb225f156 h1:hh7BAWFHv41r0gce0KRYtDJpL4erKfmB1/mpgoSADeI=
github.com/allegro/bigcache v0.0.0-20190218064605-e24eb225f156/go.mod h1:Cb/ax3seSYIx7SuZdm2G2xzfwmv3TPSk2ucNfQESPXM=
github.com/aristanetworks/goarista v0.0.0-20170210015632-ea17b1a17847 h1:rtI0fD4oG/8eVokGVPYJEW1F88p1ZNgXiEIs9thEE4A=
github.com/aristanetworks/goarista v0.0.0-20170210015632-ea17b1a17847/go.mod h1:D/tb0zPVXnP7fmsLZjtdUhSsumbK/ij54UXjjVgMGxQ=
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
github.com/btcsuite/btcd v0.20.0-beta h1:DnZGUjFbRkpytojHWwy6nfUSA7vFrzWXDLpFNzt74ZA=
github.com/btcsuite/btcd v0.20.0-beta/go.mod h1:wVuoA8VJLEcwgqHBwHmzLRazpKxTv13Px/pDuV7OomQ=
github.com/btcsuite/btcd v0.20.1-beta/go.mod h1:wVuoA8VJLEcwgqHBwHmzLRazpKxTv13Px/pDuV7OomQ=
github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f/go.mod h1:TdznJufoqS23FtqVCzL0ZqgP5MqXbb4fg/WgDys70nA=
github.com/btcsuite/btcutil v0.0.0-20190425235716-9e5f4b9a998d/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg=
github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd/go.mod h1:HHNXQzUsZCxOoE+CPiyCTO6x34Zs86zZUiwtpXoGdtg=
github.com/btcsuite/goleveldb v0.0.0-20160330041536-7834afc9e8cd/go.mod h1:F+uVaaLLH7j4eDXPRvw78tMflu7Ie2bzYOH4Y8rRKBY=
github.com/btcsuite/snappy-go v0.0.0-20151229074030-0bdef8d06723/go.mod h1:8woku9dyThutzjeg+3xrA5iCpBRH8XEEg3lh6TiUghc=
github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792/go.mod h1:ghJtEyQwv5/p4Mg4C0fgbePVuGr935/5ddU9Z3TmDRY=
github.com/btcsuite/winsvc v1.0.0/go.mod h1:jsenWakMcC0zFBFurPLEAyrnc/teJEM1O46fmI40EZs=
github.com/cespare/cp v0.1.0/go.mod h1:SOGHArjBr4JWaSDEVpWpo/hNg6RoKrls6Oh40hiwW+s=
github.com/cespare/xxhash/v2 v2.1.0 h1:yTUvW7Vhb89inJ+8irsUqiWjh8iT6sQPZiQzI6ReGkA=
github.com/cespare/xxhash/v2 v2.1.0/go.mod h1:dgIUBU3pDso/gPgZ1osOZ0iQf77oPR28Tjxl5dIMyVM=
github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd/go.mod h1:sE/e/2PUdi/liOCUjSTXgM1o87ZssimdTWN964YiIeI=
github.com/davecgh/go-spew v0.0.0-20171005155431-ecdeabc65495/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/deckarep/golang-set v0.0.0-20180603214616-504e848d77ea h1:j4317fAZh7X6GqbFowYdYdI0L9bwxL07jyPZIdepyZ0=
github.com/deckarep/golang-set v0.0.0-20180603214616-504e848d77ea/go.mod h1:93vsz/8Wt4joVM7c2AVqh+YRMiUSc14yDtF28KmMOgQ=
github.com/dgrijalva/jwt-go v0.0.0-20170201225849-2268707a8f08/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
github.com/docker/docker v0.0.0-20180625184442-8e610b2b55bf/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
github.com/edsrzf/mmap-go v0.0.0-20160512033002-935e0e8a636c/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M=
github.com/elastic/gosigar v0.0.0-20180330100440-37f05ff46ffa h1:o8OuEkracbk3qH6GvlI6XpEN1HTSxkzOG42xZpfDv/s=
github.com/elastic/gosigar v0.0.0-20180330100440-37f05ff46ffa/go.mod h1:cdorVVzy1fhmEqmtgqkoE3bYtCfSCkVyjTyCIo22xvs=
github.com/fatih/color v1.3.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
github.com/fjl/memsize v0.0.0-20180418122429-ca190fb6ffbc/go.mod h1:VvhXpOYNQvB+uIk2RvXzuaQtkQJzzIx6lSBe1xv7hi0=
github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I=
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
github.com/gizak/termui v0.0.0-20170117222342-991cd3d38091/go.mod h1:PkJoWUt/zacQKysNfQtcw1RW+eK2SxkieVBtl+4ovLA=
github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
github.com/go-ole/go-ole v1.2.1 h1:2lOsA72HgjxAuMlKpFiCbHTvu44PIVkZ5hqm3RSdI/E=
github.com/go-ole/go-ole v1.2.1/go.mod h1:7FAglXiTm7HKlQRDeOQ6ZNUHidzCWXuZWq/1dTyBNF8=
github.com/go-stack/stack v1.5.4 h1:ACUuwAbOuCKT3mK+Az9UrqaSheA8lDWOfm0+ZT62NHY=
github.com/go-stack/stack v1.5.4/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
github.com/go-stack/stack v1.8.0 h1:5SgMzNM5HxrEjV0ww2lTmX6E2Izsfxas4+YHWRs3Lsk=
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
github.com/golang/protobuf v1.2.0 h1:P3YflyNX/ehuJFLhxviNdFxQPkGK5cDcApsge1SqnvM=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.2 h1:6nsPYzhq5kReh6QImI3k5qWzO4PEbvbIW2cwSfR/6xs=
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/snappy v0.0.0-20170215233205-553a64147049 h1:K9KHZbXKpGydfDN0aZrsoHpLJlZsBrGMFWbgLDGnPZk=
github.com/golang/snappy v0.0.0-20170215233205-553a64147049/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/gorilla/websocket v1.4.1 h1:q7AeDBpnBk8AogcD4DSag/Ukw/KV+YhzLj2bP5HvKCM=
github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/hashicorp/golang-lru v0.0.0-20160813221303-0a025b7e63ad/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI=
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
github.com/huin/goupnp v0.0.0-20161224104101-679507af18f3 h1:DqD8eigqlUm0+znmx7zhL0xvTW3+e1jCekJMfBUADWI=
github.com/huin/goupnp v0.0.0-20161224104101-679507af18f3/go.mod h1:MZ2ZmwcBpvOoJ22IJsc7va19ZwoheaBk43rKg12SKag=
github.com/influxdata/influxdb v0.0.0-20180221223340-01288bdb0883/go.mod h1:qZna6X/4elxqT3yI9iZYdZrWWdeFOOprn86kgg4+IzY=
github.com/jackpal/go-nat-pmp v0.0.0-20160603034137-1fa385a6f458 h1:LPECOO5LcZx5tvkxraIptrg6AiAUf+28rFV9+noSZFA=
github.com/jackpal/go-nat-pmp v0.0.0-20160603034137-1fa385a6f458/go.mod h1:QPH045xvCAeXUZOxsnwmrtiCoxIr9eob+4orBN1SBKc=
github.com/jessevdk/go-flags v0.0.0-20141203071132-1679536dcc89/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
github.com/jrick/logrotate v1.0.0/go.mod h1:LNinyqDIJnpAur+b8yyulnQw/wDuN1+BYKlTRt3OuAQ=
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
github.com/julienschmidt/httprouter v0.0.0-20170430222011-975b5c4c7c21/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
github.com/karalabe/hid v0.0.0-20181128192157-d815e0c1a2e2/go.mod h1:YvbcH+3Wo6XPs9nkgTY3u19KXLauXW+J5nB7hEHuX0A=
github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23/go.mod h1:J+Gs4SYgM6CZQHDETBtE9HaSEkGmuNXF86RwHhHUvq4=
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
github.com/maruel/panicparse v0.0.0-20160720141634-ad661195ed0e/go.mod h1:nty42YY5QByNC5MM7q/nj938VbgPU7avs45z6NClpxI=
github.com/mattn/go-colorable v0.1.0/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
github.com/mattn/go-isatty v0.0.0-20180830101745-3fb116b82035/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
github.com/mattn/go-runewidth v0.0.3/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU=
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
github.com/mitchellh/go-wordwrap v0.0.0-20150314170334-ad45545899c7/go.mod h1:ZXFpozHsX6DPmq2I0TCekCxypsnAUbP2oI0UX1GXzOo=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826/go.mod h1:TaXosZuwdSHYgviHp1DAtfrULt5eUgsSMsZf+YrPgl8=
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
github.com/naoina/toml v0.0.0-20170918210437-9fafd6967416/go.mod h1:NBIhNtsFMo3G2szEBne+bO4gS192HuIYRqfvOWb4i1E=
github.com/nsf/termbox-go v0.0.0-20170211012700-3540b76b9c77/go.mod h1:IuKpRQcYE1Tfu+oAQqaLisqDeXgjyyltCfsaoYN18NQ=
github.com/olekukonko/tablewriter v0.0.0-20170128050532-febf2d34b54a/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo=
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v1.7.0 h1:WSHQ+IS43OoUrWtD1/bbclrwK8TTH5hzp+umCiuxHgs=
github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/gomega v1.4.3 h1:RE1xgDvH7imwFD45h+u2SgIfERHlS2yNG4DObb5BSKU=
github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
github.com/opentracing/opentracing-go v0.0.0-20180606204148-bd9c31933947/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o=
github.com/pborman/uuid v0.0.0-20170112150404-1b00554d8222/go.mod h1:VyrYX9gd7irzKovcSS6BIIEwPRkP2Wm2m9ufcdFSJ34=
github.com/peterh/liner v0.0.0-20170902204657-a37ad3984311/go.mod h1:xIteQHvHuaLYG9IFj6mSxM0fCKrs34IrEQUhOYuGPHc=
github.com/pkg/errors v0.0.0-20171216070316-e881fd58d78e h1:+RHxT/gm0O3UF7nLJbdNzAmULvCFt4XfXHWzh3XI/zs=
github.com/pkg/errors v0.0.0-20171216070316-e881fd58d78e/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo=
github.com/prometheus/client_golang v1.2.1 h1:JnMpQc6ppsNgw9QPAGF6Dod479itz7lvlsMzzNayLOI=
github.com/prometheus/client_golang v1.2.1/go.mod h1:XMU6Z2MjaRKVu/dC1qupJI9SiNkDYzz3xecMgSW/F+U=
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4 h1:gQz4mCbXsO+nc9n1hCxHcGA3Zx3Eo+UHZoInFGUIXNM=
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
github.com/prometheus/common v0.7.0 h1:L+1lyG48J1zAQXA3RBX/nG/B3gjlHq0zTt2tlbJLyCY=
github.com/prometheus/common v0.7.0/go.mod h1:DjGbpBbp5NYNiECxcL/VnbXCCaQpKd3tt26CguLLsqA=
github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
github.com/prometheus/procfs v0.0.5 h1:3+auTFlqw+ZaQYJARz6ArODtkaIwtvBTx3N2NehQlL8=
github.com/prometheus/procfs v0.0.5/go.mod h1:4A/X28fw3Fc593LaREMrKMqOKvUAntwMDaekg4FpcdQ=
github.com/prometheus/prometheus v0.0.0-20170814170113-3101606756c5/go.mod h1:oAIUtOny2rjMX0OWN5vPR5/q/twIROJvdqnQKDdil/s=
github.com/rjeczalik/notify v0.9.1/go.mod h1:rKwnCoCGeuQnwBtTSPL9Dad03Vh2n40ePRrjvIXnJho=
github.com/robertkrimen/otto v0.0.0-20170205013659-6a77b7cbc37d/go.mod h1:xvqspoSXJTIpemEonrMDFq6XzwHYYgToXWj5eRX1OtY=
github.com/rs/cors v0.0.0-20160617231935-a62a804a8a00 h1:8DPul/X0IT/1TNMIxoKLwdemEOBBHDC/K4EB16Cw5WE=
github.com/rs/cors v0.0.0-20160617231935-a62a804a8a00/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU=
github.com/rs/xhandler v0.0.0-20160618193221-ed27b6fd6521 h1:3hxavr+IHMsQBrYUPQM5v0CgENFktkkbg1sfpgM3h20=
github.com/rs/xhandler v0.0.0-20160618193221-ed27b6fd6521/go.mod h1:RvLn4FgxWubrpZHtQLnOf6EwhN2hEMusxZOhcW9H3UQ=
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
github.com/status-im/go-ethereum v1.9.5-status.6 h1:ytuTO1yBIAuTVRtRQoc2mrdyngtP+XOQ9IHIibbz7/I=
github.com/status-im/go-ethereum v1.9.5-status.6/go.mod h1:08JvQWE+IOnAFSe4UD4ACLNe2fDd9XmWMCq5Yzy9mk0=
github.com/status-im/go-ethereum v1.9.5-status.7 h1:DKH1GiF52LwaZaw6YDBliFEgm/JDsbIT+hn7ph6X94Q=
github.com/status-im/go-ethereum v1.9.5-status.7/go.mod h1:YyH5DKB6+z+Vaya7eIm67pnuPZ1oiUMbbsZW41ktN0g=
github.com/status-im/status-go v0.37.3 h1:94/bOA8qrEIgWd23mSLN39SwUJwCu2TPQFV2HzSI2ZE=
github.com/status-im/status-go v0.38.0 h1:3toC1ToY48wbRBVt7CMWSSG5FZAcPPMlnt0+G6iCbcE=
github.com/status-im/status-go/extkeys v1.0.0/go.mod h1:GdqJbrcpkNm5ZsSCpp+PdMxnXx+OcRBdm3PI0rs1FpU=
github.com/steakknife/bloomfilter v0.0.0-20180922174646-6819c0d2a570 h1:gIlAHnH1vJb5vwEjIp5kBj/eu99p/bl0Ay2goiPe5xE=
github.com/steakknife/bloomfilter v0.0.0-20180922174646-6819c0d2a570/go.mod h1:8OR4w3TdeIHIh1g6EMY5p0gVNOovcWC+1vpc7naMuAw=
github.com/steakknife/hamming v0.0.0-20180906055917-c99c65617cd3 h1:njlZPzLwU639dk2kqnCPPv+wNjq7Xb6EfUxe/oX0/NM=
github.com/steakknife/hamming v0.0.0-20180906055917-c99c65617cd3/go.mod h1:hpGUWaI9xL8pRQCTXQgocU38Qw1g0Us7n5PxxTwTCYU=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.2.0 h1:Hbg2NidpLE8veEBkEZTL3CvlkUIVzuU9jDplZO54c48=
github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE=
github.com/stretchr/testify v0.0.0-20170809224252-890a5c3458b4 h1:InXsxTNd7R4kIHKuA052litAUzokFLqjgbmhpUQTAs8=
github.com/stretchr/testify v0.0.0-20170809224252-890a5c3458b4/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/syndtr/goleveldb v0.0.0-20181128100959-b001fa50d6b2 h1:GnOzE5fEFN3b2zDhJJABEofdb51uMRNb8eqIVtdducs=
github.com/syndtr/goleveldb v0.0.0-20181128100959-b001fa50d6b2/go.mod h1:Z4AUp2Km+PwemOoO/VB5AOx9XSsIItzFjoJlOSiYmn0=
github.com/tsenart/tb v0.0.0-20181025101425-0d2499c8b6e9 h1:kjbwitOGH46vD01f2s3leBfrMnePQa3NSAIlW35MvY8=
github.com/tsenart/tb v0.0.0-20181025101425-0d2499c8b6e9/go.mod h1:EcGP24b8DY+bWHnpfJDP7fM+o8Nmz4fYH0l2xTtNr3I=
github.com/uber/jaeger-client-go v0.0.0-20180607151842-f7e0d4744fa6/go.mod h1:WVhlPFC8FDjOFMMWRy2pZqQJSXxYSwNYOkTr/Z6d3Kk=
github.com/uber/jaeger-lib v0.0.0-20180615202729-a51202d6f4a7/go.mod h1:ComeNDZlWwrWnDv8aPp0Ba6+uUTzImX/AauajbLI56U=
golang.org/x/crypto v0.0.0-20170930174604-9419663f5a44/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20191029031824-8986dd9e96cf h1:fnPsqIDRbCSgumaMCRpoIoF2s4qxv0xSSS0BVZUE/ss=
golang.org/x/crypto v0.0.0-20191029031824-8986dd9e96cf/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20191119213627-4f8c1d86b1ba h1:9bFeDpN3gTqNanMVqNcoR/pJQuP5uroC3t1D7eXozTE=
golang.org/x/crypto v0.0.0-20191119213627-4f8c1d86b1ba/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3 h1:0GoQqolDA55aaLxZyTzK/Y2ePZzZTUrRacwib7cNsYQ=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190613194153-d28f0bde5980 h1:dfGZHvZk057jK2MCeWus/TowKpJ8y4AmooUzdBSR9GU=
golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f h1:wMNYb4v58l5UBM7MYRLPG6ZhfOqbKu7X5eyFl8ZhKvA=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4 h1:YUO/7uOKsKeq9UokNS62b8FYywz3ker1l1vDZRCRefw=
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d h1:+R4KGOnez64A81RvjARKc4UT5/tI9ujCIVX+P5KiHuI=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191010194322-b09406accb47 h1:/XfQ9z7ib8eEJX2hdgFTZJ/ntt0swNk5oYBziWeTCvY=
golang.org/x/sys v0.0.0-20191010194322-b09406accb47/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20161208181325-20d25e280405 h1:829vOVxxusYHC+IqBtkX5mbKtsY9fheQiQn0MZRVLfQ=
gopkg.in/check.v1 v1.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4=
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce h1:+JknDZhAj8YMt7GC73Ei8pv4MzjDUNPHgQWJdtMAaDU=
gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce/go.mod h1:5AcXVHNjg+BDxry382+8OKon8SEWiKktQR07RKPsv1c=
gopkg.in/olebedev/go-duktape.v3 v3.0.0-20180302121509-abf0ba0be5d5/go.mod h1:uAJfkITjFhyEEuUfm7bsmCZRbW5WRq8s9EY8HZ6hCns=
gopkg.in/sourcemap.v1 v1.0.5/go.mod h1:2RlvNNSMglmRrcvhfuzp4hQHwOtjxlbjX7UPY/GXb78=
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
gopkg.in/urfave/cli.v1 v1.20.0/go.mod h1:vuBzUtMdQeixQj8LVd+/98pzhxNGQoyuPBlsXHOQNO0=
gopkg.in/yaml.v2 v2.2.1 h1:mUhvW9EsL+naU5Q3cakzfE91YhliOondGd6ZrsDBHQE=
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=

View File

@ -1,140 +0,0 @@
package whisper
import (
"bytes"
"errors"
"fmt"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/p2p/enode"
)
const (
mailServerFailedPayloadPrefix = "ERROR="
cursorSize = 36
)
func invalidResponseSizeError(size int) error {
return fmt.Errorf("unexpected payload size: %d", size)
}
// CreateMailServerRequestCompletedPayload creates a payload representing
// a successful request to mailserver
func CreateMailServerRequestCompletedPayload(requestID, lastEnvelopeHash common.Hash, cursor []byte) []byte {
payload := make([]byte, len(requestID))
copy(payload, requestID[:])
payload = append(payload, lastEnvelopeHash[:]...)
payload = append(payload, cursor...)
return payload
}
// CreateMailServerRequestFailedPayload creates a payload representing
// a failed request to a mailserver
func CreateMailServerRequestFailedPayload(requestID common.Hash, err error) []byte {
payload := []byte(mailServerFailedPayloadPrefix)
payload = append(payload, requestID[:]...)
payload = append(payload, []byte(err.Error())...)
return payload
}
// CreateMailServerEvent returns EnvelopeEvent with correct data
// if payload corresponds to any of the know mailserver events:
// * request completed successfully
// * request failed
// If the payload is unknown/unparseable, it returns `nil`
func CreateMailServerEvent(nodeID enode.ID, payload []byte) (*EnvelopeEvent, error) {
if len(payload) < common.HashLength {
return nil, invalidResponseSizeError(len(payload))
}
event, err := tryCreateMailServerRequestFailedEvent(nodeID, payload)
if err != nil || event != nil {
return event, err
}
return tryCreateMailServerRequestCompletedEvent(nodeID, payload)
}
func tryCreateMailServerRequestFailedEvent(nodeID enode.ID, payload []byte) (*EnvelopeEvent, error) {
if len(payload) < common.HashLength+len(mailServerFailedPayloadPrefix) {
return nil, nil
}
prefix, remainder := extractPrefix(payload, len(mailServerFailedPayloadPrefix))
if !bytes.Equal(prefix, []byte(mailServerFailedPayloadPrefix)) {
return nil, nil
}
var (
requestID common.Hash
errorMsg string
)
requestID, remainder = extractHash(remainder)
errorMsg = string(remainder)
event := EnvelopeEvent{
Peer: nodeID,
Hash: requestID,
Event: EventMailServerRequestCompleted,
Data: &MailServerResponse{
Error: errors.New(errorMsg),
},
}
return &event, nil
}
func tryCreateMailServerRequestCompletedEvent(nodeID enode.ID, payload []byte) (*EnvelopeEvent, error) {
// check if payload is
// - requestID or
// - requestID + lastEnvelopeHash or
// - requestID + lastEnvelopeHash + cursor
// requestID is the hash of the request envelope.
// lastEnvelopeHash is the last envelope sent by the mail server
// cursor is the db key, 36 bytes: 4 for the timestamp + 32 for the envelope hash.
if len(payload) > common.HashLength*2+cursorSize {
return nil, invalidResponseSizeError(len(payload))
}
var (
requestID common.Hash
lastEnvelopeHash common.Hash
cursor []byte
)
requestID, remainder := extractHash(payload)
if len(remainder) >= common.HashLength {
lastEnvelopeHash, remainder = extractHash(remainder)
}
if len(remainder) >= cursorSize {
cursor = remainder
}
event := EnvelopeEvent{
Peer: nodeID,
Hash: requestID,
Event: EventMailServerRequestCompleted,
Data: &MailServerResponse{
LastEnvelopeHash: lastEnvelopeHash,
Cursor: cursor,
},
}
return &event, nil
}
func extractHash(payload []byte) (common.Hash, []byte) {
prefix, remainder := extractPrefix(payload, common.HashLength)
return common.BytesToHash(prefix), remainder
}
func extractPrefix(payload []byte, size int) ([]byte, []byte) {
return payload[:size], payload[size:]
}

Some files were not shown because too many files have changed in this diff Show More