Merge branch 'bug/saved-mailserver-topics' into develop
This commit is contained in:
commit
f73fb9c3f6
|
@ -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 {
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
}
|
|
@ -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 {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
2
go.mod
|
@ -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
15
go.sum
|
@ -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=
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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 (
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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"
|
||||
|
||||
|
|
|
@ -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"
|
||||
)
|
||||
|
||||
// ----------
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -18,6 +18,7 @@ type ChatEntity interface {
|
|||
GetSigPubKey() *ecdsa.PublicKey
|
||||
GetProtobuf() proto.Message
|
||||
GetGrant() []byte
|
||||
WrapGroupMessage() bool
|
||||
|
||||
SetMessageType(messageType protobuf.MessageType)
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -21,4 +21,6 @@ type RawMessage struct {
|
|||
Payload []byte
|
||||
Sender *ecdsa.PrivateKey
|
||||
Recipients []*ecdsa.PublicKey
|
||||
SkipGroupMessageWrap bool
|
||||
SendOnPersonalTopic bool
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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"`
|
||||
}
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
ALTER TABLE raw_messages ADD COLUMN skip_group_message_wrap BOOLEAN DEFAULT FALSE;
|
|
@ -0,0 +1 @@
|
|||
ALTER TABLE raw_messages ADD COLUMN send_on_personal_topic BOOLEAN DEFAULT FALSE;
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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()
|
||||
}
|
||||
|
|
|
@ -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))
|
||||
}
|
||||
|
|
|
@ -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()
|
||||
}
|
||||
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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, ¬ificationBody{})
|
||||
|
||||
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)
|
||||
}
|
||||
|
|
|
@ -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, ¬ification))
|
||||
|
||||
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))
|
||||
|
|
|
@ -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()
|
||||
}
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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 (
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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 (
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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 (
|
||||
|
|
|
@ -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"
|
||||
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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
|
||||
}
|
|
@ -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,
|
||||
}
|
|
@ -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{})
|
||||
}
|
|
@ -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]
|
||||
}
|
|
@ -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
|
||||
}
|
|
@ -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
|
||||
}
|
|
@ -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
|
||||
}
|
|
@ -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
|
||||
}
|
|
@ -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
|
||||
}
|
|
@ -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
|
||||
}
|
|
@ -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
|
||||
)
|
|
@ -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=
|
|
@ -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
Loading…
Reference in New Issue