From 07e46714f0df6de2645b7dd19cd8e520c8c9c47e Mon Sep 17 00:00:00 2001 From: Samuel Hawksby-Robinson Date: Wed, 1 Sep 2021 13:02:18 +0100 Subject: [PATCH] Anon Metrics Broadcast (#2198) * Protobufs and adapters * Added basic anon metric service and config init * Added fibonacci interval incrementer * Added basic Client.Start func and integrated interval incrementer * Added new processed field to app metrics table * Added id column to app metrics table * Added migration clean up * Added appmetrics GetUnprocessed and SetToProcessedByIDs and tests There was a wierd bug where metrics in the db that did not explicitly insert a value would be NULL, so could not be found by . In addition I've added a new primary id field to the app_metrics table so that updates could be done against very specific metric rows. * Updated adaptors and db to handle proto_id I need a way to distinguish individual metric items from each other so that I can ignore the ones that have been seen before. * Moved incrementer into dedicated file * Resolve incrementer test fail * Finalised the main loop functionality * Implemented delete loop framework * Updated adaptors file name * Added delete loop delay and quit, and tweak on RawMessage gen * Completed delete loop logic * Added DBLock to prevent deletion during mainLoop * Added postgres DB connection, integrated into anonmetrics.Server * Removed proto_id from SQL migration and model * Integrated postgres with Server and updated adaptors * Function name update * Added sample config files for client and server * Fixes and testing for low level e2e * make generate * Fix lint * Fix for receiving an anonMetricBatch not in server mode * Postgres test fixes * Tidy up, make vendor and make generate * delinting * Fixing database tests * Attempted fix of does: cannot open `does' (No such file or directory) not: cannot open `not' (No such file or directory) exist: cannot open `exist' (No such file or directory) error on sql resource loas * Moved all anon metric postgres migration logic and sources into a the protocol/anonmetrics package or sub packages. I don't know if this will fix the does: cannot open `does' (No such file or directory) not: cannot open `not' (No such file or directory) exist: cannot open `exist' (No such file or directory) error that happens in Jenkins but this could work * Lint for the lint god * Why doesn't the linter list all its problems at once? * test tweaks * Fix for wakuV2 change * DB reset change * Fix for postgres db migrations fails * More robust implementation of postgres test setup and teardown * Added block for anon metrics functionality * Version Bump to 0.84.0 * Added test to check anon metrics broadcast is deactivated * Protobufs and adapters * Added basic anon metric service and config init * Added new processed field to app metrics table * Added id column to app metrics table * Added migration clean up * Added appmetrics GetUnprocessed and SetToProcessedByIDs and tests There was a wierd bug where metrics in the db that did not explicitly insert a value would be NULL, so could not be found by . In addition I've added a new primary id field to the app_metrics table so that updates could be done against very specific metric rows. * Updated adaptors and db to handle proto_id I need a way to distinguish individual metric items from each other so that I can ignore the ones that have been seen before. * Added postgres DB connection, integrated into anonmetrics.Server * Removed proto_id from SQL migration and model * Integrated postgres with Server and updated adaptors * Added sample config files for client and server * Fix lint * Fix for receiving an anonMetricBatch not in server mode * Postgres test fixes * Tidy up, make vendor and make generate * Moved all anon metric postgres migration logic and sources into a the protocol/anonmetrics package or sub packages. I don't know if this will fix the does: cannot open `does' (No such file or directory) not: cannot open `not' (No such file or directory) exist: cannot open `exist' (No such file or directory) error that happens in Jenkins but this could work --- VERSION | 2 +- appdatabase/migrations/bindata.go | 112 ++-- .../1629123384_add_id_to_app_metrics.up.sql | 14 + appmetrics/database.go | 166 +++++- appmetrics/database_test.go | 116 +++++ appmetrics/test_helpers.go | 21 + config/cli/anon-metric-node-client.json | 31 ++ config/cli/anon-metric-node-server.json | 30 ++ mailserver/mailserver_db_postgres.go | 4 +- mailserver/mailserver_db_postgres_test.go | 74 ++- multiaccounts/migrations/bindata.go | 14 +- params/config.go | 9 + postgres/helpers.go | 27 + protocol/anon_metrics_test.go | 209 ++++++++ protocol/anonmetrics/adaptors.go | 89 ++++ protocol/anonmetrics/client.go | 231 +++++++++ protocol/anonmetrics/interval_incrementer.go | 15 + .../anonmetrics/interval_incrementer_test.go | 21 + protocol/anonmetrics/migrations/migrations.go | 319 ++++++++++++ ..._postgres_make_anon_metrics_table.down.sql | 1 + ...65_postgres_make_anon_metrics_table.up.sql | 15 + .../anonmetrics/migrations/postgres/doc.go | 9 + protocol/anonmetrics/server.go | 189 +++++++ protocol/messenger.go | 66 +++ protocol/messenger_config.go | 18 + protocol/messenger_handler.go | 6 + protocol/messenger_response.go | 2 + protocol/migrations/migrations.go | 486 ++++++++++-------- protocol/protobuf/anon_metrics.pb.go | 188 +++++++ protocol/protobuf/anon_metrics.proto | 36 ++ .../application_metadata_message.pb.go | 79 +-- .../application_metadata_message.proto | 1 + protocol/protobuf/service.go | 2 +- protocol/transport/migrations/migrations.go | 4 +- protocol/v1/status_message.go | 2 + services/ext/service.go | 36 ++ static/bindata.go | 267 +++++++--- 37 files changed, 2489 insertions(+), 422 deletions(-) create mode 100644 appdatabase/migrations/sql/1629123384_add_id_to_app_metrics.up.sql create mode 100644 appmetrics/test_helpers.go create mode 100644 config/cli/anon-metric-node-client.json create mode 100644 config/cli/anon-metric-node-server.json create mode 100644 postgres/helpers.go create mode 100644 protocol/anon_metrics_test.go create mode 100644 protocol/anonmetrics/adaptors.go create mode 100644 protocol/anonmetrics/client.go create mode 100644 protocol/anonmetrics/interval_incrementer.go create mode 100644 protocol/anonmetrics/interval_incrementer_test.go create mode 100644 protocol/anonmetrics/migrations/migrations.go create mode 100644 protocol/anonmetrics/migrations/postgres/1619446565_postgres_make_anon_metrics_table.down.sql create mode 100644 protocol/anonmetrics/migrations/postgres/1619446565_postgres_make_anon_metrics_table.up.sql create mode 100644 protocol/anonmetrics/migrations/postgres/doc.go create mode 100644 protocol/anonmetrics/server.go create mode 100644 protocol/protobuf/anon_metrics.pb.go create mode 100644 protocol/protobuf/anon_metrics.proto diff --git a/VERSION b/VERSION index b4a141dc3..63cd8847a 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -0.85.1 +0.86.0 diff --git a/appdatabase/migrations/bindata.go b/appdatabase/migrations/bindata.go index 486c2ccd2..91fd2375a 100644 --- a/appdatabase/migrations/bindata.go +++ b/appdatabase/migrations/bindata.go @@ -42,6 +42,7 @@ // 1625872445_user_status.up.sql (351B) // 1627983977_add_gif_to_settings.up.sql (102B) // 1628580203_add_hidden_account.up.sql (67B) +// 1629123384_add_id_to_app_metrics.up.sql (589B) // doc.go (74B) package migrations @@ -126,7 +127,7 @@ func _0001_appDownSql() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "0001_app.down.sql", size: 356, mode: os.FileMode(0644), modTime: time.Unix(1596451065, 0)} + info := bindataFileInfo{name: "0001_app.down.sql", size: 356, mode: os.FileMode(0644), modTime: time.Unix(1589413297, 0)} a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xb5, 0x25, 0xa0, 0xf8, 0x7d, 0x2d, 0xd, 0xcf, 0x18, 0xe4, 0x73, 0xc3, 0x95, 0xf5, 0x24, 0x20, 0xa9, 0xe6, 0x9e, 0x1d, 0x93, 0xe5, 0xc5, 0xad, 0x93, 0x8f, 0x5e, 0x40, 0xb5, 0x30, 0xaa, 0x25}} return a, nil } @@ -146,7 +147,7 @@ func _0001_appUpSql() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "0001_app.up.sql", size: 2967, mode: os.FileMode(0644), modTime: time.Unix(1596451065, 0)} + info := bindataFileInfo{name: "0001_app.up.sql", size: 2967, mode: os.FileMode(0644), modTime: time.Unix(1589413297, 0)} a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xf7, 0x3a, 0xa7, 0xf2, 0x8f, 0xfa, 0x82, 0x7c, 0xc5, 0x49, 0xac, 0xac, 0xf, 0xc, 0x77, 0xe2, 0xba, 0xe8, 0x4d, 0xe, 0x6f, 0x5d, 0x2c, 0x2c, 0x18, 0x80, 0xc2, 0x1d, 0xe, 0x25, 0xe, 0x18}} return a, nil } @@ -166,7 +167,7 @@ func _0002_tokensDownSql() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "0002_tokens.down.sql", size: 19, mode: os.FileMode(0644), modTime: time.Unix(1596451065, 0)} + info := bindataFileInfo{name: "0002_tokens.down.sql", size: 19, mode: os.FileMode(0644), modTime: time.Unix(1585751575, 0)} a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xd1, 0x31, 0x2, 0xcc, 0x2f, 0x38, 0x90, 0xf7, 0x58, 0x37, 0x47, 0xf4, 0x18, 0xf7, 0x72, 0x74, 0x67, 0x14, 0x7e, 0xf3, 0xb1, 0xd6, 0x5f, 0xb0, 0xd5, 0xe7, 0x91, 0xf4, 0x26, 0x77, 0x8e, 0x68}} return a, nil } @@ -186,7 +187,7 @@ func _0002_tokensUpSql() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "0002_tokens.up.sql", size: 248, mode: os.FileMode(0644), modTime: time.Unix(1596451065, 0)} + info := bindataFileInfo{name: "0002_tokens.up.sql", size: 248, mode: os.FileMode(0644), modTime: time.Unix(1585751575, 0)} a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xcc, 0xd6, 0xde, 0xd3, 0x7b, 0xee, 0x92, 0x11, 0x38, 0xa4, 0xeb, 0x84, 0xca, 0xcb, 0x37, 0x75, 0x5, 0x77, 0x7f, 0x14, 0x39, 0xee, 0xa1, 0x8b, 0xd4, 0x5c, 0x6e, 0x55, 0x6, 0x50, 0x16, 0xd4}} return a, nil } @@ -206,7 +207,7 @@ func _0003_settingsDownSql() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "0003_settings.down.sql", size: 118, mode: os.FileMode(0644), modTime: time.Unix(1596451065, 0)} + info := bindataFileInfo{name: "0003_settings.down.sql", size: 118, mode: os.FileMode(0644), modTime: time.Unix(1585751575, 0)} a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xe5, 0xa6, 0xf5, 0xc0, 0x60, 0x64, 0x77, 0xe2, 0xe7, 0x3c, 0x9b, 0xb1, 0x52, 0xa9, 0x95, 0x16, 0xf8, 0x60, 0x2f, 0xa5, 0xeb, 0x46, 0xb9, 0xb9, 0x8f, 0x4c, 0xf4, 0xfd, 0xbb, 0xe7, 0xe5, 0xe5}} return a, nil } @@ -226,7 +227,7 @@ func _0003_settingsUpSql() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "0003_settings.up.sql", size: 1311, mode: os.FileMode(0644), modTime: time.Unix(1596451065, 0)} + info := bindataFileInfo{name: "0003_settings.up.sql", size: 1311, mode: os.FileMode(0644), modTime: time.Unix(1585751575, 0)} a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xea, 0x35, 0x0, 0xeb, 0xe2, 0x33, 0x68, 0xb9, 0xf4, 0xf6, 0x8e, 0x9e, 0x10, 0xe9, 0x58, 0x68, 0x28, 0xb, 0xcd, 0xec, 0x74, 0x71, 0xa7, 0x9a, 0x5a, 0x77, 0x59, 0xb1, 0x13, 0x1c, 0xa1, 0x5b}} return a, nil } @@ -246,7 +247,7 @@ func _0004_pending_stickersDownSql() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "0004_pending_stickers.down.sql", size: 0, mode: os.FileMode(0644), modTime: time.Unix(1596451065, 0)} + info := bindataFileInfo{name: "0004_pending_stickers.down.sql", size: 0, mode: os.FileMode(0644), modTime: time.Unix(1589413297, 0)} a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xe3, 0xb0, 0xc4, 0x42, 0x98, 0xfc, 0x1c, 0x14, 0x9a, 0xfb, 0xf4, 0xc8, 0x99, 0x6f, 0xb9, 0x24, 0x27, 0xae, 0x41, 0xe4, 0x64, 0x9b, 0x93, 0x4c, 0xa4, 0x95, 0x99, 0x1b, 0x78, 0x52, 0xb8, 0x55}} return a, nil } @@ -266,7 +267,7 @@ func _0004_pending_stickersUpSql() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "0004_pending_stickers.up.sql", size: 61, mode: os.FileMode(0644), modTime: time.Unix(1596451065, 0)} + info := bindataFileInfo{name: "0004_pending_stickers.up.sql", size: 61, mode: os.FileMode(0644), modTime: time.Unix(1589413297, 0)} a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x3c, 0xed, 0x25, 0xdf, 0x75, 0x2, 0x6c, 0xf0, 0xa2, 0xa8, 0x37, 0x62, 0x65, 0xad, 0xfd, 0x98, 0xa0, 0x9d, 0x63, 0x94, 0xdf, 0x6b, 0x46, 0xe0, 0x68, 0xec, 0x9c, 0x7f, 0x77, 0xdd, 0xb3, 0x6}} return a, nil } @@ -286,7 +287,7 @@ func _0005_waku_modeDownSql() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "0005_waku_mode.down.sql", size: 0, mode: os.FileMode(0644), modTime: time.Unix(1596451065, 0)} + info := bindataFileInfo{name: "0005_waku_mode.down.sql", size: 0, mode: os.FileMode(0644), modTime: time.Unix(1589413297, 0)} a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xe3, 0xb0, 0xc4, 0x42, 0x98, 0xfc, 0x1c, 0x14, 0x9a, 0xfb, 0xf4, 0xc8, 0x99, 0x6f, 0xb9, 0x24, 0x27, 0xae, 0x41, 0xe4, 0x64, 0x9b, 0x93, 0x4c, 0xa4, 0x95, 0x99, 0x1b, 0x78, 0x52, 0xb8, 0x55}} return a, nil } @@ -306,7 +307,7 @@ func _0005_waku_modeUpSql() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "0005_waku_mode.up.sql", size: 146, mode: os.FileMode(0644), modTime: time.Unix(1596451065, 0)} + info := bindataFileInfo{name: "0005_waku_mode.up.sql", size: 146, mode: os.FileMode(0644), modTime: time.Unix(1589413297, 0)} a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xa6, 0x91, 0xc, 0xd7, 0x89, 0x61, 0x2e, 0x4c, 0x5a, 0xb6, 0x67, 0xd1, 0xc1, 0x42, 0x24, 0x38, 0xd6, 0x1b, 0x75, 0x41, 0x9c, 0x23, 0xb0, 0xca, 0x5c, 0xf1, 0x5c, 0xd0, 0x13, 0x92, 0x3e, 0xe1}} return a, nil } @@ -326,7 +327,7 @@ func _0006_appearanceUpSql() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "0006_appearance.up.sql", size: 67, mode: os.FileMode(0644), modTime: time.Unix(1596451065, 0)} + info := bindataFileInfo{name: "0006_appearance.up.sql", size: 67, mode: os.FileMode(0644), modTime: time.Unix(1621263711, 0)} a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xae, 0x6, 0x25, 0x6c, 0xe4, 0x9d, 0xa7, 0x72, 0xe8, 0xbc, 0xe4, 0x1f, 0x1e, 0x2d, 0x7c, 0xb7, 0xf6, 0xa3, 0xec, 0x3b, 0x4e, 0x93, 0x2e, 0xa4, 0xec, 0x6f, 0xe5, 0x95, 0x94, 0xe8, 0x4, 0xfb}} return a, nil } @@ -346,7 +347,7 @@ func _0007_enable_waku_defaultUpSql() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "0007_enable_waku_default.up.sql", size: 38, mode: os.FileMode(0644), modTime: time.Unix(1596451065, 0)} + info := bindataFileInfo{name: "0007_enable_waku_default.up.sql", size: 38, mode: os.FileMode(0644), modTime: time.Unix(1621263711, 0)} a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xd4, 0x42, 0xb6, 0xe5, 0x48, 0x41, 0xeb, 0xc0, 0x7e, 0x3b, 0xe6, 0x8e, 0x96, 0x33, 0x20, 0x92, 0x24, 0x5a, 0x60, 0xfa, 0xa0, 0x3, 0x5e, 0x76, 0x4b, 0x89, 0xaa, 0x37, 0x66, 0xbc, 0x26, 0x11}} return a, nil } @@ -366,7 +367,7 @@ func _0008_add_push_notificationsUpSql() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "0008_add_push_notifications.up.sql", size: 349, mode: os.FileMode(0644), modTime: time.Unix(1596451065, 0)} + info := bindataFileInfo{name: "0008_add_push_notifications.up.sql", size: 349, mode: os.FileMode(0644), modTime: time.Unix(1621263711, 0)} a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x5a, 0x0, 0xbf, 0xd0, 0xdd, 0xcd, 0x73, 0xe0, 0x7c, 0x56, 0xef, 0xdc, 0x57, 0x61, 0x94, 0x64, 0x70, 0xb9, 0xfa, 0xa1, 0x2a, 0x36, 0xc, 0x2f, 0xf8, 0x95, 0xa, 0x57, 0x3e, 0x7a, 0xd7, 0x12}} return a, nil } @@ -386,7 +387,7 @@ func _0009_enable_sending_push_notificationsDownSql() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "0009_enable_sending_push_notifications.down.sql", size: 49, mode: os.FileMode(0644), modTime: time.Unix(1599738798, 0)} + info := bindataFileInfo{name: "0009_enable_sending_push_notifications.down.sql", size: 49, mode: os.FileMode(0644), modTime: time.Unix(1621263711, 0)} a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xe9, 0xae, 0x1b, 0x41, 0xcb, 0x9c, 0x2c, 0x93, 0xc6, 0x2a, 0x77, 0x3, 0xb9, 0x51, 0xe0, 0x68, 0x68, 0x0, 0xf7, 0x5b, 0xb3, 0x1e, 0x94, 0x44, 0xba, 0x9c, 0xd0, 0x3b, 0x80, 0x21, 0x6f, 0xb5}} return a, nil } @@ -406,7 +407,7 @@ func _0009_enable_sending_push_notificationsUpSql() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "0009_enable_sending_push_notifications.up.sql", size: 49, mode: os.FileMode(0644), modTime: time.Unix(1599738798, 0)} + info := bindataFileInfo{name: "0009_enable_sending_push_notifications.up.sql", size: 49, mode: os.FileMode(0644), modTime: time.Unix(1621263711, 0)} a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x1b, 0x80, 0xe4, 0x9c, 0xc8, 0xb8, 0xd5, 0xef, 0xce, 0x74, 0x9b, 0x7b, 0xdd, 0xa, 0x99, 0x1e, 0xef, 0x7f, 0xb8, 0x99, 0x84, 0x4, 0x0, 0x6b, 0x1d, 0x2c, 0xa, 0xf8, 0x2c, 0x4f, 0xb5, 0x44}} return a, nil } @@ -426,7 +427,7 @@ func _0010_add_block_mentionsDownSql() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "0010_add_block_mentions.down.sql", size: 83, mode: os.FileMode(0644), modTime: time.Unix(1599738804, 0)} + info := bindataFileInfo{name: "0010_add_block_mentions.down.sql", size: 83, mode: os.FileMode(0644), modTime: time.Unix(1621263711, 0)} a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x6d, 0x9e, 0x27, 0x1e, 0xba, 0x9f, 0xca, 0xae, 0x98, 0x2e, 0x6e, 0xe3, 0xdd, 0xac, 0x73, 0x34, 0x4e, 0x69, 0x92, 0xb5, 0xf6, 0x9, 0xab, 0x50, 0x35, 0xd, 0xee, 0xeb, 0x3e, 0xcc, 0x7e, 0xce}} return a, nil } @@ -446,7 +447,7 @@ func _0010_add_block_mentionsUpSql() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "0010_add_block_mentions.up.sql", size: 89, mode: os.FileMode(0644), modTime: time.Unix(1599738804, 0)} + info := bindataFileInfo{name: "0010_add_block_mentions.up.sql", size: 89, mode: os.FileMode(0644), modTime: time.Unix(1621263711, 0)} a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xd7, 0x23, 0x85, 0xa2, 0xb5, 0xb6, 0xb4, 0x3f, 0xdc, 0x4e, 0xff, 0xe2, 0x6b, 0x66, 0x68, 0x5e, 0xb2, 0xb4, 0x14, 0xb2, 0x1b, 0x4d, 0xb1, 0xce, 0xf7, 0x6, 0x58, 0xa7, 0xaf, 0x93, 0x3f, 0x25}} return a, nil } @@ -466,7 +467,7 @@ func _0011_allow_webview_permission_requestsDownSql() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "0011_allow_webview_permission_requests.down.sql", size: 0, mode: os.FileMode(0644), modTime: time.Unix(1599738804, 0)} + info := bindataFileInfo{name: "0011_allow_webview_permission_requests.down.sql", size: 0, mode: os.FileMode(0644), modTime: time.Unix(1621263711, 0)} a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xe3, 0xb0, 0xc4, 0x42, 0x98, 0xfc, 0x1c, 0x14, 0x9a, 0xfb, 0xf4, 0xc8, 0x99, 0x6f, 0xb9, 0x24, 0x27, 0xae, 0x41, 0xe4, 0x64, 0x9b, 0x93, 0x4c, 0xa4, 0x95, 0x99, 0x1b, 0x78, 0x52, 0xb8, 0x55}} return a, nil } @@ -486,7 +487,7 @@ func _0011_allow_webview_permission_requestsUpSql() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "0011_allow_webview_permission_requests.up.sql", size: 88, mode: os.FileMode(0644), modTime: time.Unix(1599738804, 0)} + info := bindataFileInfo{name: "0011_allow_webview_permission_requests.up.sql", size: 88, mode: os.FileMode(0644), modTime: time.Unix(1621263711, 0)} a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x43, 0x5f, 0x22, 0x4c, 0x98, 0x1d, 0xc6, 0xf4, 0x89, 0xaf, 0xf4, 0x44, 0xba, 0xf8, 0x28, 0xa7, 0xb5, 0xb9, 0xf0, 0xf2, 0xcb, 0x5, 0x59, 0x7a, 0xc, 0xdf, 0xd3, 0x38, 0xa4, 0xb8, 0x98, 0xc2}} return a, nil } @@ -506,7 +507,7 @@ func _0012_pending_transactionsDownSql() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "0012_pending_transactions.down.sql", size: 33, mode: os.FileMode(0644), modTime: time.Unix(1602496703, 0)} + info := bindataFileInfo{name: "0012_pending_transactions.down.sql", size: 33, mode: os.FileMode(0644), modTime: time.Unix(1621263711, 0)} a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x7e, 0x41, 0xfe, 0x5c, 0xd8, 0xc3, 0x29, 0xfd, 0x31, 0x78, 0x99, 0x7a, 0xeb, 0x17, 0x62, 0x88, 0x41, 0xb3, 0xe7, 0xb5, 0x5, 0x0, 0x90, 0xa1, 0x7, 0x1a, 0x23, 0x88, 0x81, 0xba, 0x56, 0x9d}} return a, nil } @@ -526,7 +527,7 @@ func _0012_pending_transactionsUpSql() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "0012_pending_transactions.up.sql", size: 321, mode: os.FileMode(0644), modTime: time.Unix(1602496703, 0)} + info := bindataFileInfo{name: "0012_pending_transactions.up.sql", size: 321, mode: os.FileMode(0644), modTime: time.Unix(1621263711, 0)} a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xd, 0x17, 0xff, 0xd7, 0xa7, 0x49, 0x1e, 0x7b, 0x34, 0x63, 0x7c, 0x53, 0xaa, 0x6b, 0x2d, 0xc8, 0xe0, 0x82, 0x21, 0x90, 0x3a, 0x94, 0xf1, 0xa6, 0xe4, 0x70, 0xe5, 0x85, 0x1a, 0x48, 0x25, 0xb}} return a, nil } @@ -546,7 +547,7 @@ func _0013_favouritesDownSql() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "0013_favourites.down.sql", size: 23, mode: os.FileMode(0644), modTime: time.Unix(1602496703, 0)} + info := bindataFileInfo{name: "0013_favourites.down.sql", size: 23, mode: os.FileMode(0644), modTime: time.Unix(1621263711, 0)} a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x32, 0xf8, 0x55, 0x13, 0x4f, 0x4a, 0x19, 0x83, 0x9c, 0xda, 0x34, 0xb8, 0x3, 0x54, 0x82, 0x1e, 0x99, 0x36, 0x6b, 0x42, 0x3, 0xf6, 0x43, 0xde, 0xe6, 0x32, 0xb6, 0xdf, 0xe2, 0x59, 0x8c, 0x84}} return a, nil } @@ -566,7 +567,7 @@ func _0013_favouritesUpSql() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "0013_favourites.up.sql", size: 132, mode: os.FileMode(0644), modTime: time.Unix(1602496703, 0)} + info := bindataFileInfo{name: "0013_favourites.up.sql", size: 132, mode: os.FileMode(0644), modTime: time.Unix(1621263711, 0)} a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xbe, 0x1, 0x27, 0x38, 0x76, 0xf5, 0xcb, 0x61, 0xda, 0x5b, 0xce, 0xd9, 0x8b, 0x18, 0x77, 0x61, 0x84, 0xe7, 0x22, 0xe2, 0x13, 0x99, 0xab, 0x32, 0xbc, 0xbe, 0xed, 0x1f, 0x2f, 0xb0, 0xe4, 0x8d}} return a, nil } @@ -586,7 +587,7 @@ func _0014_add_use_mailserversDownSql() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "0014_add_use_mailservers.down.sql", size: 0, mode: os.FileMode(0644), modTime: time.Unix(1603197658, 0)} + info := bindataFileInfo{name: "0014_add_use_mailservers.down.sql", size: 0, mode: os.FileMode(0644), modTime: time.Unix(1621263711, 0)} a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xe3, 0xb0, 0xc4, 0x42, 0x98, 0xfc, 0x1c, 0x14, 0x9a, 0xfb, 0xf4, 0xc8, 0x99, 0x6f, 0xb9, 0x24, 0x27, 0xae, 0x41, 0xe4, 0x64, 0x9b, 0x93, 0x4c, 0xa4, 0x95, 0x99, 0x1b, 0x78, 0x52, 0xb8, 0x55}} return a, nil } @@ -606,7 +607,7 @@ func _0014_add_use_mailserversUpSql() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "0014_add_use_mailservers.up.sql", size: 111, mode: os.FileMode(0644), modTime: time.Unix(1603197658, 0)} + info := bindataFileInfo{name: "0014_add_use_mailservers.up.sql", size: 111, mode: os.FileMode(0644), modTime: time.Unix(1621263711, 0)} a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xc9, 0xba, 0x65, 0xbf, 0x1b, 0xc9, 0x6d, 0x45, 0xf2, 0xf5, 0x30, 0x7c, 0xc1, 0xde, 0xb8, 0xe3, 0x3f, 0xa9, 0x2f, 0x9f, 0xea, 0x1, 0x29, 0x29, 0x65, 0xe7, 0x38, 0xab, 0xa4, 0x62, 0xf, 0xd0}} return a, nil } @@ -626,7 +627,7 @@ func _0015_link_previewsDownSql() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "0015_link_previews.down.sql", size: 0, mode: os.FileMode(0644), modTime: time.Unix(1604300676, 0)} + info := bindataFileInfo{name: "0015_link_previews.down.sql", size: 0, mode: os.FileMode(0644), modTime: time.Unix(1621263711, 0)} a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xe3, 0xb0, 0xc4, 0x42, 0x98, 0xfc, 0x1c, 0x14, 0x9a, 0xfb, 0xf4, 0xc8, 0x99, 0x6f, 0xb9, 0x24, 0x27, 0xae, 0x41, 0xe4, 0x64, 0x9b, 0x93, 0x4c, 0xa4, 0x95, 0x99, 0x1b, 0x78, 0x52, 0xb8, 0x55}} return a, nil } @@ -646,7 +647,7 @@ func _0015_link_previewsUpSql() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "0015_link_previews.up.sql", size: 203, mode: os.FileMode(0644), modTime: time.Unix(1604300676, 0)} + info := bindataFileInfo{name: "0015_link_previews.up.sql", size: 203, mode: os.FileMode(0644), modTime: time.Unix(1621263711, 0)} a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xb1, 0xf7, 0x38, 0x25, 0xa6, 0xfc, 0x6b, 0x9, 0xe4, 0xd9, 0xbf, 0x58, 0x7b, 0x80, 0xd8, 0x48, 0x63, 0xde, 0xa5, 0x5e, 0x30, 0xa3, 0xeb, 0x68, 0x8e, 0x6a, 0x9f, 0xfd, 0xf4, 0x46, 0x41, 0x34}} return a, nil } @@ -666,7 +667,7 @@ func _0016_local_notifications_preferencesDownSql() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "0016_local_notifications_preferences.down.sql", size: 43, mode: os.FileMode(0644), modTime: time.Unix(1604300676, 0)} + info := bindataFileInfo{name: "0016_local_notifications_preferences.down.sql", size: 43, mode: os.FileMode(0644), modTime: time.Unix(1621263711, 0)} a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xe0, 0x50, 0xc7, 0xdd, 0x53, 0x9c, 0x5d, 0x1e, 0xb5, 0x71, 0x25, 0x50, 0x58, 0xcf, 0x6d, 0xbe, 0x5a, 0x8, 0x12, 0xc9, 0x13, 0xd, 0x9a, 0x3d, 0x4b, 0x7a, 0x2f, 0x1b, 0xe5, 0x23, 0x52, 0x78}} return a, nil } @@ -686,7 +687,7 @@ func _0016_local_notifications_preferencesUpSql() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "0016_local_notifications_preferences.up.sql", size: 204, mode: os.FileMode(0644), modTime: time.Unix(1604300676, 0)} + info := bindataFileInfo{name: "0016_local_notifications_preferences.up.sql", size: 204, mode: os.FileMode(0644), modTime: time.Unix(1621263711, 0)} a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x3f, 0x3a, 0x16, 0x25, 0xdf, 0xba, 0x62, 0xd3, 0x81, 0x73, 0xc, 0x10, 0x85, 0xbc, 0x8d, 0xe, 0x1d, 0x62, 0xcb, 0xb, 0x6d, 0x8c, 0x4f, 0x63, 0x5f, 0xe2, 0xd, 0xc5, 0x46, 0xa8, 0x35, 0x5b}} return a, nil } @@ -706,7 +707,7 @@ func _0017_bookmarksDownSql() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "0017_bookmarks.down.sql", size: 22, mode: os.FileMode(0644), modTime: time.Unix(1605792189, 0)} + info := bindataFileInfo{name: "0017_bookmarks.down.sql", size: 22, mode: os.FileMode(0644), modTime: time.Unix(1621263711, 0)} a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x9a, 0x13, 0x2a, 0x44, 0xb0, 0x3, 0x18, 0x63, 0xb8, 0x33, 0xda, 0x3a, 0xeb, 0xb8, 0xcb, 0xd1, 0x98, 0x29, 0xa7, 0xf0, 0x6, 0x9d, 0xc9, 0x62, 0xe7, 0x89, 0x7f, 0x77, 0xaf, 0xec, 0x6b, 0x8f}} return a, nil } @@ -726,7 +727,7 @@ func _0017_bookmarksUpSql() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "0017_bookmarks.up.sql", size: 147, mode: os.FileMode(0644), modTime: time.Unix(1605792189, 0)} + info := bindataFileInfo{name: "0017_bookmarks.up.sql", size: 147, mode: os.FileMode(0644), modTime: time.Unix(1621263711, 0)} a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xbc, 0x47, 0xe1, 0xe3, 0xd8, 0xc6, 0x4, 0x6d, 0x5f, 0x2f, 0xa, 0x51, 0xa6, 0x8c, 0x6a, 0xe0, 0x3d, 0x8c, 0x91, 0x47, 0xbc, 0x1, 0x75, 0x46, 0x92, 0x2, 0x18, 0x6e, 0xe3, 0x4f, 0x18, 0x57}} return a, nil } @@ -746,7 +747,7 @@ func _0018_profile_pictures_visibilityUpSql() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "0018_profile_pictures_visibility.up.sql", size: 84, mode: os.FileMode(0644), modTime: time.Unix(1611143707, 0)} + info := bindataFileInfo{name: "0018_profile_pictures_visibility.up.sql", size: 84, mode: os.FileMode(0644), modTime: time.Unix(1621263711, 0)} a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xc9, 0xe3, 0xc5, 0xec, 0x83, 0x55, 0x45, 0x57, 0x7a, 0xaa, 0xd2, 0xa7, 0x59, 0xa7, 0x87, 0xef, 0x63, 0x19, 0x9c, 0x46, 0x9c, 0xc5, 0x32, 0x89, 0xa4, 0x68, 0x70, 0xd8, 0x83, 0x43, 0xa4, 0x72}} return a, nil } @@ -766,7 +767,7 @@ func _0019_blocks_ranges_extra_dataUpSql() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "0019_blocks_ranges_extra_data.up.sql", size: 89, mode: os.FileMode(0644), modTime: time.Unix(1628496699, 0)} + info := bindataFileInfo{name: "0019_blocks_ranges_extra_data.up.sql", size: 89, mode: os.FileMode(0644), modTime: time.Unix(1621263711, 0)} a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xa3, 0x96, 0x32, 0x58, 0xf0, 0xb9, 0xe1, 0x70, 0x81, 0xca, 0x8d, 0x45, 0x57, 0x8a, 0x7, 0x5d, 0x9e, 0x2a, 0x30, 0xb, 0xad, 0x5f, 0xf8, 0xd4, 0x30, 0x94, 0x73, 0x37, 0x8d, 0xc1, 0x9a, 0xed}} return a, nil } @@ -786,7 +787,7 @@ func _0020_metricsUpSql() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "0020_metrics.up.sql", size: 235, mode: os.FileMode(0644), modTime: time.Unix(1628496699, 0)} + info := bindataFileInfo{name: "0020_metrics.up.sql", size: 235, mode: os.FileMode(0644), modTime: time.Unix(1621263711, 0)} a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xe8, 0x32, 0xbc, 0xb6, 0x9b, 0x5a, 0x8f, 0x9f, 0x4c, 0x90, 0x81, 0x3e, 0x2e, 0xd1, 0x23, 0xcd, 0xf1, 0x83, 0x35, 0xca, 0x66, 0x87, 0x52, 0x4e, 0x30, 0x3e, 0x4f, 0xa8, 0xfd, 0x30, 0x16, 0xbd}} return a, nil } @@ -806,7 +807,7 @@ func _0021_add_session_id_to_metricsUpSql() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "0021_add_session_id_to_metrics.up.sql", size: 55, mode: os.FileMode(0644), modTime: time.Unix(1628496699, 0)} + info := bindataFileInfo{name: "0021_add_session_id_to_metrics.up.sql", size: 55, mode: os.FileMode(0644), modTime: time.Unix(1621263711, 0)} a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xb7, 0x81, 0xfc, 0x97, 0xd1, 0x8b, 0xea, 0x8e, 0xd7, 0xc2, 0x53, 0x62, 0xe9, 0xbc, 0xf, 0x8c, 0x46, 0x41, 0x41, 0xb7, 0x6, 0x35, 0xf5, 0xba, 0xbb, 0x28, 0x50, 0x48, 0xbf, 0x36, 0x90, 0x5c}} return a, nil } @@ -826,7 +827,7 @@ func _0022_pending_transfersUpSql() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "0022_pending_transfers.up.sql", size: 706, mode: os.FileMode(0644), modTime: time.Unix(1628496699, 0)} + info := bindataFileInfo{name: "0022_pending_transfers.up.sql", size: 706, mode: os.FileMode(0644), modTime: time.Unix(1621263711, 0)} a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x6a, 0x9, 0xe6, 0x6, 0xae, 0x60, 0xdd, 0xbb, 0x76, 0xac, 0xe0, 0x57, 0x30, 0x67, 0x37, 0x93, 0x40, 0x13, 0xec, 0xf2, 0x6e, 0x61, 0xa, 0x14, 0xb2, 0xb1, 0xbd, 0x91, 0xf8, 0x89, 0xb3, 0xe3}} return a, nil } @@ -846,7 +847,7 @@ func _1618237885_settings_anon_metrics_should_sendUpSql() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "1618237885_settings_anon_metrics_should_send.up.sql", size: 80, mode: os.FileMode(0644), modTime: time.Unix(1628496699, 0)} + info := bindataFileInfo{name: "1618237885_settings_anon_metrics_should_send.up.sql", size: 80, mode: os.FileMode(0644), modTime: time.Unix(1621263711, 0)} a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xea, 0x6c, 0x1d, 0x1f, 0x54, 0x62, 0x18, 0x22, 0x5c, 0xa7, 0x8c, 0x59, 0x24, 0xd3, 0x4d, 0x55, 0xc4, 0x2a, 0x9e, 0x4c, 0x37, 0x6b, 0xfd, 0xac, 0xec, 0xb7, 0x68, 0x21, 0x26, 0x26, 0xf3, 0x92}} return a, nil } @@ -866,7 +867,7 @@ func _1618395756_contacts_onlyUpSql() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "1618395756_contacts_only.up.sql", size: 136, mode: os.FileMode(0644), modTime: time.Unix(1628496699, 0)} + info := bindataFileInfo{name: "1618395756_contacts_only.up.sql", size: 136, mode: os.FileMode(0644), modTime: time.Unix(1621263711, 0)} a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x1, 0xe3, 0xd0, 0xe7, 0xf2, 0x6e, 0xbf, 0x27, 0xf6, 0xe2, 0x2e, 0x16, 0x4b, 0x52, 0x3b, 0xcf, 0x63, 0x52, 0xfc, 0x1d, 0x43, 0xba, 0x42, 0xf9, 0x1e, 0x1e, 0x39, 0x40, 0xed, 0x0, 0x20, 0xa8}} return a, nil } @@ -886,7 +887,7 @@ func _1622184614_add_default_sync_periodUpSql() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "1622184614_add_default_sync_period.up.sql", size: 125, mode: os.FileMode(0644), modTime: time.Unix(1628496699, 0)} + info := bindataFileInfo{name: "1622184614_add_default_sync_period.up.sql", size: 125, mode: os.FileMode(0644), modTime: time.Unix(1623331301, 0)} a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x60, 0x39, 0xeb, 0x8f, 0xdc, 0x1, 0x56, 0xc1, 0x9b, 0xaa, 0xda, 0x44, 0xe0, 0xdb, 0xda, 0x2c, 0xe7, 0x71, 0x8d, 0xbc, 0xc1, 0x9a, 0x4f, 0x48, 0xe0, 0x5e, 0x81, 0x1e, 0x8e, 0x6a, 0x4d, 0x3}} return a, nil } @@ -906,7 +907,7 @@ func _1625872445_user_statusUpSql() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "1625872445_user_status.up.sql", size: 351, mode: os.FileMode(0644), modTime: time.Unix(1628496699, 0)} + info := bindataFileInfo{name: "1625872445_user_status.up.sql", size: 351, mode: os.FileMode(0644), modTime: time.Unix(1628714143, 0)} a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xf5, 0xa, 0xfe, 0x7a, 0xcc, 0x9e, 0x35, 0x26, 0xb, 0xc8, 0xf2, 0x7d, 0xfa, 0x4b, 0xcf, 0x53, 0x20, 0x76, 0xc7, 0xd, 0xbc, 0x78, 0x4f, 0x74, 0x2d, 0x2e, 0x2e, 0x7e, 0x62, 0xae, 0x78, 0x1f}} return a, nil } @@ -926,7 +927,7 @@ func _1627983977_add_gif_to_settingsUpSql() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "1627983977_add_gif_to_settings.up.sql", size: 102, mode: os.FileMode(0644), modTime: time.Unix(1628574950, 0)} + info := bindataFileInfo{name: "1627983977_add_gif_to_settings.up.sql", size: 102, mode: os.FileMode(0644), modTime: time.Unix(1628714143, 0)} a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x63, 0xe6, 0xe1, 0x97, 0x64, 0x4c, 0xe2, 0x14, 0xb1, 0x96, 0x3a, 0xb0, 0xb9, 0xb7, 0xb5, 0x78, 0x4a, 0x39, 0x69, 0x89, 0xb7, 0x89, 0x19, 0xb8, 0x89, 0x1, 0xc5, 0xc2, 0x85, 0x53, 0xe2, 0x83}} return a, nil } @@ -946,11 +947,31 @@ func _1628580203_add_hidden_accountUpSql() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "1628580203_add_hidden_account.up.sql", size: 67, mode: os.FileMode(0644), modTime: time.Unix(1628680792, 0)} + info := bindataFileInfo{name: "1628580203_add_hidden_account.up.sql", size: 67, mode: os.FileMode(0644), modTime: time.Unix(1630492724, 0)} a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xcb, 0x30, 0xf1, 0xd4, 0x60, 0xe2, 0x28, 0x14, 0xcb, 0x16, 0xb, 0x9, 0xea, 0x17, 0xa, 0x9e, 0x89, 0xa8, 0x32, 0x32, 0xf8, 0x4d, 0xa0, 0xe1, 0xe5, 0x79, 0xbd, 0x7d, 0x79, 0xe9, 0x4c, 0x9e}} return a, nil } +var __1629123384_add_id_to_app_metricsUpSql = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xac\x51\xcb\x6e\xc2\x40\x0c\xbc\xe7\x2b\x7c\x04\x29\x7f\xc0\xc9\x04\xd3\x46\xdd\x07\x72\x9c\xaa\x9c\x56\x11\xb1\xaa\x48\x05\xa2\xec\x16\xa9\x7f\x5f\x41\x5a\x14\x15\xb8\xf5\xea\xf1\xcc\x78\xc6\x68\x84\x18\x04\x97\x86\xa0\xe9\xfb\xb0\xd7\x34\x74\xbb\x08\x4c\x0e\x2d\x81\x78\x48\xba\xef\xc3\x04\x5a\x64\x05\x13\x0a\xdd\x21\xcd\x32\x00\x80\xae\x85\xd2\x09\x3d\x11\xc3\x86\x4b\x8b\xbc\x85\x17\xda\x02\xd6\xe2\x4b\x57\x30\x59\x72\x92\x5f\x36\xf5\xa4\x87\x04\xaf\xc8\xc5\x33\x32\x38\x2f\xe0\x6a\x63\x46\xec\xd4\x7c\x7c\x2a\x08\xbd\xc9\x1f\xe0\x6c\x78\xd2\x21\x76\xc7\xc3\x03\xea\xb1\xd7\xa1\x49\xdd\xe1\x3d\xc4\xaf\x98\x74\xff\x60\x6d\x37\x68\x93\xb4\x0d\x4d\x02\x29\x2d\x55\x82\x76\x03\x2b\x5a\x63\x6d\x04\x8a\x9a\x99\x9c\x84\x2b\x32\x72\xa2\xc6\xb3\x71\xe8\xda\x5f\xd1\x71\xde\x0f\xc7\x9d\xc6\xa8\x2d\x2c\xbd\x37\x84\xee\xea\x75\x55\x5c\xa3\xa9\x68\xbe\xc8\x4a\x57\x11\xcb\xb9\x22\x3f\x2d\x6f\x76\x29\x23\x1f\x73\xe7\xd3\x94\xf9\x4d\xa0\x7c\x72\x7b\x3e\xb9\x69\x9e\x55\x64\xa8\x10\xf8\x07\xad\x6c\xcd\xde\xde\x79\xfe\x8a\xfd\xe6\xe7\xf5\x37\xe0\x77\x00\x00\x00\xff\xff\x7c\x73\x3b\xdc\x4d\x02\x00\x00") + +func _1629123384_add_id_to_app_metricsUpSqlBytes() ([]byte, error) { + return bindataRead( + __1629123384_add_id_to_app_metricsUpSql, + "1629123384_add_id_to_app_metrics.up.sql", + ) +} + +func _1629123384_add_id_to_app_metricsUpSql() (*asset, error) { + bytes, err := _1629123384_add_id_to_app_metricsUpSqlBytes() + if err != nil { + return nil, err + } + + info := bindataFileInfo{name: "1629123384_add_id_to_app_metrics.up.sql", size: 589, mode: os.FileMode(0644), modTime: time.Unix(1630493124, 0)} + a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xdf, 0x66, 0xc0, 0x69, 0xb, 0xad, 0x49, 0x7c, 0x8c, 0x67, 0xb8, 0xd6, 0x8d, 0x5d, 0x86, 0x1f, 0xa4, 0x53, 0xf5, 0x8, 0x1, 0xfd, 0x38, 0x49, 0xee, 0x84, 0xc0, 0xd8, 0x17, 0x72, 0x3, 0xb3}} + return a, nil +} + var _docGo = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x2c\xc9\xb1\x0d\xc4\x20\x0c\x05\xd0\x9e\x29\xfe\x02\xd8\xfd\x6d\xe3\x4b\xac\x2f\x44\x82\x09\x78\x7f\xa5\x49\xfd\xa6\x1d\xdd\xe8\xd8\xcf\x55\x8a\x2a\xe3\x47\x1f\xbe\x2c\x1d\x8c\xfa\x6f\xe3\xb4\x34\xd4\xd9\x89\xbb\x71\x59\xb6\x18\x1b\x35\x20\xa2\x9f\x0a\x03\xa2\xe5\x0d\x00\x00\xff\xff\x60\xcd\x06\xbe\x4a\x00\x00\x00") func docGoBytes() ([]byte, error) { @@ -966,7 +987,7 @@ func docGo() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "doc.go", size: 74, mode: os.FileMode(0644), modTime: time.Unix(1596451065, 0)} + info := bindataFileInfo{name: "doc.go", size: 74, mode: os.FileMode(0644), modTime: time.Unix(1585751575, 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 } @@ -1146,6 +1167,8 @@ var _bindata = map[string]func() (*asset, error){ "1628580203_add_hidden_account.up.sql": _1628580203_add_hidden_accountUpSql, + "1629123384_add_id_to_app_metrics.up.sql": _1629123384_add_id_to_app_metricsUpSql, + "doc.go": docGo, } @@ -1232,7 +1255,8 @@ var _bintree = &bintree{nil, map[string]*bintree{ "1625872445_user_status.up.sql": &bintree{_1625872445_user_statusUpSql, map[string]*bintree{}}, "1627983977_add_gif_to_settings.up.sql": &bintree{_1627983977_add_gif_to_settingsUpSql, map[string]*bintree{}}, "1628580203_add_hidden_account.up.sql": &bintree{_1628580203_add_hidden_accountUpSql, map[string]*bintree{}}, - "doc.go": &bintree{docGo, map[string]*bintree{}}, + "1629123384_add_id_to_app_metrics.up.sql": &bintree{_1629123384_add_id_to_app_metricsUpSql, map[string]*bintree{}}, + "doc.go": &bintree{docGo, map[string]*bintree{}}, }} // RestoreAsset restores an asset under the given directory. diff --git a/appdatabase/migrations/sql/1629123384_add_id_to_app_metrics.up.sql b/appdatabase/migrations/sql/1629123384_add_id_to_app_metrics.up.sql new file mode 100644 index 000000000..c694b8b9f --- /dev/null +++ b/appdatabase/migrations/sql/1629123384_add_id_to_app_metrics.up.sql @@ -0,0 +1,14 @@ +ALTER TABLE app_metrics RENAME TO temp_app_metrics; +CREATE TABLE app_metrics ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + event VARCHAR NOT NULL, + value TEXT NOT NULL, + app_version VARCHAR NOT NULL, + operating_system VARCHAR NOT NULL, + created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + session_id VARCHAR, + processed BOOLEAN NOT NULL DEFAULT FALSE); +INSERT INTO app_metrics(event, value, app_version, operating_system, created_at, session_id) +SELECT event, value, app_version, operating_system, created_at, session_id +FROM temp_app_metrics; +DROP TABLE temp_app_metrics; \ No newline at end of file diff --git a/appmetrics/database.go b/appmetrics/database.go index 6b8259c12..34e404f64 100644 --- a/appmetrics/database.go +++ b/appmetrics/database.go @@ -4,8 +4,8 @@ import ( "database/sql" "encoding/json" "errors" - "strings" + "time" "github.com/xeipuuv/gojsonschema" ) @@ -15,12 +15,16 @@ type AppMetricEventType string // Value is `json.RawMessage` so we can send any json shape, including strings // Validation is handled using JSON schemas defined in validators.go, instead of Golang structs type AppMetric struct { + ID int `json:"-"` + MessageID string `json:"message_id"` Event AppMetricEventType `json:"event"` Value json.RawMessage `json:"value"` AppVersion string `json:"app_version"` OS string `json:"os"` SessionID string `json:"session_id"` - CreatedAt string `json:"created_at"` + CreatedAt time.Time `json:"created_at"` + Processed bool `json:"processed"` + ReceivedAt time.Time `json:"received_at"` } type AppMetricValidationError struct { @@ -131,13 +135,13 @@ func (db *Database) SaveAppMetrics(appMetrics []AppMetric, sessionID string) (er _ = tx.Rollback() }() - insert, err = tx.Prepare("INSERT INTO app_metrics (event, value, app_version, operating_system, session_id) VALUES (?, ?, ?, ?, ?)") + insert, err = tx.Prepare("INSERT INTO app_metrics (event, value, app_version, operating_system, session_id, processed) VALUES (?, ?, ?, ?, ?, ?)") if err != nil { return err } for _, metric := range appMetrics { - _, err = insert.Exec(metric.Event, metric.Value, metric.AppVersion, metric.OS, sessionID) + _, err = insert.Exec(metric.Event, metric.Value, metric.AppVersion, metric.OS, sessionID, metric.Processed) if err != nil { return } @@ -151,23 +155,161 @@ func (db *Database) GetAppMetrics(limit int, offset int) (page Page, err error) return page, countErr } - rows, err := db.db.Query("SELECT event, value, app_version, operating_system, session_id, created_at FROM app_metrics LIMIT ? OFFSET ?", limit, offset) + rows, err := db.db.Query("SELECT id, event, value, app_version, operating_system, session_id, created_at, processed FROM app_metrics LIMIT ? OFFSET ?", limit, offset) if err != nil { return page, err } defer rows.Close() + page.AppMetrics, err = db.getFromRows(rows) + return page, err +} + +func (db *Database) getFromRows(rows *sql.Rows) (appMetrics []AppMetric, err error) { + var metrics []AppMetric + for rows.Next() { metric := AppMetric{} - err := rows.Scan( - &metric.Event, &metric.Value, - &metric.AppVersion, &metric.OS, - &metric.SessionID, &metric.CreatedAt, + err = rows.Scan( + &metric.ID, + &metric.Event, + &metric.Value, + &metric.AppVersion, + &metric.OS, + &metric.SessionID, + &metric.CreatedAt, + &metric.Processed, ) if err != nil { - return page, err + return metrics, err } - page.AppMetrics = append(page.AppMetrics, metric) + metrics = append(metrics, metric) } - return page, nil + return metrics, nil +} + +func (db *Database) GetUnprocessed() ([]AppMetric, error) { + rows, err := db.db.Query("SELECT id, event, value, app_version, operating_system, session_id, created_at, processed FROM app_metrics WHERE processed IS ? ORDER BY session_id ASC, created_at ASC", false) + if err != nil { + return nil, err + } + defer rows.Close() + + return db.getFromRows(rows) +} + +func (db *Database) GetUnprocessedGroupedBySession() (map[string][]AppMetric, error) { + uam, err := db.GetUnprocessed() + if err != nil { + return nil, err + } + + out := map[string][]AppMetric{} + for _, am := range uam { + out[am.SessionID] = append(out[am.SessionID], am) + } + + return out, nil +} + +func (db *Database) SetToProcessedByIDs(ids []int) (err error) { + var ( + tx *sql.Tx + update *sql.Stmt + ) + + // start txn + tx, err = db.db.Begin() + if err != nil { + return err + } + + defer func() { + if err == nil { + err = tx.Commit() + return + } + _ = tx.Rollback() + }() + + // Generate prepared statement IN list + in := "(" + for i := 0; i < len(ids); i++ { + in += "?," + } + in = in[:len(in)-1] + ")" + + update, err = tx.Prepare("UPDATE app_metrics SET processed = 1 WHERE id IN " + in) + if err != nil { + return err + } + + // Convert the ids into Stmt.Exec compatible variadic + args := make([]interface{}, 0, len(ids)) + for _, id := range ids { + args = append(args, id) + } + + _, err = update.Exec(args...) + if err != nil { + return + } + return +} + +func (db *Database) SetToProcessed(appMetrics []AppMetric) (err error) { + ids := GetAppMetricsIDs(appMetrics) + return db.SetToProcessedByIDs(ids) +} + +func (db *Database) GetMessagesOlderThan(date *time.Time) ([]AppMetric, error) { + rows, err := db.db.Query("SELECT id, event, value, app_version, operating_system, session_id, created_at, processed FROM app_metrics WHERE created_at < ?", date) + if err != nil { + return nil, err + } + defer rows.Close() + + return db.getFromRows(rows) +} + +func (db *Database) DeleteOlderThan(date *time.Time) (err error) { + var ( + tx *sql.Tx + d *sql.Stmt + ) + + // start txn + tx, err = db.db.Begin() + if err != nil { + return err + } + + defer func() { + if err == nil { + err = tx.Commit() + return + } + _ = tx.Rollback() + }() + + d, err = tx.Prepare("DELETE FROM app_metrics WHERE created_at < ?") + if err != nil { + return err + } + + _, err = d.Exec(date) + if err != nil { + return + } + return +} + +func GetAppMetricsIDs(appMetrics []AppMetric) []int { + var ids []int + + for _, am := range appMetrics { + ids = append(ids, am.ID) + } + + return ids } diff --git a/appmetrics/database_test.go b/appmetrics/database_test.go index df7888c67..c9fb41b35 100644 --- a/appmetrics/database_test.go +++ b/appmetrics/database_test.go @@ -5,6 +5,7 @@ import ( "io/ioutil" "os" "testing" + "time" "github.com/status-im/status-go/appdatabase" @@ -45,6 +46,121 @@ func TestSaveAppMetrics(t *testing.T) { require.Equal(t, appMetrics[0].Value, res[0].Value) require.Equal(t, appMetrics[0].OS, res[0].OS) require.Equal(t, appMetrics[0].AppVersion, res[0].AppVersion) + require.False(t, res[0].Processed) require.NotNil(t, res[0].CreatedAt) require.Equal(t, count, 1) } + +func TestDatabase_GetUnprocessedMetrics(t *testing.T) { + db, stop := setupTestDB(t) + defer stop() + + var uam []AppMetric + metricsPerSession := 10 + unprocessedMetricsPerSession := 5 + numberOfSessions := 3 + numberOfSessionSaves := 5 + + for i := 0; i < numberOfSessionSaves; i++ { + for ii := 1; ii < numberOfSessions+1; ii++ { + err := db.SaveAppMetrics(GenerateMetrics(metricsPerSession), "rand-omse-ssid-"+string(ii)) + require.NoError(t, err) + + uam, err = db.GetUnprocessed() + require.NoError(t, err) + require.Len(t, uam, unprocessedMetricsPerSession*ii+(i*numberOfSessions*unprocessedMetricsPerSession)) + } + } + + // Test metrics are grouped by session_id + lastSessionID := "" + sessionCount := 0 + for _, m := range uam { + if lastSessionID != m.SessionID { + lastSessionID = m.SessionID + sessionCount++ + } + } + require.Equal(t, numberOfSessions, sessionCount) +} + +func TestDatabase_SetProcessedMetrics(t *testing.T) { + db, stop := setupTestDB(t) + defer stop() + + // Add sample data to the DB + err := db.SaveAppMetrics(GenerateMetrics(20), "rand-omse-ssid") + require.NoError(t, err) + + // Get only the unprocessed metrics + uam, err := db.GetUnprocessed() + require.NoError(t, err) + + // Extract the ids from the metrics IDs + ids := GetAppMetricsIDs(uam) + + // Add some more metrics to the DB + err = db.SaveAppMetrics(GenerateMetrics(20), "rand-omse-ssid-2") + require.NoError(t, err) + + // Set metrics as processed with the given ids + err = db.SetToProcessedByIDs(ids) + require.NoError(t, err) + + // Check we have the expected number of unprocessed metrics in the db + uam, err = db.GetUnprocessed() + require.NoError(t, err) + require.Len(t, uam, 10) +} + +func TestDatabase_GetUnprocessedGroupedBySession(t *testing.T) { + db, stop := setupTestDB(t) + defer stop() + + // Add sample data to the DB + err := db.SaveAppMetrics(GenerateMetrics(20), "rand-omse-ssid") + require.NoError(t, err) + + // Add some more metrics to the DB + err = db.SaveAppMetrics(GenerateMetrics(20), "rand-omse-ssid-2") + require.NoError(t, err) + + // Check we have the expected number of unprocessed metrics in the db + uam, err := db.GetUnprocessedGroupedBySession() + require.NoError(t, err) + + // Check we have 2 groups / sessions + require.Len(t, uam, 2) + require.Len(t, uam["rand-omse-ssid"], 10) + require.Len(t, uam["rand-omse-ssid-2"], 10) +} + +func TestDatabase_DeleteOlderThan(t *testing.T) { + db, stop := setupTestDB(t) + defer stop() + + threeHoursAgo := time.Now().Add(time.Hour * -3) // go is annoying sometimes + oneHourHence := time.Now().Add(time.Hour) + + // Add sample data to the DB + err := db.SaveAppMetrics(GenerateMetrics(20), "rand-omse-ssid") + require.NoError(t, err) + + // Delete all messages older than 3 hours old + err = db.DeleteOlderThan(&threeHoursAgo) + require.NoError(t, err) + + // Get all metrics from DB, none should be deleted + ams, err := db.GetAppMetrics(100, 0) + require.NoError(t, err) + require.Len(t, ams.AppMetrics, 20) + + // Delete all messages older than 1 hours in the future + err = db.DeleteOlderThan(&oneHourHence) + require.NoError(t, err) + + // Get all metrics from DB, all should be deleted + ams, err = db.GetAppMetrics(100, 0) + require.NoError(t, err) + require.Len(t, ams.AppMetrics, 0) +} diff --git a/appmetrics/test_helpers.go b/appmetrics/test_helpers.go new file mode 100644 index 000000000..269f3de5c --- /dev/null +++ b/appmetrics/test_helpers.go @@ -0,0 +1,21 @@ +package appmetrics + +import "encoding/json" + +func GenerateMetrics(num int) []AppMetric { + var appMetrics []AppMetric + for i := 0; i < num; i++ { + am := AppMetric{ + Event: NavigateTo, + Value: json.RawMessage(`{"view_id": "some-view-id", "params": {"screen": "login"}}`), + OS: "android", + AppVersion: "1.11", + } + if i < num/2 { + am.Processed = true + } + appMetrics = append(appMetrics, am) + } + + return appMetrics +} diff --git a/config/cli/anon-metric-node-client.json b/config/cli/anon-metric-node-client.json new file mode 100644 index 000000000..8790beff0 --- /dev/null +++ b/config/cli/anon-metric-node-client.json @@ -0,0 +1,31 @@ +{ + "NetworkID": 1, + "DataDir": "/tmp/status-go-data", + "NodeKey": "03b1238c30d5925e3a17b4c1464ac686b3da98527f01b8c6a0731c451c191d30", + "Rendezvous": true, + "NoDiscovery": false, + "ListenAddr": "0.0.0.0:30303", + "RegisterTopics": ["whispermail"], + + "HTTPEnabled": true, + "HTTPHost": "127.0.0.1", + "HTTPPort": 8545, + "APIModules": "eth,net,web3,admin,appmetrics", + + "WakuConfig": { + "Enabled": true, + "EnableMailServer": true, + "DataDir": "/var/tmp/statusd/waku", + "MailServerPassword": "status-offline-inbox" + }, + + "LogFile": "/var/log/status-go.log", + "LogLevel": "DEBUG", + "LogMaxSize": 200, + "LogMaxBackups": 5, + "LogCompressRotated": true, + + "ShhextConfig": { + "AnonMetricsSendID": "04195647953b3e672ed468da732a53faf6b0ab4ba7278a22bed1519492599a9c852469667548334282f18c865e44eec30dc3f189655e4ad199605a34549713b786" + } +} \ No newline at end of file diff --git a/config/cli/anon-metric-node-server.json b/config/cli/anon-metric-node-server.json new file mode 100644 index 000000000..46f8468d1 --- /dev/null +++ b/config/cli/anon-metric-node-server.json @@ -0,0 +1,30 @@ +{ + "NetworkID": 1, + "DataDir": "/tmp/status-go-data", + "NodeKey": "b5c65bcfdb02261052b71cb5f6dec095d0e10df649b4a2b7d881e55e306cbebc", + "Rendezvous": true, + "NoDiscovery": false, + "ListenAddr": "0.0.0.0:30303", + "RegisterTopics": ["whispermail"], + + "HTTPEnabled": true, + "HTTPHost": "127.0.0.1", + "HTTPPort": 8545, + "APIModules": "eth,net,web3,admin,appmetrics", + + "WakuConfig": { + "Enabled": true, + "DataDir": "/var/tmp/statusd/waku" + }, + + "LogFile": "/var/log/status-go.log", + "LogLevel": "DEBUG", + "LogMaxSize": 200, + "LogMaxBackups": 5, + "LogCompressRotated": true, + + "ShhextConfig": { + "AnonMetricsServerEnabled": true, + "AnonMetricsServerPostgresURI": "" + } +} \ No newline at end of file diff --git a/mailserver/mailserver_db_postgres.go b/mailserver/mailserver_db_postgres.go index 35e5a32d8..54182eee2 100644 --- a/mailserver/mailserver_db_postgres.go +++ b/mailserver/mailserver_db_postgres.go @@ -166,9 +166,7 @@ func (i *PostgresDB) BuildIterator(query CursorQuery) (Iterator, error) { func (i *PostgresDB) setup() error { resources := bindata.Resource( migrations.AssetNames(), - func(name string) ([]byte, error) { - return migrations.Asset(name) - }, + migrations.Asset, ) source, err := bindata.WithInstance(resources) diff --git a/mailserver/mailserver_db_postgres_test.go b/mailserver/mailserver_db_postgres_test.go index aec5405f2..780442e79 100644 --- a/mailserver/mailserver_db_postgres_test.go +++ b/mailserver/mailserver_db_postgres_test.go @@ -1,7 +1,7 @@ // In order to run these tests, you must run a PostgreSQL database. // // Using Docker: -// docker run --name mailserver-db -e POSTGRES_HOST_AUTH_METHOD=trust -d -p 5432:5432 postgres:9.6-alpine +// docker run -e POSTGRES_HOST_AUTH_METHOD=trust -d -p 5432:5432 postgres:9.6-alpine // package mailserver @@ -10,25 +10,42 @@ import ( "testing" "time" - "github.com/stretchr/testify/require" + "github.com/stretchr/testify/suite" "github.com/ethereum/go-ethereum/rlp" + gethbridge "github.com/status-im/status-go/eth-node/bridge/geth" "github.com/status-im/status-go/eth-node/crypto" "github.com/status-im/status-go/eth-node/types" + "github.com/status-im/status-go/postgres" waku "github.com/status-im/status-go/waku/common" ) -func TestPostgresDB_BuildIteratorWithBloomFilter(t *testing.T) { +func TestMailServerPostgresDBSuite(t *testing.T) { + suite.Run(t, new(MailServerPostgresDBSuite)) +} + +type MailServerPostgresDBSuite struct { + suite.Suite +} + +func (s *MailServerPostgresDBSuite) SetupSuite() { + // ResetDefaultTestPostgresDB Required to completely reset the Postgres DB + err := postgres.ResetDefaultTestPostgresDB() + s.NoError(err) +} + +func (s *MailServerPostgresDBSuite) TestPostgresDB_BuildIteratorWithBloomFilter() { topic := []byte{0xaa, 0xbb, 0xcc, 0xdd} - db, err := NewPostgresDB("postgres://postgres@127.0.0.1:5432/postgres?sslmode=disable") - require.NoError(t, err) + db, err := NewPostgresDB(postgres.DefaultTestURI) + s.NoError(err) + defer db.Close() envelope, err := newTestEnvelope(topic) - require.NoError(t, err) + s.NoError(err) err = db.SaveEnvelope(envelope) - require.NoError(t, err) + s.NoError(err) iter, err := db.BuildIterator(CursorQuery{ start: NewDBKey(uint32(time.Now().Add(-time.Hour).Unix()), types.BytesToTopic(topic), types.Hash{}).Bytes(), @@ -36,32 +53,33 @@ func TestPostgresDB_BuildIteratorWithBloomFilter(t *testing.T) { bloom: types.TopicToBloom(types.BytesToTopic(topic)), limit: 10, }) - require.NoError(t, err) + s.NoError(err) hasNext := iter.Next() - require.True(t, hasNext) + s.True(hasNext) rawValue, err := iter.GetEnvelopeByBloomFilter(nil) - require.NoError(t, err) - require.NotEmpty(t, rawValue) + s.NoError(err) + s.NotEmpty(rawValue) var receivedEnvelope waku.Envelope err = rlp.DecodeBytes(rawValue, &receivedEnvelope) - require.NoError(t, err) - require.EqualValues(t, waku.BytesToTopic(topic), receivedEnvelope.Topic) + s.NoError(err) + s.EqualValues(waku.BytesToTopic(topic), receivedEnvelope.Topic) err = iter.Release() - require.NoError(t, err) - require.NoError(t, iter.Error()) + s.NoError(err) + s.NoError(iter.Error()) } -func TestPostgresDB_BuildIteratorWithTopic(t *testing.T) { +func (s *MailServerPostgresDBSuite) TestPostgresDB_BuildIteratorWithTopic() { topic := []byte{0x01, 0x02, 0x03, 0x04} - db, err := NewPostgresDB("postgres://postgres@127.0.0.1:5432/postgres?sslmode=disable") - require.NoError(t, err) + db, err := NewPostgresDB(postgres.DefaultTestURI) + s.NoError(err) + defer db.Close() envelope, err := newTestEnvelope(topic) - require.NoError(t, err) + s.NoError(err) err = db.SaveEnvelope(envelope) - require.NoError(t, err) + s.NoError(err) iter, err := db.BuildIterator(CursorQuery{ start: NewDBKey(uint32(time.Now().Add(-time.Hour).Unix()), types.BytesToTopic(topic), types.Hash{}).Bytes(), @@ -69,20 +87,20 @@ func TestPostgresDB_BuildIteratorWithTopic(t *testing.T) { topics: [][]byte{topic}, limit: 10, }) - require.NoError(t, err) + s.NoError(err) hasNext := iter.Next() - require.True(t, hasNext) + s.True(hasNext) rawValue, err := iter.GetEnvelopeByBloomFilter(nil) - require.NoError(t, err) - require.NotEmpty(t, rawValue) + s.NoError(err) + s.NotEmpty(rawValue) var receivedEnvelope waku.Envelope err = rlp.DecodeBytes(rawValue, &receivedEnvelope) - require.NoError(t, err) - require.EqualValues(t, waku.BytesToTopic(topic), receivedEnvelope.Topic) + s.NoError(err) + s.EqualValues(waku.BytesToTopic(topic), receivedEnvelope.Topic) err = iter.Release() - require.NoError(t, err) - require.NoError(t, iter.Error()) + s.NoError(err) + s.NoError(iter.Error()) } func newTestEnvelope(topic []byte) (types.Envelope, error) { diff --git a/multiaccounts/migrations/bindata.go b/multiaccounts/migrations/bindata.go index 22a77b411..f28355f6f 100644 --- a/multiaccounts/migrations/bindata.go +++ b/multiaccounts/migrations/bindata.go @@ -90,7 +90,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(1596451065, 0)} + info := bindataFileInfo{name: "0001_accounts.down.sql", size: 21, mode: os.FileMode(0644), modTime: time.Unix(1585751575, 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 } @@ -110,7 +110,7 @@ func _0001_accountsUpSql() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "0001_accounts.up.sql", size: 163, mode: os.FileMode(0644), modTime: time.Unix(1596451065, 0)} + info := bindataFileInfo{name: "0001_accounts.up.sql", size: 163, mode: os.FileMode(0644), modTime: time.Unix(1585751575, 0)} a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xf2, 0xfa, 0x99, 0x8e, 0x96, 0xb3, 0x13, 0x6c, 0x1f, 0x6, 0x27, 0xc5, 0xd2, 0xd4, 0xe0, 0xa5, 0x26, 0x82, 0xa7, 0x26, 0xf2, 0x68, 0x9d, 0xed, 0x9c, 0x3d, 0xbb, 0xdc, 0x37, 0x28, 0xbc, 0x1}} return a, nil } @@ -130,7 +130,7 @@ func _1605007189_identity_imagesDownSql() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "1605007189_identity_images.down.sql", size: 29, mode: os.FileMode(0644), modTime: time.Unix(1611143707, 0)} + info := bindataFileInfo{name: "1605007189_identity_images.down.sql", size: 29, mode: os.FileMode(0644), modTime: time.Unix(1621263711, 0)} a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x2f, 0xcf, 0xa7, 0xae, 0xd5, 0x4f, 0xcd, 0x14, 0x63, 0x9, 0xbe, 0x39, 0x49, 0x18, 0x96, 0xb2, 0xa3, 0x8, 0x7d, 0x41, 0xdb, 0x50, 0x5d, 0xf5, 0x4d, 0xa2, 0xd, 0x8f, 0x57, 0x79, 0x77, 0x67}} return a, nil } @@ -150,7 +150,7 @@ func _1605007189_identity_imagesUpSql() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "1605007189_identity_images.up.sql", size: 268, mode: os.FileMode(0644), modTime: time.Unix(1611143707, 0)} + info := bindataFileInfo{name: "1605007189_identity_images.up.sql", size: 268, mode: os.FileMode(0644), modTime: time.Unix(1621263711, 0)} a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x50, 0xb6, 0xc1, 0x5c, 0x76, 0x72, 0x6b, 0x22, 0x34, 0xdc, 0x96, 0xdc, 0x2b, 0xfd, 0x2d, 0xbe, 0xcc, 0x1e, 0xd4, 0x5, 0x93, 0xd, 0xc2, 0x51, 0xf3, 0x1a, 0xef, 0x2b, 0x26, 0xa4, 0xeb, 0x65}} return a, nil } @@ -170,7 +170,7 @@ func _1606224181_drop_photo_path_from_accountsDownSql() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "1606224181_drop_photo_path_from_accounts.down.sql", size: 892, mode: os.FileMode(0644), modTime: time.Unix(1611143707, 0)} + info := bindataFileInfo{name: "1606224181_drop_photo_path_from_accounts.down.sql", size: 892, mode: os.FileMode(0644), modTime: time.Unix(1621263711, 0)} a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x90, 0x24, 0x17, 0x7, 0x80, 0x93, 0x6f, 0x8d, 0x5d, 0xaa, 0x8c, 0x79, 0x15, 0x5d, 0xb3, 0x19, 0xd7, 0xd8, 0x39, 0xf9, 0x3a, 0x63, 0x8f, 0x81, 0x15, 0xb6, 0xd6, 0x9a, 0x37, 0xa8, 0x8e, 0x9b}} return a, nil } @@ -190,7 +190,7 @@ func _1606224181_drop_photo_path_from_accountsUpSql() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "1606224181_drop_photo_path_from_accounts.up.sql", size: 866, mode: os.FileMode(0644), modTime: time.Unix(1611143707, 0)} + info := bindataFileInfo{name: "1606224181_drop_photo_path_from_accounts.up.sql", size: 866, mode: os.FileMode(0644), modTime: time.Unix(1621263711, 0)} a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xff, 0x4c, 0x97, 0xee, 0xef, 0x82, 0xb8, 0x6c, 0x71, 0xbb, 0x50, 0x7b, 0xe6, 0xd9, 0x22, 0x31, 0x7c, 0x1a, 0xfe, 0x91, 0x28, 0xf6, 0x6, 0x36, 0xe, 0xb1, 0xf1, 0xc8, 0x25, 0xac, 0x7e, 0xd6}} return a, nil } @@ -210,7 +210,7 @@ func docGo() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "doc.go", size: 74, mode: os.FileMode(0644), modTime: time.Unix(1596451065, 0)} + info := bindataFileInfo{name: "doc.go", size: 74, mode: os.FileMode(0644), modTime: time.Unix(1585751575, 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 } diff --git a/params/config.go b/params/config.go index 1b752aa19..3a28a6ae8 100644 --- a/params/config.go +++ b/params/config.go @@ -566,6 +566,15 @@ type ShhextConfig struct { // DefaultPushNotificationsServers is the default-status run push notification servers DefaultPushNotificationsServers []*ecdsa.PublicKey + + // AnonMetricsSendID is the public key used by a metrics node to decrypt metrics protobufs + AnonMetricsSendID string + + // AnonMetricsServerEnabled indicates whether or not the + AnonMetricsServerEnabled bool + + // AnonMetricsServerPostgresURI is the uri used to connect to a postgres db + AnonMetricsServerPostgresURI string } // Validate validates the ShhextConfig struct and returns an error if inconsistent values are found diff --git a/postgres/helpers.go b/postgres/helpers.go new file mode 100644 index 000000000..d968c25c1 --- /dev/null +++ b/postgres/helpers.go @@ -0,0 +1,27 @@ +package postgres + +import ( + "database/sql" + // Import postgres driver + _ "github.com/lib/pq" +) + +const ( + DefaultTestURI = "postgres://postgres@127.0.0.1:5432/postgres?sslmode=disable" + DropTableURI = "postgres://postgres@127.0.0.1:5432/template1?sslmode=disable" +) + +func ResetDefaultTestPostgresDB() error { + db, err := sql.Open("postgres", DropTableURI) + if err != nil { + return err + } + + _, err = db.Exec("DROP DATABASE IF EXISTS postgres;") + if err != nil { + return err + } + + _, err = db.Exec("CREATE DATABASE postgres;") + return err +} diff --git a/protocol/anon_metrics_test.go b/protocol/anon_metrics_test.go new file mode 100644 index 000000000..e3b841887 --- /dev/null +++ b/protocol/anon_metrics_test.go @@ -0,0 +1,209 @@ +// In order to run these tests, you must run a PostgreSQL database. +// +// Using Docker: +// docker run -e POSTGRES_HOST_AUTH_METHOD=trust -d -p 5432:5432 postgres:9.6-alpine +// + +package protocol + +import ( + "context" + "crypto/ecdsa" + "testing" + + "github.com/stretchr/testify/suite" + "go.uber.org/zap" + + bindata "github.com/status-im/migrate/v4/source/go_bindata" + + appmetricsDB "github.com/status-im/status-go/appmetrics" + gethbridge "github.com/status-im/status-go/eth-node/bridge/geth" + "github.com/status-im/status-go/eth-node/crypto" + "github.com/status-im/status-go/eth-node/types" + "github.com/status-im/status-go/postgres" + "github.com/status-im/status-go/protocol/anonmetrics" + "github.com/status-im/status-go/protocol/anonmetrics/migrations" + "github.com/status-im/status-go/protocol/tt" + "github.com/status-im/status-go/services/appmetrics" + "github.com/status-im/status-go/waku" +) + +func TestMessengerAnonMetricsSuite(t *testing.T) { + suite.Run(t, new(MessengerAnonMetricsSuite)) +} + +type MessengerAnonMetricsSuite struct { + suite.Suite + alice *Messenger // client instance of Messenger + bob *Messenger // server instance of Messenger + + aliceKey *ecdsa.PrivateKey // private key for the alice instance of Messenger + bobKey *ecdsa.PrivateKey // private key for the bob instance of Messenger + + // If one wants to send messages between different instances of Messenger, + // a single Waku service should be shared. + shh types.Waku + logger *zap.Logger +} + +func (s *MessengerAnonMetricsSuite) SetupSuite() { + // ResetDefaultTestPostgresDB Required to completely reset the Postgres DB + err := postgres.ResetDefaultTestPostgresDB() + s.NoError(err) +} + +func (s *MessengerAnonMetricsSuite) SetupTest() { + var err error + + s.logger = tt.MustCreateTestLogger() + + // Setup Waku things + config := waku.DefaultConfig + config.MinimumAcceptedPoW = 0 + shh := waku.New(&config, s.logger) + s.shh = gethbridge.NewGethWakuWrapper(shh) + s.Require().NoError(shh.Start()) + + // Generate private keys for Alice and Bob + s.aliceKey, err = crypto.GenerateKey() + s.Require().NoError(err) + + s.bobKey, err = crypto.GenerateKey() + s.Require().NoError(err) + + // Generate Alice Messenger as the client + amcc := &anonmetrics.ClientConfig{ + ShouldSend: true, + SendAddress: &s.bobKey.PublicKey, + Active: anonmetrics.ActiveClientPhrase, + } + s.alice, err = newMessengerWithKey(s.shh, s.aliceKey, s.logger, []Option{WithAnonMetricsClientConfig(amcc)}) + s.Require().NoError(err) + _, err = s.alice.Start() + s.Require().NoError(err) + + // Generate Bob Messenger as the Server + amsc := &anonmetrics.ServerConfig{ + Enabled: true, + PostgresURI: postgres.DefaultTestURI, + Active: anonmetrics.ActiveServerPhrase, + } + s.bob, err = newMessengerWithKey(s.shh, s.bobKey, s.logger, []Option{WithAnonMetricsServerConfig(amsc)}) + s.Require().NoError(err) + + _, err = s.bob.Start() + s.Require().NoError(err) +} + +func (s *MessengerAnonMetricsSuite) TearDownTest() { + // Down migrate the DB + if s.bob.anonMetricsServer != nil { + postgresMigration := bindata.Resource(migrations.AssetNames(), migrations.Asset) + m, err := anonmetrics.MakeMigration(s.bob.anonMetricsServer.PostgresDB, postgresMigration) + s.NoError(err) + + err = m.Down() + s.NoError(err) + } + + // Shutdown messengers + s.NoError(s.alice.Shutdown()) + s.alice = nil + s.NoError(s.bob.Shutdown()) + s.bob = nil + _ = s.logger.Sync() +} + +func (s *MessengerAnonMetricsSuite) TestReceiveAnonMetric() { + // Create the appmetrics API to simulate incoming metrics from `status-react` + ama := appmetrics.NewAPI(appmetricsDB.NewDB(s.alice.database)) + + // Generate and store some metrics to Alice + ams := appmetricsDB.GenerateMetrics(10) + err := ama.SaveAppMetrics(context.Background(), ams) + s.Require().NoError(err) + + // Check that we have what we stored + amsdb, err := ama.GetAppMetrics(context.Background(), 100, 0) + s.Require().NoError(err) + s.Require().Len(amsdb.AppMetrics, 10) + + // Wait for messages to arrive at bob + _, err = WaitOnMessengerResponse( + s.bob, + func(r *MessengerResponse) bool { return len(r.AnonymousMetrics) > 0 }, + "no anonymous metrics received", + ) + s.Require().NoError(err) + + // Get app metrics from postgres DB + bobMetrics, err := s.bob.anonMetricsServer.GetAppMetrics(100, 0) + s.Require().NoError(err) + s.Require().Len(bobMetrics, 5) + + // Check the values of received and stored metrics against the broadcast metrics + for i, bobMetric := range bobMetrics { + s.Require().True(bobMetric.CreatedAt.Equal(amsdb.AppMetrics[i].CreatedAt), "created_at values are equal") + s.Require().Exactly(bobMetric.SessionID, amsdb.AppMetrics[i].SessionID, "session_id matched exactly") + s.Require().Exactly(bobMetric.Value, amsdb.AppMetrics[i].Value, "value matches exactly") + s.Require().Exactly(bobMetric.Event, amsdb.AppMetrics[i].Event, "event matches exactly") + s.Require().Exactly(bobMetric.OS, amsdb.AppMetrics[i].OS, "operating system matches exactly") + s.Require().Exactly(bobMetric.AppVersion, amsdb.AppMetrics[i].AppVersion, "app version matches exactly") + } +} + +// TestActivationIsOff tests if using the incorrect activation phrase for the anon metric client / server deactivates +// the client / server. This test can be removed when / if the anon metrics functionality is reintroduced / re-approved. +func (s *MessengerAnonMetricsSuite) TestActivationIsOff() { + var err error + + // Check the set up messengers are in the expected state with the correct activation phrases + s.NotNil(s.alice.anonMetricsClient) + s.NotNil(s.bob.anonMetricsServer) + + // Generate Alice Messenger as the client with an incorrect phrase + amcc := &anonmetrics.ClientConfig{ + ShouldSend: true, + SendAddress: &s.bobKey.PublicKey, + Active: "the wrong client phrase", + } + s.alice, err = newMessengerWithKey(s.shh, s.aliceKey, s.logger, []Option{WithAnonMetricsClientConfig(amcc)}) + s.NoError(err) + _, err = s.alice.Start() + s.Require().NoError(err) + + s.Nil(s.alice.anonMetricsClient) + + // Generate Alice Messenger as the client with an no activation phrase + amcc = &anonmetrics.ClientConfig{ + ShouldSend: true, + SendAddress: &s.bobKey.PublicKey, + } + s.alice, err = newMessengerWithKey(s.shh, s.aliceKey, s.logger, []Option{WithAnonMetricsClientConfig(amcc)}) + s.NoError(err) + _, err = s.alice.Start() + s.Require().NoError(err) + + s.Nil(s.alice.anonMetricsClient) + + // Generate Bob Messenger as the Server with an incorrect phrase + amsc := &anonmetrics.ServerConfig{ + Enabled: true, + PostgresURI: postgres.DefaultTestURI, + Active: "the wrong server phrase", + } + s.bob, err = newMessengerWithKey(s.shh, s.bobKey, s.logger, []Option{WithAnonMetricsServerConfig(amsc)}) + s.Require().NoError(err) + + s.Nil(s.bob.anonMetricsServer) + + // Generate Bob Messenger as the Server with no activation phrase + amsc = &anonmetrics.ServerConfig{ + Enabled: true, + PostgresURI: postgres.DefaultTestURI, + } + s.bob, err = newMessengerWithKey(s.shh, s.bobKey, s.logger, []Option{WithAnonMetricsServerConfig(amsc)}) + s.Require().NoError(err) + + s.Nil(s.bob.anonMetricsServer) +} diff --git a/protocol/anonmetrics/adaptors.go b/protocol/anonmetrics/adaptors.go new file mode 100644 index 000000000..41ad8d19f --- /dev/null +++ b/protocol/anonmetrics/adaptors.go @@ -0,0 +1,89 @@ +package anonmetrics + +import ( + "crypto/ecdsa" + "fmt" + + "github.com/davecgh/go-spew/spew" + "github.com/golang/protobuf/ptypes" + + "github.com/status-im/status-go/appmetrics" + "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/protobuf" +) + +// adaptProtoToModel is an adaptor helper function to convert a protobuf.AnonymousMetric into a appmetrics.AppMetric +func adaptProtoToModel(pbAnonMetric *protobuf.AnonymousMetric) (*appmetrics.AppMetric, error) { + t, err := ptypes.Timestamp(pbAnonMetric.CreatedAt) + if err != nil { + return nil, err + } + + return &appmetrics.AppMetric{ + MessageID: pbAnonMetric.Id, + Event: appmetrics.AppMetricEventType(pbAnonMetric.Event), + Value: pbAnonMetric.Value, + AppVersion: pbAnonMetric.AppVersion, + OS: pbAnonMetric.Os, + SessionID: pbAnonMetric.SessionId, + CreatedAt: t, + }, nil +} + +// adaptModelToProto is an adaptor helper function to convert a appmetrics.AppMetric into a protobuf.AnonymousMetric +func adaptModelToProto(modelAnonMetric appmetrics.AppMetric, sendID *ecdsa.PublicKey) (*protobuf.AnonymousMetric, error) { + id := generateProtoID(modelAnonMetric, sendID) + createdAt, err := ptypes.TimestampProto(modelAnonMetric.CreatedAt) + if err != nil { + return nil, err + } + + return &protobuf.AnonymousMetric{ + Id: id, + Event: string(modelAnonMetric.Event), + Value: modelAnonMetric.Value, + AppVersion: modelAnonMetric.AppVersion, + Os: modelAnonMetric.OS, + SessionId: modelAnonMetric.SessionID, + CreatedAt: createdAt, + }, nil +} + +func adaptModelsToProtoBatch(modelAnonMetrics []appmetrics.AppMetric, sendID *ecdsa.PublicKey) (*protobuf.AnonymousMetricBatch, error) { + amb := new(protobuf.AnonymousMetricBatch) + + for _, m := range modelAnonMetrics { + p, err := adaptModelToProto(m, sendID) + if err != nil { + return nil, err + } + + amb.Metrics = append(amb.Metrics, p) + } + + return amb, nil +} + +func adaptProtoBatchToModels(protoBatch protobuf.AnonymousMetricBatch) ([]*appmetrics.AppMetric, error) { + var ams []*appmetrics.AppMetric + + for _, pm := range protoBatch.Metrics { + m, err := adaptProtoToModel(pm) + if err != nil { + return nil, err + } + + ams = append(ams, m) + } + + return ams, nil +} + +// NEEDED because we don't send individual metrics, we send only batches +func generateProtoID(modelAnonMetric appmetrics.AppMetric, sendID *ecdsa.PublicKey) string { + return types.EncodeHex(crypto.Keccak256([]byte(fmt.Sprintf( + "%s%s", + types.EncodeHex(crypto.FromECDSAPub(sendID)), + spew.Sdump(modelAnonMetric))))) +} diff --git a/protocol/anonmetrics/client.go b/protocol/anonmetrics/client.go new file mode 100644 index 000000000..66ccbfa65 --- /dev/null +++ b/protocol/anonmetrics/client.go @@ -0,0 +1,231 @@ +package anonmetrics + +import ( + "context" + "crypto/ecdsa" + "errors" + "sync" + "time" + + "github.com/golang/protobuf/proto" + "go.uber.org/zap" + + "github.com/status-im/status-go/appmetrics" + "github.com/status-im/status-go/eth-node/crypto" + "github.com/status-im/status-go/protocol/common" + "github.com/status-im/status-go/protocol/protobuf" +) + +const ActiveClientPhrase = "yes i am wanting the activation of the anon metrics client, please thank you lots thank you" + +type ClientConfig struct { + ShouldSend bool + SendAddress *ecdsa.PublicKey + Active string +} + +type Client struct { + Config *ClientConfig + DB *appmetrics.Database + Identity *ecdsa.PrivateKey + Logger *zap.Logger + + //messageSender is a message processor used to send metric batch messages + messageSender *common.MessageSender + + IntervalInc *FibonacciIntervalIncrementer + + // mainLoopQuit is a channel that concurrently orchestrates that the main loop that should be terminated + mainLoopQuit chan struct{} + + // deleteLoopQuit is a channel that concurrently orchestrates that the delete loop that should be terminated + deleteLoopQuit chan struct{} + + // DBLock prevents deletion of DB items during mainloop + DBLock sync.Mutex +} + +func NewClient(sender *common.MessageSender) *Client { + return &Client{ + messageSender: sender, + IntervalInc: &FibonacciIntervalIncrementer{ + Last: 0, + Current: 1, + }, + } +} + +func (c *Client) sendUnprocessedMetrics() { + if c.Config.Active != ActiveClientPhrase { + return + } + + c.Logger.Debug("sendUnprocessedMetrics() triggered") + + c.DBLock.Lock() + defer c.DBLock.Unlock() + + // Get all unsent metrics grouped by session id + uam, err := c.DB.GetUnprocessedGroupedBySession() + if err != nil { + c.Logger.Error("failed to get unprocessed messages grouped by session", zap.Error(err)) + } + c.Logger.Debug("unprocessed metrics from db", zap.Reflect("uam", uam)) + + for session, batch := range uam { + c.Logger.Debug("processing uam from session", zap.String("session", session)) + + // Convert the metrics into protobuf + amb, err := adaptModelsToProtoBatch(batch, &c.Identity.PublicKey) + if err != nil { + c.Logger.Error("failed to adapt models to protobuf batch", zap.Error(err)) + return + } + + // Generate an ephemeral key per session id + ephemeralKey, err := crypto.GenerateKey() + if err != nil { + c.Logger.Error("failed to generate an ephemeral key", zap.Error(err)) + return + } + + // Prepare the protobuf message + encodedMessage, err := proto.Marshal(amb) + if err != nil { + c.Logger.Error("failed to marshal protobuf", zap.Error(err)) + return + } + rawMessage := common.RawMessage{ + Payload: encodedMessage, + Sender: ephemeralKey, + SkipEncryption: true, + SendOnPersonalTopic: true, + MessageType: protobuf.ApplicationMetadataMessage_ANONYMOUS_METRIC_BATCH, + } + + c.Logger.Debug("rawMessage prepared from unprocessed anonymous metrics", zap.Reflect("rawMessage", rawMessage)) + + // Send the metrics batch + _, err = c.messageSender.SendPrivate(context.Background(), c.Config.SendAddress, &rawMessage) + if err != nil { + c.Logger.Error("failed to send metrics batch message", zap.Error(err)) + return + } + + // Mark metrics as processed + err = c.DB.SetToProcessed(batch) + if err != nil { + c.Logger.Error("failed to set metrics as processed in db", zap.Error(err)) + } + } +} + +func (c *Client) mainLoop() error { + if c.Config.Active != ActiveClientPhrase { + return nil + } + + c.Logger.Debug("mainLoop() triggered") + + for { + c.sendUnprocessedMetrics() + + waitFor := time.Duration(c.IntervalInc.Next()) * time.Second + c.Logger.Debug("mainLoop() wait interval set", zap.Duration("waitFor", waitFor)) + select { + case <-time.After(waitFor): + case <-c.mainLoopQuit: + return nil + } + } +} + +func (c *Client) startMainLoop() { + if c.Config.Active != ActiveClientPhrase { + return + } + + c.Logger.Debug("startMainLoop() triggered") + + c.stopMainLoop() + c.mainLoopQuit = make(chan struct{}) + go func() { + c.Logger.Debug("startMainLoop() anonymous go routine triggered") + err := c.mainLoop() + if err != nil { + c.Logger.Error("main loop exited with an error", zap.Error(err)) + } + }() +} + +func (c *Client) deleteLoop() error { + // Sleep to give the main lock time to process any old messages + time.Sleep(time.Second * 10) + + for { + func() { + c.DBLock.Lock() + defer c.DBLock.Unlock() + + oneWeekAgo := time.Now().Add(time.Hour * 24 * 7 * -1) + err := c.DB.DeleteOlderThan(&oneWeekAgo) + if err != nil { + c.Logger.Error("failed to delete metrics older than given time", + zap.Time("time given", oneWeekAgo), + zap.Error(err)) + } + }() + + select { + case <-time.After(time.Hour): + case <-c.deleteLoopQuit: + return nil + } + } +} + +func (c *Client) startDeleteLoop() { + c.stopDeleteLoop() + c.deleteLoopQuit = make(chan struct{}) + go func() { + err := c.deleteLoop() + if err != nil { + c.Logger.Error("delete loop exited with an error", zap.Error(err)) + } + }() +} + +func (c *Client) Start() error { + c.Logger.Debug("Main Start() triggered") + if c.messageSender == nil { + return errors.New("can't start, missing message processor") + } + + c.startMainLoop() + c.startDeleteLoop() + return nil +} + +func (c *Client) stopMainLoop() { + c.Logger.Debug("stopMainLoop() triggered") + + if c.mainLoopQuit != nil { + c.Logger.Debug("mainLoopQuit not set, attempting to close") + + close(c.mainLoopQuit) + c.mainLoopQuit = nil + } +} + +func (c *Client) stopDeleteLoop() { + if c.deleteLoopQuit != nil { + close(c.deleteLoopQuit) + c.deleteLoopQuit = nil + } +} + +func (c *Client) Stop() error { + c.stopMainLoop() + c.stopDeleteLoop() + return nil +} diff --git a/protocol/anonmetrics/interval_incrementer.go b/protocol/anonmetrics/interval_incrementer.go new file mode 100644 index 000000000..37c203b65 --- /dev/null +++ b/protocol/anonmetrics/interval_incrementer.go @@ -0,0 +1,15 @@ +package anonmetrics + +type FibonacciIntervalIncrementer struct { + Last int64 + Current int64 +} + +func (f *FibonacciIntervalIncrementer) Next() int64 { + out := f.Last + f.Current + + f.Last = f.Current + f.Current = out + + return out +} diff --git a/protocol/anonmetrics/interval_incrementer_test.go b/protocol/anonmetrics/interval_incrementer_test.go new file mode 100644 index 000000000..11c30db09 --- /dev/null +++ b/protocol/anonmetrics/interval_incrementer_test.go @@ -0,0 +1,21 @@ +package anonmetrics + +import "testing" + +func TestFibonacciIntervalIncrementer_Next(t *testing.T) { + fii := FibonacciIntervalIncrementer{ + Last: 0, + Current: 1, + } + + expected := []int64{ + 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987, 1597, 2584, 4181, 6765, + } + + for i := 0; i < 19; i++ { + next := fii.Next() + if next != expected[i] { + t.Errorf("expected '%d', received '%d'", expected[i], next) + } + } +} diff --git a/protocol/anonmetrics/migrations/migrations.go b/protocol/anonmetrics/migrations/migrations.go new file mode 100644 index 000000000..24d0bf62b --- /dev/null +++ b/protocol/anonmetrics/migrations/migrations.go @@ -0,0 +1,319 @@ +// Code generated by go-bindata. DO NOT EDIT. +// sources: +// 1619446565_postgres_make_anon_metrics_table.down.sql (24B) +// 1619446565_postgres_make_anon_metrics_table.up.sql (443B) +// doc.go (380B) + +package migrations + +import ( + "bytes" + "compress/gzip" + "crypto/sha256" + "fmt" + "io" + "io/ioutil" + "os" + "path/filepath" + "strings" + "time" +) + +func bindataRead(data []byte, name string) ([]byte, error) { + gz, err := gzip.NewReader(bytes.NewBuffer(data)) + if err != nil { + return nil, fmt.Errorf("read %q: %v", name, err) + } + + var buf bytes.Buffer + _, err = io.Copy(&buf, gz) + clErr := gz.Close() + + if err != nil { + return nil, fmt.Errorf("read %q: %v", name, err) + } + if clErr != nil { + return nil, err + } + + return buf.Bytes(), nil +} + +type asset struct { + bytes []byte + info os.FileInfo + digest [sha256.Size]byte +} + +type bindataFileInfo struct { + name string + size int64 + mode os.FileMode + modTime time.Time +} + +func (fi bindataFileInfo) Name() string { + return fi.name +} +func (fi bindataFileInfo) Size() int64 { + return fi.size +} +func (fi bindataFileInfo) Mode() os.FileMode { + return fi.mode +} +func (fi bindataFileInfo) ModTime() time.Time { + return fi.modTime +} +func (fi bindataFileInfo) IsDir() bool { + return false +} +func (fi bindataFileInfo) Sys() interface{} { + return nil +} + +var __1619446565_postgres_make_anon_metrics_tableDownSql = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x72\x09\xf2\x0f\x50\x08\x71\x74\xf2\x71\x55\x48\x2c\x28\x88\xcf\x4d\x2d\x29\xca\x4c\x2e\xb6\xe6\x02\x04\x00\x00\xff\xff\x99\xa7\x42\x7d\x18\x00\x00\x00") + +func _1619446565_postgres_make_anon_metrics_tableDownSqlBytes() ([]byte, error) { + return bindataRead( + __1619446565_postgres_make_anon_metrics_tableDownSql, + "1619446565_postgres_make_anon_metrics_table.down.sql", + ) +} + +func _1619446565_postgres_make_anon_metrics_tableDownSql() (*asset, error) { + bytes, err := _1619446565_postgres_make_anon_metrics_tableDownSqlBytes() + if err != nil { + return nil, err + } + + info := bindataFileInfo{name: "1619446565_postgres_make_anon_metrics_table.down.sql", size: 24, mode: os.FileMode(0644), modTime: time.Unix(1630492920, 0)} + a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x75, 0xea, 0x1, 0x74, 0xe6, 0xa3, 0x11, 0xd0, 0x86, 0x87, 0x7e, 0x31, 0xb4, 0x1a, 0x27, 0x5d, 0xda, 0x77, 0xa3, 0xf5, 0x1d, 0x88, 0x79, 0xcf, 0xd5, 0x95, 0x75, 0xd, 0x47, 0xa1, 0x90, 0x5}} + return a, nil +} + +var __1619446565_postgres_make_anon_metrics_tableUpSql = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x74\x90\x4d\x6a\xc3\x30\x14\x84\xf7\x39\xc5\x2c\xdb\x10\xc8\x01\xba\x52\xdc\x17\xea\x56\xb6\x53\x59\x2e\x64\x65\x84\xfd\x30\x82\xfa\x07\x49\x75\xe9\xed\x8b\x1d\x92\x38\x81\xac\xbf\xef\x69\x46\x13\x29\x12\x9a\xa0\xc5\x4e\x12\xcc\x30\x94\x2d\x07\x67\x2b\x8f\xa7\x15\x00\xd8\x1a\x39\xa9\x58\x48\x1c\x54\x9c\x08\x75\xc4\x07\x1d\x37\xab\x99\x6d\xd7\x88\xbb\xaa\x6f\x6d\xd7\xe0\x74\x85\xda\x04\x83\xf5\x76\xc6\x2d\x7b\x6f\x1a\x2e\x6d\x8d\x2f\xa1\xa2\x37\xa1\x50\xa4\xf1\x67\x41\x48\x33\x8d\xb4\x90\x72\x33\x7b\x3c\x72\x17\x2e\xca\x2d\x1b\xcd\xf7\x0f\xe3\x3d\xcf\xd2\x3b\x30\x35\x1d\xd9\x79\xdb\x77\x0f\x4e\xfb\x81\x9d\x09\xb6\x6b\x4a\xff\xe7\x03\xb7\x0f\x34\xcf\x7e\x7a\x64\xd9\xf2\x56\xa8\x1c\x9b\xc0\x75\x69\x02\x74\x9c\x50\xae\x45\x72\x58\x28\xe7\x25\x54\xff\x3b\x8d\x60\x96\x0b\x0c\xae\xaf\xd8\x7b\xae\xb1\xcb\x32\x49\xe2\xfa\x09\xbc\xd2\x5e\x14\x52\x63\x2f\x64\x4e\xa7\x20\xc7\x15\xdb\xf1\x3e\xe9\x2c\x46\x85\x52\x94\xea\xf2\x42\x9e\x5f\xfe\x03\x00\x00\xff\xff\xee\x42\x32\x03\xbb\x01\x00\x00") + +func _1619446565_postgres_make_anon_metrics_tableUpSqlBytes() ([]byte, error) { + return bindataRead( + __1619446565_postgres_make_anon_metrics_tableUpSql, + "1619446565_postgres_make_anon_metrics_table.up.sql", + ) +} + +func _1619446565_postgres_make_anon_metrics_tableUpSql() (*asset, error) { + bytes, err := _1619446565_postgres_make_anon_metrics_tableUpSqlBytes() + if err != nil { + return nil, err + } + + info := bindataFileInfo{name: "1619446565_postgres_make_anon_metrics_table.up.sql", size: 443, mode: os.FileMode(0644), modTime: time.Unix(1630495282, 0)} + a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xd5, 0xdc, 0x72, 0x28, 0x3c, 0xf6, 0x94, 0xb0, 0x47, 0x3d, 0xca, 0x55, 0x3d, 0xf7, 0x83, 0xb8, 0x7d, 0x2f, 0x1e, 0x98, 0xb7, 0xde, 0xa, 0xff, 0xa0, 0x52, 0x60, 0x83, 0x56, 0xc5, 0xd1, 0xa2}} + return a, nil +} + +var _docGo = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x84\x8f\xbd\x6e\xf3\x30\x0c\x45\x77\x3f\xc5\x45\x96\x2c\x9f\xa5\xe5\x9b\xba\x75\xec\xde\x17\x60\xe4\x6b\x49\x88\x2d\x1a\x22\xf3\xf7\xf6\x85\xd3\x02\xcd\xd6\xf5\x00\xe7\xf0\x32\x46\x7c\x96\x6a\x98\xeb\x42\x54\x43\x63\xa2\x99\xf4\x07\x4e\x4c\x72\x31\xe2\x90\xab\x97\xcb\x29\x24\x5d\xa3\xb9\xf8\xc5\xc6\xba\xc6\xb5\xe6\x2e\xce\x78\xfd\x7f\x18\x62\x44\x92\x76\x74\x14\x69\xd3\xc2\x67\xcb\x60\x2e\xdd\x6b\xcb\xb8\x55\x2f\x10\x6c\x9d\x73\xbd\x07\xbc\x3b\x16\x8a\x39\xbc\x88\x1f\x0d\x5e\x88\x24\xc6\x3d\x33\x6b\x47\xd6\xf1\x54\xdb\x24\x2e\x61\x47\x1f\xf3\x0b\xd9\x17\x26\x59\x16\x4e\x98\xbb\xae\x4f\xd7\x64\x25\xa6\xda\x99\x5c\xfb\xe3\x1f\xc4\x8c\x8e\x26\x2b\x6d\xf7\x8b\x5c\x89\xa6\x3f\xe7\x21\x6d\xfa\xfb\x23\xdc\xb4\x9f\x0d\x62\xe0\x7d\x63\x72\x4e\x61\x18\x36\x49\x67\xc9\xc4\xa6\xe6\xb9\xd3\x86\x21\xc6\xac\x6f\x99\x8d\xbb\xf7\xba\x72\xdc\xce\x19\xdf\xbd\xaa\xcd\x30\x2a\x42\x88\xbf\x20\x64\x45\x88\xc3\x57\x00\x00\x00\xff\xff\xa9\xf1\x73\x83\x7c\x01\x00\x00") + +func docGoBytes() ([]byte, error) { + return bindataRead( + _docGo, + "doc.go", + ) +} + +func docGo() (*asset, error) { + bytes, err := docGoBytes() + if err != nil { + return nil, err + } + + info := bindataFileInfo{name: "doc.go", size: 380, mode: os.FileMode(0644), modTime: time.Unix(1630495290, 0)} + a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x49, 0x1, 0xd4, 0xd6, 0xc7, 0x44, 0xd4, 0xfd, 0x7b, 0x69, 0x1f, 0xe3, 0xe, 0x48, 0x14, 0x99, 0xf0, 0x8e, 0x43, 0xae, 0x54, 0x64, 0xa2, 0x8b, 0x82, 0x1c, 0x2b, 0xb, 0xec, 0xf5, 0xb3, 0xfc}} + return a, nil +} + +// Asset loads and returns the asset for the given name. +// It returns an error if the asset could not be found or +// could not be loaded. +func Asset(name string) ([]byte, error) { + canonicalName := strings.Replace(name, "\\", "/", -1) + if f, ok := _bindata[canonicalName]; ok { + a, err := f() + if err != nil { + return nil, fmt.Errorf("Asset %s can't read by error: %v", name, err) + } + return a.bytes, nil + } + return nil, fmt.Errorf("Asset %s not found", name) +} + +// AssetString returns the asset contents as a string (instead of a []byte). +func AssetString(name string) (string, error) { + data, err := Asset(name) + return string(data), err +} + +// MustAsset is like Asset but panics when Asset would return an error. +// It simplifies safe initialization of global variables. +func MustAsset(name string) []byte { + a, err := Asset(name) + if err != nil { + panic("asset: Asset(" + name + "): " + err.Error()) + } + + return a +} + +// MustAssetString is like AssetString but panics when Asset would return an +// error. It simplifies safe initialization of global variables. +func MustAssetString(name string) string { + return string(MustAsset(name)) +} + +// AssetInfo loads and returns the asset info for the given name. +// It returns an error if the asset could not be found or +// could not be loaded. +func AssetInfo(name string) (os.FileInfo, error) { + canonicalName := strings.Replace(name, "\\", "/", -1) + if f, ok := _bindata[canonicalName]; ok { + a, err := f() + if err != nil { + return nil, fmt.Errorf("AssetInfo %s can't read by error: %v", name, err) + } + return a.info, nil + } + return nil, fmt.Errorf("AssetInfo %s not found", name) +} + +// AssetDigest returns the digest of the file with the given name. It returns an +// error if the asset could not be found or the digest could not be loaded. +func AssetDigest(name string) ([sha256.Size]byte, error) { + canonicalName := strings.Replace(name, "\\", "/", -1) + if f, ok := _bindata[canonicalName]; ok { + a, err := f() + if err != nil { + return [sha256.Size]byte{}, fmt.Errorf("AssetDigest %s can't read by error: %v", name, err) + } + return a.digest, nil + } + return [sha256.Size]byte{}, fmt.Errorf("AssetDigest %s not found", name) +} + +// Digests returns a map of all known files and their checksums. +func Digests() (map[string][sha256.Size]byte, error) { + mp := make(map[string][sha256.Size]byte, len(_bindata)) + for name := range _bindata { + a, err := _bindata[name]() + if err != nil { + return nil, err + } + mp[name] = a.digest + } + return mp, nil +} + +// AssetNames returns the names of the assets. +func AssetNames() []string { + names := make([]string, 0, len(_bindata)) + for name := range _bindata { + names = append(names, name) + } + return names +} + +// _bindata is a table, holding each asset generator, mapped to its name. +var _bindata = map[string]func() (*asset, error){ + "1619446565_postgres_make_anon_metrics_table.down.sql": _1619446565_postgres_make_anon_metrics_tableDownSql, + + "1619446565_postgres_make_anon_metrics_table.up.sql": _1619446565_postgres_make_anon_metrics_tableUpSql, + + "doc.go": docGo, +} + +// AssetDir returns the file names below a certain +// directory embedded in the file by go-bindata. +// For example if you run go-bindata on data/... and data contains the +// following hierarchy: +// data/ +// foo.txt +// img/ +// a.png +// b.png +// then AssetDir("data") would return []string{"foo.txt", "img"}, +// AssetDir("data/img") would return []string{"a.png", "b.png"}, +// AssetDir("foo.txt") and AssetDir("notexist") would return an error, and +// AssetDir("") will return []string{"data"}. +func AssetDir(name string) ([]string, error) { + node := _bintree + if len(name) != 0 { + canonicalName := strings.Replace(name, "\\", "/", -1) + pathList := strings.Split(canonicalName, "/") + for _, p := range pathList { + node = node.Children[p] + if node == nil { + return nil, fmt.Errorf("Asset %s not found", name) + } + } + } + if node.Func != nil { + return nil, fmt.Errorf("Asset %s not found", name) + } + rv := make([]string, 0, len(node.Children)) + for childName := range node.Children { + rv = append(rv, childName) + } + return rv, nil +} + +type bintree struct { + Func func() (*asset, error) + Children map[string]*bintree +} + +var _bintree = &bintree{nil, map[string]*bintree{ + "1619446565_postgres_make_anon_metrics_table.down.sql": &bintree{_1619446565_postgres_make_anon_metrics_tableDownSql, map[string]*bintree{}}, + "1619446565_postgres_make_anon_metrics_table.up.sql": &bintree{_1619446565_postgres_make_anon_metrics_tableUpSql, map[string]*bintree{}}, + "doc.go": &bintree{docGo, map[string]*bintree{}}, +}} + +// RestoreAsset restores an asset under the given directory. +func RestoreAsset(dir, name string) error { + data, err := Asset(name) + if err != nil { + return err + } + info, err := AssetInfo(name) + if err != nil { + return err + } + err = os.MkdirAll(_filePath(dir, filepath.Dir(name)), os.FileMode(0755)) + if err != nil { + return err + } + err = ioutil.WriteFile(_filePath(dir, name), data, info.Mode()) + if err != nil { + return err + } + return os.Chtimes(_filePath(dir, name), info.ModTime(), info.ModTime()) +} + +// RestoreAssets restores an asset under the given directory recursively. +func RestoreAssets(dir, name string) error { + children, err := AssetDir(name) + // File + if err != nil { + return RestoreAsset(dir, name) + } + // Dir + for _, child := range children { + err = RestoreAssets(dir, filepath.Join(name, child)) + if err != nil { + return err + } + } + return nil +} + +func _filePath(dir, name string) string { + canonicalName := strings.Replace(name, "\\", "/", -1) + return filepath.Join(append([]string{dir}, strings.Split(canonicalName, "/")...)...) +} diff --git a/protocol/anonmetrics/migrations/postgres/1619446565_postgres_make_anon_metrics_table.down.sql b/protocol/anonmetrics/migrations/postgres/1619446565_postgres_make_anon_metrics_table.down.sql new file mode 100644 index 000000000..775be4718 --- /dev/null +++ b/protocol/anonmetrics/migrations/postgres/1619446565_postgres_make_anon_metrics_table.down.sql @@ -0,0 +1 @@ +DROP TABLE app_metrics; diff --git a/protocol/anonmetrics/migrations/postgres/1619446565_postgres_make_anon_metrics_table.up.sql b/protocol/anonmetrics/migrations/postgres/1619446565_postgres_make_anon_metrics_table.up.sql new file mode 100644 index 000000000..46a78988c --- /dev/null +++ b/protocol/anonmetrics/migrations/postgres/1619446565_postgres_make_anon_metrics_table.up.sql @@ -0,0 +1,15 @@ +CREATE TABLE app_metrics ( + id SERIAL PRIMARY KEY, + + /* Incoming metric data */ + message_id VARCHAR UNIQUE NOT NULL, + event VARCHAR NOT NULL, + value JSON NOT NULL, + app_version VARCHAR NOT NULL, + operating_system VARCHAR NOT NULL, + session_id VARCHAR NOT NULL, + created_at TIMESTAMP NOT NULL, + + /* Row metadata */ + processed BOOLEAN NOT NULL DEFAULT FALSE, + received_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP); \ No newline at end of file diff --git a/protocol/anonmetrics/migrations/postgres/doc.go b/protocol/anonmetrics/migrations/postgres/doc.go new file mode 100644 index 000000000..e3ec01af5 --- /dev/null +++ b/protocol/anonmetrics/migrations/postgres/doc.go @@ -0,0 +1,9 @@ +// This file is necessary because "github.com/status-im/migrate/v4" +// can't handle files starting with a prefix. At least that's the case +// for go-bindata. +// If go-bindata is called from the same directory, asset names +// have no prefix and "github.com/status-im/migrate/v4" works as expected. + +package postgres + +//go:generate go-bindata -pkg migrations -o ../migrations.go ./ diff --git a/protocol/anonmetrics/server.go b/protocol/anonmetrics/server.go new file mode 100644 index 000000000..e769c05e7 --- /dev/null +++ b/protocol/anonmetrics/server.go @@ -0,0 +1,189 @@ +package anonmetrics + +import ( + "database/sql" + + // Import postgres driver + _ "github.com/lib/pq" + "go.uber.org/zap" + + "github.com/status-im/migrate/v4" + "github.com/status-im/migrate/v4/database/postgres" + bindata "github.com/status-im/migrate/v4/source/go_bindata" + + "github.com/status-im/status-go/appmetrics" + "github.com/status-im/status-go/protocol/anonmetrics/migrations" + "github.com/status-im/status-go/protocol/protobuf" +) + +const ActiveServerPhrase = "I was thinking that it would be a pretty nice idea if the server functionality was working now, I express gratitude in the anticipation" + +type ServerConfig struct { + Enabled bool + PostgresURI string + Active string +} + +type Server struct { + Config *ServerConfig + Logger *zap.Logger + PostgresDB *sql.DB +} + +func NewServer(postgresURI string) (*Server, error) { + postgresMigration := bindata.Resource(migrations.AssetNames(), migrations.Asset) + db, err := NewMigratedDB(postgresURI, postgresMigration) + if err != nil { + return nil, err + } + + return &Server{ + PostgresDB: db, + }, nil +} + +func (s *Server) Stop() error { + if s.PostgresDB != nil { + return s.PostgresDB.Close() + } + return nil +} + +func (s *Server) StoreMetrics(appMetricsBatch protobuf.AnonymousMetricBatch) (appMetrics []*appmetrics.AppMetric, err error) { + if s.Config.Active != ActiveServerPhrase { + return nil, nil + } + + s.Logger.Debug("StoreMetrics() triggered with payload", + zap.Reflect("appMetricsBatch", appMetricsBatch)) + appMetrics, err = adaptProtoBatchToModels(appMetricsBatch) + if err != nil { + return + } + + var ( + tx *sql.Tx + insert *sql.Stmt + ) + + // start txn + tx, err = s.PostgresDB.Begin() + if err != nil { + return + } + + defer func() { + if err == nil { + err = tx.Commit() + return + } + _ = tx.Rollback() + }() + + //noinspection ALL + query := `INSERT INTO app_metrics (message_id, event, value, app_version, operating_system, session_id, created_at) +VALUES ($1, $2, $3, $4, $5, $6, $7) +ON CONFLICT (message_id) DO NOTHING;` + + insert, err = tx.Prepare(query) + if err != nil { + return + } + + for _, metric := range appMetrics { + _, err = insert.Exec( + metric.MessageID, + metric.Event, + metric.Value, + metric.AppVersion, + metric.OS, + metric.SessionID, + metric.CreatedAt, + ) + if err != nil { + return + } + } + return +} + +func (s *Server) getFromRows(rows *sql.Rows) (appMetrics []appmetrics.AppMetric, err error) { + for rows.Next() { + metric := appmetrics.AppMetric{} + err = rows.Scan( + &metric.ID, + &metric.MessageID, + &metric.Event, + &metric.Value, + &metric.AppVersion, + &metric.OS, + &metric.SessionID, + &metric.CreatedAt, + &metric.Processed, + &metric.ReceivedAt, + ) + if err != nil { + return nil, err + } + appMetrics = append(appMetrics, metric) + } + return appMetrics, nil +} + +func (s *Server) GetAppMetrics(limit int, offset int) ([]appmetrics.AppMetric, error) { + if s.Config.Active != ActiveServerPhrase { + return nil, nil + } + + rows, err := s.PostgresDB.Query("SELECT id, message_id, event, value, app_version, operating_system, session_id, created_at, processed, received_at FROM app_metrics LIMIT $1 OFFSET $2", limit, offset) + if err != nil { + return nil, err + } + defer rows.Close() + + return s.getFromRows(rows) +} + +func NewMigratedDB(uri string, migrationResource *bindata.AssetSource) (*sql.DB, error) { + db, err := sql.Open("postgres", uri) + if err != nil { + return nil, err + } + + if err := setup(db, migrationResource); err != nil { + return nil, err + } + + return db, nil +} + +func setup(d *sql.DB, migrationResource *bindata.AssetSource) error { + m, err := MakeMigration(d, migrationResource) + if err != nil { + return err + } + + if err = m.Up(); err != migrate.ErrNoChange { + return err + } + + return nil +} + +func MakeMigration(d *sql.DB, migrationResource *bindata.AssetSource) (*migrate.Migrate, error) { + source, err := bindata.WithInstance(migrationResource) + if err != nil { + return nil, err + } + + driver, err := postgres.WithInstance(d, &postgres.Config{}) + if err != nil { + return nil, err + } + + return migrate.NewWithInstance( + "go-bindata", + source, + "postgres", + driver) +} diff --git a/protocol/messenger.go b/protocol/messenger.go index c941a5002..babb56c38 100644 --- a/protocol/messenger.go +++ b/protocol/messenger.go @@ -22,12 +22,14 @@ import ( "github.com/golang/protobuf/proto" "github.com/status-im/status-go/appdatabase" + "github.com/status-im/status-go/appmetrics" "github.com/status-im/status-go/connection" "github.com/status-im/status-go/eth-node/crypto" "github.com/status-im/status-go/eth-node/types" userimage "github.com/status-im/status-go/images" "github.com/status-im/status-go/multiaccounts" "github.com/status-im/status-go/multiaccounts/accounts" + "github.com/status-im/status-go/protocol/anonmetrics" "github.com/status-im/status-go/protocol/audio" "github.com/status-im/status-go/protocol/common" "github.com/status-im/status-go/protocol/communities" @@ -83,6 +85,8 @@ type Messenger struct { encryptor *encryption.Protocol sender *common.MessageSender ensVerifier *ens.Verifier + anonMetricsClient *anonmetrics.Client + anonMetricsServer *anonmetrics.Server pushNotificationClient *pushnotificationclient.Client pushNotificationServer *pushnotificationserver.Server communitiesManager *communities.Manager @@ -259,6 +263,35 @@ func NewMessenger( return nil, errors.Wrap(err, "failed to create messageSender") } + // Initialise anon metrics client + var anonMetricsClient *anonmetrics.Client + if c.anonMetricsClientConfig != nil && + c.anonMetricsClientConfig.ShouldSend && + c.anonMetricsClientConfig.Active == anonmetrics.ActiveClientPhrase { + + anonMetricsClient = anonmetrics.NewClient(sender) + anonMetricsClient.Config = c.anonMetricsClientConfig + anonMetricsClient.Identity = identity + anonMetricsClient.DB = appmetrics.NewDB(database) + anonMetricsClient.Logger = logger + } + + // Initialise anon metrics server + var anonMetricsServer *anonmetrics.Server + if c.anonMetricsServerConfig != nil && + c.anonMetricsServerConfig.Enabled && + c.anonMetricsServerConfig.Active == anonmetrics.ActiveServerPhrase { + + server, err := anonmetrics.NewServer(c.anonMetricsServerConfig.PostgresURI) + if err != nil { + return nil, errors.Wrap(err, "failed to create anonmetrics.Server") + } + + anonMetricsServer = server + anonMetricsServer.Config = c.anonMetricsServerConfig + anonMetricsServer.Logger = logger + } + // Initialize push notification server var pushNotificationServer *pushnotificationserver.Server if c.pushNotificationServerConfig != nil && c.pushNotificationServerConfig.Enabled { @@ -297,6 +330,8 @@ func NewMessenger( transport: transp, encryptor: encryptionProtocol, sender: sender, + anonMetricsClient: anonMetricsClient, + anonMetricsServer: anonMetricsServer, pushNotificationClient: pushNotificationClient, pushNotificationServer: pushNotificationServer, communitiesManager: communitiesManager, @@ -332,6 +367,13 @@ func NewMessenger( logger: logger, } + if anonMetricsClient != nil { + messenger.shutdownTasks = append(messenger.shutdownTasks, anonMetricsClient.Stop) + } + if anonMetricsServer != nil { + messenger.shutdownTasks = append(messenger.shutdownTasks, anonMetricsServer.Stop) + } + if c.envelopesMonitorConfig != nil { interceptor := EnvelopeEventsInterceptor{c.envelopesMonitorConfig.EnvelopeEventsHandler, messenger} err := messenger.transport.SetEnvelopeEventsHandler(interceptor) @@ -427,6 +469,13 @@ func (m *Messenger) Start() (*MessengerResponse, error) { } } + // Start anonymous metrics client + if m.anonMetricsClient != nil { + if err := m.anonMetricsClient.Start(); err != nil { + return nil, err + } + } + ensSubscription := m.ensVerifier.Subscribe() // Subscrbe @@ -2927,6 +2976,20 @@ func (m *Messenger) handleRetrievedMessages(chatWithMessages map[transport.Filte continue } + case protobuf.AnonymousMetricBatch: + logger.Debug("Handling AnonymousMetricBatch") + if m.anonMetricsServer == nil { + logger.Warn("unable to handle AnonymousMetricBatch, anonMetricsServer is nil") + continue + } + + ams, err := m.anonMetricsServer.StoreMetrics(msg.ParsedMessage.Interface().(protobuf.AnonymousMetricBatch)) + if err != nil { + logger.Warn("failed to store AnonymousMetricBatch", zap.Error(err)) + continue + } + messageState.Response.AnonymousMetrics = append(messageState.Response.AnonymousMetrics, ams...) + default: // Check if is an encrypted PushNotificationRegistration if msg.Type == protobuf.ApplicationMetadataMessage_PUSH_NOTIFICATION_REGISTRATION { @@ -4343,6 +4406,7 @@ func (m *Messenger) encodeChatEntity(chat *Chat, message common.ChatEntity) ([]b if err != nil { return nil, err } + case ChatTypePublic, ChatTypeProfile: l.Debug("sending public message", zap.String("chatName", chat.Name)) message.SetMessageType(protobuf.MessageType_PUBLIC_GROUP) @@ -4350,6 +4414,7 @@ func (m *Messenger) encodeChatEntity(chat *Chat, message common.ChatEntity) ([]b if err != nil { return nil, err } + case ChatTypeCommunityChat: l.Debug("sending community chat message", zap.String("chatName", chat.Name)) // TODO: add grant @@ -4358,6 +4423,7 @@ func (m *Messenger) encodeChatEntity(chat *Chat, message common.ChatEntity) ([]b if err != nil { return nil, err } + case ChatTypePrivateGroupChat: message.SetMessageType(protobuf.MessageType_PRIVATE_GROUP) l.Debug("sending group message", zap.String("chatName", chat.Name)) diff --git a/protocol/messenger_config.go b/protocol/messenger_config.go index 25a8026a2..daf3fe7d7 100644 --- a/protocol/messenger_config.go +++ b/protocol/messenger_config.go @@ -6,6 +6,7 @@ import ( "go.uber.org/zap" "github.com/status-im/status-go/multiaccounts" + "github.com/status-im/status-go/protocol/anonmetrics" "github.com/status-im/status-go/protocol/common" "github.com/status-im/status-go/protocol/communities" "github.com/status-im/status-go/protocol/protobuf" @@ -48,6 +49,9 @@ type config struct { verifyENSURL string verifyENSContractAddress string + anonMetricsClientConfig *anonmetrics.ClientConfig + anonMetricsServerConfig *anonmetrics.ServerConfig + pushNotificationServerConfig *pushnotificationserver.Config pushNotificationClientConfig *pushnotificationclient.Config @@ -116,6 +120,20 @@ func WithAccount(acc *multiaccounts.Account) Option { } } +func WithAnonMetricsClientConfig(anonMetricsClientConfig *anonmetrics.ClientConfig) Option { + return func(c *config) error { + c.anonMetricsClientConfig = anonMetricsClientConfig + return nil + } +} + +func WithAnonMetricsServerConfig(anonMetricsServerConfig *anonmetrics.ServerConfig) Option { + return func(c *config) error { + c.anonMetricsServerConfig = anonMetricsServerConfig + return nil + } +} + func WithPushNotificationServerConfig(pushNotificationServerConfig *pushnotificationserver.Config) Option { return func(c *config) error { c.pushNotificationServerConfig = pushNotificationServerConfig diff --git a/protocol/messenger_handler.go b/protocol/messenger_handler.go index 5c2241bbb..90a565768 100644 --- a/protocol/messenger_handler.go +++ b/protocol/messenger_handler.go @@ -1264,6 +1264,12 @@ func (m *Messenger) HandleChatIdentity(state *ReceivedMessageState, ci protobuf. return nil } +func (m *Messenger) HandleAnonymousMetricBatch(amb protobuf.AnonymousMetricBatch) error { + + // TODO + return nil +} + func (m *Messenger) checkForEdits(message *common.Message) error { // Check for any pending edit // If any pending edits are available and valid, apply them diff --git a/protocol/messenger_response.go b/protocol/messenger_response.go index 647bde6c8..13ea165cf 100644 --- a/protocol/messenger_response.go +++ b/protocol/messenger_response.go @@ -3,6 +3,7 @@ package protocol import ( "encoding/json" + "github.com/status-im/status-go/appmetrics" "github.com/status-im/status-go/protocol/common" "github.com/status-im/status-go/protocol/communities" "github.com/status-im/status-go/protocol/encryption/multidevice" @@ -22,6 +23,7 @@ type MessengerResponse struct { Invitations []*GroupChatInvitation CommunityChanges []*communities.CommunityChanges RequestsToJoinCommunity []*communities.RequestToJoin + AnonymousMetrics []*appmetrics.AppMetric Mailservers []mailservers.Mailserver // notifications a list of notifications derived from messenger events diff --git a/protocol/migrations/migrations.go b/protocol/migrations/migrations.go index 91768a179..ff7125b47 100644 --- a/protocol/migrations/migrations.go +++ b/protocol/migrations/migrations.go @@ -1,57 +1,57 @@ -// Code generated by go-bindata. +// Code generated by go-bindata. DO NOT EDIT. // sources: -// 000001_init.down.db.sql -// 000001_init.up.db.sql -// 000002_add_last_ens_clock_value.up.sql -// 1586358095_add_replace.up.sql -// 1588665364_add_image_data.up.sql -// 1589365189_add_pow_target.up.sql -// 1591277220_add_index_messages.up.sql -// 1593087212_add_mute_chat_and_raw_message_fields.up.sql -// 1595862781_add_audio_data.up.sql -// 1595865249_create_emoji_reactions_table.up.sql -// 1596805115_create_group_chat_invitations_table.up.sql -// 1597322655_add_invitation_admin_chat_field.up.sql -// 1597757544_add_nickname.up.sql -// 1598955122_add_mentions.up.sql -// 1599641390_add_emoji_reactions_index.up.sql -// 1599720851_add_seen_index_remove_long_messages.up.sql -// 1603198582_add_profile_chat_field.up.sql -// 1603816533_add_links.up.sql -// 1603888149_create_chat_identity_last_published_table.up.sql -// 1605075346_add_communities.up.sql -// 1610117927_add_message_cache.up.sql -// 1610959908_add_dont_wrap_to_raw_messages.up.sql -// 1610960912_add_send_on_personal_topic.up.sql -// 1612870480_add_datasync_id.up.sql -// 1614152139_add_communities_request_to_join.up.sql -// 1615374373_add_confirmations.up.sql -// 1617694931_add_notification_center.up.sql -// 1618923660_create_pin_messages.up.sql -// 1619094007_add_joined_chat_field.up.sql -// 1619099821_add_last_synced_field.up.sql -// 1621933219_add_mentioned.up.sql -// 1622010048_add_unviewed_mentions_count.up.sql -// 1622061278_add_message_activity_center_notification_field.up.sql -// 1622464518_set_synced_to_from.up.sql -// 1622464519_add_chat_description.up.sql -// 1622622253_add_pinned_by_to_pin_messages.up.sql -// 1623938329_add_author_activity_center_notification_field.up.sql -// 1623938330_add_edit_messages.up.sql -// 1624978434_add_muted_community.up.sql -// 1625018910_add_repply_message_activity_center_notification_field.up.sql -// 1625762506_add_deleted_messages.up.sql -// 1627388946_add_communities_synced_at.up.sql -// 1628280060_create-usermessages-index.sql -// README.md -// doc.go -// DO NOT EDIT! +// 000001_init.down.db.sql (65B) +// 000001_init.up.db.sql (2.719kB) +// 000002_add_last_ens_clock_value.up.sql (77B) +// 1586358095_add_replace.up.sql (224B) +// 1588665364_add_image_data.up.sql (186B) +// 1589365189_add_pow_target.up.sql (66B) +// 1591277220_add_index_messages.up.sql (240B) +// 1593087212_add_mute_chat_and_raw_message_fields.up.sql (215B) +// 1595862781_add_audio_data.up.sql (246B) +// 1595865249_create_emoji_reactions_table.up.sql (300B) +// 1596805115_create_group_chat_invitations_table.up.sql (231B) +// 1597322655_add_invitation_admin_chat_field.up.sql (54B) +// 1597757544_add_nickname.up.sql (52B) +// 1598955122_add_mentions.up.sql (52B) +// 1599641390_add_emoji_reactions_index.up.sql (126B) +// 1599720851_add_seen_index_remove_long_messages.up.sql (150B) +// 1603198582_add_profile_chat_field.up.sql (45B) +// 1603816533_add_links.up.sql (48B) +// 1603888149_create_chat_identity_last_published_table.up.sql (407B) +// 1605075346_add_communities.up.sql (6.971kB) +// 1610117927_add_message_cache.up.sql (142B) +// 1610959908_add_dont_wrap_to_raw_messages.up.sql (83B) +// 1610960912_add_send_on_personal_topic.up.sql (82B) +// 1612870480_add_datasync_id.up.sql (111B) +// 1614152139_add_communities_request_to_join.up.sql (831B) +// 1615374373_add_confirmations.up.sql (227B) +// 1617694931_add_notification_center.up.sql (572B) +// 1618923660_create_pin_messages.up.sql (265B) +// 1619094007_add_joined_chat_field.up.sql (101B) +// 1619099821_add_last_synced_field.up.sql (226B) +// 1621933219_add_mentioned.up.sql (70B) +// 1622010048_add_unviewed_mentions_count.up.sql (114B) +// 1622061278_add_message_activity_center_notification_field.up.sql (80B) +// 1622464518_set_synced_to_from.up.sql (105B) +// 1622464519_add_chat_description.up.sql (93B) +// 1622622253_add_pinned_by_to_pin_messages.up.sql (52B) +// 1623938329_add_author_activity_center_notification_field.up.sql (66B) +// 1623938330_add_edit_messages.up.sql (369B) +// 1624978434_add_muted_community.up.sql (82B) +// 1625018910_add_repply_message_activity_center_notification_field.up.sql (86B) +// 1625762506_add_deleted_messages.up.sql (357B) +// 1627388946_add_communities_synced_at.up.sql (87B) +// 1628280060_create-usermessages-index.sql (80B) +// README.md (554B) +// doc.go (850B) package migrations import ( "bytes" "compress/gzip" + "crypto/sha256" "fmt" "io" "io/ioutil" @@ -64,7 +64,7 @@ import ( func bindataRead(data []byte, name string) ([]byte, error) { gz, err := gzip.NewReader(bytes.NewBuffer(data)) if err != nil { - return nil, fmt.Errorf("Read %q: %v", name, err) + return nil, fmt.Errorf("read %q: %v", name, err) } var buf bytes.Buffer @@ -72,7 +72,7 @@ func bindataRead(data []byte, name string) ([]byte, error) { clErr := gz.Close() if err != nil { - return nil, fmt.Errorf("Read %q: %v", name, err) + return nil, fmt.Errorf("read %q: %v", name, err) } if clErr != nil { return nil, err @@ -82,8 +82,9 @@ func bindataRead(data []byte, name string) ([]byte, error) { } type asset struct { - bytes []byte - info os.FileInfo + bytes []byte + info os.FileInfo + digest [sha256.Size]byte } type bindataFileInfo struct { @@ -127,8 +128,8 @@ func _000001_initDownDbSql() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "000001_init.down.db.sql", size: 65, mode: os.FileMode(436), modTime: time.Unix(1619724270, 0)} - a := &asset{bytes: bytes, info: info} + info := bindataFileInfo{name: "000001_init.down.db.sql", size: 65, mode: os.FileMode(0644), modTime: time.Unix(1585751575, 0)} + a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x5e, 0xbb, 0x3f, 0x1, 0x75, 0x19, 0x70, 0x86, 0xa7, 0x34, 0x40, 0x17, 0x34, 0x3e, 0x18, 0x51, 0x79, 0xd4, 0x22, 0xad, 0x8f, 0x80, 0xcc, 0xa6, 0xcc, 0x6, 0x2b, 0x62, 0x2, 0x47, 0xba, 0xf9}} return a, nil } @@ -147,8 +148,8 @@ func _000001_initUpDbSql() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "000001_init.up.db.sql", size: 2719, mode: os.FileMode(436), modTime: time.Unix(1619724270, 0)} - a := &asset{bytes: bytes, info: info} + info := bindataFileInfo{name: "000001_init.up.db.sql", size: 2719, mode: os.FileMode(0644), modTime: time.Unix(1585751575, 0)} + a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x60, 0xdc, 0xeb, 0xe, 0xc2, 0x4f, 0x75, 0xa, 0xf6, 0x3e, 0xc7, 0xc4, 0x4, 0xe2, 0xe1, 0xa4, 0x73, 0x2f, 0x4a, 0xad, 0x1a, 0x0, 0xc3, 0x93, 0x9d, 0x77, 0x3e, 0x31, 0x91, 0x77, 0x2e, 0xc8}} return a, nil } @@ -167,8 +168,8 @@ func _000002_add_last_ens_clock_valueUpSql() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "000002_add_last_ens_clock_value.up.sql", size: 77, mode: os.FileMode(436), modTime: time.Unix(1619724270, 0)} - a := &asset{bytes: bytes, info: info} + info := bindataFileInfo{name: "000002_add_last_ens_clock_value.up.sql", size: 77, mode: os.FileMode(0644), modTime: time.Unix(1589413297, 0)} + a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x4d, 0x3, 0x8f, 0xd5, 0x85, 0x83, 0x47, 0xbe, 0xf9, 0x82, 0x7e, 0x81, 0xa4, 0xbd, 0xaa, 0xd5, 0x98, 0x18, 0x5, 0x2d, 0x82, 0x42, 0x3b, 0x3, 0x50, 0xc3, 0x1e, 0x84, 0x35, 0xf, 0xb6, 0x2b}} return a, nil } @@ -187,8 +188,8 @@ func _1586358095_add_replaceUpSql() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "1586358095_add_replace.up.sql", size: 224, mode: os.FileMode(436), modTime: time.Unix(1619724270, 0)} - a := &asset{bytes: bytes, info: info} + info := bindataFileInfo{name: "1586358095_add_replace.up.sql", size: 224, mode: os.FileMode(0644), modTime: time.Unix(1621263711, 0)} + a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xd2, 0xb3, 0xa9, 0xc7, 0x7f, 0x9d, 0x8f, 0x43, 0x8c, 0x9e, 0x58, 0x8d, 0x44, 0xbc, 0xfa, 0x6b, 0x5f, 0x3f, 0x5a, 0xbe, 0xe8, 0xb1, 0x16, 0xf, 0x91, 0x2a, 0xa0, 0x71, 0xbb, 0x8d, 0x6b, 0xcb}} return a, nil } @@ -207,8 +208,8 @@ func _1588665364_add_image_dataUpSql() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "1588665364_add_image_data.up.sql", size: 186, mode: os.FileMode(436), modTime: time.Unix(1619724270, 0)} - a := &asset{bytes: bytes, info: info} + info := bindataFileInfo{name: "1588665364_add_image_data.up.sql", size: 186, mode: os.FileMode(0644), modTime: time.Unix(1621263711, 0)} + a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xd6, 0xc6, 0x35, 0xb4, 0x4c, 0x39, 0x96, 0x29, 0x30, 0xda, 0xf4, 0x8f, 0xcb, 0xf1, 0x9f, 0x84, 0xdc, 0x88, 0xd4, 0xd5, 0xbc, 0xb6, 0x5b, 0x46, 0x78, 0x67, 0x76, 0x1a, 0x5, 0x36, 0xdc, 0xe5}} return a, nil } @@ -227,8 +228,8 @@ func _1589365189_add_pow_targetUpSql() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "1589365189_add_pow_target.up.sql", size: 66, mode: os.FileMode(436), modTime: time.Unix(1619724270, 0)} - a := &asset{bytes: bytes, info: info} + info := bindataFileInfo{name: "1589365189_add_pow_target.up.sql", size: 66, mode: os.FileMode(0644), modTime: time.Unix(1621263711, 0)} + a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x4e, 0x3a, 0xe2, 0x2e, 0x7d, 0xaf, 0xbb, 0xcc, 0x21, 0xa1, 0x7a, 0x41, 0x9a, 0xd0, 0xbb, 0xa9, 0xc8, 0x35, 0xf9, 0x32, 0x34, 0x46, 0x44, 0x9a, 0x86, 0x40, 0x7c, 0xb9, 0x23, 0xc7, 0x3, 0x3f}} return a, nil } @@ -247,8 +248,8 @@ func _1591277220_add_index_messagesUpSql() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "1591277220_add_index_messages.up.sql", size: 240, mode: os.FileMode(436), modTime: time.Unix(1619724270, 0)} - a := &asset{bytes: bytes, info: info} + info := bindataFileInfo{name: "1591277220_add_index_messages.up.sql", size: 240, mode: os.FileMode(0644), modTime: time.Unix(1621263711, 0)} + a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x9c, 0xfe, 0xbe, 0xd5, 0xb8, 0x8f, 0xdd, 0xef, 0xbb, 0xa8, 0xad, 0x7f, 0xed, 0x5b, 0x5b, 0x2f, 0xe6, 0x82, 0x27, 0x78, 0x1f, 0xb9, 0x57, 0xdc, 0x8, 0xc2, 0xb2, 0xa9, 0x9a, 0x4, 0xe1, 0x7a}} return a, nil } @@ -267,8 +268,8 @@ func _1593087212_add_mute_chat_and_raw_message_fieldsUpSql() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "1593087212_add_mute_chat_and_raw_message_fields.up.sql", size: 215, mode: os.FileMode(436), modTime: time.Unix(1619724270, 0)} - a := &asset{bytes: bytes, info: info} + info := bindataFileInfo{name: "1593087212_add_mute_chat_and_raw_message_fields.up.sql", size: 215, mode: os.FileMode(0644), modTime: time.Unix(1621263711, 0)} + a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x73, 0x99, 0x61, 0xd1, 0xaa, 0xb4, 0xbf, 0xaf, 0xd7, 0x20, 0x17, 0x40, 0xf9, 0x2, 0xfb, 0xcc, 0x40, 0x2a, 0xd, 0x86, 0x36, 0x30, 0x88, 0x89, 0x25, 0x80, 0x42, 0xb0, 0x5b, 0xe9, 0x73, 0x78}} return a, nil } @@ -287,8 +288,8 @@ func _1595862781_add_audio_dataUpSql() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "1595862781_add_audio_data.up.sql", size: 246, mode: os.FileMode(436), modTime: time.Unix(1619724270, 0)} - a := &asset{bytes: bytes, info: info} + info := bindataFileInfo{name: "1595862781_add_audio_data.up.sql", size: 246, mode: os.FileMode(0644), modTime: time.Unix(1621263711, 0)} + a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xae, 0xd2, 0xee, 0x55, 0xfb, 0x36, 0xa4, 0x92, 0x66, 0xe, 0x81, 0x62, 0x1e, 0x7a, 0x69, 0xa, 0xd5, 0x4b, 0xa5, 0x6a, 0x8d, 0x1d, 0xce, 0xf3, 0x3e, 0xc0, 0x5f, 0x9c, 0x66, 0x1b, 0xb4, 0xed}} return a, nil } @@ -307,8 +308,8 @@ func _1595865249_create_emoji_reactions_tableUpSql() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "1595865249_create_emoji_reactions_table.up.sql", size: 300, mode: os.FileMode(436), modTime: time.Unix(1619724270, 0)} - a := &asset{bytes: bytes, info: info} + info := bindataFileInfo{name: "1595865249_create_emoji_reactions_table.up.sql", size: 300, mode: os.FileMode(0644), modTime: time.Unix(1621263711, 0)} + a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x3e, 0xc5, 0x43, 0x5c, 0x3d, 0x53, 0x43, 0x2c, 0x1a, 0xa5, 0xb6, 0xbf, 0x7, 0x4, 0x5a, 0x3e, 0x40, 0x8b, 0xa4, 0x57, 0x12, 0x58, 0xbc, 0x42, 0xe2, 0xc3, 0xde, 0x76, 0x98, 0x80, 0xe2, 0xbe}} return a, nil } @@ -327,8 +328,8 @@ func _1596805115_create_group_chat_invitations_tableUpSql() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "1596805115_create_group_chat_invitations_table.up.sql", size: 231, mode: os.FileMode(436), modTime: time.Unix(1619724270, 0)} - a := &asset{bytes: bytes, info: info} + info := bindataFileInfo{name: "1596805115_create_group_chat_invitations_table.up.sql", size: 231, mode: os.FileMode(0644), modTime: time.Unix(1621263711, 0)} + a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x6d, 0xb1, 0x14, 0x6d, 0x54, 0x28, 0x67, 0xc3, 0x23, 0x6a, 0xfc, 0x80, 0xdf, 0x9e, 0x4c, 0x35, 0x36, 0xf, 0xf8, 0xf3, 0x5f, 0xae, 0xad, 0xb, 0xc1, 0x51, 0x8e, 0x17, 0x7, 0xe5, 0x7f, 0x91}} return a, nil } @@ -347,8 +348,8 @@ func _1597322655_add_invitation_admin_chat_fieldUpSql() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "1597322655_add_invitation_admin_chat_field.up.sql", size: 54, mode: os.FileMode(436), modTime: time.Unix(1619724270, 0)} - a := &asset{bytes: bytes, info: info} + info := bindataFileInfo{name: "1597322655_add_invitation_admin_chat_field.up.sql", size: 54, mode: os.FileMode(0644), modTime: time.Unix(1621263711, 0)} + a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xa9, 0x7a, 0xa0, 0xf2, 0xdb, 0x13, 0x91, 0x91, 0xa8, 0x34, 0x1a, 0xa1, 0x49, 0x68, 0xd5, 0xae, 0x2c, 0xd8, 0xd5, 0xea, 0x8f, 0x8c, 0xc7, 0x2, 0x4e, 0x58, 0x2c, 0x3a, 0x14, 0xd4, 0x4f, 0x2c}} return a, nil } @@ -367,8 +368,8 @@ func _1597757544_add_nicknameUpSql() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "1597757544_add_nickname.up.sql", size: 52, mode: os.FileMode(436), modTime: time.Unix(1619724270, 0)} - a := &asset{bytes: bytes, info: info} + info := bindataFileInfo{name: "1597757544_add_nickname.up.sql", size: 52, mode: os.FileMode(0644), modTime: time.Unix(1621263711, 0)} + a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xf4, 0xa2, 0x64, 0x50, 0xc5, 0x4, 0xb9, 0x8b, 0xd1, 0x18, 0x9b, 0xc3, 0x91, 0x36, 0x2a, 0x1f, 0xc3, 0x6c, 0x2d, 0x92, 0xf8, 0x5e, 0xff, 0xb1, 0x59, 0x61, 0x2, 0x1c, 0xe1, 0x85, 0x90, 0xa4}} return a, nil } @@ -387,8 +388,8 @@ func _1598955122_add_mentionsUpSql() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "1598955122_add_mentions.up.sql", size: 52, mode: os.FileMode(436), modTime: time.Unix(1619724270, 0)} - a := &asset{bytes: bytes, info: info} + info := bindataFileInfo{name: "1598955122_add_mentions.up.sql", size: 52, mode: os.FileMode(0644), modTime: time.Unix(1621263711, 0)} + a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x8d, 0x22, 0x17, 0x92, 0xd2, 0x11, 0x4e, 0x7, 0x93, 0x9a, 0x55, 0xfd, 0xb, 0x97, 0xc4, 0x63, 0x6a, 0x81, 0x97, 0xcd, 0xb2, 0xf8, 0x4b, 0x5f, 0x3c, 0xfa, 0x3a, 0x38, 0x53, 0x10, 0xed, 0x9d}} return a, nil } @@ -407,8 +408,8 @@ func _1599641390_add_emoji_reactions_indexUpSql() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "1599641390_add_emoji_reactions_index.up.sql", size: 126, mode: os.FileMode(436), modTime: time.Unix(1619724270, 0)} - a := &asset{bytes: bytes, info: info} + info := bindataFileInfo{name: "1599641390_add_emoji_reactions_index.up.sql", size: 126, mode: os.FileMode(0644), modTime: time.Unix(1621263711, 0)} + a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xf9, 0xd8, 0xdc, 0xa7, 0xb, 0x92, 0x7a, 0x61, 0x37, 0x24, 0x1c, 0x77, 0x5e, 0xe, 0x7e, 0xfc, 0x9f, 0x98, 0x7b, 0x65, 0xe7, 0xf9, 0x71, 0x57, 0x89, 0x2d, 0x90, 0x1b, 0xf6, 0x5e, 0x37, 0xe8}} return a, nil } @@ -427,8 +428,8 @@ func _1599720851_add_seen_index_remove_long_messagesUpSql() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "1599720851_add_seen_index_remove_long_messages.up.sql", size: 150, mode: os.FileMode(436), modTime: time.Unix(1619724270, 0)} - a := &asset{bytes: bytes, info: info} + info := bindataFileInfo{name: "1599720851_add_seen_index_remove_long_messages.up.sql", size: 150, mode: os.FileMode(0644), modTime: time.Unix(1621263711, 0)} + a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x24, 0x1c, 0xc4, 0x78, 0x91, 0xc7, 0xeb, 0xfe, 0xc8, 0xa0, 0xd8, 0x13, 0x27, 0x97, 0xc8, 0x96, 0x56, 0x97, 0x33, 0x2c, 0x1e, 0x16, 0x8a, 0xd3, 0x49, 0x99, 0x3, 0xe9, 0xbb, 0xc4, 0x5, 0x3c}} return a, nil } @@ -447,8 +448,8 @@ func _1603198582_add_profile_chat_fieldUpSql() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "1603198582_add_profile_chat_field.up.sql", size: 45, mode: os.FileMode(436), modTime: time.Unix(1619724270, 0)} - a := &asset{bytes: bytes, info: info} + info := bindataFileInfo{name: "1603198582_add_profile_chat_field.up.sql", size: 45, mode: os.FileMode(0644), modTime: time.Unix(1621263711, 0)} + a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xaa, 0xca, 0xe, 0x46, 0xa0, 0x9, 0x9d, 0x47, 0x57, 0xe9, 0xfb, 0x17, 0xeb, 0x9c, 0xf6, 0xb8, 0x1d, 0xe9, 0xd, 0x0, 0xd5, 0xe5, 0xd8, 0x9e, 0x60, 0xa, 0xbf, 0x32, 0x2c, 0x52, 0x7f, 0x6a}} return a, nil } @@ -467,8 +468,8 @@ func _1603816533_add_linksUpSql() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "1603816533_add_links.up.sql", size: 48, mode: os.FileMode(436), modTime: time.Unix(1619724270, 0)} - a := &asset{bytes: bytes, info: info} + info := bindataFileInfo{name: "1603816533_add_links.up.sql", size: 48, mode: os.FileMode(0644), modTime: time.Unix(1621263711, 0)} + a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xc9, 0x24, 0xd6, 0x1d, 0xa, 0x83, 0x1e, 0x4d, 0xf, 0xae, 0x4d, 0x8c, 0x51, 0x32, 0xa8, 0x37, 0xb0, 0x14, 0xfb, 0x32, 0x34, 0xc8, 0xc, 0x4e, 0x5b, 0xc5, 0x15, 0x65, 0x73, 0x0, 0x0, 0x1d}} return a, nil } @@ -487,8 +488,8 @@ func _1603888149_create_chat_identity_last_published_tableUpSql() (*asset, error return nil, err } - info := bindataFileInfo{name: "1603888149_create_chat_identity_last_published_table.up.sql", size: 407, mode: os.FileMode(436), modTime: time.Unix(1619724270, 0)} - a := &asset{bytes: bytes, info: info} + info := bindataFileInfo{name: "1603888149_create_chat_identity_last_published_table.up.sql", size: 407, mode: os.FileMode(0644), modTime: time.Unix(1621263711, 0)} + a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x7f, 0x9, 0xf, 0xfb, 0xdb, 0x3c, 0x86, 0x70, 0x82, 0xda, 0x10, 0x25, 0xe2, 0x4e, 0x40, 0x45, 0xab, 0x8b, 0x1c, 0x91, 0x7c, 0xf1, 0x70, 0x2e, 0x81, 0xf3, 0x71, 0x45, 0xda, 0xe2, 0xa4, 0x57}} return a, nil } @@ -507,8 +508,8 @@ func _1605075346_add_communitiesUpSql() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "1605075346_add_communities.up.sql", size: 6971, mode: os.FileMode(436), modTime: time.Unix(1619724270, 0)} - a := &asset{bytes: bytes, info: info} + info := bindataFileInfo{name: "1605075346_add_communities.up.sql", size: 6971, mode: os.FileMode(0644), modTime: time.Unix(1621263711, 0)} + a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x1f, 0x64, 0xea, 0xb4, 0xae, 0x9e, 0xdb, 0x9, 0x58, 0xb6, 0x5c, 0x7a, 0x50, 0xc5, 0xfe, 0x93, 0x5d, 0x36, 0x85, 0x5d, 0x6a, 0xba, 0xc9, 0x7e, 0x84, 0xd7, 0xbf, 0x2a, 0x53, 0xf3, 0x97, 0xf1}} return a, nil } @@ -527,8 +528,8 @@ func _1610117927_add_message_cacheUpSql() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "1610117927_add_message_cache.up.sql", size: 142, mode: os.FileMode(436), modTime: time.Unix(1619724270, 0)} - a := &asset{bytes: bytes, info: info} + info := bindataFileInfo{name: "1610117927_add_message_cache.up.sql", size: 142, mode: os.FileMode(0644), modTime: time.Unix(1621263711, 0)} + a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x34, 0xf1, 0xf0, 0x82, 0x79, 0x28, 0x19, 0xc2, 0x39, 0x6a, 0xa5, 0x96, 0x59, 0x23, 0xa0, 0xed, 0x60, 0x58, 0x86, 0x9, 0xb9, 0xad, 0xfb, 0xa, 0xe3, 0x47, 0x6e, 0xa1, 0x18, 0xe8, 0x39, 0x2c}} return a, nil } @@ -547,8 +548,8 @@ func _1610959908_add_dont_wrap_to_raw_messagesUpSql() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "1610959908_add_dont_wrap_to_raw_messages.up.sql", size: 83, mode: os.FileMode(436), modTime: time.Unix(1619724270, 0)} - a := &asset{bytes: bytes, info: info} + info := bindataFileInfo{name: "1610959908_add_dont_wrap_to_raw_messages.up.sql", size: 83, mode: os.FileMode(0644), modTime: time.Unix(1621263711, 0)} + a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x71, 0x2, 0x9a, 0xca, 0xd4, 0x38, 0x44, 0x30, 0x2b, 0xa8, 0x27, 0x32, 0x63, 0x53, 0x22, 0x60, 0x59, 0x84, 0x23, 0x96, 0x77, 0xf0, 0x56, 0xd7, 0x94, 0xe0, 0x95, 0x28, 0x6, 0x1d, 0x4e, 0xb1}} return a, nil } @@ -567,8 +568,8 @@ func _1610960912_add_send_on_personal_topicUpSql() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "1610960912_add_send_on_personal_topic.up.sql", size: 82, mode: os.FileMode(436), modTime: time.Unix(1619724270, 0)} - a := &asset{bytes: bytes, info: info} + info := bindataFileInfo{name: "1610960912_add_send_on_personal_topic.up.sql", size: 82, mode: os.FileMode(0644), modTime: time.Unix(1621263711, 0)} + a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x77, 0xac, 0x2f, 0xc4, 0xd, 0xa7, 0x1b, 0x37, 0x30, 0xc2, 0x68, 0xee, 0xde, 0x54, 0x5e, 0xbf, 0x3f, 0xa0, 0xd6, 0xc6, 0x9f, 0xd4, 0x34, 0x12, 0x76, 0x1e, 0x66, 0x4a, 0xfc, 0xf, 0xee, 0xc9}} return a, nil } @@ -587,8 +588,8 @@ func _1612870480_add_datasync_idUpSql() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "1612870480_add_datasync_id.up.sql", size: 111, mode: os.FileMode(436), modTime: time.Unix(1619724270, 0)} - a := &asset{bytes: bytes, info: info} + info := bindataFileInfo{name: "1612870480_add_datasync_id.up.sql", size: 111, mode: os.FileMode(0644), modTime: time.Unix(1621263711, 0)} + a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x34, 0x9a, 0xbc, 0xfa, 0xaa, 0x8c, 0x9c, 0x37, 0x67, 0x15, 0x9c, 0x7e, 0x78, 0x75, 0x66, 0x82, 0x18, 0x72, 0x10, 0xbc, 0xd4, 0xab, 0x44, 0xfe, 0x57, 0x85, 0x6d, 0x19, 0xf5, 0x96, 0x8a, 0xbe}} return a, nil } @@ -607,8 +608,8 @@ func _1614152139_add_communities_request_to_joinUpSql() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "1614152139_add_communities_request_to_join.up.sql", size: 831, mode: os.FileMode(436), modTime: time.Unix(1619724270, 0)} - a := &asset{bytes: bytes, info: info} + info := bindataFileInfo{name: "1614152139_add_communities_request_to_join.up.sql", size: 831, mode: os.FileMode(0644), modTime: time.Unix(1621263711, 0)} + a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x11, 0x3, 0x26, 0xf9, 0x29, 0x50, 0x4f, 0xcd, 0x46, 0xe5, 0xb1, 0x6b, 0xb9, 0x2, 0x40, 0xb1, 0xdf, 0x4a, 0x4c, 0x7a, 0xda, 0x3, 0x35, 0xcd, 0x2d, 0xcc, 0x80, 0x7d, 0x57, 0x5f, 0x3, 0x5c}} return a, nil } @@ -627,8 +628,8 @@ func _1615374373_add_confirmationsUpSql() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "1615374373_add_confirmations.up.sql", size: 227, mode: os.FileMode(436), modTime: time.Unix(1619724270, 0)} - a := &asset{bytes: bytes, info: info} + info := bindataFileInfo{name: "1615374373_add_confirmations.up.sql", size: 227, mode: os.FileMode(0644), modTime: time.Unix(1621263711, 0)} + a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xdd, 0xa6, 0x65, 0xc5, 0x1d, 0xb2, 0x77, 0x36, 0xe3, 0x79, 0xda, 0xe8, 0x7a, 0xa4, 0xdf, 0x45, 0xae, 0xd8, 0xb4, 0xba, 0x90, 0xfd, 0x74, 0x71, 0x14, 0x75, 0x73, 0x72, 0xb9, 0x9e, 0x1, 0x81}} return a, nil } @@ -647,8 +648,8 @@ func _1617694931_add_notification_centerUpSql() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "1617694931_add_notification_center.up.sql", size: 572, mode: os.FileMode(436), modTime: time.Unix(1619724270, 0)} - a := &asset{bytes: bytes, info: info} + info := bindataFileInfo{name: "1617694931_add_notification_center.up.sql", size: 572, mode: os.FileMode(0644), modTime: time.Unix(1621263711, 0)} + a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x10, 0x45, 0xc6, 0xc9, 0x73, 0xbb, 0x1f, 0xda, 0xa3, 0x4d, 0x19, 0x98, 0x85, 0x2d, 0xca, 0xda, 0xcc, 0x3b, 0x32, 0xff, 0xc7, 0x7b, 0xe3, 0x9f, 0x9b, 0x2a, 0x93, 0xf5, 0xdf, 0x65, 0x38, 0x91}} return a, nil } @@ -667,8 +668,8 @@ func _1618923660_create_pin_messagesUpSql() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "1618923660_create_pin_messages.up.sql", size: 265, mode: os.FileMode(436), modTime: time.Unix(1622139063, 0)} - a := &asset{bytes: bytes, info: info} + info := bindataFileInfo{name: "1618923660_create_pin_messages.up.sql", size: 265, mode: os.FileMode(0644), modTime: time.Unix(1623074824, 0)} + a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x61, 0x44, 0x3a, 0xbe, 0x30, 0xd2, 0x7e, 0xc0, 0xe2, 0x8e, 0x65, 0x53, 0x54, 0xbb, 0x7a, 0x1c, 0xb3, 0x5d, 0xd2, 0xa6, 0xa9, 0x28, 0xb7, 0xa4, 0x5f, 0x8b, 0x9, 0x5f, 0x17, 0xc1, 0x85, 0x21}} return a, nil } @@ -687,8 +688,8 @@ func _1619094007_add_joined_chat_fieldUpSql() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "1619094007_add_joined_chat_field.up.sql", size: 101, mode: os.FileMode(436), modTime: time.Unix(1622139063, 0)} - a := &asset{bytes: bytes, info: info} + info := bindataFileInfo{name: "1619094007_add_joined_chat_field.up.sql", size: 101, mode: os.FileMode(0644), modTime: time.Unix(1623331301, 0)} + a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xfa, 0x30, 0x81, 0x3a, 0x2f, 0x9f, 0xb3, 0x0, 0x55, 0x8e, 0x1d, 0xa8, 0xb0, 0x68, 0xf0, 0x40, 0x1a, 0x6c, 0xaa, 0xfc, 0x33, 0xd1, 0xd1, 0x55, 0x3f, 0xf2, 0xbd, 0x54, 0xa1, 0x2b, 0x40, 0x95}} return a, nil } @@ -707,8 +708,8 @@ func _1619099821_add_last_synced_fieldUpSql() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "1619099821_add_last_synced_field.up.sql", size: 226, mode: os.FileMode(436), modTime: time.Unix(1622139063, 0)} - a := &asset{bytes: bytes, info: info} + info := bindataFileInfo{name: "1619099821_add_last_synced_field.up.sql", size: 226, mode: os.FileMode(0644), modTime: time.Unix(1623331301, 0)} + a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xf, 0x52, 0x22, 0xe, 0x2f, 0xd7, 0x93, 0x5f, 0x42, 0xc2, 0x93, 0x4, 0x35, 0x6f, 0xc9, 0x19, 0xed, 0x6b, 0x52, 0x6f, 0xae, 0x99, 0xe2, 0x68, 0x3d, 0x4f, 0x40, 0xe, 0xe1, 0xa, 0x47, 0x21}} return a, nil } @@ -727,8 +728,8 @@ func _1621933219_add_mentionedUpSql() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "1621933219_add_mentioned.up.sql", size: 70, mode: os.FileMode(436), modTime: time.Unix(1622639492, 0)} - a := &asset{bytes: bytes, info: info} + info := bindataFileInfo{name: "1621933219_add_mentioned.up.sql", size: 70, mode: os.FileMode(0644), modTime: time.Unix(1623331301, 0)} + a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x36, 0x76, 0x8a, 0xc9, 0x7, 0x8f, 0xa5, 0xcb, 0x12, 0x21, 0x4e, 0xfe, 0x96, 0x77, 0xcf, 0x7f, 0x76, 0x75, 0x36, 0x2c, 0xf8, 0x1d, 0x13, 0xcb, 0xcd, 0x6e, 0x70, 0xbf, 0xf5, 0x93, 0x67, 0xd1}} return a, nil } @@ -747,8 +748,8 @@ func _1622010048_add_unviewed_mentions_countUpSql() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "1622010048_add_unviewed_mentions_count.up.sql", size: 114, mode: os.FileMode(436), modTime: time.Unix(1623875362, 0)} - a := &asset{bytes: bytes, info: info} + info := bindataFileInfo{name: "1622010048_add_unviewed_mentions_count.up.sql", size: 114, mode: os.FileMode(0644), modTime: time.Unix(1623331301, 0)} + a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x7c, 0x16, 0x85, 0xa6, 0x5b, 0xe1, 0x66, 0xb9, 0x84, 0xbe, 0x7f, 0xa, 0x77, 0x23, 0xb9, 0xef, 0x8e, 0x2, 0x8, 0xfc, 0x61, 0xb2, 0x43, 0xa9, 0x63, 0xae, 0xb4, 0xdf, 0x30, 0xb1, 0x61, 0x4b}} return a, nil } @@ -767,8 +768,8 @@ func _1622061278_add_message_activity_center_notification_fieldUpSql() (*asset, return nil, err } - info := bindataFileInfo{name: "1622061278_add_message_activity_center_notification_field.up.sql", size: 80, mode: os.FileMode(436), modTime: time.Unix(1623875362, 0)} - a := &asset{bytes: bytes, info: info} + info := bindataFileInfo{name: "1622061278_add_message_activity_center_notification_field.up.sql", size: 80, mode: os.FileMode(0644), modTime: time.Unix(1623331301, 0)} + a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x8, 0xc, 0xa6, 0x1f, 0xa5, 0xc6, 0x7c, 0x6f, 0xab, 0x2c, 0x2d, 0xb5, 0xa4, 0xdd, 0xc1, 0xd6, 0x44, 0x83, 0xf9, 0xb1, 0xa5, 0xce, 0x34, 0x3d, 0x2, 0xa9, 0x35, 0xcf, 0xc6, 0xb2, 0x43, 0x37}} return a, nil } @@ -787,8 +788,8 @@ func _1622464518_set_synced_to_fromUpSql() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "1622464518_set_synced_to_from.up.sql", size: 105, mode: os.FileMode(436), modTime: time.Unix(1623875362, 0)} - a := &asset{bytes: bytes, info: info} + info := bindataFileInfo{name: "1622464518_set_synced_to_from.up.sql", size: 105, mode: os.FileMode(0644), modTime: time.Unix(1623331301, 0)} + a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x33, 0x3e, 0x2b, 0xa, 0x1e, 0xc7, 0x6d, 0x6f, 0xd1, 0x1d, 0xe8, 0x4b, 0xdd, 0x92, 0x76, 0xea, 0xf2, 0x3e, 0x15, 0x85, 0xc4, 0xc3, 0x31, 0xf1, 0xc0, 0xa2, 0xd7, 0x47, 0xde, 0x4e, 0xfd, 0xc6}} return a, nil } @@ -807,8 +808,8 @@ func _1622464519_add_chat_descriptionUpSql() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "1622464519_add_chat_description.up.sql", size: 93, mode: os.FileMode(436), modTime: time.Unix(1623875362, 0)} - a := &asset{bytes: bytes, info: info} + info := bindataFileInfo{name: "1622464519_add_chat_description.up.sql", size: 93, mode: os.FileMode(0644), modTime: time.Unix(1623331301, 0)} + a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x36, 0x2e, 0x89, 0x31, 0xec, 0xef, 0xeb, 0x43, 0xf5, 0x96, 0x6d, 0xce, 0x91, 0x8a, 0x37, 0x2a, 0x11, 0x7a, 0x3f, 0xd9, 0x10, 0xbb, 0xa1, 0xbc, 0x7, 0xe0, 0x3b, 0xa5, 0xf4, 0xa6, 0xf4, 0xa1}} return a, nil } @@ -827,8 +828,8 @@ func _1622622253_add_pinned_by_to_pin_messagesUpSql() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "1622622253_add_pinned_by_to_pin_messages.up.sql", size: 52, mode: os.FileMode(436), modTime: time.Unix(1623875362, 0)} - a := &asset{bytes: bytes, info: info} + info := bindataFileInfo{name: "1622622253_add_pinned_by_to_pin_messages.up.sql", size: 52, mode: os.FileMode(0644), modTime: time.Unix(1628512368, 0)} + a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x9b, 0x94, 0xa3, 0x45, 0x91, 0x1e, 0x66, 0xd1, 0x96, 0x5a, 0xaf, 0xfa, 0x29, 0x39, 0xa8, 0x3a, 0x97, 0x4c, 0x65, 0x6, 0x96, 0x90, 0x4c, 0xfe, 0xce, 0x7d, 0x5d, 0xd4, 0xb3, 0x8, 0x6d, 0x5f}} return a, nil } @@ -847,8 +848,8 @@ func _1623938329_add_author_activity_center_notification_fieldUpSql() (*asset, e return nil, err } - info := bindataFileInfo{name: "1623938329_add_author_activity_center_notification_field.up.sql", size: 66, mode: os.FileMode(436), modTime: time.Unix(1624644228, 0)} - a := &asset{bytes: bytes, info: info} + info := bindataFileInfo{name: "1623938329_add_author_activity_center_notification_field.up.sql", size: 66, mode: os.FileMode(0644), modTime: time.Unix(1628714143, 0)} + a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x36, 0xe6, 0xa7, 0xd5, 0x26, 0xff, 0xab, 0x92, 0x88, 0xf0, 0xd3, 0x34, 0xd9, 0x2f, 0xe7, 0x18, 0x1a, 0x40, 0xf9, 0xbe, 0x8e, 0xfc, 0xd0, 0x4f, 0x1f, 0x4a, 0xb9, 0x83, 0x3f, 0xa9, 0xde, 0xb}} return a, nil } @@ -867,8 +868,8 @@ func _1623938330_add_edit_messagesUpSql() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "1623938330_add_edit_messages.up.sql", size: 369, mode: os.FileMode(436), modTime: time.Unix(1627596885, 0)} - a := &asset{bytes: bytes, info: info} + info := bindataFileInfo{name: "1623938330_add_edit_messages.up.sql", size: 369, mode: os.FileMode(0644), modTime: time.Unix(1628714143, 0)} + a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x7e, 0xd2, 0xce, 0xe, 0x5c, 0x19, 0xbe, 0x5e, 0x29, 0xbe, 0x9b, 0x31, 0x53, 0x76, 0xb2, 0xc8, 0x56, 0xf0, 0x82, 0xfe, 0x7d, 0x6c, 0xe8, 0x5c, 0xe9, 0x7a, 0x5d, 0x5, 0xc4, 0x92, 0x38, 0xe3}} return a, nil } @@ -887,8 +888,8 @@ func _1624978434_add_muted_communityUpSql() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "1624978434_add_muted_community.up.sql", size: 82, mode: os.FileMode(436), modTime: time.Unix(1627596885, 0)} - a := &asset{bytes: bytes, info: info} + info := bindataFileInfo{name: "1624978434_add_muted_community.up.sql", size: 82, mode: os.FileMode(0644), modTime: time.Unix(1628714143, 0)} + a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x6, 0xdc, 0x6e, 0x6f, 0x97, 0xc7, 0x3d, 0x50, 0xab, 0x80, 0x87, 0x44, 0x43, 0x38, 0xe6, 0xc5, 0xc1, 0x91, 0x26, 0xf, 0x16, 0xe, 0xd9, 0x32, 0x37, 0x25, 0x96, 0x25, 0x6, 0xc8, 0xb5, 0x4a}} return a, nil } @@ -907,8 +908,8 @@ func _1625018910_add_repply_message_activity_center_notification_fieldUpSql() (* return nil, err } - info := bindataFileInfo{name: "1625018910_add_repply_message_activity_center_notification_field.up.sql", size: 86, mode: os.FileMode(436), modTime: time.Unix(1627596885, 0)} - a := &asset{bytes: bytes, info: info} + info := bindataFileInfo{name: "1625018910_add_repply_message_activity_center_notification_field.up.sql", size: 86, mode: os.FileMode(0644), modTime: time.Unix(1628714143, 0)} + a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xf2, 0x52, 0x12, 0x40, 0xd8, 0x6f, 0x71, 0x97, 0x46, 0x39, 0xaa, 0x74, 0x41, 0xcd, 0x45, 0x4c, 0xe8, 0xd9, 0xe2, 0x56, 0x8e, 0x78, 0x18, 0x62, 0xf6, 0xa8, 0x36, 0xe9, 0x9a, 0x1f, 0xc, 0xb1}} return a, nil } @@ -927,8 +928,8 @@ func _1625762506_add_deleted_messagesUpSql() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "1625762506_add_deleted_messages.up.sql", size: 357, mode: os.FileMode(436), modTime: time.Unix(1628037120, 0)} - a := &asset{bytes: bytes, info: info} + info := bindataFileInfo{name: "1625762506_add_deleted_messages.up.sql", size: 357, mode: os.FileMode(0644), modTime: time.Unix(1628714143, 0)} + a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xd5, 0x61, 0x42, 0xb6, 0x8c, 0x7f, 0x2d, 0xec, 0xa9, 0x6d, 0x3d, 0x0, 0xa3, 0x32, 0xd8, 0x4a, 0x38, 0x5c, 0x97, 0xfc, 0x68, 0xde, 0xa9, 0xb7, 0xd8, 0xde, 0xb, 0x29, 0x93, 0xdc, 0x81, 0xf8}} return a, nil } @@ -947,8 +948,8 @@ func _1627388946_add_communities_synced_atUpSql() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "1627388946_add_communities_synced_at.up.sql", size: 87, mode: os.FileMode(436), modTime: time.Unix(1628280009, 0)} - a := &asset{bytes: bytes, info: info} + info := bindataFileInfo{name: "1627388946_add_communities_synced_at.up.sql", size: 87, mode: os.FileMode(0644), modTime: time.Unix(1628714143, 0)} + a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xc1, 0xbd, 0x9b, 0x6a, 0xc9, 0x1a, 0x7a, 0x34, 0xcf, 0x5f, 0x80, 0x9e, 0x8c, 0x1c, 0xc0, 0xec, 0x4e, 0x78, 0xb0, 0x2d, 0x15, 0x77, 0x38, 0x4a, 0x6a, 0x5, 0x84, 0xf5, 0x8d, 0x8b, 0xbe, 0x9}} return a, nil } @@ -967,8 +968,8 @@ func _1628280060_createUsermessagesIndexSql() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "1628280060_create-usermessages-index.sql", size: 80, mode: os.FileMode(436), modTime: time.Unix(1628280187, 0)} - a := &asset{bytes: bytes, info: info} + info := bindataFileInfo{name: "1628280060_create-usermessages-index.sql", size: 80, mode: os.FileMode(0644), modTime: time.Unix(1629202661, 0)} + a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x10, 0x6f, 0x70, 0x47, 0x40, 0xab, 0xa8, 0x60, 0xe0, 0xf9, 0x8, 0x7e, 0x19, 0x9d, 0xba, 0x33, 0x16, 0xfc, 0x3c, 0xdc, 0xa8, 0xa6, 0x53, 0x61, 0x39, 0x82, 0x91, 0xcf, 0x69, 0xd8, 0xf2, 0xcf}} return a, nil } @@ -987,8 +988,8 @@ func readmeMd() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "README.md", size: 554, mode: os.FileMode(436), modTime: time.Unix(1619724270, 0)} - a := &asset{bytes: bytes, info: info} + info := bindataFileInfo{name: "README.md", size: 554, mode: os.FileMode(0644), modTime: time.Unix(1621263711, 0)} + a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x1c, 0x6e, 0xfb, 0xcc, 0x81, 0x94, 0x4d, 0x8c, 0xa0, 0x3b, 0x5, 0xb0, 0x18, 0xd6, 0xbb, 0xb3, 0x79, 0xc8, 0x8f, 0xff, 0xc1, 0x10, 0xf9, 0xf, 0x20, 0x1b, 0x4a, 0x74, 0x96, 0x42, 0xd7, 0xa8}} return a, nil } @@ -1007,8 +1008,8 @@ func docGo() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "doc.go", size: 850, mode: os.FileMode(436), modTime: time.Unix(1619724270, 0)} - a := &asset{bytes: bytes, info: info} + info := bindataFileInfo{name: "doc.go", size: 850, mode: os.FileMode(0644), modTime: time.Unix(1621263711, 0)} + a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xa0, 0xcc, 0x41, 0xe1, 0x61, 0x12, 0x97, 0xe, 0x36, 0x8c, 0xa7, 0x9e, 0xe0, 0x6e, 0x59, 0x9e, 0xee, 0xd5, 0x4a, 0xcf, 0x1e, 0x60, 0xd6, 0xc3, 0x3a, 0xc9, 0x6c, 0xf2, 0x86, 0x5a, 0xb4, 0x1e}} return a, nil } @@ -1016,8 +1017,8 @@ func docGo() (*asset, error) { // It returns an error if the asset could not be found or // could not be loaded. func Asset(name string) ([]byte, error) { - cannonicalName := strings.Replace(name, "\\", "/", -1) - if f, ok := _bindata[cannonicalName]; ok { + canonicalName := strings.Replace(name, "\\", "/", -1) + if f, ok := _bindata[canonicalName]; ok { a, err := f() if err != nil { return nil, fmt.Errorf("Asset %s can't read by error: %v", name, err) @@ -1027,6 +1028,12 @@ func Asset(name string) ([]byte, error) { return nil, fmt.Errorf("Asset %s not found", name) } +// AssetString returns the asset contents as a string (instead of a []byte). +func AssetString(name string) (string, error) { + data, err := Asset(name) + return string(data), err +} + // MustAsset is like Asset but panics when Asset would return an error. // It simplifies safe initialization of global variables. func MustAsset(name string) []byte { @@ -1038,12 +1045,18 @@ func MustAsset(name string) []byte { return a } +// MustAssetString is like AssetString but panics when Asset would return an +// error. It simplifies safe initialization of global variables. +func MustAssetString(name string) string { + return string(MustAsset(name)) +} + // AssetInfo loads and returns the asset info for the given name. // It returns an error if the asset could not be found or // could not be loaded. func AssetInfo(name string) (os.FileInfo, error) { - cannonicalName := strings.Replace(name, "\\", "/", -1) - if f, ok := _bindata[cannonicalName]; ok { + canonicalName := strings.Replace(name, "\\", "/", -1) + if f, ok := _bindata[canonicalName]; ok { a, err := f() if err != nil { return nil, fmt.Errorf("AssetInfo %s can't read by error: %v", name, err) @@ -1053,6 +1066,33 @@ func AssetInfo(name string) (os.FileInfo, error) { return nil, fmt.Errorf("AssetInfo %s not found", name) } +// AssetDigest returns the digest of the file with the given name. It returns an +// error if the asset could not be found or the digest could not be loaded. +func AssetDigest(name string) ([sha256.Size]byte, error) { + canonicalName := strings.Replace(name, "\\", "/", -1) + if f, ok := _bindata[canonicalName]; ok { + a, err := f() + if err != nil { + return [sha256.Size]byte{}, fmt.Errorf("AssetDigest %s can't read by error: %v", name, err) + } + return a.digest, nil + } + return [sha256.Size]byte{}, fmt.Errorf("AssetDigest %s not found", name) +} + +// Digests returns a map of all known files and their checksums. +func Digests() (map[string][sha256.Size]byte, error) { + mp := make(map[string][sha256.Size]byte, len(_bindata)) + for name := range _bindata { + a, err := _bindata[name]() + if err != nil { + return nil, err + } + mp[name] = a.digest + } + return mp, nil +} + // AssetNames returns the names of the assets. func AssetNames() []string { names := make([]string, 0, len(_bindata)) @@ -1065,49 +1105,93 @@ func AssetNames() []string { // _bindata is a table, holding each asset generator, mapped to its name. var _bindata = map[string]func() (*asset, error){ "000001_init.down.db.sql": _000001_initDownDbSql, + "000001_init.up.db.sql": _000001_initUpDbSql, + "000002_add_last_ens_clock_value.up.sql": _000002_add_last_ens_clock_valueUpSql, + "1586358095_add_replace.up.sql": _1586358095_add_replaceUpSql, + "1588665364_add_image_data.up.sql": _1588665364_add_image_dataUpSql, + "1589365189_add_pow_target.up.sql": _1589365189_add_pow_targetUpSql, + "1591277220_add_index_messages.up.sql": _1591277220_add_index_messagesUpSql, + "1593087212_add_mute_chat_and_raw_message_fields.up.sql": _1593087212_add_mute_chat_and_raw_message_fieldsUpSql, + "1595862781_add_audio_data.up.sql": _1595862781_add_audio_dataUpSql, + "1595865249_create_emoji_reactions_table.up.sql": _1595865249_create_emoji_reactions_tableUpSql, + "1596805115_create_group_chat_invitations_table.up.sql": _1596805115_create_group_chat_invitations_tableUpSql, + "1597322655_add_invitation_admin_chat_field.up.sql": _1597322655_add_invitation_admin_chat_fieldUpSql, + "1597757544_add_nickname.up.sql": _1597757544_add_nicknameUpSql, + "1598955122_add_mentions.up.sql": _1598955122_add_mentionsUpSql, + "1599641390_add_emoji_reactions_index.up.sql": _1599641390_add_emoji_reactions_indexUpSql, + "1599720851_add_seen_index_remove_long_messages.up.sql": _1599720851_add_seen_index_remove_long_messagesUpSql, + "1603198582_add_profile_chat_field.up.sql": _1603198582_add_profile_chat_fieldUpSql, + "1603816533_add_links.up.sql": _1603816533_add_linksUpSql, + "1603888149_create_chat_identity_last_published_table.up.sql": _1603888149_create_chat_identity_last_published_tableUpSql, + "1605075346_add_communities.up.sql": _1605075346_add_communitiesUpSql, + "1610117927_add_message_cache.up.sql": _1610117927_add_message_cacheUpSql, + "1610959908_add_dont_wrap_to_raw_messages.up.sql": _1610959908_add_dont_wrap_to_raw_messagesUpSql, + "1610960912_add_send_on_personal_topic.up.sql": _1610960912_add_send_on_personal_topicUpSql, + "1612870480_add_datasync_id.up.sql": _1612870480_add_datasync_idUpSql, + "1614152139_add_communities_request_to_join.up.sql": _1614152139_add_communities_request_to_joinUpSql, + "1615374373_add_confirmations.up.sql": _1615374373_add_confirmationsUpSql, + "1617694931_add_notification_center.up.sql": _1617694931_add_notification_centerUpSql, + "1618923660_create_pin_messages.up.sql": _1618923660_create_pin_messagesUpSql, + "1619094007_add_joined_chat_field.up.sql": _1619094007_add_joined_chat_fieldUpSql, + "1619099821_add_last_synced_field.up.sql": _1619099821_add_last_synced_fieldUpSql, + "1621933219_add_mentioned.up.sql": _1621933219_add_mentionedUpSql, + "1622010048_add_unviewed_mentions_count.up.sql": _1622010048_add_unviewed_mentions_countUpSql, + "1622061278_add_message_activity_center_notification_field.up.sql": _1622061278_add_message_activity_center_notification_fieldUpSql, + "1622464518_set_synced_to_from.up.sql": _1622464518_set_synced_to_fromUpSql, + "1622464519_add_chat_description.up.sql": _1622464519_add_chat_descriptionUpSql, + "1622622253_add_pinned_by_to_pin_messages.up.sql": _1622622253_add_pinned_by_to_pin_messagesUpSql, + "1623938329_add_author_activity_center_notification_field.up.sql": _1623938329_add_author_activity_center_notification_fieldUpSql, + "1623938330_add_edit_messages.up.sql": _1623938330_add_edit_messagesUpSql, + "1624978434_add_muted_community.up.sql": _1624978434_add_muted_communityUpSql, + "1625018910_add_repply_message_activity_center_notification_field.up.sql": _1625018910_add_repply_message_activity_center_notification_fieldUpSql, + "1625762506_add_deleted_messages.up.sql": _1625762506_add_deleted_messagesUpSql, + "1627388946_add_communities_synced_at.up.sql": _1627388946_add_communities_synced_atUpSql, + "1628280060_create-usermessages-index.sql": _1628280060_createUsermessagesIndexSql, + "README.md": readmeMd, + "doc.go": docGo, } @@ -1120,15 +1204,15 @@ var _bindata = map[string]func() (*asset, error){ // img/ // a.png // b.png -// then AssetDir("data") would return []string{"foo.txt", "img"} -// AssetDir("data/img") would return []string{"a.png", "b.png"} -// AssetDir("foo.txt") and AssetDir("notexist") would return an error +// then AssetDir("data") would return []string{"foo.txt", "img"}, +// AssetDir("data/img") would return []string{"a.png", "b.png"}, +// AssetDir("foo.txt") and AssetDir("notexist") would return an error, and // AssetDir("") will return []string{"data"}. func AssetDir(name string) ([]string, error) { node := _bintree if len(name) != 0 { - cannonicalName := strings.Replace(name, "\\", "/", -1) - pathList := strings.Split(cannonicalName, "/") + canonicalName := strings.Replace(name, "\\", "/", -1) + pathList := strings.Split(canonicalName, "/") for _, p := range pathList { node = node.Children[p] if node == nil { @@ -1150,55 +1234,56 @@ type bintree struct { Func func() (*asset, error) Children map[string]*bintree } + var _bintree = &bintree{nil, map[string]*bintree{ - "000001_init.down.db.sql": &bintree{_000001_initDownDbSql, map[string]*bintree{}}, - "000001_init.up.db.sql": &bintree{_000001_initUpDbSql, map[string]*bintree{}}, - "000002_add_last_ens_clock_value.up.sql": &bintree{_000002_add_last_ens_clock_valueUpSql, map[string]*bintree{}}, - "1586358095_add_replace.up.sql": &bintree{_1586358095_add_replaceUpSql, map[string]*bintree{}}, - "1588665364_add_image_data.up.sql": &bintree{_1588665364_add_image_dataUpSql, map[string]*bintree{}}, - "1589365189_add_pow_target.up.sql": &bintree{_1589365189_add_pow_targetUpSql, map[string]*bintree{}}, - "1591277220_add_index_messages.up.sql": &bintree{_1591277220_add_index_messagesUpSql, map[string]*bintree{}}, - "1593087212_add_mute_chat_and_raw_message_fields.up.sql": &bintree{_1593087212_add_mute_chat_and_raw_message_fieldsUpSql, map[string]*bintree{}}, - "1595862781_add_audio_data.up.sql": &bintree{_1595862781_add_audio_dataUpSql, map[string]*bintree{}}, - "1595865249_create_emoji_reactions_table.up.sql": &bintree{_1595865249_create_emoji_reactions_tableUpSql, map[string]*bintree{}}, - "1596805115_create_group_chat_invitations_table.up.sql": &bintree{_1596805115_create_group_chat_invitations_tableUpSql, map[string]*bintree{}}, - "1597322655_add_invitation_admin_chat_field.up.sql": &bintree{_1597322655_add_invitation_admin_chat_fieldUpSql, map[string]*bintree{}}, - "1597757544_add_nickname.up.sql": &bintree{_1597757544_add_nicknameUpSql, map[string]*bintree{}}, - "1598955122_add_mentions.up.sql": &bintree{_1598955122_add_mentionsUpSql, map[string]*bintree{}}, - "1599641390_add_emoji_reactions_index.up.sql": &bintree{_1599641390_add_emoji_reactions_indexUpSql, map[string]*bintree{}}, - "1599720851_add_seen_index_remove_long_messages.up.sql": &bintree{_1599720851_add_seen_index_remove_long_messagesUpSql, map[string]*bintree{}}, - "1603198582_add_profile_chat_field.up.sql": &bintree{_1603198582_add_profile_chat_fieldUpSql, map[string]*bintree{}}, - "1603816533_add_links.up.sql": &bintree{_1603816533_add_linksUpSql, map[string]*bintree{}}, - "1603888149_create_chat_identity_last_published_table.up.sql": &bintree{_1603888149_create_chat_identity_last_published_tableUpSql, map[string]*bintree{}}, - "1605075346_add_communities.up.sql": &bintree{_1605075346_add_communitiesUpSql, map[string]*bintree{}}, - "1610117927_add_message_cache.up.sql": &bintree{_1610117927_add_message_cacheUpSql, map[string]*bintree{}}, - "1610959908_add_dont_wrap_to_raw_messages.up.sql": &bintree{_1610959908_add_dont_wrap_to_raw_messagesUpSql, map[string]*bintree{}}, - "1610960912_add_send_on_personal_topic.up.sql": &bintree{_1610960912_add_send_on_personal_topicUpSql, map[string]*bintree{}}, - "1612870480_add_datasync_id.up.sql": &bintree{_1612870480_add_datasync_idUpSql, map[string]*bintree{}}, - "1614152139_add_communities_request_to_join.up.sql": &bintree{_1614152139_add_communities_request_to_joinUpSql, map[string]*bintree{}}, - "1615374373_add_confirmations.up.sql": &bintree{_1615374373_add_confirmationsUpSql, map[string]*bintree{}}, - "1617694931_add_notification_center.up.sql": &bintree{_1617694931_add_notification_centerUpSql, map[string]*bintree{}}, - "1618923660_create_pin_messages.up.sql": &bintree{_1618923660_create_pin_messagesUpSql, map[string]*bintree{}}, - "1619094007_add_joined_chat_field.up.sql": &bintree{_1619094007_add_joined_chat_fieldUpSql, map[string]*bintree{}}, - "1619099821_add_last_synced_field.up.sql": &bintree{_1619099821_add_last_synced_fieldUpSql, map[string]*bintree{}}, - "1621933219_add_mentioned.up.sql": &bintree{_1621933219_add_mentionedUpSql, map[string]*bintree{}}, - "1622010048_add_unviewed_mentions_count.up.sql": &bintree{_1622010048_add_unviewed_mentions_countUpSql, map[string]*bintree{}}, - "1622061278_add_message_activity_center_notification_field.up.sql": &bintree{_1622061278_add_message_activity_center_notification_fieldUpSql, map[string]*bintree{}}, - "1622464518_set_synced_to_from.up.sql": &bintree{_1622464518_set_synced_to_fromUpSql, map[string]*bintree{}}, - "1622464519_add_chat_description.up.sql": &bintree{_1622464519_add_chat_descriptionUpSql, map[string]*bintree{}}, - "1622622253_add_pinned_by_to_pin_messages.up.sql": &bintree{_1622622253_add_pinned_by_to_pin_messagesUpSql, map[string]*bintree{}}, - "1623938329_add_author_activity_center_notification_field.up.sql": &bintree{_1623938329_add_author_activity_center_notification_fieldUpSql, map[string]*bintree{}}, - "1623938330_add_edit_messages.up.sql": &bintree{_1623938330_add_edit_messagesUpSql, map[string]*bintree{}}, - "1624978434_add_muted_community.up.sql": &bintree{_1624978434_add_muted_communityUpSql, map[string]*bintree{}}, + "000001_init.down.db.sql": &bintree{_000001_initDownDbSql, map[string]*bintree{}}, + "000001_init.up.db.sql": &bintree{_000001_initUpDbSql, map[string]*bintree{}}, + "000002_add_last_ens_clock_value.up.sql": &bintree{_000002_add_last_ens_clock_valueUpSql, map[string]*bintree{}}, + "1586358095_add_replace.up.sql": &bintree{_1586358095_add_replaceUpSql, map[string]*bintree{}}, + "1588665364_add_image_data.up.sql": &bintree{_1588665364_add_image_dataUpSql, map[string]*bintree{}}, + "1589365189_add_pow_target.up.sql": &bintree{_1589365189_add_pow_targetUpSql, map[string]*bintree{}}, + "1591277220_add_index_messages.up.sql": &bintree{_1591277220_add_index_messagesUpSql, map[string]*bintree{}}, + "1593087212_add_mute_chat_and_raw_message_fields.up.sql": &bintree{_1593087212_add_mute_chat_and_raw_message_fieldsUpSql, map[string]*bintree{}}, + "1595862781_add_audio_data.up.sql": &bintree{_1595862781_add_audio_dataUpSql, map[string]*bintree{}}, + "1595865249_create_emoji_reactions_table.up.sql": &bintree{_1595865249_create_emoji_reactions_tableUpSql, map[string]*bintree{}}, + "1596805115_create_group_chat_invitations_table.up.sql": &bintree{_1596805115_create_group_chat_invitations_tableUpSql, map[string]*bintree{}}, + "1597322655_add_invitation_admin_chat_field.up.sql": &bintree{_1597322655_add_invitation_admin_chat_fieldUpSql, map[string]*bintree{}}, + "1597757544_add_nickname.up.sql": &bintree{_1597757544_add_nicknameUpSql, map[string]*bintree{}}, + "1598955122_add_mentions.up.sql": &bintree{_1598955122_add_mentionsUpSql, map[string]*bintree{}}, + "1599641390_add_emoji_reactions_index.up.sql": &bintree{_1599641390_add_emoji_reactions_indexUpSql, map[string]*bintree{}}, + "1599720851_add_seen_index_remove_long_messages.up.sql": &bintree{_1599720851_add_seen_index_remove_long_messagesUpSql, map[string]*bintree{}}, + "1603198582_add_profile_chat_field.up.sql": &bintree{_1603198582_add_profile_chat_fieldUpSql, map[string]*bintree{}}, + "1603816533_add_links.up.sql": &bintree{_1603816533_add_linksUpSql, map[string]*bintree{}}, + "1603888149_create_chat_identity_last_published_table.up.sql": &bintree{_1603888149_create_chat_identity_last_published_tableUpSql, map[string]*bintree{}}, + "1605075346_add_communities.up.sql": &bintree{_1605075346_add_communitiesUpSql, map[string]*bintree{}}, + "1610117927_add_message_cache.up.sql": &bintree{_1610117927_add_message_cacheUpSql, map[string]*bintree{}}, + "1610959908_add_dont_wrap_to_raw_messages.up.sql": &bintree{_1610959908_add_dont_wrap_to_raw_messagesUpSql, map[string]*bintree{}}, + "1610960912_add_send_on_personal_topic.up.sql": &bintree{_1610960912_add_send_on_personal_topicUpSql, map[string]*bintree{}}, + "1612870480_add_datasync_id.up.sql": &bintree{_1612870480_add_datasync_idUpSql, map[string]*bintree{}}, + "1614152139_add_communities_request_to_join.up.sql": &bintree{_1614152139_add_communities_request_to_joinUpSql, map[string]*bintree{}}, + "1615374373_add_confirmations.up.sql": &bintree{_1615374373_add_confirmationsUpSql, map[string]*bintree{}}, + "1617694931_add_notification_center.up.sql": &bintree{_1617694931_add_notification_centerUpSql, map[string]*bintree{}}, + "1618923660_create_pin_messages.up.sql": &bintree{_1618923660_create_pin_messagesUpSql, map[string]*bintree{}}, + "1619094007_add_joined_chat_field.up.sql": &bintree{_1619094007_add_joined_chat_fieldUpSql, map[string]*bintree{}}, + "1619099821_add_last_synced_field.up.sql": &bintree{_1619099821_add_last_synced_fieldUpSql, map[string]*bintree{}}, + "1621933219_add_mentioned.up.sql": &bintree{_1621933219_add_mentionedUpSql, map[string]*bintree{}}, + "1622010048_add_unviewed_mentions_count.up.sql": &bintree{_1622010048_add_unviewed_mentions_countUpSql, map[string]*bintree{}}, + "1622061278_add_message_activity_center_notification_field.up.sql": &bintree{_1622061278_add_message_activity_center_notification_fieldUpSql, map[string]*bintree{}}, + "1622464518_set_synced_to_from.up.sql": &bintree{_1622464518_set_synced_to_fromUpSql, map[string]*bintree{}}, + "1622464519_add_chat_description.up.sql": &bintree{_1622464519_add_chat_descriptionUpSql, map[string]*bintree{}}, + "1622622253_add_pinned_by_to_pin_messages.up.sql": &bintree{_1622622253_add_pinned_by_to_pin_messagesUpSql, map[string]*bintree{}}, + "1623938329_add_author_activity_center_notification_field.up.sql": &bintree{_1623938329_add_author_activity_center_notification_fieldUpSql, map[string]*bintree{}}, + "1623938330_add_edit_messages.up.sql": &bintree{_1623938330_add_edit_messagesUpSql, map[string]*bintree{}}, + "1624978434_add_muted_community.up.sql": &bintree{_1624978434_add_muted_communityUpSql, map[string]*bintree{}}, "1625018910_add_repply_message_activity_center_notification_field.up.sql": &bintree{_1625018910_add_repply_message_activity_center_notification_fieldUpSql, map[string]*bintree{}}, - "1625762506_add_deleted_messages.up.sql": &bintree{_1625762506_add_deleted_messagesUpSql, map[string]*bintree{}}, - "1627388946_add_communities_synced_at.up.sql": &bintree{_1627388946_add_communities_synced_atUpSql, map[string]*bintree{}}, - "1628280060_create-usermessages-index.sql": &bintree{_1628280060_createUsermessagesIndexSql, map[string]*bintree{}}, + "1625762506_add_deleted_messages.up.sql": &bintree{_1625762506_add_deleted_messagesUpSql, map[string]*bintree{}}, + "1627388946_add_communities_synced_at.up.sql": &bintree{_1627388946_add_communities_synced_atUpSql, map[string]*bintree{}}, + "1628280060_create-usermessages-index.sql": &bintree{_1628280060_createUsermessagesIndexSql, map[string]*bintree{}}, "README.md": &bintree{readmeMd, map[string]*bintree{}}, - "doc.go": &bintree{docGo, map[string]*bintree{}}, + "doc.go": &bintree{docGo, map[string]*bintree{}}, }} -// RestoreAsset restores an asset under the given directory +// RestoreAsset restores an asset under the given directory. func RestoreAsset(dir, name string) error { data, err := Asset(name) if err != nil { @@ -1216,14 +1301,10 @@ func RestoreAsset(dir, name string) error { if err != nil { return err } - err = os.Chtimes(_filePath(dir, name), info.ModTime(), info.ModTime()) - if err != nil { - return err - } - return nil + return os.Chtimes(_filePath(dir, name), info.ModTime(), info.ModTime()) } -// RestoreAssets restores an asset under the given directory recursively +// RestoreAssets restores an asset under the given directory recursively. func RestoreAssets(dir, name string) error { children, err := AssetDir(name) // File @@ -1241,7 +1322,6 @@ func RestoreAssets(dir, name string) error { } func _filePath(dir, name string) string { - cannonicalName := strings.Replace(name, "\\", "/", -1) - return filepath.Join(append([]string{dir}, strings.Split(cannonicalName, "/")...)...) + canonicalName := strings.Replace(name, "\\", "/", -1) + return filepath.Join(append([]string{dir}, strings.Split(canonicalName, "/")...)...) } - diff --git a/protocol/protobuf/anon_metrics.pb.go b/protocol/protobuf/anon_metrics.pb.go new file mode 100644 index 000000000..784d1ed24 --- /dev/null +++ b/protocol/protobuf/anon_metrics.pb.go @@ -0,0 +1,188 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// source: anon_metrics.proto + +package protobuf + +import ( + fmt "fmt" + proto "github.com/golang/protobuf/proto" + timestamp "github.com/golang/protobuf/ptypes/timestamp" + 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 + +// AnonymousMetric represents a single metric data point +type AnonymousMetric struct { + // id is the unique id of the metric message + Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` + // event is the app metric event type + Event string `protobuf:"bytes,2,opt,name=event,proto3" json:"event,omitempty"` + // value is a filtered and validated raw json payload attached to the event + Value []byte `protobuf:"bytes,3,opt,name=value,proto3" json:"value,omitempty"` + // app_version is the version of the `status-react` app that the metric came from + AppVersion string `protobuf:"bytes,4,opt,name=app_version,json=appVersion,proto3" json:"app_version,omitempty"` + // os is the operating system of the device the application is installed on + Os string `protobuf:"bytes,5,opt,name=os,proto3" json:"os,omitempty"` + // session_id is the id of the session the metric was recorded in + SessionId string `protobuf:"bytes,6,opt,name=session_id,json=sessionId,proto3" json:"session_id,omitempty"` + // created_at is the datetime at which the metric was stored in the local db + CreatedAt *timestamp.Timestamp `protobuf:"bytes,7,opt,name=created_at,json=createdAt,proto3" json:"created_at,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *AnonymousMetric) Reset() { *m = AnonymousMetric{} } +func (m *AnonymousMetric) String() string { return proto.CompactTextString(m) } +func (*AnonymousMetric) ProtoMessage() {} +func (*AnonymousMetric) Descriptor() ([]byte, []int) { + return fileDescriptor_4be044a92fa0408c, []int{0} +} + +func (m *AnonymousMetric) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_AnonymousMetric.Unmarshal(m, b) +} +func (m *AnonymousMetric) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_AnonymousMetric.Marshal(b, m, deterministic) +} +func (m *AnonymousMetric) XXX_Merge(src proto.Message) { + xxx_messageInfo_AnonymousMetric.Merge(m, src) +} +func (m *AnonymousMetric) XXX_Size() int { + return xxx_messageInfo_AnonymousMetric.Size(m) +} +func (m *AnonymousMetric) XXX_DiscardUnknown() { + xxx_messageInfo_AnonymousMetric.DiscardUnknown(m) +} + +var xxx_messageInfo_AnonymousMetric proto.InternalMessageInfo + +func (m *AnonymousMetric) GetId() string { + if m != nil { + return m.Id + } + return "" +} + +func (m *AnonymousMetric) GetEvent() string { + if m != nil { + return m.Event + } + return "" +} + +func (m *AnonymousMetric) GetValue() []byte { + if m != nil { + return m.Value + } + return nil +} + +func (m *AnonymousMetric) GetAppVersion() string { + if m != nil { + return m.AppVersion + } + return "" +} + +func (m *AnonymousMetric) GetOs() string { + if m != nil { + return m.Os + } + return "" +} + +func (m *AnonymousMetric) GetSessionId() string { + if m != nil { + return m.SessionId + } + return "" +} + +func (m *AnonymousMetric) GetCreatedAt() *timestamp.Timestamp { + if m != nil { + return m.CreatedAt + } + return nil +} + +// AnonymousMetricBatch represents a batch of AnonymousMetrics allowing broadcast of AnonymousMetrics with fewer messages +type AnonymousMetricBatch struct { + // metrics is an array of AnonymousMetric metrics + Metrics []*AnonymousMetric `protobuf:"bytes,1,rep,name=metrics,proto3" json:"metrics,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *AnonymousMetricBatch) Reset() { *m = AnonymousMetricBatch{} } +func (m *AnonymousMetricBatch) String() string { return proto.CompactTextString(m) } +func (*AnonymousMetricBatch) ProtoMessage() {} +func (*AnonymousMetricBatch) Descriptor() ([]byte, []int) { + return fileDescriptor_4be044a92fa0408c, []int{1} +} + +func (m *AnonymousMetricBatch) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_AnonymousMetricBatch.Unmarshal(m, b) +} +func (m *AnonymousMetricBatch) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_AnonymousMetricBatch.Marshal(b, m, deterministic) +} +func (m *AnonymousMetricBatch) XXX_Merge(src proto.Message) { + xxx_messageInfo_AnonymousMetricBatch.Merge(m, src) +} +func (m *AnonymousMetricBatch) XXX_Size() int { + return xxx_messageInfo_AnonymousMetricBatch.Size(m) +} +func (m *AnonymousMetricBatch) XXX_DiscardUnknown() { + xxx_messageInfo_AnonymousMetricBatch.DiscardUnknown(m) +} + +var xxx_messageInfo_AnonymousMetricBatch proto.InternalMessageInfo + +func (m *AnonymousMetricBatch) GetMetrics() []*AnonymousMetric { + if m != nil { + return m.Metrics + } + return nil +} + +func init() { + proto.RegisterType((*AnonymousMetric)(nil), "protobuf.AnonymousMetric") + proto.RegisterType((*AnonymousMetricBatch)(nil), "protobuf.AnonymousMetricBatch") +} + +func init() { + proto.RegisterFile("anon_metrics.proto", fileDescriptor_4be044a92fa0408c) +} + +var fileDescriptor_4be044a92fa0408c = []byte{ + // 269 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x5c, 0x90, 0x3d, 0x6b, 0xc3, 0x30, + 0x10, 0x86, 0x51, 0xd2, 0x24, 0xf5, 0xb9, 0x1f, 0x20, 0x32, 0xa8, 0x81, 0x12, 0x93, 0xc9, 0x93, + 0x0d, 0xc9, 0x54, 0x3a, 0x25, 0x5b, 0x29, 0x5d, 0x4c, 0xe9, 0xd0, 0xc5, 0x28, 0xb6, 0x9a, 0x0a, + 0x62, 0x9d, 0xb0, 0x64, 0x43, 0xff, 0x69, 0x7f, 0x4e, 0xb1, 0x64, 0x51, 0xc8, 0x24, 0xdd, 0xa3, + 0xf7, 0x5e, 0x78, 0x04, 0x94, 0x2b, 0x54, 0x65, 0x23, 0x6c, 0x2b, 0x2b, 0x93, 0xe9, 0x16, 0x2d, + 0xd2, 0x6b, 0x77, 0x1c, 0xbb, 0xaf, 0xd5, 0xfa, 0x84, 0x78, 0x3a, 0x8b, 0x3c, 0x80, 0xdc, 0xca, + 0x46, 0x18, 0xcb, 0x1b, 0xed, 0xa3, 0x9b, 0x5f, 0x02, 0xf7, 0x7b, 0x85, 0xea, 0xa7, 0xc1, 0xce, + 0xbc, 0xb9, 0x16, 0x7a, 0x07, 0x13, 0x59, 0x33, 0x92, 0x90, 0x34, 0x2a, 0x26, 0xb2, 0xa6, 0x4b, + 0x98, 0x89, 0x5e, 0x28, 0xcb, 0x26, 0x0e, 0xf9, 0x61, 0xa0, 0x3d, 0x3f, 0x77, 0x82, 0x4d, 0x13, + 0x92, 0xde, 0x14, 0x7e, 0xa0, 0x6b, 0x88, 0xb9, 0xd6, 0x65, 0x2f, 0x5a, 0x23, 0x51, 0xb1, 0x2b, + 0xb7, 0x01, 0x5c, 0xeb, 0x0f, 0x4f, 0x86, 0x72, 0x34, 0x6c, 0xe6, 0xcb, 0xd1, 0xd0, 0x47, 0x00, + 0x23, 0xcc, 0xf0, 0x54, 0xca, 0x9a, 0xcd, 0x1d, 0x8f, 0x46, 0xf2, 0x52, 0xd3, 0x27, 0x80, 0xaa, + 0x15, 0xdc, 0x8a, 0xba, 0xe4, 0x96, 0x2d, 0x12, 0x92, 0xc6, 0xdb, 0x55, 0xe6, 0xad, 0xb2, 0x60, + 0x95, 0xbd, 0x07, 0xab, 0x22, 0x1a, 0xd3, 0x7b, 0xbb, 0x79, 0x85, 0xe5, 0x85, 0xd9, 0x81, 0xdb, + 0xea, 0x9b, 0xee, 0x60, 0x31, 0x7e, 0x17, 0x23, 0xc9, 0x34, 0x8d, 0xb7, 0x0f, 0xff, 0x45, 0x17, + 0x0b, 0x45, 0x48, 0x1e, 0x6e, 0x3f, 0xe3, 0x2c, 0x7f, 0x0e, 0xb9, 0xe3, 0xdc, 0xdd, 0x76, 0x7f, + 0x01, 0x00, 0x00, 0xff, 0xff, 0xc7, 0x86, 0xa1, 0x32, 0x7e, 0x01, 0x00, 0x00, +} diff --git a/protocol/protobuf/anon_metrics.proto b/protocol/protobuf/anon_metrics.proto new file mode 100644 index 000000000..35b13506d --- /dev/null +++ b/protocol/protobuf/anon_metrics.proto @@ -0,0 +1,36 @@ +syntax = "proto3"; + +option go_package = "./;protobuf"; +package protobuf; + +import "google/protobuf/timestamp.proto"; + +// AnonymousMetric represents a single metric data point +message AnonymousMetric { + // id is the unique id of the metric message + string id=1; + + // event is the app metric event type + string event=2; + + // value is a filtered and validated raw json payload attached to the event + bytes value=3; + + // app_version is the version of the `status-react` app that the metric came from + string app_version=4; + + // os is the operating system of the device the application is installed on + string os=5; + + // session_id is the id of the session the metric was recorded in + string session_id=6; + + // created_at is the datetime at which the metric was stored in the local db + google.protobuf.Timestamp created_at=7; +} + +// AnonymousMetricBatch represents a batch of AnonymousMetrics allowing broadcast of AnonymousMetrics with fewer messages +message AnonymousMetricBatch { + // metrics is an array of AnonymousMetric metrics + repeated AnonymousMetric metrics=1; +} \ No newline at end of file diff --git a/protocol/protobuf/application_metadata_message.pb.go b/protocol/protobuf/application_metadata_message.pb.go index c30512f93..599ebd43c 100644 --- a/protocol/protobuf/application_metadata_message.pb.go +++ b/protocol/protobuf/application_metadata_message.pb.go @@ -56,6 +56,7 @@ const ( ApplicationMetadataMessage_STATUS_UPDATE ApplicationMetadataMessage_Type = 30 ApplicationMetadataMessage_DELETE_MESSAGE ApplicationMetadataMessage_Type = 31 ApplicationMetadataMessage_SYNC_INSTALLATION_COMMUNITY ApplicationMetadataMessage_Type = 32 + ApplicationMetadataMessage_ANONYMOUS_METRIC_BATCH ApplicationMetadataMessage_Type = 33 ) var ApplicationMetadataMessage_Type_name = map[int32]string{ @@ -92,6 +93,7 @@ var ApplicationMetadataMessage_Type_name = map[int32]string{ 30: "STATUS_UPDATE", 31: "DELETE_MESSAGE", 32: "SYNC_INSTALLATION_COMMUNITY", + 33: "ANONYMOUS_METRIC_BATCH", } var ApplicationMetadataMessage_Type_value = map[string]int32{ @@ -128,6 +130,7 @@ var ApplicationMetadataMessage_Type_value = map[string]int32{ "STATUS_UPDATE": 30, "DELETE_MESSAGE": 31, "SYNC_INSTALLATION_COMMUNITY": 32, + "ANONYMOUS_METRIC_BATCH": 33, } func (x ApplicationMetadataMessage_Type) String() string { @@ -206,42 +209,44 @@ func init() { } var fileDescriptor_ad09a6406fcf24c7 = []byte{ - // 591 bytes of a gzipped FileDescriptorProto + // 611 bytes of a gzipped FileDescriptorProto 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x84, 0x53, 0x5d, 0x4f, 0x1b, 0x3b, - 0x10, 0xbd, 0x01, 0x2e, 0x81, 0x09, 0x1f, 0x66, 0x80, 0x4b, 0xf8, 0xce, 0x4d, 0xab, 0x96, 0xb6, - 0x52, 0x2a, 0xb5, 0x8f, 0x55, 0x1f, 0x8c, 0x77, 0x00, 0xd3, 0xac, 0xbd, 0xd8, 0x5e, 0xaa, 0xf4, - 0xc5, 0x5a, 0x4a, 0x8a, 0x90, 0x80, 0x44, 0x10, 0x1e, 0xf8, 0x49, 0xfd, 0x15, 0xfd, 0x6b, 0x95, - 0x37, 0x09, 0x09, 0x25, 0x94, 0xa7, 0x5d, 0x9f, 0x73, 0x66, 0xc6, 0x73, 0x3c, 0x03, 0xd5, 0xac, - 0xdd, 0xbe, 0x38, 0xff, 0x9e, 0x75, 0xce, 0x5b, 0x57, 0xfe, 0xb2, 0xd9, 0xc9, 0x4e, 0xb3, 0x4e, - 0xe6, 0x2f, 0x9b, 0x37, 0x37, 0xd9, 0x59, 0xb3, 0xd6, 0xbe, 0x6e, 0x75, 0x5a, 0x38, 0x95, 0x7f, - 0x4e, 0x6e, 0x7f, 0x54, 0x7f, 0x4d, 0xc1, 0x1a, 0x1f, 0x04, 0xc4, 0x3d, 0x7d, 0xdc, 0x95, 0xe3, - 0x06, 0x4c, 0xdf, 0x9c, 0x9f, 0x5d, 0x65, 0x9d, 0xdb, 0xeb, 0x66, 0xb9, 0x50, 0x29, 0xec, 0xcc, - 0x98, 0x01, 0x80, 0x65, 0x28, 0xb6, 0xb3, 0xbb, 0x8b, 0x56, 0x76, 0x5a, 0x1e, 0xcb, 0xb9, 0xfe, - 0x11, 0x3f, 0xc3, 0x44, 0xe7, 0xae, 0xdd, 0x2c, 0x8f, 0x57, 0x0a, 0x3b, 0x73, 0x1f, 0xde, 0xd4, - 0xfa, 0xf5, 0x6a, 0x4f, 0xd7, 0xaa, 0xb9, 0xbb, 0x76, 0xd3, 0xe4, 0x61, 0xd5, 0x9f, 0x45, 0x98, - 0x08, 0x47, 0x2c, 0x41, 0x31, 0x55, 0x5f, 0x94, 0xfe, 0xaa, 0xd8, 0x3f, 0xc8, 0x60, 0x46, 0x1c, - 0x70, 0xe7, 0x63, 0xb2, 0x96, 0xef, 0x13, 0x2b, 0x20, 0xc2, 0x9c, 0xd0, 0xca, 0x71, 0xe1, 0x7c, - 0x9a, 0x44, 0xdc, 0x11, 0x1b, 0xc3, 0x4d, 0x58, 0x8d, 0x29, 0xde, 0x25, 0x63, 0x0f, 0x64, 0xd2, - 0x83, 0xef, 0x43, 0xc6, 0x71, 0x19, 0x16, 0x12, 0x2e, 0x8d, 0x97, 0xca, 0x3a, 0x5e, 0xaf, 0x73, - 0x27, 0xb5, 0x62, 0x13, 0x01, 0xb6, 0x0d, 0x25, 0x1e, 0xc2, 0xff, 0xe2, 0x0b, 0xd8, 0x36, 0x74, - 0x94, 0x92, 0x75, 0x9e, 0x47, 0x91, 0x21, 0x6b, 0xfd, 0x9e, 0x36, 0xde, 0x19, 0xae, 0x2c, 0x17, - 0xb9, 0x68, 0x12, 0xdf, 0xc2, 0x2b, 0x2e, 0x04, 0x25, 0xce, 0x3f, 0xa7, 0x2d, 0xe2, 0x3b, 0x78, - 0x1d, 0x91, 0xa8, 0x4b, 0x45, 0xcf, 0x8a, 0xa7, 0x70, 0x05, 0x16, 0xfb, 0xa2, 0x61, 0x62, 0x1a, - 0x97, 0x80, 0x59, 0x52, 0xd1, 0x03, 0x14, 0x70, 0x1b, 0xd6, 0xff, 0xcc, 0x3d, 0x2c, 0x28, 0x05, - 0x6b, 0x1e, 0x35, 0xe9, 0x7b, 0x06, 0xb2, 0x99, 0xd1, 0x34, 0x17, 0x42, 0xa7, 0xca, 0xb1, 0x59, - 0xfc, 0x1f, 0x36, 0x1f, 0xd3, 0x49, 0xba, 0x5b, 0x97, 0xc2, 0x87, 0x77, 0x61, 0x73, 0xb8, 0x05, - 0x6b, 0xfd, 0xf7, 0x10, 0x3a, 0x22, 0xcf, 0xa3, 0x63, 0x32, 0x4e, 0x5a, 0x8a, 0x49, 0x39, 0x36, - 0x8f, 0x55, 0xd8, 0x4a, 0x52, 0x7b, 0xe0, 0x95, 0x76, 0x72, 0x4f, 0x8a, 0x6e, 0x0a, 0x43, 0xfb, - 0xd2, 0x3a, 0xd3, 0xb5, 0x9c, 0x05, 0x87, 0xfe, 0xae, 0xf1, 0x86, 0x6c, 0xa2, 0x95, 0x25, 0xb6, - 0x80, 0xeb, 0xb0, 0xf2, 0x58, 0x7c, 0x94, 0x92, 0x69, 0x30, 0xc4, 0x97, 0x50, 0x79, 0x82, 0x1c, - 0xa4, 0x58, 0x0c, 0x5d, 0x8f, 0xaa, 0x97, 0xfb, 0xc7, 0x96, 0x42, 0x4b, 0xa3, 0xe8, 0x5e, 0xf8, - 0x72, 0x18, 0x41, 0x8a, 0xf5, 0xa1, 0xf4, 0x86, 0x7a, 0x3e, 0xff, 0x87, 0xab, 0xb0, 0xbc, 0x6f, - 0x74, 0x9a, 0xe4, 0xb6, 0x78, 0xa9, 0x8e, 0xa5, 0xeb, 0x76, 0xb7, 0x82, 0x0b, 0x30, 0xdb, 0x05, - 0x23, 0x52, 0x4e, 0xba, 0x06, 0x2b, 0x07, 0xb5, 0xd0, 0x71, 0x9c, 0x2a, 0xe9, 0x1a, 0x3e, 0x22, - 0x2b, 0x8c, 0x4c, 0x72, 0xf5, 0x2a, 0x96, 0x61, 0x69, 0x40, 0x0d, 0xe5, 0x59, 0x0b, 0xb7, 0x1e, - 0x30, 0xf7, 0xaf, 0xad, 0xfd, 0xa1, 0x96, 0x8a, 0xad, 0xe3, 0x3c, 0x94, 0x12, 0xa9, 0xee, 0xc7, - 0x7e, 0x23, 0xec, 0x0e, 0x45, 0x72, 0xb0, 0x3b, 0x9b, 0xe1, 0x26, 0xd6, 0x71, 0x97, 0xda, 0xfe, - 0xea, 0x6c, 0x85, 0x5e, 0x22, 0xaa, 0xd3, 0xd0, 0xbe, 0x6c, 0x87, 0xa1, 0x1a, 0x35, 0x33, 0xbd, - 0xd2, 0xac, 0xb2, 0x3b, 0xfb, 0xad, 0x54, 0x7b, 0xff, 0xa9, 0xbf, 0xe0, 0x27, 0x93, 0xf9, 0xdf, - 0xc7, 0xdf, 0x01, 0x00, 0x00, 0xff, 0xff, 0x54, 0x3e, 0x80, 0x7f, 0x87, 0x04, 0x00, 0x00, + 0x10, 0xbd, 0x01, 0x2e, 0x81, 0x09, 0x1f, 0x66, 0xf8, 0x0a, 0xe1, 0x2b, 0xe4, 0x5e, 0xb5, 0xb4, + 0x95, 0x52, 0xa9, 0x7d, 0xac, 0xfa, 0xe0, 0x78, 0x07, 0x62, 0x9a, 0xb5, 0x17, 0xdb, 0x4b, 0x95, + 0xbe, 0x58, 0x4b, 0x49, 0x11, 0x12, 0x90, 0x08, 0xc2, 0x03, 0x3f, 0xb0, 0xbf, 0xa2, 0x7f, 0xa6, + 0xda, 0x4d, 0x42, 0x42, 0x09, 0xe5, 0x69, 0xd7, 0xe7, 0x9c, 0x99, 0xf1, 0x1c, 0xcf, 0x40, 0x25, + 0xe9, 0x74, 0x2e, 0x2f, 0xbe, 0x27, 0xdd, 0x8b, 0xf6, 0xb5, 0xbf, 0x6a, 0x75, 0x93, 0xb3, 0xa4, + 0x9b, 0xf8, 0xab, 0xd6, 0xed, 0x6d, 0x72, 0xde, 0xaa, 0x76, 0x6e, 0xda, 0xdd, 0x36, 0xce, 0x64, + 0x9f, 0xd3, 0xbb, 0x1f, 0x95, 0x5f, 0x33, 0x50, 0xe2, 0xc3, 0x80, 0xb0, 0xaf, 0x0f, 0x7b, 0x72, + 0xdc, 0x82, 0xd9, 0xdb, 0x8b, 0xf3, 0xeb, 0xa4, 0x7b, 0x77, 0xd3, 0x2a, 0xe6, 0xca, 0xb9, 0xfd, + 0x39, 0x33, 0x04, 0xb0, 0x08, 0xf9, 0x4e, 0x72, 0x7f, 0xd9, 0x4e, 0xce, 0x8a, 0x13, 0x19, 0x37, + 0x38, 0xe2, 0x67, 0x98, 0xea, 0xde, 0x77, 0x5a, 0xc5, 0xc9, 0x72, 0x6e, 0x7f, 0xe1, 0xc3, 0x9b, + 0xea, 0xa0, 0x5e, 0xf5, 0xf9, 0x5a, 0x55, 0x77, 0xdf, 0x69, 0x99, 0x2c, 0xac, 0xf2, 0x33, 0x0f, + 0x53, 0xe9, 0x11, 0x0b, 0x90, 0x8f, 0xd5, 0x17, 0xa5, 0xbf, 0x2a, 0xf6, 0x0f, 0x32, 0x98, 0x13, + 0x75, 0xee, 0x7c, 0x48, 0xd6, 0xf2, 0x43, 0x62, 0x39, 0x44, 0x58, 0x10, 0x5a, 0x39, 0x2e, 0x9c, + 0x8f, 0xa3, 0x80, 0x3b, 0x62, 0x13, 0xb8, 0x0d, 0x1b, 0x21, 0x85, 0x35, 0x32, 0xb6, 0x2e, 0xa3, + 0x3e, 0xfc, 0x10, 0x32, 0x89, 0xab, 0xb0, 0x14, 0x71, 0x69, 0xbc, 0x54, 0xd6, 0xf1, 0x46, 0x83, + 0x3b, 0xa9, 0x15, 0x9b, 0x4a, 0x61, 0xdb, 0x54, 0xe2, 0x31, 0xfc, 0x2f, 0xfe, 0x07, 0xbb, 0x86, + 0x8e, 0x63, 0xb2, 0xce, 0xf3, 0x20, 0x30, 0x64, 0xad, 0x3f, 0xd0, 0xc6, 0x3b, 0xc3, 0x95, 0xe5, + 0x22, 0x13, 0x4d, 0xe3, 0x5b, 0x78, 0xc5, 0x85, 0xa0, 0xc8, 0xf9, 0x97, 0xb4, 0x79, 0x7c, 0x07, + 0xaf, 0x03, 0x12, 0x0d, 0xa9, 0xe8, 0x45, 0xf1, 0x0c, 0xae, 0xc3, 0xf2, 0x40, 0x34, 0x4a, 0xcc, + 0xe2, 0x0a, 0x30, 0x4b, 0x2a, 0x78, 0x84, 0x02, 0xee, 0xc2, 0xe6, 0x9f, 0xb9, 0x47, 0x05, 0x85, + 0xd4, 0x9a, 0x27, 0x4d, 0xfa, 0xbe, 0x81, 0x6c, 0x6e, 0x3c, 0xcd, 0x85, 0xd0, 0xb1, 0x72, 0x6c, + 0x1e, 0xf7, 0x60, 0xfb, 0x29, 0x1d, 0xc5, 0xb5, 0x86, 0x14, 0x3e, 0x7d, 0x17, 0xb6, 0x80, 0x3b, + 0x50, 0x1a, 0xbc, 0x87, 0xd0, 0x01, 0x79, 0x1e, 0x9c, 0x90, 0x71, 0xd2, 0x52, 0x48, 0xca, 0xb1, + 0x45, 0xac, 0xc0, 0x4e, 0x14, 0xdb, 0xba, 0x57, 0xda, 0xc9, 0x03, 0x29, 0x7a, 0x29, 0x0c, 0x1d, + 0x4a, 0xeb, 0x4c, 0xcf, 0x72, 0x96, 0x3a, 0xf4, 0x77, 0x8d, 0x37, 0x64, 0x23, 0xad, 0x2c, 0xb1, + 0x25, 0xdc, 0x84, 0xf5, 0xa7, 0xe2, 0xe3, 0x98, 0x4c, 0x93, 0x21, 0xfe, 0x0f, 0xe5, 0x67, 0xc8, + 0x61, 0x8a, 0xe5, 0xb4, 0xeb, 0x71, 0xf5, 0x32, 0xff, 0xd8, 0x4a, 0xda, 0xd2, 0x38, 0xba, 0x1f, + 0xbe, 0x9a, 0x8e, 0x20, 0x85, 0xfa, 0x48, 0x7a, 0x43, 0x7d, 0x9f, 0xd7, 0x70, 0x03, 0x56, 0x0f, + 0x8d, 0x8e, 0xa3, 0xcc, 0x16, 0x2f, 0xd5, 0x89, 0x74, 0xbd, 0xee, 0xd6, 0x71, 0x09, 0xe6, 0x7b, + 0x60, 0x40, 0xca, 0x49, 0xd7, 0x64, 0xc5, 0x54, 0x2d, 0x74, 0x18, 0xc6, 0x4a, 0xba, 0xa6, 0x0f, + 0xc8, 0x0a, 0x23, 0xa3, 0x4c, 0xbd, 0x81, 0x45, 0x58, 0x19, 0x52, 0x23, 0x79, 0x4a, 0xe9, 0xad, + 0x87, 0xcc, 0xc3, 0x6b, 0x6b, 0x7f, 0xa4, 0xa5, 0x62, 0x9b, 0xb8, 0x08, 0x85, 0x48, 0xaa, 0x87, + 0xb1, 0xdf, 0x4a, 0x77, 0x87, 0x02, 0x39, 0xdc, 0x9d, 0xed, 0xf4, 0x26, 0xd6, 0x71, 0x17, 0xdb, + 0xc1, 0xea, 0xec, 0xa4, 0xbd, 0x04, 0xd4, 0xa0, 0x91, 0x7d, 0xd9, 0x4d, 0x87, 0x6a, 0xdc, 0xcc, + 0xf4, 0x4b, 0xb3, 0x32, 0x96, 0x60, 0x8d, 0x2b, 0xad, 0x9a, 0xa1, 0x8e, 0xad, 0x0f, 0xc9, 0x19, + 0x29, 0x7c, 0x8d, 0x3b, 0x51, 0x67, 0x7b, 0xb5, 0xf9, 0x6f, 0x85, 0xea, 0xfb, 0x4f, 0x83, 0xe5, + 0x3f, 0x9d, 0xce, 0xfe, 0x3e, 0xfe, 0x0e, 0x00, 0x00, 0xff, 0xff, 0x33, 0xbf, 0x72, 0xe8, 0xa3, + 0x04, 0x00, 0x00, } diff --git a/protocol/protobuf/application_metadata_message.proto b/protocol/protobuf/application_metadata_message.proto index fb145d42a..a038410a6 100644 --- a/protocol/protobuf/application_metadata_message.proto +++ b/protocol/protobuf/application_metadata_message.proto @@ -46,5 +46,6 @@ message ApplicationMetadataMessage { STATUS_UPDATE = 30; DELETE_MESSAGE = 31; SYNC_INSTALLATION_COMMUNITY = 32; + ANONYMOUS_METRIC_BATCH = 33; } } diff --git a/protocol/protobuf/service.go b/protocol/protobuf/service.go index 22ed55a90..4c41de308 100644 --- a/protocol/protobuf/service.go +++ b/protocol/protobuf/service.go @@ -4,7 +4,7 @@ import ( "github.com/golang/protobuf/proto" ) -//go:generate protoc --go_out=. ./chat_message.proto ./application_metadata_message.proto ./membership_update_message.proto ./command.proto ./contact.proto ./pairing.proto ./push_notifications.proto ./emoji_reaction.proto ./enums.proto ./group_chat_invitation.proto ./chat_identity.proto ./communities.proto ./pin_message.proto +//go:generate protoc --go_out=. ./chat_message.proto ./application_metadata_message.proto ./membership_update_message.proto ./command.proto ./contact.proto ./pairing.proto ./push_notifications.proto ./emoji_reaction.proto ./enums.proto ./group_chat_invitation.proto ./chat_identity.proto ./communities.proto ./pin_message.proto ./anon_metrics.proto func Unmarshal(payload []byte) (*ApplicationMetadataMessage, error) { var message ApplicationMetadataMessage diff --git a/protocol/transport/migrations/migrations.go b/protocol/transport/migrations/migrations.go index 66f77e23e..f212f066c 100644 --- a/protocol/transport/migrations/migrations.go +++ b/protocol/transport/migrations/migrations.go @@ -128,7 +128,7 @@ func _1616691080_add_wakuv2_keysDownSql() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "1616691080_add_wakuV2_keys.down.sql", size: 24, mode: os.FileMode(0644), modTime: time.Unix(1624362582, 0)} + info := bindataFileInfo{name: "1616691080_add_wakuV2_keys.down.sql", size: 24, mode: os.FileMode(0644), modTime: time.Unix(1628714143, 0)} a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x42, 0xb6, 0x23, 0x70, 0xb8, 0x63, 0x18, 0x61, 0xea, 0x35, 0x6e, 0xae, 0xe9, 0x71, 0x89, 0xa, 0xa5, 0x72, 0xa2, 0x64, 0xaa, 0x45, 0x1, 0xf, 0xfc, 0xee, 0x1b, 0xd9, 0xd2, 0x27, 0xf4, 0xe2}} return a, nil } @@ -148,7 +148,7 @@ func _1616691080_add_wakuv2_keysUpSql() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "1616691080_add_wakuV2_keys.up.sql", size: 111, mode: os.FileMode(0644), modTime: time.Unix(1624362582, 0)} + info := bindataFileInfo{name: "1616691080_add_wakuV2_keys.up.sql", size: 111, mode: os.FileMode(0644), modTime: time.Unix(1628714143, 0)} a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x10, 0xf0, 0x97, 0x25, 0xfe, 0x96, 0x2c, 0xa8, 0x62, 0x4a, 0x71, 0x75, 0xff, 0x5f, 0x43, 0x1e, 0x71, 0x53, 0xf1, 0xde, 0xf, 0xcf, 0xcd, 0x87, 0x15, 0x61, 0x9d, 0x25, 0x2e, 0xaf, 0x18, 0x99}} return a, nil } diff --git a/protocol/v1/status_message.go b/protocol/v1/status_message.go index 4b368d6e9..69d21cf57 100644 --- a/protocol/v1/status_message.go +++ b/protocol/v1/status_message.go @@ -246,6 +246,8 @@ func (m *StatusMessage) HandleApplication() error { return nil case protobuf.ApplicationMetadataMessage_CHAT_IDENTITY: return m.unmarshalProtobufData(new(protobuf.ChatIdentity)) + case protobuf.ApplicationMetadataMessage_ANONYMOUS_METRIC_BATCH: + return m.unmarshalProtobufData(new(protobuf.AnonymousMetricBatch)) } return nil } diff --git a/services/ext/service.go b/services/ext/service.go index d516e4fa7..c2533ab54 100644 --- a/services/ext/service.go +++ b/services/ext/service.go @@ -4,6 +4,8 @@ import ( "context" "crypto/ecdsa" "database/sql" + "encoding/hex" + "errors" "math/big" "os" "path/filepath" @@ -23,11 +25,13 @@ import ( "github.com/status-im/status-go/connection" "github.com/status-im/status-go/db" coretypes "github.com/status-im/status-go/eth-node/core/types" + "github.com/status-im/status-go/eth-node/crypto" "github.com/status-im/status-go/eth-node/types" "github.com/status-im/status-go/multiaccounts" "github.com/status-im/status-go/multiaccounts/accounts" "github.com/status-im/status-go/params" "github.com/status-im/status-go/protocol" + "github.com/status-im/status-go/protocol/anonmetrics" "github.com/status-im/status-go/protocol/pushnotificationclient" "github.com/status-im/status-go/protocol/pushnotificationserver" "github.com/status-im/status-go/protocol/transport" @@ -414,6 +418,38 @@ func buildMessengerOptions( return nil, err } + // Generate anon metrics client config + if settings.AnonMetricsShouldSend { + keyBytes, err := hex.DecodeString(config.AnonMetricsSendID) + if err != nil { + return nil, err + } + + key, err := crypto.UnmarshalPubkey(keyBytes) + if err != nil { + return nil, err + } + + amcc := &anonmetrics.ClientConfig{ + ShouldSend: true, + SendAddress: key, + } + options = append(options, protocol.WithAnonMetricsClientConfig(amcc)) + } + + // Generate anon metrics server config + if config.AnonMetricsServerEnabled { + if len(config.AnonMetricsServerPostgresURI) == 0 { + return nil, errors.New("AnonMetricsServerPostgresURI must be set") + } + + amsc := &anonmetrics.ServerConfig{ + Enabled: true, + PostgresURI: config.AnonMetricsServerPostgresURI, + } + options = append(options, protocol.WithAnonMetricsServerConfig(amsc)) + } + if settings.PushNotificationsServerEnabled { config := &pushnotificationserver.Config{ Enabled: true, diff --git a/static/bindata.go b/static/bindata.go index f56b3caf3..ed71f21e5 100644 --- a/static/bindata.go +++ b/static/bindata.go @@ -1,28 +1,30 @@ -// Code generated by go-bindata. +// Code generated by go-bindata. DO NOT EDIT. // sources: -// ../config/README.md -// ../config/cli/fleet-eth.prod.json -// ../config/cli/fleet-eth.staging.json -// ../config/cli/fleet-eth.test.json -// ../config/cli/fleet-wakuv2.prod.json -// ../config/cli/fleet-wakuv2.test.json -// ../config/cli/les-enabled.json -// ../config/cli/mailserver-enabled.json -// ../config/status-chain-genesis.json -// keys/bootnode.key -// keys/firebaseauthkey -// keys/test-account1-status-chain.pk -// keys/test-account1.pk -// keys/test-account2-status-chain.pk -// keys/test-account2.pk -// keys/test-account3-before-eip55.pk -// DO NOT EDIT! +// ../config/README.md (2.911kB) +// ../config/cli/anon-metric-node-client.json (857B) +// ../config/cli/anon-metric-node-server.json (696B) +// ../config/cli/fleet-eth.prod.json (4.47kB) +// ../config/cli/fleet-eth.staging.json (2.145kB) +// ../config/cli/fleet-eth.test.json (2.174kB) +// ../config/cli/fleet-wakuv2.prod.json (747B) +// ../config/cli/fleet-wakuv2.test.json (748B) +// ../config/cli/les-enabled.json (58B) +// ../config/cli/mailserver-enabled.json (176B) +// ../config/status-chain-genesis.json (612B) +// keys/bootnode.key (65B) +// keys/firebaseauthkey (153B) +// keys/test-account1-status-chain.pk (489B) +// keys/test-account1.pk (491B) +// keys/test-account2-status-chain.pk (489B) +// keys/test-account2.pk (491B) +// keys/test-account3-before-eip55.pk (489B) package static import ( "bytes" "compress/gzip" + "crypto/sha256" "fmt" "io" "io/ioutil" @@ -35,7 +37,7 @@ import ( func bindataRead(data []byte, name string) ([]byte, error) { gz, err := gzip.NewReader(bytes.NewBuffer(data)) if err != nil { - return nil, fmt.Errorf("Read %q: %v", name, err) + return nil, fmt.Errorf("read %q: %v", name, err) } var buf bytes.Buffer @@ -43,7 +45,7 @@ func bindataRead(data []byte, name string) ([]byte, error) { clErr := gz.Close() if err != nil { - return nil, fmt.Errorf("Read %q: %v", name, err) + return nil, fmt.Errorf("read %q: %v", name, err) } if clErr != nil { return nil, err @@ -53,8 +55,9 @@ func bindataRead(data []byte, name string) ([]byte, error) { } type asset struct { - bytes []byte - info os.FileInfo + bytes []byte + info os.FileInfo + digest [sha256.Size]byte } type bindataFileInfo struct { @@ -98,8 +101,48 @@ func ConfigReadmeMd() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "../config/README.md", size: 2911, mode: os.FileMode(420), modTime: time.Unix(1629384820, 0)} - a := &asset{bytes: bytes, info: info} + info := bindataFileInfo{name: "../config/README.md", size: 2911, mode: os.FileMode(0644), modTime: time.Unix(1630492724, 0)} + a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x47, 0x5, 0x57, 0xc9, 0x1b, 0x14, 0xb7, 0x7, 0xe3, 0xd5, 0x54, 0x3d, 0xea, 0x6a, 0xd5, 0xda, 0xee, 0x9b, 0x48, 0xd8, 0x93, 0xf4, 0x18, 0x78, 0x14, 0x8e, 0x41, 0x61, 0x97, 0x9b, 0xc4, 0xa7}} + return a, nil +} + +var _ConfigCliAnonMetricNodeClientJson = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x64\x52\xcd\x6e\xdb\x3c\x10\xbc\xfb\x29\x04\x9e\x9d\x44\xfc\x15\xe9\x5b\x12\xe7\xfb\x12\xd4\x0e\x8c\x38\x45\x0f\x45\x0f\x2b\x71\x25\x0b\x96\x45\x81\xa2\xec\x34\x45\xde\xbd\xa0\x9c\x38\x6e\x0b\xde\x66\x87\x33\x8b\x99\xfd\x35\x49\x12\xf2\x88\xe1\xe0\xfc\xf6\x61\x4e\x66\x09\x9d\x46\x64\x0e\x01\xe6\xb5\x27\xb3\x84\x5c\x85\x5d\x77\xd5\x07\x08\x43\x7f\x51\xb9\x0b\x0b\x01\xc8\xc8\x79\x74\x16\xbf\xe0\xcf\xc8\x49\x79\x4e\x19\xd7\x05\x4f\xad\x34\x4c\x22\x07\x9a\xe5\xa2\xa0\x42\x09\x28\x94\x56\x39\xb7\x60\xb4\x64\x59\x99\xd2\x5c\x17\x0a\xd2\x8c\xd3\x42\x48\x5a\x50\x43\x2d\x4f\x8f\x82\x4f\xd8\x5a\x7c\xdd\xbb\xa1\x27\xb3\x24\xf8\x01\xdf\x6d\xe6\x75\x5f\xb8\x3d\xfa\x68\x55\x42\xd3\x1f\xf1\x45\xdd\x07\x6c\xaf\xad\x1d\xb7\x4c\x2f\xc7\x37\xe3\x29\x4f\xf9\x87\x5c\x15\x29\xfe\xd9\x75\x75\x11\x25\xbf\x93\xc3\xa6\xee\x3b\xf4\x3b\xa8\x1b\xf2\x63\x3a\x89\xac\xfb\xe7\xe7\xd5\x5d\x0b\x79\x83\xf6\xdc\x35\xc2\xf7\xae\x0f\x51\x9b\xb2\x6c\x54\xa7\xe4\x34\x5a\x39\x1f\x47\x5a\x0a\x39\x62\xd7\xab\x87\xa5\xb3\x43\x83\xd1\x87\x60\xd8\x4c\x5b\x0c\xd3\x03\xe6\x7c\x0a\x76\x57\xb7\x53\xe8\xba\x1d\x06\x1f\x17\x39\xfa\x7e\x83\xed\x70\xeb\xda\xb2\xae\xc8\x2c\x89\x2d\x24\x09\xf9\x77\x8f\x13\xb8\x84\xba\x59\xa3\xdf\xa3\xff\x73\x7a\x5e\xd4\x1e\xfc\x59\x59\xf6\xea\x00\xdb\x81\xbc\xf3\x3e\xff\xaf\xa0\xef\x0f\xce\x47\x17\xf2\x5e\xab\x2b\xcb\xa6\x6e\xf1\xa2\x6e\x73\xf7\x42\x26\x49\xf2\x76\xdc\x71\xe1\xaa\xff\xea\x06\x4f\xe2\x8d\xab\x3e\x2f\xe1\xb2\x71\xd5\x31\x90\x85\xab\x16\xb8\xc7\x26\xf2\xe6\x77\x37\x5f\xff\x3f\xc1\x4b\x78\x59\xd7\xaf\x51\x80\xa5\xe9\x19\x78\x03\xc5\x76\xe8\x62\x56\xf2\x03\xbd\x75\xbb\xce\x63\xdf\x3f\xb9\x00\xe1\x2c\x83\x38\x5e\x6f\x36\xf8\x12\xfe\x4e\xeb\xba\x75\xed\xf2\x98\xe9\x1a\x5b\x3b\x5e\x2f\x49\x05\x35\x52\x89\xcc\x48\x9e\x73\x54\x19\x43\x2b\x94\xb6\x90\x71\x06\x92\x97\x50\xaa\x3c\x85\x5c\xe4\x90\xb1\x4c\x03\x63\x39\x5a\x2a\xa9\x11\x86\x49\x63\xc0\x14\x5a\x32\xa1\x8c\x52\x99\x14\x9a\x73\xc1\x34\x2b\xa9\x2e\xb4\x92\x28\x04\x62\x3c\xf0\x82\x97\x54\x1b\x25\x25\x0a\xb0\xd4\x18\x95\x4a\xe0\x42\x0a\x93\x51\x9e\x67\x5a\x8d\xf9\x4d\xde\x7e\x07\x00\x00\xff\xff\xf7\x46\x3e\x7d\x59\x03\x00\x00") + +func ConfigCliAnonMetricNodeClientJsonBytes() ([]byte, error) { + return bindataRead( + _ConfigCliAnonMetricNodeClientJson, + "../config/cli/anon-metric-node-client.json", + ) +} + +func ConfigCliAnonMetricNodeClientJson() (*asset, error) { + bytes, err := ConfigCliAnonMetricNodeClientJsonBytes() + if err != nil { + return nil, err + } + + info := bindataFileInfo{name: "../config/cli/anon-metric-node-client.json", size: 857, mode: os.FileMode(0644), modTime: time.Unix(1630492788, 0)} + a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x90, 0xdf, 0xcd, 0xc8, 0x92, 0x1d, 0x63, 0x5e, 0xe1, 0xf9, 0x7f, 0xed, 0xf2, 0x68, 0x6b, 0x20, 0xff, 0x1d, 0x3b, 0xc9, 0x7b, 0xb9, 0x6a, 0xba, 0xd3, 0xbd, 0xf7, 0x48, 0x7b, 0x5a, 0x52, 0x79}} + return a, nil +} + +var _ConfigCliAnonMetricNodeServerJson = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x6c\x51\xcf\x6f\x9b\x30\x18\xbd\xe7\xaf\xb0\x7c\xa6\xad\x81\x98\xa4\xdc\xd2\xd2\xad\xd1\x92\x2a\x4a\x52\xed\x30\xed\x60\xe3\x0f\x62\x05\xf8\x90\x6d\x48\xd7\xa9\xff\xfb\x64\x58\xb3\xa8\x9d\x7c\x7b\xdf\xd3\xfb\xe1\xf7\x7b\x42\x08\x7d\x02\x77\x42\x73\x5c\x66\x34\x25\x61\xe0\x91\x4c\x38\x91\x69\x43\x53\x42\x6f\x5c\xdd\xde\x58\x27\x5c\x67\xaf\x4a\xbc\x52\xc2\x09\x3a\x70\x9e\x50\xc1\x37\xf8\xe5\x39\x92\xe7\x09\x97\x79\xa1\x24\x8b\xa2\x24\x64\x3c\x92\xb3\x30\x97\xbc\x48\x14\xe4\xec\x96\x2b\x06\x21\x53\x45\x32\xbd\x95\x53\x11\xc9\x99\x9a\xcf\x43\xe0\x1c\x62\x96\xe4\x12\x64\x3e\x0a\x6e\xa1\x51\xf0\xda\x63\x67\x69\x4a\x9c\xe9\xe0\xaf\x4d\xa6\x6d\x8e\x3d\x18\x6f\x55\x88\xca\x8e\xf8\x4a\x5b\x07\xcd\x42\xa9\x21\x25\xbb\x1e\x5e\x1a\xb3\x98\xc5\xef\x72\xa5\xa7\x98\x3d\xb6\x3a\xf7\x92\x3f\xe8\xe9\xa0\x6d\x0b\xa6\x16\xba\xa2\x3f\x83\x89\x67\x3d\xee\xf7\x9b\x87\x46\xc8\x0a\xd4\xa5\xab\x87\x1f\xd1\x3a\xaf\x1d\x46\xb3\x41\x3d\xa4\xe7\xd3\x06\x8d\x3f\xcd\xf9\x94\x0f\xd8\x62\xb3\x5c\xa3\xea\x2a\xf0\x3e\x14\xdc\x21\x68\xc0\x05\x27\x90\x71\x20\x54\xad\x9b\x40\xb4\x6d\x0d\xce\xf8\x20\xa3\xef\x77\x71\xec\xee\xb1\x29\x74\x49\x53\xe2\x57\x20\x84\x7e\xce\xf1\x61\x8a\x5e\x98\x8b\x39\xd4\xcd\x49\x1c\x3b\x3a\x21\xe4\x6d\xd4\x5c\x61\xf9\x45\x57\x70\xa6\x56\x58\xfe\x5b\xee\xba\xc2\x72\x2c\xb0\xc2\x72\x05\x3d\x54\x9e\x97\x3d\xdc\x3d\x7f\x3d\xc3\x6b\xf1\xb2\xd3\xaf\x5e\x20\x62\xec\x02\xbc\x13\xf9\xb1\x6b\x7d\x37\xfe\x8e\xde\x63\xdd\x1a\xb0\x76\x8b\x4e\xb8\x8b\xcc\xfe\xbc\x3b\x1c\xe0\xc5\x7d\x6c\xb7\x68\xb0\x59\x8f\x7f\xb0\x03\xd3\x83\xf9\x6f\xdd\x4f\xac\x0d\x5a\x57\x1a\xb0\xcf\xdb\xa5\x0f\x3c\xd4\x9d\xbc\xfd\x09\x00\x00\xff\xff\x34\xe5\xb6\x04\xb8\x02\x00\x00") + +func ConfigCliAnonMetricNodeServerJsonBytes() ([]byte, error) { + return bindataRead( + _ConfigCliAnonMetricNodeServerJson, + "../config/cli/anon-metric-node-server.json", + ) +} + +func ConfigCliAnonMetricNodeServerJson() (*asset, error) { + bytes, err := ConfigCliAnonMetricNodeServerJsonBytes() + if err != nil { + return nil, err + } + + info := bindataFileInfo{name: "../config/cli/anon-metric-node-server.json", size: 696, mode: os.FileMode(0644), modTime: time.Unix(1630492788, 0)} + a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xf0, 0x2f, 0x97, 0xab, 0x77, 0x61, 0x93, 0x9d, 0x1f, 0x33, 0x18, 0x72, 0xad, 0xce, 0xa3, 0x35, 0xa9, 0x44, 0xbf, 0x29, 0xa8, 0xea, 0x21, 0xb7, 0x22, 0x7f, 0x7d, 0x3a, 0x6b, 0x55, 0x3c, 0x66}} return a, nil } @@ -118,8 +161,8 @@ func ConfigCliFleetEthProdJson() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "../config/cli/fleet-eth.prod.json", size: 4470, mode: os.FileMode(420), modTime: time.Unix(1629791292, 0)} - a := &asset{bytes: bytes, info: info} + info := bindataFileInfo{name: "../config/cli/fleet-eth.prod.json", size: 4470, mode: os.FileMode(0644), modTime: time.Unix(1630492724, 0)} + a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x34, 0x7b, 0x71, 0xe3, 0x8a, 0xb0, 0x7f, 0xc3, 0xe, 0xd2, 0x67, 0x38, 0x50, 0xf4, 0x27, 0xaa, 0xec, 0x47, 0xa1, 0x1, 0xf7, 0x5d, 0xe9, 0x8f, 0x3c, 0x35, 0x9f, 0xdb, 0x9b, 0x30, 0x88, 0x26}} return a, nil } @@ -138,8 +181,8 @@ func ConfigCliFleetEthStagingJson() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "../config/cli/fleet-eth.staging.json", size: 2145, mode: os.FileMode(420), modTime: time.Unix(1629791292, 0)} - a := &asset{bytes: bytes, info: info} + info := bindataFileInfo{name: "../config/cli/fleet-eth.staging.json", size: 2145, mode: os.FileMode(0644), modTime: time.Unix(1630492724, 0)} + a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xa2, 0xe9, 0x85, 0x4b, 0x66, 0xa4, 0x1d, 0x4e, 0xaf, 0x21, 0xd7, 0xc2, 0x59, 0xf7, 0xd, 0xc2, 0x61, 0x4e, 0x4a, 0x9e, 0x38, 0x90, 0x6a, 0x2a, 0x16, 0xa6, 0x5c, 0x6d, 0x0, 0x5, 0x6, 0xb3}} return a, nil } @@ -158,8 +201,8 @@ func ConfigCliFleetEthTestJson() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "../config/cli/fleet-eth.test.json", size: 2174, mode: os.FileMode(420), modTime: time.Unix(1629791292, 0)} - a := &asset{bytes: bytes, info: info} + info := bindataFileInfo{name: "../config/cli/fleet-eth.test.json", size: 2174, mode: os.FileMode(0644), modTime: time.Unix(1630492724, 0)} + a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x55, 0x19, 0xca, 0x8d, 0xaa, 0x69, 0x9b, 0xa2, 0xa1, 0xdd, 0xef, 0xf2, 0x63, 0x5e, 0xcd, 0xe2, 0x8f, 0xc7, 0x37, 0x7e, 0x41, 0xa1, 0xc1, 0x3f, 0x65, 0x80, 0xa, 0xa4, 0x27, 0x74, 0x8d, 0xc6}} return a, nil } @@ -178,8 +221,8 @@ func ConfigCliFleetWakuv2ProdJson() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "../config/cli/fleet-wakuv2.prod.json", size: 747, mode: os.FileMode(420), modTime: time.Unix(1629791292, 0)} - a := &asset{bytes: bytes, info: info} + info := bindataFileInfo{name: "../config/cli/fleet-wakuv2.prod.json", size: 747, mode: os.FileMode(0644), modTime: time.Unix(1629202661, 0)} + a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xc3, 0x81, 0x84, 0xfd, 0x7d, 0x7e, 0x27, 0xc8, 0x5e, 0xb6, 0x38, 0xe1, 0x6, 0xa, 0xbc, 0x86, 0x87, 0x54, 0xa2, 0x2f, 0xe1, 0xa1, 0xc8, 0x6, 0x80, 0xfa, 0xed, 0xfe, 0x13, 0x6c, 0x81, 0xd9}} return a, nil } @@ -198,8 +241,8 @@ func ConfigCliFleetWakuv2TestJson() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "../config/cli/fleet-wakuv2.test.json", size: 748, mode: os.FileMode(420), modTime: time.Unix(1629791292, 0)} - a := &asset{bytes: bytes, info: info} + info := bindataFileInfo{name: "../config/cli/fleet-wakuv2.test.json", size: 748, mode: os.FileMode(0644), modTime: time.Unix(1629202661, 0)} + a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x77, 0x6d, 0x28, 0xb7, 0xc2, 0xf3, 0x22, 0xe3, 0x6d, 0xc1, 0xeb, 0x4b, 0x42, 0xe2, 0x6, 0xb0, 0x60, 0x30, 0xdb, 0xe3, 0x26, 0xff, 0x9, 0xf5, 0xea, 0xe6, 0x56, 0xce, 0xa8, 0x98, 0x61, 0x70}} return a, nil } @@ -218,8 +261,8 @@ func ConfigCliLesEnabledJson() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "../config/cli/les-enabled.json", size: 58, mode: os.FileMode(420), modTime: time.Unix(1610281385, 0)} - a := &asset{bytes: bytes, info: info} + info := bindataFileInfo{name: "../config/cli/les-enabled.json", size: 58, mode: os.FileMode(0644), modTime: time.Unix(1585751575, 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 } @@ -238,8 +281,8 @@ func ConfigCliMailserverEnabledJson() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "../config/cli/mailserver-enabled.json", size: 176, mode: os.FileMode(420), modTime: time.Unix(1610281385, 0)} - a := &asset{bytes: bytes, info: info} + info := bindataFileInfo{name: "../config/cli/mailserver-enabled.json", size: 176, mode: os.FileMode(0644), modTime: time.Unix(1585751575, 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 } @@ -258,8 +301,8 @@ func ConfigStatusChainGenesisJson() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "../config/status-chain-genesis.json", size: 612, mode: os.FileMode(420), modTime: time.Unix(1610281385, 0)} - a := &asset{bytes: bytes, info: info} + info := bindataFileInfo{name: "../config/status-chain-genesis.json", size: 612, mode: os.FileMode(0644), modTime: time.Unix(1585751575, 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 } @@ -278,8 +321,8 @@ func keysBootnodeKey() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "keys/bootnode.key", size: 65, mode: os.FileMode(420), modTime: time.Unix(1610281385, 0)} - a := &asset{bytes: bytes, info: info} + info := bindataFileInfo{name: "keys/bootnode.key", size: 65, mode: os.FileMode(0644), modTime: time.Unix(1585751575, 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 } @@ -298,8 +341,8 @@ func keysFirebaseauthkey() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "keys/firebaseauthkey", size: 153, mode: os.FileMode(420), modTime: time.Unix(1610281385, 0)} - a := &asset{bytes: bytes, info: info} + info := bindataFileInfo{name: "keys/firebaseauthkey", size: 153, mode: os.FileMode(0644), modTime: time.Unix(1585751575, 0)} + a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xe, 0x69, 0x23, 0x64, 0x7d, 0xf9, 0x14, 0x37, 0x6f, 0x2b, 0x1, 0xf0, 0xb0, 0xa4, 0xb2, 0xd0, 0x18, 0xcd, 0xf9, 0xeb, 0x57, 0xa3, 0xfd, 0x79, 0x25, 0xa7, 0x9c, 0x3, 0xce, 0x26, 0xec, 0xe1}} return a, nil } @@ -318,8 +361,8 @@ func keysTestAccount1StatusChainPk() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "keys/test-account1-status-chain.pk", size: 489, mode: os.FileMode(420), modTime: time.Unix(1610281385, 0)} - a := &asset{bytes: bytes, info: info} + info := bindataFileInfo{name: "keys/test-account1-status-chain.pk", size: 489, mode: os.FileMode(0644), modTime: time.Unix(1585751575, 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 } @@ -338,8 +381,8 @@ func keysTestAccount1Pk() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "keys/test-account1.pk", size: 491, mode: os.FileMode(420), modTime: time.Unix(1610281385, 0)} - a := &asset{bytes: bytes, info: info} + info := bindataFileInfo{name: "keys/test-account1.pk", size: 491, mode: os.FileMode(0644), modTime: time.Unix(1585751575, 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 } @@ -358,8 +401,8 @@ func keysTestAccount2StatusChainPk() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "keys/test-account2-status-chain.pk", size: 489, mode: os.FileMode(420), modTime: time.Unix(1610281385, 0)} - a := &asset{bytes: bytes, info: info} + info := bindataFileInfo{name: "keys/test-account2-status-chain.pk", size: 489, mode: os.FileMode(0644), modTime: time.Unix(1585751575, 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 } @@ -378,8 +421,8 @@ func keysTestAccount2Pk() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "keys/test-account2.pk", size: 491, mode: os.FileMode(420), modTime: time.Unix(1610281385, 0)} - a := &asset{bytes: bytes, info: info} + info := bindataFileInfo{name: "keys/test-account2.pk", size: 491, mode: os.FileMode(0644), modTime: time.Unix(1585751575, 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 } @@ -398,8 +441,8 @@ func keysTestAccount3BeforeEip55Pk() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "keys/test-account3-before-eip55.pk", size: 489, mode: os.FileMode(420), modTime: time.Unix(1610281385, 0)} - a := &asset{bytes: bytes, info: info} + info := bindataFileInfo{name: "keys/test-account3-before-eip55.pk", size: 489, mode: os.FileMode(0644), modTime: time.Unix(1585751575, 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 } @@ -407,8 +450,8 @@ func keysTestAccount3BeforeEip55Pk() (*asset, error) { // It returns an error if the asset could not be found or // could not be loaded. func Asset(name string) ([]byte, error) { - cannonicalName := strings.Replace(name, "\\", "/", -1) - if f, ok := _bindata[cannonicalName]; ok { + canonicalName := strings.Replace(name, "\\", "/", -1) + if f, ok := _bindata[canonicalName]; ok { a, err := f() if err != nil { return nil, fmt.Errorf("Asset %s can't read by error: %v", name, err) @@ -418,6 +461,12 @@ func Asset(name string) ([]byte, error) { return nil, fmt.Errorf("Asset %s not found", name) } +// AssetString returns the asset contents as a string (instead of a []byte). +func AssetString(name string) (string, error) { + data, err := Asset(name) + return string(data), err +} + // MustAsset is like Asset but panics when Asset would return an error. // It simplifies safe initialization of global variables. func MustAsset(name string) []byte { @@ -429,12 +478,18 @@ func MustAsset(name string) []byte { return a } +// MustAssetString is like AssetString but panics when Asset would return an +// error. It simplifies safe initialization of global variables. +func MustAssetString(name string) string { + return string(MustAsset(name)) +} + // AssetInfo loads and returns the asset info for the given name. // It returns an error if the asset could not be found or // could not be loaded. func AssetInfo(name string) (os.FileInfo, error) { - cannonicalName := strings.Replace(name, "\\", "/", -1) - if f, ok := _bindata[cannonicalName]; ok { + canonicalName := strings.Replace(name, "\\", "/", -1) + if f, ok := _bindata[canonicalName]; ok { a, err := f() if err != nil { return nil, fmt.Errorf("AssetInfo %s can't read by error: %v", name, err) @@ -444,6 +499,33 @@ func AssetInfo(name string) (os.FileInfo, error) { return nil, fmt.Errorf("AssetInfo %s not found", name) } +// AssetDigest returns the digest of the file with the given name. It returns an +// error if the asset could not be found or the digest could not be loaded. +func AssetDigest(name string) ([sha256.Size]byte, error) { + canonicalName := strings.Replace(name, "\\", "/", -1) + if f, ok := _bindata[canonicalName]; ok { + a, err := f() + if err != nil { + return [sha256.Size]byte{}, fmt.Errorf("AssetDigest %s can't read by error: %v", name, err) + } + return a.digest, nil + } + return [sha256.Size]byte{}, fmt.Errorf("AssetDigest %s not found", name) +} + +// Digests returns a map of all known files and their checksums. +func Digests() (map[string][sha256.Size]byte, error) { + mp := make(map[string][sha256.Size]byte, len(_bindata)) + for name := range _bindata { + a, err := _bindata[name]() + if err != nil { + return nil, err + } + mp[name] = a.digest + } + return mp, nil +} + // AssetNames returns the names of the assets. func AssetNames() []string { names := make([]string, 0, len(_bindata)) @@ -456,20 +538,39 @@ func AssetNames() []string { // _bindata is a table, holding each asset generator, mapped to its name. var _bindata = map[string]func() (*asset, error){ "../config/README.md": ConfigReadmeMd, + + "../config/cli/anon-metric-node-client.json": ConfigCliAnonMetricNodeClientJson, + + "../config/cli/anon-metric-node-server.json": ConfigCliAnonMetricNodeServerJson, + "../config/cli/fleet-eth.prod.json": ConfigCliFleetEthProdJson, + "../config/cli/fleet-eth.staging.json": ConfigCliFleetEthStagingJson, + "../config/cli/fleet-eth.test.json": ConfigCliFleetEthTestJson, + "../config/cli/fleet-wakuv2.prod.json": ConfigCliFleetWakuv2ProdJson, + "../config/cli/fleet-wakuv2.test.json": ConfigCliFleetWakuv2TestJson, + "../config/cli/les-enabled.json": ConfigCliLesEnabledJson, + "../config/cli/mailserver-enabled.json": ConfigCliMailserverEnabledJson, + "../config/status-chain-genesis.json": ConfigStatusChainGenesisJson, + "keys/bootnode.key": keysBootnodeKey, + "keys/firebaseauthkey": keysFirebaseauthkey, + "keys/test-account1-status-chain.pk": keysTestAccount1StatusChainPk, + "keys/test-account1.pk": keysTestAccount1Pk, + "keys/test-account2-status-chain.pk": keysTestAccount2StatusChainPk, + "keys/test-account2.pk": keysTestAccount2Pk, + "keys/test-account3-before-eip55.pk": keysTestAccount3BeforeEip55Pk, } @@ -482,15 +583,15 @@ var _bindata = map[string]func() (*asset, error){ // img/ // a.png // b.png -// then AssetDir("data") would return []string{"foo.txt", "img"} -// AssetDir("data/img") would return []string{"a.png", "b.png"} -// AssetDir("foo.txt") and AssetDir("notexist") would return an error +// then AssetDir("data") would return []string{"foo.txt", "img"}, +// AssetDir("data/img") would return []string{"a.png", "b.png"}, +// AssetDir("foo.txt") and AssetDir("notexist") would return an error, and // AssetDir("") will return []string{"data"}. func AssetDir(name string) ([]string, error) { node := _bintree if len(name) != 0 { - cannonicalName := strings.Replace(name, "\\", "/", -1) - pathList := strings.Split(cannonicalName, "/") + canonicalName := strings.Replace(name, "\\", "/", -1) + pathList := strings.Split(canonicalName, "/") for _, p := range pathList { node = node.Children[p] if node == nil { @@ -512,34 +613,37 @@ type bintree struct { Func func() (*asset, error) Children map[string]*bintree } + var _bintree = &bintree{nil, map[string]*bintree{ "..": &bintree{nil, map[string]*bintree{ "config": &bintree{nil, map[string]*bintree{ "README.md": &bintree{ConfigReadmeMd, map[string]*bintree{}}, "cli": &bintree{nil, map[string]*bintree{ - "fleet-eth.prod.json": &bintree{ConfigCliFleetEthProdJson, map[string]*bintree{}}, - "fleet-eth.staging.json": &bintree{ConfigCliFleetEthStagingJson, map[string]*bintree{}}, - "fleet-eth.test.json": &bintree{ConfigCliFleetEthTestJson, map[string]*bintree{}}, - "fleet-wakuv2.prod.json": &bintree{ConfigCliFleetWakuv2ProdJson, map[string]*bintree{}}, - "fleet-wakuv2.test.json": &bintree{ConfigCliFleetWakuv2TestJson, map[string]*bintree{}}, - "les-enabled.json": &bintree{ConfigCliLesEnabledJson, map[string]*bintree{}}, - "mailserver-enabled.json": &bintree{ConfigCliMailserverEnabledJson, map[string]*bintree{}}, + "anon-metric-node-client.json": &bintree{ConfigCliAnonMetricNodeClientJson, map[string]*bintree{}}, + "anon-metric-node-server.json": &bintree{ConfigCliAnonMetricNodeServerJson, map[string]*bintree{}}, + "fleet-eth.prod.json": &bintree{ConfigCliFleetEthProdJson, map[string]*bintree{}}, + "fleet-eth.staging.json": &bintree{ConfigCliFleetEthStagingJson, map[string]*bintree{}}, + "fleet-eth.test.json": &bintree{ConfigCliFleetEthTestJson, map[string]*bintree{}}, + "fleet-wakuv2.prod.json": &bintree{ConfigCliFleetWakuv2ProdJson, map[string]*bintree{}}, + "fleet-wakuv2.test.json": &bintree{ConfigCliFleetWakuv2TestJson, map[string]*bintree{}}, + "les-enabled.json": &bintree{ConfigCliLesEnabledJson, map[string]*bintree{}}, + "mailserver-enabled.json": &bintree{ConfigCliMailserverEnabledJson, map[string]*bintree{}}, }}, "status-chain-genesis.json": &bintree{ConfigStatusChainGenesisJson, map[string]*bintree{}}, }}, }}, "keys": &bintree{nil, map[string]*bintree{ - "bootnode.key": &bintree{keysBootnodeKey, map[string]*bintree{}}, - "firebaseauthkey": &bintree{keysFirebaseauthkey, map[string]*bintree{}}, + "bootnode.key": &bintree{keysBootnodeKey, map[string]*bintree{}}, + "firebaseauthkey": &bintree{keysFirebaseauthkey, map[string]*bintree{}}, "test-account1-status-chain.pk": &bintree{keysTestAccount1StatusChainPk, map[string]*bintree{}}, - "test-account1.pk": &bintree{keysTestAccount1Pk, map[string]*bintree{}}, + "test-account1.pk": &bintree{keysTestAccount1Pk, map[string]*bintree{}}, "test-account2-status-chain.pk": &bintree{keysTestAccount2StatusChainPk, map[string]*bintree{}}, - "test-account2.pk": &bintree{keysTestAccount2Pk, map[string]*bintree{}}, + "test-account2.pk": &bintree{keysTestAccount2Pk, map[string]*bintree{}}, "test-account3-before-eip55.pk": &bintree{keysTestAccount3BeforeEip55Pk, map[string]*bintree{}}, }}, }} -// RestoreAsset restores an asset under the given directory +// RestoreAsset restores an asset under the given directory. func RestoreAsset(dir, name string) error { data, err := Asset(name) if err != nil { @@ -557,14 +661,10 @@ func RestoreAsset(dir, name string) error { if err != nil { return err } - err = os.Chtimes(_filePath(dir, name), info.ModTime(), info.ModTime()) - if err != nil { - return err - } - return nil + return os.Chtimes(_filePath(dir, name), info.ModTime(), info.ModTime()) } -// RestoreAssets restores an asset under the given directory recursively +// RestoreAssets restores an asset under the given directory recursively. func RestoreAssets(dir, name string) error { children, err := AssetDir(name) // File @@ -582,7 +682,6 @@ func RestoreAssets(dir, name string) error { } func _filePath(dir, name string) string { - cannonicalName := strings.Replace(name, "\\", "/", -1) - return filepath.Join(append([]string{dir}, strings.Split(cannonicalName, "/")...)...) + canonicalName := strings.Replace(name, "\\", "/", -1) + return filepath.Join(append([]string{dir}, strings.Split(canonicalName, "/")...)...) } -