diff --git a/Cargo.lock b/Cargo.lock index f4d616807..8e127ce8f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1617,11 +1617,11 @@ checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b" [[package]] name = "beacon" version = "0.1.0" -source = "git+https://github.com/helium/proto?branch=master#47598512b7d282c34b619adf140403feeb138e71" +source = "git+https://github.com/helium/proto?branch=andymck/hip-118-visualization-data#c5c76ac1e2cb934a14c4abe7728274e522f72b1f" dependencies = [ "base64 0.21.7", "byteorder", - "helium-proto", + "helium-proto 0.1.0 (git+https://github.com/helium/proto?branch=andymck/hip-118-visualization-data)", "prost", "rand 0.8.5", "rand_chacha 0.3.0", @@ -1791,7 +1791,7 @@ dependencies = [ "futures", "futures-util", "helium-crypto", - "helium-proto", + "helium-proto 0.1.0 (git+https://github.com/helium/proto?branch=andymck/hip-118-visualization-data)", "http 0.2.11", "http-serde", "humantime-serde", @@ -2132,7 +2132,7 @@ dependencies = [ [[package]] name = "circuit-breaker" version = "0.1.0" -source = "git+https://github.com/helium/helium-anchor-gen.git?branch=main#761b839a71cc6d2aecf4be994af9d8206aeae0e1" +source = "git+https://github.com/helium/helium-anchor-gen.git?branch=main#ef686c1b0ba0ab2bd0e0377e0bf2a44630938da2" dependencies = [ "anchor-gen", "anchor-lang 0.30.1", @@ -2141,7 +2141,7 @@ dependencies = [ [[package]] name = "circuit-breaker" version = "0.1.0" -source = "git+https://github.com/helium/helium-anchor-gen.git#761b839a71cc6d2aecf4be994af9d8206aeae0e1" +source = "git+https://github.com/helium/helium-anchor-gen.git#ef686c1b0ba0ab2bd0e0377e0bf2a44630938da2" dependencies = [ "anchor-gen", "anchor-lang 0.30.1", @@ -2642,7 +2642,7 @@ dependencies = [ "axum 0.7.4", "bs58 0.4.0", "helium-crypto", - "helium-proto", + "helium-proto 0.1.0 (git+https://github.com/helium/proto?branch=andymck/hip-118-visualization-data)", "http 0.2.11", "notify", "serde", @@ -2783,7 +2783,7 @@ dependencies = [ [[package]] name = "data-credits" version = "0.2.2" -source = "git+https://github.com/helium/helium-anchor-gen.git?branch=main#761b839a71cc6d2aecf4be994af9d8206aeae0e1" +source = "git+https://github.com/helium/helium-anchor-gen.git?branch=main#ef686c1b0ba0ab2bd0e0377e0bf2a44630938da2" dependencies = [ "anchor-gen", "anchor-lang 0.30.1", @@ -2792,7 +2792,7 @@ dependencies = [ [[package]] name = "data-credits" version = "0.2.2" -source = "git+https://github.com/helium/helium-anchor-gen.git#761b839a71cc6d2aecf4be994af9d8206aeae0e1" +source = "git+https://github.com/helium/helium-anchor-gen.git#ef686c1b0ba0ab2bd0e0377e0bf2a44630938da2" dependencies = [ "anchor-gen", "anchor-lang 0.30.1", @@ -3170,7 +3170,7 @@ checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0" [[package]] name = "fanout" version = "0.1.0" -source = "git+https://github.com/helium/helium-anchor-gen.git?branch=main#761b839a71cc6d2aecf4be994af9d8206aeae0e1" +source = "git+https://github.com/helium/helium-anchor-gen.git?branch=main#ef686c1b0ba0ab2bd0e0377e0bf2a44630938da2" dependencies = [ "anchor-gen", "anchor-lang 0.30.1", @@ -3179,7 +3179,7 @@ dependencies = [ [[package]] name = "fanout" version = "0.1.0" -source = "git+https://github.com/helium/helium-anchor-gen.git#761b839a71cc6d2aecf4be994af9d8206aeae0e1" +source = "git+https://github.com/helium/helium-anchor-gen.git#ef686c1b0ba0ab2bd0e0377e0bf2a44630938da2" dependencies = [ "anchor-gen", "anchor-lang 0.30.1", @@ -3242,7 +3242,7 @@ dependencies = [ "futures-util", "h3o", "helium-crypto", - "helium-proto", + "helium-proto 0.1.0 (git+https://github.com/helium/proto?branch=andymck/hip-118-visualization-data)", "hex-literal", "http 0.2.11", "lazy_static", @@ -3755,7 +3755,7 @@ checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" [[package]] name = "helium-anchor-gen" version = "0.1.0" -source = "git+https://github.com/helium/helium-anchor-gen.git?branch=main#761b839a71cc6d2aecf4be994af9d8206aeae0e1" +source = "git+https://github.com/helium/helium-anchor-gen.git?branch=main#ef686c1b0ba0ab2bd0e0377e0bf2a44630938da2" dependencies = [ "anchor-gen", "anchor-lang 0.30.1", @@ -3777,7 +3777,7 @@ dependencies = [ [[package]] name = "helium-anchor-gen" version = "0.1.0" -source = "git+https://github.com/helium/helium-anchor-gen.git#761b839a71cc6d2aecf4be994af9d8206aeae0e1" +source = "git+https://github.com/helium/helium-anchor-gen.git#ef686c1b0ba0ab2bd0e0377e0bf2a44630938da2" dependencies = [ "anchor-gen", "anchor-lang 0.30.1", @@ -3806,7 +3806,7 @@ dependencies = [ "bs58 0.5.0", "byteorder", "ed25519-compact", - "getrandom 0.1.16", + "getrandom 0.2.10", "k256", "lazy_static", "multihash", @@ -3824,7 +3824,7 @@ dependencies = [ [[package]] name = "helium-entity-manager" version = "0.2.11" -source = "git+https://github.com/helium/helium-anchor-gen.git?branch=main#761b839a71cc6d2aecf4be994af9d8206aeae0e1" +source = "git+https://github.com/helium/helium-anchor-gen.git?branch=main#ef686c1b0ba0ab2bd0e0377e0bf2a44630938da2" dependencies = [ "anchor-gen", "anchor-lang 0.30.1", @@ -3833,7 +3833,7 @@ dependencies = [ [[package]] name = "helium-entity-manager" version = "0.2.11" -source = "git+https://github.com/helium/helium-anchor-gen.git#761b839a71cc6d2aecf4be994af9d8206aeae0e1" +source = "git+https://github.com/helium/helium-anchor-gen.git#ef686c1b0ba0ab2bd0e0377e0bf2a44630938da2" dependencies = [ "anchor-gen", "anchor-lang 0.30.1", @@ -3842,7 +3842,7 @@ dependencies = [ [[package]] name = "helium-lib" version = "0.0.0" -source = "git+https://github.com/helium/helium-wallet-rs.git?branch=master#4acf688beac3c507c33843a745516839e1f814b2" +source = "git+https://github.com/helium/helium-wallet-rs.git?branch=master#e9797e56286ca04d5f65d2721d6928ecc6de1fed" dependencies = [ "anchor-client", "anchor-spl", @@ -3855,7 +3855,7 @@ dependencies = [ "h3o", "helium-anchor-gen 0.1.0 (git+https://github.com/helium/helium-anchor-gen.git?branch=main)", "helium-crypto", - "helium-proto", + "helium-proto 0.1.0 (git+https://github.com/helium/proto?branch=master)", "hex", "hex-literal", "itertools", @@ -3879,6 +3879,22 @@ dependencies = [ "url", ] +[[package]] +name = "helium-proto" +version = "0.1.0" +source = "git+https://github.com/helium/proto?branch=andymck/hip-118-visualization-data#c5c76ac1e2cb934a14c4abe7728274e522f72b1f" +dependencies = [ + "bytes", + "prost", + "prost-build", + "serde", + "serde_json", + "strum", + "strum_macros", + "tonic", + "tonic-build", +] + [[package]] name = "helium-proto" version = "0.1.0" @@ -3898,7 +3914,7 @@ dependencies = [ [[package]] name = "helium-sub-daos" version = "0.1.8" -source = "git+https://github.com/helium/helium-anchor-gen.git?branch=main#761b839a71cc6d2aecf4be994af9d8206aeae0e1" +source = "git+https://github.com/helium/helium-anchor-gen.git?branch=main#ef686c1b0ba0ab2bd0e0377e0bf2a44630938da2" dependencies = [ "anchor-gen", "anchor-lang 0.30.1", @@ -3907,7 +3923,7 @@ dependencies = [ [[package]] name = "helium-sub-daos" version = "0.1.8" -source = "git+https://github.com/helium/helium-anchor-gen.git#761b839a71cc6d2aecf4be994af9d8206aeae0e1" +source = "git+https://github.com/helium/helium-anchor-gen.git#ef686c1b0ba0ab2bd0e0377e0bf2a44630938da2" dependencies = [ "anchor-gen", "anchor-lang 0.30.1", @@ -3945,7 +3961,7 @@ dependencies = [ "async-trait", "chrono", "derive_builder", - "helium-proto", + "helium-proto 0.1.0 (git+https://github.com/helium/proto?branch=andymck/hip-118-visualization-data)", "hextree", "rust_decimal", "rust_decimal_macros", @@ -3961,7 +3977,7 @@ checksum = "7ebdb29d2ea9ed0083cd8cece49bbd968021bd99b0849edb4a9a7ee0fdf6a4e0" [[package]] name = "hexboosting" version = "0.1.0" -source = "git+https://github.com/helium/helium-anchor-gen.git?branch=main#761b839a71cc6d2aecf4be994af9d8206aeae0e1" +source = "git+https://github.com/helium/helium-anchor-gen.git?branch=main#ef686c1b0ba0ab2bd0e0377e0bf2a44630938da2" dependencies = [ "anchor-gen", "anchor-lang 0.30.1", @@ -3970,7 +3986,7 @@ dependencies = [ [[package]] name = "hexboosting" version = "0.1.0" -source = "git+https://github.com/helium/helium-anchor-gen.git#761b839a71cc6d2aecf4be994af9d8206aeae0e1" +source = "git+https://github.com/helium/helium-anchor-gen.git#ef686c1b0ba0ab2bd0e0377e0bf2a44630938da2" dependencies = [ "anchor-gen", "anchor-lang 0.30.1", @@ -4370,11 +4386,12 @@ dependencies = [ "futures", "futures-util", "helium-crypto", - "helium-proto", + "helium-proto 0.1.0 (git+https://github.com/helium/proto?branch=andymck/hip-118-visualization-data)", "http 0.2.11", "humantime-serde", "metrics", "metrics-exporter-prometheus", + "mobile-config", "poc-metrics", "prost", "rand 0.8.5", @@ -4439,7 +4456,7 @@ dependencies = [ "futures", "futures-util", "helium-crypto", - "helium-proto", + "helium-proto 0.1.0 (git+https://github.com/helium/proto?branch=andymck/hip-118-visualization-data)", "hextree", "http 0.2.11", "http-serde", @@ -4481,7 +4498,7 @@ dependencies = [ "futures", "futures-util", "helium-crypto", - "helium-proto", + "helium-proto 0.1.0 (git+https://github.com/helium/proto?branch=andymck/hip-118-visualization-data)", "http 0.2.11", "http-serde", "humantime-serde", @@ -4523,7 +4540,7 @@ dependencies = [ "futures-util", "h3o", "helium-crypto", - "helium-proto", + "helium-proto 0.1.0 (git+https://github.com/helium/proto?branch=andymck/hip-118-visualization-data)", "http-serde", "humantime-serde", "iot-config", @@ -4781,7 +4798,7 @@ dependencies = [ [[package]] name = "lazy-distributor" version = "0.2.0" -source = "git+https://github.com/helium/helium-anchor-gen.git?branch=main#761b839a71cc6d2aecf4be994af9d8206aeae0e1" +source = "git+https://github.com/helium/helium-anchor-gen.git?branch=main#ef686c1b0ba0ab2bd0e0377e0bf2a44630938da2" dependencies = [ "anchor-gen", "anchor-lang 0.30.1", @@ -4790,7 +4807,7 @@ dependencies = [ [[package]] name = "lazy-distributor" version = "0.2.0" -source = "git+https://github.com/helium/helium-anchor-gen.git#761b839a71cc6d2aecf4be994af9d8206aeae0e1" +source = "git+https://github.com/helium/helium-anchor-gen.git#ef686c1b0ba0ab2bd0e0377e0bf2a44630938da2" dependencies = [ "anchor-gen", "anchor-lang 0.30.1", @@ -4799,7 +4816,7 @@ dependencies = [ [[package]] name = "lazy-transactions" version = "0.2.0" -source = "git+https://github.com/helium/helium-anchor-gen.git?branch=main#761b839a71cc6d2aecf4be994af9d8206aeae0e1" +source = "git+https://github.com/helium/helium-anchor-gen.git?branch=main#ef686c1b0ba0ab2bd0e0377e0bf2a44630938da2" dependencies = [ "anchor-gen", "anchor-lang 0.30.1", @@ -4808,7 +4825,7 @@ dependencies = [ [[package]] name = "lazy-transactions" version = "0.2.0" -source = "git+https://github.com/helium/helium-anchor-gen.git#761b839a71cc6d2aecf4be994af9d8206aeae0e1" +source = "git+https://github.com/helium/helium-anchor-gen.git#ef686c1b0ba0ab2bd0e0377e0bf2a44630938da2" dependencies = [ "anchor-gen", "anchor-lang 0.30.1", @@ -5129,7 +5146,7 @@ dependencies = [ "futures", "futures-util", "helium-crypto", - "helium-proto", + "helium-proto 0.1.0 (git+https://github.com/helium/proto?branch=andymck/hip-118-visualization-data)", "hextree", "http 0.2.11", "http-serde", @@ -5169,7 +5186,7 @@ dependencies = [ "futures", "h3o", "helium-crypto", - "helium-proto", + "helium-proto 0.1.0 (git+https://github.com/helium/proto?branch=andymck/hip-118-visualization-data)", "mobile-config", "prost", "rand 0.8.5", @@ -5184,7 +5201,7 @@ dependencies = [ [[package]] name = "mobile-entity-manager" version = "0.1.3" -source = "git+https://github.com/helium/helium-anchor-gen.git?branch=main#761b839a71cc6d2aecf4be994af9d8206aeae0e1" +source = "git+https://github.com/helium/helium-anchor-gen.git?branch=main#ef686c1b0ba0ab2bd0e0377e0bf2a44630938da2" dependencies = [ "anchor-gen", "anchor-lang 0.30.1", @@ -5193,7 +5210,7 @@ dependencies = [ [[package]] name = "mobile-entity-manager" version = "0.1.3" -source = "git+https://github.com/helium/helium-anchor-gen.git#761b839a71cc6d2aecf4be994af9d8206aeae0e1" +source = "git+https://github.com/helium/helium-anchor-gen.git#ef686c1b0ba0ab2bd0e0377e0bf2a44630938da2" dependencies = [ "anchor-gen", "anchor-lang 0.30.1", @@ -5214,7 +5231,7 @@ dependencies = [ "futures", "futures-util", "helium-crypto", - "helium-proto", + "helium-proto 0.1.0 (git+https://github.com/helium/proto?branch=andymck/hip-118-visualization-data)", "http 0.2.11", "http-serde", "humantime-serde", @@ -5258,7 +5275,7 @@ dependencies = [ "futures-util", "h3o", "helium-crypto", - "helium-proto", + "helium-proto 0.1.0 (git+https://github.com/helium/proto?branch=andymck/hip-118-visualization-data)", "hex-assignments", "hextree", "http-serde", @@ -5626,7 +5643,7 @@ version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "681030a937600a36906c185595136d26abfebb4aa9c65701cefcaf8578bb982b" dependencies = [ - "proc-macro-crate 1.1.3", + "proc-macro-crate 3.1.0", "proc-macro2", "quote", "syn 2.0.58", @@ -5942,7 +5959,7 @@ dependencies = [ "futures", "futures-util", "helium-crypto", - "helium-proto", + "helium-proto 0.1.0 (git+https://github.com/helium/proto?branch=andymck/hip-118-visualization-data)", "http 0.2.11", "hyper 0.14.28", "jsonrpsee", @@ -6025,7 +6042,7 @@ dependencies = [ "futures-util", "helium-anchor-gen 0.1.0 (git+https://github.com/helium/helium-anchor-gen.git)", "helium-lib", - "helium-proto", + "helium-proto 0.1.0 (git+https://github.com/helium/proto?branch=andymck/hip-118-visualization-data)", "humantime-serde", "metrics", "metrics-exporter-prometheus", @@ -6049,7 +6066,7 @@ dependencies = [ [[package]] name = "price-oracle" version = "0.2.1" -source = "git+https://github.com/helium/helium-anchor-gen.git?branch=main#761b839a71cc6d2aecf4be994af9d8206aeae0e1" +source = "git+https://github.com/helium/helium-anchor-gen.git?branch=main#ef686c1b0ba0ab2bd0e0377e0bf2a44630938da2" dependencies = [ "anchor-gen", "anchor-lang 0.30.1", @@ -6058,7 +6075,7 @@ dependencies = [ [[package]] name = "price-oracle" version = "0.2.1" -source = "git+https://github.com/helium/helium-anchor-gen.git#761b839a71cc6d2aecf4be994af9d8206aeae0e1" +source = "git+https://github.com/helium/helium-anchor-gen.git#ef686c1b0ba0ab2bd0e0377e0bf2a44630938da2" dependencies = [ "anchor-gen", "anchor-lang 0.30.1", @@ -6150,7 +6167,7 @@ dependencies = [ "custom-tracing", "file-store", "futures", - "helium-proto", + "helium-proto 0.1.0 (git+https://github.com/helium/proto?branch=andymck/hip-118-visualization-data)", "humantime-serde", "metrics", "metrics-exporter-prometheus", @@ -6201,7 +6218,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "80b776a1b2dc779f5ee0641f8ade0125bc1298dd41a9a0c16d8bd57b42d222b1" dependencies = [ "bytes", - "heck 0.4.0", + "heck 0.5.0", "itertools", "log", "multimap", @@ -6702,7 +6719,7 @@ dependencies = [ "futures", "futures-util", "helium-crypto", - "helium-proto", + "helium-proto 0.1.0 (git+https://github.com/helium/proto?branch=andymck/hip-118-visualization-data)", "humantime-serde", "lazy_static", "metrics", @@ -6736,7 +6753,7 @@ dependencies = [ [[package]] name = "rewards-oracle" version = "0.2.0" -source = "git+https://github.com/helium/helium-anchor-gen.git?branch=main#761b839a71cc6d2aecf4be994af9d8206aeae0e1" +source = "git+https://github.com/helium/helium-anchor-gen.git?branch=main#ef686c1b0ba0ab2bd0e0377e0bf2a44630938da2" dependencies = [ "anchor-gen", "anchor-lang 0.30.1", @@ -6745,7 +6762,7 @@ dependencies = [ [[package]] name = "rewards-oracle" version = "0.2.0" -source = "git+https://github.com/helium/helium-anchor-gen.git#761b839a71cc6d2aecf4be994af9d8206aeae0e1" +source = "git+https://github.com/helium/helium-anchor-gen.git#ef686c1b0ba0ab2bd0e0377e0bf2a44630938da2" dependencies = [ "anchor-gen", "anchor-lang 0.30.1", @@ -9370,7 +9387,7 @@ dependencies = [ [[package]] name = "treasury-management" version = "0.2.0" -source = "git+https://github.com/helium/helium-anchor-gen.git?branch=main#761b839a71cc6d2aecf4be994af9d8206aeae0e1" +source = "git+https://github.com/helium/helium-anchor-gen.git?branch=main#ef686c1b0ba0ab2bd0e0377e0bf2a44630938da2" dependencies = [ "anchor-gen", "anchor-lang 0.30.1", @@ -9379,7 +9396,7 @@ dependencies = [ [[package]] name = "treasury-management" version = "0.2.0" -source = "git+https://github.com/helium/helium-anchor-gen.git#761b839a71cc6d2aecf4be994af9d8206aeae0e1" +source = "git+https://github.com/helium/helium-anchor-gen.git#ef686c1b0ba0ab2bd0e0377e0bf2a44630938da2" dependencies = [ "anchor-gen", "anchor-lang 0.30.1", @@ -9425,7 +9442,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "97fee6b57c6a41524a810daee9286c02d7752c4253064d0b05472833a438f675" dependencies = [ "cfg-if", - "rand 0.7.3", + "rand 0.8.5", "static_assertions", ] @@ -9627,7 +9644,7 @@ dependencies = [ [[package]] name = "voter-stake-registry" version = "0.3.3" -source = "git+https://github.com/helium/helium-anchor-gen.git?branch=main#761b839a71cc6d2aecf4be994af9d8206aeae0e1" +source = "git+https://github.com/helium/helium-anchor-gen.git?branch=main#ef686c1b0ba0ab2bd0e0377e0bf2a44630938da2" dependencies = [ "anchor-gen", "anchor-lang 0.30.1", @@ -9636,7 +9653,7 @@ dependencies = [ [[package]] name = "voter-stake-registry" version = "0.3.3" -source = "git+https://github.com/helium/helium-anchor-gen.git#761b839a71cc6d2aecf4be994af9d8206aeae0e1" +source = "git+https://github.com/helium/helium-anchor-gen.git#ef686c1b0ba0ab2bd0e0377e0bf2a44630938da2" dependencies = [ "anchor-gen", "anchor-lang 0.30.1", diff --git a/Cargo.toml b/Cargo.toml index d891570a3..064cddcd7 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -71,10 +71,10 @@ helium-lib = { git = "https://github.com/helium/helium-wallet-rs.git", branch = hextree = { git = "https://github.com/jaykickliter/HexTree", branch = "main", features = [ "disktree", ] } -helium-proto = { git = "https://github.com/helium/proto", branch = "master", features = [ +helium-proto = { git = "https://github.com/helium/proto", branch = "andymck/hip-118-visualization-data", features = [ "services", ] } -beacon = { git = "https://github.com/helium/proto", branch = "master" } +beacon = { git = "https://github.com/helium/proto", branch = "andymck/hip-118-visualization-data" } solana-client = "1.18" solana-sdk = "1.18" solana-program = "1.18" diff --git a/file_store/src/file_info.rs b/file_store/src/file_info.rs index d0f824432..c0f6d4215 100644 --- a/file_store/src/file_info.rs +++ b/file_store/src/file_info.rs @@ -106,6 +106,11 @@ impl FileInfo { } } +pub const HEX_USAGE_COUNTS_INGEST_REPORT: &str = "hex_usage_counts_ingest_report"; +pub const RADIO_USAGE_COUNTS_INGEST_REPORT: &str = "radio_usage_counts_ingest_report"; +pub const HEX_USAGE_COUNTS_REQ: &str = "hex_usage_counts_req"; +pub const RADIO_USAGE_COUNTS_REQ: &str = "radio_usage_counts_req"; + pub const INVALIDATED_RADIO_THRESHOLD_REQ: &str = "invalidated_radio_threshold_req"; pub const INVALIDATED_RADIO_THRESHOLD_INGEST_REPORT: &str = "invalidated_radio_threshold_ingest_report"; @@ -228,6 +233,10 @@ pub enum FileType { PromotionRewardIngestReport, VerifiedPromotionReward, ServiceProviderPromotionFund, + HexUsageCountsIngestReport, + RadioUsageCountsIngestReport, + HexUsageCountsReq, + RadioUsageCountsReq, } impl fmt::Display for FileType { @@ -303,6 +312,10 @@ impl fmt::Display for FileType { Self::PromotionRewardIngestReport => PROMOTION_REWARD_INGEST_REPORT, Self::VerifiedPromotionReward => VERIFIED_PROMOTION_REWARD, Self::ServiceProviderPromotionFund => SERVICE_PROVIDER_PROMOTION_FUND, + Self::HexUsageCountsIngestReport => HEX_USAGE_COUNTS_INGEST_REPORT, + Self::RadioUsageCountsIngestReport => RADIO_USAGE_COUNTS_INGEST_REPORT, + Self::HexUsageCountsReq => HEX_USAGE_COUNTS_REQ, + Self::RadioUsageCountsReq => RADIO_USAGE_COUNTS_REQ, }; f.write_str(s) } @@ -381,6 +394,10 @@ impl FileType { Self::PromotionRewardIngestReport => PROMOTION_REWARD_INGEST_REPORT, Self::VerifiedPromotionReward => VERIFIED_PROMOTION_REWARD, Self::ServiceProviderPromotionFund => SERVICE_PROVIDER_PROMOTION_FUND, + Self::HexUsageCountsIngestReport => HEX_USAGE_COUNTS_INGEST_REPORT, + Self::RadioUsageCountsIngestReport => RADIO_USAGE_COUNTS_INGEST_REPORT, + Self::HexUsageCountsReq => HEX_USAGE_COUNTS_REQ, + Self::RadioUsageCountsReq => RADIO_USAGE_COUNTS_REQ, } } } @@ -458,6 +475,10 @@ impl FromStr for FileType { PROMOTION_REWARD_INGEST_REPORT => Self::PromotionRewardIngestReport, VERIFIED_PROMOTION_REWARD => Self::VerifiedPromotionReward, SERVICE_PROVIDER_PROMOTION_FUND => Self::ServiceProviderPromotionFund, + HEX_USAGE_COUNTS_INGEST_REPORT => Self::HexUsageCountsIngestReport, + RADIO_USAGE_COUNTS_INGEST_REPORT => Self::RadioUsageCountsIngestReport, + HEX_USAGE_COUNTS_REQ => Self::HexUsageCountsReq, + RADIO_USAGE_COUNTS_REQ => Self::RadioUsageCountsReq, _ => return Err(Error::from(io::Error::from(io::ErrorKind::InvalidInput))), }; Ok(result) diff --git a/file_store/src/lib.rs b/file_store/src/lib.rs index 9c5a132cd..090645611 100644 --- a/file_store/src/lib.rs +++ b/file_store/src/lib.rs @@ -27,6 +27,7 @@ pub mod speedtest; pub mod subscriber_verified_mapping_event; pub mod subscriber_verified_mapping_event_ingest_report; pub mod traits; +pub mod usage_counts; pub mod verified_subscriber_verified_mapping_event_ingest_report; pub mod wifi_heartbeat; diff --git a/file_store/src/traits/file_sink_write.rs b/file_store/src/traits/file_sink_write.rs index 54ea53100..ec1170b51 100644 --- a/file_store/src/traits/file_sink_write.rs +++ b/file_store/src/traits/file_sink_write.rs @@ -253,6 +253,16 @@ impl_file_sink!( FileType::WifiHeartbeatIngestReport.to_str(), "wifi_heartbeat_report" ); +impl_file_sink!( + poc_mobile::HexUsageCountsIngestReportV1, + FileType::HexUsageCountsIngestReport.to_str(), + "hex_usage_counts_ingest_report" +); +impl_file_sink!( + poc_mobile::RadioUsageCountsIngestReportV1, + FileType::RadioUsageCountsIngestReport.to_str(), + "hotspot_usage_counts_ingest_report" +); impl_file_sink!( proto::BoostedHexUpdateV1, FileType::BoostedHexUpdate.to_str(), diff --git a/file_store/src/traits/msg_verify.rs b/file_store/src/traits/msg_verify.rs index 017a1e315..8a665005a 100644 --- a/file_store/src/traits/msg_verify.rs +++ b/file_store/src/traits/msg_verify.rs @@ -96,6 +96,8 @@ impl_msg_verify!(mobile_config::BoostedHexModifiedInfoStreamReqV1, signature); impl_msg_verify!(mobile_config::BoostedHexInfoStreamResV1, signature); impl_msg_verify!(poc_mobile::SubscriberVerifiedMappingEventReqV1, signature); impl_msg_verify!(poc_mobile::PromotionRewardReqV1, signature); +impl_msg_verify!(poc_mobile::HexUsageCountsReqV1, signature); +impl_msg_verify!(poc_mobile::RadioUsageCountsReqV1, signature); #[cfg(test)] mod test { diff --git a/file_store/src/usage_counts.rs b/file_store/src/usage_counts.rs new file mode 100644 index 000000000..3a1ff0872 --- /dev/null +++ b/file_store/src/usage_counts.rs @@ -0,0 +1,230 @@ +use std::convert::TryFrom; + +use crate::{ + error::DecodeError, + traits::{MsgDecode, MsgTimestamp, TimestampDecode, TimestampEncode}, + Error, Result, +}; +use chrono::{DateTime, Utc}; +use h3o::CellIndex; +use helium_crypto::PublicKeyBinary; +use helium_proto::services::poc_mobile::{ + HexUsageCountsIngestReportV1, HexUsageCountsReqV1, RadioUsageCountsIngestReportV1, + RadioUsageCountsReqV1, +}; +use serde::{Deserialize, Serialize}; + +#[derive(Clone, Deserialize, Serialize, Debug, PartialEq)] +pub struct HexUsageCountsReq { + pub hex: CellIndex, + pub helium_mobile_subscriber_avg_count: u64, + pub helium_mobile_disco_mapping_avg_count: u64, + pub offload_avg_count: u64, + pub tmo_cell_avg_count: u64, + pub timestamp: DateTime, + pub carrier_mapping_key: PublicKeyBinary, +} + +#[derive(Clone, Deserialize, Serialize, Debug, PartialEq)] +pub struct RadioUsageCountsReq { + pub hotspot_pubkey: PublicKeyBinary, + pub cbsd_id: String, + pub helium_mobile_subscriber_avg_count: u64, + pub helium_mobile_disco_mapping_avg_count: u64, + pub offload_avg_count: u64, + pub timestamp: DateTime, + pub carrier_mapping_key: PublicKeyBinary, +} + +impl MsgDecode for HexUsageCountsReq { + type Msg = HexUsageCountsReqV1; +} + +impl MsgDecode for RadioUsageCountsReq { + type Msg = RadioUsageCountsReqV1; +} + +impl MsgTimestamp>> for HexUsageCountsReqV1 { + fn timestamp(&self) -> Result> { + self.timestamp.to_timestamp() + } +} + +impl MsgTimestamp for HexUsageCountsReq { + fn timestamp(&self) -> u64 { + self.timestamp.encode_timestamp() + } +} + +impl MsgTimestamp>> for RadioUsageCountsReqV1 { + fn timestamp(&self) -> Result> { + self.timestamp.to_timestamp() + } +} + +impl MsgTimestamp for RadioUsageCountsReq { + fn timestamp(&self) -> u64 { + self.timestamp.encode_timestamp() + } +} + +impl TryFrom for HexUsageCountsReq { + type Error = Error; + fn try_from(v: HexUsageCountsReqV1) -> Result { + let timestamp = v.timestamp()?; + let hex = CellIndex::try_from(v.hex).map_err(|_| { + DecodeError::FileStreamTryDecode(format!("invalid CellIndex {}", v.hex)) + })?; + Ok(Self { + hex, + helium_mobile_subscriber_avg_count: v.helium_mobile_subscriber_avg_count, + helium_mobile_disco_mapping_avg_count: v.helium_mobile_disco_mapping_avg_count, + offload_avg_count: v.offload_avg_count, + tmo_cell_avg_count: v.tmo_cell_avg_count, + timestamp, + carrier_mapping_key: v.carrier_mapping_key.into(), + }) + } +} + +impl From for HexUsageCountsReqV1 { + fn from(v: HexUsageCountsReq) -> Self { + let timestamp = v.timestamp(); + HexUsageCountsReqV1 { + hex: v.hex.into(), + helium_mobile_subscriber_avg_count: v.helium_mobile_subscriber_avg_count, + helium_mobile_disco_mapping_avg_count: v.helium_mobile_disco_mapping_avg_count, + offload_avg_count: v.offload_avg_count, + tmo_cell_avg_count: v.tmo_cell_avg_count, + timestamp, + carrier_mapping_key: v.carrier_mapping_key.into(), + signature: vec![], + } + } +} + +impl TryFrom for RadioUsageCountsReq { + type Error = Error; + fn try_from(v: RadioUsageCountsReqV1) -> Result { + let timestamp = v.timestamp()?; + Ok(Self { + hotspot_pubkey: v.hotspot_pubkey.into(), + cbsd_id: v.cbsd_id, + helium_mobile_subscriber_avg_count: v.helium_mobile_subscriber_avg_count, + helium_mobile_disco_mapping_avg_count: v.helium_mobile_disco_mapping_avg_count, + offload_avg_count: v.offload_avg_count, + timestamp, + carrier_mapping_key: v.carrier_mapping_key.into(), + }) + } +} + +impl From for RadioUsageCountsReqV1 { + fn from(v: RadioUsageCountsReq) -> Self { + let timestamp = v.timestamp(); + RadioUsageCountsReqV1 { + hotspot_pubkey: v.hotspot_pubkey.into(), + cbsd_id: v.cbsd_id, + helium_mobile_subscriber_avg_count: v.helium_mobile_subscriber_avg_count, + helium_mobile_disco_mapping_avg_count: v.helium_mobile_disco_mapping_avg_count, + offload_avg_count: v.offload_avg_count, + timestamp, + carrier_mapping_key: v.carrier_mapping_key.into(), + signature: vec![], + } + } +} + +#[derive(Clone, Deserialize, Serialize, Debug, PartialEq)] +pub struct HexUsageCountsIngestReport { + pub report: HexUsageCountsReq, + pub received_timestamp: DateTime, +} + +#[derive(Clone, Deserialize, Serialize, Debug, PartialEq)] +pub struct RadioUsageCountsIngestReport { + pub report: RadioUsageCountsReq, + pub received_timestamp: DateTime, +} + +impl MsgDecode for HexUsageCountsIngestReport { + type Msg = HexUsageCountsIngestReportV1; +} + +impl MsgDecode for RadioUsageCountsIngestReport { + type Msg = RadioUsageCountsIngestReportV1; +} + +impl MsgTimestamp>> for HexUsageCountsIngestReportV1 { + fn timestamp(&self) -> Result> { + self.received_timestamp.to_timestamp() + } +} + +impl MsgTimestamp for HexUsageCountsIngestReport { + fn timestamp(&self) -> u64 { + self.received_timestamp.encode_timestamp() + } +} + +impl MsgTimestamp>> for RadioUsageCountsIngestReportV1 { + fn timestamp(&self) -> Result> { + self.received_timestamp.to_timestamp() + } +} + +impl MsgTimestamp for RadioUsageCountsIngestReport { + fn timestamp(&self) -> u64 { + self.received_timestamp.encode_timestamp() + } +} + +impl TryFrom for HexUsageCountsIngestReport { + type Error = Error; + fn try_from(v: HexUsageCountsIngestReportV1) -> Result { + Ok(Self { + report: v + .clone() + .report + .ok_or_else(|| Error::not_found("ingest HexUsageCountsIngestReport report"))? + .try_into()?, + received_timestamp: v.timestamp()?, + }) + } +} + +impl From for HexUsageCountsIngestReportV1 { + fn from(v: HexUsageCountsIngestReport) -> Self { + let received_timestamp = v.received_timestamp; + let report: HexUsageCountsReqV1 = v.report.into(); + Self { + report: Some(report), + received_timestamp: received_timestamp.encode_timestamp(), + } + } +} + +impl TryFrom for RadioUsageCountsIngestReport { + type Error = Error; + fn try_from(v: RadioUsageCountsIngestReportV1) -> Result { + Ok(Self { + report: v + .clone() + .report + .ok_or_else(|| Error::not_found("ingest RadioUsageCountsIngestReport report"))? + .try_into()?, + received_timestamp: v.timestamp()?, + }) + } +} + +impl From for RadioUsageCountsIngestReportV1 { + fn from(v: RadioUsageCountsIngestReport) -> Self { + let received_timestamp = v.received_timestamp; + let report: RadioUsageCountsReqV1 = v.report.into(); + Self { + report: Some(report), + received_timestamp: received_timestamp.encode_timestamp(), + } + } +} diff --git a/ingest/Cargo.toml b/ingest/Cargo.toml index b8df84ebe..815ac1c17 100644 --- a/ingest/Cargo.toml +++ b/ingest/Cargo.toml @@ -34,6 +34,7 @@ file-store = { path = "../file_store" } poc-metrics = { path = "../metrics" } metrics = { workspace = true } metrics-exporter-prometheus = { workspace = true } +mobile-config = { path = "../mobile_config" } task-manager = { path = "../task_manager" } rand = { workspace = true } custom-tracing = { path = "../custom_tracing", features = ["grpc"] } diff --git a/ingest/src/server_mobile.rs b/ingest/src/server_mobile.rs index 71bf2bf07..acb81daad 100644 --- a/ingest/src/server_mobile.rs +++ b/ingest/src/server_mobile.rs @@ -8,15 +8,18 @@ use file_store::{ }; use futures::future::LocalBoxFuture; use futures_util::TryFutureExt; -use helium_crypto::{Network, PublicKey}; +use helium_crypto::{Network, PublicKey, PublicKeyBinary}; +use helium_proto::services::mobile_config::NetworkKeyRole; use helium_proto::services::poc_mobile::{ self, CellHeartbeatIngestReportV1, CellHeartbeatReqV1, CellHeartbeatRespV1, CoverageObjectIngestReportV1, CoverageObjectReqV1, CoverageObjectRespV1, DataTransferSessionIngestReportV1, DataTransferSessionReqV1, DataTransferSessionRespV1, + HexUsageCountsIngestReportV1, HexUsageCountsReqV1, HexUsageCountsResV1, InvalidatedRadioThresholdIngestReportV1, InvalidatedRadioThresholdReportReqV1, InvalidatedRadioThresholdReportRespV1, PromotionRewardIngestReportV1, PromotionRewardReqV1, PromotionRewardRespV1, RadioThresholdIngestReportV1, RadioThresholdReportReqV1, - RadioThresholdReportRespV1, ServiceProviderBoostedRewardsBannedRadioIngestReportV1, + RadioThresholdReportRespV1, RadioUsageCountsIngestReportV1, RadioUsageCountsReqV1, + RadioUsageCountsResV1, ServiceProviderBoostedRewardsBannedRadioIngestReportV1, ServiceProviderBoostedRewardsBannedRadioReqV1, ServiceProviderBoostedRewardsBannedRadioRespV1, SpeedtestIngestReportV1, SpeedtestReqV1, SpeedtestRespV1, SubscriberLocationIngestReportV1, SubscriberLocationReqV1, SubscriberLocationRespV1, @@ -24,6 +27,7 @@ use helium_proto::services::poc_mobile::{ SubscriberVerifiedMappingEventResV1, WifiHeartbeatIngestReportV1, WifiHeartbeatReqV1, WifiHeartbeatRespV1, }; +use mobile_config::client::{authorization_client::AuthorizationVerifier, AuthorizationClient}; use std::{net::SocketAddr, path::Path}; use task_manager::{ManagedTask, TaskManager}; use tonic::{ @@ -34,7 +38,7 @@ use tonic::{ pub type GrpcResult = std::result::Result, Status>; pub type VerifyResult = std::result::Result; -pub struct GrpcServer { +pub struct GrpcServer { heartbeat_report_sink: FileSinkClient, wifi_heartbeat_report_sink: FileSinkClient, speedtest_report_sink: FileSinkClient, @@ -48,12 +52,18 @@ pub struct GrpcServer { FileSinkClient, subscriber_mapping_event_sink: FileSinkClient, promotion_reward_sink: FileSinkClient, + hex_usage_counts_event_sink: FileSinkClient, + radio_usage_counts_event_sink: FileSinkClient, required_network: Network, address: SocketAddr, api_token: MetadataValue, + authorization_verifier: AV, } -impl ManagedTask for GrpcServer { +impl ManagedTask for GrpcServer +where + AV: AuthorizationVerifier + Send + Sync + 'static, +{ fn start_task( self: Box, shutdown: triggered::Listener, @@ -70,7 +80,10 @@ fn make_span(_request: &http::request::Request) -> ) } -impl GrpcServer { +impl GrpcServer +where + AV: AuthorizationVerifier + Send + Sync + 'static, +{ #[allow(clippy::too_many_arguments)] pub fn new( heartbeat_report_sink: FileSinkClient, @@ -88,9 +101,12 @@ impl GrpcServer { >, subscriber_mapping_event_sink: FileSinkClient, promotion_reward_sink: FileSinkClient, + hex_usage_counts_event_sink: FileSinkClient, + radio_usage_counts_event_sink: FileSinkClient, required_network: Network, address: SocketAddr, api_token: MetadataValue, + authorization_verifier: AV, ) -> Self { GrpcServer { heartbeat_report_sink, @@ -104,9 +120,12 @@ impl GrpcServer { sp_boosted_rewards_ban_sink, subscriber_mapping_event_sink, promotion_reward_sink, + hex_usage_counts_event_sink, + radio_usage_counts_event_sink, required_network, address, api_token, + authorization_verifier, } } @@ -150,10 +169,25 @@ impl GrpcServer { .map_err(|_| Status::invalid_argument("invalid signature"))?; Ok((public_key, event)) } + + async fn verify_known_carrier_key(&self, public_key: PublicKey) -> VerifyResult<()> { + let public_key_bin = PublicKeyBinary::from(public_key.clone()); + self.authorization_verifier + .verify_authorized_key(&public_key_bin, NetworkKeyRole::MobileCarrier) + .await + .map_err(|_| { + tracing::error!(%public_key_bin, "unknown carrier key"); + Status::invalid_argument("unknown carrier key") + })?; + Ok(()) + } } #[tonic::async_trait] -impl poc_mobile::PocMobile for GrpcServer { +impl poc_mobile::PocMobile for GrpcServer +where + AV: AuthorizationVerifier + Send + Sync + 'static, +{ async fn submit_speedtest( &self, request: Request, @@ -290,6 +324,30 @@ impl poc_mobile::PocMobile for GrpcServer { })) } + async fn submit_coverage_object( + &self, + request: Request, + ) -> GrpcResult { + let timestamp: u64 = Utc::now().timestamp_millis() as u64; + let event = request.into_inner(); + + custom_tracing::record_b58("pub_key", &event.pub_key); + + let report = self + .verify_public_key(event.pub_key.as_ref()) + .and_then(|public_key| self.verify_network(public_key)) + .and_then(|public_key| self.verify_signature(public_key, event)) + .map(|(_, event)| CoverageObjectIngestReportV1 { + received_timestamp: timestamp, + report: Some(event), + })?; + + _ = self.coverage_object_report_sink.write(report, []).await; + + let id = timestamp.to_string(); + Ok(Response::new(CoverageObjectRespV1 { id })) + } + async fn submit_threshold_report( &self, request: Request, @@ -365,30 +423,6 @@ impl poc_mobile::PocMobile for GrpcServer { })) } - async fn submit_coverage_object( - &self, - request: Request, - ) -> GrpcResult { - let timestamp: u64 = Utc::now().timestamp_millis() as u64; - let event = request.into_inner(); - - custom_tracing::record_b58("pub_key", &event.pub_key); - - let report = self - .verify_public_key(event.pub_key.as_ref()) - .and_then(|public_key| self.verify_network(public_key)) - .and_then(|public_key| self.verify_signature(public_key, event)) - .map(|(_, event)| CoverageObjectIngestReportV1 { - received_timestamp: timestamp, - report: Some(event), - })?; - - _ = self.coverage_object_report_sink.write(report, []).await; - - let id = timestamp.to_string(); - Ok(Response::new(CoverageObjectRespV1 { id })) - } - async fn submit_sp_boosted_rewards_banned_radio( &self, request: Request, @@ -465,6 +499,58 @@ impl poc_mobile::PocMobile for GrpcServer { let id = received_timestamp.to_string(); Ok(Response::new(PromotionRewardRespV1 { id })) } + + async fn submit_hex_usage_counts_report( + &self, + request: Request, + ) -> GrpcResult { + let timestamp = Utc::now().timestamp_millis() as u64; + let event = request.into_inner(); + + custom_tracing::record("hex", event.hex); + + let (verified_pubkey, event) = self + .verify_public_key(event.carrier_mapping_key.as_ref()) + .and_then(|public_key| self.verify_network(public_key)) + .and_then(|public_key| self.verify_signature(public_key, event.clone()))?; + self.verify_known_carrier_key(verified_pubkey).await?; + + let report = HexUsageCountsIngestReportV1 { + received_timestamp: timestamp, + report: Some(event), + }; + + _ = self.hex_usage_counts_event_sink.write(report, []).await; + + let id = timestamp.to_string(); + Ok(Response::new(HexUsageCountsResV1 { id })) + } + + async fn submit_radio_usage_counts_report( + &self, + request: Request, + ) -> GrpcResult { + let timestamp = Utc::now().timestamp_millis() as u64; + let event = request.into_inner(); + + custom_tracing::record_b58("pub_key", &event.hotspot_pubkey); + + let (verified_pubkey, event) = self + .verify_public_key(event.carrier_mapping_key.as_ref()) + .and_then(|public_key| self.verify_network(public_key)) + .and_then(|public_key| self.verify_signature(public_key, event.clone()))?; + self.verify_known_carrier_key(verified_pubkey).await?; + + let report = RadioUsageCountsIngestReportV1 { + received_timestamp: timestamp, + report: Some(event), + }; + + _ = self.radio_usage_counts_event_sink.write(report, []).await; + + let id = timestamp.to_string(); + Ok(Response::new(RadioUsageCountsResV1 { id })) + } } pub async fn grpc_server(settings: &Settings) -> Result<()> { @@ -584,6 +670,26 @@ pub async fn grpc_server(settings: &Settings) -> Result<()> { ) .await?; + let (hex_usage_counts_event_sink, hex_usage_counts_event_server) = + HexUsageCountsIngestReportV1::file_sink( + store_base_path, + file_upload.clone(), + FileSinkCommitStrategy::Automatic, + FileSinkRollTime::Duration(settings.roll_time), + env!("CARGO_PKG_NAME"), + ) + .await?; + + let (radio_usage_counts_event_sink, radio_usage_counts_event_server) = + RadioUsageCountsIngestReportV1::file_sink( + store_base_path, + file_upload.clone(), + FileSinkCommitStrategy::Automatic, + FileSinkRollTime::Duration(settings.roll_time), + env!("CARGO_PKG_NAME"), + ) + .await?; + let Some(api_token) = settings .token .as_ref() @@ -604,9 +710,12 @@ pub async fn grpc_server(settings: &Settings) -> Result<()> { sp_boosted_rewards_ban_sink, subscriber_mapping_event_sink, subscriber_referral_eligibility_sink, + hex_usage_counts_event_sink, + radio_usage_counts_event_sink, settings.network, settings.listen_addr, api_token, + AuthorizationClient::from_settings(&settings.config_client)?, ); tracing::info!( @@ -628,6 +737,8 @@ pub async fn grpc_server(settings: &Settings) -> Result<()> { .add_task(sp_boosted_rewards_ban_sink_server) .add_task(subscriber_mapping_event_server) .add_task(subscriber_referral_eligibility_server) + .add_task(hex_usage_counts_event_server) + .add_task(radio_usage_counts_event_server) .add_task(grpc_server) .build() .start() diff --git a/ingest/src/settings.rs b/ingest/src/settings.rs index b08f53b01..71ac95fd5 100644 --- a/ingest/src/settings.rs +++ b/ingest/src/settings.rs @@ -41,6 +41,8 @@ pub struct Settings { pub token: Option, /// Target output bucket details Metrics settings pub metrics: poc_metrics::Settings, + // mobile config client settings + pub config_client: mobile_config::ClientSettings, } fn default_roll_time() -> Duration { diff --git a/ingest/tests/common/mod.rs b/ingest/tests/common/mod.rs index 5584416a0..9d9989099 100644 --- a/ingest/tests/common/mod.rs +++ b/ingest/tests/common/mod.rs @@ -1,23 +1,52 @@ use anyhow::bail; use backon::{ExponentialBuilder, Retryable}; use file_store::file_sink::FileSinkClient; -use helium_crypto::{KeyTag, Keypair, Network, Sign}; +use helium_crypto::{KeyTag, Keypair, Network, PublicKeyBinary, Sign}; use helium_proto::services::poc_mobile::{ - Client as PocMobileClient, SubscriberVerifiedMappingEventIngestReportV1, - SubscriberVerifiedMappingEventReqV1, SubscriberVerifiedMappingEventResV1, + HexUsageCountsIngestReportV1, HexUsageCountsReqV1, HexUsageCountsResV1, + RadioUsageCountsIngestReportV1, RadioUsageCountsReqV1, RadioUsageCountsResV1, +}; +use helium_proto::services::{ + mobile_config::NetworkKeyRole, + poc_mobile::{ + Client as PocMobileClient, SubscriberVerifiedMappingEventIngestReportV1, + SubscriberVerifiedMappingEventReqV1, SubscriberVerifiedMappingEventResV1, + }, }; use ingest::server_mobile::GrpcServer; +use mobile_config::client::authorization_client::AuthorizationVerifier; use prost::Message; use rand::rngs::OsRng; use std::{net::SocketAddr, sync::Arc, time::Duration}; use tokio::{net::TcpListener, sync::mpsc::Receiver, time::timeout}; use tonic::{ + async_trait, metadata::{Ascii, MetadataValue}, transport::Channel, Request, }; use triggered::Trigger; +pub struct MockAuthorizationClient {} + +impl MockAuthorizationClient { + pub fn new() -> Self { + MockAuthorizationClient {} + } +} + +#[async_trait] +impl AuthorizationVerifier for MockAuthorizationClient { + type Error = anyhow::Error; + + async fn verify_authorized_key( + &self, + _pubkey: &PublicKeyBinary, + _role: NetworkKeyRole, + ) -> anyhow::Result { + Ok(true) + } +} pub async fn setup_mobile() -> anyhow::Result<(TestClient, Trigger)> { let key_pair = generate_keypair(); @@ -45,6 +74,10 @@ pub async fn setup_mobile() -> anyhow::Result<(TestClient, Trigger)> { let (sp_boosted_tx, _rx) = tokio::sync::mpsc::channel(10); let (subscriber_mapping_tx, subscriber_mapping_rx) = tokio::sync::mpsc::channel(10); let (promotion_rewards_tx, _rx) = tokio::sync::mpsc::channel(10); + let (hex_usage_count_tx, hex_usage_count_rx) = tokio::sync::mpsc::channel(10); + let (radio_usage_count_tx, radio_usage_count_rx) = tokio::sync::mpsc::channel(10); + + let auth_client = MockAuthorizationClient::new(); tokio::spawn(async move { let grpc_server = GrpcServer::new( @@ -59,9 +92,12 @@ pub async fn setup_mobile() -> anyhow::Result<(TestClient, Trigger)> { FileSinkClient::new(sp_boosted_tx, "noop"), FileSinkClient::new(subscriber_mapping_tx, "test_file_sink"), FileSinkClient::new(promotion_rewards_tx, "noop"), + FileSinkClient::new(hex_usage_count_tx, "hex_usage_test_file_sink"), + FileSinkClient::new(radio_usage_count_tx, "radio_usage_test_file_sink"), Network::MainNet, socket_addr, api_token, + auth_client, ); grpc_server.run(listener).await @@ -72,6 +108,8 @@ pub async fn setup_mobile() -> anyhow::Result<(TestClient, Trigger)> { key_pair, token.to_string(), subscriber_mapping_rx, + hex_usage_count_rx, + radio_usage_count_rx, ) .await; @@ -82,8 +120,12 @@ pub struct TestClient { client: PocMobileClient, key_pair: Arc, authorization: MetadataValue, - file_sink_rx: + subscriber_mapping_file_sink_rx: Receiver>, + hex_usage_counts_file_sink_rx: + Receiver>, + radio_usage_counts_file_sink_rx: + Receiver>, } impl TestClient { @@ -91,9 +133,15 @@ impl TestClient { socket_addr: SocketAddr, key_pair: Keypair, api_token: String, - file_sink_rx: Receiver< + subscriber_mapping_file_sink_rx: Receiver< file_store::file_sink::Message, >, + hex_usage_counts_file_sink_rx: Receiver< + file_store::file_sink::Message, + >, + radio_usage_counts_file_sink_rx: Receiver< + file_store::file_sink::Message, + >, ) -> TestClient { let client = (|| PocMobileClient::connect(format!("http://{socket_addr}"))) .retry(&ExponentialBuilder::default()) @@ -104,12 +152,55 @@ impl TestClient { client, key_pair: Arc::new(key_pair), authorization: format!("Bearer {}", api_token).try_into().unwrap(), - file_sink_rx, + subscriber_mapping_file_sink_rx, + hex_usage_counts_file_sink_rx, + radio_usage_counts_file_sink_rx, + } + } + + pub async fn subscriber_mapping_recv( + mut self, + ) -> anyhow::Result { + match timeout( + Duration::from_secs(2), + self.subscriber_mapping_file_sink_rx.recv(), + ) + .await + { + Ok(Some(msg)) => match msg { + file_store::file_sink::Message::Commit(_) => bail!("got Commit"), + file_store::file_sink::Message::Rollback(_) => bail!("got Rollback"), + file_store::file_sink::Message::Data(_, data) => Ok(data), + }, + Ok(None) => bail!("got none"), + Err(reason) => bail!("got error {reason}"), } } - pub async fn recv(mut self) -> anyhow::Result { - match timeout(Duration::from_secs(2), self.file_sink_rx.recv()).await { + pub async fn hex_usage_recv(mut self) -> anyhow::Result { + match timeout( + Duration::from_secs(2), + self.hex_usage_counts_file_sink_rx.recv(), + ) + .await + { + Ok(Some(msg)) => match msg { + file_store::file_sink::Message::Commit(_) => bail!("got Commit"), + file_store::file_sink::Message::Rollback(_) => bail!("got Rollback"), + file_store::file_sink::Message::Data(_, data) => Ok(data), + }, + Ok(None) => bail!("got none"), + Err(reason) => bail!("got error {reason}"), + } + } + + pub async fn radio_usage_recv(mut self) -> anyhow::Result { + match timeout( + Duration::from_secs(2), + self.radio_usage_counts_file_sink_rx.recv(), + ) + .await + { Ok(Some(msg)) => match msg { file_store::file_sink::Message::Commit(_) => bail!("got Commit"), file_store::file_sink::Message::Rollback(_) => bail!("got Rollback"), @@ -147,6 +238,71 @@ impl TestClient { Ok(res.into_inner()) } + + pub async fn submit_hex_usage_req( + &mut self, + hex: u64, + helium_mobile_subscriber_avg_count: u64, + helium_mobile_disco_mapping_avg_count: u64, + offload_avg_count: u64, + tmo_cell_avg_count: u64, + ) -> anyhow::Result { + let mut req = HexUsageCountsReqV1 { + hex, + helium_mobile_subscriber_avg_count, + helium_mobile_disco_mapping_avg_count, + offload_avg_count, + tmo_cell_avg_count, + timestamp: 0, + carrier_mapping_key: self.key_pair.public_key().to_vec(), + signature: vec![], + }; + + req.signature = self.key_pair.sign(&req.encode_to_vec()).expect("sign"); + + let mut request = Request::new(req); + let metadata = request.metadata_mut(); + + metadata.insert("authorization", self.authorization.clone()); + + let res = self.client.submit_hex_usage_counts_report(request).await?; + + Ok(res.into_inner()) + } + + pub async fn submit_radio_usage_req( + &mut self, + hotspot_pubkey: PublicKeyBinary, + cbsd_id: String, + helium_mobile_subscriber_avg_count: u64, + helium_mobile_disco_mapping_avg_count: u64, + offload_avg_count: u64, + ) -> anyhow::Result { + let mut req = RadioUsageCountsReqV1 { + hotspot_pubkey: hotspot_pubkey.into(), + cbsd_id, + helium_mobile_subscriber_avg_count, + helium_mobile_disco_mapping_avg_count, + offload_avg_count, + timestamp: 0, + carrier_mapping_key: self.key_pair.public_key().to_vec(), + signature: vec![], + }; + + req.signature = self.key_pair.sign(&req.encode_to_vec()).expect("sign"); + + let mut request = Request::new(req); + let metadata = request.metadata_mut(); + + metadata.insert("authorization", self.authorization.clone()); + + let res = self + .client + .submit_radio_usage_counts_report(request) + .await?; + + Ok(res.into_inner()) + } } pub fn generate_keypair() -> Keypair { diff --git a/ingest/tests/mobile_ingest.rs b/ingest/tests/mobile_ingest.rs index 477e2ede2..de076fd2f 100644 --- a/ingest/tests/mobile_ingest.rs +++ b/ingest/tests/mobile_ingest.rs @@ -1,5 +1,10 @@ +use helium_crypto::PublicKeyBinary; +use std::str::FromStr; + mod common; +const PUBKEY1: &str = "113HRxtzxFbFUjDEJJpyeMRZRtdAW38LAUnB5mshRwi6jt7uFbt"; + #[tokio::test] async fn submit_verified_subscriber_mapping_event() -> anyhow::Result<()> { let (mut client, trigger) = common::setup_mobile().await?; @@ -15,7 +20,7 @@ async fn submit_verified_subscriber_mapping_event() -> anyhow::Result<()> { let timestamp: String = res.unwrap().id; - match client.recv().await { + match client.subscriber_mapping_recv().await { Ok(report) => { assert_eq!(timestamp, report.received_timestamp.to_string()); @@ -33,3 +38,107 @@ async fn submit_verified_subscriber_mapping_event() -> anyhow::Result<()> { trigger.trigger(); Ok(()) } + +#[tokio::test] +async fn submit_hex_usage_report() -> anyhow::Result<()> { + let (mut client, trigger) = common::setup_mobile().await?; + + const HEX: u64 = 360; + const HELIUM_MOBILE_SUBSCRIBER_AVG_COUNT: u64 = 10; + const HELIUM_MOBILE_DISCO_MAPPING_AVG_COUNT: u64 = 11; + const OFFLOAD_AVG_COUNT: u64 = 12; + const TMO_CELL_AVG_COUNT: u64 = 13; + + let res = client + .submit_hex_usage_req( + HEX, + HELIUM_MOBILE_SUBSCRIBER_AVG_COUNT, + HELIUM_MOBILE_DISCO_MAPPING_AVG_COUNT, + OFFLOAD_AVG_COUNT, + TMO_CELL_AVG_COUNT, + ) + .await; + + assert!(res.is_ok()); + + let timestamp: String = res.unwrap().id; + + match client.hex_usage_recv().await { + Ok(report) => { + assert_eq!(timestamp, report.received_timestamp.to_string()); + + match report.report { + None => panic!("No report found"), + Some(event) => { + assert_eq!(HEX, event.hex); + assert_eq!( + HELIUM_MOBILE_SUBSCRIBER_AVG_COUNT, + event.helium_mobile_subscriber_avg_count + ); + assert_eq!( + HELIUM_MOBILE_DISCO_MAPPING_AVG_COUNT, + event.helium_mobile_disco_mapping_avg_count + ); + assert_eq!(OFFLOAD_AVG_COUNT, event.offload_avg_count); + assert_eq!(TMO_CELL_AVG_COUNT, event.tmo_cell_avg_count); + } + } + } + Err(e) => panic!("got error {e}"), + } + + trigger.trigger(); + Ok(()) +} + +#[tokio::test] +async fn submit_radio_usage_report() -> anyhow::Result<()> { + let (mut client, trigger) = common::setup_mobile().await?; + + let hotspot_pubkey = PublicKeyBinary::from_str(PUBKEY1)?; + let cbsd_id = "cbsd_id".to_string(); + const HELIUM_MOBILE_SUBSCRIBER_AVG_COUNT: u64 = 10; + const HELIUM_MOBILE_DISCO_MAPPING_AVG_COUNT: u64 = 11; + const OFFLOAD_AVG_COUNT: u64 = 12; + + let res = client + .submit_radio_usage_req( + hotspot_pubkey.clone(), + cbsd_id.clone(), + HELIUM_MOBILE_SUBSCRIBER_AVG_COUNT, + HELIUM_MOBILE_DISCO_MAPPING_AVG_COUNT, + OFFLOAD_AVG_COUNT, + ) + .await; + + assert!(res.is_ok()); + + let timestamp: String = res.unwrap().id; + + match client.radio_usage_recv().await { + Ok(report) => { + assert_eq!(timestamp, report.received_timestamp.to_string()); + + match report.report { + None => panic!("No report found"), + Some(event) => { + assert_eq!(hotspot_pubkey.as_ref(), event.hotspot_pubkey); + assert_eq!(cbsd_id, event.cbsd_id); + assert_eq!( + HELIUM_MOBILE_SUBSCRIBER_AVG_COUNT, + event.helium_mobile_subscriber_avg_count + ); + assert_eq!( + HELIUM_MOBILE_DISCO_MAPPING_AVG_COUNT, + event.helium_mobile_disco_mapping_avg_count + ); + assert_eq!(OFFLOAD_AVG_COUNT, event.offload_avg_count); + } + } + } + Err(e) => panic!("got error {e}"), + } + + trigger.trigger(); + Ok(()) +}