From 1adfa386115294f7b41b230d73cfa028ec505562 Mon Sep 17 00:00:00 2001 From: Andrea Maria Piana Date: Thu, 10 Dec 2020 11:12:51 +0100 Subject: [PATCH] Check hash in shouldPublish --- images/identity.go | 6 ++++ multiaccounts/migrations/bindata.go | 4 +-- protocol/messenger.go | 31 ++++++++++++++++--- protocol/migrations/migrations.go | 8 ++--- ..._chat_identity_last_published_table.up.sql | 5 +-- protocol/persistence.go | 19 ++++++------ protocol/persistence_test.go | 11 +++++-- 7 files changed, 59 insertions(+), 25 deletions(-) diff --git a/images/identity.go b/images/identity.go index 09337c2ad..2a3d5701b 100644 --- a/images/identity.go +++ b/images/identity.go @@ -3,6 +3,8 @@ package images import ( "encoding/json" "errors" + + "github.com/status-im/status-go/eth-node/crypto" ) type IdentityImage struct { @@ -24,6 +26,10 @@ func (i IdentityImage) GetType() (ImageType, error) { return it, nil } +func (i IdentityImage) Hash() []byte { + return crypto.Keccak256(i.Payload) +} + func (i IdentityImage) GetDataURI() (string, error) { return GetPayloadDataURI(i.Payload) } diff --git a/multiaccounts/migrations/bindata.go b/multiaccounts/migrations/bindata.go index a3b86071d..1cfa2b3b4 100644 --- a/multiaccounts/migrations/bindata.go +++ b/multiaccounts/migrations/bindata.go @@ -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(1607535565, 0)} + info := bindataFileInfo{name: "1606224181_drop_photo_path_from_accounts.down.sql", size: 892, mode: os.FileMode(0644), modTime: time.Unix(1608048573, 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(1607535565, 0)} + info := bindataFileInfo{name: "1606224181_drop_photo_path_from_accounts.up.sql", size: 866, mode: os.FileMode(0644), modTime: time.Unix(1608048573, 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 } diff --git a/protocol/messenger.go b/protocol/messenger.go index 94c2c8db1..5caf515c8 100644 --- a/protocol/messenger.go +++ b/protocol/messenger.go @@ -1,6 +1,7 @@ package protocol import ( + "bytes" "context" "crypto/ecdsa" "database/sql" @@ -507,7 +508,15 @@ func (m *Messenger) handleContactCodeChatIdentity(cca *protobuf.ContactCodeAdver return err } - err = m.persistence.SaveWhenChatIdentityLastPublished(contactCodeTopic) + img, err := m.multiAccounts.GetIdentityImage(m.account.KeyUID, userimage.SmallDimName) + if err != nil { + return err + } + if img == nil { + return errors.New("could not find image") + } + + err = m.persistence.SaveWhenChatIdentityLastPublished(contactCodeTopic, img.Hash()) if err != nil { return err } @@ -551,7 +560,15 @@ func (m *Messenger) handleStandaloneChatIdentity(chat *Chat) error { return err } - err = m.persistence.SaveWhenChatIdentityLastPublished(chat.ID) + img, err := m.multiAccounts.GetIdentityImage(m.account.KeyUID, userimage.SmallDimName) + if err != nil { + return err + } + if img == nil { + return errors.New("could not find image") + } + + err = m.persistence.SaveWhenChatIdentityLastPublished(chat.ID, img.Hash()) if err != nil { return err } @@ -563,20 +580,24 @@ func (m *Messenger) handleStandaloneChatIdentity(chat *Chat) error { func (m *Messenger) shouldPublishChatIdentity(chatID string) (bool, error) { // Check we have at least one image - imgs, err := m.multiAccounts.GetIdentityImages(m.account.KeyUID) + img, err := m.multiAccounts.GetIdentityImage(m.account.KeyUID, userimage.SmallDimName) if err != nil { return false, err } - if len(imgs) == 0 { + if img == nil { return false, nil } - lp, err := m.persistence.GetWhenChatIdentityLastPublished(chatID) + lp, hash, err := m.persistence.GetWhenChatIdentityLastPublished(chatID) if err != nil { return false, err } + if !bytes.Equal(hash, img.Hash()) { + return true, nil + } + return *lp == 0 || time.Now().Unix()-*lp > 24*60*60, nil } diff --git a/protocol/migrations/migrations.go b/protocol/migrations/migrations.go index 64d108c2c..6715e36b4 100644 --- a/protocol/migrations/migrations.go +++ b/protocol/migrations/migrations.go @@ -32,7 +32,7 @@ // 1603816533_add_links.down.sql (0) // 1603816533_add_links.up.sql (48B) // 1603888149_create_chat_identity_last_published_table.down.sql (40B) -// 1603888149_create_chat_identity_last_published_table.up.sql (150B) +// 1603888149_create_chat_identity_last_published_table.up.sql (175B) // doc.go (850B) package migrations @@ -742,7 +742,7 @@ func _1603888149_create_chat_identity_last_published_tableDownSql() (*asset, err return a, nil } -var __1603888149_create_chat_identity_last_published_tableUpSql = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x3c\xcb\xc1\xaa\x82\x40\x14\x06\xe0\xbd\xe0\x3b\xfc\xcb\x7b\xa1\x37\x68\x75\x1a\x8e\x34\x34\x8d\x72\x3c\x45\xae\x06\x53\x41\x69\xa8\xc0\x31\xe8\xed\x03\xa1\xf6\xdf\x67\x84\x49\x19\x4a\x3b\xc7\xb0\x05\x7c\xa9\xe0\x8b\xad\xb5\x46\x37\xb6\x29\x4c\xfd\x70\x4f\x53\x7a\x87\xd8\xce\x29\x3c\x97\x6b\x9c\xe6\x71\xe8\xf1\x97\x67\xf8\x0a\x9c\x49\xcc\x9e\x64\xcd\xfe\xe4\x1c\x2a\xb1\x47\x92\x06\x07\x6e\x50\x7a\x98\xd2\x17\xce\x1a\x85\x70\xe5\xc8\xf0\x66\xcd\xf1\xd1\xdd\xc2\xab\x8d\xcb\x00\xeb\xf5\x97\xf3\xec\x7f\xfb\x09\x00\x00\xff\xff\x3e\xfe\x77\x18\x96\x00\x00\x00") +var __1603888149_create_chat_identity_last_published_tableUpSql = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x3c\xcb\x41\xaa\xc2\x30\x14\x85\xe1\x79\xa1\x7b\x38\xc3\xf7\xc0\x1d\x38\x4a\xc3\x2d\x06\x63\x52\xd2\xab\xd8\x51\x88\x6d\x21\xc5\xa0\x42\x53\xc1\xdd\x0b\x05\x3b\x3d\xe7\xff\xa4\x23\xc1\x04\x16\x95\x26\xa8\x1a\xc6\x32\xe8\xaa\x5a\x6e\xd1\xc7\x90\xfd\x34\x8c\x8f\x3c\xe5\x8f\x4f\x61\xce\xfe\xb5\xdc\xd2\x34\xc7\x71\xc0\x5f\x59\xe0\x57\xe0\x22\x9c\x3c\x08\xb7\x62\x73\xd6\x1a\x8d\x53\x27\xe1\x3a\x1c\xa9\x83\x35\x90\xd6\xd4\x5a\x49\x86\xa3\x46\x0b\x49\xbb\x15\xa7\x67\x7f\xf7\xef\x90\x96\x11\xca\xf0\x86\xd7\x33\x86\x39\xa2\xd2\xb6\xda\xe6\xb2\xf8\xdf\x97\xc5\x37\x00\x00\xff\xff\x0a\xfa\x7a\x2a\xaf\x00\x00\x00") func _1603888149_create_chat_identity_last_published_tableUpSqlBytes() ([]byte, error) { return bindataRead( @@ -757,8 +757,8 @@ 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: 150, mode: os.FileMode(0644), modTime: time.Unix(1608048466, 0)} - a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x59, 0x86, 0xb3, 0xa5, 0xcb, 0x83, 0xd5, 0x17, 0x12, 0x32, 0x31, 0xdf, 0xac, 0x59, 0x7b, 0x6e, 0x7a, 0xe6, 0xd5, 0x67, 0xf2, 0xc5, 0x1f, 0x66, 0xc8, 0x7, 0x7d, 0x52, 0xe5, 0xcd, 0x6e, 0xd0}} + info := bindataFileInfo{name: "1603888149_create_chat_identity_last_published_table.up.sql", size: 175, mode: os.FileMode(0644), modTime: time.Unix(1608048601, 0)} + a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xb0, 0x9b, 0x9a, 0xb6, 0x33, 0x2e, 0xb1, 0x8b, 0xe4, 0x18, 0x90, 0xe, 0x40, 0xa4, 0xdd, 0x13, 0x3f, 0x50, 0x55, 0x7, 0x31, 0x50, 0xe0, 0xb8, 0x1e, 0x51, 0xcc, 0xfd, 0xa5, 0x7e, 0x3, 0x7b}} return a, nil } diff --git a/protocol/migrations/sqlite/1603888149_create_chat_identity_last_published_table.up.sql b/protocol/migrations/sqlite/1603888149_create_chat_identity_last_published_table.up.sql index 29a0a4022..942aee4e2 100644 --- a/protocol/migrations/sqlite/1603888149_create_chat_identity_last_published_table.up.sql +++ b/protocol/migrations/sqlite/1603888149_create_chat_identity_last_published_table.up.sql @@ -1,4 +1,5 @@ CREATE TABLE IF NOT EXISTS chat_identity_last_published ( chat_id VARCHAR NOT NULL PRIMARY KEY ON CONFLICT REPLACE, - clock_value INT NOT NULL -); \ No newline at end of file + clock_value INT NOT NULL, + hash BLOB NOT NULL +); diff --git a/protocol/persistence.go b/protocol/persistence.go index 1f3aca6f0..6d6aa50b6 100644 --- a/protocol/persistence.go +++ b/protocol/persistence.go @@ -768,25 +768,26 @@ func (db sqlitePersistence) TransactionsToValidate() ([]*TransactionToValidate, return transactions, nil } -func (db sqlitePersistence) GetWhenChatIdentityLastPublished(chatID string) (*int64, error) { - rows, err := db.db.Query("SELECT clock_value FROM chat_identity_last_published WHERE chat_id = ?", chatID) +func (db sqlitePersistence) GetWhenChatIdentityLastPublished(chatID string) (*int64, []byte, error) { + rows, err := db.db.Query("SELECT clock_value, hash FROM chat_identity_last_published WHERE chat_id = ?", chatID) if err != nil { - return nil, err + return nil, nil, err } defer rows.Close() var t int64 + var hash []byte for rows.Next() { - err = rows.Scan(&t) + err = rows.Scan(&t, &hash) if err != nil { - return nil, err + return nil, nil, err } } - return &t, nil + return &t, hash, nil } -func (db sqlitePersistence) SaveWhenChatIdentityLastPublished(chatID string) error { +func (db sqlitePersistence) SaveWhenChatIdentityLastPublished(chatID string, hash []byte) error { tx, err := db.db.BeginTx(context.Background(), &sql.TxOptions{}) if err != nil { return err @@ -800,13 +801,13 @@ func (db sqlitePersistence) SaveWhenChatIdentityLastPublished(chatID string) err _ = tx.Rollback() }() - stmt, err := tx.Prepare("INSERT INTO chat_identity_last_published (chat_id, clock_value) VALUES (?, ?)") + stmt, err := tx.Prepare("INSERT INTO chat_identity_last_published (chat_id, clock_value, hash) VALUES (?, ?, ?)") if err != nil { return err } defer stmt.Close() - _, err = stmt.Exec(chatID, time.Now().Unix()) + _, err = stmt.Exec(chatID, time.Now().Unix(), hash) if err != nil { return err } diff --git a/protocol/persistence_test.go b/protocol/persistence_test.go index 866a4d6bd..6d10c1793 100644 --- a/protocol/persistence_test.go +++ b/protocol/persistence_test.go @@ -1,6 +1,7 @@ package protocol import ( + "bytes" "database/sql" "io/ioutil" "math" @@ -648,22 +649,26 @@ func TestSqlitePersistence_GetWhenChatIdentityLastPublished(t *testing.T) { p := sqlitePersistence{db: db} chatID := "0xabcd1234" + hash := []byte{0x1} now := time.Now().Unix() - err = p.SaveWhenChatIdentityLastPublished(chatID) + err = p.SaveWhenChatIdentityLastPublished(chatID, hash) require.NoError(t, err) - ts, err := p.GetWhenChatIdentityLastPublished(chatID) + ts, actualHash, err := p.GetWhenChatIdentityLastPublished(chatID) require.NoError(t, err) // Check that the save happened in the last 2 seconds diff := *ts - now require.LessOrEqual(t, diff, int64(2)) + require.True(t, bytes.Equal(hash, actualHash)) + // Require unsaved values to be zero - ts2, err := p.GetWhenChatIdentityLastPublished("0xdeadbeef") + ts2, actualHash2, err := p.GetWhenChatIdentityLastPublished("0xdeadbeef") require.NoError(t, err) require.Exactly(t, int64(0), *ts2) + require.Nil(t, actualHash2) } func TestSaveLinks(t *testing.T) {