Move to protobuf for Message type (#1706)

* Use a single Message type `v1/message.go` and `message.go` are the same now, and they embed `protobuf.ChatMessage`

* Use `SendChatMessage` for sending chat messages, this is basically the old `Send` but a bit more flexible so we can send different message types (stickers,commands), and not just text.

* Remove dedup from services/shhext. Because now we process in status-protocol, dedup makes less sense, as those messages are going to be processed anyway, so removing for now, we can re-evaluate if bringing it to status-go or not.

* Change the various retrieveX method to a single one:
`RetrieveAll` will be processing those messages that it can process (Currently only `Message`), and return the rest in `RawMessages` (still transit). The format for the response is:
`Chats`: -> The chats updated by receiving the message
`Messages`: -> The messages retrieved (already matched to a chat)
`Contacts`: -> The contacts updated by the messages
`RawMessages` -> Anything else that can't be parsed, eventually as we move everything to status-protocol-go this will go away.
This commit is contained in:
Andrea Maria Piana 2019-12-05 17:25:34 +01:00 committed by GitHub
parent 429d2b4291
commit fd49b0140e
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
113 changed files with 5480 additions and 3453 deletions

View file

@ -1 +1 @@
0.35.0
0.36.0

View file

@ -1,7 +1,7 @@
// Code generated by go-bindata. DO NOT EDIT.
// sources:
// 0001_app.down.sql (387B)
// 0001_app.up.sql (2.876kB)
// 0001_app.up.sql (2.951kB)
// doc.go (74B)
package migrations
@ -86,12 +86,12 @@ func _0001_appDownSql() (*asset, error) {
return nil, err
}
info := bindataFileInfo{name: "0001_app.down.sql", size: 387, mode: os.FileMode(0644), modTime: time.Unix(1567701212, 0)}
info := bindataFileInfo{name: "0001_app.down.sql", size: 387, mode: os.FileMode(0644), modTime: time.Unix(1573806410, 0)}
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xbc, 0x9c, 0xd2, 0xe1, 0x1d, 0x8, 0x34, 0x6a, 0xc8, 0x37, 0x13, 0xb3, 0x9f, 0x26, 0x23, 0x33, 0xd4, 0x25, 0x8, 0xed, 0x53, 0xe6, 0xd, 0x46, 0xc9, 0xf4, 0x24, 0xf8, 0x1, 0x1f, 0xf5, 0xc8}}
return a, nil
}
var __0001_appUpSql = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xa4\x56\x4d\x93\xaa\x38\x14\xdd\xf3\x2b\xb2\xd4\x2a\x36\xb3\x7e\x2b\xd4\x68\x53\xc3\xc0\x0c\xe2\x74\xbf\x55\x2a\x42\x44\x4a\x20\xbc\x24\xb6\xed\xbf\x9f\xca\x17\xa0\x02\xb6\xf3\x76\x24\xf7\xe6\x78\xce\xb9\x37\x37\x2e\x63\xe8\x25\x10\x24\xde\x22\x80\xc0\x5f\x83\x30\x4a\x00\xfc\xf0\xb7\xc9\x16\x70\x22\x44\x51\xe7\x1c\xcc\x1c\x71\x6d\x08\xf8\xd7\x8b\x97\x6f\x5e\x0c\xfe\x8e\xfd\xbf\xbc\xf8\x27\xf8\x13\xfe\x74\x9d\x4f\x5c\x9e\x09\x58\x04\xd1\xc2\x99\x83\x77\x3f\x79\x8b\x76\x09\x88\xa3\x77\x7f\xf5\xc3\x71\x26\xc0\x71\x9a\xd2\x73\x2d\x24\x38\xce\x32\x46\x38\x1f\xc6\xbf\xe0\xb2\x24\x02\x2c\xa2\x28\x80\x5e\xe8\x3a\xe9\x11\xf7\x56\x8a\x57\x02\x3f\x12\xd7\xe1\x82\x32\x9c\xdb\x55\x73\xde\x9f\xc8\x55\xf1\x72\x9d\x06\x8b\xa3\xd9\xaf\x71\x65\x53\x52\x5a\x52\xa6\xbe\xc7\x99\xef\x42\xff\x9f\x1d\x04\x7e\xb8\x82\x1f\xe0\x5c\x17\xbf\xce\x04\x69\x46\xc8\xb2\x8e\xc2\x9e\x16\x1d\x9b\x83\xf7\x37\x18\xc3\x76\xf9\x63\x0a\x4e\x0a\x1a\x06\x93\x91\x16\x4a\x2d\xa6\x2d\xdd\x33\x7a\xe1\x84\x49\x4b\x8b\x4c\x09\xbb\xb5\xb2\xd5\xae\x0e\x85\xbb\x20\x70\x1d\x51\x54\x84\x0b\x5c\x35\x60\xb7\xdd\xf8\x9b\x10\xae\xc0\xc2\xdf\xf8\x61\xe2\x3a\x19\x6e\x1a\xeb\x34\x58\xc1\xb5\xb7\x0b\x12\x70\xc0\x25\x27\xae\x73\x2c\xa4\xdd\x57\xbf\xce\xc8\x17\xd8\x85\x5b\x7d\xd2\x0f\x27\xac\x9c\x62\x8c\x0c\x1e\x98\x39\x66\x0b\x59\x05\x1d\x55\x9b\xa3\xab\xb7\x8e\x62\xe8\x6f\x42\xa9\x6c\xd6\x9d\x99\x83\x18\xae\x61\x0c\xc3\x25\xec\xd0\x67\x72\x3f\x92\x1a\x02\x98\x40\xb0\xf4\xb6\x4b\x6f\x05\x9d\x27\x6e\x4a\xf9\xd2\xca\xce\xb5\x9e\x99\xaf\xc9\x6c\x08\xab\x0a\xce\x0b\x5a\x4b\x40\x09\x8c\x86\x6a\xd1\xa5\xdd\x47\xfa\x62\xdb\xe3\x37\x5a\x15\xdb\x99\xde\x1e\x96\x3a\x45\x50\x30\x5c\xf3\x83\x6e\x9d\x9a\x88\x0b\x65\x27\x59\x80\xb6\xb0\xba\x25\xfa\xb5\xc0\xfc\xd8\xde\xd7\x6e\xfb\xfe\x26\x77\x91\x7d\x79\x42\x23\x87\xc4\x97\xb9\xa6\x9c\xd4\x19\x61\x03\x19\x8c\xa4\xa4\x68\x84\x49\x2b\x69\x6e\xbe\x6e\xa6\xd2\xb0\x5b\x9d\x1a\xd7\x52\xb8\xed\x91\x92\xa6\x27\xde\x4f\xd3\x29\x0f\x1e\xba\xce\x32\x0a\xb7\x49\xec\x49\x23\xcc\xd5\xb5\xb6\xa1\x86\x30\x7b\x85\xd5\xb7\x81\xb3\xf7\x7d\x26\x31\x5d\x93\xe0\x76\xbf\x35\x7f\xd6\x83\x9a\xdd\x6f\x16\xa5\x3e\x57\x7b\xc2\x1e\xd3\x7b\x57\x7f\x1c\x92\xe0\x4c\xcd\x80\x76\x00\xac\xbd\x60\x3b\x68\x86\xe2\x3a\xa8\xfe\xde\xdc\xd1\xc3\x9a\xe9\x33\x0c\x9d\xf5\xd4\x3b\x3b\x47\x91\xa0\xe8\x35\x1f\xa7\xbb\x78\xcc\x4e\x7e\xad\x53\xa0\x06\xe7\x44\xff\x19\xee\xd3\x1d\x68\x93\xbe\xd5\x83\x15\x6e\x9a\xa2\xce\xd1\x81\x32\x64\x24\xb7\x8a\x07\x9d\xb4\x6d\xd8\xd1\x79\xa5\x23\x2b\x5c\x94\x9c\xb0\x4f\x3d\x2b\x00\x00\xa0\xc8\x86\x1f\x6e\x19\x53\x53\xee\xd1\x46\x19\x1a\x37\x59\x46\x1b\xcc\xf9\x85\xb2\x16\x5a\xef\x1e\x4a\x42\xc4\xc3\x89\xd7\x66\x71\x27\x00\x31\xf2\xeb\x4c\xb8\x40\x39\x6e\xac\x98\x1c\x37\xe8\xc0\x68\x75\xf3\xa6\xc1\x0d\xbc\xe7\x27\xf3\x04\x7d\x96\x35\xf8\x0a\xcb\x80\x7a\xf3\xef\x5f\xb8\x71\x1d\xfa\xff\xc2\x08\x73\x64\xc0\x50\x91\x7d\xc9\x96\x19\x15\x68\xf2\xbe\x5d\x60\x24\x68\x53\xa4\xd6\x19\xb5\x18\xaf\xb4\x01\xe7\xb7\x05\x2b\x31\x17\x96\x45\xeb\x91\x9d\x24\x7f\xfc\xef\xc2\xa9\x1f\xb3\xe2\x18\xae\x73\x62\x59\x5a\x63\x47\x79\x96\xf4\x42\x3a\x4e\xba\xd6\x86\x98\x4e\x38\x16\xf9\xb1\x9f\x21\xa8\x8d\x3f\xd2\xfd\x2f\x00\x00\xff\xff\x86\xe7\xc8\x0b\x3c\x0b\x00\x00")
var __0001_appUpSql = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xa4\x56\x4d\x93\xaa\x38\x14\xdd\xf3\x2b\xb2\xb4\xab\xd8\xcc\xfa\xad\x50\xa3\x4d\x0d\x03\x33\x88\xd3\xfd\x56\xa9\x34\x44\x4c\x35\x10\x5e\x12\xdb\xf6\xdf\x4f\xe5\x0b\x50\x01\xbb\xe7\xed\x48\xee\xc9\xf5\x9c\x73\x6f\x6e\x5c\xa5\x30\xc8\x20\xc8\x82\x65\x04\x41\xb8\x01\x71\x92\x01\xf8\x1a\xee\xb2\x1d\x10\x44\x4a\xda\x94\x02\x2c\x3c\x79\x69\x09\xf8\x37\x48\x57\xcf\x41\x0a\xfe\x4e\xc3\xbf\x82\xf4\x27\xf8\x13\xfe\xf4\xbd\x0f\x5c\x9d\x08\x58\x46\xc9\xd2\x7b\x02\x2f\x61\xf6\x9c\xec\x33\x90\x26\x2f\xe1\xfa\x87\xe7\xcd\x24\xc7\x79\xce\x4e\x8d\x54\xc9\x71\x51\x70\x22\xc4\x78\xfe\x33\xae\x2a\x22\xc1\x32\x49\x22\x18\xc4\xbe\x97\x1f\xf1\x60\xa5\x79\x65\xf0\x35\xf3\x3d\x21\x19\xc7\xa5\x5b\xb5\xa7\xb7\x77\x72\xd1\xbc\x7c\xaf\xc5\xf2\x68\xf7\x1b\x5c\x3b\x48\xce\x2a\xc6\xf5\xf7\x34\xf3\x7d\x1c\xfe\xb3\x87\x20\x8c\xd7\xf0\x15\x9c\x1a\xfa\xeb\x44\x90\x61\x84\x1c\xeb\x24\x1e\x68\x31\xb1\x27\xf0\xf2\x0c\x53\xd8\x2d\x7f\xcc\xa5\x53\x82\xc6\x93\xa9\x48\x97\x4a\x2f\xe6\x2d\x7d\xe3\xec\x2c\x08\x57\x96\xd2\x42\x0b\xbb\xb6\xb2\xd3\xae\x0f\xc5\xfb\x28\xf2\x3d\x49\x6b\x22\x24\xae\x5b\xb0\xdf\x6d\xc3\x6d\x0c\xd7\x60\x19\x6e\xc3\x38\xf3\xbd\x02\xb7\xad\x73\x1a\xac\xe1\x26\xd8\x47\x19\x38\xe0\x4a\x10\xdf\x3b\x52\x65\xf7\x25\x6c\x0a\xf2\x09\xf6\xf1\xce\x9c\x0c\xe3\x19\x2b\xe7\x18\x23\x9b\x0f\x2c\x3c\xbb\x85\x9c\x82\x9e\xaa\xc3\x98\xea\x6d\x92\x14\x86\xdb\x58\x29\x5b\xf4\x67\x9e\x40\x0a\x37\x30\x85\xf1\x0a\xf6\xd9\x17\x6a\x3f\x51\x1a\x22\x98\x41\xb0\x0a\x76\xab\x60\x0d\xbd\x07\x6e\x2a\xf9\xca\xca\xde\xb5\x81\x99\xdf\x93\xd9\x12\x5e\x53\x21\x28\x6b\x54\x42\x95\x18\x8d\xd5\xa2\x87\xdd\x46\x86\x62\xbb\xe3\x57\x5a\x35\xdb\x85\xd9\x1e\x97\x3a\x47\x50\x72\xdc\x88\x83\x69\x9d\x86\xc8\x33\xe3\xef\xaa\x00\x5d\x61\x4d\x4b\x0c\x6b\x81\xc5\xb1\xbb\xaf\xfd\xf6\xed\x4d\xee\x23\x6f\xd5\x3b\x9a\x38\x24\x3f\xed\x35\x15\xa4\x29\x08\x1f\x41\x70\x92\x13\xda\x4a\x0b\xab\x58\x69\xbf\xae\xa6\xd2\xb8\x5b\xbd\x1a\xdf\x51\xb8\xee\x91\x8a\xe5\xef\x62\x08\x33\x90\x3b\x0f\x7d\x6f\x95\xc4\xbb\x2c\x0d\x94\x11\xf6\xea\x3a\xdb\x50\x4b\xb8\xbb\xc2\xfa\xdb\xa6\x73\xf7\x7d\xa1\x72\xfa\x16\xe0\xf7\xbf\xf5\xf4\xa8\x07\x0d\xbb\xdf\x2c\x4a\x73\xaa\xdf\x08\xbf\x87\x0f\xae\xfe\x74\x4a\x82\x0b\x3d\x03\xba\x01\xb0\x09\xa2\xdd\xa8\x19\x9a\xeb\xa8\xfa\x5b\x73\x27\x0f\x1b\xa6\x8f\x72\x18\xd4\x43\xef\xdc\x1c\x45\x92\xa1\xef\xf9\x38\xdf\xc5\x53\x76\x8a\x4b\x93\x03\x3d\x38\x67\xfa\xcf\x72\x9f\xef\x40\x07\xfa\x52\x0f\xd6\xb8\x6d\x69\x53\xa2\x03\xe3\xc8\x4a\xee\x14\x8f\x3a\xe9\xda\xb0\xa7\xf3\x9d\x8e\xac\x31\xad\x04\xe1\x1f\x66\x56\x00\x00\x00\x2d\xc6\x1f\x6e\x15\xd3\x53\xee\xde\x46\x15\x9a\x36\x59\x45\x5b\x2c\xc4\x99\xf1\x2e\xb5\xd9\x3d\x54\x84\xc8\xbb\x13\xdf\x9b\xc5\xbd\x00\xc4\xc9\xaf\x13\x11\x12\x95\xb8\x75\x62\x4a\xdc\xa2\x03\x67\xf5\xd5\x9b\x06\xb7\xf0\x96\x9f\xc2\x49\xf6\x08\x35\xfa\x0a\xab\x80\x7e\xf3\x6f\x5f\xb8\x69\x1d\xe6\xff\xc2\x04\x73\x64\x93\x21\x5a\x7c\xaa\x96\x99\x14\x68\x71\x5f\x2e\x30\x92\xac\xa5\xb9\x73\x46\x2f\xa6\x2b\x6d\x93\x8b\xeb\x82\x55\x58\x48\xc7\xa2\xf3\xc8\x4d\x92\x3f\x0c\xa6\xa0\x22\x67\x1f\x84\x5f\xee\xfe\x6b\xd8\x51\xa3\x1b\x89\x94\x4c\x52\x2c\x49\x31\x8e\xfa\xdf\x3d\xa0\x79\x3b\x9f\x38\x6e\x4a\xe2\x04\xbb\x1a\x4d\x4a\xae\xd8\x99\xf4\xf2\x4c\xdb\x58\x8d\x06\x70\xa4\xe5\x71\x88\x90\xcc\xc5\xef\xe9\xfe\x17\x00\x00\xff\xff\xbe\x1f\x2a\xc2\x87\x0b\x00\x00")
func _0001_appUpSqlBytes() ([]byte, error) {
return bindataRead(
@ -106,8 +106,8 @@ func _0001_appUpSql() (*asset, error) {
return nil, err
}
info := bindataFileInfo{name: "0001_app.up.sql", size: 2876, mode: os.FileMode(0644), modTime: time.Unix(1567701215, 0)}
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xed, 0x65, 0x8f, 0x50, 0xd3, 0x89, 0x74, 0x2e, 0x23, 0x73, 0x25, 0xbe, 0x5b, 0x53, 0x39, 0x3f, 0x4a, 0x65, 0x55, 0x39, 0x20, 0x10, 0xaa, 0xa6, 0xb9, 0xd0, 0x4c, 0xfa, 0x86, 0xaf, 0xac, 0xb0}}
info := bindataFileInfo{name: "0001_app.up.sql", size: 2951, mode: os.FileMode(0644), modTime: time.Unix(1575407229, 0)}
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xb4, 0x2, 0xd5, 0x91, 0xff, 0x5f, 0x8f, 0xb0, 0xe8, 0x19, 0x84, 0xd1, 0xa5, 0xd5, 0xec, 0xa5, 0x4, 0x1d, 0x4c, 0x5c, 0xb5, 0xd3, 0xde, 0x36, 0xd8, 0xa6, 0x98, 0x69, 0xee, 0xfa, 0x10, 0x97}}
return a, nil
}
@ -126,7 +126,7 @@ func docGo() (*asset, error) {
return nil, err
}
info := bindataFileInfo{name: "doc.go", size: 74, mode: os.FileMode(0644), modTime: time.Unix(1566753968, 0)}
info := bindataFileInfo{name: "doc.go", size: 74, mode: os.FileMode(0644), modTime: time.Unix(1573806410, 0)}
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xde, 0x7c, 0x28, 0xcd, 0x47, 0xf2, 0xfa, 0x7c, 0x51, 0x2d, 0xd8, 0x38, 0xb, 0xb0, 0x34, 0x9d, 0x4c, 0x62, 0xa, 0x9e, 0x28, 0xc3, 0x31, 0x23, 0xd9, 0xbb, 0x89, 0x9f, 0xa0, 0x89, 0x1f, 0xe8}}
return a, nil
}

View file

@ -96,7 +96,9 @@ CREATE INDEX mailserver_request_gaps_chat_id_idx ON mailserver_request_gaps (cha
CREATE TABLE IF NOT EXISTS mailserver_topics (
topic VARCHAR PRIMARY KEY,
chat_ids VARCHAR,
last_request INTEGER DEFAULT 1
last_request INTEGER DEFAULT 1,
discovery BOOLEAN DEFAULT FALSE,
negotiated BOOLEAN DEFAULT FALSE
) WITHOUT ROWID;
CREATE TABLE IF NOT EXISTS mailserver_chat_request_ranges (

11
go.mod
View file

@ -20,10 +20,12 @@ require (
github.com/beevik/ntp v0.2.0
github.com/elastic/gosigar v0.10.5 // indirect
github.com/ethereum/go-ethereum v1.9.5
github.com/go-playground/locales v0.12.1 // indirect
github.com/go-playground/universal-translator v0.16.0 // indirect
github.com/gballet/go-libpcsclite v0.0.0-20191108122812-4678299bea08 // indirect
github.com/go-playground/universal-translator v0.17.0 // indirect
github.com/golang-migrate/migrate/v4 v4.7.0 // indirect
github.com/golang/mock v1.3.1
github.com/leodido/go-urn v1.1.0 // indirect
github.com/karalabe/usb v0.0.0-20191104083709-911d15fe12a9 // indirect
github.com/leodido/go-urn v1.2.0 // indirect
github.com/lib/pq v1.2.0
github.com/libp2p/go-libp2p v0.4.0 // indirect
github.com/libp2p/go-libp2p-core v0.2.3
@ -33,7 +35,10 @@ require (
github.com/pborman/uuid v1.2.0
github.com/pkg/errors v0.8.1
github.com/prometheus/client_golang v1.2.1
github.com/russolsen/ohyeah v0.0.0-20160324131710-f4938c005315 // indirect
github.com/russolsen/same v0.0.0-20160222130632-f089df61f51d // indirect
github.com/russolsen/transit v0.0.0-20180705123435-0794b4c4505a
github.com/status-im/keycard-go v0.0.0-20191119114148-6dd40a46baa0 // indirect
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/eth-node v0.0.0-20191126161717-86bc127b3d0a

49
go.sum
View file

@ -20,6 +20,7 @@ github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5/go.mod h1:lmUJ/7eu/Q8
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo=
github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI=
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=
@ -27,6 +28,7 @@ github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuy
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/go.mod h1:Cb/ax3seSYIx7SuZdm2G2xzfwmv3TPSk2ucNfQESPXM=
github.com/allegro/bigcache v1.1.0 h1:MLuIKTjdxDc+qsG2rhjsYjsHQC5LUGjIWzutg7M+W68=
github.com/allegro/bigcache v1.1.0/go.mod h1:Cb/ax3seSYIx7SuZdm2G2xzfwmv3TPSk2ucNfQESPXM=
github.com/allegro/bigcache v1.2.0 h1:qDaE0QoF29wKBb3+pXFrJFy1ihe5OT9OiXhg1t85SxM=
github.com/allegro/bigcache v1.2.0/go.mod h1:Cb/ax3seSYIx7SuZdm2G2xzfwmv3TPSk2ucNfQESPXM=
@ -67,6 +69,7 @@ github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792/go.mod h1:ghJtE
github.com/btcsuite/winsvc v1.0.0/go.mod h1:jsenWakMcC0zFBFurPLEAyrnc/teJEM1O46fmI40EZs=
github.com/cenkalti/backoff/v3 v3.0.0 h1:ske+9nBpD9qZsTBoF41nW5L+AIuFBKMeze18XQ3eG1c=
github.com/cenkalti/backoff/v3 v3.0.0/go.mod h1:cIeZDE3IrqwwJl6VUwCN6trj1oXrTS4rc0ij+ULvLYs=
github.com/cespare/cp v0.1.0 h1:SE+dxFebS7Iik5LK0tsi1k9ZCxEaFX4AjQmoyA+1dJk=
github.com/cespare/cp v0.1.0/go.mod h1:SOGHArjBr4JWaSDEVpWpo/hNg6RoKrls6Oh40hiwW+s=
github.com/cespare/cp v1.1.1 h1:nCb6ZLdB7NRaqsm91JtQTAme2SKJzXVsdPIPkyJr1MU=
github.com/cespare/cp v1.1.1/go.mod h1:SOGHArjBr4JWaSDEVpWpo/hNg6RoKrls6Oh40hiwW+s=
@ -125,9 +128,11 @@ github.com/eapache/go-resiliency v1.1.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5m
github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21/go.mod h1:+020luEh2TKB4/GOp8oxxtq0Daoen/Cii55CzbTV6DU=
github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I=
github.com/edsrzf/mmap-go v0.0.0-20160512033002-935e0e8a636c/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M=
github.com/edsrzf/mmap-go v0.0.0-20170320065105-0bce6a688712 h1:aaQcKT9WumO6JEJcRyTqFVq4XUZiUcKR2/GI31TOcz8=
github.com/edsrzf/mmap-go v0.0.0-20170320065105-0bce6a688712/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M=
github.com/edsrzf/mmap-go v1.0.0 h1:CEBF7HpRnUCSJgGUb5h1Gm7e3VkmVDrR8lvWVLtrOFw=
github.com/edsrzf/mmap-go v1.0.0/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/elastic/gosigar v0.10.4/go.mod h1:cdorVVzy1fhmEqmtgqkoE3bYtCfSCkVyjTyCIo22xvs=
github.com/elastic/gosigar v0.10.5 h1:GzPQ+78RaAb4J63unidA/JavQRKrB6s8IOzN6Ib59jo=
@ -136,6 +141,7 @@ github.com/elazarl/go-bindata-assetfs v1.0.0/go.mod h1:v+YaWX3bdea5J/mo8dSETolEo
github.com/ethereum/go-ethereum v1.8.20/go.mod h1:PwpWDrCLZrV+tfrhqqF6kPknbISMHaJv9Ln3kPCZLwY=
github.com/ethereum/go-ethereum v1.9.2/go.mod h1:PwpWDrCLZrV+tfrhqqF6kPknbISMHaJv9Ln3kPCZLwY=
github.com/fatih/color v1.3.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
github.com/fjl/memsize v0.0.0-20180418122429-ca190fb6ffbc h1:jtW8jbpkO4YirRSyepBOH8E+2HEw6/hKkBvFPwhUN8c=
github.com/fjl/memsize v0.0.0-20180418122429-ca190fb6ffbc/go.mod h1:VvhXpOYNQvB+uIk2RvXzuaQtkQJzzIx6lSBe1xv7hi0=
github.com/fjl/memsize v0.0.0-20180929194037-2a09253e352a h1:1znxn4+q2MrEdTk1eCk6KIV3muTYVclBIB6CTVR/zBc=
github.com/fjl/memsize v0.0.0-20180929194037-2a09253e352a/go.mod h1:VvhXpOYNQvB+uIk2RvXzuaQtkQJzzIx6lSBe1xv7hi0=
@ -144,6 +150,8 @@ github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMo
github.com/fsouza/fake-gcs-server v1.7.0/go.mod h1:5XIRs4YvwNbNoz+1JF8j6KLAyDh7RHGAyAK3EP2EsNk=
github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff h1:tY80oXqGNY4FhTFhk+o9oFHGINQ/+vhlm8HFzi6znCI=
github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff/go.mod h1:x7DCsMOv1taUwEWCzT4cmDeAkigA5/QCwUodaVOe8Ww=
github.com/gballet/go-libpcsclite v0.0.0-20191108122812-4678299bea08 h1:f6D9Hr8xV8uYKlyuj8XIruxlh9WjVjdh1gIicAS7ays=
github.com/gballet/go-libpcsclite v0.0.0-20191108122812-4678299bea08/go.mod h1:x7DCsMOv1taUwEWCzT4cmDeAkigA5/QCwUodaVOe8Ww=
github.com/gizak/termui v0.0.0-20170117222342-991cd3d38091/go.mod h1:PkJoWUt/zacQKysNfQtcw1RW+eK2SxkieVBtl+4ovLA=
github.com/go-check/check v0.0.0-20180628173108-788fd7840127/go.mod h1:9ES+weclKsC9YodN5RgxqK/VD9HM9JsCSh7rNhMZE98=
github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
@ -152,11 +160,12 @@ github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2
github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
github.com/go-logfmt/logfmt v0.4.0 h1:MP4Eh7ZCb31lleYCFuwm0oe4/YGak+5l1vA2NOE80nA=
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-playground/locales v0.12.1 h1:2FITxuFt/xuCNP1Acdhv62OzaCiviiE4kotfhkmOqEc=
github.com/go-playground/locales v0.12.1/go.mod h1:IUMDtCfWo/w/mtMfIE/IG2K+Ey3ygWanZIBtBW0W2TM=
github.com/go-playground/universal-translator v0.16.0 h1:X++omBR/4cE2MNg91AoC3rmGrCjJ8eAeUP/K/EKx4DM=
github.com/go-playground/universal-translator v0.16.0/go.mod h1:1AnU7NaIRDWWzGEKwgtJRd2xk99HeFyHw3yid4rvQIY=
github.com/go-playground/locales v0.13.0 h1:HyWk6mgj5qFqCT5fjGBuRArbVDfE4hi8+e8ceBS/t7Q=
github.com/go-playground/locales v0.13.0/go.mod h1:taPMhCMXrRLJO55olJkUXHZBHCxTMfnGwq/HNwmWNS8=
github.com/go-playground/universal-translator v0.17.0 h1:icxd5fm+REJzpZx7ZfpaD876Lmtgy7VtROAbHHXk8no=
github.com/go-playground/universal-translator v0.17.0/go.mod h1:UkSxE5sNxxRwHyU+Scu5vgOQjsIJAF8j9muTVoKLVtA=
github.com/go-sql-driver/mysql v1.4.1/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w=
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=
@ -169,6 +178,8 @@ github.com/gogo/protobuf v1.3.0 h1:G8O7TerXerS4F6sx9OV7/nRfJdnXgHZu/S/7F2SN+UE=
github.com/gogo/protobuf v1.3.0/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o=
github.com/golang-migrate/migrate/v4 v4.6.2 h1:LDDOHo/q1W5UDj6PbkxdCv7lv9yunyZHXvxuwDkGo3k=
github.com/golang-migrate/migrate/v4 v4.6.2/go.mod h1:JYi6reN3+Z734VZ0akNuyOJNcrg45ZL7LDBMW3WGJL0=
github.com/golang-migrate/migrate/v4 v4.7.0 h1:gONcHxHApDTKXDyLH/H97gEHmpu1zcnnbAaq2zgrPrs=
github.com/golang-migrate/migrate/v4 v4.7.0/go.mod h1:Qvut3N4xKWjoH3sokBccML6WyHSnggXm/DvMMnTsQIc=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6 h1:ZgQEtGgCBiWRM39fZuwSd1LwSqqSW0hOdXCYYDX0R3I=
github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
@ -277,6 +288,8 @@ github.com/kami-zh/go-capturer v0.0.0-20171211120116-e492ea43421d/go.mod h1:P2vi
github.com/karalabe/hid v0.0.0-20181128192157-d815e0c1a2e2/go.mod h1:YvbcH+3Wo6XPs9nkgTY3u19KXLauXW+J5nB7hEHuX0A=
github.com/karalabe/usb v0.0.0-20190819132248-550797b1cad8 h1:VhnqxaTIudc9IWKx8uXRLnpdSb9noCEj+vHacjmhp68=
github.com/karalabe/usb v0.0.0-20190819132248-550797b1cad8/go.mod h1:Od972xHfMJowv7NGVDiWVxk2zxnWgjLlJzE+F4F7AGU=
github.com/karalabe/usb v0.0.0-20191104083709-911d15fe12a9 h1:ZHuwnjpP8LsVsUYqTqeVAI+GfDfJ6UNPrExZF+vX/DQ=
github.com/karalabe/usb v0.0.0-20191104083709-911d15fe12a9/go.mod h1:Od972xHfMJowv7NGVDiWVxk2zxnWgjLlJzE+F4F7AGU=
github.com/kardianos/osext v0.0.0-20190222173326-2bc1f35cddc0/go.mod h1:1NbS8ALrpOvjt0rHPNLyCIeMtbizbir8U//inJ+zuB8=
github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q=
github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00=
@ -295,8 +308,8 @@ github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/kshvakov/clickhouse v1.3.5/go.mod h1:DMzX7FxRymoNkVgizH0DWAL8Cur7wHLgx3MUnGwJqpE=
github.com/leodido/go-urn v1.1.0 h1:Sm1gr51B1kKyfD2BlRcLSiEkffoG96g6TPv6eRoEiB8=
github.com/leodido/go-urn v1.1.0/go.mod h1:+cyI34gQWZcE1eQU7NVgKkkzdXDQHr1dBMtdAPozLkw=
github.com/leodido/go-urn v1.2.0 h1:hpXL4XnriNwQ/ABnpepYM/1vCLWNDfUNts8dX3xTG6Y=
github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII=
github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
github.com/lib/pq v1.2.0 h1:LXpIM/LZ5xGFhOpXAQUIMM1HdyqzVYM13zNdjCEEcA0=
github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
@ -311,14 +324,17 @@ github.com/libp2p/go-eventbus v0.1.0 h1:mlawomSAjjkk97QnYiEmHsLu7E136+2oCWSHRUvM
github.com/libp2p/go-eventbus v0.1.0/go.mod h1:vROgu5cs5T7cv7POWlWxBaVLxfSegC5UGQf8A2eEmx4=
github.com/libp2p/go-flow-metrics v0.0.1 h1:0gxuFd2GuK7IIP5pKljLwps6TvcuYgvG7Atqi3INF5s=
github.com/libp2p/go-flow-metrics v0.0.1/go.mod h1:Iv1GH0sG8DtYN3SVJ2eG221wMiNpZxBdp967ls1g+k8=
github.com/libp2p/go-libp2p v0.1.1 h1:52sB0TJuDk2nYMcMfHOKaPoaayDZjaYVCq6Vk1ejUTk=
github.com/libp2p/go-libp2p v0.1.1/go.mod h1:I00BRo1UuUSdpuc8Q2mN7yDF/oTUTRAX6JWpTiK9Rp8=
github.com/libp2p/go-libp2p v0.4.0 h1:nV2q3fdhL80OWtPyBrsoWKcw32qC4TbbR+iGjEOMRaU=
github.com/libp2p/go-libp2p v0.4.0/go.mod h1:9EsEIf9p2UDuwtPd0DwJsAl0qXVxgAnuDGRvHbfATfI=
github.com/libp2p/go-libp2p-autonat v0.1.0 h1:aCWAu43Ri4nU0ZPO7NyLzUvvfqd0nE3dX0R/ZGYVgOU=
github.com/libp2p/go-libp2p-autonat v0.1.0/go.mod h1:1tLf2yXxiE/oKGtDwPYWTSYG3PtvYlJmg7NeVtPRqH8=
github.com/libp2p/go-libp2p-blankhost v0.1.1 h1:X919sCh+KLqJcNRApj43xCSiQRYqOSI88Fdf55ngf78=
github.com/libp2p/go-libp2p-blankhost v0.1.1/go.mod h1:pf2fvdLJPsC1FsVrNP3DUUvMzUts2dsLLBEpo1vW1ro=
github.com/libp2p/go-libp2p-blankhost v0.1.4 h1:I96SWjR4rK9irDHcHq3XHN6hawCRTPUADzkJacgZLvk=
github.com/libp2p/go-libp2p-blankhost v0.1.4/go.mod h1:oJF0saYsAXQCSfDq254GMNmLNz6ZTHTOvtF4ZydUvwU=
github.com/libp2p/go-libp2p-circuit v0.1.0 h1:eniLL3Y9aq/sryfyV1IAHj5rlvuyj3b7iz8tSiZpdhY=
github.com/libp2p/go-libp2p-circuit v0.1.0/go.mod h1:Ahq4cY3V9VJcHcn1SBXjr78AbFkZeIRmfunbA7pmFh8=
github.com/libp2p/go-libp2p-circuit v0.1.3 h1:WsMYYaA0PwdpgJSQu12EzPYf5ypkLSTgcOsWr7DYrgI=
github.com/libp2p/go-libp2p-circuit v0.1.3/go.mod h1:Xqh2TjSy8DD5iV2cCOMzdynd6h8OTBGoV1AWbWor3qM=
@ -329,6 +345,7 @@ github.com/libp2p/go-libp2p-core v0.2.0/go.mod h1:X0eyB0Gy93v0DZtSYbEM7RnMChm9Uv
github.com/libp2p/go-libp2p-core v0.2.2/go.mod h1:8fcwTbsG2B+lTgRJ1ICZtiM5GWCWZVoVrLaDRvIRng0=
github.com/libp2p/go-libp2p-core v0.2.3 h1:zXikZ5pLfebtTMeIYfcwVQ2Pae77O0FIwDquwM6AGNM=
github.com/libp2p/go-libp2p-core v0.2.3/go.mod h1:GqhyQqyIAPsxFYXHMjfXgMv03lxsvM0mFzuYA9Ib42A=
github.com/libp2p/go-libp2p-crypto v0.1.0 h1:k9MFy+o2zGDNGsaoZl0MA3iZ75qXxr9OOoAZF+sD5OQ=
github.com/libp2p/go-libp2p-crypto v0.1.0/go.mod h1:sPUokVISZiy+nNuTTH/TY+leRSxnFj/2GLjtOTW90hI=
github.com/libp2p/go-libp2p-discovery v0.1.0 h1:j+R6cokKcGbnZLf4kcNwpx6mDEUPF3N6SrqMymQhmvs=
github.com/libp2p/go-libp2p-discovery v0.1.0/go.mod h1:4F/x+aldVHjHDHuX85x1zWoFTGElt8HnoDzwkFZm29g=
@ -340,18 +357,23 @@ github.com/libp2p/go-libp2p-mplex v0.2.1/go.mod h1:SC99Rxs8Vuzrf/6WhmH41kNn13TiY
github.com/libp2p/go-libp2p-nat v0.0.4 h1:+KXK324yaY701On8a0aGjTnw8467kW3ExKcqW2wwmyw=
github.com/libp2p/go-libp2p-nat v0.0.4/go.mod h1:N9Js/zVtAXqaeT99cXgTV9e75KpnWCvVOiGzlcHmBbY=
github.com/libp2p/go-libp2p-netutil v0.1.0/go.mod h1:3Qv/aDqtMLTUyQeundkKsA+YCThNdbQD54k3TqjpbFU=
github.com/libp2p/go-libp2p-peer v0.2.0 h1:EQ8kMjaCUwt/Y5uLgjT8iY2qg0mGUT0N1zUjer50DsY=
github.com/libp2p/go-libp2p-peer v0.2.0/go.mod h1:RCffaCvUyW2CJmG2gAWVqwePwW7JMgxjsHm7+J5kjWY=
github.com/libp2p/go-libp2p-peerstore v0.1.0 h1:MKh7pRNPHSh1fLPj8u/M/s/napdmeNpoi9BRy9lPN0E=
github.com/libp2p/go-libp2p-peerstore v0.1.0/go.mod h1:2CeHkQsr8svp4fZ+Oi9ykN1HBb6u0MOvdJ7YIsmcwtY=
github.com/libp2p/go-libp2p-peerstore v0.1.3 h1:wMgajt1uM2tMiqf4M+4qWKVyyFc8SfA+84VV9glZq1M=
github.com/libp2p/go-libp2p-peerstore v0.1.3/go.mod h1:BJ9sHlm59/80oSkpWgr1MyY1ciXAXV397W6h1GH/uKI=
github.com/libp2p/go-libp2p-secio v0.1.0 h1:NNP5KLxuP97sE5Bu3iuwOWyT/dKEGMN5zSLMWdB7GTQ=
github.com/libp2p/go-libp2p-secio v0.1.0/go.mod h1:tMJo2w7h3+wN4pgU2LSYeiKPrfqBgkOsdiKK77hE7c8=
github.com/libp2p/go-libp2p-secio v0.2.0 h1:ywzZBsWEEz2KNTn5RtzauEDq5RFEefPsttXYwAWqHng=
github.com/libp2p/go-libp2p-secio v0.2.0/go.mod h1:2JdZepB8J5V9mBp79BmwsaPQhRPNN2NrnB2lKQcdy6g=
github.com/libp2p/go-libp2p-swarm v0.1.0 h1:HrFk2p0awrGEgch9JXK/qp/hfjqQfgNxpLWnCiWPg5s=
github.com/libp2p/go-libp2p-swarm v0.1.0/go.mod h1:wQVsCdjsuZoc730CgOvh5ox6K8evllckjebkdiY5ta4=
github.com/libp2p/go-libp2p-swarm v0.2.2 h1:T4hUpgEs2r371PweU3DuH7EOmBIdTBCwWs+FLcgx3bQ=
github.com/libp2p/go-libp2p-swarm v0.2.2/go.mod h1:fvmtQ0T1nErXym1/aa1uJEyN7JzaTNyBcHImCxRpPKU=
github.com/libp2p/go-libp2p-testing v0.0.2/go.mod h1:gvchhf3FQOtBdr+eFUABet5a4MBLK8jM3V4Zghvmi+E=
github.com/libp2p/go-libp2p-testing v0.0.3/go.mod h1:gvchhf3FQOtBdr+eFUABet5a4MBLK8jM3V4Zghvmi+E=
github.com/libp2p/go-libp2p-testing v0.0.4 h1:Qev57UR47GcLPXWjrunv5aLIQGO4n9mhI/8/EIrEEFc=
github.com/libp2p/go-libp2p-testing v0.0.4/go.mod h1:gvchhf3FQOtBdr+eFUABet5a4MBLK8jM3V4Zghvmi+E=
github.com/libp2p/go-libp2p-testing v0.1.0 h1:WaFRj/t3HdMZGNZqnU2pS7pDRBmMeoDx7/HDNpeyT9U=
github.com/libp2p/go-libp2p-testing v0.1.0/go.mod h1:xaZWMJrPUM5GlDBxCeGUi7kI4eqnjVyavGroI2nxEM0=
@ -360,6 +382,7 @@ github.com/libp2p/go-libp2p-transport-upgrader v0.1.1/go.mod h1:IEtA6or8JUbsV07q
github.com/libp2p/go-libp2p-yamux v0.2.0/go.mod h1:Db2gU+XfLpm6E4rG5uGCFX6uXA8MEXOxFcRoXUODaK8=
github.com/libp2p/go-libp2p-yamux v0.2.1 h1:Q3XYNiKCC2vIxrvUJL+Jg1kiyeEaIDNKLjgEjo3VQdI=
github.com/libp2p/go-libp2p-yamux v0.2.1/go.mod h1:1FBXiHDk1VyRM1C0aez2bCfHQ4vMZKkAQzZbkSQt5fI=
github.com/libp2p/go-maddr-filter v0.0.4 h1:hx8HIuuwk34KePddrp2mM5ivgPkZ09JH4AvsALRbFUs=
github.com/libp2p/go-maddr-filter v0.0.4/go.mod h1:6eT12kSQMA9x2pvFQa+xesMKUBlj9VImZbj3B9FBH/Q=
github.com/libp2p/go-maddr-filter v0.0.5 h1:CW3AgbMO6vUvT4kf87y4N+0P8KUl2aqLYhrGyDUbLSg=
github.com/libp2p/go-maddr-filter v0.0.5/go.mod h1:Jk+36PMfIqCJhAnaASRH83bdAvfDRp/w6ENFaC9bG+M=
@ -380,9 +403,11 @@ github.com/libp2p/go-reuseport-transport v0.0.2/go.mod h1:YkbSDrvjUVDL6b8XqriyA2
github.com/libp2p/go-stream-muxer v0.0.1/go.mod h1:bAo8x7YkSpadMTbtTaxGVHWUQsR/l5MEaHbKaliuT14=
github.com/libp2p/go-stream-muxer-multistream v0.2.0 h1:714bRJ4Zy9mdhyTLJ+ZKiROmAFwUHpeRidG+q7LTQOg=
github.com/libp2p/go-stream-muxer-multistream v0.2.0/go.mod h1:j9eyPol/LLRqT+GPLSxvimPhNph4sfYfMoDPd7HkzIc=
github.com/libp2p/go-tcp-transport v0.1.0 h1:IGhowvEqyMFknOar4FWCKSWE0zL36UFKQtiRQD60/8o=
github.com/libp2p/go-tcp-transport v0.1.0/go.mod h1:oJ8I5VXryj493DEJ7OsBieu8fcg2nHGctwtInJVpipc=
github.com/libp2p/go-tcp-transport v0.1.1 h1:yGlqURmqgNA2fvzjSgZNlHcsd/IulAnKM8Ncu+vlqnw=
github.com/libp2p/go-tcp-transport v0.1.1/go.mod h1:3HzGvLbx6etZjnFlERyakbaYPdfjg2pWP97dFZworkY=
github.com/libp2p/go-ws-transport v0.1.0 h1:F+0OvvdmPTDsVc4AjPHjV7L7Pk1B7D5QwtDcKE2oag4=
github.com/libp2p/go-ws-transport v0.1.0/go.mod h1:rjw1MG1LU9YDC6gzmwObkPd/Sqwhw7yT74kj3raBFuo=
github.com/libp2p/go-ws-transport v0.1.2 h1:VnxQcLfSGtqupqPpBNu8fUiCv+IN1RJ2BcVqQEM+z8E=
github.com/libp2p/go-ws-transport v0.1.2/go.mod h1:dsh2Ld8F+XNmzpkaAijmg5Is+e9l6/1tK/6VFOdN69Y=
@ -400,11 +425,12 @@ github.com/mattn/go-colorable v0.1.1 h1:G1f5SKeVxmagw/IyvzvtZE4Gybcc4Tr1tf7I8z0X
github.com/mattn/go-colorable v0.1.1/go.mod h1:FuOcm+DKB9mbwrcAfNl7/TZVBZ6rcnceauSikq3lYCQ=
github.com/mattn/go-isatty v0.0.0-20180830101745-3fb116b82035/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
github.com/mattn/go-isatty v0.0.5 h1:tHXDdz1cpzGaovsTB+TVB8q90WEokoVmfMqoVcrLUgw=
github.com/mattn/go-isatty v0.0.5/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
github.com/mattn/go-isatty v0.0.7 h1:UvyT9uN+3r7yLEYSlJsbQGdsaB/a0DlgWP3pql6iwOc=
github.com/mattn/go-isatty v0.0.7/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
github.com/mattn/go-pointer v0.0.0-20190911064623-a0a44394634f h1:QTRRO+ozoYgT3CQRIzNVYJRU3DB8HRnkZv6mr4ISmMA=
github.com/mattn/go-pointer v0.0.0-20190911064623-a0a44394634f/go.mod h1:2zXcozF6qYGgmsG+SeTZz3oAbFLdD3OWqnUbNvJZAlc=
github.com/mattn/go-runewidth v0.0.3 h1:a+kO+98RDGEfo6asOGMmpodZq4FNtnGP54yps8BzLR4=
github.com/mattn/go-runewidth v0.0.3/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
github.com/mattn/go-runewidth v0.0.4 h1:2BvfKmzob6Bmd4YsL0zygOqfdFnK7GR4QL06Do4/p7Y=
github.com/mattn/go-runewidth v0.0.4/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
@ -445,12 +471,15 @@ github.com/multiformats/go-multiaddr v0.1.0/go.mod h1:xKVEak1K9cS1VdmPZW3LSIb6lg
github.com/multiformats/go-multiaddr v0.1.1 h1:rVAztJYMhCQ7vEFr8FvxW3mS+HF2eY/oPbOMeS0ZDnE=
github.com/multiformats/go-multiaddr v0.1.1/go.mod h1:aMKBKNEYmzmDmxfX88/vz+J5IU55txyt0p4aiWVohjo=
github.com/multiformats/go-multiaddr-dns v0.0.1/go.mod h1:9kWcqw/Pj6FwxAwW38n/9403szc57zJPs45fmnznu3Q=
github.com/multiformats/go-multiaddr-dns v0.0.2 h1:/Bbsgsy3R6e3jf2qBahzNHzww6usYaZ0NhNH3sqdFS8=
github.com/multiformats/go-multiaddr-dns v0.0.2/go.mod h1:9kWcqw/Pj6FwxAwW38n/9403szc57zJPs45fmnznu3Q=
github.com/multiformats/go-multiaddr-dns v0.1.0 h1:gsPeMvo91XvcsNlQXgJgfjYjbsVV99bvveguUvDBpyQ=
github.com/multiformats/go-multiaddr-dns v0.1.0/go.mod h1:01k2RAqtoXIuPa3DCavAE9/6jc6nM0H3EgZyfUhN2oY=
github.com/multiformats/go-multiaddr-fmt v0.0.1 h1:5YjeOIzbX8OTKVaN72aOzGIYW7PnrZrnkDyOfAWRSMA=
github.com/multiformats/go-multiaddr-fmt v0.0.1/go.mod h1:aBYjqL4T/7j4Qx+R73XSv/8JsgnRFlf0w2KGLCmXl3Q=
github.com/multiformats/go-multiaddr-fmt v0.1.0 h1:WLEFClPycPkp4fnIzoFoV9FVd49/eQsuaL3/CWe167E=
github.com/multiformats/go-multiaddr-fmt v0.1.0/go.mod h1:hGtDIW4PU4BqJ50gW2quDuPVjyWNZxToGUh/HwTZYJo=
github.com/multiformats/go-multiaddr-net v0.0.1 h1:76O59E3FavvHqNg7jvzWzsPSW5JSi/ek0E4eiDVbg9g=
github.com/multiformats/go-multiaddr-net v0.0.1/go.mod h1:nw6HSxNmCIQH27XPGBuX+d1tnvM7ihcFwHMSstNAVUU=
github.com/multiformats/go-multiaddr-net v0.1.0 h1:ZepO8Ezwovd+7b5XPPDhQhayk1yt0AJpzQBpq9fejx4=
github.com/multiformats/go-multiaddr-net v0.1.0/go.mod h1:5JNbcfBOP4dnhoZOv10JJVkJO0pCCEf8mTnipAo2UZQ=
@ -471,6 +500,7 @@ github.com/nsf/termbox-go v0.0.0-20170211012700-3540b76b9c77/go.mod h1:IuKpRQcYE
github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U=
github.com/okzk/sdnotify v0.0.0-20180710141335-d9becc38acbd h1:+iAPaTbi1gZpcpDwe/BW1fx7Xoesv69hLNGPheoyhBs=
github.com/okzk/sdnotify v0.0.0-20180710141335-d9becc38acbd/go.mod h1:4soZNh0zW0LtYGdQ416i0jO0EIqMGcbtaspRS4BDvRQ=
github.com/olekukonko/tablewriter v0.0.0-20170128050532-febf2d34b54a h1:m6hB6GkmZ/suOSKZM7yx3Yt+7iZ9HNfzacCykJqgXA8=
github.com/olekukonko/tablewriter v0.0.0-20170128050532-febf2d34b54a/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo=
github.com/olekukonko/tablewriter v0.0.1 h1:b3iUnf1v+ppJiOfNX4yxxqfWKMQPZR5yoh8urCTFX88=
github.com/olekukonko/tablewriter v0.0.1/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo=
@ -488,6 +518,7 @@ github.com/opencontainers/go-digest v1.0.0-rc1/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQ
github.com/opencontainers/image-spec v1.0.1 h1:JMemWkRwHx4Zj+fVxWoMCFm/8sYGGrUVojFA6h/TRcI=
github.com/opencontainers/image-spec v1.0.1/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0=
github.com/opentracing/opentracing-go v0.0.0-20180606204148-bd9c31933947/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o=
github.com/opentracing/opentracing-go v1.0.2 h1:3jA2P6O1F9UOrWVpwrIo17pu01KWvNWg4X946/Y5Zwg=
github.com/opentracing/opentracing-go v1.0.2/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o=
github.com/opentracing/opentracing-go v1.1.0 h1:pWlfV3Bxv7k65HYwkikxat0+s3pV4bsqf19k25Ur8rU=
github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o=
@ -531,6 +562,7 @@ github.com/prometheus/prometheus v0.0.0-20170814170113-3101606756c5/go.mod h1:oA
github.com/prometheus/tsdb v0.10.0 h1:If5rVCMTp6W2SiRAQFlbpJNgVlgMEd+U2GZckwK38ic=
github.com/prometheus/tsdb v0.10.0/go.mod h1:oi49uRhEe9dPUTlS3JRZOwJuVi6tmh10QSgwXEyGCt4=
github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4=
github.com/rjeczalik/notify v0.9.1 h1:CLCKso/QK1snAlnhNR/CNvNiFU2saUtjV0bx3EwNeCE=
github.com/rjeczalik/notify v0.9.1/go.mod h1:rKwnCoCGeuQnwBtTSPL9Dad03Vh2n40ePRrjvIXnJho=
github.com/rjeczalik/notify v0.9.2 h1:MiTWrPj55mNDHEiIX5YUSKefw/+lCQVoAFmD6oQm5w8=
github.com/rjeczalik/notify v0.9.2/go.mod h1:aErll2f0sUX9PXZnVNyeiObbmTlk5jnMoCa4QEjJeqM=
@ -577,6 +609,8 @@ github.com/status-im/go-multiaddr-ethv4 v1.2.0 h1:OT84UsUzTCwguqCpJqkrCMiL4VZ1Sv
github.com/status-im/go-multiaddr-ethv4 v1.2.0/go.mod h1:2VQ3C+9zEurcceasz12gPAtmEzCeyLUGPeKLSXYQKHo=
github.com/status-im/keycard-go v0.0.0-20190424133014-d95853db0f48 h1:ju5UTwk5Odtm4trrY+4Ca4RMj5OyXbmVeDAVad2T0Jw=
github.com/status-im/keycard-go v0.0.0-20190424133014-d95853db0f48/go.mod h1:RZLeN1LMWmRsyYjvAu+I6Dm9QmlDaIIt+Y+4Kd7Tp+Q=
github.com/status-im/keycard-go v0.0.0-20191119114148-6dd40a46baa0 h1:5UdlDkkBoPrJfh7zkfoR3X5utJhNs/MCQysK3x0ycgg=
github.com/status-im/keycard-go v0.0.0-20191119114148-6dd40a46baa0/go.mod h1:RZLeN1LMWmRsyYjvAu+I6Dm9QmlDaIIt+Y+4Kd7Tp+Q=
github.com/status-im/markdown v0.0.0-20191113114344-af599402d015 h1:ijC73VP0hucsy/MRn4cmtoQVB1mKdLcvurMYPvmPc4Y=
github.com/status-im/markdown v0.0.0-20191113114344-af599402d015/go.mod h1:tmG2bxyvZ2EItDO5JewbdFvV45j13IYQgvnMJ3+qAaE=
github.com/status-im/migrate/v4 v4.6.2-status.2 h1:SdC+sMDl/aI7vUlwD2qj2p7KsK4T60IS9z4/rYCCbI8=
@ -798,6 +832,7 @@ gopkg.in/natefinch/lumberjack.v2 v2.0.0 h1:1Lc07Kr7qY4U2YPouBjpCLxpiyxIVoxqXgkXL
gopkg.in/natefinch/lumberjack.v2 v2.0.0/go.mod h1:l0ndWWf7gzL7RNwBG7wST/UCcT4T24xpD6X8LsfU/+k=
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 h1:VWXVtmkY4YFVuF1FokZ0PUsuvtx3Di6z/m47daSP5f0=
gopkg.in/olebedev/go-duktape.v3 v3.0.0-20180302121509-abf0ba0be5d5/go.mod h1:uAJfkITjFhyEEuUfm7bsmCZRbW5WRq8s9EY8HZ6hCns=
gopkg.in/olebedev/go-duktape.v3 v3.0.0-20190709231704-1e4459ed25ff h1:uuol9OUzSvZntY1v963NAbVd7A+PHLMz1FlCe3Lorcs=
gopkg.in/olebedev/go-duktape.v3 v3.0.0-20190709231704-1e4459ed25ff/go.mod h1:uAJfkITjFhyEEuUfm7bsmCZRbW5WRq8s9EY8HZ6hCns=

View file

@ -86,7 +86,7 @@ func _1557732988_initialize_dbDownSql() (*asset, error) {
return nil, err
}
info := bindataFileInfo{name: "1557732988_initialize_db.down.sql", size: 72, mode: os.FileMode(0644), modTime: time.Unix(1564144050, 0)}
info := bindataFileInfo{name: "1557732988_initialize_db.down.sql", size: 72, mode: os.FileMode(0644), modTime: time.Unix(1573806410, 0)}
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x77, 0x40, 0x78, 0xb7, 0x71, 0x3c, 0x20, 0x3b, 0xc9, 0xb, 0x2f, 0x49, 0xe4, 0xff, 0x1c, 0x84, 0x54, 0xa1, 0x30, 0xe3, 0x90, 0xf8, 0x73, 0xda, 0xb0, 0x2a, 0xea, 0x8e, 0xf1, 0x82, 0xe7, 0xd2}}
return a, nil
}
@ -106,7 +106,7 @@ func _1557732988_initialize_dbUpSql() (*asset, error) {
return nil, err
}
info := bindataFileInfo{name: "1557732988_initialize_db.up.sql", size: 234, mode: os.FileMode(0644), modTime: time.Unix(1564144050, 0)}
info := bindataFileInfo{name: "1557732988_initialize_db.up.sql", size: 234, mode: os.FileMode(0644), modTime: time.Unix(1573806410, 0)}
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x8f, 0xa, 0x31, 0xf, 0x94, 0xe, 0xd7, 0xd6, 0xaa, 0x22, 0xd6, 0x6c, 0x7a, 0xbc, 0xad, 0x6a, 0xed, 0x2e, 0x7a, 0xf0, 0x24, 0x81, 0x87, 0x14, 0xe, 0x1c, 0x8a, 0xf1, 0x45, 0xaf, 0x9e, 0x85}}
return a, nil
}
@ -126,7 +126,7 @@ func staticGo() (*asset, error) {
return nil, err
}
info := bindataFileInfo{name: "static.go", size: 178, mode: os.FileMode(0644), modTime: time.Unix(1564144050, 0)}
info := bindataFileInfo{name: "static.go", size: 178, mode: os.FileMode(0644), modTime: time.Unix(1573806410, 0)}
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xab, 0x8a, 0xf4, 0x27, 0x24, 0x9d, 0x2a, 0x1, 0x7b, 0x54, 0xea, 0xae, 0x4a, 0x35, 0x40, 0x92, 0xb5, 0xf9, 0xb3, 0x54, 0x3e, 0x3a, 0x1a, 0x2b, 0xae, 0xfb, 0x9e, 0x82, 0xeb, 0x4c, 0xf, 0x6}}
return a, nil
}

View file

@ -86,7 +86,7 @@ func _0001_accountsDownSql() (*asset, error) {
return nil, err
}
info := bindataFileInfo{name: "0001_accounts.down.sql", size: 21, mode: os.FileMode(0644), modTime: time.Unix(1573216280, 0)}
info := bindataFileInfo{name: "0001_accounts.down.sql", size: 21, mode: os.FileMode(0644), modTime: time.Unix(1573806410, 0)}
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xd2, 0x61, 0x4c, 0x18, 0xfc, 0xc, 0xdf, 0x5c, 0x1f, 0x5e, 0xd3, 0xbd, 0xfa, 0x12, 0x5e, 0x8d, 0x8d, 0x8b, 0xb9, 0x5f, 0x99, 0x46, 0x63, 0xa5, 0xe3, 0xa6, 0x8a, 0x4, 0xf1, 0x73, 0x8a, 0xe9}}
return a, nil
}
@ -106,7 +106,7 @@ func _0001_accountsUpSql() (*asset, error) {
return nil, err
}
info := bindataFileInfo{name: "0001_accounts.up.sql", size: 177, mode: os.FileMode(0644), modTime: time.Unix(1574408465, 0)}
info := bindataFileInfo{name: "0001_accounts.up.sql", size: 177, mode: os.FileMode(0644), modTime: time.Unix(1574772479, 0)}
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x3e, 0x24, 0xcf, 0x7a, 0x7b, 0xb0, 0xf0, 0x95, 0x3f, 0x45, 0x63, 0x9c, 0xe1, 0xca, 0x8f, 0xe4, 0x1a, 0x83, 0x8b, 0x19, 0x1f, 0x11, 0x98, 0xc4, 0x2b, 0xa5, 0x2f, 0x79, 0x96, 0xc2, 0x8f, 0x75}}
return a, nil
}
@ -126,7 +126,7 @@ func docGo() (*asset, error) {
return nil, err
}
info := bindataFileInfo{name: "doc.go", size: 74, mode: os.FileMode(0644), modTime: time.Unix(1573216280, 0)}
info := bindataFileInfo{name: "doc.go", size: 74, mode: os.FileMode(0644), modTime: time.Unix(1573806410, 0)}
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xde, 0x7c, 0x28, 0xcd, 0x47, 0xf2, 0xfa, 0x7c, 0x51, 0x2d, 0xd8, 0x38, 0xb, 0xb0, 0x34, 0x9d, 0x4c, 0x62, 0xa, 0x9e, 0x28, 0xc3, 0x31, 0x23, 0xd9, 0xbb, 0x89, 0x9f, 0xa0, 0x89, 0x1f, 0xe8}}
return a, nil
}

View file

@ -4,6 +4,7 @@ import (
"crypto/ecdsa"
"crypto/sha1"
"encoding/hex"
"encoding/json"
"github.com/status-im/status-go/eth-node/crypto"
"github.com/status-im/status-go/eth-node/types"
@ -42,11 +43,8 @@ type Chat struct {
DeletedAtClockValue uint64 `json:"deletedAtClockValue"`
// Denormalized fields
UnviewedMessagesCount uint `json:"unviewedMessagesCount"`
LastMessageContentType string `json:"lastMessageContentType"`
LastMessageContent string `json:"lastMessageContent"`
LastMessageTimestamp int64 `json:"lastMessageTimestamp"`
LastMessageClockValue int64 `json:"lastMessageClockValue"`
UnviewedMessagesCount uint `json:"unviewedMessagesCount"`
LastMessage []byte `json:"lastMessage"`
// Group chat fields
// Members are the members who have been invited to the group chat
@ -55,6 +53,53 @@ type Chat struct {
MembershipUpdates []ChatMembershipUpdate `json:"membershipUpdates"`
}
func (c *Chat) MarshalJSON() ([]byte, error) {
type ChatAlias Chat
item := struct {
*ChatAlias
LastMessage json.RawMessage `json:"lastMessage"`
}{
ChatAlias: (*ChatAlias)(c),
LastMessage: c.LastMessage,
}
return json.Marshal(item)
}
func (c *Chat) UnmarshalJSON(data []byte) error {
type ChatAlias Chat
aux := struct {
*ChatAlias
LastMessage *Message `json:"lastMessage"`
}{
ChatAlias: (*ChatAlias)(c),
}
if err := json.Unmarshal(data, &aux); err != nil {
return err
}
c.ID = aux.ID
c.Name = aux.Name
c.Color = aux.Color
c.Active = aux.Active
c.ChatType = aux.ChatType
c.Timestamp = aux.Timestamp
c.LastClockValue = aux.LastClockValue
c.DeletedAtClockValue = aux.DeletedAtClockValue
c.UnviewedMessagesCount = aux.UnviewedMessagesCount
c.Members = aux.Members
c.MembershipUpdates = aux.MembershipUpdates
if aux.LastMessage != nil {
data, err := json.Marshal(aux.LastMessage)
if err != nil {
return err
}
c.LastMessage = data
}
return nil
}
func (c *Chat) MembersAsPublicKeys() ([]*ecdsa.PublicKey, error) {
publicKeys := make([]string, len(c.Members))
for idx, item := range c.Members {

View file

@ -12,9 +12,9 @@ import (
)
const (
contactBlocked = "contact/blocked"
contactAdded = "contact/added"
contactRequestReceived = "contact/request-received"
contactBlocked = ":contact/blocked"
contactAdded = ":contact/added"
contactRequestReceived = ":contact/request-received"
)
// ContactDeviceInfo is a struct containing information about a particular device owned by a contact

View file

@ -100,7 +100,7 @@ func _1536754952_initial_schemaDownSql() (*asset, error) {
return nil, err
}
info := bindataFileInfo{name: "1536754952_initial_schema.down.sql", size: 83, mode: os.FileMode(0644), modTime: time.Unix(1564484687, 0)}
info := bindataFileInfo{name: "1536754952_initial_schema.down.sql", size: 83, mode: os.FileMode(0644), modTime: time.Unix(1574354941, 0)}
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x44, 0xcf, 0x76, 0x71, 0x1f, 0x5e, 0x9a, 0x43, 0xd8, 0xcd, 0xb8, 0xc3, 0x70, 0xc3, 0x7f, 0xfc, 0x90, 0xb4, 0x25, 0x1e, 0xf4, 0x66, 0x20, 0xb8, 0x33, 0x7e, 0xb0, 0x76, 0x1f, 0xc, 0xc0, 0x75}}
return a, nil
}
@ -120,7 +120,7 @@ func _1536754952_initial_schemaUpSql() (*asset, error) {
return nil, err
}
info := bindataFileInfo{name: "1536754952_initial_schema.up.sql", size: 962, mode: os.FileMode(0644), modTime: time.Unix(1564484687, 0)}
info := bindataFileInfo{name: "1536754952_initial_schema.up.sql", size: 962, mode: os.FileMode(0644), modTime: time.Unix(1574354941, 0)}
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xea, 0x90, 0x5a, 0x59, 0x3e, 0x3, 0xe2, 0x3c, 0x81, 0x42, 0xcd, 0x4c, 0x9a, 0xe8, 0xda, 0x93, 0x2b, 0x70, 0xa4, 0xd5, 0x29, 0x3e, 0xd5, 0xc9, 0x27, 0xb6, 0xb7, 0x65, 0xff, 0x0, 0xcb, 0xde}}
return a, nil
}
@ -140,7 +140,7 @@ func _1539249977_update_ratchet_infoDownSql() (*asset, error) {
return nil, err
}
info := bindataFileInfo{name: "1539249977_update_ratchet_info.down.sql", size: 311, mode: os.FileMode(0644), modTime: time.Unix(1564484687, 0)}
info := bindataFileInfo{name: "1539249977_update_ratchet_info.down.sql", size: 311, mode: os.FileMode(0644), modTime: time.Unix(1574354941, 0)}
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x1, 0xa4, 0xeb, 0xa0, 0xe6, 0xa0, 0xd4, 0x48, 0xbb, 0xad, 0x6f, 0x7d, 0x67, 0x8c, 0xbd, 0x25, 0xde, 0x1f, 0x73, 0x9a, 0xbb, 0xa8, 0xc9, 0x30, 0xb7, 0xa9, 0x7c, 0xaf, 0xb5, 0x1, 0x61, 0xdd}}
return a, nil
}
@ -160,7 +160,7 @@ func _1539249977_update_ratchet_infoUpSql() (*asset, error) {
return nil, err
}
info := bindataFileInfo{name: "1539249977_update_ratchet_info.up.sql", size: 368, mode: os.FileMode(0644), modTime: time.Unix(1564484687, 0)}
info := bindataFileInfo{name: "1539249977_update_ratchet_info.up.sql", size: 368, mode: os.FileMode(0644), modTime: time.Unix(1574354941, 0)}
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xc, 0x8e, 0xbf, 0x6f, 0xa, 0xc0, 0xe1, 0x3c, 0x42, 0x28, 0x88, 0x1d, 0xdb, 0xba, 0x1c, 0x83, 0xec, 0xba, 0xd3, 0x5f, 0x5c, 0x77, 0x5e, 0xa7, 0x46, 0x36, 0xec, 0x69, 0xa, 0x4b, 0x17, 0x79}}
return a, nil
}
@ -180,7 +180,7 @@ func _1540715431_add_versionDownSql() (*asset, error) {
return nil, err
}
info := bindataFileInfo{name: "1540715431_add_version.down.sql", size: 127, mode: os.FileMode(0644), modTime: time.Unix(1564484687, 0)}
info := bindataFileInfo{name: "1540715431_add_version.down.sql", size: 127, mode: os.FileMode(0644), modTime: time.Unix(1574354941, 0)}
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xf5, 0x9, 0x4, 0xe3, 0x76, 0x2e, 0xb8, 0x9, 0x23, 0xf0, 0x70, 0x93, 0xc4, 0x50, 0xe, 0x9d, 0x84, 0x22, 0x8c, 0x94, 0xd3, 0x24, 0x9, 0x9a, 0xc1, 0xa1, 0x48, 0x45, 0xfd, 0x40, 0x6e, 0xe6}}
return a, nil
}
@ -200,7 +200,7 @@ func _1540715431_add_versionUpSql() (*asset, error) {
return nil, err
}
info := bindataFileInfo{name: "1540715431_add_version.up.sql", size: 265, mode: os.FileMode(0644), modTime: time.Unix(1564484687, 0)}
info := bindataFileInfo{name: "1540715431_add_version.up.sql", size: 265, mode: os.FileMode(0644), modTime: time.Unix(1574354941, 0)}
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xc7, 0x4c, 0x36, 0x96, 0xdf, 0x16, 0x10, 0xa6, 0x27, 0x1a, 0x79, 0x8b, 0x42, 0x83, 0x23, 0xc, 0x7e, 0xb6, 0x3d, 0x2, 0xda, 0xa4, 0xb4, 0xd, 0x27, 0x55, 0xba, 0xdc, 0xb2, 0x88, 0x8f, 0xa6}}
return a, nil
}
@ -220,7 +220,7 @@ func _1541164797_add_installationsDownSql() (*asset, error) {
return nil, err
}
info := bindataFileInfo{name: "1541164797_add_installations.down.sql", size: 26, mode: os.FileMode(0644), modTime: time.Unix(1564484687, 0)}
info := bindataFileInfo{name: "1541164797_add_installations.down.sql", size: 26, mode: os.FileMode(0644), modTime: time.Unix(1574354941, 0)}
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xf5, 0xfd, 0xe6, 0xd8, 0xca, 0x3b, 0x38, 0x18, 0xee, 0x0, 0x5f, 0x36, 0x9e, 0x1e, 0xd, 0x19, 0x3e, 0xb4, 0x73, 0x53, 0xe9, 0xa5, 0xac, 0xdd, 0xa1, 0x2f, 0xc7, 0x6c, 0xa8, 0xd9, 0xa, 0x88}}
return a, nil
}
@ -240,7 +240,7 @@ func _1541164797_add_installationsUpSql() (*asset, error) {
return nil, err
}
info := bindataFileInfo{name: "1541164797_add_installations.up.sql", size: 216, mode: os.FileMode(0644), modTime: time.Unix(1564484687, 0)}
info := bindataFileInfo{name: "1541164797_add_installations.up.sql", size: 216, mode: os.FileMode(0644), modTime: time.Unix(1574354941, 0)}
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x2d, 0x18, 0x26, 0xb8, 0x88, 0x47, 0xdb, 0x83, 0xcc, 0xb6, 0x9d, 0x1c, 0x1, 0xae, 0x2f, 0xde, 0x97, 0x82, 0x3, 0x30, 0xa8, 0x63, 0xa1, 0x78, 0x4b, 0xa5, 0x9, 0x8, 0x75, 0xa2, 0x57, 0x81}}
return a, nil
}
@ -260,7 +260,7 @@ func _1558084410_add_secretDownSql() (*asset, error) {
return nil, err
}
info := bindataFileInfo{name: "1558084410_add_secret.down.sql", size: 56, mode: os.FileMode(0644), modTime: time.Unix(1564484687, 0)}
info := bindataFileInfo{name: "1558084410_add_secret.down.sql", size: 56, mode: os.FileMode(0644), modTime: time.Unix(1574354941, 0)}
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x49, 0xb, 0x65, 0xdf, 0x59, 0xbf, 0xe9, 0x5, 0x5b, 0x6f, 0xd5, 0x3a, 0xb7, 0x57, 0xe8, 0x78, 0x38, 0x73, 0x53, 0x57, 0xf7, 0x24, 0x4, 0xe4, 0xa2, 0x49, 0x22, 0xa2, 0xc6, 0xfd, 0x80, 0xa4}}
return a, nil
}
@ -280,7 +280,7 @@ func _1558084410_add_secretUpSql() (*asset, error) {
return nil, err
}
info := bindataFileInfo{name: "1558084410_add_secret.up.sql", size: 301, mode: os.FileMode(0644), modTime: time.Unix(1564484687, 0)}
info := bindataFileInfo{name: "1558084410_add_secret.up.sql", size: 301, mode: os.FileMode(0644), modTime: time.Unix(1574354941, 0)}
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xf5, 0x32, 0x36, 0x8e, 0x47, 0xb0, 0x8f, 0xc1, 0xc6, 0xf7, 0xc6, 0x9f, 0x2d, 0x44, 0x75, 0x2b, 0x26, 0xec, 0x6, 0xa0, 0x7b, 0xa5, 0xbd, 0xc8, 0x76, 0x8a, 0x82, 0x68, 0x2, 0x42, 0xb5, 0xf4}}
return a, nil
}
@ -300,7 +300,7 @@ func _1558588866_add_versionDownSql() (*asset, error) {
return nil, err
}
info := bindataFileInfo{name: "1558588866_add_version.down.sql", size: 47, mode: os.FileMode(0644), modTime: time.Unix(1564484687, 0)}
info := bindataFileInfo{name: "1558588866_add_version.down.sql", size: 47, mode: os.FileMode(0644), modTime: time.Unix(1574354941, 0)}
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xde, 0x52, 0x34, 0x3c, 0x46, 0x4a, 0xf0, 0x72, 0x47, 0x6f, 0x49, 0x5c, 0xc7, 0xf9, 0x32, 0xce, 0xc4, 0x3d, 0xfd, 0x61, 0xa1, 0x8b, 0x8f, 0xf2, 0x31, 0x34, 0xde, 0x15, 0x49, 0xa6, 0xde, 0xb9}}
return a, nil
}
@ -320,7 +320,7 @@ func _1558588866_add_versionUpSql() (*asset, error) {
return nil, err
}
info := bindataFileInfo{name: "1558588866_add_version.up.sql", size: 57, mode: os.FileMode(0644), modTime: time.Unix(1564484687, 0)}
info := bindataFileInfo{name: "1558588866_add_version.up.sql", size: 57, mode: os.FileMode(0644), modTime: time.Unix(1574354941, 0)}
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x2a, 0xea, 0x64, 0x39, 0x61, 0x20, 0x83, 0x83, 0xb, 0x2e, 0x79, 0x64, 0xb, 0x53, 0xfa, 0xfe, 0xc6, 0xf7, 0x67, 0x42, 0xd3, 0x4f, 0xdc, 0x7e, 0x30, 0x32, 0xe8, 0x14, 0x41, 0xe9, 0xe7, 0x3b}}
return a, nil
}
@ -340,7 +340,7 @@ func _1559627659_add_contact_codeDownSql() (*asset, error) {
return nil, err
}
info := bindataFileInfo{name: "1559627659_add_contact_code.down.sql", size: 32, mode: os.FileMode(0644), modTime: time.Unix(1564484687, 0)}
info := bindataFileInfo{name: "1559627659_add_contact_code.down.sql", size: 32, mode: os.FileMode(0644), modTime: time.Unix(1574354941, 0)}
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x5d, 0x64, 0x6d, 0xce, 0x24, 0x42, 0x20, 0x8d, 0x4f, 0x37, 0xaa, 0x9d, 0xc, 0x57, 0x98, 0xc1, 0xd1, 0x1a, 0x34, 0xcd, 0x9f, 0x8f, 0x34, 0x86, 0xb3, 0xd3, 0xdc, 0xf1, 0x7d, 0xe5, 0x1b, 0x6e}}
return a, nil
}
@ -360,7 +360,7 @@ func _1559627659_add_contact_codeUpSql() (*asset, error) {
return nil, err
}
info := bindataFileInfo{name: "1559627659_add_contact_code.up.sql", size: 198, mode: os.FileMode(0644), modTime: time.Unix(1564484687, 0)}
info := bindataFileInfo{name: "1559627659_add_contact_code.up.sql", size: 198, mode: os.FileMode(0644), modTime: time.Unix(1574354941, 0)}
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x16, 0xf6, 0xc2, 0x62, 0x9c, 0xd2, 0xc9, 0x1e, 0xd8, 0xea, 0xaa, 0xea, 0x95, 0x8f, 0x89, 0x6a, 0x85, 0x5d, 0x9d, 0x99, 0x78, 0x3c, 0x90, 0x66, 0x99, 0x3e, 0x4b, 0x19, 0x62, 0xfb, 0x31, 0x4d}}
return a, nil
}
@ -380,7 +380,7 @@ func _1561368210_add_installation_metadataDownSql() (*asset, error) {
return nil, err
}
info := bindataFileInfo{name: "1561368210_add_installation_metadata.down.sql", size: 35, mode: os.FileMode(0644), modTime: time.Unix(1564484687, 0)}
info := bindataFileInfo{name: "1561368210_add_installation_metadata.down.sql", size: 35, mode: os.FileMode(0644), modTime: time.Unix(1574354941, 0)}
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xa8, 0xde, 0x3f, 0xd2, 0x4a, 0x50, 0x98, 0x56, 0xe3, 0xc0, 0xcd, 0x9d, 0xb0, 0x34, 0x3b, 0xe5, 0x62, 0x18, 0xb5, 0x20, 0xc9, 0x3e, 0xdc, 0x6a, 0x40, 0x36, 0x66, 0xea, 0x51, 0x8c, 0x71, 0xf5}}
return a, nil
}
@ -400,7 +400,7 @@ func _1561368210_add_installation_metadataUpSql() (*asset, error) {
return nil, err
}
info := bindataFileInfo{name: "1561368210_add_installation_metadata.up.sql", size: 267, mode: os.FileMode(0644), modTime: time.Unix(1564484687, 0)}
info := bindataFileInfo{name: "1561368210_add_installation_metadata.up.sql", size: 267, mode: os.FileMode(0644), modTime: time.Unix(1574354941, 0)}
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xb4, 0x71, 0x8f, 0x29, 0xb1, 0xaa, 0xd6, 0xd1, 0x8c, 0x17, 0xef, 0x6c, 0xd5, 0x80, 0xb8, 0x2c, 0xc3, 0xfe, 0xec, 0x24, 0x4d, 0xc8, 0x25, 0xd3, 0xb4, 0xcd, 0xa9, 0xac, 0x63, 0x61, 0xb2, 0x9c}}
return a, nil
}
@ -420,7 +420,7 @@ func docGo() (*asset, error) {
return nil, err
}
info := bindataFileInfo{name: "doc.go", size: 377, mode: os.FileMode(0644), modTime: time.Unix(1564484687, 0)}
info := bindataFileInfo{name: "doc.go", size: 377, mode: os.FileMode(0644), modTime: time.Unix(1574354941, 0)}
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xef, 0xaf, 0xdf, 0xcf, 0x65, 0xae, 0x19, 0xfc, 0x9d, 0x29, 0xc1, 0x91, 0xaf, 0xb5, 0xd5, 0xb1, 0x56, 0xf3, 0xee, 0xa8, 0xba, 0x13, 0x65, 0xdb, 0xab, 0xcf, 0x4e, 0xac, 0x92, 0xe9, 0x60, 0xf1}}
return a, nil
}

View file

@ -384,6 +384,11 @@ func (p *Protocol) GetOurInstallations(myIdentityKey *ecdsa.PublicKey) ([]*multi
return p.multidevice.GetOurInstallations(myIdentityKey)
}
// GetOurActiveInstallations returns all the active installations available given an identity
func (p *Protocol) GetOurActiveInstallations(myIdentityKey *ecdsa.PublicKey) ([]*multidevice.Installation, error) {
return p.multidevice.GetOurActiveInstallations(myIdentityKey)
}
// SetInstallationMetadata sets the metadata for our own installation
func (p *Protocol) SetInstallationMetadata(myIdentityKey *ecdsa.PublicKey, installationID string, data *multidevice.InstallationMetadata) error {
return p.multidevice.SetInstallationMetadata(myIdentityKey, installationID, data)

View file

@ -10,15 +10,15 @@ replace github.com/status-im/status-go/eth-node => ../eth-node
require (
github.com/cenkalti/backoff/v3 v3.0.0
github.com/ethereum/go-ethereum v1.9.5
github.com/golang/protobuf v1.3.2
github.com/gomarkdown/markdown v0.0.0-20191113114344-af599402d015
github.com/google/uuid v1.1.1
github.com/jinzhu/copier v0.0.0-20190625015134-976e0346caa8
github.com/lucasb-eyer/go-colorful v1.0.2
github.com/mattn/go-pointer v0.0.0-20190911064623-a0a44394634f
github.com/mutecomm/go-sqlcipher v0.0.0-20190227152316-55dbde17881f
github.com/pkg/errors v0.8.1
github.com/russolsen/ohyeah v0.0.0-20160324131710-f4938c005315 // indirect
github.com/russolsen/same v0.0.0-20160222130632-f089df61f51d // indirect
github.com/russolsen/transit v0.0.0-20180705123435-0794b4c4505a
github.com/status-im/doubleratchet v3.0.0+incompatible
github.com/status-im/migrate/v4 v4.6.2-status.2
@ -27,4 +27,5 @@ require (
github.com/stretchr/testify v1.4.0
github.com/vacp2p/mvds v0.0.23
go.uber.org/zap v1.13.0
golang.org/x/crypto v0.0.0-20191119213627-4f8c1d86b1ba
)

View file

@ -2,6 +2,8 @@ bazil.org/fuse v0.0.0-20160811212531-371fbbdaa898/go.mod h1:Xbm+BRKSBEpa4q4hTSxo
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
cloud.google.com/go v0.37.4/go.mod h1:NHPJ89PdicEuT9hdPXMROBD91xc5uRDxsMtSB16k7hw=
github.com/AndreasBriese/bbloom v0.0.0-20180913140656-343706a395b7/go.mod h1:bOvUY6CB00SOBii9/FifXqc0awNKxLFCL/+pkDPuyl8=
github.com/AndreasBriese/bbloom v0.0.0-20190306092124-e2d15f34fcf9/go.mod h1:bOvUY6CB00SOBii9/FifXqc0awNKxLFCL/+pkDPuyl8=
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/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78/go.mod h1:LmzpDX56iTiv29bbRTIsUNlaFfuhWRQBWjQdVyAevI8=
@ -10,6 +12,7 @@ github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03
github.com/DATA-DOG/go-sqlmock v1.3.3 h1:CWUqKXe0s8A2z6qCgkP4Kru7wC11YoAnoupUKFDnH08=
github.com/DATA-DOG/go-sqlmock v1.3.3/go.mod h1:f/Ixk793poVmq4qj/V1dPUg2JEAKC73Q5eFN3EC/SaM=
github.com/Julusian/godocdown v0.0.0-20170816220326-6d19f8ff2df8/go.mod h1:INZr5t32rG59/5xeltqoCJoNY7e5x/3xoY9WSWVWg74=
github.com/Kubuxu/go-os-helper v0.0.1/go.mod h1:N8B+I7vPCT80IcP58r50u4+gEEcsZETFUpAzWW2ep1Y=
github.com/Microsoft/go-winio v0.4.11/go.mod h1:VhR8bwka0BXejwEJY73c50VrPtXAaKcyvVC4A4RozmA=
github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5/go.mod h1:lmUJ/7eu/Q8D7ML55dXQrVaamCz2vxCfdQBasLZfHKk=
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
@ -18,7 +21,9 @@ github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMx
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/go.mod h1:Cb/ax3seSYIx7SuZdm2G2xzfwmv3TPSk2ucNfQESPXM=
github.com/allegro/bigcache v1.1.0/go.mod h1:Cb/ax3seSYIx7SuZdm2G2xzfwmv3TPSk2ucNfQESPXM=
github.com/allegro/bigcache v1.2.0 h1:qDaE0QoF29wKBb3+pXFrJFy1ihe5OT9OiXhg1t85SxM=
@ -29,12 +34,20 @@ github.com/aristanetworks/goarista v0.0.0-20170210015632-ea17b1a17847/go.mod h1:
github.com/aristanetworks/goarista v0.0.0-20181002214814-33151c4543a7/go.mod h1:D/tb0zPVXnP7fmsLZjtdUhSsumbK/ij54UXjjVgMGxQ=
github.com/aristanetworks/goarista v0.0.0-20190219163901-728bce664cf5 h1:L0TwgZQo7Mga9im6FvKEZGIvyLE/VG/HI5loz5LpvC0=
github.com/aristanetworks/goarista v0.0.0-20190219163901-728bce664cf5/go.mod h1:D/tb0zPVXnP7fmsLZjtdUhSsumbK/ij54UXjjVgMGxQ=
github.com/aristanetworks/goarista v0.0.0-20190502180301-283422fc1708/go.mod h1:D/tb0zPVXnP7fmsLZjtdUhSsumbK/ij54UXjjVgMGxQ=
github.com/aristanetworks/goarista v0.0.0-20190704150520-f44d68189fd7 h1:fKnuvQ/O22ZpD7HaJjGQXn/GxOdDJOQFL8bpM8Xe3X8=
github.com/aristanetworks/goarista v0.0.0-20190704150520-f44d68189fd7/go.mod h1:D/tb0zPVXnP7fmsLZjtdUhSsumbK/ij54UXjjVgMGxQ=
github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8=
github.com/aws/aws-sdk-go v1.17.7/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo=
github.com/beevik/ntp v0.2.0/go.mod h1:hIHWr+l3+/clUnF44zdK+CWW7fO8dR5cIylAQ76NRpg=
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/bitly/go-hostpool v0.0.0-20171023180738-a3a6125de932/go.mod h1:NOuUCSz6Q9T7+igc/hlvDOUdtWKryOrtFyIVABv/p7k=
github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869/go.mod h1:Ekp36dRnpXw/yCqJaO+ZrUyxD+3VXMFFr56k5XYrpB4=
github.com/btcsuite/btcd v0.0.0-20181013004428-67e573d211ac/go.mod h1:Dmm/EzmjnCiweXmzRIAiUWCInVmPgjkzgv5k4tVyXiQ=
github.com/btcsuite/btcd v0.0.0-20190213025234-306aecffea32/go.mod h1:DrZx5ec/dmnfpw9KyYoQyYo7d0KEvTkk/5M/vbZjAr8=
github.com/btcsuite/btcd v0.0.0-20190418232430-6867ff32788a/go.mod h1:DrZx5ec/dmnfpw9KyYoQyYo7d0KEvTkk/5M/vbZjAr8=
github.com/btcsuite/btcd v0.20.0-beta/go.mod h1:wVuoA8VJLEcwgqHBwHmzLRazpKxTv13Px/pDuV7OomQ=
github.com/btcsuite/btcd v0.20.1-beta h1:Ik4hyJqN8Jfyv3S4AGBOmyouMsYE3EdYODkMbQjwPGw=
@ -53,12 +66,20 @@ github.com/cenkalti/backoff/v3 v3.0.0/go.mod h1:cIeZDE3IrqwwJl6VUwCN6trj1oXrTS4r
github.com/cespare/cp v0.1.0/go.mod h1:SOGHArjBr4JWaSDEVpWpo/hNg6RoKrls6Oh40hiwW+s=
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/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
github.com/cockroachdb/apd v1.1.0/go.mod h1:8Sl8LxpKi29FqWXR16WEFZRNSz3SoPzUzeMeY4+DwBQ=
github.com/cockroachdb/cockroach-go v0.0.0-20181001143604-e0a95dfd547c/go.mod h1:XGLbWH/ujMcbPbhZq52Nv6UrCghb1yGn//133kEsvDk=
github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd/go.mod h1:sE/e/2PUdi/liOCUjSTXgM1o87ZssimdTWN964YiIeI=
github.com/containerd/containerd v1.2.7/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA=
github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk=
github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE=
github.com/cznic/b v0.0.0-20180115125044-35e9bbe41f07/go.mod h1:URriBxXwVq5ijiJ12C7iIZqlA69nTlI+LgI6/pwftG8=
github.com/cznic/fileutil v0.0.0-20180108211300-6a051e75936f/go.mod h1:8S58EK26zhXSxzv7NQFpnliaOQsmDUxvoQO3rt154Vg=
github.com/cznic/golex v0.0.0-20170803123110-4ab7c5e190e4/go.mod h1:+bmmJDNmKlhWNG+gwWCkaBoTy39Fs+bzRxVBzoTQbIc=
@ -77,7 +98,11 @@ github.com/deckarep/golang-set v0.0.0-20180603214616-504e848d77ea/go.mod h1:93vs
github.com/deckarep/golang-set v1.7.1 h1:SCQV0S6gTtp6itiFrTqI+pfmJ4LN85S1YzhDf9rTHJQ=
github.com/deckarep/golang-set v1.7.1/go.mod h1:93vsz/8Wt4joVM7c2AVqh+YRMiUSc14yDtF28KmMOgQ=
github.com/denisenkom/go-mssqldb v0.0.0-20190515213511-eb9f6a1743f3/go.mod h1:zAg7JM8CkOJ43xKXIj7eRO9kmWm/TW578qo+oDO6tuM=
github.com/dgraph-io/badger v1.5.5-0.20190226225317-8115aed38f8f/go.mod h1:VZxzAIRPHRVNRKRo6AXrX9BJegn6il06VMTZVJYCIjQ=
github.com/dgraph-io/badger v1.6.0-rc1/go.mod h1:zwt7syl517jmP8s94KqSxTlM6IMsdhYy6psNgSztDR4=
github.com/dgrijalva/jwt-go v0.0.0-20170201225849-2268707a8f08/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
github.com/dgryski/go-farm v0.0.0-20190104051053-3adb47b1fb0f/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw=
github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw=
github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no=
github.com/dhui/dktest v0.3.0/go.mod h1:cyzIUfGsBEbZ6BT7tnXqAShHSXCZhSNmFl70sZ7c1yc=
github.com/docker/distribution v2.7.0+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
@ -87,6 +112,7 @@ github.com/docker/docker v0.7.3-0.20190817195342-4760db040282/go.mod h1:eEKB0N0r
github.com/docker/docker v1.13.1/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec=
github.com/docker/go-units v0.3.3/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
github.com/dvyukov/go-fuzz v0.0.0-20191022152526-8cb203812681/go.mod h1:11Gm+ccJnvAhCNLlf5+cS9KjtbaD5I5zaZpFMsTHWTw=
github.com/eapache/go-resiliency v1.1.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs=
github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21/go.mod h1:+020luEh2TKB4/GOp8oxxtq0Daoen/Cii55CzbTV6DU=
@ -99,6 +125,7 @@ github.com/elastic/gosigar v0.0.0-20180330100440-37f05ff46ffa/go.mod h1:cdorVVzy
github.com/elastic/gosigar v0.10.4 h1:6jfw75dsoflhBMRdO6QPzQUgLqUYTsQQQRkkcsHsuPo=
github.com/elastic/gosigar v0.10.4/go.mod h1:cdorVVzy1fhmEqmtgqkoE3bYtCfSCkVyjTyCIo22xvs=
github.com/elazarl/go-bindata-assetfs v1.0.0/go.mod h1:v+YaWX3bdea5J/mo8dSETolEo7R71Vk1u8bnjau5yw4=
github.com/ethereum/go-ethereum v1.8.20/go.mod h1:PwpWDrCLZrV+tfrhqqF6kPknbISMHaJv9Ln3kPCZLwY=
github.com/ethereum/go-ethereum v1.9.2/go.mod h1:PwpWDrCLZrV+tfrhqqF6kPknbISMHaJv9Ln3kPCZLwY=
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=
@ -110,11 +137,18 @@ github.com/fsouza/fake-gcs-server v1.7.0/go.mod h1:5XIRs4YvwNbNoz+1JF8j6KLAyDh7R
github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff h1:tY80oXqGNY4FhTFhk+o9oFHGINQ/+vhlm8HFzi6znCI=
github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff/go.mod h1:x7DCsMOv1taUwEWCzT4cmDeAkigA5/QCwUodaVOe8Ww=
github.com/gizak/termui v0.0.0-20170117222342-991cd3d38091/go.mod h1:PkJoWUt/zacQKysNfQtcw1RW+eK2SxkieVBtl+4ovLA=
github.com/go-check/check v0.0.0-20180628173108-788fd7840127/go.mod h1:9ES+weclKsC9YodN5RgxqK/VD9HM9JsCSh7rNhMZE98=
github.com/go-kit/kit v0.8.0 h1:Wz+5lgoB0kkuqLEc6NVmwRknTKP6dTGbSqvhZtBI/j0=
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 h1:8HUsc87TaSWLKwrnumgC8/YconD2fJQsRJAsWaPg2ic=
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/go.mod h1:7FAglXiTm7HKlQRDeOQ6ZNUHidzCWXuZWq/1dTyBNF8=
github.com/go-playground/locales v0.12.1 h1:2FITxuFt/xuCNP1Acdhv62OzaCiviiE4kotfhkmOqEc=
github.com/go-playground/locales v0.12.1/go.mod h1:IUMDtCfWo/w/mtMfIE/IG2K+Ey3ygWanZIBtBW0W2TM=
github.com/go-playground/universal-translator v0.16.0 h1:X++omBR/4cE2MNg91AoC3rmGrCjJ8eAeUP/K/EKx4DM=
github.com/go-playground/universal-translator v0.16.0/go.mod h1:1AnU7NaIRDWWzGEKwgtJRd2xk99HeFyHw3yid4rvQIY=
github.com/go-sql-driver/mysql v1.4.1/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w=
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=
@ -123,12 +157,16 @@ github.com/gocql/gocql v0.0.0-20190301043612-f6df8288f9b4/go.mod h1:4Fw1eo5iaEhD
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
github.com/gogo/protobuf v1.2.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4=
github.com/gogo/protobuf v1.3.0/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o=
github.com/golang-migrate/migrate/v4 v4.6.2 h1:LDDOHo/q1W5UDj6PbkxdCv7lv9yunyZHXvxuwDkGo3k=
github.com/golang-migrate/migrate/v4 v4.6.2/go.mod h1:JYi6reN3+Z734VZ0akNuyOJNcrg45ZL7LDBMW3WGJL0=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.0/go.mod h1:Qd/q+1AKNOZr9uGQzbzCmRO6sUih6GTPZv6a1/R87v0=
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=
@ -138,8 +176,10 @@ github.com/golang/snappy v0.0.1 h1:Qgr9rKW7uDUkrbSmQeiDsGa8SjGyCOGtuasMWwvp2P4=
github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-github v17.0.0+incompatible/go.mod h1:zLgOLi98H3fifZn+44m+umXrS52loVEgC2AApnigrVQ=
github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
@ -150,9 +190,13 @@ github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+
github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg=
github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
github.com/gorilla/mux v1.7.1/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
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/graph-gophers/graphql-go v0.0.0-20190724201507-010347b5f9e6/go.mod h1:Au3iQ8DvDis8hZ4q2OzRcaKYlAsPt+fYvib5q4nIqu4=
github.com/gxed/hashland/keccakpg v0.0.1/go.mod h1:kRzw3HkwxFU1mpmPP8v1WyQzwdGfmKFJ6tItnhQ67kU=
github.com/gxed/hashland/murmur3 v0.0.1/go.mod h1:KjXop02n4/ckmZSnY2+HKcLud/tcmvhST0bie/0lS48=
github.com/gyuho/goraph v0.0.0-20171001060514-a7a4454fd3eb/go.mod h1:NtSxZCD+s3sZFwbW6WceOcUD83HM9XD5OE2r4c0P8eg=
github.com/hailocab/go-hostpool v0.0.0-20160125115350-e80d13ce29ed/go.mod h1:tMWxXQ9wFIaZeTI9F+hmhFiGpFmhOHzyShyFUhRm0H4=
github.com/hashicorp/errwrap v1.0.0 h1:hLrqtEDnRye3+sgx6z4qVLNuviH3MR5aQ0ykNJa/UYA=
github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
@ -162,6 +206,7 @@ github.com/hashicorp/golang-lru v0.0.0-20160813221303-0a025b7e63ad/go.mod h1:/m3
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hashicorp/golang-lru v0.5.1 h1:0hERBMJE1eitiLkihrMvRVBYAkpHzc/J3QdDN+dAcgU=
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
github.com/howeyc/fsnotify v0.9.0/go.mod h1:41HzSPxBGeFRQKEEwgh49TRw/nKBsYZ2cF1OzPjSJsA=
github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI=
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
@ -169,31 +214,54 @@ github.com/huin/goupnp v0.0.0-20161224104101-679507af18f3/go.mod h1:MZ2ZmwcBpvOo
github.com/huin/goupnp v1.0.0 h1:wg75sLpL6DZqwHQN6E1Cfk6mtfzS45z8OV+ic+DtHRo=
github.com/huin/goupnp v1.0.0/go.mod h1:n9v9KO1tAxYH82qOn+UTIFQDmx5n1Zxd/ClZDMX7Bnc=
github.com/huin/goutil v0.0.0-20170803182201-1ca381bf3150/go.mod h1:PpLOETDnJ0o3iZrZfqZzyLl6l7F3c6L1oWn7OICBi6o=
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
github.com/influxdata/influxdb v0.0.0-20180221223340-01288bdb0883/go.mod h1:qZna6X/4elxqT3yI9iZYdZrWWdeFOOprn86kgg4+IzY=
github.com/influxdata/influxdb v1.7.7/go.mod h1:qZna6X/4elxqT3yI9iZYdZrWWdeFOOprn86kgg4+IzY=
github.com/ipfs/go-cid v0.0.1/go.mod h1:GHWU/WuQdMPmIosc4Yn1bcCT7dSeX4lBafM7iqUPQvM=
github.com/ipfs/go-cid v0.0.2/go.mod h1:GHWU/WuQdMPmIosc4Yn1bcCT7dSeX4lBafM7iqUPQvM=
github.com/ipfs/go-cid v0.0.3/go.mod h1:GHWU/WuQdMPmIosc4Yn1bcCT7dSeX4lBafM7iqUPQvM=
github.com/ipfs/go-datastore v0.0.1/go.mod h1:d4KVXhMt913cLBEI/PXAy6ko+W7e9AhyAKBGh803qeE=
github.com/ipfs/go-detect-race v0.0.1/go.mod h1:8BNT7shDZPo99Q74BpGMK+4D8Mn4j46UU0LZ723meps=
github.com/ipfs/go-ds-badger v0.0.2/go.mod h1:Y3QpeSFWQf6MopLTiZD+VT6IC1yZqaGmjvRcKeSGij8=
github.com/ipfs/go-ds-badger v0.0.5/go.mod h1:g5AuuCGmr7efyzQhLL8MzwqcauPojGPUaHzfGTzuE3s=
github.com/ipfs/go-ds-leveldb v0.0.1/go.mod h1:feO8V3kubwsEF22n0YRQCffeb79OOYIykR4L04tMOYc=
github.com/ipfs/go-ipfs-delay v0.0.0-20181109222059-70721b86a9a8/go.mod h1:8SP1YXK1M1kXuc4KJZINY3TQQ03J2rwBG9QfXmbRPrw=
github.com/ipfs/go-ipfs-util v0.0.1/go.mod h1:spsl5z8KUnrve+73pOhSVZND1SIxPW5RyBCNzQxlJBc=
github.com/ipfs/go-log v0.0.1/go.mod h1:kL1d2/hzSpI0thNYjiKfjanbVNU+IIGA/WnNESY9leM=
github.com/jackc/fake v0.0.0-20150926172116-812a484cc733/go.mod h1:WrMFNQdiFJ80sQsxDoMokWK1W5TQtxBFNpzWTD84ibQ=
github.com/jackc/pgx v3.2.0+incompatible/go.mod h1:0ZGrqGqkRlliWnWB4zKnWtjbSWbGkVEFm4TeybAXq+I=
github.com/jackpal/gateway v1.0.5/go.mod h1:lTpwd4ACLXmpyiCTRtfiNyVnUmqT9RivzCDQetPfnjA=
github.com/jackpal/go-nat-pmp v0.0.0-20160603034137-1fa385a6f458/go.mod h1:QPH045xvCAeXUZOxsnwmrtiCoxIr9eob+4orBN1SBKc=
github.com/jackpal/go-nat-pmp v1.0.1 h1:i0LektDkO1QlrTm/cSuP+PyBCDnYvjPLGl4LdWEMiaA=
github.com/jackpal/go-nat-pmp v1.0.1/go.mod h1:QPH045xvCAeXUZOxsnwmrtiCoxIr9eob+4orBN1SBKc=
github.com/jbenet/go-cienv v0.0.0-20150120210510-1bb1476777ec/go.mod h1:rGaEvXB4uRSZMmzKNLoXvTu1sfx+1kv/DojUlPrSZGs=
github.com/jbenet/go-cienv v0.1.0/go.mod h1:TqNnHUmJgXau0nCzC7kXWeotg3J9W34CUv5Djy1+FlA=
github.com/jbenet/go-temp-err-catcher v0.0.0-20150120210811-aac704a3f4f2/go.mod h1:8GXXJV31xl8whumTzdZsTt3RnUIiPqzkyf7mxToRCMs=
github.com/jbenet/goprocess v0.0.0-20160826012719-b497e2f366b8/go.mod h1:Ly/wlsjFq/qrU3Rar62tu1gASgGw6chQbSh/XgIIXCY=
github.com/jbenet/goprocess v0.1.3/go.mod h1:5yspPrukOVuOLORacaBi858NqyClJPQxYZlqdZVfqY4=
github.com/jessevdk/go-flags v0.0.0-20141203071132-1679536dcc89/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
github.com/jinzhu/copier v0.0.0-20190625015134-976e0346caa8 h1:mGIXW/lubQ4B+3bXTLxcTMTjUNDqoF6T/HUW9LbFx9s=
github.com/jinzhu/copier v0.0.0-20190625015134-976e0346caa8/go.mod h1:yL958EeXv8Ylng6IfnvG4oflryUi3vgA3xPs9hmII1s=
github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k=
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/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=
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
github.com/kami-zh/go-capturer v0.0.0-20171211120116-e492ea43421d/go.mod h1:P2viExyCEfeWGU259JnaQ34Inuec4R38JCyBx2edgD0=
github.com/karalabe/hid v0.0.0-20181128192157-d815e0c1a2e2/go.mod h1:YvbcH+3Wo6XPs9nkgTY3u19KXLauXW+J5nB7hEHuX0A=
github.com/karalabe/usb v0.0.0-20190819132248-550797b1cad8 h1:VhnqxaTIudc9IWKx8uXRLnpdSb9noCEj+vHacjmhp68=
github.com/karalabe/usb v0.0.0-20190819132248-550797b1cad8/go.mod h1:Od972xHfMJowv7NGVDiWVxk2zxnWgjLlJzE+F4F7AGU=
github.com/kardianos/osext v0.0.0-20190222173326-2bc1f35cddc0/go.mod h1:1NbS8ALrpOvjt0rHPNLyCIeMtbizbir8U//inJ+zuB8=
github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q=
github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
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/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/koron/go-ssdp v0.0.0-20180514024734-4a0ed625a78b/go.mod h1:5Ky9EC2xfoUKUor0Hjgi2BJhCSXJfMOFlmyYrVKGQMk=
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515 h1:T+h1c/A9Gawja4Y9mFVWj2vyii2bbUNDw3kt9VxK2EY=
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
@ -202,14 +270,80 @@ github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/kshvakov/clickhouse v1.3.5/go.mod h1:DMzX7FxRymoNkVgizH0DWAL8Cur7wHLgx3MUnGwJqpE=
github.com/leodido/go-urn v1.1.0 h1:Sm1gr51B1kKyfD2BlRcLSiEkffoG96g6TPv6eRoEiB8=
github.com/leodido/go-urn v1.1.0/go.mod h1:+cyI34gQWZcE1eQU7NVgKkkzdXDQHr1dBMtdAPozLkw=
github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
github.com/lib/pq v1.2.0 h1:LXpIM/LZ5xGFhOpXAQUIMM1HdyqzVYM13zNdjCEEcA0=
github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
github.com/libp2p/go-addr-util v0.0.1/go.mod h1:4ac6O7n9rIAKB1dnd+s8IbbMXkt+oBpzX4/+RACcnlQ=
github.com/libp2p/go-buffer-pool v0.0.1/go.mod h1:xtyIz9PMobb13WaxR6Zo1Pd1zXJKYg0a8KiIvDp3TzQ=
github.com/libp2p/go-buffer-pool v0.0.2/go.mod h1:MvaB6xw5vOrDl8rYZGLFdKAuk/hRoRZd1Vi32+RXyFM=
github.com/libp2p/go-conn-security-multistream v0.1.0/go.mod h1:aw6eD7LOsHEX7+2hJkDxw1MteijaVcI+/eP2/x3J1xc=
github.com/libp2p/go-eventbus v0.1.0/go.mod h1:vROgu5cs5T7cv7POWlWxBaVLxfSegC5UGQf8A2eEmx4=
github.com/libp2p/go-flow-metrics v0.0.1/go.mod h1:Iv1GH0sG8DtYN3SVJ2eG221wMiNpZxBdp967ls1g+k8=
github.com/libp2p/go-libp2p v0.1.1/go.mod h1:I00BRo1UuUSdpuc8Q2mN7yDF/oTUTRAX6JWpTiK9Rp8=
github.com/libp2p/go-libp2p v0.4.0/go.mod h1:9EsEIf9p2UDuwtPd0DwJsAl0qXVxgAnuDGRvHbfATfI=
github.com/libp2p/go-libp2p-autonat v0.1.0/go.mod h1:1tLf2yXxiE/oKGtDwPYWTSYG3PtvYlJmg7NeVtPRqH8=
github.com/libp2p/go-libp2p-blankhost v0.1.1/go.mod h1:pf2fvdLJPsC1FsVrNP3DUUvMzUts2dsLLBEpo1vW1ro=
github.com/libp2p/go-libp2p-blankhost v0.1.4/go.mod h1:oJF0saYsAXQCSfDq254GMNmLNz6ZTHTOvtF4ZydUvwU=
github.com/libp2p/go-libp2p-circuit v0.1.0/go.mod h1:Ahq4cY3V9VJcHcn1SBXjr78AbFkZeIRmfunbA7pmFh8=
github.com/libp2p/go-libp2p-circuit v0.1.3/go.mod h1:Xqh2TjSy8DD5iV2cCOMzdynd6h8OTBGoV1AWbWor3qM=
github.com/libp2p/go-libp2p-core v0.0.1/go.mod h1:g/VxnTZ/1ygHxH3dKok7Vno1VfpvGcGip57wjTU4fco=
github.com/libp2p/go-libp2p-core v0.0.3/go.mod h1:j+YQMNz9WNSkNezXOsahp9kwZBKBvxLpKD316QWSJXE=
github.com/libp2p/go-libp2p-core v0.0.4/go.mod h1:jyuCQP356gzfCFtRKyvAbNkyeuxb7OlyhWZ3nls5d2I=
github.com/libp2p/go-libp2p-core v0.2.0/go.mod h1:X0eyB0Gy93v0DZtSYbEM7RnMChm9Uv3j7yRXjO77xSI=
github.com/libp2p/go-libp2p-core v0.2.2/go.mod h1:8fcwTbsG2B+lTgRJ1ICZtiM5GWCWZVoVrLaDRvIRng0=
github.com/libp2p/go-libp2p-core v0.2.3/go.mod h1:GqhyQqyIAPsxFYXHMjfXgMv03lxsvM0mFzuYA9Ib42A=
github.com/libp2p/go-libp2p-crypto v0.1.0/go.mod h1:sPUokVISZiy+nNuTTH/TY+leRSxnFj/2GLjtOTW90hI=
github.com/libp2p/go-libp2p-discovery v0.1.0/go.mod h1:4F/x+aldVHjHDHuX85x1zWoFTGElt8HnoDzwkFZm29g=
github.com/libp2p/go-libp2p-loggables v0.1.0/go.mod h1:EyumB2Y6PrYjr55Q3/tiJ/o3xoDasoRYM7nOzEpoa90=
github.com/libp2p/go-libp2p-mplex v0.2.0/go.mod h1:Ejl9IyjvXJ0T9iqUTE1jpYATQ9NM3g+OtR+EMMODbKo=
github.com/libp2p/go-libp2p-mplex v0.2.1/go.mod h1:SC99Rxs8Vuzrf/6WhmH41kNn13TiYdAWNYHrwImKLnE=
github.com/libp2p/go-libp2p-nat v0.0.4/go.mod h1:N9Js/zVtAXqaeT99cXgTV9e75KpnWCvVOiGzlcHmBbY=
github.com/libp2p/go-libp2p-netutil v0.1.0/go.mod h1:3Qv/aDqtMLTUyQeundkKsA+YCThNdbQD54k3TqjpbFU=
github.com/libp2p/go-libp2p-peer v0.2.0/go.mod h1:RCffaCvUyW2CJmG2gAWVqwePwW7JMgxjsHm7+J5kjWY=
github.com/libp2p/go-libp2p-peerstore v0.1.0/go.mod h1:2CeHkQsr8svp4fZ+Oi9ykN1HBb6u0MOvdJ7YIsmcwtY=
github.com/libp2p/go-libp2p-peerstore v0.1.3/go.mod h1:BJ9sHlm59/80oSkpWgr1MyY1ciXAXV397W6h1GH/uKI=
github.com/libp2p/go-libp2p-secio v0.1.0/go.mod h1:tMJo2w7h3+wN4pgU2LSYeiKPrfqBgkOsdiKK77hE7c8=
github.com/libp2p/go-libp2p-secio v0.2.0/go.mod h1:2JdZepB8J5V9mBp79BmwsaPQhRPNN2NrnB2lKQcdy6g=
github.com/libp2p/go-libp2p-swarm v0.1.0/go.mod h1:wQVsCdjsuZoc730CgOvh5ox6K8evllckjebkdiY5ta4=
github.com/libp2p/go-libp2p-swarm v0.2.2/go.mod h1:fvmtQ0T1nErXym1/aa1uJEyN7JzaTNyBcHImCxRpPKU=
github.com/libp2p/go-libp2p-testing v0.0.2/go.mod h1:gvchhf3FQOtBdr+eFUABet5a4MBLK8jM3V4Zghvmi+E=
github.com/libp2p/go-libp2p-testing v0.0.3/go.mod h1:gvchhf3FQOtBdr+eFUABet5a4MBLK8jM3V4Zghvmi+E=
github.com/libp2p/go-libp2p-testing v0.0.4/go.mod h1:gvchhf3FQOtBdr+eFUABet5a4MBLK8jM3V4Zghvmi+E=
github.com/libp2p/go-libp2p-testing v0.1.0/go.mod h1:xaZWMJrPUM5GlDBxCeGUi7kI4eqnjVyavGroI2nxEM0=
github.com/libp2p/go-libp2p-transport-upgrader v0.1.1/go.mod h1:IEtA6or8JUbsV07qPW4r01GnTenLW4oi3lOPbUMGJJA=
github.com/libp2p/go-libp2p-yamux v0.2.0/go.mod h1:Db2gU+XfLpm6E4rG5uGCFX6uXA8MEXOxFcRoXUODaK8=
github.com/libp2p/go-libp2p-yamux v0.2.1/go.mod h1:1FBXiHDk1VyRM1C0aez2bCfHQ4vMZKkAQzZbkSQt5fI=
github.com/libp2p/go-maddr-filter v0.0.4/go.mod h1:6eT12kSQMA9x2pvFQa+xesMKUBlj9VImZbj3B9FBH/Q=
github.com/libp2p/go-maddr-filter v0.0.5/go.mod h1:Jk+36PMfIqCJhAnaASRH83bdAvfDRp/w6ENFaC9bG+M=
github.com/libp2p/go-mplex v0.0.3/go.mod h1:pK5yMLmOoBR1pNCqDlA2GQrdAVTMkqFalaTWe7l4Yd0=
github.com/libp2p/go-mplex v0.1.0/go.mod h1:SXgmdki2kwCUlCCbfGLEgHjC4pFqhTp0ZoV6aiKgxDU=
github.com/libp2p/go-msgio v0.0.2/go.mod h1:63lBBgOTDKQL6EWazRMCwXsEeEeK9O2Cd+0+6OOuipQ=
github.com/libp2p/go-msgio v0.0.4/go.mod h1:63lBBgOTDKQL6EWazRMCwXsEeEeK9O2Cd+0+6OOuipQ=
github.com/libp2p/go-nat v0.0.3/go.mod h1:88nUEt0k0JD45Bk93NIwDqjlhiOwOoV36GchpcVc1yI=
github.com/libp2p/go-openssl v0.0.2/go.mod h1:v8Zw2ijCSWBQi8Pq5GAixw6DbFfa9u6VIYDXnvOXkc0=
github.com/libp2p/go-reuseport v0.0.1/go.mod h1:jn6RmB1ufnQwl0Q1f+YxAj8isJgDCQzaaxIFYDhcYEA=
github.com/libp2p/go-reuseport-transport v0.0.2/go.mod h1:YkbSDrvjUVDL6b8XqriyA20obEtsW9BLkuOUyQAOCbs=
github.com/libp2p/go-stream-muxer v0.0.1/go.mod h1:bAo8x7YkSpadMTbtTaxGVHWUQsR/l5MEaHbKaliuT14=
github.com/libp2p/go-stream-muxer-multistream v0.2.0/go.mod h1:j9eyPol/LLRqT+GPLSxvimPhNph4sfYfMoDPd7HkzIc=
github.com/libp2p/go-tcp-transport v0.1.0/go.mod h1:oJ8I5VXryj493DEJ7OsBieu8fcg2nHGctwtInJVpipc=
github.com/libp2p/go-tcp-transport v0.1.1/go.mod h1:3HzGvLbx6etZjnFlERyakbaYPdfjg2pWP97dFZworkY=
github.com/libp2p/go-ws-transport v0.1.0/go.mod h1:rjw1MG1LU9YDC6gzmwObkPd/Sqwhw7yT74kj3raBFuo=
github.com/libp2p/go-ws-transport v0.1.2/go.mod h1:dsh2Ld8F+XNmzpkaAijmg5Is+e9l6/1tK/6VFOdN69Y=
github.com/libp2p/go-yamux v1.2.2/go.mod h1:FGTiPvoV/3DVdgWpX+tM0OW3tsM+W5bSE3gZwqQTcow=
github.com/libp2p/go-yamux v1.2.3/go.mod h1:FGTiPvoV/3DVdgWpX+tM0OW3tsM+W5bSE3gZwqQTcow=
github.com/lucasb-eyer/go-colorful v1.0.2 h1:mCMFu6PgSozg9tDNMMK3g18oJBX7oYGrC09mS6CXfO4=
github.com/lucasb-eyer/go-colorful v1.0.2/go.mod h1:0MS4r+7BZKSJ5mw4/S5MPN+qHFF1fYclkSPilDOKW0s=
github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
github.com/mailru/easyjson v0.0.0-20180823135443-60711f1a8329/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
github.com/maruel/panicparse v0.0.0-20160720141634-ad661195ed0e/go.mod h1:nty42YY5QByNC5MM7q/nj938VbgPU7avs45z6NClpxI=
github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
github.com/mattn/go-colorable v0.1.0/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
github.com/mattn/go-colorable v0.1.1 h1:G1f5SKeVxmagw/IyvzvtZE4Gybcc4Tr1tf7I8z0XgOg=
github.com/mattn/go-colorable v0.1.1/go.mod h1:FuOcm+DKB9mbwrcAfNl7/TZVBZ6rcnceauSikq3lYCQ=
github.com/mattn/go-isatty v0.0.0-20180830101745-3fb116b82035/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
github.com/mattn/go-isatty v0.0.5/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
github.com/mattn/go-isatty v0.0.7 h1:UvyT9uN+3r7yLEYSlJsbQGdsaB/a0DlgWP3pql6iwOc=
github.com/mattn/go-isatty v0.0.7/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
@ -219,16 +353,24 @@ github.com/mattn/go-runewidth v0.0.4 h1:2BvfKmzob6Bmd4YsL0zygOqfdFnK7GR4QL06Do4/
github.com/mattn/go-runewidth v0.0.4/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
github.com/mattn/go-sqlite3 v1.10.0 h1:jbhqpg7tQe4SupckyijYiy0mJJ/pRyHvXf7JdWK860o=
github.com/mattn/go-sqlite3 v1.10.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc=
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/mgutz/ansi v0.0.0-20170206155736-9520e82c474b/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE=
github.com/miekg/dns v1.1.12/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg=
github.com/minio/blake2b-simd v0.0.0-20160723061019-3f5f724cb5b1 h1:lYpkrQH5ajf0OXOcUbGjvZxxijuBwbbmlSxLiuofa+g=
github.com/minio/blake2b-simd v0.0.0-20160723061019-3f5f724cb5b1/go.mod h1:pD8RvIylQ358TN4wwqatJ8rNavkEINozVn9DtGI3dfQ=
github.com/minio/sha256-simd v0.0.0-20190328051042-05b4dd3047e5 h1:l16XLUUJ34wIz+RIvLhSwGvLvKyy+W598b135bJN6mg=
github.com/minio/sha256-simd v0.0.0-20190328051042-05b4dd3047e5/go.mod h1:2FMWW+8GMoPweT6+pI63m9YE3Lmw4J71hV56Chs1E/U=
github.com/mitchellh/go-wordwrap v0.0.0-20150314170334-ad45545899c7/go.mod h1:ZXFpozHsX6DPmq2I0TCekCxypsnAUbP2oI0UX1GXzOo=
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
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/morikuni/aec v0.0.0-20170113033406-39771216ff4c/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc=
github.com/mr-tron/base58 v1.1.0/go.mod h1:xcD2VGqlgYjBdcBLw+TuYLr8afG+Hj8g2eTVqeSzSU8=
github.com/mr-tron/base58 v1.1.1/go.mod h1:xcD2VGqlgYjBdcBLw+TuYLr8afG+Hj8g2eTVqeSzSU8=
github.com/mr-tron/base58 v1.1.2 h1:ZEw4I2EgPKDJ2iEw0cNmLB3ROrEmkOtXIkaG7wZg+78=
github.com/mr-tron/base58 v1.1.2/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc=
github.com/multiformats/go-multihash v0.0.5 h1:1wxmCvTXAifAepIMyF39vZinRw5sbqjPs/UIi93+uik=
@ -240,25 +382,30 @@ github.com/nakagami/firebirdsql v0.0.0-20190310045651-3c02a58cfed8/go.mod h1:86w
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/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U=
github.com/okzk/sdnotify v0.0.0-20180710141335-d9becc38acbd/go.mod h1:4soZNh0zW0LtYGdQ416i0jO0EIqMGcbtaspRS4BDvRQ=
github.com/olekukonko/tablewriter v0.0.0-20170128050532-febf2d34b54a/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo=
github.com/olekukonko/tablewriter v0.0.1 h1:b3iUnf1v+ppJiOfNX4yxxqfWKMQPZR5yoh8urCTFX88=
github.com/olekukonko/tablewriter v0.0.1/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/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v1.8.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v1.10.1 h1:q/mM8GF/n0shIN8SaAZ0V+jnLPzen6WIVZdiwrRlMlo=
github.com/onsi/ginkgo v1.10.1/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
github.com/onsi/gomega v1.5.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
github.com/onsi/gomega v1.7.0 h1:XPnZz8VVBHjVsy1vzJmRwIcSwiUO+JFfrv/xGiigmME=
github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
github.com/opencontainers/go-digest v1.0.0-rc1/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s=
github.com/opencontainers/image-spec v1.0.1/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0=
github.com/opentracing/opentracing-go v0.0.0-20180606204148-bd9c31933947/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o=
github.com/opentracing/opentracing-go v1.0.2/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o=
github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o=
github.com/openzipkin/zipkin-go v0.1.6/go.mod h1:QgAqvLzwWbR/WpD4A3cGpPtJrZXNIiJc5AZX7/PBEpw=
github.com/oschwald/maxminddb-golang v1.3.1/go.mod h1:3jhIUymTJ5VREKyIhWm66LJiQt04F0UCDdodShpjWsY=
github.com/pborman/uuid v0.0.0-20170112150404-1b00554d8222/go.mod h1:VyrYX9gd7irzKovcSS6BIIEwPRkP2Wm2m9ufcdFSJ34=
github.com/pborman/uuid v1.2.0 h1:J7Q5mO4ysT1dv8hyrUGHb9+ooztCXu1D8MY8DZYsu3g=
github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k=
github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
github.com/peterh/liner v0.0.0-20170902204657-a37ad3984311/go.mod h1:xIteQHvHuaLYG9IFj6mSxM0fCKrs34IrEQUhOYuGPHc=
github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY=
github.com/pkg/errors v0.0.0-20171216070316-e881fd58d78e/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
@ -268,16 +415,27 @@ github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINE
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 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_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
github.com/prometheus/client_model v0.0.0-20190115171406-56726106282f/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.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/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/prometheus v0.0.0-20170814170113-3101606756c5/go.mod h1:oAIUtOny2rjMX0OWN5vPR5/q/twIROJvdqnQKDdil/s=
github.com/prometheus/tsdb v0.10.0 h1:If5rVCMTp6W2SiRAQFlbpJNgVlgMEd+U2GZckwK38ic=
github.com/prometheus/tsdb v0.10.0/go.mod h1:oi49uRhEe9dPUTlS3JRZOwJuVi6tmh10QSgwXEyGCt4=
@ -298,14 +456,26 @@ github.com/russolsen/same v0.0.0-20160222130632-f089df61f51d h1:A926QrjwToaPS7gi
github.com/russolsen/same v0.0.0-20160222130632-f089df61f51d/go.mod h1:Cpq811GTlHevuU6BZxk3ObOdK8AY5gHu9QGmDak0DT4=
github.com/russolsen/transit v0.0.0-20180705123435-0794b4c4505a h1:yVNJFSzkEG8smsvd9udiQcMJA0MIsFvlG7ba314cu+s=
github.com/russolsen/transit v0.0.0-20180705123435-0794b4c4505a/go.mod h1:TPq+fcJOdGrkpZpXF4UVmFjYxH0gGqnxdgZ+OzAmvJk=
github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g=
github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0=
github.com/shopspring/decimal v0.0.0-20180709203117-cd690d0c9e24 h1:pntxY8Ary0t43dCZ5dqY4YTJCObLY1kIXl0uzMv+7DE=
github.com/shopspring/decimal v0.0.0-20180709203117-cd690d0c9e24/go.mod h1:M+9NzErvs504Cn4c5DxATwIqPbtswREoFCre64PpcG4=
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q=
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
github.com/smola/gocompat v0.2.0/go.mod h1:1B0MlxbmoZNo3h8guHp8HztB3BSYR5itql9qtVc0ypY=
github.com/spacemonkeygo/openssl v0.0.0-20181017203307-c2dcc5cca94a/go.mod h1:7AyxJNCJ7SBZ1MfVQCWD6Uqo2oubI2Eq2y2eqf+A5r0=
github.com/spacemonkeygo/spacelog v0.0.0-20180420211403-2296661a0572/go.mod h1:w0SWMsp6j9O/dk4/ZpIhL+3CkG8ofA2vuv7k+ltqUMc=
github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
github.com/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0bLI=
github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ=
github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU=
github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo=
github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s=
github.com/src-d/envconfig v1.0.0/go.mod h1:Q9YQZ7BKITldTBnoxsE5gOeB5y66RyPXeue/R4aaNBc=
github.com/status-im/doubleratchet v3.0.0+incompatible h1:aJ1ejcSERpSzmWZBgtfYtiU2nF0Q8ZkGyuEPYETXkCY=
github.com/status-im/doubleratchet v3.0.0+incompatible/go.mod h1:1sqR0+yhiM/bd+wrdX79AOt2csZuJOni0nUDzKNuqOU=
github.com/status-im/go-ethereum v1.9.5-status.6 h1:ytuTO1yBIAuTVRtRQoc2mrdyngtP+XOQ9IHIibbz7/I=
@ -316,10 +486,13 @@ github.com/status-im/markdown v0.0.0-20191113114344-af599402d015 h1:ijC73VP0hucs
github.com/status-im/markdown v0.0.0-20191113114344-af599402d015/go.mod h1:tmG2bxyvZ2EItDO5JewbdFvV45j13IYQgvnMJ3+qAaE=
github.com/status-im/migrate/v4 v4.6.2-status.2 h1:SdC+sMDl/aI7vUlwD2qj2p7KsK4T60IS9z4/rYCCbI8=
github.com/status-im/migrate/v4 v4.6.2-status.2/go.mod h1:c/kc90n47GZu/58nnz1OMLTf7uE4Da4gZP5qmU+A/v8=
github.com/status-im/status-go v0.36.0 h1:91qDMJjHv+T3Li9FwxsWQ2JBVcYtvVDT0nGFSMnmM+8=
github.com/status-im/status-go/extkeys v1.0.0 h1:Qyirsoi5Ye5UFfisgPtCjPb/RkBxyK+UsSiEcr2PVlM=
github.com/status-im/status-go/extkeys v1.0.0/go.mod h1:GdqJbrcpkNm5ZsSCpp+PdMxnXx+OcRBdm3PI0rs1FpU=
github.com/status-im/whisper v1.5.2 h1:26NgiKusmPic38eQdtXnaY+iaQ/LuQ3Dh0kCGYT/Uxs=
github.com/status-im/whisper v1.5.2/go.mod h1:emrOxzJme0k66QtbbQ2bdd3P8RCdLZ8sTD7SkwH1s2s=
github.com/status-im/whisper v1.6.1 h1:C/T1HQHZfUI2jbccf3yIe8yfkl435I3BILIKeNASJDc=
github.com/status-im/whisper v1.6.1/go.mod h1:lygchT4p9Y1/hR451OhNNqfinvy9EYEDxtXU2T/U30Q=
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=
@ -338,10 +511,13 @@ github.com/syndtr/goleveldb v0.0.0-20181128100959-b001fa50d6b2/go.mod h1:Z4AUp2K
github.com/syndtr/goleveldb v1.0.0 h1:fBdIW9lB4Iz0n9khmH8w27SJ3QEJ7+IgjPEwGSZiFdE=
github.com/syndtr/goleveldb v1.0.0/go.mod h1:ZVVdQEZoIme9iO1Ch2Jdy24qqXrMMOU6lpPAyBWyWuQ=
github.com/tidwall/pretty v0.0.0-20180105212114-65a9db5fad51/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk=
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/tyler-smith/go-bip39 v1.0.2 h1:+t3w+KwLXO6154GNJY+qUtIxLTmFjfUmpguQT1OlOT8=
github.com/tyler-smith/go-bip39 v1.0.2/go.mod h1:sJ5fKU0s6JVwZjjcUEX2zFOnvq0ASQ2K9Zr6cf67kNs=
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=
github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0=
github.com/vacp2p/mvds v0.0.23 h1:BKdn7tyGvl/J/Pwv6FlcW6Xbzm+17jv141GB1mFXyOU=
github.com/vacp2p/mvds v0.0.23/go.mod h1:uUmtiahU7efOVl/5w5yk9jOze5xYpDZDrSrT8TvHXjQ=
github.com/wealdtech/go-ens/v3 v3.0.9 h1:gXMBNXikJ/XV9k6ybPOZMXIMPjBGSCC9N10dxe8Y2Xk=
@ -350,15 +526,26 @@ github.com/wealdtech/go-multicodec v1.2.0 h1:9AHSxcSE9F9r6ZvQLAO0EXCdM08QfYohaXm
github.com/wealdtech/go-multicodec v1.2.0/go.mod h1:aedGMaTeYkIqi/KCPre1ho5rTb3hGpu/snBOS3GQLw4=
github.com/wealdtech/go-string2eth v1.0.0 h1:jY6b1MVqU6k2Uw/kvcU1Y9/3dDyXfPzZrOFspt82UJs=
github.com/wealdtech/go-string2eth v1.0.0/go.mod h1:UZA/snEybGcD6n+Pl+yoDjmexlEJ6dtoS9myfM83Ol4=
github.com/whyrusleeping/go-keyspace v0.0.0-20160322163242-5b898ac5add1/go.mod h1:8UvriyWtv5Q5EOgjHaSseUEdkQfvwFv1I/In/O2M9gc=
github.com/whyrusleeping/go-logging v0.0.0-20170515211332-0457bb6b88fc/go.mod h1:bopw91TMyo8J3tvftk8xmU2kPmlrt4nScJQZU2hE5EM=
github.com/whyrusleeping/go-notifier v0.0.0-20170827234753-097c5d47330f/go.mod h1:cZNvX9cFybI01GriPRMXDtczuvUhgbcYr9iCGaNlRv8=
github.com/whyrusleeping/mafmt v1.2.8/go.mod h1:faQJFPbLSxzD9xpA02ttW/tS9vZykNvXwGvqIpk20FA=
github.com/whyrusleeping/mdns v0.0.0-20180901202407-ef14215e6b30/go.mod h1:j4l84WPFclQPj320J9gp0XwNKBb3U0zt5CBqjPp22G4=
github.com/whyrusleeping/mdns v0.0.0-20190826153040-b9b60ed33aa9/go.mod h1:j4l84WPFclQPj320J9gp0XwNKBb3U0zt5CBqjPp22G4=
github.com/whyrusleeping/multiaddr-filter v0.0.0-20160516205228-e903e4adabd7/go.mod h1:X2c0RVCI1eSUFI8eLcY3c0423ykwiUdxLJtkDvruhjI=
github.com/wsddn/go-ecdh v0.0.0-20161211032359-48726bab9208 h1:1cngl9mPEoITZG8s8cVcUy5CeIBYhEESkOB7m6Gmkrk=
github.com/wsddn/go-ecdh v0.0.0-20161211032359-48726bab9208/go.mod h1:IotVbo4F+mw0EzQ08zFqg7pK3FebNXpaMsRy2RT+Ees=
github.com/x-cray/logrus-prefixed-formatter v0.5.2/go.mod h1:2duySbKsL6M18s5GU7VPsoEPHyzalCE06qoARUCeBBE=
github.com/xanzy/go-gitlab v0.15.0/go.mod h1:8zdQa/ri1dfn8eS3Ir1SyfvOKlw7WBJ8DVThkpGiXrs=
github.com/xdg/scram v0.0.0-20180814205039-7eeb5667e42c/go.mod h1:lB8K/P019DLNhemzwFU4jHLhdvlE6uDZjXFejJXr49I=
github.com/xdg/stringprep v1.0.0/go.mod h1:Jhud4/sHMO4oL310DaZAKk9ZaJ08SJfe+sJh0HrGL1Y=
github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q=
gitlab.com/nyarla/go-crypt v0.0.0-20160106005555-d9a5dc2b789b/go.mod h1:T3BPAOm2cqquPa0MKWeNkmOM5RQsRhkrwMWonFMN7fE=
go.mongodb.org/mongo-driver v1.1.0/go.mod h1:u7ryQJ+DOzQmeO7zB6MHyr8jkEQvC8vH7qLUO4lqsUM=
go.opencensus.io v0.20.1/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk=
go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
go.opencensus.io v0.22.1/go.mod h1:Ap50jQcDJrx6rB6VgeeFPtuPIf3wMRvRfrfYDO6+BmA=
go.uber.org/atomic v1.4.0 h1:cxzIVoETapQEqDhQu3QfnvXAV4AlzcvUCxkVUFw3+EU=
go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
go.uber.org/atomic v1.5.0 h1:OI5t8sDa1Or+q8AeE+yKeB/SDYioSHAgcVljj9JIETY=
go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ=
@ -373,11 +560,20 @@ go.uber.org/zap v1.13.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM=
golang.org/dl v0.0.0-20190829154251-82a15e2f2ead/go.mod h1:IUMfjQLJQd4UTqG1Z90tenwKoCX93Gn3MAQJMOSBsDQ=
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-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190103213133-ff983b9c42bc/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190211182817-74369b46fc67/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190225124518-7f87c0fbb88b/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-20190325154230-a5d413f7728c/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190426145343-a29dc8fdc734/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190513172903-22d7a77e9e5f/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190530122614-20be4c3c3ed5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190618222545-ea8f1a30c443/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190923035154-9ee001bba392/go.mod h1:/lpIB1dKB+9EgE3H3cr1v9wB50oz8l4C4h62xy7jSTY=
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=
@ -395,11 +591,13 @@ golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73r
golang.org/x/net v0.0.0-20181011144130-49bb7cea24b1/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181108082009-03003ca0c849/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-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190125091013-d26f9f9a57f3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190225153610-fe579d43d832/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190227160552-c95aed5357e7/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190424112056-4829fb13d2c6/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
@ -421,9 +619,12 @@ golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5h
golang.org/x/sys v0.0.0-20180926160741-c2ed4eda69e7/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-20181122145206-62eef0e2fa9b/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190102155601-82a175fd1598/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-20190219092855-153ac476189d/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190228124157-a34e9553db1e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190426135247-a129542de9ae h1:mQLHiymj/JXKnnjc62tb7nD5pZLs940/sXJu+Xp3DBA=
golang.org/x/sys v0.0.0-20190426135247-a129542de9ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@ -436,10 +637,13 @@ golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxb
golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20181130052023-1c3d964395ce/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
golang.org/x/tools v0.0.0-20190425222832-ad9eeb80039a/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
@ -455,6 +659,7 @@ google.golang.org/appengine v1.3.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
google.golang.org/genproto v0.0.0-20180831171423-11092d34479b/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
google.golang.org/genproto v0.0.0-20190404172233-64821d5d2107/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
@ -469,13 +674,20 @@ gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4=
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
gopkg.in/go-playground/assert.v1 v1.2.1/go.mod h1:9RXL0bg/zibRAgZUYszZSwO/z8Y/a8bDuhia5mkpMnE=
gopkg.in/go-playground/validator.v9 v9.29.1 h1:SvGtYmN60a5CVKTOzMSyfzWDeZRxRuGvRQyEAKbw1xc=
gopkg.in/go-playground/validator.v9 v9.29.1/go.mod h1:+c9/zcJMFNgbLvly1L1V+PpxWdVbfP1avr/N00E2vyQ=
gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
gopkg.in/natefinch/lumberjack.v2 v2.0.0 h1:1Lc07Kr7qY4U2YPouBjpCLxpiyxIVoxqXgkXLknAOE8=
gopkg.in/natefinch/lumberjack.v2 v2.0.0/go.mod h1:l0ndWWf7gzL7RNwBG7wST/UCcT4T24xpD6X8LsfU/+k=
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/olebedev/go-duktape.v3 v3.0.0-20190709231704-1e4459ed25ff h1:uuol9OUzSvZntY1v963NAbVd7A+PHLMz1FlCe3Lorcs=
gopkg.in/olebedev/go-duktape.v3 v3.0.0-20190709231704-1e4459ed25ff/go.mod h1:uAJfkITjFhyEEuUfm7bsmCZRbW5WRq8s9EY8HZ6hCns=
gopkg.in/sourcemap.v1 v1.0.5/go.mod h1:2RlvNNSMglmRrcvhfuzp4hQHwOtjxlbjX7UPY/GXb78=
gopkg.in/src-d/go-cli.v0 v0.0.0-20181105080154-d492247bbc0d/go.mod h1:z+K8VcOYVYcSwSjGebuDL6176A1XskgbtNl64NSg+n8=
gopkg.in/src-d/go-log.v1 v1.0.1/go.mod h1:GN34hKP0g305ysm2/hctJ0Y8nWP3zxXXJ8GFabTyABE=
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 h1:NdAVW6RYxDif9DhDHaAortIu956m2c0v+09AZBPTbE0=

View file

@ -183,8 +183,8 @@ func AssetNames() []string {
// _bindata is a table, holding each asset generator, mapped to its name.
var _bindata = map[string]func() (*asset, error){
"000001_init.down.db.sql": _000001_initDownDbSql,
"000001_init.up.db.sql": _000001_initUpDbSql,
"doc.go": docGo,
"000001_init.up.db.sql": _000001_initUpDbSql,
"doc.go": docGo,
}
// AssetDir returns the file names below a certain
@ -226,11 +226,10 @@ type bintree struct {
Func func() (*asset, error)
Children map[string]*bintree
}
var _bintree = &bintree{nil, map[string]*bintree{
"000001_init.down.db.sql": {_000001_initDownDbSql, map[string]*bintree{}},
"000001_init.up.db.sql": {_000001_initUpDbSql, map[string]*bintree{}},
"doc.go": {docGo, map[string]*bintree{}},
"000001_init.down.db.sql": &bintree{_000001_initDownDbSql, map[string]*bintree{}},
"000001_init.up.db.sql": &bintree{_000001_initUpDbSql, map[string]*bintree{}},
"doc.go": &bintree{docGo, map[string]*bintree{}},
}}
// RestoreAsset restores an asset under the given directory

View file

@ -1,72 +1,159 @@
package protocol
import (
"database/sql/driver"
"crypto/ecdsa"
"encoding/json"
"strings"
"unicode"
"unicode/utf8"
"github.com/pkg/errors"
"github.com/status-im/status-go/eth-node/types"
"github.com/gomarkdown/markdown"
"github.com/status-im/status-go/protocol/protobuf"
)
type hexutilSQL types.HexBytes
func (h hexutilSQL) Value() (driver.Value, error) {
return []byte(h), nil
}
func (h hexutilSQL) String() string {
return types.EncodeHex(h)
}
func (h *hexutilSQL) Scan(value interface{}) error {
if value == nil {
return nil
}
if b, ok := value.([]byte); ok {
*h = hexutilSQL(b)
return nil
}
return errors.New("failed to scan hexutilSQL")
}
// QuotedMessage contains the original text of the message replied to
type QuotedMessage struct {
// From is a public key of the author of the message.
From string `json:"from"`
Content string `json:"content"`
From string `json:"from"`
Text string `json:"text"`
}
const (
OutgoingStatusSending = "sending"
OutgoingStatusSent = "sent"
)
// Message represents a message record in the database,
// more specifically in user_messages_legacy table.
// Encoding and decoding of byte blobs should be performed
// using hexutil package.
type Message struct {
protobuf.ChatMessage
// ID calculated as keccak256(compressedAuthorPubKey, data) where data is unencrypted payload.
ID string `json:"id"`
// WhisperTimestamp is a timestamp of a Whisper envelope.
WhisperTimestamp int64 `json:"whisperTimestamp"`
WhisperTimestamp uint64 `json:"whisperTimestamp"`
// From is a public key of the author of the message.
From string `json:"from"`
// Random 3 words name
Alias string `json:"alias"`
// Identicon of the author
Identicon string `json:"identicon"`
// To is a public key of the recipient unless it's a public message then it's empty.
To hexutilSQL `json:"to,omitempty"`
// BEGIN: fields from types.Message.
Content string `json:"content"`
ContentType string `json:"contentType"`
Timestamp int64 `json:"timestamp"`
ChatID string `json:"chatId"`
MessageType string `json:"messageType,omitempty"`
MessageStatus string `json:"messageStatus,omitempty"`
ClockValue int64 `json:"clockValue"`
// END
Username string `json:"username,omitempty"`
// The chat id to be stored locally
LocalChatID string `json:"localChatId"`
RetryCount int `json:"retryCount"`
Show bool `json:"show"` // default true
Seen bool `json:"seen"`
OutgoingStatus string `json:"outgoingStatus,omitempty"`
// MessageID of the replied message
ReplyTo string `json:"replyTo"`
QuotedMessage *QuotedMessage `json:"quotedMessage"`
// Computed fields
RTL bool `json:"rtl"`
ParsedText []byte `json:"parsedText"`
LineCount int `json:"lineCount"`
SigPubKey *ecdsa.PublicKey `json:"-"`
// RawPayload is the marshaled payload, used for resending the message
RawPayload []byte `json:"-"`
}
func (m *Message) MarshalJSON() ([]byte, error) {
type MessageAlias Message
item := struct {
ID string `json:"id"`
WhisperTimestamp uint64 `json:"whisperTimestamp"`
From string `json:"from"`
Alias string `json:"alias"`
Identicon string `json:"identicon"`
RetryCount int `json:"retryCount"`
Seen bool `json:"seen"`
OutgoingStatus string `json:"outgoingStatus,omitempty"`
QuotedMessage *QuotedMessage `json:"quotedMessage"`
RTL bool `json:"rtl"`
ParsedText json.RawMessage `json:"parsedText"`
LineCount int `json:"lineCount"`
Text string `json:"text"`
ChatId string `json:"chatId"`
LocalChatID string `json:"localChatId"`
Clock uint64 `json:"clock"`
ResponseTo string `json:"responseTo"`
EnsName string `json:"ensName"`
Sticker *protobuf.StickerMessage `json:"sticker"`
Timestamp uint64 `json:"timestamp"`
ContentType protobuf.ChatMessage_ContentType `json:"contentType"`
MessageType protobuf.ChatMessage_MessageType `json:"messageType"`
}{
ID: m.ID,
WhisperTimestamp: m.WhisperTimestamp,
From: m.From,
Alias: m.Alias,
Identicon: m.Identicon,
RetryCount: m.RetryCount,
Seen: m.Seen,
OutgoingStatus: m.OutgoingStatus,
QuotedMessage: m.QuotedMessage,
RTL: m.RTL,
ParsedText: m.ParsedText,
LineCount: m.LineCount,
Text: m.Text,
ChatId: m.ChatId,
LocalChatID: m.LocalChatID,
Clock: m.Clock,
ResponseTo: m.ResponseTo,
EnsName: m.EnsName,
Timestamp: m.Timestamp,
ContentType: m.ContentType,
MessageType: m.MessageType,
Sticker: m.GetSticker(),
}
return json.Marshal(item)
}
func (m *Message) UnmarshalJSON(data []byte) error {
type Alias Message
aux := struct {
*Alias
ResponseTo string `json:"responseTo"`
EnsName string `json:"ensName"`
ChatID string `json:"chatId"`
Sticker *protobuf.StickerMessage `json:"sticker"`
ContentType protobuf.ChatMessage_ContentType `json:"contentType"`
}{
Alias: (*Alias)(m),
}
if err := json.Unmarshal(data, &aux); err != nil {
return err
}
if aux.ContentType == protobuf.ChatMessage_STICKER {
m.Payload = &protobuf.ChatMessage_Sticker{Sticker: aux.Sticker}
}
m.ResponseTo = aux.ResponseTo
m.EnsName = aux.EnsName
m.ChatId = aux.ChatID
m.ContentType = aux.ContentType
return nil
}
// Check if the first character is Hebrew or Arabic or the RTL character
func isRTL(s string) bool {
first, _ := utf8.DecodeRuneInString(s)
return unicode.Is(unicode.Hebrew, first) ||
unicode.Is(unicode.Arabic, first) ||
// RTL character
first == '\u200f'
}
// PrepareContent return the parsed content of the message, the line-count and whether
// is a right-to-left message
func (m *Message) PrepareContent() error {
parsedText := markdown.Parse([]byte(m.Text), nil)
jsonParsedText, err := json.Marshal(parsedText)
if err != nil {
return err
}
m.ParsedText = jsonParsedText
m.LineCount = strings.Count(m.Text, "\n")
m.RTL = isRTL(m.Text)
return nil
}

View file

@ -56,7 +56,7 @@ func (h *persistentMessageHandler) chatID(chatID string) (*Chat, error) {
return nil, err
}
for _, ch := range chats {
if chat.ID == chatID {
if ch.ID == chatID {
chat = ch
break
}

View file

@ -92,25 +92,6 @@ func (p *messageProcessor) Stop() {
p.datasync.Stop() // idempotent op
}
func (p *messageProcessor) SendPrivate(
ctx context.Context,
recipient *ecdsa.PublicKey,
chatID string,
data []byte,
clock int64,
) ([]byte, *v1protocol.Message, error) {
message := v1protocol.CreatePrivateTextMessage(data, clock, chatID)
encodedMessage, err := p.encodeMessage(message)
if err != nil {
return nil, nil, errors.Wrap(err, "failed to encode message")
}
messageID, err := p.sendPrivate(ctx, recipient, encodedMessage)
if err != nil {
return nil, nil, err
}
return messageID, &message, nil
}
// SendPrivateRaw takes encoded data, encrypts it and sends through the wire.
func (p *messageProcessor) SendPrivateRaw(
ctx context.Context,
@ -125,6 +106,34 @@ func (p *messageProcessor) SendPrivateRaw(
return p.sendPrivate(ctx, recipient, data)
}
// SendGroupRaw takes encoded data, encrypts it and sends through the wire,
// always return the messageID
func (p *messageProcessor) SendGroupRaw(
ctx context.Context,
recipients []*ecdsa.PublicKey,
data []byte,
) ([]byte, error) {
p.logger.Debug(
"sending a private group message",
zap.String("site", "SendGroupRaw"),
)
// Calculate messageID first
wrappedMessage, err := p.wrapMessageV1(data)
if err != nil {
return nil, errors.Wrap(err, "failed to wrap message")
}
messageID := v1protocol.MessageID(&p.identity.PublicKey, wrappedMessage)
for _, recipient := range recipients {
_, err = p.sendPrivate(ctx, recipient, data)
if err != nil {
return nil, errors.Wrap(err, "failed to send message")
}
}
return messageID, nil
}
// sendPrivate sends data to the recipient identifying with a given public key.
func (p *messageProcessor) sendPrivate(
ctx context.Context,
@ -133,7 +142,7 @@ func (p *messageProcessor) sendPrivate(
) ([]byte, error) {
p.logger.Debug("sending private message", zap.Binary("recipient", crypto.FromECDSAPub(recipient)))
wrappedMessage, err := p.tryWrapMessageV1(data)
wrappedMessage, err := p.wrapMessageV1(data)
if err != nil {
return nil, errors.Wrap(err, "failed to wrap message")
}
@ -164,32 +173,6 @@ func (p *messageProcessor) sendPrivate(
return messageID, nil
}
func (p *messageProcessor) SendGroup(
ctx context.Context,
recipients []*ecdsa.PublicKey,
chatID string,
data []byte,
clock int64,
) ([][]byte, []*v1protocol.Message, error) {
p.logger.Debug("sending a group message", zap.Int("membersCount", len(recipients)))
message := v1protocol.CreatePrivateGroupTextMessage(data, clock, chatID)
encodedMessage, err := p.encodeMessage(message)
if err != nil {
return nil, nil, errors.Wrap(err, "failed to encode message")
}
var resultIDs [][]byte
for _, recipient := range recipients {
messageID, err := p.sendPrivate(ctx, recipient, encodedMessage)
if err != nil {
return nil, nil, err
}
resultIDs = append(resultIDs, messageID)
}
return resultIDs, nil, nil
}
func (p *messageProcessor) SendMembershipUpdate(
ctx context.Context,
recipients []*ecdsa.PublicKey,
@ -219,46 +202,11 @@ func (p *messageProcessor) SendMembershipUpdate(
return resultIDs, nil
}
func (p *messageProcessor) SendPublic(ctx context.Context, chatID string, data []byte, clock int64) ([]byte, error) {
message := v1protocol.CreatePublicTextMessage(data, clock, chatID)
encodedMessage, err := p.encodeMessage(message)
if err != nil {
return nil, errors.Wrap(err, "failed to encode message")
}
wrappedMessage, err := p.tryWrapMessageV1(encodedMessage)
if err != nil {
return nil, errors.Wrap(err, "failed to wrap message")
}
messageSpec, err := p.protocol.BuildPublicMessage(p.identity, wrappedMessage)
if err != nil {
return nil, errors.Wrap(err, "failed to build public message")
}
newMessage, err := messageSpecToWhisper(messageSpec)
if err != nil {
return nil, err
}
hash, err := p.transport.SendPublic(ctx, newMessage, chatID)
if err != nil {
return nil, err
}
messageID := v1protocol.MessageID(&p.identity.PublicKey, wrappedMessage)
p.transport.Track([][]byte{messageID}, hash, newMessage)
return messageID, nil
}
// SendPublicRaw takes encoded data, encrypts it and sends through the wire.
func (p *messageProcessor) SendPublicRaw(ctx context.Context, chatName string, data []byte) ([]byte, error) {
var newMessage *types.NewMessage
wrappedMessage, err := p.tryWrapMessageV1(data)
wrappedMessage, err := p.wrapMessageV1(data)
if err != nil {
return nil, errors.Wrap(err, "failed to wrap message")
}
@ -282,61 +230,6 @@ func (p *messageProcessor) SendPublicRaw(ctx context.Context, chatName string, d
return messageID, nil
}
// Process processes received Whisper messages through all the layers
// and returns decoded user messages.
// It also handled all non-user messages like PairMessage.
func (p *messageProcessor) Process(shhMessage *types.Message) ([]*v1protocol.Message, error) {
logger := p.logger.With(zap.String("site", "Process"))
var decodedMessages []*v1protocol.Message
hlogger := logger.With(zap.Binary("hash", shhMessage.Hash))
hlogger.Debug("handling a received message")
statusMessages, err := p.handleMessages(shhMessage, true)
if err != nil {
return nil, err
}
for _, statusMessage := range statusMessages {
switch m := statusMessage.ParsedMessage.(type) {
case v1protocol.Message:
m.ID = statusMessage.ID
m.SigPubKey = statusMessage.SigPubKey()
decodedMessages = append(decodedMessages, &m)
case v1protocol.MembershipUpdateMessage:
// Handle user message that can be attached to the membership update.
userMessage := m.Message
if userMessage != nil {
userMessage.ID = statusMessage.ID
userMessage.SigPubKey = statusMessage.SigPubKey()
decodedMessages = append(decodedMessages, userMessage)
}
if err := p.processMembershipUpdate(m); err != nil {
hlogger.Error("failed to process MembershipUpdateMessage", zap.Error(err))
}
case v1protocol.PairMessage:
fromOurDevice := isPubKeyEqual(statusMessage.SigPubKey(), &p.identity.PublicKey)
if !fromOurDevice {
hlogger.Debug("received PairMessage from not our device, skipping")
break
}
if err := p.processPairMessage(m); err != nil {
hlogger.Error("failed to process PairMessage", zap.Error(err))
}
default:
hlogger.Error(
"skipped a public message of unsupported type",
zap.Any("value", statusMessage.ParsedMessage),
)
}
}
return decodedMessages, nil
}
func (p *messageProcessor) processMembershipUpdate(m v1protocol.MembershipUpdateMessage) error {
if err := m.Verify(); err != nil {
return err
@ -443,23 +336,12 @@ func (p *messageProcessor) handleErrDeviceNotFound(ctx context.Context, publicKe
return nil
}
func (p *messageProcessor) encodeMessage(message v1protocol.Message) ([]byte, error) {
encodedMessage, err := v1protocol.EncodeMessage(message)
func (p *messageProcessor) wrapMessageV1(encodedMessage []byte) ([]byte, error) {
wrappedMessage, err := v1protocol.WrapMessageV1(encodedMessage, p.identity)
if err != nil {
return nil, errors.Wrap(err, "failed to encode message")
return nil, errors.Wrap(err, "failed to wrap message")
}
return encodedMessage, nil
}
func (p *messageProcessor) tryWrapMessageV1(encodedMessage []byte) ([]byte, error) {
if p.featureFlags.sendV1Messages {
wrappedMessage, err := v1protocol.WrapMessageV1(encodedMessage, p.identity)
if err != nil {
return nil, errors.Wrap(err, "failed to wrap message")
}
return wrappedMessage, nil
}
return encodedMessage, nil
return wrappedMessage, nil
}
func (p *messageProcessor) addToDataSync(publicKey *ecdsa.PublicKey, message []byte) error {
@ -520,15 +402,9 @@ func (p *messageProcessor) sendMessageSpec(ctx context.Context, publicKey *ecdsa
case messageSpec.SharedSecret != nil:
logger.Debug("sending using shared secret")
hash, err = p.transport.SendPrivateWithSharedSecret(ctx, newMessage, publicKey, messageSpec.SharedSecret)
case messageSpec.PartitionedTopicMode() == encryption.PartitionTopicV1:
default:
logger.Debug("sending partitioned topic")
hash, err = p.transport.SendPrivateWithPartitioned(ctx, newMessage, publicKey)
case !p.featureFlags.genericDiscoveryTopicEnabled:
logger.Debug("sending partitioned topic (generic discovery topic disabled)")
hash, err = p.transport.SendPrivateWithPartitioned(ctx, newMessage, publicKey)
default:
logger.Debug("sending using discovery topic")
hash, err = p.transport.SendPrivateOnDiscovery(ctx, newMessage, publicKey)
}
if err != nil {
return nil, nil, err

View file

@ -17,6 +17,7 @@ import (
"github.com/status-im/status-go/protocol/encryption"
"github.com/status-im/status-go/protocol/encryption/multidevice"
"github.com/status-im/status-go/protocol/encryption/sharedsecret"
"github.com/status-im/status-go/protocol/protobuf"
"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"
@ -33,20 +34,19 @@ type MessageProcessorSuite struct {
processor *messageProcessor
tmpDir string
testMessage v1protocol.Message
testMessage Message
logger *zap.Logger
}
func (s *MessageProcessorSuite) SetupTest() {
s.testMessage = v1protocol.Message{
Text: "abc123",
ContentT: "text/plain",
MessageT: "public-group-user-message",
Clock: 154593077368201,
Timestamp: 1545930773682,
Content: v1protocol.Content{
ChatID: "testing-adamb",
Text: "abc123",
s.testMessage = Message{
ChatMessage: protobuf.ChatMessage{
Text: "abc123",
ChatId: "testing-adamb",
ContentType: protobuf.ChatMessage_TEXT_PLAIN,
MessageType: protobuf.ChatMessage_PUBLIC_GROUP,
Clock: 154593077368201,
Timestamp: 1545930773682,
},
}
@ -110,48 +110,6 @@ func (s *MessageProcessorSuite) TearDownTest() {
_ = s.logger.Sync()
}
func (s *MessageProcessorSuite) TestHandleDecodedMessagesSingle() {
privateKey, err := crypto.GenerateKey()
s.Require().NoError(err)
encodedPayload, err := v1protocol.EncodeMessage(s.testMessage)
s.Require().NoError(err)
message := &types.Message{}
message.Sig = crypto.FromECDSAPub(&privateKey.PublicKey)
message.Payload = encodedPayload
decodedMessages, err := s.processor.handleMessages(message, true)
s.Require().NoError(err)
s.Require().Equal(1, len(decodedMessages))
s.Require().Equal(encodedPayload, decodedMessages[0].DecryptedPayload)
s.Require().Equal(&privateKey.PublicKey, decodedMessages[0].SigPubKey())
s.Require().Equal(v1protocol.MessageID(&privateKey.PublicKey, encodedPayload), decodedMessages[0].ID)
s.Require().Equal(s.testMessage, decodedMessages[0].ParsedMessage)
s.Require().Equal(v1protocol.MessageT, decodedMessages[0].MessageType)
}
func (s *MessageProcessorSuite) TestHandleDecodedMessagesRaw() {
privateKey, err := crypto.GenerateKey()
s.Require().NoError(err)
encodedPayload, err := v1protocol.EncodeMessage(s.testMessage)
s.Require().NoError(err)
message := &types.Message{}
message.Sig = crypto.FromECDSAPub(&privateKey.PublicKey)
message.Payload = encodedPayload
decodedMessages, err := s.processor.handleMessages(message, false)
s.Require().NoError(err)
s.Require().Equal(1, len(decodedMessages))
s.Require().Equal(message, decodedMessages[0].TransportMessage)
s.Require().Equal(encodedPayload, decodedMessages[0].DecryptedPayload)
s.Require().Equal(&privateKey.PublicKey, decodedMessages[0].SigPubKey())
s.Require().Equal(v1protocol.MessageID(&privateKey.PublicKey, encodedPayload), decodedMessages[0].ID)
s.Require().Equal(nil, decodedMessages[0].ParsedMessage)
}
func (s *MessageProcessorSuite) TestHandleDecodedMessagesWrapped() {
relayerKey, err := crypto.GenerateKey()
s.Require().NoError(err)
@ -159,7 +117,7 @@ func (s *MessageProcessorSuite) TestHandleDecodedMessagesWrapped() {
authorKey, err := crypto.GenerateKey()
s.Require().NoError(err)
encodedPayload, err := v1protocol.EncodeMessage(s.testMessage)
encodedPayload, err := proto.Marshal(&s.testMessage)
s.Require().NoError(err)
wrappedPayload, err := v1protocol.WrapMessageV1(encodedPayload, authorKey)
@ -175,8 +133,9 @@ func (s *MessageProcessorSuite) TestHandleDecodedMessagesWrapped() {
s.Require().Equal(1, len(decodedMessages))
s.Require().Equal(&authorKey.PublicKey, decodedMessages[0].SigPubKey())
s.Require().Equal(v1protocol.MessageID(&authorKey.PublicKey, wrappedPayload), decodedMessages[0].ID)
parsedMessage := decodedMessages[0].ParsedMessage.(protobuf.ChatMessage)
s.Require().Equal(encodedPayload, decodedMessages[0].DecryptedPayload)
s.Require().Equal(s.testMessage, decodedMessages[0].ParsedMessage)
s.Require().True(proto.Equal(&s.testMessage.ChatMessage, &parsedMessage))
s.Require().Equal(v1protocol.MessageT, decodedMessages[0].MessageType)
}
@ -187,7 +146,7 @@ func (s *MessageProcessorSuite) TestHandleDecodedMessagesDatasync() {
authorKey, err := crypto.GenerateKey()
s.Require().NoError(err)
encodedPayload, err := v1protocol.EncodeMessage(s.testMessage)
encodedPayload, err := proto.Marshal(&s.testMessage)
s.Require().NoError(err)
wrappedPayload, err := v1protocol.WrapMessageV1(encodedPayload, authorKey)
@ -195,7 +154,6 @@ func (s *MessageProcessorSuite) TestHandleDecodedMessagesDatasync() {
dataSyncMessage := datasyncproto.Payload{
Messages: []*datasyncproto.Message{
{Body: encodedPayload},
{Body: wrappedPayload},
},
}
@ -209,18 +167,13 @@ func (s *MessageProcessorSuite) TestHandleDecodedMessagesDatasync() {
s.Require().NoError(err)
// We send two messages, the unwrapped one will be attributed to the relayer, while the wrapped one will be attributed to the author
s.Require().Equal(2, len(decodedMessages))
s.Require().Equal(&relayerKey.PublicKey, decodedMessages[0].SigPubKey())
s.Require().Equal(v1protocol.MessageID(&relayerKey.PublicKey, encodedPayload), decodedMessages[0].ID)
s.Require().Equal(1, len(decodedMessages))
s.Require().Equal(&authorKey.PublicKey, decodedMessages[0].SigPubKey())
s.Require().Equal(v1protocol.MessageID(&authorKey.PublicKey, wrappedPayload), decodedMessages[0].ID)
s.Require().Equal(encodedPayload, decodedMessages[0].DecryptedPayload)
s.Require().Equal(s.testMessage, decodedMessages[0].ParsedMessage)
parsedMessage := decodedMessages[0].ParsedMessage.(protobuf.ChatMessage)
s.Require().True(proto.Equal(&s.testMessage.ChatMessage, &parsedMessage))
s.Require().Equal(v1protocol.MessageT, decodedMessages[0].MessageType)
s.Require().Equal(&authorKey.PublicKey, decodedMessages[1].SigPubKey())
s.Require().Equal(v1protocol.MessageID(&authorKey.PublicKey, wrappedPayload), decodedMessages[1].ID)
s.Require().Equal(encodedPayload, decodedMessages[1].DecryptedPayload)
s.Require().Equal(s.testMessage, decodedMessages[1].ParsedMessage)
s.Require().Equal(v1protocol.MessageT, decodedMessages[1].MessageType)
}
func (s *MessageProcessorSuite) TestHandleDecodedMessagesDatasyncEncrypted() {
@ -230,7 +183,7 @@ func (s *MessageProcessorSuite) TestHandleDecodedMessagesDatasyncEncrypted() {
authorKey, err := crypto.GenerateKey()
s.Require().NoError(err)
encodedPayload, err := v1protocol.EncodeMessage(s.testMessage)
encodedPayload, err := proto.Marshal(&s.testMessage)
s.Require().NoError(err)
wrappedPayload, err := v1protocol.WrapMessageV1(encodedPayload, authorKey)
@ -238,8 +191,7 @@ func (s *MessageProcessorSuite) TestHandleDecodedMessagesDatasyncEncrypted() {
dataSyncMessage := datasyncproto.Payload{
Messages: []*datasyncproto.Message{
{Body: encodedPayload},
{Body: wrappedPayload},
&datasyncproto.Message{Body: wrappedPayload},
},
}
marshalledDataSyncMessage, err := proto.Marshal(&dataSyncMessage)
@ -276,16 +228,11 @@ func (s *MessageProcessorSuite) TestHandleDecodedMessagesDatasyncEncrypted() {
// We send two messages, the unwrapped one will be attributed to the relayer,
// while the wrapped one will be attributed to the author.
s.Require().Equal(2, len(decodedMessages))
s.Require().Equal(&relayerKey.PublicKey, decodedMessages[0].SigPubKey())
s.Require().Equal(v1protocol.MessageID(&relayerKey.PublicKey, encodedPayload), decodedMessages[0].ID)
s.Require().Equal(1, len(decodedMessages))
s.Require().Equal(&authorKey.PublicKey, decodedMessages[0].SigPubKey())
s.Require().Equal(v1protocol.MessageID(&authorKey.PublicKey, wrappedPayload), decodedMessages[0].ID)
s.Require().Equal(encodedPayload, decodedMessages[0].DecryptedPayload)
s.Require().Equal(s.testMessage, decodedMessages[0].ParsedMessage)
parsedMessage := decodedMessages[0].ParsedMessage.(protobuf.ChatMessage)
s.Require().True(proto.Equal(&s.testMessage.ChatMessage, &parsedMessage))
s.Require().Equal(v1protocol.MessageT, decodedMessages[0].MessageType)
s.Require().Equal(&authorKey.PublicKey, decodedMessages[1].SigPubKey())
s.Require().Equal(v1protocol.MessageID(&authorKey.PublicKey, wrappedPayload), decodedMessages[1].ID)
s.Require().Equal(encodedPayload, decodedMessages[1].DecryptedPayload)
s.Require().Equal(s.testMessage, decodedMessages[1].ParsedMessage)
s.Require().Equal(v1protocol.MessageT, decodedMessages[1].MessageType)
}

View file

@ -4,12 +4,15 @@ import (
"context"
"crypto/ecdsa"
"database/sql"
"strings"
"encoding/hex"
"encoding/json"
"strconv"
"time"
"github.com/pkg/errors"
"go.uber.org/zap"
"github.com/golang/protobuf/proto"
"github.com/status-im/status-go/eth-node/crypto"
"github.com/status-im/status-go/eth-node/types"
enstypes "github.com/status-im/status-go/eth-node/types/ens"
@ -18,11 +21,14 @@ import (
"github.com/status-im/status-go/protocol/encryption/sharedsecret"
"github.com/status-im/status-go/protocol/identity/alias"
"github.com/status-im/status-go/protocol/identity/identicon"
"github.com/status-im/status-go/protocol/protobuf"
"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"
)
const PubKeyStringLength = 132
var (
ErrChatIDEmpty = errors.New("chat ID is empty")
ErrNotImplemented = errors.New("not implemented")
@ -46,20 +52,29 @@ type Messenger struct {
processor *messageProcessor
logger *zap.Logger
ownMessages []*v1protocol.Message
featureFlags featureFlags
messagesPersistenceEnabled bool
shutdownTasks []func() error
}
type featureFlags struct {
genericDiscoveryTopicEnabled bool
// sendV1Messages indicates whether we should send
// messages compatible only with V1 and later.
// V1 messages adds additional wrapping
// which contains a signature and payload.
sendV1Messages bool
type RawResponse struct {
Filter *transport.Filter `json:"filter"`
Messages []*v1protocol.StatusMessage `json:"messages"`
}
type MessengerResponse struct {
Chats []*Chat `json:"chats,omitEmpty"`
Messages []*Message `json:"messages,omitEmpty"`
Contacts []*Contact `json:"contacts,omitEmpty"`
// Raw unprocessed messages
RawMessages []*RawResponse `json:"rawMessages,omitEmpty"`
}
func (m *MessengerResponse) IsEmpty() bool {
return len(m.Chats) == 0 && len(m.Messages) == 0 && len(m.Contacts) == 0 && len(m.RawMessages) == 0
}
type featureFlags struct {
// datasync indicates whether direct messages should be sent exclusively
// using datasync, breaking change for non-v1 clients. Public messages
// are not impacted
@ -117,13 +132,6 @@ func WithCustomLogger(logger *zap.Logger) Option {
}
}
func WithGenericDiscoveryTopicSupport() Option {
return func(c *config) error {
c.featureFlags.genericDiscoveryTopicEnabled = true
return nil
}
}
func WithMessagesPersistenceEnabled() Option {
return func(c *config) error {
c.messagesPersistenceEnabled = true
@ -145,13 +153,6 @@ func WithDatabase(db *sql.DB) Option {
}
}
func WithSendV1Messages() Option {
return func(c *config) error {
c.featureFlags.sendV1Messages = true
return nil
}
}
func WithDatasync() func(c *config) error {
return func(c *config) error {
c.featureFlags.datasync = true
@ -267,7 +268,6 @@ func NewMessenger(
nil,
c.envelopesMonitorConfig,
logger,
transport.SetGenericDiscoveryTopicSupport(c.featureFlags.genericDiscoveryTopicEnabled),
)
if err != nil {
return nil, errors.Wrap(err, "failed to create a WhisperServiceTransport")
@ -624,47 +624,58 @@ func (m *Messenger) Contacts() ([]*Contact, error) {
return m.persistence.Contacts()
}
func (m *Messenger) Send(ctx context.Context, chatID string, data []byte) ([][]byte, error) {
logger := m.logger.With(zap.String("site", "Send"), zap.String("chatID", chatID))
func timestampInMs() uint64 {
return uint64(time.Now().UnixNano() / int64(time.Millisecond))
}
// A valid added chat is required.
chat, err := m.chatByID(chatID)
// ReSendChatMessage pulls a message from the database and sends it again
func (m *Messenger) ReSendChatMessage(ctx context.Context, messageID string) (*MessengerResponse, error) {
logger := m.logger.With(zap.String("site", "ReSendChatMessage"))
var response MessengerResponse
message, err := m.persistence.MessageByID(messageID)
if err != nil {
return nil, err
}
if message == nil {
return nil, errors.New("message not found")
}
if message.RawPayload == nil {
return nil, errors.New("message payload not found, can't resend message")
}
clock, err := m.persistence.LastMessageClock(chat.ID)
chat, err := m.chatByID(message.LocalChatID)
if err != nil {
return nil, err
}
logger.Debug("last message clock received", zap.Int64("clock", clock))
switch chat.ChatType {
case ChatTypeOneToOne:
logger.Debug("sending private message", zap.Binary("publicKey", crypto.FromECDSAPub(chat.PublicKey)))
id, message, err := m.processor.SendPrivate(ctx, chat.PublicKey, chat.ID, data, clock)
publicKey := crypto.FromECDSAPub(chat.PublicKey)
logger.Debug("re-sending private message", zap.Binary("publicKey", publicKey))
id, err := m.processor.SendPrivateRaw(ctx, chat.PublicKey, message.RawPayload)
if err != nil {
return nil, err
}
if err := m.cacheOwnMessage(chatID, id, message); err != nil {
message.ID = "0x" + hex.EncodeToString(id)
err = m.sendToPairedDevices(ctx, message.RawPayload)
if err != nil {
return nil, err
}
return [][]byte{id}, nil
case ChatTypePublic:
logger.Debug("sending public message", zap.String("chatName", chat.Name))
id, err := m.processor.SendPublic(ctx, chat.ID, data, clock)
logger.Debug("re-sending public message", zap.String("chatName", chat.Name))
id, err := m.processor.SendPublicRaw(ctx, chat.ID, message.RawPayload)
if err != nil {
return nil, err
}
return [][]byte{id}, nil
message.ID = "0x" + hex.EncodeToString(id)
case ChatTypePrivateGroupChat:
logger.Debug("sending group message", zap.String("chatName", chat.Name))
logger.Debug("re-sending group message", zap.String("chatName", chat.Name))
recipients, err := chat.MembersAsPublicKeys()
if err != nil {
return nil, err
}
// Filter me out of recipients.
n := 0
for _, item := range recipients {
if !isPubKeyEqual(item, &m.identity.PublicKey) {
@ -672,40 +683,186 @@ func (m *Messenger) Send(ctx context.Context, chatID string, data []byte) ([][]b
n++
}
}
ids, messages, err := m.processor.SendGroup(ctx, recipients[:n], chat.ID, data, clock)
id, err := m.processor.SendGroupRaw(ctx, recipients[:n], message.RawPayload)
if err != nil {
return nil, err
}
for idx, message := range messages {
if err := m.cacheOwnMessage(chatID, ids[idx], message); err != nil {
return nil, err
}
message.ID = "0x" + hex.EncodeToString(id)
err = m.sendToPairedDevices(ctx, message.RawPayload)
if err != nil {
return nil, err
}
return ids, nil
default:
return nil, errors.New("chat is neither public nor private")
return nil, errors.New("chat type not supported")
}
response.Messages = []*Message{message}
response.Chats = []*Chat{chat}
return &response, nil
}
func (m *Messenger) cacheOwnMessage(chatID string, id []byte, message *v1protocol.Message) error {
// Save our message because it won't be received from the transport layer.
message.ID = id // a Message need ID to be properly stored in the db
message.SigPubKey = &m.identity.PublicKey
message.ChatID = chatID
if m.messagesPersistenceEnabled {
_, err := m.persistence.SaveMessages([]*v1protocol.Message{message})
// sendToPairedDevices will check if we have any paired devices and send to them if necessary
func (m *Messenger) sendToPairedDevices(ctx context.Context, payload []byte) error {
activeInstallations, err := m.encryptor.GetOurActiveInstallations(&m.identity.PublicKey)
if err != nil {
return err
}
// We send a message to any paired device
if len(activeInstallations) > 1 {
_, err := m.processor.SendPrivateRaw(ctx, &m.identity.PublicKey, payload)
if err != nil {
return err
}
}
// Cache it to be returned in Retrieve().
m.ownMessages = append(m.ownMessages, message)
return nil
}
// SendChatMessage takes a minimal message and sends it based on the corresponding chat
func (m *Messenger) SendChatMessage(ctx context.Context, message *Message) (*MessengerResponse, error) {
logger := m.logger.With(zap.String("site", "Send"), zap.String("chatID", message.ChatId))
var response MessengerResponse
// A valid added chat is required.
chat, err := m.chatByID(message.ChatId)
if err != nil {
return nil, err
}
clock := chat.LastClockValue
timestamp := timestampInMs()
if clock == 0 || clock < timestamp {
clock = timestamp
} else {
clock = clock + 1
}
message.LocalChatID = chat.ID
message.Clock = clock
message.Timestamp = timestamp
message.From = "0x" + hex.EncodeToString(crypto.FromECDSAPub(&m.identity.PublicKey))
message.SigPubKey = &m.identity.PublicKey
message.WhisperTimestamp = timestamp
message.Seen = true
message.OutgoingStatus = OutgoingStatusSending
identicon, err := identicon.GenerateBase64(message.From)
if err != nil {
return nil, err
}
message.Identicon = identicon
alias, err := alias.GenerateFromPublicKeyString(message.From)
if err != nil {
return nil, err
}
message.Alias = alias
switch chat.ChatType {
case ChatTypeOneToOne:
publicKey := crypto.FromECDSAPub(chat.PublicKey)
logger.Debug("sending private message", zap.Binary("publicKey", publicKey))
message.MessageType = protobuf.ChatMessage_ONE_TO_ONE
encodedMessage, err := proto.Marshal(message)
if err != nil {
return nil, err
}
message.RawPayload = encodedMessage
id, err := m.processor.SendPrivateRaw(ctx, chat.PublicKey, encodedMessage)
if err != nil {
return nil, err
}
message.ID = "0x" + hex.EncodeToString(id)
err = m.sendToPairedDevices(ctx, encodedMessage)
if err != nil {
return nil, err
}
case ChatTypePublic:
logger.Debug("sending public message", zap.String("chatName", chat.Name))
message.MessageType = protobuf.ChatMessage_PUBLIC_GROUP
encodedMessage, err := proto.Marshal(message)
if err != nil {
return nil, err
}
message.RawPayload = encodedMessage
id, err := m.processor.SendPublicRaw(ctx, chat.ID, encodedMessage)
if err != nil {
return nil, err
}
message.ID = "0x" + hex.EncodeToString(id)
case ChatTypePrivateGroupChat:
logger.Debug("sending public message", zap.String("chatName", chat.Name))
message.MessageType = protobuf.ChatMessage_PRIVATE_GROUP
encodedMessage, err := proto.Marshal(message)
if err != nil {
return nil, err
}
message.RawPayload = encodedMessage
logger.Debug("sending group message", zap.String("chatName", chat.Name))
recipients, err := chat.MembersAsPublicKeys()
if err != nil {
return nil, err
}
n := 0
for _, item := range recipients {
if !isPubKeyEqual(item, &m.identity.PublicKey) {
recipients[n] = item
n++
}
}
id, err := m.processor.SendGroupRaw(ctx, recipients[:n], encodedMessage)
if err != nil {
return nil, err
}
message.ID = "0x" + hex.EncodeToString(id)
err = m.sendToPairedDevices(ctx, encodedMessage)
if err != nil {
return nil, err
}
default:
return nil, errors.New("chat type not supported")
}
err = message.PrepareContent()
if err != nil {
return nil, err
}
jsonMessage, err := json.Marshal(message)
if err != nil {
return nil, err
}
chat.LastClockValue = clock
chat.LastMessage = jsonMessage
chat.Timestamp = int64(timestamp)
if err := m.SaveChat(*chat); err != nil {
return nil, err
}
err = m.persistence.SaveMessagesLegacy([]*Message{message})
if err != nil {
return nil, err
}
response.Chats = []*Chat{chat}
response.Messages = []*Message{message}
return &response, nil
}
// SendRaw takes encoded data, encrypts it and sends through the wire.
// DEPRECATED
func (m *Messenger) SendRaw(ctx context.Context, chat Chat, data []byte) ([]byte, error) {
@ -717,94 +874,48 @@ func (m *Messenger) SendRaw(ctx context.Context, chat Chat, data []byte) ([]byte
return nil, errors.New("chat is neither public nor private")
}
type RetrieveConfig struct {
From time.Time
To time.Time
latest bool
last24Hours bool
}
var (
RetrieveLatest = RetrieveConfig{latest: true}
RetrieveLastDay = RetrieveConfig{latest: true, last24Hours: true}
)
// RetrieveAll retrieves all previously fetched messages
func (m *Messenger) RetrieveAll(ctx context.Context, c RetrieveConfig) ([]*v1protocol.Message, error) {
result, err := m.retrieveLatest(ctx)
if err != nil {
return nil, err
}
postProcess := newPostProcessor(m, postProcessorConfig{
MatchChat: true,
Persist: true,
})
result, err = postProcess.Run(result)
if err != nil {
return nil, errors.Wrap(err, "failed to post process messages")
}
retrievedMessages, err := m.retrieveSaved(ctx, c)
if err != nil {
return nil, errors.Wrap(err, "failed to get saved messages")
}
result = append(result, retrievedMessages...)
// Include own messages.
result = append(result, m.ownMessages...)
m.ownMessages = nil
return result, nil
}
func (m *Messenger) retrieveLatest(ctx context.Context) ([]*v1protocol.Message, error) {
latest, err := m.transport.RetrieveAllMessages()
if err != nil {
return nil, errors.Wrap(err, "failed to retrieve messages")
}
logger := m.logger.With(zap.String("site", "retrieveLatest"))
logger.Debug("retrieved messages", zap.Int("count", len(latest)))
var result []*v1protocol.Message
for _, transpMessage := range latest {
protoMessages, err := m.processor.Process(transpMessage.Message)
if err != nil {
return nil, err
}
result = append(result, protoMessages...)
}
return result, nil
}
func (m *Messenger) retrieveSaved(ctx context.Context, c RetrieveConfig) (messages []*v1protocol.Message, err error) {
if !m.messagesPersistenceEnabled {
return nil, nil
}
if !c.latest {
return m.persistence.Messages(c.From, c.To)
}
if c.last24Hours {
to := time.Now()
from := to.Add(-time.Hour * 24)
return m.persistence.Messages(from, to)
}
return nil, nil
}
// DEPRECATED
func (m *Messenger) RetrieveRawAll() (map[transport.Filter][]*v1protocol.StatusMessage, error) {
// RetrieveAll retrieves messages from all filters, processes them and returns a
// MessengerResponse to the client
func (m *Messenger) RetrieveAll() (*MessengerResponse, error) {
chatWithMessages, err := m.transport.RetrieveRawAll()
if err != nil {
return nil, err
}
logger := m.logger.With(zap.String("site", "RetrieveRawAll"))
result := make(map[transport.Filter][]*v1protocol.StatusMessage)
return m.handleRetrievedMessages(chatWithMessages)
}
func (m *Messenger) handleRetrievedMessages(chatWithMessages map[transport.Filter][]*types.Message) (*MessengerResponse, error) {
response := &MessengerResponse{
Chats: []*Chat{},
Messages: []*Message{},
}
allChats, err := m.persistence.Chats()
if err != nil {
return nil, err
}
postProcessor := newPostProcessor(m, postProcessorConfig{MatchChat: true})
logger := m.logger.With(zap.String("site", "RetrieveAll"))
rawMessages := make(map[transport.Filter][]*v1protocol.StatusMessage)
// We should query this instead
contacts, err := m.Contacts()
if err != nil {
return nil, err
}
blockedContacts := make(map[string]bool)
for _, c := range contacts {
if c.IsBlocked() {
blockedContacts[c.ID] = true
}
}
allContactsMap := make(map[string]*Contact)
allChatsMap := make(map[string]*Chat)
existingMessagesMap := make(map[string]bool)
for chat, messages := range chatWithMessages {
for _, shhMessage := range messages {
@ -816,48 +927,130 @@ func (m *Messenger) RetrieveRawAll() (map[transport.Filter][]*v1protocol.StatusM
}
for _, msg := range statusMessages {
if msg.ParsedMessage != nil {
if textMessage, ok := msg.ParsedMessage.(v1protocol.Message); ok {
textMessage.Content = v1protocol.PrepareContent(textMessage.Content)
msg.ParsedMessage = textMessage
// Check for messages from blocked users
senderID := "0x" + hex.EncodeToString(crypto.FromECDSAPub(msg.SigPubKey()))
if blockedContacts[senderID] {
continue
}
// Don't process duplicates
messageID := "0x" + hex.EncodeToString(msg.ID)
if _, ok := existingMessagesMap[messageID]; ok {
continue
}
existingMessagesMap[messageID] = true
// Check against the database, this is probably a bit slow for
// each message, but for now might do, we'll make it faster later
existingMessage, err := m.persistence.MessageByID(messageID)
if err != nil && err != errRecordNotFound {
return nil, err
}
if existingMessage != nil {
continue
}
publicKey := msg.SigPubKey()
if publicKey == nil {
return nil, errors.New("public key can't be nil")
}
var contact *Contact
if c, ok := allContactsMap[senderID]; ok {
contact = c
} else {
c, err := buildContact(publicKey)
if err != nil {
logger.Info("failed to build contact", zap.Error(err))
continue
}
contact = c
allContactsMap[senderID] = c
response.Contacts = append(response.Contacts, c)
}
if msg.ParsedMessage != nil {
if textMessage, ok := msg.ParsedMessage.(protobuf.ChatMessage); ok {
receivedMessage := &Message{
ID: messageID,
ChatMessage: textMessage,
From: contact.ID,
Alias: contact.Alias,
SigPubKey: publicKey,
Identicon: contact.Identicon,
WhisperTimestamp: uint64(msg.TransportMessage.Timestamp) * 1000,
}
receivedMessage.PrepareContent()
chat, err := postProcessor.matchMessage(receivedMessage, allChats)
if err != nil {
logger.Warn("failed to match message", zap.String("receivedChatID", receivedMessage.ChatId), zap.Error(err))
continue
}
// If deleted-at is greater, ignore message
if chat.DeletedAtClockValue >= receivedMessage.Clock {
continue
}
// Set the LocalChatID for the message
receivedMessage.LocalChatID = chat.ID
if c, ok := allChatsMap[chat.ID]; ok {
chat = c
}
// Increase unviewed count
if !isPubKeyEqual(receivedMessage.SigPubKey, &m.identity.PublicKey) {
chat.UnviewedMessagesCount++
} else {
// Our own message, mark as sent
receivedMessage.OutgoingStatus = OutgoingStatusSent
}
// Update chat timestamp
chat.Timestamp = int64(timestampInMs())
// Update last clock value
if chat.LastClockValue <= receivedMessage.Clock {
chat.LastClockValue = receivedMessage.Clock
encodedLastMessage, err := json.Marshal(receivedMessage)
if err != nil {
return nil, err
}
chat.LastMessage = encodedLastMessage
}
// Set chat active
chat.Active = true
// Set in the map
allChatsMap[chat.ID] = chat
// Add to response
response.Messages = append(response.Messages, receivedMessage)
}
} else {
// RawMessage, not processed here, pass straight to the client
rawMessages[chat] = append(rawMessages[chat], msg)
}
}
result[chat] = append(result[chat], statusMessages...)
}
}
err = m.updateContactsFromMessages(result)
err = m.persistence.SetContactsGeneratedData(response.Contacts, nil)
if err != nil {
return nil, err
}
return result, nil
}
func (m *Messenger) updateContactsFromMessages(messages map[transport.Filter][]*v1protocol.StatusMessage) error {
allContactsMap := make(map[string]bool)
var allContacts []Contact
for _, chatMessages := range messages {
for _, message := range chatMessages {
publicKey := message.SigPubKey()
address := strings.ToLower(crypto.PubkeyToAddress(*publicKey).Hex())
if _, ok := allContactsMap[address]; ok {
continue
}
contact, err := buildContact(publicKey)
if err != nil {
continue
}
allContactsMap[address] = true
allContacts = append(allContacts, *contact)
}
for _, c := range allChatsMap {
response.Chats = append(response.Chats, c)
}
return m.persistence.SetContactsGeneratedData(allContacts, nil)
m.persistence.SaveChats(response.Chats)
m.SaveMessages(response.Messages)
for filter, messages := range rawMessages {
response.RawMessages = append(response.RawMessages, &RawResponse{Filter: &filter, Messages: messages})
}
return response, nil
}
func (m *Messenger) RequestHistoricMessages(
@ -909,6 +1102,47 @@ func (m *Messenger) SaveMessages(messages []*Message) error {
return m.persistence.SaveMessagesLegacy(messages)
}
// AddSystemMessages format an array of system-messages and saves them to the database
// It's needed until group chats are fully in status-go.
func (m *Messenger) AddSystemMessages(messages []*Message) ([]*Message, error) {
timestamp := timestampInMs()
for _, message := range messages {
message.LocalChatID = message.ChatId
message.Timestamp = timestamp
message.WhisperTimestamp = timestamp
message.Seen = true
identicon, err := identicon.GenerateBase64(message.From)
if err != nil {
return nil, err
}
message.Identicon = identicon
alias, err := alias.GenerateFromPublicKeyString(message.From)
if err != nil {
return nil, err
}
message.ID = "0x" + hex.EncodeToString(crypto.Keccak256([]byte(message.Text+message.From+strconv.FormatUint(message.Clock, 10))))
message.Alias = alias
message.ContentType = protobuf.ChatMessage_STATUS
message.MessageType = protobuf.ChatMessage_SYSTEM_MESSAGE_PRIVATE_GROUP
err = message.PrepareContent()
if err != nil {
return nil, err
}
}
err := m.SaveMessages(messages)
if err != nil {
return nil, err
}
return messages, nil
}
// DEPRECATED: required by status-react.
func (m *Messenger) DeleteMessage(id string) error {
return m.persistence.DeleteMessage(id)
@ -920,8 +1154,8 @@ func (m *Messenger) DeleteMessagesByChatID(id string) error {
}
// DEPRECATED: required by status-react.
func (m *Messenger) MarkMessagesSeen(ids ...string) error {
return m.persistence.MarkMessagesSeen(ids...)
func (m *Messenger) MarkMessagesSeen(chatID string, ids []string) error {
return m.persistence.MarkMessagesSeen(chatID, ids)
}
// DEPRECATED: required by status-react.
@ -955,100 +1189,68 @@ func newPostProcessor(m *Messenger, config postProcessorConfig) *postProcessor {
}
}
func (p *postProcessor) Run(messages []*v1protocol.Message) ([]*v1protocol.Message, error) {
var err error
p.logger.Debug("running post processor", zap.Int("messages", len(messages)))
var fns []func([]*v1protocol.Message) ([]*v1protocol.Message, error)
// Order is important. Persisting messages should be always at the end.
if p.config.MatchChat {
fns = append(fns, p.matchMessages)
}
if p.config.Parse {
fns = append(fns, p.parseMessages)
}
if p.config.Persist {
fns = append(fns, p.saveMessages)
}
for _, fn := range fns {
messages, err = fn(messages)
if err != nil {
return nil, err
}
}
return messages, nil
}
func (p *postProcessor) saveMessages(messages []*v1protocol.Message) ([]*v1protocol.Message, error) {
_, err := p.persistence.SaveMessages(messages)
if err != nil {
return nil, err
}
return messages, nil
}
func (p *postProcessor) parseMessages(messages []*v1protocol.Message) ([]*v1protocol.Message, error) {
for _, m := range messages {
m.Content = v1protocol.PrepareContent(m.Content)
}
return messages, nil
}
func (p *postProcessor) matchMessages(messages []*v1protocol.Message) ([]*v1protocol.Message, error) {
func (p *postProcessor) matchMessages(messages []*Message) ([]*Message, error) {
chats, err := p.persistence.Chats()
if err != nil {
return nil, err
}
result := make([]*v1protocol.Message, 0, len(messages))
result := make([]*Message, 0, len(messages))
for _, message := range messages {
chat, err := p.matchMessage(message, chats)
if err != nil {
p.logger.Error("failed to match a chat to a message", zap.Error(err))
continue
}
message.ChatID = chat.ID
message.LocalChatID = chat.ID
result = append(result, message)
}
return result, nil
}
func (p *postProcessor) matchMessage(message *v1protocol.Message, chats []*Chat) (*Chat, error) {
func (p *postProcessor) matchMessage(message *Message, chats []*Chat) (*Chat, error) {
if message.SigPubKey == nil {
p.logger.Error("public key can't be empty")
return nil, errors.New("received a message with empty public key")
}
switch {
case message.MessageT == v1protocol.MessageTypePublicGroup:
case message.MessageType == protobuf.ChatMessage_PUBLIC_GROUP:
// For public messages, all outgoing and incoming messages have the same chatID
// equal to a public chat name.
chatID := message.Content.ChatID
chatID := message.ChatId
chat := findChatByID(chatID, chats)
if chat == nil {
return nil, errors.New("received a public message from non-existing chat")
}
return chat, nil
case message.MessageT == v1protocol.MessageTypePrivate && isPubKeyEqual(message.SigPubKey, p.myPublicKey):
// It's a private message coming from us so we rely on Message.Content.ChatID.
case message.MessageType == protobuf.ChatMessage_ONE_TO_ONE && isPubKeyEqual(message.SigPubKey, p.myPublicKey):
// It's a private message coming from us so we rely on Message.ChatId
// If chat does not exist, it should be created to support multidevice synchronization.
chatID := message.Content.ChatID
chatID := message.ChatId
chat := findChatByID(chatID, chats)
if chat == nil {
// TODO: this should be a three-word name used in the mobile client
newChat := CreateOneToOneChat(chatID[:8], message.SigPubKey)
if len(chatID) != PubKeyStringLength {
return nil, errors.New("invalid pubkey length")
}
bytePubKey, err := hex.DecodeString(chatID[2:])
if err != nil {
return nil, errors.Wrap(err, "failed to decode hex chatID")
}
pubKey, err := crypto.UnmarshalPubkey(bytePubKey)
if err != nil {
return nil, errors.Wrap(err, "failed to decode pubkey")
}
newChat := CreateOneToOneChat(chatID[:8], pubKey)
if err := p.persistence.SaveChat(newChat); err != nil {
return nil, errors.Wrap(err, "failed to save newly created chat")
}
chat = &newChat
}
return chat, nil
case message.MessageT == v1protocol.MessageTypePrivate:
case message.MessageType == protobuf.ChatMessage_ONE_TO_ONE:
// It's an incoming private message. ChatID is calculated from the signature.
// If a chat does not exist, a new one is created and saved.
chatID := types.EncodeHex(crypto.FromECDSAPub(message.SigPubKey))
@ -1062,21 +1264,34 @@ func (p *postProcessor) matchMessage(message *v1protocol.Message, chats []*Chat)
chat = &newChat
}
return chat, nil
case message.MessageT == v1protocol.MessageTypePrivateGroup:
case message.MessageType == protobuf.ChatMessage_PRIVATE_GROUP:
// In the case of a group message, ChatID is the same for all messages belonging to a group.
// It needs to be verified if the signature public key belongs to the chat.
chatID := message.Content.ChatID
chatID := message.ChatId
chat := findChatByID(chatID, chats)
if chat == nil {
return nil, errors.New("received group chat message for non-existing chat")
}
sigPubKeyHex := types.EncodeHex(crypto.FromECDSAPub(message.SigPubKey))
theirKeyHex := types.EncodeHex(crypto.FromECDSAPub(message.SigPubKey))
myKeyHex := types.EncodeHex(crypto.FromECDSAPub(p.myPublicKey))
var theyJoined bool
var iJoined bool
for _, member := range chat.Members {
if member.ID == sigPubKeyHex {
return chat, nil
if member.ID == theirKeyHex && member.Joined {
theyJoined = true
}
}
for _, member := range chat.Members {
if member.ID == myKeyHex && member.Joined {
iJoined = true
}
}
if theyJoined && iJoined {
return chat, nil
}
return nil, errors.New("did not find a matching group chat")
default:
return nil, errors.New("can not match a chat because there is no valid case")
@ -1098,7 +1313,7 @@ func (m *Messenger) VerifyENSNames(rpcEndpoint, contractAddress string, ensDetai
}
// Update contacts
var contacts []Contact
var contacts []*Contact
for _, details := range ensResponse {
if details.Error == nil {
contact, err := buildContact(details.PublicKey)
@ -1109,7 +1324,7 @@ func (m *Messenger) VerifyENSNames(rpcEndpoint, contractAddress string, ensDetai
contact.ENSVerifiedAt = details.VerifiedAt
contact.Name = details.Name
contacts = append(contacts, *contact)
contacts = append(contacts, contact)
} else {
m.logger.Warn("Failed to resolve ens name",
zap.String("name", details.Name),
@ -1133,8 +1348,3 @@ func (m *Messenger) VerifyENSNames(rpcEndpoint, contractAddress string, ensDetai
func GenerateAlias(id string) (string, error) {
return alias.GenerateFromPublicKeyString(id)
}
// PrepareContent parses the content of a message and returns the parsed version
func (m *Messenger) PrepareContent(content v1protocol.Content) v1protocol.Content {
return v1protocol.PrepareContent(content)
}

File diff suppressed because it is too large Load diff

View file

@ -1,15 +1,15 @@
// Code generated by go-bindata. DO NOT EDIT.
// sources:
// 000001_init.down.db.sql (82B)
// 000001_init.up.db.sql (840B)
// 000001_init.up.db.sql (832B)
// 000002_add_chats.down.db.sql (74B)
// 000002_add_chats.up.db.sql (599B)
// 000002_add_chats.up.db.sql (495B)
// 000003_add_contacts.down.db.sql (21B)
// 000003_add_contacts.up.db.sql (381B)
// 000004_user_messages_compatibility.down.sql (33B)
// 000004_user_messages_compatibility.up.sql (928B)
// 000004_user_messages_compatibility.up.sql (980B)
// 1567112142_user_messages.down.sql (26B)
// 1567112142_user_messages.up.sql (551B)
// 1567112142_user_messages.up.sql (543B)
// doc.go (377B)
package migrations
@ -94,12 +94,12 @@ func _000001_initDownDbSql() (*asset, error) {
return nil, err
}
info := bindataFileInfo{name: "000001_init.down.db.sql", size: 82, mode: os.FileMode(0644), modTime: time.Unix(1564484687, 0)}
info := bindataFileInfo{name: "000001_init.down.db.sql", size: 82, mode: os.FileMode(0644), modTime: time.Unix(1574354941, 0)}
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xe8, 0x5f, 0xe0, 0x6, 0xfc, 0xed, 0xb7, 0xff, 0xb5, 0xf3, 0x33, 0x45, 0x1, 0x5b, 0x84, 0x80, 0x74, 0x60, 0x81, 0xa6, 0x8b, 0xb4, 0xd4, 0xad, 0x10, 0xa8, 0xb3, 0x61, 0x6f, 0xc5, 0x2f, 0xaa}}
return a, nil
}
var __000001_initUpDbSql = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x94\x52\xb1\x6e\xc2\x30\x14\xdc\xf3\x15\x6f\x24\x12\x43\xf7\x4e\x0e\xbc\x80\xd5\xd4\x6e\x1d\xa7\xc0\x14\x19\xe2\x82\x0b\x09\x11\x36\x52\xf9\xfb\xaa\x49\x8c\x02\x45\x15\xac\xef\xce\xe7\xbb\x7b\x6f\x24\x90\x48\x04\x49\xa2\x04\x81\xc6\xc0\xb8\x04\x9c\xd3\x54\xa6\x70\xb4\xfa\x90\x97\xda\x5a\xb5\xd6\x16\x06\x01\x00\x80\x29\x20\x4a\x78\x04\x19\xa3\xef\x19\x36\x6c\x96\x25\xc9\xb0\x01\x57\x1b\xe5\x72\x53\xc0\x07\x11\xa3\x29\x11\xd7\xe8\xbe\x72\xba\x72\xb9\x3b\xd5\xda\x53\x5a\xa4\xfb\xe3\x06\xe2\xf4\xb7\x03\x89\x73\xd9\x49\xec\xf6\xab\x2d\x44\x74\x42\x59\x37\x71\xa6\xd4\xd6\xa9\xb2\xbe\x98\xfa\xaf\xbc\xa1\x9e\x82\x37\x71\x29\x5c\x1f\x97\x3b\xb3\xca\xb7\xfa\xd4\xc4\x6b\x87\x9f\x3b\xb5\xb6\x40\x99\x3c\x07\x81\x31\xc6\x24\x4b\x24\x3c\x05\xe1\x73\x10\x74\xdd\x51\x36\xc6\xb9\x0f\x6f\x81\xb3\xcb\xe6\x06\x1d\xd2\x7b\x71\xab\xed\x52\x97\x4b\x7d\xb0\x1b\x53\xe7\xc7\xba\x50\xae\x5f\xb9\x2f\xf4\x4d\xd0\x57\x22\x16\xf0\x82\x8b\xab\x72\x0b\xe5\x54\xbb\x99\x47\x56\x12\x73\x81\x74\xc2\x1a\xbd\xb3\x4d\x10\x18\xa3\x40\x36\xc2\xb4\x79\x6e\x07\xa6\x08\x83\x10\x66\x54\x4e\x79\x26\x41\xf0\x19\x1d\xff\x9f\xa5\x91\xea\x02\x75\x29\xae\x1a\x7e\xc8\xa6\x2a\x4a\x53\x41\xc4\x79\x82\x84\xfd\x5d\x46\x4c\x92\x14\x5b\xe6\xd7\xde\x54\xba\xb8\x8b\x7a\x7f\xf6\x96\xdf\x5e\xbc\x67\x0e\x7b\x81\xc2\xdf\x63\xf8\x09\x00\x00\xff\xff\x66\xab\x2d\x2f\x48\x03\x00\x00")
var __000001_initUpDbSql = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x94\x92\xcd\x6e\xea\x30\x10\x85\xf7\x79\x8a\x59\x12\x89\xc5\xdd\xdf\x95\x03\x13\xb0\x9a\xda\xad\xe3\x14\x58\x45\x26\x71\xc1\x85\x84\x08\x1b\xa9\xbc\x7d\x45\x7e\x68\x48\xab\x0a\x96\x9e\x39\x3e\x9e\xef\x8c\x27\x02\x89\x44\x90\x24\x88\x10\x68\x08\x8c\x4b\xc0\x25\x8d\x65\x0c\x27\xab\x8f\x69\xa1\xad\x55\x1b\x6d\x61\xe4\x01\x00\x98\x1c\x82\x88\x07\x90\x30\xfa\x9a\x60\xad\x66\x49\x14\x8d\xeb\x66\xb6\x55\x2e\x35\x39\xbc\x11\x31\x99\x13\x31\xec\x1e\x4a\xa7\x4b\x97\xba\x73\xa5\x81\x32\xd9\x54\x5b\xff\x41\xd5\xe9\x4f\x07\x12\x97\xed\x31\xdb\x1f\xb2\x1d\x04\x74\xf6\x2d\x30\x85\xb6\x4e\x15\xd5\x4d\xb5\x7b\xa2\x1b\xa4\xe7\xd0\x3d\x7e\x6b\x5c\x9d\xd6\x7b\x93\xa5\x3b\x7d\xae\xb1\x9a\xe2\xfb\x5e\x6d\xec\x65\x96\x2b\x00\x4c\x31\x24\x49\x24\xe1\x9f\xe7\xff\xf7\xbc\x36\x33\xca\xa6\xb8\xec\xa0\x2d\x70\x76\x9b\xd8\xa8\xed\xf4\x6e\xfc\x96\x72\xa1\x8b\xb5\x3e\xda\xad\xa9\xd2\x53\x95\x2b\xd7\x8f\xba\x0b\xf2\x45\xd0\x67\x22\x56\xf0\x84\xab\x41\xa8\xb9\x72\xaa\xd9\xc8\x23\xab\x08\xb9\x40\x3a\x63\xb5\xdf\x75\x4c\x10\x18\xa2\x40\x36\xc1\xb8\xbe\x6e\x47\x26\xf7\x3d\x1f\x16\x54\xce\x79\x22\x41\xf0\x05\x9d\xfe\xcd\x52\x5b\xb5\x40\x2d\xc5\x20\xe1\x87\xc6\x54\x79\x61\x4a\x08\x38\x8f\x90\xb0\x9f\xcb\x08\x49\x14\x63\xa3\xfc\x38\x98\x52\xe7\x77\x49\xef\x67\x6f\xf4\xcd\x4f\xef\x94\xe3\x1e\x90\x7f\xf9\x0c\x5f\x01\x00\x00\xff\xff\x22\x17\x48\xa6\x40\x03\x00\x00")
func _000001_initUpDbSqlBytes() ([]byte, error) {
return bindataRead(
@ -114,8 +114,8 @@ func _000001_initUpDbSql() (*asset, error) {
return nil, err
}
info := bindataFileInfo{name: "000001_init.up.db.sql", size: 840, mode: os.FileMode(0644), modTime: time.Unix(1564484687, 0)}
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xe7, 0x27, 0x96, 0x3b, 0x72, 0x81, 0x7d, 0xba, 0xa4, 0xfb, 0xf7, 0x4, 0xd, 0x6f, 0xc8, 0x30, 0xfe, 0x47, 0xe0, 0x9, 0xf, 0x43, 0x13, 0x6, 0x55, 0xfc, 0xee, 0x15, 0x69, 0x99, 0x53, 0x3f}}
info := bindataFileInfo{name: "000001_init.up.db.sql", size: 832, mode: os.FileMode(0644), modTime: time.Unix(1575009877, 0)}
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x1c, 0xa4, 0xac, 0x0, 0xd3, 0x19, 0x53, 0x35, 0x91, 0x1c, 0x94, 0xea, 0xde, 0xa7, 0x75, 0xb6, 0x73, 0x1d, 0x42, 0x14, 0xca, 0x84, 0x5b, 0xdb, 0x10, 0x94, 0x28, 0xc0, 0x33, 0x95, 0x7f, 0xf}}
return a, nil
}
@ -134,12 +134,12 @@ func _000002_add_chatsDownDbSql() (*asset, error) {
return nil, err
}
info := bindataFileInfo{name: "000002_add_chats.down.db.sql", size: 74, mode: os.FileMode(0644), modTime: time.Unix(1565597460, 0)}
info := bindataFileInfo{name: "000002_add_chats.down.db.sql", size: 74, mode: os.FileMode(0644), modTime: time.Unix(1574354941, 0)}
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xd3, 0xa7, 0xf0, 0x94, 0x7a, 0x9, 0xdc, 0x6c, 0x7b, 0xdc, 0x12, 0x30, 0x55, 0x31, 0x17, 0xf2, 0xcc, 0x6e, 0xfd, 0xbb, 0x70, 0xb9, 0xd8, 0x9f, 0x81, 0x83, 0xdc, 0x1d, 0x1c, 0x3a, 0x8d, 0xce}}
return a, nil
}
var __000002_add_chatsUpDbSql = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x8c\x92\x4f\x4b\x03\x31\x10\xc5\xef\xf3\x29\x06\x3c\x54\x21\x07\x3d\x88\x42\x4f\xd9\x6d\x8a\x8b\x71\x53\xd2\x54\xec\x29\xa4\xd9\xc1\x2e\xdd\x7f\x74\xb3\x95\x7e\x7b\x69\x5d\x6a\xff\x58\xf0\x98\xbc\xf7\x7b\x93\x17\x26\xd6\x82\x1b\x81\x86\x47\x52\x60\x32\xc6\x54\x19\x14\x1f\xc9\xd4\x4c\xd1\x2f\x5d\x68\xf1\x16\xf2\x0c\xdf\xb9\x8e\x5f\xb8\xc6\x89\x4e\xde\xb8\x9e\xe3\xab\x98\xa3\x4a\x31\x56\xe9\x58\x26\xb1\x41\x2d\x26\x92\xc7\x82\x41\xe5\x4a\x3a\xb8\x77\x59\xe9\x4c\x4a\x06\xbe\x2e\xea\xf5\xc5\x3d\x8e\xc4\x98\xcf\xa4\xc1\xc1\x8d\x7b\x78\x7e\xca\x1e\x07\x0c\xc2\xb6\x21\x4c\x52\x73\x04\x3b\x1f\xf2\x0d\x61\xa4\x94\x14\x3c\xbd\xa4\x8d\x9e\x09\x06\x21\x2f\xa9\x0d\xae\x6c\xce\xe8\x8c\x0a\x0a\x94\x59\x17\xac\x2f\x6a\xbf\xb2\x1b\x57\x74\xa7\x23\x0e\x49\xf7\x0c\x9a\x6e\x51\xe4\xde\xae\x68\x8b\x91\x54\x11\x83\xae\xda\xe4\xf4\x45\x99\x2d\xa9\x6d\xdd\x27\x59\x5f\x77\x55\xb8\xca\x17\xae\xfd\xdf\xa0\xbd\xf1\x37\xb3\x0a\x54\x05\xbb\x6f\xdf\x7f\xd3\xdf\x96\x2b\xea\x49\xfb\x73\xf2\xf4\x35\x0c\x4a\x2a\x17\xb4\x6e\xfb\x82\xfd\x69\x99\x37\xb6\x6b\x32\x17\xe8\x47\x80\xbb\x21\x00\x8c\xb4\x9a\xf4\xcb\x71\xe9\x1b\x1e\xcb\xbb\x6d\xb1\xbd\x67\x08\xdf\x01\x00\x00\xff\xff\x44\xe3\x59\x6f\x57\x02\x00\x00")
var __000002_add_chatsUpDbSql = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x8c\x91\xc1\x6a\x32\x31\x14\x85\xf7\xf7\x29\x2e\xfc\x0b\xff\xc2\x2c\xda\x45\x69\xc1\x55\x66\x8c\x74\x68\x3a\x91\x18\x4b\x5d\x85\x98\xb9\xd4\xc1\xc4\x19\x4c\xc6\xe2\xdb\x17\xdb\x41\xb4\x52\xe8\x32\xb9\xdf\x77\xce\xe2\x14\x8a\x33\xcd\x51\xb3\x5c\x70\x2c\xa7\x58\x49\x8d\xfc\xad\x9c\xeb\x39\xba\xb5\x4d\x11\xff\x43\x53\xe3\x2b\x53\xc5\x13\x53\x38\x53\xe5\x0b\x53\x4b\x7c\xe6\x4b\x94\x15\x16\xb2\x9a\x8a\xb2\xd0\xa8\xf8\x4c\xb0\x82\x67\xb0\xb5\x81\x4e\xf4\x31\xab\x5a\x08\x91\x81\x6b\x7d\xbb\xbb\xfa\xc7\x09\x9f\xb2\x85\xd0\x38\xfa\x67\xef\x1e\x1f\xea\xfb\x51\x06\xe9\xd0\x11\x96\x95\x3e\x93\xad\x4b\xcd\x9e\x30\x97\x52\x70\x56\x5d\xdb\x5a\x2d\x78\x06\xa9\x09\x14\x93\x0d\xdd\x0f\xbb\x26\x4f\x89\x6a\x63\x93\x71\xbe\x75\x1b\xb3\xb7\xbe\xbf\xac\x38\x25\xdd\x66\xd0\xf5\x2b\xdf\x38\xb3\xa1\x03\xe6\x42\xe6\x19\xf4\xdb\x7d\x43\x1f\x54\x9b\x40\x31\xda\x77\x32\xae\xed\xb7\xe9\x57\xdf\xdb\xf8\xb7\xa2\x2f\x70\xc8\x1c\xaa\x02\x85\x15\xed\xe2\xe5\x6b\xdd\x74\xa6\xef\x6a\x9b\xe8\xfb\x00\x37\x63\x00\x98\x28\x39\x1b\x46\xbb\xe6\xc6\xe7\xe7\xe3\x8a\x66\x60\xc6\xf0\x19\x00\x00\xff\xff\x99\xae\x9f\xf2\xef\x01\x00\x00")
func _000002_add_chatsUpDbSqlBytes() ([]byte, error) {
return bindataRead(
@ -154,8 +154,8 @@ func _000002_add_chatsUpDbSql() (*asset, error) {
return nil, err
}
info := bindataFileInfo{name: "000002_add_chats.up.db.sql", size: 599, mode: os.FileMode(0644), modTime: time.Unix(1572543168, 0)}
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xdb, 0xf, 0xef, 0x31, 0x64, 0x3, 0xf0, 0x58, 0x1e, 0xed, 0x1e, 0x7e, 0xce, 0x4, 0x20, 0x51, 0x79, 0xf9, 0xca, 0xc3, 0xb9, 0xc9, 0x60, 0x25, 0x2f, 0x6b, 0x99, 0xb1, 0x92, 0x6d, 0x56, 0x31}}
info := bindataFileInfo{name: "000002_add_chats.up.db.sql", size: 495, mode: os.FileMode(0644), modTime: time.Unix(1575009877, 0)}
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x6e, 0xca, 0x2b, 0xf7, 0xca, 0x21, 0xda, 0x17, 0x1f, 0x97, 0xa8, 0x12, 0xb5, 0x6c, 0xad, 0x92, 0xe7, 0x2, 0xaf, 0x1, 0xcb, 0x5e, 0xe9, 0x71, 0xc4, 0x81, 0xa7, 0x3, 0x93, 0x5b, 0x73, 0x73}}
return a, nil
}
@ -174,7 +174,7 @@ func _000003_add_contactsDownDbSql() (*asset, error) {
return nil, err
}
info := bindataFileInfo{name: "000003_add_contacts.down.db.sql", size: 21, mode: os.FileMode(0644), modTime: time.Unix(1565597570, 0)}
info := bindataFileInfo{name: "000003_add_contacts.down.db.sql", size: 21, mode: os.FileMode(0644), modTime: time.Unix(1574354941, 0)}
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xfc, 0x7e, 0xb, 0xec, 0x72, 0xcd, 0x21, 0x3e, 0xa2, 0x38, 0xe0, 0x95, 0x7e, 0xce, 0x4a, 0x17, 0xc8, 0xd0, 0x1c, 0xfa, 0xa3, 0x23, 0x5, 0xab, 0x89, 0xf9, 0xfc, 0x63, 0x7, 0x28, 0xe9, 0x93}}
return a, nil
}
@ -194,7 +194,7 @@ func _000003_add_contactsUpDbSql() (*asset, error) {
return nil, err
}
info := bindataFileInfo{name: "000003_add_contacts.up.db.sql", size: 381, mode: os.FileMode(0644), modTime: time.Unix(1572543168, 0)}
info := bindataFileInfo{name: "000003_add_contacts.up.db.sql", size: 381, mode: os.FileMode(0644), modTime: time.Unix(1574354941, 0)}
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x45, 0xfe, 0x1e, 0xf2, 0x75, 0x33, 0x37, 0x8e, 0x7f, 0x93, 0x6f, 0x16, 0xbb, 0xf8, 0xa4, 0x70, 0x6b, 0xe0, 0xc1, 0x4f, 0x99, 0x8d, 0xc8, 0x2d, 0x40, 0xf1, 0xed, 0x65, 0x90, 0xc3, 0xad, 0xc7}}
return a, nil
}
@ -214,12 +214,12 @@ func _000004_user_messages_compatibilityDownSql() (*asset, error) {
return nil, err
}
info := bindataFileInfo{name: "000004_user_messages_compatibility.down.sql", size: 33, mode: os.FileMode(0644), modTime: time.Unix(1565631683, 0)}
info := bindataFileInfo{name: "000004_user_messages_compatibility.down.sql", size: 33, mode: os.FileMode(0644), modTime: time.Unix(1574354941, 0)}
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xb9, 0xaf, 0x48, 0x80, 0x3d, 0x54, 0x5e, 0x53, 0xee, 0x98, 0x26, 0xbb, 0x99, 0x6a, 0xd8, 0x37, 0x94, 0xf2, 0xf, 0x82, 0xfa, 0xb7, 0x6a, 0x68, 0xcd, 0x8b, 0xe2, 0xc4, 0x6, 0x25, 0xdc, 0x6}}
return a, nil
}
var __000004_user_messages_compatibilityUpSql = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xa4\x92\xcf\x6e\xe2\x3c\x14\xc5\xf7\x3c\xc5\xd9\x01\x12\xf9\xd4\x45\xd5\x4d\x57\x81\x9a\x6f\xa2\xc9\x24\x55\x30\x23\xba\xb2\x4c\xb8\x43\xac\x49\x6c\x64\xdf\x0c\x13\xa9\x0f\x3f\xa2\x84\xaa\x61\xe8\x6a\xb2\xc8\xc2\xbf\x73\xec\x73\xff\x44\x11\x12\x1e\x07\x98\xe6\xe0\x3c\x6b\xcb\xe0\x4a\x9f\x7e\x26\x80\xf5\xb6\x26\x54\x3a\xc0\xbb\xa3\xd9\x41\x07\x1c\x09\x9e\xea\x0e\xce\xc2\xf0\x28\x8a\x70\xac\xc8\x9e\xcc\x35\x35\x64\xd9\xd8\x3d\x8c\xfd\x61\xac\x61\x8a\x42\xe9\x5d\x5d\xff\x37\x5a\x14\x22\x96\x02\x32\x9e\xa7\x02\xc9\x12\x59\x2e\x21\x36\xc9\x4a\xae\xd0\x06\xf2\xaa\xa1\x10\xf4\x9e\x82\xaa\x69\xaf\xcb\x0e\x93\x11\x00\x98\x1d\xbe\xc7\xc5\xe2\x4b\x5c\xe0\xb9\x48\xbe\xc5\xc5\x0b\xbe\x8a\x17\xe4\x19\x16\x79\xb6\x4c\x93\x85\x44\x21\x9e\xd3\x78\x21\x66\x6f\xfa\x63\x65\xc2\x81\xbc\x62\xd3\x50\x60\xdd\x1c\x90\x64\x52\xfc\x2f\x8a\xb7\xf7\xb2\x75\x9a\x9e\x75\xc1\xb5\xbe\x24\x48\xb1\x91\x57\x64\x47\x81\x8d\xd5\x6c\x9c\xc5\x3c\xcd\xe7\xe7\xd3\xd2\x59\x26\xcb\xef\x61\x86\x9e\x9e\x2a\xee\x0e\xf4\x89\xe4\x54\xa3\xd5\xcd\x3b\x3e\x9f\x0e\x62\x5e\x5f\x5a\x69\x56\x1f\xea\x1f\x52\x4f\xec\x3b\x55\xba\xd6\xf2\xc0\x8b\x27\xb1\x8c\xd7\xa9\xc4\xdd\x45\x77\xa8\x3b\xc5\x6e\xf8\x6e\xdf\xec\x41\xe0\x21\x09\xac\xb9\x0d\x43\x56\xd6\xae\xfc\xa9\x7e\xe9\xba\xa5\x1b\x79\x43\xe5\x8e\x98\xe7\x79\x2a\xe2\xec\xef\x38\xb2\x58\xf7\x23\x0a\x44\xf6\x73\xdd\x32\x4e\x57\xbd\xd0\xb5\xbc\x77\xc6\xee\xaf\xb2\x8c\xa6\x8f\xa3\xcb\x36\x25\xd9\x93\xd8\xc0\xec\x7e\xab\x7e\xa0\x79\x76\x73\x9b\x26\x67\x3c\x7d\xbc\x61\x24\xed\xcb\x4a\x6d\x3b\x75\x69\x78\x9e\xe1\xf6\x25\xe7\xf8\xed\x36\xb0\x9f\x8c\xef\xfe\xf1\x1b\xe3\xf5\xf5\x63\x47\x67\x88\x1e\xee\x67\x78\xb8\x9f\x9e\x80\xd9\xcd\x2e\x0b\x70\xaa\xf7\x4f\x00\x00\x00\xff\xff\xe0\x0c\x93\xa2\xa0\x03\x00\x00")
var __000004_user_messages_compatibilityUpSql = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xa4\x52\xc1\x6e\xda\x40\x10\xbd\xf3\x15\x73\x0b\x48\xb8\xca\x21\xca\x25\x27\x43\x96\xd6\xaa\x6b\x47\xc6\xa9\xc8\x69\xb5\xd8\x53\xbc\x62\xbd\x6b\xed\x8c\x4b\x2c\xe5\xe3\x2b\x03\x26\x40\x51\x2f\xf5\xc1\x87\x79\x33\x6f\xde\xdb\x79\x41\x00\x11\xdf\x11\xe8\xba\x71\x9e\x95\x65\xe0\x4a\xf5\x3f\x4d\xc0\x6a\x6d\x10\x2a\x45\xe0\xdd\x4e\x97\xa0\x08\x76\x08\x1e\x4d\x07\xce\x82\xe6\x51\x10\xc0\xae\x42\xdb\x0f\x1b\xac\xd1\xb2\xb6\x1b\xd0\xf6\x97\xb6\x9a\x31\xa0\xc2\x3b\x63\xbe\x8c\xe6\x99\x08\x73\x01\x79\x38\x8b\x05\x44\x0b\x48\xd2\x1c\xc4\x2a\x5a\xe6\x4b\x68\x09\xbd\xac\x91\x48\x6d\x90\xa4\xc1\x8d\x2a\x3a\x18\x8f\x00\x00\x74\x09\x3f\xc3\x6c\xfe\x2d\xcc\xe0\x25\x8b\x7e\x84\xd9\x1b\x7c\x17\x6f\x90\x26\x30\x4f\x93\x45\x1c\xcd\x73\xc8\xc4\x4b\x1c\xce\xc5\x74\xdf\xbf\xab\x34\x35\xe8\x25\xeb\x1a\x89\x55\xdd\x40\x94\xe4\xe2\xab\xc8\xf6\xfb\x92\xd7\x38\x3e\xf4\x91\x6b\x7d\x81\x90\x8b\x55\x7e\x85\x94\x48\xac\xad\x62\xed\x2c\xcc\xe2\x74\x76\xa8\x32\xbe\xf3\x49\xc9\xe5\x40\xe1\x2c\xa3\x65\xc9\x5d\x83\xfd\xb6\x2b\xb8\x37\x67\x55\x8d\xc3\xf4\x91\xef\x5c\xdf\x35\x61\xa5\x58\x9e\x19\xbf\x44\x8d\x2b\x94\x91\xff\xee\xf1\xc8\xbe\x93\x85\x6b\x2d\x5f\xf0\xc3\xb3\x58\x84\xaf\x71\x0e\xf7\x43\x1f\x35\xce\x12\x4a\x76\x97\xf2\x8e\xc7\x38\x79\x3a\x0a\x33\xae\xd8\xca\xdf\xca\xb4\xb7\x8c\x12\xa2\x85\x59\x9a\xc6\x22\x4c\xfe\xde\xb8\x08\xe3\xe5\xf1\x46\xae\xe5\x8d\xd3\x76\x23\x89\x15\xb7\x74\xb9\xb9\x51\x9e\xb0\x94\xfb\xf7\xfe\x7c\x7e\xaf\x76\xb2\x51\x9d\x71\xaa\x3c\xab\x12\xeb\x62\x8b\x5e\x36\xaa\xd8\x7e\xaa\x1c\xaa\x95\xa2\x6a\xe0\x1e\x4d\x9e\x46\x43\x02\xa3\xe4\x59\xac\x40\x97\xef\xf2\x18\x82\x34\xb9\x99\xc0\xf1\x01\x9e\x3c\xdd\x18\x44\xe5\x8b\x4a\xae\xbb\xd3\x1d\xd2\x04\x6e\x93\x1c\x24\xb5\x6b\x62\x3f\xbe\xbb\xff\xcf\xef\x0e\x3e\x3e\xce\xaf\x30\x85\xe0\xf1\x61\x0a\x8f\x0f\x93\x1e\xd0\xe5\x74\xc8\x4e\xef\xf7\x4f\x00\x00\x00\xff\xff\x91\x46\x82\xd5\xd4\x03\x00\x00")
func _000004_user_messages_compatibilityUpSqlBytes() ([]byte, error) {
return bindataRead(
@ -234,8 +234,8 @@ func _000004_user_messages_compatibilityUpSql() (*asset, error) {
return nil, err
}
info := bindataFileInfo{name: "000004_user_messages_compatibility.up.sql", size: 928, mode: os.FileMode(0644), modTime: time.Unix(1569474812, 0)}
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x60, 0x6c, 0x7f, 0xfb, 0xb3, 0x30, 0xd8, 0xbf, 0x6, 0x4a, 0x4a, 0xec, 0x9e, 0xd7, 0xa, 0x5e, 0x8, 0xbb, 0xf8, 0x11, 0x97, 0x80, 0xd3, 0xfa, 0x2c, 0x1e, 0x82, 0xb2, 0xe2, 0xe7, 0x6e, 0xa}}
info := bindataFileInfo{name: "000004_user_messages_compatibility.up.sql", size: 980, mode: os.FileMode(0644), modTime: time.Unix(1575009877, 0)}
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xc, 0x7a, 0xba, 0xae, 0x6d, 0xef, 0x69, 0x12, 0x6b, 0x48, 0xe3, 0xa7, 0xad, 0x21, 0x4a, 0xcf, 0x4f, 0xbc, 0x14, 0xc1, 0x19, 0x69, 0x1c, 0xc, 0xa2, 0x3d, 0xbc, 0x12, 0x32, 0x71, 0x76, 0x15}}
return a, nil
}
@ -254,12 +254,12 @@ func _1567112142_user_messagesDownSql() (*asset, error) {
return nil, err
}
info := bindataFileInfo{name: "1567112142_user_messages.down.sql", size: 26, mode: os.FileMode(0644), modTime: time.Unix(1568961800, 0)}
info := bindataFileInfo{name: "1567112142_user_messages.down.sql", size: 26, mode: os.FileMode(0644), modTime: time.Unix(1574354941, 0)}
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x79, 0x8e, 0xbe, 0x63, 0x64, 0x52, 0xa3, 0x13, 0x83, 0xc7, 0x47, 0xff, 0x56, 0xa9, 0xc, 0x72, 0xb4, 0x97, 0x6, 0xc7, 0xa5, 0x68, 0xb6, 0x55, 0x6a, 0xd5, 0xb0, 0x12, 0xfb, 0x4c, 0xa5, 0x27}}
return a, nil
}
var __1567112142_user_messagesUpSql = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x6c\x90\x51\x6f\x9b\x30\x14\x85\xdf\xf9\x15\xe7\xad\xad\xb4\x54\x7b\xef\x13\x01\x67\x43\x42\x64\x23\xce\xd6\xb7\xc8\xd8\xb7\xc5\x8a\xb1\x11\xbe\x2c\xe5\xdf\x4f\xa1\xb0\x2d\x53\x5f\xcf\x77\xfd\xdd\x73\xbd\xd9\x20\x1f\x42\x0f\xe5\x27\xf4\x03\xfd\xb2\x61\x8c\x6e\x82\x1e\x48\x31\x19\x8c\x91\x86\x53\x47\x31\xaa\x57\x8a\x60\xd5\x38\x7a\x4c\x36\x1b\xfc\x24\x98\xe0\xef\x18\x9e\xc8\x80\x03\x22\xab\x09\x8d\xd2\xe7\x8b\x1a\x0c\x74\xe8\x7a\xc5\xb6\x71\x84\x8b\xe5\x16\x96\xaf\x8f\x1a\xd2\x6a\x8c\x04\xcb\x77\x11\x3e\xf0\xd5\x6e\xae\x9b\x2f\x2d\x0d\x04\x7a\xd3\xd4\x33\x5e\xc2\x00\x6e\x09\x3a\xf8\x18\x1c\x41\x3b\x4b\x9e\x1f\x93\xbc\xde\x7f\x83\x4c\xb7\xa5\xb8\x6d\xf5\x94\x24\x59\x2d\x52\x29\x16\x58\xec\x50\xed\x25\xc4\x73\x71\x90\x87\xff\x0e\xb8\x4f\x00\xc0\x1a\x6c\xcb\xfd\x16\xc7\xaa\xf8\x7e\x14\xf3\x74\x75\x2c\xcb\x4f\x33\xd4\xad\xe2\x93\x35\xf8\x91\xd6\xd9\xd7\xb4\xfe\x43\x51\x8b\x9d\xa8\x45\x95\x89\xc3\x3c\x13\xef\xad\x79\xc0\xbe\x42\x2e\x4a\x21\x05\xb2\xf4\x90\xa5\xb9\x58\x24\xc1\x33\x79\x3e\xf1\xd4\xd3\x6a\x7a\x27\x4b\x95\x0f\x08\xd3\x1b\x43\x8a\x67\xb9\x28\x5c\xd0\x67\x6c\x8b\x2f\x45\xb5\x24\x6c\x3b\x8a\xac\xba\xfe\x26\x5d\x57\xad\xbd\xff\x31\xac\x25\x6e\xc5\xfd\xd8\x38\xab\x4f\x67\x9a\xe6\x5f\x78\x0f\x5f\x9c\x7a\x8d\x28\x2a\xf9\xf7\xde\x5c\xec\xd2\x63\x29\xf1\x39\x79\x78\x4a\x7e\x07\x00\x00\xff\xff\x07\x0e\xee\x5c\x27\x02\x00\x00")
var __1567112142_user_messagesUpSql = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x5c\x4f\x4d\x73\x9b\x30\x14\xbc\xf3\x2b\xf6\x96\x64\xa6\xce\xf4\x9e\x13\x06\xb9\x65\x86\xc1\x2d\x96\xdb\xdc\x3c\x42\x7a\x09\x1a\x0b\x89\x41\x8f\x3a\xfc\xfb\x0e\x04\x37\x75\x8e\x6f\x77\xdf\x7e\x6c\x36\xc8\x87\xd0\x43\xf9\x09\xfd\x40\x7f\x6c\x18\xa3\x9b\xa0\x07\x52\x4c\x06\x63\xa4\xe1\xd4\x51\x8c\xea\x95\x22\x58\x35\x8e\x1e\x93\xcd\x06\xbf\x09\x26\xf8\x3b\x86\x27\x32\xe0\x80\xc8\x6a\x42\xa3\xf4\xf9\xa2\x06\x03\x1d\xba\x5e\xb1\x6d\x1c\xe1\x62\xb9\x85\xe5\xf9\xa9\x21\xad\xc6\x48\xb0\x7c\x17\xe1\x03\xcf\xee\x66\x4e\xbe\xb4\x34\x10\xe8\x4d\x53\xcf\x78\x09\x03\xb8\x25\xe8\xe0\x63\x70\x04\xed\x2c\x79\x7e\x4c\xf2\x7a\xff\x03\x32\xdd\x96\xe2\xb6\xd5\x53\x92\x64\xb5\x48\xa5\x58\xc9\x62\x87\x6a\x2f\x21\x9e\x8b\x83\x3c\x7c\x1a\x70\x9f\x00\x80\x35\xd8\x96\xfb\x2d\x8e\x55\xf1\xf3\x28\x16\x75\x75\x2c\xcb\x2f\x0b\xa9\x5b\xc5\x27\x6b\xf0\x2b\xad\xb3\xef\x69\xfd\x8f\x45\x2d\x76\xa2\x16\x55\x26\x0e\x8b\x26\xde\x5b\xf3\x80\x7d\x85\x5c\x94\x42\x0a\x64\xe9\x21\x4b\x73\xb1\x9a\x04\xcf\xe4\xf9\xc4\x53\x4f\x28\x2a\xf9\x8e\xae\x35\x3e\xa1\x4c\x6f\x0c\x29\x9e\xd7\x53\xbb\xa0\xcf\xd8\x16\xdf\x3e\x04\xb6\xa3\xc8\xaa\xeb\x6f\xd0\x6b\xc4\xb5\xef\x7f\x0e\xd7\xf0\x5b\xe3\x7e\x6c\x9c\xd5\xa7\x33\x4d\xcb\xfa\x77\xf0\xc5\xa9\xd7\x38\x77\xf9\xd8\x99\x8b\x5d\x7a\x2c\x25\xbe\x26\x0f\x4f\xc9\xdf\x00\x00\x00\xff\xff\x6e\x1c\xcd\x6f\x1f\x02\x00\x00")
func _1567112142_user_messagesUpSqlBytes() ([]byte, error) {
return bindataRead(
@ -274,8 +274,8 @@ func _1567112142_user_messagesUpSql() (*asset, error) {
return nil, err
}
info := bindataFileInfo{name: "1567112142_user_messages.up.sql", size: 551, mode: os.FileMode(0644), modTime: time.Unix(1568961800, 0)}
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x7a, 0x11, 0x2, 0x79, 0x3b, 0xc5, 0x37, 0xe7, 0x3f, 0xa9, 0x35, 0x99, 0xa5, 0x3f, 0x32, 0xa3, 0xbe, 0xf7, 0x53, 0xf3, 0xea, 0x72, 0xbd, 0xb, 0xfc, 0xa7, 0xdc, 0x97, 0x1c, 0x6, 0x71, 0x16}}
info := bindataFileInfo{name: "1567112142_user_messages.up.sql", size: 543, mode: os.FileMode(0644), modTime: time.Unix(1575009877, 0)}
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xff, 0xc0, 0x47, 0x32, 0xa9, 0xa4, 0x6, 0x63, 0x6b, 0xe7, 0x79, 0x2b, 0x80, 0x52, 0x2b, 0x6f, 0xf9, 0x9d, 0x9a, 0xc2, 0xa9, 0x7a, 0xf7, 0x4d, 0x14, 0x12, 0x21, 0x10, 0xc4, 0x30, 0x42, 0xaa}}
return a, nil
}
@ -294,7 +294,7 @@ func docGo() (*asset, error) {
return nil, err
}
info := bindataFileInfo{name: "doc.go", size: 377, mode: os.FileMode(0644), modTime: time.Unix(1564484687, 0)}
info := bindataFileInfo{name: "doc.go", size: 377, mode: os.FileMode(0644), modTime: time.Unix(1574354941, 0)}
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xef, 0xaf, 0xdf, 0xcf, 0x65, 0xae, 0x19, 0xfc, 0x9d, 0x29, 0xc1, 0x91, 0xaf, 0xb5, 0xd5, 0xb1, 0x56, 0xf3, 0xee, 0xa8, 0xba, 0x13, 0x65, 0xdb, 0xab, 0xcf, 0x4e, 0xac, 0x92, 0xe9, 0x60, 0xf1}}
return a, nil
}
@ -454,17 +454,17 @@ type bintree struct {
}
var _bintree = &bintree{nil, map[string]*bintree{
"000001_init.down.db.sql": {_000001_initDownDbSql, map[string]*bintree{}},
"000001_init.up.db.sql": {_000001_initUpDbSql, map[string]*bintree{}},
"000002_add_chats.down.db.sql": {_000002_add_chatsDownDbSql, map[string]*bintree{}},
"000002_add_chats.up.db.sql": {_000002_add_chatsUpDbSql, map[string]*bintree{}},
"000003_add_contacts.down.db.sql": {_000003_add_contactsDownDbSql, map[string]*bintree{}},
"000003_add_contacts.up.db.sql": {_000003_add_contactsUpDbSql, map[string]*bintree{}},
"000004_user_messages_compatibility.down.sql": {_000004_user_messages_compatibilityDownSql, map[string]*bintree{}},
"000004_user_messages_compatibility.up.sql": {_000004_user_messages_compatibilityUpSql, map[string]*bintree{}},
"1567112142_user_messages.down.sql": {_1567112142_user_messagesDownSql, map[string]*bintree{}},
"1567112142_user_messages.up.sql": {_1567112142_user_messagesUpSql, map[string]*bintree{}},
"doc.go": {docGo, map[string]*bintree{}},
"000001_init.down.db.sql": &bintree{_000001_initDownDbSql, map[string]*bintree{}},
"000001_init.up.db.sql": &bintree{_000001_initUpDbSql, map[string]*bintree{}},
"000002_add_chats.down.db.sql": &bintree{_000002_add_chatsDownDbSql, map[string]*bintree{}},
"000002_add_chats.up.db.sql": &bintree{_000002_add_chatsUpDbSql, map[string]*bintree{}},
"000003_add_contacts.down.db.sql": &bintree{_000003_add_contactsDownDbSql, map[string]*bintree{}},
"000003_add_contacts.up.db.sql": &bintree{_000003_add_contactsUpDbSql, map[string]*bintree{}},
"000004_user_messages_compatibility.down.sql": &bintree{_000004_user_messages_compatibilityDownSql, map[string]*bintree{}},
"000004_user_messages_compatibility.up.sql": &bintree{_000004_user_messages_compatibilityUpSql, map[string]*bintree{}},
"1567112142_user_messages.down.sql": &bintree{_1567112142_user_messagesDownSql, map[string]*bintree{}},
"1567112142_user_messages.up.sql": &bintree{_1567112142_user_messagesUpSql, map[string]*bintree{}},
"doc.go": &bintree{docGo, map[string]*bintree{}},
}}
// RestoreAsset restores an asset under the given directory.

View file

@ -1,8 +1,8 @@
CREATE TABLE IF NOT EXISTS user_messages (
id BLOB UNIQUE NOT NULL,
chat_id VARCHAR NOT NULL,
content_type VARCHAR,
message_type VARCHAR,
content_type INT,
message_type INT,
text TEXT,
clock BIGINT,
timestamp BIGINT,

View file

@ -9,10 +9,7 @@ deleted_at_clock_value INT NOT NULL DEFAULT 0,
public_key BLOB,
unviewed_message_count INT NOT NULL DEFAULT 0,
last_clock_value INT NOT NULL DEFAULT 0,
last_message_content_type VARCHAR,
last_message_content VARCHAR,
last_message_timestamp INT,
last_message_clock_value INT,
last_message BLOB,
members BLOB,
membership_updates BLOB
);

View file

@ -5,19 +5,22 @@ CREATE TABLE IF NOT EXISTS user_messages_legacy (
whisper_timestamp INTEGER NOT NULL,
source TEXT NOT NULL,
destination BLOB,
content VARCHAR NOT NULL,
content_type VARCHAR NOT NULL,
text VARCHAR NOT NULL,
content_type INT NOT NULL,
username VARCHAR,
timestamp INT NOT NULL,
chat_id VARCHAR NOT NULL,
local_chat_id VARCHAR NOT NULL,
retry_count INT NOT NULL DEFAULT 0,
reply_to VARCHAR,
message_type VARCHAR,
message_status VARCHAR,
response_to VARCHAR,
message_type INT,
clock_value INT NOT NULL,
show BOOLEAN NOT NULL DEFAULT TRUE,
seen BOOLEAN NOT NULL DEFAULT FALSE,
outgoing_status VARCHAR
outgoing_status VARCHAR,
parsed_text BLOB,
raw_payload BLOB,
sticker_pack INT,
sticker_hash VARCHAR
);
CREATE INDEX idx_source ON user_messages_legacy(source);

View file

@ -6,8 +6,8 @@ DROP TABLE user_messages;
CREATE TABLE IF NOT EXISTS user_messages (
id BLOB UNIQUE NOT NULL,
chat_id VARCHAR NOT NULL REFERENCES chats(id) ON DELETE CASCADE,
content_type VARCHAR,
message_type VARCHAR,
content_type INT,
message_type INT,
text TEXT,
clock BIGINT,
timestamp BIGINT,

View file

@ -6,12 +6,9 @@ import (
"database/sql"
"encoding/gob"
"encoding/hex"
"time"
"github.com/pkg/errors"
"github.com/status-im/status-go/eth-node/crypto"
v1protocol "github.com/status-im/status-go/protocol/v1"
)
var (
@ -24,21 +21,46 @@ type sqlitePersistence struct {
db *sql.DB
}
func (db sqlitePersistence) LastMessageClock(chatID string) (int64, error) {
if chatID == "" {
return 0, errors.New("chat ID is empty")
}
var last sql.NullInt64
err := db.db.QueryRow("SELECT max(clock) FROM user_messages WHERE chat_id = ?", chatID).Scan(&last)
if err != nil {
return 0, err
}
return last.Int64, nil
func (db sqlitePersistence) SaveChat(chat Chat) error {
return db.saveChat(nil, chat)
}
func (db sqlitePersistence) SaveChat(chat Chat) error {
func (db sqlitePersistence) SaveChats(chats []*Chat) error {
tx, err := db.db.BeginTx(context.Background(), &sql.TxOptions{})
defer func() {
if err == nil {
err = tx.Commit()
return
}
// don't shadow original error
_ = tx.Rollback()
}()
for _, chat := range chats {
err := db.saveChat(tx, *chat)
if err != nil {
return err
}
}
return nil
}
func (db sqlitePersistence) saveChat(tx *sql.Tx, chat Chat) error {
var err error
if tx == nil {
tx, err = db.db.BeginTx(context.Background(), &sql.TxOptions{})
if err != nil {
return err
}
defer func() {
if err == nil {
err = tx.Commit()
return
}
// don't shadow original error
_ = tx.Rollback()
}()
}
pkey := []byte{}
// For one to one chatID is an encoded public key
@ -72,8 +94,8 @@ func (db sqlitePersistence) SaveChat(chat Chat) error {
}
// Insert record
stmt, err := db.db.Prepare(`INSERT INTO chats(id, name, color, active, type, timestamp, deleted_at_clock_value, public_key, unviewed_message_count, last_clock_value, last_message_content_type, last_message_content, last_message_timestamp, last_message_clock_value, members, membership_updates)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`)
stmt, err := tx.Prepare(`INSERT INTO chats(id, name, color, active, type, timestamp, deleted_at_clock_value, public_key, unviewed_message_count, last_clock_value, last_message, members, membership_updates)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`)
if err != nil {
return err
}
@ -90,10 +112,7 @@ func (db sqlitePersistence) SaveChat(chat Chat) error {
pkey,
chat.UnviewedMessagesCount,
chat.LastClockValue,
chat.LastMessageContentType,
chat.LastMessageContent,
chat.LastMessageTimestamp,
chat.LastMessageClockValue,
chat.LastMessage,
encodedMembers.Bytes(),
encodedMembershipUpdates.Bytes(),
)
@ -141,10 +160,7 @@ func (db sqlitePersistence) chats(tx *sql.Tx) (chats []*Chat, err error) {
public_key,
unviewed_message_count,
last_clock_value,
last_message_content_type,
last_message_content,
last_message_timestamp,
last_message_clock_value,
last_message,
members,
membership_updates
FROM chats
@ -157,11 +173,6 @@ func (db sqlitePersistence) chats(tx *sql.Tx) (chats []*Chat, err error) {
for rows.Next() {
var (
lastMessageContentType sql.NullString
lastMessageContent sql.NullString
lastMessageTimestamp sql.NullInt64
lastMessageClockValue sql.NullInt64
chat Chat
encodedMembers []byte
encodedMembershipUpdates []byte
@ -178,20 +189,13 @@ func (db sqlitePersistence) chats(tx *sql.Tx) (chats []*Chat, err error) {
&pkey,
&chat.UnviewedMessagesCount,
&chat.LastClockValue,
&lastMessageContentType,
&lastMessageContent,
&lastMessageTimestamp,
&lastMessageClockValue,
&chat.LastMessage,
&encodedMembers,
&encodedMembershipUpdates,
)
if err != nil {
return
}
chat.LastMessageContent = lastMessageContent.String
chat.LastMessageContentType = lastMessageContentType.String
chat.LastMessageTimestamp = lastMessageTimestamp.Int64
chat.LastMessageClockValue = lastMessageClockValue.Int64
// Restore members
membersDecoder := gob.NewDecoder(bytes.NewBuffer(encodedMembers))
@ -289,7 +293,7 @@ func (db sqlitePersistence) Contacts() ([]*Contact, error) {
return response, nil
}
func (db sqlitePersistence) SetContactsENSData(contacts []Contact) error {
func (db sqlitePersistence) SetContactsENSData(contacts []*Contact) error {
tx, err := db.db.BeginTx(context.Background(), &sql.TxOptions{})
if err != nil {
return err
@ -323,7 +327,7 @@ func (db sqlitePersistence) SetContactsENSData(contacts []Contact) error {
// SetContactsGeneratedData sets a contact generated data if not existing already
// in the database
func (db sqlitePersistence) SetContactsGeneratedData(contacts []Contact, tx *sql.Tx) (err error) {
func (db sqlitePersistence) SetContactsGeneratedData(contacts []*Contact, tx *sql.Tx) (err error) {
if tx == nil {
tx, err = db.db.BeginTx(context.Background(), &sql.TxOptions{})
if err != nil {
@ -435,109 +439,3 @@ func (db sqlitePersistence) SaveContact(contact Contact, tx *sql.Tx) (err error)
)
return
}
// Messages returns messages for a given contact, in a given period. Ordered by a timestamp.
func (db sqlitePersistence) Messages(from, to time.Time) (result []*v1protocol.Message, err error) {
rows, err := db.db.Query(`
SELECT
id,
chat_id,
content_type,
message_type,
text,
clock,
timestamp,
content_chat_id,
content_text,
public_key,
flags
FROM user_messages
WHERE timestamp >= ? AND timestamp <= ?
ORDER BY timestamp`,
v1protocol.TimestampInMsFromTime(from),
v1protocol.TimestampInMsFromTime(to),
)
if err != nil {
return
}
defer rows.Close()
for rows.Next() {
msg := v1protocol.Message{
Content: v1protocol.Content{},
}
var pkey []byte
err = rows.Scan(
&msg.ID, &msg.ChatID, &msg.ContentT, &msg.MessageT, &msg.Text, &msg.Clock,
&msg.Timestamp, &msg.Content.ChatID, &msg.Content.Text, &pkey, &msg.Flags,
)
if err != nil {
return
}
if len(pkey) != 0 {
msg.SigPubKey, err = crypto.UnmarshalPubkey(pkey)
if err != nil {
return
}
}
result = append(result, &msg)
}
return
}
func (db sqlitePersistence) SaveMessages(messages []*v1protocol.Message) (last int64, err error) {
tx, err := db.db.BeginTx(context.Background(), &sql.TxOptions{})
if err != nil {
return
}
defer func() {
if err == nil {
err = tx.Commit()
return
}
// don't shadow original error
_ = tx.Rollback()
}()
stmt, err := tx.Prepare(`
INSERT OR IGNORE INTO user_messages(
id,
chat_id,
content_type,
message_type,
text,
clock,
timestamp,
content_chat_id,
content_text,
public_key,
flags
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
`)
if err != nil {
return
}
var rst sql.Result
for _, msg := range messages {
var pkey []byte
if msg.SigPubKey != nil {
pkey = crypto.FromECDSAPub(msg.SigPubKey)
}
rst, err = stmt.Exec(
msg.ID, msg.ChatID, msg.ContentT, msg.MessageT, msg.Text, msg.Clock, msg.Timestamp,
msg.Content.ChatID, msg.Content.Text, pkey, msg.Flags,
)
if err != nil {
return
}
last, err = rst.LastInsertId()
if err != nil {
return
}
}
return
}

View file

@ -3,7 +3,9 @@ package protocol
import (
"context"
"database/sql"
"encoding/json"
"fmt"
"github.com/status-im/status-go/protocol/protobuf"
"strings"
"github.com/pkg/errors"
@ -17,42 +19,46 @@ func (db sqlitePersistence) tableUserMessagesLegacyAllFields() string {
return `id,
whisper_timestamp,
source,
destination,
content,
text,
content_type,
username,
timestamp,
chat_id,
local_chat_id,
retry_count,
message_type,
message_status,
clock_value,
show,
seen,
outgoing_status,
reply_to`
parsed_text,
raw_payload,
sticker_pack,
sticker_hash,
response_to`
}
func (db sqlitePersistence) tableUserMessagesLegacyAllFieldsJoin() string {
return `m1.id,
m1.whisper_timestamp,
m1.source,
m1.destination,
m1.content,
m1.text,
m1.content_type,
m1.username,
m1.timestamp,
m1.chat_id,
m1.local_chat_id,
m1.retry_count,
m1.message_type,
m1.message_status,
m1.clock_value,
m1.show,
m1.seen,
m1.outgoing_status,
m1.reply_to,
m1.parsed_text,
m1.raw_payload,
m1.sticker_pack,
m1.sticker_hash,
m1.response_to,
m2.source,
m2.content,
m2.text,
c.alias,
c.identicon`
}
@ -66,30 +72,35 @@ type scanner interface {
}
func (db sqlitePersistence) tableUserMessagesLegacyScanAllFields(row scanner, message *Message, others ...interface{}) error {
var quotedContent sql.NullString
var quotedText sql.NullString
var quotedFrom sql.NullString
var alias sql.NullString
var identicon sql.NullString
sticker := &protobuf.StickerMessage{}
args := []interface{}{
&message.ID,
&message.WhisperTimestamp,
&message.From, // source in table
&message.To, // destination in table
&message.Content,
&message.Text,
&message.ContentType,
&message.Alias,
&message.Timestamp,
&message.ChatID,
&message.ChatId,
&message.LocalChatID,
&message.RetryCount,
&message.MessageType,
&message.MessageStatus,
&message.ClockValue,
&message.Show,
&message.Clock,
&message.Seen,
&message.OutgoingStatus,
&message.ReplyTo,
&message.ParsedText,
&message.RawPayload,
&sticker.Pack,
&sticker.Hash,
&message.ResponseTo,
&quotedFrom,
&quotedContent,
&quotedText,
&alias,
&identicon,
}
@ -98,45 +109,70 @@ func (db sqlitePersistence) tableUserMessagesLegacyScanAllFields(row scanner, me
return err
}
if quotedContent.Valid {
if quotedText.Valid {
message.QuotedMessage = &QuotedMessage{
From: quotedFrom.String,
Content: quotedContent.String,
From: quotedFrom.String,
Text: quotedText.String,
}
}
message.Alias = alias.String
message.Identicon = identicon.String
if message.ContentType == protobuf.ChatMessage_STICKER {
message.Payload = &protobuf.ChatMessage_Sticker{Sticker: sticker}
}
return nil
}
func (db sqlitePersistence) tableUserMessagesLegacyAllValues(message *Message) []interface{} {
func (db sqlitePersistence) tableUserMessagesLegacyAllValues(message *Message) ([]interface{}, error) {
sticker := message.GetSticker()
if sticker == nil {
sticker = &protobuf.StickerMessage{}
}
return []interface{}{
message.ID,
message.WhisperTimestamp,
message.From, // source in table
message.To, // destination in table
message.Content,
message.Text,
message.ContentType,
message.Alias,
message.Timestamp,
message.ChatID,
message.ChatId,
message.LocalChatID,
message.RetryCount,
message.MessageType,
message.MessageStatus,
message.ClockValue,
message.Show,
message.Clock,
message.Seen,
message.OutgoingStatus,
message.ReplyTo,
}
message.ParsedText,
message.RawPayload,
sticker.Pack,
sticker.Hash,
message.ResponseTo,
}, nil
}
func (db sqlitePersistence) MessageByID(id string) (*Message, error) {
func (db sqlitePersistence) messageByID(tx *sql.Tx, id string) (*Message, error) {
var err error
if tx == nil {
tx, err = db.db.BeginTx(context.Background(), &sql.TxOptions{})
if err != nil {
return nil, err
}
defer func() {
if err == nil {
err = tx.Commit()
return
}
// don't shadow original error
_ = tx.Rollback()
}()
}
var message Message
allFields := db.tableUserMessagesLegacyAllFieldsJoin()
row := db.db.QueryRow(
row := tx.QueryRow(
fmt.Sprintf(`
SELECT
%s
@ -145,7 +181,7 @@ func (db sqlitePersistence) MessageByID(id string) (*Message, error) {
LEFT JOIN
user_messages_legacy m2
ON
m1.reply_to = m2.id
m1.response_to = m2.id
LEFT JOIN
contacts c
@ -156,7 +192,7 @@ func (db sqlitePersistence) MessageByID(id string) (*Message, error) {
`, allFields),
id,
)
err := db.tableUserMessagesLegacyScanAllFields(row, &message)
err = db.tableUserMessagesLegacyScanAllFields(row, &message)
switch err {
case sql.ErrNoRows:
return nil, errRecordNotFound
@ -167,6 +203,10 @@ func (db sqlitePersistence) MessageByID(id string) (*Message, error) {
}
}
func (db sqlitePersistence) MessageByID(id string) (*Message, error) {
return db.messageByID(nil, id)
}
func (db sqlitePersistence) MessagesExist(ids []string) (map[string]bool, error) {
result := make(map[string]bool)
if len(ids) == 0 {
@ -224,7 +264,7 @@ func (db sqlitePersistence) MessageByChatID(chatID string, currCursor string, li
LEFT JOIN
user_messages_legacy m2
ON
m1.reply_to = m2.id
m1.response_to = m2.id
LEFT JOIN
contacts c
@ -232,7 +272,7 @@ func (db sqlitePersistence) MessageByChatID(chatID string, currCursor string, li
m1.source = c.id
WHERE
m1.chat_id = ? %s
m1.local_chat_id = ? %s
ORDER BY cursor DESC
LIMIT ?
`, allFields, cursorWhere),
@ -290,7 +330,13 @@ func (db sqlitePersistence) SaveMessagesLegacy(messages []*Message) (err error)
}
for _, msg := range messages {
_, err = stmt.Exec(db.tableUserMessagesLegacyAllValues(msg)...)
var allValues []interface{}
allValues, err = db.tableUserMessagesLegacyAllValues(msg)
if err != nil {
return
}
_, err = stmt.Exec(allValues...)
if err != nil {
return
}
@ -304,24 +350,49 @@ func (db sqlitePersistence) DeleteMessage(id string) error {
}
func (db sqlitePersistence) DeleteMessagesByChatID(id string) error {
_, err := db.db.Exec(`DELETE FROM user_messages_legacy WHERE chat_id = ?`, id)
_, err := db.db.Exec(`DELETE FROM user_messages_legacy WHERE local_chat_id = ?`, id)
return err
}
func (db sqlitePersistence) MarkMessagesSeen(ids ...string) error {
func (db sqlitePersistence) MarkMessagesSeen(chatID string, ids []string) error {
tx, err := db.db.BeginTx(context.Background(), &sql.TxOptions{})
if err != nil {
return err
}
defer func() {
if err == nil {
err = tx.Commit()
return
}
// don't shadow original error
_ = tx.Rollback()
}()
idsArgs := make([]interface{}, 0, len(ids))
for _, id := range ids {
idsArgs = append(idsArgs, id)
}
inVector := strings.Repeat("?, ", len(ids)-1) + "?"
_, err := db.db.Exec(
_, err = tx.Exec(
fmt.Sprintf(`
UPDATE user_messages_legacy
SET seen = 1
WHERE id IN (%s)
`, inVector),
idsArgs...)
if err != nil {
return err
}
// Update denormalized count
_, err = tx.Exec(
`UPDATE chats
SET unviewed_message_count =
(SELECT COUNT(1)
FROM user_messages_legacy
WHERE local_chat_id = ? AND seen = 0)
WHERE id = ?`, chatID, chatID)
return err
}
@ -335,10 +406,11 @@ func (db sqlitePersistence) UpdateMessageOutgoingStatus(id string, newOutgoingSt
}
// BlockContact updates a contact, deletes all the messages and 1-to-1 chat, updates the unread messages count and returns a map with the new count
func (db sqlitePersistence) BlockContact(contact Contact) (chats []*Chat, err error) {
func (db sqlitePersistence) BlockContact(contact Contact) ([]*Chat, error) {
var chats []*Chat
tx, err := db.db.BeginTx(context.Background(), &sql.TxOptions{})
if err != nil {
return
return nil, err
}
defer func() {
if err == nil {
@ -357,36 +429,69 @@ func (db sqlitePersistence) BlockContact(contact Contact) (chats []*Chat, err er
contact.ID,
)
if err != nil {
return
return nil, err
}
// Update contact
err = db.SaveContact(contact, tx)
if err != nil {
return
return nil, err
}
// Delete one-to-one chat
_, err = tx.Exec("DELETE FROM chats WHERE id = ?", contact.ID)
if err != nil {
return
return nil, err
}
// Recalculate denormalized fields
_, err = tx.Exec(`
UPDATE chats
SET
unviewed_message_count = (SELECT COUNT(1) FROM user_messages_legacy WHERE seen = 0 AND chat_id = chats.id),
last_message_content = (SELECT content from user_messages_legacy WHERE chat_id = chats.id ORDER BY clock_value DESC LIMIT 1),
last_message_timestamp = (SELECT timestamp from user_messages_legacy WHERE chat_id = chats.id ORDER BY clock_value DESC LIMIT 1),
last_message_clock_value = (SELECT clock_value from user_messages_legacy WHERE chat_id = chats.id ORDER BY clock_value DESC LIMIT 1),
last_message_content_type = (SELECT content_type from user_messages_legacy WHERE chat_id = chats.id ORDER BY clock_value DESC LIMIT 1)
`)
unviewed_message_count = (SELECT COUNT(1) FROM user_messages_legacy WHERE seen = 0 AND local_chat_id = chats.id)`)
if err != nil {
return
return nil, err
}
// return the updated chats
chats, err = db.chats(tx)
return
if err != nil {
return nil, err
}
for _, c := range chats {
var lastMessageID string
row := tx.QueryRow(`SELECT id FROM user_messages_legacy WHERE local_chat_id = ? ORDER BY clock_value DESC LIMIT 1`, c.ID)
switch err := row.Scan(&lastMessageID); err {
case nil:
message, err := db.messageByID(tx, lastMessageID)
if err != nil {
return nil, err
}
if message != nil {
encodedMessage, err := json.Marshal(message)
if err != nil {
return nil, err
}
_, err = tx.Exec(`UPDATE chats SET last_message = ? WHERE id = ?`, encodedMessage, c.ID)
if err != nil {
return nil, err
}
c.LastMessage = encodedMessage
}
case sql.ErrNoRows:
// Reset LastMessage
_, err = tx.Exec(`UPDATE chats SET last_message = NULL WHERE id = ?`, c.ID)
if err != nil {
return nil, err
}
c.LastMessage = nil
default:
return nil, err
}
}
return chats, err
}

View file

@ -9,6 +9,7 @@ import (
"strings"
"testing"
"github.com/status-im/status-go/protocol/protobuf"
"github.com/status-im/status-go/protocol/sqlite"
"github.com/stretchr/testify/require"
)
@ -84,19 +85,24 @@ func TestMessageByChatID(t *testing.T) {
var messages []*Message
for i := 0; i < count; i++ {
messages = append(messages, &Message{
ID: strconv.Itoa(i),
ChatID: chatID,
From: "me",
ClockValue: int64(i),
ID: strconv.Itoa(i),
LocalChatID: chatID,
ChatMessage: protobuf.ChatMessage{
Clock: uint64(i),
},
From: "me",
})
// Add some other chats.
if count%5 == 0 {
messages = append(messages, &Message{
ID: strconv.Itoa(count + i),
ChatID: "other-chat",
From: "me",
ClockValue: int64(i),
ID: strconv.Itoa(count + i),
LocalChatID: "other-chat",
ChatMessage: protobuf.ChatMessage{
Clock: uint64(i),
},
From: "me",
})
}
}
@ -106,10 +112,13 @@ func TestMessageByChatID(t *testing.T) {
allCount := count + outOfOrderCount
for i := 0; i < pageSize+1; i++ {
messages = append(messages, &Message{
ID: strconv.Itoa(count*2 + i),
ChatID: chatID,
From: "me",
ClockValue: int64(i), // use very old clock values
ID: strconv.Itoa(count*2 + i),
LocalChatID: chatID,
ChatMessage: protobuf.ChatMessage{
Clock: uint64(i),
},
From: "me",
})
}
@ -143,7 +152,7 @@ func TestMessageByChatID(t *testing.T) {
t,
// Verify descending order.
sort.SliceIsSorted(result, func(i, j int) bool {
return result[i].ClockValue > result[j].ClockValue
return result[i].Clock > result[j].Clock
}),
)
}
@ -154,28 +163,35 @@ func TestMessageReplies(t *testing.T) {
p := sqlitePersistence{db: db}
chatID := "super-chat"
message1 := &Message{
ID: "id-1",
ChatID: chatID,
Content: "content-1",
From: "1",
ClockValue: int64(1),
ID: "id-1",
LocalChatID: chatID,
ChatMessage: protobuf.ChatMessage{
Text: "content-1",
Clock: uint64(1),
},
From: "1",
}
message2 := &Message{
ID: "id-2",
ChatID: chatID,
Content: "content-2",
From: "2",
ClockValue: int64(2),
ReplyTo: "id-1",
ID: "id-2",
LocalChatID: chatID,
ChatMessage: protobuf.ChatMessage{
Text: "content-2",
Clock: uint64(2),
ResponseTo: "id-1",
},
From: "2",
}
message3 := &Message{
ID: "id-3",
ChatID: chatID,
Content: "content-3",
From: "3",
ClockValue: int64(3),
ReplyTo: "non-existing",
ID: "id-3",
LocalChatID: chatID,
ChatMessage: protobuf.ChatMessage{
Text: "content-3",
Clock: uint64(3),
ResponseTo: "non-existing",
},
From: "3",
}
messages := []*Message{message1, message2, message3}
@ -186,22 +202,22 @@ func TestMessageReplies(t *testing.T) {
retrievedMessages, _, err := p.MessageByChatID(chatID, "", 10)
require.NoError(t, err)
require.Equal(t, "non-existing", retrievedMessages[0].ReplyTo)
require.Equal(t, "non-existing", retrievedMessages[0].ResponseTo)
require.Nil(t, retrievedMessages[0].QuotedMessage)
require.Equal(t, "id-1", retrievedMessages[1].ReplyTo)
require.Equal(t, &QuotedMessage{From: "1", Content: "content-1"}, retrievedMessages[1].QuotedMessage)
require.Equal(t, "id-1", retrievedMessages[1].ResponseTo)
require.Equal(t, &QuotedMessage{From: "1", Text: "content-1"}, retrievedMessages[1].QuotedMessage)
require.Equal(t, "", retrievedMessages[2].ReplyTo)
require.Equal(t, "", retrievedMessages[2].ResponseTo)
require.Nil(t, retrievedMessages[2].QuotedMessage)
}
func TestMessageByChatIDWithTheSameClockValues(t *testing.T) {
func TestMessageByChatIDWithTheSameClocks(t *testing.T) {
db, err := openTestDB()
require.NoError(t, err)
p := sqlitePersistence{db: db}
chatID := "super-chat"
clockValues := []int64{10, 10, 9, 9, 9, 11, 12, 11, 100000, 6, 4, 5, 5, 5, 5}
clockValues := []uint64{10, 10, 9, 9, 9, 11, 12, 11, 100000, 6, 4, 5, 5, 5, 5}
count := len(clockValues)
pageSize := 2
@ -209,10 +225,12 @@ func TestMessageByChatIDWithTheSameClockValues(t *testing.T) {
for i, clock := range clockValues {
messages = append(messages, &Message{
ID: strconv.Itoa(i),
ChatID: chatID,
From: "me",
ClockValue: clock,
ID: strconv.Itoa(i),
LocalChatID: chatID,
ChatMessage: protobuf.ChatMessage{
Clock: clock,
},
From: "me",
})
}
@ -242,16 +260,16 @@ func TestMessageByChatIDWithTheSameClockValues(t *testing.T) {
require.Empty(t, cursor) // for loop should exit because of cursor being empty
require.Len(t, result, count)
// Verify the order.
expectedClockValues := make([]int64, len(clockValues))
copy(expectedClockValues, clockValues)
sort.Slice(expectedClockValues, func(i, j int) bool {
return expectedClockValues[i] > expectedClockValues[j]
expectedClocks := make([]uint64, len(clockValues))
copy(expectedClocks, clockValues)
sort.Slice(expectedClocks, func(i, j int) bool {
return expectedClocks[i] > expectedClocks[j]
})
resultClockValues := make([]int64, 0, len(clockValues))
resultClocks := make([]uint64, 0, len(clockValues))
for _, m := range result {
resultClockValues = append(resultClockValues, m.ClockValue)
resultClocks = append(resultClocks, m.Clock)
}
require.EqualValues(t, expectedClockValues, resultClockValues)
require.EqualValues(t, expectedClocks, resultClocks)
}
func TestDeleteMessageByID(t *testing.T) {
@ -299,6 +317,7 @@ func TestDeleteMessagesByChatID(t *testing.T) {
}
func TestMarkMessageSeen(t *testing.T) {
chatID := "test-chat"
db, err := openTestDB()
require.NoError(t, err)
p := sqlitePersistence{db: db}
@ -311,7 +330,7 @@ func TestMarkMessageSeen(t *testing.T) {
require.NoError(t, err)
require.False(t, m.Seen)
err = p.MarkMessagesSeen(m.ID)
err = p.MarkMessagesSeen(chatID, []string{m.ID})
require.NoError(t, err)
m, err = p.MessageByID(id)
@ -348,12 +367,12 @@ func TestSetContactGeneratedData(t *testing.T) {
LastUpdated: 20,
SystemTags: []string{"1", "2"},
DeviceInfo: []ContactDeviceInfo{
{
ContactDeviceInfo{
InstallationID: "1",
Timestamp: 2,
FCMToken: "token",
},
{
ContactDeviceInfo{
InstallationID: "2",
Timestamp: 3,
FCMToken: "token-2",
@ -377,7 +396,7 @@ func TestSetContactGeneratedData(t *testing.T) {
err = p.SaveContact(existingContact, nil)
require.NoError(t, err)
err = p.SetContactsGeneratedData([]Contact{existingContactUpdate, nonExistingContactUpdate}, nil)
err = p.SetContactsGeneratedData([]*Contact{&existingContactUpdate, &nonExistingContactUpdate}, nil)
require.NoError(t, err)
allContacts, err := p.Contacts()
@ -401,9 +420,10 @@ func openTestDB() (*sql.DB, error) {
}
func insertMinimalMessage(p sqlitePersistence, id string) error {
return p.SaveMessagesLegacy([]*Message{{
ID: id,
ChatID: "chat-id",
From: "me",
return p.SaveMessagesLegacy([]*Message{&Message{
ID: id,
LocalChatID: "chat-id",
ChatMessage: protobuf.ChatMessage{Text: "some-text"},
From: "me",
}})
}

View file

@ -0,0 +1,421 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// source: message.proto
package protobuf
import (
fmt "fmt"
proto "github.com/golang/protobuf/proto"
math "math"
)
// Reference imports to suppress errors if they are not otherwise used.
var _ = proto.Marshal
var _ = fmt.Errorf
var _ = math.Inf
// This is a compile-time assertion to ensure that this generated file
// is compatible with the proto package it is being compiled against.
// A compilation error at this line likely means your copy of the
// proto package needs to be updated.
const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package
type ChatMessage_MessageType int32
const (
ChatMessage_ONE_TO_ONE ChatMessage_MessageType = 0
ChatMessage_PUBLIC_GROUP ChatMessage_MessageType = 1
ChatMessage_PRIVATE_GROUP ChatMessage_MessageType = 2
// Only local
ChatMessage_SYSTEM_MESSAGE_PRIVATE_GROUP ChatMessage_MessageType = 3
)
var ChatMessage_MessageType_name = map[int32]string{
0: "ONE_TO_ONE",
1: "PUBLIC_GROUP",
2: "PRIVATE_GROUP",
3: "SYSTEM_MESSAGE_PRIVATE_GROUP",
}
var ChatMessage_MessageType_value = map[string]int32{
"ONE_TO_ONE": 0,
"PUBLIC_GROUP": 1,
"PRIVATE_GROUP": 2,
"SYSTEM_MESSAGE_PRIVATE_GROUP": 3,
}
func (x ChatMessage_MessageType) String() string {
return proto.EnumName(ChatMessage_MessageType_name, int32(x))
}
func (ChatMessage_MessageType) EnumDescriptor() ([]byte, []int) {
return fileDescriptor_33c57e4bae7b9afd, []int{1, 0}
}
type ChatMessage_ContentType int32
const (
ChatMessage_TEXT_PLAIN ChatMessage_ContentType = 0
ChatMessage_STICKER ChatMessage_ContentType = 1
ChatMessage_STATUS ChatMessage_ContentType = 2
ChatMessage_EMOJI ChatMessage_ContentType = 3
ChatMessage_COMMAND ChatMessage_ContentType = 4
ChatMessage_COMMAND_REQUEST ChatMessage_ContentType = 5
)
var ChatMessage_ContentType_name = map[int32]string{
0: "TEXT_PLAIN",
1: "STICKER",
2: "STATUS",
3: "EMOJI",
4: "COMMAND",
5: "COMMAND_REQUEST",
}
var ChatMessage_ContentType_value = map[string]int32{
"TEXT_PLAIN": 0,
"STICKER": 1,
"STATUS": 2,
"EMOJI": 3,
"COMMAND": 4,
"COMMAND_REQUEST": 5,
}
func (x ChatMessage_ContentType) String() string {
return proto.EnumName(ChatMessage_ContentType_name, int32(x))
}
func (ChatMessage_ContentType) EnumDescriptor() ([]byte, []int) {
return fileDescriptor_33c57e4bae7b9afd, []int{1, 1}
}
type ApplicationMetadataMessage_MessageType int32
const (
ApplicationMetadataMessage_TEXT_MESSAGE ApplicationMetadataMessage_MessageType = 0
ApplicationMetadataMessage_CONTACT_REQUEST ApplicationMetadataMessage_MessageType = 1
ApplicationMetadataMessage_MEMBERSHIP_UPDATE ApplicationMetadataMessage_MessageType = 2
ApplicationMetadataMessage_PAIR_INSTALLATION ApplicationMetadataMessage_MessageType = 3
ApplicationMetadataMessage_SYNC_INSTALLATION ApplicationMetadataMessage_MessageType = 4
)
var ApplicationMetadataMessage_MessageType_name = map[int32]string{
0: "TEXT_MESSAGE",
1: "CONTACT_REQUEST",
2: "MEMBERSHIP_UPDATE",
3: "PAIR_INSTALLATION",
4: "SYNC_INSTALLATION",
}
var ApplicationMetadataMessage_MessageType_value = map[string]int32{
"TEXT_MESSAGE": 0,
"CONTACT_REQUEST": 1,
"MEMBERSHIP_UPDATE": 2,
"PAIR_INSTALLATION": 3,
"SYNC_INSTALLATION": 4,
}
func (x ApplicationMetadataMessage_MessageType) String() string {
return proto.EnumName(ApplicationMetadataMessage_MessageType_name, int32(x))
}
func (ApplicationMetadataMessage_MessageType) EnumDescriptor() ([]byte, []int) {
return fileDescriptor_33c57e4bae7b9afd, []int{2, 0}
}
type StickerMessage struct {
Hash string `protobuf:"bytes,1,opt,name=hash,proto3" json:"hash,omitempty"`
Pack int32 `protobuf:"varint,2,opt,name=pack,proto3" json:"pack,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *StickerMessage) Reset() { *m = StickerMessage{} }
func (m *StickerMessage) String() string { return proto.CompactTextString(m) }
func (*StickerMessage) ProtoMessage() {}
func (*StickerMessage) Descriptor() ([]byte, []int) {
return fileDescriptor_33c57e4bae7b9afd, []int{0}
}
func (m *StickerMessage) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_StickerMessage.Unmarshal(m, b)
}
func (m *StickerMessage) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_StickerMessage.Marshal(b, m, deterministic)
}
func (m *StickerMessage) XXX_Merge(src proto.Message) {
xxx_messageInfo_StickerMessage.Merge(m, src)
}
func (m *StickerMessage) XXX_Size() int {
return xxx_messageInfo_StickerMessage.Size(m)
}
func (m *StickerMessage) XXX_DiscardUnknown() {
xxx_messageInfo_StickerMessage.DiscardUnknown(m)
}
var xxx_messageInfo_StickerMessage proto.InternalMessageInfo
func (m *StickerMessage) GetHash() string {
if m != nil {
return m.Hash
}
return ""
}
func (m *StickerMessage) GetPack() int32 {
if m != nil {
return m.Pack
}
return 0
}
type ChatMessage struct {
// Lamport timestamp of the chat message
Clock uint64 `protobuf:"varint,1,opt,name=clock,proto3" json:"clock,omitempty"`
// Unix timestamps in milliseconds, currently not used as we use whisper as more reliable, but here
// so that we don't rely on it
Timestamp uint64 `protobuf:"varint,2,opt,name=timestamp,proto3" json:"timestamp,omitempty"`
// Text of the message
Text string `protobuf:"bytes,3,opt,name=text,proto3" json:"text,omitempty"`
// Id of the message that we are replying to
ResponseTo string `protobuf:"bytes,4,opt,name=response_to,json=responseTo,proto3" json:"response_to,omitempty"`
// Ens name of the sender
EnsName string `protobuf:"bytes,5,opt,name=ens_name,json=ensName,proto3" json:"ens_name,omitempty"`
// Chat id, this field is symmetric for public-chats and private group chats,
// but asymmetric in case of one-to-ones, as the sender will use the chat-id
// of the received, while the receiver will use the chat-id of the sender.
// Probably should be the concatenation of sender-pk & receiver-pk in alphabetical order
ChatId string `protobuf:"bytes,6,opt,name=chat_id,json=chatId,proto3" json:"chat_id,omitempty"`
// The type of message (public/one-to-one/private-group-chat)
MessageType ChatMessage_MessageType `protobuf:"varint,7,opt,name=message_type,json=messageType,proto3,enum=protobuf.ChatMessage_MessageType" json:"message_type,omitempty"`
// The type of the content of the message
ContentType ChatMessage_ContentType `protobuf:"varint,8,opt,name=content_type,json=contentType,proto3,enum=protobuf.ChatMessage_ContentType" json:"content_type,omitempty"`
// Types that are valid to be assigned to Payload:
// *ChatMessage_Sticker
Payload isChatMessage_Payload `protobuf_oneof:"payload"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *ChatMessage) Reset() { *m = ChatMessage{} }
func (m *ChatMessage) String() string { return proto.CompactTextString(m) }
func (*ChatMessage) ProtoMessage() {}
func (*ChatMessage) Descriptor() ([]byte, []int) {
return fileDescriptor_33c57e4bae7b9afd, []int{1}
}
func (m *ChatMessage) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_ChatMessage.Unmarshal(m, b)
}
func (m *ChatMessage) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_ChatMessage.Marshal(b, m, deterministic)
}
func (m *ChatMessage) XXX_Merge(src proto.Message) {
xxx_messageInfo_ChatMessage.Merge(m, src)
}
func (m *ChatMessage) XXX_Size() int {
return xxx_messageInfo_ChatMessage.Size(m)
}
func (m *ChatMessage) XXX_DiscardUnknown() {
xxx_messageInfo_ChatMessage.DiscardUnknown(m)
}
var xxx_messageInfo_ChatMessage proto.InternalMessageInfo
func (m *ChatMessage) GetClock() uint64 {
if m != nil {
return m.Clock
}
return 0
}
func (m *ChatMessage) GetTimestamp() uint64 {
if m != nil {
return m.Timestamp
}
return 0
}
func (m *ChatMessage) GetText() string {
if m != nil {
return m.Text
}
return ""
}
func (m *ChatMessage) GetResponseTo() string {
if m != nil {
return m.ResponseTo
}
return ""
}
func (m *ChatMessage) GetEnsName() string {
if m != nil {
return m.EnsName
}
return ""
}
func (m *ChatMessage) GetChatId() string {
if m != nil {
return m.ChatId
}
return ""
}
func (m *ChatMessage) GetMessageType() ChatMessage_MessageType {
if m != nil {
return m.MessageType
}
return ChatMessage_ONE_TO_ONE
}
func (m *ChatMessage) GetContentType() ChatMessage_ContentType {
if m != nil {
return m.ContentType
}
return ChatMessage_TEXT_PLAIN
}
type isChatMessage_Payload interface {
isChatMessage_Payload()
}
type ChatMessage_Sticker struct {
Sticker *StickerMessage `protobuf:"bytes,9,opt,name=sticker,proto3,oneof"`
}
func (*ChatMessage_Sticker) isChatMessage_Payload() {}
func (m *ChatMessage) GetPayload() isChatMessage_Payload {
if m != nil {
return m.Payload
}
return nil
}
func (m *ChatMessage) GetSticker() *StickerMessage {
if x, ok := m.GetPayload().(*ChatMessage_Sticker); ok {
return x.Sticker
}
return nil
}
// XXX_OneofWrappers is for the internal use of the proto package.
func (*ChatMessage) XXX_OneofWrappers() []interface{} {
return []interface{}{
(*ChatMessage_Sticker)(nil),
}
}
type ApplicationMetadataMessage struct {
// Signature of the payload field
Signature []byte `protobuf:"bytes,1,opt,name=signature,proto3" json:"signature,omitempty"`
// This is the encoded protobuf of the application level message, i.e ChatMessage
Payload []byte `protobuf:"bytes,2,opt,name=payload,proto3" json:"payload,omitempty"`
// The type of protobuf message sent
MessageType ApplicationMetadataMessage_MessageType `protobuf:"varint,3,opt,name=message_type,json=messageType,proto3,enum=protobuf.ApplicationMetadataMessage_MessageType" json:"message_type,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *ApplicationMetadataMessage) Reset() { *m = ApplicationMetadataMessage{} }
func (m *ApplicationMetadataMessage) String() string { return proto.CompactTextString(m) }
func (*ApplicationMetadataMessage) ProtoMessage() {}
func (*ApplicationMetadataMessage) Descriptor() ([]byte, []int) {
return fileDescriptor_33c57e4bae7b9afd, []int{2}
}
func (m *ApplicationMetadataMessage) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_ApplicationMetadataMessage.Unmarshal(m, b)
}
func (m *ApplicationMetadataMessage) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_ApplicationMetadataMessage.Marshal(b, m, deterministic)
}
func (m *ApplicationMetadataMessage) XXX_Merge(src proto.Message) {
xxx_messageInfo_ApplicationMetadataMessage.Merge(m, src)
}
func (m *ApplicationMetadataMessage) XXX_Size() int {
return xxx_messageInfo_ApplicationMetadataMessage.Size(m)
}
func (m *ApplicationMetadataMessage) XXX_DiscardUnknown() {
xxx_messageInfo_ApplicationMetadataMessage.DiscardUnknown(m)
}
var xxx_messageInfo_ApplicationMetadataMessage proto.InternalMessageInfo
func (m *ApplicationMetadataMessage) GetSignature() []byte {
if m != nil {
return m.Signature
}
return nil
}
func (m *ApplicationMetadataMessage) GetPayload() []byte {
if m != nil {
return m.Payload
}
return nil
}
func (m *ApplicationMetadataMessage) GetMessageType() ApplicationMetadataMessage_MessageType {
if m != nil {
return m.MessageType
}
return ApplicationMetadataMessage_TEXT_MESSAGE
}
func init() {
proto.RegisterEnum("protobuf.ChatMessage_MessageType", ChatMessage_MessageType_name, ChatMessage_MessageType_value)
proto.RegisterEnum("protobuf.ChatMessage_ContentType", ChatMessage_ContentType_name, ChatMessage_ContentType_value)
proto.RegisterEnum("protobuf.ApplicationMetadataMessage_MessageType", ApplicationMetadataMessage_MessageType_name, ApplicationMetadataMessage_MessageType_value)
proto.RegisterType((*StickerMessage)(nil), "protobuf.StickerMessage")
proto.RegisterType((*ChatMessage)(nil), "protobuf.ChatMessage")
proto.RegisterType((*ApplicationMetadataMessage)(nil), "protobuf.ApplicationMetadataMessage")
}
func init() { proto.RegisterFile("message.proto", fileDescriptor_33c57e4bae7b9afd) }
var fileDescriptor_33c57e4bae7b9afd = []byte{
// 563 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x7c, 0x52, 0x5f, 0x6f, 0xda, 0x3e,
0x14, 0x25, 0x10, 0xa0, 0xdc, 0xd0, 0xfe, 0x5c, 0xff, 0x36, 0x2d, 0x9b, 0x2a, 0x8d, 0xf1, 0xc4,
0x13, 0x9a, 0xba, 0x3d, 0xec, 0x35, 0x4d, 0xad, 0x36, 0x1b, 0xf9, 0x33, 0xdb, 0x4c, 0xeb, 0x93,
0xe5, 0x06, 0xaf, 0xa0, 0x96, 0x24, 0x22, 0xae, 0x34, 0xbe, 0xcf, 0x3e, 0xc9, 0x3e, 0xd9, 0x14,
0x07, 0x0a, 0x4c, 0xea, 0x9e, 0xec, 0x73, 0x7c, 0x7d, 0xee, 0xbd, 0xe7, 0x5e, 0x38, 0x5e, 0xaa,
0xb2, 0x94, 0x77, 0x6a, 0x5c, 0xac, 0x72, 0x9d, 0xe3, 0x23, 0x73, 0xdc, 0x3e, 0xfe, 0x18, 0x7e,
0x82, 0x13, 0xa6, 0x17, 0xe9, 0xbd, 0x5a, 0x85, 0x75, 0x04, 0xc6, 0x60, 0xcf, 0x65, 0x39, 0x77,
0xad, 0x81, 0x35, 0xea, 0x51, 0x73, 0xaf, 0xb8, 0x42, 0xa6, 0xf7, 0x6e, 0x73, 0x60, 0x8d, 0xda,
0xd4, 0xdc, 0x87, 0xbf, 0x6d, 0x70, 0xfc, 0xb9, 0xd4, 0xdb, 0x7f, 0x2f, 0xa0, 0x9d, 0x3e, 0xe4,
0xe9, 0xbd, 0xf9, 0x68, 0xd3, 0x1a, 0xe0, 0x33, 0xe8, 0xe9, 0xc5, 0x52, 0x95, 0x5a, 0x2e, 0x0b,
0xf3, 0xdd, 0xa6, 0x3b, 0xa2, 0xd2, 0xd5, 0xea, 0xa7, 0x76, 0x5b, 0x75, 0xae, 0xea, 0x8e, 0xdf,
0x82, 0xb3, 0x52, 0x65, 0x91, 0x67, 0xa5, 0x12, 0x3a, 0x77, 0x6d, 0xf3, 0x04, 0x5b, 0x8a, 0xe7,
0xf8, 0x35, 0x1c, 0xa9, 0xac, 0x14, 0x99, 0x5c, 0x2a, 0xb7, 0x6d, 0x5e, 0xbb, 0x2a, 0x2b, 0x23,
0xb9, 0x54, 0xf8, 0x15, 0x74, 0xd3, 0xb9, 0xd4, 0x62, 0x31, 0x73, 0x3b, 0xe6, 0xa5, 0x53, 0xc1,
0x60, 0x86, 0x2f, 0xa1, 0xbf, 0x71, 0x40, 0xe8, 0x75, 0xa1, 0xdc, 0xee, 0xc0, 0x1a, 0x9d, 0x9c,
0xbf, 0x1b, 0x6f, 0x7d, 0x18, 0xef, 0x75, 0x32, 0xde, 0x9c, 0x7c, 0x5d, 0x28, 0xea, 0x2c, 0x77,
0xa0, 0x52, 0x49, 0xf3, 0x4c, 0xab, 0x4c, 0xd7, 0x2a, 0x47, 0xff, 0x52, 0xf1, 0xeb, 0xc8, 0x5a,
0x25, 0xdd, 0x01, 0xfc, 0x11, 0xba, 0x65, 0x6d, 0xb9, 0xdb, 0x1b, 0x58, 0x23, 0xe7, 0xdc, 0xdd,
0x09, 0x1c, 0xce, 0xe2, 0xba, 0x41, 0xb7, 0xa1, 0xc3, 0x19, 0x38, 0x7b, 0x75, 0xe1, 0x13, 0x80,
0x38, 0x22, 0x82, 0xc7, 0x22, 0x8e, 0x08, 0x6a, 0x60, 0x04, 0xfd, 0x64, 0x7a, 0x31, 0x09, 0x7c,
0x71, 0x45, 0xe3, 0x69, 0x82, 0x2c, 0x7c, 0x0a, 0xc7, 0x09, 0x0d, 0xbe, 0x79, 0x9c, 0x6c, 0xa8,
0x26, 0x1e, 0xc0, 0x19, 0xbb, 0x61, 0x9c, 0x84, 0x22, 0x24, 0x8c, 0x79, 0x57, 0x44, 0x1c, 0x46,
0xb4, 0x86, 0x29, 0x38, 0x7b, 0x75, 0x57, 0x59, 0x38, 0xf9, 0xce, 0x45, 0x32, 0xf1, 0x82, 0x08,
0x35, 0xb0, 0x03, 0x5d, 0xc6, 0x03, 0xff, 0x0b, 0xa1, 0xc8, 0xc2, 0x00, 0x1d, 0xc6, 0x3d, 0x3e,
0x65, 0xa8, 0x89, 0x7b, 0xd0, 0x26, 0x61, 0xfc, 0x39, 0x40, 0xad, 0x2a, 0xc6, 0x8f, 0xc3, 0xd0,
0x8b, 0x2e, 0x91, 0x8d, 0xff, 0x87, 0xff, 0x36, 0x40, 0x50, 0xf2, 0x75, 0x4a, 0x18, 0x47, 0xed,
0x8b, 0x1e, 0x74, 0x0b, 0xb9, 0x7e, 0xc8, 0xe5, 0x6c, 0xf8, 0xab, 0x09, 0x6f, 0xbc, 0xa2, 0x78,
0x58, 0xa4, 0x52, 0x2f, 0xf2, 0x2c, 0x54, 0x5a, 0xce, 0xa4, 0x96, 0xdb, 0x9d, 0x3a, 0x83, 0x5e,
0xb9, 0xb8, 0xcb, 0xa4, 0x7e, 0x5c, 0x29, 0xb3, 0x57, 0x7d, 0xba, 0x23, 0xb0, 0xfb, 0xa4, 0x63,
0x36, 0xab, 0x4f, 0xb7, 0x10, 0xb3, 0xbf, 0xc6, 0xdd, 0x32, 0x83, 0x7a, 0xbf, 0xf3, 0xf9, 0xf9,
0x9c, 0xcf, 0x4e, 0x7f, 0xb8, 0x3e, 0x9c, 0x00, 0x82, 0xbe, 0xf1, 0x66, 0x63, 0x25, 0x6a, 0xd4,
0xcd, 0x46, 0xdc, 0xf3, 0xf9, 0x53, 0xb3, 0x16, 0x7e, 0x09, 0xa7, 0x21, 0x09, 0x2f, 0x08, 0x65,
0xd7, 0x41, 0x22, 0xa6, 0xc9, 0xa5, 0xc7, 0x09, 0x6a, 0x56, 0x74, 0xe2, 0x05, 0x54, 0x04, 0x11,
0xe3, 0xde, 0x64, 0xe2, 0xf1, 0x20, 0x8e, 0x50, 0xab, 0xa2, 0xd9, 0x4d, 0xe4, 0x1f, 0xd2, 0xf6,
0x6d, 0xc7, 0x14, 0xfe, 0xe1, 0x4f, 0x00, 0x00, 0x00, 0xff, 0xff, 0xf6, 0xa4, 0x11, 0xfe, 0xc7,
0x03, 0x00, 0x00,
}

View file

@ -0,0 +1,70 @@
syntax = "proto3";
package protobuf;
message StickerMessage {
string hash = 1;
int32 pack = 2;
}
message ChatMessage {
// Lamport timestamp of the chat message
uint64 clock = 1;
// Unix timestamps in milliseconds, currently not used as we use whisper as more reliable, but here
// so that we don't rely on it
uint64 timestamp = 2;
// Text of the message
string text = 3;
// Id of the message that we are replying to
string response_to = 4;
// Ens name of the sender
string ens_name = 5;
// Chat id, this field is symmetric for public-chats and private group chats,
// but asymmetric in case of one-to-ones, as the sender will use the chat-id
// of the received, while the receiver will use the chat-id of the sender.
// Probably should be the concatenation of sender-pk & receiver-pk in alphabetical order
string chat_id = 6;
// The type of message (public/one-to-one/private-group-chat)
MessageType message_type = 7;
// The type of the content of the message
ContentType content_type = 8;
oneof payload {
StickerMessage sticker = 9;
}
enum MessageType {
ONE_TO_ONE = 0;
PUBLIC_GROUP = 1;
PRIVATE_GROUP = 2;
// Only local
SYSTEM_MESSAGE_PRIVATE_GROUP = 3;
}
enum ContentType {
TEXT_PLAIN = 0;
STICKER = 1;
STATUS = 2;
EMOJI = 3;
COMMAND = 4;
COMMAND_REQUEST = 5;
}
}
message ApplicationMetadataMessage {
// Signature of the payload field
bytes signature = 1;
// This is the encoded protobuf of the application level message, i.e ChatMessage
bytes payload = 2;
// The type of protobuf message sent
MessageType message_type = 3;
enum MessageType {
TEXT_MESSAGE = 0;
CONTACT_REQUEST = 1;
MEMBERSHIP_UPDATE = 2;
PAIR_INSTALLATION = 3;
SYNC_INSTALLATION = 4;
}
}

View file

@ -1,11 +1,11 @@
package applicationmetadata
package protobuf
import (
"crypto/ecdsa"
"github.com/status-im/status-go/eth-node/crypto"
)
func (m *Message) RecoverKey() (*ecdsa.PublicKey, error) {
func (m *ApplicationMetadataMessage) RecoverKey() (*ecdsa.PublicKey, error) {
if m.Signature == nil {
return nil, nil
}

View file

@ -1,4 +1,4 @@
package applicationmetadata
package protobuf
import (
"github.com/golang/protobuf/proto"
@ -6,8 +6,8 @@ import (
//go:generate protoc --go_out=. ./message.proto
func Unmarshal(payload []byte) (*Message, error) {
var message Message
func Unmarshal(payload []byte) (*ApplicationMetadataMessage, error) {
var message ApplicationMetadataMessage
err := proto.Unmarshal(payload, &message)
if err != nil {
return nil, err

View file

@ -96,14 +96,11 @@ func newFiltersManager(db *sql.DB, w types.Whisper, privateKey *ecdsa.PrivateKey
func (s *filtersManager) Init(
chatIDs []string,
publicKeys []*ecdsa.PublicKey,
genericDiscoveryTopicEnabled bool,
) ([]*Filter, error) {
logger := s.logger.With(zap.String("site", "Init"))
logger.Info("initializing")
s.genericDiscoveryTopicEnabled = genericDiscoveryTopicEnabled
// Load our contact code.
_, err := s.LoadContactCode(&s.privateKey.PublicKey)
if err != nil {
@ -148,7 +145,7 @@ func (s *filtersManager) Init(
}
// DEPRECATED
func (s *filtersManager) InitWithFilters(filters []*Filter, genericDiscoveryTopicEnabled bool) ([]*Filter, error) {
func (s *filtersManager) InitWithFilters(filters []*Filter) ([]*Filter, error) {
var (
chatIDs []string
publicKeys []*ecdsa.PublicKey
@ -166,7 +163,7 @@ func (s *filtersManager) InitWithFilters(filters []*Filter, genericDiscoveryTopi
}
}
return s.Init(chatIDs, publicKeys, genericDiscoveryTopicEnabled)
return s.Init(chatIDs, publicKeys)
}
func (s *filtersManager) Reset() error {
@ -315,8 +312,8 @@ func (s *filtersManager) LoadNegotiated(secret types.NegotiatedSecret) (*Filter,
return chat, nil
}
// LoadDiscovery adds 1-2 discovery filters: one for generic discovery topic (if enabled)
// and one for the personal discovery topic.
// LoadDiscovery adds 1 discovery filter
// for the personal discovery topic.
func (s *filtersManager) LoadDiscovery() ([]*Filter, error) {
s.mutex.Lock()
defer s.mutex.Unlock()
@ -328,12 +325,6 @@ func (s *filtersManager) LoadDiscovery() ([]*Filter, error) {
expectedTopicCount := 1
if s.genericDiscoveryTopicEnabled {
expectedTopicCount = 2
if chat, ok := s.filters[discoveryTopic]; ok {
result = append(result, chat)
}
}
if chat, ok := s.filters[personalDiscoveryTopic]; ok {
result = append(result, chat)
}
@ -365,29 +356,6 @@ func (s *filtersManager) LoadDiscovery() ([]*Filter, error) {
s.filters[personalDiscoveryChat.ChatID] = personalDiscoveryChat
if s.genericDiscoveryTopicEnabled {
// Load generic discovery topic.
discoveryChat := &Filter{
ChatID: discoveryTopic,
Identity: identityStr,
Discovery: true,
Listen: true,
OneToOne: true,
}
discoveryResponse, err = s.addAsymmetric(discoveryChat.ChatID, true)
if err != nil {
return nil, err
}
discoveryChat.Topic = discoveryResponse.Topic
discoveryChat.FilterID = discoveryResponse.FilterID
s.filters[discoveryChat.ChatID] = discoveryChat
return []*Filter{discoveryChat, personalDiscoveryChat}, nil
}
return []*Filter{personalDiscoveryChat}, nil
}

View file

@ -85,21 +85,8 @@ func (s *FiltersManagerSuite) TearDownTest() {
_ = s.logger.Sync()
}
func (s *FiltersManagerSuite) TestDiscoveryAndPartitionedTopic() {
_, err := s.chats.Init(nil, nil, true)
s.Require().NoError(err)
s.Require().Equal(4, len(s.chats.filters), "It creates four filters")
discoveryFilter := s.chats.filters[discoveryTopic]
s.Require().NotNil(discoveryFilter, "It adds the discovery filter")
s.Require().True(discoveryFilter.Listen)
s.assertRequiredFilters()
}
func (s *FiltersManagerSuite) TestPartitionedTopicWithDiscoveryDisabled() {
_, err := s.chats.Init(nil, nil, false)
_, err := s.chats.Init(nil, nil)
s.Require().NoError(err)
s.Require().Equal(3, len(s.chats.filters), "It creates three filters")

View file

@ -86,7 +86,7 @@ func _1561059285_add_whisper_keysDownSql() (*asset, error) {
return nil, err
}
info := bindataFileInfo{name: "1561059285_add_whisper_keys.down.sql", size: 25, mode: os.FileMode(0644), modTime: time.Unix(1564484687, 0)}
info := bindataFileInfo{name: "1561059285_add_whisper_keys.down.sql", size: 25, mode: os.FileMode(0644), modTime: time.Unix(1574354941, 0)}
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xb9, 0x31, 0x3f, 0xce, 0xfa, 0x44, 0x36, 0x1b, 0xb0, 0xec, 0x5d, 0xb, 0x90, 0xb, 0x21, 0x4f, 0xd5, 0xe5, 0x50, 0xed, 0xc7, 0x43, 0xdf, 0x83, 0xb4, 0x3a, 0xc1, 0x55, 0x2e, 0x53, 0x7c, 0x67}}
return a, nil
}
@ -106,7 +106,7 @@ func _1561059285_add_whisper_keysUpSql() (*asset, error) {
return nil, err
}
info := bindataFileInfo{name: "1561059285_add_whisper_keys.up.sql", size: 112, mode: os.FileMode(0644), modTime: time.Unix(1564484687, 0)}
info := bindataFileInfo{name: "1561059285_add_whisper_keys.up.sql", size: 112, mode: os.FileMode(0644), modTime: time.Unix(1574354941, 0)}
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x25, 0x41, 0xc, 0x92, 0xdd, 0x9e, 0xff, 0x5d, 0xd0, 0x93, 0xe4, 0x24, 0x50, 0x29, 0xcf, 0xc6, 0xf7, 0x49, 0x3c, 0x73, 0xd9, 0x8c, 0xfa, 0xf2, 0xcf, 0xf6, 0x6f, 0xbc, 0x31, 0xe6, 0xf7, 0xe2}}
return a, nil
}
@ -126,7 +126,7 @@ func docGo() (*asset, error) {
return nil, err
}
info := bindataFileInfo{name: "doc.go", size: 373, mode: os.FileMode(0644), modTime: time.Unix(1564484687, 0)}
info := bindataFileInfo{name: "doc.go", size: 373, mode: os.FileMode(0644), modTime: time.Unix(1574354941, 0)}
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x23, 0x6a, 0xc1, 0xce, 0x94, 0xf6, 0xef, 0xf1, 0x97, 0x95, 0xb, 0x35, 0xaf, 0x5f, 0xe7, 0x5f, 0xac, 0x6e, 0xb8, 0xab, 0xba, 0xb5, 0x35, 0x97, 0x22, 0x36, 0x11, 0xce, 0x44, 0xfc, 0xfa, 0xac}}
return a, nil
}
@ -270,9 +270,9 @@ type bintree struct {
}
var _bintree = &bintree{nil, map[string]*bintree{
"1561059285_add_whisper_keys.down.sql": {_1561059285_add_whisper_keysDownSql, map[string]*bintree{}},
"1561059285_add_whisper_keys.up.sql": {_1561059285_add_whisper_keysUpSql, map[string]*bintree{}},
"doc.go": {docGo, map[string]*bintree{}},
"1561059285_add_whisper_keys.down.sql": &bintree{_1561059285_add_whisper_keysDownSql, map[string]*bintree{}},
"1561059285_add_whisper_keys.up.sql": &bintree{_1561059285_add_whisper_keysUpSql, map[string]*bintree{}},
"doc.go": &bintree{docGo, map[string]*bintree{}},
}}
// RestoreAsset restores an asset under the given directory.

View file

@ -58,13 +58,6 @@ func (m *whisperServiceKeysManager) RawSymKey(id string) ([]byte, error) {
type Option func(*WhisperServiceTransport) error
func SetGenericDiscoveryTopicSupport(val bool) Option {
return func(t *WhisperServiceTransport) error {
t.genericDiscoveryTopicEnabled = val
return nil
}
}
// WhisperServiceTransport is a transport based on Whisper service.
type WhisperServiceTransport struct {
shh types.Whisper
@ -75,8 +68,6 @@ type WhisperServiceTransport struct {
mailservers []string
envelopesMonitor *EnvelopesMonitor
genericDiscoveryTopicEnabled bool
}
// NewWhisperServiceTransport returns a new WhisperServiceTransport.
@ -131,7 +122,7 @@ func NewWhisperServiceTransport(
}
func (a *WhisperServiceTransport) InitFilters(chatIDs []string, publicKeys []*ecdsa.PublicKey) ([]*Filter, error) {
return a.filters.Init(chatIDs, publicKeys, a.genericDiscoveryTopicEnabled)
return a.filters.Init(chatIDs, publicKeys)
}
func (a *WhisperServiceTransport) Filters() []*Filter {
@ -140,7 +131,7 @@ func (a *WhisperServiceTransport) Filters() []*Filter {
// DEPRECATED
func (a *WhisperServiceTransport) LoadFilters(filters []*Filter) ([]*Filter, error) {
return a.filters.InitWithFilters(filters, a.genericDiscoveryTopicEnabled)
return a.filters.InitWithFilters(filters)
}
// DEPRECATED
@ -247,7 +238,7 @@ func (a *WhisperServiceTransport) RetrievePublicMessages(chatID string) ([]*type
func (a *WhisperServiceTransport) RetrievePrivateMessages(publicKey *ecdsa.PublicKey) ([]*types.Message, error) {
chats := a.filters.FiltersByPublicKey(publicKey)
discoveryChats, err := a.filters.Init(nil, nil, true)
discoveryChats, err := a.filters.Init(nil, nil)
if err != nil {
return nil, err
}

View file

@ -5,7 +5,7 @@ import "time"
const clockBumpInMs = int64(time.Minute / time.Millisecond)
// CalcMessageClock calculates a new clock value for Message.
// It is used to properly sort messages and accomodate the fact
// It is used to properly sort messages and accommodate the fact
// that time might be different on each device.
func CalcMessageClock(lastObservedValue int64, timeInMs TimestampInMs) int64 {
clock := lastObservedValue

View file

@ -1,38 +0,0 @@
package protocol
import (
"github.com/gomarkdown/markdown"
"github.com/gomarkdown/markdown/ast"
"strings"
"unicode"
"unicode/utf8"
)
// Content contains the chat ID and the actual text of a message.
type Content struct {
ChatID string `json:"chat_id"`
Text string `json:"text"`
ResponseTo string `json:"response-to"`
Name string `json:"name"` // the ENS name of the sender
ParsedText ast.Node `json:"parsedText"`
LineCount int `json:"lineCount"`
RTL bool `json:"rtl"`
}
// Check if the first character is Hebrew or Arabic or the RTL character
func isRTL(s string) bool {
first, _ := utf8.DecodeRuneInString(s)
return unicode.Is(unicode.Hebrew, first) ||
unicode.Is(unicode.Arabic, first) ||
// RTL character
first == '\u200f'
}
// PrepareContent return the parsed content of the message, the line-count and whether
// is a right-to-left message
func PrepareContent(content Content) Content {
content.ParsedText = markdown.Parse([]byte(content.Text), nil)
content.LineCount = strings.Count(content.Text, "\n")
content.RTL = isRTL(content.Text)
return content
}

View file

@ -14,7 +14,6 @@ import (
// More about Transit: https://github.com/cognitect/transit-format
func NewMessageDecoder(r io.Reader) *transit.Decoder {
decoder := transit.NewDecoder(r)
decoder.AddHandler(messageTag, statusMessageHandler)
decoder.AddHandler(pairMessageTag, pairMessageHandler)
decoder.AddHandler(membershipUpdateTag, membershipUpdateMessageHandler)
return decoder
@ -26,76 +25,6 @@ const (
membershipUpdateTag = "g5"
)
func statusMessageHandler(d transit.Decoder, value interface{}) (interface{}, error) {
taggedValue, ok := value.(transit.TaggedValue)
if !ok {
return nil, errors.New("not a tagged value")
}
values, ok := taggedValue.Value.([]interface{})
if !ok {
return nil, errors.New("tagged value does not contain values")
}
sm := Message{}
for idx, v := range values {
var ok bool
switch idx {
case 0:
sm.Text, ok = v.(string)
case 1:
sm.ContentT, ok = v.(string)
case 2:
var messageT transit.Keyword
messageT, ok = v.(transit.Keyword)
if ok {
sm.MessageT = string(messageT)
}
case 3:
sm.Clock, ok = v.(int64)
case 4:
var timestamp int64
timestamp, ok = v.(int64)
if ok {
sm.Timestamp = TimestampInMs(timestamp)
}
case 5:
var content map[interface{}]interface{}
content, ok = v.(map[interface{}]interface{})
if !ok {
break
}
for key, contentVal := range content {
var keyKeyword transit.Keyword
keyKeyword, ok = key.(transit.Keyword)
if !ok {
break
}
switch keyKeyword {
case transit.Keyword("text"):
sm.Content.Text, ok = contentVal.(string)
case transit.Keyword("response-to"):
sm.Content.ResponseTo, ok = contentVal.(string)
case transit.Keyword("name"):
sm.Content.Name, ok = contentVal.(string)
case transit.Keyword("chat-id"):
sm.Content.ChatID, ok = contentVal.(string)
}
}
default:
// skip any other values
ok = true
}
if !ok {
return nil, fmt.Errorf("invalid value for index: %d", idx)
}
}
return sm, nil
}
func pairMessageHandler(d transit.Decoder, value interface{}) (interface{}, error) {
taggedValue, ok := value.(transit.TaggedValue)
if !ok {
@ -196,21 +125,6 @@ func membershipUpdateMessageHandler(d transit.Decoder, value interface{}) (inter
m.Updates = append(m.Updates, update)
}
case 2:
if v == nil {
continue
}
messageI, err := statusMessageHandler(d, v)
if err != nil {
return nil, fmt.Errorf("failed to handle message in membership update: %v", err)
}
var message Message
message, ok = messageI.(Message)
if ok {
m.Message = &message
}
default:
// skip any other values
ok = true

View file

@ -10,7 +10,6 @@ import (
)
var (
messageType = reflect.TypeOf(Message{})
pairMessageType = reflect.TypeOf(PairMessage{})
membershipUpdateType = reflect.TypeOf(MembershipUpdateMessage{})
@ -22,7 +21,6 @@ var (
// More about Transit: https://github.com/cognitect/transit-format
func NewMessageEncoder(w io.Writer) *transit.Encoder {
encoder := transit.NewEncoder(w, false)
encoder.AddHandler(messageType, defaultMessageValueEncoder)
encoder.AddHandler(pairMessageType, defaultMessageValueEncoder)
encoder.AddHandler(membershipUpdateType, defaultMessageValueEncoder)
return encoder
@ -36,9 +34,6 @@ func (messageValueEncoder) IsStringable(reflect.Value) bool {
func (messageValueEncoder) Encode(e transit.Encoder, value reflect.Value, asString bool) error {
switch message := value.Interface().(type) {
case Message:
taggedValue := encodeMessageToTaggedValue(message)
return e.EncodeInterface(taggedValue, false)
case PairMessage:
taggedValue := transit.TaggedValue{
Tag: pairMessageTag,
@ -86,9 +81,6 @@ func (messageValueEncoder) Encode(e transit.Encoder, value reflect.Value, asStri
message.ChatID,
updatesList,
}
if message.Message != nil {
value = append(value, encodeMessageToTaggedValue(*message.Message))
}
taggedValue := transit.TaggedValue{
Tag: membershipUpdateTag,
Value: value,
@ -98,20 +90,3 @@ func (messageValueEncoder) Encode(e transit.Encoder, value reflect.Value, asStri
return errors.New("unknown message type to encode")
}
func encodeMessageToTaggedValue(m Message) transit.TaggedValue {
return transit.TaggedValue{
Tag: messageTag,
Value: []interface{}{
m.Text,
m.ContentT,
transit.Keyword(m.MessageT),
m.Clock,
m.Timestamp,
map[interface{}]interface{}{
transit.Keyword("chat-id"): m.Content.ChatID,
transit.Keyword("text"): m.Content.Text,
},
},
}
}

View file

@ -33,7 +33,6 @@ const (
type MembershipUpdateMessage struct {
ChatID string `json:"chatId"` // UUID concatenated with hex-encoded public key of the creator for the chat
Updates []MembershipUpdate `json:"updates"`
Message *Message `json:"message"` // optional message
}
// Verify makes sure that the received update message has a valid signature.

View file

@ -33,26 +33,9 @@ var (
},
},
},
Message: nil,
}
)
func TestDecodeMembershipUpdateMessage(t *testing.T) {
val, err := decodeTransitMessage(testMembershipUpdateMessageBytes)
require.NoError(t, err)
require.EqualValues(t, testMembershipUpdateMessageStruct, val)
}
func TestEncodeMembershipUpdateMessage(t *testing.T) {
data, err := EncodeMembershipUpdateMessage(testMembershipUpdateMessageStruct)
require.NoError(t, err)
// Decode it back to a struct and compare. Comparing bytes is not an option because,
// for example, map encoding is non-deterministic.
val, err := decodeTransitMessage(data)
require.NoError(t, err)
require.EqualValues(t, testMembershipUpdateMessageStruct, val)
}
func TestTupleMembershipUpdateEvent(t *testing.T) {
event1 := testMembershipUpdateMessageStruct.Updates[0].Events[0]
result1 := tupleMembershipUpdateEvent(event1)

View file

@ -1,29 +1,14 @@
package protocol
import (
"bytes"
"crypto/ecdsa"
"encoding/hex"
"encoding/json"
"strings"
"time"
"github.com/golang/protobuf/proto"
"github.com/pkg/errors"
"github.com/status-im/status-go/eth-node/crypto"
"github.com/status-im/status-go/eth-node/types"
)
const (
// ContentTypeTextPlain means that the message contains plain text.
ContentTypeTextPlain = "text/plain"
)
// Message types.
const (
MessageTypePublicGroup = "public-group-user-message"
MessageTypePrivate = "user-message"
MessageTypePrivateGroup = "group-user-message"
"github.com/status-im/status-go/protocol/protobuf"
)
var (
@ -60,95 +45,11 @@ const (
MessageRead Flags = 1 << iota
)
// Message is a chat message sent by an user.
type Message struct {
Text string `json:"text"` // TODO: why is this duplicated?
ContentT string `json:"content_type"`
MessageT string `json:"message_type"`
Clock int64 `json:"clock"` // lamport timestamp; see CalcMessageClock for more details
Timestamp TimestampInMs `json:"timestamp"`
Content Content `json:"content"`
Flags Flags `json:"-"`
ID []byte `json:"-"`
SigPubKey *ecdsa.PublicKey `json:"-"`
ChatID string `json:"-"` // reference to Chat.ID; not connected to Content.ChatID which is set by sender
}
func (m *Message) MarshalJSON() ([]byte, error) {
type MessageAlias Message
item := struct {
*MessageAlias
ID string `json:"id"`
}{
MessageAlias: (*MessageAlias)(m),
ID: "0x" + hex.EncodeToString(m.ID),
}
return json.Marshal(item)
}
// createTextMessage creates a Message.
func createTextMessage(data []byte, lastClock int64, chatID, messageType string) Message {
text := strings.TrimSpace(string(data))
ts := TimestampInMsFromTime(time.Now())
clock := CalcMessageClock(lastClock, ts)
return Message{
Text: text,
ContentT: ContentTypeTextPlain,
MessageT: messageType,
Clock: clock,
Timestamp: ts,
Content: Content{ChatID: chatID, Text: text},
}
}
// CreatePublicTextMessage creates a public text Message.
func CreatePublicTextMessage(data []byte, lastClock int64, chatID string) Message {
m := createTextMessage(data, lastClock, chatID, MessageTypePublicGroup)
return m
}
// CreatePrivateTextMessage creates a one-to-one message.
func CreatePrivateTextMessage(data []byte, lastClock int64, chatID string) Message {
return createTextMessage(data, lastClock, chatID, MessageTypePrivate)
}
// CreatePrivateGroupTextMessage creates a group message.
func CreatePrivateGroupTextMessage(data []byte, lastClock int64, chatID string) Message {
return createTextMessage(data, lastClock, chatID, MessageTypePrivateGroup)
}
func decodeTransitMessage(originalPayload []byte) (interface{}, error) {
payload := make([]byte, len(originalPayload))
copy(payload, originalPayload)
// This modifies the payload
buf := bytes.NewBuffer(payload)
decoder := NewMessageDecoder(buf)
value, err := decoder.Decode()
if err != nil {
return nil, err
}
return value, nil
}
// EncodeMessage encodes a Message using Transit serialization.
func EncodeMessage(value Message) ([]byte, error) {
var buf bytes.Buffer
encoder := NewMessageEncoder(&buf)
if err := encoder.Encode(value); err != nil {
return nil, err
}
return buf.Bytes(), nil
}
// MessageID calculates the messageID from author's compressed public key
// and not encrypted but encoded payload.
func MessageID(author *ecdsa.PublicKey, data []byte) types.HexBytes {
keyBytes := crypto.FromECDSAPub(author)
return crypto.Keccak256(append(keyBytes, data...))
return types.HexBytes(crypto.Keccak256(append(keyBytes, data...)))
}
// WrapMessageV1 wraps a payload into a protobuf message and signs it if an identity is provided
@ -162,7 +63,7 @@ func WrapMessageV1(payload []byte, identity *ecdsa.PrivateKey) ([]byte, error) {
}
}
message := &StatusProtocolMessage{
message := &protobuf.ApplicationMetadataMessage{
Signature: signature,
Payload: payload,
}

View file

@ -1,85 +0,0 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// source: message.proto
package protocol
import (
fmt "fmt"
proto "github.com/golang/protobuf/proto"
math "math"
)
// Reference imports to suppress errors if they are not otherwise used.
var _ = proto.Marshal
var _ = fmt.Errorf
var _ = math.Inf
// This is a compile-time assertion to ensure that this generated file
// is compatible with the proto package it is being compiled against.
// A compilation error at this line likely means your copy of the
// proto package needs to be updated.
const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package
type StatusProtocolMessage struct {
Signature []byte `protobuf:"bytes,4001,opt,name=signature,proto3" json:"signature,omitempty"`
Payload []byte `protobuf:"bytes,4002,opt,name=payload,proto3" json:"payload,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *StatusProtocolMessage) Reset() { *m = StatusProtocolMessage{} }
func (m *StatusProtocolMessage) String() string { return proto.CompactTextString(m) }
func (*StatusProtocolMessage) ProtoMessage() {}
func (*StatusProtocolMessage) Descriptor() ([]byte, []int) {
return fileDescriptor_33c57e4bae7b9afd, []int{0}
}
func (m *StatusProtocolMessage) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_StatusProtocolMessage.Unmarshal(m, b)
}
func (m *StatusProtocolMessage) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_StatusProtocolMessage.Marshal(b, m, deterministic)
}
func (m *StatusProtocolMessage) XXX_Merge(src proto.Message) {
xxx_messageInfo_StatusProtocolMessage.Merge(m, src)
}
func (m *StatusProtocolMessage) XXX_Size() int {
return xxx_messageInfo_StatusProtocolMessage.Size(m)
}
func (m *StatusProtocolMessage) XXX_DiscardUnknown() {
xxx_messageInfo_StatusProtocolMessage.DiscardUnknown(m)
}
var xxx_messageInfo_StatusProtocolMessage proto.InternalMessageInfo
func (m *StatusProtocolMessage) GetSignature() []byte {
if m != nil {
return m.Signature
}
return nil
}
func (m *StatusProtocolMessage) GetPayload() []byte {
if m != nil {
return m.Payload
}
return nil
}
func init() {
proto.RegisterType((*StatusProtocolMessage)(nil), "protocol.StatusProtocolMessage")
}
func init() { proto.RegisterFile("message.proto", fileDescriptor_33c57e4bae7b9afd) }
var fileDescriptor_33c57e4bae7b9afd = []byte{
// 109 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0xe2, 0xcd, 0x4d, 0x2d, 0x2e,
0x4e, 0x4c, 0x4f, 0xd5, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0xe2, 0x2e, 0x2e, 0x49, 0x2c, 0x29,
0x2d, 0x06, 0x73, 0x94, 0x02, 0xb9, 0x44, 0x83, 0xc1, 0xdc, 0x00, 0x10, 0x37, 0x39, 0x3f, 0xc7,
0x17, 0xa2, 0x56, 0x48, 0x96, 0x8b, 0xb3, 0x38, 0x33, 0x3d, 0x2f, 0xb1, 0xa4, 0xb4, 0x28, 0x55,
0x62, 0xa1, 0xbc, 0x02, 0xa3, 0x06, 0x4f, 0x10, 0x42, 0x44, 0x48, 0x92, 0x8b, 0xbd, 0x20, 0xb1,
0x32, 0x27, 0x3f, 0x31, 0x45, 0x62, 0x11, 0x44, 0x12, 0xc6, 0x4f, 0x62, 0x03, 0x9b, 0x6c, 0x0c,
0x08, 0x00, 0x00, 0xff, 0xff, 0x92, 0x1a, 0x92, 0xf0, 0x77, 0x00, 0x00, 0x00,
}

View file

@ -9,50 +9,6 @@ import (
"github.com/stretchr/testify/require"
)
var (
testMessageBytes = []byte(`["~#c4",["abc123","text/plain","~:public-group-user-message",154593077368201,1545930773682,["^ ","~:chat-id","testing-adamb","~:name", "test-name","~:response-to", "id","~:text","abc123"]]]`)
testMessageStruct = Message{
Text: "abc123",
ContentT: "text/plain",
MessageT: "public-group-user-message",
Clock: 154593077368201,
Timestamp: 1545930773682,
Content: Content{
ChatID: "testing-adamb",
Text: "abc123",
ResponseTo: "id",
Name: "test-name",
},
}
)
func TestDecodeTransitMessage(t *testing.T) {
val, err := decodeTransitMessage(testMessageBytes)
require.NoError(t, err)
require.EqualValues(t, testMessageStruct, val)
}
func BenchmarkDecodeTransitMessage(b *testing.B) {
_, err := decodeTransitMessage(testMessageBytes)
if err != nil {
b.Fatalf("failed to decode message: %v", err)
}
b.ResetTimer()
for n := 0; n < b.N; n++ {
_, _ = decodeTransitMessage(testMessageBytes)
}
data, err := EncodeMessage(testMessageStruct)
require.NoError(b, err)
// Decode it back to a struct because, for example, map encoding is non-deterministic
// and it is not possible to compare bytes.
val, err := decodeTransitMessage(data)
require.NoError(b, err)
require.EqualValues(b, testMessageStruct, val)
}
func TestMessageID(t *testing.T) {
key, err := crypto.GenerateKey()
require.NoError(t, err)

View file

@ -1,33 +0,0 @@
package protocol
import (
"testing"
"github.com/stretchr/testify/require"
)
var (
testPairMessageBytes = []byte(`["~#p2",["installation-id","desktop","name","token"]]`)
testPairMessageStruct = PairMessage{
Name: "name",
DeviceType: "desktop",
FCMToken: "token",
InstallationID: "installation-id",
}
)
func TestDecodePairMessage(t *testing.T) {
val, err := decodeTransitMessage(testPairMessageBytes)
require.NoError(t, err)
require.EqualValues(t, testPairMessageStruct, val)
}
func TestEncodePairMessage(t *testing.T) {
data, err := EncodePairMessage(testPairMessageStruct)
require.NoError(t, err)
// Decode it back to a struct because, for example, map encoding is non-deterministic
// and it is not possible to compare bytes.
val, err := decodeTransitMessage(data)
require.NoError(t, err)
require.EqualValues(t, testPairMessageStruct, val)
}

View file

@ -2,6 +2,7 @@ package protocol
import (
"crypto/ecdsa"
"encoding/json"
"log"
"github.com/golang/protobuf/proto"
@ -9,9 +10,9 @@ import (
"github.com/pkg/errors"
"github.com/status-im/status-go/eth-node/crypto"
"github.com/status-im/status-go/eth-node/types"
"github.com/status-im/status-go/protocol/applicationmetadata"
"github.com/status-im/status-go/protocol/datasync"
"github.com/status-im/status-go/protocol/encryption"
"github.com/status-im/status-go/protocol/protobuf"
)
type StatusMessageT int
@ -25,26 +26,43 @@ const (
// StatusMessage is any Status Protocol message.
type StatusMessage struct {
// TransportMessage is the parsed message received from the transport layer, i.e the input
TransportMessage *types.Message
TransportMessage *types.Message `json:"transportMessage"`
// MessageType is the type of application message contained
MessageType StatusMessageT
MessageType StatusMessageT `json:"-"`
// ParsedMessage is the parsed message by the application layer, i.e the output
ParsedMessage interface{}
ParsedMessage interface{} `json:"-"`
// TransportPayload is the payload as received from the transport layer
TransportPayload []byte
TransportPayload []byte `json:"-"`
// DecryptedPayload is the payload after having been processed by the encryption layer
DecryptedPayload []byte
DecryptedPayload []byte `json:"decryptedPayload"`
// ID is the canonical ID of the message
ID types.HexBytes
ID types.HexBytes `json:"id"`
// Hash is the transport layer hash
Hash []byte
Hash []byte `json:"-"`
// TransportLayerSigPubKey contains the public key provided by the transport layer
TransportLayerSigPubKey *ecdsa.PublicKey
TransportLayerSigPubKey *ecdsa.PublicKey `json:"-"`
// ApplicationMetadataLayerPubKey contains the public key provided by the application metadata layer
ApplicationMetadataLayerSigPubKey *ecdsa.PublicKey
ApplicationMetadataLayerSigPubKey *ecdsa.PublicKey `json:"-"`
}
// Temporary JSON marshaling for those messages that are not yet processed
// by the go code
func (m *StatusMessage) MarshalJSON() ([]byte, error) {
item := struct {
ID types.HexBytes `json:"id"`
Payload string `json:"payload"`
From types.HexBytes `json:"from"`
Timestamp uint32 `json:"timestamp"`
}{
ID: m.ID,
Payload: string(m.DecryptedPayload),
Timestamp: m.TransportMessage.Timestamp,
From: m.TransportMessage.Sig,
}
return json.Marshal(item)
}
// SigPubKey returns the most important signature, from the application layer to transport
@ -126,12 +144,9 @@ func (m *StatusMessage) HandleDatasync(datasync *datasync.DataSync) ([]*StatusMe
}
func (m *StatusMessage) HandleApplicationMetadata() error {
message, err := applicationmetadata.Unmarshal(m.DecryptedPayload)
// Not an applicationmetadata message, calculate ID using the previous
// signature
message, err := protobuf.Unmarshal(m.DecryptedPayload)
if err != nil {
m.ID = MessageID(m.SigPubKey(), m.DecryptedPayload)
return nil
return err
}
recoveredKey, err := message.RecoverKey()
@ -147,26 +162,18 @@ func (m *StatusMessage) HandleApplicationMetadata() error {
}
func (m *StatusMessage) HandleApplication() error {
value, err := decodeTransitMessage(m.DecryptedPayload)
if err != nil {
log.Printf("[message::DecodeMessage] could not decode message: %#x, err: %v", m.Hash, err.Error())
return err
}
m.ParsedMessage = value
switch m.ParsedMessage.(type) {
case Message:
m.MessageType = MessageT
case MembershipUpdateMessage:
m.MessageType = MembershipUpdateMessageT
case PairMessage:
m.MessageType = PairMessageT
// By default we null the parsed message field, as
// otherwise is populated with the raw transit and we are
// unable to marshal in case it contains maps
// as they have type map[interface{}]interface{}
default:
m.ParsedMessage = nil
// Try protobuf first
var message protobuf.ChatMessage
err := proto.Unmarshal(m.DecryptedPayload, &message)
if err != nil {
m.ParsedMessage = nil
log.Printf("[message::DecodeMessage] could not decode protobuf message: %#x, err: %v", m.Hash, err.Error())
} else {
m.MessageType = MessageT
m.ParsedMessage = message
return nil
}
return nil
}

View file

@ -34,6 +34,8 @@ type MailserverRequestGap struct {
type MailserverTopic struct {
Topic string `json:"topic"`
Discovery bool `json:"discovery?"`
Negotiated bool `json:"negotiated?"`
ChatIDs []string `json:"chat-ids"`
LastRequest int `json:"last-request"` // default is 1
}
@ -212,11 +214,15 @@ func (d *Database) AddTopic(topic MailserverTopic) error {
_, err := d.db.Exec(`INSERT OR REPLACE INTO mailserver_topics(
topic,
chat_ids,
last_request
) VALUES (?, ?, ?)`,
last_request,
discovery,
negotiated
) VALUES (?, ?, ?,?,?)`,
topic.Topic,
chatIDs,
topic.LastRequest,
topic.Discovery,
topic.Negotiated,
)
return err
}
@ -224,7 +230,7 @@ func (d *Database) AddTopic(topic MailserverTopic) error {
func (d *Database) Topics() ([]MailserverTopic, error) {
var result []MailserverTopic
rows, err := d.db.Query(`SELECT topic, chat_ids, last_request FROM mailserver_topics`)
rows, err := d.db.Query(`SELECT topic, chat_ids, last_request,discovery,negotiated FROM mailserver_topics`)
if err != nil {
return nil, err
}
@ -238,6 +244,8 @@ func (d *Database) Topics() ([]MailserverTopic, error) {
&t.Topic,
&chatIDs,
&t.LastRequest,
&t.Discovery,
&t.Negotiated,
); err != nil {
return nil, err
}

View file

@ -27,7 +27,6 @@ import (
"github.com/status-im/status-go/protocol"
"github.com/status-im/status-go/protocol/encryption/multidevice"
statustransp "github.com/status-im/status-go/protocol/transport/whisper"
statusprotomessage "github.com/status-im/status-go/protocol/v1"
)
const (
@ -444,10 +443,6 @@ func (api *PublicAPI) SendPublicMessage(ctx context.Context, msg SendPublicMessa
return api.service.messenger.SendRaw(ctx, chat, msg.Payload)
}
func (api *PublicAPI) PrepareContent(ctx context.Context, content statusprotomessage.Content) statusprotomessage.Content {
return api.service.messenger.PrepareContent(content)
}
// SendDirectMessage sends a 1:1 chat message to the underlying transport
// Message's payload is a transit encoded message.
// It's important to call PublicAPI.afterSend() so that the client receives a signal
@ -648,8 +643,8 @@ func (api *PublicAPI) ChatMessages(chatID, cursor string, limit int) (*Applicati
}, nil
}
func (api *PublicAPI) SaveMessages(messages []*protocol.Message) error {
return api.service.messenger.SaveMessages(messages)
func (api *PublicAPI) AddSystemMessages(messages []*protocol.Message) ([]*protocol.Message, error) {
return api.service.messenger.AddSystemMessages(messages)
}
func (api *PublicAPI) DeleteMessage(id string) error {
@ -660,14 +655,22 @@ func (api *PublicAPI) DeleteMessagesByChatID(id string) error {
return api.service.messenger.DeleteMessagesByChatID(id)
}
func (api *PublicAPI) MarkMessagesSeen(ids []string) error {
return api.service.messenger.MarkMessagesSeen(ids...)
func (api *PublicAPI) MarkMessagesSeen(chatID string, ids []string) error {
return api.service.messenger.MarkMessagesSeen(chatID, ids)
}
func (api *PublicAPI) UpdateMessageOutgoingStatus(id, newOutgoingStatus string) error {
return api.service.messenger.UpdateMessageOutgoingStatus(id, newOutgoingStatus)
}
func (api *PublicAPI) SendChatMessage(ctx context.Context, message *protocol.Message) (*protocol.MessengerResponse, error) {
return api.service.messenger.SendChatMessage(ctx, message)
}
func (api *PublicAPI) ReSendChatMessage(ctx context.Context, messageID string) (*protocol.MessengerResponse, error) {
return api.service.messenger.ReSendChatMessage(ctx, messageID)
}
// -----
// HELPER
// -----

View file

@ -4,7 +4,6 @@ import (
"context"
"crypto/ecdsa"
"database/sql"
"encoding/hex"
"fmt"
"os"
"path/filepath"
@ -12,7 +11,6 @@ import (
"github.com/status-im/status-go/logutils"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/node"
"github.com/ethereum/go-ethereum/p2p"
@ -163,87 +161,14 @@ func (s *Service) retrieveMessagesLoop(tick time.Duration, cancel <-chan struct{
for {
select {
case <-ticker.C:
chatWithMessages, err := s.messenger.RetrieveRawAll()
response, err := s.messenger.RetrieveAll()
if err != nil {
log.Error("failed to retrieve raw messages", "err", err)
continue
}
var messageIDs []string
for _, messages := range chatWithMessages {
for _, message := range messages {
messageIDs = append(messageIDs, message.ID.String())
}
if !response.IsEmpty() {
PublisherSignalHandler{}.NewMessages(response)
}
existingMessages, err := s.messenger.MessagesExist(messageIDs)
if err != nil {
log.Error("failed to check existing messages", "err", err)
continue
}
var signalMessages []*signal.Messages
for chat, messages := range chatWithMessages {
var dedupMessages []*dedup.DeduplicateMessage
// Filter out already saved messages
for _, message := range messages {
if !existingMessages[message.ID.String()] {
id := fmt.Sprintf("0x%s", hex.EncodeToString(crypto.FromECDSAPub(message.SigPubKey())))
identicon, err := protocol.Identicon(id)
if err != nil {
log.Error("failed to generate identicon", "err", err)
continue
}
alias, err := protocol.GenerateAlias(id)
if err != nil {
log.Error("failed to generate identicon", "err", err)
continue
}
dedupMessage := &dedup.DeduplicateMessage{
Metadata: dedup.Metadata{
Author: dedup.Author{
PublicKey: crypto.FromECDSAPub(message.SigPubKey()),
Alias: alias,
Identicon: identicon,
},
MessageID: message.ID,
EncryptionID: message.Hash,
},
Message: message.TransportMessage,
}
dedupMessage.Message.Payload = message.DecryptedPayload
dedupMessage.Payload = string(message.DecryptedPayload)
dedupMessage.ParsedMessage = message.ParsedMessage
dedupMessage.MessageType = message.MessageType
dedupMessages = append(dedupMessages, dedupMessage)
}
}
dedupMessages = s.deduplicator.Deduplicate(dedupMessages)
if len(dedupMessages) != 0 {
signalMessage := &signal.Messages{
Chat: chat,
Error: nil, // TODO: what is it needed for?
Messages: dedupMessages,
}
signalMessages = append(signalMessages, signalMessage)
}
}
log.Debug("retrieve messages loop", "messages", len(signalMessages))
if len(signalMessages) == 0 {
continue
}
PublisherSignalHandler{}.NewMessages(signalMessages)
case <-cancel:
return
}
@ -425,16 +350,9 @@ func buildMessengerOptions(config params.ShhextConfig, db *sql.DB, envelopesMoni
protocol.WithOnNegotiatedFilters(onNegotiatedFilters),
}
if !config.DisableGenericDiscoveryTopic {
options = append(options, protocol.WithGenericDiscoveryTopicSupport())
}
if config.DataSyncEnabled {
options = append(options, protocol.WithDatasync())
}
if config.SendV1Messages {
options = append(options, protocol.WithSendV1Messages())
}
return options
}

View file

@ -2,6 +2,7 @@ package shhext
import (
"github.com/status-im/status-go/eth-node/types"
"github.com/status-im/status-go/protocol"
"github.com/status-im/status-go/signal"
)
@ -43,6 +44,6 @@ func (h PublisherSignalHandler) WhisperFilterAdded(filters []*signal.Filter) {
signal.SendWhisperFilterAdded(filters)
}
func (h PublisherSignalHandler) NewMessages(messages []*signal.Messages) {
signal.SendNewMessages(messages)
func (h PublisherSignalHandler) NewMessages(response *protocol.MessengerResponse) {
signal.SendNewMessages(response)
}

View file

@ -4,6 +4,7 @@ import (
"encoding/hex"
"github.com/ethereum/go-ethereum/common/hexutil"
statusproto "github.com/status-im/status-go/protocol"
"github.com/status-im/status-go/services/shhext/dedup"
"github.com/status-im/status-go/eth-node/types"
@ -88,11 +89,6 @@ type WhisperFilterAddedSignal struct {
Filters []*Filter `json:"filters"`
}
// NewMessagesSignal notifies clients of new messages
type NewMessagesSignal struct {
Messages []*Messages `json:"messages"`
}
// SendEnvelopeSent triggered when envelope delivered at least to 1 peer.
func SendEnvelopeSent(identifiers [][]byte) {
var hexIdentifiers []hexutil.Bytes
@ -172,6 +168,6 @@ func SendWhisperFilterAdded(filters []*Filter) {
send(EventWhisperFilterAdded, WhisperFilterAddedSignal{Filters: filters})
}
func SendNewMessages(messages []*Messages) {
send(EventNewMessages, NewMessagesSignal{Messages: messages})
func SendNewMessages(response *statusproto.MessengerResponse) {
send(EventNewMessages, response)
}

View file

@ -97,7 +97,7 @@ func ConfigReadmeMd() (*asset, error) {
return nil, err
}
info := bindataFileInfo{name: "../config/README.md", size: 3330, mode: os.FileMode(0644), modTime: time.Unix(1564144050, 0)}
info := bindataFileInfo{name: "../config/README.md", size: 3330, mode: os.FileMode(0644), modTime: time.Unix(1573806410, 0)}
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x65, 0xb9, 0xf5, 0x6, 0xbe, 0x7d, 0x85, 0x3b, 0x8, 0xbc, 0x5c, 0x71, 0x85, 0x19, 0xd1, 0xde, 0x38, 0xb5, 0xe9, 0x90, 0x5c, 0x45, 0xb2, 0xa5, 0x8a, 0x91, 0xee, 0xeb, 0x1e, 0xb4, 0xa9, 0x8f}}
return a, nil
}
@ -117,7 +117,7 @@ func ConfigCliFleetEthBetaJson() (*asset, error) {
return nil, err
}
info := bindataFileInfo{name: "../config/cli/fleet-eth.beta.json", size: 3261, mode: os.FileMode(0644), modTime: time.Unix(1564144050, 0)}
info := bindataFileInfo{name: "../config/cli/fleet-eth.beta.json", size: 3261, mode: os.FileMode(0644), modTime: time.Unix(1573806410, 0)}
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x2b, 0xae, 0x42, 0x4b, 0xa4, 0xd9, 0x2, 0x69, 0x99, 0x29, 0x7e, 0x1, 0x4e, 0xd9, 0x58, 0x84, 0x28, 0x3a, 0x81, 0xc4, 0xde, 0x1d, 0xea, 0x51, 0xc8, 0x21, 0xff, 0x7b, 0xff, 0x23, 0x1c, 0x16}}
return a, nil
}
@ -137,7 +137,7 @@ func ConfigCliFleetEthStagingJson() (*asset, error) {
return nil, err
}
info := bindataFileInfo{name: "../config/cli/fleet-eth.staging.json", size: 1862, mode: os.FileMode(0644), modTime: time.Unix(1564144050, 0)}
info := bindataFileInfo{name: "../config/cli/fleet-eth.staging.json", size: 1862, mode: os.FileMode(0644), modTime: time.Unix(1573806410, 0)}
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xae, 0x85, 0xa1, 0x10, 0x16, 0x87, 0x10, 0x1c, 0xc3, 0xf4, 0xc7, 0xc, 0x2e, 0x51, 0xb7, 0x3, 0x61, 0x16, 0x99, 0x84, 0x3d, 0x5d, 0x82, 0x62, 0xfb, 0xf4, 0x5e, 0x19, 0xda, 0xb9, 0xaa, 0xc4}}
return a, nil
}
@ -157,7 +157,7 @@ func ConfigCliFleetEthTestJson() (*asset, error) {
return nil, err
}
info := bindataFileInfo{name: "../config/cli/fleet-eth.test.json", size: 1543, mode: os.FileMode(0644), modTime: time.Unix(1564144050, 0)}
info := bindataFileInfo{name: "../config/cli/fleet-eth.test.json", size: 1543, mode: os.FileMode(0644), modTime: time.Unix(1573806410, 0)}
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x68, 0xef, 0x71, 0xa1, 0x38, 0x37, 0xf0, 0x0, 0xbb, 0x95, 0x26, 0x2a, 0x2a, 0x65, 0x98, 0xfe, 0xe5, 0x3f, 0xbf, 0xb, 0x68, 0xa6, 0xb5, 0xa4, 0x10, 0xc1, 0x4b, 0x67, 0xb4, 0x4e, 0x32, 0xc0}}
return a, nil
}
@ -177,7 +177,7 @@ func ConfigCliLesEnabledJson() (*asset, error) {
return nil, err
}
info := bindataFileInfo{name: "../config/cli/les-enabled.json", size: 58, mode: os.FileMode(0644), modTime: time.Unix(1564144050, 0)}
info := bindataFileInfo{name: "../config/cli/les-enabled.json", size: 58, mode: os.FileMode(0644), modTime: time.Unix(1573806410, 0)}
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x7e, 0xee, 0x27, 0xa7, 0x74, 0xa0, 0x46, 0xa1, 0x41, 0xed, 0x4d, 0x16, 0x5b, 0xf3, 0xf0, 0x7c, 0xc8, 0x2f, 0x6f, 0x47, 0xa4, 0xbb, 0x5f, 0x43, 0x33, 0xd, 0x9, 0x9d, 0xea, 0x9e, 0x15, 0xee}}
return a, nil
}
@ -197,7 +197,7 @@ func ConfigCliMailserverEnabledJson() (*asset, error) {
return nil, err
}
info := bindataFileInfo{name: "../config/cli/mailserver-enabled.json", size: 176, mode: os.FileMode(0644), modTime: time.Unix(1564144050, 0)}
info := bindataFileInfo{name: "../config/cli/mailserver-enabled.json", size: 176, mode: os.FileMode(0644), modTime: time.Unix(1573806410, 0)}
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x34, 0xec, 0x81, 0x8b, 0x99, 0xb6, 0xdb, 0xc0, 0x8b, 0x46, 0x97, 0x96, 0xc7, 0x58, 0x30, 0x33, 0xef, 0x54, 0x25, 0x87, 0x7b, 0xb9, 0x94, 0x6b, 0x18, 0xa4, 0x5b, 0x58, 0x67, 0x7c, 0x44, 0xa6}}
return a, nil
}
@ -217,7 +217,7 @@ func ConfigStatusChainGenesisJson() (*asset, error) {
return nil, err
}
info := bindataFileInfo{name: "../config/status-chain-genesis.json", size: 612, mode: os.FileMode(0644), modTime: time.Unix(1564144050, 0)}
info := bindataFileInfo{name: "../config/status-chain-genesis.json", size: 612, mode: os.FileMode(0644), modTime: time.Unix(1573806410, 0)}
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xb, 0xf0, 0xc, 0x1, 0x95, 0x65, 0x6, 0x55, 0x48, 0x8f, 0x83, 0xa0, 0xb4, 0x81, 0xda, 0xad, 0x30, 0x6d, 0xb2, 0x78, 0x1b, 0x26, 0x4, 0x13, 0x12, 0x9, 0x6, 0xae, 0x3a, 0x2c, 0x1, 0x71}}
return a, nil
}
@ -237,7 +237,7 @@ func keysBootnodeKey() (*asset, error) {
return nil, err
}
info := bindataFileInfo{name: "keys/bootnode.key", size: 65, mode: os.FileMode(0644), modTime: time.Unix(1564144050, 0)}
info := bindataFileInfo{name: "keys/bootnode.key", size: 65, mode: os.FileMode(0644), modTime: time.Unix(1573806410, 0)}
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x31, 0xcf, 0x27, 0xd4, 0x96, 0x2e, 0x32, 0xcd, 0x58, 0x96, 0x2a, 0xe5, 0x8c, 0xa0, 0xf1, 0x73, 0x1f, 0xd6, 0xd6, 0x8b, 0xb, 0x73, 0xd3, 0x2c, 0x84, 0x1a, 0x56, 0xa4, 0x74, 0xb6, 0x95, 0x20}}
return a, nil
}
@ -277,7 +277,7 @@ func keysTestAccount1StatusChainPk() (*asset, error) {
return nil, err
}
info := bindataFileInfo{name: "keys/test-account1-status-chain.pk", size: 489, mode: os.FileMode(0644), modTime: time.Unix(1564144050, 0)}
info := bindataFileInfo{name: "keys/test-account1-status-chain.pk", size: 489, mode: os.FileMode(0644), modTime: time.Unix(1573806410, 0)}
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x8f, 0xba, 0x35, 0x1, 0x2b, 0x9d, 0xad, 0xf0, 0x2d, 0x3c, 0x4d, 0x6, 0xb5, 0x22, 0x2, 0x47, 0xd4, 0x1c, 0xf4, 0x31, 0x2f, 0xb, 0x5b, 0x27, 0x5d, 0x43, 0x97, 0x58, 0x2d, 0xf0, 0xe1, 0xbe}}
return a, nil
}
@ -297,7 +297,7 @@ func keysTestAccount1Pk() (*asset, error) {
return nil, err
}
info := bindataFileInfo{name: "keys/test-account1.pk", size: 491, mode: os.FileMode(0644), modTime: time.Unix(1564144050, 0)}
info := bindataFileInfo{name: "keys/test-account1.pk", size: 491, mode: os.FileMode(0644), modTime: time.Unix(1573806410, 0)}
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x9, 0x43, 0xc2, 0xf4, 0x8c, 0xc6, 0x64, 0x25, 0x8c, 0x7, 0x8c, 0xa8, 0x89, 0x2b, 0x7b, 0x9b, 0x4f, 0x81, 0xcb, 0xce, 0x3d, 0xef, 0x82, 0x9c, 0x27, 0x27, 0xa9, 0xc5, 0x46, 0x70, 0x30, 0x38}}
return a, nil
}
@ -317,7 +317,7 @@ func keysTestAccount2StatusChainPk() (*asset, error) {
return nil, err
}
info := bindataFileInfo{name: "keys/test-account2-status-chain.pk", size: 489, mode: os.FileMode(0644), modTime: time.Unix(1564144050, 0)}
info := bindataFileInfo{name: "keys/test-account2-status-chain.pk", size: 489, mode: os.FileMode(0644), modTime: time.Unix(1573806410, 0)}
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x9, 0xf8, 0x5c, 0xe9, 0x92, 0x96, 0x2d, 0x88, 0x2b, 0x8e, 0x42, 0x3f, 0xa4, 0x93, 0x6c, 0xad, 0xe9, 0xc0, 0x1b, 0x8a, 0x8, 0x8c, 0x5e, 0x7a, 0x84, 0xa2, 0xf, 0x9f, 0x77, 0x58, 0x2c, 0x2c}}
return a, nil
}
@ -337,7 +337,7 @@ func keysTestAccount2Pk() (*asset, error) {
return nil, err
}
info := bindataFileInfo{name: "keys/test-account2.pk", size: 491, mode: os.FileMode(0644), modTime: time.Unix(1564144050, 0)}
info := bindataFileInfo{name: "keys/test-account2.pk", size: 491, mode: os.FileMode(0644), modTime: time.Unix(1573806410, 0)}
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x9f, 0x72, 0xd5, 0x95, 0x5c, 0x5a, 0x99, 0x9d, 0x2f, 0x21, 0x83, 0xd7, 0x10, 0x17, 0x4a, 0x3d, 0x65, 0xc9, 0x26, 0x1a, 0x2c, 0x9d, 0x65, 0x63, 0xd2, 0xa0, 0xfc, 0x7c, 0x0, 0x87, 0x38, 0x9f}}
return a, nil
}
@ -357,7 +357,7 @@ func keysTestAccount3BeforeEip55Pk() (*asset, error) {
return nil, err
}
info := bindataFileInfo{name: "keys/test-account3-before-eip55.pk", size: 489, mode: os.FileMode(0644), modTime: time.Unix(1564144050, 0)}
info := bindataFileInfo{name: "keys/test-account3-before-eip55.pk", size: 489, mode: os.FileMode(0644), modTime: time.Unix(1573806410, 0)}
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x81, 0x40, 0x56, 0xc1, 0x5e, 0x10, 0x6e, 0x28, 0x15, 0x3, 0x4e, 0xc4, 0xc4, 0x71, 0x4d, 0x16, 0x99, 0xcc, 0x1b, 0x63, 0xee, 0x10, 0x20, 0xe4, 0x59, 0x52, 0x3f, 0xc0, 0xad, 0x15, 0x13, 0x72}}
return a, nil
}

View file

@ -86,7 +86,7 @@ func configPublicChainAccountsJson() (*asset, error) {
return nil, err
}
info := bindataFileInfo{name: "config/public-chain-accounts.json", size: 307, mode: os.FileMode(0644), modTime: time.Unix(1564144050, 0)}
info := bindataFileInfo{name: "config/public-chain-accounts.json", size: 307, mode: os.FileMode(0644), modTime: time.Unix(1573806410, 0)}
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x76, 0x5d, 0xc0, 0xfe, 0x57, 0x50, 0x18, 0xec, 0x2d, 0x61, 0x1b, 0xa9, 0x81, 0x11, 0x5f, 0x77, 0xf7, 0xb6, 0x67, 0x82, 0x1, 0x40, 0x68, 0x9d, 0xc5, 0x41, 0xaf, 0xce, 0x43, 0x81, 0x92, 0x96}}
return a, nil
}
@ -106,7 +106,7 @@ func configStatusChainAccountsJson() (*asset, error) {
return nil, err
}
info := bindataFileInfo{name: "config/status-chain-accounts.json", size: 543, mode: os.FileMode(0644), modTime: time.Unix(1564144050, 0)}
info := bindataFileInfo{name: "config/status-chain-accounts.json", size: 543, mode: os.FileMode(0644), modTime: time.Unix(1573806410, 0)}
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x8e, 0xb3, 0x61, 0x51, 0x70, 0x3c, 0x12, 0x3e, 0xf1, 0x1c, 0x81, 0xfb, 0x9a, 0x7c, 0xe3, 0x63, 0xd0, 0x8f, 0x12, 0xc5, 0x2d, 0xf4, 0xea, 0x27, 0x33, 0xef, 0xca, 0xf9, 0x3f, 0x72, 0x44, 0xbf}}
return a, nil
}
@ -126,7 +126,7 @@ func configTestDataJson() (*asset, error) {
return nil, err
}
info := bindataFileInfo{name: "config/test-data.json", size: 84, mode: os.FileMode(0644), modTime: time.Unix(1564144050, 0)}
info := bindataFileInfo{name: "config/test-data.json", size: 84, mode: os.FileMode(0644), modTime: time.Unix(1573806410, 0)}
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xce, 0x9d, 0x80, 0xf5, 0x87, 0xfa, 0x57, 0x1d, 0xa1, 0xd5, 0x7a, 0x10, 0x3, 0xac, 0xd7, 0xf4, 0x64, 0x32, 0x96, 0x2b, 0xb7, 0x21, 0xb7, 0xa6, 0x80, 0x40, 0xe9, 0x65, 0xe3, 0xd6, 0xbd, 0x40}}
return a, nil
}

View file

@ -36,66 +36,66 @@ type ErrorCode uint32
const (
SCardSuccess ErrorCode = 0x00000000 /* No error was encountered. */
ErrSCardInternal = 0x80100001 /* An internal consistency check failed. */
ErrSCardCancelled = 0x80100002 /* The action was cancelled by an SCardCancel request. */
ErrSCardInvalidHandle = 0x80100003 /* The supplied handle was invalid. */
ErrSCardInvalidParameter = 0x80100004 /* One or more of the supplied parameters could not be properly interpreted. */
ErrSCardInvalidTarget = 0x80100005 /* Registry startup information is missing or invalid. */
ErrSCardNoMemory = 0x80100006 /* Not enough memory available to complete this command. */
ErrSCardWaitedTooLong = 0x80100007 /* An internal consistency timer has expired. */
ErrSCardInsufficientBuffer = 0x80100008 /* The data buffer to receive returned data is too small for the returned data. */
ErrScardUnknownReader = 0x80100009 /* The specified reader name is not recognized. */
ErrSCardTimeout = 0x8010000A /* The user-specified timeout value has expired. */
ErrSCardSharingViolation = 0x8010000B /* The smart card cannot be accessed because of other connections outstanding. */
ErrSCardNoSmartCard = 0x8010000C /* The operation requires a Smart Card, but no Smart Card is currently in the device. */
ErrSCardUnknownCard = 0x8010000D /* The specified smart card name is not recognized. */
ErrSCardCannotDispose = 0x8010000E /* The system could not dispose of the media in the requested manner. */
ErrSCardProtoMismatch = 0x8010000F /* The requested protocols are incompatible with the protocol currently in use with the smart card. */
ErrSCardNotReady = 0x80100010 /* The reader or smart card is not ready to accept commands. */
ErrSCardInvalidValue = 0x80100011 /* One or more of the supplied parameters values could not be properly interpreted. */
ErrSCardSystemCancelled = 0x80100012 /* The action was cancelled by the system, presumably to log off or shut down. */
ErrSCardCommError = 0x80100013 /* An internal communications error has been detected. */
ErrScardUnknownError = 0x80100014 /* An internal error has been detected, but the source is unknown. */
ErrSCardInvalidATR = 0x80100015 /* An ATR obtained from the registry is not a valid ATR string. */
ErrSCardNotTransacted = 0x80100016 /* An attempt was made to end a non-existent transaction. */
ErrSCardReaderUnavailable = 0x80100017 /* The specified reader is not currently available for use. */
ErrSCardShutdown = 0x80100018 /* The operation has been aborted to allow the server application to exit. */
ErrSCardPCITooSmall = 0x80100019 /* The PCI Receive buffer was too small. */
ErrSCardReaderUnsupported = 0x8010001A /* The reader driver does not meet minimal requirements for support. */
ErrSCardDuplicateReader = 0x8010001B /* The reader driver did not produce a unique reader name. */
ErrSCardCardUnsupported = 0x8010001C /* The smart card does not meet minimal requirements for support. */
ErrScardNoService = 0x8010001D /* The Smart card resource manager is not running. */
ErrSCardServiceStopped = 0x8010001E /* The Smart card resource manager has shut down. */
ErrSCardUnexpected = 0x8010001F /* An unexpected card error has occurred. */
ErrSCardUnsupportedFeature = 0x8010001F /* This smart card does not support the requested feature. */
ErrSCardICCInstallation = 0x80100020 /* No primary provider can be found for the smart card. */
ErrSCardICCCreateOrder = 0x80100021 /* The requested order of object creation is not supported. */
ErrSCardDirNotFound = 0x80100023 /* The identified directory does not exist in the smart card. */
ErrSCardFileNotFound = 0x80100024 /* The identified file does not exist in the smart card. */
ErrSCardNoDir = 0x80100025 /* The supplied path does not represent a smart card directory. */
ErrSCardNoFile = 0x80100026 /* The supplied path does not represent a smart card file. */
ErrScardNoAccess = 0x80100027 /* Access is denied to this file. */
ErrSCardWriteTooMany = 0x80100028 /* The smart card does not have enough memory to store the information. */
ErrSCardBadSeek = 0x80100029 /* There was an error trying to set the smart card file object pointer. */
ErrSCardInvalidCHV = 0x8010002A /* The supplied PIN is incorrect. */
ErrSCardUnknownResMNG = 0x8010002B /* An unrecognized error code was returned from a layered component. */
ErrSCardNoSuchCertificate = 0x8010002C /* The requested certificate does not exist. */
ErrSCardCertificateUnavailable = 0x8010002D /* The requested certificate could not be obtained. */
ErrSCardNoReadersAvailable = 0x8010002E /* Cannot find a smart card reader. */
ErrSCardCommDataLost = 0x8010002F /* A communications error with the smart card has been detected. Retry the operation. */
ErrScardNoKeyContainer = 0x80100030 /* The requested key container does not exist on the smart card. */
ErrSCardServerTooBusy = 0x80100031 /* The Smart Card Resource Manager is too busy to complete this operation. */
ErrSCardUnsupportedCard = 0x80100065 /* The reader cannot communicate with the card, due to ATR string configuration conflicts. */
ErrSCardUnresponsiveCard = 0x80100066 /* The smart card is not responding to a reset. */
ErrSCardUnpoweredCard = 0x80100067 /* Power has been removed from the smart card, so that further communication is not possible. */
ErrSCardResetCard = 0x80100068 /* The smart card has been reset, so any shared state information is invalid. */
ErrSCardRemovedCard = 0x80100069 /* The smart card has been removed, so further communication is not possible. */
ErrSCardSecurityViolation = 0x8010006A /* Access was denied because of a security violation. */
ErrSCardWrongCHV = 0x8010006B /* The card cannot be accessed because the wrong PIN was presented. */
ErrSCardCHVBlocked = 0x8010006C /* The card cannot be accessed because the maximum number of PIN entry attempts has been reached. */
ErrSCardEOF = 0x8010006D /* The end of the smart card file has been reached. */
ErrSCardCancelledByUser = 0x8010006E /* The user pressed "Cancel" on a Smart Card Selection Dialog. */
ErrSCardCardNotAuthenticated = 0x8010006F /* No PIN was presented to the smart card. */
ErrSCardInternal ErrorCode = 0x80100001 /* An internal consistency check failed. */
ErrSCardCancelled ErrorCode = 0x80100002 /* The action was cancelled by an SCardCancel request. */
ErrSCardInvalidHandle ErrorCode = 0x80100003 /* The supplied handle was invalid. */
ErrSCardInvalidParameter ErrorCode = 0x80100004 /* One or more of the supplied parameters could not be properly interpreted. */
ErrSCardInvalidTarget ErrorCode = 0x80100005 /* Registry startup information is missing or invalid. */
ErrSCardNoMemory ErrorCode = 0x80100006 /* Not enough memory available to complete this command. */
ErrSCardWaitedTooLong ErrorCode = 0x80100007 /* An internal consistency timer has expired. */
ErrSCardInsufficientBuffer ErrorCode = 0x80100008 /* The data buffer to receive returned data is too small for the returned data. */
ErrScardUnknownReader ErrorCode = 0x80100009 /* The specified reader name is not recognized. */
ErrSCardTimeout ErrorCode = 0x8010000A /* The user-specified timeout value has expired. */
ErrSCardSharingViolation ErrorCode = 0x8010000B /* The smart card cannot be accessed because of other connections outstanding. */
ErrSCardNoSmartCard ErrorCode = 0x8010000C /* The operation requires a Smart Card, but no Smart Card is currently in the device. */
ErrSCardUnknownCard ErrorCode = 0x8010000D /* The specified smart card name is not recognized. */
ErrSCardCannotDispose ErrorCode = 0x8010000E /* The system could not dispose of the media in the requested manner. */
ErrSCardProtoMismatch ErrorCode = 0x8010000F /* The requested protocols are incompatible with the protocol currently in use with the smart card. */
ErrSCardNotReady ErrorCode = 0x80100010 /* The reader or smart card is not ready to accept commands. */
ErrSCardInvalidValue ErrorCode = 0x80100011 /* One or more of the supplied parameters values could not be properly interpreted. */
ErrSCardSystemCancelled ErrorCode = 0x80100012 /* The action was cancelled by the system, presumably to log off or shut down. */
ErrSCardCommError ErrorCode = 0x80100013 /* An internal communications error has been detected. */
ErrScardUnknownError ErrorCode = 0x80100014 /* An internal error has been detected, but the source is unknown. */
ErrSCardInvalidATR ErrorCode = 0x80100015 /* An ATR obtained from the registry is not a valid ATR string. */
ErrSCardNotTransacted ErrorCode = 0x80100016 /* An attempt was made to end a non-existent transaction. */
ErrSCardReaderUnavailable ErrorCode = 0x80100017 /* The specified reader is not currently available for use. */
ErrSCardShutdown ErrorCode = 0x80100018 /* The operation has been aborted to allow the server application to exit. */
ErrSCardPCITooSmall ErrorCode = 0x80100019 /* The PCI Receive buffer was too small. */
ErrSCardReaderUnsupported ErrorCode = 0x8010001A /* The reader driver does not meet minimal requirements for support. */
ErrSCardDuplicateReader ErrorCode = 0x8010001B /* The reader driver did not produce a unique reader name. */
ErrSCardCardUnsupported ErrorCode = 0x8010001C /* The smart card does not meet minimal requirements for support. */
ErrScardNoService ErrorCode = 0x8010001D /* The Smart card resource manager is not running. */
ErrSCardServiceStopped ErrorCode = 0x8010001E /* The Smart card resource manager has shut down. */
ErrSCardUnexpected ErrorCode = 0x8010001F /* An unexpected card error has occurred. */
ErrSCardUnsupportedFeature ErrorCode = 0x8010001F /* This smart card does not support the requested feature. */
ErrSCardICCInstallation ErrorCode = 0x80100020 /* No primary provider can be found for the smart card. */
ErrSCardICCCreateOrder ErrorCode = 0x80100021 /* The requested order of object creation is not supported. */
ErrSCardDirNotFound ErrorCode = 0x80100023 /* The identified directory does not exist in the smart card. */
ErrSCardFileNotFound ErrorCode = 0x80100024 /* The identified file does not exist in the smart card. */
ErrSCardNoDir ErrorCode = 0x80100025 /* The supplied path does not represent a smart card directory. */
ErrSCardNoFile ErrorCode = 0x80100026 /* The supplied path does not represent a smart card file. */
ErrScardNoAccess ErrorCode = 0x80100027 /* Access is denied to this file. */
ErrSCardWriteTooMany ErrorCode = 0x80100028 /* The smart card does not have enough memory to store the information. */
ErrSCardBadSeek ErrorCode = 0x80100029 /* There was an error trying to set the smart card file object pointer. */
ErrSCardInvalidCHV ErrorCode = 0x8010002A /* The supplied PIN is incorrect. */
ErrSCardUnknownResMNG ErrorCode = 0x8010002B /* An unrecognized error code was returned from a layered component. */
ErrSCardNoSuchCertificate ErrorCode = 0x8010002C /* The requested certificate does not exist. */
ErrSCardCertificateUnavailable ErrorCode = 0x8010002D /* The requested certificate could not be obtained. */
ErrSCardNoReadersAvailable ErrorCode = 0x8010002E /* Cannot find a smart card reader. */
ErrSCardCommDataLost ErrorCode = 0x8010002F /* A communications error with the smart card has been detected. Retry the operation. */
ErrScardNoKeyContainer ErrorCode = 0x80100030 /* The requested key container does not exist on the smart card. */
ErrSCardServerTooBusy ErrorCode = 0x80100031 /* The Smart Card Resource Manager is too busy to complete this operation. */
ErrSCardUnsupportedCard ErrorCode = 0x80100065 /* The reader cannot communicate with the card, due to ATR string configuration conflicts. */
ErrSCardUnresponsiveCard ErrorCode = 0x80100066 /* The smart card is not responding to a reset. */
ErrSCardUnpoweredCard ErrorCode = 0x80100067 /* Power has been removed from the smart card, so that further communication is not possible. */
ErrSCardResetCard ErrorCode = 0x80100068 /* The smart card has been reset, so any shared state information is invalid. */
ErrSCardRemovedCard ErrorCode = 0x80100069 /* The smart card has been removed, so further communication is not possible. */
ErrSCardSecurityViolation ErrorCode = 0x8010006A /* Access was denied because of a security violation. */
ErrSCardWrongCHV ErrorCode = 0x8010006B /* The card cannot be accessed because the wrong PIN was presented. */
ErrSCardCHVBlocked ErrorCode = 0x8010006C /* The card cannot be accessed because the maximum number of PIN entry attempts has been reached. */
ErrSCardEOF ErrorCode = 0x8010006D /* The end of the smart card file has been reached. */
ErrSCardCancelledByUser ErrorCode = 0x8010006E /* The user pressed "Cancel" on a Smart Card Selection Dialog. */
ErrSCardCardNotAuthenticated ErrorCode = 0x8010006F /* No PIN was presented to the smart card. */
)
// Code returns the error code, with an uint32 type to be used in PutUInt32
@ -106,95 +106,95 @@ func (code ErrorCode) Code() uint32 {
func (code ErrorCode) Error() error {
switch code {
case SCardSuccess:
return fmt.Errorf("Command successful")
return fmt.Errorf("command successful")
case ErrSCardInternal:
return fmt.Errorf("Internal error")
return fmt.Errorf("internal error")
case ErrSCardCancelled:
return fmt.Errorf("Command cancelled")
return fmt.Errorf("command cancelled")
case ErrSCardInvalidHandle:
return fmt.Errorf("Invalid handle")
return fmt.Errorf("invalid handle")
case ErrSCardInvalidParameter:
return fmt.Errorf("Invalid parameter given")
return fmt.Errorf("invalid parameter given")
case ErrSCardInvalidTarget:
return fmt.Errorf("Invalid target given")
return fmt.Errorf("invalid target given")
case ErrSCardNoMemory:
return fmt.Errorf("Not enough memory")
return fmt.Errorf("not enough memory")
case ErrSCardWaitedTooLong:
return fmt.Errorf("Waited too long")
return fmt.Errorf("waited too long")
case ErrSCardInsufficientBuffer:
return fmt.Errorf("Insufficient buffer")
return fmt.Errorf("insufficient buffer")
case ErrScardUnknownReader:
return fmt.Errorf("Unknown reader specified")
return fmt.Errorf("unknown reader specified")
case ErrSCardTimeout:
return fmt.Errorf("Command timeout")
return fmt.Errorf("command timeout")
case ErrSCardSharingViolation:
return fmt.Errorf("Sharing violation")
return fmt.Errorf("sharing violation")
case ErrSCardNoSmartCard:
return fmt.Errorf("No smart card inserted")
return fmt.Errorf("no smart card inserted")
case ErrSCardUnknownCard:
return fmt.Errorf("Unknown card")
return fmt.Errorf("unknown card")
case ErrSCardCannotDispose:
return fmt.Errorf("Cannot dispose handle")
return fmt.Errorf("cannot dispose handle")
case ErrSCardProtoMismatch:
return fmt.Errorf("Card protocol mismatch")
return fmt.Errorf("card protocol mismatch")
case ErrSCardNotReady:
return fmt.Errorf("Subsystem not ready")
return fmt.Errorf("subsystem not ready")
case ErrSCardInvalidValue:
return fmt.Errorf("Invalid value given")
return fmt.Errorf("invalid value given")
case ErrSCardSystemCancelled:
return fmt.Errorf("System cancelled")
return fmt.Errorf("system cancelled")
case ErrSCardCommError:
return fmt.Errorf("RPC transport error")
return fmt.Errorf("rpc transport error")
case ErrScardUnknownError:
return fmt.Errorf("Unknown error")
return fmt.Errorf("unknown error")
case ErrSCardInvalidATR:
return fmt.Errorf("Invalid ATR")
return fmt.Errorf("invalid ATR")
case ErrSCardNotTransacted:
return fmt.Errorf("Transaction failed")
return fmt.Errorf("transaction failed")
case ErrSCardReaderUnavailable:
return fmt.Errorf("Reader is unavailable")
return fmt.Errorf("reader is unavailable")
/* case SCARD_P_SHUTDOWN: */
case ErrSCardPCITooSmall:
return fmt.Errorf("PCI struct too small")
case ErrSCardReaderUnsupported:
return fmt.Errorf("Reader is unsupported")
return fmt.Errorf("reader is unsupported")
case ErrSCardDuplicateReader:
return fmt.Errorf("Reader already exists")
return fmt.Errorf("reader already exists")
case ErrSCardCardUnsupported:
return fmt.Errorf("Card is unsupported")
return fmt.Errorf("card is unsupported")
case ErrScardNoService:
return fmt.Errorf("Service not available")
return fmt.Errorf("service not available")
case ErrSCardServiceStopped:
return fmt.Errorf("Service was stopped")
return fmt.Errorf("service was stopped")
/* case SCARD_E_UNEXPECTED: */
/* case SCARD_E_ICC_CREATEORDER: */
@ -210,7 +210,7 @@ func (code ErrorCode) Error() error {
/* case SCARD_E_NO_SUCH_CERTIFICATE: */
/* case SCARD_E_CERTIFICATE_UNAVAILABLE: */
case ErrSCardNoReadersAvailable:
return fmt.Errorf("Cannot find a smart card reader")
return fmt.Errorf("cannot find a smart card reader")
/* case SCARD_E_COMM_DATA_LOST: */
/* case SCARD_E_NO_KEY_CONTAINER: */
@ -238,7 +238,7 @@ func (code ErrorCode) Error() error {
/* case SCARD_W_CARD_NOT_AUTHENTICATED: */
case ErrSCardUnsupportedFeature:
return fmt.Errorf("Feature not supported")
return fmt.Errorf("feature not supported")
default:
return fmt.Errorf("unknown error: %08x", code)

View file

@ -291,16 +291,16 @@ func (client *Client) Connect(name string, shareMode uint32, preferredProtocol u
*
* These data are passed throw the field \c sharedSegmentMsg.data.
*/
type transmit struct {
hCard uint32
ioSendPciProtocol uint32
ioSendPciLength uint32
cbSendLength uint32
ioRecvPciProtocol uint32
ioRecvPciLength uint32
pcbRecvLength uint32
rv uint32
}
//type transmit struct {
//hCard uint32
//ioSendPciProtocol uint32
//ioSendPciLength uint32
//cbSendLength uint32
//ioRecvPciProtocol uint32
//ioRecvPciLength uint32
//pcbRecvLength uint32
//rv uint32
//}
// SCardIoRequest contains the info needed for performing an IO request
type SCardIoRequest struct {
@ -336,7 +336,7 @@ func (card *Card) Transmit(adpu []byte) ([]byte, *SCardIoRequest, error) {
return nil, nil, err
}
if n != len(adpu) {
return nil, nil, fmt.Errorf("Invalid number of bytes written: expected %d, got %d", len(adpu), n)
return nil, nil, fmt.Errorf("invalid number of bytes written: expected %d, got %d", len(adpu), n)
}
response := [TransmitRequestLength]byte{}
total := 0

26
vendor/github.com/go-playground/locales/.travis.yml generated vendored Normal file
View file

@ -0,0 +1,26 @@
language: go
go:
- 1.13.1
- tip
matrix:
allow_failures:
- go: tip
notifications:
email:
recipients: dean.karn@gmail.com
on_success: change
on_failure: always
before_install:
- go install github.com/mattn/goveralls
# Only clone the most recent commit.
git:
depth: 1
script:
- go test -v -race -covermode=atomic -coverprofile=coverage.coverprofile ./...
after_success: |
goveralls -coverprofile=coverage.coverprofile -service travis-ci -repotoken $COVERALLS_TOKEN

View file

@ -1,6 +1,6 @@
## locales
<img align="right" src="https://raw.githubusercontent.com/go-playground/locales/master/logo.png">![Project status](https://img.shields.io/badge/version-0.12.1-green.svg)
[![Build Status](https://semaphoreci.com/api/v1/joeybloggs/locales/branches/master/badge.svg)](https://semaphoreci.com/joeybloggs/locales)
<img align="right" src="https://raw.githubusercontent.com/go-playground/locales/master/logo.png">![Project status](https://img.shields.io/badge/version-0.13.0-green.svg)
[![Build Status](https://travis-ci.org/go-playground/locales.svg?branch=master)](https://travis-ci.org/go-playground/locales)
[![Go Report Card](https://goreportcard.com/badge/github.com/go-playground/locales)](https://goreportcard.com/report/github.com/go-playground/locales)
[![GoDoc](https://godoc.org/github.com/go-playground/locales?status.svg)](https://godoc.org/github.com/go-playground/locales)
![License](https://img.shields.io/dub/l/vibe-d.svg)

5
vendor/github.com/go-playground/locales/go.mod generated vendored Normal file
View file

@ -0,0 +1,5 @@
module github.com/go-playground/locales
go 1.13
require golang.org/x/text v0.3.2

3
vendor/github.com/go-playground/locales/go.sum generated vendored Normal file
View file

@ -0,0 +1,3 @@
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=

View file

@ -21,4 +21,5 @@ _testmain.go
*.exe
*.test
*.prof
*.prof
*.coverprofile

View file

@ -0,0 +1,27 @@
language: go
go:
- 1.13.4
- tip
matrix:
allow_failures:
- go: tip
notifications:
email:
recipients: dean.karn@gmail.com
on_success: change
on_failure: always
before_install:
- go install github.com/mattn/goveralls
# Only clone the most recent commit.
git:
depth: 1
script:
- go test -v -race -covermode=atomic -coverprofile=coverage.coverprofile ./...
after_success: |
[ $TRAVIS_GO_VERSION = 1.13.4 ] &&
goveralls -coverprofile=coverage.coverprofile -service travis-ci -repotoken $COVERALLS_TOKEN

View file

@ -1,7 +1,6 @@
## universal-translator
<img align="right" src="https://raw.githubusercontent.com/go-playground/universal-translator/master/logo.png">
![Project status](https://img.shields.io/badge/version-0.16.0-green.svg)
[![Build Status](https://semaphoreci.com/api/v1/joeybloggs/universal-translator/branches/master/badge.svg)](https://semaphoreci.com/joeybloggs/universal-translator)
<img align="right" src="https://raw.githubusercontent.com/go-playground/universal-translator/master/logo.png">![Project status](https://img.shields.io/badge/version-0.17.0-green.svg)
[![Build Status](https://travis-ci.org/go-playground/universal-translator.svg?branch=master)](https://travis-ci.org/go-playground/universal-translator)
[![Coverage Status](https://coveralls.io/repos/github/go-playground/universal-translator/badge.svg)](https://coveralls.io/github/go-playground/universal-translator)
[![Go Report Card](https://goreportcard.com/badge/github.com/go-playground/universal-translator)](https://goreportcard.com/report/github.com/go-playground/universal-translator)
[![GoDoc](https://godoc.org/github.com/go-playground/universal-translator?status.svg)](https://godoc.org/github.com/go-playground/universal-translator)
@ -46,9 +45,9 @@ Please see https://godoc.org/github.com/go-playground/universal-translator for u
##### Examples:
- [Basic](https://github.com/go-playground/universal-translator/tree/master/examples/basic)
- [Full - no files](https://github.com/go-playground/universal-translator/tree/master/examples/full-no-files)
- [Full - with files](https://github.com/go-playground/universal-translator/tree/master/examples/full-with-files)
- [Basic](https://github.com/go-playground/universal-translator/tree/master/_examples/basic)
- [Full - no files](https://github.com/go-playground/universal-translator/tree/master/_examples/full-no-files)
- [Full - with files](https://github.com/go-playground/universal-translator/tree/master/_examples/full-with-files)
File formatting
--------------
@ -57,10 +56,10 @@ they are only separated for easy viewing.
##### Examples:
- [Formats](https://github.com/go-playground/universal-translator/tree/master/examples/file-formats)
- [Formats](https://github.com/go-playground/universal-translator/tree/master/_examples/file-formats)
##### Basic Makeup
NOTE: not all fields are needed for all translation types, see [examples](https://github.com/go-playground/universal-translator/tree/master/examples/file-formats)
NOTE: not all fields are needed for all translation types, see [examples](https://github.com/go-playground/universal-translator/tree/master/_examples/file-formats)
```json
{
"locale": "en",

View file

@ -0,0 +1,5 @@
module github.com/go-playground/universal-translator
go 1.13
require github.com/go-playground/locales v0.13.0

View file

@ -0,0 +1,4 @@
github.com/go-playground/locales v0.13.0 h1:HyWk6mgj5qFqCT5fjGBuRArbVDfE4hi8+e8ceBS/t7Q=
github.com/go-playground/locales v0.13.0/go.mod h1:taPMhCMXrRLJO55olJkUXHZBHCxTMfnGwq/HNwmWNS8=
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=

View file

@ -1,6 +1,6 @@
run:
# timeout for analysis, e.g. 30s, 5m, default is 1m
deadline: 2m
timeout: 2m
linters:
enable:
#- golint

View file

@ -6,8 +6,8 @@ matrix:
- go: master
include:
# Supported versions of Go: https://golang.org/dl/
- go: "1.11.x"
- go: "1.12.x"
- go: "1.13.x"
- go: master
go_import_path: github.com/golang-migrate/migrate
@ -34,7 +34,7 @@ before_install:
- sudo apt-get update
- sudo apt-get -y -o Dpkg::Options::="--force-confnew" install docker-ce
# Install golangci-lint
- curl -sfL https://install.goreleaser.com/github.com/golangci/golangci-lint.sh | sh -s -- -b $(go env GOPATH)/bin v1.17.1
- curl -sfL https://install.goreleaser.com/github.com/golangci/golangci-lint.sh | sh -s -- -b $(go env GOPATH)/bin v1.20.0
- echo "TRAVIS_GO_VERSION=${TRAVIS_GO_VERSION}"
install:
@ -57,7 +57,7 @@ deploy:
secure: hWH1HLPpzpfA8pXQ93T1qKQVFSpQp0as/JLQ7D91jHuJ8p+RxVeqblDrR6HQY/95R/nyiE9GJmvUolSuw5h449LSrGxPtVWhdh6EnkxlQHlen5XeMhVjRjFV0sE9qGe8v7uAkiTfRO61ktTWHrEAvw5qpyqnNISodmZS78XIasPODQbNlzwINhWhDTHIjXGb4FpizYaL3OGCanrxfR9fQyCaqKGGBjRq3Mfq8U6Yd4mApmsE+uJxgaZV8K5zBqpkSzQRWhcVGNL5DuLsU3gfSJOo7kZeA2G71SHffH577dBoqtCZ4VFv169CoUZehLWCb+7XKJZmHXVujCURATSySLGUOPc6EoLFAn3YtsCA04mS4bZVo5FZPWVwfhjmkhtDR4f6wscKp7r1HsFHSOgm59QfETQdrn4MnZ44H2Jd39axqndn5DvK9EcZVjPHynOPnueXP2u6mTuUgh2VyyWBCDO3CNo0fGlo7VJI69IkIWNSD87K9cHZWYMClyKZkUzS+PmRAhHRYbVd+9ZjKOmnU36kUHNDG/ft1D4ogsY+rhVtXB4lgWDM5adri+EIScYdYnB1/pQexLBigcJY9uE7nQTR0U6QgVNYvun7uRNs40E0c4voSfmPdFO0FlOD2y1oQhnaXfWLbu9nMcTcs4RFGrcC7NzkUN4/WjG8s285V6w=
skip_cleanup: true
on:
go: "1.12.x"
go: "1.13.x"
repo: golang-migrate/migrate
tags: true
file:
@ -75,7 +75,7 @@ deploy:
package_glob: '*.deb'
skip_cleanup: true
on:
go: "1.12.x"
go: "1.13.x"
repo: golang-migrate/migrate
tags: true
- provider: packagecloud
@ -87,7 +87,7 @@ deploy:
package_glob: '*.deb'
skip_cleanup: true
on:
go: "1.12.x"
go: "1.13.x"
repo: golang-migrate/migrate
tags: true
- provider: packagecloud
@ -99,7 +99,7 @@ deploy:
package_glob: '*.deb'
skip_cleanup: true
on:
go: "1.12.x"
go: "1.13.x"
repo: golang-migrate/migrate
tags: true
- provider: packagecloud
@ -111,7 +111,7 @@ deploy:
package_glob: '*.deb'
skip_cleanup: true
on:
go: "1.12.x"
go: "1.13.x"
repo: golang-migrate/migrate
tags: true
- provider: packagecloud
@ -123,13 +123,13 @@ deploy:
package_glob: '*.deb'
skip_cleanup: true
on:
go: "1.12.x"
go: "1.13.x"
repo: golang-migrate/migrate
tags: true
- provider: script
script: ./docker-deploy.sh
skip_cleanup: true
on:
go: "1.12.x"
go: "1.13.x"
repo: golang-migrate/migrate
tags: true

View file

@ -8,7 +8,7 @@ WORKDIR /go/src/github.com/golang-migrate/migrate
COPY . ./
ENV GO111MODULE=on
ENV DATABASES="postgres mysql redshift cassandra spanner cockroachdb clickhouse mongodb sqlserver"
ENV DATABASES="postgres mysql redshift cassandra spanner cockroachdb clickhouse mongodb sqlserver firebird"
ENV SOURCES="file go_bindata github github_ee aws_s3 google_cloud_storage godoc_vfs gitlab"
RUN go build -a -o build/migrate.linux-386 -ldflags="-s -w -X main.Version=${VERSION}" -tags "$DATABASES $SOURCES" ./cmd/migrate

View file

@ -1,5 +1,5 @@
SOURCE ?= file go_bindata github github_ee aws_s3 google_cloud_storage godoc_vfs gitlab
DATABASE ?= postgres mysql redshift cassandra spanner cockroachdb clickhouse mongodb sqlserver
DATABASE ?= postgres mysql redshift cassandra spanner cockroachdb clickhouse mongodb sqlserver firebird
VERSION ?= $(shell git describe --tags 2>/dev/null | cut -c 2-)
TEST_FLAGS ?=
REPO_OWNER ?= $(shell cd .. && basename "$$(pwd)")

View file

@ -3,7 +3,7 @@
[![Coverage Status](https://img.shields.io/coveralls/github/golang-migrate/migrate/master.svg)](https://coveralls.io/github/golang-migrate/migrate?branch=master)
[![packagecloud.io](https://img.shields.io/badge/deb-packagecloud.io-844fec.svg)](https://packagecloud.io/golang-migrate/migrate?filter=debs)
[![Docker Pulls](https://img.shields.io/docker/pulls/migrate/migrate.svg)](https://hub.docker.com/r/migrate/migrate/)
![Supported Go Versions](https://img.shields.io/badge/Go-1.11%2C%201.12-lightgrey.svg)
![Supported Go Versions](https://img.shields.io/badge/Go-1.12%2C%201.13-lightgrey.svg)
[![GitHub Release](https://img.shields.io/github/release/golang-migrate/migrate.svg)](https://github.com/golang-migrate/migrate/releases)
[![Go Report Card](https://goreportcard.com/badge/github.com/golang-migrate/migrate)](https://goreportcard.com/report/github.com/golang-migrate/migrate)
@ -36,7 +36,7 @@ Database drivers run migrations. [Add a new database?](database/driver.go)
* [Google Cloud Spanner](database/spanner)
* [CockroachDB](database/cockroachdb)
* [ClickHouse](database/clickhouse)
* [Firebird](database/firebird) ([todo #49](https://github.com/golang-migrate/migrate/issues/49))
* [Firebird](database/firebird)
* [MS SQL Server](database/sqlserver)
### Database URLs

View file

@ -54,3 +54,5 @@ require (
google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb
google.golang.org/grpc v1.20.1 // indirect
)
go 1.12

View file

@ -74,6 +74,8 @@ extern "C" {
#pragma warning(disable:4996)
#endif
#pragma GCC diagnostic ignored "-Wstringop-overflow"
#ifdef __cplusplus
extern "C" {
#endif
@ -428,7 +430,7 @@ struct hid_device_info HID_API_EXPORT * HID_API_CALL hid_enumerate(unsigned shor
if (str) {
len = strlen(str);
cur_dev->path = (char*) calloc(len+1, sizeof(char));
strncpy(cur_dev->path, str, sizeof(cur_dev->path));
strncpy(cur_dev->path, str, len+1);
cur_dev->path[len] = '\0';
}
else

View file

@ -6,4 +6,6 @@
*.test
*.out
*.txt
*.txt
vendor/

View file

@ -3,6 +3,9 @@ language: go
go:
- 1.9.x
- 1.10.x
- 1.11.x
- 1.12.x
- 1.13.x
- tip
before_install:

21
vendor/github.com/leodido/go-urn/LICENSE generated vendored Normal file
View file

@ -0,0 +1,21 @@
MIT License
Copyright (c) 2018 Leonardo Di Donato
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

5
vendor/github.com/leodido/go-urn/go.mod generated vendored Normal file
View file

@ -0,0 +1,5 @@
module github.com/leodido/go-urn
go 1.13
require github.com/stretchr/testify v1.4.0

11
vendor/github.com/leodido/go-urn/go.sum generated vendored Normal file
View file

@ -0,0 +1,11 @@
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/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=

File diff suppressed because it is too large Load diff

View file

@ -1,12 +1,21 @@
SHELL := /bin/bash
build: machine.go
images: docs/urn.png
machine.go: machine.go.rl
ragel -Z -G2 -e -o $@ $<
@gofmt -w -s $@
@sed -i '/^\/\/line/d' $@
@$(MAKE) -s file=$@ snake2camel
@gofmt -w -s $@
.PHONY: build
build: machine.go
docs/urn.dot: machine.go.rl
@mkdir -p docs
ragel -Z -e -Vp $< -o $@
docs/urn.png: docs/urn.dot
dot $< -Tpng -o $@
.PHONY: bench
bench: *_test.go machine.go
@ -14,4 +23,17 @@ bench: *_test.go machine.go
.PHONY: tests
tests: *_test.go machine.go
go test -race -timeout 10s -coverprofile=coverage.out -covermode=atomic -v ./...
go test -race -timeout 10s -coverprofile=coverage.out -covermode=atomic -v ./...
.PHONY: clean
clean:
@rm -rf docs
@rm -f machine.go
.PHONY: snake2camel
snake2camel:
@awk -i inplace '{ \
while ( match($$0, /(.*)([a-z]+[0-9]*)_([a-zA-Z0-9])(.*)/, cap) ) \
$$0 = cap[1] cap[2] toupper(cap[3]) cap[4]; \
print \
}' $(file)

View file

@ -1,85 +0,0 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// source: message.proto
package applicationmetadata
import (
fmt "fmt"
proto "github.com/golang/protobuf/proto"
math "math"
)
// Reference imports to suppress errors if they are not otherwise used.
var _ = proto.Marshal
var _ = fmt.Errorf
var _ = math.Inf
// This is a compile-time assertion to ensure that this generated file
// is compatible with the proto package it is being compiled against.
// A compilation error at this line likely means your copy of the
// proto package needs to be updated.
const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package
type Message struct {
Signature []byte `protobuf:"bytes,4001,opt,name=signature,proto3" json:"signature,omitempty"`
Payload []byte `protobuf:"bytes,4002,opt,name=payload,proto3" json:"payload,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *Message) Reset() { *m = Message{} }
func (m *Message) String() string { return proto.CompactTextString(m) }
func (*Message) ProtoMessage() {}
func (*Message) Descriptor() ([]byte, []int) {
return fileDescriptor_33c57e4bae7b9afd, []int{0}
}
func (m *Message) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_Message.Unmarshal(m, b)
}
func (m *Message) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_Message.Marshal(b, m, deterministic)
}
func (m *Message) XXX_Merge(src proto.Message) {
xxx_messageInfo_Message.Merge(m, src)
}
func (m *Message) XXX_Size() int {
return xxx_messageInfo_Message.Size(m)
}
func (m *Message) XXX_DiscardUnknown() {
xxx_messageInfo_Message.DiscardUnknown(m)
}
var xxx_messageInfo_Message proto.InternalMessageInfo
func (m *Message) GetSignature() []byte {
if m != nil {
return m.Signature
}
return nil
}
func (m *Message) GetPayload() []byte {
if m != nil {
return m.Payload
}
return nil
}
func init() {
proto.RegisterType((*Message)(nil), "applicationmetadata.Message")
}
func init() { proto.RegisterFile("message.proto", fileDescriptor_33c57e4bae7b9afd) }
var fileDescriptor_33c57e4bae7b9afd = []byte{
// 112 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0xe2, 0xcd, 0x4d, 0x2d, 0x2e,
0x4e, 0x4c, 0x4f, 0xd5, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x12, 0x4e, 0x2c, 0x28, 0xc8, 0xc9,
0x4c, 0x4e, 0x2c, 0xc9, 0xcc, 0xcf, 0xcb, 0x4d, 0x2d, 0x49, 0x4c, 0x49, 0x2c, 0x49, 0x54, 0x72,
0xe6, 0x62, 0xf7, 0x85, 0xa8, 0x12, 0x92, 0xe5, 0xe2, 0x2c, 0xce, 0x4c, 0xcf, 0x4b, 0x2c, 0x29,
0x2d, 0x4a, 0x95, 0x58, 0x28, 0xaf, 0xc0, 0xa8, 0xc1, 0x13, 0x84, 0x10, 0x11, 0x92, 0xe4, 0x62,
0x2f, 0x48, 0xac, 0xcc, 0xc9, 0x4f, 0x4c, 0x91, 0x58, 0x04, 0x91, 0x84, 0xf1, 0x93, 0xd8, 0xc0,
0x16, 0x18, 0x03, 0x02, 0x00, 0x00, 0xff, 0xff, 0xb0, 0x7f, 0x4a, 0x96, 0x71, 0x00, 0x00, 0x00,
}

View file

@ -1,8 +0,0 @@
syntax = "proto3";
package applicationmetadata;
message Message {
bytes signature = 4001;
bytes payload = 4002;
}

View file

@ -4,6 +4,7 @@ import (
"crypto/ecdsa"
"crypto/sha1"
"encoding/hex"
"encoding/json"
"github.com/status-im/status-go/eth-node/crypto"
"github.com/status-im/status-go/eth-node/types"
@ -42,11 +43,8 @@ type Chat struct {
DeletedAtClockValue uint64 `json:"deletedAtClockValue"`
// Denormalized fields
UnviewedMessagesCount uint `json:"unviewedMessagesCount"`
LastMessageContentType string `json:"lastMessageContentType"`
LastMessageContent string `json:"lastMessageContent"`
LastMessageTimestamp int64 `json:"lastMessageTimestamp"`
LastMessageClockValue int64 `json:"lastMessageClockValue"`
UnviewedMessagesCount uint `json:"unviewedMessagesCount"`
LastMessage []byte `json:"lastMessage"`
// Group chat fields
// Members are the members who have been invited to the group chat
@ -55,6 +53,53 @@ type Chat struct {
MembershipUpdates []ChatMembershipUpdate `json:"membershipUpdates"`
}
func (c *Chat) MarshalJSON() ([]byte, error) {
type ChatAlias Chat
item := struct {
*ChatAlias
LastMessage json.RawMessage `json:"lastMessage"`
}{
ChatAlias: (*ChatAlias)(c),
LastMessage: c.LastMessage,
}
return json.Marshal(item)
}
func (c *Chat) UnmarshalJSON(data []byte) error {
type ChatAlias Chat
aux := struct {
*ChatAlias
LastMessage *Message `json:"lastMessage"`
}{
ChatAlias: (*ChatAlias)(c),
}
if err := json.Unmarshal(data, &aux); err != nil {
return err
}
c.ID = aux.ID
c.Name = aux.Name
c.Color = aux.Color
c.Active = aux.Active
c.ChatType = aux.ChatType
c.Timestamp = aux.Timestamp
c.LastClockValue = aux.LastClockValue
c.DeletedAtClockValue = aux.DeletedAtClockValue
c.UnviewedMessagesCount = aux.UnviewedMessagesCount
c.Members = aux.Members
c.MembershipUpdates = aux.MembershipUpdates
if aux.LastMessage != nil {
data, err := json.Marshal(aux.LastMessage)
if err != nil {
return err
}
c.LastMessage = data
}
return nil
}
func (c *Chat) MembersAsPublicKeys() ([]*ecdsa.PublicKey, error) {
publicKeys := make([]string, len(c.Members))
for idx, item := range c.Members {

View file

@ -12,9 +12,9 @@ import (
)
const (
contactBlocked = "contact/blocked"
contactAdded = "contact/added"
contactRequestReceived = "contact/request-received"
contactBlocked = ":contact/blocked"
contactAdded = ":contact/added"
contactRequestReceived = ":contact/request-received"
)
// ContactDeviceInfo is a struct containing information about a particular device owned by a contact

View file

@ -100,7 +100,7 @@ func _1536754952_initial_schemaDownSql() (*asset, error) {
return nil, err
}
info := bindataFileInfo{name: "1536754952_initial_schema.down.sql", size: 83, mode: os.FileMode(0644), modTime: time.Unix(1564484687, 0)}
info := bindataFileInfo{name: "1536754952_initial_schema.down.sql", size: 83, mode: os.FileMode(0644), modTime: time.Unix(1574354941, 0)}
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x44, 0xcf, 0x76, 0x71, 0x1f, 0x5e, 0x9a, 0x43, 0xd8, 0xcd, 0xb8, 0xc3, 0x70, 0xc3, 0x7f, 0xfc, 0x90, 0xb4, 0x25, 0x1e, 0xf4, 0x66, 0x20, 0xb8, 0x33, 0x7e, 0xb0, 0x76, 0x1f, 0xc, 0xc0, 0x75}}
return a, nil
}
@ -120,7 +120,7 @@ func _1536754952_initial_schemaUpSql() (*asset, error) {
return nil, err
}
info := bindataFileInfo{name: "1536754952_initial_schema.up.sql", size: 962, mode: os.FileMode(0644), modTime: time.Unix(1564484687, 0)}
info := bindataFileInfo{name: "1536754952_initial_schema.up.sql", size: 962, mode: os.FileMode(0644), modTime: time.Unix(1574354941, 0)}
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xea, 0x90, 0x5a, 0x59, 0x3e, 0x3, 0xe2, 0x3c, 0x81, 0x42, 0xcd, 0x4c, 0x9a, 0xe8, 0xda, 0x93, 0x2b, 0x70, 0xa4, 0xd5, 0x29, 0x3e, 0xd5, 0xc9, 0x27, 0xb6, 0xb7, 0x65, 0xff, 0x0, 0xcb, 0xde}}
return a, nil
}
@ -140,7 +140,7 @@ func _1539249977_update_ratchet_infoDownSql() (*asset, error) {
return nil, err
}
info := bindataFileInfo{name: "1539249977_update_ratchet_info.down.sql", size: 311, mode: os.FileMode(0644), modTime: time.Unix(1564484687, 0)}
info := bindataFileInfo{name: "1539249977_update_ratchet_info.down.sql", size: 311, mode: os.FileMode(0644), modTime: time.Unix(1574354941, 0)}
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x1, 0xa4, 0xeb, 0xa0, 0xe6, 0xa0, 0xd4, 0x48, 0xbb, 0xad, 0x6f, 0x7d, 0x67, 0x8c, 0xbd, 0x25, 0xde, 0x1f, 0x73, 0x9a, 0xbb, 0xa8, 0xc9, 0x30, 0xb7, 0xa9, 0x7c, 0xaf, 0xb5, 0x1, 0x61, 0xdd}}
return a, nil
}
@ -160,7 +160,7 @@ func _1539249977_update_ratchet_infoUpSql() (*asset, error) {
return nil, err
}
info := bindataFileInfo{name: "1539249977_update_ratchet_info.up.sql", size: 368, mode: os.FileMode(0644), modTime: time.Unix(1564484687, 0)}
info := bindataFileInfo{name: "1539249977_update_ratchet_info.up.sql", size: 368, mode: os.FileMode(0644), modTime: time.Unix(1574354941, 0)}
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xc, 0x8e, 0xbf, 0x6f, 0xa, 0xc0, 0xe1, 0x3c, 0x42, 0x28, 0x88, 0x1d, 0xdb, 0xba, 0x1c, 0x83, 0xec, 0xba, 0xd3, 0x5f, 0x5c, 0x77, 0x5e, 0xa7, 0x46, 0x36, 0xec, 0x69, 0xa, 0x4b, 0x17, 0x79}}
return a, nil
}
@ -180,7 +180,7 @@ func _1540715431_add_versionDownSql() (*asset, error) {
return nil, err
}
info := bindataFileInfo{name: "1540715431_add_version.down.sql", size: 127, mode: os.FileMode(0644), modTime: time.Unix(1564484687, 0)}
info := bindataFileInfo{name: "1540715431_add_version.down.sql", size: 127, mode: os.FileMode(0644), modTime: time.Unix(1574354941, 0)}
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xf5, 0x9, 0x4, 0xe3, 0x76, 0x2e, 0xb8, 0x9, 0x23, 0xf0, 0x70, 0x93, 0xc4, 0x50, 0xe, 0x9d, 0x84, 0x22, 0x8c, 0x94, 0xd3, 0x24, 0x9, 0x9a, 0xc1, 0xa1, 0x48, 0x45, 0xfd, 0x40, 0x6e, 0xe6}}
return a, nil
}
@ -200,7 +200,7 @@ func _1540715431_add_versionUpSql() (*asset, error) {
return nil, err
}
info := bindataFileInfo{name: "1540715431_add_version.up.sql", size: 265, mode: os.FileMode(0644), modTime: time.Unix(1564484687, 0)}
info := bindataFileInfo{name: "1540715431_add_version.up.sql", size: 265, mode: os.FileMode(0644), modTime: time.Unix(1574354941, 0)}
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xc7, 0x4c, 0x36, 0x96, 0xdf, 0x16, 0x10, 0xa6, 0x27, 0x1a, 0x79, 0x8b, 0x42, 0x83, 0x23, 0xc, 0x7e, 0xb6, 0x3d, 0x2, 0xda, 0xa4, 0xb4, 0xd, 0x27, 0x55, 0xba, 0xdc, 0xb2, 0x88, 0x8f, 0xa6}}
return a, nil
}
@ -220,7 +220,7 @@ func _1541164797_add_installationsDownSql() (*asset, error) {
return nil, err
}
info := bindataFileInfo{name: "1541164797_add_installations.down.sql", size: 26, mode: os.FileMode(0644), modTime: time.Unix(1564484687, 0)}
info := bindataFileInfo{name: "1541164797_add_installations.down.sql", size: 26, mode: os.FileMode(0644), modTime: time.Unix(1574354941, 0)}
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xf5, 0xfd, 0xe6, 0xd8, 0xca, 0x3b, 0x38, 0x18, 0xee, 0x0, 0x5f, 0x36, 0x9e, 0x1e, 0xd, 0x19, 0x3e, 0xb4, 0x73, 0x53, 0xe9, 0xa5, 0xac, 0xdd, 0xa1, 0x2f, 0xc7, 0x6c, 0xa8, 0xd9, 0xa, 0x88}}
return a, nil
}
@ -240,7 +240,7 @@ func _1541164797_add_installationsUpSql() (*asset, error) {
return nil, err
}
info := bindataFileInfo{name: "1541164797_add_installations.up.sql", size: 216, mode: os.FileMode(0644), modTime: time.Unix(1564484687, 0)}
info := bindataFileInfo{name: "1541164797_add_installations.up.sql", size: 216, mode: os.FileMode(0644), modTime: time.Unix(1574354941, 0)}
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x2d, 0x18, 0x26, 0xb8, 0x88, 0x47, 0xdb, 0x83, 0xcc, 0xb6, 0x9d, 0x1c, 0x1, 0xae, 0x2f, 0xde, 0x97, 0x82, 0x3, 0x30, 0xa8, 0x63, 0xa1, 0x78, 0x4b, 0xa5, 0x9, 0x8, 0x75, 0xa2, 0x57, 0x81}}
return a, nil
}
@ -260,7 +260,7 @@ func _1558084410_add_secretDownSql() (*asset, error) {
return nil, err
}
info := bindataFileInfo{name: "1558084410_add_secret.down.sql", size: 56, mode: os.FileMode(0644), modTime: time.Unix(1564484687, 0)}
info := bindataFileInfo{name: "1558084410_add_secret.down.sql", size: 56, mode: os.FileMode(0644), modTime: time.Unix(1574354941, 0)}
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x49, 0xb, 0x65, 0xdf, 0x59, 0xbf, 0xe9, 0x5, 0x5b, 0x6f, 0xd5, 0x3a, 0xb7, 0x57, 0xe8, 0x78, 0x38, 0x73, 0x53, 0x57, 0xf7, 0x24, 0x4, 0xe4, 0xa2, 0x49, 0x22, 0xa2, 0xc6, 0xfd, 0x80, 0xa4}}
return a, nil
}
@ -280,7 +280,7 @@ func _1558084410_add_secretUpSql() (*asset, error) {
return nil, err
}
info := bindataFileInfo{name: "1558084410_add_secret.up.sql", size: 301, mode: os.FileMode(0644), modTime: time.Unix(1564484687, 0)}
info := bindataFileInfo{name: "1558084410_add_secret.up.sql", size: 301, mode: os.FileMode(0644), modTime: time.Unix(1574354941, 0)}
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xf5, 0x32, 0x36, 0x8e, 0x47, 0xb0, 0x8f, 0xc1, 0xc6, 0xf7, 0xc6, 0x9f, 0x2d, 0x44, 0x75, 0x2b, 0x26, 0xec, 0x6, 0xa0, 0x7b, 0xa5, 0xbd, 0xc8, 0x76, 0x8a, 0x82, 0x68, 0x2, 0x42, 0xb5, 0xf4}}
return a, nil
}
@ -300,7 +300,7 @@ func _1558588866_add_versionDownSql() (*asset, error) {
return nil, err
}
info := bindataFileInfo{name: "1558588866_add_version.down.sql", size: 47, mode: os.FileMode(0644), modTime: time.Unix(1564484687, 0)}
info := bindataFileInfo{name: "1558588866_add_version.down.sql", size: 47, mode: os.FileMode(0644), modTime: time.Unix(1574354941, 0)}
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xde, 0x52, 0x34, 0x3c, 0x46, 0x4a, 0xf0, 0x72, 0x47, 0x6f, 0x49, 0x5c, 0xc7, 0xf9, 0x32, 0xce, 0xc4, 0x3d, 0xfd, 0x61, 0xa1, 0x8b, 0x8f, 0xf2, 0x31, 0x34, 0xde, 0x15, 0x49, 0xa6, 0xde, 0xb9}}
return a, nil
}
@ -320,7 +320,7 @@ func _1558588866_add_versionUpSql() (*asset, error) {
return nil, err
}
info := bindataFileInfo{name: "1558588866_add_version.up.sql", size: 57, mode: os.FileMode(0644), modTime: time.Unix(1564484687, 0)}
info := bindataFileInfo{name: "1558588866_add_version.up.sql", size: 57, mode: os.FileMode(0644), modTime: time.Unix(1574354941, 0)}
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x2a, 0xea, 0x64, 0x39, 0x61, 0x20, 0x83, 0x83, 0xb, 0x2e, 0x79, 0x64, 0xb, 0x53, 0xfa, 0xfe, 0xc6, 0xf7, 0x67, 0x42, 0xd3, 0x4f, 0xdc, 0x7e, 0x30, 0x32, 0xe8, 0x14, 0x41, 0xe9, 0xe7, 0x3b}}
return a, nil
}
@ -340,7 +340,7 @@ func _1559627659_add_contact_codeDownSql() (*asset, error) {
return nil, err
}
info := bindataFileInfo{name: "1559627659_add_contact_code.down.sql", size: 32, mode: os.FileMode(0644), modTime: time.Unix(1564484687, 0)}
info := bindataFileInfo{name: "1559627659_add_contact_code.down.sql", size: 32, mode: os.FileMode(0644), modTime: time.Unix(1574354941, 0)}
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x5d, 0x64, 0x6d, 0xce, 0x24, 0x42, 0x20, 0x8d, 0x4f, 0x37, 0xaa, 0x9d, 0xc, 0x57, 0x98, 0xc1, 0xd1, 0x1a, 0x34, 0xcd, 0x9f, 0x8f, 0x34, 0x86, 0xb3, 0xd3, 0xdc, 0xf1, 0x7d, 0xe5, 0x1b, 0x6e}}
return a, nil
}
@ -360,7 +360,7 @@ func _1559627659_add_contact_codeUpSql() (*asset, error) {
return nil, err
}
info := bindataFileInfo{name: "1559627659_add_contact_code.up.sql", size: 198, mode: os.FileMode(0644), modTime: time.Unix(1564484687, 0)}
info := bindataFileInfo{name: "1559627659_add_contact_code.up.sql", size: 198, mode: os.FileMode(0644), modTime: time.Unix(1574354941, 0)}
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x16, 0xf6, 0xc2, 0x62, 0x9c, 0xd2, 0xc9, 0x1e, 0xd8, 0xea, 0xaa, 0xea, 0x95, 0x8f, 0x89, 0x6a, 0x85, 0x5d, 0x9d, 0x99, 0x78, 0x3c, 0x90, 0x66, 0x99, 0x3e, 0x4b, 0x19, 0x62, 0xfb, 0x31, 0x4d}}
return a, nil
}
@ -380,7 +380,7 @@ func _1561368210_add_installation_metadataDownSql() (*asset, error) {
return nil, err
}
info := bindataFileInfo{name: "1561368210_add_installation_metadata.down.sql", size: 35, mode: os.FileMode(0644), modTime: time.Unix(1564484687, 0)}
info := bindataFileInfo{name: "1561368210_add_installation_metadata.down.sql", size: 35, mode: os.FileMode(0644), modTime: time.Unix(1574354941, 0)}
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xa8, 0xde, 0x3f, 0xd2, 0x4a, 0x50, 0x98, 0x56, 0xe3, 0xc0, 0xcd, 0x9d, 0xb0, 0x34, 0x3b, 0xe5, 0x62, 0x18, 0xb5, 0x20, 0xc9, 0x3e, 0xdc, 0x6a, 0x40, 0x36, 0x66, 0xea, 0x51, 0x8c, 0x71, 0xf5}}
return a, nil
}
@ -400,7 +400,7 @@ func _1561368210_add_installation_metadataUpSql() (*asset, error) {
return nil, err
}
info := bindataFileInfo{name: "1561368210_add_installation_metadata.up.sql", size: 267, mode: os.FileMode(0644), modTime: time.Unix(1564484687, 0)}
info := bindataFileInfo{name: "1561368210_add_installation_metadata.up.sql", size: 267, mode: os.FileMode(0644), modTime: time.Unix(1574354941, 0)}
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xb4, 0x71, 0x8f, 0x29, 0xb1, 0xaa, 0xd6, 0xd1, 0x8c, 0x17, 0xef, 0x6c, 0xd5, 0x80, 0xb8, 0x2c, 0xc3, 0xfe, 0xec, 0x24, 0x4d, 0xc8, 0x25, 0xd3, 0xb4, 0xcd, 0xa9, 0xac, 0x63, 0x61, 0xb2, 0x9c}}
return a, nil
}
@ -420,7 +420,7 @@ func docGo() (*asset, error) {
return nil, err
}
info := bindataFileInfo{name: "doc.go", size: 377, mode: os.FileMode(0644), modTime: time.Unix(1564484687, 0)}
info := bindataFileInfo{name: "doc.go", size: 377, mode: os.FileMode(0644), modTime: time.Unix(1574354941, 0)}
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xef, 0xaf, 0xdf, 0xcf, 0x65, 0xae, 0x19, 0xfc, 0x9d, 0x29, 0xc1, 0x91, 0xaf, 0xb5, 0xd5, 0xb1, 0x56, 0xf3, 0xee, 0xa8, 0xba, 0x13, 0x65, 0xdb, 0xab, 0xcf, 0x4e, 0xac, 0x92, 0xe9, 0x60, 0xf1}}
return a, nil
}

View file

@ -384,6 +384,11 @@ func (p *Protocol) GetOurInstallations(myIdentityKey *ecdsa.PublicKey) ([]*multi
return p.multidevice.GetOurInstallations(myIdentityKey)
}
// GetOurActiveInstallations returns all the active installations available given an identity
func (p *Protocol) GetOurActiveInstallations(myIdentityKey *ecdsa.PublicKey) ([]*multidevice.Installation, error) {
return p.multidevice.GetOurActiveInstallations(myIdentityKey)
}
// SetInstallationMetadata sets the metadata for our own installation
func (p *Protocol) SetInstallationMetadata(myIdentityKey *ecdsa.PublicKey, installationID string, data *multidevice.InstallationMetadata) error {
return p.multidevice.SetInstallationMetadata(myIdentityKey, installationID, data)

View file

@ -10,15 +10,15 @@ replace github.com/status-im/status-go/eth-node => ../eth-node
require (
github.com/cenkalti/backoff/v3 v3.0.0
github.com/ethereum/go-ethereum v1.9.5
github.com/golang/protobuf v1.3.2
github.com/gomarkdown/markdown v0.0.0-20191113114344-af599402d015
github.com/google/uuid v1.1.1
github.com/jinzhu/copier v0.0.0-20190625015134-976e0346caa8
github.com/lucasb-eyer/go-colorful v1.0.2
github.com/mattn/go-pointer v0.0.0-20190911064623-a0a44394634f
github.com/mutecomm/go-sqlcipher v0.0.0-20190227152316-55dbde17881f
github.com/pkg/errors v0.8.1
github.com/russolsen/ohyeah v0.0.0-20160324131710-f4938c005315 // indirect
github.com/russolsen/same v0.0.0-20160222130632-f089df61f51d // indirect
github.com/russolsen/transit v0.0.0-20180705123435-0794b4c4505a
github.com/status-im/doubleratchet v3.0.0+incompatible
github.com/status-im/migrate/v4 v4.6.2-status.2
@ -27,4 +27,5 @@ require (
github.com/stretchr/testify v1.4.0
github.com/vacp2p/mvds v0.0.23
go.uber.org/zap v1.13.0
golang.org/x/crypto v0.0.0-20191119213627-4f8c1d86b1ba
)

View file

@ -2,6 +2,8 @@ bazil.org/fuse v0.0.0-20160811212531-371fbbdaa898/go.mod h1:Xbm+BRKSBEpa4q4hTSxo
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
cloud.google.com/go v0.37.4/go.mod h1:NHPJ89PdicEuT9hdPXMROBD91xc5uRDxsMtSB16k7hw=
github.com/AndreasBriese/bbloom v0.0.0-20180913140656-343706a395b7/go.mod h1:bOvUY6CB00SOBii9/FifXqc0awNKxLFCL/+pkDPuyl8=
github.com/AndreasBriese/bbloom v0.0.0-20190306092124-e2d15f34fcf9/go.mod h1:bOvUY6CB00SOBii9/FifXqc0awNKxLFCL/+pkDPuyl8=
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/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78/go.mod h1:LmzpDX56iTiv29bbRTIsUNlaFfuhWRQBWjQdVyAevI8=
@ -10,6 +12,7 @@ github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03
github.com/DATA-DOG/go-sqlmock v1.3.3 h1:CWUqKXe0s8A2z6qCgkP4Kru7wC11YoAnoupUKFDnH08=
github.com/DATA-DOG/go-sqlmock v1.3.3/go.mod h1:f/Ixk793poVmq4qj/V1dPUg2JEAKC73Q5eFN3EC/SaM=
github.com/Julusian/godocdown v0.0.0-20170816220326-6d19f8ff2df8/go.mod h1:INZr5t32rG59/5xeltqoCJoNY7e5x/3xoY9WSWVWg74=
github.com/Kubuxu/go-os-helper v0.0.1/go.mod h1:N8B+I7vPCT80IcP58r50u4+gEEcsZETFUpAzWW2ep1Y=
github.com/Microsoft/go-winio v0.4.11/go.mod h1:VhR8bwka0BXejwEJY73c50VrPtXAaKcyvVC4A4RozmA=
github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5/go.mod h1:lmUJ/7eu/Q8D7ML55dXQrVaamCz2vxCfdQBasLZfHKk=
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
@ -18,7 +21,9 @@ github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMx
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/go.mod h1:Cb/ax3seSYIx7SuZdm2G2xzfwmv3TPSk2ucNfQESPXM=
github.com/allegro/bigcache v1.1.0/go.mod h1:Cb/ax3seSYIx7SuZdm2G2xzfwmv3TPSk2ucNfQESPXM=
github.com/allegro/bigcache v1.2.0 h1:qDaE0QoF29wKBb3+pXFrJFy1ihe5OT9OiXhg1t85SxM=
@ -29,12 +34,20 @@ github.com/aristanetworks/goarista v0.0.0-20170210015632-ea17b1a17847/go.mod h1:
github.com/aristanetworks/goarista v0.0.0-20181002214814-33151c4543a7/go.mod h1:D/tb0zPVXnP7fmsLZjtdUhSsumbK/ij54UXjjVgMGxQ=
github.com/aristanetworks/goarista v0.0.0-20190219163901-728bce664cf5 h1:L0TwgZQo7Mga9im6FvKEZGIvyLE/VG/HI5loz5LpvC0=
github.com/aristanetworks/goarista v0.0.0-20190219163901-728bce664cf5/go.mod h1:D/tb0zPVXnP7fmsLZjtdUhSsumbK/ij54UXjjVgMGxQ=
github.com/aristanetworks/goarista v0.0.0-20190502180301-283422fc1708/go.mod h1:D/tb0zPVXnP7fmsLZjtdUhSsumbK/ij54UXjjVgMGxQ=
github.com/aristanetworks/goarista v0.0.0-20190704150520-f44d68189fd7 h1:fKnuvQ/O22ZpD7HaJjGQXn/GxOdDJOQFL8bpM8Xe3X8=
github.com/aristanetworks/goarista v0.0.0-20190704150520-f44d68189fd7/go.mod h1:D/tb0zPVXnP7fmsLZjtdUhSsumbK/ij54UXjjVgMGxQ=
github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8=
github.com/aws/aws-sdk-go v1.17.7/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo=
github.com/beevik/ntp v0.2.0/go.mod h1:hIHWr+l3+/clUnF44zdK+CWW7fO8dR5cIylAQ76NRpg=
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/bitly/go-hostpool v0.0.0-20171023180738-a3a6125de932/go.mod h1:NOuUCSz6Q9T7+igc/hlvDOUdtWKryOrtFyIVABv/p7k=
github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869/go.mod h1:Ekp36dRnpXw/yCqJaO+ZrUyxD+3VXMFFr56k5XYrpB4=
github.com/btcsuite/btcd v0.0.0-20181013004428-67e573d211ac/go.mod h1:Dmm/EzmjnCiweXmzRIAiUWCInVmPgjkzgv5k4tVyXiQ=
github.com/btcsuite/btcd v0.0.0-20190213025234-306aecffea32/go.mod h1:DrZx5ec/dmnfpw9KyYoQyYo7d0KEvTkk/5M/vbZjAr8=
github.com/btcsuite/btcd v0.0.0-20190418232430-6867ff32788a/go.mod h1:DrZx5ec/dmnfpw9KyYoQyYo7d0KEvTkk/5M/vbZjAr8=
github.com/btcsuite/btcd v0.20.0-beta/go.mod h1:wVuoA8VJLEcwgqHBwHmzLRazpKxTv13Px/pDuV7OomQ=
github.com/btcsuite/btcd v0.20.1-beta h1:Ik4hyJqN8Jfyv3S4AGBOmyouMsYE3EdYODkMbQjwPGw=
@ -53,12 +66,20 @@ github.com/cenkalti/backoff/v3 v3.0.0/go.mod h1:cIeZDE3IrqwwJl6VUwCN6trj1oXrTS4r
github.com/cespare/cp v0.1.0/go.mod h1:SOGHArjBr4JWaSDEVpWpo/hNg6RoKrls6Oh40hiwW+s=
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/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
github.com/cockroachdb/apd v1.1.0/go.mod h1:8Sl8LxpKi29FqWXR16WEFZRNSz3SoPzUzeMeY4+DwBQ=
github.com/cockroachdb/cockroach-go v0.0.0-20181001143604-e0a95dfd547c/go.mod h1:XGLbWH/ujMcbPbhZq52Nv6UrCghb1yGn//133kEsvDk=
github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd/go.mod h1:sE/e/2PUdi/liOCUjSTXgM1o87ZssimdTWN964YiIeI=
github.com/containerd/containerd v1.2.7/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA=
github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk=
github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE=
github.com/cznic/b v0.0.0-20180115125044-35e9bbe41f07/go.mod h1:URriBxXwVq5ijiJ12C7iIZqlA69nTlI+LgI6/pwftG8=
github.com/cznic/fileutil v0.0.0-20180108211300-6a051e75936f/go.mod h1:8S58EK26zhXSxzv7NQFpnliaOQsmDUxvoQO3rt154Vg=
github.com/cznic/golex v0.0.0-20170803123110-4ab7c5e190e4/go.mod h1:+bmmJDNmKlhWNG+gwWCkaBoTy39Fs+bzRxVBzoTQbIc=
@ -77,7 +98,11 @@ github.com/deckarep/golang-set v0.0.0-20180603214616-504e848d77ea/go.mod h1:93vs
github.com/deckarep/golang-set v1.7.1 h1:SCQV0S6gTtp6itiFrTqI+pfmJ4LN85S1YzhDf9rTHJQ=
github.com/deckarep/golang-set v1.7.1/go.mod h1:93vsz/8Wt4joVM7c2AVqh+YRMiUSc14yDtF28KmMOgQ=
github.com/denisenkom/go-mssqldb v0.0.0-20190515213511-eb9f6a1743f3/go.mod h1:zAg7JM8CkOJ43xKXIj7eRO9kmWm/TW578qo+oDO6tuM=
github.com/dgraph-io/badger v1.5.5-0.20190226225317-8115aed38f8f/go.mod h1:VZxzAIRPHRVNRKRo6AXrX9BJegn6il06VMTZVJYCIjQ=
github.com/dgraph-io/badger v1.6.0-rc1/go.mod h1:zwt7syl517jmP8s94KqSxTlM6IMsdhYy6psNgSztDR4=
github.com/dgrijalva/jwt-go v0.0.0-20170201225849-2268707a8f08/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
github.com/dgryski/go-farm v0.0.0-20190104051053-3adb47b1fb0f/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw=
github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw=
github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no=
github.com/dhui/dktest v0.3.0/go.mod h1:cyzIUfGsBEbZ6BT7tnXqAShHSXCZhSNmFl70sZ7c1yc=
github.com/docker/distribution v2.7.0+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
@ -87,6 +112,7 @@ github.com/docker/docker v0.7.3-0.20190817195342-4760db040282/go.mod h1:eEKB0N0r
github.com/docker/docker v1.13.1/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec=
github.com/docker/go-units v0.3.3/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
github.com/dvyukov/go-fuzz v0.0.0-20191022152526-8cb203812681/go.mod h1:11Gm+ccJnvAhCNLlf5+cS9KjtbaD5I5zaZpFMsTHWTw=
github.com/eapache/go-resiliency v1.1.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs=
github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21/go.mod h1:+020luEh2TKB4/GOp8oxxtq0Daoen/Cii55CzbTV6DU=
@ -99,6 +125,7 @@ github.com/elastic/gosigar v0.0.0-20180330100440-37f05ff46ffa/go.mod h1:cdorVVzy
github.com/elastic/gosigar v0.10.4 h1:6jfw75dsoflhBMRdO6QPzQUgLqUYTsQQQRkkcsHsuPo=
github.com/elastic/gosigar v0.10.4/go.mod h1:cdorVVzy1fhmEqmtgqkoE3bYtCfSCkVyjTyCIo22xvs=
github.com/elazarl/go-bindata-assetfs v1.0.0/go.mod h1:v+YaWX3bdea5J/mo8dSETolEo7R71Vk1u8bnjau5yw4=
github.com/ethereum/go-ethereum v1.8.20/go.mod h1:PwpWDrCLZrV+tfrhqqF6kPknbISMHaJv9Ln3kPCZLwY=
github.com/ethereum/go-ethereum v1.9.2/go.mod h1:PwpWDrCLZrV+tfrhqqF6kPknbISMHaJv9Ln3kPCZLwY=
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=
@ -110,11 +137,18 @@ github.com/fsouza/fake-gcs-server v1.7.0/go.mod h1:5XIRs4YvwNbNoz+1JF8j6KLAyDh7R
github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff h1:tY80oXqGNY4FhTFhk+o9oFHGINQ/+vhlm8HFzi6znCI=
github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff/go.mod h1:x7DCsMOv1taUwEWCzT4cmDeAkigA5/QCwUodaVOe8Ww=
github.com/gizak/termui v0.0.0-20170117222342-991cd3d38091/go.mod h1:PkJoWUt/zacQKysNfQtcw1RW+eK2SxkieVBtl+4ovLA=
github.com/go-check/check v0.0.0-20180628173108-788fd7840127/go.mod h1:9ES+weclKsC9YodN5RgxqK/VD9HM9JsCSh7rNhMZE98=
github.com/go-kit/kit v0.8.0 h1:Wz+5lgoB0kkuqLEc6NVmwRknTKP6dTGbSqvhZtBI/j0=
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 h1:8HUsc87TaSWLKwrnumgC8/YconD2fJQsRJAsWaPg2ic=
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/go.mod h1:7FAglXiTm7HKlQRDeOQ6ZNUHidzCWXuZWq/1dTyBNF8=
github.com/go-playground/locales v0.12.1 h1:2FITxuFt/xuCNP1Acdhv62OzaCiviiE4kotfhkmOqEc=
github.com/go-playground/locales v0.12.1/go.mod h1:IUMDtCfWo/w/mtMfIE/IG2K+Ey3ygWanZIBtBW0W2TM=
github.com/go-playground/universal-translator v0.16.0 h1:X++omBR/4cE2MNg91AoC3rmGrCjJ8eAeUP/K/EKx4DM=
github.com/go-playground/universal-translator v0.16.0/go.mod h1:1AnU7NaIRDWWzGEKwgtJRd2xk99HeFyHw3yid4rvQIY=
github.com/go-sql-driver/mysql v1.4.1/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w=
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=
@ -123,12 +157,16 @@ github.com/gocql/gocql v0.0.0-20190301043612-f6df8288f9b4/go.mod h1:4Fw1eo5iaEhD
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
github.com/gogo/protobuf v1.2.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4=
github.com/gogo/protobuf v1.3.0/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o=
github.com/golang-migrate/migrate/v4 v4.6.2 h1:LDDOHo/q1W5UDj6PbkxdCv7lv9yunyZHXvxuwDkGo3k=
github.com/golang-migrate/migrate/v4 v4.6.2/go.mod h1:JYi6reN3+Z734VZ0akNuyOJNcrg45ZL7LDBMW3WGJL0=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.0/go.mod h1:Qd/q+1AKNOZr9uGQzbzCmRO6sUih6GTPZv6a1/R87v0=
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=
@ -138,8 +176,10 @@ github.com/golang/snappy v0.0.1 h1:Qgr9rKW7uDUkrbSmQeiDsGa8SjGyCOGtuasMWwvp2P4=
github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-github v17.0.0+incompatible/go.mod h1:zLgOLi98H3fifZn+44m+umXrS52loVEgC2AApnigrVQ=
github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
@ -150,9 +190,13 @@ github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+
github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg=
github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
github.com/gorilla/mux v1.7.1/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
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/graph-gophers/graphql-go v0.0.0-20190724201507-010347b5f9e6/go.mod h1:Au3iQ8DvDis8hZ4q2OzRcaKYlAsPt+fYvib5q4nIqu4=
github.com/gxed/hashland/keccakpg v0.0.1/go.mod h1:kRzw3HkwxFU1mpmPP8v1WyQzwdGfmKFJ6tItnhQ67kU=
github.com/gxed/hashland/murmur3 v0.0.1/go.mod h1:KjXop02n4/ckmZSnY2+HKcLud/tcmvhST0bie/0lS48=
github.com/gyuho/goraph v0.0.0-20171001060514-a7a4454fd3eb/go.mod h1:NtSxZCD+s3sZFwbW6WceOcUD83HM9XD5OE2r4c0P8eg=
github.com/hailocab/go-hostpool v0.0.0-20160125115350-e80d13ce29ed/go.mod h1:tMWxXQ9wFIaZeTI9F+hmhFiGpFmhOHzyShyFUhRm0H4=
github.com/hashicorp/errwrap v1.0.0 h1:hLrqtEDnRye3+sgx6z4qVLNuviH3MR5aQ0ykNJa/UYA=
github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
@ -162,6 +206,7 @@ github.com/hashicorp/golang-lru v0.0.0-20160813221303-0a025b7e63ad/go.mod h1:/m3
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hashicorp/golang-lru v0.5.1 h1:0hERBMJE1eitiLkihrMvRVBYAkpHzc/J3QdDN+dAcgU=
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
github.com/howeyc/fsnotify v0.9.0/go.mod h1:41HzSPxBGeFRQKEEwgh49TRw/nKBsYZ2cF1OzPjSJsA=
github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI=
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
@ -169,31 +214,54 @@ github.com/huin/goupnp v0.0.0-20161224104101-679507af18f3/go.mod h1:MZ2ZmwcBpvOo
github.com/huin/goupnp v1.0.0 h1:wg75sLpL6DZqwHQN6E1Cfk6mtfzS45z8OV+ic+DtHRo=
github.com/huin/goupnp v1.0.0/go.mod h1:n9v9KO1tAxYH82qOn+UTIFQDmx5n1Zxd/ClZDMX7Bnc=
github.com/huin/goutil v0.0.0-20170803182201-1ca381bf3150/go.mod h1:PpLOETDnJ0o3iZrZfqZzyLl6l7F3c6L1oWn7OICBi6o=
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
github.com/influxdata/influxdb v0.0.0-20180221223340-01288bdb0883/go.mod h1:qZna6X/4elxqT3yI9iZYdZrWWdeFOOprn86kgg4+IzY=
github.com/influxdata/influxdb v1.7.7/go.mod h1:qZna6X/4elxqT3yI9iZYdZrWWdeFOOprn86kgg4+IzY=
github.com/ipfs/go-cid v0.0.1/go.mod h1:GHWU/WuQdMPmIosc4Yn1bcCT7dSeX4lBafM7iqUPQvM=
github.com/ipfs/go-cid v0.0.2/go.mod h1:GHWU/WuQdMPmIosc4Yn1bcCT7dSeX4lBafM7iqUPQvM=
github.com/ipfs/go-cid v0.0.3/go.mod h1:GHWU/WuQdMPmIosc4Yn1bcCT7dSeX4lBafM7iqUPQvM=
github.com/ipfs/go-datastore v0.0.1/go.mod h1:d4KVXhMt913cLBEI/PXAy6ko+W7e9AhyAKBGh803qeE=
github.com/ipfs/go-detect-race v0.0.1/go.mod h1:8BNT7shDZPo99Q74BpGMK+4D8Mn4j46UU0LZ723meps=
github.com/ipfs/go-ds-badger v0.0.2/go.mod h1:Y3QpeSFWQf6MopLTiZD+VT6IC1yZqaGmjvRcKeSGij8=
github.com/ipfs/go-ds-badger v0.0.5/go.mod h1:g5AuuCGmr7efyzQhLL8MzwqcauPojGPUaHzfGTzuE3s=
github.com/ipfs/go-ds-leveldb v0.0.1/go.mod h1:feO8V3kubwsEF22n0YRQCffeb79OOYIykR4L04tMOYc=
github.com/ipfs/go-ipfs-delay v0.0.0-20181109222059-70721b86a9a8/go.mod h1:8SP1YXK1M1kXuc4KJZINY3TQQ03J2rwBG9QfXmbRPrw=
github.com/ipfs/go-ipfs-util v0.0.1/go.mod h1:spsl5z8KUnrve+73pOhSVZND1SIxPW5RyBCNzQxlJBc=
github.com/ipfs/go-log v0.0.1/go.mod h1:kL1d2/hzSpI0thNYjiKfjanbVNU+IIGA/WnNESY9leM=
github.com/jackc/fake v0.0.0-20150926172116-812a484cc733/go.mod h1:WrMFNQdiFJ80sQsxDoMokWK1W5TQtxBFNpzWTD84ibQ=
github.com/jackc/pgx v3.2.0+incompatible/go.mod h1:0ZGrqGqkRlliWnWB4zKnWtjbSWbGkVEFm4TeybAXq+I=
github.com/jackpal/gateway v1.0.5/go.mod h1:lTpwd4ACLXmpyiCTRtfiNyVnUmqT9RivzCDQetPfnjA=
github.com/jackpal/go-nat-pmp v0.0.0-20160603034137-1fa385a6f458/go.mod h1:QPH045xvCAeXUZOxsnwmrtiCoxIr9eob+4orBN1SBKc=
github.com/jackpal/go-nat-pmp v1.0.1 h1:i0LektDkO1QlrTm/cSuP+PyBCDnYvjPLGl4LdWEMiaA=
github.com/jackpal/go-nat-pmp v1.0.1/go.mod h1:QPH045xvCAeXUZOxsnwmrtiCoxIr9eob+4orBN1SBKc=
github.com/jbenet/go-cienv v0.0.0-20150120210510-1bb1476777ec/go.mod h1:rGaEvXB4uRSZMmzKNLoXvTu1sfx+1kv/DojUlPrSZGs=
github.com/jbenet/go-cienv v0.1.0/go.mod h1:TqNnHUmJgXau0nCzC7kXWeotg3J9W34CUv5Djy1+FlA=
github.com/jbenet/go-temp-err-catcher v0.0.0-20150120210811-aac704a3f4f2/go.mod h1:8GXXJV31xl8whumTzdZsTt3RnUIiPqzkyf7mxToRCMs=
github.com/jbenet/goprocess v0.0.0-20160826012719-b497e2f366b8/go.mod h1:Ly/wlsjFq/qrU3Rar62tu1gASgGw6chQbSh/XgIIXCY=
github.com/jbenet/goprocess v0.1.3/go.mod h1:5yspPrukOVuOLORacaBi858NqyClJPQxYZlqdZVfqY4=
github.com/jessevdk/go-flags v0.0.0-20141203071132-1679536dcc89/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
github.com/jinzhu/copier v0.0.0-20190625015134-976e0346caa8 h1:mGIXW/lubQ4B+3bXTLxcTMTjUNDqoF6T/HUW9LbFx9s=
github.com/jinzhu/copier v0.0.0-20190625015134-976e0346caa8/go.mod h1:yL958EeXv8Ylng6IfnvG4oflryUi3vgA3xPs9hmII1s=
github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k=
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/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=
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
github.com/kami-zh/go-capturer v0.0.0-20171211120116-e492ea43421d/go.mod h1:P2viExyCEfeWGU259JnaQ34Inuec4R38JCyBx2edgD0=
github.com/karalabe/hid v0.0.0-20181128192157-d815e0c1a2e2/go.mod h1:YvbcH+3Wo6XPs9nkgTY3u19KXLauXW+J5nB7hEHuX0A=
github.com/karalabe/usb v0.0.0-20190819132248-550797b1cad8 h1:VhnqxaTIudc9IWKx8uXRLnpdSb9noCEj+vHacjmhp68=
github.com/karalabe/usb v0.0.0-20190819132248-550797b1cad8/go.mod h1:Od972xHfMJowv7NGVDiWVxk2zxnWgjLlJzE+F4F7AGU=
github.com/kardianos/osext v0.0.0-20190222173326-2bc1f35cddc0/go.mod h1:1NbS8ALrpOvjt0rHPNLyCIeMtbizbir8U//inJ+zuB8=
github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q=
github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
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/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/koron/go-ssdp v0.0.0-20180514024734-4a0ed625a78b/go.mod h1:5Ky9EC2xfoUKUor0Hjgi2BJhCSXJfMOFlmyYrVKGQMk=
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515 h1:T+h1c/A9Gawja4Y9mFVWj2vyii2bbUNDw3kt9VxK2EY=
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
@ -202,14 +270,80 @@ github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/kshvakov/clickhouse v1.3.5/go.mod h1:DMzX7FxRymoNkVgizH0DWAL8Cur7wHLgx3MUnGwJqpE=
github.com/leodido/go-urn v1.1.0 h1:Sm1gr51B1kKyfD2BlRcLSiEkffoG96g6TPv6eRoEiB8=
github.com/leodido/go-urn v1.1.0/go.mod h1:+cyI34gQWZcE1eQU7NVgKkkzdXDQHr1dBMtdAPozLkw=
github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
github.com/lib/pq v1.2.0 h1:LXpIM/LZ5xGFhOpXAQUIMM1HdyqzVYM13zNdjCEEcA0=
github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
github.com/libp2p/go-addr-util v0.0.1/go.mod h1:4ac6O7n9rIAKB1dnd+s8IbbMXkt+oBpzX4/+RACcnlQ=
github.com/libp2p/go-buffer-pool v0.0.1/go.mod h1:xtyIz9PMobb13WaxR6Zo1Pd1zXJKYg0a8KiIvDp3TzQ=
github.com/libp2p/go-buffer-pool v0.0.2/go.mod h1:MvaB6xw5vOrDl8rYZGLFdKAuk/hRoRZd1Vi32+RXyFM=
github.com/libp2p/go-conn-security-multistream v0.1.0/go.mod h1:aw6eD7LOsHEX7+2hJkDxw1MteijaVcI+/eP2/x3J1xc=
github.com/libp2p/go-eventbus v0.1.0/go.mod h1:vROgu5cs5T7cv7POWlWxBaVLxfSegC5UGQf8A2eEmx4=
github.com/libp2p/go-flow-metrics v0.0.1/go.mod h1:Iv1GH0sG8DtYN3SVJ2eG221wMiNpZxBdp967ls1g+k8=
github.com/libp2p/go-libp2p v0.1.1/go.mod h1:I00BRo1UuUSdpuc8Q2mN7yDF/oTUTRAX6JWpTiK9Rp8=
github.com/libp2p/go-libp2p v0.4.0/go.mod h1:9EsEIf9p2UDuwtPd0DwJsAl0qXVxgAnuDGRvHbfATfI=
github.com/libp2p/go-libp2p-autonat v0.1.0/go.mod h1:1tLf2yXxiE/oKGtDwPYWTSYG3PtvYlJmg7NeVtPRqH8=
github.com/libp2p/go-libp2p-blankhost v0.1.1/go.mod h1:pf2fvdLJPsC1FsVrNP3DUUvMzUts2dsLLBEpo1vW1ro=
github.com/libp2p/go-libp2p-blankhost v0.1.4/go.mod h1:oJF0saYsAXQCSfDq254GMNmLNz6ZTHTOvtF4ZydUvwU=
github.com/libp2p/go-libp2p-circuit v0.1.0/go.mod h1:Ahq4cY3V9VJcHcn1SBXjr78AbFkZeIRmfunbA7pmFh8=
github.com/libp2p/go-libp2p-circuit v0.1.3/go.mod h1:Xqh2TjSy8DD5iV2cCOMzdynd6h8OTBGoV1AWbWor3qM=
github.com/libp2p/go-libp2p-core v0.0.1/go.mod h1:g/VxnTZ/1ygHxH3dKok7Vno1VfpvGcGip57wjTU4fco=
github.com/libp2p/go-libp2p-core v0.0.3/go.mod h1:j+YQMNz9WNSkNezXOsahp9kwZBKBvxLpKD316QWSJXE=
github.com/libp2p/go-libp2p-core v0.0.4/go.mod h1:jyuCQP356gzfCFtRKyvAbNkyeuxb7OlyhWZ3nls5d2I=
github.com/libp2p/go-libp2p-core v0.2.0/go.mod h1:X0eyB0Gy93v0DZtSYbEM7RnMChm9Uv3j7yRXjO77xSI=
github.com/libp2p/go-libp2p-core v0.2.2/go.mod h1:8fcwTbsG2B+lTgRJ1ICZtiM5GWCWZVoVrLaDRvIRng0=
github.com/libp2p/go-libp2p-core v0.2.3/go.mod h1:GqhyQqyIAPsxFYXHMjfXgMv03lxsvM0mFzuYA9Ib42A=
github.com/libp2p/go-libp2p-crypto v0.1.0/go.mod h1:sPUokVISZiy+nNuTTH/TY+leRSxnFj/2GLjtOTW90hI=
github.com/libp2p/go-libp2p-discovery v0.1.0/go.mod h1:4F/x+aldVHjHDHuX85x1zWoFTGElt8HnoDzwkFZm29g=
github.com/libp2p/go-libp2p-loggables v0.1.0/go.mod h1:EyumB2Y6PrYjr55Q3/tiJ/o3xoDasoRYM7nOzEpoa90=
github.com/libp2p/go-libp2p-mplex v0.2.0/go.mod h1:Ejl9IyjvXJ0T9iqUTE1jpYATQ9NM3g+OtR+EMMODbKo=
github.com/libp2p/go-libp2p-mplex v0.2.1/go.mod h1:SC99Rxs8Vuzrf/6WhmH41kNn13TiYdAWNYHrwImKLnE=
github.com/libp2p/go-libp2p-nat v0.0.4/go.mod h1:N9Js/zVtAXqaeT99cXgTV9e75KpnWCvVOiGzlcHmBbY=
github.com/libp2p/go-libp2p-netutil v0.1.0/go.mod h1:3Qv/aDqtMLTUyQeundkKsA+YCThNdbQD54k3TqjpbFU=
github.com/libp2p/go-libp2p-peer v0.2.0/go.mod h1:RCffaCvUyW2CJmG2gAWVqwePwW7JMgxjsHm7+J5kjWY=
github.com/libp2p/go-libp2p-peerstore v0.1.0/go.mod h1:2CeHkQsr8svp4fZ+Oi9ykN1HBb6u0MOvdJ7YIsmcwtY=
github.com/libp2p/go-libp2p-peerstore v0.1.3/go.mod h1:BJ9sHlm59/80oSkpWgr1MyY1ciXAXV397W6h1GH/uKI=
github.com/libp2p/go-libp2p-secio v0.1.0/go.mod h1:tMJo2w7h3+wN4pgU2LSYeiKPrfqBgkOsdiKK77hE7c8=
github.com/libp2p/go-libp2p-secio v0.2.0/go.mod h1:2JdZepB8J5V9mBp79BmwsaPQhRPNN2NrnB2lKQcdy6g=
github.com/libp2p/go-libp2p-swarm v0.1.0/go.mod h1:wQVsCdjsuZoc730CgOvh5ox6K8evllckjebkdiY5ta4=
github.com/libp2p/go-libp2p-swarm v0.2.2/go.mod h1:fvmtQ0T1nErXym1/aa1uJEyN7JzaTNyBcHImCxRpPKU=
github.com/libp2p/go-libp2p-testing v0.0.2/go.mod h1:gvchhf3FQOtBdr+eFUABet5a4MBLK8jM3V4Zghvmi+E=
github.com/libp2p/go-libp2p-testing v0.0.3/go.mod h1:gvchhf3FQOtBdr+eFUABet5a4MBLK8jM3V4Zghvmi+E=
github.com/libp2p/go-libp2p-testing v0.0.4/go.mod h1:gvchhf3FQOtBdr+eFUABet5a4MBLK8jM3V4Zghvmi+E=
github.com/libp2p/go-libp2p-testing v0.1.0/go.mod h1:xaZWMJrPUM5GlDBxCeGUi7kI4eqnjVyavGroI2nxEM0=
github.com/libp2p/go-libp2p-transport-upgrader v0.1.1/go.mod h1:IEtA6or8JUbsV07qPW4r01GnTenLW4oi3lOPbUMGJJA=
github.com/libp2p/go-libp2p-yamux v0.2.0/go.mod h1:Db2gU+XfLpm6E4rG5uGCFX6uXA8MEXOxFcRoXUODaK8=
github.com/libp2p/go-libp2p-yamux v0.2.1/go.mod h1:1FBXiHDk1VyRM1C0aez2bCfHQ4vMZKkAQzZbkSQt5fI=
github.com/libp2p/go-maddr-filter v0.0.4/go.mod h1:6eT12kSQMA9x2pvFQa+xesMKUBlj9VImZbj3B9FBH/Q=
github.com/libp2p/go-maddr-filter v0.0.5/go.mod h1:Jk+36PMfIqCJhAnaASRH83bdAvfDRp/w6ENFaC9bG+M=
github.com/libp2p/go-mplex v0.0.3/go.mod h1:pK5yMLmOoBR1pNCqDlA2GQrdAVTMkqFalaTWe7l4Yd0=
github.com/libp2p/go-mplex v0.1.0/go.mod h1:SXgmdki2kwCUlCCbfGLEgHjC4pFqhTp0ZoV6aiKgxDU=
github.com/libp2p/go-msgio v0.0.2/go.mod h1:63lBBgOTDKQL6EWazRMCwXsEeEeK9O2Cd+0+6OOuipQ=
github.com/libp2p/go-msgio v0.0.4/go.mod h1:63lBBgOTDKQL6EWazRMCwXsEeEeK9O2Cd+0+6OOuipQ=
github.com/libp2p/go-nat v0.0.3/go.mod h1:88nUEt0k0JD45Bk93NIwDqjlhiOwOoV36GchpcVc1yI=
github.com/libp2p/go-openssl v0.0.2/go.mod h1:v8Zw2ijCSWBQi8Pq5GAixw6DbFfa9u6VIYDXnvOXkc0=
github.com/libp2p/go-reuseport v0.0.1/go.mod h1:jn6RmB1ufnQwl0Q1f+YxAj8isJgDCQzaaxIFYDhcYEA=
github.com/libp2p/go-reuseport-transport v0.0.2/go.mod h1:YkbSDrvjUVDL6b8XqriyA20obEtsW9BLkuOUyQAOCbs=
github.com/libp2p/go-stream-muxer v0.0.1/go.mod h1:bAo8x7YkSpadMTbtTaxGVHWUQsR/l5MEaHbKaliuT14=
github.com/libp2p/go-stream-muxer-multistream v0.2.0/go.mod h1:j9eyPol/LLRqT+GPLSxvimPhNph4sfYfMoDPd7HkzIc=
github.com/libp2p/go-tcp-transport v0.1.0/go.mod h1:oJ8I5VXryj493DEJ7OsBieu8fcg2nHGctwtInJVpipc=
github.com/libp2p/go-tcp-transport v0.1.1/go.mod h1:3HzGvLbx6etZjnFlERyakbaYPdfjg2pWP97dFZworkY=
github.com/libp2p/go-ws-transport v0.1.0/go.mod h1:rjw1MG1LU9YDC6gzmwObkPd/Sqwhw7yT74kj3raBFuo=
github.com/libp2p/go-ws-transport v0.1.2/go.mod h1:dsh2Ld8F+XNmzpkaAijmg5Is+e9l6/1tK/6VFOdN69Y=
github.com/libp2p/go-yamux v1.2.2/go.mod h1:FGTiPvoV/3DVdgWpX+tM0OW3tsM+W5bSE3gZwqQTcow=
github.com/libp2p/go-yamux v1.2.3/go.mod h1:FGTiPvoV/3DVdgWpX+tM0OW3tsM+W5bSE3gZwqQTcow=
github.com/lucasb-eyer/go-colorful v1.0.2 h1:mCMFu6PgSozg9tDNMMK3g18oJBX7oYGrC09mS6CXfO4=
github.com/lucasb-eyer/go-colorful v1.0.2/go.mod h1:0MS4r+7BZKSJ5mw4/S5MPN+qHFF1fYclkSPilDOKW0s=
github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
github.com/mailru/easyjson v0.0.0-20180823135443-60711f1a8329/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
github.com/maruel/panicparse v0.0.0-20160720141634-ad661195ed0e/go.mod h1:nty42YY5QByNC5MM7q/nj938VbgPU7avs45z6NClpxI=
github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
github.com/mattn/go-colorable v0.1.0/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
github.com/mattn/go-colorable v0.1.1 h1:G1f5SKeVxmagw/IyvzvtZE4Gybcc4Tr1tf7I8z0XgOg=
github.com/mattn/go-colorable v0.1.1/go.mod h1:FuOcm+DKB9mbwrcAfNl7/TZVBZ6rcnceauSikq3lYCQ=
github.com/mattn/go-isatty v0.0.0-20180830101745-3fb116b82035/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
github.com/mattn/go-isatty v0.0.5/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
github.com/mattn/go-isatty v0.0.7 h1:UvyT9uN+3r7yLEYSlJsbQGdsaB/a0DlgWP3pql6iwOc=
github.com/mattn/go-isatty v0.0.7/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
@ -219,16 +353,24 @@ github.com/mattn/go-runewidth v0.0.4 h1:2BvfKmzob6Bmd4YsL0zygOqfdFnK7GR4QL06Do4/
github.com/mattn/go-runewidth v0.0.4/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
github.com/mattn/go-sqlite3 v1.10.0 h1:jbhqpg7tQe4SupckyijYiy0mJJ/pRyHvXf7JdWK860o=
github.com/mattn/go-sqlite3 v1.10.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc=
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/mgutz/ansi v0.0.0-20170206155736-9520e82c474b/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE=
github.com/miekg/dns v1.1.12/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg=
github.com/minio/blake2b-simd v0.0.0-20160723061019-3f5f724cb5b1 h1:lYpkrQH5ajf0OXOcUbGjvZxxijuBwbbmlSxLiuofa+g=
github.com/minio/blake2b-simd v0.0.0-20160723061019-3f5f724cb5b1/go.mod h1:pD8RvIylQ358TN4wwqatJ8rNavkEINozVn9DtGI3dfQ=
github.com/minio/sha256-simd v0.0.0-20190328051042-05b4dd3047e5 h1:l16XLUUJ34wIz+RIvLhSwGvLvKyy+W598b135bJN6mg=
github.com/minio/sha256-simd v0.0.0-20190328051042-05b4dd3047e5/go.mod h1:2FMWW+8GMoPweT6+pI63m9YE3Lmw4J71hV56Chs1E/U=
github.com/mitchellh/go-wordwrap v0.0.0-20150314170334-ad45545899c7/go.mod h1:ZXFpozHsX6DPmq2I0TCekCxypsnAUbP2oI0UX1GXzOo=
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
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/morikuni/aec v0.0.0-20170113033406-39771216ff4c/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc=
github.com/mr-tron/base58 v1.1.0/go.mod h1:xcD2VGqlgYjBdcBLw+TuYLr8afG+Hj8g2eTVqeSzSU8=
github.com/mr-tron/base58 v1.1.1/go.mod h1:xcD2VGqlgYjBdcBLw+TuYLr8afG+Hj8g2eTVqeSzSU8=
github.com/mr-tron/base58 v1.1.2 h1:ZEw4I2EgPKDJ2iEw0cNmLB3ROrEmkOtXIkaG7wZg+78=
github.com/mr-tron/base58 v1.1.2/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc=
github.com/multiformats/go-multihash v0.0.5 h1:1wxmCvTXAifAepIMyF39vZinRw5sbqjPs/UIi93+uik=
@ -240,25 +382,30 @@ github.com/nakagami/firebirdsql v0.0.0-20190310045651-3c02a58cfed8/go.mod h1:86w
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/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U=
github.com/okzk/sdnotify v0.0.0-20180710141335-d9becc38acbd/go.mod h1:4soZNh0zW0LtYGdQ416i0jO0EIqMGcbtaspRS4BDvRQ=
github.com/olekukonko/tablewriter v0.0.0-20170128050532-febf2d34b54a/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo=
github.com/olekukonko/tablewriter v0.0.1 h1:b3iUnf1v+ppJiOfNX4yxxqfWKMQPZR5yoh8urCTFX88=
github.com/olekukonko/tablewriter v0.0.1/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/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v1.8.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v1.10.1 h1:q/mM8GF/n0shIN8SaAZ0V+jnLPzen6WIVZdiwrRlMlo=
github.com/onsi/ginkgo v1.10.1/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
github.com/onsi/gomega v1.5.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
github.com/onsi/gomega v1.7.0 h1:XPnZz8VVBHjVsy1vzJmRwIcSwiUO+JFfrv/xGiigmME=
github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
github.com/opencontainers/go-digest v1.0.0-rc1/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s=
github.com/opencontainers/image-spec v1.0.1/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0=
github.com/opentracing/opentracing-go v0.0.0-20180606204148-bd9c31933947/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o=
github.com/opentracing/opentracing-go v1.0.2/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o=
github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o=
github.com/openzipkin/zipkin-go v0.1.6/go.mod h1:QgAqvLzwWbR/WpD4A3cGpPtJrZXNIiJc5AZX7/PBEpw=
github.com/oschwald/maxminddb-golang v1.3.1/go.mod h1:3jhIUymTJ5VREKyIhWm66LJiQt04F0UCDdodShpjWsY=
github.com/pborman/uuid v0.0.0-20170112150404-1b00554d8222/go.mod h1:VyrYX9gd7irzKovcSS6BIIEwPRkP2Wm2m9ufcdFSJ34=
github.com/pborman/uuid v1.2.0 h1:J7Q5mO4ysT1dv8hyrUGHb9+ooztCXu1D8MY8DZYsu3g=
github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k=
github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
github.com/peterh/liner v0.0.0-20170902204657-a37ad3984311/go.mod h1:xIteQHvHuaLYG9IFj6mSxM0fCKrs34IrEQUhOYuGPHc=
github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY=
github.com/pkg/errors v0.0.0-20171216070316-e881fd58d78e/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
@ -268,16 +415,27 @@ github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINE
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 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_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
github.com/prometheus/client_model v0.0.0-20190115171406-56726106282f/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.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/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/prometheus v0.0.0-20170814170113-3101606756c5/go.mod h1:oAIUtOny2rjMX0OWN5vPR5/q/twIROJvdqnQKDdil/s=
github.com/prometheus/tsdb v0.10.0 h1:If5rVCMTp6W2SiRAQFlbpJNgVlgMEd+U2GZckwK38ic=
github.com/prometheus/tsdb v0.10.0/go.mod h1:oi49uRhEe9dPUTlS3JRZOwJuVi6tmh10QSgwXEyGCt4=
@ -298,14 +456,26 @@ github.com/russolsen/same v0.0.0-20160222130632-f089df61f51d h1:A926QrjwToaPS7gi
github.com/russolsen/same v0.0.0-20160222130632-f089df61f51d/go.mod h1:Cpq811GTlHevuU6BZxk3ObOdK8AY5gHu9QGmDak0DT4=
github.com/russolsen/transit v0.0.0-20180705123435-0794b4c4505a h1:yVNJFSzkEG8smsvd9udiQcMJA0MIsFvlG7ba314cu+s=
github.com/russolsen/transit v0.0.0-20180705123435-0794b4c4505a/go.mod h1:TPq+fcJOdGrkpZpXF4UVmFjYxH0gGqnxdgZ+OzAmvJk=
github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g=
github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0=
github.com/shopspring/decimal v0.0.0-20180709203117-cd690d0c9e24 h1:pntxY8Ary0t43dCZ5dqY4YTJCObLY1kIXl0uzMv+7DE=
github.com/shopspring/decimal v0.0.0-20180709203117-cd690d0c9e24/go.mod h1:M+9NzErvs504Cn4c5DxATwIqPbtswREoFCre64PpcG4=
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q=
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
github.com/smola/gocompat v0.2.0/go.mod h1:1B0MlxbmoZNo3h8guHp8HztB3BSYR5itql9qtVc0ypY=
github.com/spacemonkeygo/openssl v0.0.0-20181017203307-c2dcc5cca94a/go.mod h1:7AyxJNCJ7SBZ1MfVQCWD6Uqo2oubI2Eq2y2eqf+A5r0=
github.com/spacemonkeygo/spacelog v0.0.0-20180420211403-2296661a0572/go.mod h1:w0SWMsp6j9O/dk4/ZpIhL+3CkG8ofA2vuv7k+ltqUMc=
github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
github.com/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0bLI=
github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ=
github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU=
github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo=
github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s=
github.com/src-d/envconfig v1.0.0/go.mod h1:Q9YQZ7BKITldTBnoxsE5gOeB5y66RyPXeue/R4aaNBc=
github.com/status-im/doubleratchet v3.0.0+incompatible h1:aJ1ejcSERpSzmWZBgtfYtiU2nF0Q8ZkGyuEPYETXkCY=
github.com/status-im/doubleratchet v3.0.0+incompatible/go.mod h1:1sqR0+yhiM/bd+wrdX79AOt2csZuJOni0nUDzKNuqOU=
github.com/status-im/go-ethereum v1.9.5-status.6 h1:ytuTO1yBIAuTVRtRQoc2mrdyngtP+XOQ9IHIibbz7/I=
@ -316,10 +486,13 @@ github.com/status-im/markdown v0.0.0-20191113114344-af599402d015 h1:ijC73VP0hucs
github.com/status-im/markdown v0.0.0-20191113114344-af599402d015/go.mod h1:tmG2bxyvZ2EItDO5JewbdFvV45j13IYQgvnMJ3+qAaE=
github.com/status-im/migrate/v4 v4.6.2-status.2 h1:SdC+sMDl/aI7vUlwD2qj2p7KsK4T60IS9z4/rYCCbI8=
github.com/status-im/migrate/v4 v4.6.2-status.2/go.mod h1:c/kc90n47GZu/58nnz1OMLTf7uE4Da4gZP5qmU+A/v8=
github.com/status-im/status-go v0.36.0 h1:91qDMJjHv+T3Li9FwxsWQ2JBVcYtvVDT0nGFSMnmM+8=
github.com/status-im/status-go/extkeys v1.0.0 h1:Qyirsoi5Ye5UFfisgPtCjPb/RkBxyK+UsSiEcr2PVlM=
github.com/status-im/status-go/extkeys v1.0.0/go.mod h1:GdqJbrcpkNm5ZsSCpp+PdMxnXx+OcRBdm3PI0rs1FpU=
github.com/status-im/whisper v1.5.2 h1:26NgiKusmPic38eQdtXnaY+iaQ/LuQ3Dh0kCGYT/Uxs=
github.com/status-im/whisper v1.5.2/go.mod h1:emrOxzJme0k66QtbbQ2bdd3P8RCdLZ8sTD7SkwH1s2s=
github.com/status-im/whisper v1.6.1 h1:C/T1HQHZfUI2jbccf3yIe8yfkl435I3BILIKeNASJDc=
github.com/status-im/whisper v1.6.1/go.mod h1:lygchT4p9Y1/hR451OhNNqfinvy9EYEDxtXU2T/U30Q=
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=
@ -338,10 +511,13 @@ github.com/syndtr/goleveldb v0.0.0-20181128100959-b001fa50d6b2/go.mod h1:Z4AUp2K
github.com/syndtr/goleveldb v1.0.0 h1:fBdIW9lB4Iz0n9khmH8w27SJ3QEJ7+IgjPEwGSZiFdE=
github.com/syndtr/goleveldb v1.0.0/go.mod h1:ZVVdQEZoIme9iO1Ch2Jdy24qqXrMMOU6lpPAyBWyWuQ=
github.com/tidwall/pretty v0.0.0-20180105212114-65a9db5fad51/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk=
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/tyler-smith/go-bip39 v1.0.2 h1:+t3w+KwLXO6154GNJY+qUtIxLTmFjfUmpguQT1OlOT8=
github.com/tyler-smith/go-bip39 v1.0.2/go.mod h1:sJ5fKU0s6JVwZjjcUEX2zFOnvq0ASQ2K9Zr6cf67kNs=
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=
github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0=
github.com/vacp2p/mvds v0.0.23 h1:BKdn7tyGvl/J/Pwv6FlcW6Xbzm+17jv141GB1mFXyOU=
github.com/vacp2p/mvds v0.0.23/go.mod h1:uUmtiahU7efOVl/5w5yk9jOze5xYpDZDrSrT8TvHXjQ=
github.com/wealdtech/go-ens/v3 v3.0.9 h1:gXMBNXikJ/XV9k6ybPOZMXIMPjBGSCC9N10dxe8Y2Xk=
@ -350,15 +526,26 @@ github.com/wealdtech/go-multicodec v1.2.0 h1:9AHSxcSE9F9r6ZvQLAO0EXCdM08QfYohaXm
github.com/wealdtech/go-multicodec v1.2.0/go.mod h1:aedGMaTeYkIqi/KCPre1ho5rTb3hGpu/snBOS3GQLw4=
github.com/wealdtech/go-string2eth v1.0.0 h1:jY6b1MVqU6k2Uw/kvcU1Y9/3dDyXfPzZrOFspt82UJs=
github.com/wealdtech/go-string2eth v1.0.0/go.mod h1:UZA/snEybGcD6n+Pl+yoDjmexlEJ6dtoS9myfM83Ol4=
github.com/whyrusleeping/go-keyspace v0.0.0-20160322163242-5b898ac5add1/go.mod h1:8UvriyWtv5Q5EOgjHaSseUEdkQfvwFv1I/In/O2M9gc=
github.com/whyrusleeping/go-logging v0.0.0-20170515211332-0457bb6b88fc/go.mod h1:bopw91TMyo8J3tvftk8xmU2kPmlrt4nScJQZU2hE5EM=
github.com/whyrusleeping/go-notifier v0.0.0-20170827234753-097c5d47330f/go.mod h1:cZNvX9cFybI01GriPRMXDtczuvUhgbcYr9iCGaNlRv8=
github.com/whyrusleeping/mafmt v1.2.8/go.mod h1:faQJFPbLSxzD9xpA02ttW/tS9vZykNvXwGvqIpk20FA=
github.com/whyrusleeping/mdns v0.0.0-20180901202407-ef14215e6b30/go.mod h1:j4l84WPFclQPj320J9gp0XwNKBb3U0zt5CBqjPp22G4=
github.com/whyrusleeping/mdns v0.0.0-20190826153040-b9b60ed33aa9/go.mod h1:j4l84WPFclQPj320J9gp0XwNKBb3U0zt5CBqjPp22G4=
github.com/whyrusleeping/multiaddr-filter v0.0.0-20160516205228-e903e4adabd7/go.mod h1:X2c0RVCI1eSUFI8eLcY3c0423ykwiUdxLJtkDvruhjI=
github.com/wsddn/go-ecdh v0.0.0-20161211032359-48726bab9208 h1:1cngl9mPEoITZG8s8cVcUy5CeIBYhEESkOB7m6Gmkrk=
github.com/wsddn/go-ecdh v0.0.0-20161211032359-48726bab9208/go.mod h1:IotVbo4F+mw0EzQ08zFqg7pK3FebNXpaMsRy2RT+Ees=
github.com/x-cray/logrus-prefixed-formatter v0.5.2/go.mod h1:2duySbKsL6M18s5GU7VPsoEPHyzalCE06qoARUCeBBE=
github.com/xanzy/go-gitlab v0.15.0/go.mod h1:8zdQa/ri1dfn8eS3Ir1SyfvOKlw7WBJ8DVThkpGiXrs=
github.com/xdg/scram v0.0.0-20180814205039-7eeb5667e42c/go.mod h1:lB8K/P019DLNhemzwFU4jHLhdvlE6uDZjXFejJXr49I=
github.com/xdg/stringprep v1.0.0/go.mod h1:Jhud4/sHMO4oL310DaZAKk9ZaJ08SJfe+sJh0HrGL1Y=
github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q=
gitlab.com/nyarla/go-crypt v0.0.0-20160106005555-d9a5dc2b789b/go.mod h1:T3BPAOm2cqquPa0MKWeNkmOM5RQsRhkrwMWonFMN7fE=
go.mongodb.org/mongo-driver v1.1.0/go.mod h1:u7ryQJ+DOzQmeO7zB6MHyr8jkEQvC8vH7qLUO4lqsUM=
go.opencensus.io v0.20.1/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk=
go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
go.opencensus.io v0.22.1/go.mod h1:Ap50jQcDJrx6rB6VgeeFPtuPIf3wMRvRfrfYDO6+BmA=
go.uber.org/atomic v1.4.0 h1:cxzIVoETapQEqDhQu3QfnvXAV4AlzcvUCxkVUFw3+EU=
go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
go.uber.org/atomic v1.5.0 h1:OI5t8sDa1Or+q8AeE+yKeB/SDYioSHAgcVljj9JIETY=
go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ=
@ -373,11 +560,20 @@ go.uber.org/zap v1.13.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM=
golang.org/dl v0.0.0-20190829154251-82a15e2f2ead/go.mod h1:IUMfjQLJQd4UTqG1Z90tenwKoCX93Gn3MAQJMOSBsDQ=
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-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190103213133-ff983b9c42bc/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190211182817-74369b46fc67/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190225124518-7f87c0fbb88b/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-20190325154230-a5d413f7728c/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190426145343-a29dc8fdc734/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190513172903-22d7a77e9e5f/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190530122614-20be4c3c3ed5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190618222545-ea8f1a30c443/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190923035154-9ee001bba392/go.mod h1:/lpIB1dKB+9EgE3H3cr1v9wB50oz8l4C4h62xy7jSTY=
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=
@ -395,11 +591,13 @@ golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73r
golang.org/x/net v0.0.0-20181011144130-49bb7cea24b1/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181108082009-03003ca0c849/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-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190125091013-d26f9f9a57f3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190225153610-fe579d43d832/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190227160552-c95aed5357e7/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190424112056-4829fb13d2c6/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
@ -421,9 +619,12 @@ golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5h
golang.org/x/sys v0.0.0-20180926160741-c2ed4eda69e7/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-20181122145206-62eef0e2fa9b/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190102155601-82a175fd1598/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-20190219092855-153ac476189d/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190228124157-a34e9553db1e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190426135247-a129542de9ae h1:mQLHiymj/JXKnnjc62tb7nD5pZLs940/sXJu+Xp3DBA=
golang.org/x/sys v0.0.0-20190426135247-a129542de9ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@ -436,10 +637,13 @@ golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxb
golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20181130052023-1c3d964395ce/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
golang.org/x/tools v0.0.0-20190425222832-ad9eeb80039a/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
@ -455,6 +659,7 @@ google.golang.org/appengine v1.3.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
google.golang.org/genproto v0.0.0-20180831171423-11092d34479b/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
google.golang.org/genproto v0.0.0-20190404172233-64821d5d2107/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
@ -469,13 +674,20 @@ gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4=
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
gopkg.in/go-playground/assert.v1 v1.2.1/go.mod h1:9RXL0bg/zibRAgZUYszZSwO/z8Y/a8bDuhia5mkpMnE=
gopkg.in/go-playground/validator.v9 v9.29.1 h1:SvGtYmN60a5CVKTOzMSyfzWDeZRxRuGvRQyEAKbw1xc=
gopkg.in/go-playground/validator.v9 v9.29.1/go.mod h1:+c9/zcJMFNgbLvly1L1V+PpxWdVbfP1avr/N00E2vyQ=
gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
gopkg.in/natefinch/lumberjack.v2 v2.0.0 h1:1Lc07Kr7qY4U2YPouBjpCLxpiyxIVoxqXgkXLknAOE8=
gopkg.in/natefinch/lumberjack.v2 v2.0.0/go.mod h1:l0ndWWf7gzL7RNwBG7wST/UCcT4T24xpD6X8LsfU/+k=
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/olebedev/go-duktape.v3 v3.0.0-20190709231704-1e4459ed25ff h1:uuol9OUzSvZntY1v963NAbVd7A+PHLMz1FlCe3Lorcs=
gopkg.in/olebedev/go-duktape.v3 v3.0.0-20190709231704-1e4459ed25ff/go.mod h1:uAJfkITjFhyEEuUfm7bsmCZRbW5WRq8s9EY8HZ6hCns=
gopkg.in/sourcemap.v1 v1.0.5/go.mod h1:2RlvNNSMglmRrcvhfuzp4hQHwOtjxlbjX7UPY/GXb78=
gopkg.in/src-d/go-cli.v0 v0.0.0-20181105080154-d492247bbc0d/go.mod h1:z+K8VcOYVYcSwSjGebuDL6176A1XskgbtNl64NSg+n8=
gopkg.in/src-d/go-log.v1 v1.0.1/go.mod h1:GN34hKP0g305ysm2/hctJ0Y8nWP3zxXXJ8GFabTyABE=
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 h1:NdAVW6RYxDif9DhDHaAortIu956m2c0v+09AZBPTbE0=

View file

@ -1,72 +1,159 @@
package protocol
import (
"database/sql/driver"
"crypto/ecdsa"
"encoding/json"
"strings"
"unicode"
"unicode/utf8"
"github.com/pkg/errors"
"github.com/status-im/status-go/eth-node/types"
"github.com/gomarkdown/markdown"
"github.com/status-im/status-go/protocol/protobuf"
)
type hexutilSQL types.HexBytes
func (h hexutilSQL) Value() (driver.Value, error) {
return []byte(h), nil
}
func (h hexutilSQL) String() string {
return types.EncodeHex(h)
}
func (h *hexutilSQL) Scan(value interface{}) error {
if value == nil {
return nil
}
if b, ok := value.([]byte); ok {
*h = hexutilSQL(b)
return nil
}
return errors.New("failed to scan hexutilSQL")
}
// QuotedMessage contains the original text of the message replied to
type QuotedMessage struct {
// From is a public key of the author of the message.
From string `json:"from"`
Content string `json:"content"`
From string `json:"from"`
Text string `json:"text"`
}
const (
OutgoingStatusSending = "sending"
OutgoingStatusSent = "sent"
)
// Message represents a message record in the database,
// more specifically in user_messages_legacy table.
// Encoding and decoding of byte blobs should be performed
// using hexutil package.
type Message struct {
protobuf.ChatMessage
// ID calculated as keccak256(compressedAuthorPubKey, data) where data is unencrypted payload.
ID string `json:"id"`
// WhisperTimestamp is a timestamp of a Whisper envelope.
WhisperTimestamp int64 `json:"whisperTimestamp"`
WhisperTimestamp uint64 `json:"whisperTimestamp"`
// From is a public key of the author of the message.
From string `json:"from"`
// Random 3 words name
Alias string `json:"alias"`
// Identicon of the author
Identicon string `json:"identicon"`
// To is a public key of the recipient unless it's a public message then it's empty.
To hexutilSQL `json:"to,omitempty"`
// BEGIN: fields from types.Message.
Content string `json:"content"`
ContentType string `json:"contentType"`
Timestamp int64 `json:"timestamp"`
ChatID string `json:"chatId"`
MessageType string `json:"messageType,omitempty"`
MessageStatus string `json:"messageStatus,omitempty"`
ClockValue int64 `json:"clockValue"`
// END
Username string `json:"username,omitempty"`
// The chat id to be stored locally
LocalChatID string `json:"localChatId"`
RetryCount int `json:"retryCount"`
Show bool `json:"show"` // default true
Seen bool `json:"seen"`
OutgoingStatus string `json:"outgoingStatus,omitempty"`
// MessageID of the replied message
ReplyTo string `json:"replyTo"`
QuotedMessage *QuotedMessage `json:"quotedMessage"`
// Computed fields
RTL bool `json:"rtl"`
ParsedText []byte `json:"parsedText"`
LineCount int `json:"lineCount"`
SigPubKey *ecdsa.PublicKey `json:"-"`
// RawPayload is the marshaled payload, used for resending the message
RawPayload []byte `json:"-"`
}
func (m *Message) MarshalJSON() ([]byte, error) {
type MessageAlias Message
item := struct {
ID string `json:"id"`
WhisperTimestamp uint64 `json:"whisperTimestamp"`
From string `json:"from"`
Alias string `json:"alias"`
Identicon string `json:"identicon"`
RetryCount int `json:"retryCount"`
Seen bool `json:"seen"`
OutgoingStatus string `json:"outgoingStatus,omitempty"`
QuotedMessage *QuotedMessage `json:"quotedMessage"`
RTL bool `json:"rtl"`
ParsedText json.RawMessage `json:"parsedText"`
LineCount int `json:"lineCount"`
Text string `json:"text"`
ChatId string `json:"chatId"`
LocalChatID string `json:"localChatId"`
Clock uint64 `json:"clock"`
ResponseTo string `json:"responseTo"`
EnsName string `json:"ensName"`
Sticker *protobuf.StickerMessage `json:"sticker"`
Timestamp uint64 `json:"timestamp"`
ContentType protobuf.ChatMessage_ContentType `json:"contentType"`
MessageType protobuf.ChatMessage_MessageType `json:"messageType"`
}{
ID: m.ID,
WhisperTimestamp: m.WhisperTimestamp,
From: m.From,
Alias: m.Alias,
Identicon: m.Identicon,
RetryCount: m.RetryCount,
Seen: m.Seen,
OutgoingStatus: m.OutgoingStatus,
QuotedMessage: m.QuotedMessage,
RTL: m.RTL,
ParsedText: m.ParsedText,
LineCount: m.LineCount,
Text: m.Text,
ChatId: m.ChatId,
LocalChatID: m.LocalChatID,
Clock: m.Clock,
ResponseTo: m.ResponseTo,
EnsName: m.EnsName,
Timestamp: m.Timestamp,
ContentType: m.ContentType,
MessageType: m.MessageType,
Sticker: m.GetSticker(),
}
return json.Marshal(item)
}
func (m *Message) UnmarshalJSON(data []byte) error {
type Alias Message
aux := struct {
*Alias
ResponseTo string `json:"responseTo"`
EnsName string `json:"ensName"`
ChatID string `json:"chatId"`
Sticker *protobuf.StickerMessage `json:"sticker"`
ContentType protobuf.ChatMessage_ContentType `json:"contentType"`
}{
Alias: (*Alias)(m),
}
if err := json.Unmarshal(data, &aux); err != nil {
return err
}
if aux.ContentType == protobuf.ChatMessage_STICKER {
m.Payload = &protobuf.ChatMessage_Sticker{Sticker: aux.Sticker}
}
m.ResponseTo = aux.ResponseTo
m.EnsName = aux.EnsName
m.ChatId = aux.ChatID
m.ContentType = aux.ContentType
return nil
}
// Check if the first character is Hebrew or Arabic or the RTL character
func isRTL(s string) bool {
first, _ := utf8.DecodeRuneInString(s)
return unicode.Is(unicode.Hebrew, first) ||
unicode.Is(unicode.Arabic, first) ||
// RTL character
first == '\u200f'
}
// PrepareContent return the parsed content of the message, the line-count and whether
// is a right-to-left message
func (m *Message) PrepareContent() error {
parsedText := markdown.Parse([]byte(m.Text), nil)
jsonParsedText, err := json.Marshal(parsedText)
if err != nil {
return err
}
m.ParsedText = jsonParsedText
m.LineCount = strings.Count(m.Text, "\n")
m.RTL = isRTL(m.Text)
return nil
}

View file

@ -56,7 +56,7 @@ func (h *persistentMessageHandler) chatID(chatID string) (*Chat, error) {
return nil, err
}
for _, ch := range chats {
if chat.ID == chatID {
if ch.ID == chatID {
chat = ch
break
}

View file

@ -92,25 +92,6 @@ func (p *messageProcessor) Stop() {
p.datasync.Stop() // idempotent op
}
func (p *messageProcessor) SendPrivate(
ctx context.Context,
recipient *ecdsa.PublicKey,
chatID string,
data []byte,
clock int64,
) ([]byte, *v1protocol.Message, error) {
message := v1protocol.CreatePrivateTextMessage(data, clock, chatID)
encodedMessage, err := p.encodeMessage(message)
if err != nil {
return nil, nil, errors.Wrap(err, "failed to encode message")
}
messageID, err := p.sendPrivate(ctx, recipient, encodedMessage)
if err != nil {
return nil, nil, err
}
return messageID, &message, nil
}
// SendPrivateRaw takes encoded data, encrypts it and sends through the wire.
func (p *messageProcessor) SendPrivateRaw(
ctx context.Context,
@ -125,6 +106,34 @@ func (p *messageProcessor) SendPrivateRaw(
return p.sendPrivate(ctx, recipient, data)
}
// SendGroupRaw takes encoded data, encrypts it and sends through the wire,
// always return the messageID
func (p *messageProcessor) SendGroupRaw(
ctx context.Context,
recipients []*ecdsa.PublicKey,
data []byte,
) ([]byte, error) {
p.logger.Debug(
"sending a private group message",
zap.String("site", "SendGroupRaw"),
)
// Calculate messageID first
wrappedMessage, err := p.wrapMessageV1(data)
if err != nil {
return nil, errors.Wrap(err, "failed to wrap message")
}
messageID := v1protocol.MessageID(&p.identity.PublicKey, wrappedMessage)
for _, recipient := range recipients {
_, err = p.sendPrivate(ctx, recipient, data)
if err != nil {
return nil, errors.Wrap(err, "failed to send message")
}
}
return messageID, nil
}
// sendPrivate sends data to the recipient identifying with a given public key.
func (p *messageProcessor) sendPrivate(
ctx context.Context,
@ -133,7 +142,7 @@ func (p *messageProcessor) sendPrivate(
) ([]byte, error) {
p.logger.Debug("sending private message", zap.Binary("recipient", crypto.FromECDSAPub(recipient)))
wrappedMessage, err := p.tryWrapMessageV1(data)
wrappedMessage, err := p.wrapMessageV1(data)
if err != nil {
return nil, errors.Wrap(err, "failed to wrap message")
}
@ -164,32 +173,6 @@ func (p *messageProcessor) sendPrivate(
return messageID, nil
}
func (p *messageProcessor) SendGroup(
ctx context.Context,
recipients []*ecdsa.PublicKey,
chatID string,
data []byte,
clock int64,
) ([][]byte, []*v1protocol.Message, error) {
p.logger.Debug("sending a group message", zap.Int("membersCount", len(recipients)))
message := v1protocol.CreatePrivateGroupTextMessage(data, clock, chatID)
encodedMessage, err := p.encodeMessage(message)
if err != nil {
return nil, nil, errors.Wrap(err, "failed to encode message")
}
var resultIDs [][]byte
for _, recipient := range recipients {
messageID, err := p.sendPrivate(ctx, recipient, encodedMessage)
if err != nil {
return nil, nil, err
}
resultIDs = append(resultIDs, messageID)
}
return resultIDs, nil, nil
}
func (p *messageProcessor) SendMembershipUpdate(
ctx context.Context,
recipients []*ecdsa.PublicKey,
@ -219,46 +202,11 @@ func (p *messageProcessor) SendMembershipUpdate(
return resultIDs, nil
}
func (p *messageProcessor) SendPublic(ctx context.Context, chatID string, data []byte, clock int64) ([]byte, error) {
message := v1protocol.CreatePublicTextMessage(data, clock, chatID)
encodedMessage, err := p.encodeMessage(message)
if err != nil {
return nil, errors.Wrap(err, "failed to encode message")
}
wrappedMessage, err := p.tryWrapMessageV1(encodedMessage)
if err != nil {
return nil, errors.Wrap(err, "failed to wrap message")
}
messageSpec, err := p.protocol.BuildPublicMessage(p.identity, wrappedMessage)
if err != nil {
return nil, errors.Wrap(err, "failed to build public message")
}
newMessage, err := messageSpecToWhisper(messageSpec)
if err != nil {
return nil, err
}
hash, err := p.transport.SendPublic(ctx, newMessage, chatID)
if err != nil {
return nil, err
}
messageID := v1protocol.MessageID(&p.identity.PublicKey, wrappedMessage)
p.transport.Track([][]byte{messageID}, hash, newMessage)
return messageID, nil
}
// SendPublicRaw takes encoded data, encrypts it and sends through the wire.
func (p *messageProcessor) SendPublicRaw(ctx context.Context, chatName string, data []byte) ([]byte, error) {
var newMessage *types.NewMessage
wrappedMessage, err := p.tryWrapMessageV1(data)
wrappedMessage, err := p.wrapMessageV1(data)
if err != nil {
return nil, errors.Wrap(err, "failed to wrap message")
}
@ -282,61 +230,6 @@ func (p *messageProcessor) SendPublicRaw(ctx context.Context, chatName string, d
return messageID, nil
}
// Process processes received Whisper messages through all the layers
// and returns decoded user messages.
// It also handled all non-user messages like PairMessage.
func (p *messageProcessor) Process(shhMessage *types.Message) ([]*v1protocol.Message, error) {
logger := p.logger.With(zap.String("site", "Process"))
var decodedMessages []*v1protocol.Message
hlogger := logger.With(zap.Binary("hash", shhMessage.Hash))
hlogger.Debug("handling a received message")
statusMessages, err := p.handleMessages(shhMessage, true)
if err != nil {
return nil, err
}
for _, statusMessage := range statusMessages {
switch m := statusMessage.ParsedMessage.(type) {
case v1protocol.Message:
m.ID = statusMessage.ID
m.SigPubKey = statusMessage.SigPubKey()
decodedMessages = append(decodedMessages, &m)
case v1protocol.MembershipUpdateMessage:
// Handle user message that can be attached to the membership update.
userMessage := m.Message
if userMessage != nil {
userMessage.ID = statusMessage.ID
userMessage.SigPubKey = statusMessage.SigPubKey()
decodedMessages = append(decodedMessages, userMessage)
}
if err := p.processMembershipUpdate(m); err != nil {
hlogger.Error("failed to process MembershipUpdateMessage", zap.Error(err))
}
case v1protocol.PairMessage:
fromOurDevice := isPubKeyEqual(statusMessage.SigPubKey(), &p.identity.PublicKey)
if !fromOurDevice {
hlogger.Debug("received PairMessage from not our device, skipping")
break
}
if err := p.processPairMessage(m); err != nil {
hlogger.Error("failed to process PairMessage", zap.Error(err))
}
default:
hlogger.Error(
"skipped a public message of unsupported type",
zap.Any("value", statusMessage.ParsedMessage),
)
}
}
return decodedMessages, nil
}
func (p *messageProcessor) processMembershipUpdate(m v1protocol.MembershipUpdateMessage) error {
if err := m.Verify(); err != nil {
return err
@ -443,23 +336,12 @@ func (p *messageProcessor) handleErrDeviceNotFound(ctx context.Context, publicKe
return nil
}
func (p *messageProcessor) encodeMessage(message v1protocol.Message) ([]byte, error) {
encodedMessage, err := v1protocol.EncodeMessage(message)
func (p *messageProcessor) wrapMessageV1(encodedMessage []byte) ([]byte, error) {
wrappedMessage, err := v1protocol.WrapMessageV1(encodedMessage, p.identity)
if err != nil {
return nil, errors.Wrap(err, "failed to encode message")
return nil, errors.Wrap(err, "failed to wrap message")
}
return encodedMessage, nil
}
func (p *messageProcessor) tryWrapMessageV1(encodedMessage []byte) ([]byte, error) {
if p.featureFlags.sendV1Messages {
wrappedMessage, err := v1protocol.WrapMessageV1(encodedMessage, p.identity)
if err != nil {
return nil, errors.Wrap(err, "failed to wrap message")
}
return wrappedMessage, nil
}
return encodedMessage, nil
return wrappedMessage, nil
}
func (p *messageProcessor) addToDataSync(publicKey *ecdsa.PublicKey, message []byte) error {
@ -520,15 +402,9 @@ func (p *messageProcessor) sendMessageSpec(ctx context.Context, publicKey *ecdsa
case messageSpec.SharedSecret != nil:
logger.Debug("sending using shared secret")
hash, err = p.transport.SendPrivateWithSharedSecret(ctx, newMessage, publicKey, messageSpec.SharedSecret)
case messageSpec.PartitionedTopicMode() == encryption.PartitionTopicV1:
default:
logger.Debug("sending partitioned topic")
hash, err = p.transport.SendPrivateWithPartitioned(ctx, newMessage, publicKey)
case !p.featureFlags.genericDiscoveryTopicEnabled:
logger.Debug("sending partitioned topic (generic discovery topic disabled)")
hash, err = p.transport.SendPrivateWithPartitioned(ctx, newMessage, publicKey)
default:
logger.Debug("sending using discovery topic")
hash, err = p.transport.SendPrivateOnDiscovery(ctx, newMessage, publicKey)
}
if err != nil {
return nil, nil, err

View file

@ -4,12 +4,15 @@ import (
"context"
"crypto/ecdsa"
"database/sql"
"strings"
"encoding/hex"
"encoding/json"
"strconv"
"time"
"github.com/pkg/errors"
"go.uber.org/zap"
"github.com/golang/protobuf/proto"
"github.com/status-im/status-go/eth-node/crypto"
"github.com/status-im/status-go/eth-node/types"
enstypes "github.com/status-im/status-go/eth-node/types/ens"
@ -18,11 +21,14 @@ import (
"github.com/status-im/status-go/protocol/encryption/sharedsecret"
"github.com/status-im/status-go/protocol/identity/alias"
"github.com/status-im/status-go/protocol/identity/identicon"
"github.com/status-im/status-go/protocol/protobuf"
"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"
)
const PubKeyStringLength = 132
var (
ErrChatIDEmpty = errors.New("chat ID is empty")
ErrNotImplemented = errors.New("not implemented")
@ -46,20 +52,29 @@ type Messenger struct {
processor *messageProcessor
logger *zap.Logger
ownMessages []*v1protocol.Message
featureFlags featureFlags
messagesPersistenceEnabled bool
shutdownTasks []func() error
}
type featureFlags struct {
genericDiscoveryTopicEnabled bool
// sendV1Messages indicates whether we should send
// messages compatible only with V1 and later.
// V1 messages adds additional wrapping
// which contains a signature and payload.
sendV1Messages bool
type RawResponse struct {
Filter *transport.Filter `json:"filter"`
Messages []*v1protocol.StatusMessage `json:"messages"`
}
type MessengerResponse struct {
Chats []*Chat `json:"chats,omitEmpty"`
Messages []*Message `json:"messages,omitEmpty"`
Contacts []*Contact `json:"contacts,omitEmpty"`
// Raw unprocessed messages
RawMessages []*RawResponse `json:"rawMessages,omitEmpty"`
}
func (m *MessengerResponse) IsEmpty() bool {
return len(m.Chats) == 0 && len(m.Messages) == 0 && len(m.Contacts) == 0 && len(m.RawMessages) == 0
}
type featureFlags struct {
// datasync indicates whether direct messages should be sent exclusively
// using datasync, breaking change for non-v1 clients. Public messages
// are not impacted
@ -117,13 +132,6 @@ func WithCustomLogger(logger *zap.Logger) Option {
}
}
func WithGenericDiscoveryTopicSupport() Option {
return func(c *config) error {
c.featureFlags.genericDiscoveryTopicEnabled = true
return nil
}
}
func WithMessagesPersistenceEnabled() Option {
return func(c *config) error {
c.messagesPersistenceEnabled = true
@ -145,13 +153,6 @@ func WithDatabase(db *sql.DB) Option {
}
}
func WithSendV1Messages() Option {
return func(c *config) error {
c.featureFlags.sendV1Messages = true
return nil
}
}
func WithDatasync() func(c *config) error {
return func(c *config) error {
c.featureFlags.datasync = true
@ -267,7 +268,6 @@ func NewMessenger(
nil,
c.envelopesMonitorConfig,
logger,
transport.SetGenericDiscoveryTopicSupport(c.featureFlags.genericDiscoveryTopicEnabled),
)
if err != nil {
return nil, errors.Wrap(err, "failed to create a WhisperServiceTransport")
@ -624,47 +624,58 @@ func (m *Messenger) Contacts() ([]*Contact, error) {
return m.persistence.Contacts()
}
func (m *Messenger) Send(ctx context.Context, chatID string, data []byte) ([][]byte, error) {
logger := m.logger.With(zap.String("site", "Send"), zap.String("chatID", chatID))
func timestampInMs() uint64 {
return uint64(time.Now().UnixNano() / int64(time.Millisecond))
}
// A valid added chat is required.
chat, err := m.chatByID(chatID)
// ReSendChatMessage pulls a message from the database and sends it again
func (m *Messenger) ReSendChatMessage(ctx context.Context, messageID string) (*MessengerResponse, error) {
logger := m.logger.With(zap.String("site", "ReSendChatMessage"))
var response MessengerResponse
message, err := m.persistence.MessageByID(messageID)
if err != nil {
return nil, err
}
if message == nil {
return nil, errors.New("message not found")
}
if message.RawPayload == nil {
return nil, errors.New("message payload not found, can't resend message")
}
clock, err := m.persistence.LastMessageClock(chat.ID)
chat, err := m.chatByID(message.LocalChatID)
if err != nil {
return nil, err
}
logger.Debug("last message clock received", zap.Int64("clock", clock))
switch chat.ChatType {
case ChatTypeOneToOne:
logger.Debug("sending private message", zap.Binary("publicKey", crypto.FromECDSAPub(chat.PublicKey)))
id, message, err := m.processor.SendPrivate(ctx, chat.PublicKey, chat.ID, data, clock)
publicKey := crypto.FromECDSAPub(chat.PublicKey)
logger.Debug("re-sending private message", zap.Binary("publicKey", publicKey))
id, err := m.processor.SendPrivateRaw(ctx, chat.PublicKey, message.RawPayload)
if err != nil {
return nil, err
}
if err := m.cacheOwnMessage(chatID, id, message); err != nil {
message.ID = "0x" + hex.EncodeToString(id)
err = m.sendToPairedDevices(ctx, message.RawPayload)
if err != nil {
return nil, err
}
return [][]byte{id}, nil
case ChatTypePublic:
logger.Debug("sending public message", zap.String("chatName", chat.Name))
id, err := m.processor.SendPublic(ctx, chat.ID, data, clock)
logger.Debug("re-sending public message", zap.String("chatName", chat.Name))
id, err := m.processor.SendPublicRaw(ctx, chat.ID, message.RawPayload)
if err != nil {
return nil, err
}
return [][]byte{id}, nil
message.ID = "0x" + hex.EncodeToString(id)
case ChatTypePrivateGroupChat:
logger.Debug("sending group message", zap.String("chatName", chat.Name))
logger.Debug("re-sending group message", zap.String("chatName", chat.Name))
recipients, err := chat.MembersAsPublicKeys()
if err != nil {
return nil, err
}
// Filter me out of recipients.
n := 0
for _, item := range recipients {
if !isPubKeyEqual(item, &m.identity.PublicKey) {
@ -672,40 +683,186 @@ func (m *Messenger) Send(ctx context.Context, chatID string, data []byte) ([][]b
n++
}
}
ids, messages, err := m.processor.SendGroup(ctx, recipients[:n], chat.ID, data, clock)
id, err := m.processor.SendGroupRaw(ctx, recipients[:n], message.RawPayload)
if err != nil {
return nil, err
}
for idx, message := range messages {
if err := m.cacheOwnMessage(chatID, ids[idx], message); err != nil {
return nil, err
}
message.ID = "0x" + hex.EncodeToString(id)
err = m.sendToPairedDevices(ctx, message.RawPayload)
if err != nil {
return nil, err
}
return ids, nil
default:
return nil, errors.New("chat is neither public nor private")
return nil, errors.New("chat type not supported")
}
response.Messages = []*Message{message}
response.Chats = []*Chat{chat}
return &response, nil
}
func (m *Messenger) cacheOwnMessage(chatID string, id []byte, message *v1protocol.Message) error {
// Save our message because it won't be received from the transport layer.
message.ID = id // a Message need ID to be properly stored in the db
message.SigPubKey = &m.identity.PublicKey
message.ChatID = chatID
if m.messagesPersistenceEnabled {
_, err := m.persistence.SaveMessages([]*v1protocol.Message{message})
// sendToPairedDevices will check if we have any paired devices and send to them if necessary
func (m *Messenger) sendToPairedDevices(ctx context.Context, payload []byte) error {
activeInstallations, err := m.encryptor.GetOurActiveInstallations(&m.identity.PublicKey)
if err != nil {
return err
}
// We send a message to any paired device
if len(activeInstallations) > 1 {
_, err := m.processor.SendPrivateRaw(ctx, &m.identity.PublicKey, payload)
if err != nil {
return err
}
}
// Cache it to be returned in Retrieve().
m.ownMessages = append(m.ownMessages, message)
return nil
}
// SendChatMessage takes a minimal message and sends it based on the corresponding chat
func (m *Messenger) SendChatMessage(ctx context.Context, message *Message) (*MessengerResponse, error) {
logger := m.logger.With(zap.String("site", "Send"), zap.String("chatID", message.ChatId))
var response MessengerResponse
// A valid added chat is required.
chat, err := m.chatByID(message.ChatId)
if err != nil {
return nil, err
}
clock := chat.LastClockValue
timestamp := timestampInMs()
if clock == 0 || clock < timestamp {
clock = timestamp
} else {
clock = clock + 1
}
message.LocalChatID = chat.ID
message.Clock = clock
message.Timestamp = timestamp
message.From = "0x" + hex.EncodeToString(crypto.FromECDSAPub(&m.identity.PublicKey))
message.SigPubKey = &m.identity.PublicKey
message.WhisperTimestamp = timestamp
message.Seen = true
message.OutgoingStatus = OutgoingStatusSending
identicon, err := identicon.GenerateBase64(message.From)
if err != nil {
return nil, err
}
message.Identicon = identicon
alias, err := alias.GenerateFromPublicKeyString(message.From)
if err != nil {
return nil, err
}
message.Alias = alias
switch chat.ChatType {
case ChatTypeOneToOne:
publicKey := crypto.FromECDSAPub(chat.PublicKey)
logger.Debug("sending private message", zap.Binary("publicKey", publicKey))
message.MessageType = protobuf.ChatMessage_ONE_TO_ONE
encodedMessage, err := proto.Marshal(message)
if err != nil {
return nil, err
}
message.RawPayload = encodedMessage
id, err := m.processor.SendPrivateRaw(ctx, chat.PublicKey, encodedMessage)
if err != nil {
return nil, err
}
message.ID = "0x" + hex.EncodeToString(id)
err = m.sendToPairedDevices(ctx, encodedMessage)
if err != nil {
return nil, err
}
case ChatTypePublic:
logger.Debug("sending public message", zap.String("chatName", chat.Name))
message.MessageType = protobuf.ChatMessage_PUBLIC_GROUP
encodedMessage, err := proto.Marshal(message)
if err != nil {
return nil, err
}
message.RawPayload = encodedMessage
id, err := m.processor.SendPublicRaw(ctx, chat.ID, encodedMessage)
if err != nil {
return nil, err
}
message.ID = "0x" + hex.EncodeToString(id)
case ChatTypePrivateGroupChat:
logger.Debug("sending public message", zap.String("chatName", chat.Name))
message.MessageType = protobuf.ChatMessage_PRIVATE_GROUP
encodedMessage, err := proto.Marshal(message)
if err != nil {
return nil, err
}
message.RawPayload = encodedMessage
logger.Debug("sending group message", zap.String("chatName", chat.Name))
recipients, err := chat.MembersAsPublicKeys()
if err != nil {
return nil, err
}
n := 0
for _, item := range recipients {
if !isPubKeyEqual(item, &m.identity.PublicKey) {
recipients[n] = item
n++
}
}
id, err := m.processor.SendGroupRaw(ctx, recipients[:n], encodedMessage)
if err != nil {
return nil, err
}
message.ID = "0x" + hex.EncodeToString(id)
err = m.sendToPairedDevices(ctx, encodedMessage)
if err != nil {
return nil, err
}
default:
return nil, errors.New("chat type not supported")
}
err = message.PrepareContent()
if err != nil {
return nil, err
}
jsonMessage, err := json.Marshal(message)
if err != nil {
return nil, err
}
chat.LastClockValue = clock
chat.LastMessage = jsonMessage
chat.Timestamp = int64(timestamp)
if err := m.SaveChat(*chat); err != nil {
return nil, err
}
err = m.persistence.SaveMessagesLegacy([]*Message{message})
if err != nil {
return nil, err
}
response.Chats = []*Chat{chat}
response.Messages = []*Message{message}
return &response, nil
}
// SendRaw takes encoded data, encrypts it and sends through the wire.
// DEPRECATED
func (m *Messenger) SendRaw(ctx context.Context, chat Chat, data []byte) ([]byte, error) {
@ -717,94 +874,48 @@ func (m *Messenger) SendRaw(ctx context.Context, chat Chat, data []byte) ([]byte
return nil, errors.New("chat is neither public nor private")
}
type RetrieveConfig struct {
From time.Time
To time.Time
latest bool
last24Hours bool
}
var (
RetrieveLatest = RetrieveConfig{latest: true}
RetrieveLastDay = RetrieveConfig{latest: true, last24Hours: true}
)
// RetrieveAll retrieves all previously fetched messages
func (m *Messenger) RetrieveAll(ctx context.Context, c RetrieveConfig) ([]*v1protocol.Message, error) {
result, err := m.retrieveLatest(ctx)
if err != nil {
return nil, err
}
postProcess := newPostProcessor(m, postProcessorConfig{
MatchChat: true,
Persist: true,
})
result, err = postProcess.Run(result)
if err != nil {
return nil, errors.Wrap(err, "failed to post process messages")
}
retrievedMessages, err := m.retrieveSaved(ctx, c)
if err != nil {
return nil, errors.Wrap(err, "failed to get saved messages")
}
result = append(result, retrievedMessages...)
// Include own messages.
result = append(result, m.ownMessages...)
m.ownMessages = nil
return result, nil
}
func (m *Messenger) retrieveLatest(ctx context.Context) ([]*v1protocol.Message, error) {
latest, err := m.transport.RetrieveAllMessages()
if err != nil {
return nil, errors.Wrap(err, "failed to retrieve messages")
}
logger := m.logger.With(zap.String("site", "retrieveLatest"))
logger.Debug("retrieved messages", zap.Int("count", len(latest)))
var result []*v1protocol.Message
for _, transpMessage := range latest {
protoMessages, err := m.processor.Process(transpMessage.Message)
if err != nil {
return nil, err
}
result = append(result, protoMessages...)
}
return result, nil
}
func (m *Messenger) retrieveSaved(ctx context.Context, c RetrieveConfig) (messages []*v1protocol.Message, err error) {
if !m.messagesPersistenceEnabled {
return nil, nil
}
if !c.latest {
return m.persistence.Messages(c.From, c.To)
}
if c.last24Hours {
to := time.Now()
from := to.Add(-time.Hour * 24)
return m.persistence.Messages(from, to)
}
return nil, nil
}
// DEPRECATED
func (m *Messenger) RetrieveRawAll() (map[transport.Filter][]*v1protocol.StatusMessage, error) {
// RetrieveAll retrieves messages from all filters, processes them and returns a
// MessengerResponse to the client
func (m *Messenger) RetrieveAll() (*MessengerResponse, error) {
chatWithMessages, err := m.transport.RetrieveRawAll()
if err != nil {
return nil, err
}
logger := m.logger.With(zap.String("site", "RetrieveRawAll"))
result := make(map[transport.Filter][]*v1protocol.StatusMessage)
return m.handleRetrievedMessages(chatWithMessages)
}
func (m *Messenger) handleRetrievedMessages(chatWithMessages map[transport.Filter][]*types.Message) (*MessengerResponse, error) {
response := &MessengerResponse{
Chats: []*Chat{},
Messages: []*Message{},
}
allChats, err := m.persistence.Chats()
if err != nil {
return nil, err
}
postProcessor := newPostProcessor(m, postProcessorConfig{MatchChat: true})
logger := m.logger.With(zap.String("site", "RetrieveAll"))
rawMessages := make(map[transport.Filter][]*v1protocol.StatusMessage)
// We should query this instead
contacts, err := m.Contacts()
if err != nil {
return nil, err
}
blockedContacts := make(map[string]bool)
for _, c := range contacts {
if c.IsBlocked() {
blockedContacts[c.ID] = true
}
}
allContactsMap := make(map[string]*Contact)
allChatsMap := make(map[string]*Chat)
existingMessagesMap := make(map[string]bool)
for chat, messages := range chatWithMessages {
for _, shhMessage := range messages {
@ -816,48 +927,130 @@ func (m *Messenger) RetrieveRawAll() (map[transport.Filter][]*v1protocol.StatusM
}
for _, msg := range statusMessages {
if msg.ParsedMessage != nil {
if textMessage, ok := msg.ParsedMessage.(v1protocol.Message); ok {
textMessage.Content = v1protocol.PrepareContent(textMessage.Content)
msg.ParsedMessage = textMessage
// Check for messages from blocked users
senderID := "0x" + hex.EncodeToString(crypto.FromECDSAPub(msg.SigPubKey()))
if blockedContacts[senderID] {
continue
}
// Don't process duplicates
messageID := "0x" + hex.EncodeToString(msg.ID)
if _, ok := existingMessagesMap[messageID]; ok {
continue
}
existingMessagesMap[messageID] = true
// Check against the database, this is probably a bit slow for
// each message, but for now might do, we'll make it faster later
existingMessage, err := m.persistence.MessageByID(messageID)
if err != nil && err != errRecordNotFound {
return nil, err
}
if existingMessage != nil {
continue
}
publicKey := msg.SigPubKey()
if publicKey == nil {
return nil, errors.New("public key can't be nil")
}
var contact *Contact
if c, ok := allContactsMap[senderID]; ok {
contact = c
} else {
c, err := buildContact(publicKey)
if err != nil {
logger.Info("failed to build contact", zap.Error(err))
continue
}
contact = c
allContactsMap[senderID] = c
response.Contacts = append(response.Contacts, c)
}
if msg.ParsedMessage != nil {
if textMessage, ok := msg.ParsedMessage.(protobuf.ChatMessage); ok {
receivedMessage := &Message{
ID: messageID,
ChatMessage: textMessage,
From: contact.ID,
Alias: contact.Alias,
SigPubKey: publicKey,
Identicon: contact.Identicon,
WhisperTimestamp: uint64(msg.TransportMessage.Timestamp) * 1000,
}
receivedMessage.PrepareContent()
chat, err := postProcessor.matchMessage(receivedMessage, allChats)
if err != nil {
logger.Warn("failed to match message", zap.String("receivedChatID", receivedMessage.ChatId), zap.Error(err))
continue
}
// If deleted-at is greater, ignore message
if chat.DeletedAtClockValue >= receivedMessage.Clock {
continue
}
// Set the LocalChatID for the message
receivedMessage.LocalChatID = chat.ID
if c, ok := allChatsMap[chat.ID]; ok {
chat = c
}
// Increase unviewed count
if !isPubKeyEqual(receivedMessage.SigPubKey, &m.identity.PublicKey) {
chat.UnviewedMessagesCount++
} else {
// Our own message, mark as sent
receivedMessage.OutgoingStatus = OutgoingStatusSent
}
// Update chat timestamp
chat.Timestamp = int64(timestampInMs())
// Update last clock value
if chat.LastClockValue <= receivedMessage.Clock {
chat.LastClockValue = receivedMessage.Clock
encodedLastMessage, err := json.Marshal(receivedMessage)
if err != nil {
return nil, err
}
chat.LastMessage = encodedLastMessage
}
// Set chat active
chat.Active = true
// Set in the map
allChatsMap[chat.ID] = chat
// Add to response
response.Messages = append(response.Messages, receivedMessage)
}
} else {
// RawMessage, not processed here, pass straight to the client
rawMessages[chat] = append(rawMessages[chat], msg)
}
}
result[chat] = append(result[chat], statusMessages...)
}
}
err = m.updateContactsFromMessages(result)
err = m.persistence.SetContactsGeneratedData(response.Contacts, nil)
if err != nil {
return nil, err
}
return result, nil
}
func (m *Messenger) updateContactsFromMessages(messages map[transport.Filter][]*v1protocol.StatusMessage) error {
allContactsMap := make(map[string]bool)
var allContacts []Contact
for _, chatMessages := range messages {
for _, message := range chatMessages {
publicKey := message.SigPubKey()
address := strings.ToLower(crypto.PubkeyToAddress(*publicKey).Hex())
if _, ok := allContactsMap[address]; ok {
continue
}
contact, err := buildContact(publicKey)
if err != nil {
continue
}
allContactsMap[address] = true
allContacts = append(allContacts, *contact)
}
for _, c := range allChatsMap {
response.Chats = append(response.Chats, c)
}
return m.persistence.SetContactsGeneratedData(allContacts, nil)
m.persistence.SaveChats(response.Chats)
m.SaveMessages(response.Messages)
for filter, messages := range rawMessages {
response.RawMessages = append(response.RawMessages, &RawResponse{Filter: &filter, Messages: messages})
}
return response, nil
}
func (m *Messenger) RequestHistoricMessages(
@ -909,6 +1102,47 @@ func (m *Messenger) SaveMessages(messages []*Message) error {
return m.persistence.SaveMessagesLegacy(messages)
}
// AddSystemMessages format an array of system-messages and saves them to the database
// It's needed until group chats are fully in status-go.
func (m *Messenger) AddSystemMessages(messages []*Message) ([]*Message, error) {
timestamp := timestampInMs()
for _, message := range messages {
message.LocalChatID = message.ChatId
message.Timestamp = timestamp
message.WhisperTimestamp = timestamp
message.Seen = true
identicon, err := identicon.GenerateBase64(message.From)
if err != nil {
return nil, err
}
message.Identicon = identicon
alias, err := alias.GenerateFromPublicKeyString(message.From)
if err != nil {
return nil, err
}
message.ID = "0x" + hex.EncodeToString(crypto.Keccak256([]byte(message.Text+message.From+strconv.FormatUint(message.Clock, 10))))
message.Alias = alias
message.ContentType = protobuf.ChatMessage_STATUS
message.MessageType = protobuf.ChatMessage_SYSTEM_MESSAGE_PRIVATE_GROUP
err = message.PrepareContent()
if err != nil {
return nil, err
}
}
err := m.SaveMessages(messages)
if err != nil {
return nil, err
}
return messages, nil
}
// DEPRECATED: required by status-react.
func (m *Messenger) DeleteMessage(id string) error {
return m.persistence.DeleteMessage(id)
@ -920,8 +1154,8 @@ func (m *Messenger) DeleteMessagesByChatID(id string) error {
}
// DEPRECATED: required by status-react.
func (m *Messenger) MarkMessagesSeen(ids ...string) error {
return m.persistence.MarkMessagesSeen(ids...)
func (m *Messenger) MarkMessagesSeen(chatID string, ids []string) error {
return m.persistence.MarkMessagesSeen(chatID, ids)
}
// DEPRECATED: required by status-react.
@ -955,100 +1189,68 @@ func newPostProcessor(m *Messenger, config postProcessorConfig) *postProcessor {
}
}
func (p *postProcessor) Run(messages []*v1protocol.Message) ([]*v1protocol.Message, error) {
var err error
p.logger.Debug("running post processor", zap.Int("messages", len(messages)))
var fns []func([]*v1protocol.Message) ([]*v1protocol.Message, error)
// Order is important. Persisting messages should be always at the end.
if p.config.MatchChat {
fns = append(fns, p.matchMessages)
}
if p.config.Parse {
fns = append(fns, p.parseMessages)
}
if p.config.Persist {
fns = append(fns, p.saveMessages)
}
for _, fn := range fns {
messages, err = fn(messages)
if err != nil {
return nil, err
}
}
return messages, nil
}
func (p *postProcessor) saveMessages(messages []*v1protocol.Message) ([]*v1protocol.Message, error) {
_, err := p.persistence.SaveMessages(messages)
if err != nil {
return nil, err
}
return messages, nil
}
func (p *postProcessor) parseMessages(messages []*v1protocol.Message) ([]*v1protocol.Message, error) {
for _, m := range messages {
m.Content = v1protocol.PrepareContent(m.Content)
}
return messages, nil
}
func (p *postProcessor) matchMessages(messages []*v1protocol.Message) ([]*v1protocol.Message, error) {
func (p *postProcessor) matchMessages(messages []*Message) ([]*Message, error) {
chats, err := p.persistence.Chats()
if err != nil {
return nil, err
}
result := make([]*v1protocol.Message, 0, len(messages))
result := make([]*Message, 0, len(messages))
for _, message := range messages {
chat, err := p.matchMessage(message, chats)
if err != nil {
p.logger.Error("failed to match a chat to a message", zap.Error(err))
continue
}
message.ChatID = chat.ID
message.LocalChatID = chat.ID
result = append(result, message)
}
return result, nil
}
func (p *postProcessor) matchMessage(message *v1protocol.Message, chats []*Chat) (*Chat, error) {
func (p *postProcessor) matchMessage(message *Message, chats []*Chat) (*Chat, error) {
if message.SigPubKey == nil {
p.logger.Error("public key can't be empty")
return nil, errors.New("received a message with empty public key")
}
switch {
case message.MessageT == v1protocol.MessageTypePublicGroup:
case message.MessageType == protobuf.ChatMessage_PUBLIC_GROUP:
// For public messages, all outgoing and incoming messages have the same chatID
// equal to a public chat name.
chatID := message.Content.ChatID
chatID := message.ChatId
chat := findChatByID(chatID, chats)
if chat == nil {
return nil, errors.New("received a public message from non-existing chat")
}
return chat, nil
case message.MessageT == v1protocol.MessageTypePrivate && isPubKeyEqual(message.SigPubKey, p.myPublicKey):
// It's a private message coming from us so we rely on Message.Content.ChatID.
case message.MessageType == protobuf.ChatMessage_ONE_TO_ONE && isPubKeyEqual(message.SigPubKey, p.myPublicKey):
// It's a private message coming from us so we rely on Message.ChatId
// If chat does not exist, it should be created to support multidevice synchronization.
chatID := message.Content.ChatID
chatID := message.ChatId
chat := findChatByID(chatID, chats)
if chat == nil {
// TODO: this should be a three-word name used in the mobile client
newChat := CreateOneToOneChat(chatID[:8], message.SigPubKey)
if len(chatID) != PubKeyStringLength {
return nil, errors.New("invalid pubkey length")
}
bytePubKey, err := hex.DecodeString(chatID[2:])
if err != nil {
return nil, errors.Wrap(err, "failed to decode hex chatID")
}
pubKey, err := crypto.UnmarshalPubkey(bytePubKey)
if err != nil {
return nil, errors.Wrap(err, "failed to decode pubkey")
}
newChat := CreateOneToOneChat(chatID[:8], pubKey)
if err := p.persistence.SaveChat(newChat); err != nil {
return nil, errors.Wrap(err, "failed to save newly created chat")
}
chat = &newChat
}
return chat, nil
case message.MessageT == v1protocol.MessageTypePrivate:
case message.MessageType == protobuf.ChatMessage_ONE_TO_ONE:
// It's an incoming private message. ChatID is calculated from the signature.
// If a chat does not exist, a new one is created and saved.
chatID := types.EncodeHex(crypto.FromECDSAPub(message.SigPubKey))
@ -1062,21 +1264,34 @@ func (p *postProcessor) matchMessage(message *v1protocol.Message, chats []*Chat)
chat = &newChat
}
return chat, nil
case message.MessageT == v1protocol.MessageTypePrivateGroup:
case message.MessageType == protobuf.ChatMessage_PRIVATE_GROUP:
// In the case of a group message, ChatID is the same for all messages belonging to a group.
// It needs to be verified if the signature public key belongs to the chat.
chatID := message.Content.ChatID
chatID := message.ChatId
chat := findChatByID(chatID, chats)
if chat == nil {
return nil, errors.New("received group chat message for non-existing chat")
}
sigPubKeyHex := types.EncodeHex(crypto.FromECDSAPub(message.SigPubKey))
theirKeyHex := types.EncodeHex(crypto.FromECDSAPub(message.SigPubKey))
myKeyHex := types.EncodeHex(crypto.FromECDSAPub(p.myPublicKey))
var theyJoined bool
var iJoined bool
for _, member := range chat.Members {
if member.ID == sigPubKeyHex {
return chat, nil
if member.ID == theirKeyHex && member.Joined {
theyJoined = true
}
}
for _, member := range chat.Members {
if member.ID == myKeyHex && member.Joined {
iJoined = true
}
}
if theyJoined && iJoined {
return chat, nil
}
return nil, errors.New("did not find a matching group chat")
default:
return nil, errors.New("can not match a chat because there is no valid case")
@ -1098,7 +1313,7 @@ func (m *Messenger) VerifyENSNames(rpcEndpoint, contractAddress string, ensDetai
}
// Update contacts
var contacts []Contact
var contacts []*Contact
for _, details := range ensResponse {
if details.Error == nil {
contact, err := buildContact(details.PublicKey)
@ -1109,7 +1324,7 @@ func (m *Messenger) VerifyENSNames(rpcEndpoint, contractAddress string, ensDetai
contact.ENSVerifiedAt = details.VerifiedAt
contact.Name = details.Name
contacts = append(contacts, *contact)
contacts = append(contacts, contact)
} else {
m.logger.Warn("Failed to resolve ens name",
zap.String("name", details.Name),
@ -1133,8 +1348,3 @@ func (m *Messenger) VerifyENSNames(rpcEndpoint, contractAddress string, ensDetai
func GenerateAlias(id string) (string, error) {
return alias.GenerateFromPublicKeyString(id)
}
// PrepareContent parses the content of a message and returns the parsed version
func (m *Messenger) PrepareContent(content v1protocol.Content) v1protocol.Content {
return v1protocol.PrepareContent(content)
}

View file

@ -1,15 +1,15 @@
// Code generated by go-bindata. DO NOT EDIT.
// sources:
// 000001_init.down.db.sql (82B)
// 000001_init.up.db.sql (840B)
// 000001_init.up.db.sql (832B)
// 000002_add_chats.down.db.sql (74B)
// 000002_add_chats.up.db.sql (599B)
// 000002_add_chats.up.db.sql (495B)
// 000003_add_contacts.down.db.sql (21B)
// 000003_add_contacts.up.db.sql (381B)
// 000004_user_messages_compatibility.down.sql (33B)
// 000004_user_messages_compatibility.up.sql (928B)
// 000004_user_messages_compatibility.up.sql (980B)
// 1567112142_user_messages.down.sql (26B)
// 1567112142_user_messages.up.sql (551B)
// 1567112142_user_messages.up.sql (543B)
// doc.go (377B)
package migrations
@ -94,12 +94,12 @@ func _000001_initDownDbSql() (*asset, error) {
return nil, err
}
info := bindataFileInfo{name: "000001_init.down.db.sql", size: 82, mode: os.FileMode(0644), modTime: time.Unix(1564484687, 0)}
info := bindataFileInfo{name: "000001_init.down.db.sql", size: 82, mode: os.FileMode(0644), modTime: time.Unix(1574354941, 0)}
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xe8, 0x5f, 0xe0, 0x6, 0xfc, 0xed, 0xb7, 0xff, 0xb5, 0xf3, 0x33, 0x45, 0x1, 0x5b, 0x84, 0x80, 0x74, 0x60, 0x81, 0xa6, 0x8b, 0xb4, 0xd4, 0xad, 0x10, 0xa8, 0xb3, 0x61, 0x6f, 0xc5, 0x2f, 0xaa}}
return a, nil
}
var __000001_initUpDbSql = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x94\x52\xb1\x6e\xc2\x30\x14\xdc\xf3\x15\x6f\x24\x12\x43\xf7\x4e\x0e\xbc\x80\xd5\xd4\x6e\x1d\xa7\xc0\x14\x19\xe2\x82\x0b\x09\x11\x36\x52\xf9\xfb\xaa\x49\x8c\x02\x45\x15\xac\xef\xce\xe7\xbb\x7b\x6f\x24\x90\x48\x04\x49\xa2\x04\x81\xc6\xc0\xb8\x04\x9c\xd3\x54\xa6\x70\xb4\xfa\x90\x97\xda\x5a\xb5\xd6\x16\x06\x01\x00\x80\x29\x20\x4a\x78\x04\x19\xa3\xef\x19\x36\x6c\x96\x25\xc9\xb0\x01\x57\x1b\xe5\x72\x53\xc0\x07\x11\xa3\x29\x11\xd7\xe8\xbe\x72\xba\x72\xb9\x3b\xd5\xda\x53\x5a\xa4\xfb\xe3\x06\xe2\xf4\xb7\x03\x89\x73\xd9\x49\xec\xf6\xab\x2d\x44\x74\x42\x59\x37\x71\xa6\xd4\xd6\xa9\xb2\xbe\x98\xfa\xaf\xbc\xa1\x9e\x82\x37\x71\x29\x5c\x1f\x97\x3b\xb3\xca\xb7\xfa\xd4\xc4\x6b\x87\x9f\x3b\xb5\xb6\x40\x99\x3c\x07\x81\x31\xc6\x24\x4b\x24\x3c\x05\xe1\x73\x10\x74\xdd\x51\x36\xc6\xb9\x0f\x6f\x81\xb3\xcb\xe6\x06\x1d\xd2\x7b\x71\xab\xed\x52\x97\x4b\x7d\xb0\x1b\x53\xe7\xc7\xba\x50\xae\x5f\xb9\x2f\xf4\x4d\xd0\x57\x22\x16\xf0\x82\x8b\xab\x72\x0b\xe5\x54\xbb\x99\x47\x56\x12\x73\x81\x74\xc2\x1a\xbd\xb3\x4d\x10\x18\xa3\x40\x36\xc2\xb4\x79\x6e\x07\xa6\x08\x83\x10\x66\x54\x4e\x79\x26\x41\xf0\x19\x1d\xff\x9f\xa5\x91\xea\x02\x75\x29\xae\x1a\x7e\xc8\xa6\x2a\x4a\x53\x41\xc4\x79\x82\x84\xfd\x5d\x46\x4c\x92\x14\x5b\xe6\xd7\xde\x54\xba\xb8\x8b\x7a\x7f\xf6\x96\xdf\x5e\xbc\x67\x0e\x7b\x81\xc2\xdf\x63\xf8\x09\x00\x00\xff\xff\x66\xab\x2d\x2f\x48\x03\x00\x00")
var __000001_initUpDbSql = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x94\x92\xcd\x6e\xea\x30\x10\x85\xf7\x79\x8a\x59\x12\x89\xc5\xdd\xdf\x95\x03\x13\xb0\x9a\xda\xad\xe3\x14\x58\x45\x26\x71\xc1\x85\x84\x08\x1b\xa9\xbc\x7d\x45\x7e\x68\x48\xab\x0a\x96\x9e\x39\x3e\x9e\xef\x8c\x27\x02\x89\x44\x90\x24\x88\x10\x68\x08\x8c\x4b\xc0\x25\x8d\x65\x0c\x27\xab\x8f\x69\xa1\xad\x55\x1b\x6d\x61\xe4\x01\x00\x98\x1c\x82\x88\x07\x90\x30\xfa\x9a\x60\xad\x66\x49\x14\x8d\xeb\x66\xb6\x55\x2e\x35\x39\xbc\x11\x31\x99\x13\x31\xec\x1e\x4a\xa7\x4b\x97\xba\x73\xa5\x81\x32\xd9\x54\x5b\xff\x41\xd5\xe9\x4f\x07\x12\x97\xed\x31\xdb\x1f\xb2\x1d\x04\x74\xf6\x2d\x30\x85\xb6\x4e\x15\xd5\x4d\xb5\x7b\xa2\x1b\xa4\xe7\xd0\x3d\x7e\x6b\x5c\x9d\xd6\x7b\x93\xa5\x3b\x7d\xae\xb1\x9a\xe2\xfb\x5e\x6d\xec\x65\x96\x2b\x00\x4c\x31\x24\x49\x24\xe1\x9f\xe7\xff\xf7\xbc\x36\x33\xca\xa6\xb8\xec\xa0\x2d\x70\x76\x9b\xd8\xa8\xed\xf4\x6e\xfc\x96\x72\xa1\x8b\xb5\x3e\xda\xad\xa9\xd2\x53\x95\x2b\xd7\x8f\xba\x0b\xf2\x45\xd0\x67\x22\x56\xf0\x84\xab\x41\xa8\xb9\x72\xaa\xd9\xc8\x23\xab\x08\xb9\x40\x3a\x63\xb5\xdf\x75\x4c\x10\x18\xa2\x40\x36\xc1\xb8\xbe\x6e\x47\x26\xf7\x3d\x1f\x16\x54\xce\x79\x22\x41\xf0\x05\x9d\xfe\xcd\x52\x5b\xb5\x40\x2d\xc5\x20\xe1\x87\xc6\x54\x79\x61\x4a\x08\x38\x8f\x90\xb0\x9f\xcb\x08\x49\x14\x63\xa3\xfc\x38\x98\x52\xe7\x77\x49\xef\x67\x6f\xf4\xcd\x4f\xef\x94\xe3\x1e\x90\x7f\xf9\x0c\x5f\x01\x00\x00\xff\xff\x22\x17\x48\xa6\x40\x03\x00\x00")
func _000001_initUpDbSqlBytes() ([]byte, error) {
return bindataRead(
@ -114,8 +114,8 @@ func _000001_initUpDbSql() (*asset, error) {
return nil, err
}
info := bindataFileInfo{name: "000001_init.up.db.sql", size: 840, mode: os.FileMode(0644), modTime: time.Unix(1564484687, 0)}
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xe7, 0x27, 0x96, 0x3b, 0x72, 0x81, 0x7d, 0xba, 0xa4, 0xfb, 0xf7, 0x4, 0xd, 0x6f, 0xc8, 0x30, 0xfe, 0x47, 0xe0, 0x9, 0xf, 0x43, 0x13, 0x6, 0x55, 0xfc, 0xee, 0x15, 0x69, 0x99, 0x53, 0x3f}}
info := bindataFileInfo{name: "000001_init.up.db.sql", size: 832, mode: os.FileMode(0644), modTime: time.Unix(1575009877, 0)}
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x1c, 0xa4, 0xac, 0x0, 0xd3, 0x19, 0x53, 0x35, 0x91, 0x1c, 0x94, 0xea, 0xde, 0xa7, 0x75, 0xb6, 0x73, 0x1d, 0x42, 0x14, 0xca, 0x84, 0x5b, 0xdb, 0x10, 0x94, 0x28, 0xc0, 0x33, 0x95, 0x7f, 0xf}}
return a, nil
}
@ -134,12 +134,12 @@ func _000002_add_chatsDownDbSql() (*asset, error) {
return nil, err
}
info := bindataFileInfo{name: "000002_add_chats.down.db.sql", size: 74, mode: os.FileMode(0644), modTime: time.Unix(1565597460, 0)}
info := bindataFileInfo{name: "000002_add_chats.down.db.sql", size: 74, mode: os.FileMode(0644), modTime: time.Unix(1574354941, 0)}
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xd3, 0xa7, 0xf0, 0x94, 0x7a, 0x9, 0xdc, 0x6c, 0x7b, 0xdc, 0x12, 0x30, 0x55, 0x31, 0x17, 0xf2, 0xcc, 0x6e, 0xfd, 0xbb, 0x70, 0xb9, 0xd8, 0x9f, 0x81, 0x83, 0xdc, 0x1d, 0x1c, 0x3a, 0x8d, 0xce}}
return a, nil
}
var __000002_add_chatsUpDbSql = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x8c\x92\x4f\x4b\x03\x31\x10\xc5\xef\xf3\x29\x06\x3c\x54\x21\x07\x3d\x88\x42\x4f\xd9\x6d\x8a\x8b\x71\x53\xd2\x54\xec\x29\xa4\xd9\xc1\x2e\xdd\x7f\x74\xb3\x95\x7e\x7b\x69\x5d\x6a\xff\x58\xf0\x98\xbc\xf7\x7b\x93\x17\x26\xd6\x82\x1b\x81\x86\x47\x52\x60\x32\xc6\x54\x19\x14\x1f\xc9\xd4\x4c\xd1\x2f\x5d\x68\xf1\x16\xf2\x0c\xdf\xb9\x8e\x5f\xb8\xc6\x89\x4e\xde\xb8\x9e\xe3\xab\x98\xa3\x4a\x31\x56\xe9\x58\x26\xb1\x41\x2d\x26\x92\xc7\x82\x41\xe5\x4a\x3a\xb8\x77\x59\xe9\x4c\x4a\x06\xbe\x2e\xea\xf5\xc5\x3d\x8e\xc4\x98\xcf\xa4\xc1\xc1\x8d\x7b\x78\x7e\xca\x1e\x07\x0c\xc2\xb6\x21\x4c\x52\x73\x04\x3b\x1f\xf2\x0d\x61\xa4\x94\x14\x3c\xbd\xa4\x8d\x9e\x09\x06\x21\x2f\xa9\x0d\xae\x6c\xce\xe8\x8c\x0a\x0a\x94\x59\x17\xac\x2f\x6a\xbf\xb2\x1b\x57\x74\xa7\x23\x0e\x49\xf7\x0c\x9a\x6e\x51\xe4\xde\xae\x68\x8b\x91\x54\x11\x83\xae\xda\xe4\xf4\x45\x99\x2d\xa9\x6d\xdd\x27\x59\x5f\x77\x55\xb8\xca\x17\xae\xfd\xdf\xa0\xbd\xf1\x37\xb3\x0a\x54\x05\xbb\x6f\xdf\x7f\xd3\xdf\x96\x2b\xea\x49\xfb\x73\xf2\xf4\x35\x0c\x4a\x2a\x17\xb4\x6e\xfb\x82\xfd\x69\x99\x37\xb6\x6b\x32\x17\xe8\x47\x80\xbb\x21\x00\x8c\xb4\x9a\xf4\xcb\x71\xe9\x1b\x1e\xcb\xbb\x6d\xb1\xbd\x67\x08\xdf\x01\x00\x00\xff\xff\x44\xe3\x59\x6f\x57\x02\x00\x00")
var __000002_add_chatsUpDbSql = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x8c\x91\xc1\x6a\x32\x31\x14\x85\xf7\xf7\x29\x2e\xfc\x0b\xff\xc2\x2c\xda\x45\x69\xc1\x55\x66\x8c\x74\x68\x3a\x91\x18\x4b\x5d\x85\x98\xb9\xd4\xc1\xc4\x19\x4c\xc6\xe2\xdb\x17\xdb\x41\xb4\x52\xe8\x32\xb9\xdf\x77\xce\xe2\x14\x8a\x33\xcd\x51\xb3\x5c\x70\x2c\xa7\x58\x49\x8d\xfc\xad\x9c\xeb\x39\xba\xb5\x4d\x11\xff\x43\x53\xe3\x2b\x53\xc5\x13\x53\x38\x53\xe5\x0b\x53\x4b\x7c\xe6\x4b\x94\x15\x16\xb2\x9a\x8a\xb2\xd0\xa8\xf8\x4c\xb0\x82\x67\xb0\xb5\x81\x4e\xf4\x31\xab\x5a\x08\x91\x81\x6b\x7d\xbb\xbb\xfa\xc7\x09\x9f\xb2\x85\xd0\x38\xfa\x67\xef\x1e\x1f\xea\xfb\x51\x06\xe9\xd0\x11\x96\x95\x3e\x93\xad\x4b\xcd\x9e\x30\x97\x52\x70\x56\x5d\xdb\x5a\x2d\x78\x06\xa9\x09\x14\x93\x0d\xdd\x0f\xbb\x26\x4f\x89\x6a\x63\x93\x71\xbe\x75\x1b\xb3\xb7\xbe\xbf\xac\x38\x25\xdd\x66\xd0\xf5\x2b\xdf\x38\xb3\xa1\x03\xe6\x42\xe6\x19\xf4\xdb\x7d\x43\x1f\x54\x9b\x40\x31\xda\x77\x32\xae\xed\xb7\xe9\x57\xdf\xdb\xf8\xb7\xa2\x2f\x70\xc8\x1c\xaa\x02\x85\x15\xed\xe2\xe5\x6b\xdd\x74\xa6\xef\x6a\x9b\xe8\xfb\x00\x37\x63\x00\x98\x28\x39\x1b\x46\xbb\xe6\xc6\xe7\xe7\xe3\x8a\x66\x60\xc6\xf0\x19\x00\x00\xff\xff\x99\xae\x9f\xf2\xef\x01\x00\x00")
func _000002_add_chatsUpDbSqlBytes() ([]byte, error) {
return bindataRead(
@ -154,8 +154,8 @@ func _000002_add_chatsUpDbSql() (*asset, error) {
return nil, err
}
info := bindataFileInfo{name: "000002_add_chats.up.db.sql", size: 599, mode: os.FileMode(0644), modTime: time.Unix(1572543168, 0)}
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xdb, 0xf, 0xef, 0x31, 0x64, 0x3, 0xf0, 0x58, 0x1e, 0xed, 0x1e, 0x7e, 0xce, 0x4, 0x20, 0x51, 0x79, 0xf9, 0xca, 0xc3, 0xb9, 0xc9, 0x60, 0x25, 0x2f, 0x6b, 0x99, 0xb1, 0x92, 0x6d, 0x56, 0x31}}
info := bindataFileInfo{name: "000002_add_chats.up.db.sql", size: 495, mode: os.FileMode(0644), modTime: time.Unix(1575009877, 0)}
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x6e, 0xca, 0x2b, 0xf7, 0xca, 0x21, 0xda, 0x17, 0x1f, 0x97, 0xa8, 0x12, 0xb5, 0x6c, 0xad, 0x92, 0xe7, 0x2, 0xaf, 0x1, 0xcb, 0x5e, 0xe9, 0x71, 0xc4, 0x81, 0xa7, 0x3, 0x93, 0x5b, 0x73, 0x73}}
return a, nil
}
@ -174,7 +174,7 @@ func _000003_add_contactsDownDbSql() (*asset, error) {
return nil, err
}
info := bindataFileInfo{name: "000003_add_contacts.down.db.sql", size: 21, mode: os.FileMode(0644), modTime: time.Unix(1565597570, 0)}
info := bindataFileInfo{name: "000003_add_contacts.down.db.sql", size: 21, mode: os.FileMode(0644), modTime: time.Unix(1574354941, 0)}
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xfc, 0x7e, 0xb, 0xec, 0x72, 0xcd, 0x21, 0x3e, 0xa2, 0x38, 0xe0, 0x95, 0x7e, 0xce, 0x4a, 0x17, 0xc8, 0xd0, 0x1c, 0xfa, 0xa3, 0x23, 0x5, 0xab, 0x89, 0xf9, 0xfc, 0x63, 0x7, 0x28, 0xe9, 0x93}}
return a, nil
}
@ -194,7 +194,7 @@ func _000003_add_contactsUpDbSql() (*asset, error) {
return nil, err
}
info := bindataFileInfo{name: "000003_add_contacts.up.db.sql", size: 381, mode: os.FileMode(0644), modTime: time.Unix(1572543168, 0)}
info := bindataFileInfo{name: "000003_add_contacts.up.db.sql", size: 381, mode: os.FileMode(0644), modTime: time.Unix(1574354941, 0)}
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x45, 0xfe, 0x1e, 0xf2, 0x75, 0x33, 0x37, 0x8e, 0x7f, 0x93, 0x6f, 0x16, 0xbb, 0xf8, 0xa4, 0x70, 0x6b, 0xe0, 0xc1, 0x4f, 0x99, 0x8d, 0xc8, 0x2d, 0x40, 0xf1, 0xed, 0x65, 0x90, 0xc3, 0xad, 0xc7}}
return a, nil
}
@ -214,12 +214,12 @@ func _000004_user_messages_compatibilityDownSql() (*asset, error) {
return nil, err
}
info := bindataFileInfo{name: "000004_user_messages_compatibility.down.sql", size: 33, mode: os.FileMode(0644), modTime: time.Unix(1565631683, 0)}
info := bindataFileInfo{name: "000004_user_messages_compatibility.down.sql", size: 33, mode: os.FileMode(0644), modTime: time.Unix(1574354941, 0)}
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xb9, 0xaf, 0x48, 0x80, 0x3d, 0x54, 0x5e, 0x53, 0xee, 0x98, 0x26, 0xbb, 0x99, 0x6a, 0xd8, 0x37, 0x94, 0xf2, 0xf, 0x82, 0xfa, 0xb7, 0x6a, 0x68, 0xcd, 0x8b, 0xe2, 0xc4, 0x6, 0x25, 0xdc, 0x6}}
return a, nil
}
var __000004_user_messages_compatibilityUpSql = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xa4\x92\xcf\x6e\xe2\x3c\x14\xc5\xf7\x3c\xc5\xd9\x01\x12\xf9\xd4\x45\xd5\x4d\x57\x81\x9a\x6f\xa2\xc9\x24\x55\x30\x23\xba\xb2\x4c\xb8\x43\xac\x49\x6c\x64\xdf\x0c\x13\xa9\x0f\x3f\xa2\x84\xaa\x61\xe8\x6a\xb2\xc8\xc2\xbf\x73\xec\x73\xff\x44\x11\x12\x1e\x07\x98\xe6\xe0\x3c\x6b\xcb\xe0\x4a\x9f\x7e\x26\x80\xf5\xb6\x26\x54\x3a\xc0\xbb\xa3\xd9\x41\x07\x1c\x09\x9e\xea\x0e\xce\xc2\xf0\x28\x8a\x70\xac\xc8\x9e\xcc\x35\x35\x64\xd9\xd8\x3d\x8c\xfd\x61\xac\x61\x8a\x42\xe9\x5d\x5d\xff\x37\x5a\x14\x22\x96\x02\x32\x9e\xa7\x02\xc9\x12\x59\x2e\x21\x36\xc9\x4a\xae\xd0\x06\xf2\xaa\xa1\x10\xf4\x9e\x82\xaa\x69\xaf\xcb\x0e\x93\x11\x00\x98\x1d\xbe\xc7\xc5\xe2\x4b\x5c\xe0\xb9\x48\xbe\xc5\xc5\x0b\xbe\x8a\x17\xe4\x19\x16\x79\xb6\x4c\x93\x85\x44\x21\x9e\xd3\x78\x21\x66\x6f\xfa\x63\x65\xc2\x81\xbc\x62\xd3\x50\x60\xdd\x1c\x90\x64\x52\xfc\x2f\x8a\xb7\xf7\xb2\x75\x9a\x9e\x75\xc1\xb5\xbe\x24\x48\xb1\x91\x57\x64\x47\x81\x8d\xd5\x6c\x9c\xc5\x3c\xcd\xe7\xe7\xd3\xd2\x59\x26\xcb\xef\x61\x86\x9e\x9e\x2a\xee\x0e\xf4\x89\xe4\x54\xa3\xd5\xcd\x3b\x3e\x9f\x0e\x62\x5e\x5f\x5a\x69\x56\x1f\xea\x1f\x52\x4f\xec\x3b\x55\xba\xd6\xf2\xc0\x8b\x27\xb1\x8c\xd7\xa9\xc4\xdd\x45\x77\xa8\x3b\xc5\x6e\xf8\x6e\xdf\xec\x41\xe0\x21\x09\xac\xb9\x0d\x43\x56\xd6\xae\xfc\xa9\x7e\xe9\xba\xa5\x1b\x79\x43\xe5\x8e\x98\xe7\x79\x2a\xe2\xec\xef\x38\xb2\x58\xf7\x23\x0a\x44\xf6\x73\xdd\x32\x4e\x57\xbd\xd0\xb5\xbc\x77\xc6\xee\xaf\xb2\x8c\xa6\x8f\xa3\xcb\x36\x25\xd9\x93\xd8\xc0\xec\x7e\xab\x7e\xa0\x79\x76\x73\x9b\x26\x67\x3c\x7d\xbc\x61\x24\xed\xcb\x4a\x6d\x3b\x75\x69\x78\x9e\xe1\xf6\x25\xe7\xf8\xed\x36\xb0\x9f\x8c\xef\xfe\xf1\x1b\xe3\xf5\xf5\x63\x47\x67\x88\x1e\xee\x67\x78\xb8\x9f\x9e\x80\xd9\xcd\x2e\x0b\x70\xaa\xf7\x4f\x00\x00\x00\xff\xff\xe0\x0c\x93\xa2\xa0\x03\x00\x00")
var __000004_user_messages_compatibilityUpSql = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xa4\x52\xc1\x6e\xda\x40\x10\xbd\xf3\x15\x73\x0b\x48\xb8\xca\x21\xca\x25\x27\x43\x96\xd6\xaa\x6b\x47\xc6\xa9\xc8\x69\xb5\xd8\x53\xbc\x62\xbd\x6b\xed\x8c\x4b\x2c\xe5\xe3\x2b\x03\x26\x40\x51\x2f\xf5\xc1\x87\x79\x33\x6f\xde\xdb\x79\x41\x00\x11\xdf\x11\xe8\xba\x71\x9e\x95\x65\xe0\x4a\xf5\x3f\x4d\xc0\x6a\x6d\x10\x2a\x45\xe0\xdd\x4e\x97\xa0\x08\x76\x08\x1e\x4d\x07\xce\x82\xe6\x51\x10\xc0\xae\x42\xdb\x0f\x1b\xac\xd1\xb2\xb6\x1b\xd0\xf6\x97\xb6\x9a\x31\xa0\xc2\x3b\x63\xbe\x8c\xe6\x99\x08\x73\x01\x79\x38\x8b\x05\x44\x0b\x48\xd2\x1c\xc4\x2a\x5a\xe6\x4b\x68\x09\xbd\xac\x91\x48\x6d\x90\xa4\xc1\x8d\x2a\x3a\x18\x8f\x00\x00\x74\x09\x3f\xc3\x6c\xfe\x2d\xcc\xe0\x25\x8b\x7e\x84\xd9\x1b\x7c\x17\x6f\x90\x26\x30\x4f\x93\x45\x1c\xcd\x73\xc8\xc4\x4b\x1c\xce\xc5\x74\xdf\xbf\xab\x34\x35\xe8\x25\xeb\x1a\x89\x55\xdd\x40\x94\xe4\xe2\xab\xc8\xf6\xfb\x92\xd7\x38\x3e\xf4\x91\x6b\x7d\x81\x90\x8b\x55\x7e\x85\x94\x48\xac\xad\x62\xed\x2c\xcc\xe2\x74\x76\xa8\x32\xbe\xf3\x49\xc9\xe5\x40\xe1\x2c\xa3\x65\xc9\x5d\x83\xfd\xb6\x2b\xb8\x37\x67\x55\x8d\xc3\xf4\x91\xef\x5c\xdf\x35\x61\xa5\x58\x9e\x19\xbf\x44\x8d\x2b\x94\x91\xff\xee\xf1\xc8\xbe\x93\x85\x6b\x2d\x5f\xf0\xc3\xb3\x58\x84\xaf\x71\x0e\xf7\x43\x1f\x35\xce\x12\x4a\x76\x97\xf2\x8e\xc7\x38\x79\x3a\x0a\x33\xae\xd8\xca\xdf\xca\xb4\xb7\x8c\x12\xa2\x85\x59\x9a\xc6\x22\x4c\xfe\xde\xb8\x08\xe3\xe5\xf1\x46\xae\xe5\x8d\xd3\x76\x23\x89\x15\xb7\x74\xb9\xb9\x51\x9e\xb0\x94\xfb\xf7\xfe\x7c\x7e\xaf\x76\xb2\x51\x9d\x71\xaa\x3c\xab\x12\xeb\x62\x8b\x5e\x36\xaa\xd8\x7e\xaa\x1c\xaa\x95\xa2\x6a\xe0\x1e\x4d\x9e\x46\x43\x02\xa3\xe4\x59\xac\x40\x97\xef\xf2\x18\x82\x34\xb9\x99\xc0\xf1\x01\x9e\x3c\xdd\x18\x44\xe5\x8b\x4a\xae\xbb\xd3\x1d\xd2\x04\x6e\x93\x1c\x24\xb5\x6b\x62\x3f\xbe\xbb\xff\xcf\xef\x0e\x3e\x3e\xce\xaf\x30\x85\xe0\xf1\x61\x0a\x8f\x0f\x93\x1e\xd0\xe5\x74\xc8\x4e\xef\xf7\x4f\x00\x00\x00\xff\xff\x91\x46\x82\xd5\xd4\x03\x00\x00")
func _000004_user_messages_compatibilityUpSqlBytes() ([]byte, error) {
return bindataRead(
@ -234,8 +234,8 @@ func _000004_user_messages_compatibilityUpSql() (*asset, error) {
return nil, err
}
info := bindataFileInfo{name: "000004_user_messages_compatibility.up.sql", size: 928, mode: os.FileMode(0644), modTime: time.Unix(1569474812, 0)}
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x60, 0x6c, 0x7f, 0xfb, 0xb3, 0x30, 0xd8, 0xbf, 0x6, 0x4a, 0x4a, 0xec, 0x9e, 0xd7, 0xa, 0x5e, 0x8, 0xbb, 0xf8, 0x11, 0x97, 0x80, 0xd3, 0xfa, 0x2c, 0x1e, 0x82, 0xb2, 0xe2, 0xe7, 0x6e, 0xa}}
info := bindataFileInfo{name: "000004_user_messages_compatibility.up.sql", size: 980, mode: os.FileMode(0644), modTime: time.Unix(1575009877, 0)}
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xc, 0x7a, 0xba, 0xae, 0x6d, 0xef, 0x69, 0x12, 0x6b, 0x48, 0xe3, 0xa7, 0xad, 0x21, 0x4a, 0xcf, 0x4f, 0xbc, 0x14, 0xc1, 0x19, 0x69, 0x1c, 0xc, 0xa2, 0x3d, 0xbc, 0x12, 0x32, 0x71, 0x76, 0x15}}
return a, nil
}
@ -254,12 +254,12 @@ func _1567112142_user_messagesDownSql() (*asset, error) {
return nil, err
}
info := bindataFileInfo{name: "1567112142_user_messages.down.sql", size: 26, mode: os.FileMode(0644), modTime: time.Unix(1568961800, 0)}
info := bindataFileInfo{name: "1567112142_user_messages.down.sql", size: 26, mode: os.FileMode(0644), modTime: time.Unix(1574354941, 0)}
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x79, 0x8e, 0xbe, 0x63, 0x64, 0x52, 0xa3, 0x13, 0x83, 0xc7, 0x47, 0xff, 0x56, 0xa9, 0xc, 0x72, 0xb4, 0x97, 0x6, 0xc7, 0xa5, 0x68, 0xb6, 0x55, 0x6a, 0xd5, 0xb0, 0x12, 0xfb, 0x4c, 0xa5, 0x27}}
return a, nil
}
var __1567112142_user_messagesUpSql = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x6c\x90\x51\x6f\x9b\x30\x14\x85\xdf\xf9\x15\xe7\xad\xad\xb4\x54\x7b\xef\x13\x01\x67\x43\x42\x64\x23\xce\xd6\xb7\xc8\xd8\xb7\xc5\x8a\xb1\x11\xbe\x2c\xe5\xdf\x4f\xa1\xb0\x2d\x53\x5f\xcf\x77\xfd\xdd\x73\xbd\xd9\x20\x1f\x42\x0f\xe5\x27\xf4\x03\xfd\xb2\x61\x8c\x6e\x82\x1e\x48\x31\x19\x8c\x91\x86\x53\x47\x31\xaa\x57\x8a\x60\xd5\x38\x7a\x4c\x36\x1b\xfc\x24\x98\xe0\xef\x18\x9e\xc8\x80\x03\x22\xab\x09\x8d\xd2\xe7\x8b\x1a\x0c\x74\xe8\x7a\xc5\xb6\x71\x84\x8b\xe5\x16\x96\xaf\x8f\x1a\xd2\x6a\x8c\x04\xcb\x77\x11\x3e\xf0\xd5\x6e\xae\x9b\x2f\x2d\x0d\x04\x7a\xd3\xd4\x33\x5e\xc2\x00\x6e\x09\x3a\xf8\x18\x1c\x41\x3b\x4b\x9e\x1f\x93\xbc\xde\x7f\x83\x4c\xb7\xa5\xb8\x6d\xf5\x94\x24\x59\x2d\x52\x29\x16\x58\xec\x50\xed\x25\xc4\x73\x71\x90\x87\xff\x0e\xb8\x4f\x00\xc0\x1a\x6c\xcb\xfd\x16\xc7\xaa\xf8\x7e\x14\xf3\x74\x75\x2c\xcb\x4f\x33\xd4\xad\xe2\x93\x35\xf8\x91\xd6\xd9\xd7\xb4\xfe\x43\x51\x8b\x9d\xa8\x45\x95\x89\xc3\x3c\x13\xef\xad\x79\xc0\xbe\x42\x2e\x4a\x21\x05\xb2\xf4\x90\xa5\xb9\x58\x24\xc1\x33\x79\x3e\xf1\xd4\xd3\x6a\x7a\x27\x4b\x95\x0f\x08\xd3\x1b\x43\x8a\x67\xb9\x28\x5c\xd0\x67\x6c\x8b\x2f\x45\xb5\x24\x6c\x3b\x8a\xac\xba\xfe\x26\x5d\x57\xad\xbd\xff\x31\xac\x25\x6e\xc5\xfd\xd8\x38\xab\x4f\x67\x9a\xe6\x5f\x78\x0f\x5f\x9c\x7a\x8d\x28\x2a\xf9\xf7\xde\x5c\xec\xd2\x63\x29\xf1\x39\x79\x78\x4a\x7e\x07\x00\x00\xff\xff\x07\x0e\xee\x5c\x27\x02\x00\x00")
var __1567112142_user_messagesUpSql = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x5c\x4f\x4d\x73\x9b\x30\x14\xbc\xf3\x2b\xf6\x96\x64\xa6\xce\xf4\x9e\x13\x06\xb9\x65\x86\xc1\x2d\x96\xdb\xdc\x3c\x42\x7a\x09\x1a\x0b\x89\x41\x8f\x3a\xfc\xfb\x0e\x04\x37\x75\x8e\x6f\x77\xdf\x7e\x6c\x36\xc8\x87\xd0\x43\xf9\x09\xfd\x40\x7f\x6c\x18\xa3\x9b\xa0\x07\x52\x4c\x06\x63\xa4\xe1\xd4\x51\x8c\xea\x95\x22\x58\x35\x8e\x1e\x93\xcd\x06\xbf\x09\x26\xf8\x3b\x86\x27\x32\xe0\x80\xc8\x6a\x42\xa3\xf4\xf9\xa2\x06\x03\x1d\xba\x5e\xb1\x6d\x1c\xe1\x62\xb9\x85\xe5\xf9\xa9\x21\xad\xc6\x48\xb0\x7c\x17\xe1\x03\xcf\xee\x66\x4e\xbe\xb4\x34\x10\xe8\x4d\x53\xcf\x78\x09\x03\xb8\x25\xe8\xe0\x63\x70\x04\xed\x2c\x79\x7e\x4c\xf2\x7a\xff\x03\x32\xdd\x96\xe2\xb6\xd5\x53\x92\x64\xb5\x48\xa5\x58\xc9\x62\x87\x6a\x2f\x21\x9e\x8b\x83\x3c\x7c\x1a\x70\x9f\x00\x80\x35\xd8\x96\xfb\x2d\x8e\x55\xf1\xf3\x28\x16\x75\x75\x2c\xcb\x2f\x0b\xa9\x5b\xc5\x27\x6b\xf0\x2b\xad\xb3\xef\x69\xfd\x8f\x45\x2d\x76\xa2\x16\x55\x26\x0e\x8b\x26\xde\x5b\xf3\x80\x7d\x85\x5c\x94\x42\x0a\x64\xe9\x21\x4b\x73\xb1\x9a\x04\xcf\xe4\xf9\xc4\x53\x4f\x28\x2a\xf9\x8e\xae\x35\x3e\xa1\x4c\x6f\x0c\x29\x9e\xd7\x53\xbb\xa0\xcf\xd8\x16\xdf\x3e\x04\xb6\xa3\xc8\xaa\xeb\x6f\xd0\x6b\xc4\xb5\xef\x7f\x0e\xd7\xf0\x5b\xe3\x7e\x6c\x9c\xd5\xa7\x33\x4d\xcb\xfa\x77\xf0\xc5\xa9\xd7\x38\x77\xf9\xd8\x99\x8b\x5d\x7a\x2c\x25\xbe\x26\x0f\x4f\xc9\xdf\x00\x00\x00\xff\xff\x6e\x1c\xcd\x6f\x1f\x02\x00\x00")
func _1567112142_user_messagesUpSqlBytes() ([]byte, error) {
return bindataRead(
@ -274,8 +274,8 @@ func _1567112142_user_messagesUpSql() (*asset, error) {
return nil, err
}
info := bindataFileInfo{name: "1567112142_user_messages.up.sql", size: 551, mode: os.FileMode(0644), modTime: time.Unix(1568961800, 0)}
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x7a, 0x11, 0x2, 0x79, 0x3b, 0xc5, 0x37, 0xe7, 0x3f, 0xa9, 0x35, 0x99, 0xa5, 0x3f, 0x32, 0xa3, 0xbe, 0xf7, 0x53, 0xf3, 0xea, 0x72, 0xbd, 0xb, 0xfc, 0xa7, 0xdc, 0x97, 0x1c, 0x6, 0x71, 0x16}}
info := bindataFileInfo{name: "1567112142_user_messages.up.sql", size: 543, mode: os.FileMode(0644), modTime: time.Unix(1575009877, 0)}
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xff, 0xc0, 0x47, 0x32, 0xa9, 0xa4, 0x6, 0x63, 0x6b, 0xe7, 0x79, 0x2b, 0x80, 0x52, 0x2b, 0x6f, 0xf9, 0x9d, 0x9a, 0xc2, 0xa9, 0x7a, 0xf7, 0x4d, 0x14, 0x12, 0x21, 0x10, 0xc4, 0x30, 0x42, 0xaa}}
return a, nil
}
@ -294,7 +294,7 @@ func docGo() (*asset, error) {
return nil, err
}
info := bindataFileInfo{name: "doc.go", size: 377, mode: os.FileMode(0644), modTime: time.Unix(1564484687, 0)}
info := bindataFileInfo{name: "doc.go", size: 377, mode: os.FileMode(0644), modTime: time.Unix(1574354941, 0)}
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xef, 0xaf, 0xdf, 0xcf, 0x65, 0xae, 0x19, 0xfc, 0x9d, 0x29, 0xc1, 0x91, 0xaf, 0xb5, 0xd5, 0xb1, 0x56, 0xf3, 0xee, 0xa8, 0xba, 0x13, 0x65, 0xdb, 0xab, 0xcf, 0x4e, 0xac, 0x92, 0xe9, 0x60, 0xf1}}
return a, nil
}
@ -454,17 +454,17 @@ type bintree struct {
}
var _bintree = &bintree{nil, map[string]*bintree{
"000001_init.down.db.sql": {_000001_initDownDbSql, map[string]*bintree{}},
"000001_init.up.db.sql": {_000001_initUpDbSql, map[string]*bintree{}},
"000002_add_chats.down.db.sql": {_000002_add_chatsDownDbSql, map[string]*bintree{}},
"000002_add_chats.up.db.sql": {_000002_add_chatsUpDbSql, map[string]*bintree{}},
"000003_add_contacts.down.db.sql": {_000003_add_contactsDownDbSql, map[string]*bintree{}},
"000003_add_contacts.up.db.sql": {_000003_add_contactsUpDbSql, map[string]*bintree{}},
"000004_user_messages_compatibility.down.sql": {_000004_user_messages_compatibilityDownSql, map[string]*bintree{}},
"000004_user_messages_compatibility.up.sql": {_000004_user_messages_compatibilityUpSql, map[string]*bintree{}},
"1567112142_user_messages.down.sql": {_1567112142_user_messagesDownSql, map[string]*bintree{}},
"1567112142_user_messages.up.sql": {_1567112142_user_messagesUpSql, map[string]*bintree{}},
"doc.go": {docGo, map[string]*bintree{}},
"000001_init.down.db.sql": &bintree{_000001_initDownDbSql, map[string]*bintree{}},
"000001_init.up.db.sql": &bintree{_000001_initUpDbSql, map[string]*bintree{}},
"000002_add_chats.down.db.sql": &bintree{_000002_add_chatsDownDbSql, map[string]*bintree{}},
"000002_add_chats.up.db.sql": &bintree{_000002_add_chatsUpDbSql, map[string]*bintree{}},
"000003_add_contacts.down.db.sql": &bintree{_000003_add_contactsDownDbSql, map[string]*bintree{}},
"000003_add_contacts.up.db.sql": &bintree{_000003_add_contactsUpDbSql, map[string]*bintree{}},
"000004_user_messages_compatibility.down.sql": &bintree{_000004_user_messages_compatibilityDownSql, map[string]*bintree{}},
"000004_user_messages_compatibility.up.sql": &bintree{_000004_user_messages_compatibilityUpSql, map[string]*bintree{}},
"1567112142_user_messages.down.sql": &bintree{_1567112142_user_messagesDownSql, map[string]*bintree{}},
"1567112142_user_messages.up.sql": &bintree{_1567112142_user_messagesUpSql, map[string]*bintree{}},
"doc.go": &bintree{docGo, map[string]*bintree{}},
}}
// RestoreAsset restores an asset under the given directory.

View file

@ -6,12 +6,9 @@ import (
"database/sql"
"encoding/gob"
"encoding/hex"
"time"
"github.com/pkg/errors"
"github.com/status-im/status-go/eth-node/crypto"
v1protocol "github.com/status-im/status-go/protocol/v1"
)
var (
@ -24,21 +21,46 @@ type sqlitePersistence struct {
db *sql.DB
}
func (db sqlitePersistence) LastMessageClock(chatID string) (int64, error) {
if chatID == "" {
return 0, errors.New("chat ID is empty")
}
var last sql.NullInt64
err := db.db.QueryRow("SELECT max(clock) FROM user_messages WHERE chat_id = ?", chatID).Scan(&last)
if err != nil {
return 0, err
}
return last.Int64, nil
func (db sqlitePersistence) SaveChat(chat Chat) error {
return db.saveChat(nil, chat)
}
func (db sqlitePersistence) SaveChat(chat Chat) error {
func (db sqlitePersistence) SaveChats(chats []*Chat) error {
tx, err := db.db.BeginTx(context.Background(), &sql.TxOptions{})
defer func() {
if err == nil {
err = tx.Commit()
return
}
// don't shadow original error
_ = tx.Rollback()
}()
for _, chat := range chats {
err := db.saveChat(tx, *chat)
if err != nil {
return err
}
}
return nil
}
func (db sqlitePersistence) saveChat(tx *sql.Tx, chat Chat) error {
var err error
if tx == nil {
tx, err = db.db.BeginTx(context.Background(), &sql.TxOptions{})
if err != nil {
return err
}
defer func() {
if err == nil {
err = tx.Commit()
return
}
// don't shadow original error
_ = tx.Rollback()
}()
}
pkey := []byte{}
// For one to one chatID is an encoded public key
@ -72,8 +94,8 @@ func (db sqlitePersistence) SaveChat(chat Chat) error {
}
// Insert record
stmt, err := db.db.Prepare(`INSERT INTO chats(id, name, color, active, type, timestamp, deleted_at_clock_value, public_key, unviewed_message_count, last_clock_value, last_message_content_type, last_message_content, last_message_timestamp, last_message_clock_value, members, membership_updates)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`)
stmt, err := tx.Prepare(`INSERT INTO chats(id, name, color, active, type, timestamp, deleted_at_clock_value, public_key, unviewed_message_count, last_clock_value, last_message, members, membership_updates)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`)
if err != nil {
return err
}
@ -90,10 +112,7 @@ func (db sqlitePersistence) SaveChat(chat Chat) error {
pkey,
chat.UnviewedMessagesCount,
chat.LastClockValue,
chat.LastMessageContentType,
chat.LastMessageContent,
chat.LastMessageTimestamp,
chat.LastMessageClockValue,
chat.LastMessage,
encodedMembers.Bytes(),
encodedMembershipUpdates.Bytes(),
)
@ -141,10 +160,7 @@ func (db sqlitePersistence) chats(tx *sql.Tx) (chats []*Chat, err error) {
public_key,
unviewed_message_count,
last_clock_value,
last_message_content_type,
last_message_content,
last_message_timestamp,
last_message_clock_value,
last_message,
members,
membership_updates
FROM chats
@ -157,11 +173,6 @@ func (db sqlitePersistence) chats(tx *sql.Tx) (chats []*Chat, err error) {
for rows.Next() {
var (
lastMessageContentType sql.NullString
lastMessageContent sql.NullString
lastMessageTimestamp sql.NullInt64
lastMessageClockValue sql.NullInt64
chat Chat
encodedMembers []byte
encodedMembershipUpdates []byte
@ -178,20 +189,13 @@ func (db sqlitePersistence) chats(tx *sql.Tx) (chats []*Chat, err error) {
&pkey,
&chat.UnviewedMessagesCount,
&chat.LastClockValue,
&lastMessageContentType,
&lastMessageContent,
&lastMessageTimestamp,
&lastMessageClockValue,
&chat.LastMessage,
&encodedMembers,
&encodedMembershipUpdates,
)
if err != nil {
return
}
chat.LastMessageContent = lastMessageContent.String
chat.LastMessageContentType = lastMessageContentType.String
chat.LastMessageTimestamp = lastMessageTimestamp.Int64
chat.LastMessageClockValue = lastMessageClockValue.Int64
// Restore members
membersDecoder := gob.NewDecoder(bytes.NewBuffer(encodedMembers))
@ -289,7 +293,7 @@ func (db sqlitePersistence) Contacts() ([]*Contact, error) {
return response, nil
}
func (db sqlitePersistence) SetContactsENSData(contacts []Contact) error {
func (db sqlitePersistence) SetContactsENSData(contacts []*Contact) error {
tx, err := db.db.BeginTx(context.Background(), &sql.TxOptions{})
if err != nil {
return err
@ -323,7 +327,7 @@ func (db sqlitePersistence) SetContactsENSData(contacts []Contact) error {
// SetContactsGeneratedData sets a contact generated data if not existing already
// in the database
func (db sqlitePersistence) SetContactsGeneratedData(contacts []Contact, tx *sql.Tx) (err error) {
func (db sqlitePersistence) SetContactsGeneratedData(contacts []*Contact, tx *sql.Tx) (err error) {
if tx == nil {
tx, err = db.db.BeginTx(context.Background(), &sql.TxOptions{})
if err != nil {
@ -435,109 +439,3 @@ func (db sqlitePersistence) SaveContact(contact Contact, tx *sql.Tx) (err error)
)
return
}
// Messages returns messages for a given contact, in a given period. Ordered by a timestamp.
func (db sqlitePersistence) Messages(from, to time.Time) (result []*v1protocol.Message, err error) {
rows, err := db.db.Query(`
SELECT
id,
chat_id,
content_type,
message_type,
text,
clock,
timestamp,
content_chat_id,
content_text,
public_key,
flags
FROM user_messages
WHERE timestamp >= ? AND timestamp <= ?
ORDER BY timestamp`,
v1protocol.TimestampInMsFromTime(from),
v1protocol.TimestampInMsFromTime(to),
)
if err != nil {
return
}
defer rows.Close()
for rows.Next() {
msg := v1protocol.Message{
Content: v1protocol.Content{},
}
var pkey []byte
err = rows.Scan(
&msg.ID, &msg.ChatID, &msg.ContentT, &msg.MessageT, &msg.Text, &msg.Clock,
&msg.Timestamp, &msg.Content.ChatID, &msg.Content.Text, &pkey, &msg.Flags,
)
if err != nil {
return
}
if len(pkey) != 0 {
msg.SigPubKey, err = crypto.UnmarshalPubkey(pkey)
if err != nil {
return
}
}
result = append(result, &msg)
}
return
}
func (db sqlitePersistence) SaveMessages(messages []*v1protocol.Message) (last int64, err error) {
tx, err := db.db.BeginTx(context.Background(), &sql.TxOptions{})
if err != nil {
return
}
defer func() {
if err == nil {
err = tx.Commit()
return
}
// don't shadow original error
_ = tx.Rollback()
}()
stmt, err := tx.Prepare(`
INSERT OR IGNORE INTO user_messages(
id,
chat_id,
content_type,
message_type,
text,
clock,
timestamp,
content_chat_id,
content_text,
public_key,
flags
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
`)
if err != nil {
return
}
var rst sql.Result
for _, msg := range messages {
var pkey []byte
if msg.SigPubKey != nil {
pkey = crypto.FromECDSAPub(msg.SigPubKey)
}
rst, err = stmt.Exec(
msg.ID, msg.ChatID, msg.ContentT, msg.MessageT, msg.Text, msg.Clock, msg.Timestamp,
msg.Content.ChatID, msg.Content.Text, pkey, msg.Flags,
)
if err != nil {
return
}
last, err = rst.LastInsertId()
if err != nil {
return
}
}
return
}

View file

@ -3,7 +3,9 @@ package protocol
import (
"context"
"database/sql"
"encoding/json"
"fmt"
"github.com/status-im/status-go/protocol/protobuf"
"strings"
"github.com/pkg/errors"
@ -17,42 +19,46 @@ func (db sqlitePersistence) tableUserMessagesLegacyAllFields() string {
return `id,
whisper_timestamp,
source,
destination,
content,
text,
content_type,
username,
timestamp,
chat_id,
local_chat_id,
retry_count,
message_type,
message_status,
clock_value,
show,
seen,
outgoing_status,
reply_to`
parsed_text,
raw_payload,
sticker_pack,
sticker_hash,
response_to`
}
func (db sqlitePersistence) tableUserMessagesLegacyAllFieldsJoin() string {
return `m1.id,
m1.whisper_timestamp,
m1.source,
m1.destination,
m1.content,
m1.text,
m1.content_type,
m1.username,
m1.timestamp,
m1.chat_id,
m1.local_chat_id,
m1.retry_count,
m1.message_type,
m1.message_status,
m1.clock_value,
m1.show,
m1.seen,
m1.outgoing_status,
m1.reply_to,
m1.parsed_text,
m1.raw_payload,
m1.sticker_pack,
m1.sticker_hash,
m1.response_to,
m2.source,
m2.content,
m2.text,
c.alias,
c.identicon`
}
@ -66,30 +72,35 @@ type scanner interface {
}
func (db sqlitePersistence) tableUserMessagesLegacyScanAllFields(row scanner, message *Message, others ...interface{}) error {
var quotedContent sql.NullString
var quotedText sql.NullString
var quotedFrom sql.NullString
var alias sql.NullString
var identicon sql.NullString
sticker := &protobuf.StickerMessage{}
args := []interface{}{
&message.ID,
&message.WhisperTimestamp,
&message.From, // source in table
&message.To, // destination in table
&message.Content,
&message.Text,
&message.ContentType,
&message.Alias,
&message.Timestamp,
&message.ChatID,
&message.ChatId,
&message.LocalChatID,
&message.RetryCount,
&message.MessageType,
&message.MessageStatus,
&message.ClockValue,
&message.Show,
&message.Clock,
&message.Seen,
&message.OutgoingStatus,
&message.ReplyTo,
&message.ParsedText,
&message.RawPayload,
&sticker.Pack,
&sticker.Hash,
&message.ResponseTo,
&quotedFrom,
&quotedContent,
&quotedText,
&alias,
&identicon,
}
@ -98,45 +109,70 @@ func (db sqlitePersistence) tableUserMessagesLegacyScanAllFields(row scanner, me
return err
}
if quotedContent.Valid {
if quotedText.Valid {
message.QuotedMessage = &QuotedMessage{
From: quotedFrom.String,
Content: quotedContent.String,
From: quotedFrom.String,
Text: quotedText.String,
}
}
message.Alias = alias.String
message.Identicon = identicon.String
if message.ContentType == protobuf.ChatMessage_STICKER {
message.Payload = &protobuf.ChatMessage_Sticker{Sticker: sticker}
}
return nil
}
func (db sqlitePersistence) tableUserMessagesLegacyAllValues(message *Message) []interface{} {
func (db sqlitePersistence) tableUserMessagesLegacyAllValues(message *Message) ([]interface{}, error) {
sticker := message.GetSticker()
if sticker == nil {
sticker = &protobuf.StickerMessage{}
}
return []interface{}{
message.ID,
message.WhisperTimestamp,
message.From, // source in table
message.To, // destination in table
message.Content,
message.Text,
message.ContentType,
message.Alias,
message.Timestamp,
message.ChatID,
message.ChatId,
message.LocalChatID,
message.RetryCount,
message.MessageType,
message.MessageStatus,
message.ClockValue,
message.Show,
message.Clock,
message.Seen,
message.OutgoingStatus,
message.ReplyTo,
}
message.ParsedText,
message.RawPayload,
sticker.Pack,
sticker.Hash,
message.ResponseTo,
}, nil
}
func (db sqlitePersistence) MessageByID(id string) (*Message, error) {
func (db sqlitePersistence) messageByID(tx *sql.Tx, id string) (*Message, error) {
var err error
if tx == nil {
tx, err = db.db.BeginTx(context.Background(), &sql.TxOptions{})
if err != nil {
return nil, err
}
defer func() {
if err == nil {
err = tx.Commit()
return
}
// don't shadow original error
_ = tx.Rollback()
}()
}
var message Message
allFields := db.tableUserMessagesLegacyAllFieldsJoin()
row := db.db.QueryRow(
row := tx.QueryRow(
fmt.Sprintf(`
SELECT
%s
@ -145,7 +181,7 @@ func (db sqlitePersistence) MessageByID(id string) (*Message, error) {
LEFT JOIN
user_messages_legacy m2
ON
m1.reply_to = m2.id
m1.response_to = m2.id
LEFT JOIN
contacts c
@ -156,7 +192,7 @@ func (db sqlitePersistence) MessageByID(id string) (*Message, error) {
`, allFields),
id,
)
err := db.tableUserMessagesLegacyScanAllFields(row, &message)
err = db.tableUserMessagesLegacyScanAllFields(row, &message)
switch err {
case sql.ErrNoRows:
return nil, errRecordNotFound
@ -167,6 +203,10 @@ func (db sqlitePersistence) MessageByID(id string) (*Message, error) {
}
}
func (db sqlitePersistence) MessageByID(id string) (*Message, error) {
return db.messageByID(nil, id)
}
func (db sqlitePersistence) MessagesExist(ids []string) (map[string]bool, error) {
result := make(map[string]bool)
if len(ids) == 0 {
@ -224,7 +264,7 @@ func (db sqlitePersistence) MessageByChatID(chatID string, currCursor string, li
LEFT JOIN
user_messages_legacy m2
ON
m1.reply_to = m2.id
m1.response_to = m2.id
LEFT JOIN
contacts c
@ -232,7 +272,7 @@ func (db sqlitePersistence) MessageByChatID(chatID string, currCursor string, li
m1.source = c.id
WHERE
m1.chat_id = ? %s
m1.local_chat_id = ? %s
ORDER BY cursor DESC
LIMIT ?
`, allFields, cursorWhere),
@ -290,7 +330,13 @@ func (db sqlitePersistence) SaveMessagesLegacy(messages []*Message) (err error)
}
for _, msg := range messages {
_, err = stmt.Exec(db.tableUserMessagesLegacyAllValues(msg)...)
var allValues []interface{}
allValues, err = db.tableUserMessagesLegacyAllValues(msg)
if err != nil {
return
}
_, err = stmt.Exec(allValues...)
if err != nil {
return
}
@ -304,24 +350,49 @@ func (db sqlitePersistence) DeleteMessage(id string) error {
}
func (db sqlitePersistence) DeleteMessagesByChatID(id string) error {
_, err := db.db.Exec(`DELETE FROM user_messages_legacy WHERE chat_id = ?`, id)
_, err := db.db.Exec(`DELETE FROM user_messages_legacy WHERE local_chat_id = ?`, id)
return err
}
func (db sqlitePersistence) MarkMessagesSeen(ids ...string) error {
func (db sqlitePersistence) MarkMessagesSeen(chatID string, ids []string) error {
tx, err := db.db.BeginTx(context.Background(), &sql.TxOptions{})
if err != nil {
return err
}
defer func() {
if err == nil {
err = tx.Commit()
return
}
// don't shadow original error
_ = tx.Rollback()
}()
idsArgs := make([]interface{}, 0, len(ids))
for _, id := range ids {
idsArgs = append(idsArgs, id)
}
inVector := strings.Repeat("?, ", len(ids)-1) + "?"
_, err := db.db.Exec(
_, err = tx.Exec(
fmt.Sprintf(`
UPDATE user_messages_legacy
SET seen = 1
WHERE id IN (%s)
`, inVector),
idsArgs...)
if err != nil {
return err
}
// Update denormalized count
_, err = tx.Exec(
`UPDATE chats
SET unviewed_message_count =
(SELECT COUNT(1)
FROM user_messages_legacy
WHERE local_chat_id = ? AND seen = 0)
WHERE id = ?`, chatID, chatID)
return err
}
@ -335,10 +406,11 @@ func (db sqlitePersistence) UpdateMessageOutgoingStatus(id string, newOutgoingSt
}
// BlockContact updates a contact, deletes all the messages and 1-to-1 chat, updates the unread messages count and returns a map with the new count
func (db sqlitePersistence) BlockContact(contact Contact) (chats []*Chat, err error) {
func (db sqlitePersistence) BlockContact(contact Contact) ([]*Chat, error) {
var chats []*Chat
tx, err := db.db.BeginTx(context.Background(), &sql.TxOptions{})
if err != nil {
return
return nil, err
}
defer func() {
if err == nil {
@ -357,36 +429,69 @@ func (db sqlitePersistence) BlockContact(contact Contact) (chats []*Chat, err er
contact.ID,
)
if err != nil {
return
return nil, err
}
// Update contact
err = db.SaveContact(contact, tx)
if err != nil {
return
return nil, err
}
// Delete one-to-one chat
_, err = tx.Exec("DELETE FROM chats WHERE id = ?", contact.ID)
if err != nil {
return
return nil, err
}
// Recalculate denormalized fields
_, err = tx.Exec(`
UPDATE chats
SET
unviewed_message_count = (SELECT COUNT(1) FROM user_messages_legacy WHERE seen = 0 AND chat_id = chats.id),
last_message_content = (SELECT content from user_messages_legacy WHERE chat_id = chats.id ORDER BY clock_value DESC LIMIT 1),
last_message_timestamp = (SELECT timestamp from user_messages_legacy WHERE chat_id = chats.id ORDER BY clock_value DESC LIMIT 1),
last_message_clock_value = (SELECT clock_value from user_messages_legacy WHERE chat_id = chats.id ORDER BY clock_value DESC LIMIT 1),
last_message_content_type = (SELECT content_type from user_messages_legacy WHERE chat_id = chats.id ORDER BY clock_value DESC LIMIT 1)
`)
unviewed_message_count = (SELECT COUNT(1) FROM user_messages_legacy WHERE seen = 0 AND local_chat_id = chats.id)`)
if err != nil {
return
return nil, err
}
// return the updated chats
chats, err = db.chats(tx)
return
if err != nil {
return nil, err
}
for _, c := range chats {
var lastMessageID string
row := tx.QueryRow(`SELECT id FROM user_messages_legacy WHERE local_chat_id = ? ORDER BY clock_value DESC LIMIT 1`, c.ID)
switch err := row.Scan(&lastMessageID); err {
case nil:
message, err := db.messageByID(tx, lastMessageID)
if err != nil {
return nil, err
}
if message != nil {
encodedMessage, err := json.Marshal(message)
if err != nil {
return nil, err
}
_, err = tx.Exec(`UPDATE chats SET last_message = ? WHERE id = ?`, encodedMessage, c.ID)
if err != nil {
return nil, err
}
c.LastMessage = encodedMessage
}
case sql.ErrNoRows:
// Reset LastMessage
_, err = tx.Exec(`UPDATE chats SET last_message = NULL WHERE id = ?`, c.ID)
if err != nil {
return nil, err
}
c.LastMessage = nil
default:
return nil, err
}
}
return chats, err
}

View file

@ -0,0 +1,421 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// source: message.proto
package protobuf
import (
fmt "fmt"
proto "github.com/golang/protobuf/proto"
math "math"
)
// Reference imports to suppress errors if they are not otherwise used.
var _ = proto.Marshal
var _ = fmt.Errorf
var _ = math.Inf
// This is a compile-time assertion to ensure that this generated file
// is compatible with the proto package it is being compiled against.
// A compilation error at this line likely means your copy of the
// proto package needs to be updated.
const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package
type ChatMessage_MessageType int32
const (
ChatMessage_ONE_TO_ONE ChatMessage_MessageType = 0
ChatMessage_PUBLIC_GROUP ChatMessage_MessageType = 1
ChatMessage_PRIVATE_GROUP ChatMessage_MessageType = 2
// Only local
ChatMessage_SYSTEM_MESSAGE_PRIVATE_GROUP ChatMessage_MessageType = 3
)
var ChatMessage_MessageType_name = map[int32]string{
0: "ONE_TO_ONE",
1: "PUBLIC_GROUP",
2: "PRIVATE_GROUP",
3: "SYSTEM_MESSAGE_PRIVATE_GROUP",
}
var ChatMessage_MessageType_value = map[string]int32{
"ONE_TO_ONE": 0,
"PUBLIC_GROUP": 1,
"PRIVATE_GROUP": 2,
"SYSTEM_MESSAGE_PRIVATE_GROUP": 3,
}
func (x ChatMessage_MessageType) String() string {
return proto.EnumName(ChatMessage_MessageType_name, int32(x))
}
func (ChatMessage_MessageType) EnumDescriptor() ([]byte, []int) {
return fileDescriptor_33c57e4bae7b9afd, []int{1, 0}
}
type ChatMessage_ContentType int32
const (
ChatMessage_TEXT_PLAIN ChatMessage_ContentType = 0
ChatMessage_STICKER ChatMessage_ContentType = 1
ChatMessage_STATUS ChatMessage_ContentType = 2
ChatMessage_EMOJI ChatMessage_ContentType = 3
ChatMessage_COMMAND ChatMessage_ContentType = 4
ChatMessage_COMMAND_REQUEST ChatMessage_ContentType = 5
)
var ChatMessage_ContentType_name = map[int32]string{
0: "TEXT_PLAIN",
1: "STICKER",
2: "STATUS",
3: "EMOJI",
4: "COMMAND",
5: "COMMAND_REQUEST",
}
var ChatMessage_ContentType_value = map[string]int32{
"TEXT_PLAIN": 0,
"STICKER": 1,
"STATUS": 2,
"EMOJI": 3,
"COMMAND": 4,
"COMMAND_REQUEST": 5,
}
func (x ChatMessage_ContentType) String() string {
return proto.EnumName(ChatMessage_ContentType_name, int32(x))
}
func (ChatMessage_ContentType) EnumDescriptor() ([]byte, []int) {
return fileDescriptor_33c57e4bae7b9afd, []int{1, 1}
}
type ApplicationMetadataMessage_MessageType int32
const (
ApplicationMetadataMessage_TEXT_MESSAGE ApplicationMetadataMessage_MessageType = 0
ApplicationMetadataMessage_CONTACT_REQUEST ApplicationMetadataMessage_MessageType = 1
ApplicationMetadataMessage_MEMBERSHIP_UPDATE ApplicationMetadataMessage_MessageType = 2
ApplicationMetadataMessage_PAIR_INSTALLATION ApplicationMetadataMessage_MessageType = 3
ApplicationMetadataMessage_SYNC_INSTALLATION ApplicationMetadataMessage_MessageType = 4
)
var ApplicationMetadataMessage_MessageType_name = map[int32]string{
0: "TEXT_MESSAGE",
1: "CONTACT_REQUEST",
2: "MEMBERSHIP_UPDATE",
3: "PAIR_INSTALLATION",
4: "SYNC_INSTALLATION",
}
var ApplicationMetadataMessage_MessageType_value = map[string]int32{
"TEXT_MESSAGE": 0,
"CONTACT_REQUEST": 1,
"MEMBERSHIP_UPDATE": 2,
"PAIR_INSTALLATION": 3,
"SYNC_INSTALLATION": 4,
}
func (x ApplicationMetadataMessage_MessageType) String() string {
return proto.EnumName(ApplicationMetadataMessage_MessageType_name, int32(x))
}
func (ApplicationMetadataMessage_MessageType) EnumDescriptor() ([]byte, []int) {
return fileDescriptor_33c57e4bae7b9afd, []int{2, 0}
}
type StickerMessage struct {
Hash string `protobuf:"bytes,1,opt,name=hash,proto3" json:"hash,omitempty"`
Pack int32 `protobuf:"varint,2,opt,name=pack,proto3" json:"pack,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *StickerMessage) Reset() { *m = StickerMessage{} }
func (m *StickerMessage) String() string { return proto.CompactTextString(m) }
func (*StickerMessage) ProtoMessage() {}
func (*StickerMessage) Descriptor() ([]byte, []int) {
return fileDescriptor_33c57e4bae7b9afd, []int{0}
}
func (m *StickerMessage) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_StickerMessage.Unmarshal(m, b)
}
func (m *StickerMessage) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_StickerMessage.Marshal(b, m, deterministic)
}
func (m *StickerMessage) XXX_Merge(src proto.Message) {
xxx_messageInfo_StickerMessage.Merge(m, src)
}
func (m *StickerMessage) XXX_Size() int {
return xxx_messageInfo_StickerMessage.Size(m)
}
func (m *StickerMessage) XXX_DiscardUnknown() {
xxx_messageInfo_StickerMessage.DiscardUnknown(m)
}
var xxx_messageInfo_StickerMessage proto.InternalMessageInfo
func (m *StickerMessage) GetHash() string {
if m != nil {
return m.Hash
}
return ""
}
func (m *StickerMessage) GetPack() int32 {
if m != nil {
return m.Pack
}
return 0
}
type ChatMessage struct {
// Lamport timestamp of the chat message
Clock uint64 `protobuf:"varint,1,opt,name=clock,proto3" json:"clock,omitempty"`
// Unix timestamps in milliseconds, currently not used as we use whisper as more reliable, but here
// so that we don't rely on it
Timestamp uint64 `protobuf:"varint,2,opt,name=timestamp,proto3" json:"timestamp,omitempty"`
// Text of the message
Text string `protobuf:"bytes,3,opt,name=text,proto3" json:"text,omitempty"`
// Id of the message that we are replying to
ResponseTo string `protobuf:"bytes,4,opt,name=response_to,json=responseTo,proto3" json:"response_to,omitempty"`
// Ens name of the sender
EnsName string `protobuf:"bytes,5,opt,name=ens_name,json=ensName,proto3" json:"ens_name,omitempty"`
// Chat id, this field is symmetric for public-chats and private group chats,
// but asymmetric in case of one-to-ones, as the sender will use the chat-id
// of the received, while the receiver will use the chat-id of the sender.
// Probably should be the concatenation of sender-pk & receiver-pk in alphabetical order
ChatId string `protobuf:"bytes,6,opt,name=chat_id,json=chatId,proto3" json:"chat_id,omitempty"`
// The type of message (public/one-to-one/private-group-chat)
MessageType ChatMessage_MessageType `protobuf:"varint,7,opt,name=message_type,json=messageType,proto3,enum=protobuf.ChatMessage_MessageType" json:"message_type,omitempty"`
// The type of the content of the message
ContentType ChatMessage_ContentType `protobuf:"varint,8,opt,name=content_type,json=contentType,proto3,enum=protobuf.ChatMessage_ContentType" json:"content_type,omitempty"`
// Types that are valid to be assigned to Payload:
// *ChatMessage_Sticker
Payload isChatMessage_Payload `protobuf_oneof:"payload"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *ChatMessage) Reset() { *m = ChatMessage{} }
func (m *ChatMessage) String() string { return proto.CompactTextString(m) }
func (*ChatMessage) ProtoMessage() {}
func (*ChatMessage) Descriptor() ([]byte, []int) {
return fileDescriptor_33c57e4bae7b9afd, []int{1}
}
func (m *ChatMessage) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_ChatMessage.Unmarshal(m, b)
}
func (m *ChatMessage) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_ChatMessage.Marshal(b, m, deterministic)
}
func (m *ChatMessage) XXX_Merge(src proto.Message) {
xxx_messageInfo_ChatMessage.Merge(m, src)
}
func (m *ChatMessage) XXX_Size() int {
return xxx_messageInfo_ChatMessage.Size(m)
}
func (m *ChatMessage) XXX_DiscardUnknown() {
xxx_messageInfo_ChatMessage.DiscardUnknown(m)
}
var xxx_messageInfo_ChatMessage proto.InternalMessageInfo
func (m *ChatMessage) GetClock() uint64 {
if m != nil {
return m.Clock
}
return 0
}
func (m *ChatMessage) GetTimestamp() uint64 {
if m != nil {
return m.Timestamp
}
return 0
}
func (m *ChatMessage) GetText() string {
if m != nil {
return m.Text
}
return ""
}
func (m *ChatMessage) GetResponseTo() string {
if m != nil {
return m.ResponseTo
}
return ""
}
func (m *ChatMessage) GetEnsName() string {
if m != nil {
return m.EnsName
}
return ""
}
func (m *ChatMessage) GetChatId() string {
if m != nil {
return m.ChatId
}
return ""
}
func (m *ChatMessage) GetMessageType() ChatMessage_MessageType {
if m != nil {
return m.MessageType
}
return ChatMessage_ONE_TO_ONE
}
func (m *ChatMessage) GetContentType() ChatMessage_ContentType {
if m != nil {
return m.ContentType
}
return ChatMessage_TEXT_PLAIN
}
type isChatMessage_Payload interface {
isChatMessage_Payload()
}
type ChatMessage_Sticker struct {
Sticker *StickerMessage `protobuf:"bytes,9,opt,name=sticker,proto3,oneof"`
}
func (*ChatMessage_Sticker) isChatMessage_Payload() {}
func (m *ChatMessage) GetPayload() isChatMessage_Payload {
if m != nil {
return m.Payload
}
return nil
}
func (m *ChatMessage) GetSticker() *StickerMessage {
if x, ok := m.GetPayload().(*ChatMessage_Sticker); ok {
return x.Sticker
}
return nil
}
// XXX_OneofWrappers is for the internal use of the proto package.
func (*ChatMessage) XXX_OneofWrappers() []interface{} {
return []interface{}{
(*ChatMessage_Sticker)(nil),
}
}
type ApplicationMetadataMessage struct {
// Signature of the payload field
Signature []byte `protobuf:"bytes,1,opt,name=signature,proto3" json:"signature,omitempty"`
// This is the encoded protobuf of the application level message, i.e ChatMessage
Payload []byte `protobuf:"bytes,2,opt,name=payload,proto3" json:"payload,omitempty"`
// The type of protobuf message sent
MessageType ApplicationMetadataMessage_MessageType `protobuf:"varint,3,opt,name=message_type,json=messageType,proto3,enum=protobuf.ApplicationMetadataMessage_MessageType" json:"message_type,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *ApplicationMetadataMessage) Reset() { *m = ApplicationMetadataMessage{} }
func (m *ApplicationMetadataMessage) String() string { return proto.CompactTextString(m) }
func (*ApplicationMetadataMessage) ProtoMessage() {}
func (*ApplicationMetadataMessage) Descriptor() ([]byte, []int) {
return fileDescriptor_33c57e4bae7b9afd, []int{2}
}
func (m *ApplicationMetadataMessage) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_ApplicationMetadataMessage.Unmarshal(m, b)
}
func (m *ApplicationMetadataMessage) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_ApplicationMetadataMessage.Marshal(b, m, deterministic)
}
func (m *ApplicationMetadataMessage) XXX_Merge(src proto.Message) {
xxx_messageInfo_ApplicationMetadataMessage.Merge(m, src)
}
func (m *ApplicationMetadataMessage) XXX_Size() int {
return xxx_messageInfo_ApplicationMetadataMessage.Size(m)
}
func (m *ApplicationMetadataMessage) XXX_DiscardUnknown() {
xxx_messageInfo_ApplicationMetadataMessage.DiscardUnknown(m)
}
var xxx_messageInfo_ApplicationMetadataMessage proto.InternalMessageInfo
func (m *ApplicationMetadataMessage) GetSignature() []byte {
if m != nil {
return m.Signature
}
return nil
}
func (m *ApplicationMetadataMessage) GetPayload() []byte {
if m != nil {
return m.Payload
}
return nil
}
func (m *ApplicationMetadataMessage) GetMessageType() ApplicationMetadataMessage_MessageType {
if m != nil {
return m.MessageType
}
return ApplicationMetadataMessage_TEXT_MESSAGE
}
func init() {
proto.RegisterEnum("protobuf.ChatMessage_MessageType", ChatMessage_MessageType_name, ChatMessage_MessageType_value)
proto.RegisterEnum("protobuf.ChatMessage_ContentType", ChatMessage_ContentType_name, ChatMessage_ContentType_value)
proto.RegisterEnum("protobuf.ApplicationMetadataMessage_MessageType", ApplicationMetadataMessage_MessageType_name, ApplicationMetadataMessage_MessageType_value)
proto.RegisterType((*StickerMessage)(nil), "protobuf.StickerMessage")
proto.RegisterType((*ChatMessage)(nil), "protobuf.ChatMessage")
proto.RegisterType((*ApplicationMetadataMessage)(nil), "protobuf.ApplicationMetadataMessage")
}
func init() { proto.RegisterFile("message.proto", fileDescriptor_33c57e4bae7b9afd) }
var fileDescriptor_33c57e4bae7b9afd = []byte{
// 563 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x7c, 0x52, 0x5f, 0x6f, 0xda, 0x3e,
0x14, 0x25, 0x10, 0xa0, 0xdc, 0xd0, 0xfe, 0x5c, 0xff, 0x36, 0x2d, 0x9b, 0x2a, 0x8d, 0xf1, 0xc4,
0x13, 0x9a, 0xba, 0x3d, 0xec, 0x35, 0x4d, 0xad, 0x36, 0x1b, 0xf9, 0x33, 0xdb, 0x4c, 0xeb, 0x93,
0xe5, 0x06, 0xaf, 0xa0, 0x96, 0x24, 0x22, 0xae, 0x34, 0xbe, 0xcf, 0x3e, 0xc9, 0x3e, 0xd9, 0x14,
0x07, 0x0a, 0x4c, 0xea, 0x9e, 0xec, 0x73, 0x7c, 0x7d, 0xee, 0xbd, 0xe7, 0x5e, 0x38, 0x5e, 0xaa,
0xb2, 0x94, 0x77, 0x6a, 0x5c, 0xac, 0x72, 0x9d, 0xe3, 0x23, 0x73, 0xdc, 0x3e, 0xfe, 0x18, 0x7e,
0x82, 0x13, 0xa6, 0x17, 0xe9, 0xbd, 0x5a, 0x85, 0x75, 0x04, 0xc6, 0x60, 0xcf, 0x65, 0x39, 0x77,
0xad, 0x81, 0x35, 0xea, 0x51, 0x73, 0xaf, 0xb8, 0x42, 0xa6, 0xf7, 0x6e, 0x73, 0x60, 0x8d, 0xda,
0xd4, 0xdc, 0x87, 0xbf, 0x6d, 0x70, 0xfc, 0xb9, 0xd4, 0xdb, 0x7f, 0x2f, 0xa0, 0x9d, 0x3e, 0xe4,
0xe9, 0xbd, 0xf9, 0x68, 0xd3, 0x1a, 0xe0, 0x33, 0xe8, 0xe9, 0xc5, 0x52, 0x95, 0x5a, 0x2e, 0x0b,
0xf3, 0xdd, 0xa6, 0x3b, 0xa2, 0xd2, 0xd5, 0xea, 0xa7, 0x76, 0x5b, 0x75, 0xae, 0xea, 0x8e, 0xdf,
0x82, 0xb3, 0x52, 0x65, 0x91, 0x67, 0xa5, 0x12, 0x3a, 0x77, 0x6d, 0xf3, 0x04, 0x5b, 0x8a, 0xe7,
0xf8, 0x35, 0x1c, 0xa9, 0xac, 0x14, 0x99, 0x5c, 0x2a, 0xb7, 0x6d, 0x5e, 0xbb, 0x2a, 0x2b, 0x23,
0xb9, 0x54, 0xf8, 0x15, 0x74, 0xd3, 0xb9, 0xd4, 0x62, 0x31, 0x73, 0x3b, 0xe6, 0xa5, 0x53, 0xc1,
0x60, 0x86, 0x2f, 0xa1, 0xbf, 0x71, 0x40, 0xe8, 0x75, 0xa1, 0xdc, 0xee, 0xc0, 0x1a, 0x9d, 0x9c,
0xbf, 0x1b, 0x6f, 0x7d, 0x18, 0xef, 0x75, 0x32, 0xde, 0x9c, 0x7c, 0x5d, 0x28, 0xea, 0x2c, 0x77,
0xa0, 0x52, 0x49, 0xf3, 0x4c, 0xab, 0x4c, 0xd7, 0x2a, 0x47, 0xff, 0x52, 0xf1, 0xeb, 0xc8, 0x5a,
0x25, 0xdd, 0x01, 0xfc, 0x11, 0xba, 0x65, 0x6d, 0xb9, 0xdb, 0x1b, 0x58, 0x23, 0xe7, 0xdc, 0xdd,
0x09, 0x1c, 0xce, 0xe2, 0xba, 0x41, 0xb7, 0xa1, 0xc3, 0x19, 0x38, 0x7b, 0x75, 0xe1, 0x13, 0x80,
0x38, 0x22, 0x82, 0xc7, 0x22, 0x8e, 0x08, 0x6a, 0x60, 0x04, 0xfd, 0x64, 0x7a, 0x31, 0x09, 0x7c,
0x71, 0x45, 0xe3, 0x69, 0x82, 0x2c, 0x7c, 0x0a, 0xc7, 0x09, 0x0d, 0xbe, 0x79, 0x9c, 0x6c, 0xa8,
0x26, 0x1e, 0xc0, 0x19, 0xbb, 0x61, 0x9c, 0x84, 0x22, 0x24, 0x8c, 0x79, 0x57, 0x44, 0x1c, 0x46,
0xb4, 0x86, 0x29, 0x38, 0x7b, 0x75, 0x57, 0x59, 0x38, 0xf9, 0xce, 0x45, 0x32, 0xf1, 0x82, 0x08,
0x35, 0xb0, 0x03, 0x5d, 0xc6, 0x03, 0xff, 0x0b, 0xa1, 0xc8, 0xc2, 0x00, 0x1d, 0xc6, 0x3d, 0x3e,
0x65, 0xa8, 0x89, 0x7b, 0xd0, 0x26, 0x61, 0xfc, 0x39, 0x40, 0xad, 0x2a, 0xc6, 0x8f, 0xc3, 0xd0,
0x8b, 0x2e, 0x91, 0x8d, 0xff, 0x87, 0xff, 0x36, 0x40, 0x50, 0xf2, 0x75, 0x4a, 0x18, 0x47, 0xed,
0x8b, 0x1e, 0x74, 0x0b, 0xb9, 0x7e, 0xc8, 0xe5, 0x6c, 0xf8, 0xab, 0x09, 0x6f, 0xbc, 0xa2, 0x78,
0x58, 0xa4, 0x52, 0x2f, 0xf2, 0x2c, 0x54, 0x5a, 0xce, 0xa4, 0x96, 0xdb, 0x9d, 0x3a, 0x83, 0x5e,
0xb9, 0xb8, 0xcb, 0xa4, 0x7e, 0x5c, 0x29, 0xb3, 0x57, 0x7d, 0xba, 0x23, 0xb0, 0xfb, 0xa4, 0x63,
0x36, 0xab, 0x4f, 0xb7, 0x10, 0xb3, 0xbf, 0xc6, 0xdd, 0x32, 0x83, 0x7a, 0xbf, 0xf3, 0xf9, 0xf9,
0x9c, 0xcf, 0x4e, 0x7f, 0xb8, 0x3e, 0x9c, 0x00, 0x82, 0xbe, 0xf1, 0x66, 0x63, 0x25, 0x6a, 0xd4,
0xcd, 0x46, 0xdc, 0xf3, 0xf9, 0x53, 0xb3, 0x16, 0x7e, 0x09, 0xa7, 0x21, 0x09, 0x2f, 0x08, 0x65,
0xd7, 0x41, 0x22, 0xa6, 0xc9, 0xa5, 0xc7, 0x09, 0x6a, 0x56, 0x74, 0xe2, 0x05, 0x54, 0x04, 0x11,
0xe3, 0xde, 0x64, 0xe2, 0xf1, 0x20, 0x8e, 0x50, 0xab, 0xa2, 0xd9, 0x4d, 0xe4, 0x1f, 0xd2, 0xf6,
0x6d, 0xc7, 0x14, 0xfe, 0xe1, 0x4f, 0x00, 0x00, 0x00, 0xff, 0xff, 0xf6, 0xa4, 0x11, 0xfe, 0xc7,
0x03, 0x00, 0x00,
}

View file

@ -0,0 +1,70 @@
syntax = "proto3";
package protobuf;
message StickerMessage {
string hash = 1;
int32 pack = 2;
}
message ChatMessage {
// Lamport timestamp of the chat message
uint64 clock = 1;
// Unix timestamps in milliseconds, currently not used as we use whisper as more reliable, but here
// so that we don't rely on it
uint64 timestamp = 2;
// Text of the message
string text = 3;
// Id of the message that we are replying to
string response_to = 4;
// Ens name of the sender
string ens_name = 5;
// Chat id, this field is symmetric for public-chats and private group chats,
// but asymmetric in case of one-to-ones, as the sender will use the chat-id
// of the received, while the receiver will use the chat-id of the sender.
// Probably should be the concatenation of sender-pk & receiver-pk in alphabetical order
string chat_id = 6;
// The type of message (public/one-to-one/private-group-chat)
MessageType message_type = 7;
// The type of the content of the message
ContentType content_type = 8;
oneof payload {
StickerMessage sticker = 9;
}
enum MessageType {
ONE_TO_ONE = 0;
PUBLIC_GROUP = 1;
PRIVATE_GROUP = 2;
// Only local
SYSTEM_MESSAGE_PRIVATE_GROUP = 3;
}
enum ContentType {
TEXT_PLAIN = 0;
STICKER = 1;
STATUS = 2;
EMOJI = 3;
COMMAND = 4;
COMMAND_REQUEST = 5;
}
}
message ApplicationMetadataMessage {
// Signature of the payload field
bytes signature = 1;
// This is the encoded protobuf of the application level message, i.e ChatMessage
bytes payload = 2;
// The type of protobuf message sent
MessageType message_type = 3;
enum MessageType {
TEXT_MESSAGE = 0;
CONTACT_REQUEST = 1;
MEMBERSHIP_UPDATE = 2;
PAIR_INSTALLATION = 3;
SYNC_INSTALLATION = 4;
}
}

View file

@ -0,0 +1,22 @@
package protobuf
import (
"crypto/ecdsa"
"github.com/status-im/status-go/eth-node/crypto"
)
func (m *ApplicationMetadataMessage) RecoverKey() (*ecdsa.PublicKey, error) {
if m.Signature == nil {
return nil, nil
}
recoveredKey, err := crypto.SigToPub(
crypto.Keccak256(m.Payload),
m.Signature,
)
if err != nil {
return nil, err
}
return recoveredKey, nil
}

View file

@ -0,0 +1,17 @@
package protobuf
import (
"github.com/golang/protobuf/proto"
)
//go:generate protoc --go_out=. ./message.proto
func Unmarshal(payload []byte) (*ApplicationMetadataMessage, error) {
var message ApplicationMetadataMessage
err := proto.Unmarshal(payload, &message)
if err != nil {
return nil, err
}
return &message, nil
}

View file

@ -96,14 +96,11 @@ func newFiltersManager(db *sql.DB, w types.Whisper, privateKey *ecdsa.PrivateKey
func (s *filtersManager) Init(
chatIDs []string,
publicKeys []*ecdsa.PublicKey,
genericDiscoveryTopicEnabled bool,
) ([]*Filter, error) {
logger := s.logger.With(zap.String("site", "Init"))
logger.Info("initializing")
s.genericDiscoveryTopicEnabled = genericDiscoveryTopicEnabled
// Load our contact code.
_, err := s.LoadContactCode(&s.privateKey.PublicKey)
if err != nil {
@ -148,7 +145,7 @@ func (s *filtersManager) Init(
}
// DEPRECATED
func (s *filtersManager) InitWithFilters(filters []*Filter, genericDiscoveryTopicEnabled bool) ([]*Filter, error) {
func (s *filtersManager) InitWithFilters(filters []*Filter) ([]*Filter, error) {
var (
chatIDs []string
publicKeys []*ecdsa.PublicKey
@ -166,7 +163,7 @@ func (s *filtersManager) InitWithFilters(filters []*Filter, genericDiscoveryTopi
}
}
return s.Init(chatIDs, publicKeys, genericDiscoveryTopicEnabled)
return s.Init(chatIDs, publicKeys)
}
func (s *filtersManager) Reset() error {
@ -315,8 +312,8 @@ func (s *filtersManager) LoadNegotiated(secret types.NegotiatedSecret) (*Filter,
return chat, nil
}
// LoadDiscovery adds 1-2 discovery filters: one for generic discovery topic (if enabled)
// and one for the personal discovery topic.
// LoadDiscovery adds 1 discovery filter
// for the personal discovery topic.
func (s *filtersManager) LoadDiscovery() ([]*Filter, error) {
s.mutex.Lock()
defer s.mutex.Unlock()
@ -328,12 +325,6 @@ func (s *filtersManager) LoadDiscovery() ([]*Filter, error) {
expectedTopicCount := 1
if s.genericDiscoveryTopicEnabled {
expectedTopicCount = 2
if chat, ok := s.filters[discoveryTopic]; ok {
result = append(result, chat)
}
}
if chat, ok := s.filters[personalDiscoveryTopic]; ok {
result = append(result, chat)
}
@ -365,29 +356,6 @@ func (s *filtersManager) LoadDiscovery() ([]*Filter, error) {
s.filters[personalDiscoveryChat.ChatID] = personalDiscoveryChat
if s.genericDiscoveryTopicEnabled {
// Load generic discovery topic.
discoveryChat := &Filter{
ChatID: discoveryTopic,
Identity: identityStr,
Discovery: true,
Listen: true,
OneToOne: true,
}
discoveryResponse, err = s.addAsymmetric(discoveryChat.ChatID, true)
if err != nil {
return nil, err
}
discoveryChat.Topic = discoveryResponse.Topic
discoveryChat.FilterID = discoveryResponse.FilterID
s.filters[discoveryChat.ChatID] = discoveryChat
return []*Filter{discoveryChat, personalDiscoveryChat}, nil
}
return []*Filter{personalDiscoveryChat}, nil
}

View file

@ -86,7 +86,7 @@ func _1561059285_add_whisper_keysDownSql() (*asset, error) {
return nil, err
}
info := bindataFileInfo{name: "1561059285_add_whisper_keys.down.sql", size: 25, mode: os.FileMode(0644), modTime: time.Unix(1564484687, 0)}
info := bindataFileInfo{name: "1561059285_add_whisper_keys.down.sql", size: 25, mode: os.FileMode(0644), modTime: time.Unix(1574354941, 0)}
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xb9, 0x31, 0x3f, 0xce, 0xfa, 0x44, 0x36, 0x1b, 0xb0, 0xec, 0x5d, 0xb, 0x90, 0xb, 0x21, 0x4f, 0xd5, 0xe5, 0x50, 0xed, 0xc7, 0x43, 0xdf, 0x83, 0xb4, 0x3a, 0xc1, 0x55, 0x2e, 0x53, 0x7c, 0x67}}
return a, nil
}
@ -106,7 +106,7 @@ func _1561059285_add_whisper_keysUpSql() (*asset, error) {
return nil, err
}
info := bindataFileInfo{name: "1561059285_add_whisper_keys.up.sql", size: 112, mode: os.FileMode(0644), modTime: time.Unix(1564484687, 0)}
info := bindataFileInfo{name: "1561059285_add_whisper_keys.up.sql", size: 112, mode: os.FileMode(0644), modTime: time.Unix(1574354941, 0)}
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x25, 0x41, 0xc, 0x92, 0xdd, 0x9e, 0xff, 0x5d, 0xd0, 0x93, 0xe4, 0x24, 0x50, 0x29, 0xcf, 0xc6, 0xf7, 0x49, 0x3c, 0x73, 0xd9, 0x8c, 0xfa, 0xf2, 0xcf, 0xf6, 0x6f, 0xbc, 0x31, 0xe6, 0xf7, 0xe2}}
return a, nil
}
@ -126,7 +126,7 @@ func docGo() (*asset, error) {
return nil, err
}
info := bindataFileInfo{name: "doc.go", size: 373, mode: os.FileMode(0644), modTime: time.Unix(1564484687, 0)}
info := bindataFileInfo{name: "doc.go", size: 373, mode: os.FileMode(0644), modTime: time.Unix(1574354941, 0)}
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x23, 0x6a, 0xc1, 0xce, 0x94, 0xf6, 0xef, 0xf1, 0x97, 0x95, 0xb, 0x35, 0xaf, 0x5f, 0xe7, 0x5f, 0xac, 0x6e, 0xb8, 0xab, 0xba, 0xb5, 0x35, 0x97, 0x22, 0x36, 0x11, 0xce, 0x44, 0xfc, 0xfa, 0xac}}
return a, nil
}
@ -270,9 +270,9 @@ type bintree struct {
}
var _bintree = &bintree{nil, map[string]*bintree{
"1561059285_add_whisper_keys.down.sql": {_1561059285_add_whisper_keysDownSql, map[string]*bintree{}},
"1561059285_add_whisper_keys.up.sql": {_1561059285_add_whisper_keysUpSql, map[string]*bintree{}},
"doc.go": {docGo, map[string]*bintree{}},
"1561059285_add_whisper_keys.down.sql": &bintree{_1561059285_add_whisper_keysDownSql, map[string]*bintree{}},
"1561059285_add_whisper_keys.up.sql": &bintree{_1561059285_add_whisper_keysUpSql, map[string]*bintree{}},
"doc.go": &bintree{docGo, map[string]*bintree{}},
}}
// RestoreAsset restores an asset under the given directory.

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