diff --git a/.gitignore b/.gitignore index 50af4c7..79749b6 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ **target /Cargo.lock /.idea -/.fleet \ No newline at end of file +/.fleet +nimcache/ diff --git a/Cargo.lock b/Cargo.lock index 06bdc08..7dbbffb 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -530,8 +530,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bfd4d1b31faaa3a89d7934dbded3111da0d2ef28e3ebccdb4f0179f5929d1ef1" dependencies = [ "iana-time-zone", + "js-sys", "num-integer", "num-traits", + "time", + "wasm-bindgen", "winapi", ] @@ -1292,7 +1295,7 @@ checksum = "4eb1a864a501629691edf6c15a593b7a51eebaa1e8468e9ddc623de7c9b58ec6" dependencies = [ "cfg-if", "libc", - "wasi", + "wasi 0.11.0+wasi-snapshot-preview1", ] [[package]] @@ -1695,7 +1698,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8f3d0b296e374a4e6f3c7b0a1f5a51d748a0d34c85e7dc48fc3fa9a87657fe09" dependencies = [ "libc", - "wasi", + "wasi 0.11.0+wasi-snapshot-preview1", "windows-sys 0.48.0", ] @@ -2812,6 +2815,17 @@ dependencies = [ "once_cell", ] +[[package]] +name = "time" +version = "0.1.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b797afad3f312d1c66a56d11d0316f916356d11bd158fbc6ca6389ff6bf805a" +dependencies = [ + "libc", + "wasi 0.10.0+wasi-snapshot-preview1", + "winapi", +] + [[package]] name = "tiny-keccak" version = "2.0.2" @@ -3034,6 +3048,9 @@ name = "uuid" version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f00cc9702ca12d3c81455259621e676d0f7251cec66a21e98fe2e9a37db93b2a" +dependencies = [ + "getrandom", +] [[package]] name = "valuable" @@ -3053,6 +3070,7 @@ version = "0.5.0" dependencies = [ "aes-gcm", "base64 0.21.0", + "chrono", "enr", "futures", "hex", @@ -3071,6 +3089,7 @@ dependencies = [ "sscanf", "tokio", "url", + "uuid", "waku-sys", ] @@ -3092,6 +3111,12 @@ dependencies = [ "winapi-util", ] +[[package]] +name = "wasi" +version = "0.10.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f" + [[package]] name = "wasi" version = "0.11.0+wasi-snapshot-preview1" diff --git a/examples/Cargo.lock b/examples/Cargo.lock index 5627c99..6ccf393 100644 --- a/examples/Cargo.lock +++ b/examples/Cargo.lock @@ -168,19 +168,13 @@ dependencies = [ [[package]] name = "aho-corasick" -version = "1.1.2" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2969dcb958b36655471fc61f7e416fa76033bdd4bfed0678d8fee1e2d07a1f0" +checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" dependencies = [ "memchr", ] -[[package]] -name = "allocator-api2" -version = "0.2.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0942ffc6dcaadf03badf6e6a2d0228460359d5e34b57ccdc720b7382dfbd5ec5" - [[package]] name = "android-activity" version = "0.4.3" @@ -220,6 +214,12 @@ dependencies = [ "libc", ] +[[package]] +name = "anyhow" +version = "1.0.93" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c95c10ba0b00a02636238b814946408b1322d5ac4760326e6fb8ec956d85775" + [[package]] name = "arboard" version = "3.4.1" @@ -231,7 +231,7 @@ dependencies = [ "objc2 0.5.2", "objc2-app-kit", "objc2-foundation", - "parking_lot 0.12.1", + "parking_lot 0.12.3", "x11rb", ] @@ -445,9 +445,9 @@ dependencies = [ [[package]] name = "arrayref" -version = "0.3.7" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b4930d2cb77ce62f89ee5d5289b4ac049559b1c45539271f5ed4fdc7db34545" +checksum = "76a2e8124351fda1ef8aaaa3bbd7ebbcb486bbcd4225aca0aa0d84bb2db8fecb" [[package]] name = "arrayvec" @@ -496,7 +496,7 @@ checksum = "30ca9a001c1e8ba5149f91a74362376cc6bc5b919d92d988668657bd570bdcec" dependencies = [ "async-task", "concurrent-queue", - "fastrand 2.0.1", + "fastrand 2.2.0", "futures-lite 2.5.0", "slab", ] @@ -535,9 +535,9 @@ dependencies = [ [[package]] name = "async-io" -version = "2.3.3" +version = "2.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d6baa8f0178795da0e71bc42c9e5d13261aac7ee549853162e66a241ba17964" +checksum = "43a2b323ccce0a1d90b449fd71f2a06ca7faa7c54c2751f06c9bd851fc061059" dependencies = [ "async-lock 3.4.0", "cfg-if", @@ -545,11 +545,11 @@ dependencies = [ "futures-io", "futures-lite 2.5.0", "parking", - "polling 3.7.2", - "rustix 0.38.31", + "polling 3.7.4", + "rustix 0.38.41", "slab", "tracing", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -585,7 +585,7 @@ dependencies = [ "cfg-if", "event-listener 3.1.0", "futures-lite 1.13.0", - "rustix 0.38.31", + "rustix 0.38.41", "windows-sys 0.48.0", ] @@ -597,25 +597,25 @@ checksum = "3b43422f69d8ff38f95f1b2bb76517c91589a924d1559a0e935d7c8ce0274c11" dependencies = [ "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.89", ] [[package]] name = "async-signal" -version = "0.2.9" +version = "0.2.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dfb3634b73397aa844481f814fad23bbf07fdb0eabec10f2eb95e58944b1ec32" +checksum = "637e00349800c0bdf8bfc21ebbc0b6524abea702b0da4168ac00d070d0c0b9f3" dependencies = [ - "async-io 2.3.3", + "async-io 2.4.0", "async-lock 3.4.0", "atomic-waker", "cfg-if", "futures-core", "futures-io", - "rustix 0.38.31", + "rustix 0.38.41", "signal-hook-registry", "slab", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -632,7 +632,7 @@ checksum = "721cae7de5c34fbb2acd27e21e6d2cf7b886dce0c27388d46c4e6c47ea4318dd" dependencies = [ "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.89", ] [[package]] @@ -687,21 +687,21 @@ dependencies = [ [[package]] name = "autocfg" -version = "1.1.0" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" +checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" [[package]] name = "backtrace" -version = "0.3.69" +version = "0.3.71" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2089b7e3f35b9dd2d0ed921ead4f6d318c27680d4a5bd167b3ee120edb105837" +checksum = "26b05800d2e817c8b3b4b54abd461726265fa9789ae34330622f2db9ee696f9d" dependencies = [ "addr2line", "cc", "cfg-if", "libc", - "miniz_oxide 0.7.2", + "miniz_oxide 0.7.4", "object 0.32.2", "rustc-demangle", ] @@ -743,7 +743,7 @@ dependencies = [ "futures", "serde_json", "tokio", - "tokio-util 0.7.10", + "tokio-util 0.7.12", "waku-bindings", ] @@ -866,9 +866,9 @@ checksum = "771fe0050b883fcc3ea2359b1a96bcfbc090b7116eae7c3c512c7a083fdf23d3" [[package]] name = "bumpalo" -version = "3.15.3" +version = "3.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ea184aa71bb362a1157c896979544cc23974e08fd265f29ea96b59f0b4a555b" +checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" [[package]] name = "bytecheck" @@ -894,9 +894,9 @@ dependencies = [ [[package]] name = "bytemuck" -version = "1.19.0" +version = "1.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8334215b81e418a0a7bdb8ef0849474f40bb10c8b71f1c4ed315cff49f32494d" +checksum = "8b37c88a63ffd85d15b406896cc343916d7cf57838a847b3a6f2ca5d39a5695a" dependencies = [ "bytemuck_derive", ] @@ -909,7 +909,7 @@ checksum = "bcfcc3cd946cb52f0bbfdbbcfa2f4e24f75ebb6c0e1002f7c25904fada18b9ec" dependencies = [ "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.89", ] [[package]] @@ -920,9 +920,9 @@ checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" [[package]] name = "bytes" -version = "1.5.0" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2bd12c1caf447e69cd4528f47f94d203fd2582878ecb9e9465484c4148a8223" +checksum = "325918d6fe32f23b19878fe4b34794ae41fc19ddbe53b10571a4874d44ffd39b" [[package]] name = "calloop" @@ -938,6 +938,12 @@ dependencies = [ "vec_map", ] +[[package]] +name = "cassowary" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df8670b8c7b9dae1793364eafadf7239c40d669904660c5960d74cfd80b46a53" + [[package]] name = "cast" version = "0.3.0" @@ -946,11 +952,13 @@ checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5" [[package]] name = "cc" -version = "1.0.88" +version = "1.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02f341c093d19155a6e41631ce5971aac4e9a868262212153124c15fa22d1cdc" +checksum = "f34d93e62b03caf570cccc334cbc6c2fceca82f39211051345108adcba3eebdc" dependencies = [ + "jobserver", "libc", + "shlex", ] [[package]] @@ -980,6 +988,12 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fd16c4719339c4530435d38e511904438d07cce7950afa3718a84ac36c10e89e" +[[package]] +name = "cfg_aliases" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" + [[package]] name = "cgl" version = "0.3.2" @@ -991,14 +1005,16 @@ dependencies = [ [[package]] name = "chrono" -version = "0.4.34" +version = "0.4.38" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5bc015644b92d5890fab7489e49d21f879d5c990186827d42ec511919404f38b" +checksum = "a21f936df1771bf62b77f047b726c4625ff2e8aa607c01ec06e5a05bd8463401" dependencies = [ "android-tzdata", "iana-time-zone", + "js-sys", "num-traits", - "windows-targets 0.52.4", + "wasm-bindgen", + "windows-targets 0.52.6", ] [[package]] @@ -1013,13 +1029,13 @@ dependencies = [ [[package]] name = "clang-sys" -version = "1.7.0" +version = "1.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67523a3b4be3ce1989d607a828d036249522dd9c1c8de7f4dd2dae43a37369d1" +checksum = "0b023947811758c97c59bf9d1c188fd619ad4718dcaa767947df1cadb14f39f4" dependencies = [ "glob", "libc", - "libloading 0.8.2", + "libloading 0.8.6", ] [[package]] @@ -1030,7 +1046,7 @@ checksum = "a0610544180c38b88101fecf2dd634b174a62eef6946f84dfc6a7127512b381c" dependencies = [ "bitflags 1.3.2", "textwrap", - "unicode-width", + "unicode-width 0.1.12", ] [[package]] @@ -1132,18 +1148,18 @@ checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8" [[package]] name = "const_format" -version = "0.2.32" +version = "0.2.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3a214c7af3d04997541b18d432afaff4c455e79e2029079647e72fc2bd27673" +checksum = "c990efc7a285731f9a4378d81aff2f0e85a2c8781a05ef0f8baa8dac54d0ff48" dependencies = [ "const_format_proc_macros", ] [[package]] name = "const_format_proc_macros" -version = "0.2.32" +version = "0.2.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7f6ff08fd20f4f299298a28e2dfa8a8ba1036e6cd2460ac1de7b425d76f2500" +checksum = "e026b6ce194a874cb9cf32cd5772d1ef9767cc8fcb5765948d74f37a9d8b2bf6" dependencies = [ "proc-macro2", "quote", @@ -1171,9 +1187,9 @@ dependencies = [ [[package]] name = "core-foundation-sys" -version = "0.8.6" +version = "0.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f" +checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" [[package]] name = "core-graphics" @@ -1223,9 +1239,9 @@ dependencies = [ [[package]] name = "cpufeatures" -version = "0.2.12" +version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53fe5e26ff1b7aef8bca9c6080520cfb8d9333c7568e1829cef191a9723e5504" +checksum = "16b80225097f2e5ae4e7179dd2266824648f3e2f49d9134d584b76389d31c4c3" dependencies = [ "libc", ] @@ -1291,9 +1307,9 @@ dependencies = [ [[package]] name = "crc32fast" -version = "1.4.0" +version = "1.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3855a8a784b474f333699ef2bbca9db2c4a1f6d9088a90a2d25b1eb53111eaa" +checksum = "a97769d94ddab943e4510d138150169a2758b5ef3eb191a9ee688de3e23ef7b3" dependencies = [ "cfg-if", ] @@ -1355,9 +1371,34 @@ dependencies = [ [[package]] name = "crossbeam-utils" -version = "0.8.19" +version = "0.8.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "248e3bacc7dc6baa3b21e405ee045c3047101a49145e7e9eca583ab4c2ca5345" +checksum = "22ec99545bb0ed0ea7bb9b8e1e9122ea386ff8a48c0922e43f36d45ab09e0e80" + +[[package]] +name = "crossterm" +version = "0.25.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e64e6c0fbe2c17357405f7c758c1ef960fce08bdfb2c03d88d2a18d7e09c4b67" +dependencies = [ + "bitflags 1.3.2", + "crossterm_winapi", + "libc", + "mio 0.8.11", + "parking_lot 0.12.3", + "signal-hook", + "signal-hook-mio", + "winapi", +] + +[[package]] +name = "crossterm_winapi" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "acdd7c62a3665c7f6830a51635d9ac9b23ed385797f70a83bb8bafe9c572ab2b" +dependencies = [ + "winapi", +] [[package]] name = "crunchy" @@ -1390,9 +1431,9 @@ dependencies = [ [[package]] name = "csv" -version = "1.3.0" +version = "1.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac574ff4d437a7b5ad237ef331c17ccca63c46479e5b5453eb8e10bb99a759fe" +checksum = "acdc4883a9c96732e4733212c01447ebd805833b7275a73ca3ee080fd77afdaf" dependencies = [ "csv-core", "itoa", @@ -1420,19 +1461,19 @@ dependencies = [ [[package]] name = "ctrlc" -version = "3.4.4" +version = "3.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "672465ae37dc1bc6380a6547a8883d5dd397b0f1faaad4f265726cc7042a5345" +checksum = "90eeab0aa92f3f9b4e87f258c72b139c207d251f9cbc1080a0086b86a8870dd3" dependencies = [ - "nix 0.28.0", - "windows-sys 0.52.0", + "nix 0.29.0", + "windows-sys 0.59.0", ] [[package]] name = "darling" -version = "0.20.8" +version = "0.20.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "54e36fcd13ed84ffdfda6f5be89b31287cbb80c439841fe69e04841435464391" +checksum = "6f63b86c8a8826a49b8c21f08a2d07338eec8d900540f8630dc76284be802989" dependencies = [ "darling_core", "darling_macro", @@ -1440,39 +1481,39 @@ dependencies = [ [[package]] name = "darling_core" -version = "0.20.8" +version = "0.20.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c2cf1c23a687a1feeb728783b993c4e1ad83d99f351801977dd809b48d0a70f" +checksum = "95133861a8032aaea082871032f5815eb9e98cef03fa916ab4500513994df9e5" dependencies = [ "fnv", "ident_case", "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.89", ] [[package]] name = "darling_macro" -version = "0.20.8" +version = "0.20.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a668eda54683121533a393014d8692171709ff57a7d61f187b6e782719f8933f" +checksum = "d336a2a514f6ccccaa3e09b02d41d35330c07ddf03a62165fcec10bb561c7806" dependencies = [ "darling_core", "quote", - "syn 2.0.52", + "syn 2.0.89", ] [[package]] name = "data-encoding" -version = "2.5.0" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e962a19be5cfc3f3bf6dd8f61eb50107f356ad6270fbb3ed41476571db78be5" +checksum = "e8566979429cf69b49a5c740c60791108e86440e8be149bbea4fe54d2c32d6e2" [[package]] name = "data-encoding-macro" -version = "0.1.14" +version = "0.1.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "20c01c06f5f429efdf2bae21eb67c28b3df3cf85b7dd2d8ef09c0838dac5d33e" +checksum = "f1559b6cba622276d6d63706db152618eeb15b89b3e4041446b05876e352e639" dependencies = [ "data-encoding", "data-encoding-macro-internal", @@ -1480,9 +1521,9 @@ dependencies = [ [[package]] name = "data-encoding-macro-internal" -version = "0.1.12" +version = "0.1.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0047d07f2c89b17dd631c80450d69841a6b5d7fb17278cbc43d7e4cfcf2576f3" +checksum = "332d754c0af53bc87c108fed664d121ecf59207ec4196041f04d6ab9002ad33f" dependencies = [ "data-encoding", "syn 1.0.109", @@ -1526,13 +1567,24 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bd0c93bb4b0c6d9b77f4435b0ae98c24d17f1c45b2ff844c6151a07256ca923b" +[[package]] +name = "displaydoc" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.89", +] + [[package]] name = "dlib" version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "330c60081dcc4c72131f8eb70510f1ac07223e5d4163db481a04a0befcffa412" dependencies = [ - "libloading 0.8.2", + "libloading 0.8.6", ] [[package]] @@ -1637,9 +1689,9 @@ dependencies = [ [[package]] name = "either" -version = "1.10.0" +version = "1.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11157ac094ffbdde99aa67b23417ebdd801842852b500e395a45a9c0aac03e4a" +checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0" [[package]] name = "elliptic-curve" @@ -1728,28 +1780,28 @@ checksum = "de0d48a183585823424a4ce1aa132d174a6a81bd540895822eb4c8373a8e49e8" dependencies = [ "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.89", ] [[package]] name = "enumset" -version = "1.1.3" +version = "1.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "226c0da7462c13fb57e5cc9e0dc8f0635e7d27f276a3a7fd30054647f669007d" +checksum = "d07a4b049558765cef5f0c1a273c3fc57084d768b44d2f98127aef4cceb17293" dependencies = [ "enumset_derive", ] [[package]] name = "enumset_derive" -version = "0.8.1" +version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e08b6c6ab82d70f08844964ba10c7babb716de2ecaeab9be5717918a5177d3af" +checksum = "59c3b24c345d8c314966bdc1832f6c2635bfcce8e7cf363bd115987bba2ee242" dependencies = [ "darling", "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.89", ] [[package]] @@ -1766,7 +1818,7 @@ dependencies = [ "emath", "log", "nohash-hasher", - "parking_lot 0.12.1", + "parking_lot 0.12.3", ] [[package]] @@ -1777,12 +1829,12 @@ checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" [[package]] name = "errno" -version = "0.3.8" +version = "0.3.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a258e46cdc063eb8519c00b9fc845fc47bcfca4130e2f08e88665ceda8474245" +checksum = "33d852cb9b869c2a9b3df2f71a3074817f01e1844f839a144f5fcef059a4eb5d" dependencies = [ "libc", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -1856,9 +1908,9 @@ dependencies = [ [[package]] name = "fastrand" -version = "2.0.1" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25cbce373ec4653f1a01a31e8a5e5ec0c622dc27ff9c4e6606eefef5cbbed4a5" +checksum = "486f806e73c5707928240ddc295403b1b93c96a02038563881c4a2fd84b81ac4" [[package]] name = "fdeflate" @@ -1881,9 +1933,9 @@ dependencies = [ [[package]] name = "flate2" -version = "1.0.34" +version = "1.0.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1b589b4dc103969ad3cf85c950899926ec64300a1a46d76c03a6072957036f0" +checksum = "c936bfdafb507ebbf50b8074c54fa31c5be9a1e7e5f467dd659697041407d07c" dependencies = [ "crc32fast", "miniz_oxide 0.8.0", @@ -1937,9 +1989,9 @@ checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c" [[package]] name = "futures" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "645c6916888f6cb6350d2550b80fb63e734897a8498abe35cfb732b6487804b0" +checksum = "65bc07b1a8bc7c85c5f2e110c476c7389b4554ba72af57d8445ea63a576b0876" dependencies = [ "futures-channel", "futures-core", @@ -1952,9 +2004,9 @@ dependencies = [ [[package]] name = "futures-channel" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eac8f7d7865dcb88bd4373ab671c8cf4508703796caa2b1985a9ca867b3fcb78" +checksum = "2dff15bf788c671c1934e366d07e30c1814a8ef514e1af724a602e8a2fbe1b10" dependencies = [ "futures-core", "futures-sink", @@ -1962,15 +2014,15 @@ dependencies = [ [[package]] name = "futures-core" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d" +checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e" [[package]] name = "futures-executor" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a576fc72ae164fca6b9db127eaa9a9dda0d61316034f33a0a0d4eda41f02b01d" +checksum = "1e28d1d997f585e54aebc3f97d39e72338912123a67330d723fdbb564d646c9f" dependencies = [ "futures-core", "futures-task", @@ -1979,9 +2031,9 @@ dependencies = [ [[package]] name = "futures-io" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a44623e20b9681a318efdd71c299b6b222ed6f231972bfe2f224ebad6311f0c1" +checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6" [[package]] name = "futures-lite" @@ -2004,7 +2056,7 @@ version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cef40d21ae2c515b51041df9ed313ed21e572df340ea58a922a0aefe7e8891a1" dependencies = [ - "fastrand 2.0.1", + "fastrand 2.2.0", "futures-core", "futures-io", "parking", @@ -2013,32 +2065,32 @@ dependencies = [ [[package]] name = "futures-macro" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" +checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" dependencies = [ "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.89", ] [[package]] name = "futures-sink" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fb8e00e87438d937621c1c6269e53f536c14d3fbd6a042bb24879e57d474fb5" +checksum = "e575fab7d1e0dcb8d0c7bcf9a63ee213816ab51902e6d244a95819acacf1d4f7" [[package]] name = "futures-task" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004" +checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988" [[package]] name = "futures-util" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48" +checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81" dependencies = [ "futures-channel", "futures-core", @@ -2083,9 +2135,9 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.12" +version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "190092ea657667030ac6a35e305e62fc4dd69fd98ac98631e5d3a2b1575a12b5" +checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" dependencies = [ "cfg-if", "libc", @@ -2094,9 +2146,9 @@ dependencies = [ [[package]] name = "ghash" -version = "0.5.0" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d930750de5717d2dd0b8c0d42c076c0e884c81a73e6cab859bbd2339c71e3e40" +checksum = "f0d8a4362ccb29cb0b265253fb0a2728f592895ee6854fd9bc13f2ffda266ff1" dependencies = [ "opaque-debug", "polyval", @@ -2155,7 +2207,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8fc93b03242719b8ad39fb26ed2b01737144ce7bd4bfc7adadcef806596760fe" dependencies = [ "bitflags 1.3.2", - "cfg_aliases", + "cfg_aliases 0.1.1", "cgl", "core-foundation", "dispatch", @@ -2177,7 +2229,7 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "629a873fc04062830bfe8f97c03773bcd7b371e23bcc465d0a61448cd1588fa4" dependencies = [ - "cfg_aliases", + "cfg_aliases 0.1.1", "glutin", "raw-window-handle", "winit", @@ -2258,19 +2310,15 @@ dependencies = [ [[package]] name = "hashbrown" -version = "0.14.3" +version = "0.14.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604" -dependencies = [ - "ahash 0.8.6", - "allocator-api2", -] +checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" [[package]] name = "hashbrown" -version = "0.15.1" +version = "0.15.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a9bfc1af68b1726ea47d3d5109de126281def866b33970e10fbab11b5dafab3" +checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289" [[package]] name = "hermit-abi" @@ -2283,9 +2331,9 @@ dependencies = [ [[package]] name = "hermit-abi" -version = "0.3.8" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "379dada1584ad501b383485dd706b8afb7a70fcbc7f4da7d780638a5a6124a60" +checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" [[package]] name = "hermit-abi" @@ -2319,9 +2367,9 @@ dependencies = [ [[package]] name = "iana-time-zone" -version = "0.1.60" +version = "0.1.61" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7ffbb5a1b541ea2561f8c41c087286cc091e21e556a4f09a8f6cbf17b69b141" +checksum = "235e081f3925a06703c2d0117ea8b91f042756fd6e7a6e5d901e8ca1a996b220" dependencies = [ "android_system_properties", "core-foundation-sys", @@ -2340,6 +2388,124 @@ dependencies = [ "cc", ] +[[package]] +name = "icu_collections" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db2fa452206ebee18c4b5c2274dbf1de17008e874b4dc4f0aea9d01ca79e4526" +dependencies = [ + "displaydoc", + "yoke", + "zerofrom", + "zerovec", +] + +[[package]] +name = "icu_locid" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13acbb8371917fc971be86fc8057c41a64b521c184808a698c02acc242dbf637" +dependencies = [ + "displaydoc", + "litemap", + "tinystr", + "writeable", + "zerovec", +] + +[[package]] +name = "icu_locid_transform" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "01d11ac35de8e40fdeda00d9e1e9d92525f3f9d887cdd7aa81d727596788b54e" +dependencies = [ + "displaydoc", + "icu_locid", + "icu_locid_transform_data", + "icu_provider", + "tinystr", + "zerovec", +] + +[[package]] +name = "icu_locid_transform_data" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fdc8ff3388f852bede6b579ad4e978ab004f139284d7b28715f773507b946f6e" + +[[package]] +name = "icu_normalizer" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19ce3e0da2ec68599d193c93d088142efd7f9c5d6fc9b803774855747dc6a84f" +dependencies = [ + "displaydoc", + "icu_collections", + "icu_normalizer_data", + "icu_properties", + "icu_provider", + "smallvec", + "utf16_iter", + "utf8_iter", + "write16", + "zerovec", +] + +[[package]] +name = "icu_normalizer_data" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8cafbf7aa791e9b22bec55a167906f9e1215fd475cd22adfcf660e03e989516" + +[[package]] +name = "icu_properties" +version = "1.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93d6020766cfc6302c15dbbc9c8778c37e62c14427cb7f6e601d849e092aeef5" +dependencies = [ + "displaydoc", + "icu_collections", + "icu_locid_transform", + "icu_properties_data", + "icu_provider", + "tinystr", + "zerovec", +] + +[[package]] +name = "icu_properties_data" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67a8effbc3dd3e4ba1afa8ad918d5684b8868b3b26500753effea8d2eed19569" + +[[package]] +name = "icu_provider" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ed421c8a8ef78d3e2dbc98a973be2f3770cb42b606e3ab18d6237c4dfde68d9" +dependencies = [ + "displaydoc", + "icu_locid", + "icu_provider_macros", + "stable_deref_trait", + "tinystr", + "writeable", + "yoke", + "zerofrom", + "zerovec", +] + +[[package]] +name = "icu_provider_macros" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ec89e9337638ecdc08744df490b221a7399bf8d164eb52a665454e60e075ad6" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.89", +] + [[package]] name = "ident_case" version = "1.0.1" @@ -2348,12 +2514,23 @@ checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" [[package]] name = "idna" -version = "0.5.0" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6" +checksum = "686f825264d630750a544639377bae737628043f20d38bbc029e8f29ea968a7e" dependencies = [ - "unicode-bidi", - "unicode-normalization", + "idna_adapter", + "smallvec", + "utf8_iter", +] + +[[package]] +name = "idna_adapter" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "daca1df1c957320b2cf139ac61e7bd64fed304c5040df000a745aa1de3b4ef71" +dependencies = [ + "icu_normalizer", + "icu_properties", ] [[package]] @@ -2380,9 +2557,9 @@ dependencies = [ [[package]] name = "include_dir_macros" -version = "0.7.3" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b139284b5cf57ecfa712bcc66950bb635b31aff41c188e8a4cfc758eca374a3f" +checksum = "7cab85a7ed0bd5f0e76d93846e0147172bed2e2d3f859bcc33a8d9699cad1a75" dependencies = [ "proc-macro2", "quote", @@ -2412,7 +2589,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "707907fe3c25f5424cce2cb7e1cbcafee6bdbe735ca90ef77c29e84591e5b9da" dependencies = [ "equivalent", - "hashbrown 0.15.1", + "hashbrown 0.15.2", ] [[package]] @@ -2426,9 +2603,9 @@ dependencies = [ [[package]] name = "instant" -version = "0.1.12" +version = "0.1.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" +checksum = "e0242819d153cba4b4b05a5a8f2a7e9bbf97b6055b2a002b395c96b5ff3c0222" dependencies = [ "cfg-if", "js-sys", @@ -2442,7 +2619,7 @@ version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "eae7b9aee968036d54dce06cebaefd919e4472e753296daccd6d344e3e2df0c2" dependencies = [ - "hermit-abi 0.3.8", + "hermit-abi 0.3.9", "libc", "windows-sys 0.48.0", ] @@ -2458,9 +2635,9 @@ dependencies = [ [[package]] name = "itoa" -version = "1.0.10" +version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1a46d1a171d865aa5f83f92695765caa047a9b4cbae2cbf37dbd613a793fd4c" +checksum = "d75a2a4b1b190afb6f5425f10f6a8f959d2ea0b9c2b1d79553551850539e4674" [[package]] name = "jni" @@ -2484,11 +2661,20 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8eaf4bc02d17cbdd7ff4c7438cafcdf7fb9a4613313ad11b4f8fefe7d3fa0130" +[[package]] +name = "jobserver" +version = "0.1.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48d1dbcbbeb6a7fec7e059840aa538bd62aaccf972c7346c4d9d2059312853d0" +dependencies = [ + "libc", +] + [[package]] name = "js-sys" -version = "0.3.68" +version = "0.3.73" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "406cda4b368d531c842222cf9d2600a9a4acce8d29423695379c6868a143a9ee" +checksum = "fb15147158e79fd8b8afd0252522769c4f48725460b37338544d8379d94fc8f9" dependencies = [ "wasm-bindgen", ] @@ -2522,9 +2708,9 @@ checksum = "e2db585e1d738fc771bf08a151420d3ed193d9d895a36df7f6f8a9456b911ddc" [[package]] name = "lazy_static" -version = "1.4.0" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" [[package]] name = "lazycell" @@ -2540,9 +2726,9 @@ checksum = "884e2677b40cc8c339eaefcb701c32ef1fd2493d71118dc0ca4b6a736c93bd67" [[package]] name = "libc" -version = "0.2.153" +version = "0.2.167" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd" +checksum = "09d6582e104315a817dff97f75133544b2e094ee22447d2acf4a74e189ba06fc" [[package]] name = "libloading" @@ -2556,12 +2742,12 @@ dependencies = [ [[package]] name = "libloading" -version = "0.8.2" +version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2caa5afb8bf9f3a2652760ce7d4f62d21c4d5a423e68466fca30df82f2330164" +checksum = "fc2f4eb4bc735547cfed7c0a4922cbd04a4655978c09b54f1f7b228750664c34" dependencies = [ "cfg-if", - "windows-targets 0.52.4", + "windows-targets 0.52.6", ] [[package]] @@ -2583,15 +2769,21 @@ checksum = "ef53942eb7bf7ff43a617b3e2c1c4a5ecf5944a7c1bc12d7ee39bbb15e5c1519" [[package]] name = "linux-raw-sys" -version = "0.4.13" +version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "01cda141df6706de531b6c46c3a33ecca755538219bd484262fa09410c13539c" +checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" + +[[package]] +name = "litemap" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ee93343901ab17bd981295f2cf0026d4ad018c7c31ba84549a4ddbb47a45104" [[package]] name = "lock_api" -version = "0.4.11" +version = "0.4.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c168f8615b12bc01f9c17e2eb0cc07dcae1940121185446edc3744920e8ef45" +checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17" dependencies = [ "autocfg", "scopeguard", @@ -2599,9 +2791,9 @@ dependencies = [ [[package]] name = "log" -version = "0.4.21" +version = "0.4.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c" +checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" [[package]] name = "loupe" @@ -2633,6 +2825,15 @@ dependencies = [ "libc", ] +[[package]] +name = "mach2" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19b955cdeb2a02b9117f121ce63aa52d08ade45de53e48fe6a38b39c10f6f709" +dependencies = [ + "libc", +] + [[package]] name = "malloc_buf" version = "0.0.6" @@ -2644,9 +2845,9 @@ dependencies = [ [[package]] name = "memchr" -version = "2.7.1" +version = "2.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "523dc4f511e55ab87b694dc30d0f820d60906ef06413f93d4d7a1385599cc149" +checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" [[package]] name = "memmap2" @@ -2692,9 +2893,9 @@ checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" [[package]] name = "miniz_oxide" -version = "0.7.2" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d811f3e15f28568be3407c8e7fdb6514c1cda3cb30683f15b6a1a1dc4ea14a7" +checksum = "b8a240ddb74feaf34a79a7add65a741f3167852fba007066dcac1ca548d89c08" dependencies = [ "adler", ] @@ -2711,9 +2912,9 @@ dependencies = [ [[package]] name = "mio" -version = "0.8.10" +version = "0.8.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f3d0b296e374a4e6f3c7b0a1f5a51d748a0d34c85e7dc48fc3fa9a87657fe09" +checksum = "a4a650543ca06a924e8b371db273b2756685faae30f8487da1b56505a8f78b0c" dependencies = [ "libc", "log", @@ -2721,6 +2922,17 @@ dependencies = [ "windows-sys 0.48.0", ] +[[package]] +name = "mio" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2886843bf800fba2e3377cff24abf6379b4c4d5c6681eaf9ea5b0d15090450bd" +dependencies = [ + "libc", + "wasi", + "windows-sys 0.52.0", +] + [[package]] name = "more-asserts" version = "0.2.2" @@ -2779,7 +2991,7 @@ dependencies = [ "proc-macro2", "quote", "syn 1.0.109", - "synstructure", + "synstructure 0.12.6", ] [[package]] @@ -2850,13 +3062,13 @@ dependencies = [ [[package]] name = "nix" -version = "0.28.0" +version = "0.29.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab2156c4fce2f8df6c499cc1c763e4394b7482525bf2a9701c9d79d215f519e4" +checksum = "71e2746dc3a24dd78b3cfcb7be93368c6de9963d30f43a6a73998a9cf4b17b46" dependencies = [ "bitflags 2.6.0", "cfg-if", - "cfg_aliases", + "cfg_aliases 0.2.1", "libc", ] @@ -2922,9 +3134,9 @@ dependencies = [ [[package]] name = "num-iter" -version = "0.1.44" +version = "0.1.45" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d869c01cc0c455284163fd0092f1f93835385ccab5a98a0dcc497b2f8bf055a9" +checksum = "1429034a0490724d0075ebb2bc9e875d6503c3cf69e235a8941aa757d83ef5bf" dependencies = [ "autocfg", "num-integer", @@ -2952,16 +3164,6 @@ dependencies = [ "autocfg", ] -[[package]] -name = "num_cpus" -version = "1.16.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" -dependencies = [ - "hermit-abi 0.3.8", - "libc", -] - [[package]] name = "num_enum" version = "0.5.11" @@ -3001,7 +3203,7 @@ dependencies = [ "proc-macro-crate", "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.89", ] [[package]] @@ -3167,9 +3369,9 @@ checksum = "b7e5500299e16ebb147ae15a00a942af264cf3688f47923b8fc2cd5858f23ad3" [[package]] name = "oorandom" -version = "11.1.3" +version = "11.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ab1bc2a289d34bd04a330323ac98a1b4bc82c9d9fcb1e66b63caa84da26b575" +checksum = "b410bbe7e14ab526a0e86877eb47c6996a2bd7746f027ba551028c925390e4e9" [[package]] name = "opaque-debug" @@ -3230,12 +3432,12 @@ dependencies = [ [[package]] name = "parking_lot" -version = "0.12.1" +version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" +checksum = "f1bf18183cf54e8d6059647fc3063646a1801cf30896933ec2311622cc4b9a27" dependencies = [ "lock_api", - "parking_lot_core 0.9.9", + "parking_lot_core 0.9.10", ] [[package]] @@ -3254,22 +3456,22 @@ dependencies = [ [[package]] name = "parking_lot_core" -version = "0.9.9" +version = "0.9.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c42a9226546d68acdd9c0a280d17ce19bfe27a46bf68784e4066115788d008e" +checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" dependencies = [ "cfg-if", "libc", - "redox_syscall 0.4.1", + "redox_syscall 0.5.7", "smallvec", - "windows-targets 0.48.5", + "windows-targets 0.52.6", ] [[package]] name = "paste" -version = "1.0.14" +version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "de3145af08024dea9fa9914f381a17b8fc6034dfb00f3a84013f7ff43f29ed4c" +checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" [[package]] name = "peeking_take_while" @@ -3285,9 +3487,9 @@ checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" [[package]] name = "pin-project-lite" -version = "0.2.13" +version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8afb450f006bf6385ca15ef45d71d2288452bc3683ce2e2cacc0d18e4be60b58" +checksum = "915a1e146535de9163f3987b8944ed8cf49a18bb0056bcebcdcece385cece4ff" [[package]] name = "pin-utils" @@ -3302,7 +3504,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "96c8c490f422ef9a4efd2cb5b42b76c8613d7e7dfc1caf667b8a3350a5acc066" dependencies = [ "atomic-waker", - "fastrand 2.0.1", + "fastrand 2.2.0", "futures-io", ] @@ -3324,9 +3526,9 @@ checksum = "953ec861398dccce10c670dfeaf3ec4911ca479e9c02154b3a215178c5f566f2" [[package]] name = "plotters" -version = "0.3.5" +version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2c224ba00d7cadd4d5c660deaf2098e5e80e07846537c51f9cfa4be50c1fd45" +checksum = "5aeb6f403d7a4911efb1e33402027fc44f29b5bf6def3effcc22d7bb75f2b747" dependencies = [ "num-traits", "plotters-backend", @@ -3337,15 +3539,15 @@ dependencies = [ [[package]] name = "plotters-backend" -version = "0.3.5" +version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e76628b4d3a7581389a35d5b6e2139607ad7c75b17aed325f210aa91f4a9609" +checksum = "df42e13c12958a16b3f7f4386b9ab1f3e7933914ecea48da7139435263a4172a" [[package]] name = "plotters-svg" -version = "0.3.5" +version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38f6d39893cca0701371e3c27294f09797214b86f1fb951b89ade8ec04e2abab" +checksum = "51bae2ac328883f7acdfea3d66a7c35751187f870bc81f94563733a154d7a670" dependencies = [ "plotters-backend", ] @@ -3390,24 +3592,24 @@ dependencies = [ [[package]] name = "polling" -version = "3.7.2" +version = "3.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3ed00ed3fbf728b5816498ecd316d1716eecaced9c0c8d2c5a6740ca214985b" +checksum = "a604568c3202727d1507653cb121dbd627a58684eb09a820fd746bee38b4442f" dependencies = [ "cfg-if", "concurrent-queue", "hermit-abi 0.4.0", "pin-project-lite", - "rustix 0.38.31", + "rustix 0.38.41", "tracing", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] name = "polyval" -version = "0.6.1" +version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d52cff9d1d4dee5fe6d03729099f4a310a41179e0a10dbf542039873f2e826fb" +checksum = "9d1fe60d06143b2430aa532c94cfe9e29783047f06c0d7fd359a9a51b729fa25" dependencies = [ "cfg-if", "cpufeatures", @@ -3417,9 +3619,12 @@ dependencies = [ [[package]] name = "ppv-lite86" -version = "0.2.17" +version = "0.2.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" +checksum = "77957b295656769bb8ad2b6a6b09d897d94f05c41b069aede1fcdaa675eaea04" +dependencies = [ + "zerocopy", +] [[package]] name = "proc-macro-crate" @@ -3457,13 +3662,36 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.78" +version = "1.0.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2422ad645d89c99f8f3e6b88a9fdeca7fabeac836b1002371c4367c8f984aae" +checksum = "37d3544b3f2748c54e147655edb5025752e2303145b5aefb3c3ea2c78b973bb0" dependencies = [ "unicode-ident", ] +[[package]] +name = "prost" +version = "0.11.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b82eaa1d779e9a4bc1c3217db8ffbeabaae1dca241bf70183242128d48681cd" +dependencies = [ + "bytes", + "prost-derive", +] + +[[package]] +name = "prost-derive" +version = "0.11.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5d2d8d10f3c6ded6da8b05b5fb3b8a5082514344d56c9f871412d29b4e075b4" +dependencies = [ + "anyhow", + "itertools", + "proc-macro2", + "quote", + "syn 1.0.109", +] + [[package]] name = "ptr_meta" version = "0.1.4" @@ -3486,9 +3714,9 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.35" +version = "1.0.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef" +checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af" dependencies = [ "proc-macro2", ] @@ -3573,15 +3801,6 @@ dependencies = [ "bitflags 1.3.2", ] -[[package]] -name = "redox_syscall" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa" -dependencies = [ - "bitflags 1.3.2", -] - [[package]] name = "redox_syscall" version = "0.5.7" @@ -3604,25 +3823,25 @@ dependencies = [ [[package]] name = "regex" -version = "1.10.3" +version = "1.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b62dbe01f0b06f9d8dc7d49e05a0785f153b00b2c227856282f671e0318c9b15" +checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191" dependencies = [ "aho-corasick", "memchr", "regex-automata", - "regex-syntax 0.8.2", + "regex-syntax 0.8.5", ] [[package]] name = "regex-automata" -version = "0.4.5" +version = "0.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5bb987efffd3c6d0d8f5f89510bb458559eab11e4f869acb20bf845e016259cd" +checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908" dependencies = [ "aho-corasick", "memchr", - "regex-syntax 0.8.2", + "regex-syntax 0.8.5", ] [[package]] @@ -3633,20 +3852,20 @@ checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" [[package]] name = "regex-syntax" -version = "0.8.2" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f" +checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" [[package]] name = "region" -version = "3.0.0" +version = "3.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76e189c2369884dce920945e2ddf79b3dff49e071a167dd1817fa9c4c00d512e" +checksum = "e6b6ebd13bc009aef9cd476c1310d49ac354d36e240cf1bd753290f3dc7199a7" dependencies = [ "bitflags 1.3.2", "libc", - "mach", - "winapi", + "mach2", + "windows-sys 0.52.0", ] [[package]] @@ -3671,9 +3890,9 @@ dependencies = [ [[package]] name = "rkyv" -version = "0.7.44" +version = "0.7.45" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5cba464629b3394fc4dbc6f940ff8f5b4ff5c7aef40f29166fd4ad12acbc99c0" +checksum = "9008cd6385b9e161d8229e1f6549dd23c3d022f132a2ea37ac3a10ac4935779b" dependencies = [ "bitvec", "bytecheck", @@ -3689,9 +3908,9 @@ dependencies = [ [[package]] name = "rkyv_derive" -version = "0.7.44" +version = "0.7.45" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7dddfff8de25e6f62b9d64e6e432bf1c6736c57d20323e15ee10435fbda7c65" +checksum = "503d1d27590a2b0a3a4ca4c94755aa2875657196ecbf401a42eff41d7de532c0" dependencies = [ "proc-macro2", "quote", @@ -3700,9 +3919,9 @@ dependencies = [ [[package]] name = "rln" -version = "0.3.5" +version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a4832ceea2ad76962de5daf7e9c6a8667b2488f72f63335e3da991ebd89e904" +checksum = "96293aa6359623a3b4a0d8c186df23d559d6fd04d3c03f119c86238c22ccee71" dependencies = [ "ark-bn254", "ark-circom", @@ -3740,9 +3959,9 @@ dependencies = [ [[package]] name = "rustc-demangle" -version = "0.1.23" +version = "0.1.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" +checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" [[package]] name = "rustc-hash" @@ -3758,9 +3977,9 @@ checksum = "3e75f6a532d0fd9f7f13144f392b6ad56a32696bfcd9c78f797f16bbb6f072d6" [[package]] name = "rustc_version" -version = "0.4.0" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" +checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92" dependencies = [ "semver", ] @@ -3781,28 +4000,28 @@ dependencies = [ [[package]] name = "rustix" -version = "0.38.31" +version = "0.38.41" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ea3e1a662af26cd7a3ba09c0297a31af215563ecf42817c98df621387f4e949" +checksum = "d7f649912bc1495e167a6edee79151c84b1bad49748cb4f1f1167f459f6224f6" dependencies = [ "bitflags 2.6.0", "errno", "libc", - "linux-raw-sys 0.4.13", + "linux-raw-sys 0.4.14", "windows-sys 0.52.0", ] [[package]] name = "rustversion" -version = "1.0.14" +version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ffc183a10b4478d04cbbbfc96d0873219d962dd5accaff2ffbd4ceb7df837f4" +checksum = "0e819f2bc632f285be6d7cd36e25940d45b2391dd6d9b939e79de557f7014248" [[package]] name = "ryu" -version = "1.0.17" +version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e86697c916019a8588c99b5fac3cead74ec0b4b819707a682fd4d23fa0ce1ba1" +checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" [[package]] name = "same-file" @@ -3898,9 +4117,9 @@ dependencies = [ [[package]] name = "semver" -version = "1.0.22" +version = "1.0.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92d43fe69e652f3df9bdc2b85b2854a0825b86e4fb76bc44d945137d053639ca" +checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b" [[package]] name = "serde" @@ -3949,7 +4168,7 @@ checksum = "8c805777e3930c8883389c602315a24224bcc738b63905ef87cd1420353ea93e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.89", ] [[package]] @@ -3971,7 +4190,7 @@ checksum = "6c64451ba24fc7a6a2d60fc75dd9c83c90903b19028d4eff35e88fc1e86564e9" dependencies = [ "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.89", ] [[package]] @@ -4021,11 +4240,32 @@ version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" +[[package]] +name = "signal-hook" +version = "0.3.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8621587d4798caf8eb44879d42e56b9a93ea5dcd315a6487c357130095b62801" +dependencies = [ + "libc", + "signal-hook-registry", +] + +[[package]] +name = "signal-hook-mio" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34db1a06d485c9142248b7a054f034b349b212551f3dfd19c94d45a754a217cd" +dependencies = [ + "libc", + "mio 0.8.11", + "signal-hook", +] + [[package]] name = "signal-hook-registry" -version = "1.4.1" +version = "1.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8229b473baa5980ac72ef434c4415e70c4b5e71b423043adb4ba059f89c99a1" +checksum = "a9e9e0b4211b72e7b8b6e85c807d36c212bdb33ea8587f7569562a84df5465b1" dependencies = [ "libc", ] @@ -4048,9 +4288,9 @@ checksum = "d66dc143e6b11c1eddc06d5c423cfc97062865baf299914ab64caa38182078fe" [[package]] name = "simdutf8" -version = "0.1.4" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f27f6278552951f1f2b8cf9da965d10969b2efdea95a6ec47987ab46edfe263a" +checksum = "e3a9fe34e3e7a50316060351f37187a3f546bce95496156754b601a5fa71b76e" [[package]] name = "slab" @@ -4088,9 +4328,9 @@ dependencies = [ [[package]] name = "smallvec" -version = "1.13.1" +version = "1.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6ecd384b10a64542d77071bd64bd7b231f4ed5940fba55e98c3de13824cf3d7" +checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" [[package]] name = "smart-default" @@ -4144,9 +4384,9 @@ dependencies = [ [[package]] name = "socket2" -version = "0.5.6" +version = "0.5.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05ffd9c0a93b7543e062e759284fcf5f5e3b098501104bfbdde4d404db792871" +checksum = "c970269d99b64e60ec3bd6ad27270092a5394c4e309314b18ae3fe575695fbe8" dependencies = [ "libc", "windows-sys 0.52.0", @@ -4164,9 +4404,9 @@ dependencies = [ [[package]] name = "sscanf" -version = "0.4.1" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c713ebd15ce561dd4a13ed62bc2a0368e16806fc30dcaf66ecf1256b2a3fdde6" +checksum = "a147d3cf7e723671ed11355b5b008c8019195f7fc902e213f5557d931e9f839d" dependencies = [ "const_format", "lazy_static", @@ -4176,17 +4416,17 @@ dependencies = [ [[package]] name = "sscanf_macro" -version = "0.4.1" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "84955aa74a157e5834d58a07be11af7f0ab923f0194a0bb2ea6b3db8b5d1611d" +checksum = "af3a37bdf8e90e77cc60f74473edf28d922ae2eacdd595e67724ccd2381774cc" dependencies = [ "convert_case", "proc-macro2", "quote", "regex-syntax 0.6.29", "strsim", - "syn 2.0.52", - "unicode-width", + "syn 2.0.89", + "unicode-width 0.1.12", ] [[package]] @@ -4215,9 +4455,9 @@ checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" [[package]] name = "subtle" -version = "2.5.0" +version = "2.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81cdd64d312baedb58e21336b31bc043b77e01cc99033ce76ef539f78e965ebc" +checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" [[package]] name = "syn" @@ -4232,9 +4472,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.52" +version = "2.0.89" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b699d15b36d1f02c3e7c69f8ffef53de37aefae075d8488d4ba1a7788d574a07" +checksum = "44d46482f1c1c87acd84dea20c1bf5ebff4c757009ed6bf19cfd36fb10e92c4e" dependencies = [ "proc-macro2", "quote", @@ -4253,6 +4493,17 @@ dependencies = [ "unicode-xid", ] +[[package]] +name = "synstructure" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8af7666ab7b6390ab78131fb5b0fce11d6b7a6951602017c35fa82800708971" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.89", +] + [[package]] name = "tap" version = "1.0.1" @@ -4261,9 +4512,9 @@ checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" [[package]] name = "target-lexicon" -version = "0.12.14" +version = "0.12.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e1fc403891a21bcfb7c37834ba66a547a8f402146eba7265b5a6d88059c9ff2f" +checksum = "61c41af27dd6d1e27b1b16b489db798443478cef1f06a660c96db617ba5de3b1" [[package]] name = "tempfile" @@ -4272,8 +4523,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "85b77fafb263dd9d05cbeac119526425676db3784113aa9295c88498cbf8bff1" dependencies = [ "cfg-if", - "fastrand 2.0.1", - "rustix 0.38.31", + "fastrand 2.2.0", + "rustix 0.38.41", "windows-sys 0.52.0", ] @@ -4283,7 +4534,7 @@ version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060" dependencies = [ - "unicode-width", + "unicode-width 0.1.12", ] [[package]] @@ -4366,6 +4617,16 @@ dependencies = [ "strict-num", ] +[[package]] +name = "tinystr" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9117f5d4db391c1cf6927e7bea3db74b9a1c1add8f7eda9ffd5364f40f57b82f" +dependencies = [ + "displaydoc", + "zerovec", +] + [[package]] name = "tinytemplate" version = "1.2.1" @@ -4378,9 +4639,9 @@ dependencies = [ [[package]] name = "tinyvec" -version = "1.6.0" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50" +checksum = "445e881f4f6d382d5f27c034e25eb92edd7c784ceab92a0937db7f2e9471b938" dependencies = [ "tinyvec_macros", ] @@ -4393,32 +4654,31 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.36.0" +version = "1.41.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61285f6515fa018fb2d1e46eb21223fff441ee8db5d0f1435e8ab4f5cdb80931" +checksum = "22cfb5bee7a6a52939ca9224d6ac897bb669134078daa8735560897f69de4d33" dependencies = [ "backtrace", "bytes", "libc", - "mio", - "num_cpus", - "parking_lot 0.12.1", + "mio 1.0.3", + "parking_lot 0.12.3", "pin-project-lite", "signal-hook-registry", - "socket2 0.5.6", + "socket2 0.5.8", "tokio-macros", - "windows-sys 0.48.0", + "windows-sys 0.52.0", ] [[package]] name = "tokio-macros" -version = "2.2.0" +version = "2.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" +checksum = "693d596312e88961bc67d7f1f97af8a70227d9f90c31bba5806eec004978d752" dependencies = [ "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.89", ] [[package]] @@ -4437,15 +4697,15 @@ dependencies = [ [[package]] name = "tokio-util" -version = "0.7.10" +version = "0.7.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5419f34732d9eb6ee4c3578b7989078579b7f039cbbb9ca2c4da015749371e15" +checksum = "61e7c3654c13bcd040d4a03abee2c75b1d14a37b423cf5a813ceae1cc903ec6a" dependencies = [ "bytes", "futures-core", "futures-sink", "futures-util", - "hashbrown 0.14.3", + "hashbrown 0.14.5", "pin-project-lite", "tokio", ] @@ -4467,11 +4727,26 @@ dependencies = [ "winnow", ] +[[package]] +name = "toy-chat" +version = "0.1.0" +dependencies = [ + "chrono", + "crossterm", + "prost", + "serde", + "serde_json", + "tokio", + "tui", + "unicode-width 0.1.12", + "waku-bindings", +] + [[package]] name = "tracing" -version = "0.1.40" +version = "0.1.41" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" +checksum = "784e0ac535deb450455cbfa28a6f0df145ea1bb7ae51b821cf5e7927fdcfbdd0" dependencies = [ "log", "pin-project-lite", @@ -4481,20 +4756,20 @@ dependencies = [ [[package]] name = "tracing-attributes" -version = "0.1.27" +version = "0.1.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" +checksum = "395ae124c09f9e6918a2310af6038fba074bcf474ac352496d5910dd59a2226d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.89", ] [[package]] name = "tracing-core" -version = "0.1.32" +version = "0.1.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" +checksum = "e672c95779cf947c5311f83787af4fa8fffd12fb27e4993211a84bdfd9610f9c" dependencies = [ "once_cell", "valuable", @@ -4502,12 +4777,12 @@ dependencies = [ [[package]] name = "tracing-error" -version = "0.2.0" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d686ec1c0f384b1277f097b2f279a2ecc11afe8c133c1aabf036a27cb4cd206e" +checksum = "8b1581020d7a273442f5b45074a6a57d5757ad0a47dac0e9f0bd57b81936f3db" dependencies = [ "tracing", - "tracing-subscriber 0.3.18", + "tracing-subscriber 0.3.19", ] [[package]] @@ -4521,9 +4796,9 @@ dependencies = [ [[package]] name = "tracing-subscriber" -version = "0.3.18" +version = "0.3.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad0f048c97dbd9faa9b7df56362b8ebcaa52adb06b498c050d2f4e32f90a7a8b" +checksum = "e8189decb5ac0fa7bc8b96b7cb9b2701d60d48805aca84a238004d665fcc4008" dependencies = [ "sharded-slab", "thread_local", @@ -4536,6 +4811,19 @@ version = "0.25.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5902c5d130972a0000f60860bfbf46f7ca3db5391eddfedd1b8728bd9dc96c0e" +[[package]] +name = "tui" +version = "0.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ccdd26cbd674007e649a272da4475fb666d3aa0ad0531da7136db6fab0e5bad1" +dependencies = [ + "bitflags 1.3.2", + "cassowary", + "crossterm", + "unicode-segmentation", + "unicode-width 0.1.12", +] + [[package]] name = "typenum" version = "1.17.0" @@ -4553,44 +4841,35 @@ dependencies = [ "winapi", ] -[[package]] -name = "unicode-bidi" -version = "0.3.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08f95100a766bf4f8f28f90d77e0a5461bbdb219042e7679bebe79004fed8d75" - [[package]] name = "unicode-ident" -version = "1.0.12" +version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" +checksum = "adb9e6ca4f869e1180728b7950e35922a7fc6397f7b641499e8f3ef06e50dc83" [[package]] -name = "unicode-normalization" -version = "0.1.23" +name = "unicode-segmentation" +version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a56d1686db2308d901306f92a263857ef59ea39678a5458e7cb17f01415101f5" -dependencies = [ - "tinyvec", -] +checksum = "f6ccf251212114b54433ec949fd6a7841275f9ada20dddd2f29e9ceea4501493" [[package]] -name = "unicode-segmentation" -version = "1.11.0" +name = "unicode-width" +version = "0.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d4c87d22b6e3f4a18d4d40ef354e97c90fcb14dd91d7dc0aa9d8a1172ebf7202" +checksum = "68f5e5f3158ecfd4b8ff6fe086db7c8467a2dfdac97fe420f2b7c4aa97af66d6" [[package]] name = "unicode-width" -version = "0.1.11" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e51733f11c9c4f72aa0c160008246859e340b00807569a0da0e7a1079b27ba85" +checksum = "1fc81956842c57dac11422a97c3b8195a1ff727f06e85c84ed2e8aa277c9a0fd" [[package]] name = "unicode-xid" -version = "0.2.4" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c" +checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" [[package]] name = "universal-hash" @@ -4610,20 +4889,35 @@ checksum = "6889a77d49f1f013504cec6bf97a2c730394adedaeb1deb5ea08949a50541105" [[package]] name = "url" -version = "2.5.0" +version = "2.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "31e6302e3bb753d46e83516cae55ae196fc0c309407cf11ab35cc51a4c2a4633" +checksum = "32f8b686cadd1473f4bd0117a5d28d36b1ade384ea9b5069a1c40aefed7fda60" dependencies = [ "form_urlencoded", "idna", "percent-encoding", ] +[[package]] +name = "utf16_iter" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8232dd3cdaed5356e0f716d285e4b40b932ac434100fe9b7e0e8e935b9e6246" + +[[package]] +name = "utf8_iter" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" + [[package]] name = "uuid" -version = "1.7.0" +version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f00cc9702ca12d3c81455259621e676d0f7251cec66a21e98fe2e9a37db93b2a" +checksum = "f8c5f0a0af699448548ad1a2fbf920fb4bee257eae39953ba95cb84891a0446a" +dependencies = [ + "getrandom", +] [[package]] name = "valuable" @@ -4639,9 +4933,9 @@ checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191" [[package]] name = "version_check" -version = "0.9.4" +version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" +checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" [[package]] name = "waker-fn" @@ -4655,6 +4949,7 @@ version = "0.5.0" dependencies = [ "aes-gcm", "base64 0.21.7", + "chrono", "enr", "hex", "libc", @@ -4671,6 +4966,7 @@ dependencies = [ "sscanf", "tokio", "url", + "uuid", "waku-sys", ] @@ -4700,46 +4996,48 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasm-bindgen" -version = "0.2.91" +version = "0.2.96" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1e124130aee3fb58c5bdd6b639a0509486b0338acaaae0c84a5124b0f588b7f" +checksum = "21d3b25c3ea1126a2ad5f4f9068483c2af1e64168f847abe863a526b8dbfe00b" dependencies = [ "cfg-if", + "once_cell", "wasm-bindgen-macro", ] [[package]] name = "wasm-bindgen-backend" -version = "0.2.91" +version = "0.2.96" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c9e7e1900c352b609c8488ad12639a311045f40a35491fb69ba8c12f758af70b" +checksum = "52857d4c32e496dc6537646b5b117081e71fd2ff06de792e3577a150627db283" dependencies = [ "bumpalo", "log", "once_cell", "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.89", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-futures" -version = "0.4.41" +version = "0.4.46" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "877b9c3f61ceea0e56331985743b13f3d25c406a7098d45180fb5f09bc19ed97" +checksum = "951fe82312ed48443ac78b66fa43eded9999f738f6022e67aead7b708659e49a" dependencies = [ "cfg-if", "js-sys", + "once_cell", "wasm-bindgen", "web-sys", ] [[package]] name = "wasm-bindgen-macro" -version = "0.2.91" +version = "0.2.96" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b30af9e2d358182b5c7449424f017eba305ed32a7010509ede96cdc4696c46ed" +checksum = "920b0ffe069571ebbfc9ddc0b36ba305ef65577c94b06262ed793716a1afd981" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -4747,30 +5045,31 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.91" +version = "0.2.96" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "642f325be6301eb8107a83d12a8ac6c1e1c54345a7ef1a9261962dfefda09e66" +checksum = "bf59002391099644be3524e23b781fa43d2be0c5aa0719a18c0731b9d195cab6" dependencies = [ "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.89", "wasm-bindgen-backend", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.91" +version = "0.2.96" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f186bd2dcf04330886ce82d6f33dd75a7bfcf69ecf5763b89fcde53b6ac9838" +checksum = "e5047c5392700766601942795a436d7d2599af60dcc3cc1248c9120bfb0827b0" [[package]] name = "wasm-encoder" -version = "0.201.0" +version = "0.221.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9c7d2731df60006819b013f64ccc2019691deccf6e11a1804bc850cd6748f1a" +checksum = "de35b6c3ef1f53ac7a31b5e69bc00f1542ea337e7e7162dc34c68b537ff82690" dependencies = [ "leb128", + "wasmparser 0.221.0", ] [[package]] @@ -4828,7 +5127,7 @@ dependencies = [ "target-lexicon", "thiserror", "wasmer-types", - "wasmparser", + "wasmparser 0.83.0", ] [[package]] @@ -5010,24 +5309,35 @@ version = "0.83.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "718ed7c55c2add6548cca3ddd6383d738cd73b892df400e96b9aa876f0141d7a" +[[package]] +name = "wasmparser" +version = "0.221.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8659e755615170cfe20da468865c989da78c5da16d8652e69a75acda02406a92" +dependencies = [ + "bitflags 2.6.0", + "indexmap 2.6.0", + "semver", +] + [[package]] name = "wast" -version = "201.0.0" +version = "221.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ef6e1ef34d7da3e2b374fd2b1a9c0227aff6cad596e1b24df9b58d0f6222faa" +checksum = "9d8eb1933d493dd07484a255c3f52236123333f5befaa3be36182a50d393ec54" dependencies = [ "bumpalo", "leb128", "memchr", - "unicode-width", + "unicode-width 0.2.0", "wasm-encoder", ] [[package]] name = "wat" -version = "1.201.0" +version = "1.221.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "453d5b37a45b98dee4f4cb68015fc73634d7883bbef1c65e6e9c78d454cf3f32" +checksum = "c813fd4e5b2b97242830b56e7b7dc5479bc17aaa8730109be35e61909af83993" dependencies = [ "wast", ] @@ -5119,9 +5429,9 @@ dependencies = [ [[package]] name = "web-sys" -version = "0.3.68" +version = "0.3.73" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96565907687f7aceb35bc5fc03770a8a0471d82e479f25832f54a0e3f4b28446" +checksum = "476364ff87d0ae6bfb661053a9104ab312542658c3d8f963b7ace80b6f9b26b9" dependencies = [ "js-sys", "wasm-bindgen", @@ -5153,7 +5463,7 @@ dependencies = [ "either", "home", "once_cell", - "rustix 0.38.31", + "rustix 0.38.41", ] [[package]] @@ -5174,11 +5484,11 @@ checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" [[package]] name = "winapi-util" -version = "0.1.6" +version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f29e6f9198ba0d26b4c9f07dbe6f9ed633e1f3d5b8b414090084349e46a52596" +checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" dependencies = [ - "winapi", + "windows-sys 0.59.0", ] [[package]] @@ -5204,7 +5514,7 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" dependencies = [ - "windows-targets 0.52.4", + "windows-targets 0.52.6", ] [[package]] @@ -5266,7 +5576,16 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" dependencies = [ - "windows-targets 0.52.4", + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-sys" +version = "0.59.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" +dependencies = [ + "windows-targets 0.52.6", ] [[package]] @@ -5301,17 +5620,18 @@ dependencies = [ [[package]] name = "windows-targets" -version = "0.52.4" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7dd37b7e5ab9018759f893a1952c9420d060016fc19a472b4bb20d1bdd694d1b" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" dependencies = [ - "windows_aarch64_gnullvm 0.52.4", - "windows_aarch64_msvc 0.52.4", - "windows_i686_gnu 0.52.4", - "windows_i686_msvc 0.52.4", - "windows_x86_64_gnu 0.52.4", - "windows_x86_64_gnullvm 0.52.4", - "windows_x86_64_msvc 0.52.4", + "windows_aarch64_gnullvm 0.52.6", + "windows_aarch64_msvc 0.52.6", + "windows_i686_gnu 0.52.6", + "windows_i686_gnullvm", + "windows_i686_msvc 0.52.6", + "windows_x86_64_gnu 0.52.6", + "windows_x86_64_gnullvm 0.52.6", + "windows_x86_64_msvc 0.52.6", ] [[package]] @@ -5328,9 +5648,9 @@ checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" [[package]] name = "windows_aarch64_gnullvm" -version = "0.52.4" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bcf46cf4c365c6f2d1cc93ce535f2c8b244591df96ceee75d8e83deb70a9cac9" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" [[package]] name = "windows_aarch64_msvc" @@ -5352,9 +5672,9 @@ checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" [[package]] name = "windows_aarch64_msvc" -version = "0.52.4" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da9f259dd3bcf6990b55bffd094c4f7235817ba4ceebde8e6d11cd0c5633b675" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" [[package]] name = "windows_i686_gnu" @@ -5376,9 +5696,15 @@ checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" [[package]] name = "windows_i686_gnu" -version = "0.52.4" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b474d8268f99e0995f25b9f095bc7434632601028cf86590aea5c8a5cb7801d3" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" [[package]] name = "windows_i686_msvc" @@ -5400,9 +5726,9 @@ checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" [[package]] name = "windows_i686_msvc" -version = "0.52.4" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1515e9a29e5bed743cb4415a9ecf5dfca648ce85ee42e15873c3cd8610ff8e02" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" [[package]] name = "windows_x86_64_gnu" @@ -5424,9 +5750,9 @@ checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" [[package]] name = "windows_x86_64_gnu" -version = "0.52.4" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5eee091590e89cc02ad514ffe3ead9eb6b660aedca2183455434b93546371a03" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" [[package]] name = "windows_x86_64_gnullvm" @@ -5442,9 +5768,9 @@ checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" [[package]] name = "windows_x86_64_gnullvm" -version = "0.52.4" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77ca79f2451b49fa9e2af39f0747fe999fcda4f5e241b2898624dca97a1f2177" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" [[package]] name = "windows_x86_64_msvc" @@ -5466,9 +5792,9 @@ checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" [[package]] name = "windows_x86_64_msvc" -version = "0.52.4" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32b752e52a2da0ddfbdbcc6fceadfeede4c939ed16d13e648833a61dfb611ed8" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" [[package]] name = "winit" @@ -5478,14 +5804,14 @@ checksum = "9596d90b45384f5281384ab204224876e8e8bf7d58366d9b795ad99aa9894b94" dependencies = [ "android-activity", "bitflags 1.3.2", - "cfg_aliases", + "cfg_aliases 0.1.1", "core-foundation", "core-graphics", "dispatch", "instant", "libc", "log", - "mio", + "mio 0.8.11", "ndk", "objc2 0.3.0-beta.3.patch-leaks.3", "once_cell", @@ -5514,6 +5840,18 @@ dependencies = [ "memchr", ] +[[package]] +name = "write16" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d1890f4022759daae28ed4fe62859b1236caebfc61ede2f63ed4e695f3f6d936" + +[[package]] +name = "writeable" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e9df38ee2d2c3c5948ea468a8406ff0db0b29ae1ffde1bcf20ef305bcc95c51" + [[package]] name = "wyz" version = "0.5.1" @@ -5541,7 +5879,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5d91ffca73ee7f68ce055750bf9f6eca0780b8c85eff9bc046a3b0da41755e12" dependencies = [ "gethostname", - "rustix 0.38.31", + "rustix 0.38.41", "x11rb-protocol", ] @@ -5559,12 +5897,12 @@ checksum = "0ef33da6b1660b4ddbfb3aef0ade110c8b8a781a3b6382fa5f2b5b040fd55f61" [[package]] name = "xdg-home" -version = "1.2.0" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca91dcf8f93db085f3a0a29358cd0b9d670915468f4290e8b85d118a34211ab8" +checksum = "ec1cdab258fb55c0da61328dc52c8764709b249011b2cad0454c72f0bf10a1f6" dependencies = [ "libc", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -5573,6 +5911,30 @@ version = "0.8.23" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "af310deaae937e48a26602b730250b4949e125f468f11e6990be3e5304ddd96f" +[[package]] +name = "yoke" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "120e6aef9aa629e3d4f52dc8cc43a015c7724194c97dfaf45180d2daf2b77f40" +dependencies = [ + "serde", + "stable_deref_trait", + "yoke-derive", + "zerofrom", +] + +[[package]] +name = "yoke-derive" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2380878cad4ac9aac1e2435f3eb4020e8374b5f13c296cb75b4620ff8e229154" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.89", + "synstructure 0.13.1", +] + [[package]] name = "zbus" version = "3.15.2" @@ -5641,29 +6003,51 @@ dependencies = [ [[package]] name = "zerocopy" -version = "0.7.32" +version = "0.7.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d4d3961e53fa4c9a25a8637fc2bfaf2595b3d3ae34875568a5cf64787716be" +checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0" dependencies = [ + "byteorder", "zerocopy-derive", ] [[package]] name = "zerocopy-derive" -version = "0.7.32" +version = "0.7.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ce1b18ccd8e73a9321186f97e46f9f04b778851177567b1975109d26a08d2a6" +checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.89", +] + +[[package]] +name = "zerofrom" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cff3ee08c995dee1859d998dea82f7374f2826091dd9cd47def953cae446cd2e" +dependencies = [ + "zerofrom-derive", +] + +[[package]] +name = "zerofrom-derive" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "595eed982f7d355beb85837f651fa22e90b3c044842dc7f2c2842c086f295808" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.89", + "synstructure 0.13.1", ] [[package]] name = "zeroize" -version = "1.7.0" +version = "1.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "525b4ec142c6b68a2d10f01f7bbf6755599ca3f81ea53b8431b7dd348f5fdb2d" +checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde" dependencies = [ "zeroize_derive", ] @@ -5676,14 +6060,14 @@ checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" dependencies = [ "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.89", ] [[package]] name = "zerokit_utils" -version = "0.3.2" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a27b6b92ef0c85678bd788fa425a260f0b9eaabefcadf86c06e6a533cb9b295" +checksum = "1c5d529c636d8882d5fa8730fa5431a8796664d631f29ba99d70ca893323fdda" dependencies = [ "ark-ff", "color-eyre", @@ -5693,6 +6077,28 @@ dependencies = [ "sled", ] +[[package]] +name = "zerovec" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa2b893d79df23bfb12d5461018d408ea19dfafe76c2c7ef6d4eba614f8ff079" +dependencies = [ + "yoke", + "zerofrom", + "zerovec-derive", +] + +[[package]] +name = "zerovec-derive" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6eafa6dfb17584ea3e2bd6e76e0cc15ad7af12b09abdd1ca55961bed9b1063c6" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.89", +] + [[package]] name = "zvariant" version = "3.15.2" diff --git a/examples/Cargo.toml b/examples/Cargo.toml index a679a1a..c502dfe 100644 --- a/examples/Cargo.toml +++ b/examples/Cargo.toml @@ -2,5 +2,6 @@ members = [ "basic", - "tic-tac-toe-gui" + "tic-tac-toe-gui", + "toy-chat" ] diff --git a/examples/basic/src/main.rs b/examples/basic/src/main.rs index f7b9a1d..d0da1c3 100644 --- a/examples/basic/src/main.rs +++ b/examples/basic/src/main.rs @@ -1,10 +1,9 @@ use std::io::Error; use std::str::from_utf8; -use std::time::SystemTime; use tokio::time::{sleep, Duration}; use waku::{ - general::pubsubtopic::PubsubTopic, waku_new, Encoding, Event, LibwakuResponse, - WakuContentTopic, WakuMessage, WakuNodeConfig, + general::pubsubtopic::PubsubTopic, waku_new, Encoding, LibwakuResponse, WakuContentTopic, + WakuEvent, WakuMessage, WakuNodeConfig, }; #[tokio::main] @@ -13,12 +12,14 @@ async fn main() -> Result<(), Error> { tcp_port: Some(60010), // TODO: use any available port. ..Default::default() })) + .await .expect("should instantiate"); let node2 = waku_new(Some(WakuNodeConfig { tcp_port: Some(60020), // TODO: use any available port. ..Default::default() })) + .await .expect("should instantiate"); // ======================================================================== @@ -26,12 +27,12 @@ async fn main() -> Result<(), Error> { node2 .set_event_callback(|response| { if let LibwakuResponse::Success(v) = response { - let event: Event = + let event: WakuEvent = serde_json::from_str(v.unwrap().as_str()).expect("Parsing event to succeed"); match event { - Event::WakuMessage(evt) => { - println!("WakuMessage event received: {:?}", evt.waku_message); + WakuEvent::WakuMessage(evt) => { + // println!("WakuMessage event received: {:?}", evt.waku_message); let message = evt.waku_message; let payload = message.payload.to_vec(); let msg = from_utf8(&payload).expect("should be valid message"); @@ -39,7 +40,13 @@ async fn main() -> Result<(), Error> { println!("Message Received in NODE 2: {}", msg); println!("::::::::::::::::::::::::::::::::::::::::::::::::::::"); } - Event::Unrecognized(err) => panic!("Unrecognized waku event: {:?}", err), + WakuEvent::RelayTopicHealthChange(_evt) => { + // dbg!("Relay topic change evt", evt); + } + WakuEvent::ConnectionChange(_evt) => { + // dbg!("Conn change evt", evt); + } + WakuEvent::Unrecognized(err) => panic!("Unrecognized waku event: {:?}", err), _ => panic!("event case not expected"), }; } @@ -49,12 +56,12 @@ async fn main() -> Result<(), Error> { node1 .set_event_callback(|response| { if let LibwakuResponse::Success(v) = response { - let event: Event = + let event: WakuEvent = serde_json::from_str(v.unwrap().as_str()).expect("Parsing event to succeed"); match event { - Event::WakuMessage(evt) => { - println!("WakuMessage event received: {:?}", evt.waku_message); + WakuEvent::WakuMessage(evt) => { + // println!("WakuMessage event received: {:?}", evt.waku_message); let message = evt.waku_message; let payload = message.payload.to_vec(); let msg = from_utf8(&payload).expect("should be valid message"); @@ -62,15 +69,21 @@ async fn main() -> Result<(), Error> { println!("Message Received in NODE 1: {}", msg); println!("::::::::::::::::::::::::::::::::::::::::::::::::::::"); } - Event::Unrecognized(err) => panic!("Unrecognized waku event: {:?}", err), + WakuEvent::RelayTopicHealthChange(_evt) => { + // dbg!("Relay topic change evt", evt); + } + WakuEvent::ConnectionChange(_evt) => { + // dbg!("Conn change evt", evt); + } + WakuEvent::Unrecognized(err) => panic!("Unrecognized waku event: {:?}", err), _ => panic!("event case not expected"), }; } }) .expect("set event call back working"); - let node1 = node1.start().expect("node1 should start"); - let node2 = node2.start().expect("node2 should start"); + let node1 = node1.start().await.expect("node1 should start"); + let node2 = node2.start().await.expect("node2 should start"); // ======================================================================== // Subscribe to pubsub topic @@ -78,10 +91,12 @@ async fn main() -> Result<(), Error> { node1 .relay_subscribe(&topic) + .await .expect("node1 should subscribe"); node2 .relay_subscribe(&topic) + .await .expect("node2 should subscribe"); // ======================================================================== @@ -89,10 +104,12 @@ async fn main() -> Result<(), Error> { let addresses2 = node2 .listen_addresses() + .await .expect("should obtain the addresses"); node1 .connect(&addresses2[0], None) + .await .expect("node1 should connect to node2"); // ======================================================================== @@ -104,21 +121,10 @@ async fn main() -> Result<(), Error> { // Publish a message let content_topic = WakuContentTopic::new("waku", "2", "test", Encoding::Proto); - let message = WakuMessage::new( - "Hello world", - content_topic, - 0, - SystemTime::now() - .duration_since(SystemTime::UNIX_EPOCH) - .unwrap() - .as_millis() - .try_into() - .unwrap(), - Vec::new(), - false, - ); + let message = WakuMessage::new("Hello world", content_topic, 0, Vec::new(), false); node1 .relay_publish_message(&message, &topic, None) + .await .expect("should have sent the message"); // ======================================================================== @@ -129,13 +135,13 @@ async fn main() -> Result<(), Error> { // ======================================================================== // Stop both instances - let node1 = node1.stop().expect("should stop"); - let node2 = node2.stop().expect("should stop"); + let node1 = node1.stop().await.expect("should stop"); + let node2 = node2.stop().await.expect("should stop"); // ======================================================================== // Free resources - node1.waku_destroy().expect("should deallocate"); - node2.waku_destroy().expect("should deallocate"); + node1.waku_destroy().await.expect("should deallocate"); + node2.waku_destroy().await.expect("should deallocate"); Ok(()) } diff --git a/examples/tic-tac-toe-gui/src/main.rs b/examples/tic-tac-toe-gui/src/main.rs index 553e5dc..97dbf51 100644 --- a/examples/tic-tac-toe-gui/src/main.rs +++ b/examples/tic-tac-toe-gui/src/main.rs @@ -2,11 +2,12 @@ use eframe::egui; use serde::{Deserialize, Serialize}; use std::str::from_utf8; use std::sync::{Arc, Mutex}; -use std::time::{SystemTime, Duration}; +use std::time::Duration; +use tokio::task; use tokio::sync::mpsc; use waku::{ - waku_new, Encoding, Event, LibwakuResponse, WakuContentTopic, + waku_new, Encoding, WakuEvent, LibwakuResponse, WakuContentTopic, WakuMessage, WakuNodeConfig, WakuNodeHandle, Initialized, Running, general::pubsubtopic::PubsubTopic, }; @@ -48,16 +49,16 @@ impl TicTacToeApp { } } - fn start(self) -> TicTacToeApp { + async fn start(self) -> TicTacToeApp { let tx_clone = self.tx.clone(); let my_closure = move |response| { if let LibwakuResponse::Success(v) = response { - let event: Event = + let event: WakuEvent = serde_json::from_str(v.unwrap().as_str()).expect("Parsing event to succeed"); match event { - Event::WakuMessage(evt) => { + WakuEvent::WakuMessage(evt) => { // println!("WakuMessage event received: {:?}", evt.waku_message); let message = evt.waku_message; let payload = message.payload.to_vec(); @@ -73,8 +74,14 @@ impl TicTacToeApp { // Handle the error as needed, or just log and skip } } - } - Event::Unrecognized(err) => panic!("Unrecognized waku event: {:?}", err), + }, + WakuEvent::RelayTopicHealthChange(_evt) => { + // dbg!("Relay topic change evt", evt); + }, + WakuEvent::ConnectionChange(_evt) => { + // dbg!("Conn change evt", evt); + }, + WakuEvent::Unrecognized(err) => panic!("Unrecognized waku event: {:?}", err), _ => panic!("event case not expected"), }; } @@ -83,17 +90,22 @@ impl TicTacToeApp { // Establish a closure that handles the incoming messages self.waku.set_event_callback(my_closure).expect("set event call back working"); - let _ = self.waku.version(); - // Start the waku node - let waku = self.waku.start().expect("waku should start"); + let waku = self.waku.start().await.expect("waku should start"); // Subscribe to desired topic using the relay protocol - // self.waku.relay_subscribe(&self.game_topic.to_string()).expect("waku should subscribe"); + waku.relay_subscribe(&self.game_topic).await.expect("waku should subscribe"); + + // Example filter subscription. This is needed in edge nodes (resource-restricted devices) + // Nodes usually use either relay or lightpush/filter protocols + + // let ctopic = WakuContentTopic::new("waku", "2", "tictactoegame", Encoding::Proto); + // let content_topics = vec![ctopic]; + // waku.filter_subscribe(&self.game_topic, content_topics).await.expect("waku should subscribe"); - let ctopic = WakuContentTopic::new("waku", "2", "tictactoegame", Encoding::Proto); - let content_topics = vec![ctopic]; - waku.filter_subscribe(&self.game_topic, content_topics).expect("waku should subscribe"); + // End filter example ---------------------------------------- + + // Example to establish direct connection to a well-known node // Connect to hard-coded node // let target_node_multi_addr = @@ -105,9 +117,11 @@ impl TicTacToeApp { // self.waku.connect(&target_node_multi_addr, None) // .expect("waku should connect to other node"); + // End example direct connection + TicTacToeApp { game_state: self.game_state, - waku: waku, + waku, game_topic: self.game_topic, tx: self.tx, player_role: self.player_role, @@ -116,7 +130,7 @@ impl TicTacToeApp { } impl TicTacToeApp { - fn send_game_state(&self, game_state: &GameState) { + async fn send_game_state(&self, game_state: &GameState) { let serialized_game_state = serde_json::to_string(game_state).unwrap(); let content_topic = WakuContentTopic::new("waku", "2", "tictactoegame", Encoding::Proto); @@ -124,44 +138,58 @@ impl TicTacToeApp { &serialized_game_state, content_topic, 0, - SystemTime::now() - .duration_since(SystemTime::UNIX_EPOCH) - .unwrap() - .as_millis() - .try_into() - .unwrap(), Vec::new(), false, ); - // self.waku.relay_publish_message(&message, &self.game_topic.to_string(), None) - // .expect("Failed to send message"); - self.waku.lightpush_publish_message(&message, &self.game_topic).expect("Failed to send message"); + if let Ok(msg_hash) = self.waku.relay_publish_message(&message, &self.game_topic, None).await { + dbg!(format!("message hash published: {}", msg_hash)); + } + + // Example lightpush publish message. This is needed in edge nodes (resource-restricted devices) + // Nodes usually use either relay or lightpush/filter protocols + // + // let msg_hash_ret = self.waku.lightpush_publish_message(&message, &self.game_topic).await; + // match msg_hash_ret { + // Ok(msg_hash) => println!("Published message hash {:?}", msg_hash.to_string()), + // Err(error) => println!("Failed to publish with lightpush: {}", error) + // } + // End example lightpush publish message } fn make_move(&mut self, row: usize, col: usize) { if let Ok(mut game_state) = self.game_state.try_lock() { if let Some(my_role) = self.player_role { - if (*game_state).current_turn != my_role { + if game_state.current_turn != my_role { return; // skip click if not my turn } } - if (*game_state).board[row][col].is_none() && (*game_state).moves_left > 0 { - (*game_state).board[row][col] = Some((*game_state).current_turn); - (*game_state).moves_left -= 1; + if game_state.board[row][col].is_none() && game_state.moves_left > 0 { + game_state.board[row][col] = Some(game_state.current_turn); + game_state.moves_left -= 1; if let Some(winner) = self.check_winner(&game_state) { - (*game_state).current_turn = winner; + game_state.current_turn = winner; } else { - (*game_state).current_turn = match (*game_state).current_turn { + game_state.current_turn = match game_state.current_turn { Player::X => Player::O, Player::O => Player::X, }; } - self.send_game_state(&game_state); // Send updated state after a move + // Call the async function in a blocking context + task::block_in_place(|| { + // Obtain the current runtime handle + let handle = tokio::runtime::Handle::current(); + + // Block on the async function + handle.block_on(async { + // Assuming `self` is available in the current context + self.send_game_state(&game_state).await; + }); + }); } } } @@ -227,7 +255,7 @@ impl eframe::App for TicTacToeApp { if ui.button("Play as O").clicked() { self.player_role = Some(Player::O); if let Ok(mut game_state) = self.game_state.try_lock() { - (*game_state).current_turn = Player::X; // player X should start + game_state.current_turn = Player::X; // player X should start } } @@ -301,6 +329,10 @@ impl eframe::App for TicTacToeApp { } }); } + + fn on_exit(&mut self, _gl: Option<&eframe::glow::Context>) { + // TODO: implement the cleanup an proper stop of waku node + } } #[tokio::main] @@ -316,7 +348,7 @@ async fn main() -> eframe::Result<()> { // node_key: Some(SecretKey::from_str("2fc0515879e52b7b73297cfd6ab3abf7c344ef84b7a90ff6f4cc19e05a198027").unwrap()), max_message_size: Some("1024KiB".to_string()), relay_topics: vec![String::from(&game_topic)], - log_level: Some("DEBUG"), // Supported: TRACE, DEBUG, INFO, NOTICE, WARN, ERROR or FATAL + log_level: Some("FATAL"), // Supported: TRACE, DEBUG, INFO, NOTICE, WARN, ERROR or FATAL keep_alive: Some(true), @@ -328,7 +360,7 @@ async fn main() -> eframe::Result<()> { // discv5_enr_auto_update: Some(false), ..Default::default() - })) + })).await .expect("should instantiate"); let game_state = GameState { @@ -341,7 +373,7 @@ async fn main() -> eframe::Result<()> { let clone = shared_state.clone(); let app = TicTacToeApp::new(waku, game_topic, clone, tx); - let app = app.start(); + let app = app.start().await; let clone = shared_state.clone(); // Listen for messages in the main thread diff --git a/examples/toy-chat/Cargo.toml b/examples/toy-chat/Cargo.toml new file mode 100644 index 0000000..abc5442 --- /dev/null +++ b/examples/toy-chat/Cargo.toml @@ -0,0 +1,19 @@ +[package] +name = "toy-chat" +version = "0.1.0" +edition = "2021" +authors = [ + "Daniel Sanchez Quiros " +] +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +waku = { path = "../../waku-bindings", package = "waku-bindings" } +serde_json = "1.0" +serde = { version = "1.0", features = ["derive"] } +tui = "0.19" +crossterm = "0.25" +unicode-width = "0.1" +prost = "0.11" +chrono = "0.4" +tokio = { version = "1", features = ["full"] } \ No newline at end of file diff --git a/examples/toy-chat/src/main.rs b/examples/toy-chat/src/main.rs new file mode 100644 index 0000000..e5890fd --- /dev/null +++ b/examples/toy-chat/src/main.rs @@ -0,0 +1,361 @@ +mod protocol; + +use crate::protocol::{Chat2Message, TOY_CHAT_CONTENT_TOPIC}; +use tokio::task; +use crossterm::{ + event::{self, DisableMouseCapture, EnableMouseCapture, Event, KeyCode}, + execute, + terminal::{disable_raw_mode, enable_raw_mode, EnterAlternateScreen, LeaveAlternateScreen}, +}; +use prost::Message; +use chrono::Utc; +use std::io::Write; +use std::sync::{Arc, RwLock}; +use std::{error::Error, io}; +use std::time::Duration; +use tui::{ + backend::{Backend, CrosstermBackend}, + layout::{Constraint, Direction, Layout}, + style::{Color, Modifier, Style}, + text::{Span, Spans, Text}, + widgets::{Block, Borders, List, ListItem, Paragraph}, + Frame, Terminal, +}; +use unicode_width::UnicodeWidthStr; +use waku::{ + general::pubsubtopic::PubsubTopic, general::Result, waku_new, Initialized, LibwakuResponse, Running, WakuEvent, + WakuMessage, WakuNodeConfig, WakuNodeHandle, +}; + +enum InputMode { + Normal, + Editing, +} + +const STORE_NODE: &str = "/dns4/store-01.do-ams3.status.staging.status.im/tcp/30303/p2p/16Uiu2HAm3xVDaz6SRJ6kErwC21zBJEZjavVXg7VSkoWzaV1aMA3F"; + +const DEFAULT_PUBSUB_TOPIC: &str = "/waku/2/rs/16/32"; + +/// App holds the state of the application +struct App { + /// Current value of the input box + input: String, + nick: String, + /// Current input mode + input_mode: InputMode, + /// History of recorded messages + messages: Arc>>, + waku: WakuNodeHandle, +} + +impl App { + async fn new(nick: String) -> Result> { + let pubsub_topic = PubsubTopic::new(DEFAULT_PUBSUB_TOPIC); + let waku = waku_new(Some(WakuNodeConfig { + tcp_port: Some(60010), + cluster_id: Some(16), + shards: vec![1, 32, 64, 128, 256], + // node_key: Some(SecretKey::from_str("2fc0515879e52b7b73297cfd6ab3abf7c344ef84b7a90ff6f4cc19e05a198027").unwrap()), + max_message_size: Some("1024KiB".to_string()), + relay_topics: vec![String::from(&pubsub_topic)], + log_level: Some("FATAL"), // Supported: TRACE, DEBUG, INFO, NOTICE, WARN, ERROR or FATAL + + keep_alive: Some(true), + + // Discovery + dns_discovery: Some(true), + dns_discovery_url: Some("enrtree://AMOJVZX4V6EXP7NTJPMAYJYST2QP6AJXYW76IU6VGJS7UVSNDYZG4@boot.prod.status.nodes.status.im"), + // discv5_discovery: Some(true), + // discv5_udp_port: Some(9001), + // discv5_enr_auto_update: Some(false), + + ..Default::default() + })).await?; + + Ok(App { + input: String::new(), + input_mode: InputMode::Normal, + messages: Arc::new(RwLock::new(Vec::new())), + nick, + waku, + }) + } + + async fn start_waku_node(self) -> Result> { + + let shared_messages = Arc::clone(&self.messages); + + self.waku.set_event_callback(move|response| { + if let LibwakuResponse::Success(v) = response { + let event: WakuEvent = + serde_json::from_str(v.unwrap().as_str()).expect("failed parsing event in set_event_callback"); + + match event { + WakuEvent::WakuMessage(evt) => { + + if evt.waku_message.content_topic != TOY_CHAT_CONTENT_TOPIC { + return; // skip the messages that don't belong to the toy chat + } + + match ::decode(evt.waku_message.payload()) { + Ok(chat_message) => { + // Add the new message to the front + { + let mut messages_lock = shared_messages.write().unwrap(); + messages_lock.insert(0, chat_message); // Insert at the front (index 0) + } + } + Err(e) => { + let mut out = std::io::stderr(); + write!(out, "{e:?}").unwrap(); + } + } + }, + WakuEvent::RelayTopicHealthChange(_evt) => { + // dbg!("Relay topic change evt", evt); + }, + WakuEvent::ConnectionChange(_evt) => { + // dbg!("Conn change evt", evt); + }, + WakuEvent::Unrecognized(err) => eprintln!("Unrecognized waku event: {:?}", err), + _ => eprintln!("event case not expected"), + }; + } + })?; + + let waku = self.waku.start().await?; + + Ok(App { + input: self.input, + nick: self.nick, + input_mode: self.input_mode, + messages: self.messages, + waku, + }) + } +} + +impl App { + + async fn retrieve_history(&mut self) { + let one_day_in_secs = 60 * 60 * 24; + let time_start = (Duration::from_secs(Utc::now().timestamp() as u64) + - Duration::from_secs(one_day_in_secs)) + .as_nanos() as u64; + + let include_data = true; + + let messages = self.waku.store_query(None, + vec![TOY_CHAT_CONTENT_TOPIC.clone()], + STORE_NODE, + include_data, + Some(time_start), + None, + None).await.unwrap(); + + let messages: Vec<_> = messages + .into_iter() + // we expect messages because the query was passed with include_data == true + .filter(|item| item.message.is_some()) + .map(|store_resp_msg| { + ::decode(store_resp_msg.message.unwrap().payload()) + .expect("Toy chat messages should be decodeable") + }) + .collect(); + + if !messages.is_empty() { + *self.messages.write().unwrap() = messages; + } + } + + fn run_main_loop( + &mut self, + terminal: &mut Terminal, + ) -> std::result::Result<(), Box> { + loop { + terminal.draw(|f| ui(f, self))?; + + if event::poll(Duration::from_millis(500)).unwrap() { + if let Event::Key(key) = event::read()? { + match self.input_mode { + InputMode::Normal => match key.code { + KeyCode::Char('e') => { + self.input_mode = InputMode::Editing; + } + KeyCode::Char('q') => { + return Ok(()); + } + _ => {} + }, + InputMode::Editing => match key.code { + KeyCode::Enter => { + let message_content: String = self.input.drain(..).collect(); + let message = Chat2Message::new(&self.nick, &message_content); + let mut buff = Vec::new(); + let meta = Vec::new(); + Message::encode(&message, &mut buff)?; + let waku_message = WakuMessage::new( + buff, + TOY_CHAT_CONTENT_TOPIC.clone(), + 1, + meta, + false, + ); + + // Call the async function in a blocking context + task::block_in_place(|| { + // Obtain the current runtime handle + let handle = tokio::runtime::Handle::current(); + + // Block on the async function + handle.block_on(async { + // Assuming `self` is available in the current context + let pubsub_topic = PubsubTopic::new(DEFAULT_PUBSUB_TOPIC); + if let Err(e) = self.waku.relay_publish_message( + &waku_message, + &pubsub_topic, + None, + ).await { + let mut out = std::io::stderr(); + write!(out, "{e:?}").unwrap(); + } + }); + }); + } + KeyCode::Char(c) => { + self.input.push(c); + } + KeyCode::Backspace => { + self.input.pop(); + } + KeyCode::Esc => { + self.input_mode = InputMode::Normal; + } + _ => {} + }, + } + } + } + } + } + + async fn stop_app(self) { + self.waku.stop().await.expect("the node should stop properly"); + } +} + +#[tokio::main] +async fn main() -> std::result::Result<(), Box> { + let nick = std::env::args().nth(1).expect("Nick to be set"); + + let app = App::new(nick).await?; + let mut app = app.start_waku_node().await?; + + // setup terminal + enable_raw_mode()?; + let mut stdout = io::stdout(); + execute!(stdout, EnterAlternateScreen, EnableMouseCapture)?; + let backend = CrosstermBackend::new(stdout); + let mut terminal = Terminal::new(backend)?; + + app.retrieve_history().await; + let res = app.run_main_loop(&mut terminal); + app.stop_app().await; + + // restore terminal + disable_raw_mode()?; + execute!( + terminal.backend_mut(), + LeaveAlternateScreen, + DisableMouseCapture + )?; + terminal.show_cursor()?; + + if let Err(err) = res { + println!("{err:?}") + } + Ok(()) +} + +fn ui(f: &mut Frame, app: &App) { + let chunks = Layout::default() + .direction(Direction::Vertical) + .margin(2) + .constraints( + [ + Constraint::Length(1), + Constraint::Length(3), + Constraint::Min(1), + ] + .as_ref(), + ) + .split(f.size()); + + let (msg, style) = match app.input_mode { + InputMode::Normal => ( + vec![ + Span::raw("Press "), + Span::styled("q", Style::default().add_modifier(Modifier::BOLD)), + Span::raw(" to exit, "), + Span::styled("e", Style::default().add_modifier(Modifier::BOLD)), + Span::raw(" to start writing a message."), + ], + Style::default().add_modifier(Modifier::RAPID_BLINK), + ), + InputMode::Editing => ( + vec![ + Span::raw("Press "), + Span::styled("Esc", Style::default().add_modifier(Modifier::BOLD)), + Span::raw(" to stop editing, "), + Span::styled("Enter", Style::default().add_modifier(Modifier::BOLD)), + Span::raw(" to record the message"), + ], + Style::default(), + ), + }; + let mut text = Text::from(Spans::from(msg)); + text.patch_style(style); + let help_message = Paragraph::new(text); + f.render_widget(help_message, chunks[0]); + + let input = Paragraph::new(app.input.as_ref()) + .style(match app.input_mode { + InputMode::Normal => Style::default(), + InputMode::Editing => Style::default().fg(Color::Yellow), + }) + .block(Block::default().borders(Borders::ALL).title("Input")); + f.render_widget(input, chunks[1]); + match app.input_mode { + InputMode::Normal => + // Hide the cursor. `Frame` does this by default, so we don't need to do anything here + {} + + InputMode::Editing => { + // Make the cursor visible and ask tui-rs to put it at the specified coordinates after rendering + f.set_cursor( + // Put cursor past the end of the input text + chunks[1].x + app.input.width() as u16 + 1, + // Move one line down, from the border to the input line + chunks[1].y + 1, + ) + } + } + + let messages: Vec = app + .messages + .read() + .unwrap() + .iter() + .map(|message| { + let content = vec![Spans::from(Span::raw(format!( + "[{} - {}]: {}", + message.timestamp().unwrap().format("%d-%m-%y %H:%M"), + message.nick(), + message.message() + )))]; + ListItem::new(content) + }) + .collect(); + let messages = List::new(messages).block(Block::default().borders(Borders::ALL).title("Chat")); + f.render_widget(messages, chunks[2]); +} diff --git a/examples/toy-chat/src/protocol.rs b/examples/toy-chat/src/protocol.rs new file mode 100644 index 0000000..27fcbbd --- /dev/null +++ b/examples/toy-chat/src/protocol.rs @@ -0,0 +1,37 @@ +use chrono::{DateTime, LocalResult, TimeZone, Utc}; +use prost::Message; +use waku::{Encoding, WakuContentTopic}; + +pub static TOY_CHAT_CONTENT_TOPIC: WakuContentTopic = + WakuContentTopic::new("toy-chat", "2", "huilong", Encoding::Proto); + +#[derive(Clone, Message)] +pub struct Chat2Message { + #[prost(uint64, tag = "1")] + timestamp: u64, + #[prost(string, tag = "2")] + nick: String, + #[prost(bytes, tag = "3")] + payload: Vec, +} + +impl Chat2Message { + pub fn new(nick: &str, payload: &str) -> Self { + Self { + timestamp: Utc::now().timestamp() as u64, + nick: nick.to_string(), + payload: payload.as_bytes().to_vec(), + } + } + pub fn message(&self) -> String { + String::from_utf8(self.payload.clone()).unwrap() + } + + pub fn nick(&self) -> &str { + &self.nick + } + + pub fn timestamp(&self) -> LocalResult> { + Utc.timestamp_opt(self.timestamp as i64, 0) + } +} diff --git a/waku-bindings/Cargo.toml b/waku-bindings/Cargo.toml index 58c5830..57e6364 100644 --- a/waku-bindings/Cargo.toml +++ b/waku-bindings/Cargo.toml @@ -33,6 +33,8 @@ serde-aux = "4.3.1" rln = "0.3.4" tokio = { version = "1", features = ["full"] } regex = "1" +chrono = "0.4" +uuid = { version = "1.3", features = ["v4"] } [dev-dependencies] futures = "0.3.25" diff --git a/waku-bindings/src/general/contenttopic.rs b/waku-bindings/src/general/contenttopic.rs index 381f57a..f8d8d9f 100644 --- a/waku-bindings/src/general/contenttopic.rs +++ b/waku-bindings/src/general/contenttopic.rs @@ -1,4 +1,6 @@ // std +use crate::general::waku_decode::WakuDecode; +use crate::general::Result; use std::borrow::Cow; use std::fmt::{Display, Formatter}; use std::str::FromStr; @@ -79,6 +81,12 @@ impl WakuContentTopic { } } +impl WakuDecode for WakuContentTopic { + fn decode(input: &str) -> Result { + Ok(serde_json::from_str(input).expect("could not parse store resp")) + } +} + impl FromStr for WakuContentTopic { type Err = String; diff --git a/waku-bindings/src/utils.rs b/waku-bindings/src/general/libwaku_response.rs similarity index 50% rename from waku-bindings/src/utils.rs rename to waku-bindings/src/general/libwaku_response.rs index 760f774..cd66bd8 100644 --- a/waku-bindings/src/utils.rs +++ b/waku-bindings/src/general/libwaku_response.rs @@ -1,11 +1,10 @@ +use crate::general::waku_decode::WakuDecode; use crate::general::Result; -use core::str::FromStr; use std::convert::TryFrom; -use std::{slice, str}; -use waku_sys::WakuCallBack; +use std::str; use waku_sys::{RET_ERR, RET_MISSING_CALLBACK, RET_OK}; -#[derive(Debug, Default, PartialEq)] +#[derive(Debug, Clone, Default, PartialEq)] pub enum LibwakuResponse { Success(Option), Failure(String), @@ -31,45 +30,8 @@ impl TryFrom<(u32, &str)> for LibwakuResponse { } } -// Define the WakuDecode trait -pub trait WakuDecode: Sized { - fn decode(input: &str) -> Result; -} - -pub fn decode(input: String) -> Result { - T::decode(input.as_str()) -} - -unsafe extern "C" fn trampoline( - ret_code: ::std::os::raw::c_int, - data: *const ::std::os::raw::c_char, - data_len: usize, - user_data: *mut ::std::os::raw::c_void, -) where - F: FnMut(LibwakuResponse), -{ - let closure = &mut *(user_data as *mut F); - - let response = if data.is_null() { - "" - } else { - str::from_utf8(slice::from_raw_parts(data as *mut u8, data_len)) - .expect("could not retrieve response") - }; - - let result = LibwakuResponse::try_from((ret_code as u32, response)) - .expect("invalid response obtained from libwaku"); - - closure(result); -} - -pub fn get_trampoline(_closure: &F) -> WakuCallBack -where - F: FnMut(LibwakuResponse), -{ - Some(trampoline::) -} - +/// Used in cases where the FFI call doesn't return additional information in the +/// callback. Instead, it returns RET_OK, RET_ERR, etc. pub fn handle_no_response(code: i32, result: LibwakuResponse) -> Result<()> { if result == LibwakuResponse::Undefined && code as u32 == RET_OK { // Some functions will only execute the callback on error @@ -87,24 +49,11 @@ pub fn handle_no_response(code: i32, result: LibwakuResponse) -> Result<()> { } } -pub fn handle_json_response(code: i32, result: LibwakuResponse) -> Result { - match result { - LibwakuResponse::Success(v) => decode(v.unwrap_or_default()), - LibwakuResponse::Failure(v) => Err(v), - LibwakuResponse::MissingCallback => panic!("callback is required"), - LibwakuResponse::Undefined => panic!( - "undefined ffi state: code({}) was returned but callback was not executed", - code - ), - } -} - -pub fn handle_response(code: i32, result: LibwakuResponse) -> Result { +/// Used in cases where the FFI function returns a code (RET_OK, RET_ERR, etc) plus additional +/// information, i.e. LibwakuResponse +pub fn handle_response(code: i32, result: LibwakuResponse) -> Result { match result { - LibwakuResponse::Success(v) => v - .unwrap_or_default() - .parse() - .map_err(|_| "could not parse value".into()), + LibwakuResponse::Success(v) => WakuDecode::decode(&v.unwrap_or_default()), LibwakuResponse::Failure(v) => Err(v), LibwakuResponse::MissingCallback => panic!("callback is required"), LibwakuResponse::Undefined => panic!( diff --git a/waku-bindings/src/general/messagehash.rs b/waku-bindings/src/general/messagehash.rs new file mode 100644 index 0000000..e236d4c --- /dev/null +++ b/waku-bindings/src/general/messagehash.rs @@ -0,0 +1,52 @@ +use crate::general::waku_decode::WakuDecode; +use hex::FromHex; +use serde::{Deserialize, Serialize}; +use std::convert::TryInto; +use std::fmt; +use std::fmt::Write; +use std::hash::Hash; +use std::str::FromStr; + +/// Waku message hash, hex encoded sha256 digest of the message +#[derive(Debug, Deserialize, Serialize, PartialEq, Eq, Clone, Hash)] +pub struct MessageHash([u8; 32]); + +impl MessageHash { + fn to_hex_string(&self) -> String { + self.0.iter().fold(String::new(), |mut output, b| { + let _ = write!(output, "{b:02X}"); + output + }) + } +} + +impl FromStr for MessageHash { + type Err = String; + + fn from_str(s: &str) -> std::result::Result { + let s = s.strip_prefix("0x").unwrap_or(s); + // Decode the hexadecimal string to a Vec + // We expect a string format like: d38220de82fbcf2df865b680692fce98c36600fdd1d954b8a71e916dc4222b8e + let bytes = Vec::from_hex(s).map_err(|e| format!("Hex decode error MessageHash: {}", e))?; + + // Ensure the length is exactly 32 bytes + let res = bytes + .try_into() + .map_err(|_| "Hex string must represent exactly 32 bytes".to_string())?; + + Ok(MessageHash(res)) + } +} + +impl WakuDecode for MessageHash { + fn decode(input: &str) -> Result { + MessageHash::from_str(input) + } +} + +// Implement the Display trait +impl fmt::Display for MessageHash { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "{}", self.to_hex_string()) + } +} diff --git a/waku-bindings/src/general/mod.rs b/waku-bindings/src/general/mod.rs index 90a6724..25e74f8 100644 --- a/waku-bindings/src/general/mod.rs +++ b/waku-bindings/src/general/mod.rs @@ -1,17 +1,20 @@ //! Waku [general](https://rfc.vac.dev/spec/36/#general) types pub mod contenttopic; +pub mod libwaku_response; +pub mod messagehash; pub mod pubsubtopic; +pub mod time; +pub mod waku_decode; // crates +use crate::general::time::get_now_in_nanosecs; use contenttopic::WakuContentTopic; use serde::{Deserialize, Serialize}; use serde_aux::prelude::*; /// Waku message version pub type WakuMessageVersion = usize; -/// Waku message hash, hex encoded sha256 digest of the message -pub type MessageHash = String; pub type Result = std::result::Result; @@ -30,7 +33,7 @@ pub struct WakuMessage { pub version: WakuMessageVersion, /// Unix timestamp in nanoseconds #[serde(deserialize_with = "deserialize_number_from_string")] - pub timestamp: usize, + pub timestamp: u64, #[serde(with = "base64_serde", default = "Vec::new")] pub meta: Vec, #[serde(default)] @@ -40,12 +43,31 @@ pub struct WakuMessage { _extras: serde_json::Value, } +#[derive(Clone, Serialize, Deserialize, Debug, Default)] +#[serde(rename_all = "camelCase")] +pub struct WakuStoreRespMessage { + // #[serde(with = "base64_serde", default = "Vec::new")] + pub payload: Vec, + /// The content topic to be set on the message + // #[serde(rename = "contentTopic")] + pub content_topic: String, + // #[serde(with = "base64_serde", default = "Vec::new")] + pub meta: Vec, + /// The Waku Message version number + #[serde(default)] + pub version: WakuMessageVersion, + /// Unix timestamp in nanoseconds + pub timestamp: usize, + #[serde(default)] + pub ephemeral: bool, + pub proof: Vec, +} + impl WakuMessage { pub fn new, META: AsRef<[u8]>>( payload: PAYLOAD, content_topic: WakuContentTopic, version: WakuMessageVersion, - timestamp: usize, meta: META, ephemeral: bool, ) -> Self { @@ -56,12 +78,22 @@ impl WakuMessage { payload, content_topic, version, - timestamp, + timestamp: get_now_in_nanosecs(), meta, ephemeral, _extras: Default::default(), } } + + pub fn payload(&self) -> &[u8] { + &self.payload + } +} + +impl WakuStoreRespMessage { + pub fn payload(&self) -> &[u8] { + &self.payload + } } mod base64_serde { diff --git a/waku-bindings/src/general/pubsubtopic.rs b/waku-bindings/src/general/pubsubtopic.rs index c3adc56..de1ce17 100644 --- a/waku-bindings/src/general/pubsubtopic.rs +++ b/waku-bindings/src/general/pubsubtopic.rs @@ -1,4 +1,7 @@ -#[derive(Debug, Clone, PartialEq, Eq, Hash)] +use serde::{Deserialize, Serialize}; + +#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] pub struct PubsubTopic(String); impl PubsubTopic { diff --git a/waku-bindings/src/general/time.rs b/waku-bindings/src/general/time.rs new file mode 100644 index 0000000..2024b84 --- /dev/null +++ b/waku-bindings/src/general/time.rs @@ -0,0 +1,7 @@ +use std::time::{SystemTime, UNIX_EPOCH}; + +pub fn get_now_in_nanosecs() -> u64 { + let now = SystemTime::now(); + let since_epoch = now.duration_since(UNIX_EPOCH).expect("Time went backwards"); + since_epoch.as_secs() * 1_000_000_000 + since_epoch.subsec_nanos() as u64 +} diff --git a/waku-bindings/src/general/waku_decode.rs b/waku-bindings/src/general/waku_decode.rs new file mode 100644 index 0000000..892e37f --- /dev/null +++ b/waku-bindings/src/general/waku_decode.rs @@ -0,0 +1,26 @@ +use crate::general::Result; +use multiaddr::Multiaddr; +// Define the WakuDecode trait +pub trait WakuDecode: Sized { + fn decode(input: &str) -> Result; +} + +impl WakuDecode for String { + fn decode(input: &str) -> Result { + Ok(input.to_string()) + } +} + +pub fn decode(input: String) -> Result { + T::decode(input.as_str()) +} + +impl WakuDecode for Vec { + fn decode(input: &str) -> Result { + input + .split(',') + .map(|s| s.trim().parse::().map_err(|err| err.to_string())) + .collect::>>() // Collect results into a Vec + .map_err(|err| format!("could not parse Multiaddr: {}", err)) + } +} diff --git a/waku-bindings/src/lib.rs b/waku-bindings/src/lib.rs index dc14d4b..ca01ae9 100644 --- a/waku-bindings/src/lib.rs +++ b/waku-bindings/src/lib.rs @@ -2,11 +2,11 @@ //! //! Implementation on top of [`waku-bindings`](https://rfc.vac.dev/spec/36/) pub mod general; +mod macros; pub mod node; -pub mod utils; // Re-export the LibwakuResponse type to make it accessible outside this module -pub use utils::LibwakuResponse; +pub use general::libwaku_response::LibwakuResponse; // Required so functions inside libwaku can call RLN functions even if we // use it within the bindings functions @@ -15,9 +15,9 @@ pub use utils::LibwakuResponse; use rln; pub use node::{ - waku_create_content_topic, waku_new, Event, Initialized, Key, Multiaddr, PublicKey, RLNConfig, - Running, SecretKey, WakuMessageEvent, WakuNodeConfig, WakuNodeHandle, + waku_create_content_topic, waku_new, Initialized, Key, Multiaddr, PublicKey, RLNConfig, + Running, SecretKey, WakuEvent, WakuMessageEvent, WakuNodeConfig, WakuNodeHandle, }; pub use general::contenttopic::{Encoding, WakuContentTopic}; -pub use general::{MessageHash, Result, WakuMessage, WakuMessageVersion}; +pub use general::{messagehash::MessageHash, Result, WakuMessage, WakuMessageVersion}; diff --git a/waku-bindings/src/macros.rs b/waku-bindings/src/macros.rs new file mode 100644 index 0000000..4959638 --- /dev/null +++ b/waku-bindings/src/macros.rs @@ -0,0 +1,73 @@ +use crate::general::libwaku_response::LibwakuResponse; + +use std::{slice, str}; +use waku_sys::WakuCallBack; + +unsafe extern "C" fn trampoline( + ret_code: ::std::os::raw::c_int, + data: *const ::std::os::raw::c_char, + data_len: usize, + user_data: *mut ::std::os::raw::c_void, +) where + F: FnMut(LibwakuResponse), +{ + let closure = &mut *(user_data as *mut F); + + let response = if data.is_null() { + "" + } else { + str::from_utf8(slice::from_raw_parts(data as *mut u8, data_len)) + .expect("could not retrieve response") + }; + + let result = LibwakuResponse::try_from((ret_code as u32, response)) + .expect("invalid response obtained from libwaku"); + + closure(result); +} + +pub fn get_trampoline(_closure: &F) -> WakuCallBack +where + F: FnMut(LibwakuResponse), +{ + Some(trampoline::) +} + +#[macro_export] +macro_rules! handle_ffi_call { + // Case: With or without additional arguments + ($waku_fn:expr, $resp_hndlr:expr, $ctx:expr $(, $($arg:expr),*)?) => {{ + use $crate::macros::get_trampoline; + use std::sync::Arc; + use tokio::sync::Notify; + use libc::*; + + let mut result = LibwakuResponse::default(); + let notify = Arc::new(Notify::new()); + let notify_clone = notify.clone(); + + // Callback to update the result and notify the waiter + let result_cb = |r: LibwakuResponse| { + result = r; + notify_clone.notify_one(); + }; + + // Create trampoline and invoke the `waku_sys` function + let code = unsafe { + let mut closure = result_cb; + let cb = get_trampoline(&closure); + $waku_fn( + $ctx, // Pass the context + $($($arg),*,)? // Expand the variadic arguments if provided + cb, // Pass the callback trampoline + &mut closure as *mut _ as *mut c_void + ) + }; + + // Wait for the callback to notify us + notify.notified().await; + + // Handle the response + $resp_hndlr(code, result) + }}; +} diff --git a/waku-bindings/src/node/config.rs b/waku-bindings/src/node/config.rs index 8d26f3b..68ca58e 100644 --- a/waku-bindings/src/node/config.rs +++ b/waku-bindings/src/node/config.rs @@ -33,6 +33,10 @@ pub struct WakuNodeConfig { #[serde(skip_serializing_if = "Option::is_none")] pub max_message_size: Option, + /// Store protocol + #[serde(skip_serializing_if = "Option::is_none")] + pub storenode: Option<&'static str>, + /// RLN configuration #[serde(skip_serializing_if = "Option::is_none")] pub rln_relay: Option, diff --git a/waku-bindings/src/node/context.rs b/waku-bindings/src/node/context.rs index 5305a4a..87afae5 100644 --- a/waku-bindings/src/node/context.rs +++ b/waku-bindings/src/node/context.rs @@ -2,7 +2,8 @@ use std::ffi::c_void; use std::ptr::null_mut; use std::sync::{Arc, Mutex}; -use crate::utils::{get_trampoline, LibwakuResponse}; +use crate::general::libwaku_response::LibwakuResponse; +use crate::macros::get_trampoline; type LibwakuResponseClosure = dyn FnMut(LibwakuResponse) + Send + Sync; diff --git a/waku-bindings/src/node/events.rs b/waku-bindings/src/node/events.rs index 2ee759c..fea3e6b 100644 --- a/waku-bindings/src/node/events.rs +++ b/waku-bindings/src/node/events.rs @@ -2,7 +2,7 @@ //! //! Asynchronous events require a callback to be registered. //! An example of an asynchronous event that might be emitted is receiving a message. -//! When an event is emitted, this callback will be triggered receiving an [`Event`] +//! When an event is emitted, this callback will be triggered receiving an [`WakuEvent`] // crates use serde::{Deserialize, Serialize}; @@ -17,9 +17,16 @@ use crate::MessageHash; #[non_exhaustive] #[derive(Serialize, Deserialize, Debug)] #[serde(tag = "eventType", rename_all = "camelCase")] -pub enum Event { +pub enum WakuEvent { #[serde(rename = "message")] WakuMessage(WakuMessageEvent), + + #[serde(rename = "relay_topic_health_change")] + RelayTopicHealthChange(TopicHealthEvent), + + #[serde(rename = "connection_change")] + ConnectionChange(ConnectionChangeEvent), + Unrecognized(serde_json::Value), } @@ -35,14 +42,64 @@ pub struct WakuMessageEvent { pub waku_message: WakuMessage, } +/// Type of `event` field for a `topic health` event +#[derive(Serialize, Deserialize, Debug)] +#[serde(rename_all = "camelCase")] +pub struct TopicHealthEvent { + /// The pubsub topic on which the message was received + pub pubsub_topic: String, + /// The message hash + pub topic_health: String, +} + +/// Type of `event` field for a `connection change` event +#[derive(Serialize, Deserialize, Debug)] +#[serde(rename_all = "camelCase")] +pub struct ConnectionChangeEvent { + /// The pubsub topic on which the message was received + pub peer_id: String, + /// The message hash + pub peer_event: String, +} + #[cfg(test)] mod tests { - use crate::Event; + use crate::WakuEvent; + use crate::WakuEvent::{ConnectionChange, RelayTopicHealthChange}; #[test] fn deserialize_message_event() { - let s = "{\"eventType\":\"message\",\"messageHash\":\"0x26ff3d7fbc950ea2158ce62fd76fd745eee0323c9eac23d0713843b0f04ea27c\",\"pubsubTopic\":\"/waku/2/default-waku/proto\",\"wakuMessage\":{\"payload\":\"SGkgZnJvbSDwn6aAIQ==\",\"contentTopic\":\"/toychat/2/huilong/proto\",\"timestamp\":1665580926660}}"; - let evt: Event = serde_json::from_str(s).unwrap(); - assert!(matches!(evt, Event::WakuMessage(_))); + let s = "{\"eventType\":\"message\",\"messageHash\":[91, 70, 26, 8, 141, 232, 150, 200, 26, 206, 224, 175, 249, 74, 61, 140, 231, 126, 224, 160, 91, 80, 162, 65, 250, 171, 84, 149, 133, 110, 214, 101],\"pubsubTopic\":\"/waku/2/default-waku/proto\",\"wakuMessage\":{\"payload\":\"SGkgZnJvbSDwn6aAIQ==\",\"contentTopic\":\"/toychat/2/huilong/proto\",\"timestamp\":1665580926660}}"; + let evt: WakuEvent = serde_json::from_str(s).unwrap(); + assert!(matches!(evt, WakuEvent::WakuMessage(_))); + } + + #[test] + fn deserialize_topic_health_change_event() { + let s = "{\"eventType\":\"relay_topic_health_change\", \"pubsubTopic\":\"/waku/2/rs/16/1\",\"topicHealth\":\"MinimallyHealthy\"}"; + let evt: WakuEvent = serde_json::from_str(s).unwrap(); + match evt { + RelayTopicHealthChange(topic_health_event) => { + assert_eq!(topic_health_event.pubsub_topic, "/waku/2/rs/16/1"); + assert_eq!(topic_health_event.topic_health, "MinimallyHealthy"); + } + _ => panic!("Expected RelayTopicHealthChange event, but got {:?}", evt), + } + } + + #[test] + fn deserialize_connection_change_event() { + let s = "{\"eventType\":\"connection_change\", \"peerId\":\"16Uiu2HAmAR24Mbb6VuzoyUiGx42UenDkshENVDj4qnmmbabLvo31\",\"peerEvent\":\"Joined\"}"; + let evt: WakuEvent = serde_json::from_str(s).unwrap(); + match evt { + ConnectionChange(conn_change_event) => { + assert_eq!( + conn_change_event.peer_id, + "16Uiu2HAmAR24Mbb6VuzoyUiGx42UenDkshENVDj4qnmmbabLvo31" + ); + assert_eq!(conn_change_event.peer_event, "Joined"); + } + _ => panic!("Expected RelayTopicHealthChange event, but got {:?}", evt), + } } } diff --git a/waku-bindings/src/node/filter.rs b/waku-bindings/src/node/filter.rs index 9bf0208..51b8267 100644 --- a/waku-bindings/src/node/filter.rs +++ b/waku-bindings/src/node/filter.rs @@ -2,99 +2,58 @@ // std use std::ffi::CString; -// crates -use libc::*; // internal use crate::general::contenttopic::WakuContentTopic; +use crate::general::libwaku_response::{handle_no_response, LibwakuResponse}; use crate::general::pubsubtopic::PubsubTopic; use crate::general::Result; +use crate::handle_ffi_call; use crate::node::context::WakuNodeContext; -use crate::utils::{get_trampoline, handle_no_response, LibwakuResponse}; -pub fn waku_filter_subscribe( +pub async fn waku_filter_subscribe( ctx: &WakuNodeContext, pubsub_topic: &PubsubTopic, content_topics: Vec, ) -> Result<()> { + let pubsub_topic = CString::new(String::from(pubsub_topic)) + .expect("CString should build properly from pubsub topic"); let content_topics = WakuContentTopic::join_content_topics(content_topics); - - let pubsub_topic_ptr = CString::new(String::from(pubsub_topic)) - .expect("CString should build properly from pubsub topic") - .into_raw(); - let content_topics_ptr = CString::new(content_topics) - .expect("CString should build properly from content topic") - .into_raw(); - - let mut result: LibwakuResponse = Default::default(); - let result_cb = |r: LibwakuResponse| result = r; - let code = unsafe { - let mut closure = result_cb; - let cb = get_trampoline(&closure); - let out = waku_sys::waku_filter_subscribe( - ctx.get_ptr(), - pubsub_topic_ptr, - content_topics_ptr, - cb, - &mut closure as *mut _ as *mut c_void, - ); - - drop(CString::from_raw(pubsub_topic_ptr)); - drop(CString::from_raw(content_topics_ptr)); - - out - }; - - handle_no_response(code, result) + let content_topics = + CString::new(content_topics).expect("CString should build properly from content topic"); + + handle_ffi_call!( + waku_sys::waku_filter_subscribe, + handle_no_response, + ctx.get_ptr(), + pubsub_topic.as_ptr(), + content_topics.as_ptr() + ) } -pub fn waku_filter_unsubscribe( +pub async fn waku_filter_unsubscribe( ctx: &WakuNodeContext, pubsub_topic: &PubsubTopic, content_topics: Vec, // comma-separated list of content topics ) -> Result<()> { - let content_topics_topics = WakuContentTopic::join_content_topics(content_topics); - - let pubsub_topic_ptr = CString::new(String::from(pubsub_topic)) - .expect("CString should build properly from pubsub topic") - .into_raw(); - let content_topics_topics_ptr = CString::new(content_topics_topics) - .expect("CString should build properly from content topic") - .into_raw(); - - let mut result: LibwakuResponse = Default::default(); - let result_cb = |r: LibwakuResponse| result = r; - let code = unsafe { - let mut closure = result_cb; - let cb = get_trampoline(&closure); - let out = waku_sys::waku_filter_unsubscribe( - ctx.get_ptr(), - pubsub_topic_ptr, - content_topics_topics_ptr, - cb, - &mut closure as *mut _ as *mut c_void, - ); - - drop(CString::from_raw(pubsub_topic_ptr)); - drop(CString::from_raw(content_topics_topics_ptr)); - - out - }; - - handle_no_response(code, result) + let pubsub_topic = CString::new(String::from(pubsub_topic)) + .expect("CString should build properly from pubsub topic"); + let content_topics = WakuContentTopic::join_content_topics(content_topics); + let content_topics = + CString::new(content_topics).expect("CString should build properly from content topic"); + + handle_ffi_call!( + waku_sys::waku_filter_unsubscribe, + handle_no_response, + ctx.get_ptr(), + pubsub_topic.as_ptr(), + content_topics.as_ptr() + ) } -pub fn waku_filter_unsubscribe_all(ctx: &WakuNodeContext) -> Result<()> { - let mut result: LibwakuResponse = Default::default(); - let result_cb = |r: LibwakuResponse| result = r; - let code = unsafe { - let mut closure = result_cb; - let cb = get_trampoline(&closure); - waku_sys::waku_filter_unsubscribe_all( - ctx.get_ptr(), - cb, - &mut closure as *mut _ as *mut c_void, - ) - }; - - handle_no_response(code, result) +pub async fn waku_filter_unsubscribe_all(ctx: &WakuNodeContext) -> Result<()> { + handle_ffi_call!( + waku_sys::waku_filter_unsubscribe_all, + handle_no_response, + ctx.get_ptr() + ) } diff --git a/waku-bindings/src/node/lightpush.rs b/waku-bindings/src/node/lightpush.rs index 925c01c..24a5536 100644 --- a/waku-bindings/src/node/lightpush.rs +++ b/waku-bindings/src/node/lightpush.rs @@ -2,48 +2,33 @@ // std use std::ffi::CString; -// crates -use libc::*; // internal -use crate::general::{MessageHash, Result, WakuMessage}; +use crate::general::libwaku_response::{handle_response, LibwakuResponse}; +use crate::general::{messagehash::MessageHash, Result, WakuMessage}; +use crate::handle_ffi_call; use crate::node::context::WakuNodeContext; -use crate::utils::{get_trampoline, handle_response, LibwakuResponse}; use crate::general::pubsubtopic::PubsubTopic; -pub fn waku_lightpush_publish_message( +pub async fn waku_lightpush_publish_message( ctx: &WakuNodeContext, message: &WakuMessage, pubsub_topic: &PubsubTopic, ) -> Result { - let message_ptr = CString::new( + let message = CString::new( serde_json::to_string(&message) .expect("WakuMessages should always be able to success serializing"), ) - .expect("CString should build properly from the serialized waku message") - .into_raw(); - let pubsub_topic_ptr = CString::new(String::from(pubsub_topic)) - .expect("CString should build properly from pubsub topic") - .into_raw(); + .expect("CString should build properly from the serialized waku message"); - let mut result: LibwakuResponse = Default::default(); - let result_cb = |r: LibwakuResponse| result = r; - let code = unsafe { - let mut closure = result_cb; - let cb = get_trampoline(&closure); - let out = waku_sys::waku_lightpush_publish( - ctx.get_ptr(), - pubsub_topic_ptr, - message_ptr, - cb, - &mut closure as *mut _ as *mut c_void, - ); + let pubsub_topic = CString::new(String::from(pubsub_topic)) + .expect("CString should build properly from pubsub topic"); - drop(CString::from_raw(message_ptr)); - drop(CString::from_raw(pubsub_topic_ptr)); - - out - }; - - handle_response(code, result) + handle_ffi_call!( + waku_sys::waku_lightpush_publish, + handle_response, + ctx.get_ptr(), + pubsub_topic.as_ptr(), + message.as_ptr() + ) } diff --git a/waku-bindings/src/node/management.rs b/waku-bindings/src/node/management.rs index eb30998..cad28f4 100644 --- a/waku-bindings/src/node/management.rs +++ b/waku-bindings/src/node/management.rs @@ -5,41 +5,42 @@ use std::ffi::CString; // crates use libc::c_void; use multiaddr::Multiaddr; +use std::sync::Arc; +use tokio::sync::Notify; // internal use super::config::WakuNodeConfig; +use crate::general::libwaku_response::{handle_no_response, handle_response, LibwakuResponse}; use crate::general::Result; +use crate::handle_ffi_call; +use crate::macros::get_trampoline; use crate::node::context::WakuNodeContext; -use crate::utils::LibwakuResponse; -use crate::utils::WakuDecode; -use crate::utils::{get_trampoline, handle_json_response, handle_no_response, handle_response}; /// Instantiates a Waku node /// as per the [specification](https://rfc.vac.dev/spec/36/#extern-char-waku_newchar-jsonconfig) -pub fn waku_new(config: Option) -> Result { - unsafe { - waku_sys::waku_setup(); - } - +pub async fn waku_new(config: Option) -> Result { let config = config.unwrap_or_default(); - let config_ptr = CString::new( + let config = CString::new( serde_json::to_string(&config) .expect("Serialization from properly built NodeConfig should never fail"), ) - .expect("CString should build properly from the config") - .into_raw(); - - let mut result: LibwakuResponse = Default::default(); - let result_cb = |r: LibwakuResponse| result = r; + .expect("CString should build properly from the config"); + let config_ptr = config.as_ptr(); + + let notify = Arc::new(Notify::new()); + let notify_clone = notify.clone(); + let mut result = LibwakuResponse::default(); + let result_cb = |r: LibwakuResponse| { + result = r; + notify_clone.notify_one(); // Notify that the value has been updated + }; let obj_ptr = unsafe { let mut closure = result_cb; let cb = get_trampoline(&closure); - let out = waku_sys::waku_new(config_ptr, cb, &mut closure as *mut _ as *mut c_void); - - drop(CString::from_raw(config_ptr)); - - out + waku_sys::waku_new(config_ptr, cb, &mut closure as *mut _ as *mut c_void) }; + notify.notified().await; // Wait until a result is received + match result { LibwakuResponse::MissingCallback => panic!("callback is required"), LibwakuResponse::Failure(v) => Err(v), @@ -47,112 +48,73 @@ pub fn waku_new(config: Option) -> Result { } } -pub fn waku_destroy(ctx: &WakuNodeContext) -> Result<()> { - let mut result: LibwakuResponse = Default::default(); - let result_cb = |r: LibwakuResponse| result = r; - let code = unsafe { - let mut closure = result_cb; - let cb = get_trampoline(&closure); - waku_sys::waku_destroy(ctx.get_ptr(), cb, &mut closure as *mut _ as *mut c_void) - }; - - handle_no_response(code, result) +pub async fn waku_destroy(ctx: &WakuNodeContext) -> Result<()> { + handle_ffi_call!(waku_sys::waku_destroy, handle_no_response, ctx.get_ptr()) } /// Start a Waku node mounting all the protocols that were enabled during the Waku node instantiation. /// as per the [specification](https://rfc.vac.dev/spec/36/#extern-char-waku_start) -pub fn waku_start(ctx: &WakuNodeContext) -> Result<()> { - let mut result: LibwakuResponse = Default::default(); - let result_cb = |r: LibwakuResponse| result = r; - let code = unsafe { - let mut closure = result_cb; - let cb = get_trampoline(&closure); - waku_sys::waku_start(ctx.get_ptr(), cb, &mut closure as *mut _ as *mut c_void) - }; - - handle_no_response(code, result) +pub async fn waku_start(ctx: &WakuNodeContext) -> Result<()> { + handle_ffi_call!(waku_sys::waku_start, handle_no_response, ctx.get_ptr()) } /// Stops a Waku node /// as per the [specification](https://rfc.vac.dev/spec/36/#extern-char-waku_stop) -pub fn waku_stop(ctx: &WakuNodeContext) -> Result<()> { - let mut result: LibwakuResponse = Default::default(); - let result_cb = |r: LibwakuResponse| result = r; - let code = unsafe { - let mut closure = result_cb; - let cb = get_trampoline(&closure); - waku_sys::waku_stop(ctx.get_ptr(), cb, &mut closure as *mut _ as *mut c_void) - }; - - handle_no_response(code, result) +pub async fn waku_stop(ctx: &WakuNodeContext) -> Result<()> { + handle_ffi_call!(waku_sys::waku_stop, handle_no_response, ctx.get_ptr()) } /// nwaku version -#[allow(clippy::not_unsafe_ptr_arg_deref)] -pub fn waku_version(ctx: &WakuNodeContext) -> Result { - let mut result: LibwakuResponse = Default::default(); - let result_cb = |r: LibwakuResponse| result = r; - let code = unsafe { - let mut closure = result_cb; - let cb = get_trampoline(&closure); - waku_sys::waku_version(ctx.get_ptr(), cb, &mut closure as *mut _ as *mut c_void) - }; - - handle_response(code, result) -} - -// Implement WakuDecode for Vec -impl WakuDecode for Vec { - fn decode(input: &str) -> Result { - input - .split(',') - .map(|s| s.trim().parse::().map_err(|err| err.to_string())) - .collect::>>() // Collect results into a Vec - .map_err(|err| format!("could not parse Multiaddr: {}", err)) - } +pub async fn waku_version(ctx: &WakuNodeContext) -> Result { + handle_ffi_call!(waku_sys::waku_version, handle_response, ctx.get_ptr()) } /// Get the multiaddresses the Waku node is listening to /// as per [specification](https://rfc.vac.dev/spec/36/#extern-char-waku_listen_addresses) -pub fn waku_listen_addresses(ctx: &WakuNodeContext) -> Result> { - let mut result: LibwakuResponse = Default::default(); - let result_cb = |r: LibwakuResponse| result = r; - let code = unsafe { - let mut closure = result_cb; - let cb = get_trampoline(&closure); - waku_sys::waku_listen_addresses(ctx.get_ptr(), cb, &mut closure as *mut _ as *mut c_void) - }; - - handle_json_response(code, result) +pub async fn waku_listen_addresses(ctx: &WakuNodeContext) -> Result> { + handle_ffi_call!( + waku_sys::waku_listen_addresses, + handle_response, + ctx.get_ptr() + ) } #[cfg(test)] mod test { use super::waku_new; - use crate::node::management::{waku_listen_addresses, waku_start, waku_stop, waku_version}; + use crate::node::management::{ + waku_destroy, waku_listen_addresses, waku_start, waku_stop, waku_version, + }; use serial_test::serial; - #[test] + #[tokio::test] #[serial] - fn waku_flow() { - let node = waku_new(None).unwrap(); + async fn waku_flow() { + let node = waku_new(None).await.unwrap(); - waku_start(&node).unwrap(); + waku_start(&node).await.unwrap(); // test addresses - let addresses = waku_listen_addresses(&node).unwrap(); + let addresses = waku_listen_addresses(&node).await.unwrap(); dbg!(&addresses); assert!(!addresses.is_empty()); - waku_stop(&node).unwrap(); + waku_stop(&node).await.unwrap(); + waku_destroy(&node).await.unwrap(); } - #[test] + #[tokio::test] #[serial] - fn nwaku_version() { - let node = waku_new(None).unwrap(); - let version = waku_version(&node).expect("should return the version"); + async fn nwaku_version() { + let node = waku_new(None).await.unwrap(); + + let version = waku_version(&node) + .await + .expect("should return the version"); + print!("Current version: {}", version); + assert!(!version.is_empty()); + waku_destroy(&node).await.unwrap(); } } diff --git a/waku-bindings/src/node/mod.rs b/waku-bindings/src/node/mod.rs index 72cda20..e24ada9 100644 --- a/waku-bindings/src/node/mod.rs +++ b/waku-bindings/src/node/mod.rs @@ -8,6 +8,7 @@ mod lightpush; mod management; mod peers; mod relay; +mod store; // std pub use aes_gcm::Key; @@ -15,20 +16,19 @@ pub use multiaddr::Multiaddr; pub use secp256k1::{PublicKey, SecretKey}; use std::marker::PhantomData; use std::time::Duration; +use store::{StoreQueryRequest, StoreWakuMessageResponse}; // internal use crate::general::contenttopic::{Encoding, WakuContentTopic}; +use crate::general::libwaku_response::LibwakuResponse; pub use crate::general::pubsubtopic::PubsubTopic; -use crate::general::{MessageHash, Result, WakuMessage}; -use crate::utils::LibwakuResponse; +use crate::general::{messagehash::MessageHash, Result, WakuMessage}; use crate::node::context::WakuNodeContext; pub use config::RLNConfig; pub use config::WakuNodeConfig; -pub use events::{Event, WakuMessageEvent}; +pub use events::{WakuEvent, WakuMessageEvent}; pub use relay::waku_create_content_topic; -use std::time::SystemTime; - // Define state marker types pub struct Initialized; pub struct Running; @@ -41,34 +41,41 @@ pub struct WakuNodeHandle { /// Spawn a new Waku node with the given configuration (default configuration if `None` provided) /// as per the [specification](https://rfc.vac.dev/spec/36/#extern-char-waku_newchar-jsonconfig) -pub fn waku_new(config: Option) -> Result> { +pub async fn waku_new(config: Option) -> Result> { Ok(WakuNodeHandle { - ctx: management::waku_new(config)?, + ctx: management::waku_new(config).await?, _state: PhantomData, }) } impl WakuNodeHandle { /// Get the nwaku version - pub fn version(&self) -> Result { - management::waku_version(&self.ctx) + pub async fn version(&self) -> Result { + management::waku_version(&self.ctx).await } - pub fn waku_destroy(self) -> Result<()> { - let res = management::waku_destroy(&self.ctx); + pub async fn waku_destroy(self) -> Result<()> { + let res = management::waku_destroy(&self.ctx).await; self.ctx.reset_ptr(); res } + + /// Subscribe to WakuRelay to receive messages matching a content filter. + pub async fn relay_subscribe(&self, pubsub_topic: &PubsubTopic) -> Result<()> { + relay::waku_relay_subscribe(&self.ctx, pubsub_topic).await + } } impl WakuNodeHandle { /// Start a Waku node mounting all the protocols that were enabled during the Waku node instantiation. /// as per the [specification](https://rfc.vac.dev/spec/36/#extern-char-waku_start) - pub fn start(self) -> Result> { - management::waku_start(&self.ctx).map(|_| WakuNodeHandle { - ctx: self.ctx, - _state: PhantomData, - }) + pub async fn start(self) -> Result> { + management::waku_start(&self.ctx) + .await + .map(|_| WakuNodeHandle { + ctx: self.ctx, + _state: PhantomData, + }) } pub fn set_event_callback( @@ -82,17 +89,19 @@ impl WakuNodeHandle { impl WakuNodeHandle { /// Stops a Waku node /// as per the [specification](https://rfc.vac.dev/spec/36/#extern-char-waku_stop) - pub fn stop(self) -> Result> { - management::waku_stop(&self.ctx).map(|_| WakuNodeHandle { - ctx: self.ctx, - _state: PhantomData, - }) + pub async fn stop(self) -> Result> { + management::waku_stop(&self.ctx) + .await + .map(|_| WakuNodeHandle { + ctx: self.ctx, + _state: PhantomData, + }) } /// Get the multiaddresses the Waku node is listening to /// as per [specification](https://rfc.vac.dev/spec/36/#extern-char-waku_listen_addresses) - pub fn listen_addresses(&self) -> Result> { - management::waku_listen_addresses(&self.ctx) + pub async fn listen_addresses(&self) -> Result> { + management::waku_listen_addresses(&self.ctx).await } /// Dial peer using a multiaddress @@ -100,11 +109,11 @@ impl WakuNodeHandle { /// If the function execution takes longer than `timeout` value, the execution will be canceled and an error returned. /// Use 0 for no timeout /// As per the [specification](https://rfc.vac.dev/spec/36/#extern-char-waku_connect_peerchar-address-int-timeoutms) - pub fn connect(&self, address: &Multiaddr, timeout: Option) -> Result<()> { - peers::waku_connect(&self.ctx, address, timeout) + pub async fn connect(&self, address: &Multiaddr, timeout: Option) -> Result<()> { + peers::waku_connect(&self.ctx, address, timeout).await } - pub fn relay_publish_txt( + pub async fn relay_publish_txt( &self, pubsub_topic: &PubsubTopic, msg_txt: &String, @@ -112,70 +121,93 @@ impl WakuNodeHandle { timeout: Option, ) -> Result { let content_topic = WakuContentTopic::new("waku", "2", content_topic_name, Encoding::Proto); - let message = WakuMessage::new( - msg_txt, - content_topic, - 0, - SystemTime::now() - .duration_since(SystemTime::UNIX_EPOCH) - .unwrap() - .as_millis() - .try_into() - .unwrap(), - Vec::new(), - false, - ); - - relay::waku_relay_publish_message(&self.ctx, &message, pubsub_topic, timeout) + let message = WakuMessage::new(msg_txt, content_topic, 0, Vec::new(), false); + relay::waku_relay_publish_message(&self.ctx, &message, pubsub_topic, timeout).await } /// Publish a message using Waku Relay. /// As per the [specification](https://rfc.vac.dev/spec/36/#extern-char-waku_relay_publishchar-messagejson-char-pubsubtopic-int-timeoutms) /// The pubsub_topic parameter is optional and if not specified it will be derived from the contentTopic. - pub fn relay_publish_message( + pub async fn relay_publish_message( &self, message: &WakuMessage, pubsub_topic: &PubsubTopic, timeout: Option, ) -> Result { - relay::waku_relay_publish_message(&self.ctx, message, pubsub_topic, timeout) - } - - /// Subscribe to WakuRelay to receive messages matching a content filter. - pub fn relay_subscribe(&self, pubsub_topic: &PubsubTopic) -> Result<()> { - relay::waku_relay_subscribe(&self.ctx, pubsub_topic) + relay::waku_relay_publish_message(&self.ctx, message, pubsub_topic, timeout).await } /// Closes the pubsub subscription to stop receiving messages matching a content filter. No more messages will be received from this pubsub topic - pub fn relay_unsubscribe(&self, pubsub_topic: &PubsubTopic) -> Result<()> { - relay::waku_relay_unsubscribe(&self.ctx, pubsub_topic) + pub async fn relay_unsubscribe(&self, pubsub_topic: &PubsubTopic) -> Result<()> { + relay::waku_relay_unsubscribe(&self.ctx, pubsub_topic).await } - pub fn filter_subscribe( + pub async fn filter_subscribe( &self, pubsub_topic: &PubsubTopic, content_topics: Vec, ) -> Result<()> { - filter::waku_filter_subscribe(&self.ctx, pubsub_topic, content_topics) + filter::waku_filter_subscribe(&self.ctx, pubsub_topic, content_topics).await } - pub fn filter_unsubscribe( + pub async fn filter_unsubscribe( &self, pubsub_topic: &PubsubTopic, content_topics: Vec, ) -> Result<()> { - filter::waku_filter_unsubscribe(&self.ctx, pubsub_topic, content_topics) + filter::waku_filter_unsubscribe(&self.ctx, pubsub_topic, content_topics).await } - pub fn filter_unsubscribe_all(&self) -> Result<()> { - filter::waku_filter_unsubscribe_all(&self.ctx) + pub async fn filter_unsubscribe_all(&self) -> Result<()> { + filter::waku_filter_unsubscribe_all(&self.ctx).await } - pub fn lightpush_publish_message( + pub async fn lightpush_publish_message( &self, message: &WakuMessage, pubsub_topic: &PubsubTopic, ) -> Result { - lightpush::waku_lightpush_publish_message(&self.ctx, message, pubsub_topic) + lightpush::waku_lightpush_publish_message(&self.ctx, message, pubsub_topic).await + } + + #[allow(clippy::too_many_arguments)] + pub async fn store_query( + &self, + pubsub_topic: Option, + content_topics: Vec, + peer_addr: &str, + include_data: bool, // is true, resp contains payload, etc. Only msg_hashes otherwise + time_start: Option, // unix time nanoseconds + time_end: Option, // unix time nanoseconds + timeout_millis: Option, + ) -> Result> { + let mut cursor: Option = None; + + let mut messages: Vec = Vec::new(); + + loop { + let query = StoreQueryRequest::new() + .with_pubsub_topic(pubsub_topic.clone()) + .with_content_topics(content_topics.clone()) + .with_include_data(include_data) + .with_time_start(time_start) + .with_time_end(time_end) + .with_pagination_cursor(cursor) + .with_pagination_forward(true); + + let response = + store::waku_store_query(&self.ctx, query, peer_addr, timeout_millis).await?; + + messages.extend(response.messages); + + if response.pagination_cursor.is_none() { + break; + } + cursor = response.pagination_cursor; + } + + messages.reverse(); + + Ok(messages) } } diff --git a/waku-bindings/src/node/peers.rs b/waku-bindings/src/node/peers.rs index a5bf0ef..7b7d875 100644 --- a/waku-bindings/src/node/peers.rs +++ b/waku-bindings/src/node/peers.rs @@ -4,47 +4,33 @@ use std::ffi::CString; use std::time::Duration; // crates -use libc::*; use multiaddr::Multiaddr; // internal +use crate::general::libwaku_response::{handle_no_response, LibwakuResponse}; use crate::general::Result; +use crate::handle_ffi_call; use crate::node::context::WakuNodeContext; -use crate::utils::LibwakuResponse; -use crate::utils::{get_trampoline, handle_no_response}; /// Dial peer using a multiaddress /// If `timeout` as milliseconds doesn't fit into a `i32` it is clamped to [`i32::MAX`] /// If the function execution takes longer than `timeout` value, the execution will be canceled and an error returned. /// Use 0 for no timeout /// As per the [specification](https://rfc.vac.dev/spec/36/#extern-char-waku_connect_peerchar-address-int-timeoutms) -pub fn waku_connect( +pub async fn waku_connect( ctx: &WakuNodeContext, address: &Multiaddr, timeout: Option, ) -> Result<()> { - let address_ptr = CString::new(address.to_string()) - .expect("CString should build properly from multiaddress") - .into_raw(); + let address = + CString::new(address.to_string()).expect("CString should build properly from multiaddress"); - let mut result: LibwakuResponse = Default::default(); - let result_cb = |r: LibwakuResponse| result = r; - let code = unsafe { - let mut closure = result_cb; - let cb = get_trampoline(&closure); - let out = waku_sys::waku_connect( - ctx.get_ptr(), - address_ptr, - timeout - .map(|duration| duration.as_millis().try_into().unwrap_or(u32::MAX)) - .unwrap_or(0), - cb, - &mut closure as *mut _ as *mut c_void, - ); - - drop(CString::from_raw(address_ptr)); - - out - }; - - handle_no_response(code, result) + handle_ffi_call!( + waku_sys::waku_connect, + handle_no_response, + ctx.get_ptr(), + address.as_ptr(), + timeout + .map(|duration| duration.as_millis().try_into().unwrap_or(u32::MAX)) + .unwrap_or(0) + ) } diff --git a/waku-bindings/src/node/relay.rs b/waku-bindings/src/node/relay.rs index d945a61..c271357 100644 --- a/waku-bindings/src/node/relay.rs +++ b/waku-bindings/src/node/relay.rs @@ -3,154 +3,99 @@ // std use std::ffi::CString; use std::time::Duration; -// crates -use libc::*; // internal use crate::general::contenttopic::{Encoding, WakuContentTopic}; +use crate::general::libwaku_response::{handle_no_response, handle_response, LibwakuResponse}; use crate::general::pubsubtopic::PubsubTopic; -use crate::general::{MessageHash, Result, WakuMessage}; +use crate::general::{messagehash::MessageHash, Result, WakuMessage}; +use crate::handle_ffi_call; use crate::node::context::WakuNodeContext; -use crate::utils::{get_trampoline, handle_no_response, handle_response, LibwakuResponse}; /// Create a content topic according to [RFC 23](https://rfc.vac.dev/spec/23/) /// As per the [specification](https://rfc.vac.dev/spec/36/#extern-char-waku_content_topicchar-applicationname-unsigned-int-applicationversion-char-contenttopicname-char-encoding) #[allow(clippy::not_unsafe_ptr_arg_deref)] -pub fn waku_create_content_topic( +pub async fn waku_create_content_topic( ctx: &WakuNodeContext, application_name: &str, application_version: u32, content_topic_name: &str, encoding: Encoding, -) -> WakuContentTopic { - let application_name_ptr = CString::new(application_name) - .expect("Application name should always transform to CString") - .into_raw(); - let content_topic_name_ptr = CString::new(content_topic_name) - .expect("Content topic should always transform to CString") - .into_raw(); - let encoding_ptr = CString::new(encoding.to_string()) - .expect("Encoding should always transform to CString") - .into_raw(); - - let mut result: LibwakuResponse = Default::default(); - let result_cb = |r: LibwakuResponse| result = r; - let code = unsafe { - let mut closure = result_cb; - let cb = get_trampoline(&closure); - let out = waku_sys::waku_content_topic( - ctx.get_ptr(), - application_name_ptr, - application_version, - content_topic_name_ptr, - encoding_ptr, - cb, - &mut closure as *mut _ as *mut c_void, - ); - - drop(CString::from_raw(application_name_ptr)); - drop(CString::from_raw(content_topic_name_ptr)); - drop(CString::from_raw(encoding_ptr)); - - out - }; - - handle_response(code, result).expect("&str from result should always be extracted") +) -> Result { + let application_name = CString::new(application_name) + .expect("Application name should always transform to CString"); + let content_topic_name = + CString::new(content_topic_name).expect("Content topic should always transform to CString"); + let encoding = + CString::new(encoding.to_string()).expect("Encoding should always transform to CString"); + + handle_ffi_call!( + waku_sys::waku_content_topic, + handle_response, + ctx.get_ptr(), + application_name.as_ptr(), + application_version, + content_topic_name.as_ptr(), + encoding.as_ptr() + ) } /// Publish a message using Waku Relay /// As per the [specification](https://rfc.vac.dev/spec/36/#extern-char-waku_relay_publishchar-messagejson-char-pubsubtopic-int-timeoutms) -pub fn waku_relay_publish_message( +pub async fn waku_relay_publish_message( ctx: &WakuNodeContext, message: &WakuMessage, pubsub_topic: &PubsubTopic, timeout: Option, ) -> Result { - let message_ptr = CString::new( + let message = CString::new( serde_json::to_string(&message) .expect("WakuMessages should always be able to success serializing"), ) - .expect("CString should build properly from the serialized waku message") - .into_raw(); - let pubsub_topic_ptr = CString::new(String::from(pubsub_topic)) - .expect("CString should build properly from pubsub topic") - .into_raw(); - - let mut result: LibwakuResponse = Default::default(); - let result_cb = |r: LibwakuResponse| result = r; - let code = unsafe { - let mut closure = result_cb; - let cb = get_trampoline(&closure); - let out = waku_sys::waku_relay_publish( - ctx.get_ptr(), - pubsub_topic_ptr, - message_ptr, - timeout - .map(|duration| { - duration - .as_millis() - .try_into() - .expect("Duration as milliseconds should fit in a u32") - }) - .unwrap_or(0), - cb, - &mut closure as *mut _ as *mut c_void, - ); - - drop(CString::from_raw(message_ptr)); - drop(CString::from_raw(pubsub_topic_ptr)); - - out - }; - - handle_response(code, result) + .expect("CString should build properly from the serialized waku message"); + + let pubsub_topic = CString::new(String::from(pubsub_topic)) + .expect("CString should build properly from pubsub topic"); + + handle_ffi_call!( + waku_sys::waku_relay_publish, + handle_response, + ctx.get_ptr(), + pubsub_topic.as_ptr(), + message.as_ptr(), + timeout + .map(|duration| { + duration + .as_millis() + .try_into() + .expect("Duration as milliseconds should fit in a u32") + }) + .unwrap_or(0) + ) } -pub fn waku_relay_subscribe(ctx: &WakuNodeContext, pubsub_topic: &PubsubTopic) -> Result<()> { - let pubsub_topic_ptr = CString::new(String::from(pubsub_topic)) - .expect("CString should build properly from pubsub topic") - .into_raw(); - - let mut result: LibwakuResponse = Default::default(); - let result_cb = |r: LibwakuResponse| result = r; - let code = unsafe { - let mut closure = result_cb; - let cb = get_trampoline(&closure); - let out = waku_sys::waku_relay_subscribe( - ctx.get_ptr(), - pubsub_topic_ptr, - cb, - &mut closure as *mut _ as *mut c_void, - ); +pub async fn waku_relay_subscribe(ctx: &WakuNodeContext, pubsub_topic: &PubsubTopic) -> Result<()> { + let pubsub_topic = CString::new(String::from(pubsub_topic)) + .expect("CString should build properly from pubsub topic"); - drop(CString::from_raw(pubsub_topic_ptr)); - - out - }; - - handle_no_response(code, result) + handle_ffi_call!( + waku_sys::waku_relay_subscribe, + handle_no_response, + ctx.get_ptr(), + pubsub_topic.as_ptr() + ) } -pub fn waku_relay_unsubscribe(ctx: &WakuNodeContext, pubsub_topic: &PubsubTopic) -> Result<()> { - let pubsub_topic_ptr = CString::new(String::from(pubsub_topic)) - .expect("CString should build properly from pubsub topic") - .into_raw(); - - let mut result: LibwakuResponse = Default::default(); - let result_cb = |r: LibwakuResponse| result = r; - let code = unsafe { - let mut closure = result_cb; - let cb = get_trampoline(&closure); - let out = waku_sys::waku_relay_subscribe( - ctx.get_ptr(), - pubsub_topic_ptr, - cb, - &mut closure as *mut _ as *mut c_void, - ); - - drop(CString::from_raw(pubsub_topic_ptr)); - - out - }; - - handle_no_response(code, result) +pub async fn waku_relay_unsubscribe( + ctx: &WakuNodeContext, + pubsub_topic: &PubsubTopic, +) -> Result<()> { + let pubsub_topic = CString::new(String::from(pubsub_topic)) + .expect("CString should build properly from pubsub topic"); + + handle_ffi_call!( + waku_sys::waku_relay_unsubscribe, + handle_no_response, + ctx.get_ptr(), + pubsub_topic.as_ptr() + ) } diff --git a/waku-bindings/src/node/store.rs b/waku-bindings/src/node/store.rs new file mode 100644 index 0000000..8fe36cb --- /dev/null +++ b/waku-bindings/src/node/store.rs @@ -0,0 +1,172 @@ +//! Waku store protocol related methods + +// std +use std::ffi::CString; +use uuid::Uuid; +// crates +use tokio::time::Duration; +// internal +use crate::general::libwaku_response::{handle_response, LibwakuResponse}; +use crate::general::time::get_now_in_nanosecs; +use crate::general::waku_decode::WakuDecode; +use crate::general::{ + contenttopic::WakuContentTopic, messagehash::MessageHash, pubsubtopic::PubsubTopic, Result, + WakuStoreRespMessage, +}; +use crate::handle_ffi_call; +use crate::node::context::WakuNodeContext; +use multiaddr::Multiaddr; +use serde::{Deserialize, Serialize}; + +#[derive(Clone, Serialize, Deserialize, Debug)] +#[serde(rename_all = "camelCase")] +pub struct PagingOptions { + pub page_size: usize, + pub cursor: Option, + pub forward: bool, +} + +/// Criteria used to retrieve historical messages +#[derive(Clone, Serialize, Debug)] +pub struct StoreQueryRequest { + /// if true, the store-response will include the full message content. If false, + /// the store-response will only include a list of message hashes. + request_id: String, + include_data: bool, + #[serde(skip_serializing_if = "Option::is_none")] + pubsub_topic: Option, + content_topics: Vec, + #[serde(skip_serializing_if = "Option::is_none")] + time_start: Option, + #[serde(skip_serializing_if = "Option::is_none")] + time_end: Option, + #[serde(skip_serializing_if = "Option::is_none")] + message_hashes: Option>, + #[serde(skip_serializing_if = "Option::is_none")] + pagination_cursor: Option, // Message hash (key) from where to start query (exclusive) + pagination_forward: bool, + #[serde(skip_serializing_if = "Option::is_none")] + pagination_limit: Option, +} + +impl StoreQueryRequest { + pub fn new() -> Self { + StoreQueryRequest { + request_id: Uuid::new_v4().to_string(), + include_data: true, + pubsub_topic: None, + content_topics: Vec::new(), + time_start: Some(get_now_in_nanosecs()), + time_end: Some(get_now_in_nanosecs()), + message_hashes: None, + pagination_cursor: None, + pagination_forward: true, + pagination_limit: Some(25), + } + } + + pub fn with_include_data(mut self, include_data: bool) -> Self { + self.include_data = include_data; + self + } + + pub fn with_pubsub_topic(mut self, pubsub_topic: Option) -> Self { + self.pubsub_topic = pubsub_topic; + self + } + + pub fn with_content_topics(mut self, content_topics: Vec) -> Self { + self.content_topics = content_topics; + self + } + + pub fn with_time_start(mut self, time_start: Option) -> Self { + self.time_start = time_start; + self + } + + pub fn with_time_end(mut self, time_end: Option) -> Self { + self.time_end = time_end; + self + } + + #[allow(dead_code)] + pub fn with_message_hashes(mut self, message_hashes: Vec) -> Self { + self.message_hashes = Some(message_hashes); + self + } + + pub fn with_pagination_cursor(mut self, pagination_cursor: Option) -> Self { + self.pagination_cursor = pagination_cursor; + self + } + + pub fn with_pagination_forward(mut self, pagination_forward: bool) -> Self { + self.pagination_forward = pagination_forward; + self + } +} + +#[derive(Clone, Deserialize, Debug)] +#[serde(rename_all = "camelCase")] +pub struct StoreWakuMessageResponse { + pub message_hash: MessageHash, + pub message: Option, // None if include_data == false + pub pubsub_topic: String, +} + +#[derive(Clone, Deserialize, Debug)] +#[serde(rename_all = "camelCase")] +pub struct StoreResponse { + #[allow(unused)] + pub request_id: String, + + #[serde(skip_serializing_if = "Option::is_none")] + #[allow(unused)] + pub status_code: u32, + + #[allow(unused)] + pub status_desc: String, + + /// Array of retrieved historical messages in [`WakuMessage`] format + // #[serde(default)] + pub messages: Vec, + /// Paging information in [`PagingOptions`] format from which to resume further historical queries + #[serde(skip_serializing_if = "Option::is_none")] + pub pagination_cursor: Option, +} + +// Implement WakuDecode for Vec +impl WakuDecode for StoreResponse { + fn decode(input: &str) -> Result { + Ok(serde_json::from_str(input).expect("could not parse store resp")) + } +} + +pub async fn waku_store_query( + ctx: &WakuNodeContext, + query: StoreQueryRequest, + peer_addr: &str, + timeout_millis: Option, +) -> Result { + let json_query = CString::new( + serde_json::to_string(&query).expect("StoreQuery should always be able to be serialized"), + ) + .expect("CString should build properly from the serialized filter subscription"); + + peer_addr + .parse::() + .expect("correct multiaddress in store query"); + let peer_addr = CString::new(peer_addr).expect("peer_addr CString should be created"); + + let timeout_millis = timeout_millis.unwrap_or(Duration::from_secs(10)); + + handle_ffi_call!( + waku_sys::waku_store_query, + handle_response, + ctx.get_ptr(), + json_query.as_ptr(), + peer_addr.as_ptr(), + timeout_millis.as_millis() as i32 + ) +} diff --git a/waku-bindings/tests/node.rs b/waku-bindings/tests/node.rs index d588928..8dec139 100644 --- a/waku-bindings/tests/node.rs +++ b/waku-bindings/tests/node.rs @@ -4,13 +4,13 @@ use secp256k1::SecretKey; use serial_test::serial; use std::str::FromStr; use std::sync::{Arc, Mutex}; -use std::time::{Duration, SystemTime}; +use std::time::Duration; use std::{collections::HashSet, str::from_utf8}; use tokio::time; use tokio::time::sleep; use waku_bindings::node::PubsubTopic; use waku_bindings::{ - waku_new, Encoding, Event, Initialized, MessageHash, WakuContentTopic, WakuMessage, + waku_new, Encoding, Initialized, MessageHash, WakuContentTopic, WakuEvent, WakuMessage, WakuNodeConfig, WakuNodeHandle, }; use waku_bindings::{LibwakuResponse, Running}; @@ -18,15 +18,13 @@ const ECHO_TIMEOUT: u64 = 1000; const ECHO_MESSAGE: &str = "Hi from 🦀!"; const TEST_PUBSUBTOPIC: &str = "test"; -fn try_publish_relay_messages( +async fn try_publish_relay_messages( node: &WakuNodeHandle, msg: &WakuMessage, ) -> Result, String> { - Ok(HashSet::from([node.relay_publish_message( - msg, - &PubsubTopic::new(TEST_PUBSUBTOPIC), - None, - )?])) + Ok(HashSet::from([node + .relay_publish_message(msg, &PubsubTopic::new(TEST_PUBSUBTOPIC), None) + .await?])) } async fn test_echo_messages( @@ -45,16 +43,22 @@ async fn test_echo_messages( let rx_waku_message_cloned = rx_waku_message.clone(); let closure = move |response| { if let LibwakuResponse::Success(v) = response { - let event: Event = - serde_json::from_str(v.unwrap().as_str()).expect("Parsing event to succeed"); + let event: WakuEvent = serde_json::from_str(v.unwrap().as_str()) + .expect("Parsing event to succeed test_echo_messages"); match event { - Event::WakuMessage(evt) => { + WakuEvent::WakuMessage(evt) => { if let Ok(mut msg_lock) = rx_waku_message_cloned.lock() { *msg_lock = evt.waku_message; } } - Event::Unrecognized(err) => panic!("Unrecognized waku event: {:?}", err), + WakuEvent::RelayTopicHealthChange(_evt) => { + // dbg!("Relay topic change evt", evt); + } + WakuEvent::ConnectionChange(_evt) => { + // dbg!("Conn change evt", evt); + } + WakuEvent::Unrecognized(err) => panic!("Unrecognized waku event: {:?}", err), _ => panic!("event case not expected"), }; } @@ -66,21 +70,23 @@ async fn test_echo_messages( .set_event_callback(closure) .expect("set event call back working"); // Set the event callback with the closure - let node1 = node1.start()?; - let node2 = node2.start()?; + let node1 = node1.start().await?; + let node2 = node2.start().await?; node1 .relay_subscribe(&PubsubTopic::new(TEST_PUBSUBTOPIC)) + .await .unwrap(); node2 .relay_subscribe(&PubsubTopic::new(TEST_PUBSUBTOPIC)) + .await .unwrap(); - sleep(Duration::from_secs(3)).await; + sleep(Duration::from_secs(5)).await; // Interconnect nodes // Replace all matches with 127.0.0.1 to avoid issue with NAT or firewall. - let addresses1 = node1.listen_addresses().unwrap(); + let addresses1 = node1.listen_addresses().await.unwrap(); let addresses1 = &addresses1[0].to_string(); let re = Regex::new(r"\b(?:\d{1,3}\.){3}\d{1,3}\b").unwrap(); @@ -89,26 +95,16 @@ async fn test_echo_messages( let addresses1 = addresses1.parse::().expect("parse multiaddress"); println!("Connecting node1 to node2: {}", addresses1); - node2.connect(&addresses1, None).unwrap(); + node2.connect(&addresses1, None).await.unwrap(); // Wait for mesh to form sleep(Duration::from_secs(3)).await; dbg!("Before publish"); - let message = WakuMessage::new( - content, - content_topic, - 1, - SystemTime::now() - .duration_since(SystemTime::UNIX_EPOCH) - .unwrap() - .as_millis() - .try_into() - .unwrap(), - Vec::new(), - false, - ); - let _ids = try_publish_relay_messages(&node1, &message).expect("send relay messages"); + let message = WakuMessage::new(content, content_topic, 1, Vec::new(), false); + let _ids = try_publish_relay_messages(&node1, &message) + .await + .expect("send relay messages"); // Wait for the msg to arrive let rx_waku_message_cloned = rx_waku_message.clone(); @@ -118,8 +114,8 @@ async fn test_echo_messages( let payload = msg.payload.to_vec(); let payload_str = from_utf8(&payload).expect("should be valid message"); if payload_str == ECHO_MESSAGE { - node1.stop()?; - node2.stop()?; + node1.stop().await?; + node2.stop().await?; return Ok(()); } } else { @@ -127,11 +123,11 @@ async fn test_echo_messages( } } - let node1 = node1.stop()?; - let node2 = node2.stop()?; + let node1 = node1.stop().await?; + let node2 = node2.stop().await?; - node1.waku_destroy()?; - node2.waku_destroy()?; + node1.waku_destroy().await?; + node2.waku_destroy().await?; return Err("Unexpected test ending".to_string()); } @@ -143,11 +139,13 @@ async fn default_echo() -> Result<(), String> { let node1 = waku_new(Some(WakuNodeConfig { tcp_port: Some(60010), ..Default::default() - }))?; + })) + .await?; let node2 = waku_new(Some(WakuNodeConfig { tcp_port: Some(60020), ..Default::default() - }))?; + })) + .await?; let content_topic = WakuContentTopic::new("toychat", "2", "huilong", Encoding::Proto); @@ -165,9 +163,9 @@ async fn default_echo() -> Result<(), String> { Ok(()) } -#[test] +#[tokio::test] #[serial] -fn node_restart() { +async fn node_restart() { let config = WakuNodeConfig { node_key: Some( SecretKey::from_str("05f381866cc21f6c1e2e80e07fa732008e36d942dce3206ad6dcd6793c98d609") @@ -177,9 +175,14 @@ fn node_restart() { }; for _ in 0..3 { - let node = waku_new(config.clone().into()).expect("default config should be valid"); - let node = node.start().expect("node should start with valid config"); - let node = node.stop().expect("node should stop"); - node.waku_destroy().expect("free resources"); + let node = waku_new(config.clone().into()) + .await + .expect("default config should be valid"); + let node = node + .start() + .await + .expect("node should start with valid config"); + let node = node.stop().await.expect("node should stop"); + node.waku_destroy().await.expect("free resources"); } } diff --git a/waku-sys/build.rs b/waku-sys/build.rs index b41bba1..2183e60 100644 --- a/waku-sys/build.rs +++ b/waku-sys/build.rs @@ -66,27 +66,11 @@ fn generate_bindgen_code(project_dir: &Path) { ); println!("cargo:rustc-link-lib=static=backtrace"); - println!("cargo:rustc-link-lib=stdc++"); - - println!( - "cargo:rustc-link-search={}", - vendor_path.join("vendor/negentropy/cpp").display() - ); - println!("cargo:rustc-link-lib=static=negentropy"); - - println!("cargo:rustc-link-lib=ssl"); - println!("cargo:rustc-link-lib=crypto"); - cc::Build::new() .file("src/cmd.c") // Compile the C file .compile("cmditems"); // Compile it as a library println!("cargo:rustc-link-lib=static=cmditems"); - // TODO: Determine if pthread is automatically included - println!("cargo:rustc-link-lib=pthread"); - - // TODO: Test in other architectures - // Generate waku bindings with bindgen let bindings = bindgen::Builder::default() // The input header we would like to generate diff --git a/waku-sys/vendor b/waku-sys/vendor index d814519..625c8ee 160000 --- a/waku-sys/vendor +++ b/waku-sys/vendor @@ -1 +1 @@ -Subproject commit d814519578380bf01398c29424a5fd1005ed3a29 +Subproject commit 625c8ee51bc3e065da0e2e8d3a53d3634589f548