From 6ace4a919568f9da223608ea1d5835ecee108310 Mon Sep 17 00:00:00 2001 From: Nathan McCarty Date: Mon, 10 Jan 2022 14:05:13 -0500 Subject: [PATCH 001/107] Initial Commit --- libp2p-networking/.gitignore | 2 + libp2p-networking/Cargo.lock | 2928 +++++++++++++++++++++++++++++++++ libp2p-networking/Cargo.toml | 11 + libp2p-networking/default.nix | 13 + libp2p-networking/flake.lock | 117 ++ libp2p-networking/flake.nix | 73 + libp2p-networking/shell.nix | 14 + libp2p-networking/src/lib.rs | 8 + 8 files changed, 3166 insertions(+) create mode 100644 libp2p-networking/.gitignore create mode 100644 libp2p-networking/Cargo.lock create mode 100644 libp2p-networking/Cargo.toml create mode 100644 libp2p-networking/default.nix create mode 100644 libp2p-networking/flake.lock create mode 100644 libp2p-networking/flake.nix create mode 100644 libp2p-networking/shell.nix create mode 100644 libp2p-networking/src/lib.rs diff --git a/libp2p-networking/.gitignore b/libp2p-networking/.gitignore new file mode 100644 index 0000000000..d787b7061e --- /dev/null +++ b/libp2p-networking/.gitignore @@ -0,0 +1,2 @@ +/target +/result diff --git a/libp2p-networking/Cargo.lock b/libp2p-networking/Cargo.lock new file mode 100644 index 0000000000..52aff3963c --- /dev/null +++ b/libp2p-networking/Cargo.lock @@ -0,0 +1,2928 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "adler" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" + +[[package]] +name = "aead" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b613b8e1e3cf911a086f53f03bf286f52fd7a7258e4fa606f0ef220d39d8877" +dependencies = [ + "generic-array", +] + +[[package]] +name = "aes" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e8b47f52ea9bae42228d07ec09eb676433d7c4ed1ebdf0f1d1c29ed446f1ab8" +dependencies = [ + "cfg-if", + "cipher", + "cpufeatures", + "opaque-debug", +] + +[[package]] +name = "aes-gcm" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df5f85a83a7d8b0442b6aa7b504b8212c1733da07b98aae43d4bc21b2cb3cdf6" +dependencies = [ + "aead", + "aes", + "cipher", + "ctr", + "ghash", + "subtle", +] + +[[package]] +name = "ahash" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fcb51a0695d8f838b1ee009b3fbf66bda078cd64590202a864a8f3e8c4315c47" +dependencies = [ + "getrandom 0.2.3", + "once_cell", + "version_check", +] + +[[package]] +name = "aho-corasick" +version = "0.7.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e37cfd5e7657ada45f742d6e99ca5788580b5c529dc78faf11ece6dc702656f" +dependencies = [ + "memchr", +] + +[[package]] +name = "anyhow" +version = "1.0.52" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "84450d0b4a8bd1ba4144ce8ce718fbc5d071358b1e5384bace6536b3d1f2d5b3" + +[[package]] +name = "arrayref" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4c527152e37cf757a3f78aae5a06fbeefdb07ccc535c980a3208ee3060dd544" + +[[package]] +name = "arrayvec" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23b62fc65de8e4e7f52534fb52b0f3ed04746ae267519eef2a83941e8085068b" + +[[package]] +name = "asn1_der" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e22d1f4b888c298a027c99dc9048015fac177587de20fc30232a057dfbe24a21" + +[[package]] +name = "async-channel" +version = "1.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2114d64672151c0c5eaa5e131ec84a74f06e1e559830dabba01ca30605d66319" +dependencies = [ + "concurrent-queue", + "event-listener", + "futures-core", +] + +[[package]] +name = "async-executor" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "871f9bb5e0a22eeb7e8cf16641feb87c9dc67032ccf8ff49e772eb9941d3a965" +dependencies = [ + "async-task", + "concurrent-queue", + "fastrand", + "futures-lite", + "once_cell", + "slab", +] + +[[package]] +name = "async-global-executor" +version = "2.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9586ec52317f36de58453159d48351bc244bc24ced3effc1fce22f3d48664af6" +dependencies = [ + "async-channel", + "async-executor", + "async-io", + "async-mutex", + "blocking", + "futures-lite", + "num_cpus", + "once_cell", +] + +[[package]] +name = "async-io" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a811e6a479f2439f0c04038796b5cfb3d2ad56c230e0f2d3f7b04d68cfee607b" +dependencies = [ + "concurrent-queue", + "futures-lite", + "libc", + "log", + "once_cell", + "parking", + "polling", + "slab", + "socket2 0.4.2", + "waker-fn", + "winapi", +] + +[[package]] +name = "async-lock" +version = "2.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6a8ea61bf9947a1007c5cada31e647dbc77b103c679858150003ba697ea798b" +dependencies = [ + "event-listener", +] + +[[package]] +name = "async-mutex" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "479db852db25d9dbf6204e6cb6253698f175c15726470f78af0d918e99d6156e" +dependencies = [ + "event-listener", +] + +[[package]] +name = "async-std" +version = "1.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8056f1455169ab86dd47b47391e4ab0cbd25410a70e9fe675544f49bafaf952" +dependencies = [ + "async-channel", + "async-global-executor", + "async-io", + "async-lock", + "crossbeam-utils", + "futures-channel", + "futures-core", + "futures-io", + "futures-lite", + "gloo-timers", + "kv-log-macro", + "log", + "memchr", + "num_cpus", + "once_cell", + "pin-project-lite 0.2.8", + "pin-utils", + "slab", + "wasm-bindgen-futures", +] + +[[package]] +name = "async-std-resolver" +version = "0.20.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed4e2c3da14d8ad45acb1e3191db7a918e9505b6f155b218e70a7c9a1a48c638" +dependencies = [ + "async-std", + "async-trait", + "futures-io", + "futures-util", + "pin-utils", + "trust-dns-resolver", +] + +[[package]] +name = "async-task" +version = "4.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e91831deabf0d6d7ec49552e489aed63b7456a7a3c46cff62adad428110b0af0" + +[[package]] +name = "async-trait" +version = "0.1.52" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "061a7acccaa286c011ddc30970520b98fa40e00c9d644633fb26b5fc63a265e3" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "asynchronous-codec" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0de5164e5edbf51c45fb8c2d9664ae1c095cce1b265ecf7569093c0d66ef690" +dependencies = [ + "bytes", + "futures-sink", + "futures-util", + "memchr", + "pin-project-lite 0.2.8", +] + +[[package]] +name = "atomic" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b88d82667eca772c4aa12f0f1348b3ae643424c8876448f3f7bd5787032e234c" +dependencies = [ + "autocfg", +] + +[[package]] +name = "atomic-waker" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "065374052e7df7ee4047b1160cca5e1467a12351a40b3da123c870ba0b8eda2a" + +[[package]] +name = "autocfg" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a" + +[[package]] +name = "base64" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "904dfeac50f3cdaba28fc6f57fdcddb75f49ed61346676a78c4ffe55877802fd" + +[[package]] +name = "bimap" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50ae17cabbc8a38a1e3e4c1a6a664e9a09672dc14d0896fa8d865d3a5a446b07" + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] +name = "blake2" +version = "0.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0a4e37d16930f5459780f5621038b6382b9bb37c19016f39fb6b5808d831f174" +dependencies = [ + "crypto-mac", + "digest", + "opaque-debug", +] + +[[package]] +name = "block-buffer" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4152116fd6e9dadb291ae18fc1ec3575ed6d84c29642d97890f4b4a3417297e4" +dependencies = [ + "block-padding", + "generic-array", +] + +[[package]] +name = "block-padding" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d696c370c750c948ada61c69a0ee2cbbb9c50b1019ddb86d9317157a99c2cae" + +[[package]] +name = "blocking" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "046e47d4b2d391b1f6f8b407b1deb8dee56c1852ccd868becf2710f601b5f427" +dependencies = [ + "async-channel", + "async-task", + "atomic-waker", + "fastrand", + "futures-lite", + "once_cell", +] + +[[package]] +name = "bs58" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "771fe0050b883fcc3ea2359b1a96bcfbc090b7116eae7c3c512c7a083fdf23d3" + +[[package]] +name = "bumpalo" +version = "3.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4a45a46ab1f2412e53d3a0ade76ffad2025804294569aae387231a0cd6e0899" + +[[package]] +name = "byteorder" +version = "1.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" + +[[package]] +name = "bytes" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4872d67bab6358e59559027aa3b9157c53d9358c51423c17554809a8858e0f8" + +[[package]] +name = "cache-padded" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1db59621ec70f09c5e9b597b220c7a2b43611f4710dc03ceb8748637775692c" + +[[package]] +name = "cc" +version = "1.0.72" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22a9137b95ea06864e018375b72adfb7db6e6f68cfc8df5a04d00288050485ee" + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "chacha20" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f08493fa7707effc63254c66c6ea908675912493cd67952eda23c09fae2610b1" +dependencies = [ + "cfg-if", + "cipher", + "cpufeatures", + "zeroize", +] + +[[package]] +name = "chacha20poly1305" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6547abe025f4027edacd9edaa357aded014eecec42a5070d9b885c3c334aba2" +dependencies = [ + "aead", + "chacha20", + "cipher", + "poly1305", + "zeroize", +] + +[[package]] +name = "cipher" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ee52072ec15386f770805afd189a01c8841be8696bed250fa2f13c4c0d6dfb7" +dependencies = [ + "generic-array", +] + +[[package]] +name = "concurrent-queue" +version = "1.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "30ed07550be01594c6026cff2a1d7fe9c8f683caa798e12b68694ac9e88286a3" +dependencies = [ + "cache-padded", +] + +[[package]] +name = "cpufeatures" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95059428f66df56b63431fdb4e1947ed2190586af5c5a8a8b71122bdf5a7f469" +dependencies = [ + "libc", +] + +[[package]] +name = "crc32fast" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "738c290dfaea84fc1ca15ad9c168d083b05a714e1efddd8edaab678dc28d2836" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "crossbeam-utils" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cfcae03edb34f947e64acdb1c33ec169824e20657e9ecb61cef6c8c74dcb8120" +dependencies = [ + "cfg-if", + "lazy_static", +] + +[[package]] +name = "crunchy" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" + +[[package]] +name = "crypto-mac" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b584a330336237c1eecd3e94266efb216c56ed91225d634cb2991c5f3fd1aeab" +dependencies = [ + "generic-array", + "subtle", +] + +[[package]] +name = "ctor" +version = "0.1.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ccc0a48a9b826acdf4028595adc9db92caea352f7af011a3034acd172a52a0aa" +dependencies = [ + "quote", + "syn", +] + +[[package]] +name = "ctr" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "049bb91fb4aaf0e3c7efa6cd5ef877dbbbd15b39dad06d9948de4ec8a75761ea" +dependencies = [ + "cipher", +] + +[[package]] +name = "cuckoofilter" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b810a8449931679f64cd7eef1bbd0fa315801b6d5d9cdc1ace2804d6529eee18" +dependencies = [ + "byteorder", + "fnv", + "rand 0.7.3", +] + +[[package]] +name = "curve25519-dalek" +version = "3.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b9fdf9972b2bd6af2d913799d9ebc165ea4d2e65878e329d9c6b372c4491b61" +dependencies = [ + "byteorder", + "digest", + "rand_core 0.5.1", + "subtle", + "zeroize", +] + +[[package]] +name = "data-encoding" +version = "2.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ee2393c4a91429dffb4bedf19f4d6abf27d8a732c8ce4980305d782e5426d57" + +[[package]] +name = "digest" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066" +dependencies = [ + "generic-array", +] + +[[package]] +name = "dns-parser" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4d33be9473d06f75f58220f71f7a9317aca647dc061dbd3c361b0bef505fbea" +dependencies = [ + "byteorder", + "quick-error", +] + +[[package]] +name = "doc-comment" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fea41bba32d969b513997752735605054bc0dfa92b4c56bf1189f2e174be7a10" + +[[package]] +name = "dtoa" +version = "0.4.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56899898ce76aaf4a0f24d914c97ea6ed976d42fec6ad33fcbb0a1103e07b2b0" + +[[package]] +name = "ed25519" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "74e1069e39f1454367eb2de793ed062fac4c35c2934b76a81d90dd9abcd28816" +dependencies = [ + "signature", +] + +[[package]] +name = "ed25519-dalek" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c762bae6dcaf24c4c84667b8579785430908723d5c889f469d76a41d59cc7a9d" +dependencies = [ + "curve25519-dalek", + "ed25519", + "rand 0.7.3", + "serde", + "sha2", + "zeroize", +] + +[[package]] +name = "either" +version = "1.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457" + +[[package]] +name = "enum-as-inner" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c5f0096a91d210159eceb2ff5e1c4da18388a170e1e3ce948aac9c8fdbbf595" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "event-listener" +version = "2.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f7531096570974c3a9dcf9e4b8e1cede1ec26cf5046219fb3b9d897503b9be59" + +[[package]] +name = "fastrand" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "779d043b6a0b90cc4c0ed7ee380a6504394cee7efd7db050e3774eee387324b2" +dependencies = [ + "instant", +] + +[[package]] +name = "fixedbitset" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "279fb028e20b3c4c320317955b77c5e0c9701f05a1d309905d6fc702cdc5053e" + +[[package]] +name = "flate2" +version = "1.0.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e6988e897c1c9c485f43b47a529cef42fde0547f9d8d41a7062518f1d8fc53f" +dependencies = [ + "cfg-if", + "crc32fast", + "libc", + "libz-sys", + "miniz_oxide", +] + +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + +[[package]] +name = "form_urlencoded" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5fc25a87fa4fd2094bffb06925852034d90a17f0d1e05197d4956d3555752191" +dependencies = [ + "matches", + "percent-encoding", +] + +[[package]] +name = "futures" +version = "0.3.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "28560757fe2bb34e79f907794bb6b22ae8b0e5c669b638a1132f2592b19035b4" +dependencies = [ + "futures-channel", + "futures-core", + "futures-executor", + "futures-io", + "futures-sink", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-channel" +version = "0.3.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba3dda0b6588335f360afc675d0564c17a77a2bda81ca178a4b6081bd86c7f0b" +dependencies = [ + "futures-core", + "futures-sink", +] + +[[package]] +name = "futures-core" +version = "0.3.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d0c8ff0461b82559810cdccfde3215c3f373807f5e5232b71479bff7bb2583d7" + +[[package]] +name = "futures-executor" +version = "0.3.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29d6d2ff5bb10fb95c85b8ce46538a2e5f5e7fdc755623a7d4529ab8a4ed9d2a" +dependencies = [ + "futures-core", + "futures-task", + "futures-util", + "num_cpus", +] + +[[package]] +name = "futures-io" +version = "0.3.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1f9d34af5a1aac6fb380f735fe510746c38067c5bf16c7fd250280503c971b2" + +[[package]] +name = "futures-lite" +version = "1.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7694489acd39452c77daa48516b894c153f192c3578d5a839b62c58099fcbf48" +dependencies = [ + "fastrand", + "futures-core", + "futures-io", + "memchr", + "parking", + "pin-project-lite 0.2.8", + "waker-fn", +] + +[[package]] +name = "futures-macro" +version = "0.3.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6dbd947adfffb0efc70599b3ddcf7b5597bb5fa9e245eb99f62b3a5f7bb8bd3c" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "futures-rustls" +version = "0.22.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d383f0425d991a05e564c2f3ec150bd6dde863179c131dd60d8aa73a05434461" +dependencies = [ + "futures-io", + "rustls", + "webpki", +] + +[[package]] +name = "futures-sink" +version = "0.3.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3055baccb68d74ff6480350f8d6eb8fcfa3aa11bdc1a1ae3afdd0514617d508" + +[[package]] +name = "futures-task" +version = "0.3.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ee7c6485c30167ce4dfb83ac568a849fe53274c831081476ee13e0dce1aad72" + +[[package]] +name = "futures-timer" +version = "3.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e64b03909df88034c26dc1547e8970b91f98bdb65165d6a4e9110d94263dbb2c" + +[[package]] +name = "futures-util" +version = "0.3.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9b5cf40b47a271f77a8b1bec03ca09044d99d2372c0de244e66430761127164" +dependencies = [ + "futures-channel", + "futures-core", + "futures-io", + "futures-macro", + "futures-sink", + "futures-task", + "memchr", + "pin-project-lite 0.2.8", + "pin-utils", + "slab", +] + +[[package]] +name = "generic-array" +version = "0.14.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd48d33ec7f05fbfa152300fdad764757cbded343c1aa1cff2fbaf4134851803" +dependencies = [ + "typenum", + "version_check", +] + +[[package]] +name = "getrandom" +version = "0.1.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8fc3cb4d91f53b50155bdcfd23f6a4c39ae1969c2ae85982b135750cccaf5fce" +dependencies = [ + "cfg-if", + "libc", + "wasi 0.9.0+wasi-snapshot-preview1", +] + +[[package]] +name = "getrandom" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7fcd999463524c52659517fe2cea98493cfe485d10565e7b0fb07dbba7ad2753" +dependencies = [ + "cfg-if", + "libc", + "wasi 0.10.2+wasi-snapshot-preview1", +] + +[[package]] +name = "ghash" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1583cc1656d7839fd3732b80cf4f38850336cdb9b8ded1cd399ca62958de3c99" +dependencies = [ + "opaque-debug", + "polyval", +] + +[[package]] +name = "gloo-timers" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f16c88aa13d2656ef20d1c042086b8767bbe2bdb62526894275a1b062161b2e" +dependencies = [ + "futures-channel", + "futures-core", + "js-sys", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "hashbrown" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e" +dependencies = [ + "ahash", +] + +[[package]] +name = "heck" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d621efb26863f0e9924c6ac577e8275e5e6b77455db64ffa6c65c904e9e132c" +dependencies = [ + "unicode-segmentation", +] + +[[package]] +name = "hermit-abi" +version = "0.1.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" +dependencies = [ + "libc", +] + +[[package]] +name = "hex" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" + +[[package]] +name = "hex_fmt" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b07f60793ff0a4d9cef0f18e63b5357e06209987153a64648c972c1e5aff336f" + +[[package]] +name = "hmac" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "126888268dcc288495a26bf004b38c5fdbb31682f992c84ceb046a1f0fe38840" +dependencies = [ + "crypto-mac", + "digest", +] + +[[package]] +name = "hmac-drbg" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "17ea0a1394df5b6574da6e0c1ade9e78868c9fb0a4e5ef4428e32da4676b85b1" +dependencies = [ + "digest", + "generic-array", + "hmac", +] + +[[package]] +name = "hostname" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c731c3e10504cc8ed35cfe2f1db4c9274c3d35fa486e3b31df46f068ef3e867" +dependencies = [ + "libc", + "match_cfg", + "winapi", +] + +[[package]] +name = "httparse" +version = "1.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "acd94fdbe1d4ff688b67b04eee2e17bd50995534a61539e45adfefb45e5e5503" + +[[package]] +name = "idna" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "418a0a6fab821475f634efe3ccc45c013f742efe03d853e8d3355d5cb850ecf8" +dependencies = [ + "matches", + "unicode-bidi", + "unicode-normalization", +] + +[[package]] +name = "if-addrs" +version = "0.6.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2273e421f7c4f0fc99e1934fe4776f59d8df2972f4199d703fc0da9f2a9f73de" +dependencies = [ + "if-addrs-sys", + "libc", + "winapi", +] + +[[package]] +name = "if-addrs-sys" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "de74b9dd780476e837e5eb5ab7c88b49ed304126e412030a0adba99c8efe79ea" +dependencies = [ + "cc", + "libc", +] + +[[package]] +name = "if-watch" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae8ab7f67bad3240049cb24fb9cb0b4c2c6af4c245840917fbbdededeee91179" +dependencies = [ + "async-io", + "futures", + "futures-lite", + "if-addrs", + "ipnet", + "libc", + "log", + "winapi", +] + +[[package]] +name = "indexmap" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282a6247722caba404c065016bbfa522806e51714c34f5dfc3e4a3a46fcb4223" +dependencies = [ + "autocfg", + "hashbrown", +] + +[[package]] +name = "instant" +version = "0.1.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "ipconfig" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f7e2f18aece9709094573a9f24f483c4f65caa4298e2f7ae1b71cc65d853fad7" +dependencies = [ + "socket2 0.3.19", + "widestring", + "winapi", + "winreg", +] + +[[package]] +name = "ipnet" +version = "2.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68f2d64f2edebec4ce84ad108148e67e1064789bee435edc5b60ad398714a3a9" + +[[package]] +name = "itertools" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a9a9d19fa1e79b6215ff29b9d6880b706147f16e9b1dbb1e4e5947b5b02bc5e3" +dependencies = [ + "either", +] + +[[package]] +name = "itoa" +version = "0.4.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b71991ff56294aa922b450139ee08b3bfc70982c6b2c7562771375cf73542dd4" + +[[package]] +name = "js-sys" +version = "0.3.55" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7cc9ffccd38c451a86bf13657df244e9c3f37493cce8e5e21e940963777acc84" +dependencies = [ + "wasm-bindgen", +] + +[[package]] +name = "keccak" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67c21572b4949434e4fc1e1978b99c5f77064153c59d998bf13ecd96fb5ecba7" + +[[package]] +name = "kv-log-macro" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0de8b303297635ad57c9f5059fd9cee7a47f8e8daa09df0fcd07dd39fb22977f" +dependencies = [ + "log", +] + +[[package]] +name = "lazy_static" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" + +[[package]] +name = "libc" +version = "0.2.112" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b03d17f364a3a042d5e5d46b053bbbf82c92c9430c592dd4c064dc6ee997125" + +[[package]] +name = "libp2p" +version = "0.41.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2ec5b70fc23ed1b1b1169ce0d1116260a343f67cf7088b498b8d99255cd68c32" +dependencies = [ + "atomic", + "bytes", + "futures", + "futures-timer", + "getrandom 0.2.3", + "instant", + "lazy_static", + "libp2p-core", + "libp2p-deflate", + "libp2p-dns", + "libp2p-floodsub", + "libp2p-gossipsub", + "libp2p-identify", + "libp2p-kad", + "libp2p-mdns", + "libp2p-metrics", + "libp2p-mplex", + "libp2p-noise", + "libp2p-ping", + "libp2p-plaintext", + "libp2p-pnet", + "libp2p-relay", + "libp2p-rendezvous", + "libp2p-request-response", + "libp2p-swarm", + "libp2p-swarm-derive", + "libp2p-tcp", + "libp2p-uds", + "libp2p-wasm-ext", + "libp2p-websocket", + "libp2p-yamux", + "multiaddr", + "parking_lot", + "pin-project 1.0.10", + "rand 0.7.3", + "smallvec", +] + +[[package]] +name = "libp2p-core" +version = "0.30.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef22d9bba1e8bcb7ec300073e6802943fe8abb8190431842262b5f1c30abba1" +dependencies = [ + "asn1_der", + "bs58", + "ed25519-dalek", + "either", + "fnv", + "futures", + "futures-timer", + "lazy_static", + "libsecp256k1", + "log", + "multiaddr", + "multihash", + "multistream-select", + "parking_lot", + "pin-project 1.0.10", + "prost", + "prost-build", + "rand 0.8.4", + "ring", + "rw-stream-sink", + "sha2", + "smallvec", + "thiserror", + "unsigned-varint", + "void", + "zeroize", +] + +[[package]] +name = "libp2p-deflate" +version = "0.30.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51a800adb195f33de63f4b17b63fe64cfc23bf2c6a0d3d0d5321328664e65197" +dependencies = [ + "flate2", + "futures", + "libp2p-core", +] + +[[package]] +name = "libp2p-dns" +version = "0.30.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb8f89d15cb6e3c5bc22afff7513b11bab7856f2872d3cfba86f7f63a06bc498" +dependencies = [ + "async-std-resolver", + "futures", + "libp2p-core", + "log", + "smallvec", + "trust-dns-resolver", +] + +[[package]] +name = "libp2p-floodsub" +version = "0.32.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "709047c957360e8f2b3f7e987c0e272038e3003e0cdaf08b42668132ff910161" +dependencies = [ + "cuckoofilter", + "fnv", + "futures", + "libp2p-core", + "libp2p-swarm", + "log", + "prost", + "prost-build", + "rand 0.7.3", + "smallvec", +] + +[[package]] +name = "libp2p-gossipsub" +version = "0.34.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "98942284cc1a91f24527a8b1e5bc06f7dd22fc6cee5be3d9bf5785bf902eb934" +dependencies = [ + "asynchronous-codec", + "base64", + "byteorder", + "bytes", + "fnv", + "futures", + "futures-timer", + "hex_fmt", + "instant", + "libp2p-core", + "libp2p-swarm", + "log", + "open-metrics-client", + "pin-project 1.0.10", + "prost", + "prost-build", + "rand 0.7.3", + "regex", + "sha2", + "smallvec", + "unsigned-varint", +] + +[[package]] +name = "libp2p-identify" +version = "0.32.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32329181638a103321c05ef697f406abbccc695780b7c7d3dc34206758e9eb09" +dependencies = [ + "futures", + "futures-timer", + "libp2p-core", + "libp2p-swarm", + "log", + "lru", + "prost", + "prost-build", + "smallvec", +] + +[[package]] +name = "libp2p-kad" +version = "0.33.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fe4538a739911c178ec96398caa7d9eb3dc540f07613c819b38722a697eaccc" +dependencies = [ + "arrayvec", + "asynchronous-codec", + "bytes", + "either", + "fnv", + "futures", + "futures-timer", + "instant", + "libp2p-core", + "libp2p-swarm", + "log", + "prost", + "prost-build", + "rand 0.7.3", + "sha2", + "smallvec", + "uint", + "unsigned-varint", + "void", +] + +[[package]] +name = "libp2p-mdns" +version = "0.33.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13ea6cb29b2be3317a483f5687cdf4ea387e87331731e53c8a2c9feae7c97cac" +dependencies = [ + "async-io", + "data-encoding", + "dns-parser", + "futures", + "if-watch", + "lazy_static", + "libp2p-core", + "libp2p-swarm", + "log", + "rand 0.8.4", + "smallvec", + "socket2 0.4.2", + "void", +] + +[[package]] +name = "libp2p-metrics" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d59f3be49edeecff13ef0d0dc28295ba4a33910611715f04236325d08e4119e0" +dependencies = [ + "libp2p-core", + "libp2p-gossipsub", + "libp2p-identify", + "libp2p-kad", + "libp2p-ping", + "libp2p-swarm", + "open-metrics-client", +] + +[[package]] +name = "libp2p-mplex" +version = "0.30.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f2cd64ef597f40e14bfce0497f50ecb63dd6d201c61796daeb4227078834fbf" +dependencies = [ + "asynchronous-codec", + "bytes", + "futures", + "libp2p-core", + "log", + "nohash-hasher", + "parking_lot", + "rand 0.7.3", + "smallvec", + "unsigned-varint", +] + +[[package]] +name = "libp2p-noise" +version = "0.33.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8772c7a99088221bb7ca9c5c0574bf55046a7ab4c319f3619b275f28c8fb87a" +dependencies = [ + "bytes", + "curve25519-dalek", + "futures", + "lazy_static", + "libp2p-core", + "log", + "prost", + "prost-build", + "rand 0.8.4", + "sha2", + "snow", + "static_assertions", + "x25519-dalek", + "zeroize", +] + +[[package]] +name = "libp2p-ping" +version = "0.32.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d210cc0774142575a6a95f2c3590f9009cb838652cd295110a12a5d032ac07e0" +dependencies = [ + "futures", + "futures-timer", + "instant", + "libp2p-core", + "libp2p-swarm", + "log", + "rand 0.7.3", + "void", +] + +[[package]] +name = "libp2p-plaintext" +version = "0.30.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5fba1a6ff33e4a274c89a3b1d78b9f34f32af13265cc5c46c16938262d4e945a" +dependencies = [ + "asynchronous-codec", + "bytes", + "futures", + "libp2p-core", + "log", + "prost", + "prost-build", + "unsigned-varint", + "void", +] + +[[package]] +name = "libp2p-pnet" +version = "0.22.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0f1a458bbda880107b5b36fcb9b5a1ef0c329685da0e203ed692a8ebe64cc92c" +dependencies = [ + "futures", + "log", + "pin-project 1.0.10", + "rand 0.7.3", + "salsa20", + "sha3", +] + +[[package]] +name = "libp2p-relay" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "352001594ebc7538538c5439e6bf8348995ebf28b1b042d8193532e90bc77aee" +dependencies = [ + "asynchronous-codec", + "bytes", + "futures", + "futures-timer", + "instant", + "libp2p-core", + "libp2p-swarm", + "log", + "pin-project 1.0.10", + "prost", + "prost-build", + "rand 0.7.3", + "smallvec", + "unsigned-varint", + "void", +] + +[[package]] +name = "libp2p-rendezvous" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "921bc44c31225d42ac282e0e5a2f5311e4c50906a9e02d861fe8107a9396be49" +dependencies = [ + "asynchronous-codec", + "bimap", + "futures", + "futures-timer", + "instant", + "libp2p-core", + "libp2p-swarm", + "log", + "prost", + "prost-build", + "rand 0.8.4", + "sha2", + "thiserror", + "unsigned-varint", + "void", +] + +[[package]] +name = "libp2p-request-response" +version = "0.14.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ddfda221e6fea477db4fbe6f566cfd3e0850abb97d6249b8fcb731cb94cc946b" +dependencies = [ + "async-trait", + "bytes", + "futures", + "instant", + "libp2p-core", + "libp2p-swarm", + "log", + "lru", + "rand 0.7.3", + "smallvec", + "unsigned-varint", +] + +[[package]] +name = "libp2p-swarm" +version = "0.32.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb84d40627cd109bbbf43da9269d4ef75903f42356c88d98b2b55c47c430c792" +dependencies = [ + "either", + "futures", + "futures-timer", + "instant", + "libp2p-core", + "log", + "rand 0.7.3", + "smallvec", + "void", +] + +[[package]] +name = "libp2p-swarm-derive" +version = "0.26.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7dd93a7dad9b61c39797572e4fb4fdba8415d6348b4e745b3d4cb008f84331ab" +dependencies = [ + "quote", + "syn", +] + +[[package]] +name = "libp2p-tcp" +version = "0.30.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7399c5b6361ef525d41c11fcf51635724f832baf5819b30d3d873eabb4fbae4b" +dependencies = [ + "async-io", + "futures", + "futures-timer", + "if-watch", + "ipnet", + "libc", + "libp2p-core", + "log", + "socket2 0.4.2", +] + +[[package]] +name = "libp2p-uds" +version = "0.30.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8b7563e46218165dfd60f64b96f7ce84590d75f53ecbdc74a7dd01450dc5973" +dependencies = [ + "async-std", + "futures", + "libp2p-core", + "log", +] + +[[package]] +name = "libp2p-wasm-ext" +version = "0.30.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1008a302b73c5020251f9708c653f5ed08368e530e247cc9cd2f109ff30042cf" +dependencies = [ + "futures", + "js-sys", + "libp2p-core", + "parity-send-wrapper", + "wasm-bindgen", + "wasm-bindgen-futures", +] + +[[package]] +name = "libp2p-websocket" +version = "0.32.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa92005fbd67695715c821e1acfe4d7be9fd2d88738574e93d645c49ec2831c8" +dependencies = [ + "either", + "futures", + "futures-rustls", + "libp2p-core", + "log", + "quicksink", + "rw-stream-sink", + "soketto", + "url", + "webpki-roots", +] + +[[package]] +name = "libp2p-yamux" +version = "0.34.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e7362abb8867d7187e7e93df17f460d554c997fc5c8ac57dc1259057f6889af" +dependencies = [ + "futures", + "libp2p-core", + "parking_lot", + "thiserror", + "yamux", +] + +[[package]] +name = "libsecp256k1" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0452aac8bab02242429380e9b2f94ea20cea2b37e2c1777a1358799bbe97f37" +dependencies = [ + "arrayref", + "base64", + "digest", + "hmac-drbg", + "libsecp256k1-core", + "libsecp256k1-gen-ecmult", + "libsecp256k1-gen-genmult", + "rand 0.8.4", + "serde", + "sha2", + "typenum", +] + +[[package]] +name = "libsecp256k1-core" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5be9b9bb642d8522a44d533eab56c16c738301965504753b03ad1de3425d5451" +dependencies = [ + "crunchy", + "digest", + "subtle", +] + +[[package]] +name = "libsecp256k1-gen-ecmult" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3038c808c55c87e8a172643a7d87187fc6c4174468159cb3090659d55bcb4809" +dependencies = [ + "libsecp256k1-core", +] + +[[package]] +name = "libsecp256k1-gen-genmult" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3db8d6ba2cec9eacc40e6e8ccc98931840301f1006e95647ceb2dd5c3aa06f7c" +dependencies = [ + "libsecp256k1-core", +] + +[[package]] +name = "libz-sys" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "de5435b8549c16d423ed0c03dbaafe57cf6c3344744f1242520d59c9d8ecec66" +dependencies = [ + "cc", + "pkg-config", + "vcpkg", +] + +[[package]] +name = "linked-hash-map" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7fb9b38af92608140b86b693604b9ffcc5824240a484d1ecd4795bacb2fe88f3" + +[[package]] +name = "lock_api" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712a4d093c9976e24e7dbca41db895dabcbac38eb5f4045393d17a95bdfb1109" +dependencies = [ + "scopeguard", +] + +[[package]] +name = "log" +version = "0.4.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51b9bbe6c47d51fc3e1a9b945965946b4c44142ab8792c50835a980d362c2710" +dependencies = [ + "cfg-if", + "value-bag", +] + +[[package]] +name = "lru" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "274353858935c992b13c0ca408752e2121da852d07dec7ce5f108c77dfa14d1f" +dependencies = [ + "hashbrown", +] + +[[package]] +name = "lru-cache" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "31e24f1ad8321ca0e8a1e0ac13f23cb668e6f5466c2c57319f6a5cf1cc8e3b1c" +dependencies = [ + "linked-hash-map", +] + +[[package]] +name = "match_cfg" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ffbee8634e0d45d258acb448e7eaab3fce7a0a467395d4d9f228e3c1f01fb2e4" + +[[package]] +name = "matches" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a3e378b66a060d48947b590737b30a1be76706c8dd7b8ba0f2fe3989c68a853f" + +[[package]] +name = "memchr" +version = "2.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "308cc39be01b73d0d18f82a0e7b2a3df85245f84af96fdddc5d202d27e47b86a" + +[[package]] +name = "miniz_oxide" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a92518e98c078586bc6c934028adcca4c92a53d6a958196de835170a01d84e4b" +dependencies = [ + "adler", + "autocfg", +] + +[[package]] +name = "multiaddr" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48ee4ea82141951ac6379f964f71b20876d43712bea8faf6dd1a375e08a46499" +dependencies = [ + "arrayref", + "bs58", + "byteorder", + "data-encoding", + "multihash", + "percent-encoding", + "serde", + "static_assertions", + "unsigned-varint", + "url", +] + +[[package]] +name = "multihash" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "752a61cd890ff691b4411423d23816d5866dd5621e4d1c5687a53b94b5a979d8" +dependencies = [ + "digest", + "generic-array", + "multihash-derive", + "sha2", + "unsigned-varint", +] + +[[package]] +name = "multihash-derive" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "424f6e86263cd5294cbd7f1e95746b95aca0e0d66bff31e5a40d6baa87b4aa99" +dependencies = [ + "proc-macro-crate", + "proc-macro-error", + "proc-macro2", + "quote", + "syn", + "synstructure", +] + +[[package]] +name = "multimap" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5ce46fe64a9d73be07dcbe690a38ce1b293be448fd8ce1e6c1b8062c9f72c6a" + +[[package]] +name = "multistream-select" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56a336acba8bc87c8876f6425407dbbe6c417bf478b22015f8fb0994ef3bc0ab" +dependencies = [ + "bytes", + "futures", + "log", + "pin-project 1.0.10", + "smallvec", + "unsigned-varint", +] + +[[package]] +name = "networking-demo" +version = "0.1.0" +dependencies = [ + "libp2p", + "snafu", + "tracing", +] + +[[package]] +name = "nohash-hasher" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2bf50223579dc7cdcfb3bfcacf7069ff68243f8c363f62ffa99cf000a6b9c451" + +[[package]] +name = "num_cpus" +version = "1.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19e64526ebdee182341572e50e9ad03965aa510cd94427a4549448f285e957a1" +dependencies = [ + "hermit-abi", + "libc", +] + +[[package]] +name = "once_cell" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da32515d9f6e6e489d7bc9d84c71b060db7247dc035bbe44eac88cf87486d8d5" + +[[package]] +name = "opaque-debug" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" + +[[package]] +name = "open-metrics-client" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7337d80c23c2d8b1349563981bc4fb531220733743ba8115454a67b181173f0d" +dependencies = [ + "dtoa", + "itoa", + "open-metrics-client-derive-text-encode", + "owning_ref", +] + +[[package]] +name = "open-metrics-client-derive-text-encode" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a15c83b586f00268c619c1cb3340ec1a6f59dd9ba1d9833a273a68e6d5cd8ffc" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "owning_ref" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ff55baddef9e4ad00f88b6c743a2a8062d4c6ade126c2a528644b8e444d52ce" +dependencies = [ + "stable_deref_trait", +] + +[[package]] +name = "parity-send-wrapper" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa9777aa91b8ad9dd5aaa04a9b6bcb02c7f1deb952fca5a66034d5e63afc5c6f" + +[[package]] +name = "parking" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "427c3892f9e783d91cc128285287e70a59e206ca452770ece88a76f7a3eddd72" + +[[package]] +name = "parking_lot" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d17b78036a60663b797adeaee46f5c9dfebb86948d1255007a1d6be0271ff99" +dependencies = [ + "instant", + "lock_api", + "parking_lot_core", +] + +[[package]] +name = "parking_lot_core" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d76e8e1493bcac0d2766c42737f34458f1c8c50c0d23bcb24ea953affb273216" +dependencies = [ + "cfg-if", + "instant", + "libc", + "redox_syscall", + "smallvec", + "winapi", +] + +[[package]] +name = "percent-encoding" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e" + +[[package]] +name = "pest" +version = "2.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "10f4872ae94d7b90ae48754df22fd42ad52ce740b8f370b03da4835417403e53" +dependencies = [ + "ucd-trie", +] + +[[package]] +name = "petgraph" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a13a2fa9d0b63e5f22328828741e523766fff0ee9e779316902290dff3f824f" +dependencies = [ + "fixedbitset", + "indexmap", +] + +[[package]] +name = "pin-project" +version = "0.4.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9615c18d31137579e9ff063499264ddc1278e7b1982757ebc111028c4d1dc909" +dependencies = [ + "pin-project-internal 0.4.29", +] + +[[package]] +name = "pin-project" +version = "1.0.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "58ad3879ad3baf4e44784bc6a718a8698867bb991f8ce24d1bcbe2cfb4c3a75e" +dependencies = [ + "pin-project-internal 1.0.10", +] + +[[package]] +name = "pin-project-internal" +version = "0.4.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "044964427019eed9d49d9d5bbce6047ef18f37100ea400912a9fa4a3523ab12a" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "pin-project-internal" +version = "1.0.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "744b6f092ba29c3650faf274db506afd39944f48420f6c86b17cfe0ee1cb36bb" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "pin-project-lite" +version = "0.1.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "257b64915a082f7811703966789728173279bdebb956b143dbcd23f6f970a777" + +[[package]] +name = "pin-project-lite" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e280fbe77cc62c91527259e9442153f4688736748d24660126286329742b4c6c" + +[[package]] +name = "pin-utils" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" + +[[package]] +name = "pkg-config" +version = "0.3.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "58893f751c9b0412871a09abd62ecd2a00298c6c83befa223ef98c52aef40cbe" + +[[package]] +name = "polling" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "685404d509889fade3e86fe3a5803bca2ec09b0c0778d5ada6ec8bf7a8de5259" +dependencies = [ + "cfg-if", + "libc", + "log", + "wepoll-ffi", + "winapi", +] + +[[package]] +name = "poly1305" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "048aeb476be11a4b6ca432ca569e375810de9294ae78f4774e78ea98a9246ede" +dependencies = [ + "cpufeatures", + "opaque-debug", + "universal-hash", +] + +[[package]] +name = "polyval" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8419d2b623c7c0896ff2d5d96e2cb4ede590fed28fcc34934f4c33c036e620a1" +dependencies = [ + "cfg-if", + "cpufeatures", + "opaque-debug", + "universal-hash", +] + +[[package]] +name = "ppv-lite86" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eb9f9e6e233e5c4a35559a617bf40a4ec447db2e84c20b55a6f83167b7e57872" + +[[package]] +name = "proc-macro-crate" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ebace6889caf889b4d3f76becee12e90353f2b8c7d875534a71e5742f8f6f83" +dependencies = [ + "thiserror", + "toml", +] + +[[package]] +name = "proc-macro-error" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" +dependencies = [ + "proc-macro-error-attr", + "proc-macro2", + "quote", + "syn", + "version_check", +] + +[[package]] +name = "proc-macro-error-attr" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" +dependencies = [ + "proc-macro2", + "quote", + "version_check", +] + +[[package]] +name = "proc-macro2" +version = "1.0.36" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7342d5883fbccae1cc37a2353b09c87c9b0f3afd73f5fb9bba687a1f733b029" +dependencies = [ + "unicode-xid", +] + +[[package]] +name = "prost" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "444879275cb4fd84958b1a1d5420d15e6fcf7c235fe47f053c9c2a80aceb6001" +dependencies = [ + "bytes", + "prost-derive", +] + +[[package]] +name = "prost-build" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62941722fb675d463659e49c4f3fe1fe792ff24fe5bbaa9c08cd3b98a1c354f5" +dependencies = [ + "bytes", + "heck", + "itertools", + "lazy_static", + "log", + "multimap", + "petgraph", + "prost", + "prost-types", + "regex", + "tempfile", + "which", +] + +[[package]] +name = "prost-derive" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f9cc1a3263e07e0bf68e96268f37665207b49560d98739662cdfaae215c720fe" +dependencies = [ + "anyhow", + "itertools", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "prost-types" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "534b7a0e836e3c482d2693070f982e39e7611da9695d4d1f5a4b186b51faef0a" +dependencies = [ + "bytes", + "prost", +] + +[[package]] +name = "quick-error" +version = "1.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0" + +[[package]] +name = "quicksink" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77de3c815e5a160b1539c6592796801df2043ae35e123b46d73380cfa57af858" +dependencies = [ + "futures-core", + "futures-sink", + "pin-project-lite 0.1.12", +] + +[[package]] +name = "quote" +version = "1.0.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "47aa80447ce4daf1717500037052af176af5d38cc3e571d9ec1c7353fc10c87d" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "rand" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03" +dependencies = [ + "getrandom 0.1.16", + "libc", + "rand_chacha 0.2.2", + "rand_core 0.5.1", + "rand_hc 0.2.0", +] + +[[package]] +name = "rand" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e7573632e6454cf6b99d7aac4ccca54be06da05aca2ef7423d22d27d4d4bcd8" +dependencies = [ + "libc", + "rand_chacha 0.3.1", + "rand_core 0.6.3", + "rand_hc 0.3.1", +] + +[[package]] +name = "rand_chacha" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4c8ed856279c9737206bf725bf36935d8666ead7aa69b52be55af369d193402" +dependencies = [ + "ppv-lite86", + "rand_core 0.5.1", +] + +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", + "rand_core 0.6.3", +] + +[[package]] +name = "rand_core" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19" +dependencies = [ + "getrandom 0.1.16", +] + +[[package]] +name = "rand_core" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d34f1408f55294453790c48b2f1ebbb1c5b4b7563eb1f418bcfcfdbb06ebb4e7" +dependencies = [ + "getrandom 0.2.3", +] + +[[package]] +name = "rand_hc" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c" +dependencies = [ + "rand_core 0.5.1", +] + +[[package]] +name = "rand_hc" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d51e9f596de227fda2ea6c84607f5558e196eeaf43c986b724ba4fb8fdf497e7" +dependencies = [ + "rand_core 0.6.3", +] + +[[package]] +name = "redox_syscall" +version = "0.2.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8383f39639269cde97d255a32bdb68c047337295414940c68bdd30c2e13203ff" +dependencies = [ + "bitflags", +] + +[[package]] +name = "regex" +version = "1.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d07a8629359eb56f1e2fb1652bb04212c072a87ba68546a04065d525673ac461" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.6.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f497285884f3fcff424ffc933e56d7cbca511def0c9831a7f9b5f6153e3cc89b" + +[[package]] +name = "remove_dir_all" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3acd125665422973a33ac9d3dd2df85edad0f4ae9b00dafb1a05e43a9f5ef8e7" +dependencies = [ + "winapi", +] + +[[package]] +name = "resolv-conf" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52e44394d2086d010551b14b53b1f24e31647570cd1deb0379e2c21b329aba00" +dependencies = [ + "hostname", + "quick-error", +] + +[[package]] +name = "ring" +version = "0.16.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3053cf52e236a3ed746dfc745aa9cacf1b791d846bdaf412f60a8d7d6e17c8fc" +dependencies = [ + "cc", + "libc", + "once_cell", + "spin", + "untrusted", + "web-sys", + "winapi", +] + +[[package]] +name = "rustc_version" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0dfe2087c51c460008730de8b57e6a320782fbfb312e1f4d520e6c6fae155ee" +dependencies = [ + "semver", +] + +[[package]] +name = "rustls" +version = "0.20.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d37e5e2290f3e040b594b1a9e04377c2c671f1a1cfd9bfdef82106ac1c113f84" +dependencies = [ + "log", + "ring", + "sct", + "webpki", +] + +[[package]] +name = "rw-stream-sink" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4da5fcb054c46f5a5dff833b129285a93d3f0179531735e6c866e8cc307d2020" +dependencies = [ + "futures", + "pin-project 0.4.29", + "static_assertions", +] + +[[package]] +name = "salsa20" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c0fbb5f676da676c260ba276a8f43a8dc67cf02d1438423aeb1c677a7212686" +dependencies = [ + "cipher", +] + +[[package]] +name = "scopeguard" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" + +[[package]] +name = "sct" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d53dcdb7c9f8158937a7981b48accfd39a43af418591a5d008c7b22b5e1b7ca4" +dependencies = [ + "ring", + "untrusted", +] + +[[package]] +name = "semver" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f301af10236f6df4160f7c3f04eec6dbc70ace82d23326abad5edee88801c6b6" +dependencies = [ + "semver-parser", +] + +[[package]] +name = "semver-parser" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "00b0bef5b7f9e0df16536d3961cfb6e84331c065b4066afb39768d0e319411f7" +dependencies = [ + "pest", +] + +[[package]] +name = "serde" +version = "1.0.133" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97565067517b60e2d1ea8b268e59ce036de907ac523ad83a0475da04e818989a" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.133" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed201699328568d8d08208fdd080e3ff594e6c422e438b6705905da01005d537" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "sha-1" +version = "0.9.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "99cd6713db3cf16b6c84e06321e049a9b9f699826e16096d23bbcc44d15d51a6" +dependencies = [ + "block-buffer", + "cfg-if", + "cpufeatures", + "digest", + "opaque-debug", +] + +[[package]] +name = "sha2" +version = "0.9.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4d58a1e1bf39749807d89cf2d98ac2dfa0ff1cb3faa38fbb64dd88ac8013d800" +dependencies = [ + "block-buffer", + "cfg-if", + "cpufeatures", + "digest", + "opaque-debug", +] + +[[package]] +name = "sha3" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f81199417d4e5de3f04b1e871023acea7389672c4135918f05aa9cbf2f2fa809" +dependencies = [ + "block-buffer", + "digest", + "keccak", + "opaque-debug", +] + +[[package]] +name = "signature" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f054c6c1a6e95179d6f23ed974060dcefb2d9388bb7256900badad682c499de4" + +[[package]] +name = "slab" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9def91fd1e018fe007022791f865d0ccc9b3a0d5001e01aabb8b40e46000afb5" + +[[package]] +name = "smallvec" +version = "1.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ecab6c735a6bb4139c0caafd0cc3635748bbb3acf4550e8138122099251f309" + +[[package]] +name = "snafu" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2eba135d2c579aa65364522eb78590cdf703176ef71ad4c32b00f58f7afb2df5" +dependencies = [ + "doc-comment", + "snafu-derive", +] + +[[package]] +name = "snafu-derive" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a7fe9b0669ef117c5cabc5549638528f36771f058ff977d7689deb517833a75" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "snow" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6142f7c25e94f6fd25a32c3348ec230df9109b463f59c8c7acc4bd34936babb7" +dependencies = [ + "aes-gcm", + "blake2", + "chacha20poly1305", + "rand 0.8.4", + "rand_core 0.6.3", + "ring", + "rustc_version", + "sha2", + "subtle", + "x25519-dalek", +] + +[[package]] +name = "socket2" +version = "0.3.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "122e570113d28d773067fab24266b66753f6ea915758651696b6e35e49f88d6e" +dependencies = [ + "cfg-if", + "libc", + "winapi", +] + +[[package]] +name = "socket2" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5dc90fe6c7be1a323296982db1836d1ea9e47b6839496dde9a541bc496df3516" +dependencies = [ + "libc", + "winapi", +] + +[[package]] +name = "soketto" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41d1c5305e39e09653383c2c7244f2f78b3bcae37cf50c64cb4789c9f5096ec2" +dependencies = [ + "base64", + "bytes", + "flate2", + "futures", + "httparse", + "log", + "rand 0.8.4", + "sha-1", +] + +[[package]] +name = "spin" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" + +[[package]] +name = "stable_deref_trait" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" + +[[package]] +name = "static_assertions" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" + +[[package]] +name = "subtle" +version = "2.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6bdef32e8150c2a081110b42772ffe7d7c9032b606bc226c8260fd97e0976601" + +[[package]] +name = "syn" +version = "1.0.85" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a684ac3dcd8913827e18cd09a68384ee66c1de24157e3c556c9ab16d85695fb7" +dependencies = [ + "proc-macro2", + "quote", + "unicode-xid", +] + +[[package]] +name = "synstructure" +version = "0.12.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f36bdaa60a83aca3921b5259d5400cbf5e90fc51931376a9bd4a0eb79aa7210f" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "unicode-xid", +] + +[[package]] +name = "tempfile" +version = "3.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5cdb1ef4eaeeaddc8fbd371e5017057064af0911902ef36b39801f67cc6d79e4" +dependencies = [ + "cfg-if", + "fastrand", + "libc", + "redox_syscall", + "remove_dir_all", + "winapi", +] + +[[package]] +name = "thiserror" +version = "1.0.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "854babe52e4df1653706b98fcfc05843010039b406875930a70e4d9644e5c417" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa32fd3f627f367fe16f893e2597ae3c05020f8bba2666a4e6ea73d377e5714b" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "tinyvec" +version = "1.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c1c1d5a42b6245520c249549ec267180beaffcc0615401ac8e31853d4b6d8d2" +dependencies = [ + "tinyvec_macros", +] + +[[package]] +name = "tinyvec_macros" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c" + +[[package]] +name = "toml" +version = "0.5.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a31142970826733df8241ef35dc040ef98c679ab14d7c3e54d827099b3acecaa" +dependencies = [ + "serde", +] + +[[package]] +name = "tracing" +version = "0.1.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "375a639232caf30edfc78e8d89b2d4c375515393e7af7e16f01cd96917fb2105" +dependencies = [ + "cfg-if", + "pin-project-lite 0.2.8", + "tracing-attributes", + "tracing-core", +] + +[[package]] +name = "tracing-attributes" +version = "0.1.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4f480b8f81512e825f337ad51e94c1eb5d3bbdf2b363dcd01e2b19a9ffe3f8e" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "tracing-core" +version = "0.1.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f4ed65637b8390770814083d20756f87bfa2c21bf2f110babdc5438351746e4" +dependencies = [ + "lazy_static", +] + +[[package]] +name = "trust-dns-proto" +version = "0.20.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ad0d7f5db438199a6e2609debe3f69f808d074e0a2888ee0bccb45fe234d03f4" +dependencies = [ + "async-trait", + "cfg-if", + "data-encoding", + "enum-as-inner", + "futures-channel", + "futures-io", + "futures-util", + "idna", + "ipnet", + "lazy_static", + "log", + "rand 0.8.4", + "smallvec", + "thiserror", + "tinyvec", + "url", +] + +[[package]] +name = "trust-dns-resolver" +version = "0.20.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6ad17b608a64bd0735e67bde16b0636f8aa8591f831a25d18443ed00a699770" +dependencies = [ + "cfg-if", + "futures-util", + "ipconfig", + "lazy_static", + "log", + "lru-cache", + "parking_lot", + "resolv-conf", + "smallvec", + "thiserror", + "trust-dns-proto", +] + +[[package]] +name = "typenum" +version = "1.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dcf81ac59edc17cc8697ff311e8f5ef2d99fcbd9817b34cec66f90b6c3dfd987" + +[[package]] +name = "ucd-trie" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56dee185309b50d1f11bfedef0fe6d036842e3fb77413abef29f8f8d1c5d4c1c" + +[[package]] +name = "uint" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6470ab50f482bde894a037a57064480a246dbfdd5960bd65a44824693f08da5f" +dependencies = [ + "byteorder", + "crunchy", + "hex", + "static_assertions", +] + +[[package]] +name = "unicode-bidi" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a01404663e3db436ed2746d9fefef640d868edae3cceb81c3b8d5732fda678f" + +[[package]] +name = "unicode-normalization" +version = "0.1.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d54590932941a9e9266f0832deed84ebe1bf2e4c9e4a3554d393d18f5e854bf9" +dependencies = [ + "tinyvec", +] + +[[package]] +name = "unicode-segmentation" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8895849a949e7845e06bd6dc1aa51731a103c42707010a5b591c0038fb73385b" + +[[package]] +name = "unicode-xid" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3" + +[[package]] +name = "universal-hash" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f214e8f697e925001e66ec2c6e37a4ef93f0f78c2eed7814394e10c62025b05" +dependencies = [ + "generic-array", + "subtle", +] + +[[package]] +name = "unsigned-varint" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d86a8dc7f45e4c1b0d30e43038c38f274e77af056aa5f74b93c2cf9eb3c1c836" +dependencies = [ + "asynchronous-codec", + "bytes", + "futures-io", + "futures-util", +] + +[[package]] +name = "untrusted" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a" + +[[package]] +name = "url" +version = "2.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a507c383b2d33b5fc35d1861e77e6b383d158b2da5e14fe51b83dfedf6fd578c" +dependencies = [ + "form_urlencoded", + "idna", + "matches", + "percent-encoding", +] + +[[package]] +name = "value-bag" +version = "1.0.0-alpha.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "79923f7731dc61ebfba3633098bf3ac533bbd35ccd8c57e7088d9a5eebe0263f" +dependencies = [ + "ctor", + "version_check", +] + +[[package]] +name = "vcpkg" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" + +[[package]] +name = "version_check" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" + +[[package]] +name = "void" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" + +[[package]] +name = "waker-fn" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d5b2c62b4012a3e1eca5a7e077d13b3bf498c4073e33ccd58626607748ceeca" + +[[package]] +name = "wasi" +version = "0.9.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519" + +[[package]] +name = "wasi" +version = "0.10.2+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6" + +[[package]] +name = "wasm-bindgen" +version = "0.2.78" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "632f73e236b219150ea279196e54e610f5dbafa5d61786303d4da54f84e47fce" +dependencies = [ + "cfg-if", + "wasm-bindgen-macro", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.78" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a317bf8f9fba2476b4b2c85ef4c4af8ff39c3c7f0cdfeed4f82c34a880aa837b" +dependencies = [ + "bumpalo", + "lazy_static", + "log", + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-futures" +version = "0.4.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e8d7523cb1f2a4c96c1317ca690031b714a51cc14e05f712446691f413f5d39" +dependencies = [ + "cfg-if", + "js-sys", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.78" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d56146e7c495528bf6587663bea13a8eb588d39b36b679d83972e1a2dbbdacf9" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.78" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7803e0eea25835f8abdc585cd3021b3deb11543c6fe226dcd30b228857c5c5ab" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.78" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0237232789cf037d5480773fe568aac745bfe2afbc11a863e97901780a6b47cc" + +[[package]] +name = "web-sys" +version = "0.3.55" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38eb105f1c59d9eaa6b5cdc92b859d85b926e82cb2e0945cd0c9259faa6fe9fb" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "webpki" +version = "0.22.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f095d78192e208183081cc07bc5515ef55216397af48b873e5edcd72637fa1bd" +dependencies = [ + "ring", + "untrusted", +] + +[[package]] +name = "webpki-roots" +version = "0.22.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "552ceb903e957524388c4d3475725ff2c8b7960922063af6ce53c9a43da07449" +dependencies = [ + "webpki", +] + +[[package]] +name = "wepoll-ffi" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d743fdedc5c64377b5fc2bc036b01c7fd642205a0d96356034ae3404d49eb7fb" +dependencies = [ + "cc", +] + +[[package]] +name = "which" +version = "4.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea187a8ef279bc014ec368c27a920da2024d2a711109bfbe3440585d5cf27ad9" +dependencies = [ + "either", + "lazy_static", + "libc", +] + +[[package]] +name = "widestring" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c168940144dd21fd8046987c16a46a33d5fc84eec29ef9dcddc2ac9e31526b7c" + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + +[[package]] +name = "winreg" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2986deb581c4fe11b621998a5e53361efe6b48a151178d0cd9eeffa4dc6acc9" +dependencies = [ + "winapi", +] + +[[package]] +name = "x25519-dalek" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2392b6b94a576b4e2bf3c5b2757d63f10ada8020a2e4d08ac849ebcf6ea8e077" +dependencies = [ + "curve25519-dalek", + "rand_core 0.5.1", + "zeroize", +] + +[[package]] +name = "yamux" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7d9028f208dd5e63c614be69f115c1b53cacc1111437d4c765185856666c107" +dependencies = [ + "futures", + "log", + "nohash-hasher", + "parking_lot", + "rand 0.8.4", + "static_assertions", +] + +[[package]] +name = "zeroize" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4756f7db3f7b5574938c3eb1c117038b8e07f95ee6718c0efad4ac21508f1efd" +dependencies = [ + "zeroize_derive", +] + +[[package]] +name = "zeroize_derive" +version = "1.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "65f1a51723ec88c66d5d1fe80c841f17f63587d6691901d66be9bec6c3b51f73" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "synstructure", +] diff --git a/libp2p-networking/Cargo.toml b/libp2p-networking/Cargo.toml new file mode 100644 index 0000000000..fac72a9d4a --- /dev/null +++ b/libp2p-networking/Cargo.toml @@ -0,0 +1,11 @@ +[package] +name = "networking-demo" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +libp2p = "0.41.1" +snafu = "0.7.0" +tracing = "0.1.29" diff --git a/libp2p-networking/default.nix b/libp2p-networking/default.nix new file mode 100644 index 0000000000..19e1e7a5bc --- /dev/null +++ b/libp2p-networking/default.nix @@ -0,0 +1,13 @@ +(import + ( + let + lock = builtins.fromJSON (builtins.readFile ./flake.lock); + in + fetchTarball { + url = "https://github.com/edolstra/flake-compat/archive/${lock.nodes.flake-compat.locked.rev}.tar.gz"; + sha256 = lock.nodes.flake-compat.locked.narHash; + } + ) + { + src = ./.; + }).defaultNix.default diff --git a/libp2p-networking/flake.lock b/libp2p-networking/flake.lock new file mode 100644 index 0000000000..f4535eaef9 --- /dev/null +++ b/libp2p-networking/flake.lock @@ -0,0 +1,117 @@ +{ + "nodes": { + "crate2nix": { + "flake": false, + "locked": { + "lastModified": 1636361151, + "narHash": "sha256-PCyoPHYRG4gtgfBuk+N6qcPbc8EvooLBQ4tfeQjrjx0=", + "owner": "balsoft", + "repo": "crate2nix", + "rev": "08c87b1883cfc554a506cdfcbaa487b189cbbd22", + "type": "github" + }, + "original": { + "owner": "balsoft", + "ref": "balsoft/fix-broken-ifd", + "repo": "crate2nix", + "type": "github" + } + }, + "fenix": { + "inputs": { + "nixpkgs": [ + "nixpkgs" + ], + "rust-analyzer-src": "rust-analyzer-src" + }, + "locked": { + "lastModified": 1641709553, + "narHash": "sha256-wFx7U4klsmMZIufILyojgPUTYmtmIVD/M7Wg0JgcbJc=", + "owner": "nix-community", + "repo": "fenix", + "rev": "43fa994400794b5cb09ab9be894372c9e51bf7a6", + "type": "github" + }, + "original": { + "owner": "nix-community", + "repo": "fenix", + "type": "github" + } + }, + "flake-compat": { + "flake": false, + "locked": { + "lastModified": 1641205782, + "narHash": "sha256-4jY7RCWUoZ9cKD8co0/4tFARpWB+57+r1bLLvXNJliY=", + "owner": "edolstra", + "repo": "flake-compat", + "rev": "b7547d3eed6f32d06102ead8991ec52ab0a4f1a7", + "type": "github" + }, + "original": { + "owner": "edolstra", + "repo": "flake-compat", + "type": "github" + } + }, + "nixpkgs": { + "locked": { + "lastModified": 1641760999, + "narHash": "sha256-UhSV8Qe8TBrZksBZSYqwNsWFY7EgCJCJTlRxXJSL4Jg=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "8928525bd8b8cdc1235a92a89b72cbbe5bd8a00d", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixpkgs-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "root": { + "inputs": { + "crate2nix": "crate2nix", + "fenix": "fenix", + "flake-compat": "flake-compat", + "nixpkgs": "nixpkgs", + "utils": "utils" + } + }, + "rust-analyzer-src": { + "flake": false, + "locked": { + "lastModified": 1641653161, + "narHash": "sha256-gajsOT+HAfCEngraBy1K7UmLpDdQo4wtmhnzju4qKLI=", + "owner": "rust-analyzer", + "repo": "rust-analyzer", + "rev": "0f8c96c92689af8378dbe9f466c6bf15a3a27458", + "type": "github" + }, + "original": { + "owner": "rust-analyzer", + "ref": "nightly", + "repo": "rust-analyzer", + "type": "github" + } + }, + "utils": { + "locked": { + "lastModified": 1638122382, + "narHash": "sha256-sQzZzAbvKEqN9s0bzWuYmRaA03v40gaJ4+iL1LXjaeI=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "74f7e4319258e287b0f9cb95426c9853b282730b", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + } + }, + "root": "root", + "version": 7 +} diff --git a/libp2p-networking/flake.nix b/libp2p-networking/flake.nix new file mode 100644 index 0000000000..128489fb16 --- /dev/null +++ b/libp2p-networking/flake.nix @@ -0,0 +1,73 @@ +{ + description = "PhaseLock consensus library"; + + inputs = { + nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable"; + utils.url = "github:numtide/flake-utils"; + flake-compat = { + url = "github:edolstra/flake-compat"; + flake = false; + }; + crate2nix = { + url = "github:balsoft/crate2nix/balsoft/fix-broken-ifd"; + flake = false; + }; + fenix = { + url = "github:nix-community/fenix"; + inputs.nixpkgs.follows = "nixpkgs"; + }; + }; + + outputs = { self, nixpkgs, flake-compat, utils, crate2nix, fenix }: + utils.lib.eachDefaultSystem (system: + let + fenixPackage = fenix.packages.${system}.stable.withComponents [ "cargo" "clippy" "rust-src" "rustc" "rustfmt"]; + rustOverlay = final: prev: + { + inherit fenixPackage; + rustc = fenixPackage; + cargo = fenixPackage; + rust-src = fenixPackage; + }; + + pkgs = import nixpkgs { + inherit system; + overlays = [ + rustOverlay + ]; + }; + + # DON'T FORGET TO PUT YOUR PACKAGE NAME HERE, REMOVING `throw` + crateName = "networking-demo"; + + inherit (import "${crate2nix}/tools.nix" { inherit pkgs; }) + generatedCargoNix; + + project = import + (generatedCargoNix { + name = crateName; + src = ./.; + }) + { + inherit pkgs; + defaultCrateOverrides = pkgs.defaultCrateOverrides // { + # Crate dependency overrides go here + }; + }; + + in + { + packages.${crateName} = project.rootCrate.build; + packages.tests.${crateName} = project.rootCrate.build.override { + runTests = true; + }; + + defaultPackage = self.packages.${system}.${crateName}; + + devShell = pkgs.mkShell { + inputsFrom = builtins.attrValues self.packages.${system}; + buildInputs = + with pkgs; [ cargo-audit nixpkgs-fmt git-chglog fenix.packages.${system}.rust-analyzer fenixPackage ]; + }; + }); +} diff --git a/libp2p-networking/shell.nix b/libp2p-networking/shell.nix new file mode 100644 index 0000000000..741471c4c6 --- /dev/null +++ b/libp2p-networking/shell.nix @@ -0,0 +1,14 @@ +(import + ( + let + lock = builtins.fromJSON (builtins.readFile ./flake.lock); + in + fetchTarball { + url = "https://github.com/edolstra/flake-compat/archive/${lock.nodes.flake-compat.locked.rev}.tar.gz"; + sha256 = lock.nodes.flake-compat.locked.narHash; + } + ) + { + src = ./.; + }).shellNix.default + diff --git a/libp2p-networking/src/lib.rs b/libp2p-networking/src/lib.rs new file mode 100644 index 0000000000..1b4a90c938 --- /dev/null +++ b/libp2p-networking/src/lib.rs @@ -0,0 +1,8 @@ +#[cfg(test)] +mod tests { + #[test] + fn it_works() { + let result = 2 + 2; + assert_eq!(result, 4); + } +} From 16cb6d3fb7f063a56d44de059bc63b7d12dc19fc Mon Sep 17 00:00:00 2001 From: Nathan McCarty Date: Tue, 11 Jan 2022 12:46:16 -0500 Subject: [PATCH 002/107] Add binary target and set version --- libp2p-networking/Cargo.lock | 136 ++++++++++++++++++++++++++- libp2p-networking/Cargo.toml | 3 +- libp2p-networking/flake.nix | 2 +- libp2p-networking/src/bin/clichat.rs | 6 ++ 4 files changed, 144 insertions(+), 3 deletions(-) create mode 100644 libp2p-networking/src/bin/clichat.rs diff --git a/libp2p-networking/Cargo.lock b/libp2p-networking/Cargo.lock index 52aff3963c..a835c43b2c 100644 --- a/libp2p-networking/Cargo.lock +++ b/libp2p-networking/Cargo.lock @@ -2,6 +2,15 @@ # It is not intended for manual editing. version = 3 +[[package]] +name = "addr2line" +version = "0.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9ecd88a8c8378ca913a680cd98f0f13ac67383d35993f86c90a70e3f137816b" +dependencies = [ + "gimli", +] + [[package]] name = "adler" version = "1.0.2" @@ -257,6 +266,21 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a" +[[package]] +name = "backtrace" +version = "0.3.63" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "321629d8ba6513061f26707241fa9bc89524ff1cd7a915a97ef0c62c666ce1b6" +dependencies = [ + "addr2line", + "cc", + "cfg-if", + "libc", + "miniz_oxide", + "object", + "rustc-demangle", +] + [[package]] name = "base64" version = "0.13.0" @@ -392,6 +416,33 @@ dependencies = [ "generic-array", ] +[[package]] +name = "color-eyre" +version = "0.5.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f1885697ee8a177096d42f158922251a41973117f6d8a234cee94b9509157b7" +dependencies = [ + "backtrace", + "color-spantrace", + "eyre", + "indenter", + "once_cell", + "owo-colors", + "tracing-error", +] + +[[package]] +name = "color-spantrace" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6eee477a4a8a72f4addd4de416eb56d54bc307b284d6601bafdee1f4ea462d1" +dependencies = [ + "once_cell", + "owo-colors", + "tracing-core", + "tracing-error", +] + [[package]] name = "concurrent-queue" version = "1.2.2" @@ -572,6 +623,16 @@ version = "2.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f7531096570974c3a9dcf9e4b8e1cede1ec26cf5046219fb3b9d897503b9be59" +[[package]] +name = "eyre" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "221239d1d5ea86bf5d6f91c9d6bc3646ffe471b08ff9b0f91c44f115ac969d2b" +dependencies = [ + "indenter", + "once_cell", +] + [[package]] name = "fastrand" version = "1.6.0" @@ -780,6 +841,12 @@ dependencies = [ "polyval", ] +[[package]] +name = "gimli" +version = "0.26.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78cc372d058dcf6d5ecd98510e7fbc9e5aec4d21de70f65fea8fecebcd881bd4" + [[package]] name = "gloo-timers" version = "0.2.2" @@ -918,6 +985,12 @@ dependencies = [ "winapi", ] +[[package]] +name = "indenter" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce23b50ad8242c51a442f3ff322d56b02f08852c77e4c0b4d3fd684abc89c683" + [[package]] name = "indexmap" version = "1.8.0" @@ -1686,8 +1759,9 @@ dependencies = [ [[package]] name = "networking-demo" -version = "0.1.0" +version = "0.0.0" dependencies = [ + "color-eyre", "libp2p", "snafu", "tracing", @@ -1709,6 +1783,15 @@ dependencies = [ "libc", ] +[[package]] +name = "object" +version = "0.27.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67ac1d3f9a1d3616fd9a60c8d74296f22406a238b6a72f5cc1e6f314df4ffbf9" +dependencies = [ + "memchr", +] + [[package]] name = "once_cell" version = "1.9.0" @@ -1753,6 +1836,12 @@ dependencies = [ "stable_deref_trait", ] +[[package]] +name = "owo-colors" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2386b4ebe91c2f7f51082d4cefa145d030e33a1842a96b12e4885cc3c01f7a55" + [[package]] name = "parity-send-wrapper" version = "0.1.0" @@ -2184,6 +2273,12 @@ dependencies = [ "winapi", ] +[[package]] +name = "rustc-demangle" +version = "0.1.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ef03e0a2b150c7a90d01faf6254c9c48a41e95fb2a8c2ac1c6f0d2b9aefc342" + [[package]] name = "rustc_version" version = "0.3.3" @@ -2317,6 +2412,15 @@ dependencies = [ "opaque-debug", ] +[[package]] +name = "sharded-slab" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "900fba806f70c630b0a382d0d825e17a0f19fcd059a2ade1ff237bcddf446b31" +dependencies = [ + "lazy_static", +] + [[package]] name = "signature" version = "1.5.0" @@ -2493,6 +2597,15 @@ dependencies = [ "syn", ] +[[package]] +name = "thread_local" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8018d24e04c95ac8790716a5987d0fec4f8b27249ffa0f7d33f1369bdfb88cbd" +dependencies = [ + "once_cell", +] + [[package]] name = "tinyvec" version = "1.5.1" @@ -2549,6 +2662,27 @@ dependencies = [ "lazy_static", ] +[[package]] +name = "tracing-error" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4d7c0b83d4a500748fa5879461652b361edf5c9d51ede2a2ac03875ca185e24" +dependencies = [ + "tracing", + "tracing-subscriber", +] + +[[package]] +name = "tracing-subscriber" +version = "0.2.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e0d2eaa99c3c2e41547cfa109e910a68ea03823cccad4a0525dcbc9b01e8c71" +dependencies = [ + "sharded-slab", + "thread_local", + "tracing-core", +] + [[package]] name = "trust-dns-proto" version = "0.20.3" diff --git a/libp2p-networking/Cargo.toml b/libp2p-networking/Cargo.toml index fac72a9d4a..1c216d7a65 100644 --- a/libp2p-networking/Cargo.toml +++ b/libp2p-networking/Cargo.toml @@ -1,11 +1,12 @@ [package] name = "networking-demo" -version = "0.1.0" +version = "0.0.0" edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] +color-eyre = "0.5.11" libp2p = "0.41.1" snafu = "0.7.0" tracing = "0.1.29" diff --git a/libp2p-networking/flake.nix b/libp2p-networking/flake.nix index 128489fb16..dcfb9531e3 100644 --- a/libp2p-networking/flake.nix +++ b/libp2p-networking/flake.nix @@ -21,7 +21,7 @@ outputs = { self, nixpkgs, flake-compat, utils, crate2nix, fenix }: utils.lib.eachDefaultSystem (system: let - fenixPackage = fenix.packages.${system}.stable.withComponents [ "cargo" "clippy" "rust-src" "rustc" "rustfmt"]; + fenixPackage = fenix.packages.${system}.stable.withComponents [ "cargo" "clippy" "rust-src" "rustc" "rustfmt" ]; rustOverlay = final: prev: { inherit fenixPackage; diff --git a/libp2p-networking/src/bin/clichat.rs b/libp2p-networking/src/bin/clichat.rs new file mode 100644 index 0000000000..9b05bf9dc0 --- /dev/null +++ b/libp2p-networking/src/bin/clichat.rs @@ -0,0 +1,6 @@ +use color_eyre::eyre::{eyre, Result}; + +fn main() -> Result<()> { + color_eyre::install()?; + Err(eyre!("Not implemented yet")) +} From 776b4765f8baebffd12c056b4751d2f2e8d3d36b Mon Sep 17 00:00:00 2001 From: Nathan McCarty Date: Tue, 11 Jan 2022 12:52:36 -0500 Subject: [PATCH 003/107] Add protobuf to nix flake so we can build libp2p --- libp2p-networking/.envrc | 5 +++++ libp2p-networking/flake.nix | 5 ++++- 2 files changed, 9 insertions(+), 1 deletion(-) create mode 100644 libp2p-networking/.envrc diff --git a/libp2p-networking/.envrc b/libp2p-networking/.envrc new file mode 100644 index 0000000000..261d630018 --- /dev/null +++ b/libp2p-networking/.envrc @@ -0,0 +1,5 @@ +# reload when these files change +watch_file flake.nix +watch_file flake.lock +# load the flake devShell +eval "$(nix print-dev-env)" diff --git a/libp2p-networking/flake.nix b/libp2p-networking/flake.nix index dcfb9531e3..d5611d5ae9 100644 --- a/libp2p-networking/flake.nix +++ b/libp2p-networking/flake.nix @@ -52,6 +52,9 @@ inherit pkgs; defaultCrateOverrides = pkgs.defaultCrateOverrides // { # Crate dependency overrides go here + prost-build = attrs: { + buildInputs = [ pkgs.protobuf ]; + }; }; }; @@ -67,7 +70,7 @@ devShell = pkgs.mkShell { inputsFrom = builtins.attrValues self.packages.${system}; buildInputs = - with pkgs; [ cargo-audit nixpkgs-fmt git-chglog fenix.packages.${system}.rust-analyzer fenixPackage ]; + with pkgs; [ cargo-audit nixpkgs-fmt git-chglog fenix.packages.${system}.rust-analyzer fenixPackage protobuf ]; }; }); } From c1c3c8f0173f2cf7b9e6aae3ed07de677db309f4 Mon Sep 17 00:00:00 2001 From: Justin Restivo Date: Wed, 12 Jan 2022 11:51:15 -0500 Subject: [PATCH 004/107] feat: build with nix on darwin --- libp2p-networking/flake.nix | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/libp2p-networking/flake.nix b/libp2p-networking/flake.nix index d5611d5ae9..2d78051efb 100644 --- a/libp2p-networking/flake.nix +++ b/libp2p-networking/flake.nix @@ -54,6 +54,16 @@ # Crate dependency overrides go here prost-build = attrs: { buildInputs = [ pkgs.protobuf ]; + PROTOC = "${pkgs.protobuf}/bin/protoc"; + PROTOC_INCLUDE = "${pkgs.protobuf}/include"; + }; + libp2p-core = attrs: { + buildInputs = [ pkgs.protobuf ]; + PROTOC = "${pkgs.protobuf}/bin/protoc"; + PROTOC_INCLUDE = "${pkgs.protobuf}/include"; + }; + networking-demo = attrs: { + buildInputs = (attrs.buildInputs or [ ]) ++ (pkgs.lib.optionals pkgs.stdenv.isDarwin [ pkgs.darwin.apple_sdk.frameworks.Security ]); }; }; }; @@ -61,7 +71,7 @@ in { packages.${crateName} = project.rootCrate.build; - packages.tests.${crateName} = project.rootCrate.build.override { + checks.${crateName} = project.rootCrate.build.override { runTests = true; }; @@ -70,7 +80,8 @@ devShell = pkgs.mkShell { inputsFrom = builtins.attrValues self.packages.${system}; buildInputs = - with pkgs; [ cargo-audit nixpkgs-fmt git-chglog fenix.packages.${system}.rust-analyzer fenixPackage protobuf ]; + with pkgs; [ cargo-audit nixpkgs-fmt git-chglog fenix.packages.${system}.rust-analyzer fenixPackage protobuf] + ++ lib.optionals stdenv.isDarwin [ darwin.apple_sdk.frameworks.Security ]; }; }); } From e55d9946a92b62a0f2a8cc33a7e5592184f59e58 Mon Sep 17 00:00:00 2001 From: Nathan McCarty Date: Tue, 11 Jan 2022 15:49:34 -0500 Subject: [PATCH 005/107] Really basic boiler plate --- libp2p-networking/Cargo.lock | 53 ++++++++++++++++++++++++++++ libp2p-networking/Cargo.toml | 1 + libp2p-networking/src/bin/clichat.rs | 20 +++++++++++ 3 files changed, 74 insertions(+) diff --git a/libp2p-networking/Cargo.lock b/libp2p-networking/Cargo.lock index a835c43b2c..822ea235f8 100644 --- a/libp2p-networking/Cargo.lock +++ b/libp2p-networking/Cargo.lock @@ -370,6 +370,12 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c1db59621ec70f09c5e9b597b220c7a2b43611f4710dc03ceb8748637775692c" +[[package]] +name = "cassowary" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df8670b8c7b9dae1793364eafadf7239c40d669904660c5960d74cfd80b46a53" + [[package]] name = "cc" version = "1.0.72" @@ -1765,6 +1771,7 @@ dependencies = [ "libp2p", "snafu", "tracing", + "tui", ] [[package]] @@ -1783,6 +1790,12 @@ dependencies = [ "libc", ] +[[package]] +name = "numtoa" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8f8bdf33df195859076e54ab11ee78a1b208382d3a26ec40d142ffc1ecc49ef" + [[package]] name = "object" version = "0.27.1" @@ -2222,6 +2235,15 @@ dependencies = [ "bitflags", ] +[[package]] +name = "redox_termios" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8440d8acb4fd3d277125b4bd01a6f38aee8d814b3b5fc09b3f2b825d37d3fe8f" +dependencies = [ + "redox_syscall", +] + [[package]] name = "regex" version = "1.5.4" @@ -2577,6 +2599,18 @@ dependencies = [ "winapi", ] +[[package]] +name = "termion" +version = "1.5.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "077185e2eac69c3f8379a4298e1e07cd36beb962290d4a51199acf0fdc10607e" +dependencies = [ + "libc", + "numtoa", + "redox_syscall", + "redox_termios", +] + [[package]] name = "thiserror" version = "1.0.30" @@ -2726,6 +2760,19 @@ dependencies = [ "trust-dns-proto", ] +[[package]] +name = "tui" +version = "0.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "39c8ce4e27049eed97cfa363a5048b09d995e209994634a0efc26a14ab6c0c23" +dependencies = [ + "bitflags", + "cassowary", + "termion", + "unicode-segmentation", + "unicode-width", +] + [[package]] name = "typenum" version = "1.15.0" @@ -2771,6 +2818,12 @@ version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8895849a949e7845e06bd6dc1aa51731a103c42707010a5b591c0038fb73385b" +[[package]] +name = "unicode-width" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ed742d4ea2bd1176e236172c8429aaf54486e7ac098db29ffe6529e0ce50973" + [[package]] name = "unicode-xid" version = "0.2.2" diff --git a/libp2p-networking/Cargo.toml b/libp2p-networking/Cargo.toml index 1c216d7a65..d032e2c95b 100644 --- a/libp2p-networking/Cargo.toml +++ b/libp2p-networking/Cargo.toml @@ -10,3 +10,4 @@ color-eyre = "0.5.11" libp2p = "0.41.1" snafu = "0.7.0" tracing = "0.1.29" +tui = "0.16.0" diff --git a/libp2p-networking/src/bin/clichat.rs b/libp2p-networking/src/bin/clichat.rs index 9b05bf9dc0..33e4527cca 100644 --- a/libp2p-networking/src/bin/clichat.rs +++ b/libp2p-networking/src/bin/clichat.rs @@ -1,6 +1,26 @@ +use std::collections::VecDeque; + use color_eyre::eyre::{eyre, Result}; +#[derive(Debug, Clone)] +pub struct Message { + sender: String, + content: String, +} + fn main() -> Result<()> { color_eyre::install()?; + // Setup a ring buffer to hold messages, 25 of them should do for the demo + let mut buffer: VecDeque = VecDeque::new(); + // Put a few dummy messages in there so we can display something + buffer.push_back(Message { + sender: "Nathan".to_string(), + content: "Hello".to_string(), + }); + buffer.push_back(Message { + sender: "Justin".to_string(), + content: "hi!".to_string(), + }); + Err(eyre!("Not implemented yet")) } From 244762167f30bbe451569e6ccb573e203b38bc22 Mon Sep 17 00:00:00 2001 From: Nathan McCarty Date: Wed, 12 Jan 2022 12:44:06 -0500 Subject: [PATCH 006/107] Basic Skelton UI --- libp2p-networking/Cargo.lock | 142 +++++++++++++++++++++----- libp2p-networking/Cargo.toml | 4 +- libp2p-networking/src/bin/clichat.rs | 147 ++++++++++++++++++++++++++- 3 files changed, 259 insertions(+), 34 deletions(-) diff --git a/libp2p-networking/Cargo.lock b/libp2p-networking/Cargo.lock index 822ea235f8..343d6f8773 100644 --- a/libp2p-networking/Cargo.lock +++ b/libp2p-networking/Cargo.lock @@ -486,6 +486,56 @@ dependencies = [ "lazy_static", ] +[[package]] +name = "crossterm" +version = "0.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0ebde6a9dd5e331cd6c6f48253254d117642c31653baa475e394657c59c1f7d" +dependencies = [ + "bitflags", + "crossterm_winapi 0.8.0", + "libc", + "mio", + "parking_lot", + "signal-hook", + "signal-hook-mio", + "winapi", +] + +[[package]] +name = "crossterm" +version = "0.22.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c85525306c4291d1b73ce93c8acf9c339f9b213aef6c1d85c3830cbf1c16325c" +dependencies = [ + "bitflags", + "crossterm_winapi 0.9.0", + "libc", + "mio", + "parking_lot", + "signal-hook", + "signal-hook-mio", + "winapi", +] + +[[package]] +name = "crossterm_winapi" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a6966607622438301997d3dac0d2f6e9a90c68bb6bc1785ea98456ab93c0507" +dependencies = [ + "winapi", +] + +[[package]] +name = "crossterm_winapi" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2ae1b35a484aa10e07fe0638d02301c5ad24de82d310ccbd2f3693da5f09bf1c" +dependencies = [ + "winapi", +] + [[package]] name = "crunchy" version = "0.2.2" @@ -1698,6 +1748,28 @@ dependencies = [ "autocfg", ] +[[package]] +name = "mio" +version = "0.7.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8067b404fe97c70829f082dec8bcf4f71225d7eaea1d8645349cb76fa06205cc" +dependencies = [ + "libc", + "log", + "miow", + "ntapi", + "winapi", +] + +[[package]] +name = "miow" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9f1c5b025cda876f66ef43a113f91ebc9f4ccef34843000e0adf6ebbab84e21" +dependencies = [ + "winapi", +] + [[package]] name = "multiaddr" version = "0.13.0" @@ -1768,7 +1840,9 @@ name = "networking-demo" version = "0.0.0" dependencies = [ "color-eyre", + "crossterm 0.22.1", "libp2p", + "parking_lot", "snafu", "tracing", "tui", @@ -1780,6 +1854,15 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2bf50223579dc7cdcfb3bfcacf7069ff68243f8c363f62ffa99cf000a6b9c451" +[[package]] +name = "ntapi" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f6bb902e437b6d86e03cce10a7e2af662292c5dfef23b65899ea3ac9354ad44" +dependencies = [ + "winapi", +] + [[package]] name = "num_cpus" version = "1.13.1" @@ -1790,12 +1873,6 @@ dependencies = [ "libc", ] -[[package]] -name = "numtoa" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8f8bdf33df195859076e54ab11ee78a1b208382d3a26ec40d142ffc1ecc49ef" - [[package]] name = "object" version = "0.27.1" @@ -2235,15 +2312,6 @@ dependencies = [ "bitflags", ] -[[package]] -name = "redox_termios" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8440d8acb4fd3d277125b4bd01a6f38aee8d814b3b5fc09b3f2b825d37d3fe8f" -dependencies = [ - "redox_syscall", -] - [[package]] name = "regex" version = "1.5.4" @@ -2443,6 +2511,36 @@ dependencies = [ "lazy_static", ] +[[package]] +name = "signal-hook" +version = "0.3.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "647c97df271007dcea485bb74ffdb57f2e683f1306c854f468a0c244badabf2d" +dependencies = [ + "libc", + "signal-hook-registry", +] + +[[package]] +name = "signal-hook-mio" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29fd5867f1c4f2c5be079aee7a2adf1152ebb04a4bc4d341f504b7dece607ed4" +dependencies = [ + "libc", + "mio", + "signal-hook", +] + +[[package]] +name = "signal-hook-registry" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e51e73328dc4ac0c7ccbda3a494dfa03df1de2f46018127f60c693f2648455b0" +dependencies = [ + "libc", +] + [[package]] name = "signature" version = "1.5.0" @@ -2599,18 +2697,6 @@ dependencies = [ "winapi", ] -[[package]] -name = "termion" -version = "1.5.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "077185e2eac69c3f8379a4298e1e07cd36beb962290d4a51199acf0fdc10607e" -dependencies = [ - "libc", - "numtoa", - "redox_syscall", - "redox_termios", -] - [[package]] name = "thiserror" version = "1.0.30" @@ -2768,7 +2854,7 @@ checksum = "39c8ce4e27049eed97cfa363a5048b09d995e209994634a0efc26a14ab6c0c23" dependencies = [ "bitflags", "cassowary", - "termion", + "crossterm 0.20.0", "unicode-segmentation", "unicode-width", ] diff --git a/libp2p-networking/Cargo.toml b/libp2p-networking/Cargo.toml index d032e2c95b..981851b441 100644 --- a/libp2p-networking/Cargo.toml +++ b/libp2p-networking/Cargo.toml @@ -7,7 +7,9 @@ edition = "2021" [dependencies] color-eyre = "0.5.11" +crossterm = "0.22.1" libp2p = "0.41.1" +parking_lot = "0.11.2" snafu = "0.7.0" tracing = "0.1.29" -tui = "0.16.0" +tui = { version = "0.16.0", features = ["crossterm"], default-features = false } diff --git a/libp2p-networking/src/bin/clichat.rs b/libp2p-networking/src/bin/clichat.rs index 33e4527cca..47878218d7 100644 --- a/libp2p-networking/src/bin/clichat.rs +++ b/libp2p-networking/src/bin/clichat.rs @@ -1,6 +1,21 @@ use std::collections::VecDeque; +use std::sync::Arc; -use color_eyre::eyre::{eyre, Result}; +use color_eyre::eyre::{eyre, Result, WrapErr}; +use crossterm::{ + event::{self, DisableMouseCapture, EnableMouseCapture, Event, KeyCode}, + execute, + terminal::{disable_raw_mode, enable_raw_mode, EnterAlternateScreen, LeaveAlternateScreen}, +}; + +use parking_lot::Mutex; +use tui::{ + backend::{Backend, CrosstermBackend}, + layout::{Constraint, Layout}, + style::{Color, Modifier, Style}, + widgets::{Block, Borders, Cell, Row, Table, TableState}, + Frame, Terminal, +}; #[derive(Debug, Clone)] pub struct Message { @@ -8,19 +23,141 @@ pub struct Message { content: String, } +/// Struct for the TUI app +struct TableApp { + state: TableState, + message_buffer: Arc>>, +} + +impl TableApp { + pub fn new(message_buffer: Arc>>) -> Self { + Self { + state: TableState::default(), + message_buffer, + } + } + pub fn next(&mut self) { + let buffer_handle = self.message_buffer.lock(); + let i = match self.state.selected() { + Some(i) => { + if i >= buffer_handle.len() { + 0 + } else { + i + i + } + } + None => 0, + }; + self.state.select(Some(i)); + } + + pub fn previous(&mut self) { + let buffer_handle = self.message_buffer.lock(); + let i = match self.state.selected() { + Some(i) => { + if i == 0 { + buffer_handle.len() - 1 + } else { + i - 1 + } + } + None => 0, + }; + self.state.select(Some(i)); + } +} + fn main() -> Result<()> { color_eyre::install()?; // Setup a ring buffer to hold messages, 25 of them should do for the demo - let mut buffer: VecDeque = VecDeque::new(); + let message_buffer: Arc>> = Arc::new(Mutex::new(VecDeque::new())); // Put a few dummy messages in there so we can display something - buffer.push_back(Message { + let mut buffer_handle = message_buffer.lock(); + buffer_handle.push_back(Message { sender: "Nathan".to_string(), content: "Hello".to_string(), }); - buffer.push_back(Message { + buffer_handle.push_back(Message { sender: "Justin".to_string(), content: "hi!".to_string(), }); + std::mem::drop(buffer_handle); + // -- Setup the TUI + // Start by setting up the terminal + enable_raw_mode()?; // Turn on raw mode + // Get stdio and configure the terminal + let mut stdout = std::io::stdout(); + execute!(stdout, EnterAlternateScreen, EnableMouseCapture)?; + let backend = CrosstermBackend::new(stdout); + let mut terminal = Terminal::new(backend)?; + // -- Create the app and run it + let app = TableApp::new(message_buffer.clone()); + let res = run_app(&mut terminal, app); + // -- Tear down the TUI, and restore the terminal + disable_raw_mode()?; + execute!( + terminal.backend_mut(), + LeaveAlternateScreen, + DisableMouseCapture + )?; + terminal.show_cursor()?; + // Print the messages + let messages = message_buffer.lock().iter().cloned().collect::>(); + println!("{:?}", messages); + res +} + +fn run_app(terminal: &mut Terminal, mut app: TableApp) -> Result<()> { + loop { + terminal + .draw(|f| ui(f, &mut app).expect("Failed to draw UI")) + .context("Failed drawing application")?; + match event::read().context("Failed to read event")? { + Event::Key(key) => match key.code { + KeyCode::Char('q') => return Ok(()), + KeyCode::Down => app.next(), + KeyCode::Up => app.previous(), + _ => {} + }, + _ => (), + } + } +} + +fn ui(f: &mut Frame, app: &mut TableApp) -> Result<()> { + let rects = Layout::default() + .constraints([Constraint::Percentage(100)].as_ref()) + .margin(5) + .split(f.size()); + + // Styles + let selected_style = Style::default().add_modifier(Modifier::REVERSED); + let normal_style = Style::default().bg(Color::Blue); + // Setup header + let header_cells = ["Sender", "Message"] + .iter() + .map(|h| Cell::from(*h).style(Style::default().fg(Color::Red))); + let header = Row::new(header_cells).style(normal_style); + // Generate the rows + let handle = app.message_buffer.lock(); // Lock the messages mutex + let rows = handle.iter().map(|message| { + let sender = message.sender.clone(); + let content = message.content.clone(); + let height = content.chars().filter(|c| *c == '\n').count() + 1; + let cells = vec![Cell::from(sender), Cell::from(content)]; + Row::new(cells).height(height as u16) + }); + let table = Table::new(rows) + .header(header) + .block(Block::default().borders(Borders::ALL).title("Messages")) + .highlight_style(selected_style) + .highlight_symbol(">> ") + .widths(&[ + Constraint::Percentage(50), + Constraint::Length(30), + Constraint::Min(10), + ]); + f.render_stateful_widget(table, rects[0], &mut app.state); - Err(eyre!("Not implemented yet")) + Ok(()) } From ad61734a93fea81634481cac286b6f9182d0f72d Mon Sep 17 00:00:00 2001 From: Nathan McCarty Date: Wed, 12 Jan 2022 13:06:30 -0500 Subject: [PATCH 007/107] Fix wrap around --- libp2p-networking/src/bin/clichat.rs | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/libp2p-networking/src/bin/clichat.rs b/libp2p-networking/src/bin/clichat.rs index 47878218d7..82517009e3 100644 --- a/libp2p-networking/src/bin/clichat.rs +++ b/libp2p-networking/src/bin/clichat.rs @@ -38,17 +38,8 @@ impl TableApp { } pub fn next(&mut self) { let buffer_handle = self.message_buffer.lock(); - let i = match self.state.selected() { - Some(i) => { - if i >= buffer_handle.len() { - 0 - } else { - i + i - } - } - None => 0, - }; - self.state.select(Some(i)); + let i = self.state.selected().unwrap_or(0) + 1; + self.state.select(Some(i % buffer_handle.len())); } pub fn previous(&mut self) { @@ -81,6 +72,14 @@ fn main() -> Result<()> { sender: "Justin".to_string(), content: "hi!".to_string(), }); + buffer_handle.push_back(Message { + sender: "Joe".to_string(), + content: "test".to_string(), + }); + buffer_handle.push_back(Message { + sender: "John".to_string(), + content: "test 2".to_string(), + }); std::mem::drop(buffer_handle); // -- Setup the TUI // Start by setting up the terminal From 26a7d3d86e11b81a41b41f0de6717dc7d86013ee Mon Sep 17 00:00:00 2001 From: Nathan McCarty Date: Wed, 12 Jan 2022 13:25:43 -0500 Subject: [PATCH 008/107] Basic networking skeleton and clippy --- libp2p-networking/Cargo.lock | 23 ++++++++++ libp2p-networking/Cargo.toml | 3 ++ libp2p-networking/src/bin/clichat.rs | 15 ++++--- libp2p-networking/src/lib.rs | 66 +++++++++++++++++++++++++--- 4 files changed, 95 insertions(+), 12 deletions(-) diff --git a/libp2p-networking/Cargo.lock b/libp2p-networking/Cargo.lock index 343d6f8773..bc06931007 100644 --- a/libp2p-networking/Cargo.lock +++ b/libp2p-networking/Cargo.lock @@ -96,6 +96,16 @@ version = "0.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e22d1f4b888c298a027c99dc9048015fac177587de20fc30232a057dfbe24a21" +[[package]] +name = "async-attributes" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a3203e79f4dd9bdda415ed03cf14dae5a2bf775c683a00f94e9cd1faf0f596e5" +dependencies = [ + "quote", + "syn", +] + [[package]] name = "async-channel" version = "1.6.1" @@ -180,6 +190,7 @@ version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f8056f1455169ab86dd47b47391e4ab0cbd25410a70e9fe675544f49bafaf952" dependencies = [ + "async-attributes", "async-channel", "async-global-executor", "async-io", @@ -293,6 +304,15 @@ version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "50ae17cabbc8a38a1e3e4c1a6a664e9a09672dc14d0896fa8d865d3a5a446b07" +[[package]] +name = "bincode" +version = "1.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1f45e9417d87227c7a56d22e471c6206462cba514c7590c09aff4cf6d1ddcad" +dependencies = [ + "serde", +] + [[package]] name = "bitflags" version = "1.3.2" @@ -1839,10 +1859,13 @@ dependencies = [ name = "networking-demo" version = "0.0.0" dependencies = [ + "async-std", + "bincode", "color-eyre", "crossterm 0.22.1", "libp2p", "parking_lot", + "serde", "snafu", "tracing", "tui", diff --git a/libp2p-networking/Cargo.toml b/libp2p-networking/Cargo.toml index 981851b441..20b07b7f1b 100644 --- a/libp2p-networking/Cargo.toml +++ b/libp2p-networking/Cargo.toml @@ -6,10 +6,13 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] +async-std = { version = "1.10.0", features = ["attributes"] } +bincode = "1.3.3" color-eyre = "0.5.11" crossterm = "0.22.1" libp2p = "0.41.1" parking_lot = "0.11.2" +serde = { version = "1.0.133", features = ["derive"] } snafu = "0.7.0" tracing = "0.1.29" tui = { version = "0.16.0", features = ["crossterm"], default-features = false } diff --git a/libp2p-networking/src/bin/clichat.rs b/libp2p-networking/src/bin/clichat.rs index 82517009e3..37107cac45 100644 --- a/libp2p-networking/src/bin/clichat.rs +++ b/libp2p-networking/src/bin/clichat.rs @@ -1,7 +1,7 @@ use std::collections::VecDeque; use std::sync::Arc; -use color_eyre::eyre::{eyre, Result, WrapErr}; +use color_eyre::eyre::{Result, WrapErr}; use crossterm::{ event::{self, DisableMouseCapture, EnableMouseCapture, Event, KeyCode}, execute, @@ -58,8 +58,12 @@ impl TableApp { } } -fn main() -> Result<()> { +#[async_std::main] +async fn main() -> Result<()> { color_eyre::install()?; + // -- Spin up the network connection + + // -- Spin up the UI // Setup a ring buffer to hold messages, 25 of them should do for the demo let message_buffer: Arc>> = Arc::new(Mutex::new(VecDeque::new())); // Put a few dummy messages in there so we can display something @@ -111,14 +115,13 @@ fn run_app(terminal: &mut Terminal, mut app: TableApp) -> Result< terminal .draw(|f| ui(f, &mut app).expect("Failed to draw UI")) .context("Failed drawing application")?; - match event::read().context("Failed to read event")? { - Event::Key(key) => match key.code { + if let Event::Key(key) = event::read().context("Failed to read event")? { + match key.code { KeyCode::Char('q') => return Ok(()), KeyCode::Down => app.next(), KeyCode::Up => app.previous(), _ => {} - }, - _ => (), + } } } } diff --git a/libp2p-networking/src/lib.rs b/libp2p-networking/src/lib.rs index 1b4a90c938..e3fad4e232 100644 --- a/libp2p-networking/src/lib.rs +++ b/libp2p-networking/src/lib.rs @@ -1,8 +1,62 @@ -#[cfg(test)] -mod tests { - #[test] - fn it_works() { - let result = 2 + 2; - assert_eq!(result, 4); +#![warn( + clippy::all, + clippy::pedantic, + rust_2018_idioms, + // missing_docs, + // clippy::missing_docs_in_private_items, + clippy::panic +)] +#![allow( + clippy::option_if_let_else, + clippy::must_use_candidate, + clippy::module_name_repetitions, + clippy::similar_names, + clippy::unused_self +)] + +use std::marker::PhantomData; + +use libp2p::{ + gossipsub::{Gossipsub, GossipsubEvent}, + identify::{Identify, IdentifyEvent}, + kad::{store::MemoryStore, Kademlia, KademliaEvent}, + NetworkBehaviour, +}; + +#[derive(NetworkBehaviour)] +#[behaviour(out_event = "NetworkEvent")] +#[behaviour(event_process = false)] +pub struct NetworkDef { + pub gossipsub: Gossipsub, + pub kadem: Kademlia, + pub identity: Identify, +} + +#[derive(Debug)] +pub enum NetworkEvent { + Gossip(GossipsubEvent), + Kadem(KademliaEvent), + Ident(IdentifyEvent), +} + +impl From for NetworkEvent { + fn from(source: IdentifyEvent) -> Self { + NetworkEvent::Ident(source) + } +} + +impl From for NetworkEvent { + fn from(source: KademliaEvent) -> Self { + NetworkEvent::Kadem(source) } } + +impl From for NetworkEvent { + fn from(source: GossipsubEvent) -> Self { + NetworkEvent::Gossip(source) + } +} + +pub struct Network { + _phantom: PhantomData, +} From 024634c1ff9ca3244760e11c2854573e5c5e8b1c Mon Sep 17 00:00:00 2001 From: Nathan McCarty Date: Wed, 12 Jan 2022 13:40:08 -0500 Subject: [PATCH 009/107] Setup tracing --- libp2p-networking/Cargo.lock | 112 ++++++++++++++++++++++++- libp2p-networking/Cargo.toml | 2 + libp2p-networking/src/bin/clichat.rs | 2 + libp2p-networking/src/lib.rs | 2 + libp2p-networking/src/tracing_setup.rs | 107 +++++++++++++++++++++++ 5 files changed, 221 insertions(+), 4 deletions(-) create mode 100644 libp2p-networking/src/tracing_setup.rs diff --git a/libp2p-networking/Cargo.lock b/libp2p-networking/Cargo.lock index bc06931007..cbd66c707a 100644 --- a/libp2p-networking/Cargo.lock +++ b/libp2p-networking/Cargo.lock @@ -72,6 +72,15 @@ dependencies = [ "memchr", ] +[[package]] +name = "ansi_term" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d52a9bb7ec0cf484c551830a7ce27bd20d67eac647e1befb56b0be4ee39a55d2" +dependencies = [ + "winapi", +] + [[package]] name = "anyhow" version = "1.0.52" @@ -454,7 +463,7 @@ dependencies = [ "indenter", "once_cell", "owo-colors", - "tracing-error", + "tracing-error 0.1.2", ] [[package]] @@ -466,7 +475,7 @@ dependencies = [ "once_cell", "owo-colors", "tracing-core", - "tracing-error", + "tracing-error 0.1.2", ] [[package]] @@ -1119,6 +1128,12 @@ version = "0.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b71991ff56294aa922b450139ee08b3bfc70982c6b2c7562771375cf73542dd4" +[[package]] +name = "itoa" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1aab8fc367588b89dcee83ab0fd66b72b50b72fa1904d7095045ace2b0c81c35" + [[package]] name = "js-sys" version = "0.3.55" @@ -1746,6 +1761,15 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ffbee8634e0d45d258acb448e7eaab3fce7a0a467395d4d9f228e3c1f01fb2e4" +[[package]] +name = "matchers" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8263075bb86c5a1b1427b5ae862e8889656f126e9f77c484496e8b47cf5c5558" +dependencies = [ + "regex-automata", +] + [[package]] name = "matches" version = "0.1.9" @@ -1868,6 +1892,8 @@ dependencies = [ "serde", "snafu", "tracing", + "tracing-error 0.2.0", + "tracing-subscriber 0.3.5", "tui", ] @@ -1924,7 +1950,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7337d80c23c2d8b1349563981bc4fb531220733743ba8115454a67b181173f0d" dependencies = [ "dtoa", - "itoa", + "itoa 0.4.8", "open-metrics-client-derive-text-encode", "owning_ref", ] @@ -2346,6 +2372,15 @@ dependencies = [ "regex-syntax", ] +[[package]] +name = "regex-automata" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132" +dependencies = [ + "regex-syntax", +] + [[package]] name = "regex-syntax" version = "0.6.25" @@ -2424,6 +2459,12 @@ dependencies = [ "static_assertions", ] +[[package]] +name = "ryu" +version = "1.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73b4b750c782965c211b42f022f59af1fbceabdd026623714f104152f1ec149f" + [[package]] name = "salsa20" version = "0.9.0" @@ -2487,6 +2528,17 @@ dependencies = [ "syn", ] +[[package]] +name = "serde_json" +version = "1.0.74" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee2bb9cd061c5865d345bb02ca49fcef1391741b672b54a0bf7b679badec3142" +dependencies = [ + "itoa 1.0.1", + "ryu", + "serde", +] + [[package]] name = "sha-1" version = "0.9.8" @@ -2812,7 +2864,38 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b4d7c0b83d4a500748fa5879461652b361edf5c9d51ede2a2ac03875ca185e24" dependencies = [ "tracing", - "tracing-subscriber", + "tracing-subscriber 0.2.25", +] + +[[package]] +name = "tracing-error" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d686ec1c0f384b1277f097b2f279a2ecc11afe8c133c1aabf036a27cb4cd206e" +dependencies = [ + "tracing", + "tracing-subscriber 0.3.5", +] + +[[package]] +name = "tracing-log" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a6923477a48e41c1951f1999ef8bb5a3023eb723ceadafe78ffb65dc366761e3" +dependencies = [ + "lazy_static", + "log", + "tracing-core", +] + +[[package]] +name = "tracing-serde" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fb65ea441fbb84f9f6748fd496cf7f63ec9af5bca94dd86456978d055e8eb28b" +dependencies = [ + "serde", + "tracing-core", ] [[package]] @@ -2826,6 +2909,27 @@ dependencies = [ "tracing-core", ] +[[package]] +name = "tracing-subscriber" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d81bfa81424cc98cb034b837c985b7a290f592e5b4322f353f94a0ab0f9f594" +dependencies = [ + "ansi_term", + "lazy_static", + "matchers", + "regex", + "serde", + "serde_json", + "sharded-slab", + "smallvec", + "thread_local", + "tracing", + "tracing-core", + "tracing-log", + "tracing-serde", +] + [[package]] name = "trust-dns-proto" version = "0.20.3" diff --git a/libp2p-networking/Cargo.toml b/libp2p-networking/Cargo.toml index 20b07b7f1b..5bf4d9d513 100644 --- a/libp2p-networking/Cargo.toml +++ b/libp2p-networking/Cargo.toml @@ -15,4 +15,6 @@ parking_lot = "0.11.2" serde = { version = "1.0.133", features = ["derive"] } snafu = "0.7.0" tracing = "0.1.29" +tracing-error = "0.2.0" +tracing-subscriber = { version = "0.3.5", features = ["env-filter", "json"] } tui = { version = "0.16.0", features = ["crossterm"], default-features = false } diff --git a/libp2p-networking/src/bin/clichat.rs b/libp2p-networking/src/bin/clichat.rs index 37107cac45..2030570b30 100644 --- a/libp2p-networking/src/bin/clichat.rs +++ b/libp2p-networking/src/bin/clichat.rs @@ -60,7 +60,9 @@ impl TableApp { #[async_std::main] async fn main() -> Result<()> { + // -- Setup color_eyre and tracing color_eyre::install()?; + networking_demo::tracing_setup::setup_tracing(); // -- Spin up the network connection // -- Spin up the UI diff --git a/libp2p-networking/src/lib.rs b/libp2p-networking/src/lib.rs index e3fad4e232..896b2f561c 100644 --- a/libp2p-networking/src/lib.rs +++ b/libp2p-networking/src/lib.rs @@ -14,6 +14,8 @@ clippy::unused_self )] +pub mod tracing_setup; + use std::marker::PhantomData; use libp2p::{ diff --git a/libp2p-networking/src/tracing_setup.rs b/libp2p-networking/src/tracing_setup.rs new file mode 100644 index 0000000000..e3de37b2e4 --- /dev/null +++ b/libp2p-networking/src/tracing_setup.rs @@ -0,0 +1,107 @@ +#![allow(clippy::pedantic, clippy::panic)] +use std::env::{var, VarError}; +use tracing_error::ErrorLayer; +use tracing_subscriber::{ + fmt::{self, format::FmtSpan, writer::BoxMakeWriter}, + prelude::*, + EnvFilter, Registry, +}; + +fn parse_span_events() -> FmtSpan { + match var("RUST_LOG_SPAN_EVENTS") { + Ok(value) => value + .to_ascii_lowercase() + .split(',') + .map(|filter| match filter.trim() { + "new" => FmtSpan::NEW, + "enter" => FmtSpan::ENTER, + "exit" => FmtSpan::EXIT, + "close" => FmtSpan::CLOSE, + "active" => FmtSpan::ACTIVE, + "full" => FmtSpan::FULL, + _ => panic!( + "test-env-log: RUST_LOG_SPAN_EVENTS must contain filters separated by `,`.\n\t\ + For example: `active` or `new,close`\n\t\ + Supported filters: new, enter, exit, close, active, full\n\t\ + Got: {}", + value + ), + }) + .fold(FmtSpan::NONE, |acc, filter| filter | acc), + Err(VarError::NotUnicode(_)) => { + panic!("test-env-log: RUST_LOG_SPAN_EVENTS must contain a valid UTF-8 string") + } + Err(VarError::NotPresent) => FmtSpan::NONE, + } +} + +fn parse_writer() -> BoxMakeWriter { + let file = var("RUST_LOG_OUTPUT").map(|x| x.trim().to_lowercase()); + match file.as_deref() { + Ok("stderr") => BoxMakeWriter::new(std::io::stderr), + Ok("stdout") => BoxMakeWriter::new(std::io::stdout), + Ok(_) => panic!("Invalid RUST_LOG_OUTPUT value"), + Err(_) => BoxMakeWriter::new(std::io::stderr), + } +} + +fn internal_setup_tracing(writer: BoxMakeWriter) { + let internal_event_filter = parse_span_events(); + let fmt_env = var("RUST_LOG_FORMAT").map(|x| x.to_lowercase()); + match fmt_env.as_deref().map(|x| x.trim()) { + Ok("full") => { + let fmt_layer = fmt::Layer::default() + .with_span_events(internal_event_filter) + .with_writer(writer); + let _subscriber = Registry::default() + .with(EnvFilter::from_default_env()) + .with(ErrorLayer::default()) + .with(fmt_layer) + .init(); + } + Ok("json") => { + let fmt_layer = fmt::Layer::default() + .with_span_events(internal_event_filter) + .json() + .with_writer(writer); + let _subscriber = Registry::default() + .with(EnvFilter::from_default_env()) + .with(ErrorLayer::default()) + .with(fmt_layer) + .init(); + } + Ok("compact") => { + let fmt_layer = fmt::Layer::default() + .with_span_events(internal_event_filter) + .compact() + .with_writer(writer); + let _subscriber = Registry::default() + .with(EnvFilter::from_default_env()) + .with(ErrorLayer::default()) + .with(fmt_layer) + .init(); + } + _ => { + let fmt_layer = fmt::Layer::default() + .with_span_events(internal_event_filter) + .with_ansi(true) + .pretty() + .with_writer(writer); + let _subscriber = Registry::default() + .with(EnvFilter::from_default_env()) + .with(ErrorLayer::default()) + .with(fmt_layer) + .init(); + } + }; +} + +pub fn setup_tracing() { + let writer = parse_writer(); + internal_setup_tracing(writer); +} + +pub fn setup_tracing_test() { + let writer = BoxMakeWriter::new(fmt::writer::TestWriter::new()); + internal_setup_tracing(writer); +} From 8e20f97f7eed4a8e824c51bdb147be35d8fdb0e3 Mon Sep 17 00:00:00 2001 From: Nathan McCarty Date: Wed, 12 Jan 2022 13:58:43 -0500 Subject: [PATCH 010/107] Generate PeerId --- libp2p-networking/src/bin/clichat.rs | 11 ++++++++--- libp2p-networking/src/lib.rs | 26 +++++++++++++++++++++++++- 2 files changed, 33 insertions(+), 4 deletions(-) diff --git a/libp2p-networking/src/bin/clichat.rs b/libp2p-networking/src/bin/clichat.rs index 2030570b30..a010753394 100644 --- a/libp2p-networking/src/bin/clichat.rs +++ b/libp2p-networking/src/bin/clichat.rs @@ -1,5 +1,5 @@ -use std::collections::VecDeque; use std::sync::Arc; +use std::{collections::VecDeque, marker::PhantomData}; use color_eyre::eyre::{Result, WrapErr}; use crossterm::{ @@ -7,8 +7,9 @@ use crossterm::{ execute, terminal::{disable_raw_mode, enable_raw_mode, EnterAlternateScreen, LeaveAlternateScreen}, }; - use parking_lot::Mutex; +use serde::{Deserialize, Serialize}; +use tracing::instrument; use tui::{ backend::{Backend, CrosstermBackend}, layout::{Constraint, Layout}, @@ -17,7 +18,9 @@ use tui::{ Frame, Terminal, }; -#[derive(Debug, Clone)] +use networking_demo::Network; + +#[derive(Debug, Clone, Serialize, Deserialize)] pub struct Message { sender: String, content: String, @@ -59,11 +62,13 @@ impl TableApp { } #[async_std::main] +#[instrument] async fn main() -> Result<()> { // -- Setup color_eyre and tracing color_eyre::install()?; networking_demo::tracing_setup::setup_tracing(); // -- Spin up the network connection + let _networking: Network = Network::new(PhantomData); // -- Spin up the UI // Setup a ring buffer to hold messages, 25 of them should do for the demo diff --git a/libp2p-networking/src/lib.rs b/libp2p-networking/src/lib.rs index 896b2f561c..9f3d356a6e 100644 --- a/libp2p-networking/src/lib.rs +++ b/libp2p-networking/src/lib.rs @@ -21,9 +21,12 @@ use std::marker::PhantomData; use libp2p::{ gossipsub::{Gossipsub, GossipsubEvent}, identify::{Identify, IdentifyEvent}, + identity::Keypair, kad::{store::MemoryStore, Kademlia, KademliaEvent}, - NetworkBehaviour, + NetworkBehaviour, PeerId, }; +use serde::{de::DeserializeOwned, Serialize}; +use tracing::{debug, instrument}; #[derive(NetworkBehaviour)] #[behaviour(out_event = "NetworkEvent")] @@ -60,5 +63,26 @@ impl From for NetworkEvent { } pub struct Network { + pub identity: Keypair, + pub peer_id: PeerId, _phantom: PhantomData, } + +impl Network { + /// Creates a new `Network` with the given settings. + /// + /// Currently: + /// * Generates a random key pair and associated [`PeerId`] + #[instrument] + pub fn new(_: PhantomData) -> Self { + // Generate a random PeerId + let identity = Keypair::generate_ed25519(); + let peer_id = PeerId::from(identity.public()); + debug!(?peer_id); + Self { + identity, + peer_id, + _phantom: PhantomData, + } + } +} From 9c450ed7ef0f327aebff26253d72c8d87d13b4a3 Mon Sep 17 00:00:00 2001 From: Nathan McCarty Date: Wed, 12 Jan 2022 14:09:51 -0500 Subject: [PATCH 011/107] Launch transport --- libp2p-networking/src/bin/clichat.rs | 4 +++- libp2p-networking/src/lib.rs | 26 ++++++++++++++++++++++---- 2 files changed, 25 insertions(+), 5 deletions(-) diff --git a/libp2p-networking/src/bin/clichat.rs b/libp2p-networking/src/bin/clichat.rs index a010753394..6f6a56fae5 100644 --- a/libp2p-networking/src/bin/clichat.rs +++ b/libp2p-networking/src/bin/clichat.rs @@ -68,7 +68,9 @@ async fn main() -> Result<()> { color_eyre::install()?; networking_demo::tracing_setup::setup_tracing(); // -- Spin up the network connection - let _networking: Network = Network::new(PhantomData); + let _networking: Network = Network::new(PhantomData) + .await + .context("Failed to launch network")?; // -- Spin up the UI // Setup a ring buffer to hold messages, 25 of them should do for the demo diff --git a/libp2p-networking/src/lib.rs b/libp2p-networking/src/lib.rs index 9f3d356a6e..d380443311 100644 --- a/libp2p-networking/src/lib.rs +++ b/libp2p-networking/src/lib.rs @@ -19,6 +19,7 @@ pub mod tracing_setup; use std::marker::PhantomData; use libp2p::{ + core::{muxing::StreamMuxerBox, transport::Boxed}, gossipsub::{Gossipsub, GossipsubEvent}, identify::{Identify, IdentifyEvent}, identity::Keypair, @@ -26,7 +27,8 @@ use libp2p::{ NetworkBehaviour, PeerId, }; use serde::{de::DeserializeOwned, Serialize}; -use tracing::{debug, instrument}; +use snafu::{ResultExt, Snafu}; +use tracing::{debug, instrument, trace}; #[derive(NetworkBehaviour)] #[behaviour(out_event = "NetworkEvent")] @@ -65,6 +67,7 @@ impl From for NetworkEvent { pub struct Network { pub identity: Keypair, pub peer_id: PeerId, + pub transport: Boxed<(PeerId, StreamMuxerBox)>, _phantom: PhantomData, } @@ -74,15 +77,30 @@ impl Network { /// Currently: /// * Generates a random key pair and associated [`PeerId`] #[instrument] - pub fn new(_: PhantomData) -> Self { + pub async fn new(_: PhantomData) -> Result { // Generate a random PeerId let identity = Keypair::generate_ed25519(); let peer_id = PeerId::from(identity.public()); debug!(?peer_id); - Self { + // TODO: Maybe not use a development only networking backend + let transport = libp2p::development_transport(identity.clone()) + .await + .context(TransportLaunchSnafu)?; + trace!("Launched network transport"); + Ok(Self { identity, peer_id, + transport, _phantom: PhantomData, - } + }) } } + +#[derive(Debug, Snafu)] +pub enum NetworkError { + /// Error establishing backend connection + TransportLaunch { + /// The underlying source of the error + source: std::io::Error, + }, +} From 836f024345ef1fcc95db090f064bf147c5d7cf54 Mon Sep 17 00:00:00 2001 From: Nathan McCarty Date: Wed, 12 Jan 2022 15:15:51 -0500 Subject: [PATCH 012/107] Construct the gossipsub --- libp2p-networking/Cargo.lock | 85 ++++++++++++++++++++++++++++++------ libp2p-networking/Cargo.toml | 1 + libp2p-networking/src/lib.rs | 71 ++++++++++++++++++++++++++++-- 3 files changed, 139 insertions(+), 18 deletions(-) diff --git a/libp2p-networking/Cargo.lock b/libp2p-networking/Cargo.lock index cbd66c707a..3f286307e9 100644 --- a/libp2p-networking/Cargo.lock +++ b/libp2p-networking/Cargo.lock @@ -99,6 +99,12 @@ version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "23b62fc65de8e4e7f52534fb52b0f3ed04746ae267519eef2a83941e8085068b" +[[package]] +name = "arrayvec" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8da52d66c7071e2e3fa2a1e5c6d088fec47b593032b254f5e980de8ea54454d6" + [[package]] name = "asn1_der" version = "0.7.5" @@ -335,10 +341,24 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0a4e37d16930f5459780f5621038b6382b9bb37c19016f39fb6b5808d831f174" dependencies = [ "crypto-mac", - "digest", + "digest 0.9.0", "opaque-debug", ] +[[package]] +name = "blake3" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "882e99e4a0cb2ae6cb6e442102e8e6b7131718d94110e64c3e6a34ea9b106f37" +dependencies = [ + "arrayref", + "arrayvec 0.7.2", + "cc", + "cfg-if", + "constant_time_eq", + "digest 0.10.1", +] + [[package]] name = "block-buffer" version = "0.9.0" @@ -349,6 +369,15 @@ dependencies = [ "generic-array", ] +[[package]] +name = "block-buffer" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1d36a02058e76b040de25a4464ba1c80935655595b661505c8b39b664828b95" +dependencies = [ + "generic-array", +] + [[package]] name = "block-padding" version = "0.2.1" @@ -487,6 +516,12 @@ dependencies = [ "cache-padded", ] +[[package]] +name = "constant_time_eq" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "245097e9a4535ee1e3e3931fcfcd55a796a44c643e8596ff6566d68f09b87bbc" + [[package]] name = "cpufeatures" version = "0.2.1" @@ -571,6 +606,15 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" +[[package]] +name = "crypto-common" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "683d6b536309245c849479fba3da410962a43ed8e51c26b729208ec0ac2798d0" +dependencies = [ + "generic-array", +] + [[package]] name = "crypto-mac" version = "0.8.0" @@ -618,7 +662,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0b9fdf9972b2bd6af2d913799d9ebc165ea4d2e65878e329d9c6b372c4491b61" dependencies = [ "byteorder", - "digest", + "digest 0.9.0", "rand_core 0.5.1", "subtle", "zeroize", @@ -639,6 +683,18 @@ dependencies = [ "generic-array", ] +[[package]] +name = "digest" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b697d66081d42af4fba142d56918a3cb21dc8eb63372c6b85d14f44fb9c5979b" +dependencies = [ + "block-buffer 0.10.0", + "crypto-common", + "generic-array", + "subtle", +] + [[package]] name = "dns-parser" version = "0.8.0" @@ -991,7 +1047,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "126888268dcc288495a26bf004b38c5fdbb31682f992c84ceb046a1f0fe38840" dependencies = [ "crypto-mac", - "digest", + "digest 0.9.0", ] [[package]] @@ -1000,7 +1056,7 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "17ea0a1394df5b6574da6e0c1ade9e78868c9fb0a4e5ef4428e32da4676b85b1" dependencies = [ - "digest", + "digest 0.9.0", "generic-array", "hmac", ] @@ -1343,7 +1399,7 @@ version = "0.33.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4fe4538a739911c178ec96398caa7d9eb3dc540f07613c819b38722a697eaccc" dependencies = [ - "arrayvec", + "arrayvec 0.5.2", "asynchronous-codec", "bytes", "either", @@ -1661,7 +1717,7 @@ checksum = "b0452aac8bab02242429380e9b2f94ea20cea2b37e2c1777a1358799bbe97f37" dependencies = [ "arrayref", "base64", - "digest", + "digest 0.9.0", "hmac-drbg", "libsecp256k1-core", "libsecp256k1-gen-ecmult", @@ -1679,7 +1735,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5be9b9bb642d8522a44d533eab56c16c738301965504753b03ad1de3425d5451" dependencies = [ "crunchy", - "digest", + "digest 0.9.0", "subtle", ] @@ -1838,7 +1894,7 @@ version = "0.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "752a61cd890ff691b4411423d23816d5866dd5621e4d1c5687a53b94b5a979d8" dependencies = [ - "digest", + "digest 0.9.0", "generic-array", "multihash-derive", "sha2", @@ -1885,6 +1941,7 @@ version = "0.0.0" dependencies = [ "async-std", "bincode", + "blake3", "color-eyre", "crossterm 0.22.1", "libp2p", @@ -2545,10 +2602,10 @@ version = "0.9.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "99cd6713db3cf16b6c84e06321e049a9b9f699826e16096d23bbcc44d15d51a6" dependencies = [ - "block-buffer", + "block-buffer 0.9.0", "cfg-if", "cpufeatures", - "digest", + "digest 0.9.0", "opaque-debug", ] @@ -2558,10 +2615,10 @@ version = "0.9.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4d58a1e1bf39749807d89cf2d98ac2dfa0ff1cb3faa38fbb64dd88ac8013d800" dependencies = [ - "block-buffer", + "block-buffer 0.9.0", "cfg-if", "cpufeatures", - "digest", + "digest 0.9.0", "opaque-debug", ] @@ -2571,8 +2628,8 @@ version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f81199417d4e5de3f04b1e871023acea7389672c4135918f05aa9cbf2f2fa809" dependencies = [ - "block-buffer", - "digest", + "block-buffer 0.9.0", + "digest 0.9.0", "keccak", "opaque-debug", ] diff --git a/libp2p-networking/Cargo.toml b/libp2p-networking/Cargo.toml index 5bf4d9d513..98fb192980 100644 --- a/libp2p-networking/Cargo.toml +++ b/libp2p-networking/Cargo.toml @@ -8,6 +8,7 @@ edition = "2021" [dependencies] async-std = { version = "1.10.0", features = ["attributes"] } bincode = "1.3.3" +blake3 = "1.3.0" color-eyre = "0.5.11" crossterm = "0.22.1" libp2p = "0.41.1" diff --git a/libp2p-networking/src/lib.rs b/libp2p-networking/src/lib.rs index d380443311..335cd72ebf 100644 --- a/libp2p-networking/src/lib.rs +++ b/libp2p-networking/src/lib.rs @@ -16,18 +16,21 @@ pub mod tracing_setup; -use std::marker::PhantomData; +use std::{marker::PhantomData, time::Duration}; use libp2p::{ core::{muxing::StreamMuxerBox, transport::Boxed}, - gossipsub::{Gossipsub, GossipsubEvent}, + gossipsub::{ + Gossipsub, GossipsubConfig, GossipsubConfigBuilder, GossipsubEvent, GossipsubMessage, + IdentTopic as Topic, MessageAuthenticity, MessageId, ValidationMode, + }, identify::{Identify, IdentifyEvent}, identity::Keypair, kad::{store::MemoryStore, Kademlia, KademliaEvent}, - NetworkBehaviour, PeerId, + NetworkBehaviour, PeerId, Swarm, }; use serde::{de::DeserializeOwned, Serialize}; -use snafu::{ResultExt, Snafu}; +use snafu::{ResultExt, Snafu, Whatever}; use tracing::{debug, instrument, trace}; #[derive(NetworkBehaviour)] @@ -68,6 +71,7 @@ pub struct Network { pub identity: Keypair, pub peer_id: PeerId, pub transport: Boxed<(PeerId, StreamMuxerBox)>, + pub broadcast_topic: Topic, _phantom: PhantomData, } @@ -76,6 +80,9 @@ impl Network { /// /// Currently: /// * Generates a random key pair and associated [`PeerId`] + /// * Launches a development-only type of transport backend + /// * Generates a connection to the "broadcast" topic + /// * Creates a swarm to manage peers and events #[instrument] pub async fn new(_: PhantomData) -> Result { // Generate a random PeerId @@ -87,10 +94,54 @@ impl Network { .await .context(TransportLaunchSnafu)?; trace!("Launched network transport"); + let broadcast_topic = Topic::new("broadcast"); + // Generate the swarm + let mut swarm: Swarm = { + // Use the hash of the message's contents as the ID + // Use blake3 for much paranoia at very high speeds + let message_id_fn = |message: &GossipsubMessage| { + let hash = blake3::hash(&message.data); + MessageId::from(hash.as_bytes().to_vec()) + }; + // Create a custom gossipsub + // TODO: Extract these defaults into some sort of config + // Use a jank match because Gossipsubconfigbuilder::build returns a non-static str for + // some god forsaken reason + let gossipsub_config = match GossipsubConfigBuilder::default() + // Use a reasonable 10 second heartbeat interval by default + .heartbeat_interval(Duration::from_secs(10)) + // Force all messages to have valid signatures + .validation_mode(ValidationMode::Strict) + // Use the (blake3) hash of a message as its ID + .message_id_fn(message_id_fn) + .build() + { + Ok(x) => x, + Err(string) => { + return Err(GossipsubConfigSnafu { + message: string.to_string(), + } + .build()) + } + }; + // - Build a gossipsub network behavior + let mut gossipsub: Gossipsub = Gossipsub::new( + MessageAuthenticity::Signed(identity.clone()), + gossipsub_config, + ) + .map_err(|s| { + GossipsubBuildSnafu { + message: s.to_string(), + } + .build() + })?; + todo!("I am supposed to panic here") + }; Ok(Self { identity, peer_id, transport, + broadcast_topic, _phantom: PhantomData, }) } @@ -103,4 +154,16 @@ pub enum NetworkError { /// The underlying source of the error source: std::io::Error, }, + /// Error building the gossipsub configuration + #[snafu(display("Error building the gossipsub configuration: {}", message))] + GossipsubConfig { + /// The underlying source of the error + message: String, + }, + /// Error building the gossipsub instance + #[snafu(display("Error building the gossipsub implementation {message}"))] + GossipsubBuild { + /// The underlying source of the error + message: String, + }, } From 15fad55830a488a13ccf6ed9e1dd80df5bbd1dd0 Mon Sep 17 00:00:00 2001 From: Justin Restivo Date: Thu, 13 Jan 2022 11:49:04 -0500 Subject: [PATCH 013/107] Construct the swarm --- libp2p-networking/src/bin/clichat.rs | 16 +++- libp2p-networking/src/lib.rs | 111 +++++++++++++++++++-------- 2 files changed, 90 insertions(+), 37 deletions(-) diff --git a/libp2p-networking/src/bin/clichat.rs b/libp2p-networking/src/bin/clichat.rs index 6f6a56fae5..f9f25a16a1 100644 --- a/libp2p-networking/src/bin/clichat.rs +++ b/libp2p-networking/src/bin/clichat.rs @@ -1,6 +1,7 @@ use std::sync::Arc; use std::{collections::VecDeque, marker::PhantomData}; +use async_std::task::spawn; use color_eyre::eyre::{Result, WrapErr}; use crossterm::{ event::{self, DisableMouseCapture, EnableMouseCapture, Event, KeyCode}, @@ -9,7 +10,7 @@ use crossterm::{ }; use parking_lot::Mutex; use serde::{Deserialize, Serialize}; -use tracing::instrument; +use tracing::{instrument, trace}; use tui::{ backend::{Backend, CrosstermBackend}, layout::{Constraint, Layout}, @@ -18,7 +19,7 @@ use tui::{ Frame, Terminal, }; -use networking_demo::Network; +use networking_demo::{gen_multiaddr, Network, NetworkDef}; #[derive(Debug, Clone, Serialize, Deserialize)] pub struct Message { @@ -68,9 +69,16 @@ async fn main() -> Result<()> { color_eyre::install()?; networking_demo::tracing_setup::setup_tracing(); // -- Spin up the network connection - let _networking: Network = Network::new(PhantomData) + let mut networking: Network = Network::new(PhantomData) .await .context("Failed to launch network")?; + // TODO feed port in from cli instead of using randomly assigned port + let listen_addr = gen_multiaddr(0); + networking.start(listen_addr)?; + + spawn(async move { + trace!("handling events"); + }); // -- Spin up the UI // Setup a ring buffer to hold messages, 25 of them should do for the demo @@ -129,6 +137,8 @@ fn run_app(terminal: &mut Terminal, mut app: TableApp) -> Result< KeyCode::Char('q') => return Ok(()), KeyCode::Down => app.next(), KeyCode::Up => app.previous(), + KeyCode::Char('k') => app.previous(), + KeyCode::Char('j') => app.next(), _ => {} } } diff --git a/libp2p-networking/src/lib.rs b/libp2p-networking/src/lib.rs index 335cd72ebf..95adb406b5 100644 --- a/libp2p-networking/src/lib.rs +++ b/libp2p-networking/src/lib.rs @@ -19,18 +19,20 @@ pub mod tracing_setup; use std::{marker::PhantomData, time::Duration}; use libp2p::{ + build_multiaddr, core::{muxing::StreamMuxerBox, transport::Boxed}, gossipsub::{ - Gossipsub, GossipsubConfig, GossipsubConfigBuilder, GossipsubEvent, GossipsubMessage, - IdentTopic as Topic, MessageAuthenticity, MessageId, ValidationMode, + Gossipsub, GossipsubConfigBuilder, GossipsubEvent, GossipsubMessage, IdentTopic as Topic, + MessageAuthenticity, MessageId, ValidationMode, }, - identify::{Identify, IdentifyEvent}, + identify::{Identify, IdentifyConfig, IdentifyEvent}, identity::Keypair, kad::{store::MemoryStore, Kademlia, KademliaEvent}, - NetworkBehaviour, PeerId, Swarm, + swarm::NetworkBehaviour, + Multiaddr, NetworkBehaviour, PeerId, Swarm, TransportError, }; use serde::{de::DeserializeOwned, Serialize}; -use snafu::{ResultExt, Snafu, Whatever}; +use snafu::{ResultExt, Snafu}; use tracing::{debug, instrument, trace}; #[derive(NetworkBehaviour)] @@ -39,7 +41,7 @@ use tracing::{debug, instrument, trace}; pub struct NetworkDef { pub gossipsub: Gossipsub, pub kadem: Kademlia, - pub identity: Identify, + pub identify: Identify, } #[derive(Debug)] @@ -67,15 +69,42 @@ impl From for NetworkEvent { } } -pub struct Network { +pub struct Network { pub identity: Keypair, pub peer_id: PeerId, - pub transport: Boxed<(PeerId, StreamMuxerBox)>, pub broadcast_topic: Topic, - _phantom: PhantomData, + pub swarm: Swarm, + _phantom: PhantomData, } -impl Network { +impl std::fmt::Debug for Network { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!( + f, + "identity public key: {:?}, peer id: {:?}, topic: {:?}", + self.identity.public(), + self.peer_id, + self.broadcast_topic + ) + } +} + +impl Network { + /// starts the swarm listening on `listen_addr` + #[instrument] + pub fn start(&mut self, listen_addr: Multiaddr) -> Result<(), NetworkError> { + self.swarm.listen_on(listen_addr).context(TransportSnafu)?; + Ok(()) + } +} + +/// bind all interfaces on port `port` +/// TODO something more general +pub fn gen_multiaddr(port: u16) -> Multiaddr { + build_multiaddr!(Ip4([0, 0, 0, 0]), Tcp(port)) +} + +impl Network { /// Creates a new `Network` with the given settings. /// /// Currently: @@ -84,19 +113,20 @@ impl Network { /// * Generates a connection to the "broadcast" topic /// * Creates a swarm to manage peers and events #[instrument] - pub async fn new(_: PhantomData) -> Result { + pub async fn new(_: PhantomData) -> Result { // Generate a random PeerId let identity = Keypair::generate_ed25519(); let peer_id = PeerId::from(identity.public()); debug!(?peer_id); // TODO: Maybe not use a development only networking backend - let transport = libp2p::development_transport(identity.clone()) - .await - .context(TransportLaunchSnafu)?; + let transport: Boxed<(PeerId, StreamMuxerBox)> = + libp2p::development_transport(identity.clone()) + .await + .context(TransportLaunchSnafu)?; trace!("Launched network transport"); let broadcast_topic = Topic::new("broadcast"); // Generate the swarm - let mut swarm: Swarm = { + let swarm: Swarm = { // Use the hash of the message's contents as the ID // Use blake3 for much paranoia at very high speeds let message_id_fn = |message: &GossipsubMessage| { @@ -107,7 +137,7 @@ impl Network { // TODO: Extract these defaults into some sort of config // Use a jank match because Gossipsubconfigbuilder::build returns a non-static str for // some god forsaken reason - let gossipsub_config = match GossipsubConfigBuilder::default() + let gossipsub_config = GossipsubConfigBuilder::default() // Use a reasonable 10 second heartbeat interval by default .heartbeat_interval(Duration::from_secs(10)) // Force all messages to have valid signatures @@ -115,33 +145,41 @@ impl Network { // Use the (blake3) hash of a message as its ID .message_id_fn(message_id_fn) .build() - { - Ok(x) => x, - Err(string) => { - return Err(GossipsubConfigSnafu { - message: string.to_string(), - } - .build()) - } - }; + .map_err(|s| GossipsubConfigSnafu { message: s }.build())?; // - Build a gossipsub network behavior - let mut gossipsub: Gossipsub = Gossipsub::new( + let gossipsub: Gossipsub = Gossipsub::new( MessageAuthenticity::Signed(identity.clone()), gossipsub_config, ) - .map_err(|s| { - GossipsubBuildSnafu { - message: s.to_string(), - } - .build() - })?; - todo!("I am supposed to panic here") + .map_err(|s| GossipsubBuildSnafu { message: s }.build())?; + + // - Build a identify network behavior needed for own + // node connection information + // E.g. this will answer the question: how are other nodes + // seeing the peer from behind a NAT + let identify = Identify::new(IdentifyConfig::new( + "Spectrum validation gossip 0.1".to_string(), + identity.public(), + )); + + // - Build DHT needed for peer discovery + // TODO check into the MemoryStore defaults + let kadem = Kademlia::new(peer_id, MemoryStore::new(peer_id)); + + let network = NetworkDef { + gossipsub, + kadem, + identify, + }; + + Swarm::new(transport, network, peer_id) }; + Ok(Self { identity, peer_id, - transport, broadcast_topic, + swarm, _phantom: PhantomData, }) } @@ -149,6 +187,11 @@ impl Network { #[derive(Debug, Snafu)] pub enum NetworkError { + /// Error during dialing or listening + Transport { + /// The underlying source of the error + source: TransportError, + }, /// Error establishing backend connection TransportLaunch { /// The underlying source of the error From 7d2e6a3866ca35f401146e8880a17457aaf65a36 Mon Sep 17 00:00:00 2001 From: Justin Restivo Date: Thu, 13 Jan 2022 14:06:01 -0500 Subject: [PATCH 014/107] Log to file + structopt --- libp2p-networking/Cargo.lock | 73 ++++++++++++++++++++++++++ libp2p-networking/Cargo.toml | 2 + libp2p-networking/src/bin/clichat.rs | 23 +++++--- libp2p-networking/src/lib.rs | 4 ++ libp2p-networking/src/tracing_setup.rs | 10 +++- 5 files changed, 103 insertions(+), 9 deletions(-) diff --git a/libp2p-networking/Cargo.lock b/libp2p-networking/Cargo.lock index 3f286307e9..7eb88ec3b2 100644 --- a/libp2p-networking/Cargo.lock +++ b/libp2p-networking/Cargo.lock @@ -286,6 +286,17 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "065374052e7df7ee4047b1160cca5e1467a12351a40b3da123c870ba0b8eda2a" +[[package]] +name = "atty" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" +dependencies = [ + "hermit-abi", + "libc", + "winapi", +] + [[package]] name = "autocfg" version = "1.0.1" @@ -480,6 +491,21 @@ dependencies = [ "generic-array", ] +[[package]] +name = "clap" +version = "2.34.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a0610544180c38b88101fecf2dd634b174a62eef6946f84dfc6a7127512b381c" +dependencies = [ + "ansi_term", + "atty", + "bitflags", + "strsim", + "textwrap", + "unicode-width", + "vec_map", +] + [[package]] name = "color-eyre" version = "0.5.11" @@ -1944,10 +1970,12 @@ dependencies = [ "blake3", "color-eyre", "crossterm 0.22.1", + "futures", "libp2p", "parking_lot", "serde", "snafu", + "structopt", "tracing", "tracing-error 0.2.0", "tracing-subscriber 0.3.5", @@ -2786,6 +2814,36 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" +[[package]] +name = "strsim" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" + +[[package]] +name = "structopt" +version = "0.3.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "40b9788f4202aa75c240ecc9c15c65185e6a39ccdeb0fd5d008b98825464c87c" +dependencies = [ + "clap", + "lazy_static", + "structopt-derive", +] + +[[package]] +name = "structopt-derive" +version = "0.4.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dcb5ae327f9cc13b68763b5749770cb9e048a99bd9dfdfa58d0cf05d5f64afe0" +dependencies = [ + "heck", + "proc-macro-error", + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "subtle" version = "2.4.1" @@ -2829,6 +2887,15 @@ dependencies = [ "winapi", ] +[[package]] +name = "textwrap" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060" +dependencies = [ + "unicode-width", +] + [[package]] name = "thiserror" version = "1.0.30" @@ -3156,6 +3223,12 @@ version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" +[[package]] +name = "vec_map" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191" + [[package]] name = "version_check" version = "0.9.4" diff --git a/libp2p-networking/Cargo.toml b/libp2p-networking/Cargo.toml index 98fb192980..39df04106d 100644 --- a/libp2p-networking/Cargo.toml +++ b/libp2p-networking/Cargo.toml @@ -11,10 +11,12 @@ bincode = "1.3.3" blake3 = "1.3.0" color-eyre = "0.5.11" crossterm = "0.22.1" +futures = "0.3.19" libp2p = "0.41.1" parking_lot = "0.11.2" serde = { version = "1.0.133", features = ["derive"] } snafu = "0.7.0" +structopt = "0.3.25" tracing = "0.1.29" tracing-error = "0.2.0" tracing-subscriber = { version = "0.3.5", features = ["env-filter", "json"] } diff --git a/libp2p-networking/src/bin/clichat.rs b/libp2p-networking/src/bin/clichat.rs index f9f25a16a1..266ca14566 100644 --- a/libp2p-networking/src/bin/clichat.rs +++ b/libp2p-networking/src/bin/clichat.rs @@ -1,7 +1,7 @@ use std::sync::Arc; use std::{collections::VecDeque, marker::PhantomData}; +use structopt::StructOpt; -use async_std::task::spawn; use color_eyre::eyre::{Result, WrapErr}; use crossterm::{ event::{self, DisableMouseCapture, EnableMouseCapture, Event, KeyCode}, @@ -62,6 +62,18 @@ impl TableApp { } } +#[derive(StructOpt)] +struct CliOpt { + /// Path to the node configuration file + #[structopt( + long = "port", + short = "p", + )] + port: Option, +} + + + #[async_std::main] #[instrument] async fn main() -> Result<()> { @@ -72,13 +84,10 @@ async fn main() -> Result<()> { let mut networking: Network = Network::new(PhantomData) .await .context("Failed to launch network")?; - // TODO feed port in from cli instead of using randomly assigned port - let listen_addr = gen_multiaddr(0); + let port = CliOpt::from_args().port.unwrap_or(0u16); + let listen_addr = gen_multiaddr(port); networking.start(listen_addr)?; - - spawn(async move { - trace!("handling events"); - }); + networking.spawn_listeners().await; // -- Spin up the UI // Setup a ring buffer to hold messages, 25 of them should do for the demo diff --git a/libp2p-networking/src/lib.rs b/libp2p-networking/src/lib.rs index 95adb406b5..8454fb03db 100644 --- a/libp2p-networking/src/lib.rs +++ b/libp2p-networking/src/lib.rs @@ -183,6 +183,10 @@ impl Network { _phantom: PhantomData, }) } + + pub async fn spawn_listeners(&mut self){ + todo!() + } } #[derive(Debug, Snafu)] diff --git a/libp2p-networking/src/tracing_setup.rs b/libp2p-networking/src/tracing_setup.rs index e3de37b2e4..21f7d3667b 100644 --- a/libp2p-networking/src/tracing_setup.rs +++ b/libp2p-networking/src/tracing_setup.rs @@ -1,5 +1,6 @@ #![allow(clippy::pedantic, clippy::panic)] use std::env::{var, VarError}; +use std::fs::File; use tracing_error::ErrorLayer; use tracing_subscriber::{ fmt::{self, format::FmtSpan, writer::BoxMakeWriter}, @@ -40,8 +41,13 @@ fn parse_writer() -> BoxMakeWriter { match file.as_deref() { Ok("stderr") => BoxMakeWriter::new(std::io::stderr), Ok("stdout") => BoxMakeWriter::new(std::io::stdout), - Ok(_) => panic!("Invalid RUST_LOG_OUTPUT value"), - Err(_) => BoxMakeWriter::new(std::io::stderr), + Ok(filename) => { + match File::create(filename) { + Ok(handle) => BoxMakeWriter::new(handle), + _ => BoxMakeWriter::new(std::io::stdout) + } + }, + Err(_) => panic!("Invalid RUST_LOG_OUTPUT value"), } } From fefa09a8b4fdeba15753dab93b83b5881f2c94d2 Mon Sep 17 00:00:00 2001 From: Justin Restivo Date: Fri, 14 Jan 2022 12:51:57 -0500 Subject: [PATCH 015/107] Gossipping between peers --- libp2p-networking/Cargo.lock | 36 ++++- libp2p-networking/Cargo.toml | 1 + libp2p-networking/README | 9 ++ libp2p-networking/src/bin/clichat.rs | 146 +++++++++++++++++--- libp2p-networking/src/lib.rs | 178 +++++++++++++++++++++++-- libp2p-networking/src/tracing_setup.rs | 10 +- 6 files changed, 342 insertions(+), 38 deletions(-) create mode 100644 libp2p-networking/README diff --git a/libp2p-networking/Cargo.lock b/libp2p-networking/Cargo.lock index 7eb88ec3b2..ac70cb765c 100644 --- a/libp2p-networking/Cargo.lock +++ b/libp2p-networking/Cargo.lock @@ -828,6 +828,19 @@ dependencies = [ "miniz_oxide", ] +[[package]] +name = "flume" +version = "0.10.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d04dafd11240188e146b6f6476a898004cace3be31d4ec5e08e216bf4947ac0" +dependencies = [ + "futures-core", + "futures-sink", + "nanorand", + "pin-project 1.0.10", + "spin 0.9.2", +] + [[package]] name = "fnv" version = "1.0.7" @@ -994,8 +1007,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7fcd999463524c52659517fe2cea98493cfe485d10565e7b0fb07dbba7ad2753" dependencies = [ "cfg-if", + "js-sys", "libc", "wasi 0.10.2+wasi-snapshot-preview1", + "wasm-bindgen", ] [[package]] @@ -1961,6 +1976,15 @@ dependencies = [ "unsigned-varint", ] +[[package]] +name = "nanorand" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "729eb334247daa1803e0a094d0a5c55711b85571179f5ec6e53eccfdf7008958" +dependencies = [ + "getrandom 0.2.3", +] + [[package]] name = "networking-demo" version = "0.0.0" @@ -1970,6 +1994,7 @@ dependencies = [ "blake3", "color-eyre", "crossterm 0.22.1", + "flume", "futures", "libp2p", "parking_lot", @@ -2500,7 +2525,7 @@ dependencies = [ "cc", "libc", "once_cell", - "spin", + "spin 0.5.2", "untrusted", "web-sys", "winapi", @@ -2802,6 +2827,15 @@ version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" +[[package]] +name = "spin" +version = "0.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "511254be0c5bcf062b019a6c89c01a664aa359ded62f78aa72c6fc137c0590e5" +dependencies = [ + "lock_api", +] + [[package]] name = "stable_deref_trait" version = "1.2.0" diff --git a/libp2p-networking/Cargo.toml b/libp2p-networking/Cargo.toml index 39df04106d..8b0db570b0 100644 --- a/libp2p-networking/Cargo.toml +++ b/libp2p-networking/Cargo.toml @@ -11,6 +11,7 @@ bincode = "1.3.3" blake3 = "1.3.0" color-eyre = "0.5.11" crossterm = "0.22.1" +flume = "0.10.10" futures = "0.3.19" libp2p = "0.41.1" parking_lot = "0.11.2" diff --git a/libp2p-networking/README b/libp2p-networking/README new file mode 100644 index 0000000000..226dff99a1 --- /dev/null +++ b/libp2p-networking/README @@ -0,0 +1,9 @@ +# USAGE + +To get very verbose logging: + +```bash +RUST_LOG_OUTPUT=OUTFILE RUST_LOG="trace" cargo run --release +``` + + diff --git a/libp2p-networking/src/bin/clichat.rs b/libp2p-networking/src/bin/clichat.rs index 266ca14566..7b6cb9e2fe 100644 --- a/libp2p-networking/src/bin/clichat.rs +++ b/libp2p-networking/src/bin/clichat.rs @@ -1,3 +1,5 @@ +use libp2p::{gossipsub::GossipsubMessage, Multiaddr}; + use std::sync::Arc; use std::{collections::VecDeque, marker::PhantomData}; use structopt::StructOpt; @@ -10,32 +12,75 @@ use crossterm::{ }; use parking_lot::Mutex; use serde::{Deserialize, Serialize}; -use tracing::{instrument, trace}; +use tracing::instrument; use tui::{ backend::{Backend, CrosstermBackend}, layout::{Constraint, Layout}, style::{Color, Modifier, Style}, - widgets::{Block, Borders, Cell, Row, Table, TableState}, + widgets::{Block, Borders, Cell, Paragraph, Row, Table, TableState}, Frame, Terminal, }; -use networking_demo::{gen_multiaddr, Network, NetworkDef}; +use flume::{Receiver, Sender}; +use networking_demo::{gen_multiaddr, GossipMsg, Network, NetworkDef, SwarmAction, SwarmResult}; #[derive(Debug, Clone, Serialize, Deserialize)] pub struct Message { sender: String, content: String, + topic: String, +} + +impl GossipMsg for Message { + fn topic(&self) -> libp2p::gossipsub::IdentTopic { + libp2p::gossipsub::IdentTopic::new(self.topic.clone()) + } + fn data(&self) -> Vec { + self.content.as_bytes().into() + } +} + +impl From for Message { + fn from(msg: GossipsubMessage) -> Self { + let content = String::from_utf8_lossy(&msg.data).to_string(); + let sender = msg + .source + .map(|p| p.to_string()) + .unwrap_or_else(|| "UNKNOWN".to_string()); + Message { + sender, + content, + topic: msg.topic.into_string(), + } + } +} + +enum InputMode { + Normal, + Editing, } /// Struct for the TUI app struct TableApp { + send_swarm: Sender>, + recv_swarm: Receiver>, + input_mode: InputMode, + input: String, state: TableState, message_buffer: Arc>>, } impl TableApp { - pub fn new(message_buffer: Arc>>) -> Self { + pub fn new( + message_buffer: Arc>>, + send_swarm: Sender>, + recv_swarm: Receiver>, + ) -> Self { Self { + send_swarm, + recv_swarm, + input_mode: InputMode::Normal, + input: String::new(), state: TableState::default(), message_buffer, } @@ -62,17 +107,16 @@ impl TableApp { } } +/// command line arguments #[derive(StructOpt)] struct CliOpt { /// Path to the node configuration file - #[structopt( - long = "port", - short = "p", - )] + #[structopt(long = "port", short = "p")] port: Option, -} - + #[structopt()] + first_dial: Option, +} #[async_std::main] #[instrument] @@ -85,9 +129,10 @@ async fn main() -> Result<()> { .await .context("Failed to launch network")?; let port = CliOpt::from_args().port.unwrap_or(0u16); + let known_peer = CliOpt::from_args().first_dial; let listen_addr = gen_multiaddr(port); - networking.start(listen_addr)?; - networking.spawn_listeners().await; + networking.start(listen_addr, known_peer)?; + let (send_chan, recv_chan) = networking.spawn_listeners().await; // -- Spin up the UI // Setup a ring buffer to hold messages, 25 of them should do for the demo @@ -97,18 +142,22 @@ async fn main() -> Result<()> { buffer_handle.push_back(Message { sender: "Nathan".to_string(), content: "Hello".to_string(), + topic: "global".to_string(), }); buffer_handle.push_back(Message { sender: "Justin".to_string(), content: "hi!".to_string(), + topic: "global".to_string(), }); buffer_handle.push_back(Message { sender: "Joe".to_string(), content: "test".to_string(), + topic: "global".to_string(), }); buffer_handle.push_back(Message { sender: "John".to_string(), content: "test 2".to_string(), + topic: "global".to_string(), }); std::mem::drop(buffer_handle); // -- Setup the TUI @@ -120,7 +169,9 @@ async fn main() -> Result<()> { let backend = CrosstermBackend::new(stdout); let mut terminal = Terminal::new(backend)?; // -- Create the app and run it - let app = TableApp::new(message_buffer.clone()); + let app = TableApp::new(message_buffer.clone(), send_chan, recv_chan); + app.send_swarm + .send(SwarmAction::Subscribe("global".to_string()))?; let res = run_app(&mut terminal, app); // -- Tear down the TUI, and restore the terminal disable_raw_mode()?; @@ -138,17 +189,59 @@ async fn main() -> Result<()> { fn run_app(terminal: &mut Terminal, mut app: TableApp) -> Result<()> { loop { + if let Ok(res) = app.recv_swarm.try_recv() { + match res { + SwarmResult::GossipMsg(s) => app.message_buffer.lock().push_back(s), + } + } terminal .draw(|f| ui(f, &mut app).expect("Failed to draw UI")) .context("Failed drawing application")?; - if let Event::Key(key) = event::read().context("Failed to read event")? { - match key.code { - KeyCode::Char('q') => return Ok(()), - KeyCode::Down => app.next(), - KeyCode::Up => app.previous(), - KeyCode::Char('k') => app.previous(), - KeyCode::Char('j') => app.next(), - _ => {} + match app.input_mode { + InputMode::Normal => { + if let Event::Key(key) = event::read().context("Failed to read event")? { + match key.code { + KeyCode::Char('q') => { + app.send_swarm.send(SwarmAction::Shutdown)?; + return Ok(()); + } + KeyCode::Down => app.next(), + KeyCode::Up => app.previous(), + KeyCode::Char('k') => app.previous(), + KeyCode::Char('j') => app.next(), + KeyCode::Esc => app.input_mode = InputMode::Editing, + _ => {} + } + } + } + InputMode::Editing => { + if let Event::Key(key) = event::read().context("Failed to read event")? { + match key.code { + // broadcast message to the swarm with the global topic + KeyCode::Enter => { + let (s, r) = flume::unbounded(); + app.send_swarm.send(SwarmAction::GetId(s))?; + let msg = SwarmAction::GossipMsg(Message { + topic: "global".to_string(), + content: app.input, + // FIXME this should NOT be needed. Get it from the swarm. + sender: r.recv()?.to_string(), + }); + app.send_swarm.send(msg)?; + app.input = String::new(); + } + KeyCode::Char(c) => { + app.input.push(c); + } + KeyCode::Backspace => { + app.input.pop(); + } + KeyCode::Esc => { + app.input_mode = InputMode::Normal; + } + _ => {} + } + } } } } @@ -156,7 +249,8 @@ fn run_app(terminal: &mut Terminal, mut app: TableApp) -> Result< fn ui(f: &mut Frame, app: &mut TableApp) -> Result<()> { let rects = Layout::default() - .constraints([Constraint::Percentage(100)].as_ref()) + // two rectanges: one for messages, the other for input + .constraints([Constraint::Percentage(90), Constraint::Percentage(10)].as_ref()) .margin(5) .split(f.size()); @@ -189,5 +283,13 @@ fn ui(f: &mut Frame, app: &mut TableApp) -> Result<()> { ]); f.render_stateful_widget(table, rects[0], &mut app.state); + 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, rects[1]); + Ok(()) } diff --git a/libp2p-networking/src/lib.rs b/libp2p-networking/src/lib.rs index 8454fb03db..05c0b9af19 100644 --- a/libp2p-networking/src/lib.rs +++ b/libp2p-networking/src/lib.rs @@ -16,24 +16,33 @@ pub mod tracing_setup; +use async_std::task::spawn; use std::{marker::PhantomData, time::Duration}; +use flume::{unbounded, Receiver, Sender}; +use futures::{select, StreamExt}; use libp2p::{ build_multiaddr, core::{muxing::StreamMuxerBox, transport::Boxed}, gossipsub::{ - Gossipsub, GossipsubConfigBuilder, GossipsubEvent, GossipsubMessage, IdentTopic as Topic, - MessageAuthenticity, MessageId, ValidationMode, + Gossipsub, + GossipsubConfigBuilder, + GossipsubEvent, + GossipsubMessage, + IdentTopic as Topic, + MessageAuthenticity, + MessageId, + ValidationMode, //Topic, }, identify::{Identify, IdentifyConfig, IdentifyEvent}, identity::Keypair, kad::{store::MemoryStore, Kademlia, KademliaEvent}, - swarm::NetworkBehaviour, + swarm::{NetworkBehaviour, SwarmEvent}, Multiaddr, NetworkBehaviour, PeerId, Swarm, TransportError, }; use serde::{de::DeserializeOwned, Serialize}; use snafu::{ResultExt, Snafu}; -use tracing::{debug, instrument, trace}; +use tracing::{debug, error, info, info_span, instrument, trace, warn, Instrument}; #[derive(NetworkBehaviour)] #[behaviour(out_event = "NetworkEvent")] @@ -77,6 +86,28 @@ pub struct Network { _phantom: PhantomData, } +/// holds requests to the swarm +pub enum SwarmAction { + Shutdown, + GossipMsg(N), // topic, message + GetId(Sender), + Subscribe(String), + Unsubscribe(String), +} + +/// holds events of the swarm to be relayed +/// out +pub enum SwarmResult { + GossipMsg(N), +} + +/// trait to get out the topic and contents of a message +/// such that it may be "gossipped" to other people +pub trait GossipMsg: Send { + fn topic(&self) -> Topic; + fn data(&self) -> Vec; +} + impl std::fmt::Debug for Network { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { write!( @@ -89,11 +120,25 @@ impl std::fmt::Debug for Network { } } -impl Network { +impl Network { /// starts the swarm listening on `listen_addr` + /// and optionally dials into peer `known_peer` #[instrument] - pub fn start(&mut self, listen_addr: Multiaddr) -> Result<(), NetworkError> { + pub fn start( + &mut self, + listen_addr: Multiaddr, + known_peer: Option, + ) -> Result<(), NetworkError> { self.swarm.listen_on(listen_addr).context(TransportSnafu)?; + if let Some(known_peer) = known_peer { + let dialing = known_peer.clone(); + match self.swarm.dial(known_peer) { + Ok(_) => { + info!("Dialed {:?}", dialing); + } + Err(e) => error!("Dial {:?} failed: {:?}", dialing, e), + }; + } Ok(()) } } @@ -104,7 +149,16 @@ pub fn gen_multiaddr(port: u16) -> Multiaddr { build_multiaddr!(Ip4([0, 0, 0, 0]), Tcp(port)) } -impl Network { +impl Network +where + N: DeserializeOwned + + Serialize + + From + + GossipMsg + + std::fmt::Debug + + Send + + 'static, +{ /// Creates a new `Network` with the given settings. /// /// Currently: @@ -184,8 +238,109 @@ impl Network { }) } - pub async fn spawn_listeners(&mut self){ - todo!() + /// spawn a task to listen for requests on the returned channel + /// as well as any events produced by libp2p + /// `mut_mut` is disabled b/c must consume `self` + /// TODO why does clippy not like `panic` with select? + #[allow(clippy::mut_mut, clippy::panic)] + #[instrument] + pub async fn spawn_listeners(mut self) -> (Sender>, Receiver>) { + let (s_input, s_output) = unbounded::>(); + let (r_input, r_output) = unbounded::>(); + spawn(async move { + loop { + select! { + event = self.swarm.select_next_some() => { + info!("libp2p event {:?}", event); + match event { + SwarmEvent::Dialing(_) + | SwarmEvent::NewListenAddr {..} + | SwarmEvent::ExpiredListenAddr {..} + | SwarmEvent::ListenerClosed {..} + | SwarmEvent::ConnectionEstablished {..} + | SwarmEvent::ConnectionClosed {..} + | SwarmEvent::IncomingConnection {..} + | SwarmEvent::IncomingConnectionError {..} + | SwarmEvent::OutgoingConnectionError {..} + | SwarmEvent::BannedPeer {..} + | SwarmEvent::ListenerError {..} => { + }, + SwarmEvent::Behaviour(b) => { + match b { + NetworkEvent::Gossip(g) => { + match g { + GossipsubEvent::Message { message, .. } => { + r_input.send(SwarmResult::GossipMsg(message.into())).map_err(|_e| NetworkError::StreamClosed)?; + }, + _ => { + info!(?g); + } + } + }, + NetworkEvent::Kadem(_k) => { + // TODO + }, + NetworkEvent::Ident(_i) => { + // TODO + }, + + } + }, + } + }, + msg = s_output.recv_async() => { + match msg { + Ok(msg) => { + match msg { + SwarmAction::Shutdown => { + warn!("Libp2p listener shutting down"); + break + }, + SwarmAction::GossipMsg(msg) => { + info!("broadcasting message {:?}", msg); + let topic = ::topic(&msg); + let contents = ::data(&msg); + match self.swarm + .behaviour_mut().gossipsub.publish(topic.clone(), contents.clone()) { + Ok(_) => (), + Err(_) => { + error!("error publishing to topic {:?} with msg {:?}", topic, contents); + } + } + }, + SwarmAction::GetId(reply_chan) => { + // FIXME proper error handling + reply_chan.send(self.peer_id).map_err(|_e| NetworkError::StreamClosed)?; + }, + SwarmAction::Subscribe(t) => { + match self.swarm.behaviour_mut().gossipsub.subscribe(&Topic::new(t.clone())) { + Ok(_) => (), + Err(_) => { + error!("error subscribing to topic {}", t); + } + } + } + SwarmAction::Unsubscribe(t) => { + match self.swarm.behaviour_mut().gossipsub.unsubscribe(&Topic::new(t.clone())) { + Ok(_) => (), + Err(_) => { + error!("error unsubscribing to topic {}", t); + } + } + } + + } + }, + Err(e) => { + error!("Error receiving msg: {:?}", e); + } + } + } + } + } + Ok::<(), NetworkError>(()) + }.instrument(info_span!( "Libp2p Event Handler"))); + (s_input, r_output) } } @@ -213,4 +368,9 @@ pub enum NetworkError { /// The underlying source of the error message: String, }, + // FIXME ideally include more information + // run into lifetime errors when making NetworkError generic over + // the type of message + // occurs if one of the channels to or from the swarm is closed + StreamClosed, } diff --git a/libp2p-networking/src/tracing_setup.rs b/libp2p-networking/src/tracing_setup.rs index 21f7d3667b..aa32fb2f13 100644 --- a/libp2p-networking/src/tracing_setup.rs +++ b/libp2p-networking/src/tracing_setup.rs @@ -41,13 +41,11 @@ fn parse_writer() -> BoxMakeWriter { match file.as_deref() { Ok("stderr") => BoxMakeWriter::new(std::io::stderr), Ok("stdout") => BoxMakeWriter::new(std::io::stdout), - Ok(filename) => { - match File::create(filename) { - Ok(handle) => BoxMakeWriter::new(handle), - _ => BoxMakeWriter::new(std::io::stdout) - } + Ok(filename) => match File::create(filename) { + Ok(handle) => BoxMakeWriter::new(handle), + _ => panic!("Could not open RUST_LOG_OUTPUT for writing."), }, - Err(_) => panic!("Invalid RUST_LOG_OUTPUT value"), + Err(_) => BoxMakeWriter::new(std::io::stdout), } } From 098784837914c0df4577f022885486dde9769eab Mon Sep 17 00:00:00 2001 From: Justin Restivo Date: Mon, 17 Jan 2022 08:27:31 -0500 Subject: [PATCH 016/107] Fix error with duplicate messages --- libp2p-networking/Cargo.lock | 44 +++------ libp2p-networking/Cargo.toml | 4 +- libp2p-networking/src/bin/clichat.rs | 129 ++++++++++++++++----------- libp2p-networking/src/lib.rs | 24 ++--- 4 files changed, 105 insertions(+), 96 deletions(-) diff --git a/libp2p-networking/Cargo.lock b/libp2p-networking/Cargo.lock index ac70cb765c..728ce50ee0 100644 --- a/libp2p-networking/Cargo.lock +++ b/libp2p-networking/Cargo.lock @@ -508,9 +508,9 @@ dependencies = [ [[package]] name = "color-eyre" -version = "0.5.11" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f1885697ee8a177096d42f158922251a41973117f6d8a234cee94b9509157b7" +checksum = "9d6ec7641ff3474b7593009c809db602c414cd97c7d47a78ed004162b74ff96c" dependencies = [ "backtrace", "color-spantrace", @@ -518,19 +518,19 @@ dependencies = [ "indenter", "once_cell", "owo-colors", - "tracing-error 0.1.2", + "tracing-error", ] [[package]] name = "color-spantrace" -version = "0.1.6" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6eee477a4a8a72f4addd4de416eb56d54bc307b284d6601bafdee1f4ea462d1" +checksum = "1ba75b3d9449ecdccb27ecbc479fdc0b87fa2dd43d2f8298f9bf0e59aacc8dce" dependencies = [ "once_cell", "owo-colors", "tracing-core", - "tracing-error 0.1.2", + "tracing-error", ] [[package]] @@ -600,6 +600,7 @@ checksum = "c85525306c4291d1b73ce93c8acf9c339f9b213aef6c1d85c3830cbf1c16325c" dependencies = [ "bitflags", "crossterm_winapi 0.9.0", + "futures-core", "libc", "mio", "parking_lot", @@ -2002,8 +2003,8 @@ dependencies = [ "snafu", "structopt", "tracing", - "tracing-error 0.2.0", - "tracing-subscriber 0.3.5", + "tracing-error", + "tracing-subscriber", "tui", ] @@ -2087,9 +2088,9 @@ dependencies = [ [[package]] name = "owo-colors" -version = "1.3.0" +version = "3.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2386b4ebe91c2f7f51082d4cefa145d030e33a1842a96b12e4885cc3c01f7a55" +checksum = "20448fd678ec04e6ea15bbe0476874af65e98a01515d667aa49f1434dc44ebf4" [[package]] name = "parity-send-wrapper" @@ -3015,16 +3016,6 @@ dependencies = [ "lazy_static", ] -[[package]] -name = "tracing-error" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4d7c0b83d4a500748fa5879461652b361edf5c9d51ede2a2ac03875ca185e24" -dependencies = [ - "tracing", - "tracing-subscriber 0.2.25", -] - [[package]] name = "tracing-error" version = "0.2.0" @@ -3032,7 +3023,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d686ec1c0f384b1277f097b2f279a2ecc11afe8c133c1aabf036a27cb4cd206e" dependencies = [ "tracing", - "tracing-subscriber 0.3.5", + "tracing-subscriber", ] [[package]] @@ -3056,17 +3047,6 @@ dependencies = [ "tracing-core", ] -[[package]] -name = "tracing-subscriber" -version = "0.2.25" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e0d2eaa99c3c2e41547cfa109e910a68ea03823cccad4a0525dcbc9b01e8c71" -dependencies = [ - "sharded-slab", - "thread_local", - "tracing-core", -] - [[package]] name = "tracing-subscriber" version = "0.3.5" diff --git a/libp2p-networking/Cargo.toml b/libp2p-networking/Cargo.toml index 8b0db570b0..1c48540b3f 100644 --- a/libp2p-networking/Cargo.toml +++ b/libp2p-networking/Cargo.toml @@ -9,8 +9,8 @@ edition = "2021" async-std = { version = "1.10.0", features = ["attributes"] } bincode = "1.3.3" blake3 = "1.3.0" -color-eyre = "0.5.11" -crossterm = "0.22.1" +color-eyre = "0.6.0" +crossterm = { version = "0.22.1", features = ["event-stream"] } flume = "0.10.10" futures = "0.3.19" libp2p = "0.41.1" diff --git a/libp2p-networking/src/bin/clichat.rs b/libp2p-networking/src/bin/clichat.rs index 7b6cb9e2fe..68aef4cbee 100644 --- a/libp2p-networking/src/bin/clichat.rs +++ b/libp2p-networking/src/bin/clichat.rs @@ -4,12 +4,14 @@ use std::sync::Arc; use std::{collections::VecDeque, marker::PhantomData}; use structopt::StructOpt; +use futures::{select, StreamExt, FutureExt}; use color_eyre::eyre::{Result, WrapErr}; use crossterm::{ event::{self, DisableMouseCapture, EnableMouseCapture, Event, KeyCode}, execute, terminal::{disable_raw_mode, enable_raw_mode, EnterAlternateScreen, LeaveAlternateScreen}, }; +use std::time::{Duration}; use parking_lot::Mutex; use serde::{Deserialize, Serialize}; use tracing::instrument; @@ -172,7 +174,7 @@ async fn main() -> Result<()> { let app = TableApp::new(message_buffer.clone(), send_chan, recv_chan); app.send_swarm .send(SwarmAction::Subscribe("global".to_string()))?; - let res = run_app(&mut terminal, app); + let res = run_app(&mut terminal, app).await; // -- Tear down the TUI, and restore the terminal disable_raw_mode()?; execute!( @@ -187,70 +189,92 @@ async fn main() -> Result<()> { res } -fn run_app(terminal: &mut Terminal, mut app: TableApp) -> Result<()> { +async fn run_app(terminal: &mut Terminal, mut app: TableApp) -> Result<()> { + let mut events = event::EventStream::new(); loop { - if let Ok(res) = app.recv_swarm.try_recv() { - match res { - SwarmResult::GossipMsg(s) => app.message_buffer.lock().push_back(s), - } - } terminal .draw(|f| ui(f, &mut app).expect("Failed to draw UI")) .context("Failed drawing application")?; - match app.input_mode { - InputMode::Normal => { - if let Event::Key(key) = event::read().context("Failed to read event")? { - match key.code { - KeyCode::Char('q') => { - app.send_swarm.send(SwarmAction::Shutdown)?; - return Ok(()); - } - KeyCode::Down => app.next(), - KeyCode::Up => app.previous(), - KeyCode::Char('k') => app.previous(), - KeyCode::Char('j') => app.next(), - KeyCode::Esc => app.input_mode = InputMode::Editing, - _ => {} + select!( + _ = async_std::task::sleep(Duration::from_nanos(1)).fuse() => {} + swarm_msg = app.recv_swarm.recv_async() => { + if let Ok(res) = swarm_msg { + match res { + SwarmResult::GossipMsg(s) => app.message_buffer.lock().push_back(s), } } - } - InputMode::Editing => { - if let Event::Key(key) = event::read().context("Failed to read event")? { - match key.code { - // broadcast message to the swarm with the global topic - KeyCode::Enter => { - let (s, r) = flume::unbounded(); - app.send_swarm.send(SwarmAction::GetId(s))?; - let msg = SwarmAction::GossipMsg(Message { - topic: "global".to_string(), - content: app.input, - // FIXME this should NOT be needed. Get it from the swarm. - sender: r.recv()?.to_string(), - }); - app.send_swarm.send(msg)?; - app.input = String::new(); - } - KeyCode::Char(c) => { - app.input.push(c); - } - KeyCode::Backspace => { - app.input.pop(); + }, + user_event = events.next().fuse() => { + match app.input_mode { + InputMode::Normal => { + if let Some(Ok(Event::Key(key))) = user_event { + match key.code { + KeyCode::Char('q') => { + app.send_swarm.send_async(SwarmAction::Shutdown).await?; + return Ok(()); + } + KeyCode::Down => app.next(), + KeyCode::Up => app.previous(), + KeyCode::Char('k') => app.previous(), + KeyCode::Char('j') => app.next(), + KeyCode::Tab => app.input_mode = InputMode::Editing, + _ => {} + } } - KeyCode::Esc => { - app.input_mode = InputMode::Normal; + } + InputMode::Editing => { + if let Some(Ok(Event::Key(key))) = user_event { + match key.code { + // broadcast message to the swarm with the global topic + KeyCode::Enter => { + let (s, r) = flume::unbounded(); + app.send_swarm.send_async(SwarmAction::GetId(s)).await?; + let msg = Message { + topic: "global".to_string(), + content: app.input, + // FIXME this should NOT be needed. Get it from the swarm. + sender: r.recv_async().await?.to_string(), + }; + let (s, r) = flume::unbounded(); + app.send_swarm.send_async(SwarmAction::GossipMsg(msg.clone(), s)).await?; + let mb_handle = app.message_buffer.clone(); + async_std::task::spawn(async move { + match r.recv_async().await? { + Ok(_) => mb_handle.lock().push_back(msg), + Err(_) => (), + } + Result::<(), flume::RecvError>::Ok(()) + }); + app.input = String::new() + } + KeyCode::Char(c) => { + app.input.push(c); + } + KeyCode::Backspace => { + app.input.pop(); + } + KeyCode::Tab => { + app.input_mode = InputMode::Normal; + } + _ => {} + } } - _ => {} } } } - } + + ); } } fn ui(f: &mut Frame, app: &mut TableApp) -> Result<()> { let rects = Layout::default() // two rectanges: one for messages, the other for input - .constraints([Constraint::Percentage(90), Constraint::Percentage(10)].as_ref()) + .constraints( + [Constraint::Percentage(60), + Constraint::Percentage(30), + Constraint::Percentage(10) + ].as_ref()) .margin(5) .split(f.size()); @@ -280,7 +304,12 @@ fn ui(f: &mut Frame, app: &mut TableApp) -> Result<()> { Constraint::Percentage(50), Constraint::Length(30), Constraint::Min(10), - ]); + ]) + .style(match app.input_mode { + InputMode::Editing => Style::default(), + InputMode::Normal => Style::default().fg(Color::Yellow), + }) + ; f.render_stateful_widget(table, rects[0], &mut app.state); let input = Paragraph::new(app.input.as_ref()) @@ -289,7 +318,7 @@ fn ui(f: &mut Frame, app: &mut TableApp) -> Result<()> { InputMode::Editing => Style::default().fg(Color::Yellow), }) .block(Block::default().borders(Borders::ALL).title("Input")); - f.render_widget(input, rects[1]); + f.render_widget(input, rects[2]); Ok(()) } diff --git a/libp2p-networking/src/lib.rs b/libp2p-networking/src/lib.rs index 05c0b9af19..4ff107a863 100644 --- a/libp2p-networking/src/lib.rs +++ b/libp2p-networking/src/lib.rs @@ -25,6 +25,7 @@ use libp2p::{ build_multiaddr, core::{muxing::StreamMuxerBox, transport::Boxed}, gossipsub::{ + error::PublishError, Gossipsub, GossipsubConfigBuilder, GossipsubEvent, @@ -32,7 +33,7 @@ use libp2p::{ IdentTopic as Topic, MessageAuthenticity, MessageId, - ValidationMode, //Topic, + ValidationMode, }, identify::{Identify, IdentifyConfig, IdentifyEvent}, identity::Keypair, @@ -89,7 +90,7 @@ pub struct Network { /// holds requests to the swarm pub enum SwarmAction { Shutdown, - GossipMsg(N), // topic, message + GossipMsg(N, Sender>), // topic, message GetId(Sender), Subscribe(String), Unsubscribe(String), @@ -296,21 +297,17 @@ where warn!("Libp2p listener shutting down"); break }, - SwarmAction::GossipMsg(msg) => { + SwarmAction::GossipMsg(msg, chan) => { info!("broadcasting message {:?}", msg); let topic = ::topic(&msg); let contents = ::data(&msg); - match self.swarm - .behaviour_mut().gossipsub.publish(topic.clone(), contents.clone()) { - Ok(_) => (), - Err(_) => { - error!("error publishing to topic {:?} with msg {:?}", topic, contents); - } - } + let res = self.swarm + .behaviour_mut().gossipsub.publish(topic.clone(), contents.clone()).map(|_| ()).context(PublishSnafu); + chan.send_async(res).await.map_err(|_e| NetworkError::StreamClosed)?; }, SwarmAction::GetId(reply_chan) => { // FIXME proper error handling - reply_chan.send(self.peer_id).map_err(|_e| NetworkError::StreamClosed)?; + reply_chan.send_async(self.peer_id).await.map_err(|_e| NetworkError::StreamClosed)?; }, SwarmAction::Subscribe(t) => { match self.swarm.behaviour_mut().gossipsub.subscribe(&Topic::new(t.clone())) { @@ -357,7 +354,7 @@ pub enum NetworkError { source: std::io::Error, }, /// Error building the gossipsub configuration - #[snafu(display("Error building the gossipsub configuration: {}", message))] + #[snafu(display("Error building the gossipsub configuration: {message}"))] GossipsubConfig { /// The underlying source of the error message: String, @@ -373,4 +370,7 @@ pub enum NetworkError { // the type of message // occurs if one of the channels to or from the swarm is closed StreamClosed, + PublishError { + source: PublishError + } } From 3779f01f00806059166506452e79bb045150921c Mon Sep 17 00:00:00 2001 From: Justin Restivo Date: Mon, 17 Jan 2022 09:16:54 -0500 Subject: [PATCH 017/107] move ui to separate file --- libp2p-networking/src/bin/clichat.rs | 234 +------------------------- libp2p-networking/src/lib.rs | 1 + libp2p-networking/src/ui.rs | 235 +++++++++++++++++++++++++++ 3 files changed, 243 insertions(+), 227 deletions(-) create mode 100644 libp2p-networking/src/ui.rs diff --git a/libp2p-networking/src/bin/clichat.rs b/libp2p-networking/src/bin/clichat.rs index 68aef4cbee..9c80236b17 100644 --- a/libp2p-networking/src/bin/clichat.rs +++ b/libp2p-networking/src/bin/clichat.rs @@ -1,113 +1,26 @@ -use libp2p::{gossipsub::GossipsubMessage, Multiaddr}; + +use libp2p::{Multiaddr}; +use networking_demo::ui::{Message, run_app, TableApp}; use std::sync::Arc; use std::{collections::VecDeque, marker::PhantomData}; use structopt::StructOpt; -use futures::{select, StreamExt, FutureExt}; use color_eyre::eyre::{Result, WrapErr}; use crossterm::{ - event::{self, DisableMouseCapture, EnableMouseCapture, Event, KeyCode}, + event::{DisableMouseCapture, EnableMouseCapture}, execute, terminal::{disable_raw_mode, enable_raw_mode, EnterAlternateScreen, LeaveAlternateScreen}, }; -use std::time::{Duration}; use parking_lot::Mutex; -use serde::{Deserialize, Serialize}; + use tracing::instrument; use tui::{ - backend::{Backend, CrosstermBackend}, - layout::{Constraint, Layout}, - style::{Color, Modifier, Style}, - widgets::{Block, Borders, Cell, Paragraph, Row, Table, TableState}, - Frame, Terminal, + backend::CrosstermBackend, Terminal, }; -use flume::{Receiver, Sender}; -use networking_demo::{gen_multiaddr, GossipMsg, Network, NetworkDef, SwarmAction, SwarmResult}; - -#[derive(Debug, Clone, Serialize, Deserialize)] -pub struct Message { - sender: String, - content: String, - topic: String, -} - -impl GossipMsg for Message { - fn topic(&self) -> libp2p::gossipsub::IdentTopic { - libp2p::gossipsub::IdentTopic::new(self.topic.clone()) - } - fn data(&self) -> Vec { - self.content.as_bytes().into() - } -} - -impl From for Message { - fn from(msg: GossipsubMessage) -> Self { - let content = String::from_utf8_lossy(&msg.data).to_string(); - let sender = msg - .source - .map(|p| p.to_string()) - .unwrap_or_else(|| "UNKNOWN".to_string()); - Message { - sender, - content, - topic: msg.topic.into_string(), - } - } -} - -enum InputMode { - Normal, - Editing, -} - -/// Struct for the TUI app -struct TableApp { - send_swarm: Sender>, - recv_swarm: Receiver>, - input_mode: InputMode, - input: String, - state: TableState, - message_buffer: Arc>>, -} - -impl TableApp { - pub fn new( - message_buffer: Arc>>, - send_swarm: Sender>, - recv_swarm: Receiver>, - ) -> Self { - Self { - send_swarm, - recv_swarm, - input_mode: InputMode::Normal, - input: String::new(), - state: TableState::default(), - message_buffer, - } - } - pub fn next(&mut self) { - let buffer_handle = self.message_buffer.lock(); - let i = self.state.selected().unwrap_or(0) + 1; - self.state.select(Some(i % buffer_handle.len())); - } - pub fn previous(&mut self) { - let buffer_handle = self.message_buffer.lock(); - let i = match self.state.selected() { - Some(i) => { - if i == 0 { - buffer_handle.len() - 1 - } else { - i - 1 - } - } - None => 0, - }; - self.state.select(Some(i)); - } -} +use networking_demo::{gen_multiaddr, Network, NetworkDef, SwarmAction}; /// command line arguments #[derive(StructOpt)] @@ -189,136 +102,3 @@ async fn main() -> Result<()> { res } -async fn run_app(terminal: &mut Terminal, mut app: TableApp) -> Result<()> { - let mut events = event::EventStream::new(); - loop { - terminal - .draw(|f| ui(f, &mut app).expect("Failed to draw UI")) - .context("Failed drawing application")?; - select!( - _ = async_std::task::sleep(Duration::from_nanos(1)).fuse() => {} - swarm_msg = app.recv_swarm.recv_async() => { - if let Ok(res) = swarm_msg { - match res { - SwarmResult::GossipMsg(s) => app.message_buffer.lock().push_back(s), - } - } - }, - user_event = events.next().fuse() => { - match app.input_mode { - InputMode::Normal => { - if let Some(Ok(Event::Key(key))) = user_event { - match key.code { - KeyCode::Char('q') => { - app.send_swarm.send_async(SwarmAction::Shutdown).await?; - return Ok(()); - } - KeyCode::Down => app.next(), - KeyCode::Up => app.previous(), - KeyCode::Char('k') => app.previous(), - KeyCode::Char('j') => app.next(), - KeyCode::Tab => app.input_mode = InputMode::Editing, - _ => {} - } - } - } - InputMode::Editing => { - if let Some(Ok(Event::Key(key))) = user_event { - match key.code { - // broadcast message to the swarm with the global topic - KeyCode::Enter => { - let (s, r) = flume::unbounded(); - app.send_swarm.send_async(SwarmAction::GetId(s)).await?; - let msg = Message { - topic: "global".to_string(), - content: app.input, - // FIXME this should NOT be needed. Get it from the swarm. - sender: r.recv_async().await?.to_string(), - }; - let (s, r) = flume::unbounded(); - app.send_swarm.send_async(SwarmAction::GossipMsg(msg.clone(), s)).await?; - let mb_handle = app.message_buffer.clone(); - async_std::task::spawn(async move { - match r.recv_async().await? { - Ok(_) => mb_handle.lock().push_back(msg), - Err(_) => (), - } - Result::<(), flume::RecvError>::Ok(()) - }); - app.input = String::new() - } - KeyCode::Char(c) => { - app.input.push(c); - } - KeyCode::Backspace => { - app.input.pop(); - } - KeyCode::Tab => { - app.input_mode = InputMode::Normal; - } - _ => {} - } - } - } - } - } - - ); - } -} - -fn ui(f: &mut Frame, app: &mut TableApp) -> Result<()> { - let rects = Layout::default() - // two rectanges: one for messages, the other for input - .constraints( - [Constraint::Percentage(60), - Constraint::Percentage(30), - Constraint::Percentage(10) - ].as_ref()) - .margin(5) - .split(f.size()); - - // Styles - let selected_style = Style::default().add_modifier(Modifier::REVERSED); - let normal_style = Style::default().bg(Color::Blue); - // Setup header - let header_cells = ["Sender", "Message"] - .iter() - .map(|h| Cell::from(*h).style(Style::default().fg(Color::Red))); - let header = Row::new(header_cells).style(normal_style); - // Generate the rows - let handle = app.message_buffer.lock(); // Lock the messages mutex - let rows = handle.iter().map(|message| { - let sender = message.sender.clone(); - let content = message.content.clone(); - let height = content.chars().filter(|c| *c == '\n').count() + 1; - let cells = vec![Cell::from(sender), Cell::from(content)]; - Row::new(cells).height(height as u16) - }); - let table = Table::new(rows) - .header(header) - .block(Block::default().borders(Borders::ALL).title("Messages")) - .highlight_style(selected_style) - .highlight_symbol(">> ") - .widths(&[ - Constraint::Percentage(50), - Constraint::Length(30), - Constraint::Min(10), - ]) - .style(match app.input_mode { - InputMode::Editing => Style::default(), - InputMode::Normal => Style::default().fg(Color::Yellow), - }) - ; - f.render_stateful_widget(table, rects[0], &mut app.state); - - 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, rects[2]); - - Ok(()) -} diff --git a/libp2p-networking/src/lib.rs b/libp2p-networking/src/lib.rs index 4ff107a863..a632d3f034 100644 --- a/libp2p-networking/src/lib.rs +++ b/libp2p-networking/src/lib.rs @@ -44,6 +44,7 @@ use libp2p::{ use serde::{de::DeserializeOwned, Serialize}; use snafu::{ResultExt, Snafu}; use tracing::{debug, error, info, info_span, instrument, trace, warn, Instrument}; +pub mod ui; #[derive(NetworkBehaviour)] #[behaviour(out_event = "NetworkEvent")] diff --git a/libp2p-networking/src/ui.rs b/libp2p-networking/src/ui.rs new file mode 100644 index 0000000000..3cd1394814 --- /dev/null +++ b/libp2p-networking/src/ui.rs @@ -0,0 +1,235 @@ +use color_eyre::{Report, eyre::{Result, WrapErr}}; +use crossterm::event::{self, Event, KeyCode}; +use flume::{Sender, Receiver}; +use futures::{select, StreamExt, FutureExt}; +use async_std::task::{sleep, spawn}; +use parking_lot::Mutex; +use libp2p::gossipsub::GossipsubMessage; +use serde::{Serialize, Deserialize}; +use tracing::instrument; +use tui::{widgets::{Block, Borders, Row, Cell, Table, Paragraph, TableState}, style::{Color, Modifier, Style}, Frame, layout::{Layout, Constraint}, backend::Backend, Terminal}; +use std::{time::Duration, sync::Arc, collections::VecDeque}; + +use crate::{SwarmResult, GossipMsg, SwarmAction}; + +#[derive(Debug, Copy, Clone)] +pub enum InputMode { + Normal, + Editing, +} + +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct Message { + pub sender: String, + pub content: String, + pub topic: String, +} + +impl GossipMsg for Message { + fn topic(&self) -> libp2p::gossipsub::IdentTopic { + libp2p::gossipsub::IdentTopic::new(self.topic.clone()) + } + fn data(&self) -> Vec { + self.content.as_bytes().into() + } +} + +impl From for Message { + fn from(msg: GossipsubMessage) -> Self { + let content = String::from_utf8_lossy(&msg.data).to_string(); + let sender = msg + .source + .map_or_else(|| "UNKNOWN".to_string(), |p| p.to_string()); + Message { + sender, + content, + topic: msg.topic.into_string(), + } + } +} + + +#[derive(Debug)] +/// Struct for the TUI app +pub struct TableApp { + pub send_swarm: Sender>, + pub recv_swarm: Receiver>, + pub input_mode: InputMode, + pub input: String, + pub state: TableState, + pub message_buffer: Arc>>, +} + +impl TableApp { + pub fn new( + message_buffer: Arc>>, + send_swarm: Sender>, + recv_swarm: Receiver>, + ) -> Self { + Self { + send_swarm, + recv_swarm, + input_mode: InputMode::Normal, + input: String::new(), + state: TableState::default(), + message_buffer, + } + } + pub fn next(&mut self) { + let buffer_handle = self.message_buffer.lock(); + let i = self.state.selected().unwrap_or(0) + 1; + self.state.select(Some(i % buffer_handle.len())); + } + + pub fn previous(&mut self) { + let buffer_handle = self.message_buffer.lock(); + let i = match self.state.selected() { + Some(i) => { + if i == 0 { + buffer_handle.len() - 1 + } else { + i - 1 + } + } + None => 0, + }; + self.state.select(Some(i)); + } +} + +#[allow(clippy::mut_mut, clippy::panic)] +#[instrument(skip(terminal, app))] +pub async fn run_app(terminal: &mut Terminal, mut app: TableApp) -> Result<()> { + let mut events = event::EventStream::new(); + loop { + terminal + .draw(|f| ui(f, &mut app).expect("Failed to draw UI")) + .context("Failed drawing application")?; + select!( + _ = sleep(Duration::from_nanos(1)).fuse() => {} + swarm_msg = app.recv_swarm.recv_async() => { + if let Ok(res) = swarm_msg { + match res { + SwarmResult::GossipMsg(s) => app.message_buffer.lock().push_back(s), + } + } + }, + user_event = events.next().fuse() => { + match app.input_mode { + InputMode::Normal => { + if let Some(Ok(Event::Key(key))) = user_event { + match key.code { + KeyCode::Char('q') => { + app.send_swarm.send_async(SwarmAction::Shutdown).await?; + return Ok(()); + } + KeyCode::Down | KeyCode::Char('j') => app.next(), + KeyCode::Up | KeyCode::Char('k')=> app.previous(), + KeyCode::Tab => app.input_mode = InputMode::Editing, + _ => {} + } + } + } + InputMode::Editing => { + if let Some(Ok(Event::Key(key))) = user_event { + match key.code { + // broadcast message to the swarm with the global topic + KeyCode::Enter => { + let mb_handle = app.message_buffer.clone(); + let send_swarm = app.send_swarm.clone(); + // we don't want this to block the event loop + spawn(async move { + let (s, r) = flume::unbounded(); + send_swarm.send_async(SwarmAction::GetId(s)).await.context("")?; + let msg = Message { + topic: "global".to_string(), + content: app.input, + // FIXME this should NOT be needed. Get it from the swarm. + sender: r.recv_async().await?.to_string(), + }; + let (s, r) = flume::unbounded(); + send_swarm.send_async(SwarmAction::GossipMsg(msg.clone(), s)).await?; + // if it's a duplicate message (error case), fail silently and do nothing + if r.recv_async().await?.is_ok() { + mb_handle.lock().push_back(msg); + } + Result::<(), Report>::Ok(()) + }); + app.input = String::new(); + } + KeyCode::Char(c) => { + app.input.push(c); + } + KeyCode::Backspace => { + app.input.pop(); + } + KeyCode::Tab => { + app.input_mode = InputMode::Normal; + } + _ => {} + } + } + } + } + } + + ); + } +} + +#[allow(clippy::unnecessary_wraps)] +fn ui(f: &mut Frame<'_, B>, app: &mut TableApp) -> Result<()> { + let rects = Layout::default() + // two rectanges: one for messages, the other for input + .constraints( + [Constraint::Percentage(60), + Constraint::Percentage(30), + Constraint::Percentage(10) + ].as_ref()) + .margin(5) + .split(f.size()); + + // Styles + let selected_style = Style::default().add_modifier(Modifier::REVERSED); + let normal_style = Style::default().bg(Color::Blue); + // Setup header + let header_cells = ["Sender", "Message"] + .iter() + .map(|h| Cell::from(*h).style(Style::default().fg(Color::Red))); + let header = Row::new(header_cells).style(normal_style); + // Generate the rows + let handle = app.message_buffer.lock(); // Lock the messages mutex + let rows : Vec> = handle.iter().map(|message| { + let sender = message.sender.clone(); + let content = message.content.clone(); + let height = content.chars().filter(|c| *c == '\n').count() + 1; + let cells = vec![Cell::from(sender), Cell::from(content)]; + Ok(Row::new(cells).height(u16::try_from(height).context("row too low")?)) + }).collect::>, Report>>()?; + let table = Table::new(rows.into_iter()) + .header(header) + .block(Block::default().borders(Borders::ALL).title("Messages")) + .highlight_style(selected_style) + .highlight_symbol(">> ") + .widths(&[ + Constraint::Percentage(50), + Constraint::Length(30), + Constraint::Min(10), + ]) + .style(match app.input_mode { + InputMode::Editing => Style::default(), + InputMode::Normal => Style::default().fg(Color::Yellow), + }) + ; + f.render_stateful_widget(table, rects[0], &mut app.state); + + 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, rects[2]); + + Ok(()) +} From d050be2ef8daa2c9479473024049fea4de1dd6ee Mon Sep 17 00:00:00 2001 From: Justin Restivo Date: Mon, 17 Jan 2022 14:45:57 -0500 Subject: [PATCH 018/107] Maintain connected peer list --- libp2p-networking/src/bin/clichat.rs | 11 +--- libp2p-networking/src/lib.rs | 62 ++++++++++++------ libp2p-networking/src/ui.rs | 97 ++++++++++++++++++++-------- 3 files changed, 115 insertions(+), 55 deletions(-) diff --git a/libp2p-networking/src/bin/clichat.rs b/libp2p-networking/src/bin/clichat.rs index 9c80236b17..b8e3beab1a 100644 --- a/libp2p-networking/src/bin/clichat.rs +++ b/libp2p-networking/src/bin/clichat.rs @@ -1,6 +1,5 @@ - -use libp2p::{Multiaddr}; -use networking_demo::ui::{Message, run_app, TableApp}; +use libp2p::Multiaddr; +use networking_demo::ui::{run_app, Message, TableApp}; use std::sync::Arc; use std::{collections::VecDeque, marker::PhantomData}; @@ -15,10 +14,7 @@ use crossterm::{ use parking_lot::Mutex; use tracing::instrument; -use tui::{ - backend::CrosstermBackend, Terminal, -}; - +use tui::{backend::CrosstermBackend, Terminal}; use networking_demo::{gen_multiaddr, Network, NetworkDef, SwarmAction}; @@ -101,4 +97,3 @@ async fn main() -> Result<()> { println!("{:?}", messages); res } - diff --git a/libp2p-networking/src/lib.rs b/libp2p-networking/src/lib.rs index a632d3f034..fa893f7733 100644 --- a/libp2p-networking/src/lib.rs +++ b/libp2p-networking/src/lib.rs @@ -17,7 +17,7 @@ pub mod tracing_setup; use async_std::task::spawn; -use std::{marker::PhantomData, time::Duration}; +use std::{collections::HashSet, marker::PhantomData, time::Duration}; use flume::{unbounded, Receiver, Sender}; use futures::{select, StreamExt}; @@ -25,15 +25,8 @@ use libp2p::{ build_multiaddr, core::{muxing::StreamMuxerBox, transport::Boxed}, gossipsub::{ - error::PublishError, - Gossipsub, - GossipsubConfigBuilder, - GossipsubEvent, - GossipsubMessage, - IdentTopic as Topic, - MessageAuthenticity, - MessageId, - ValidationMode, + error::PublishError, Gossipsub, GossipsubConfigBuilder, GossipsubEvent, GossipsubMessage, + IdentTopic as Topic, MessageAuthenticity, MessageId, ValidationMode, }, identify::{Identify, IdentifyConfig, IdentifyEvent}, identity::Keypair, @@ -81,10 +74,12 @@ impl From for NetworkEvent { } pub struct Network { + pub connected_peers: HashSet, pub identity: Keypair, pub peer_id: PeerId, pub broadcast_topic: Topic, pub swarm: Swarm, + pub max_num_peers: usize, _phantom: PhantomData, } @@ -97,9 +92,10 @@ pub enum SwarmAction { Unsubscribe(String), } -/// holds events of the swarm to be relayed +/// holds events of the swarm to be relayed to the cli event loop /// out pub enum SwarmResult { + UpdateConnectedPeers(HashSet), GossipMsg(N), } @@ -136,6 +132,9 @@ impl Net let dialing = known_peer.clone(); match self.swarm.dial(known_peer) { Ok(_) => { + // TODO may need to ad address here + // Kademlia::add_address + // self.swarm.kadem.add_add info!("Dialed {:?}", dialing); } Err(e) => error!("Dial {:?} failed: {:?}", dialing, e), @@ -234,7 +233,9 @@ where Ok(Self { identity, peer_id, + connected_peers: HashSet::new(), broadcast_topic, + max_num_peers: 5, swarm, _phantom: PhantomData, }) @@ -249,6 +250,13 @@ where pub async fn spawn_listeners(mut self) -> (Sender>, Receiver>) { let (s_input, s_output) = unbounded::>(); let (r_input, r_output) = unbounded::>(); + // TODO fix this error handling + let _ = r_input + .send_async(SwarmResult::UpdateConnectedPeers( + self.connected_peers.clone(), + )) + .await + .map_err(|_e| NetworkError::StreamClosed); spawn(async move { loop { select! { @@ -259,8 +267,6 @@ where | SwarmEvent::NewListenAddr {..} | SwarmEvent::ExpiredListenAddr {..} | SwarmEvent::ListenerClosed {..} - | SwarmEvent::ConnectionEstablished {..} - | SwarmEvent::ConnectionClosed {..} | SwarmEvent::IncomingConnection {..} | SwarmEvent::IncomingConnectionError {..} | SwarmEvent::OutgoingConnectionError {..} @@ -272,14 +278,15 @@ where NetworkEvent::Gossip(g) => { match g { GossipsubEvent::Message { message, .. } => { - r_input.send(SwarmResult::GossipMsg(message.into())).map_err(|_e| NetworkError::StreamClosed)?; + // FIXME proper error handling + r_input.send_async(SwarmResult::GossipMsg(message.into())).await.map_err(|_e| NetworkError::StreamClosed)?; }, _ => { info!(?g); } } }, - NetworkEvent::Kadem(_k) => { + NetworkEvent::Kadem(_event) => { // TODO }, NetworkEvent::Ident(_i) => { @@ -288,6 +295,24 @@ where } }, + SwarmEvent::ConnectionEstablished { peer_id, .. } => { + self.connected_peers.insert(peer_id); + r_input.send_async(SwarmResult::UpdateConnectedPeers(self.connected_peers.clone())).await.map_err(|_e| NetworkError::StreamClosed)?; + } + SwarmEvent::ConnectionClosed { peer_id, .. } => { + self.connected_peers.remove(&peer_id); + // search for more peers + let peers = self.swarm.behaviour_mut().gossipsub.peer_protocol().map(|(&p, _)| p); + for peer in peers { + if !self.connected_peers.contains(&peer) && self.connected_peers.len() <= self.max_num_peers + { + self.connected_peers.insert(peer); + + } + } + + r_input.send_async(SwarmResult::UpdateConnectedPeers(self.connected_peers.clone())).await.map_err(|_e| NetworkError::StreamClosed)?; + } } }, msg = s_output.recv_async() => { @@ -325,8 +350,7 @@ where error!("error unsubscribing to topic {}", t); } } - } - + }, } }, Err(e) => { @@ -372,6 +396,6 @@ pub enum NetworkError { // occurs if one of the channels to or from the swarm is closed StreamClosed, PublishError { - source: PublishError - } + source: PublishError, + }, } diff --git a/libp2p-networking/src/ui.rs b/libp2p-networking/src/ui.rs index 3cd1394814..ab6d6609cf 100644 --- a/libp2p-networking/src/ui.rs +++ b/libp2p-networking/src/ui.rs @@ -1,16 +1,29 @@ -use color_eyre::{Report, eyre::{Result, WrapErr}}; -use crossterm::event::{self, Event, KeyCode}; -use flume::{Sender, Receiver}; -use futures::{select, StreamExt, FutureExt}; use async_std::task::{sleep, spawn}; -use parking_lot::Mutex; +use color_eyre::{ + eyre::{Result, WrapErr}, + Report, +}; +use crossterm::event::{self, Event, KeyCode}; +use flume::{Receiver, Sender}; +use futures::{select, FutureExt, StreamExt}; use libp2p::gossipsub::GossipsubMessage; -use serde::{Serialize, Deserialize}; -use tracing::instrument; -use tui::{widgets::{Block, Borders, Row, Cell, Table, Paragraph, TableState}, style::{Color, Modifier, Style}, Frame, layout::{Layout, Constraint}, backend::Backend, Terminal}; -use std::{time::Duration, sync::Arc, collections::VecDeque}; +use parking_lot::Mutex; +use serde::{Deserialize, Serialize}; +use std::{ + collections::{HashSet, VecDeque}, + sync::Arc, + time::Duration, +}; +use tracing::{error, instrument}; +use tui::{ + backend::Backend, + layout::{Constraint, Layout}, + style::{Color, Modifier, Style}, + widgets::{Block, Borders, Cell, Paragraph, Row, Table, TableState}, + Frame, Terminal, +}; -use crate::{SwarmResult, GossipMsg, SwarmAction}; +use crate::{GossipMsg, SwarmAction, SwarmResult}; #[derive(Debug, Copy, Clone)] pub enum InputMode { @@ -48,7 +61,6 @@ impl From for Message { } } - #[derive(Debug)] /// Struct for the TUI app pub struct TableApp { @@ -58,6 +70,7 @@ pub struct TableApp { pub input: String, pub state: TableState, pub message_buffer: Arc>>, + pub peer_list: Arc>>, } impl TableApp { @@ -73,6 +86,7 @@ impl TableApp { input: String::new(), state: TableState::default(), message_buffer, + peer_list: Arc::new(Mutex::new(HashSet::new())), } } pub fn next(&mut self) { @@ -106,14 +120,20 @@ pub async fn run_app(terminal: &mut Terminal, mut app: TableApp) .draw(|f| ui(f, &mut app).expect("Failed to draw UI")) .context("Failed drawing application")?; select!( + // force a periodic refresh _ = sleep(Duration::from_nanos(1)).fuse() => {} + // swarm may have instructions swarm_msg = app.recv_swarm.recv_async() => { if let Ok(res) = swarm_msg { match res { SwarmResult::GossipMsg(s) => app.message_buffer.lock().push_back(s), + SwarmResult::UpdateConnectedPeers(peer_set) => { + *app.peer_list.lock() = peer_set.into_iter().map(|p| p.to_string()).collect::>(); + } } } }, + // user driven events user_event = events.next().fuse() => { match app.input_mode { InputMode::Normal => { @@ -139,7 +159,7 @@ pub async fn run_app(terminal: &mut Terminal, mut app: TableApp) let send_swarm = app.send_swarm.clone(); // we don't want this to block the event loop spawn(async move { - let (s, r) = flume::unbounded(); + let (s, r) = flume::bounded(1); send_swarm.send_async(SwarmAction::GetId(s)).await.context("")?; let msg = Message { topic: "global".to_string(), @@ -147,7 +167,7 @@ pub async fn run_app(terminal: &mut Terminal, mut app: TableApp) // FIXME this should NOT be needed. Get it from the swarm. sender: r.recv_async().await?.to_string(), }; - let (s, r) = flume::unbounded(); + let (s, r) = flume::bounded(1); send_swarm.send_async(SwarmAction::GossipMsg(msg.clone(), s)).await?; // if it's a duplicate message (error case), fail silently and do nothing if r.recv_async().await?.is_ok() { @@ -182,10 +202,13 @@ fn ui(f: &mut Frame<'_, B>, app: &mut TableApp) -> Result<()> { let rects = Layout::default() // two rectanges: one for messages, the other for input .constraints( - [Constraint::Percentage(60), - Constraint::Percentage(30), - Constraint::Percentage(10) - ].as_ref()) + [ + Constraint::Percentage(60), + Constraint::Percentage(30), + Constraint::Percentage(10), + ] + .as_ref(), + ) .margin(5) .split(f.size()); @@ -198,15 +221,19 @@ fn ui(f: &mut Frame<'_, B>, app: &mut TableApp) -> Result<()> { .map(|h| Cell::from(*h).style(Style::default().fg(Color::Red))); let header = Row::new(header_cells).style(normal_style); // Generate the rows - let handle = app.message_buffer.lock(); // Lock the messages mutex - let rows : Vec> = handle.iter().map(|message| { - let sender = message.sender.clone(); - let content = message.content.clone(); - let height = content.chars().filter(|c| *c == '\n').count() + 1; - let cells = vec![Cell::from(sender), Cell::from(content)]; - Ok(Row::new(cells).height(u16::try_from(height).context("row too low")?)) - }).collect::>, Report>>()?; - let table = Table::new(rows.into_iter()) + let message_handle = app.message_buffer.lock(); // Lock the messages mutex + let message_rows: Vec> = message_handle + .iter() + .map(|message| { + let sender = message.sender.clone(); + let content = message.content.clone(); + let height = content.chars().filter(|c| *c == '\n').count() + 1; + let cells = vec![Cell::from(sender), Cell::from(content)]; + Ok(Row::new(cells) + .height(u16::try_from(height).context("integer overflow calculating row")?)) + }) + .collect::>, Report>>()?; + let message_table = Table::new(message_rows.into_iter()) .header(header) .block(Block::default().borders(Borders::ALL).title("Messages")) .highlight_style(selected_style) @@ -219,9 +246,23 @@ fn ui(f: &mut Frame<'_, B>, app: &mut TableApp) -> Result<()> { .style(match app.input_mode { InputMode::Editing => Style::default(), InputMode::Normal => Style::default().fg(Color::Yellow), + }); + f.render_stateful_widget(message_table, rects[0], &mut app.state); + + let peerid_handle = app.peer_list.lock(); + let peerid_rows: Vec> = peerid_handle + .iter() + .map(|peer_id| { + let height = peer_id.chars().filter(|c| *c == '\n').count() + 1; + let cells = vec![Cell::from(peer_id.clone())]; + Ok(Row::new(cells) + .height(u16::try_from(height).context("integer overflow calculating row")?)) }) - ; - f.render_stateful_widget(table, rects[0], &mut app.state); + .collect::>, Report>>()?; + let peerid_table = Table::new(peerid_rows.into_iter()) + .block(Block::default().borders(Borders::ALL).title("peer ids")) + .widths(&[Constraint::Percentage(100)]); + f.render_stateful_widget(peerid_table, rects[1], &mut app.state); let input = Paragraph::new(app.input.as_ref()) .style(match app.input_mode { From 829617b040a7c2794ea0715a7451dfefe253190b Mon Sep 17 00:00:00 2001 From: Justin Restivo Date: Tue, 18 Jan 2022 14:10:47 -0500 Subject: [PATCH 019/107] Missing edge case on reconnect to bootstrap peer --- libp2p-networking/src/lib.rs | 128 ++++++++++++++++++++++++++++------- 1 file changed, 103 insertions(+), 25 deletions(-) diff --git a/libp2p-networking/src/lib.rs b/libp2p-networking/src/lib.rs index fa893f7733..9d0f91b56c 100644 --- a/libp2p-networking/src/lib.rs +++ b/libp2p-networking/src/lib.rs @@ -16,21 +16,21 @@ pub mod tracing_setup; -use async_std::task::spawn; -use std::{collections::HashSet, marker::PhantomData, time::Duration}; +use async_std::task::{spawn, sleep}; +use std::{collections::{HashSet, HashMap}, marker::PhantomData, time::Duration}; use flume::{unbounded, Receiver, Sender}; -use futures::{select, StreamExt}; +use futures::{select, FutureExt, StreamExt}; use libp2p::{ build_multiaddr, - core::{muxing::StreamMuxerBox, transport::Boxed}, + core::{muxing::StreamMuxerBox, transport::Boxed, ConnectedPoint}, gossipsub::{ error::PublishError, Gossipsub, GossipsubConfigBuilder, GossipsubEvent, GossipsubMessage, IdentTopic as Topic, MessageAuthenticity, MessageId, ValidationMode, }, identify::{Identify, IdentifyConfig, IdentifyEvent}, identity::Keypair, - kad::{store::MemoryStore, Kademlia, KademliaEvent}, + kad::{store::MemoryStore, Kademlia, KademliaEvent, self, GetClosestPeersOk, KademliaConfig}, swarm::{NetworkBehaviour, SwarmEvent}, Multiaddr, NetworkBehaviour, PeerId, Swarm, TransportError, }; @@ -39,11 +39,18 @@ use snafu::{ResultExt, Snafu}; use tracing::{debug, error, info, info_span, instrument, trace, warn, Instrument}; pub mod ui; +/// event_process is false because +/// injecting events does not play well +/// with asyncrony #[derive(NetworkBehaviour)] #[behaviour(out_event = "NetworkEvent")] #[behaviour(event_process = false)] pub struct NetworkDef { + /// NOTE gossipsub works ONLY for sharing messsages right now + /// in the future it may be able to do peer discovery and routing + /// at which point we can scrap kadem pub gossipsub: Gossipsub, + /// used for passive peer discovery and peer routing pub kadem: Kademlia, pub identify: Identify, } @@ -75,6 +82,8 @@ impl From for NetworkEvent { pub struct Network { pub connected_peers: HashSet, + pub connecting_peers: HashSet, + pub known_peers: HashSet, pub identity: Keypair, pub peer_id: PeerId, pub broadcast_topic: Topic, @@ -132,9 +141,6 @@ impl Net let dialing = known_peer.clone(); match self.swarm.dial(known_peer) { Ok(_) => { - // TODO may need to ad address here - // Kademlia::add_address - // self.swarm.kadem.add_add info!("Dialed {:?}", dialing); } Err(e) => error!("Dial {:?} failed: {:?}", dialing, e), @@ -193,12 +199,18 @@ where // Use a jank match because Gossipsubconfigbuilder::build returns a non-static str for // some god forsaken reason let gossipsub_config = GossipsubConfigBuilder::default() - // Use a reasonable 10 second heartbeat interval by default - .heartbeat_interval(Duration::from_secs(10)) + .heartbeat_interval(Duration::from_secs(1)) // Force all messages to have valid signatures .validation_mode(ValidationMode::Strict) // Use the (blake3) hash of a message as its ID .message_id_fn(message_id_fn) + .mesh_n_low(1) + .gossip_factor(1.0f64) + .mesh_outbound_min(0) + .opportunistic_graft_ticks(1) + + // defaults to true but we want this + .do_px() .build() .map_err(|s| GossipsubConfigSnafu { message: s }.build())?; // - Build a gossipsub network behavior @@ -219,7 +231,9 @@ where // - Build DHT needed for peer discovery // TODO check into the MemoryStore defaults - let kadem = Kademlia::new(peer_id, MemoryStore::new(peer_id)); + let mut kconfig = KademliaConfig::default(); + kconfig.set_caching(kad::KademliaCaching::Disabled); + let kadem = Kademlia::with_config(peer_id, MemoryStore::new(peer_id), kconfig); let network = NetworkDef { gossipsub, @@ -234,6 +248,8 @@ where identity, peer_id, connected_peers: HashSet::new(), + connecting_peers: HashSet::new(), + known_peers: HashSet::new(), broadcast_topic, max_num_peers: 5, swarm, @@ -257,11 +273,32 @@ where )) .await .map_err(|_e| NetworkError::StreamClosed); + + let mut bootstrapped = false; spawn(async move { loop { select! { + _ = sleep(Duration::from_secs(10)).fuse() => { + if !bootstrapped { + if self.connecting_peers.len() + self.connected_peers.len() <= self.max_num_peers { + let potential_peers : HashSet = self.known_peers.difference(&self.connecting_peers.union(&self.connected_peers).cloned().collect()).cloned().collect(); + for a_peer in potential_peers { + match self.swarm.dial(a_peer) { + Ok(_) => { + self.connecting_peers.insert(a_peer); + + } + Err(e) => error!("Dial {:?} failed: {:?}", a_peer, e), + }; + } + } + for a_peer in self.connected_peers.clone() { + let _ = self.swarm.behaviour_mut().kadem.get_closest_peers(a_peer); + } + } + } event = self.swarm.select_next_some() => { - info!("libp2p event {:?}", event); + error!("libp2p event {:?}", event); match event { SwarmEvent::Dialing(_) | SwarmEvent::NewListenAddr {..} @@ -286,30 +323,71 @@ where } } }, - NetworkEvent::Kadem(_event) => { - // TODO + NetworkEvent::Kadem(event) => { + match event { + KademliaEvent::OutboundQueryCompleted { result, ..} => { + match result { + // FIXME rebootstrap or fail in the failed + // bootstrap case + kad::QueryResult::Bootstrap(Ok(_bootstrap)) => { + // when bootstrap succeeds, + // get more peers + // let _ = self.swarm.behaviour_mut().kadem.get_closest_peers(self.peer_id); + bootstrapped = false; + }, + kad::QueryResult::GetClosestPeers(result) => { + match result { + Ok(GetClosestPeersOk { key: _key, peers }) => { + for peer in peers { + self.known_peers.insert(peer); + } + }, + _ => {} + } + }, + _ => {} + } + }, + KademliaEvent::RoutingUpdated { peer, is_new_peer: _is_new_peer, addresses: _addresses, .. } => { + self.known_peers.insert(peer); + }, + _ => {} + } }, - NetworkEvent::Ident(_i) => { + NetworkEvent::Ident(i) => { // TODO }, } }, - SwarmEvent::ConnectionEstablished { peer_id, .. } => { + SwarmEvent::ConnectionEstablished { peer_id, endpoint, .. } => { + match endpoint { + ConnectedPoint::Dialer { address } => { + self.swarm.behaviour_mut().kadem.add_address(&peer_id, address); + }, + ConnectedPoint::Listener { local_addr: _, send_back_addr } => { + self.swarm.behaviour_mut().kadem.add_address(&peer_id, send_back_addr); + }, + } self.connected_peers.insert(peer_id); + self.connecting_peers.remove(&peer_id); + // now we have at least one peer so we can bootstrap + if !bootstrapped { + // TODO error handling + let _ = self.swarm.behaviour_mut().kadem.bootstrap(); + } r_input.send_async(SwarmResult::UpdateConnectedPeers(self.connected_peers.clone())).await.map_err(|_e| NetworkError::StreamClosed)?; } SwarmEvent::ConnectionClosed { peer_id, .. } => { self.connected_peers.remove(&peer_id); - // search for more peers - let peers = self.swarm.behaviour_mut().gossipsub.peer_protocol().map(|(&p, _)| p); - for peer in peers { - if !self.connected_peers.contains(&peer) && self.connected_peers.len() <= self.max_num_peers - { - self.connected_peers.insert(peer); - - } - } + self.known_peers.remove(&peer_id); + let _ = self.swarm.disconnect_peer_id(peer_id); + // self.swarm.behaviour_mut().kadem.disconnect_peer_id(); + // if self.connected_peers.len() <= self.max_num_peers { + // // search for more peers + // // TODO error handling + // let _ = self.swarm.behaviour_mut().kadem.get_closest_peers(self.peer_id); + // } r_input.send_async(SwarmResult::UpdateConnectedPeers(self.connected_peers.clone())).await.map_err(|_e| NetworkError::StreamClosed)?; } From e3d000988e2669e152c6ece34d78d44341703996 Mon Sep 17 00:00:00 2001 From: Justin Restivo Date: Tue, 18 Jan 2022 15:24:43 -0500 Subject: [PATCH 020/107] mesh works --- libp2p-networking/src/lib.rs | 39 +++++++++++++++++++----------------- 1 file changed, 21 insertions(+), 18 deletions(-) diff --git a/libp2p-networking/src/lib.rs b/libp2p-networking/src/lib.rs index 9d0f91b56c..7885b08818 100644 --- a/libp2p-networking/src/lib.rs +++ b/libp2p-networking/src/lib.rs @@ -16,8 +16,12 @@ pub mod tracing_setup; -use async_std::task::{spawn, sleep}; -use std::{collections::{HashSet, HashMap}, marker::PhantomData, time::Duration}; +use async_std::task::{sleep, spawn}; +use std::{ + collections::{HashMap, HashSet}, + marker::PhantomData, + time::Duration, +}; use flume::{unbounded, Receiver, Sender}; use futures::{select, FutureExt, StreamExt}; @@ -30,7 +34,7 @@ use libp2p::{ }, identify::{Identify, IdentifyConfig, IdentifyEvent}, identity::Keypair, - kad::{store::MemoryStore, Kademlia, KademliaEvent, self, GetClosestPeersOk, KademliaConfig}, + kad::{self, store::MemoryStore, GetClosestPeersOk, Kademlia, KademliaConfig, KademliaEvent}, swarm::{NetworkBehaviour, SwarmEvent}, Multiaddr, NetworkBehaviour, PeerId, Swarm, TransportError, }; @@ -82,6 +86,7 @@ impl From for NetworkEvent { pub struct Network { pub connected_peers: HashSet, + // TODO replace this with a set of queryids pub connecting_peers: HashSet, pub known_peers: HashSet, pub identity: Keypair, @@ -208,7 +213,6 @@ where .gossip_factor(1.0f64) .mesh_outbound_min(0) .opportunistic_graft_ticks(1) - // defaults to true but we want this .do_px() .build() @@ -279,6 +283,8 @@ where loop { select! { _ = sleep(Duration::from_secs(10)).fuse() => { + // if we're bootstrapped, do nothing + // otherwise periodically get more peers if !bootstrapped { if self.connecting_peers.len() + self.connected_peers.len() <= self.max_num_peers { let potential_peers : HashSet = self.known_peers.difference(&self.connecting_peers.union(&self.connected_peers).cloned().collect()).cloned().collect(); @@ -292,9 +298,6 @@ where }; } } - for a_peer in self.connected_peers.clone() { - let _ = self.swarm.behaviour_mut().kadem.get_closest_peers(a_peer); - } } } event = self.swarm.select_next_some() => { @@ -330,9 +333,7 @@ where // FIXME rebootstrap or fail in the failed // bootstrap case kad::QueryResult::Bootstrap(Ok(_bootstrap)) => { - // when bootstrap succeeds, - // get more peers - // let _ = self.swarm.behaviour_mut().kadem.get_closest_peers(self.peer_id); + // we're bootstrapped bootstrapped = false; }, kad::QueryResult::GetClosestPeers(result) => { @@ -355,7 +356,16 @@ where } }, NetworkEvent::Ident(i) => { - // TODO + match i { + IdentifyEvent::Received { peer_id, info, .. } => { + for addr in info.listen_addrs { + self.swarm.behaviour_mut().kadem + .add_address(&peer_id, addr.clone()); + } + }, + _ => {} + + } }, } @@ -381,13 +391,6 @@ where SwarmEvent::ConnectionClosed { peer_id, .. } => { self.connected_peers.remove(&peer_id); self.known_peers.remove(&peer_id); - let _ = self.swarm.disconnect_peer_id(peer_id); - // self.swarm.behaviour_mut().kadem.disconnect_peer_id(); - // if self.connected_peers.len() <= self.max_num_peers { - // // search for more peers - // // TODO error handling - // let _ = self.swarm.behaviour_mut().kadem.get_closest_peers(self.peer_id); - // } r_input.send_async(SwarmResult::UpdateConnectedPeers(self.connected_peers.clone())).await.map_err(|_e| NetworkError::StreamClosed)?; } From 90e7ed144b6be194b1371e1b479f7abfc37835cb Mon Sep 17 00:00:00 2001 From: Justin Restivo Date: Tue, 18 Jan 2022 19:36:35 -0500 Subject: [PATCH 021/107] Fix clippy, pruning nodes. --- libp2p-networking/Cargo.lock | 1 + libp2p-networking/Cargo.toml | 1 + libp2p-networking/README | 20 +++++++ libp2p-networking/src/bin/clichat.rs | 2 +- libp2p-networking/src/lib.rs | 82 ++++++++++++++++++---------- libp2p-networking/src/ui.rs | 2 +- 6 files changed, 76 insertions(+), 32 deletions(-) diff --git a/libp2p-networking/Cargo.lock b/libp2p-networking/Cargo.lock index 728ce50ee0..86468e4fb8 100644 --- a/libp2p-networking/Cargo.lock +++ b/libp2p-networking/Cargo.lock @@ -1999,6 +1999,7 @@ dependencies = [ "futures", "libp2p", "parking_lot", + "rand 0.8.4", "serde", "snafu", "structopt", diff --git a/libp2p-networking/Cargo.toml b/libp2p-networking/Cargo.toml index 1c48540b3f..5c5edaf17f 100644 --- a/libp2p-networking/Cargo.toml +++ b/libp2p-networking/Cargo.toml @@ -22,3 +22,4 @@ tracing = "0.1.29" tracing-error = "0.2.0" tracing-subscriber = { version = "0.3.5", features = ["env-filter", "json"] } tui = { version = "0.16.0", features = ["crossterm"], default-features = false } +rand = "0.8.4" diff --git a/libp2p-networking/README b/libp2p-networking/README index 226dff99a1..20aa0604ea 100644 --- a/libp2p-networking/README +++ b/libp2p-networking/README @@ -6,4 +6,24 @@ To get very verbose logging: RUST_LOG_OUTPUT=OUTFILE RUST_LOG="trace" cargo run --release ``` +The idea here is to spin up several such nodes. Something akin to (in separate terminals) + +``` +nix develop -c "RUST_LOG_OUTPUT=OUTFILE_0 RUST_LOG=error cargo run --release -- -p 1111" +nix develop -c "RUST_LOG_OUTPUT=OUTFILE_0 RUST_LOG=error cargo run --release -- /ip4/127.0.0.1/tcp/1111 -p 2222" +nix develop -c "RUST_LOG_OUTPUT=OUTFILE_0 RUST_LOG=error cargo run --release -- /ip4/127.0.0.1/tcp/2222 -p 3333" +nix develop -c "RUST_LOG_OUTPUT=OUTFILE_0 RUST_LOG=error cargo run --release -- /ip4/127.0.0.1/tcp/3333 -p 4444" +nix develop -c "RUST_LOG_OUTPUT=OUTFILE_0 RUST_LOG=error cargo run --release -- /ip4/127.0.0.1/tcp/4444 -p 5555" +nix develop -c "RUST_LOG_OUTPUT=OUTFILE_0 RUST_LOG=error cargo run --release -- /ip4/127.0.0.1/tcp/5555 -p 6666" +nix develop -c "RUST_LOG_OUTPUT=OUTFILE_0 RUST_LOG=error cargo run --release -- /ip4/127.0.0.1/tcp/6666 -p 7777" +nix develop -c "RUST_LOG_OUTPUT=OUTFILE_0 RUST_LOG=error cargo run --release -- /ip4/127.0.0.1/tcp/7777 -p 8888" +nix develop -c "RUST_LOG_OUTPUT=OUTFILE_0 RUST_LOG=error cargo run --release -- /ip4/127.0.0.1/tcp/8888 -p 9999" +``` + +At this point one may kill/start more nodes. The idea is that each node will continue to attempt to connect to nodes +until it hits at least 5 peers. + +Node reconnection has a ui bug but seems to functionally work. I suspect this is a idiosynrasy with +local ports. + diff --git a/libp2p-networking/src/bin/clichat.rs b/libp2p-networking/src/bin/clichat.rs index b8e3beab1a..61b7ccfb14 100644 --- a/libp2p-networking/src/bin/clichat.rs +++ b/libp2p-networking/src/bin/clichat.rs @@ -43,7 +43,7 @@ async fn main() -> Result<()> { let known_peer = CliOpt::from_args().first_dial; let listen_addr = gen_multiaddr(port); networking.start(listen_addr, known_peer)?; - let (send_chan, recv_chan) = networking.spawn_listeners().await; + let (send_chan, recv_chan) = networking.spawn_listeners().await?; // -- Spin up the UI // Setup a ring buffer to hold messages, 25 of them should do for the demo diff --git a/libp2p-networking/src/lib.rs b/libp2p-networking/src/lib.rs index 7885b08818..841c61fb91 100644 --- a/libp2p-networking/src/lib.rs +++ b/libp2p-networking/src/lib.rs @@ -17,11 +17,8 @@ pub mod tracing_setup; use async_std::task::{sleep, spawn}; -use std::{ - collections::{HashMap, HashSet}, - marker::PhantomData, - time::Duration, -}; +use rand::{seq::IteratorRandom, thread_rng}; +use std::{collections::HashSet, marker::PhantomData, time::Duration}; use flume::{unbounded, Receiver, Sender}; use futures::{select, FutureExt, StreamExt}; @@ -34,7 +31,10 @@ use libp2p::{ }, identify::{Identify, IdentifyConfig, IdentifyEvent}, identity::Keypair, - kad::{self, store::MemoryStore, GetClosestPeersOk, Kademlia, KademliaConfig, KademliaEvent}, + kad::{ + self, store::MemoryStore, GetClosestPeersOk, Kademlia, KademliaConfig, KademliaEvent, + QueryResult, + }, swarm::{NetworkBehaviour, SwarmEvent}, Multiaddr, NetworkBehaviour, PeerId, Swarm, TransportError, }; @@ -43,7 +43,7 @@ use snafu::{ResultExt, Snafu}; use tracing::{debug, error, info, info_span, instrument, trace, warn, Instrument}; pub mod ui; -/// event_process is false because +/// `event_process` is false because /// injecting events does not play well /// with asyncrony #[derive(NetworkBehaviour)] @@ -94,6 +94,7 @@ pub struct Network { pub broadcast_topic: Topic, pub swarm: Swarm, pub max_num_peers: usize, + pub min_num_peers: usize, _phantom: PhantomData, } @@ -209,12 +210,6 @@ where .validation_mode(ValidationMode::Strict) // Use the (blake3) hash of a message as its ID .message_id_fn(message_id_fn) - .mesh_n_low(1) - .gossip_factor(1.0f64) - .mesh_outbound_min(0) - .opportunistic_graft_ticks(1) - // defaults to true but we want this - .do_px() .build() .map_err(|s| GossipsubConfigSnafu { message: s }.build())?; // - Build a gossipsub network behavior @@ -255,7 +250,8 @@ where connecting_peers: HashSet::new(), known_peers: HashSet::new(), broadcast_topic, - max_num_peers: 5, + max_num_peers: 6, + min_num_peers: 5, swarm, _phantom: PhantomData, }) @@ -265,29 +261,36 @@ where /// as well as any events produced by libp2p /// `mut_mut` is disabled b/c must consume `self` /// TODO why does clippy not like `panic` with select? - #[allow(clippy::mut_mut, clippy::panic)] + #[allow( + clippy::mut_mut, + clippy::panic, + clippy::single_match, + clippy::collapsible_match + )] #[instrument] - pub async fn spawn_listeners(mut self) -> (Sender>, Receiver>) { + pub async fn spawn_listeners( + mut self, + ) -> Result<(Sender>, Receiver>), NetworkError> { let (s_input, s_output) = unbounded::>(); let (r_input, r_output) = unbounded::>(); - // TODO fix this error handling - let _ = r_input + r_input .send_async(SwarmResult::UpdateConnectedPeers( self.connected_peers.clone(), )) .await - .map_err(|_e| NetworkError::StreamClosed); + .map_err(|_e| NetworkError::StreamClosed)?; let mut bootstrapped = false; spawn(async move { loop { select! { - _ = sleep(Duration::from_secs(10)).fuse() => { + _ = sleep(Duration::from_secs(1)).fuse() => { // if we're bootstrapped, do nothing // otherwise periodically get more peers if !bootstrapped { - if self.connecting_peers.len() + self.connected_peers.len() <= self.max_num_peers { - let potential_peers : HashSet = self.known_peers.difference(&self.connecting_peers.union(&self.connected_peers).cloned().collect()).cloned().collect(); + if self.connecting_peers.len() + self.connected_peers.len() <= self.min_num_peers { + // TODO there's *got* to be a better way to do this + let potential_peers : HashSet = self.known_peers.difference(&self.connecting_peers.union(&self.connected_peers).copied().collect()).copied().collect(); for a_peer in potential_peers { match self.swarm.dial(a_peer) { Ok(_) => { @@ -297,11 +300,18 @@ where Err(e) => error!("Dial {:?} failed: {:?}", a_peer, e), }; } + } else if self.connected_peers.len() > self.max_num_peers { + let peers_to_rm = self.connected_peers.iter().copied().choose_multiple(&mut thread_rng(), self.connected_peers.len() - self.max_num_peers); + for a_peer in peers_to_rm { + // FIXME the error is () ? + let _ = self.swarm.disconnect_peer_id(a_peer); + } + } } } event = self.swarm.select_next_some() => { - error!("libp2p event {:?}", event); + warn!("libp2p event {:?}", event); match event { SwarmEvent::Dialing(_) | SwarmEvent::NewListenAddr {..} @@ -332,11 +342,21 @@ where match result { // FIXME rebootstrap or fail in the failed // bootstrap case - kad::QueryResult::Bootstrap(Ok(_bootstrap)) => { - // we're bootstrapped - bootstrapped = false; + QueryResult::Bootstrap(r) => { + match r { + Ok(_bootstrap) => { + // we're bootstrapped + // don't bootstrap again + bootstrapped = false; + }, + Err(_) => { + // try again + bootstrapped = true; + } + + } }, - kad::QueryResult::GetClosestPeers(result) => { + QueryResult::GetClosestPeers(result) => { match result { Ok(GetClosestPeersOk { key: _key, peers }) => { for peer in peers { @@ -362,6 +382,7 @@ where self.swarm.behaviour_mut().kadem .add_address(&peer_id, addr.clone()); } + self.known_peers.insert(peer_id); }, _ => {} @@ -383,8 +404,8 @@ where self.connecting_peers.remove(&peer_id); // now we have at least one peer so we can bootstrap if !bootstrapped { - // TODO error handling - let _ = self.swarm.behaviour_mut().kadem.bootstrap(); + // this in theory should never happen... + self.swarm.behaviour_mut().kadem.bootstrap().map_err(|_e| NetworkError::NoKnownPeers)?; } r_input.send_async(SwarmResult::UpdateConnectedPeers(self.connected_peers.clone())).await.map_err(|_e| NetworkError::StreamClosed)?; } @@ -443,7 +464,7 @@ where } Ok::<(), NetworkError>(()) }.instrument(info_span!( "Libp2p Event Handler"))); - (s_input, r_output) + Ok((s_input, r_output)) } } @@ -479,4 +500,5 @@ pub enum NetworkError { PublishError { source: PublishError, }, + NoKnownPeers, } diff --git a/libp2p-networking/src/ui.rs b/libp2p-networking/src/ui.rs index ab6d6609cf..43e19193a1 100644 --- a/libp2p-networking/src/ui.rs +++ b/libp2p-networking/src/ui.rs @@ -14,7 +14,7 @@ use std::{ sync::Arc, time::Duration, }; -use tracing::{error, instrument}; +use tracing::instrument; use tui::{ backend::Backend, layout::{Constraint, Layout}, From aaa669f44444925dbc5990f86bfa11a1aaf52a53 Mon Sep 17 00:00:00 2001 From: Justin Restivo Date: Tue, 18 Jan 2022 20:07:05 -0500 Subject: [PATCH 022/107] Add known peers --- libp2p-networking/src/lib.rs | 13 ++++----- libp2p-networking/src/ui.rs | 54 +++++++++++++++++++++++++++++++----- 2 files changed, 53 insertions(+), 14 deletions(-) diff --git a/libp2p-networking/src/lib.rs b/libp2p-networking/src/lib.rs index 841c61fb91..5016c0310b 100644 --- a/libp2p-networking/src/lib.rs +++ b/libp2p-networking/src/lib.rs @@ -111,6 +111,7 @@ pub enum SwarmAction { /// out pub enum SwarmResult { UpdateConnectedPeers(HashSet), + UpdateKnownPeers(HashSet), GossipMsg(N), } @@ -273,12 +274,6 @@ where ) -> Result<(Sender>, Receiver>), NetworkError> { let (s_input, s_output) = unbounded::>(); let (r_input, r_output) = unbounded::>(); - r_input - .send_async(SwarmResult::UpdateConnectedPeers( - self.connected_peers.clone(), - )) - .await - .map_err(|_e| NetworkError::StreamClosed)?; let mut bootstrapped = false; spawn(async move { @@ -362,6 +357,7 @@ where for peer in peers { self.known_peers.insert(peer); } + r_input.send_async(SwarmResult::UpdateKnownPeers(self.known_peers.clone())).await.map_err(|_e| NetworkError::StreamClosed)?; }, _ => {} } @@ -371,6 +367,7 @@ where }, KademliaEvent::RoutingUpdated { peer, is_new_peer: _is_new_peer, addresses: _addresses, .. } => { self.known_peers.insert(peer); + r_input.send_async(SwarmResult::UpdateKnownPeers(self.known_peers.clone())).await.map_err(|_e| NetworkError::StreamClosed)?; }, _ => {} } @@ -383,6 +380,7 @@ where .add_address(&peer_id, addr.clone()); } self.known_peers.insert(peer_id); + r_input.send_async(SwarmResult::UpdateKnownPeers(self.known_peers.clone())).await.map_err(|_e| NetworkError::StreamClosed)?; }, _ => {} @@ -411,9 +409,10 @@ where } SwarmEvent::ConnectionClosed { peer_id, .. } => { self.connected_peers.remove(&peer_id); - self.known_peers.remove(&peer_id); + // self.known_peers.remove(&peer_id); r_input.send_async(SwarmResult::UpdateConnectedPeers(self.connected_peers.clone())).await.map_err(|_e| NetworkError::StreamClosed)?; + r_input.send_async(SwarmResult::UpdateKnownPeers(self.known_peers.clone())).await.map_err(|_e| NetworkError::StreamClosed)?; } } }, diff --git a/libp2p-networking/src/ui.rs b/libp2p-networking/src/ui.rs index 43e19193a1..87aab24ff3 100644 --- a/libp2p-networking/src/ui.rs +++ b/libp2p-networking/src/ui.rs @@ -17,7 +17,7 @@ use std::{ use tracing::instrument; use tui::{ backend::Backend, - layout::{Constraint, Layout}, + layout::{Constraint, Direction, Layout}, style::{Color, Modifier, Style}, widgets::{Block, Borders, Cell, Paragraph, Row, Table, TableState}, Frame, Terminal, @@ -70,7 +70,8 @@ pub struct TableApp { pub input: String, pub state: TableState, pub message_buffer: Arc>>, - pub peer_list: Arc>>, + pub connected_peer_list: Arc>>, + pub known_peer_list: Arc>>, } impl TableApp { @@ -86,7 +87,8 @@ impl TableApp { input: String::new(), state: TableState::default(), message_buffer, - peer_list: Arc::new(Mutex::new(HashSet::new())), + connected_peer_list: Arc::new(Mutex::new(HashSet::new())), + known_peer_list: Arc::new(Mutex::new(HashSet::new())), } } pub fn next(&mut self) { @@ -128,7 +130,10 @@ pub async fn run_app(terminal: &mut Terminal, mut app: TableApp) match res { SwarmResult::GossipMsg(s) => app.message_buffer.lock().push_back(s), SwarmResult::UpdateConnectedPeers(peer_set) => { - *app.peer_list.lock() = peer_set.into_iter().map(|p| p.to_string()).collect::>(); + *app.connected_peer_list.lock() = peer_set.into_iter().map(|p| p.to_string()).collect::>(); + } + SwarmResult::UpdateKnownPeers(peer_set) => { + *app.known_peer_list.lock() = peer_set.into_iter().map(|p| p.to_string()).collect::>(); } } } @@ -249,7 +254,13 @@ fn ui(f: &mut Frame<'_, B>, app: &mut TableApp) -> Result<()> { }); f.render_stateful_widget(message_table, rects[0], &mut app.state); - let peerid_handle = app.peer_list.lock(); + let peer_chunks = Layout::default() + .direction(Direction::Horizontal) + .constraints([Constraint::Percentage(50), Constraint::Percentage(50)].as_ref()) + .split(rects[1]); + + // TODO this is repetitive. Separate out into function. + let peerid_handle = app.connected_peer_list.lock(); let peerid_rows: Vec> = peerid_handle .iter() .map(|peer_id| { @@ -260,9 +271,38 @@ fn ui(f: &mut Frame<'_, B>, app: &mut TableApp) -> Result<()> { }) .collect::>, Report>>()?; let peerid_table = Table::new(peerid_rows.into_iter()) - .block(Block::default().borders(Borders::ALL).title("peer ids")) + .block( + Block::default() + .borders(Borders::ALL) + .title("connected peer ids"), + ) + .widths(&[Constraint::Percentage(100)]); + f.render_stateful_widget(peerid_table, peer_chunks[0], &mut app.state); + + let mut known_peerid_handle = app + .known_peer_list + .lock() + .iter() + .cloned() + .collect::>(); + known_peerid_handle.sort(); + let known_peerid_rows: Vec> = known_peerid_handle + .iter() + .map(|peer_id| { + let height = peer_id.chars().filter(|c| *c == '\n').count() + 1; + let cells = vec![Cell::from(peer_id.clone())]; + Ok(Row::new(cells) + .height(u16::try_from(height).context("integer overflow calculating row")?)) + }) + .collect::>, Report>>()?; + let known_peerid_table = Table::new(known_peerid_rows.into_iter()) + .block( + Block::default() + .borders(Borders::ALL) + .title("known peer ids"), + ) .widths(&[Constraint::Percentage(100)]); - f.render_stateful_widget(peerid_table, rects[1], &mut app.state); + f.render_stateful_widget(known_peerid_table, peer_chunks[1], &mut app.state); let input = Paragraph::new(app.input.as_ref()) .style(match app.input_mode { From 5ff4dbf785dee2d32baf7b2ffc67c3b4d2d6d2ef Mon Sep 17 00:00:00 2001 From: Justin Restivo Date: Thu, 20 Jan 2022 10:07:34 -0500 Subject: [PATCH 023/107] Direct messages over substream --- libp2p-networking/Cargo.lock | 1 + libp2p-networking/Cargo.toml | 1 + libp2p-networking/src/bin/clichat.rs | 17 +-- libp2p-networking/src/lib.rs | 165 +++++++++++++++++---------- libp2p-networking/src/message.rs | 134 ++++++++++++++++++++++ libp2p-networking/src/ui.rs | 77 +++++++------ 6 files changed, 289 insertions(+), 106 deletions(-) create mode 100644 libp2p-networking/src/message.rs diff --git a/libp2p-networking/Cargo.lock b/libp2p-networking/Cargo.lock index 86468e4fb8..e8a92e533b 100644 --- a/libp2p-networking/Cargo.lock +++ b/libp2p-networking/Cargo.lock @@ -1991,6 +1991,7 @@ name = "networking-demo" version = "0.0.0" dependencies = [ "async-std", + "async-trait", "bincode", "blake3", "color-eyre", diff --git a/libp2p-networking/Cargo.toml b/libp2p-networking/Cargo.toml index 5c5edaf17f..e535c3d75b 100644 --- a/libp2p-networking/Cargo.toml +++ b/libp2p-networking/Cargo.toml @@ -23,3 +23,4 @@ tracing-error = "0.2.0" tracing-subscriber = { version = "0.3.5", features = ["env-filter", "json"] } tui = { version = "0.16.0", features = ["crossterm"], default-features = false } rand = "0.8.4" +async-trait = "0.1.52" diff --git a/libp2p-networking/src/bin/clichat.rs b/libp2p-networking/src/bin/clichat.rs index 61b7ccfb14..2f4bbf5a65 100644 --- a/libp2p-networking/src/bin/clichat.rs +++ b/libp2p-networking/src/bin/clichat.rs @@ -1,8 +1,9 @@ use libp2p::Multiaddr; -use networking_demo::ui::{run_app, Message, TableApp}; +use networking_demo::message::Message; +use networking_demo::ui::{run_app, TableApp}; use std::sync::Arc; -use std::{collections::VecDeque, marker::PhantomData}; +use std::collections::VecDeque; use structopt::StructOpt; use color_eyre::eyre::{Result, WrapErr}; @@ -16,7 +17,7 @@ use parking_lot::Mutex; use tracing::instrument; use tui::{backend::CrosstermBackend, Terminal}; -use networking_demo::{gen_multiaddr, Network, NetworkDef, SwarmAction}; +use networking_demo::{gen_multiaddr, Network, SwarmAction}; /// command line arguments #[derive(StructOpt)] @@ -36,7 +37,7 @@ async fn main() -> Result<()> { color_eyre::install()?; networking_demo::tracing_setup::setup_tracing(); // -- Spin up the network connection - let mut networking: Network = Network::new(PhantomData) + let mut networking: Network = Network::new() .await .context("Failed to launch network")?; let port = CliOpt::from_args().port.unwrap_or(0u16); @@ -53,22 +54,22 @@ async fn main() -> Result<()> { buffer_handle.push_back(Message { sender: "Nathan".to_string(), content: "Hello".to_string(), - topic: "global".to_string(), + topic: "Generated".to_string(), }); buffer_handle.push_back(Message { sender: "Justin".to_string(), content: "hi!".to_string(), - topic: "global".to_string(), + topic: "Generated".to_string(), }); buffer_handle.push_back(Message { sender: "Joe".to_string(), content: "test".to_string(), - topic: "global".to_string(), + topic: "Generated".to_string(), }); buffer_handle.push_back(Message { sender: "John".to_string(), content: "test 2".to_string(), - topic: "global".to_string(), + topic: "Generated".to_string(), }); std::mem::drop(buffer_handle); // -- Setup the TUI diff --git a/libp2p-networking/src/lib.rs b/libp2p-networking/src/lib.rs index 5016c0310b..9e02e1d9e9 100644 --- a/libp2p-networking/src/lib.rs +++ b/libp2p-networking/src/lib.rs @@ -17,8 +17,9 @@ pub mod tracing_setup; use async_std::task::{sleep, spawn}; +use message::{DirectMessageCodec, DirectMessageRequest, DirectMessageResponse}; use rand::{seq::IteratorRandom, thread_rng}; -use std::{collections::HashSet, marker::PhantomData, time::Duration}; +use std::{collections::HashSet, marker::PhantomData, time::Duration, iter}; use flume::{unbounded, Receiver, Sender}; use futures::{select, FutureExt, StreamExt}; @@ -35,56 +36,91 @@ use libp2p::{ self, store::MemoryStore, GetClosestPeersOk, Kademlia, KademliaConfig, KademliaEvent, QueryResult, }, - swarm::{NetworkBehaviour, SwarmEvent}, + request_response::{ + RequestResponse, RequestResponseConfig, RequestResponseEvent, RequestResponseMessage, ProtocolSupport, + }, + swarm::{SwarmEvent}, Multiaddr, NetworkBehaviour, PeerId, Swarm, TransportError, }; use serde::{de::DeserializeOwned, Serialize}; use snafu::{ResultExt, Snafu}; use tracing::{debug, error, info, info_span, instrument, trace, warn, Instrument}; + +use crate::message::DirectMessageProtocol; + pub mod ui; +pub mod message; /// `event_process` is false because /// injecting events does not play well /// with asyncrony #[derive(NetworkBehaviour)] -#[behaviour(out_event = "NetworkEvent")] +#[behaviour(out_event = "NetworkEvent")] #[behaviour(event_process = false)] -pub struct NetworkDef { +pub struct NetworkDef< + T: std::fmt::Debug + Send + Sync + Clone + Serialize + DeserializeOwned + 'static, +> { + /// purpose: broadcasting messages to many peers /// NOTE gossipsub works ONLY for sharing messsages right now /// in the future it may be able to do peer discovery and routing - /// at which point we can scrap kadem + /// https://github.com/libp2p/rust-libp2p/issues/2398 pub gossipsub: Gossipsub, - /// used for passive peer discovery and peer routing + /// purpose: peer routing pub kadem: Kademlia, + /// purpose: peer discovery pub identify: Identify, + /// purpose: directly messaging peer + pub request_response: RequestResponse>, } #[derive(Debug)] -pub enum NetworkEvent { +pub enum NetworkEvent { Gossip(GossipsubEvent), Kadem(KademliaEvent), Ident(IdentifyEvent), + RequestResponse(RequestResponseEvent, DirectMessageResponse>), +} + +#[derive(Debug)] +pub enum SendDirectMsgEvent { + NotifyPeer(T), } -impl From for NetworkEvent { +impl + From for NetworkEvent +{ fn from(source: IdentifyEvent) -> Self { NetworkEvent::Ident(source) } } -impl From for NetworkEvent { +impl + From for NetworkEvent +{ fn from(source: KademliaEvent) -> Self { NetworkEvent::Kadem(source) } } -impl From for NetworkEvent { +impl + From for NetworkEvent +{ fn from(source: GossipsubEvent) -> Self { NetworkEvent::Gossip(source) } } -pub struct Network { +impl + From, DirectMessageResponse>> for NetworkEvent +{ + fn from(source: RequestResponseEvent, DirectMessageResponse>) -> Self { + NetworkEvent::RequestResponse(source) + } +} + +pub struct Network< + T: Send + Sync + Clone + 'static + std::fmt::Debug + Serialize + DeserializeOwned, +> { pub connected_peers: HashSet, // TODO replace this with a set of queryids pub connecting_peers: HashSet, @@ -92,10 +128,9 @@ pub struct Network { pub identity: Keypair, pub peer_id: PeerId, pub broadcast_topic: Topic, - pub swarm: Swarm, + pub swarm: Swarm>, pub max_num_peers: usize, pub min_num_peers: usize, - _phantom: PhantomData, } /// holds requests to the swarm @@ -105,6 +140,7 @@ pub enum SwarmAction { GetId(Sender), Subscribe(String), Unsubscribe(String), + DirectMessage(PeerId, N), } /// holds events of the swarm to be relayed to the cli event loop @@ -113,6 +149,7 @@ pub enum SwarmResult { UpdateConnectedPeers(HashSet), UpdateKnownPeers(HashSet), GossipMsg(N), + DirectMessage(N), } /// trait to get out the topic and contents of a message @@ -122,22 +159,27 @@ pub trait GossipMsg: Send { fn data(&self) -> Vec; } -impl std::fmt::Debug for Network { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!( - f, - "identity public key: {:?}, peer id: {:?}, topic: {:?}", - self.identity.public(), - self.peer_id, - self.broadcast_topic - ) - } +/// bind all interfaces on port `port` +/// TODO something more general +pub fn gen_multiaddr(port: u16) -> Multiaddr { + build_multiaddr!(Ip4([0, 0, 0, 0]), Tcp(port)) } -impl Network { +impl Network +where + M: std::fmt::Debug + + Send + + Sync + + Clone + + 'static + + Serialize + + DeserializeOwned + + GossipMsg + + From, +{ /// starts the swarm listening on `listen_addr` /// and optionally dials into peer `known_peer` - #[instrument] + #[instrument(skip(self))] pub fn start( &mut self, listen_addr: Multiaddr, @@ -155,24 +197,7 @@ impl Net } Ok(()) } -} -/// bind all interfaces on port `port` -/// TODO something more general -pub fn gen_multiaddr(port: u16) -> Multiaddr { - build_multiaddr!(Ip4([0, 0, 0, 0]), Tcp(port)) -} - -impl Network -where - N: DeserializeOwned - + Serialize - + From - + GossipMsg - + std::fmt::Debug - + Send - + 'static, -{ /// Creates a new `Network` with the given settings. /// /// Currently: @@ -181,7 +206,7 @@ where /// * Generates a connection to the "broadcast" topic /// * Creates a swarm to manage peers and events #[instrument] - pub async fn new(_: PhantomData) -> Result { + pub async fn new() -> Result { // Generate a random PeerId let identity = Keypair::generate_ed25519(); let peer_id = PeerId::from(identity.public()); @@ -194,7 +219,7 @@ where trace!("Launched network transport"); let broadcast_topic = Topic::new("broadcast"); // Generate the swarm - let swarm: Swarm = { + let swarm: Swarm> = { // Use the hash of the message's contents as the ID // Use blake3 for much paranoia at very high speeds let message_id_fn = |message: &GossipsubMessage| { @@ -235,10 +260,18 @@ where kconfig.set_caching(kad::KademliaCaching::Disabled); let kadem = Kademlia::with_config(peer_id, MemoryStore::new(peer_id), kconfig); + // request response for direct messages + let request_response = RequestResponse::new( + DirectMessageCodec(PhantomData::), + iter::once((DirectMessageProtocol(), ProtocolSupport::Full)), + RequestResponseConfig::default(), + ); + let network = NetworkDef { gossipsub, kadem, identify, + request_response, }; Swarm::new(transport, network, peer_id) @@ -254,11 +287,10 @@ where max_num_peers: 6, min_num_peers: 5, swarm, - _phantom: PhantomData, }) } - /// spawn a task to listen for requests on the returned channel + /// Spawn a task to listen for requests on the returned channel /// as well as any events produced by libp2p /// `mut_mut` is disabled b/c must consume `self` /// TODO why does clippy not like `panic` with select? @@ -268,12 +300,12 @@ where clippy::single_match, clippy::collapsible_match )] - #[instrument] + #[instrument(skip(self))] pub async fn spawn_listeners( mut self, - ) -> Result<(Sender>, Receiver>), NetworkError> { - let (s_input, s_output) = unbounded::>(); - let (r_input, r_output) = unbounded::>(); + ) -> Result<(Sender>, Receiver>), NetworkError> { + let (s_input, s_output) = unbounded::>(); + let (r_input, r_output) = unbounded::>(); let mut bootstrapped = false; spawn(async move { @@ -281,11 +313,11 @@ where select! { _ = sleep(Duration::from_secs(1)).fuse() => { // if we're bootstrapped, do nothing - // otherwise periodically get more peers + // otherwise periodically get more peers if needed if !bootstrapped { if self.connecting_peers.len() + self.connected_peers.len() <= self.min_num_peers { - // TODO there's *got* to be a better way to do this - let potential_peers : HashSet = self.known_peers.difference(&self.connecting_peers.union(&self.connected_peers).copied().collect()).copied().collect(); + let used_peers = self.connecting_peers.union(&self.connected_peers).copied().collect(); + let potential_peers : HashSet = self.known_peers.difference(&used_peers).copied().collect(); for a_peer in potential_peers { match self.swarm.dial(a_peer) { Ok(_) => { @@ -306,6 +338,7 @@ where } } event = self.swarm.select_next_some() => { + // TODO re enable this warn!("libp2p event {:?}", event); match event { SwarmEvent::Dialing(_) @@ -320,10 +353,17 @@ where }, SwarmEvent::Behaviour(b) => { match b { + NetworkEvent::RequestResponse(msg) => { + match msg { + RequestResponseEvent::Message { message: RequestResponseMessage::Request{ request: DirectMessageRequest(m), ..}, .. } => { + r_input.send_async(SwarmResult::DirectMessage(m)).await.map_err(|_e| NetworkError::StreamClosed)?; + }, + _ => {} + } + } NetworkEvent::Gossip(g) => { match g { GossipsubEvent::Message { message, .. } => { - // FIXME proper error handling r_input.send_async(SwarmResult::GossipMsg(message.into())).await.map_err(|_e| NetworkError::StreamClosed)?; }, _ => { @@ -426,8 +466,8 @@ where }, SwarmAction::GossipMsg(msg, chan) => { info!("broadcasting message {:?}", msg); - let topic = ::topic(&msg); - let contents = ::data(&msg); + let topic = ::topic(&msg); + let contents = ::data(&msg); let res = self.swarm .behaviour_mut().gossipsub.publish(topic.clone(), contents.clone()).map(|_| ()).context(PublishSnafu); chan.send_async(res).await.map_err(|_e| NetworkError::StreamClosed)?; @@ -452,6 +492,9 @@ where } } }, + SwarmAction::DirectMessage(pid, msg) => { + self.swarm.behaviour_mut().request_response.send_request(&pid, DirectMessageRequest(msg)); + } } }, Err(e) => { @@ -491,13 +534,15 @@ pub enum NetworkError { /// The underlying source of the error message: String, }, - // FIXME ideally include more information - // run into lifetime errors when making NetworkError generic over - // the type of message - // occurs if one of the channels to or from the swarm is closed + /// Error if one of the channels to or from the swarm is closed + /// FIXME ideally include more information + /// run into lifetime errors when making NetworkError generic over + /// the type of message. StreamClosed, + /// Error publishing a gossipsub message PublishError { source: PublishError, }, + /// Error when there are no known peers to bootstrap off NoKnownPeers, } diff --git a/libp2p-networking/src/message.rs b/libp2p-networking/src/message.rs new file mode 100644 index 0000000000..5427565222 --- /dev/null +++ b/libp2p-networking/src/message.rs @@ -0,0 +1,134 @@ +use std::{marker::PhantomData, io::{Error, ErrorKind}}; + +use async_std::io; +use async_trait::async_trait; +use bincode::{DefaultOptions, Options}; +use futures::{AsyncRead, AsyncWrite, AsyncWriteExt}; +use libp2p::{gossipsub::GossipsubMessage, core::{ProtocolName, upgrade::{write_length_prefixed, read_length_prefixed}}, request_response::RequestResponseCodec}; +use serde::{Serialize, Deserialize, de::DeserializeOwned}; + +use crate::GossipMsg; + +#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq)] +pub struct Message { + pub sender: String, + pub content: String, + pub topic: String, +} + +impl GossipMsg for Message { + fn topic(&self) -> libp2p::gossipsub::IdentTopic { + libp2p::gossipsub::IdentTopic::new(self.topic.clone()) + } + fn data(&self) -> Vec { + self.content.as_bytes().into() + } +} + +impl From for Message { + fn from(msg: GossipsubMessage) -> Self { + let content = String::from_utf8_lossy(&msg.data).to_string(); + let sender = msg + .source + .map_or_else(|| "UNKNOWN".to_string(), |p| p.to_string()); + Message { + sender, + content, + topic: msg.topic.into_string(), + } + } +} + +#[derive(Debug, Clone)] +pub struct DirectMessageProtocol(); +#[derive(Clone, Debug, Serialize, Deserialize)] +pub struct DirectMessageCodec(pub PhantomData); +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +pub struct DirectMessageRequest(pub T); +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct DirectMessageResponse(); + +impl ProtocolName for DirectMessageProtocol { + fn protocol_name(&self) -> &[u8] { + "/spectrum_send_msg/1".as_bytes() + } +} + + +// TODO are generics useful here? Could also just pass in vec of already serialized bytes +#[async_trait] +impl RequestResponseCodec + for DirectMessageCodec +{ + type Protocol = DirectMessageProtocol; + + type Request = DirectMessageRequest; + + type Response = DirectMessageResponse; + + async fn read_request( + &mut self, + _: &DirectMessageProtocol, + io: &mut T, + ) -> io::Result + where + T: AsyncRead + Unpin + Send, + { + // FIXME magic numbers... + let vec = read_length_prefixed(io, 1_000_000).await?; + + let bincode_options = DefaultOptions::new().with_limit(16_384); + + if vec.is_empty() { + return Err(io::ErrorKind::UnexpectedEof.into()); + } + + // NOTE error handling could be better... + // but the trait locks into io::Result : ( + Ok(DirectMessageRequest( + bincode_options.deserialize(&vec).map_err(|e| Error::new(ErrorKind::Other, e.to_string()))?, + )) + } + + async fn read_response( + &mut self, + _: &DirectMessageProtocol, + _: &mut T, + ) -> io::Result + where + T: AsyncRead + Unpin + Send, + { + // NOTE no replies + Ok(DirectMessageResponse()) + } + + async fn write_request( + &mut self, + _: &DirectMessageProtocol, + io: &mut T, + DirectMessageRequest(msg): DirectMessageRequest, + ) -> io::Result<()> + where + T: AsyncWrite + Unpin + Send, + { + let bincode_options = DefaultOptions::new().with_limit(16_384); + write_length_prefixed(io, bincode_options.serialize(&msg).map_err(|e| Error::new(io::ErrorKind::Other, e.to_string()))?).await?; + io.close().await?; + + Ok(()) + } + + async fn write_response( + &mut self, + _: &DirectMessageProtocol, + io: &mut T, + DirectMessageResponse(): DirectMessageResponse, + ) -> io::Result<()> + where + T: AsyncWrite + Unpin + Send, + { + io.close().await?; + Ok(()) + } +} + diff --git a/libp2p-networking/src/ui.rs b/libp2p-networking/src/ui.rs index 87aab24ff3..179af6d3f8 100644 --- a/libp2p-networking/src/ui.rs +++ b/libp2p-networking/src/ui.rs @@ -1,4 +1,9 @@ -use async_std::task::{sleep, spawn}; +use async_std::{ + task::{sleep, spawn}, +}; + + + use color_eyre::{ eyre::{Result, WrapErr}, Report, @@ -6,9 +11,11 @@ use color_eyre::{ use crossterm::event::{self, Event, KeyCode}; use flume::{Receiver, Sender}; use futures::{select, FutureExt, StreamExt}; -use libp2p::gossipsub::GossipsubMessage; +use libp2p::{ + PeerId, +}; use parking_lot::Mutex; -use serde::{Deserialize, Serialize}; + use std::{ collections::{HashSet, VecDeque}, sync::Arc, @@ -23,7 +30,7 @@ use tui::{ Frame, Terminal, }; -use crate::{GossipMsg, SwarmAction, SwarmResult}; +use crate::{SwarmAction, SwarmResult, message::Message}; #[derive(Debug, Copy, Clone)] pub enum InputMode { @@ -31,35 +38,7 @@ pub enum InputMode { Editing, } -#[derive(Debug, Clone, Serialize, Deserialize)] -pub struct Message { - pub sender: String, - pub content: String, - pub topic: String, -} -impl GossipMsg for Message { - fn topic(&self) -> libp2p::gossipsub::IdentTopic { - libp2p::gossipsub::IdentTopic::new(self.topic.clone()) - } - fn data(&self) -> Vec { - self.content.as_bytes().into() - } -} - -impl From for Message { - fn from(msg: GossipsubMessage) -> Self { - let content = String::from_utf8_lossy(&msg.data).to_string(); - let sender = msg - .source - .map_or_else(|| "UNKNOWN".to_string(), |p| p.to_string()); - Message { - sender, - content, - topic: msg.topic.into_string(), - } - } -} #[derive(Debug)] /// Struct for the TUI app @@ -70,7 +49,7 @@ pub struct TableApp { pub input: String, pub state: TableState, pub message_buffer: Arc>>, - pub connected_peer_list: Arc>>, + pub connected_peer_list: Arc>>, pub known_peer_list: Arc>>, } @@ -128,9 +107,9 @@ pub async fn run_app(terminal: &mut Terminal, mut app: TableApp) swarm_msg = app.recv_swarm.recv_async() => { if let Ok(res) = swarm_msg { match res { - SwarmResult::GossipMsg(s) => app.message_buffer.lock().push_back(s), + SwarmResult::DirectMessage(m) | SwarmResult::GossipMsg(m) => app.message_buffer.lock().push_back(m), SwarmResult::UpdateConnectedPeers(peer_set) => { - *app.connected_peer_list.lock() = peer_set.into_iter().map(|p| p.to_string()).collect::>(); + *app.connected_peer_list.lock() = peer_set.clone(); } SwarmResult::UpdateKnownPeers(peer_set) => { *app.known_peer_list.lock() = peer_set.into_iter().map(|p| p.to_string()).collect::>(); @@ -158,6 +137,29 @@ pub async fn run_app(terminal: &mut Terminal, mut app: TableApp) InputMode::Editing => { if let Some(Ok(Event::Key(key))) = user_event { match key.code { + // right arrow key sends a direct message + // over a substream to an arbitrary connected peer + // if there are no connected peers, noop. + KeyCode::Right => { + let mb_handle = app.message_buffer.clone(); + let send_swarm = app.send_swarm.clone(); + if let Some(selected_peer) = app.connected_peer_list.lock().iter().copied().next() { + spawn(async move { + let (s, r) = flume::bounded(1); + send_swarm.send_async(SwarmAction::GetId(s)).await.context("")?; + let msg = Message { + topic: "DM".to_string(), + content: app.input, + sender: r.recv_async().await?.to_string(), + }; + send_swarm.send_async(SwarmAction::DirectMessage(selected_peer, msg.clone())).await?; + mb_handle.lock().push_back(msg); + // if it's a duplicate message (error case), fail silently and do nothing + Result::<(), Report>::Ok(()) + }); + } + app.input = String::new(); + } // broadcast message to the swarm with the global topic KeyCode::Enter => { let mb_handle = app.message_buffer.clone(); @@ -169,7 +171,6 @@ pub async fn run_app(terminal: &mut Terminal, mut app: TableApp) let msg = Message { topic: "global".to_string(), content: app.input, - // FIXME this should NOT be needed. Get it from the swarm. sender: r.recv_async().await?.to_string(), }; let (s, r) = flume::bounded(1); @@ -264,8 +265,8 @@ fn ui(f: &mut Frame<'_, B>, app: &mut TableApp) -> Result<()> { let peerid_rows: Vec> = peerid_handle .iter() .map(|peer_id| { - let height = peer_id.chars().filter(|c| *c == '\n').count() + 1; - let cells = vec![Cell::from(peer_id.clone())]; + let height = peer_id.to_base58().chars().filter(|c| *c == '\n').count() + 1; + let cells = vec![Cell::from(peer_id.to_base58())]; Ok(Row::new(cells) .height(u16::try_from(height).context("integer overflow calculating row")?)) }) From 936e968180a4106c6c3c424d8ee3d7e4ce311e2a Mon Sep 17 00:00:00 2001 From: Justin Restivo Date: Thu, 20 Jan 2022 12:35:22 -0500 Subject: [PATCH 024/107] Reuse old port now persists --- libp2p-networking/src/lib.rs | 4 ++-- libp2p-networking/src/message.rs | 2 ++ 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/libp2p-networking/src/lib.rs b/libp2p-networking/src/lib.rs index 9e02e1d9e9..95116be890 100644 --- a/libp2p-networking/src/lib.rs +++ b/libp2p-networking/src/lib.rs @@ -423,7 +423,6 @@ where r_input.send_async(SwarmResult::UpdateKnownPeers(self.known_peers.clone())).await.map_err(|_e| NetworkError::StreamClosed)?; }, _ => {} - } }, @@ -449,7 +448,8 @@ where } SwarmEvent::ConnectionClosed { peer_id, .. } => { self.connected_peers.remove(&peer_id); - // self.known_peers.remove(&peer_id); + // FIXME remove stale address, not *all* addresses + self.swarm.behaviour_mut().kadem.remove_peer(&peer_id); r_input.send_async(SwarmResult::UpdateConnectedPeers(self.connected_peers.clone())).await.map_err(|_e| NetworkError::StreamClosed)?; r_input.send_async(SwarmResult::UpdateKnownPeers(self.known_peers.clone())).await.map_err(|_e| NetworkError::StreamClosed)?; diff --git a/libp2p-networking/src/message.rs b/libp2p-networking/src/message.rs index 5427565222..be4bd23f9b 100644 --- a/libp2p-networking/src/message.rs +++ b/libp2p-networking/src/message.rs @@ -75,6 +75,8 @@ impl RequestRes T: AsyncRead + Unpin + Send, { // FIXME magic numbers... + // it looks like the easiest thing to do + // is to set an upper limit threshold and use that let vec = read_length_prefixed(io, 1_000_000).await?; let bincode_options = DefaultOptions::new().with_limit(16_384); From db45efea26403f68322cfddafd77abd8f5d4f819 Mon Sep 17 00:00:00 2001 From: Justin Restivo Date: Thu, 20 Jan 2022 14:36:03 -0500 Subject: [PATCH 025/107] State is represented as peerids --- libp2p-networking/src/lib.rs | 1 - libp2p-networking/src/ui.rs | 26 +++++++++++--------------- 2 files changed, 11 insertions(+), 16 deletions(-) diff --git a/libp2p-networking/src/lib.rs b/libp2p-networking/src/lib.rs index 95116be890..d49782f503 100644 --- a/libp2p-networking/src/lib.rs +++ b/libp2p-networking/src/lib.rs @@ -441,7 +441,6 @@ where self.connecting_peers.remove(&peer_id); // now we have at least one peer so we can bootstrap if !bootstrapped { - // this in theory should never happen... self.swarm.behaviour_mut().kadem.bootstrap().map_err(|_e| NetworkError::NoKnownPeers)?; } r_input.send_async(SwarmResult::UpdateConnectedPeers(self.connected_peers.clone())).await.map_err(|_e| NetworkError::StreamClosed)?; diff --git a/libp2p-networking/src/ui.rs b/libp2p-networking/src/ui.rs index 179af6d3f8..92679d890e 100644 --- a/libp2p-networking/src/ui.rs +++ b/libp2p-networking/src/ui.rs @@ -1,6 +1,4 @@ -use async_std::{ - task::{sleep, spawn}, -}; +use async_std::task::{sleep, spawn}; @@ -11,9 +9,7 @@ use color_eyre::{ use crossterm::event::{self, Event, KeyCode}; use flume::{Receiver, Sender}; use futures::{select, FutureExt, StreamExt}; -use libp2p::{ - PeerId, -}; +use libp2p::PeerId; use parking_lot::Mutex; use std::{ @@ -38,8 +34,6 @@ pub enum InputMode { Editing, } - - #[derive(Debug)] /// Struct for the TUI app pub struct TableApp { @@ -50,7 +44,7 @@ pub struct TableApp { pub state: TableState, pub message_buffer: Arc>>, pub connected_peer_list: Arc>>, - pub known_peer_list: Arc>>, + pub known_peer_list: Arc>>, } impl TableApp { @@ -103,7 +97,7 @@ pub async fn run_app(terminal: &mut Terminal, mut app: TableApp) select!( // force a periodic refresh _ = sleep(Duration::from_nanos(1)).fuse() => {} - // swarm may have instructions + // swarm generated events swarm_msg = app.recv_swarm.recv_async() => { if let Ok(res) = swarm_msg { match res { @@ -112,7 +106,7 @@ pub async fn run_app(terminal: &mut Terminal, mut app: TableApp) *app.connected_peer_list.lock() = peer_set.clone(); } SwarmResult::UpdateKnownPeers(peer_set) => { - *app.known_peer_list.lock() = peer_set.into_iter().map(|p| p.to_string()).collect::>(); + *app.known_peer_list.lock() = peer_set.clone(); } } } @@ -284,14 +278,14 @@ fn ui(f: &mut Frame<'_, B>, app: &mut TableApp) -> Result<()> { .known_peer_list .lock() .iter() - .cloned() - .collect::>(); + .copied() + .collect::>(); known_peerid_handle.sort(); let known_peerid_rows: Vec> = known_peerid_handle .iter() .map(|peer_id| { - let height = peer_id.chars().filter(|c| *c == '\n').count() + 1; - let cells = vec![Cell::from(peer_id.clone())]; + let height = peer_id.to_base58().chars().filter(|c| *c == '\n').count() + 1; + let cells = vec![Cell::from(peer_id.to_base58())]; Ok(Row::new(cells) .height(u16::try_from(height).context("integer overflow calculating row")?)) }) @@ -315,3 +309,5 @@ fn ui(f: &mut Frame<'_, B>, app: &mut TableApp) -> Result<()> { Ok(()) } + + From 9b855d01a83356743c4038d6bf9b876ac30503e8 Mon Sep 17 00:00:00 2001 From: Justin Restivo Date: Fri, 21 Jan 2022 13:57:21 -0500 Subject: [PATCH 026/107] Randomly connect to needed peers --- libp2p-networking/src/lib.rs | 14 ++++++++++---- libp2p-networking/src/ui.rs | 4 ++-- 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/libp2p-networking/src/lib.rs b/libp2p-networking/src/lib.rs index d49782f503..ee783d6bf5 100644 --- a/libp2p-networking/src/lib.rs +++ b/libp2p-networking/src/lib.rs @@ -311,6 +311,12 @@ where spawn(async move { loop { select! { + _ = sleep(Duration::from_secs(30)).fuse() => { + if !bootstrapped { + let random_peer = PeerId::random(); + self.swarm.behaviour_mut().kadem.get_closest_peers(random_peer); + } + }, _ = sleep(Duration::from_secs(1)).fuse() => { // if we're bootstrapped, do nothing // otherwise periodically get more peers if needed @@ -318,7 +324,9 @@ where if self.connecting_peers.len() + self.connected_peers.len() <= self.min_num_peers { let used_peers = self.connecting_peers.union(&self.connected_peers).copied().collect(); let potential_peers : HashSet = self.known_peers.difference(&used_peers).copied().collect(); - for a_peer in potential_peers { + let num_to_connect = self.min_num_peers + 1 - (self.connected_peers.len() + self.connecting_peers.len()); + let chosen_peers = potential_peers.iter().copied().choose_multiple(&mut thread_rng(), num_to_connect); + for a_peer in chosen_peers { match self.swarm.dial(a_peer) { Ok(_) => { self.connecting_peers.insert(a_peer); @@ -366,9 +374,7 @@ where GossipsubEvent::Message { message, .. } => { r_input.send_async(SwarmResult::GossipMsg(message.into())).await.map_err(|_e| NetworkError::StreamClosed)?; }, - _ => { - info!(?g); - } + _ => {} } }, NetworkEvent::Kadem(event) => { diff --git a/libp2p-networking/src/ui.rs b/libp2p-networking/src/ui.rs index 92679d890e..08146eff69 100644 --- a/libp2p-networking/src/ui.rs +++ b/libp2p-networking/src/ui.rs @@ -269,7 +269,7 @@ fn ui(f: &mut Frame<'_, B>, app: &mut TableApp) -> Result<()> { .block( Block::default() .borders(Borders::ALL) - .title("connected peer ids"), + .title(format!("connected peer ids ({})", peerid_handle.len())), ) .widths(&[Constraint::Percentage(100)]); f.render_stateful_widget(peerid_table, peer_chunks[0], &mut app.state); @@ -294,7 +294,7 @@ fn ui(f: &mut Frame<'_, B>, app: &mut TableApp) -> Result<()> { .block( Block::default() .borders(Borders::ALL) - .title("known peer ids"), + .title(format!("known peer ids ({:?})", known_peerid_handle.len())), ) .widths(&[Constraint::Percentage(100)]); f.render_stateful_widget(known_peerid_table, peer_chunks[1], &mut app.state); From 1a4b34a8c1c1931e5c5055e920fe37c5d85bd64f Mon Sep 17 00:00:00 2001 From: Justin Restivo Date: Fri, 21 Jan 2022 14:00:27 -0500 Subject: [PATCH 027/107] cargo fmt --- libp2p-networking/src/bin/clichat.rs | 7 +++---- libp2p-networking/src/lib.rs | 13 ++++++------ libp2p-networking/src/message.rs | 30 +++++++++++++++++++++------- libp2p-networking/src/ui.rs | 6 +----- 4 files changed, 33 insertions(+), 23 deletions(-) diff --git a/libp2p-networking/src/bin/clichat.rs b/libp2p-networking/src/bin/clichat.rs index 2f4bbf5a65..2b6b67056b 100644 --- a/libp2p-networking/src/bin/clichat.rs +++ b/libp2p-networking/src/bin/clichat.rs @@ -2,8 +2,8 @@ use libp2p::Multiaddr; use networking_demo::message::Message; use networking_demo::ui::{run_app, TableApp}; -use std::sync::Arc; use std::collections::VecDeque; +use std::sync::Arc; use structopt::StructOpt; use color_eyre::eyre::{Result, WrapErr}; @@ -37,9 +37,8 @@ async fn main() -> Result<()> { color_eyre::install()?; networking_demo::tracing_setup::setup_tracing(); // -- Spin up the network connection - let mut networking: Network = Network::new() - .await - .context("Failed to launch network")?; + let mut networking: Network = + Network::new().await.context("Failed to launch network")?; let port = CliOpt::from_args().port.unwrap_or(0u16); let known_peer = CliOpt::from_args().first_dial; let listen_addr = gen_multiaddr(port); diff --git a/libp2p-networking/src/lib.rs b/libp2p-networking/src/lib.rs index ee783d6bf5..ed2d4262bc 100644 --- a/libp2p-networking/src/lib.rs +++ b/libp2p-networking/src/lib.rs @@ -19,7 +19,7 @@ pub mod tracing_setup; use async_std::task::{sleep, spawn}; use message::{DirectMessageCodec, DirectMessageRequest, DirectMessageResponse}; use rand::{seq::IteratorRandom, thread_rng}; -use std::{collections::HashSet, marker::PhantomData, time::Duration, iter}; +use std::{collections::HashSet, iter, marker::PhantomData, time::Duration}; use flume::{unbounded, Receiver, Sender}; use futures::{select, FutureExt, StreamExt}; @@ -37,9 +37,10 @@ use libp2p::{ QueryResult, }, request_response::{ - RequestResponse, RequestResponseConfig, RequestResponseEvent, RequestResponseMessage, ProtocolSupport, + ProtocolSupport, RequestResponse, RequestResponseConfig, RequestResponseEvent, + RequestResponseMessage, }, - swarm::{SwarmEvent}, + swarm::SwarmEvent, Multiaddr, NetworkBehaviour, PeerId, Swarm, TransportError, }; use serde::{de::DeserializeOwned, Serialize}; @@ -48,8 +49,8 @@ use tracing::{debug, error, info, info_span, instrument, trace, warn, Instrument use crate::message::DirectMessageProtocol; -pub mod ui; pub mod message; +pub mod ui; /// `event_process` is false because /// injecting events does not play well @@ -545,9 +546,7 @@ pub enum NetworkError { /// the type of message. StreamClosed, /// Error publishing a gossipsub message - PublishError { - source: PublishError, - }, + PublishError { source: PublishError }, /// Error when there are no known peers to bootstrap off NoKnownPeers, } diff --git a/libp2p-networking/src/message.rs b/libp2p-networking/src/message.rs index be4bd23f9b..be4b95870d 100644 --- a/libp2p-networking/src/message.rs +++ b/libp2p-networking/src/message.rs @@ -1,11 +1,21 @@ -use std::{marker::PhantomData, io::{Error, ErrorKind}}; +use std::{ + io::{Error, ErrorKind}, + marker::PhantomData, +}; use async_std::io; use async_trait::async_trait; use bincode::{DefaultOptions, Options}; use futures::{AsyncRead, AsyncWrite, AsyncWriteExt}; -use libp2p::{gossipsub::GossipsubMessage, core::{ProtocolName, upgrade::{write_length_prefixed, read_length_prefixed}}, request_response::RequestResponseCodec}; -use serde::{Serialize, Deserialize, de::DeserializeOwned}; +use libp2p::{ + core::{ + upgrade::{read_length_prefixed, write_length_prefixed}, + ProtocolName, + }, + gossipsub::GossipsubMessage, + request_response::RequestResponseCodec, +}; +use serde::{de::DeserializeOwned, Deserialize, Serialize}; use crate::GossipMsg; @@ -54,7 +64,6 @@ impl ProtocolName for DirectMessageProtocol { } } - // TODO are generics useful here? Could also just pass in vec of already serialized bytes #[async_trait] impl RequestResponseCodec @@ -88,7 +97,9 @@ impl RequestRes // NOTE error handling could be better... // but the trait locks into io::Result : ( Ok(DirectMessageRequest( - bincode_options.deserialize(&vec).map_err(|e| Error::new(ErrorKind::Other, e.to_string()))?, + bincode_options + .deserialize(&vec) + .map_err(|e| Error::new(ErrorKind::Other, e.to_string()))?, )) } @@ -114,7 +125,13 @@ impl RequestRes T: AsyncWrite + Unpin + Send, { let bincode_options = DefaultOptions::new().with_limit(16_384); - write_length_prefixed(io, bincode_options.serialize(&msg).map_err(|e| Error::new(io::ErrorKind::Other, e.to_string()))?).await?; + write_length_prefixed( + io, + bincode_options + .serialize(&msg) + .map_err(|e| Error::new(io::ErrorKind::Other, e.to_string()))?, + ) + .await?; io.close().await?; Ok(()) @@ -133,4 +150,3 @@ impl RequestRes Ok(()) } } - diff --git a/libp2p-networking/src/ui.rs b/libp2p-networking/src/ui.rs index 08146eff69..a23717b862 100644 --- a/libp2p-networking/src/ui.rs +++ b/libp2p-networking/src/ui.rs @@ -1,7 +1,5 @@ use async_std::task::{sleep, spawn}; - - use color_eyre::{ eyre::{Result, WrapErr}, Report, @@ -26,7 +24,7 @@ use tui::{ Frame, Terminal, }; -use crate::{SwarmAction, SwarmResult, message::Message}; +use crate::{message::Message, SwarmAction, SwarmResult}; #[derive(Debug, Copy, Clone)] pub enum InputMode { @@ -309,5 +307,3 @@ fn ui(f: &mut Frame<'_, B>, app: &mut TableApp) -> Result<()> { Ok(()) } - - From 2638c9408523b00d5afa46d86192019584ee5919 Mon Sep 17 00:00:00 2001 From: Nathan McCarty Date: Mon, 24 Jan 2022 12:08:53 -0500 Subject: [PATCH 028/107] style: Slightly clean up match statement --- libp2p-networking/src/lib.rs | 148 ++++++++++++++++++----------------- 1 file changed, 75 insertions(+), 73 deletions(-) diff --git a/libp2p-networking/src/lib.rs b/libp2p-networking/src/lib.rs index ed2d4262bc..ea2ae741dc 100644 --- a/libp2p-networking/src/lib.rs +++ b/libp2p-networking/src/lib.rs @@ -311,6 +311,8 @@ where let mut bootstrapped = false; spawn(async move { loop { + // NOTE(nm): rustformat doesn't really work inside of macros, I would like to + // refactor these all out to local methods for formatability select! { _ = sleep(Duration::from_secs(30)).fuse() => { if !bootstrapped { @@ -347,95 +349,95 @@ where } } event = self.swarm.select_next_some() => { + // Make the match cleaner + #[allow(clippy::enum_glob_use)] + use SwarmEvent::*; + #[allow(clippy::enum_glob_use)] + use NetworkEvent::*; // TODO re enable this warn!("libp2p event {:?}", event); match event { - SwarmEvent::Dialing(_) - | SwarmEvent::NewListenAddr {..} - | SwarmEvent::ExpiredListenAddr {..} - | SwarmEvent::ListenerClosed {..} - | SwarmEvent::IncomingConnection {..} - | SwarmEvent::IncomingConnectionError {..} - | SwarmEvent::OutgoingConnectionError {..} - | SwarmEvent::BannedPeer {..} - | SwarmEvent::ListenerError {..} => { + Dialing(_) + | NewListenAddr {..} + | ExpiredListenAddr {..} + | ListenerClosed {..} + | IncomingConnection {..} + | IncomingConnectionError {..} + | OutgoingConnectionError {..} + | BannedPeer {..} + | ListenerError {..} => { }, - SwarmEvent::Behaviour(b) => { - match b { - NetworkEvent::RequestResponse(msg) => { - match msg { - RequestResponseEvent::Message { message: RequestResponseMessage::Request{ request: DirectMessageRequest(m), ..}, .. } => { - r_input.send_async(SwarmResult::DirectMessage(m)).await.map_err(|_e| NetworkError::StreamClosed)?; - }, - _ => {} - } - } - NetworkEvent::Gossip(g) => { - match g { - GossipsubEvent::Message { message, .. } => { - r_input.send_async(SwarmResult::GossipMsg(message.into())).await.map_err(|_e| NetworkError::StreamClosed)?; - }, - _ => {} - } + Behaviour(RequestResponse(msg)) => { + match msg { + RequestResponseEvent::Message { message: RequestResponseMessage::Request{ request: DirectMessageRequest(m), ..}, .. } => { + r_input.send_async(SwarmResult::DirectMessage(m)).await.map_err(|_e| NetworkError::StreamClosed)?; }, - NetworkEvent::Kadem(event) => { - match event { - KademliaEvent::OutboundQueryCompleted { result, ..} => { - match result { - // FIXME rebootstrap or fail in the failed - // bootstrap case - QueryResult::Bootstrap(r) => { - match r { - Ok(_bootstrap) => { - // we're bootstrapped - // don't bootstrap again - bootstrapped = false; - }, - Err(_) => { - // try again - bootstrapped = true; - } - - } + _ => {} + } + }, + Behaviour(Gossip(g)) => { + match g { + GossipsubEvent::Message { message, .. } => { + r_input.send_async(SwarmResult::GossipMsg(message.into())).await.map_err(|_e| NetworkError::StreamClosed)?; + }, + _ => {} + } + }, + Behaviour(Kadem(event)) => { + match event { + KademliaEvent::OutboundQueryCompleted { result, ..} => { + match result { + // FIXME rebootstrap or fail in the failed + // bootstrap case + QueryResult::Bootstrap(r) => { + match r { + Ok(_bootstrap) => { + // we're bootstrapped + // don't bootstrap again + bootstrapped = false; }, - QueryResult::GetClosestPeers(result) => { - match result { - Ok(GetClosestPeersOk { key: _key, peers }) => { - for peer in peers { - self.known_peers.insert(peer); - } - r_input.send_async(SwarmResult::UpdateKnownPeers(self.known_peers.clone())).await.map_err(|_e| NetworkError::StreamClosed)?; - }, - _ => {} + Err(_) => { + // try again + bootstrapped = true; + } + + } + }, + QueryResult::GetClosestPeers(result) => { + match result { + Ok(GetClosestPeersOk { key: _key, peers }) => { + for peer in peers { + self.known_peers.insert(peer); } + r_input.send_async(SwarmResult::UpdateKnownPeers(self.known_peers.clone())).await.map_err(|_e| NetworkError::StreamClosed)?; }, _ => {} } }, - KademliaEvent::RoutingUpdated { peer, is_new_peer: _is_new_peer, addresses: _addresses, .. } => { - self.known_peers.insert(peer); - r_input.send_async(SwarmResult::UpdateKnownPeers(self.known_peers.clone())).await.map_err(|_e| NetworkError::StreamClosed)?; - }, _ => {} } }, - NetworkEvent::Ident(i) => { - match i { - IdentifyEvent::Received { peer_id, info, .. } => { - for addr in info.listen_addrs { - self.swarm.behaviour_mut().kadem - .add_address(&peer_id, addr.clone()); - } - self.known_peers.insert(peer_id); - r_input.send_async(SwarmResult::UpdateKnownPeers(self.known_peers.clone())).await.map_err(|_e| NetworkError::StreamClosed)?; - }, - _ => {} + KademliaEvent::RoutingUpdated { peer, is_new_peer: _is_new_peer, addresses: _addresses, .. } => { + self.known_peers.insert(peer); + r_input.send_async(SwarmResult::UpdateKnownPeers(self.known_peers.clone())).await.map_err(|_e| NetworkError::StreamClosed)?; + }, + _ => {} + } + }, + Behaviour(Ident(i)) => { + match i { + IdentifyEvent::Received { peer_id, info, .. } => { + for addr in info.listen_addrs { + self.swarm.behaviour_mut().kadem + .add_address(&peer_id, addr.clone()); } + self.known_peers.insert(peer_id); + r_input.send_async(SwarmResult::UpdateKnownPeers(self.known_peers.clone())).await.map_err(|_e| NetworkError::StreamClosed)?; }, - + _ => {} } }, - SwarmEvent::ConnectionEstablished { peer_id, endpoint, .. } => { + ConnectionEstablished { peer_id, endpoint, .. } => { match endpoint { ConnectedPoint::Dialer { address } => { self.swarm.behaviour_mut().kadem.add_address(&peer_id, address); @@ -452,7 +454,7 @@ where } r_input.send_async(SwarmResult::UpdateConnectedPeers(self.connected_peers.clone())).await.map_err(|_e| NetworkError::StreamClosed)?; } - SwarmEvent::ConnectionClosed { peer_id, .. } => { + ConnectionClosed { peer_id, .. } => { self.connected_peers.remove(&peer_id); // FIXME remove stale address, not *all* addresses self.swarm.behaviour_mut().kadem.remove_peer(&peer_id); @@ -510,7 +512,7 @@ where } } } - Ok::<(), NetworkError>(()) + Ok::<(), NetworkError>(()) }.instrument(info_span!( "Libp2p Event Handler"))); Ok((s_input, r_output)) } From 13271a8372a032bf6c3880f8db5bf3668ac6955c Mon Sep 17 00:00:00 2001 From: Nathan McCarty Date: Mon, 24 Jan 2022 15:03:19 -0500 Subject: [PATCH 029/107] style: fold out if-let --- libp2p-networking/src/ui.rs | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/libp2p-networking/src/ui.rs b/libp2p-networking/src/ui.rs index a23717b862..a0b8589e48 100644 --- a/libp2p-networking/src/ui.rs +++ b/libp2p-networking/src/ui.rs @@ -111,9 +111,9 @@ pub async fn run_app(terminal: &mut Terminal, mut app: TableApp) }, // user driven events user_event = events.next().fuse() => { + if let Some(Ok(Event::Key(key))) = user_event { match app.input_mode { InputMode::Normal => { - if let Some(Ok(Event::Key(key))) = user_event { match key.code { KeyCode::Char('q') => { app.send_swarm.send_async(SwarmAction::Shutdown).await?; @@ -124,10 +124,9 @@ pub async fn run_app(terminal: &mut Terminal, mut app: TableApp) KeyCode::Tab => app.input_mode = InputMode::Editing, _ => {} } - } + } InputMode::Editing => { - if let Some(Ok(Event::Key(key))) = user_event { match key.code { // right arrow key sends a direct message // over a substream to an arbitrary connected peer @@ -186,11 +185,10 @@ pub async fn run_app(terminal: &mut Terminal, mut app: TableApp) } _ => {} } - } + } - } + }} } - ); } } From db13f10241b64946b1d174ae93ec4f6a9af1bad8 Mon Sep 17 00:00:00 2001 From: Nathan McCarty Date: Mon, 24 Jan 2022 15:12:39 -0500 Subject: [PATCH 030/107] style: Manual formatting --- libp2p-networking/src/lib.rs | 125 ++++++++++++++++++++++++----------- 1 file changed, 87 insertions(+), 38 deletions(-) diff --git a/libp2p-networking/src/lib.rs b/libp2p-networking/src/lib.rs index ea2ae741dc..bc4b27ea5f 100644 --- a/libp2p-networking/src/lib.rs +++ b/libp2p-networking/src/lib.rs @@ -324,28 +324,58 @@ where // if we're bootstrapped, do nothing // otherwise periodically get more peers if needed if !bootstrapped { - if self.connecting_peers.len() + self.connected_peers.len() <= self.min_num_peers { - let used_peers = self.connecting_peers.union(&self.connected_peers).copied().collect(); - let potential_peers : HashSet = self.known_peers.difference(&used_peers).copied().collect(); - let num_to_connect = self.min_num_peers + 1 - (self.connected_peers.len() + self.connecting_peers.len()); - let chosen_peers = potential_peers.iter().copied().choose_multiple(&mut thread_rng(), num_to_connect); - for a_peer in chosen_peers { - match self.swarm.dial(a_peer) { - Ok(_) => { - self.connecting_peers.insert(a_peer); + if self.connecting_peers.len() + + self.connected_peers.len() + <= self.min_num_peers { + // Calcuate the currently connected peers + let used_peers = self + .connecting_peers + .union(&self.connected_peers) + .copied() + .collect(); + // Calcuate the list of "new" peers, once not currently used for + // a connection + let potential_peers: HashSet = + self + .known_peers + .difference(&used_peers) + .copied() + .collect(); + // Number of peers we want to try connecting to + let num_to_connect = + self.min_num_peers + 1 + - (self.connected_peers.len() + self.connecting_peers.len()); + // Random(?) subset of the availible peers to try connecting to + let chosen_peers = + potential_peers + .iter() + .copied() + .choose_multiple(&mut thread_rng(), num_to_connect); + // Try dialing each random (?) peer + for a_peer in chosen_peers { + match self.swarm.dial(a_peer) { + Ok(_) => { + self.connecting_peers.insert(a_peer); + } + Err(e) => error!("Dial {:?} failed: {:?}", a_peer, e), + }; + } + } else if self.connected_peers.len() > self.max_num_peers { + // If we are connected to too many peers, try disconnecting from + // a random (?) subset + let peers_to_rm = self + .connected_peers + .iter() + .copied() + .choose_multiple(&mut thread_rng(), + self.connected_peers.len() + - self.max_num_peers); + for a_peer in peers_to_rm { + // FIXME the error is () ? + let _ = self.swarm.disconnect_peer_id(a_peer); + } - } - Err(e) => error!("Dial {:?} failed: {:?}", a_peer, e), - }; - } - } else if self.connected_peers.len() > self.max_num_peers { - let peers_to_rm = self.connected_peers.iter().copied().choose_multiple(&mut thread_rng(), self.connected_peers.len() - self.max_num_peers); - for a_peer in peers_to_rm { - // FIXME the error is () ? - let _ = self.swarm.disconnect_peer_id(a_peer); } - - } } } event = self.swarm.select_next_some() => { @@ -467,8 +497,10 @@ where msg = s_output.recv_async() => { match msg { Ok(msg) => { + #[allow(clippy::enum_glob_use)] + use SwarmAction::{Shutdown, GetId, Subscribe, Unsubscribe, DirectMessage}; match msg { - SwarmAction::Shutdown => { + Shutdown => { warn!("Libp2p listener shutting down"); break }, @@ -476,32 +508,49 @@ where info!("broadcasting message {:?}", msg); let topic = ::topic(&msg); let contents = ::data(&msg); - let res = self.swarm - .behaviour_mut().gossipsub.publish(topic.clone(), contents.clone()).map(|_| ()).context(PublishSnafu); - chan.send_async(res).await.map_err(|_e| NetworkError::StreamClosed)?; + let res = self + .swarm + .behaviour_mut() + .gossipsub + .publish(topic.clone(), contents.clone()) + .map(|_| ()).context(PublishSnafu); + chan + .send_async(res) + .await + .map_err(|_e| NetworkError::StreamClosed)?; }, - SwarmAction::GetId(reply_chan) => { + GetId(reply_chan) => { // FIXME proper error handling - reply_chan.send_async(self.peer_id).await.map_err(|_e| NetworkError::StreamClosed)?; + reply_chan + .send_async(self.peer_id) + .await + .map_err(|_e| NetworkError::StreamClosed)?; }, - SwarmAction::Subscribe(t) => { - match self.swarm.behaviour_mut().gossipsub.subscribe(&Topic::new(t.clone())) { - Ok(_) => (), - Err(_) => { + Subscribe(t) => { + if self + .swarm + .behaviour_mut() + .gossipsub + .subscribe(&Topic::new(t.clone())) + .is_err() { error!("error subscribing to topic {}", t); } - } } - SwarmAction::Unsubscribe(t) => { - match self.swarm.behaviour_mut().gossipsub.unsubscribe(&Topic::new(t.clone())) { - Ok(_) => (), - Err(_) => { + Unsubscribe(t) => { + if self + .swarm + .behaviour_mut() + .gossipsub.unsubscribe(&Topic::new(t.clone())) + .is_err() { error!("error unsubscribing to topic {}", t); } - } }, - SwarmAction::DirectMessage(pid, msg) => { - self.swarm.behaviour_mut().request_response.send_request(&pid, DirectMessageRequest(msg)); + DirectMessage(pid, msg) => { + self + .swarm + .behaviour_mut() + .request_response + .send_request(&pid, DirectMessageRequest(msg)); } } }, From a717c4150b214757b4ffa087d6d531c1b55621c6 Mon Sep 17 00:00:00 2001 From: Justin Restivo Date: Tue, 25 Jan 2022 11:39:38 -0500 Subject: [PATCH 031/107] separate out to helper functions --- libp2p-networking/src/lib.rs | 564 ++++++++++++++++++++--------------- 1 file changed, 322 insertions(+), 242 deletions(-) diff --git a/libp2p-networking/src/lib.rs b/libp2p-networking/src/lib.rs index bc4b27ea5f..4c1d5f6550 100644 --- a/libp2p-networking/src/lib.rs +++ b/libp2p-networking/src/lib.rs @@ -19,16 +19,17 @@ pub mod tracing_setup; use async_std::task::{sleep, spawn}; use message::{DirectMessageCodec, DirectMessageRequest, DirectMessageResponse}; use rand::{seq::IteratorRandom, thread_rng}; -use std::{collections::HashSet, iter, marker::PhantomData, time::Duration}; +use std::{collections::HashSet, io::Error, iter, marker::PhantomData, time::Duration}; use flume::{unbounded, Receiver, Sender}; use futures::{select, FutureExt, StreamExt}; use libp2p::{ build_multiaddr, - core::{muxing::StreamMuxerBox, transport::Boxed, ConnectedPoint}, + core::{either::EitherError, muxing::StreamMuxerBox, transport::Boxed, ConnectedPoint}, gossipsub::{ - error::PublishError, Gossipsub, GossipsubConfigBuilder, GossipsubEvent, GossipsubMessage, - IdentTopic as Topic, MessageAuthenticity, MessageId, ValidationMode, + error::{GossipsubHandlerError, PublishError}, + Gossipsub, GossipsubConfigBuilder, GossipsubEvent, GossipsubMessage, IdentTopic as Topic, + MessageAuthenticity, MessageId, ValidationMode, }, identify::{Identify, IdentifyConfig, IdentifyEvent}, identity::Keypair, @@ -40,7 +41,7 @@ use libp2p::{ ProtocolSupport, RequestResponse, RequestResponseConfig, RequestResponseEvent, RequestResponseMessage, }, - swarm::SwarmEvent, + swarm::{ProtocolsHandlerUpgrErr, SwarmEvent}, Multiaddr, NetworkBehaviour, PeerId, Swarm, TransportError, }; use serde::{de::DeserializeOwned, Serialize}; @@ -291,6 +292,314 @@ where }) } + #[inline] + fn handle_peer_discovery(mut self, bootstrapped: bool) -> Self { + if !bootstrapped { + let random_peer = PeerId::random(); + self.swarm + .behaviour_mut() + .kadem + .get_closest_peers(random_peer); + } + self + } + + #[inline] + fn handle_num_connections(mut self, bootstrapped: bool) -> Self { + // if we're bootstrapped, do nothing + // otherwise periodically get more peers if needed + if !bootstrapped { + if self.connecting_peers.len() + self.connected_peers.len() <= self.min_num_peers { + // Calcuate the currently connected peers + let used_peers = self + .connecting_peers + .union(&self.connected_peers) + .copied() + .collect(); + // Calcuate the list of "new" peers, once not currently used for + // a connection + let potential_peers: HashSet = + self.known_peers.difference(&used_peers).copied().collect(); + // Number of peers we want to try connecting to + let num_to_connect = self.min_num_peers + 1 + - (self.connected_peers.len() + self.connecting_peers.len()); + // Random(?) subset of the availible peers to try connecting to + let chosen_peers = potential_peers + .iter() + .copied() + .choose_multiple(&mut thread_rng(), num_to_connect); + // Try dialing each random (?) peer + for a_peer in chosen_peers { + match self.swarm.dial(a_peer) { + Ok(_) => { + self.connecting_peers.insert(a_peer); + } + Err(e) => error!("Dial {:?} failed: {:?}", a_peer, e), + }; + } + } else if self.connected_peers.len() > self.max_num_peers { + // If we are connected to too many peers, try disconnecting from + // a random (?) subset + let peers_to_rm = self.connected_peers.iter().copied().choose_multiple( + &mut thread_rng(), + self.connected_peers.len() - self.max_num_peers, + ); + for a_peer in peers_to_rm { + // FIXME the error is () ? + let _ = self.swarm.disconnect_peer_id(a_peer); + } + } + } + self + } + + async fn handle_ui_events( + mut self, + msg: Result, flume::RecvError>, + ) -> Result<(Self, bool), NetworkError> { + match msg { + Ok(msg) => { + #[allow(clippy::enum_glob_use)] + use SwarmAction::{DirectMessage, GetId, Shutdown, Subscribe, Unsubscribe}; + match msg { + Shutdown => { + warn!("Libp2p listener shutting down"); + return Ok((self, true)); + } + SwarmAction::GossipMsg(msg, chan) => { + info!("broadcasting message {:?}", msg); + let topic = ::topic(&msg); + let contents = ::data(&msg); + let res = self + .swarm + .behaviour_mut() + .gossipsub + .publish(topic.clone(), contents.clone()) + .map(|_| ()) + .context(PublishSnafu); + chan.send_async(res) + .await + .map_err(|_e| NetworkError::StreamClosed)?; + } + GetId(reply_chan) => { + // FIXME proper error handling + reply_chan + .send_async(self.peer_id) + .await + .map_err(|_e| NetworkError::StreamClosed)?; + } + Subscribe(t) => { + if self + .swarm + .behaviour_mut() + .gossipsub + .subscribe(&Topic::new(t.clone())) + .is_err() + { + error!("error subscribing to topic {}", t); + } + } + Unsubscribe(t) => { + if self + .swarm + .behaviour_mut() + .gossipsub + .unsubscribe(&Topic::new(t.clone())) + .is_err() + { + error!("error unsubscribing to topic {}", t); + } + } + DirectMessage(pid, msg) => { + self.swarm + .behaviour_mut() + .request_response + .send_request(&pid, DirectMessageRequest(msg)); + } + } + } + Err(e) => { + error!("Error receiving msg: {:?}", e); + } + } + Ok((self, false)) + } + + async fn handle_swarm_events( + mut self, + bootstrapped: &mut bool, + event: SwarmEvent< + NetworkEvent, + EitherError< + EitherError, Error>, + ProtocolsHandlerUpgrErr, + >, + >, + r_input: &Sender>, + ) -> Result { + // Make the match cleaner + #[allow(clippy::enum_glob_use)] + use NetworkEvent::*; + #[allow(clippy::enum_glob_use)] + use SwarmEvent::*; + // TODO re enable this + warn!("libp2p event {:?}", event); + match event { + Behaviour(RequestResponse(msg)) => { + if let RequestResponseEvent::Message { + message: + RequestResponseMessage::Request { + request: DirectMessageRequest(m), + .. + }, + .. + } = msg + { + r_input + .send_async(SwarmResult::DirectMessage(m)) + .await + .map_err(|_e| NetworkError::StreamClosed)?; + } + } + Behaviour(Gossip(GossipsubEvent::Message { message, .. })) => { + r_input + .send_async(SwarmResult::GossipMsg(message.into())) + .await + .map_err(|_e| NetworkError::StreamClosed)?; + }, + Behaviour(Kadem(event)) => { + match event { + KademliaEvent::OutboundQueryCompleted { result, .. } => { + match result { + // FIXME rebootstrap or fail in the failed + // bootstrap case + QueryResult::Bootstrap(r) => { + match r { + Ok(_bootstrap) => { + // we're bootstrapped + // don't bootstrap again + *bootstrapped = false; + } + Err(_) => { + // try again + *bootstrapped = true; + } + } + } + QueryResult::GetClosestPeers(Ok(GetClosestPeersOk { + peers, .. + })) => { + for peer in peers { + self.known_peers.insert(peer); + } + r_input + .send_async(SwarmResult::UpdateKnownPeers( + self.known_peers.clone(), + )) + .await + .map_err(|_e| NetworkError::StreamClosed)?; + } + _ => {} + } + } + KademliaEvent::RoutingUpdated { + peer, + is_new_peer: _is_new_peer, + addresses: _addresses, + .. + } => { + self.known_peers.insert(peer); + r_input + .send_async(SwarmResult::UpdateKnownPeers(self.known_peers.clone())) + .await + .map_err(|_e| NetworkError::StreamClosed)?; + } + _ => {} + } + } + Behaviour(Ident(i)) => { + if let IdentifyEvent::Received { peer_id, info, .. } = i { + for addr in info.listen_addrs { + self.swarm + .behaviour_mut() + .kadem + .add_address(&peer_id, addr.clone()); + } + self.known_peers.insert(peer_id); + r_input + .send_async(SwarmResult::UpdateKnownPeers(self.known_peers.clone())) + .await + .map_err(|_e| NetworkError::StreamClosed)?; + } + }, + ConnectionEstablished { + peer_id, endpoint, .. + } => { + match endpoint { + ConnectedPoint::Dialer { address } => { + self.swarm + .behaviour_mut() + .kadem + .add_address(&peer_id, address); + } + ConnectedPoint::Listener { + local_addr: _, + send_back_addr, + } => { + self.swarm + .behaviour_mut() + .kadem + .add_address(&peer_id, send_back_addr); + } + } + self.connected_peers.insert(peer_id); + self.connecting_peers.remove(&peer_id); + // now we have at least one peer so we can bootstrap + if !*bootstrapped { + self.swarm + .behaviour_mut() + .kadem + .bootstrap() + .map_err(|_e| NetworkError::NoKnownPeers)?; + } + r_input + .send_async(SwarmResult::UpdateConnectedPeers( + self.connected_peers.clone(), + )) + .await + .map_err(|_e| NetworkError::StreamClosed)?; + } + ConnectionClosed { peer_id, .. } => { + self.connected_peers.remove(&peer_id); + // FIXME remove stale address, not *all* addresses + self.swarm.behaviour_mut().kadem.remove_peer(&peer_id); + + r_input + .send_async(SwarmResult::UpdateConnectedPeers( + self.connected_peers.clone(), + )) + .await + .map_err(|_e| NetworkError::StreamClosed)?; + r_input + .send_async(SwarmResult::UpdateKnownPeers(self.known_peers.clone())) + .await + .map_err(|_e| NetworkError::StreamClosed)?; + }, + Dialing(_) + | NewListenAddr { .. } + | ExpiredListenAddr { .. } + | ListenerClosed { .. } + | IncomingConnection { .. } + | IncomingConnectionError { .. } + | OutgoingConnectionError { .. } + | BannedPeer { .. } + | ListenerError { .. } + | Behaviour(_) => {} + , + } + Ok(self) + } + /// Spawn a task to listen for requests on the returned channel /// as well as any events produced by libp2p /// `mut_mut` is disabled b/c must consume `self` @@ -307,256 +616,27 @@ where ) -> Result<(Sender>, Receiver>), NetworkError> { let (s_input, s_output) = unbounded::>(); let (r_input, r_output) = unbounded::>(); - let mut bootstrapped = false; + spawn(async move { loop { // NOTE(nm): rustformat doesn't really work inside of macros, I would like to // refactor these all out to local methods for formatability select! { _ = sleep(Duration::from_secs(30)).fuse() => { - if !bootstrapped { - let random_peer = PeerId::random(); - self.swarm.behaviour_mut().kadem.get_closest_peers(random_peer); - } + self = self.handle_peer_discovery(bootstrapped); }, _ = sleep(Duration::from_secs(1)).fuse() => { - // if we're bootstrapped, do nothing - // otherwise periodically get more peers if needed - if !bootstrapped { - if self.connecting_peers.len() - + self.connected_peers.len() - <= self.min_num_peers { - // Calcuate the currently connected peers - let used_peers = self - .connecting_peers - .union(&self.connected_peers) - .copied() - .collect(); - // Calcuate the list of "new" peers, once not currently used for - // a connection - let potential_peers: HashSet = - self - .known_peers - .difference(&used_peers) - .copied() - .collect(); - // Number of peers we want to try connecting to - let num_to_connect = - self.min_num_peers + 1 - - (self.connected_peers.len() + self.connecting_peers.len()); - // Random(?) subset of the availible peers to try connecting to - let chosen_peers = - potential_peers - .iter() - .copied() - .choose_multiple(&mut thread_rng(), num_to_connect); - // Try dialing each random (?) peer - for a_peer in chosen_peers { - match self.swarm.dial(a_peer) { - Ok(_) => { - self.connecting_peers.insert(a_peer); - } - Err(e) => error!("Dial {:?} failed: {:?}", a_peer, e), - }; - } - } else if self.connected_peers.len() > self.max_num_peers { - // If we are connected to too many peers, try disconnecting from - // a random (?) subset - let peers_to_rm = self - .connected_peers - .iter() - .copied() - .choose_multiple(&mut thread_rng(), - self.connected_peers.len() - - self.max_num_peers); - for a_peer in peers_to_rm { - // FIXME the error is () ? - let _ = self.swarm.disconnect_peer_id(a_peer); - } - - } - } + self = self.handle_num_connections(bootstrapped); } event = self.swarm.select_next_some() => { - // Make the match cleaner - #[allow(clippy::enum_glob_use)] - use SwarmEvent::*; - #[allow(clippy::enum_glob_use)] - use NetworkEvent::*; - // TODO re enable this - warn!("libp2p event {:?}", event); - match event { - Dialing(_) - | NewListenAddr {..} - | ExpiredListenAddr {..} - | ListenerClosed {..} - | IncomingConnection {..} - | IncomingConnectionError {..} - | OutgoingConnectionError {..} - | BannedPeer {..} - | ListenerError {..} => { - }, - Behaviour(RequestResponse(msg)) => { - match msg { - RequestResponseEvent::Message { message: RequestResponseMessage::Request{ request: DirectMessageRequest(m), ..}, .. } => { - r_input.send_async(SwarmResult::DirectMessage(m)).await.map_err(|_e| NetworkError::StreamClosed)?; - }, - _ => {} - } - }, - Behaviour(Gossip(g)) => { - match g { - GossipsubEvent::Message { message, .. } => { - r_input.send_async(SwarmResult::GossipMsg(message.into())).await.map_err(|_e| NetworkError::StreamClosed)?; - }, - _ => {} - } - }, - Behaviour(Kadem(event)) => { - match event { - KademliaEvent::OutboundQueryCompleted { result, ..} => { - match result { - // FIXME rebootstrap or fail in the failed - // bootstrap case - QueryResult::Bootstrap(r) => { - match r { - Ok(_bootstrap) => { - // we're bootstrapped - // don't bootstrap again - bootstrapped = false; - }, - Err(_) => { - // try again - bootstrapped = true; - } - - } - }, - QueryResult::GetClosestPeers(result) => { - match result { - Ok(GetClosestPeersOk { key: _key, peers }) => { - for peer in peers { - self.known_peers.insert(peer); - } - r_input.send_async(SwarmResult::UpdateKnownPeers(self.known_peers.clone())).await.map_err(|_e| NetworkError::StreamClosed)?; - }, - _ => {} - } - }, - _ => {} - } - }, - KademliaEvent::RoutingUpdated { peer, is_new_peer: _is_new_peer, addresses: _addresses, .. } => { - self.known_peers.insert(peer); - r_input.send_async(SwarmResult::UpdateKnownPeers(self.known_peers.clone())).await.map_err(|_e| NetworkError::StreamClosed)?; - }, - _ => {} - } - }, - Behaviour(Ident(i)) => { - match i { - IdentifyEvent::Received { peer_id, info, .. } => { - for addr in info.listen_addrs { - self.swarm.behaviour_mut().kadem - .add_address(&peer_id, addr.clone()); - } - self.known_peers.insert(peer_id); - r_input.send_async(SwarmResult::UpdateKnownPeers(self.known_peers.clone())).await.map_err(|_e| NetworkError::StreamClosed)?; - }, - _ => {} - } - }, - ConnectionEstablished { peer_id, endpoint, .. } => { - match endpoint { - ConnectedPoint::Dialer { address } => { - self.swarm.behaviour_mut().kadem.add_address(&peer_id, address); - }, - ConnectedPoint::Listener { local_addr: _, send_back_addr } => { - self.swarm.behaviour_mut().kadem.add_address(&peer_id, send_back_addr); - }, - } - self.connected_peers.insert(peer_id); - self.connecting_peers.remove(&peer_id); - // now we have at least one peer so we can bootstrap - if !bootstrapped { - self.swarm.behaviour_mut().kadem.bootstrap().map_err(|_e| NetworkError::NoKnownPeers)?; - } - r_input.send_async(SwarmResult::UpdateConnectedPeers(self.connected_peers.clone())).await.map_err(|_e| NetworkError::StreamClosed)?; - } - ConnectionClosed { peer_id, .. } => { - self.connected_peers.remove(&peer_id); - // FIXME remove stale address, not *all* addresses - self.swarm.behaviour_mut().kadem.remove_peer(&peer_id); - - r_input.send_async(SwarmResult::UpdateConnectedPeers(self.connected_peers.clone())).await.map_err(|_e| NetworkError::StreamClosed)?; - r_input.send_async(SwarmResult::UpdateKnownPeers(self.known_peers.clone())).await.map_err(|_e| NetworkError::StreamClosed)?; - } - } + self = self.handle_swarm_events(&mut bootstrapped, event, &r_input).await?; }, msg = s_output.recv_async() => { - match msg { - Ok(msg) => { - #[allow(clippy::enum_glob_use)] - use SwarmAction::{Shutdown, GetId, Subscribe, Unsubscribe, DirectMessage}; - match msg { - Shutdown => { - warn!("Libp2p listener shutting down"); - break - }, - SwarmAction::GossipMsg(msg, chan) => { - info!("broadcasting message {:?}", msg); - let topic = ::topic(&msg); - let contents = ::data(&msg); - let res = self - .swarm - .behaviour_mut() - .gossipsub - .publish(topic.clone(), contents.clone()) - .map(|_| ()).context(PublishSnafu); - chan - .send_async(res) - .await - .map_err(|_e| NetworkError::StreamClosed)?; - }, - GetId(reply_chan) => { - // FIXME proper error handling - reply_chan - .send_async(self.peer_id) - .await - .map_err(|_e| NetworkError::StreamClosed)?; - }, - Subscribe(t) => { - if self - .swarm - .behaviour_mut() - .gossipsub - .subscribe(&Topic::new(t.clone())) - .is_err() { - error!("error subscribing to topic {}", t); - } - } - Unsubscribe(t) => { - if self - .swarm - .behaviour_mut() - .gossipsub.unsubscribe(&Topic::new(t.clone())) - .is_err() { - error!("error unsubscribing to topic {}", t); - } - }, - DirectMessage(pid, msg) => { - self - .swarm - .behaviour_mut() - .request_response - .send_request(&pid, DirectMessageRequest(msg)); - } - } - }, - Err(e) => { - error!("Error receiving msg: {:?}", e); - } + let (s, shutdown) = self.handle_ui_events(msg).await?; + self = s; + if shutdown { + break } } } From fd0abf02dd8137a2ed52721356eef1da5066152b Mon Sep 17 00:00:00 2001 From: Justin Restivo Date: Tue, 25 Jan 2022 18:03:37 -0500 Subject: [PATCH 032/107] Refactor to split control flow out of select --- libp2p-networking/src/lib.rs | 454 ++++++++++++++++++------------- libp2p-networking/src/message.rs | 2 +- 2 files changed, 267 insertions(+), 189 deletions(-) diff --git a/libp2p-networking/src/lib.rs b/libp2p-networking/src/lib.rs index 4c1d5f6550..3eb6ad305c 100644 --- a/libp2p-networking/src/lib.rs +++ b/libp2p-networking/src/lib.rs @@ -19,7 +19,14 @@ pub mod tracing_setup; use async_std::task::{sleep, spawn}; use message::{DirectMessageCodec, DirectMessageRequest, DirectMessageResponse}; use rand::{seq::IteratorRandom, thread_rng}; -use std::{collections::HashSet, io::Error, iter, marker::PhantomData, time::Duration}; +use std::{ + collections::HashSet, + io::Error, + iter, + marker::PhantomData, + task::{Context, Poll}, + time::Duration, +}; use flume::{unbounded, Receiver, Sender}; use futures::{select, FutureExt, StreamExt}; @@ -41,7 +48,10 @@ use libp2p::{ ProtocolSupport, RequestResponse, RequestResponseConfig, RequestResponseEvent, RequestResponseMessage, }, - swarm::{ProtocolsHandlerUpgrErr, SwarmEvent}, + swarm::{ + NetworkBehaviour, NetworkBehaviourAction, NetworkBehaviourEventProcess, PollParameters, + ProtocolsHandlerUpgrErr, SwarmEvent, + }, Multiaddr, NetworkBehaviour, PeerId, Swarm, TransportError, }; use serde::{de::DeserializeOwned, Serialize}; @@ -57,10 +67,20 @@ pub mod ui; /// injecting events does not play well /// with asyncrony #[derive(NetworkBehaviour)] -#[behaviour(out_event = "NetworkEvent")] -#[behaviour(event_process = false)] +#[behaviour( + out_event = "SwarmResult", + poll_method = "poll", + event_process = true +)] pub struct NetworkDef< - T: std::fmt::Debug + Send + Sync + Clone + Serialize + DeserializeOwned + 'static, + T: std::fmt::Debug + + Send + + Sync + + Clone + + Serialize + + DeserializeOwned + + 'static + + From, > { /// purpose: broadcasting messages to many peers /// NOTE gossipsub works ONLY for sharing messsages right now @@ -73,60 +93,190 @@ pub struct NetworkDef< pub identify: Identify, /// purpose: directly messaging peer pub request_response: RequestResponse>, + #[behaviour(ignore)] + pub bootstrap: bool, + #[behaviour(ignore)] + pub connected_peers: HashSet, + // TODO replace this with a set of queryids + #[behaviour(ignore)] + pub connecting_peers: HashSet, + #[behaviour(ignore)] + pub known_peers: HashSet, + #[behaviour(ignore)] + pub ui_events: Vec>, } -#[derive(Debug)] -pub enum NetworkEvent { - Gossip(GossipsubEvent), - Kadem(KademliaEvent), - Ident(IdentifyEvent), - RequestResponse(RequestResponseEvent, DirectMessageResponse>), -} +impl< + T: std::fmt::Debug + + Send + + Sync + + Clone + + Serialize + + DeserializeOwned + + 'static + + From, + > NetworkDef +{ + fn poll( + &mut self, + _cx: &mut Context<'_>, + _: &mut impl PollParameters, + ) -> Poll, ::ProtocolsHandler>> + { + if !self.ui_events.is_empty() { + return Poll::Ready(NetworkBehaviourAction::GenerateEvent( + self.ui_events.remove(0), + )); + } -#[derive(Debug)] -pub enum SendDirectMsgEvent { - NotifyPeer(T), + Poll::Pending + } } -impl - From for NetworkEvent +impl< + T: std::fmt::Debug + + Send + + Sync + + Clone + + Serialize + + DeserializeOwned + + 'static + + From, + > NetworkBehaviourEventProcess for NetworkDef { - fn from(source: IdentifyEvent) -> Self { - NetworkEvent::Ident(source) + fn inject_event(&mut self, event: GossipsubEvent) { + error!(?event, "gossipsub msg recv-ed"); + if let GossipsubEvent::Message { message, .. } = event { + error!("correct message form"); + self.ui_events.push(SwarmResult::GossipMsg(message.into())); + } } } -impl - From for NetworkEvent +impl< + T: std::fmt::Debug + + Send + + Sync + + Clone + + Serialize + + DeserializeOwned + + 'static + + From, + > NetworkBehaviourEventProcess for NetworkDef { - fn from(source: KademliaEvent) -> Self { - NetworkEvent::Kadem(source) + fn inject_event(&mut self, event: KademliaEvent) { + error!(?event, "kadem msg recv-ed"); + match event { + KademliaEvent::OutboundQueryCompleted { result, .. } => { + match result { + // FIXME rebootstrap or fail in the failed + // bootstrap case + QueryResult::Bootstrap(r) => { + match r { + Ok(_bootstrap) => { + // we're bootstrapped + // don't bootstrap again + self.bootstrap = false; + } + Err(_) => { + // try again + self.bootstrap = true; + } + } + } + QueryResult::GetClosestPeers(Ok(GetClosestPeersOk { peers, .. })) => { + for peer in peers { + self.known_peers.insert(peer); + } + self.ui_events + .push(SwarmResult::UpdateKnownPeers(self.known_peers.clone())); + } + _ => {} + } + } + KademliaEvent::RoutingUpdated { + peer, + is_new_peer: _is_new_peer, + addresses: _addresses, + .. + } => { + self.known_peers.insert(peer); + self.ui_events + .push(SwarmResult::UpdateKnownPeers(self.known_peers.clone())); + } + _ => {} + } } } -impl - From for NetworkEvent +// as NetworkBehaviourEventProcess>>> + +impl< + T: std::fmt::Debug + + Send + + Sync + + Clone + + Serialize + + DeserializeOwned + + 'static + + From, + > NetworkBehaviourEventProcess for NetworkDef { - fn from(source: GossipsubEvent) -> Self { - NetworkEvent::Gossip(source) + fn inject_event(&mut self, event: IdentifyEvent) { + if let IdentifyEvent::Received { peer_id, info, .. } = event { + for addr in info.listen_addrs { + self.kadem.add_address(&peer_id, addr.clone()); + } + self.known_peers.insert(peer_id); + self.ui_events + .push(SwarmResult::UpdateKnownPeers(self.known_peers.clone())); + } } } -impl - From, DirectMessageResponse>> for NetworkEvent +// impl NetworkBehaviourEventProcess>> for NetworkDef { +impl + NetworkBehaviourEventProcess< + RequestResponseEvent, DirectMessageResponse>, + > for NetworkDef +where + T: std::fmt::Debug + + Send + + Sync + + Clone + + Serialize + + DeserializeOwned + + 'static + + From, { - fn from(source: RequestResponseEvent, DirectMessageResponse>) -> Self { - NetworkEvent::RequestResponse(source) + fn inject_event( + &mut self, + event: RequestResponseEvent, DirectMessageResponse>, + ) { + if let RequestResponseEvent::Message { + message: + RequestResponseMessage::Request { + request: DirectMessageRequest(m), + .. + }, + .. + } = event + { + self.ui_events.push(SwarmResult::DirectMessage(m)); + } } } pub struct Network< - T: Send + Sync + Clone + 'static + std::fmt::Debug + Serialize + DeserializeOwned, + T: Send + + Sync + + Clone + + 'static + + std::fmt::Debug + + Serialize + + DeserializeOwned + + From, > { - pub connected_peers: HashSet, - // TODO replace this with a set of queryids - pub connecting_peers: HashSet, - pub known_peers: HashSet, pub identity: Keypair, pub peer_id: PeerId, pub broadcast_topic: Topic, @@ -147,7 +297,8 @@ pub enum SwarmAction { /// holds events of the swarm to be relayed to the cli event loop /// out -pub enum SwarmResult { +#[derive(Debug)] +pub enum SwarmResult { UpdateConnectedPeers(HashSet), UpdateKnownPeers(HashSet), GossipMsg(N), @@ -274,6 +425,12 @@ where kadem, identify, request_response, + connected_peers: HashSet::new(), + connecting_peers: HashSet::new(), + known_peers: HashSet::new(), + ui_events: Vec::new(), + // TODO implement the rest of this + bootstrap: false, }; Swarm::new(transport, network, peer_id) @@ -282,9 +439,6 @@ where Ok(Self { identity, peer_id, - connected_peers: HashSet::new(), - connecting_peers: HashSet::new(), - known_peers: HashSet::new(), broadcast_topic, max_num_peers: 6, min_num_peers: 5, @@ -293,7 +447,7 @@ where } #[inline] - fn handle_peer_discovery(mut self, bootstrapped: bool) -> Self { + fn handle_peer_discovery(&mut self, bootstrapped: bool) { if !bootstrapped { let random_peer = PeerId::random(); self.swarm @@ -301,28 +455,28 @@ where .kadem .get_closest_peers(random_peer); } - self } #[inline] - fn handle_num_connections(mut self, bootstrapped: bool) -> Self { + fn handle_num_connections(&mut self, bootstrapped: bool) { + let swarm = self.swarm.behaviour(); // if we're bootstrapped, do nothing // otherwise periodically get more peers if needed if !bootstrapped { - if self.connecting_peers.len() + self.connected_peers.len() <= self.min_num_peers { + if swarm.connecting_peers.len() + swarm.connected_peers.len() <= self.min_num_peers { // Calcuate the currently connected peers - let used_peers = self + let used_peers = swarm .connecting_peers - .union(&self.connected_peers) + .union(&swarm.connected_peers) .copied() .collect(); // Calcuate the list of "new" peers, once not currently used for // a connection let potential_peers: HashSet = - self.known_peers.difference(&used_peers).copied().collect(); + swarm.known_peers.difference(&used_peers).copied().collect(); // Number of peers we want to try connecting to let num_to_connect = self.min_num_peers + 1 - - (self.connected_peers.len() + self.connecting_peers.len()); + - (swarm.connected_peers.len() + swarm.connecting_peers.len()); // Random(?) subset of the availible peers to try connecting to let chosen_peers = potential_peers .iter() @@ -332,17 +486,17 @@ where for a_peer in chosen_peers { match self.swarm.dial(a_peer) { Ok(_) => { - self.connecting_peers.insert(a_peer); + self.swarm.behaviour_mut().connecting_peers.insert(a_peer); } Err(e) => error!("Dial {:?} failed: {:?}", a_peer, e), }; } - } else if self.connected_peers.len() > self.max_num_peers { + } else if swarm.connected_peers.len() > self.max_num_peers { // If we are connected to too many peers, try disconnecting from // a random (?) subset - let peers_to_rm = self.connected_peers.iter().copied().choose_multiple( + let peers_to_rm = swarm.connected_peers.iter().copied().choose_multiple( &mut thread_rng(), - self.connected_peers.len() - self.max_num_peers, + swarm.connected_peers.len() - self.max_num_peers, ); for a_peer in peers_to_rm { // FIXME the error is () ? @@ -350,13 +504,12 @@ where } } } - self } async fn handle_ui_events( - mut self, + &mut self, msg: Result, flume::RecvError>, - ) -> Result<(Self, bool), NetworkError> { + ) -> Result { match msg { Ok(msg) => { #[allow(clippy::enum_glob_use)] @@ -364,10 +517,10 @@ where match msg { Shutdown => { warn!("Libp2p listener shutting down"); - return Ok((self, true)); + return Ok(true); } SwarmAction::GossipMsg(msg, chan) => { - info!("broadcasting message {:?}", msg); + error!("broadcasting message {:?}", msg); let topic = ::topic(&msg); let contents = ::data(&msg); let res = self @@ -377,6 +530,8 @@ where .publish(topic.clone(), contents.clone()) .map(|_| ()) .context(PublishSnafu); + error!("publishing reuslt! {:?}", res); + chan.send_async(res) .await .map_err(|_e| NetworkError::StreamClosed)?; @@ -422,116 +577,29 @@ where error!("Error receiving msg: {:?}", e); } } - Ok((self, false)) + Ok(false) } async fn handle_swarm_events( - mut self, + &mut self, bootstrapped: &mut bool, event: SwarmEvent< - NetworkEvent, + SwarmResult, EitherError< EitherError, Error>, ProtocolsHandlerUpgrErr, >, >, - r_input: &Sender>, - ) -> Result { + send_to_ui: &Sender>, + ) -> Result<(), NetworkError> { // Make the match cleaner #[allow(clippy::enum_glob_use)] - use NetworkEvent::*; - #[allow(clippy::enum_glob_use)] use SwarmEvent::*; + // TODO re enable this - warn!("libp2p event {:?}", event); + // warn!("libp2p event {:?}", event); match event { - Behaviour(RequestResponse(msg)) => { - if let RequestResponseEvent::Message { - message: - RequestResponseMessage::Request { - request: DirectMessageRequest(m), - .. - }, - .. - } = msg - { - r_input - .send_async(SwarmResult::DirectMessage(m)) - .await - .map_err(|_e| NetworkError::StreamClosed)?; - } - } - Behaviour(Gossip(GossipsubEvent::Message { message, .. })) => { - r_input - .send_async(SwarmResult::GossipMsg(message.into())) - .await - .map_err(|_e| NetworkError::StreamClosed)?; - }, - Behaviour(Kadem(event)) => { - match event { - KademliaEvent::OutboundQueryCompleted { result, .. } => { - match result { - // FIXME rebootstrap or fail in the failed - // bootstrap case - QueryResult::Bootstrap(r) => { - match r { - Ok(_bootstrap) => { - // we're bootstrapped - // don't bootstrap again - *bootstrapped = false; - } - Err(_) => { - // try again - *bootstrapped = true; - } - } - } - QueryResult::GetClosestPeers(Ok(GetClosestPeersOk { - peers, .. - })) => { - for peer in peers { - self.known_peers.insert(peer); - } - r_input - .send_async(SwarmResult::UpdateKnownPeers( - self.known_peers.clone(), - )) - .await - .map_err(|_e| NetworkError::StreamClosed)?; - } - _ => {} - } - } - KademliaEvent::RoutingUpdated { - peer, - is_new_peer: _is_new_peer, - addresses: _addresses, - .. - } => { - self.known_peers.insert(peer); - r_input - .send_async(SwarmResult::UpdateKnownPeers(self.known_peers.clone())) - .await - .map_err(|_e| NetworkError::StreamClosed)?; - } - _ => {} - } - } - Behaviour(Ident(i)) => { - if let IdentifyEvent::Received { peer_id, info, .. } = i { - for addr in info.listen_addrs { - self.swarm - .behaviour_mut() - .kadem - .add_address(&peer_id, addr.clone()); - } - self.known_peers.insert(peer_id); - r_input - .send_async(SwarmResult::UpdateKnownPeers(self.known_peers.clone())) - .await - .map_err(|_e| NetworkError::StreamClosed)?; - } - }, + // TODO handle swarm action by sending to swarm ConnectionEstablished { peer_id, endpoint, .. } => { @@ -552,8 +620,8 @@ where .add_address(&peer_id, send_back_addr); } } - self.connected_peers.insert(peer_id); - self.connecting_peers.remove(&peer_id); + self.swarm.behaviour_mut().connected_peers.insert(peer_id); + self.swarm.behaviour_mut().connecting_peers.remove(&peer_id); // now we have at least one peer so we can bootstrap if !*bootstrapped { self.swarm @@ -562,29 +630,30 @@ where .bootstrap() .map_err(|_e| NetworkError::NoKnownPeers)?; } - r_input + send_to_ui .send_async(SwarmResult::UpdateConnectedPeers( - self.connected_peers.clone(), + self.swarm.behaviour_mut().connected_peers.clone(), )) .await .map_err(|_e| NetworkError::StreamClosed)?; } ConnectionClosed { peer_id, .. } => { - self.connected_peers.remove(&peer_id); + let swarm = self.swarm.behaviour_mut(); + swarm.connected_peers.remove(&peer_id); // FIXME remove stale address, not *all* addresses - self.swarm.behaviour_mut().kadem.remove_peer(&peer_id); + swarm.kadem.remove_peer(&peer_id); - r_input + send_to_ui .send_async(SwarmResult::UpdateConnectedPeers( - self.connected_peers.clone(), + swarm.connected_peers.clone(), )) .await .map_err(|_e| NetworkError::StreamClosed)?; - r_input - .send_async(SwarmResult::UpdateKnownPeers(self.known_peers.clone())) + send_to_ui + .send_async(SwarmResult::UpdateKnownPeers(swarm.known_peers.clone())) .await .map_err(|_e| NetworkError::StreamClosed)?; - }, + } Dialing(_) | NewListenAddr { .. } | ExpiredListenAddr { .. } @@ -593,11 +662,15 @@ where | IncomingConnectionError { .. } | OutgoingConnectionError { .. } | BannedPeer { .. } - | ListenerError { .. } - | Behaviour(_) => {} - , + | ListenerError { .. } => {} + Behaviour(b) => { + send_to_ui + .send_async(b) + .await + .map_err(|_e| NetworkError::StreamClosed)?; + } } - Ok(self) + Ok(()) } /// Spawn a task to listen for requests on the returned channel @@ -618,31 +691,36 @@ where let (r_input, r_output) = unbounded::>(); let mut bootstrapped = false; - spawn(async move { - loop { - // NOTE(nm): rustformat doesn't really work inside of macros, I would like to - // refactor these all out to local methods for formatability - select! { - _ = sleep(Duration::from_secs(30)).fuse() => { - self = self.handle_peer_discovery(bootstrapped); - }, - _ = sleep(Duration::from_secs(1)).fuse() => { - self = self.handle_num_connections(bootstrapped); - } - event = self.swarm.select_next_some() => { - self = self.handle_swarm_events(&mut bootstrapped, event, &r_input).await?; - }, - msg = s_output.recv_async() => { - let (s, shutdown) = self.handle_ui_events(msg).await?; - self = s; - if shutdown { - break + spawn( + async move { + loop { + // NOTE(nm): rustformat doesn't really work inside of macros, I would like to + // refactor these all out to local methods for formatability + select! { + _ = sleep(Duration::from_secs(30)).fuse() => { + self.handle_peer_discovery(bootstrapped); + }, + _ = sleep(Duration::from_secs(1)).fuse() => { + self.handle_num_connections(bootstrapped); + } + event = self.swarm.next() => { + if let Some(event) = event { + error!("handling event {:?}", event); + self.handle_swarm_events(&mut bootstrapped, event, &r_input).await?; + } + }, + msg = s_output.recv_async() => { + let shutdown = self.handle_ui_events(msg).await?; + if shutdown { + break + } } } } + Ok::<(), NetworkError>(()) } - Ok::<(), NetworkError>(()) - }.instrument(info_span!( "Libp2p Event Handler"))); + .instrument(info_span!("Libp2p Event Handler")), + ); Ok((s_input, r_output)) } } diff --git a/libp2p-networking/src/message.rs b/libp2p-networking/src/message.rs index be4b95870d..5eeeefc63c 100644 --- a/libp2p-networking/src/message.rs +++ b/libp2p-networking/src/message.rs @@ -66,7 +66,7 @@ impl ProtocolName for DirectMessageProtocol { // TODO are generics useful here? Could also just pass in vec of already serialized bytes #[async_trait] -impl RequestResponseCodec +impl RequestResponseCodec for DirectMessageCodec { type Protocol = DirectMessageProtocol; From 8730fc69126f195cc4b48735dbf1826048c98775 Mon Sep 17 00:00:00 2001 From: Justin Restivo Date: Wed, 26 Jan 2022 09:29:18 -0500 Subject: [PATCH 033/107] Remove generics from DirectMessageCodec --- libp2p-networking/src/lib.rs | 36 ++++++++++++------- libp2p-networking/src/message.rs | 60 ++++++++++---------------------- 2 files changed, 41 insertions(+), 55 deletions(-) diff --git a/libp2p-networking/src/lib.rs b/libp2p-networking/src/lib.rs index 3eb6ad305c..37b75d88f1 100644 --- a/libp2p-networking/src/lib.rs +++ b/libp2p-networking/src/lib.rs @@ -17,13 +17,13 @@ pub mod tracing_setup; use async_std::task::{sleep, spawn}; +use bincode::{ErrorKind, Options}; use message::{DirectMessageCodec, DirectMessageRequest, DirectMessageResponse}; use rand::{seq::IteratorRandom, thread_rng}; use std::{ collections::HashSet, io::Error, iter, - marker::PhantomData, task::{Context, Poll}, time::Duration, }; @@ -92,7 +92,7 @@ pub struct NetworkDef< /// purpose: peer discovery pub identify: Identify, /// purpose: directly messaging peer - pub request_response: RequestResponse>, + pub request_response: RequestResponse, #[behaviour(ignore)] pub bootstrap: bool, #[behaviour(ignore)] @@ -236,9 +236,8 @@ impl< // impl NetworkBehaviourEventProcess>> for NetworkDef { impl - NetworkBehaviourEventProcess< - RequestResponseEvent, DirectMessageResponse>, - > for NetworkDef + NetworkBehaviourEventProcess> + for NetworkDef where T: std::fmt::Debug + Send @@ -251,7 +250,7 @@ where { fn inject_event( &mut self, - event: RequestResponseEvent, DirectMessageResponse>, + event: RequestResponseEvent, ) { if let RequestResponseEvent::Message { message: @@ -262,7 +261,13 @@ where .. } = event { - self.ui_events.push(SwarmResult::DirectMessage(m)); + let bincode_options = bincode::DefaultOptions::new().with_limit(16_384); + match bincode_options.deserialize(&m) { + Ok(msg) => { + self.ui_events.push(SwarmResult::DirectMessage(msg)); + } + Err(_) => todo!(), + } } } } @@ -415,7 +420,7 @@ where // request response for direct messages let request_response = RequestResponse::new( - DirectMessageCodec(PhantomData::), + DirectMessageCodec(), iter::once((DirectMessageProtocol(), ProtocolSupport::Full)), RequestResponseConfig::default(), ); @@ -566,10 +571,13 @@ where } } DirectMessage(pid, msg) => { - self.swarm - .behaviour_mut() - .request_response - .send_request(&pid, DirectMessageRequest(msg)); + let bincode_options = bincode::DefaultOptions::new().with_limit(16_384); + self.swarm.behaviour_mut().request_response.send_request( + &pid, + DirectMessageRequest( + bincode_options.serialize(&msg).context(BincodeSnafu)?, + ), + ); } } } @@ -595,7 +603,7 @@ where // Make the match cleaner #[allow(clippy::enum_glob_use)] use SwarmEvent::*; - + // TODO re enable this // warn!("libp2p event {:?}", event); match event { @@ -758,4 +766,6 @@ pub enum NetworkError { PublishError { source: PublishError }, /// Error when there are no known peers to bootstrap off NoKnownPeers, + /// Error encoding message + BincodeError { source: Box }, } diff --git a/libp2p-networking/src/message.rs b/libp2p-networking/src/message.rs index 5eeeefc63c..ae882dde74 100644 --- a/libp2p-networking/src/message.rs +++ b/libp2p-networking/src/message.rs @@ -1,11 +1,6 @@ -use std::{ - io::{Error, ErrorKind}, - marker::PhantomData, -}; - use async_std::io; use async_trait::async_trait; -use bincode::{DefaultOptions, Options}; + use futures::{AsyncRead, AsyncWrite, AsyncWriteExt}; use libp2p::{ core::{ @@ -15,7 +10,7 @@ use libp2p::{ gossipsub::GossipsubMessage, request_response::RequestResponseCodec, }; -use serde::{de::DeserializeOwned, Deserialize, Serialize}; +use serde::{Deserialize, Serialize}; use crate::GossipMsg; @@ -52,11 +47,11 @@ impl From for Message { #[derive(Debug, Clone)] pub struct DirectMessageProtocol(); #[derive(Clone, Debug, Serialize, Deserialize)] -pub struct DirectMessageCodec(pub PhantomData); +pub struct DirectMessageCodec(); #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] -pub struct DirectMessageRequest(pub T); +pub struct DirectMessageRequest(pub Vec); #[derive(Debug, Clone, PartialEq, Eq)] -pub struct DirectMessageResponse(); +pub struct DirectMessageResponse(pub Vec); impl ProtocolName for DirectMessageProtocol { fn protocol_name(&self) -> &[u8] { @@ -64,14 +59,11 @@ impl ProtocolName for DirectMessageProtocol { } } -// TODO are generics useful here? Could also just pass in vec of already serialized bytes #[async_trait] -impl RequestResponseCodec - for DirectMessageCodec -{ +impl RequestResponseCodec for DirectMessageCodec { type Protocol = DirectMessageProtocol; - type Request = DirectMessageRequest; + type Request = DirectMessageRequest; type Response = DirectMessageResponse; @@ -86,52 +78,35 @@ impl Re // FIXME magic numbers... // it looks like the easiest thing to do // is to set an upper limit threshold and use that - let vec = read_length_prefixed(io, 1_000_000).await?; - - let bincode_options = DefaultOptions::new().with_limit(16_384); + let msg = read_length_prefixed(io, 1_000_000).await?; - if vec.is_empty() { - return Err(io::ErrorKind::UnexpectedEof.into()); - } - - // NOTE error handling could be better... - // but the trait locks into io::Result : ( - Ok(DirectMessageRequest( - bincode_options - .deserialize(&vec) - .map_err(|e| Error::new(ErrorKind::Other, e.to_string()))?, - )) + // NOTE we don't error here. We'll wrap this in a behaviour and get better error messages + // there + Ok(DirectMessageRequest(msg)) } async fn read_response( &mut self, _: &DirectMessageProtocol, - _: &mut T, + io: &mut T, ) -> io::Result where T: AsyncRead + Unpin + Send, { - // NOTE no replies - Ok(DirectMessageResponse()) + let msg = read_length_prefixed(io, 1_000_000).await?; + Ok(DirectMessageResponse(msg)) } async fn write_request( &mut self, _: &DirectMessageProtocol, io: &mut T, - DirectMessageRequest(msg): DirectMessageRequest, + DirectMessageRequest(msg): DirectMessageRequest, ) -> io::Result<()> where T: AsyncWrite + Unpin + Send, { - let bincode_options = DefaultOptions::new().with_limit(16_384); - write_length_prefixed( - io, - bincode_options - .serialize(&msg) - .map_err(|e| Error::new(io::ErrorKind::Other, e.to_string()))?, - ) - .await?; + write_length_prefixed(io, msg).await?; io.close().await?; Ok(()) @@ -141,11 +116,12 @@ impl Re &mut self, _: &DirectMessageProtocol, io: &mut T, - DirectMessageResponse(): DirectMessageResponse, + DirectMessageResponse(msg): DirectMessageResponse, ) -> io::Result<()> where T: AsyncWrite + Unpin + Send, { + write_length_prefixed(io, msg).await?; io.close().await?; Ok(()) } From 1bd3fd03ccd9f1bcd2cc8d715fcd23a096c9a270 Mon Sep 17 00:00:00 2001 From: Justin Restivo Date: Wed, 26 Jan 2022 10:15:10 -0500 Subject: [PATCH 034/107] remove generics for direct messaging --- libp2p-networking/src/bin/clichat.rs | 2 +- libp2p-networking/src/lib.rs | 153 ++++++--------------------- libp2p-networking/src/message.rs | 2 +- libp2p-networking/src/ui.rs | 25 +++-- 4 files changed, 50 insertions(+), 132 deletions(-) diff --git a/libp2p-networking/src/bin/clichat.rs b/libp2p-networking/src/bin/clichat.rs index 2b6b67056b..9a3847d268 100644 --- a/libp2p-networking/src/bin/clichat.rs +++ b/libp2p-networking/src/bin/clichat.rs @@ -37,7 +37,7 @@ async fn main() -> Result<()> { color_eyre::install()?; networking_demo::tracing_setup::setup_tracing(); // -- Spin up the network connection - let mut networking: Network = + let mut networking: Network = Network::new().await.context("Failed to launch network")?; let port = CliOpt::from_args().port.unwrap_or(0u16); let known_peer = CliOpt::from_args().first_dial; diff --git a/libp2p-networking/src/lib.rs b/libp2p-networking/src/lib.rs index 37b75d88f1..459a760a10 100644 --- a/libp2p-networking/src/lib.rs +++ b/libp2p-networking/src/lib.rs @@ -54,7 +54,6 @@ use libp2p::{ }, Multiaddr, NetworkBehaviour, PeerId, Swarm, TransportError, }; -use serde::{de::DeserializeOwned, Serialize}; use snafu::{ResultExt, Snafu}; use tracing::{debug, error, info, info_span, instrument, trace, warn, Instrument}; @@ -63,25 +62,13 @@ use crate::message::DirectMessageProtocol; pub mod message; pub mod ui; -/// `event_process` is false because -/// injecting events does not play well -/// with asyncrony #[derive(NetworkBehaviour)] #[behaviour( - out_event = "SwarmResult", + out_event = "SwarmResult", poll_method = "poll", event_process = true )] -pub struct NetworkDef< - T: std::fmt::Debug - + Send - + Sync - + Clone - + Serialize - + DeserializeOwned - + 'static - + From, -> { +pub struct NetworkDef { /// purpose: broadcasting messages to many peers /// NOTE gossipsub works ONLY for sharing messsages right now /// in the future it may be able to do peer discovery and routing @@ -103,25 +90,16 @@ pub struct NetworkDef< #[behaviour(ignore)] pub known_peers: HashSet, #[behaviour(ignore)] - pub ui_events: Vec>, + pub ui_events: Vec, } -impl< - T: std::fmt::Debug - + Send - + Sync - + Clone - + Serialize - + DeserializeOwned - + 'static - + From, - > NetworkDef +impl NetworkDef { fn poll( &mut self, _cx: &mut Context<'_>, _: &mut impl PollParameters, - ) -> Poll, ::ProtocolsHandler>> + ) -> Poll::ProtocolsHandler>> { if !self.ui_events.is_empty() { return Poll::Ready(NetworkBehaviourAction::GenerateEvent( @@ -133,36 +111,18 @@ impl< } } -impl< - T: std::fmt::Debug - + Send - + Sync - + Clone - + Serialize - + DeserializeOwned - + 'static - + From, - > NetworkBehaviourEventProcess for NetworkDef +impl NetworkBehaviourEventProcess for NetworkDef { fn inject_event(&mut self, event: GossipsubEvent) { error!(?event, "gossipsub msg recv-ed"); if let GossipsubEvent::Message { message, .. } = event { error!("correct message form"); - self.ui_events.push(SwarmResult::GossipMsg(message.into())); + self.ui_events.push(SwarmResult::GossipMsg(message.data)); } } } -impl< - T: std::fmt::Debug - + Send - + Sync - + Clone - + Serialize - + DeserializeOwned - + 'static - + From, - > NetworkBehaviourEventProcess for NetworkDef +impl NetworkBehaviourEventProcess for NetworkDef { fn inject_event(&mut self, event: KademliaEvent) { error!(?event, "kadem msg recv-ed"); @@ -209,18 +169,7 @@ impl< } } -// as NetworkBehaviourEventProcess>>> - -impl< - T: std::fmt::Debug - + Send - + Sync - + Clone - + Serialize - + DeserializeOwned - + 'static - + From, - > NetworkBehaviourEventProcess for NetworkDef +impl NetworkBehaviourEventProcess for NetworkDef { fn inject_event(&mut self, event: IdentifyEvent) { if let IdentifyEvent::Received { peer_id, info, .. } = event { @@ -234,19 +183,7 @@ impl< } } -// impl NetworkBehaviourEventProcess>> for NetworkDef { -impl - NetworkBehaviourEventProcess> - for NetworkDef -where - T: std::fmt::Debug - + Send - + Sync - + Clone - + Serialize - + DeserializeOwned - + 'static - + From, +impl NetworkBehaviourEventProcess> for NetworkDef { fn inject_event( &mut self, @@ -255,59 +192,45 @@ where if let RequestResponseEvent::Message { message: RequestResponseMessage::Request { - request: DirectMessageRequest(m), + request: DirectMessageRequest(msg), .. }, .. } = event { - let bincode_options = bincode::DefaultOptions::new().with_limit(16_384); - match bincode_options.deserialize(&m) { - Ok(msg) => { - self.ui_events.push(SwarmResult::DirectMessage(msg)); - } - Err(_) => todo!(), - } + self.ui_events.push(SwarmResult::DirectMessage(msg)); } } } -pub struct Network< - T: Send - + Sync - + Clone - + 'static - + std::fmt::Debug - + Serialize - + DeserializeOwned - + From, -> { +pub struct Network { pub identity: Keypair, pub peer_id: PeerId, pub broadcast_topic: Topic, - pub swarm: Swarm>, + pub swarm: Swarm, pub max_num_peers: usize, pub min_num_peers: usize, } /// holds requests to the swarm -pub enum SwarmAction { +// TODO refactor so order matches for DirectMessage and GossipMsg +pub enum SwarmAction { Shutdown, - GossipMsg(N, Sender>), // topic, message + GossipMsg(Topic, Vec, Sender>), // topic, message GetId(Sender), Subscribe(String), Unsubscribe(String), - DirectMessage(PeerId, N), + DirectMessage(PeerId, Vec), } /// holds events of the swarm to be relayed to the cli event loop /// out #[derive(Debug)] -pub enum SwarmResult { +pub enum SwarmResult { UpdateConnectedPeers(HashSet), UpdateKnownPeers(HashSet), - GossipMsg(N), - DirectMessage(N), + GossipMsg(Vec), + DirectMessage(Vec), } /// trait to get out the topic and contents of a message @@ -323,18 +246,7 @@ pub fn gen_multiaddr(port: u16) -> Multiaddr { build_multiaddr!(Ip4([0, 0, 0, 0]), Tcp(port)) } -impl Network -where - M: std::fmt::Debug - + Send - + Sync - + Clone - + 'static - + Serialize - + DeserializeOwned - + GossipMsg - + From, -{ +impl Network { /// starts the swarm listening on `listen_addr` /// and optionally dials into peer `known_peer` #[instrument(skip(self))] @@ -377,7 +289,7 @@ where trace!("Launched network transport"); let broadcast_topic = Topic::new("broadcast"); // Generate the swarm - let swarm: Swarm> = { + let swarm: Swarm = { // Use the hash of the message's contents as the ID // Use blake3 for much paranoia at very high speeds let message_id_fn = |message: &GossipsubMessage| { @@ -513,7 +425,7 @@ where async fn handle_ui_events( &mut self, - msg: Result, flume::RecvError>, + msg: Result, ) -> Result { match msg { Ok(msg) => { @@ -524,15 +436,12 @@ where warn!("Libp2p listener shutting down"); return Ok(true); } - SwarmAction::GossipMsg(msg, chan) => { - error!("broadcasting message {:?}", msg); - let topic = ::topic(&msg); - let contents = ::data(&msg); + SwarmAction::GossipMsg(topic, contents, chan) => { let res = self .swarm .behaviour_mut() .gossipsub - .publish(topic.clone(), contents.clone()) + .publish(topic, contents.clone()) .map(|_| ()) .context(PublishSnafu); error!("publishing reuslt! {:?}", res); @@ -592,13 +501,13 @@ where &mut self, bootstrapped: &mut bool, event: SwarmEvent< - SwarmResult, + SwarmResult, EitherError< EitherError, Error>, ProtocolsHandlerUpgrErr, >, >, - send_to_ui: &Sender>, + send_to_ui: &Sender, ) -> Result<(), NetworkError> { // Make the match cleaner #[allow(clippy::enum_glob_use)] @@ -694,9 +603,9 @@ where #[instrument(skip(self))] pub async fn spawn_listeners( mut self, - ) -> Result<(Sender>, Receiver>), NetworkError> { - let (s_input, s_output) = unbounded::>(); - let (r_input, r_output) = unbounded::>(); + ) -> Result<(Sender, Receiver), NetworkError> { + let (s_input, s_output) = unbounded::(); + let (r_input, r_output) = unbounded::(); let mut bootstrapped = false; spawn( diff --git a/libp2p-networking/src/message.rs b/libp2p-networking/src/message.rs index ae882dde74..ab91e90644 100644 --- a/libp2p-networking/src/message.rs +++ b/libp2p-networking/src/message.rs @@ -50,7 +50,7 @@ pub struct DirectMessageProtocol(); pub struct DirectMessageCodec(); #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] pub struct DirectMessageRequest(pub Vec); -#[derive(Debug, Clone, PartialEq, Eq)] +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] pub struct DirectMessageResponse(pub Vec); impl ProtocolName for DirectMessageProtocol { diff --git a/libp2p-networking/src/ui.rs b/libp2p-networking/src/ui.rs index a0b8589e48..f1ad250e93 100644 --- a/libp2p-networking/src/ui.rs +++ b/libp2p-networking/src/ui.rs @@ -1,5 +1,6 @@ use async_std::task::{sleep, spawn}; +use bincode::Options; use color_eyre::{ eyre::{Result, WrapErr}, Report, @@ -7,7 +8,7 @@ use color_eyre::{ use crossterm::event::{self, Event, KeyCode}; use flume::{Receiver, Sender}; use futures::{select, FutureExt, StreamExt}; -use libp2p::PeerId; +use libp2p::{PeerId, gossipsub::Topic}; use parking_lot::Mutex; use std::{ @@ -35,8 +36,8 @@ pub enum InputMode { #[derive(Debug)] /// Struct for the TUI app pub struct TableApp { - pub send_swarm: Sender>, - pub recv_swarm: Receiver>, + pub send_swarm: Sender, + pub recv_swarm: Receiver, pub input_mode: InputMode, pub input: String, pub state: TableState, @@ -48,8 +49,8 @@ pub struct TableApp { impl TableApp { pub fn new( message_buffer: Arc>>, - send_swarm: Sender>, - recv_swarm: Receiver>, + send_swarm: Sender, + recv_swarm: Receiver, ) -> Self { Self { send_swarm, @@ -99,7 +100,11 @@ pub async fn run_app(terminal: &mut Terminal, mut app: TableApp) swarm_msg = app.recv_swarm.recv_async() => { if let Ok(res) = swarm_msg { match res { - SwarmResult::DirectMessage(m) | SwarmResult::GossipMsg(m) => app.message_buffer.lock().push_back(m), + SwarmResult::DirectMessage(m) | SwarmResult::GossipMsg(m) => { + let bincode_options = bincode::DefaultOptions::new().with_limit(16_384); + let msg : Message = bincode_options.deserialize(&m)?; + app.message_buffer.lock().push_back(msg); + }, SwarmResult::UpdateConnectedPeers(peer_set) => { *app.connected_peer_list.lock() = peer_set.clone(); } @@ -143,7 +148,9 @@ pub async fn run_app(terminal: &mut Terminal, mut app: TableApp) content: app.input, sender: r.recv_async().await?.to_string(), }; - send_swarm.send_async(SwarmAction::DirectMessage(selected_peer, msg.clone())).await?; + let bincode_options = bincode::DefaultOptions::new().with_limit(16_384); + let s_msg = bincode_options.serialize(&msg)?; + send_swarm.send_async(SwarmAction::DirectMessage(selected_peer, s_msg)).await?; mb_handle.lock().push_back(msg); // if it's a duplicate message (error case), fail silently and do nothing Result::<(), Report>::Ok(()) @@ -165,7 +172,9 @@ pub async fn run_app(terminal: &mut Terminal, mut app: TableApp) sender: r.recv_async().await?.to_string(), }; let (s, r) = flume::bounded(1); - send_swarm.send_async(SwarmAction::GossipMsg(msg.clone(), s)).await?; + let bincode_options = bincode::DefaultOptions::new().with_limit(16_384); + let s_msg = bincode_options.serialize(&msg)?; + send_swarm.send_async(SwarmAction::GossipMsg(Topic::new(msg.topic.clone()), s_msg, s)).await?; // if it's a duplicate message (error case), fail silently and do nothing if r.recv_async().await?.is_ok() { mb_handle.lock().push_back(msg); From 84e886720e3bbbf154f0aa890d0060e0bdf392d8 Mon Sep 17 00:00:00 2001 From: Justin Restivo Date: Wed, 26 Jan 2022 10:39:25 -0500 Subject: [PATCH 035/107] Cleanup --- libp2p-networking/src/lib.rs | 95 ++++++++++++++++++++------------ libp2p-networking/src/message.rs | 11 ---- 2 files changed, 59 insertions(+), 47 deletions(-) diff --git a/libp2p-networking/src/lib.rs b/libp2p-networking/src/lib.rs index 459a760a10..60f3acb9cb 100644 --- a/libp2p-networking/src/lib.rs +++ b/libp2p-networking/src/lib.rs @@ -17,7 +17,6 @@ pub mod tracing_setup; use async_std::task::{sleep, spawn}; -use bincode::{ErrorKind, Options}; use message::{DirectMessageCodec, DirectMessageRequest, DirectMessageResponse}; use rand::{seq::IteratorRandom, thread_rng}; use std::{ @@ -32,7 +31,7 @@ use flume::{unbounded, Receiver, Sender}; use futures::{select, FutureExt, StreamExt}; use libp2p::{ build_multiaddr, - core::{either::EitherError, muxing::StreamMuxerBox, transport::Boxed, ConnectedPoint}, + core::{either::EitherError, muxing::StreamMuxerBox, transport::{Boxed}, ConnectedPoint, upgrade}, gossipsub::{ error::{GossipsubHandlerError, PublishError}, Gossipsub, GossipsubConfigBuilder, GossipsubEvent, GossipsubMessage, IdentTopic as Topic, @@ -52,7 +51,7 @@ use libp2p::{ NetworkBehaviour, NetworkBehaviourAction, NetworkBehaviourEventProcess, PollParameters, ProtocolsHandlerUpgrErr, SwarmEvent, }, - Multiaddr, NetworkBehaviour, PeerId, Swarm, TransportError, + Multiaddr, NetworkBehaviour, PeerId, Swarm, TransportError, tcp, dns, websocket, noise, Transport, yamux, mplex, }; use snafu::{ResultExt, Snafu}; use tracing::{debug, error, info, info_span, instrument, trace, warn, Instrument}; @@ -212,11 +211,9 @@ pub struct Network { pub min_num_peers: usize, } -/// holds requests to the swarm -// TODO refactor so order matches for DirectMessage and GossipMsg pub enum SwarmAction { Shutdown, - GossipMsg(Topic, Vec, Sender>), // topic, message + GossipMsg(Topic, Vec, Sender>), GetId(Sender), Subscribe(String), Unsubscribe(String), @@ -224,7 +221,6 @@ pub enum SwarmAction { } /// holds events of the swarm to be relayed to the cli event loop -/// out #[derive(Debug)] pub enum SwarmResult { UpdateConnectedPeers(HashSet), @@ -233,19 +229,45 @@ pub enum SwarmResult { DirectMessage(Vec), } -/// trait to get out the topic and contents of a message -/// such that it may be "gossipped" to other people -pub trait GossipMsg: Send { - fn topic(&self) -> Topic; - fn data(&self) -> Vec; -} - /// bind all interfaces on port `port` /// TODO something more general pub fn gen_multiaddr(port: u16) -> Multiaddr { build_multiaddr!(Ip4([0, 0, 0, 0]), Tcp(port)) } +/// generate authenticated transport, copied from `development_transport` +/// for definition of XX +/// # Errors +/// could not sign the noise key with `identity` +pub async fn gen_transport(identity: Keypair) -> std::io::Result> { + let transport = { + let tcp = tcp::TcpConfig::new().nodelay(true); + let dns_tcp = dns::DnsConfig::system(tcp).await?; + let ws_dns_tcp = websocket::WsConfig::new(dns_tcp.clone()); + dns_tcp.or_transport(ws_dns_tcp) + }; + + // keys for signing messages + let noise_keys = noise::Keypair::::new() + .into_authentic(&identity) + .expect("Signing libp2p-noise static DH keypair failed."); + + Ok(transport + .upgrade(upgrade::Version::V1) + // authentication: messages are signed + .authenticate(noise::NoiseConfig::xx(noise_keys).into_authenticated()) + // muxxing streams + // useful because only one connection opened + // https://docs.libp2p.io/concepts/stream-multiplexing/ + .multiplex(upgrade::SelectUpgrade::new( + yamux::YamuxConfig::default(), + mplex::MplexConfig::default(), + )) + .timeout(std::time::Duration::from_secs(20)) + .boxed()) + +} + impl Network { /// starts the swarm listening on `listen_addr` /// and optionally dials into peer `known_peer` @@ -346,7 +368,6 @@ impl Network { connecting_peers: HashSet::new(), known_peers: HashSet::new(), ui_events: Vec::new(), - // TODO implement the rest of this bootstrap: false, }; @@ -363,9 +384,11 @@ impl Network { }) } + /// peer discovery mechanism + /// looks up a random peer #[inline] - fn handle_peer_discovery(&mut self, bootstrapped: bool) { - if !bootstrapped { + fn handle_peer_discovery(&mut self) { + if !self.swarm.behaviour().bootstrap { let random_peer = PeerId::random(); self.swarm .behaviour_mut() @@ -374,12 +397,14 @@ impl Network { } } + /// Keep the number of open connections between threshold specified by + /// the swarm #[inline] - fn handle_num_connections(&mut self, bootstrapped: bool) { + fn handle_num_connections(&mut self) { let swarm = self.swarm.behaviour(); // if we're bootstrapped, do nothing // otherwise periodically get more peers if needed - if !bootstrapped { + if !swarm.bootstrap { if swarm.connecting_peers.len() + swarm.connected_peers.len() <= self.min_num_peers { // Calcuate the currently connected peers let used_peers = swarm @@ -423,6 +448,14 @@ impl Network { } } + // event handler for UI. + // currectly supported actions include + // - shutting down the swarm + // - gossipping a message to known peers on the `global` topic + // - returning the id of the current peer + // - subscribing to a topic + // - unsubscribing from a toipc + // - direct messaging a peer async fn handle_ui_events( &mut self, msg: Result, @@ -480,12 +513,9 @@ impl Network { } } DirectMessage(pid, msg) => { - let bincode_options = bincode::DefaultOptions::new().with_limit(16_384); self.swarm.behaviour_mut().request_response.send_request( &pid, - DirectMessageRequest( - bincode_options.serialize(&msg).context(BincodeSnafu)?, - ), + DirectMessageRequest(msg), ); } } @@ -497,9 +527,9 @@ impl Network { Ok(false) } + /// event handler for events emited from the swarm async fn handle_swarm_events( &mut self, - bootstrapped: &mut bool, event: SwarmEvent< SwarmResult, EitherError< @@ -514,9 +544,8 @@ impl Network { use SwarmEvent::*; // TODO re enable this - // warn!("libp2p event {:?}", event); + info!("libp2p event {:?}", event); match event { - // TODO handle swarm action by sending to swarm ConnectionEstablished { peer_id, endpoint, .. } => { @@ -540,7 +569,7 @@ impl Network { self.swarm.behaviour_mut().connected_peers.insert(peer_id); self.swarm.behaviour_mut().connecting_peers.remove(&peer_id); // now we have at least one peer so we can bootstrap - if !*bootstrapped { + if !self.swarm.behaviour().bootstrap { self.swarm .behaviour_mut() .kadem @@ -593,7 +622,6 @@ impl Network { /// Spawn a task to listen for requests on the returned channel /// as well as any events produced by libp2p /// `mut_mut` is disabled b/c must consume `self` - /// TODO why does clippy not like `panic` with select? #[allow( clippy::mut_mut, clippy::panic, @@ -606,24 +634,21 @@ impl Network { ) -> Result<(Sender, Receiver), NetworkError> { let (s_input, s_output) = unbounded::(); let (r_input, r_output) = unbounded::(); - let mut bootstrapped = false; spawn( async move { loop { - // NOTE(nm): rustformat doesn't really work inside of macros, I would like to - // refactor these all out to local methods for formatability select! { _ = sleep(Duration::from_secs(30)).fuse() => { - self.handle_peer_discovery(bootstrapped); + self.handle_peer_discovery(); }, _ = sleep(Duration::from_secs(1)).fuse() => { - self.handle_num_connections(bootstrapped); + self.handle_num_connections(); } event = self.swarm.next() => { if let Some(event) = event { error!("handling event {:?}", event); - self.handle_swarm_events(&mut bootstrapped, event, &r_input).await?; + self.handle_swarm_events(event, &r_input).await?; } }, msg = s_output.recv_async() => { @@ -675,6 +700,4 @@ pub enum NetworkError { PublishError { source: PublishError }, /// Error when there are no known peers to bootstrap off NoKnownPeers, - /// Error encoding message - BincodeError { source: Box }, } diff --git a/libp2p-networking/src/message.rs b/libp2p-networking/src/message.rs index ab91e90644..d2054a60af 100644 --- a/libp2p-networking/src/message.rs +++ b/libp2p-networking/src/message.rs @@ -12,8 +12,6 @@ use libp2p::{ }; use serde::{Deserialize, Serialize}; -use crate::GossipMsg; - #[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq)] pub struct Message { pub sender: String, @@ -21,15 +19,6 @@ pub struct Message { pub topic: String, } -impl GossipMsg for Message { - fn topic(&self) -> libp2p::gossipsub::IdentTopic { - libp2p::gossipsub::IdentTopic::new(self.topic.clone()) - } - fn data(&self) -> Vec { - self.content.as_bytes().into() - } -} - impl From for Message { fn from(msg: GossipsubMessage) -> Self { let content = String::from_utf8_lossy(&msg.data).to_string(); From ea5c8964f9c06fbab69b452e048cfb8b94bca84b Mon Sep 17 00:00:00 2001 From: Justin Restivo Date: Wed, 26 Jan 2022 10:56:11 -0500 Subject: [PATCH 036/107] Cleanup --- libp2p-networking/src/bin/clichat.rs | 3 +- libp2p-networking/src/lib.rs | 44 +++++++++++++--------------- libp2p-networking/src/ui.rs | 10 ++++--- 3 files changed, 28 insertions(+), 29 deletions(-) diff --git a/libp2p-networking/src/bin/clichat.rs b/libp2p-networking/src/bin/clichat.rs index 9a3847d268..4b1019497d 100644 --- a/libp2p-networking/src/bin/clichat.rs +++ b/libp2p-networking/src/bin/clichat.rs @@ -37,8 +37,7 @@ async fn main() -> Result<()> { color_eyre::install()?; networking_demo::tracing_setup::setup_tracing(); // -- Spin up the network connection - let mut networking: Network = - Network::new().await.context("Failed to launch network")?; + let mut networking: Network = Network::new().await.context("Failed to launch network")?; let port = CliOpt::from_args().port.unwrap_or(0u16); let known_peer = CliOpt::from_args().first_dial; let listen_addr = gen_multiaddr(port); diff --git a/libp2p-networking/src/lib.rs b/libp2p-networking/src/lib.rs index 60f3acb9cb..641af54b47 100644 --- a/libp2p-networking/src/lib.rs +++ b/libp2p-networking/src/lib.rs @@ -31,7 +31,10 @@ use flume::{unbounded, Receiver, Sender}; use futures::{select, FutureExt, StreamExt}; use libp2p::{ build_multiaddr, - core::{either::EitherError, muxing::StreamMuxerBox, transport::{Boxed}, ConnectedPoint, upgrade}, + core::{ + either::EitherError, muxing::StreamMuxerBox, transport::Boxed, upgrade, ConnectedPoint, + }, + dns, gossipsub::{ error::{GossipsubHandlerError, PublishError}, Gossipsub, GossipsubConfigBuilder, GossipsubEvent, GossipsubMessage, IdentTopic as Topic, @@ -43,6 +46,7 @@ use libp2p::{ self, store::MemoryStore, GetClosestPeersOk, Kademlia, KademliaConfig, KademliaEvent, QueryResult, }, + mplex, noise, request_response::{ ProtocolSupport, RequestResponse, RequestResponseConfig, RequestResponseEvent, RequestResponseMessage, @@ -51,7 +55,7 @@ use libp2p::{ NetworkBehaviour, NetworkBehaviourAction, NetworkBehaviourEventProcess, PollParameters, ProtocolsHandlerUpgrErr, SwarmEvent, }, - Multiaddr, NetworkBehaviour, PeerId, Swarm, TransportError, tcp, dns, websocket, noise, Transport, yamux, mplex, + tcp, websocket, yamux, Multiaddr, NetworkBehaviour, PeerId, Swarm, Transport, TransportError, }; use snafu::{ResultExt, Snafu}; use tracing::{debug, error, info, info_span, instrument, trace, warn, Instrument}; @@ -62,11 +66,7 @@ pub mod message; pub mod ui; #[derive(NetworkBehaviour)] -#[behaviour( - out_event = "SwarmResult", - poll_method = "poll", - event_process = true -)] +#[behaviour(out_event = "SwarmResult", poll_method = "poll", event_process = true)] pub struct NetworkDef { /// purpose: broadcasting messages to many peers /// NOTE gossipsub works ONLY for sharing messsages right now @@ -92,14 +92,15 @@ pub struct NetworkDef { pub ui_events: Vec, } -impl NetworkDef -{ +impl NetworkDef { fn poll( &mut self, _cx: &mut Context<'_>, _: &mut impl PollParameters, ) -> Poll::ProtocolsHandler>> { + // push events that must be relayed back to UI onto queue + // to be consumed by UI event handler if !self.ui_events.is_empty() { return Poll::Ready(NetworkBehaviourAction::GenerateEvent( self.ui_events.remove(0), @@ -110,8 +111,7 @@ impl NetworkDef } } -impl NetworkBehaviourEventProcess for NetworkDef -{ +impl NetworkBehaviourEventProcess for NetworkDef { fn inject_event(&mut self, event: GossipsubEvent) { error!(?event, "gossipsub msg recv-ed"); if let GossipsubEvent::Message { message, .. } = event { @@ -121,8 +121,7 @@ impl NetworkBehaviourEventProcess for NetworkDef } } -impl NetworkBehaviourEventProcess for NetworkDef -{ +impl NetworkBehaviourEventProcess for NetworkDef { fn inject_event(&mut self, event: KademliaEvent) { error!(?event, "kadem msg recv-ed"); match event { @@ -168,8 +167,7 @@ impl NetworkBehaviourEventProcess for NetworkDef } } -impl NetworkBehaviourEventProcess for NetworkDef -{ +impl NetworkBehaviourEventProcess for NetworkDef { fn inject_event(&mut self, event: IdentifyEvent) { if let IdentifyEvent::Received { peer_id, info, .. } = event { for addr in info.listen_addrs { @@ -182,7 +180,8 @@ impl NetworkBehaviourEventProcess for NetworkDef } } -impl NetworkBehaviourEventProcess> for NetworkDef +impl NetworkBehaviourEventProcess> + for NetworkDef { fn inject_event( &mut self, @@ -265,7 +264,6 @@ pub async fn gen_transport(identity: Keypair) -> std::io::Result { #[allow(clippy::enum_glob_use)] - use SwarmAction::{DirectMessage, GetId, Shutdown, Subscribe, Unsubscribe}; + use SwarmAction::*; match msg { Shutdown => { warn!("Libp2p listener shutting down"); @@ -479,6 +477,7 @@ impl Network { .context(PublishSnafu); error!("publishing reuslt! {:?}", res); + // send result back to ui to confirm this isn't a duplicate message chan.send_async(res) .await .map_err(|_e| NetworkError::StreamClosed)?; @@ -513,10 +512,10 @@ impl Network { } } DirectMessage(pid, msg) => { - self.swarm.behaviour_mut().request_response.send_request( - &pid, - DirectMessageRequest(msg), - ); + self.swarm + .behaviour_mut() + .request_response + .send_request(&pid, DirectMessageRequest(msg)); } } } @@ -543,7 +542,6 @@ impl Network { #[allow(clippy::enum_glob_use)] use SwarmEvent::*; - // TODO re enable this info!("libp2p event {:?}", event); match event { ConnectionEstablished { diff --git a/libp2p-networking/src/ui.rs b/libp2p-networking/src/ui.rs index f1ad250e93..94b17177b4 100644 --- a/libp2p-networking/src/ui.rs +++ b/libp2p-networking/src/ui.rs @@ -8,7 +8,7 @@ use color_eyre::{ use crossterm::event::{self, Event, KeyCode}; use flume::{Receiver, Sender}; use futures::{select, FutureExt, StreamExt}; -use libp2p::{PeerId, gossipsub::Topic}; +use libp2p::{gossipsub::Topic, PeerId}; use parking_lot::Mutex; use std::{ @@ -88,6 +88,8 @@ impl TableApp { #[allow(clippy::mut_mut, clippy::panic)] #[instrument(skip(terminal, app))] pub async fn run_app(terminal: &mut Terminal, mut app: TableApp) -> Result<()> { + #[allow(clippy::enum_glob_use)] + use SwarmResult::*; let mut events = event::EventStream::new(); loop { terminal @@ -100,15 +102,15 @@ pub async fn run_app(terminal: &mut Terminal, mut app: TableApp) swarm_msg = app.recv_swarm.recv_async() => { if let Ok(res) = swarm_msg { match res { - SwarmResult::DirectMessage(m) | SwarmResult::GossipMsg(m) => { + DirectMessage(m) | SwarmResult::GossipMsg(m) => { let bincode_options = bincode::DefaultOptions::new().with_limit(16_384); let msg : Message = bincode_options.deserialize(&m)?; app.message_buffer.lock().push_back(msg); }, - SwarmResult::UpdateConnectedPeers(peer_set) => { + UpdateConnectedPeers(peer_set) => { *app.connected_peer_list.lock() = peer_set.clone(); } - SwarmResult::UpdateKnownPeers(peer_set) => { + UpdateKnownPeers(peer_set) => { *app.known_peer_list.lock() = peer_set.clone(); } } From 6877833bbba0fe138c4515244fd89bee7193a152 Mon Sep 17 00:00:00 2001 From: Justin Restivo Date: Wed, 26 Jan 2022 11:06:46 -0500 Subject: [PATCH 037/107] Move direct message to separate file --- libp2p-networking/src/direct_message.rs | 88 +++++++++++++++++++ libp2p-networking/src/lib.rs | 5 +- libp2p-networking/src/message.rs | 111 +----------------------- 3 files changed, 95 insertions(+), 109 deletions(-) create mode 100644 libp2p-networking/src/direct_message.rs diff --git a/libp2p-networking/src/direct_message.rs b/libp2p-networking/src/direct_message.rs new file mode 100644 index 0000000000..cf0e85af82 --- /dev/null +++ b/libp2p-networking/src/direct_message.rs @@ -0,0 +1,88 @@ +use async_std::io; +use async_trait::async_trait; +use futures::{AsyncRead, AsyncWrite, AsyncWriteExt}; +use libp2p::{request_response::RequestResponseCodec, core::{ProtocolName, upgrade::{read_length_prefixed, write_length_prefixed}}}; +use serde::{Serialize, Deserialize}; + +#[derive(Debug, Clone)] +pub struct DirectMessageProtocol(); +#[derive(Clone, Debug, Serialize, Deserialize)] +pub struct DirectMessageCodec(); +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +pub struct DirectMessageRequest(pub Vec); +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +pub struct DirectMessageResponse(pub Vec); + +impl ProtocolName for DirectMessageProtocol { + fn protocol_name(&self) -> &[u8] { + "/spectrum_send_msg/1".as_bytes() + } +} + +#[async_trait] +impl RequestResponseCodec for DirectMessageCodec { + type Protocol = DirectMessageProtocol; + + type Request = DirectMessageRequest; + + type Response = DirectMessageResponse; + + async fn read_request( + &mut self, + _: &DirectMessageProtocol, + io: &mut T, + ) -> io::Result + where + T: AsyncRead + Unpin + Send, + { + // FIXME magic numbers... + // it looks like the easiest thing to do + // is to set an upper limit threshold and use that + let msg = read_length_prefixed(io, 1_000_000).await?; + + // NOTE we don't error here. We'll wrap this in a behaviour and get better error messages + // there + Ok(DirectMessageRequest(msg)) + } + + async fn read_response( + &mut self, + _: &DirectMessageProtocol, + io: &mut T, + ) -> io::Result + where + T: AsyncRead + Unpin + Send, + { + let msg = read_length_prefixed(io, 1_000_000).await?; + Ok(DirectMessageResponse(msg)) + } + + async fn write_request( + &mut self, + _: &DirectMessageProtocol, + io: &mut T, + DirectMessageRequest(msg): DirectMessageRequest, + ) -> io::Result<()> + where + T: AsyncWrite + Unpin + Send, + { + write_length_prefixed(io, msg).await?; + io.close().await?; + + Ok(()) + } + + async fn write_response( + &mut self, + _: &DirectMessageProtocol, + io: &mut T, + DirectMessageResponse(msg): DirectMessageResponse, + ) -> io::Result<()> + where + T: AsyncWrite + Unpin + Send, + { + write_length_prefixed(io, msg).await?; + io.close().await?; + Ok(()) + } +} diff --git a/libp2p-networking/src/lib.rs b/libp2p-networking/src/lib.rs index 641af54b47..2c56d3c1b0 100644 --- a/libp2p-networking/src/lib.rs +++ b/libp2p-networking/src/lib.rs @@ -15,9 +15,10 @@ )] pub mod tracing_setup; +pub mod direct_message; use async_std::task::{sleep, spawn}; -use message::{DirectMessageCodec, DirectMessageRequest, DirectMessageResponse}; +use direct_message::{DirectMessageCodec, DirectMessageRequest, DirectMessageResponse}; use rand::{seq::IteratorRandom, thread_rng}; use std::{ collections::HashSet, @@ -60,7 +61,7 @@ use libp2p::{ use snafu::{ResultExt, Snafu}; use tracing::{debug, error, info, info_span, instrument, trace, warn, Instrument}; -use crate::message::DirectMessageProtocol; +use crate::direct_message::DirectMessageProtocol; pub mod message; pub mod ui; diff --git a/libp2p-networking/src/message.rs b/libp2p-networking/src/message.rs index d2054a60af..0f2edca878 100644 --- a/libp2p-networking/src/message.rs +++ b/libp2p-networking/src/message.rs @@ -1,15 +1,8 @@ -use async_std::io; -use async_trait::async_trait; -use futures::{AsyncRead, AsyncWrite, AsyncWriteExt}; -use libp2p::{ - core::{ - upgrade::{read_length_prefixed, write_length_prefixed}, - ProtocolName, - }, - gossipsub::GossipsubMessage, - request_response::RequestResponseCodec, -}; + + + + use serde::{Deserialize, Serialize}; #[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq)] @@ -19,99 +12,3 @@ pub struct Message { pub topic: String, } -impl From for Message { - fn from(msg: GossipsubMessage) -> Self { - let content = String::from_utf8_lossy(&msg.data).to_string(); - let sender = msg - .source - .map_or_else(|| "UNKNOWN".to_string(), |p| p.to_string()); - Message { - sender, - content, - topic: msg.topic.into_string(), - } - } -} - -#[derive(Debug, Clone)] -pub struct DirectMessageProtocol(); -#[derive(Clone, Debug, Serialize, Deserialize)] -pub struct DirectMessageCodec(); -#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] -pub struct DirectMessageRequest(pub Vec); -#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] -pub struct DirectMessageResponse(pub Vec); - -impl ProtocolName for DirectMessageProtocol { - fn protocol_name(&self) -> &[u8] { - "/spectrum_send_msg/1".as_bytes() - } -} - -#[async_trait] -impl RequestResponseCodec for DirectMessageCodec { - type Protocol = DirectMessageProtocol; - - type Request = DirectMessageRequest; - - type Response = DirectMessageResponse; - - async fn read_request( - &mut self, - _: &DirectMessageProtocol, - io: &mut T, - ) -> io::Result - where - T: AsyncRead + Unpin + Send, - { - // FIXME magic numbers... - // it looks like the easiest thing to do - // is to set an upper limit threshold and use that - let msg = read_length_prefixed(io, 1_000_000).await?; - - // NOTE we don't error here. We'll wrap this in a behaviour and get better error messages - // there - Ok(DirectMessageRequest(msg)) - } - - async fn read_response( - &mut self, - _: &DirectMessageProtocol, - io: &mut T, - ) -> io::Result - where - T: AsyncRead + Unpin + Send, - { - let msg = read_length_prefixed(io, 1_000_000).await?; - Ok(DirectMessageResponse(msg)) - } - - async fn write_request( - &mut self, - _: &DirectMessageProtocol, - io: &mut T, - DirectMessageRequest(msg): DirectMessageRequest, - ) -> io::Result<()> - where - T: AsyncWrite + Unpin + Send, - { - write_length_prefixed(io, msg).await?; - io.close().await?; - - Ok(()) - } - - async fn write_response( - &mut self, - _: &DirectMessageProtocol, - io: &mut T, - DirectMessageResponse(msg): DirectMessageResponse, - ) -> io::Result<()> - where - T: AsyncWrite + Unpin + Send, - { - write_length_prefixed(io, msg).await?; - io.close().await?; - Ok(()) - } -} From 9b3c47d850d80464973db8918794e040cd52cfea Mon Sep 17 00:00:00 2001 From: Justin Restivo Date: Wed, 26 Jan 2022 11:18:40 -0500 Subject: [PATCH 038/107] Refactor structure for counter example and tests --- .../{src/bin => examples}/clichat.rs | 0 libp2p-networking/examples/counter.rs | 36 +++++++++++++++++++ libp2p-networking/src/direct_message.rs | 23 +++++++----- libp2p-networking/src/lib.rs | 3 +- libp2p-networking/src/message.rs | 6 ---- libp2p-networking/tests/counter.rs | 7 ++++ 6 files changed, 58 insertions(+), 17 deletions(-) rename libp2p-networking/{src/bin => examples}/clichat.rs (100%) create mode 100644 libp2p-networking/examples/counter.rs create mode 100644 libp2p-networking/tests/counter.rs diff --git a/libp2p-networking/src/bin/clichat.rs b/libp2p-networking/examples/clichat.rs similarity index 100% rename from libp2p-networking/src/bin/clichat.rs rename to libp2p-networking/examples/clichat.rs diff --git a/libp2p-networking/examples/counter.rs b/libp2p-networking/examples/counter.rs new file mode 100644 index 0000000000..ba797db790 --- /dev/null +++ b/libp2p-networking/examples/counter.rs @@ -0,0 +1,36 @@ +use libp2p::Multiaddr; + +use structopt::StructOpt; + +use color_eyre::eyre::{Result, WrapErr}; + +use tracing::instrument; + +use networking_demo::{gen_multiaddr, Network}; + +/// command line arguments +#[derive(StructOpt)] +struct CliOpt { + /// Path to the node configuration file + #[structopt(long = "port", short = "p")] + port: Option, + + #[structopt()] + first_dial: Option, +} + +#[async_std::main] +#[instrument] +async fn main() -> Result<()> { + // -- Setup color_eyre and tracing + color_eyre::install()?; + networking_demo::tracing_setup::setup_tracing(); + // -- Spin up the network connection + let mut networking: Network = Network::new().await.context("Failed to launch network")?; + let port = CliOpt::from_args().port.unwrap_or(0u16); + let known_peer = CliOpt::from_args().first_dial; + let listen_addr = gen_multiaddr(port); + networking.start(listen_addr, known_peer)?; + let (_send_chan, _recv_chan) = networking.spawn_listeners().await?; + todo!() +} diff --git a/libp2p-networking/src/direct_message.rs b/libp2p-networking/src/direct_message.rs index cf0e85af82..19e42790d8 100644 --- a/libp2p-networking/src/direct_message.rs +++ b/libp2p-networking/src/direct_message.rs @@ -1,8 +1,14 @@ use async_std::io; use async_trait::async_trait; use futures::{AsyncRead, AsyncWrite, AsyncWriteExt}; -use libp2p::{request_response::RequestResponseCodec, core::{ProtocolName, upgrade::{read_length_prefixed, write_length_prefixed}}}; -use serde::{Serialize, Deserialize}; +use libp2p::{ + core::{ + upgrade::{read_length_prefixed, write_length_prefixed}, + ProtocolName, + }, + request_response::RequestResponseCodec, +}; +use serde::{Deserialize, Serialize}; #[derive(Debug, Clone)] pub struct DirectMessageProtocol(); @@ -19,6 +25,8 @@ impl ProtocolName for DirectMessageProtocol { } } +const MAX_MSG_SIZE: usize = 1_000_000; + #[async_trait] impl RequestResponseCodec for DirectMessageCodec { type Protocol = DirectMessageProtocol; @@ -35,13 +43,10 @@ impl RequestResponseCodec for DirectMessageCodec { where T: AsyncRead + Unpin + Send, { - // FIXME magic numbers... - // it looks like the easiest thing to do - // is to set an upper limit threshold and use that - let msg = read_length_prefixed(io, 1_000_000).await?; + let msg = read_length_prefixed(io, MAX_MSG_SIZE).await?; - // NOTE we don't error here. We'll wrap this in a behaviour and get better error messages - // there + // NOTE we don't error here unless message is too big. + // We'll wrap this in a networkbehaviour and get parsing messages there Ok(DirectMessageRequest(msg)) } @@ -53,7 +58,7 @@ impl RequestResponseCodec for DirectMessageCodec { where T: AsyncRead + Unpin + Send, { - let msg = read_length_prefixed(io, 1_000_000).await?; + let msg = read_length_prefixed(io, MAX_MSG_SIZE).await?; Ok(DirectMessageResponse(msg)) } diff --git a/libp2p-networking/src/lib.rs b/libp2p-networking/src/lib.rs index 2c56d3c1b0..a63470c989 100644 --- a/libp2p-networking/src/lib.rs +++ b/libp2p-networking/src/lib.rs @@ -14,8 +14,8 @@ clippy::unused_self )] -pub mod tracing_setup; pub mod direct_message; +pub mod tracing_setup; use async_std::task::{sleep, spawn}; use direct_message::{DirectMessageCodec, DirectMessageRequest, DirectMessageResponse}; @@ -302,7 +302,6 @@ impl Network { let identity = Keypair::generate_ed25519(); let peer_id = PeerId::from(identity.public()); debug!(?peer_id); - // TODO: Maybe not use a development only networking backend let transport: Boxed<(PeerId, StreamMuxerBox)> = libp2p::development_transport(identity.clone()) .await diff --git a/libp2p-networking/src/message.rs b/libp2p-networking/src/message.rs index 0f2edca878..7377b4f2f2 100644 --- a/libp2p-networking/src/message.rs +++ b/libp2p-networking/src/message.rs @@ -1,8 +1,3 @@ - - - - - use serde::{Deserialize, Serialize}; #[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq)] @@ -11,4 +6,3 @@ pub struct Message { pub content: String, pub topic: String, } - diff --git a/libp2p-networking/tests/counter.rs b/libp2p-networking/tests/counter.rs new file mode 100644 index 0000000000..649ce95c99 --- /dev/null +++ b/libp2p-networking/tests/counter.rs @@ -0,0 +1,7 @@ +use tracing::instrument; + +#[async_std::test] +#[instrument] +async fn test_counter() { + todo!() +} From 6813c2a81a1669e28c21e417927e2667e49b0de4 Mon Sep 17 00:00:00 2001 From: Justin Restivo Date: Thu, 27 Jan 2022 08:40:07 -0500 Subject: [PATCH 039/107] feat: testing handles --- libp2p-networking/examples/clichat.rs | 2 +- libp2p-networking/examples/counter.rs | 2 +- libp2p-networking/src/lib.rs | 35 +++++++---- libp2p-networking/tests/counter.rs | 86 ++++++++++++++++++++++++++- 4 files changed, 110 insertions(+), 15 deletions(-) diff --git a/libp2p-networking/examples/clichat.rs b/libp2p-networking/examples/clichat.rs index 4b1019497d..f229ff6feb 100644 --- a/libp2p-networking/examples/clichat.rs +++ b/libp2p-networking/examples/clichat.rs @@ -41,7 +41,7 @@ async fn main() -> Result<()> { let port = CliOpt::from_args().port.unwrap_or(0u16); let known_peer = CliOpt::from_args().first_dial; let listen_addr = gen_multiaddr(port); - networking.start(listen_addr, known_peer)?; + networking.start(listen_addr, known_peer).await?; let (send_chan, recv_chan) = networking.spawn_listeners().await?; // -- Spin up the UI diff --git a/libp2p-networking/examples/counter.rs b/libp2p-networking/examples/counter.rs index ba797db790..24acd719f1 100644 --- a/libp2p-networking/examples/counter.rs +++ b/libp2p-networking/examples/counter.rs @@ -30,7 +30,7 @@ async fn main() -> Result<()> { let port = CliOpt::from_args().port.unwrap_or(0u16); let known_peer = CliOpt::from_args().first_dial; let listen_addr = gen_multiaddr(port); - networking.start(listen_addr, known_peer)?; + networking.start(listen_addr, known_peer).await?; let (_send_chan, _recv_chan) = networking.spawn_listeners().await?; todo!() } diff --git a/libp2p-networking/src/lib.rs b/libp2p-networking/src/lib.rs index a63470c989..7879599301 100644 --- a/libp2p-networking/src/lib.rs +++ b/libp2p-networking/src/lib.rs @@ -270,13 +270,21 @@ pub async fn gen_transport(identity: Keypair) -> std::io::Result, - ) -> Result<(), NetworkError> { - self.swarm.listen_on(listen_addr).context(TransportSnafu)?; + ) -> Result { + let listen_id = self.swarm.listen_on(listen_addr).context(TransportSnafu)?; + let addr = loop { + match self.swarm.next().await { + Some(SwarmEvent::NewListenAddr { address, .. }) => break address, + _ => continue, + }; + }; + error!("listen addr: {:?}", listen_id); if let Some(known_peer) = known_peer { let dialing = known_peer.clone(); match self.swarm.dial(known_peer) { @@ -286,7 +294,7 @@ impl Network { Err(e) => error!("Dial {:?} failed: {:?}", dialing, e), }; } - Ok(()) + Ok(addr) } /// Creates a new `Network` with the given settings. @@ -330,6 +338,9 @@ impl Network { .map_err(|s| GossipsubConfigSnafu { message: s }.build())?; // - Build a gossipsub network behavior let gossipsub: Gossipsub = Gossipsub::new( + // TODO do we even need this? + // if messages are signed at the the consensus level AND the network + // level (noise), this feels redundant. MessageAuthenticity::Signed(identity.clone()), gossipsub_config, ) @@ -446,14 +457,14 @@ impl Network { } } - // event handler for UI. - // currectly supported actions include - // - shutting down the swarm - // - gossipping a message to known peers on the `global` topic - // - returning the id of the current peer - // - subscribing to a topic - // - unsubscribing from a toipc - // - direct messaging a peer + /// event handler for UI. + /// currectly supported actions include + /// - shutting down the swarm + /// - gossipping a message to known peers on the `global` topic + /// - returning the id of the current peer + /// - subscribing to a topic + /// - unsubscribing from a toipc + /// - direct messaging a peer async fn handle_ui_events( &mut self, msg: Result, diff --git a/libp2p-networking/tests/counter.rs b/libp2p-networking/tests/counter.rs index 649ce95c99..2035eaaa9b 100644 --- a/libp2p-networking/tests/counter.rs +++ b/libp2p-networking/tests/counter.rs @@ -1,7 +1,91 @@ +use flume::{Receiver, SendError, Sender}; +use libp2p::Multiaddr; +use networking_demo::{gen_multiaddr, Network, NetworkError, SwarmAction, SwarmResult}; + +use serde::{Deserialize, Serialize}; use tracing::instrument; +pub type Counter = u8; + +#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq)] +pub enum CounterMessage { + IncrementCounter { from: Counter, to: Counter }, + AskForCounter, + MyCounterIs(Counter), +} + +#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq)] +pub struct CounterState(Counter); + +#[derive(Clone, Debug)] +pub struct SwarmHandle { + counter: CounterState, + send_chan: Sender, + recv_chan: Receiver, + listen_addr: Multiaddr, +} + +impl SwarmHandle { + pub async fn new(known_addr: Option) -> Result { + let listen_addr = gen_multiaddr(0); + let mut network = Network::new().await?; + let listen_addr = network.start(listen_addr, known_addr).await?; + let (send_chan, recv_chan) = network.spawn_listeners().await?; + Ok(SwarmHandle { + counter: CounterState::default(), + send_chan, + recv_chan, + listen_addr, + }) + } + + pub async fn shutdown(&self) -> Result<(), SendError> { + self.send_chan.send_async(SwarmAction::Shutdown).await + } +} + +impl Default for CounterState { + fn default() -> Self { + Self(0) + } +} + +pub async fn spin_up_swarms(num_of_nodes: usize) -> Result, NetworkError> { + let bootstrap = SwarmHandle::new(None).await?; + let bootstrap_addr = bootstrap.listen_addr.clone(); + let mut handles = Vec::new(); + for _ in 0..(num_of_nodes - 1) { + handles.push(SwarmHandle::new(Some(bootstrap_addr.clone())).await?); + } + Ok(handles) +} + +#[async_std::test] +#[instrument] +async fn test_spinup() { + // NOTE we want this to panic if we can't spin up the swarms. + // that amounts to a failed test. + let handles = spin_up_swarms(5).await.unwrap(); + for handle in handles.iter() { + handle + .send_chan + .send_async(SwarmAction::Shutdown) + .await + .unwrap(); + } +} + #[async_std::test] #[instrument] async fn test_counter() { - todo!() + // NOTE we want this to panic if we can't spin up the swarms. + // that amounts to a failed test. + let handles = spin_up_swarms(5).await.unwrap(); + for handle in handles.iter() { + handle + .send_chan + .send_async(SwarmAction::Shutdown) + .await + .unwrap(); + } } From 326741abd1c0b8437f15377292e2366ef4ad192b Mon Sep 17 00:00:00 2001 From: Justin Restivo Date: Thu, 27 Jan 2022 11:59:28 -0500 Subject: [PATCH 040/107] feat: add event handler --- libp2p-networking/src/lib.rs | 48 ++++++--- libp2p-networking/src/ui.rs | 5 +- libp2p-networking/tests/counter.rs | 168 +++++++++++++++++++++++++---- 3 files changed, 189 insertions(+), 32 deletions(-) diff --git a/libp2p-networking/src/lib.rs b/libp2p-networking/src/lib.rs index 7879599301..28f1f573da 100644 --- a/libp2p-networking/src/lib.rs +++ b/libp2p-networking/src/lib.rs @@ -14,6 +14,9 @@ clippy::unused_self )] +// FIXME instrument all functions +// FIXME debug impl for Network, NetworkDef + pub mod direct_message; pub mod tracing_setup; @@ -50,7 +53,7 @@ use libp2p::{ mplex, noise, request_response::{ ProtocolSupport, RequestResponse, RequestResponseConfig, RequestResponseEvent, - RequestResponseMessage, + RequestResponseMessage, ResponseChannel, }, swarm::{ NetworkBehaviour, NetworkBehaviourAction, NetworkBehaviourEventProcess, PollParameters, @@ -188,16 +191,23 @@ impl NetworkBehaviourEventProcess, ) { - if let RequestResponseEvent::Message { - message: + if let RequestResponseEvent::Message { message, .. } = event { + match message { RequestResponseMessage::Request { request: DirectMessageRequest(msg), + channel, + .. + } => { + self.ui_events + .push(SwarmResult::DirectRequest(msg, channel)); + } + RequestResponseMessage::Response { + response: DirectMessageResponse(msg), .. - }, - .. - } = event - { - self.ui_events.push(SwarmResult::DirectMessage(msg)); + } => { + self.ui_events.push(SwarmResult::DirectResponse(msg)); + } + } } } } @@ -217,16 +227,19 @@ pub enum SwarmAction { GetId(Sender), Subscribe(String), Unsubscribe(String), - DirectMessage(PeerId, Vec), + DirectRequest(PeerId, Vec), + DirectResponse(ResponseChannel, Vec), } -/// holds events of the swarm to be relayed to the cli event loop +/// events generated by the swarm that we wish +/// to relay to UI #[derive(Debug)] pub enum SwarmResult { UpdateConnectedPeers(HashSet), UpdateKnownPeers(HashSet), GossipMsg(Vec), - DirectMessage(Vec), + DirectRequest(Vec, ResponseChannel), + DirectResponse(Vec), } /// bind all interfaces on port `port` @@ -522,12 +535,22 @@ impl Network { error!("error unsubscribing to topic {}", t); } } - DirectMessage(pid, msg) => { + DirectRequest(pid, msg) => { self.swarm .behaviour_mut() .request_response .send_request(&pid, DirectMessageRequest(msg)); } + DirectResponse(chan, msg) => { + let res = self + .swarm + .behaviour_mut() + .request_response + .send_response(chan, DirectMessageResponse(msg)); + if let Err(e) = res { + error!(?e, "problem with replying"); + } + } } } Err(e) => { @@ -619,6 +642,7 @@ impl Network { | BannedPeer { .. } | ListenerError { .. } => {} Behaviour(b) => { + // forward messages directly to UI send_to_ui .send_async(b) .await diff --git a/libp2p-networking/src/ui.rs b/libp2p-networking/src/ui.rs index 94b17177b4..49f2992480 100644 --- a/libp2p-networking/src/ui.rs +++ b/libp2p-networking/src/ui.rs @@ -102,7 +102,7 @@ pub async fn run_app(terminal: &mut Terminal, mut app: TableApp) swarm_msg = app.recv_swarm.recv_async() => { if let Ok(res) = swarm_msg { match res { - DirectMessage(m) | SwarmResult::GossipMsg(m) => { + DirectRequest(m, _) | SwarmResult::GossipMsg(m) => { let bincode_options = bincode::DefaultOptions::new().with_limit(16_384); let msg : Message = bincode_options.deserialize(&m)?; app.message_buffer.lock().push_back(msg); @@ -113,6 +113,7 @@ pub async fn run_app(terminal: &mut Terminal, mut app: TableApp) UpdateKnownPeers(peer_set) => { *app.known_peer_list.lock() = peer_set.clone(); } + DirectResponse(_) => { /* NOTE unimplemented in this example */ } } } }, @@ -152,7 +153,7 @@ pub async fn run_app(terminal: &mut Terminal, mut app: TableApp) }; let bincode_options = bincode::DefaultOptions::new().with_limit(16_384); let s_msg = bincode_options.serialize(&msg)?; - send_swarm.send_async(SwarmAction::DirectMessage(selected_peer, s_msg)).await?; + send_swarm.send_async(SwarmAction::DirectRequest(selected_peer, s_msg)).await?; mb_handle.lock().push_back(msg); // if it's a duplicate message (error case), fail silently and do nothing Result::<(), Report>::Ok(()) diff --git a/libp2p-networking/tests/counter.rs b/libp2p-networking/tests/counter.rs index 2035eaaa9b..90879f9003 100644 --- a/libp2p-networking/tests/counter.rs +++ b/libp2p-networking/tests/counter.rs @@ -1,46 +1,84 @@ -use flume::{Receiver, SendError, Sender}; -use libp2p::Multiaddr; -use networking_demo::{gen_multiaddr, Network, NetworkError, SwarmAction, SwarmResult}; +use std::sync::Arc; + +use async_std::{sync::Mutex, task::spawn}; +use bincode::Options; +use flume::{select, Receiver, RecvError, SendError, Sender}; +use futures::{select, Future, FutureExt, SinkExt}; +use libp2p::{ + request_response::{RequestResponse, RequestResponseCodec}, + Multiaddr, PeerId, +}; +use networking_demo::{ + direct_message::{DirectMessageCodec, DirectMessageResponse}, + gen_multiaddr, Network, NetworkError, SwarmAction, SwarmResult, +}; use serde::{Deserialize, Serialize}; +use snafu::ResultExt; use tracing::instrument; pub type Counter = u8; #[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq)] pub enum CounterMessage { - IncrementCounter { from: Counter, to: Counter }, + IncrementCounter { + from: CounterState, + to: CounterState, + }, AskForCounter, - MyCounterIs(Counter), + MyCounterIs(CounterState), } #[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq)] pub struct CounterState(Counter); -#[derive(Clone, Debug)] +#[derive(Debug)] pub struct SwarmHandle { - counter: CounterState, + /// the only piece of contested data. + state: Arc>, + /// send an action to the networkbehaviour send_chan: Sender, + /// receive an action from the networkbehaviour recv_chan: Receiver, + /// kill the networkbheaviour + kill_switch: Sender<()>, + /// receiving end of killing the network behaviour + recv_kill: Receiver<()>, + /// the local address we're listening on listen_addr: Multiaddr, + /// the peer id + peer_id: PeerId, } impl SwarmHandle { pub async fn new(known_addr: Option) -> Result { let listen_addr = gen_multiaddr(0); let mut network = Network::new().await?; + let mut peer_id = network.peer_id.clone(); let listen_addr = network.start(listen_addr, known_addr).await?; let (send_chan, recv_chan) = network.spawn_listeners().await?; + let (kill_switch, recv_kill) = flume::bounded(1); Ok(SwarmHandle { - counter: CounterState::default(), + state: Arc::new(Mutex::new(CounterState::default())), send_chan, recv_chan, + kill_switch, + recv_kill, listen_addr, + peer_id, }) } - pub async fn shutdown(&self) -> Result<(), SendError> { - self.send_chan.send_async(SwarmAction::Shutdown).await + pub async fn kill(&self) -> Result<(), NetworkError> { + self.send_chan + .send_async(SwarmAction::Shutdown) + .await + .map_err(|_e| NetworkError::StreamClosed)?; + self.kill_switch + .send_async(()) + .await + .map_err(|_e| NetworkError::StreamClosed)?; + Ok(()) } } @@ -50,16 +88,93 @@ impl Default for CounterState { } } -pub async fn spin_up_swarms(num_of_nodes: usize) -> Result, NetworkError> { +pub async fn spin_up_swarms(num_of_nodes: usize) -> Result>, NetworkError> { let bootstrap = SwarmHandle::new(None).await?; let bootstrap_addr = bootstrap.listen_addr.clone(); let mut handles = Vec::new(); for _ in 0..(num_of_nodes - 1) { - handles.push(SwarmHandle::new(Some(bootstrap_addr.clone())).await?); + handles.push(Arc::new( + SwarmHandle::new(Some(bootstrap_addr.clone())).await?, + )); } Ok(handles) } +pub async fn handle_event(event: SwarmResult, handle: Arc) { + use CounterMessage::*; + #[allow(clippy::enum_glob_use)] + use SwarmResult::*; + let bincode_options = bincode::DefaultOptions::new().with_limit(16_384); + match event { + GossipMsg(m) | DirectResponse(m) => { + if let Ok(msg) = bincode_options.deserialize::<'_, CounterMessage>(&m) { + match msg { + MyCounterIs(c) | CounterMessage::IncrementCounter { to: c, .. } => { + *handle.state.lock().await = c; + } + // NOTE doesn't make sense at the request level + AskForCounter => {} + } + } + } + DirectRequest(m, chan) => { + if let Ok(msg) = bincode_options.deserialize::<'_, CounterMessage>(&m) { + match msg { + IncrementCounter { to, .. } => { + *handle.state.lock().await = to; + } + AskForCounter => { + let response = MyCounterIs(handle.state.lock().await.clone()); + // FIXME error handling + let serialized_response = bincode_options.serialize(&response).unwrap(); + // FIXME error handling + handle + .send_chan + .send_async(SwarmAction::DirectResponse(chan, serialized_response)) + .await + .unwrap(); + } + // NOTE doesn't make sense as request type + // TODO maybe should check this at the type level + CounterMessage::MyCounterIs(_) => {} + } + } + } + _ => {} + } +} + +// TODO move this into the handle code +// TODO snafu error handler type that is either a serialization error +// OR channel sending error +// TODO instrumentation +pub async fn spawn_handler( + handle: Arc, + event_handler: impl (Fn(SwarmResult, Arc) -> Fut) + + std::marker::Sync + + std::marker::Send + + 'static, +) where + Fut: Future + std::marker::Send + 'static + std::marker::Sync, +{ + let recv_kill = handle.recv_kill.clone(); + let recv_event = handle.recv_chan.clone(); + let new_handle = handle.clone(); + spawn(async move { + loop { + select!( + _ = recv_kill.recv_async().fuse() => { + break; + }, + event = recv_event.recv_async().fuse() => { + event_handler(event?, new_handle.clone()).await; + }, + ); + } + Ok::<(), RecvError>(()) + }); +} + #[async_std::test] #[instrument] async fn test_spinup() { @@ -72,20 +187,37 @@ async fn test_spinup() { .send_async(SwarmAction::Shutdown) .await .unwrap(); + handle.kill_switch.send_async(()).await.unwrap(); + } +} + +#[async_std::test] +#[instrument] +async fn test_request_response() { + // NOTE we want this to panic if we can't spin up the swarms. + // that amounts to a failed test. + let handles = spin_up_swarms(5).await.unwrap(); + + // cleanup + for handle in handles.into_iter() { + handle.kill().await.unwrap(); } } #[async_std::test] #[instrument] -async fn test_counter() { +async fn test_gossip() { // NOTE we want this to panic if we can't spin up the swarms. // that amounts to a failed test. let handles = spin_up_swarms(5).await.unwrap(); for handle in handles.iter() { - handle - .send_chan - .send_async(SwarmAction::Shutdown) - .await - .unwrap(); + spawn_handler(handle.clone(), handle_event).await; + } + + // + + // cleanup + for handle in handles.into_iter() { + handle.kill().await.unwrap(); } } From ca30f6e2f1c2aaff1cc303cabab0e745fe35391e Mon Sep 17 00:00:00 2001 From: Justin Restivo Date: Thu, 27 Jan 2022 12:11:52 -0500 Subject: [PATCH 041/107] chore: clippy --- libp2p-networking/tests/counter.rs | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/libp2p-networking/tests/counter.rs b/libp2p-networking/tests/counter.rs index 90879f9003..76f6bbbba9 100644 --- a/libp2p-networking/tests/counter.rs +++ b/libp2p-networking/tests/counter.rs @@ -2,19 +2,17 @@ use std::sync::Arc; use async_std::{sync::Mutex, task::spawn}; use bincode::Options; -use flume::{select, Receiver, RecvError, SendError, Sender}; -use futures::{select, Future, FutureExt, SinkExt}; +use flume::{Receiver, RecvError, Sender}; +use futures::{select, Future, FutureExt}; use libp2p::{ - request_response::{RequestResponse, RequestResponseCodec}, Multiaddr, PeerId, }; use networking_demo::{ - direct_message::{DirectMessageCodec, DirectMessageResponse}, gen_multiaddr, Network, NetworkError, SwarmAction, SwarmResult, }; use serde::{Deserialize, Serialize}; -use snafu::ResultExt; + use tracing::instrument; pub type Counter = u8; @@ -54,7 +52,7 @@ impl SwarmHandle { pub async fn new(known_addr: Option) -> Result { let listen_addr = gen_multiaddr(0); let mut network = Network::new().await?; - let mut peer_id = network.peer_id.clone(); + let peer_id = network.peer_id.clone(); let listen_addr = network.start(listen_addr, known_addr).await?; let (send_chan, recv_chan) = network.spawn_listeners().await?; let (kill_switch, recv_kill) = flume::bounded(1); @@ -144,7 +142,6 @@ pub async fn handle_event(event: SwarmResult, handle: Arc) { } } -// TODO move this into the handle code // TODO snafu error handler type that is either a serialization error // OR channel sending error // TODO instrumentation From 64d9e4ea6cf69112264e1c1bb45f219966aac9f5 Mon Sep 17 00:00:00 2001 From: Justin Restivo Date: Thu, 27 Jan 2022 13:39:59 -0500 Subject: [PATCH 042/107] feat: handle error type --- libp2p-networking/tests/counter.rs | 65 +++++++++++++++++------------- 1 file changed, 37 insertions(+), 28 deletions(-) diff --git a/libp2p-networking/tests/counter.rs b/libp2p-networking/tests/counter.rs index 76f6bbbba9..3c65daa63c 100644 --- a/libp2p-networking/tests/counter.rs +++ b/libp2p-networking/tests/counter.rs @@ -2,17 +2,14 @@ use std::sync::Arc; use async_std::{sync::Mutex, task::spawn}; use bincode::Options; -use flume::{Receiver, RecvError, Sender}; +use flume::{Receiver, RecvError, SendError, Sender}; use futures::{select, Future, FutureExt}; -use libp2p::{ - Multiaddr, PeerId, -}; -use networking_demo::{ - gen_multiaddr, Network, NetworkError, SwarmAction, SwarmResult, -}; +use libp2p::{Multiaddr, PeerId}; +use networking_demo::{gen_multiaddr, Network, NetworkError, SwarmAction, SwarmResult}; use serde::{Deserialize, Serialize}; +use snafu::{ResultExt, Snafu}; use tracing::instrument; pub type Counter = u8; @@ -27,7 +24,7 @@ pub enum CounterMessage { MyCounterIs(CounterState), } -#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq)] +#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, Default)] pub struct CounterState(Counter); #[derive(Debug)] @@ -49,12 +46,15 @@ pub struct SwarmHandle { } impl SwarmHandle { - pub async fn new(known_addr: Option) -> Result { + pub async fn new(known_addr: Option) -> Result { let listen_addr = gen_multiaddr(0); - let mut network = Network::new().await?; - let peer_id = network.peer_id.clone(); - let listen_addr = network.start(listen_addr, known_addr).await?; - let (send_chan, recv_chan) = network.spawn_listeners().await?; + let mut network = Network::new().await.context(NetworkSnafu)?; + let peer_id = network.peer_id; + let listen_addr = network + .start(listen_addr, known_addr) + .await + .context(NetworkSnafu)?; + let (send_chan, recv_chan) = network.spawn_listeners().await.context(NetworkSnafu)?; let (kill_switch, recv_kill) = flume::bounded(1); Ok(SwarmHandle { state: Arc::new(Mutex::new(CounterState::default())), @@ -80,13 +80,7 @@ impl SwarmHandle { } } -impl Default for CounterState { - fn default() -> Self { - Self(0) - } -} - -pub async fn spin_up_swarms(num_of_nodes: usize) -> Result>, NetworkError> { +pub async fn spin_up_swarms(num_of_nodes: usize) -> Result>, HandlerError> { let bootstrap = SwarmHandle::new(None).await?; let bootstrap_addr = bootstrap.listen_addr.clone(); let mut handles = Vec::new(); @@ -98,7 +92,10 @@ pub async fn spin_up_swarms(num_of_nodes: usize) -> Result> Ok(handles) } -pub async fn handle_event(event: SwarmResult, handle: Arc) { +pub async fn handle_event( + event: SwarmResult, + handle: Arc, +) -> Result<(), HandlerError> { use CounterMessage::*; #[allow(clippy::enum_glob_use)] use SwarmResult::*; @@ -124,13 +121,15 @@ pub async fn handle_event(event: SwarmResult, handle: Arc) { AskForCounter => { let response = MyCounterIs(handle.state.lock().await.clone()); // FIXME error handling - let serialized_response = bincode_options.serialize(&response).unwrap(); + let serialized_response = bincode_options + .serialize(&response) + .context(SerializationSnafu)?; // FIXME error handling handle .send_chan .send_async(SwarmAction::DirectResponse(chan, serialized_response)) .await - .unwrap(); + .context(SendSnafu)? } // NOTE doesn't make sense as request type // TODO maybe should check this at the type level @@ -139,7 +138,8 @@ pub async fn handle_event(event: SwarmResult, handle: Arc) { } } _ => {} - } + }; + Ok(()) } // TODO snafu error handler type that is either a serialization error @@ -152,11 +152,11 @@ pub async fn spawn_handler( + std::marker::Send + 'static, ) where - Fut: Future + std::marker::Send + 'static + std::marker::Sync, + Fut: + Future> + std::marker::Send + 'static + std::marker::Sync, { let recv_kill = handle.recv_kill.clone(); let recv_event = handle.recv_chan.clone(); - let new_handle = handle.clone(); spawn(async move { loop { select!( @@ -164,11 +164,11 @@ pub async fn spawn_handler( break; }, event = recv_event.recv_async().fuse() => { - event_handler(event?, new_handle.clone()).await; + event_handler(event.context(RecvSnafu)?, handle.clone()).await?; }, ); } - Ok::<(), RecvError>(()) + Ok::<(), HandlerError>(()) }); } @@ -218,3 +218,12 @@ async fn test_gossip() { handle.kill().await.unwrap(); } } + +#[derive(Debug, Snafu)] +pub enum HandlerError { + NetworkError { source: NetworkError }, + SerializationError { source: Box }, + DeserializationError {}, + SendError { source: SendError }, + RecvError { source: RecvError }, +} From 2db74cc4332b1f83e863f04f954da5e99543f9ec Mon Sep 17 00:00:00 2001 From: Justin Restivo Date: Thu, 27 Jan 2022 14:22:30 -0500 Subject: [PATCH 043/107] feat: instrumentation + gossip test --- libp2p-networking/src/lib.rs | 16 ++++++---- libp2p-networking/tests/counter.rs | 49 ++++++++++++++++-------------- 2 files changed, 37 insertions(+), 28 deletions(-) diff --git a/libp2p-networking/src/lib.rs b/libp2p-networking/src/lib.rs index 28f1f573da..95ed2470bd 100644 --- a/libp2p-networking/src/lib.rs +++ b/libp2p-networking/src/lib.rs @@ -221,6 +221,7 @@ pub struct Network { pub min_num_peers: usize, } +#[derive(Debug)] pub enum SwarmAction { Shutdown, GossipMsg(Topic, Vec, Sender>), @@ -252,6 +253,7 @@ pub fn gen_multiaddr(port: u16) -> Multiaddr { /// for definition of XX /// # Errors /// could not sign the noise key with `identity` +#[instrument(skip(identity))] pub async fn gen_transport(identity: Keypair) -> std::io::Result> { let transport = { let tcp = tcp::TcpConfig::new().nodelay(true); @@ -290,19 +292,19 @@ impl Network { listen_addr: Multiaddr, known_peer: Option, ) -> Result { - let listen_id = self.swarm.listen_on(listen_addr).context(TransportSnafu)?; + self.swarm.listen_on(listen_addr).context(TransportSnafu)?; let addr = loop { match self.swarm.next().await { Some(SwarmEvent::NewListenAddr { address, .. }) => break address, _ => continue, }; }; - error!("listen addr: {:?}", listen_id); + error!("listen addr: {:?}", addr.clone()); if let Some(known_peer) = known_peer { let dialing = known_peer.clone(); match self.swarm.dial(known_peer) { Ok(_) => { - info!("Dialed {:?}", dialing); + warn!("Dialed {:?}", dialing); } Err(e) => error!("Dial {:?} failed: {:?}", dialing, e), }; @@ -408,7 +410,7 @@ impl Network { /// peer discovery mechanism /// looks up a random peer - #[inline] + #[instrument(skip(self))] fn handle_peer_discovery(&mut self) { if !self.swarm.behaviour().bootstrap { let random_peer = PeerId::random(); @@ -421,7 +423,7 @@ impl Network { /// Keep the number of open connections between threshold specified by /// the swarm - #[inline] + #[instrument(skip(self))] fn handle_num_connections(&mut self) { let swarm = self.swarm.behaviour(); // if we're bootstrapped, do nothing @@ -478,6 +480,7 @@ impl Network { /// - subscribing to a topic /// - unsubscribing from a toipc /// - direct messaging a peer + #[instrument(skip(self))] async fn handle_ui_events( &mut self, msg: Result, @@ -561,6 +564,7 @@ impl Network { } /// event handler for events emited from the swarm + #[instrument(skip(self))] async fn handle_swarm_events( &mut self, event: SwarmEvent< @@ -680,7 +684,7 @@ impl Network { } event = self.swarm.next() => { if let Some(event) = event { - error!("handling event {:?}", event); + error!("peerid {:?}\t\thandling event {:?}", self.peer_id, event); self.handle_swarm_events(event, &r_input).await?; } }, diff --git a/libp2p-networking/tests/counter.rs b/libp2p-networking/tests/counter.rs index 3c65daa63c..ed0d381c30 100644 --- a/libp2p-networking/tests/counter.rs +++ b/libp2p-networking/tests/counter.rs @@ -1,16 +1,17 @@ -use std::sync::Arc; +use std::{sync::Arc, time::Duration}; -use async_std::{sync::Mutex, task::spawn}; +use async_std::{sync::Mutex, task::{spawn, sleep}}; use bincode::Options; use flume::{Receiver, RecvError, SendError, Sender}; use futures::{select, Future, FutureExt}; -use libp2p::{Multiaddr, PeerId}; +use libp2p::{Multiaddr, PeerId, gossipsub::Topic}; use networking_demo::{gen_multiaddr, Network, NetworkError, SwarmAction, SwarmResult}; +use rand::{seq::IteratorRandom, thread_rng}; use serde::{Deserialize, Serialize}; use snafu::{ResultExt, Snafu}; -use tracing::instrument; +use tracing::{instrument, info_span, Instrument}; pub type Counter = u8; @@ -46,6 +47,7 @@ pub struct SwarmHandle { } impl SwarmHandle { + #[instrument] pub async fn new(known_addr: Option) -> Result { let listen_addr = gen_multiaddr(0); let mut network = Network::new().await.context(NetworkSnafu)?; @@ -67,6 +69,7 @@ impl SwarmHandle { }) } + #[instrument] pub async fn kill(&self) -> Result<(), NetworkError> { self.send_chan .send_async(SwarmAction::Shutdown) @@ -80,9 +83,11 @@ impl SwarmHandle { } } +#[instrument] pub async fn spin_up_swarms(num_of_nodes: usize) -> Result>, HandlerError> { let bootstrap = SwarmHandle::new(None).await?; let bootstrap_addr = bootstrap.listen_addr.clone(); + sleep(Duration::from_secs(30)).await; let mut handles = Vec::new(); for _ in 0..(num_of_nodes - 1) { handles.push(Arc::new( @@ -145,6 +150,7 @@ pub async fn handle_event( // TODO snafu error handler type that is either a serialization error // OR channel sending error // TODO instrumentation +#[instrument(skip(event_handler))] pub async fn spawn_handler( handle: Arc, event_handler: impl (Fn(SwarmResult, Arc) -> Fut) @@ -169,25 +175,10 @@ pub async fn spawn_handler( ); } Ok::<(), HandlerError>(()) - }); -} - -#[async_std::test] -#[instrument] -async fn test_spinup() { - // NOTE we want this to panic if we can't spin up the swarms. - // that amounts to a failed test. - let handles = spin_up_swarms(5).await.unwrap(); - for handle in handles.iter() { - handle - .send_chan - .send_async(SwarmAction::Shutdown) - .await - .unwrap(); - handle.kill_switch.send_async(()).await.unwrap(); - } + }.instrument(info_span!("Libp2p Event Handler"))); } +/// check that we can direct message to increment counter #[async_std::test] #[instrument] async fn test_request_response() { @@ -201,9 +192,12 @@ async fn test_request_response() { } } +/// check that we can broadcast a message out and get counter increments #[async_std::test] #[instrument] async fn test_gossip() { + color_eyre::install().unwrap(); + networking_demo::tracing_setup::setup_tracing(); // NOTE we want this to panic if we can't spin up the swarms. // that amounts to a failed test. let handles = spin_up_swarms(5).await.unwrap(); @@ -211,7 +205,18 @@ async fn test_gossip() { spawn_handler(handle.clone(), handle_event).await; } - // + let msg_handle = handles.iter().choose(&mut thread_rng()).unwrap(); + let bincode_options = bincode::DefaultOptions::new().with_limit(16_384); + let msg_inner = bincode_options.serialize(&CounterMessage::IncrementCounter { from: CounterState(0), to: CounterState(5)}).unwrap(); + let (send, recv) = flume::bounded(1); + let msg = SwarmAction::GossipMsg(Topic::new("global"), msg_inner, send); + msg_handle.send_chan.send_async(msg).await.unwrap(); + recv.recv_async().await.unwrap().unwrap(); + sleep(Duration::from_secs(30)).await; + + for handle in handles.iter() { + assert_eq!(*handle.state.lock().await, CounterState(5)); + } // cleanup for handle in handles.into_iter() { From 91b30f1f9bc15ae3832b3f4854e83474c8b230d5 Mon Sep 17 00:00:00 2001 From: Justin Restivo Date: Fri, 28 Jan 2022 12:04:45 -0500 Subject: [PATCH 044/107] fix: passing the gossip test --- libp2p-networking/src/lib.rs | 30 +++++-- libp2p-networking/tests/counter.rs | 122 ++++++++++++++++++++++------- 2 files changed, 118 insertions(+), 34 deletions(-) diff --git a/libp2p-networking/src/lib.rs b/libp2p-networking/src/lib.rs index 95ed2470bd..cbab576308 100644 --- a/libp2p-networking/src/lib.rs +++ b/libp2p-networking/src/lib.rs @@ -85,6 +85,7 @@ pub struct NetworkDef { pub request_response: RequestResponse, #[behaviour(ignore)] pub bootstrap: bool, + // TODO separate out into ConnectionData struct #[behaviour(ignore)] pub connected_peers: HashSet, // TODO replace this with a set of queryids @@ -96,6 +97,13 @@ pub struct NetworkDef { pub ui_events: Vec, } +#[derive(Default, Debug, Clone)] +pub struct ConnectionData { + pub connected_peers: HashSet, + pub connecting_peers: HashSet, + pub known_peers: HashSet, +} + impl NetworkDef { fn poll( &mut self, @@ -299,14 +307,17 @@ impl Network { _ => continue, }; }; - error!("listen addr: {:?}", addr.clone()); + info!("peerid {:?} listen addr: {:?}", self.peer_id, addr); if let Some(known_peer) = known_peer { let dialing = known_peer.clone(); match self.swarm.dial(known_peer) { Ok(_) => { - warn!("Dialed {:?}", dialing); + warn!("peerid {:?} dialed {:?}", self.peer_id, dialing); } - Err(e) => error!("Dial {:?} failed: {:?}", dialing, e), + Err(e) => error!( + "peerid {:?} dialed {:?} and failed with error: {:?}", + self.peer_id, dialing, e + ), }; } Ok(addr) @@ -402,8 +413,8 @@ impl Network { identity, peer_id, broadcast_topic, - max_num_peers: 6, - min_num_peers: 5, + max_num_peers: 600, + min_num_peers: 50, swarm, }) } @@ -454,10 +465,15 @@ impl Network { Ok(_) => { self.swarm.behaviour_mut().connecting_peers.insert(a_peer); } - Err(e) => error!("Dial {:?} failed: {:?}", a_peer, e), + Err(e) => { + info!("Peer {:?} dial {:?} failed: {:?}", self.peer_id, a_peer, e); + } }; } - } else if swarm.connected_peers.len() > self.max_num_peers { + } + // TODO fix this so it does *not* happen on bootstrap nodes + // will need to introduce node types + else if swarm.connected_peers.len() > self.max_num_peers { // If we are connected to too many peers, try disconnecting from // a random (?) subset let peers_to_rm = swarm.connected_peers.iter().copied().choose_multiple( diff --git a/libp2p-networking/tests/counter.rs b/libp2p-networking/tests/counter.rs index ed0d381c30..323fa223f6 100644 --- a/libp2p-networking/tests/counter.rs +++ b/libp2p-networking/tests/counter.rs @@ -1,19 +1,25 @@ use std::{sync::Arc, time::Duration}; -use async_std::{sync::Mutex, task::{spawn, sleep}}; +use async_std::{ + sync::Mutex, + task::{sleep, spawn}, +}; use bincode::Options; use flume::{Receiver, RecvError, SendError, Sender}; use futures::{select, Future, FutureExt}; -use libp2p::{Multiaddr, PeerId, gossipsub::Topic}; -use networking_demo::{gen_multiaddr, Network, NetworkError, SwarmAction, SwarmResult}; +use libp2p::{gossipsub::Topic, Multiaddr, PeerId}; +use networking_demo::{ + gen_multiaddr, ConnectionData, Network, NetworkError, SwarmAction, SwarmResult, +}; use rand::{seq::IteratorRandom, thread_rng}; use serde::{Deserialize, Serialize}; use snafu::{ResultExt, Snafu}; -use tracing::{instrument, info_span, Instrument}; +use tracing::{error, info_span, instrument, warn, Instrument}; pub type Counter = u8; +const TOTAL_NUM_PEERS: usize = 20; #[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq)] pub enum CounterMessage { @@ -44,11 +50,14 @@ pub struct SwarmHandle { listen_addr: Multiaddr, /// the peer id peer_id: PeerId, + /// the connection metadata + connection_state: Arc>, } impl SwarmHandle { #[instrument] pub async fn new(known_addr: Option) -> Result { + //`randomly assigned port let listen_addr = gen_multiaddr(0); let mut network = Network::new().await.context(NetworkSnafu)?; let peer_id = network.peer_id; @@ -58,6 +67,12 @@ impl SwarmHandle { .context(NetworkSnafu)?; let (send_chan, recv_chan) = network.spawn_listeners().await.context(NetworkSnafu)?; let (kill_switch, recv_kill) = flume::bounded(1); + + send_chan + .send_async(SwarmAction::Subscribe("global".to_string())) + .await + .context(SendSnafu)?; + Ok(SwarmHandle { state: Arc::new(Mutex::new(CounterState::default())), send_chan, @@ -66,6 +81,7 @@ impl SwarmHandle { recv_kill, listen_addr, peer_id, + connection_state: Default::default(), }) } @@ -85,18 +101,28 @@ impl SwarmHandle { #[instrument] pub async fn spin_up_swarms(num_of_nodes: usize) -> Result>, HandlerError> { + // FIXME change API to accomodate multiple bootstrap nodes let bootstrap = SwarmHandle::new(None).await?; let bootstrap_addr = bootstrap.listen_addr.clone(); - sleep(Duration::from_secs(30)).await; + warn!( + "boostrap node {} on addr {}", + bootstrap.peer_id, bootstrap_addr + ); + // give a split second to initialize + // TODO the proper way to do this is to make it event driven. Once it bootstraps *successfully* + // THEN add next peer + sleep(Duration::from_secs(1)).await; let mut handles = Vec::new(); for _ in 0..(num_of_nodes - 1) { handles.push(Arc::new( SwarmHandle::new(Some(bootstrap_addr.clone())).await?, )); + sleep(Duration::from_secs(1)).await; } Ok(handles) } +#[instrument] pub async fn handle_event( event: SwarmResult, handle: Arc, @@ -107,7 +133,7 @@ pub async fn handle_event( let bincode_options = bincode::DefaultOptions::new().with_limit(16_384); match event { GossipMsg(m) | DirectResponse(m) => { - if let Ok(msg) = bincode_options.deserialize::<'_, CounterMessage>(&m) { + if let Ok(msg) = bincode_options.deserialize::(&m) { match msg { MyCounterIs(c) | CounterMessage::IncrementCounter { to: c, .. } => { *handle.state.lock().await = c; @@ -118,7 +144,7 @@ pub async fn handle_event( } } DirectRequest(m, chan) => { - if let Ok(msg) = bincode_options.deserialize::<'_, CounterMessage>(&m) { + if let Ok(msg) = bincode_options.deserialize::(&m) { match msg { IncrementCounter { to, .. } => { *handle.state.lock().await = to; @@ -142,14 +168,18 @@ pub async fn handle_event( } } } - _ => {} + UpdateConnectedPeers(p) => { + handle.connection_state.lock().await.connected_peers = p; + } + UpdateKnownPeers(p) => { + handle.connection_state.lock().await.known_peers = p; + } }; Ok(()) } // TODO snafu error handler type that is either a serialization error // OR channel sending error -// TODO instrumentation #[instrument(skip(event_handler))] pub async fn spawn_handler( handle: Arc, @@ -163,19 +193,22 @@ pub async fn spawn_handler( { let recv_kill = handle.recv_kill.clone(); let recv_event = handle.recv_chan.clone(); - spawn(async move { - loop { - select!( - _ = recv_kill.recv_async().fuse() => { - break; - }, - event = recv_event.recv_async().fuse() => { - event_handler(event.context(RecvSnafu)?, handle.clone()).await?; - }, - ); + spawn( + async move { + loop { + select!( + _ = recv_kill.recv_async().fuse() => { + break; + }, + event = recv_event.recv_async().fuse() => { + event_handler(event.context(RecvSnafu)?, handle.clone()).await?; + }, + ); + } + Ok::<(), HandlerError>(()) } - Ok::<(), HandlerError>(()) - }.instrument(info_span!("Libp2p Event Handler"))); + .instrument(info_span!("Libp2p Event Handler")), + ); } /// check that we can direct message to increment counter @@ -184,7 +217,7 @@ pub async fn spawn_handler( async fn test_request_response() { // NOTE we want this to panic if we can't spin up the swarms. // that amounts to a failed test. - let handles = spin_up_swarms(5).await.unwrap(); + let handles = spin_up_swarms(3).await.unwrap(); // cleanup for handle in handles.into_iter() { @@ -200,28 +233,63 @@ async fn test_gossip() { networking_demo::tracing_setup::setup_tracing(); // NOTE we want this to panic if we can't spin up the swarms. // that amounts to a failed test. - let handles = spin_up_swarms(5).await.unwrap(); + let handles = spin_up_swarms(TOTAL_NUM_PEERS).await.unwrap(); for handle in handles.iter() { spawn_handler(handle.clone(), handle_event).await; } + print_connections(&handles).await; let msg_handle = handles.iter().choose(&mut thread_rng()).unwrap(); + *msg_handle.state.lock().await = CounterState(5); let bincode_options = bincode::DefaultOptions::new().with_limit(16_384); - let msg_inner = bincode_options.serialize(&CounterMessage::IncrementCounter { from: CounterState(0), to: CounterState(5)}).unwrap(); + let msg_inner = bincode_options + .serialize(&CounterMessage::IncrementCounter { + from: CounterState(0), + to: CounterState(5), + }) + .unwrap(); let (send, recv) = flume::bounded(1); let msg = SwarmAction::GossipMsg(Topic::new("global"), msg_inner, send); msg_handle.send_chan.send_async(msg).await.unwrap(); recv.recv_async().await.unwrap().unwrap(); - sleep(Duration::from_secs(30)).await; - for handle in handles.iter() { - assert_eq!(*handle.state.lock().await, CounterState(5)); + // block to let the gossipping happen + sleep(Duration::from_millis(10)).await; + + print_connections(&handles).await; + + let mut failing_idxs = Vec::new(); + for (i, handle) in handles.iter().enumerate() { + if *handle.state.lock().await != CounterState(5) { + failing_idxs.push(i); + } } // cleanup for handle in handles.into_iter() { handle.kill().await.unwrap(); } + + if !failing_idxs.is_empty() { + error!(?failing_idxs, "failing idxs!!"); + panic!("some nodes did not receive the message {:?}", failing_idxs); + } +} + +async fn print_connections(handles: &[Arc]) { + error!("PRINTING CONNECTION STATES"); + for (i, handle) in handles.iter().enumerate() { + error!( + "peer {}, connected to {:?}", + i, + handle.connection_state.lock().await.connected_peers + ); + error!( + "peer {}, knowns about {:?}", + i, + handle.connection_state.lock().await.known_peers + ); + } } #[derive(Debug, Snafu)] From 3760276a1f9b3c88814165f0fe2c2e582b35f051 Mon Sep 17 00:00:00 2001 From: Justin Restivo Date: Fri, 28 Jan 2022 14:30:37 -0500 Subject: [PATCH 045/107] feat: testbed --- libp2p-networking/flake.lock | 12 ++-- libp2p-networking/tests/counter.rs | 98 +++++++++++++++++++----------- 2 files changed, 67 insertions(+), 43 deletions(-) diff --git a/libp2p-networking/flake.lock b/libp2p-networking/flake.lock index f4535eaef9..7dd05b06fe 100644 --- a/libp2p-networking/flake.lock +++ b/libp2p-networking/flake.lock @@ -25,11 +25,11 @@ "rust-analyzer-src": "rust-analyzer-src" }, "locked": { - "lastModified": 1641709553, - "narHash": "sha256-wFx7U4klsmMZIufILyojgPUTYmtmIVD/M7Wg0JgcbJc=", + "lastModified": 1643264637, + "narHash": "sha256-jR8Cke8Ukj0ZcpmHaz+TcpUzL5O1xtiEinzbvx4PMfU=", "owner": "nix-community", "repo": "fenix", - "rev": "43fa994400794b5cb09ab9be894372c9e51bf7a6", + "rev": "51cf29a5c001389a5781b4115315dd2012590551", "type": "github" }, "original": { @@ -82,11 +82,11 @@ "rust-analyzer-src": { "flake": false, "locked": { - "lastModified": 1641653161, - "narHash": "sha256-gajsOT+HAfCEngraBy1K7UmLpDdQo4wtmhnzju4qKLI=", + "lastModified": 1643220707, + "narHash": "sha256-XMBer+U/1WqPu25aJs/LkMxrnJnEKiezsAtfSpkkPik=", "owner": "rust-analyzer", "repo": "rust-analyzer", - "rev": "0f8c96c92689af8378dbe9f466c6bf15a3a27458", + "rev": "e149a15edd354dd0f995532d16a3e8dc21367e06", "type": "github" }, "original": { diff --git a/libp2p-networking/tests/counter.rs b/libp2p-networking/tests/counter.rs index 323fa223f6..9739a02eaa 100644 --- a/libp2p-networking/tests/counter.rs +++ b/libp2p-networking/tests/counter.rs @@ -122,6 +122,35 @@ pub async fn spin_up_swarms(num_of_nodes: usize) -> Result> Ok(handles) } +/// general function to spin up testing infra +/// perform tests +/// then return +// pub async fn test_bed(run_test: impl FnOnce(&[Arc]) -> Fut) where +// Fut: Future, +pub async fn test_bed(run_test: F) where + Fut: Future, + F: FnOnce(Vec>) -> Fut +{ + color_eyre::install().unwrap(); + networking_demo::tracing_setup::setup_tracing(); + // NOTE we want this to panic if we can't spin up the swarms. + // that amounts to a failed test. + let handles : Vec> = spin_up_swarms(TOTAL_NUM_PEERS).await.unwrap().try_into().unwrap(); + for handle in handles.iter() { + spawn_handler(handle.clone(), handle_event).await; + } + print_connections(&handles).await; + + + run_test(handles.clone()).await; + + // cleanup + for handle in handles.into_iter() { + handle.kill().await.unwrap(); + } + +} + #[instrument] pub async fn handle_event( event: SwarmResult, @@ -229,51 +258,46 @@ async fn test_request_response() { #[async_std::test] #[instrument] async fn test_gossip() { - color_eyre::install().unwrap(); - networking_demo::tracing_setup::setup_tracing(); - // NOTE we want this to panic if we can't spin up the swarms. - // that amounts to a failed test. - let handles = spin_up_swarms(TOTAL_NUM_PEERS).await.unwrap(); - for handle in handles.iter() { - spawn_handler(handle.clone(), handle_event).await; - } - print_connections(&handles).await; - - let msg_handle = handles.iter().choose(&mut thread_rng()).unwrap(); - *msg_handle.state.lock().await = CounterState(5); - let bincode_options = bincode::DefaultOptions::new().with_limit(16_384); - let msg_inner = bincode_options - .serialize(&CounterMessage::IncrementCounter { - from: CounterState(0), - to: CounterState(5), - }) + async fn run_test(handles: Vec>) { + let msg_handle = handles.iter().choose(&mut thread_rng()).unwrap(); + *msg_handle.state.lock().await = CounterState(5); + let bincode_options = bincode::DefaultOptions::new().with_limit(16_384); + let msg_inner = bincode_options + .serialize(&CounterMessage::IncrementCounter { + from: CounterState(0), + to: CounterState(5), + }) .unwrap(); - let (send, recv) = flume::bounded(1); - let msg = SwarmAction::GossipMsg(Topic::new("global"), msg_inner, send); - msg_handle.send_chan.send_async(msg).await.unwrap(); - recv.recv_async().await.unwrap().unwrap(); + let (send, recv) = flume::bounded(1); + let msg = SwarmAction::GossipMsg(Topic::new("global"), msg_inner, send); + msg_handle.send_chan.send_async(msg).await.unwrap(); + recv.recv_async().await.unwrap().unwrap(); - // block to let the gossipping happen - sleep(Duration::from_millis(10)).await; + // block to let the gossipping happen + // TODO make this event driven + // e.g. everyone receives the gossipmsg event + // or timeout + sleep(Duration::from_millis(10)).await; - print_connections(&handles).await; + print_connections(&handles).await; - let mut failing_idxs = Vec::new(); - for (i, handle) in handles.iter().enumerate() { - if *handle.state.lock().await != CounterState(5) { - failing_idxs.push(i); + let mut failing_idxs = Vec::new(); + for (i, handle) in handles.iter().enumerate() { + if *handle.state.lock().await != CounterState(5) { + failing_idxs.push(i); + } + } + if !failing_idxs.is_empty() { + error!(?failing_idxs, "failing idxs!!"); + panic!("some nodes did not receive the message {:?}", failing_idxs); } - } - // cleanup - for handle in handles.into_iter() { - handle.kill().await.unwrap(); } - if !failing_idxs.is_empty() { - error!(?failing_idxs, "failing idxs!!"); - panic!("some nodes did not receive the message {:?}", failing_idxs); - } + + + test_bed::<_, _>(run_test).await; + } async fn print_connections(handles: &[Arc]) { From e13557ce5f9bc43701398eac85453fc3957703fe Mon Sep 17 00:00:00 2001 From: Justin Restivo Date: Mon, 31 Jan 2022 09:21:50 -0500 Subject: [PATCH 046/107] feat: add requestresponse test --- libp2p-networking/src/lib.rs | 14 ++--- libp2p-networking/src/ui.rs | 11 +++- libp2p-networking/tests/counter.rs | 97 ++++++++++++++++++++---------- 3 files changed, 79 insertions(+), 43 deletions(-) diff --git a/libp2p-networking/src/lib.rs b/libp2p-networking/src/lib.rs index cbab576308..7cd7f66b54 100644 --- a/libp2p-networking/src/lib.rs +++ b/libp2p-networking/src/lib.rs @@ -14,7 +14,6 @@ clippy::unused_self )] -// FIXME instrument all functions // FIXME debug impl for Network, NetworkDef pub mod direct_message; @@ -125,9 +124,8 @@ impl NetworkDef { impl NetworkBehaviourEventProcess for NetworkDef { fn inject_event(&mut self, event: GossipsubEvent) { - error!(?event, "gossipsub msg recv-ed"); + info!(?event, "gossipsub msg recv-ed"); if let GossipsubEvent::Message { message, .. } = event { - error!("correct message form"); self.ui_events.push(SwarmResult::GossipMsg(message.data)); } } @@ -135,7 +133,7 @@ impl NetworkBehaviourEventProcess for NetworkDef { impl NetworkBehaviourEventProcess for NetworkDef { fn inject_event(&mut self, event: KademliaEvent) { - error!(?event, "kadem msg recv-ed"); + info!(?event, "kadem msg recv-ed"); match event { KademliaEvent::OutboundQueryCompleted { result, .. } => { match result { @@ -518,7 +516,7 @@ impl Network { .publish(topic, contents.clone()) .map(|_| ()) .context(PublishSnafu); - error!("publishing reuslt! {:?}", res); + info!("publishing reuslt! {:?}", res); // send result back to ui to confirm this isn't a duplicate message chan.send_async(res) @@ -567,7 +565,7 @@ impl Network { .request_response .send_response(chan, DirectMessageResponse(msg)); if let Err(e) = res { - error!(?e, "problem with replying"); + error!("Error replying to direct message. {:?}", e); } } } @@ -700,7 +698,7 @@ impl Network { } event = self.swarm.next() => { if let Some(event) = event { - error!("peerid {:?}\t\thandling event {:?}", self.peer_id, event); + info!("peerid {:?}\t\thandling event {:?}", self.peer_id, event); self.handle_swarm_events(event, &r_input).await?; } }, @@ -714,7 +712,7 @@ impl Network { } Ok::<(), NetworkError>(()) } - .instrument(info_span!("Libp2p Event Handler")), + .instrument(info_span!("Libp2p NetworkBehaviour Handler")), ); Ok((s_input, r_output)) } diff --git a/libp2p-networking/src/ui.rs b/libp2p-networking/src/ui.rs index 49f2992480..9a39b70e27 100644 --- a/libp2p-networking/src/ui.rs +++ b/libp2p-networking/src/ui.rs @@ -16,7 +16,7 @@ use std::{ sync::Arc, time::Duration, }; -use tracing::instrument; +use tracing::{info_span, instrument, Instrument}; use tui::{ backend::Backend, layout::{Constraint, Direction, Layout}, @@ -47,6 +47,7 @@ pub struct TableApp { } impl TableApp { + #[instrument] pub fn new( message_buffer: Arc>>, send_swarm: Sender, @@ -63,12 +64,15 @@ impl TableApp { known_peer_list: Arc::new(Mutex::new(HashSet::new())), } } + + #[instrument] pub fn next(&mut self) { let buffer_handle = self.message_buffer.lock(); let i = self.state.selected().unwrap_or(0) + 1; self.state.select(Some(i % buffer_handle.len())); } + #[instrument] pub fn previous(&mut self) { let buffer_handle = self.message_buffer.lock(); let i = match self.state.selected() { @@ -157,7 +161,8 @@ pub async fn run_app(terminal: &mut Terminal, mut app: TableApp) mb_handle.lock().push_back(msg); // if it's a duplicate message (error case), fail silently and do nothing Result::<(), Report>::Ok(()) - }); + }.instrument(info_span!("Direct Message Handler")), + ); } app.input = String::new(); } @@ -183,7 +188,7 @@ pub async fn run_app(terminal: &mut Terminal, mut app: TableApp) mb_handle.lock().push_back(msg); } Result::<(), Report>::Ok(()) - }); + }.instrument(info_span!("Broadcast Handler"))); app.input = String::new(); } KeyCode::Char(c) => { diff --git a/libp2p-networking/tests/counter.rs b/libp2p-networking/tests/counter.rs index 9739a02eaa..cb0ac7f5f1 100644 --- a/libp2p-networking/tests/counter.rs +++ b/libp2p-networking/tests/counter.rs @@ -16,11 +16,14 @@ use rand::{seq::IteratorRandom, thread_rng}; use serde::{Deserialize, Serialize}; use snafu::{ResultExt, Snafu}; -use tracing::{error, info_span, instrument, warn, Instrument}; +use std::sync::Once; +use tracing::{error, info, info_span, instrument, warn, Instrument}; pub type Counter = u8; const TOTAL_NUM_PEERS: usize = 20; +static INIT: Once = Once::new(); + #[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq)] pub enum CounterMessage { IncrementCounter { @@ -104,7 +107,7 @@ pub async fn spin_up_swarms(num_of_nodes: usize) -> Result> // FIXME change API to accomodate multiple bootstrap nodes let bootstrap = SwarmHandle::new(None).await?; let bootstrap_addr = bootstrap.listen_addr.clone(); - warn!( + info!( "boostrap node {} on addr {}", bootstrap.peer_id, bootstrap_addr ); @@ -123,32 +126,34 @@ pub async fn spin_up_swarms(num_of_nodes: usize) -> Result> } /// general function to spin up testing infra -/// perform tests -/// then return -// pub async fn test_bed(run_test: impl FnOnce(&[Arc]) -> Fut) where -// Fut: Future, -pub async fn test_bed(run_test: F) where +/// perform tests by calling `run_test` +/// then cleanup +pub async fn test_bed(run_test: F) +where Fut: Future, - F: FnOnce(Vec>) -> Fut + F: FnOnce(Vec>) -> Fut, { - color_eyre::install().unwrap(); - networking_demo::tracing_setup::setup_tracing(); + // only call once otherwise panics + // https://github.com/yaahc/color-eyre/issues/78 + INIT.call_once(|| { + color_eyre::install().unwrap(); + networking_demo::tracing_setup::setup_tracing(); + }); + // NOTE we want this to panic if we can't spin up the swarms. // that amounts to a failed test. - let handles : Vec> = spin_up_swarms(TOTAL_NUM_PEERS).await.unwrap().try_into().unwrap(); + let handles: Vec> = spin_up_swarms(TOTAL_NUM_PEERS).await.unwrap(); for handle in handles.iter() { spawn_handler(handle.clone(), handle_event).await; } print_connections(&handles).await; - run_test(handles.clone()).await; // cleanup for handle in handles.into_iter() { handle.kill().await.unwrap(); } - } #[instrument] @@ -240,25 +245,59 @@ pub async fn spawn_handler( ); } +// given a slice of handles assumed to be larger than 0 +// chooses one +// # Panics +// panics if handles is of length 0 +pub fn get_random_handle(handles: &[Arc]) -> Arc { + handles.iter().choose(&mut thread_rng()).unwrap().clone() +} + /// check that we can direct message to increment counter #[async_std::test] #[instrument] async fn test_request_response() { - // NOTE we want this to panic if we can't spin up the swarms. - // that amounts to a failed test. - let handles = spin_up_swarms(3).await.unwrap(); + async fn run_request_response(handles: Vec>) { + let send_handle = get_random_handle(handles.as_slice()); + let recv_handle = get_random_handle(handles.as_slice()); - // cleanup - for handle in handles.into_iter() { - handle.kill().await.unwrap(); + *send_handle.state.lock().await = CounterState(5); + + let bincode_options = bincode::DefaultOptions::new().with_limit(16_384); + let msg_inner = bincode_options + .serialize(&CounterMessage::IncrementCounter { + from: CounterState(0), + to: CounterState(5), + }) + .unwrap(); + let msg = SwarmAction::DirectRequest(recv_handle.peer_id, msg_inner); + send_handle.send_chan.send_async(msg).await.unwrap(); + + // block to let the direction message + // TODO make this event driven + // e.g. everyone receives the gossipmsg event + // or timeout + sleep(Duration::from_millis(10)).await; + + for handle in handles.iter() { + let expected_state = + if handle.peer_id == send_handle.peer_id || handle.peer_id == recv_handle.peer_id { + CounterState(5) + } else { + CounterState::default() + }; + assert_eq!(*handle.state.lock().await, expected_state); + } } + + test_bed(run_request_response).await } /// check that we can broadcast a message out and get counter increments #[async_std::test] #[instrument] async fn test_gossip() { - async fn run_test(handles: Vec>) { + async fn run_gossip(handles: Vec>) { let msg_handle = handles.iter().choose(&mut thread_rng()).unwrap(); *msg_handle.state.lock().await = CounterState(5); let bincode_options = bincode::DefaultOptions::new().with_limit(16_384); @@ -267,20 +306,18 @@ async fn test_gossip() { from: CounterState(0), to: CounterState(5), }) - .unwrap(); + .unwrap(); let (send, recv) = flume::bounded(1); let msg = SwarmAction::GossipMsg(Topic::new("global"), msg_inner, send); msg_handle.send_chan.send_async(msg).await.unwrap(); recv.recv_async().await.unwrap().unwrap(); // block to let the gossipping happen - // TODO make this event driven + // TODO make this event driven // e.g. everyone receives the gossipmsg event // or timeout sleep(Duration::from_millis(10)).await; - print_connections(&handles).await; - let mut failing_idxs = Vec::new(); for (i, handle) in handles.iter().enumerate() { if *handle.state.lock().await != CounterState(5) { @@ -291,24 +328,20 @@ async fn test_gossip() { error!(?failing_idxs, "failing idxs!!"); panic!("some nodes did not receive the message {:?}", failing_idxs); } - } - - - test_bed::<_, _>(run_test).await; - + test_bed(run_gossip).await; } async fn print_connections(handles: &[Arc]) { - error!("PRINTING CONNECTION STATES"); + warn!("PRINTING CONNECTION STATES"); for (i, handle) in handles.iter().enumerate() { - error!( + warn!( "peer {}, connected to {:?}", i, handle.connection_state.lock().await.connected_peers ); - error!( + warn!( "peer {}, knowns about {:?}", i, handle.connection_state.lock().await.known_peers From dc33e7be64f55a030e40742c7062466ee5c15704 Mon Sep 17 00:00:00 2001 From: Justin Restivo Date: Mon, 31 Jan 2022 09:30:59 -0500 Subject: [PATCH 047/107] docs: update README --- libp2p-networking/README | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/libp2p-networking/README b/libp2p-networking/README index 20aa0604ea..ce968fc9bb 100644 --- a/libp2p-networking/README +++ b/libp2p-networking/README @@ -1,5 +1,9 @@ # USAGE +Networking library inteded for use with Phaselock. Builds upon abstractions on libp2p-rs. + +## CLI Demo + To get very verbose logging: ```bash @@ -20,10 +24,21 @@ nix develop -c "RUST_LOG_OUTPUT=OUTFILE_0 RUST_LOG=error cargo run --release -- nix develop -c "RUST_LOG_OUTPUT=OUTFILE_0 RUST_LOG=error cargo run --release -- /ip4/127.0.0.1/tcp/8888 -p 9999" ``` -At this point one may kill/start more nodes. The idea is that each node will continue to attempt to connect to nodes +At this point the idea is that each node will continue to attempt to connect to nodes until it hits at least 5 peers. -Node reconnection has a ui bug but seems to functionally work. I suspect this is a idiosynrasy with -local ports. +Use `Tab` to switch between messages and prompt. Press `Enter` to broadcast a message to all connected nodes. +Press `Right Arrow` to direct-send a message to a randomly selected peer. +Press `q` to quit the program from the messages view. + +## Counter Tests + +`cargo test --release` +spawns off two tests. One that uses gossipsub to broadcast a counter increment, and another that increments a counter directly. +This often times fails on MacOS due to "too many open files." The fix here is: + +```bash +ulimit -n 10240 +``` From b45a54fe457a1f181c89b1fbc97f16a0851195c5 Mon Sep 17 00:00:00 2001 From: Justin Restivo Date: Mon, 31 Jan 2022 11:05:22 -0500 Subject: [PATCH 048/107] docs: add comments --- libp2p-networking/tests/counter.rs | 47 +++++++++++++++++++++--------- 1 file changed, 34 insertions(+), 13 deletions(-) diff --git a/libp2p-networking/tests/counter.rs b/libp2p-networking/tests/counter.rs index cb0ac7f5f1..def0c74702 100644 --- a/libp2p-networking/tests/counter.rs +++ b/libp2p-networking/tests/counter.rs @@ -24,6 +24,10 @@ const TOTAL_NUM_PEERS: usize = 20; static INIT: Once = Once::new(); +/// Message types. We can either +/// - increment the Counter +/// - request a counter value +/// - reply with a counter value #[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq)] pub enum CounterMessage { IncrementCounter { @@ -37,27 +41,32 @@ pub enum CounterMessage { #[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, Default)] pub struct CounterState(Counter); +/// A handle containing: +/// - A reference to the state +/// - Controls for the swarm +/// #[derive(Debug)] pub struct SwarmHandle { - /// the only piece of contested data. + /// the state. TODO make this generic state: Arc>, /// send an action to the networkbehaviour send_chan: Sender, /// receive an action from the networkbehaviour recv_chan: Receiver, - /// kill the networkbheaviour + /// kill the event handler for events from the swarm kill_switch: Sender<()>, - /// receiving end of killing the network behaviour + /// receiving end of `kill_switch` recv_kill: Receiver<()>, /// the local address we're listening on listen_addr: Multiaddr, - /// the peer id + /// the peer id of the networkbehaviour peer_id: PeerId, - /// the connection metadata + /// the connection metadata associated with the networkbehaviour connection_state: Arc>, } impl SwarmHandle { + /// constructs a new node listening on `known_addr` #[instrument] pub async fn new(known_addr: Option) -> Result { //`randomly assigned port @@ -88,6 +97,10 @@ impl SwarmHandle { }) } + /// Cleanly shuts down a swarm node + /// This is done by sending a message to + /// the swarm event handler to stop handling events + /// and a message to the swarm itself to spin down #[instrument] pub async fn kill(&self) -> Result<(), NetworkError> { self.send_chan @@ -102,6 +115,7 @@ impl SwarmHandle { } } +/// spins up `num_of_nodes` nodes and connects them to each other #[instrument] pub async fn spin_up_swarms(num_of_nodes: usize) -> Result>, HandlerError> { // FIXME change API to accomodate multiple bootstrap nodes @@ -127,7 +141,7 @@ pub async fn spin_up_swarms(num_of_nodes: usize) -> Result> /// general function to spin up testing infra /// perform tests by calling `run_test` -/// then cleanup +/// then cleans up tests pub async fn test_bed(run_test: F) where Fut: Future, @@ -156,6 +170,9 @@ where } } +/// event handler for events from the swarm +/// - updates state based on events received +/// - replies to direct messages #[instrument] pub async fn handle_event( event: SwarmResult, @@ -212,8 +229,10 @@ pub async fn handle_event( Ok(()) } -// TODO snafu error handler type that is either a serialization error -// OR channel sending error +/// Glue function that listens for events from the Swarm corresponding to `handle` +/// and calls `event_handler` when an event is observed. +/// The idea is that this function can be used independent of the actual behaviour +/// we want #[instrument(skip(event_handler))] pub async fn spawn_handler( handle: Arc, @@ -241,14 +260,14 @@ pub async fn spawn_handler( } Ok::<(), HandlerError>(()) } - .instrument(info_span!("Libp2p Event Handler")), + .instrument(info_span!("Libp2p Counter Handler")), ); } -// given a slice of handles assumed to be larger than 0 -// chooses one -// # Panics -// panics if handles is of length 0 +/// given a slice of handles assumed to be larger than 0 +/// chooses one +/// # Panics +/// panics if handles is of length 0 pub fn get_random_handle(handles: &[Arc]) -> Arc { handles.iter().choose(&mut thread_rng()).unwrap().clone() } @@ -333,6 +352,8 @@ async fn test_gossip() { test_bed(run_gossip).await; } +/// print the connections for each handle in `handles` +/// useful for debugging async fn print_connections(handles: &[Arc]) { warn!("PRINTING CONNECTION STATES"); for (i, handle) in handles.iter().enumerate() { From a5a1936053127a89ed5cc5ceb4fad93702342f3b Mon Sep 17 00:00:00 2001 From: Justin Restivo Date: Mon, 31 Jan 2022 12:34:03 -0500 Subject: [PATCH 049/107] docs: turn on clippy missing_docs --- libp2p-networking/src/direct_message.rs | 8 ++- libp2p-networking/src/lib.rs | 69 ++++++++++++++++++++----- libp2p-networking/src/message.rs | 4 ++ libp2p-networking/src/tracing_setup.rs | 6 +-- libp2p-networking/src/ui.rs | 1 + libp2p-networking/tests/counter.rs | 4 +- 6 files changed, 70 insertions(+), 22 deletions(-) diff --git a/libp2p-networking/src/direct_message.rs b/libp2p-networking/src/direct_message.rs index 19e42790d8..85f896e5df 100644 --- a/libp2p-networking/src/direct_message.rs +++ b/libp2p-networking/src/direct_message.rs @@ -10,13 +10,17 @@ use libp2p::{ }; use serde::{Deserialize, Serialize}; +/// the protocol for direct messages #[derive(Debug, Clone)] pub struct DirectMessageProtocol(); +/// the codec for direct messages #[derive(Clone, Debug, Serialize, Deserialize)] pub struct DirectMessageCodec(); -#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +/// wrapper type describing a serialized direct message +#[derive(Debug, Clone, PartialEq, Eq)] pub struct DirectMessageRequest(pub Vec); -#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +/// wrapper type describing the response to direct message +#[derive(Debug, Clone, PartialEq, Eq)] pub struct DirectMessageResponse(pub Vec); impl ProtocolName for DirectMessageProtocol { diff --git a/libp2p-networking/src/lib.rs b/libp2p-networking/src/lib.rs index 7cd7f66b54..f6336bf2e9 100644 --- a/libp2p-networking/src/lib.rs +++ b/libp2p-networking/src/lib.rs @@ -2,7 +2,7 @@ clippy::all, clippy::pedantic, rust_2018_idioms, - // missing_docs, + missing_docs, // clippy::missing_docs_in_private_items, clippy::panic )] @@ -13,10 +13,13 @@ clippy::similar_names, clippy::unused_self )] +//! Library for p2p communication // FIXME debug impl for Network, NetworkDef +/// Direct Messages between two nodes pub mod direct_message; +/// wrapper for tracing niceties pub mod tracing_setup; use async_std::task::{sleep, spawn}; @@ -65,11 +68,18 @@ use tracing::{debug, error, info, info_span, instrument, trace, warn, Instrument use crate::direct_message::DirectMessageProtocol; +/// example message used by the UI library pub mod message; +/// UI library for clichat example pub mod ui; #[derive(NetworkBehaviour)] #[behaviour(out_event = "SwarmResult", poll_method = "poll", event_process = true)] +/// Overarching network behaviour performing: +/// - network topology discovoery +/// - direct messaging +/// - p2p broadcast +/// - connection management pub struct NetworkDef { /// purpose: broadcasting messages to many peers /// NOTE gossipsub works ONLY for sharing messsages right now @@ -82,24 +92,33 @@ pub struct NetworkDef { pub identify: Identify, /// purpose: directly messaging peer pub request_response: RequestResponse, + /// if the node has been bootstrapped into the kademlia network #[behaviour(ignore)] pub bootstrap: bool, // TODO separate out into ConnectionData struct + /// set of connected peers #[behaviour(ignore)] pub connected_peers: HashSet, // TODO replace this with a set of queryids + /// set of currently connecting peers #[behaviour(ignore)] pub connecting_peers: HashSet, + /// set of peers that were at one point connected #[behaviour(ignore)] pub known_peers: HashSet, + /// set of events to send to UI #[behaviour(ignore)] - pub ui_events: Vec, + pub client_event_queue: Vec, } +/// metadata about connections #[derive(Default, Debug, Clone)] pub struct ConnectionData { + /// set of currently connecting peers pub connected_peers: HashSet, + /// set of peers that were at one point connected pub connecting_peers: HashSet, + /// set of events to send to UI pub known_peers: HashSet, } @@ -112,9 +131,9 @@ impl NetworkDef { { // push events that must be relayed back to UI onto queue // to be consumed by UI event handler - if !self.ui_events.is_empty() { + if !self.client_event_queue.is_empty() { return Poll::Ready(NetworkBehaviourAction::GenerateEvent( - self.ui_events.remove(0), + self.client_event_queue.remove(0), )); } @@ -126,7 +145,7 @@ impl NetworkBehaviourEventProcess for NetworkDef { fn inject_event(&mut self, event: GossipsubEvent) { info!(?event, "gossipsub msg recv-ed"); if let GossipsubEvent::Message { message, .. } = event { - self.ui_events.push(SwarmResult::GossipMsg(message.data)); + self.client_event_queue.push(SwarmResult::GossipMsg(message.data)); } } } @@ -156,7 +175,7 @@ impl NetworkBehaviourEventProcess for NetworkDef { for peer in peers { self.known_peers.insert(peer); } - self.ui_events + self.client_event_queue .push(SwarmResult::UpdateKnownPeers(self.known_peers.clone())); } _ => {} @@ -169,7 +188,7 @@ impl NetworkBehaviourEventProcess for NetworkDef { .. } => { self.known_peers.insert(peer); - self.ui_events + self.client_event_queue .push(SwarmResult::UpdateKnownPeers(self.known_peers.clone())); } _ => {} @@ -184,7 +203,7 @@ impl NetworkBehaviourEventProcess for NetworkDef { self.kadem.add_address(&peer_id, addr.clone()); } self.known_peers.insert(peer_id); - self.ui_events + self.client_event_queue .push(SwarmResult::UpdateKnownPeers(self.known_peers.clone())); } } @@ -204,48 +223,68 @@ impl NetworkBehaviourEventProcess { - self.ui_events + self.client_event_queue .push(SwarmResult::DirectRequest(msg, channel)); } RequestResponseMessage::Response { response: DirectMessageResponse(msg), .. } => { - self.ui_events.push(SwarmResult::DirectResponse(msg)); + self.client_event_queue.push(SwarmResult::DirectResponse(msg)); } } } } } +/// Network definition pub struct Network { + /// pub/private key from with peer_id is derived pub identity: Keypair, + /// peer id of network node pub peer_id: PeerId, + /// TODO do we need this pub broadcast_topic: Topic, + /// the swarm of networkbehaviours pub swarm: Swarm, + /// maximum number of connections to maintain pub max_num_peers: usize, + /// minimum numer of connections to maintain pub min_num_peers: usize, } +/// Actions to send from the client to the swarm #[derive(Debug)] pub enum SwarmAction { + /// kill the swarm Shutdown, + /// broadcast a serialized message GossipMsg(Topic, Vec, Sender>), + /// send the peer id GetId(Sender), + /// subscribe to a topic Subscribe(String), + /// unsubscribe from a topic Unsubscribe(String), + /// direct message a serialized message DirectRequest(PeerId, Vec), + /// direct reply to a message DirectResponse(ResponseChannel, Vec), } /// events generated by the swarm that we wish -/// to relay to UI +/// to relay to the client #[derive(Debug)] pub enum SwarmResult { + /// connected to a new peer UpdateConnectedPeers(HashSet), + /// discovered a new peer UpdateKnownPeers(HashSet), + /// recv-ed a broadcast GossipMsg(Vec), + /// recv-ed a direct message from a node DirectRequest(Vec, ResponseChannel), + /// recv-ed a direct response from a node DirectResponse(Vec), } @@ -400,7 +439,7 @@ impl Network { connected_peers: HashSet::new(), connecting_peers: HashSet::new(), known_peers: HashSet::new(), - ui_events: Vec::new(), + client_event_queue: Vec::new(), bootstrap: false, }; @@ -718,6 +757,7 @@ impl Network { } } +/// wrapper type for errors generated by the `Network` #[derive(Debug, Snafu)] pub enum NetworkError { /// Error during dialing or listening @@ -748,7 +788,10 @@ pub enum NetworkError { /// the type of message. StreamClosed, /// Error publishing a gossipsub message - PublishError { source: PublishError }, + PublishError { + /// The underlying source of the error + source: PublishError + }, /// Error when there are no known peers to bootstrap off NoKnownPeers, } diff --git a/libp2p-networking/src/message.rs b/libp2p-networking/src/message.rs index 7377b4f2f2..53d66df80f 100644 --- a/libp2p-networking/src/message.rs +++ b/libp2p-networking/src/message.rs @@ -1,8 +1,12 @@ use serde::{Deserialize, Serialize}; +/// example message that may be sent to the swarm. Used in the UI #[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq)] pub struct Message { + /// the peerid of the sende4r pub sender: String, + /// the content of the message pub content: String, + /// the topic associated with the msg pub topic: String, } diff --git a/libp2p-networking/src/tracing_setup.rs b/libp2p-networking/src/tracing_setup.rs index aa32fb2f13..ced710372e 100644 --- a/libp2p-networking/src/tracing_setup.rs +++ b/libp2p-networking/src/tracing_setup.rs @@ -100,12 +100,8 @@ fn internal_setup_tracing(writer: BoxMakeWriter) { }; } +/// set up the tracer pub fn setup_tracing() { let writer = parse_writer(); internal_setup_tracing(writer); } - -pub fn setup_tracing_test() { - let writer = BoxMakeWriter::new(fmt::writer::TestWriter::new()); - internal_setup_tracing(writer); -} diff --git a/libp2p-networking/src/ui.rs b/libp2p-networking/src/ui.rs index 9a39b70e27..391119ad8c 100644 --- a/libp2p-networking/src/ui.rs +++ b/libp2p-networking/src/ui.rs @@ -1,3 +1,4 @@ +#![allow(missing_docs)] use async_std::task::{sleep, spawn}; use bincode::Options; diff --git a/libp2p-networking/tests/counter.rs b/libp2p-networking/tests/counter.rs index def0c74702..03970e7d53 100644 --- a/libp2p-networking/tests/counter.rs +++ b/libp2p-networking/tests/counter.rs @@ -148,7 +148,7 @@ where F: FnOnce(Vec>) -> Fut, { // only call once otherwise panics - // https://github.com/yaahc/color-eyre/issues/78 + // INIT.call_once(|| { color_eyre::install().unwrap(); networking_demo::tracing_setup::setup_tracing(); @@ -215,7 +215,7 @@ pub async fn handle_event( } // NOTE doesn't make sense as request type // TODO maybe should check this at the type level - CounterMessage::MyCounterIs(_) => {} + MyCounterIs(_) => {} } } } From ca029c1ad31c99ebee82d9a6aa9485ab5eb298a2 Mon Sep 17 00:00:00 2001 From: Justin Restivo Date: Mon, 31 Jan 2022 12:39:47 -0500 Subject: [PATCH 050/107] chore: remove clippy warnings --- libp2p-networking/src/lib.rs | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/libp2p-networking/src/lib.rs b/libp2p-networking/src/lib.rs index f6336bf2e9..8380fd7a8c 100644 --- a/libp2p-networking/src/lib.rs +++ b/libp2p-networking/src/lib.rs @@ -145,7 +145,8 @@ impl NetworkBehaviourEventProcess for NetworkDef { fn inject_event(&mut self, event: GossipsubEvent) { info!(?event, "gossipsub msg recv-ed"); if let GossipsubEvent::Message { message, .. } = event { - self.client_event_queue.push(SwarmResult::GossipMsg(message.data)); + self.client_event_queue + .push(SwarmResult::GossipMsg(message.data)); } } } @@ -230,7 +231,8 @@ impl NetworkBehaviourEventProcess { - self.client_event_queue.push(SwarmResult::DirectResponse(msg)); + self.client_event_queue + .push(SwarmResult::DirectResponse(msg)); } } } @@ -617,6 +619,7 @@ impl Network { } /// event handler for events emited from the swarm + #[allow(clippy::type_complexity)] #[instrument(skip(self))] async fn handle_swarm_events( &mut self, @@ -712,12 +715,7 @@ impl Network { /// Spawn a task to listen for requests on the returned channel /// as well as any events produced by libp2p /// `mut_mut` is disabled b/c must consume `self` - #[allow( - clippy::mut_mut, - clippy::panic, - clippy::single_match, - clippy::collapsible_match - )] + #[allow(clippy::panic)] #[instrument(skip(self))] pub async fn spawn_listeners( mut self, @@ -788,9 +786,9 @@ pub enum NetworkError { /// the type of message. StreamClosed, /// Error publishing a gossipsub message - PublishError { + PublishError { /// The underlying source of the error - source: PublishError + source: PublishError, }, /// Error when there are no known peers to bootstrap off NoKnownPeers, From 00de825a269d0edeeb162bec425572cffcaefd2d Mon Sep 17 00:00:00 2001 From: Justin Restivo Date: Mon, 31 Jan 2022 13:06:12 -0500 Subject: [PATCH 051/107] feat: split out bootstrap and regular nodes --- libp2p-networking/examples/clichat.rs | 6 ++++-- libp2p-networking/examples/counter.rs | 12 +----------- libp2p-networking/src/lib.rs | 27 +++++++++++++++++++++------ libp2p-networking/tests/counter.rs | 14 +++++++++----- 4 files changed, 35 insertions(+), 24 deletions(-) diff --git a/libp2p-networking/examples/clichat.rs b/libp2p-networking/examples/clichat.rs index f229ff6feb..c446f909c9 100644 --- a/libp2p-networking/examples/clichat.rs +++ b/libp2p-networking/examples/clichat.rs @@ -17,7 +17,7 @@ use parking_lot::Mutex; use tracing::instrument; use tui::{backend::CrosstermBackend, Terminal}; -use networking_demo::{gen_multiaddr, Network, SwarmAction}; +use networking_demo::{gen_multiaddr, NetworkNode, NetworkNodeType, SwarmAction}; /// command line arguments #[derive(StructOpt)] @@ -37,7 +37,9 @@ async fn main() -> Result<()> { color_eyre::install()?; networking_demo::tracing_setup::setup_tracing(); // -- Spin up the network connection - let mut networking: Network = Network::new().await.context("Failed to launch network")?; + let mut networking: NetworkNode = NetworkNode::new(NetworkNodeType::Regular) + .await + .context("Failed to launch network")?; let port = CliOpt::from_args().port.unwrap_or(0u16); let known_peer = CliOpt::from_args().first_dial; let listen_addr = gen_multiaddr(port); diff --git a/libp2p-networking/examples/counter.rs b/libp2p-networking/examples/counter.rs index 24acd719f1..718083f2b2 100644 --- a/libp2p-networking/examples/counter.rs +++ b/libp2p-networking/examples/counter.rs @@ -6,7 +6,7 @@ use color_eyre::eyre::{Result, WrapErr}; use tracing::instrument; -use networking_demo::{gen_multiaddr, Network}; +use networking_demo::{gen_multiaddr, NetworkNode}; /// command line arguments #[derive(StructOpt)] @@ -22,15 +22,5 @@ struct CliOpt { #[async_std::main] #[instrument] async fn main() -> Result<()> { - // -- Setup color_eyre and tracing - color_eyre::install()?; - networking_demo::tracing_setup::setup_tracing(); - // -- Spin up the network connection - let mut networking: Network = Network::new().await.context("Failed to launch network")?; - let port = CliOpt::from_args().port.unwrap_or(0u16); - let known_peer = CliOpt::from_args().first_dial; - let listen_addr = gen_multiaddr(port); - networking.start(listen_addr, known_peer).await?; - let (_send_chan, _recv_chan) = networking.spawn_listeners().await?; todo!() } diff --git a/libp2p-networking/src/lib.rs b/libp2p-networking/src/lib.rs index 8380fd7a8c..9da5acdeeb 100644 --- a/libp2p-networking/src/lib.rs +++ b/libp2p-networking/src/lib.rs @@ -239,8 +239,19 @@ impl NetworkBehaviourEventProcess std::io::Result Result { + pub async fn new(node_type: NetworkNodeType) -> Result { // Generate a random PeerId let identity = Keypair::generate_ed25519(); let peer_id = PeerId::from(identity.public()); @@ -455,6 +468,7 @@ impl Network { max_num_peers: 600, min_num_peers: 50, swarm, + node_type, }) } @@ -510,9 +524,10 @@ impl Network { }; } } - // TODO fix this so it does *not* happen on bootstrap nodes - // will need to introduce node types - else if swarm.connected_peers.len() > self.max_num_peers { + // NOTE only prune node connections if we aren't a bootstrap node + else if swarm.connected_peers.len() > self.max_num_peers + && self.node_type == NetworkNodeType::Regular + { // If we are connected to too many peers, try disconnecting from // a random (?) subset let peers_to_rm = swarm.connected_peers.iter().copied().choose_multiple( diff --git a/libp2p-networking/tests/counter.rs b/libp2p-networking/tests/counter.rs index 03970e7d53..c2bd24cbb4 100644 --- a/libp2p-networking/tests/counter.rs +++ b/libp2p-networking/tests/counter.rs @@ -9,7 +9,8 @@ use flume::{Receiver, RecvError, SendError, Sender}; use futures::{select, Future, FutureExt}; use libp2p::{gossipsub::Topic, Multiaddr, PeerId}; use networking_demo::{ - gen_multiaddr, ConnectionData, Network, NetworkError, SwarmAction, SwarmResult, + gen_multiaddr, ConnectionData, NetworkError, NetworkNode, NetworkNodeType, SwarmAction, + SwarmResult, }; use rand::{seq::IteratorRandom, thread_rng}; @@ -68,10 +69,13 @@ pub struct SwarmHandle { impl SwarmHandle { /// constructs a new node listening on `known_addr` #[instrument] - pub async fn new(known_addr: Option) -> Result { + pub async fn new( + known_addr: Option, + node_type: NetworkNodeType, + ) -> Result { //`randomly assigned port let listen_addr = gen_multiaddr(0); - let mut network = Network::new().await.context(NetworkSnafu)?; + let mut network = NetworkNode::new(node_type).await.context(NetworkSnafu)?; let peer_id = network.peer_id; let listen_addr = network .start(listen_addr, known_addr) @@ -119,7 +123,7 @@ impl SwarmHandle { #[instrument] pub async fn spin_up_swarms(num_of_nodes: usize) -> Result>, HandlerError> { // FIXME change API to accomodate multiple bootstrap nodes - let bootstrap = SwarmHandle::new(None).await?; + let bootstrap = SwarmHandle::new(None, NetworkNodeType::Bootstrap).await?; let bootstrap_addr = bootstrap.listen_addr.clone(); info!( "boostrap node {} on addr {}", @@ -132,7 +136,7 @@ pub async fn spin_up_swarms(num_of_nodes: usize) -> Result> let mut handles = Vec::new(); for _ in 0..(num_of_nodes - 1) { handles.push(Arc::new( - SwarmHandle::new(Some(bootstrap_addr.clone())).await?, + SwarmHandle::new(Some(bootstrap_addr.clone()), NetworkNodeType::Regular).await?, )); sleep(Duration::from_secs(1)).await; } From 75e95181d9cb8d123f08eadd042b1ca0d7a14cc7 Mon Sep 17 00:00:00 2001 From: Justin Restivo Date: Mon, 31 Jan 2022 13:35:12 -0500 Subject: [PATCH 052/107] feat: Debug impls for Network, NetworkDef --- libp2p-networking/examples/counter.rs | 24 +----------------------- libp2p-networking/src/lib.rs | 27 +++++++++++++++++++++++++-- libp2p-networking/tests/counter.rs | 2 +- 3 files changed, 27 insertions(+), 26 deletions(-) diff --git a/libp2p-networking/examples/counter.rs b/libp2p-networking/examples/counter.rs index 718083f2b2..4804093a64 100644 --- a/libp2p-networking/examples/counter.rs +++ b/libp2p-networking/examples/counter.rs @@ -1,26 +1,4 @@ -use libp2p::Multiaddr; - -use structopt::StructOpt; - -use color_eyre::eyre::{Result, WrapErr}; - -use tracing::instrument; - -use networking_demo::{gen_multiaddr, NetworkNode}; - -/// command line arguments -#[derive(StructOpt)] -struct CliOpt { - /// Path to the node configuration file - #[structopt(long = "port", short = "p")] - port: Option, - - #[structopt()] - first_dial: Option, -} - #[async_std::main] -#[instrument] -async fn main() -> Result<()> { +async fn main() { todo!() } diff --git a/libp2p-networking/src/lib.rs b/libp2p-networking/src/lib.rs index 9da5acdeeb..f6ae7e288d 100644 --- a/libp2p-networking/src/lib.rs +++ b/libp2p-networking/src/lib.rs @@ -15,8 +15,6 @@ )] //! Library for p2p communication -// FIXME debug impl for Network, NetworkDef - /// Direct Messages between two nodes pub mod direct_message; /// wrapper for tracing niceties @@ -25,6 +23,7 @@ pub mod tracing_setup; use async_std::task::{sleep, spawn}; use direct_message::{DirectMessageCodec, DirectMessageRequest, DirectMessageResponse}; use rand::{seq::IteratorRandom, thread_rng}; +use std::fmt::Debug; use std::{ collections::HashSet, io::Error, @@ -111,6 +110,17 @@ pub struct NetworkDef { pub client_event_queue: Vec, } +impl Debug for NetworkDef { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.debug_struct("NetworkDef") + .field("bootstrap", &self.bootstrap) + .field("connected_peers", &self.connected_peers) + .field("connecting_peers", &self.connecting_peers) + .field("known_peers", &self.known_peers) + .finish() + } +} + /// metadata about connections #[derive(Default, Debug, Clone)] pub struct ConnectionData { @@ -268,6 +278,19 @@ pub struct NetworkNode { pub node_type: NetworkNodeType, } +impl Debug for NetworkNode { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.debug_struct("Network") + .field("peer_id", &self.peer_id) + .field("broadcast_topic", &self.broadcast_topic) + .field("swarm", self.swarm.behaviour()) + .field("max_num_peers", &self.max_num_peers) + .field("min_num_peers", &self.min_num_peers) + .field("node_type", &self.node_type) + .finish() + } +} + /// Actions to send from the client to the swarm #[derive(Debug)] pub enum SwarmAction { diff --git a/libp2p-networking/tests/counter.rs b/libp2p-networking/tests/counter.rs index c2bd24cbb4..6b1c190d00 100644 --- a/libp2p-networking/tests/counter.rs +++ b/libp2p-networking/tests/counter.rs @@ -300,7 +300,7 @@ async fn test_request_response() { // TODO make this event driven // e.g. everyone receives the gossipmsg event // or timeout - sleep(Duration::from_millis(10)).await; + sleep(Duration::from_secs(1)).await; for handle in handles.iter() { let expected_state = From 719674f04e806ac259bcf016545110a6339c25b4 Mon Sep 17 00:00:00 2001 From: Justin Restivo Date: Tue, 1 Feb 2022 09:29:31 -0500 Subject: [PATCH 053/107] feat: generic state --- libp2p-networking/examples/clichat.rs | 4 +- libp2p-networking/flake.lock | 18 ++-- libp2p-networking/src/lib.rs | 75 +++++++++-------- libp2p-networking/src/ui.rs | 25 +++--- libp2p-networking/tests/counter.rs | 114 ++++++++++++++------------ 5 files changed, 121 insertions(+), 115 deletions(-) diff --git a/libp2p-networking/examples/clichat.rs b/libp2p-networking/examples/clichat.rs index c446f909c9..dd83a4528e 100644 --- a/libp2p-networking/examples/clichat.rs +++ b/libp2p-networking/examples/clichat.rs @@ -17,7 +17,7 @@ use parking_lot::Mutex; use tracing::instrument; use tui::{backend::CrosstermBackend, Terminal}; -use networking_demo::{gen_multiaddr, NetworkNode, NetworkNodeType, SwarmAction}; +use networking_demo::{gen_multiaddr, ClientRequest, NetworkNode, NetworkNodeType}; /// command line arguments #[derive(StructOpt)] @@ -83,7 +83,7 @@ async fn main() -> Result<()> { // -- Create the app and run it let app = TableApp::new(message_buffer.clone(), send_chan, recv_chan); app.send_swarm - .send(SwarmAction::Subscribe("global".to_string()))?; + .send(ClientRequest::Subscribe("global".to_string()))?; let res = run_app(&mut terminal, app).await; // -- Tear down the TUI, and restore the terminal disable_raw_mode()?; diff --git a/libp2p-networking/flake.lock b/libp2p-networking/flake.lock index 7dd05b06fe..40258af6db 100644 --- a/libp2p-networking/flake.lock +++ b/libp2p-networking/flake.lock @@ -25,11 +25,11 @@ "rust-analyzer-src": "rust-analyzer-src" }, "locked": { - "lastModified": 1643264637, - "narHash": "sha256-jR8Cke8Ukj0ZcpmHaz+TcpUzL5O1xtiEinzbvx4PMfU=", + "lastModified": 1643610217, + "narHash": "sha256-3cFZt9Eyz70s1CNYO3wJeUDgLUC9tC4s5hNpLtX3FQY=", "owner": "nix-community", "repo": "fenix", - "rev": "51cf29a5c001389a5781b4115315dd2012590551", + "rev": "bd91b6fddf7fdf90ad9924339fcb40f008f57447", "type": "github" }, "original": { @@ -56,11 +56,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1641760999, - "narHash": "sha256-UhSV8Qe8TBrZksBZSYqwNsWFY7EgCJCJTlRxXJSL4Jg=", + "lastModified": 1643381941, + "narHash": "sha256-pHTwvnN4tTsEKkWlXQ8JMY423epos8wUOhthpwJjtpc=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "8928525bd8b8cdc1235a92a89b72cbbe5bd8a00d", + "rev": "5efc8ca954272c4376ac929f4c5ffefcc20551d5", "type": "github" }, "original": { @@ -82,11 +82,11 @@ "rust-analyzer-src": { "flake": false, "locked": { - "lastModified": 1643220707, - "narHash": "sha256-XMBer+U/1WqPu25aJs/LkMxrnJnEKiezsAtfSpkkPik=", + "lastModified": 1643580505, + "narHash": "sha256-6+d/x7ZIyvkPLdn7ziXuPyKfxt/7z5PCWs7B960DFqk=", "owner": "rust-analyzer", "repo": "rust-analyzer", - "rev": "e149a15edd354dd0f995532d16a3e8dc21367e06", + "rev": "fd3942eb620e37a4e4bfdd587d8a2893ccf6fea0", "type": "github" }, "original": { diff --git a/libp2p-networking/src/lib.rs b/libp2p-networking/src/lib.rs index f6ae7e288d..1b6ee56d99 100644 --- a/libp2p-networking/src/lib.rs +++ b/libp2p-networking/src/lib.rs @@ -72,18 +72,18 @@ pub mod message; /// UI library for clichat example pub mod ui; -#[derive(NetworkBehaviour)] -#[behaviour(out_event = "SwarmResult", poll_method = "poll", event_process = true)] /// Overarching network behaviour performing: /// - network topology discovoery /// - direct messaging /// - p2p broadcast /// - connection management +#[derive(NetworkBehaviour)] +#[behaviour(out_event = "NetworkEvent", poll_method = "poll", event_process = true)] pub struct NetworkDef { /// purpose: broadcasting messages to many peers /// NOTE gossipsub works ONLY for sharing messsages right now /// in the future it may be able to do peer discovery and routing - /// https://github.com/libp2p/rust-libp2p/issues/2398 + /// <`https://github.com/libp2p/rust-libp2p/issues/2398> pub gossipsub: Gossipsub, /// purpose: peer routing pub kadem: Kademlia, @@ -107,7 +107,7 @@ pub struct NetworkDef { pub known_peers: HashSet, /// set of events to send to UI #[behaviour(ignore)] - pub client_event_queue: Vec, + pub client_event_queue: Vec, } impl Debug for NetworkDef { @@ -137,7 +137,7 @@ impl NetworkDef { &mut self, _cx: &mut Context<'_>, _: &mut impl PollParameters, - ) -> Poll::ProtocolsHandler>> + ) -> Poll::ProtocolsHandler>> { // push events that must be relayed back to UI onto queue // to be consumed by UI event handler @@ -156,7 +156,7 @@ impl NetworkBehaviourEventProcess for NetworkDef { info!(?event, "gossipsub msg recv-ed"); if let GossipsubEvent::Message { message, .. } = event { self.client_event_queue - .push(SwarmResult::GossipMsg(message.data)); + .push(NetworkEvent::GossipMsg(message.data)); } } } @@ -187,7 +187,7 @@ impl NetworkBehaviourEventProcess for NetworkDef { self.known_peers.insert(peer); } self.client_event_queue - .push(SwarmResult::UpdateKnownPeers(self.known_peers.clone())); + .push(NetworkEvent::UpdateKnownPeers(self.known_peers.clone())); } _ => {} } @@ -200,7 +200,7 @@ impl NetworkBehaviourEventProcess for NetworkDef { } => { self.known_peers.insert(peer); self.client_event_queue - .push(SwarmResult::UpdateKnownPeers(self.known_peers.clone())); + .push(NetworkEvent::UpdateKnownPeers(self.known_peers.clone())); } _ => {} } @@ -215,7 +215,7 @@ impl NetworkBehaviourEventProcess for NetworkDef { } self.known_peers.insert(peer_id); self.client_event_queue - .push(SwarmResult::UpdateKnownPeers(self.known_peers.clone())); + .push(NetworkEvent::UpdateKnownPeers(self.known_peers.clone())); } } } @@ -235,14 +235,14 @@ impl NetworkBehaviourEventProcess { self.client_event_queue - .push(SwarmResult::DirectRequest(msg, channel)); + .push(NetworkEvent::DirectRequest(msg, channel)); } RequestResponseMessage::Response { response: DirectMessageResponse(msg), .. } => { self.client_event_queue - .push(SwarmResult::DirectResponse(msg)); + .push(NetworkEvent::DirectResponse(msg)); } } } @@ -260,14 +260,14 @@ pub enum NetworkNodeType { Regular, } +// FIXME split this out into network config + swarm + /// Network definition pub struct NetworkNode { /// pub/private key from with peer_id is derived pub identity: Keypair, /// peer id of network node pub peer_id: PeerId, - /// TODO do we need this - pub broadcast_topic: Topic, /// the swarm of networkbehaviours pub swarm: Swarm, /// maximum number of connections to maintain @@ -282,7 +282,6 @@ impl Debug for NetworkNode { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { f.debug_struct("Network") .field("peer_id", &self.peer_id) - .field("broadcast_topic", &self.broadcast_topic) .field("swarm", self.swarm.behaviour()) .field("max_num_peers", &self.max_num_peers) .field("min_num_peers", &self.min_num_peers) @@ -293,7 +292,7 @@ impl Debug for NetworkNode { /// Actions to send from the client to the swarm #[derive(Debug)] -pub enum SwarmAction { +pub enum ClientRequest { /// kill the swarm Shutdown, /// broadcast a serialized message @@ -313,7 +312,7 @@ pub enum SwarmAction { /// events generated by the swarm that we wish /// to relay to the client #[derive(Debug)] -pub enum SwarmResult { +pub enum NetworkEvent { /// connected to a new peer UpdateConnectedPeers(HashSet), /// discovered a new peer @@ -337,10 +336,14 @@ pub fn gen_multiaddr(port: u16) -> Multiaddr { /// # Errors /// could not sign the noise key with `identity` #[instrument(skip(identity))] -pub async fn gen_transport(identity: Keypair) -> std::io::Result> { +pub async fn gen_transport( + identity: Keypair, +) -> Result, NetworkError> { let transport = { let tcp = tcp::TcpConfig::new().nodelay(true); - let dns_tcp = dns::DnsConfig::system(tcp).await?; + let dns_tcp = dns::DnsConfig::system(tcp) + .await + .context(TransportLaunchSnafu)?; let ws_dns_tcp = websocket::WsConfig::new(dns_tcp.clone()); dns_tcp.or_transport(ws_dns_tcp) }; @@ -402,7 +405,8 @@ impl NetworkNode { /// /// Currently: /// * Generates a random key pair and associated [`PeerId`] - /// * Launches a development-only type of transport backend + /// * Launches a hopefully production ready transport: + /// TCP + DNS + Websocket + XX auth /// * Generates a connection to the "broadcast" topic /// * Creates a swarm to manage peers and events #[instrument] @@ -411,12 +415,8 @@ impl NetworkNode { let identity = Keypair::generate_ed25519(); let peer_id = PeerId::from(identity.public()); debug!(?peer_id); - let transport: Boxed<(PeerId, StreamMuxerBox)> = - libp2p::development_transport(identity.clone()) - .await - .context(TransportLaunchSnafu)?; + let transport: Boxed<(PeerId, StreamMuxerBox)> = gen_transport(identity.clone()).await?; trace!("Launched network transport"); - let broadcast_topic = Topic::new("broadcast"); // Generate the swarm let swarm: Swarm = { // Use the hash of the message's contents as the ID @@ -487,7 +487,6 @@ impl NetworkNode { Ok(Self { identity, peer_id, - broadcast_topic, max_num_peers: 600, min_num_peers: 50, swarm, @@ -574,20 +573,20 @@ impl NetworkNode { /// - unsubscribing from a toipc /// - direct messaging a peer #[instrument(skip(self))] - async fn handle_ui_events( + async fn handle_client_requests( &mut self, - msg: Result, + msg: Result, ) -> Result { match msg { Ok(msg) => { #[allow(clippy::enum_glob_use)] - use SwarmAction::*; + use ClientRequest::*; match msg { Shutdown => { warn!("Libp2p listener shutting down"); return Ok(true); } - SwarmAction::GossipMsg(topic, contents, chan) => { + ClientRequest::GossipMsg(topic, contents, chan) => { let res = self .swarm .behaviour_mut() @@ -662,13 +661,13 @@ impl NetworkNode { async fn handle_swarm_events( &mut self, event: SwarmEvent< - SwarmResult, + NetworkEvent, EitherError< EitherError, Error>, ProtocolsHandlerUpgrErr, >, >, - send_to_ui: &Sender, + send_to_ui: &Sender, ) -> Result<(), NetworkError> { // Make the match cleaner #[allow(clippy::enum_glob_use)] @@ -707,7 +706,7 @@ impl NetworkNode { .map_err(|_e| NetworkError::NoKnownPeers)?; } send_to_ui - .send_async(SwarmResult::UpdateConnectedPeers( + .send_async(NetworkEvent::UpdateConnectedPeers( self.swarm.behaviour_mut().connected_peers.clone(), )) .await @@ -720,13 +719,13 @@ impl NetworkNode { swarm.kadem.remove_peer(&peer_id); send_to_ui - .send_async(SwarmResult::UpdateConnectedPeers( + .send_async(NetworkEvent::UpdateConnectedPeers( swarm.connected_peers.clone(), )) .await .map_err(|_e| NetworkError::StreamClosed)?; send_to_ui - .send_async(SwarmResult::UpdateKnownPeers(swarm.known_peers.clone())) + .send_async(NetworkEvent::UpdateKnownPeers(swarm.known_peers.clone())) .await .map_err(|_e| NetworkError::StreamClosed)?; } @@ -757,9 +756,9 @@ impl NetworkNode { #[instrument(skip(self))] pub async fn spawn_listeners( mut self, - ) -> Result<(Sender, Receiver), NetworkError> { - let (s_input, s_output) = unbounded::(); - let (r_input, r_output) = unbounded::(); + ) -> Result<(Sender, Receiver), NetworkError> { + let (s_input, s_output) = unbounded::(); + let (r_input, r_output) = unbounded::(); spawn( async move { @@ -778,7 +777,7 @@ impl NetworkNode { } }, msg = s_output.recv_async() => { - let shutdown = self.handle_ui_events(msg).await?; + let shutdown = self.handle_client_requests(msg).await?; if shutdown { break } diff --git a/libp2p-networking/src/ui.rs b/libp2p-networking/src/ui.rs index 391119ad8c..41316a0d52 100644 --- a/libp2p-networking/src/ui.rs +++ b/libp2p-networking/src/ui.rs @@ -1,6 +1,7 @@ #![allow(missing_docs)] use async_std::task::{sleep, spawn}; +use crate::NetworkEvent; use bincode::Options; use color_eyre::{ eyre::{Result, WrapErr}, @@ -26,7 +27,7 @@ use tui::{ Frame, Terminal, }; -use crate::{message::Message, SwarmAction, SwarmResult}; +use crate::{message::Message, ClientRequest}; #[derive(Debug, Copy, Clone)] pub enum InputMode { @@ -37,8 +38,8 @@ pub enum InputMode { #[derive(Debug)] /// Struct for the TUI app pub struct TableApp { - pub send_swarm: Sender, - pub recv_swarm: Receiver, + pub send_swarm: Sender, + pub recv_swarm: Receiver, pub input_mode: InputMode, pub input: String, pub state: TableState, @@ -51,8 +52,8 @@ impl TableApp { #[instrument] pub fn new( message_buffer: Arc>>, - send_swarm: Sender, - recv_swarm: Receiver, + send_swarm: Sender, + recv_swarm: Receiver, ) -> Self { Self { send_swarm, @@ -94,7 +95,7 @@ impl TableApp { #[instrument(skip(terminal, app))] pub async fn run_app(terminal: &mut Terminal, mut app: TableApp) -> Result<()> { #[allow(clippy::enum_glob_use)] - use SwarmResult::*; + use NetworkEvent::*; let mut events = event::EventStream::new(); loop { terminal @@ -107,7 +108,7 @@ pub async fn run_app(terminal: &mut Terminal, mut app: TableApp) swarm_msg = app.recv_swarm.recv_async() => { if let Ok(res) = swarm_msg { match res { - DirectRequest(m, _) | SwarmResult::GossipMsg(m) => { + DirectRequest(m, _) | GossipMsg(m) => { let bincode_options = bincode::DefaultOptions::new().with_limit(16_384); let msg : Message = bincode_options.deserialize(&m)?; app.message_buffer.lock().push_back(msg); @@ -129,7 +130,7 @@ pub async fn run_app(terminal: &mut Terminal, mut app: TableApp) InputMode::Normal => { match key.code { KeyCode::Char('q') => { - app.send_swarm.send_async(SwarmAction::Shutdown).await?; + app.send_swarm.send_async(ClientRequest::Shutdown).await?; return Ok(()); } KeyCode::Down | KeyCode::Char('j') => app.next(), @@ -150,7 +151,7 @@ pub async fn run_app(terminal: &mut Terminal, mut app: TableApp) if let Some(selected_peer) = app.connected_peer_list.lock().iter().copied().next() { spawn(async move { let (s, r) = flume::bounded(1); - send_swarm.send_async(SwarmAction::GetId(s)).await.context("")?; + send_swarm.send_async(ClientRequest::GetId(s)).await.context("")?; let msg = Message { topic: "DM".to_string(), content: app.input, @@ -158,7 +159,7 @@ pub async fn run_app(terminal: &mut Terminal, mut app: TableApp) }; let bincode_options = bincode::DefaultOptions::new().with_limit(16_384); let s_msg = bincode_options.serialize(&msg)?; - send_swarm.send_async(SwarmAction::DirectRequest(selected_peer, s_msg)).await?; + send_swarm.send_async(ClientRequest::DirectRequest(selected_peer, s_msg)).await?; mb_handle.lock().push_back(msg); // if it's a duplicate message (error case), fail silently and do nothing Result::<(), Report>::Ok(()) @@ -174,7 +175,7 @@ pub async fn run_app(terminal: &mut Terminal, mut app: TableApp) // we don't want this to block the event loop spawn(async move { let (s, r) = flume::bounded(1); - send_swarm.send_async(SwarmAction::GetId(s)).await.context("")?; + send_swarm.send_async(ClientRequest::GetId(s)).await.context("")?; let msg = Message { topic: "global".to_string(), content: app.input, @@ -183,7 +184,7 @@ pub async fn run_app(terminal: &mut Terminal, mut app: TableApp) let (s, r) = flume::bounded(1); let bincode_options = bincode::DefaultOptions::new().with_limit(16_384); let s_msg = bincode_options.serialize(&msg)?; - send_swarm.send_async(SwarmAction::GossipMsg(Topic::new(msg.topic.clone()), s_msg, s)).await?; + send_swarm.send_async(ClientRequest::GossipMsg(Topic::new(msg.topic.clone()), s_msg, s)).await?; // if it's a duplicate message (error case), fail silently and do nothing if r.recv_async().await?.is_ok() { mb_handle.lock().push_back(msg); diff --git a/libp2p-networking/tests/counter.rs b/libp2p-networking/tests/counter.rs index 6b1c190d00..7253e67202 100644 --- a/libp2p-networking/tests/counter.rs +++ b/libp2p-networking/tests/counter.rs @@ -9,10 +9,11 @@ use flume::{Receiver, RecvError, SendError, Sender}; use futures::{select, Future, FutureExt}; use libp2p::{gossipsub::Topic, Multiaddr, PeerId}; use networking_demo::{ - gen_multiaddr, ConnectionData, NetworkError, NetworkNode, NetworkNodeType, SwarmAction, - SwarmResult, + gen_multiaddr, ClientRequest, ConnectionData, NetworkError, NetworkEvent, NetworkNode, + NetworkNodeType, }; use rand::{seq::IteratorRandom, thread_rng}; +use std::fmt::Debug; use serde::{Deserialize, Serialize}; @@ -47,13 +48,13 @@ pub struct CounterState(Counter); /// - Controls for the swarm /// #[derive(Debug)] -pub struct SwarmHandle { +pub struct SwarmHandle { /// the state. TODO make this generic - state: Arc>, + state: Arc>, /// send an action to the networkbehaviour - send_chan: Sender, + send_chan: Sender, /// receive an action from the networkbehaviour - recv_chan: Receiver, + recv_chan: Receiver, /// kill the event handler for events from the swarm kill_switch: Sender<()>, /// receiving end of `kill_switch` @@ -66,7 +67,7 @@ pub struct SwarmHandle { connection_state: Arc>, } -impl SwarmHandle { +impl SwarmHandle { /// constructs a new node listening on `known_addr` #[instrument] pub async fn new( @@ -85,12 +86,12 @@ impl SwarmHandle { let (kill_switch, recv_kill) = flume::bounded(1); send_chan - .send_async(SwarmAction::Subscribe("global".to_string())) + .send_async(ClientRequest::Subscribe("global".to_string())) .await .context(SendSnafu)?; Ok(SwarmHandle { - state: Arc::new(Mutex::new(CounterState::default())), + state: Arc::new(Mutex::new(S::default())), send_chan, recv_chan, kill_switch, @@ -108,7 +109,7 @@ impl SwarmHandle { #[instrument] pub async fn kill(&self) -> Result<(), NetworkError> { self.send_chan - .send_async(SwarmAction::Shutdown) + .send_async(ClientRequest::Shutdown) .await .map_err(|_e| NetworkError::StreamClosed)?; self.kill_switch @@ -117,39 +118,43 @@ impl SwarmHandle { .map_err(|_e| NetworkError::StreamClosed)?; Ok(()) } -} -/// spins up `num_of_nodes` nodes and connects them to each other -#[instrument] -pub async fn spin_up_swarms(num_of_nodes: usize) -> Result>, HandlerError> { - // FIXME change API to accomodate multiple bootstrap nodes - let bootstrap = SwarmHandle::new(None, NetworkNodeType::Bootstrap).await?; - let bootstrap_addr = bootstrap.listen_addr.clone(); - info!( - "boostrap node {} on addr {}", - bootstrap.peer_id, bootstrap_addr - ); - // give a split second to initialize - // TODO the proper way to do this is to make it event driven. Once it bootstraps *successfully* - // THEN add next peer - sleep(Duration::from_secs(1)).await; - let mut handles = Vec::new(); - for _ in 0..(num_of_nodes - 1) { - handles.push(Arc::new( - SwarmHandle::new(Some(bootstrap_addr.clone()), NetworkNodeType::Regular).await?, - )); + /// spins up `num_of_nodes` nodes and connects them to each other + #[instrument] + pub async fn spin_up_swarms(num_of_nodes: usize) -> Result>, HandlerError> { + // FIXME change API to accomodate multiple bootstrap nodes + let bootstrap: SwarmHandle = SwarmHandle::new(None, NetworkNodeType::Bootstrap).await?; + let bootstrap_addr = bootstrap.listen_addr.clone(); + info!( + "boostrap node {} on addr {}", + bootstrap.peer_id, bootstrap_addr + ); + // give a split second to initialize + // TODO the proper way to do this is to make it event driven. Once it bootstraps *successfully* + // THEN add next peer sleep(Duration::from_secs(1)).await; + let mut handles = Vec::new(); + for _ in 0..(num_of_nodes - 1) { + handles.push(Arc::new( + SwarmHandle::new(Some(bootstrap_addr.clone()), NetworkNodeType::Regular).await?, + )); + sleep(Duration::from_secs(1)).await; + } + Ok(handles) } - Ok(handles) } /// general function to spin up testing infra /// perform tests by calling `run_test` /// then cleans up tests -pub async fn test_bed(run_test: F) -where - Fut: Future, - F: FnOnce(Vec>) -> Fut, +pub async fn test_bed( + run_test: F, + client_handler: G, +) where + FutF: Future, + FutG: Future> + 'static + Send + Sync, + F: FnOnce(Vec>>) -> FutF, + G: Fn(NetworkEvent, Arc>) -> FutG + 'static + Send + Sync, { // only call once otherwise panics // @@ -160,9 +165,10 @@ where // NOTE we want this to panic if we can't spin up the swarms. // that amounts to a failed test. - let handles: Vec> = spin_up_swarms(TOTAL_NUM_PEERS).await.unwrap(); + let handles: Vec>> = + SwarmHandle::spin_up_swarms(TOTAL_NUM_PEERS).await.unwrap(); for handle in handles.iter() { - spawn_handler(handle.clone(), handle_event).await; + spawn_handler(handle.clone(), client_handler.clone()).await; } print_connections(&handles).await; @@ -178,13 +184,13 @@ where /// - updates state based on events received /// - replies to direct messages #[instrument] -pub async fn handle_event( - event: SwarmResult, - handle: Arc, +pub async fn handle_counter_event( + event: NetworkEvent, + handle: Arc>, ) -> Result<(), HandlerError> { use CounterMessage::*; #[allow(clippy::enum_glob_use)] - use SwarmResult::*; + use NetworkEvent::*; let bincode_options = bincode::DefaultOptions::new().with_limit(16_384); match event { GossipMsg(m) | DirectResponse(m) => { @@ -213,7 +219,7 @@ pub async fn handle_event( // FIXME error handling handle .send_chan - .send_async(SwarmAction::DirectResponse(chan, serialized_response)) + .send_async(ClientRequest::DirectResponse(chan, serialized_response)) .await .context(SendSnafu)? } @@ -238,9 +244,9 @@ pub async fn handle_event( /// The idea is that this function can be used independent of the actual behaviour /// we want #[instrument(skip(event_handler))] -pub async fn spawn_handler( - handle: Arc, - event_handler: impl (Fn(SwarmResult, Arc) -> Fut) +pub async fn spawn_handler( + handle: Arc>, + event_handler: impl (Fn(NetworkEvent, Arc>) -> Fut) + std::marker::Sync + std::marker::Send + 'static, @@ -272,7 +278,7 @@ pub async fn spawn_handler( /// chooses one /// # Panics /// panics if handles is of length 0 -pub fn get_random_handle(handles: &[Arc]) -> Arc { +pub fn get_random_handle(handles: &[Arc>]) -> Arc> { handles.iter().choose(&mut thread_rng()).unwrap().clone() } @@ -280,7 +286,7 @@ pub fn get_random_handle(handles: &[Arc]) -> Arc { #[async_std::test] #[instrument] async fn test_request_response() { - async fn run_request_response(handles: Vec>) { + async fn run_request_response(handles: Vec>>) { let send_handle = get_random_handle(handles.as_slice()); let recv_handle = get_random_handle(handles.as_slice()); @@ -293,7 +299,7 @@ async fn test_request_response() { to: CounterState(5), }) .unwrap(); - let msg = SwarmAction::DirectRequest(recv_handle.peer_id, msg_inner); + let msg = ClientRequest::DirectRequest(recv_handle.peer_id, msg_inner); send_handle.send_chan.send_async(msg).await.unwrap(); // block to let the direction message @@ -313,14 +319,14 @@ async fn test_request_response() { } } - test_bed(run_request_response).await + test_bed(run_request_response, handle_counter_event).await } /// check that we can broadcast a message out and get counter increments #[async_std::test] #[instrument] async fn test_gossip() { - async fn run_gossip(handles: Vec>) { + async fn run_gossip(handles: Vec>>) { let msg_handle = handles.iter().choose(&mut thread_rng()).unwrap(); *msg_handle.state.lock().await = CounterState(5); let bincode_options = bincode::DefaultOptions::new().with_limit(16_384); @@ -331,7 +337,7 @@ async fn test_gossip() { }) .unwrap(); let (send, recv) = flume::bounded(1); - let msg = SwarmAction::GossipMsg(Topic::new("global"), msg_inner, send); + let msg = ClientRequest::GossipMsg(Topic::new("global"), msg_inner, send); msg_handle.send_chan.send_async(msg).await.unwrap(); recv.recv_async().await.unwrap().unwrap(); @@ -353,12 +359,12 @@ async fn test_gossip() { } } - test_bed(run_gossip).await; + test_bed(run_gossip, handle_counter_event).await; } /// print the connections for each handle in `handles` /// useful for debugging -async fn print_connections(handles: &[Arc]) { +async fn print_connections(handles: &[Arc>]) { warn!("PRINTING CONNECTION STATES"); for (i, handle) in handles.iter().enumerate() { warn!( @@ -379,6 +385,6 @@ pub enum HandlerError { NetworkError { source: NetworkError }, SerializationError { source: Box }, DeserializationError {}, - SendError { source: SendError }, + SendError { source: SendError }, RecvError { source: RecvError }, } From 78c4b1bdf39bb0c43dc0c55304afed814e967691 Mon Sep 17 00:00:00 2001 From: Justin Restivo Date: Tue, 1 Feb 2022 11:12:23 -0500 Subject: [PATCH 054/107] refactor: - Network -> NetworkNode - SwarmHandle -> NetworkNodeHandle - Move SwarmHandle to separate file - Move Network to separate file - Move testing infra to separate file --- libp2p-networking/examples/clichat.rs | 2 +- libp2p-networking/src/lib.rs | 813 +------------------ libp2p-networking/src/network_node.rs | 805 ++++++++++++++++++ libp2p-networking/src/network_node_handle.rs | 257 ++++++ libp2p-networking/src/node_handle.rs | 0 libp2p-networking/src/ui.rs | 4 +- libp2p-networking/tests/common.rs | 1 + libp2p-networking/tests/counter.rs | 260 +----- 8 files changed, 1098 insertions(+), 1044 deletions(-) create mode 100644 libp2p-networking/src/network_node.rs create mode 100644 libp2p-networking/src/network_node_handle.rs create mode 100644 libp2p-networking/src/node_handle.rs create mode 100644 libp2p-networking/tests/common.rs diff --git a/libp2p-networking/examples/clichat.rs b/libp2p-networking/examples/clichat.rs index dd83a4528e..339ad242ea 100644 --- a/libp2p-networking/examples/clichat.rs +++ b/libp2p-networking/examples/clichat.rs @@ -17,7 +17,7 @@ use parking_lot::Mutex; use tracing::instrument; use tui::{backend::CrosstermBackend, Terminal}; -use networking_demo::{gen_multiaddr, ClientRequest, NetworkNode, NetworkNodeType}; +use networking_demo::network_node::{gen_multiaddr, ClientRequest, NetworkNode, NetworkNodeType}; /// command line arguments #[derive(StructOpt)] diff --git a/libp2p-networking/src/lib.rs b/libp2p-networking/src/lib.rs index 1b6ee56d99..28e0ffcc71 100644 --- a/libp2p-networking/src/lib.rs +++ b/libp2p-networking/src/lib.rs @@ -17,816 +17,17 @@ /// Direct Messages between two nodes pub mod direct_message; -/// wrapper for tracing niceties -pub mod tracing_setup; - -use async_std::task::{sleep, spawn}; -use direct_message::{DirectMessageCodec, DirectMessageRequest, DirectMessageResponse}; -use rand::{seq::IteratorRandom, thread_rng}; -use std::fmt::Debug; -use std::{ - collections::HashSet, - io::Error, - iter, - task::{Context, Poll}, - time::Duration, -}; - -use flume::{unbounded, Receiver, Sender}; -use futures::{select, FutureExt, StreamExt}; -use libp2p::{ - build_multiaddr, - core::{ - either::EitherError, muxing::StreamMuxerBox, transport::Boxed, upgrade, ConnectedPoint, - }, - dns, - gossipsub::{ - error::{GossipsubHandlerError, PublishError}, - Gossipsub, GossipsubConfigBuilder, GossipsubEvent, GossipsubMessage, IdentTopic as Topic, - MessageAuthenticity, MessageId, ValidationMode, - }, - identify::{Identify, IdentifyConfig, IdentifyEvent}, - identity::Keypair, - kad::{ - self, store::MemoryStore, GetClosestPeersOk, Kademlia, KademliaConfig, KademliaEvent, - QueryResult, - }, - mplex, noise, - request_response::{ - ProtocolSupport, RequestResponse, RequestResponseConfig, RequestResponseEvent, - RequestResponseMessage, ResponseChannel, - }, - swarm::{ - NetworkBehaviour, NetworkBehaviourAction, NetworkBehaviourEventProcess, PollParameters, - ProtocolsHandlerUpgrErr, SwarmEvent, - }, - tcp, websocket, yamux, Multiaddr, NetworkBehaviour, PeerId, Swarm, Transport, TransportError, -}; -use snafu::{ResultExt, Snafu}; -use tracing::{debug, error, info, info_span, instrument, trace, warn, Instrument}; -use crate::direct_message::DirectMessageProtocol; +/// Wrapper for tracing niceties +pub mod tracing_setup; -/// example message used by the UI library +/// Example message used by the UI library pub mod message; /// UI library for clichat example pub mod ui; -/// Overarching network behaviour performing: -/// - network topology discovoery -/// - direct messaging -/// - p2p broadcast -/// - connection management -#[derive(NetworkBehaviour)] -#[behaviour(out_event = "NetworkEvent", poll_method = "poll", event_process = true)] -pub struct NetworkDef { - /// purpose: broadcasting messages to many peers - /// NOTE gossipsub works ONLY for sharing messsages right now - /// in the future it may be able to do peer discovery and routing - /// <`https://github.com/libp2p/rust-libp2p/issues/2398> - pub gossipsub: Gossipsub, - /// purpose: peer routing - pub kadem: Kademlia, - /// purpose: peer discovery - pub identify: Identify, - /// purpose: directly messaging peer - pub request_response: RequestResponse, - /// if the node has been bootstrapped into the kademlia network - #[behaviour(ignore)] - pub bootstrap: bool, - // TODO separate out into ConnectionData struct - /// set of connected peers - #[behaviour(ignore)] - pub connected_peers: HashSet, - // TODO replace this with a set of queryids - /// set of currently connecting peers - #[behaviour(ignore)] - pub connecting_peers: HashSet, - /// set of peers that were at one point connected - #[behaviour(ignore)] - pub known_peers: HashSet, - /// set of events to send to UI - #[behaviour(ignore)] - pub client_event_queue: Vec, -} - -impl Debug for NetworkDef { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - f.debug_struct("NetworkDef") - .field("bootstrap", &self.bootstrap) - .field("connected_peers", &self.connected_peers) - .field("connecting_peers", &self.connecting_peers) - .field("known_peers", &self.known_peers) - .finish() - } -} - -/// metadata about connections -#[derive(Default, Debug, Clone)] -pub struct ConnectionData { - /// set of currently connecting peers - pub connected_peers: HashSet, - /// set of peers that were at one point connected - pub connecting_peers: HashSet, - /// set of events to send to UI - pub known_peers: HashSet, -} - -impl NetworkDef { - fn poll( - &mut self, - _cx: &mut Context<'_>, - _: &mut impl PollParameters, - ) -> Poll::ProtocolsHandler>> - { - // push events that must be relayed back to UI onto queue - // to be consumed by UI event handler - if !self.client_event_queue.is_empty() { - return Poll::Ready(NetworkBehaviourAction::GenerateEvent( - self.client_event_queue.remove(0), - )); - } - - Poll::Pending - } -} - -impl NetworkBehaviourEventProcess for NetworkDef { - fn inject_event(&mut self, event: GossipsubEvent) { - info!(?event, "gossipsub msg recv-ed"); - if let GossipsubEvent::Message { message, .. } = event { - self.client_event_queue - .push(NetworkEvent::GossipMsg(message.data)); - } - } -} - -impl NetworkBehaviourEventProcess for NetworkDef { - fn inject_event(&mut self, event: KademliaEvent) { - info!(?event, "kadem msg recv-ed"); - match event { - KademliaEvent::OutboundQueryCompleted { result, .. } => { - match result { - // FIXME rebootstrap or fail in the failed - // bootstrap case - QueryResult::Bootstrap(r) => { - match r { - Ok(_bootstrap) => { - // we're bootstrapped - // don't bootstrap again - self.bootstrap = false; - } - Err(_) => { - // try again - self.bootstrap = true; - } - } - } - QueryResult::GetClosestPeers(Ok(GetClosestPeersOk { peers, .. })) => { - for peer in peers { - self.known_peers.insert(peer); - } - self.client_event_queue - .push(NetworkEvent::UpdateKnownPeers(self.known_peers.clone())); - } - _ => {} - } - } - KademliaEvent::RoutingUpdated { - peer, - is_new_peer: _is_new_peer, - addresses: _addresses, - .. - } => { - self.known_peers.insert(peer); - self.client_event_queue - .push(NetworkEvent::UpdateKnownPeers(self.known_peers.clone())); - } - _ => {} - } - } -} - -impl NetworkBehaviourEventProcess for NetworkDef { - fn inject_event(&mut self, event: IdentifyEvent) { - if let IdentifyEvent::Received { peer_id, info, .. } = event { - for addr in info.listen_addrs { - self.kadem.add_address(&peer_id, addr.clone()); - } - self.known_peers.insert(peer_id); - self.client_event_queue - .push(NetworkEvent::UpdateKnownPeers(self.known_peers.clone())); - } - } -} - -impl NetworkBehaviourEventProcess> - for NetworkDef -{ - fn inject_event( - &mut self, - event: RequestResponseEvent, - ) { - if let RequestResponseEvent::Message { message, .. } = event { - match message { - RequestResponseMessage::Request { - request: DirectMessageRequest(msg), - channel, - .. - } => { - self.client_event_queue - .push(NetworkEvent::DirectRequest(msg, channel)); - } - RequestResponseMessage::Response { - response: DirectMessageResponse(msg), - .. - } => { - self.client_event_queue - .push(NetworkEvent::DirectResponse(msg)); - } - } - } - } -} - -/// this is mostly to estimate how many network connections -/// a node should allow -#[derive(Debug, Copy, Clone, PartialEq, Eq)] -pub enum NetworkNodeType { - /// bootstrap node accepts all connections - Bootstrap, - /// regular node has a limit to the - /// number of connections to accept - Regular, -} - -// FIXME split this out into network config + swarm - -/// Network definition -pub struct NetworkNode { - /// pub/private key from with peer_id is derived - pub identity: Keypair, - /// peer id of network node - pub peer_id: PeerId, - /// the swarm of networkbehaviours - pub swarm: Swarm, - /// maximum number of connections to maintain - pub max_num_peers: usize, - /// minimum numer of connections to maintain - pub min_num_peers: usize, - /// the type of node the network is - pub node_type: NetworkNodeType, -} - -impl Debug for NetworkNode { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - f.debug_struct("Network") - .field("peer_id", &self.peer_id) - .field("swarm", self.swarm.behaviour()) - .field("max_num_peers", &self.max_num_peers) - .field("min_num_peers", &self.min_num_peers) - .field("node_type", &self.node_type) - .finish() - } -} - -/// Actions to send from the client to the swarm -#[derive(Debug)] -pub enum ClientRequest { - /// kill the swarm - Shutdown, - /// broadcast a serialized message - GossipMsg(Topic, Vec, Sender>), - /// send the peer id - GetId(Sender), - /// subscribe to a topic - Subscribe(String), - /// unsubscribe from a topic - Unsubscribe(String), - /// direct message a serialized message - DirectRequest(PeerId, Vec), - /// direct reply to a message - DirectResponse(ResponseChannel, Vec), -} - -/// events generated by the swarm that we wish -/// to relay to the client -#[derive(Debug)] -pub enum NetworkEvent { - /// connected to a new peer - UpdateConnectedPeers(HashSet), - /// discovered a new peer - UpdateKnownPeers(HashSet), - /// recv-ed a broadcast - GossipMsg(Vec), - /// recv-ed a direct message from a node - DirectRequest(Vec, ResponseChannel), - /// recv-ed a direct response from a node - DirectResponse(Vec), -} - -/// bind all interfaces on port `port` -/// TODO something more general -pub fn gen_multiaddr(port: u16) -> Multiaddr { - build_multiaddr!(Ip4([0, 0, 0, 0]), Tcp(port)) -} - -/// generate authenticated transport, copied from `development_transport` -/// for definition of XX -/// # Errors -/// could not sign the noise key with `identity` -#[instrument(skip(identity))] -pub async fn gen_transport( - identity: Keypair, -) -> Result, NetworkError> { - let transport = { - let tcp = tcp::TcpConfig::new().nodelay(true); - let dns_tcp = dns::DnsConfig::system(tcp) - .await - .context(TransportLaunchSnafu)?; - let ws_dns_tcp = websocket::WsConfig::new(dns_tcp.clone()); - dns_tcp.or_transport(ws_dns_tcp) - }; - - // keys for signing messages - let noise_keys = noise::Keypair::::new() - .into_authentic(&identity) - .expect("Signing libp2p-noise static DH keypair failed."); - - Ok(transport - .upgrade(upgrade::Version::V1) - // authentication: messages are signed - .authenticate(noise::NoiseConfig::xx(noise_keys).into_authenticated()) - // muxxing streams - // useful because only one connection opened - // https://docs.libp2p.io/concepts/stream-multiplexing/ - .multiplex(upgrade::SelectUpgrade::new( - yamux::YamuxConfig::default(), - mplex::MplexConfig::default(), - )) - .timeout(std::time::Duration::from_secs(20)) - .boxed()) -} - -impl NetworkNode { - /// starts the swarm listening on `listen_addr` - /// and optionally dials into peer `known_peer` - /// returns the address the swarm is listening upon - #[instrument(skip(self))] - pub async fn start( - &mut self, - listen_addr: Multiaddr, - known_peer: Option, - ) -> Result { - self.swarm.listen_on(listen_addr).context(TransportSnafu)?; - let addr = loop { - match self.swarm.next().await { - Some(SwarmEvent::NewListenAddr { address, .. }) => break address, - _ => continue, - }; - }; - info!("peerid {:?} listen addr: {:?}", self.peer_id, addr); - if let Some(known_peer) = known_peer { - let dialing = known_peer.clone(); - match self.swarm.dial(known_peer) { - Ok(_) => { - warn!("peerid {:?} dialed {:?}", self.peer_id, dialing); - } - Err(e) => error!( - "peerid {:?} dialed {:?} and failed with error: {:?}", - self.peer_id, dialing, e - ), - }; - } - Ok(addr) - } - - /// Creates a new `Network` with the given settings. - /// - /// Currently: - /// * Generates a random key pair and associated [`PeerId`] - /// * Launches a hopefully production ready transport: - /// TCP + DNS + Websocket + XX auth - /// * Generates a connection to the "broadcast" topic - /// * Creates a swarm to manage peers and events - #[instrument] - pub async fn new(node_type: NetworkNodeType) -> Result { - // Generate a random PeerId - let identity = Keypair::generate_ed25519(); - let peer_id = PeerId::from(identity.public()); - debug!(?peer_id); - let transport: Boxed<(PeerId, StreamMuxerBox)> = gen_transport(identity.clone()).await?; - trace!("Launched network transport"); - // Generate the swarm - let swarm: Swarm = { - // Use the hash of the message's contents as the ID - // Use blake3 for much paranoia at very high speeds - let message_id_fn = |message: &GossipsubMessage| { - let hash = blake3::hash(&message.data); - MessageId::from(hash.as_bytes().to_vec()) - }; - // Create a custom gossipsub - // TODO: Extract these defaults into some sort of config - // Use a jank match because Gossipsubconfigbuilder::build returns a non-static str for - // some god forsaken reason - let gossipsub_config = GossipsubConfigBuilder::default() - .heartbeat_interval(Duration::from_secs(1)) - // Force all messages to have valid signatures - .validation_mode(ValidationMode::Strict) - // Use the (blake3) hash of a message as its ID - .message_id_fn(message_id_fn) - .build() - .map_err(|s| GossipsubConfigSnafu { message: s }.build())?; - // - Build a gossipsub network behavior - let gossipsub: Gossipsub = Gossipsub::new( - // TODO do we even need this? - // if messages are signed at the the consensus level AND the network - // level (noise), this feels redundant. - MessageAuthenticity::Signed(identity.clone()), - gossipsub_config, - ) - .map_err(|s| GossipsubBuildSnafu { message: s }.build())?; - - // - Build a identify network behavior needed for own - // node connection information - // E.g. this will answer the question: how are other nodes - // seeing the peer from behind a NAT - let identify = Identify::new(IdentifyConfig::new( - "Spectrum validation gossip 0.1".to_string(), - identity.public(), - )); - - // - Build DHT needed for peer discovery - // TODO check into the MemoryStore defaults - let mut kconfig = KademliaConfig::default(); - kconfig.set_caching(kad::KademliaCaching::Disabled); - let kadem = Kademlia::with_config(peer_id, MemoryStore::new(peer_id), kconfig); - - // request response for direct messages - let request_response = RequestResponse::new( - DirectMessageCodec(), - iter::once((DirectMessageProtocol(), ProtocolSupport::Full)), - RequestResponseConfig::default(), - ); - - let network = NetworkDef { - gossipsub, - kadem, - identify, - request_response, - connected_peers: HashSet::new(), - connecting_peers: HashSet::new(), - known_peers: HashSet::new(), - client_event_queue: Vec::new(), - bootstrap: false, - }; - - Swarm::new(transport, network, peer_id) - }; - - Ok(Self { - identity, - peer_id, - max_num_peers: 600, - min_num_peers: 50, - swarm, - node_type, - }) - } - - /// peer discovery mechanism - /// looks up a random peer - #[instrument(skip(self))] - fn handle_peer_discovery(&mut self) { - if !self.swarm.behaviour().bootstrap { - let random_peer = PeerId::random(); - self.swarm - .behaviour_mut() - .kadem - .get_closest_peers(random_peer); - } - } - - /// Keep the number of open connections between threshold specified by - /// the swarm - #[instrument(skip(self))] - fn handle_num_connections(&mut self) { - let swarm = self.swarm.behaviour(); - // if we're bootstrapped, do nothing - // otherwise periodically get more peers if needed - if !swarm.bootstrap { - if swarm.connecting_peers.len() + swarm.connected_peers.len() <= self.min_num_peers { - // Calcuate the currently connected peers - let used_peers = swarm - .connecting_peers - .union(&swarm.connected_peers) - .copied() - .collect(); - // Calcuate the list of "new" peers, once not currently used for - // a connection - let potential_peers: HashSet = - swarm.known_peers.difference(&used_peers).copied().collect(); - // Number of peers we want to try connecting to - let num_to_connect = self.min_num_peers + 1 - - (swarm.connected_peers.len() + swarm.connecting_peers.len()); - // Random(?) subset of the availible peers to try connecting to - let chosen_peers = potential_peers - .iter() - .copied() - .choose_multiple(&mut thread_rng(), num_to_connect); - // Try dialing each random (?) peer - for a_peer in chosen_peers { - match self.swarm.dial(a_peer) { - Ok(_) => { - self.swarm.behaviour_mut().connecting_peers.insert(a_peer); - } - Err(e) => { - info!("Peer {:?} dial {:?} failed: {:?}", self.peer_id, a_peer, e); - } - }; - } - } - // NOTE only prune node connections if we aren't a bootstrap node - else if swarm.connected_peers.len() > self.max_num_peers - && self.node_type == NetworkNodeType::Regular - { - // If we are connected to too many peers, try disconnecting from - // a random (?) subset - let peers_to_rm = swarm.connected_peers.iter().copied().choose_multiple( - &mut thread_rng(), - swarm.connected_peers.len() - self.max_num_peers, - ); - for a_peer in peers_to_rm { - // FIXME the error is () ? - let _ = self.swarm.disconnect_peer_id(a_peer); - } - } - } - } - - /// event handler for UI. - /// currectly supported actions include - /// - shutting down the swarm - /// - gossipping a message to known peers on the `global` topic - /// - returning the id of the current peer - /// - subscribing to a topic - /// - unsubscribing from a toipc - /// - direct messaging a peer - #[instrument(skip(self))] - async fn handle_client_requests( - &mut self, - msg: Result, - ) -> Result { - match msg { - Ok(msg) => { - #[allow(clippy::enum_glob_use)] - use ClientRequest::*; - match msg { - Shutdown => { - warn!("Libp2p listener shutting down"); - return Ok(true); - } - ClientRequest::GossipMsg(topic, contents, chan) => { - let res = self - .swarm - .behaviour_mut() - .gossipsub - .publish(topic, contents.clone()) - .map(|_| ()) - .context(PublishSnafu); - info!("publishing reuslt! {:?}", res); - - // send result back to ui to confirm this isn't a duplicate message - chan.send_async(res) - .await - .map_err(|_e| NetworkError::StreamClosed)?; - } - GetId(reply_chan) => { - // FIXME proper error handling - reply_chan - .send_async(self.peer_id) - .await - .map_err(|_e| NetworkError::StreamClosed)?; - } - Subscribe(t) => { - if self - .swarm - .behaviour_mut() - .gossipsub - .subscribe(&Topic::new(t.clone())) - .is_err() - { - error!("error subscribing to topic {}", t); - } - } - Unsubscribe(t) => { - if self - .swarm - .behaviour_mut() - .gossipsub - .unsubscribe(&Topic::new(t.clone())) - .is_err() - { - error!("error unsubscribing to topic {}", t); - } - } - DirectRequest(pid, msg) => { - self.swarm - .behaviour_mut() - .request_response - .send_request(&pid, DirectMessageRequest(msg)); - } - DirectResponse(chan, msg) => { - let res = self - .swarm - .behaviour_mut() - .request_response - .send_response(chan, DirectMessageResponse(msg)); - if let Err(e) = res { - error!("Error replying to direct message. {:?}", e); - } - } - } - } - Err(e) => { - error!("Error receiving msg: {:?}", e); - } - } - Ok(false) - } - - /// event handler for events emited from the swarm - #[allow(clippy::type_complexity)] - #[instrument(skip(self))] - async fn handle_swarm_events( - &mut self, - event: SwarmEvent< - NetworkEvent, - EitherError< - EitherError, Error>, - ProtocolsHandlerUpgrErr, - >, - >, - send_to_ui: &Sender, - ) -> Result<(), NetworkError> { - // Make the match cleaner - #[allow(clippy::enum_glob_use)] - use SwarmEvent::*; - - info!("libp2p event {:?}", event); - match event { - ConnectionEstablished { - peer_id, endpoint, .. - } => { - match endpoint { - ConnectedPoint::Dialer { address } => { - self.swarm - .behaviour_mut() - .kadem - .add_address(&peer_id, address); - } - ConnectedPoint::Listener { - local_addr: _, - send_back_addr, - } => { - self.swarm - .behaviour_mut() - .kadem - .add_address(&peer_id, send_back_addr); - } - } - self.swarm.behaviour_mut().connected_peers.insert(peer_id); - self.swarm.behaviour_mut().connecting_peers.remove(&peer_id); - // now we have at least one peer so we can bootstrap - if !self.swarm.behaviour().bootstrap { - self.swarm - .behaviour_mut() - .kadem - .bootstrap() - .map_err(|_e| NetworkError::NoKnownPeers)?; - } - send_to_ui - .send_async(NetworkEvent::UpdateConnectedPeers( - self.swarm.behaviour_mut().connected_peers.clone(), - )) - .await - .map_err(|_e| NetworkError::StreamClosed)?; - } - ConnectionClosed { peer_id, .. } => { - let swarm = self.swarm.behaviour_mut(); - swarm.connected_peers.remove(&peer_id); - // FIXME remove stale address, not *all* addresses - swarm.kadem.remove_peer(&peer_id); - - send_to_ui - .send_async(NetworkEvent::UpdateConnectedPeers( - swarm.connected_peers.clone(), - )) - .await - .map_err(|_e| NetworkError::StreamClosed)?; - send_to_ui - .send_async(NetworkEvent::UpdateKnownPeers(swarm.known_peers.clone())) - .await - .map_err(|_e| NetworkError::StreamClosed)?; - } - Dialing(_) - | NewListenAddr { .. } - | ExpiredListenAddr { .. } - | ListenerClosed { .. } - | IncomingConnection { .. } - | IncomingConnectionError { .. } - | OutgoingConnectionError { .. } - | BannedPeer { .. } - | ListenerError { .. } => {} - Behaviour(b) => { - // forward messages directly to UI - send_to_ui - .send_async(b) - .await - .map_err(|_e| NetworkError::StreamClosed)?; - } - } - Ok(()) - } - - /// Spawn a task to listen for requests on the returned channel - /// as well as any events produced by libp2p - /// `mut_mut` is disabled b/c must consume `self` - #[allow(clippy::panic)] - #[instrument(skip(self))] - pub async fn spawn_listeners( - mut self, - ) -> Result<(Sender, Receiver), NetworkError> { - let (s_input, s_output) = unbounded::(); - let (r_input, r_output) = unbounded::(); - - spawn( - async move { - loop { - select! { - _ = sleep(Duration::from_secs(30)).fuse() => { - self.handle_peer_discovery(); - }, - _ = sleep(Duration::from_secs(1)).fuse() => { - self.handle_num_connections(); - } - event = self.swarm.next() => { - if let Some(event) = event { - info!("peerid {:?}\t\thandling event {:?}", self.peer_id, event); - self.handle_swarm_events(event, &r_input).await?; - } - }, - msg = s_output.recv_async() => { - let shutdown = self.handle_client_requests(msg).await?; - if shutdown { - break - } - } - } - } - Ok::<(), NetworkError>(()) - } - .instrument(info_span!("Libp2p NetworkBehaviour Handler")), - ); - Ok((s_input, r_output)) - } -} +/// Network behaviour wrapper +pub mod network_node; -/// wrapper type for errors generated by the `Network` -#[derive(Debug, Snafu)] -pub enum NetworkError { - /// Error during dialing or listening - Transport { - /// The underlying source of the error - source: TransportError, - }, - /// Error establishing backend connection - TransportLaunch { - /// The underlying source of the error - source: std::io::Error, - }, - /// Error building the gossipsub configuration - #[snafu(display("Error building the gossipsub configuration: {message}"))] - GossipsubConfig { - /// The underlying source of the error - message: String, - }, - /// Error building the gossipsub instance - #[snafu(display("Error building the gossipsub implementation {message}"))] - GossipsubBuild { - /// The underlying source of the error - message: String, - }, - /// Error if one of the channels to or from the swarm is closed - /// FIXME ideally include more information - /// run into lifetime errors when making NetworkError generic over - /// the type of message. - StreamClosed, - /// Error publishing a gossipsub message - PublishError { - /// The underlying source of the error - source: PublishError, - }, - /// Error when there are no known peers to bootstrap off - NoKnownPeers, -} +/// handle for network behaviour +pub mod network_node_handle; diff --git a/libp2p-networking/src/network_node.rs b/libp2p-networking/src/network_node.rs new file mode 100644 index 0000000000..27c7ab8afd --- /dev/null +++ b/libp2p-networking/src/network_node.rs @@ -0,0 +1,805 @@ +use crate::direct_message::{DirectMessageCodec, DirectMessageRequest, DirectMessageResponse}; +use async_std::task::{sleep, spawn}; +use rand::{seq::IteratorRandom, thread_rng}; +use std::fmt::Debug; +use std::{ + collections::HashSet, + io::Error, + iter, + task::{Context, Poll}, + time::Duration, +}; + +use flume::{unbounded, Receiver, Sender}; +use futures::{select, FutureExt, StreamExt}; +use libp2p::{ + build_multiaddr, + core::{ + either::EitherError, muxing::StreamMuxerBox, transport::Boxed, upgrade, ConnectedPoint, + }, + dns, + gossipsub::{ + error::{GossipsubHandlerError, PublishError}, + Gossipsub, GossipsubConfigBuilder, GossipsubEvent, GossipsubMessage, IdentTopic as Topic, + MessageAuthenticity, MessageId, ValidationMode, + }, + identify::{Identify, IdentifyConfig, IdentifyEvent}, + identity::Keypair, + kad::{ + self, store::MemoryStore, GetClosestPeersOk, Kademlia, KademliaConfig, KademliaEvent, + QueryResult, + }, + mplex, noise, + request_response::{ + ProtocolSupport, RequestResponse, RequestResponseConfig, RequestResponseEvent, + RequestResponseMessage, ResponseChannel, + }, + swarm::{ + NetworkBehaviour, NetworkBehaviourAction, NetworkBehaviourEventProcess, PollParameters, + ProtocolsHandlerUpgrErr, SwarmEvent, + }, + tcp, websocket, yamux, Multiaddr, NetworkBehaviour, PeerId, Swarm, Transport, TransportError, +}; +use snafu::{ResultExt, Snafu}; +use tracing::{debug, error, info, info_span, instrument, trace, warn, Instrument}; + +use crate::direct_message::DirectMessageProtocol; + +/// Overarching network behaviour performing: +/// - network topology discovoery +/// - direct messaging +/// - p2p broadcast +/// - connection management +#[derive(NetworkBehaviour)] +#[behaviour(out_event = "NetworkEvent", poll_method = "poll", event_process = true)] +pub struct NetworkDef { + /// purpose: broadcasting messages to many peers + /// NOTE gossipsub works ONLY for sharing messsages right now + /// in the future it may be able to do peer discovery and routing + /// <`https://github.com/libp2p/rust-libp2p/issues/2398> + pub gossipsub: Gossipsub, + /// purpose: peer routing + pub kadem: Kademlia, + /// purpose: peer discovery + pub identify: Identify, + /// purpose: directly messaging peer + pub request_response: RequestResponse, + /// if the node has been bootstrapped into the kademlia network + #[behaviour(ignore)] + pub bootstrap: bool, + // TODO separate out into ConnectionData struct + /// set of connected peers + #[behaviour(ignore)] + pub connected_peers: HashSet, + // TODO replace this with a set of queryids + /// set of currently connecting peers + #[behaviour(ignore)] + pub connecting_peers: HashSet, + /// set of peers that were at one point connected + #[behaviour(ignore)] + pub known_peers: HashSet, + /// set of events to send to UI + #[behaviour(ignore)] + pub client_event_queue: Vec, +} + +impl Debug for NetworkDef { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.debug_struct("NetworkDef") + .field("bootstrap", &self.bootstrap) + .field("connected_peers", &self.connected_peers) + .field("connecting_peers", &self.connecting_peers) + .field("known_peers", &self.known_peers) + .finish() + } +} + +/// metadata about connections +#[derive(Default, Debug, Clone)] +pub struct ConnectionData { + /// set of currently connecting peers + pub connected_peers: HashSet, + /// set of peers that were at one point connected + pub connecting_peers: HashSet, + /// set of events to send to UI + pub known_peers: HashSet, +} + +impl NetworkDef { + fn poll( + &mut self, + _cx: &mut Context<'_>, + _: &mut impl PollParameters, + ) -> Poll::ProtocolsHandler>> + { + // push events that must be relayed back to UI onto queue + // to be consumed by UI event handler + if !self.client_event_queue.is_empty() { + return Poll::Ready(NetworkBehaviourAction::GenerateEvent( + self.client_event_queue.remove(0), + )); + } + + Poll::Pending + } +} + +impl NetworkBehaviourEventProcess for NetworkDef { + fn inject_event(&mut self, event: GossipsubEvent) { + info!(?event, "gossipsub msg recv-ed"); + if let GossipsubEvent::Message { message, .. } = event { + self.client_event_queue + .push(NetworkEvent::GossipMsg(message.data)); + } + } +} + +impl NetworkBehaviourEventProcess for NetworkDef { + fn inject_event(&mut self, event: KademliaEvent) { + info!(?event, "kadem msg recv-ed"); + match event { + KademliaEvent::OutboundQueryCompleted { result, .. } => { + match result { + // FIXME rebootstrap or fail in the failed + // bootstrap case + QueryResult::Bootstrap(r) => { + match r { + Ok(_bootstrap) => { + // we're bootstrapped + // don't bootstrap again + self.bootstrap = false; + } + Err(_) => { + // try again + self.bootstrap = true; + } + } + } + QueryResult::GetClosestPeers(Ok(GetClosestPeersOk { peers, .. })) => { + for peer in peers { + self.known_peers.insert(peer); + } + self.client_event_queue + .push(NetworkEvent::UpdateKnownPeers(self.known_peers.clone())); + } + _ => {} + } + } + KademliaEvent::RoutingUpdated { + peer, + is_new_peer: _is_new_peer, + addresses: _addresses, + .. + } => { + self.known_peers.insert(peer); + self.client_event_queue + .push(NetworkEvent::UpdateKnownPeers(self.known_peers.clone())); + } + _ => {} + } + } +} + +impl NetworkBehaviourEventProcess for NetworkDef { + fn inject_event(&mut self, event: IdentifyEvent) { + if let IdentifyEvent::Received { peer_id, info, .. } = event { + for addr in info.listen_addrs { + self.kadem.add_address(&peer_id, addr.clone()); + } + self.known_peers.insert(peer_id); + self.client_event_queue + .push(NetworkEvent::UpdateKnownPeers(self.known_peers.clone())); + } + } +} + +impl NetworkBehaviourEventProcess> + for NetworkDef +{ + fn inject_event( + &mut self, + event: RequestResponseEvent, + ) { + if let RequestResponseEvent::Message { message, .. } = event { + match message { + RequestResponseMessage::Request { + request: DirectMessageRequest(msg), + channel, + .. + } => { + self.client_event_queue + .push(NetworkEvent::DirectRequest(msg, channel)); + } + RequestResponseMessage::Response { + response: DirectMessageResponse(msg), + .. + } => { + self.client_event_queue + .push(NetworkEvent::DirectResponse(msg)); + } + } + } + } +} + +/// this is mostly to estimate how many network connections +/// a node should allow +#[derive(Debug, Copy, Clone, PartialEq, Eq)] +pub enum NetworkNodeType { + /// bootstrap node accepts all connections + Bootstrap, + /// regular node has a limit to the + /// number of connections to accept + Regular, +} + +// FIXME split this out into network config + swarm + +/// Network definition +pub struct NetworkNode { + /// pub/private key from with peer_id is derived + pub identity: Keypair, + /// peer id of network node + pub peer_id: PeerId, + /// the swarm of networkbehaviours + pub swarm: Swarm, + /// maximum number of connections to maintain + pub max_num_peers: usize, + /// minimum numer of connections to maintain + pub min_num_peers: usize, + /// the type of node the network is + pub node_type: NetworkNodeType, +} + +impl Debug for NetworkNode { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.debug_struct("Network") + .field("peer_id", &self.peer_id) + .field("swarm", self.swarm.behaviour()) + .field("max_num_peers", &self.max_num_peers) + .field("min_num_peers", &self.min_num_peers) + .field("node_type", &self.node_type) + .finish() + } +} + +/// Actions to send from the client to the swarm +#[derive(Debug)] +pub enum ClientRequest { + /// kill the swarm + Shutdown, + /// broadcast a serialized message + GossipMsg(Topic, Vec, Sender>), + /// send the peer id + GetId(Sender), + /// subscribe to a topic + Subscribe(String), + /// unsubscribe from a topic + Unsubscribe(String), + /// direct message a serialized message + DirectRequest(PeerId, Vec), + /// direct reply to a message + DirectResponse(ResponseChannel, Vec), +} + +/// events generated by the swarm that we wish +/// to relay to the client +#[derive(Debug)] +pub enum NetworkEvent { + /// connected to a new peer + UpdateConnectedPeers(HashSet), + /// discovered a new peer + UpdateKnownPeers(HashSet), + /// recv-ed a broadcast + GossipMsg(Vec), + /// recv-ed a direct message from a node + DirectRequest(Vec, ResponseChannel), + /// recv-ed a direct response from a node + DirectResponse(Vec), +} + +/// bind all interfaces on port `port` +/// TODO something more general +pub fn gen_multiaddr(port: u16) -> Multiaddr { + build_multiaddr!(Ip4([0, 0, 0, 0]), Tcp(port)) +} + +/// generate authenticated transport, copied from `development_transport` +/// for definition of XX +/// # Errors +/// could not sign the noise key with `identity` +#[instrument(skip(identity))] +pub async fn gen_transport( + identity: Keypair, +) -> Result, NetworkError> { + let transport = { + let tcp = tcp::TcpConfig::new().nodelay(true); + let dns_tcp = dns::DnsConfig::system(tcp) + .await + .context(TransportLaunchSnafu)?; + let ws_dns_tcp = websocket::WsConfig::new(dns_tcp.clone()); + dns_tcp.or_transport(ws_dns_tcp) + }; + + // keys for signing messages + let noise_keys = noise::Keypair::::new() + .into_authentic(&identity) + .expect("Signing libp2p-noise static DH keypair failed."); + + Ok(transport + .upgrade(upgrade::Version::V1) + // authentication: messages are signed + .authenticate(noise::NoiseConfig::xx(noise_keys).into_authenticated()) + // muxxing streams + // useful because only one connection opened + // https://docs.libp2p.io/concepts/stream-multiplexing/ + .multiplex(upgrade::SelectUpgrade::new( + yamux::YamuxConfig::default(), + mplex::MplexConfig::default(), + )) + .timeout(std::time::Duration::from_secs(20)) + .boxed()) +} + +impl NetworkNode { + /// starts the swarm listening on `listen_addr` + /// and optionally dials into peer `known_peer` + /// returns the address the swarm is listening upon + #[instrument(skip(self))] + pub async fn start( + &mut self, + listen_addr: Multiaddr, + known_peer: Option, + ) -> Result { + self.swarm.listen_on(listen_addr).context(TransportSnafu)?; + let addr = loop { + match self.swarm.next().await { + Some(SwarmEvent::NewListenAddr { address, .. }) => break address, + _ => continue, + }; + }; + info!("peerid {:?} listen addr: {:?}", self.peer_id, addr); + if let Some(known_peer) = known_peer { + let dialing = known_peer.clone(); + match self.swarm.dial(known_peer) { + Ok(_) => { + warn!("peerid {:?} dialed {:?}", self.peer_id, dialing); + } + Err(e) => error!( + "peerid {:?} dialed {:?} and failed with error: {:?}", + self.peer_id, dialing, e + ), + }; + } + Ok(addr) + } + + /// Creates a new `Network` with the given settings. + /// + /// Currently: + /// * Generates a random key pair and associated [`PeerId`] + /// * Launches a hopefully production ready transport: + /// TCP + DNS + Websocket + XX auth + /// * Generates a connection to the "broadcast" topic + /// * Creates a swarm to manage peers and events + #[instrument] + pub async fn new(node_type: NetworkNodeType) -> Result { + // Generate a random PeerId + let identity = Keypair::generate_ed25519(); + let peer_id = PeerId::from(identity.public()); + debug!(?peer_id); + let transport: Boxed<(PeerId, StreamMuxerBox)> = gen_transport(identity.clone()).await?; + trace!("Launched network transport"); + // Generate the swarm + let swarm: Swarm = { + // Use the hash of the message's contents as the ID + // Use blake3 for much paranoia at very high speeds + let message_id_fn = |message: &GossipsubMessage| { + let hash = blake3::hash(&message.data); + MessageId::from(hash.as_bytes().to_vec()) + }; + // Create a custom gossipsub + // TODO: Extract these defaults into some sort of config + // Use a jank match because Gossipsubconfigbuilder::build returns a non-static str for + // some god forsaken reason + let gossipsub_config = GossipsubConfigBuilder::default() + .heartbeat_interval(Duration::from_secs(1)) + // Force all messages to have valid signatures + .validation_mode(ValidationMode::Strict) + // Use the (blake3) hash of a message as its ID + .message_id_fn(message_id_fn) + .build() + .map_err(|s| GossipsubConfigSnafu { message: s }.build())?; + // - Build a gossipsub network behavior + let gossipsub: Gossipsub = Gossipsub::new( + // TODO do we even need this? + // if messages are signed at the the consensus level AND the network + // level (noise), this feels redundant. + MessageAuthenticity::Signed(identity.clone()), + gossipsub_config, + ) + .map_err(|s| GossipsubBuildSnafu { message: s }.build())?; + + // - Build a identify network behavior needed for own + // node connection information + // E.g. this will answer the question: how are other nodes + // seeing the peer from behind a NAT + let identify = Identify::new(IdentifyConfig::new( + "Spectrum validation gossip 0.1".to_string(), + identity.public(), + )); + + // - Build DHT needed for peer discovery + // TODO check into the MemoryStore defaults + let mut kconfig = KademliaConfig::default(); + kconfig.set_caching(kad::KademliaCaching::Disabled); + let kadem = Kademlia::with_config(peer_id, MemoryStore::new(peer_id), kconfig); + + // request response for direct messages + let request_response = RequestResponse::new( + DirectMessageCodec(), + iter::once((DirectMessageProtocol(), ProtocolSupport::Full)), + RequestResponseConfig::default(), + ); + + let network = NetworkDef { + gossipsub, + kadem, + identify, + request_response, + connected_peers: HashSet::new(), + connecting_peers: HashSet::new(), + known_peers: HashSet::new(), + client_event_queue: Vec::new(), + bootstrap: false, + }; + + Swarm::new(transport, network, peer_id) + }; + + Ok(Self { + identity, + peer_id, + max_num_peers: 600, + min_num_peers: 50, + swarm, + node_type, + }) + } + + /// peer discovery mechanism + /// looks up a random peer + #[instrument(skip(self))] + fn handle_peer_discovery(&mut self) { + if !self.swarm.behaviour().bootstrap { + let random_peer = PeerId::random(); + self.swarm + .behaviour_mut() + .kadem + .get_closest_peers(random_peer); + } + } + + /// Keep the number of open connections between threshold specified by + /// the swarm + #[instrument(skip(self))] + fn handle_num_connections(&mut self) { + let swarm = self.swarm.behaviour(); + // if we're bootstrapped, do nothing + // otherwise periodically get more peers if needed + if !swarm.bootstrap { + if swarm.connecting_peers.len() + swarm.connected_peers.len() <= self.min_num_peers { + // Calcuate the currently connected peers + let used_peers = swarm + .connecting_peers + .union(&swarm.connected_peers) + .copied() + .collect(); + // Calcuate the list of "new" peers, once not currently used for + // a connection + let potential_peers: HashSet = + swarm.known_peers.difference(&used_peers).copied().collect(); + // Number of peers we want to try connecting to + let num_to_connect = self.min_num_peers + 1 + - (swarm.connected_peers.len() + swarm.connecting_peers.len()); + // Random(?) subset of the availible peers to try connecting to + let chosen_peers = potential_peers + .iter() + .copied() + .choose_multiple(&mut thread_rng(), num_to_connect); + // Try dialing each random (?) peer + for a_peer in chosen_peers { + match self.swarm.dial(a_peer) { + Ok(_) => { + self.swarm.behaviour_mut().connecting_peers.insert(a_peer); + } + Err(e) => { + info!("Peer {:?} dial {:?} failed: {:?}", self.peer_id, a_peer, e); + } + }; + } + } + // NOTE only prune node connections if we aren't a bootstrap node + else if swarm.connected_peers.len() > self.max_num_peers + && self.node_type == NetworkNodeType::Regular + { + // If we are connected to too many peers, try disconnecting from + // a random (?) subset + let peers_to_rm = swarm.connected_peers.iter().copied().choose_multiple( + &mut thread_rng(), + swarm.connected_peers.len() - self.max_num_peers, + ); + for a_peer in peers_to_rm { + // FIXME the error is () ? + let _ = self.swarm.disconnect_peer_id(a_peer); + } + } + } + } + + /// event handler for UI. + /// currectly supported actions include + /// - shutting down the swarm + /// - gossipping a message to known peers on the `global` topic + /// - returning the id of the current peer + /// - subscribing to a topic + /// - unsubscribing from a toipc + /// - direct messaging a peer + #[instrument(skip(self))] + async fn handle_client_requests( + &mut self, + msg: Result, + ) -> Result { + match msg { + Ok(msg) => { + #[allow(clippy::enum_glob_use)] + use ClientRequest::*; + match msg { + Shutdown => { + warn!("Libp2p listener shutting down"); + return Ok(true); + } + ClientRequest::GossipMsg(topic, contents, chan) => { + let res = self + .swarm + .behaviour_mut() + .gossipsub + .publish(topic, contents.clone()) + .map(|_| ()) + .context(PublishSnafu); + info!("publishing reuslt! {:?}", res); + + // send result back to ui to confirm this isn't a duplicate message + chan.send_async(res) + .await + .map_err(|_e| NetworkError::StreamClosed)?; + } + GetId(reply_chan) => { + // FIXME proper error handling + reply_chan + .send_async(self.peer_id) + .await + .map_err(|_e| NetworkError::StreamClosed)?; + } + Subscribe(t) => { + if self + .swarm + .behaviour_mut() + .gossipsub + .subscribe(&Topic::new(t.clone())) + .is_err() + { + error!("error subscribing to topic {}", t); + } + } + Unsubscribe(t) => { + if self + .swarm + .behaviour_mut() + .gossipsub + .unsubscribe(&Topic::new(t.clone())) + .is_err() + { + error!("error unsubscribing to topic {}", t); + } + } + DirectRequest(pid, msg) => { + self.swarm + .behaviour_mut() + .request_response + .send_request(&pid, DirectMessageRequest(msg)); + } + DirectResponse(chan, msg) => { + let res = self + .swarm + .behaviour_mut() + .request_response + .send_response(chan, DirectMessageResponse(msg)); + if let Err(e) = res { + error!("Error replying to direct message. {:?}", e); + } + } + } + } + Err(e) => { + error!("Error receiving msg: {:?}", e); + } + } + Ok(false) + } + + /// event handler for events emited from the swarm + #[allow(clippy::type_complexity)] + #[instrument(skip(self))] + async fn handle_swarm_events( + &mut self, + event: SwarmEvent< + NetworkEvent, + EitherError< + EitherError, Error>, + ProtocolsHandlerUpgrErr, + >, + >, + send_to_ui: &Sender, + ) -> Result<(), NetworkError> { + // Make the match cleaner + #[allow(clippy::enum_glob_use)] + use SwarmEvent::*; + + info!("libp2p event {:?}", event); + match event { + ConnectionEstablished { + peer_id, endpoint, .. + } => { + match endpoint { + ConnectedPoint::Dialer { address } => { + self.swarm + .behaviour_mut() + .kadem + .add_address(&peer_id, address); + } + ConnectedPoint::Listener { + local_addr: _, + send_back_addr, + } => { + self.swarm + .behaviour_mut() + .kadem + .add_address(&peer_id, send_back_addr); + } + } + self.swarm.behaviour_mut().connected_peers.insert(peer_id); + self.swarm.behaviour_mut().connecting_peers.remove(&peer_id); + // now we have at least one peer so we can bootstrap + if !self.swarm.behaviour().bootstrap { + self.swarm + .behaviour_mut() + .kadem + .bootstrap() + .map_err(|_e| NetworkError::NoKnownPeers)?; + } + send_to_ui + .send_async(NetworkEvent::UpdateConnectedPeers( + self.swarm.behaviour_mut().connected_peers.clone(), + )) + .await + .map_err(|_e| NetworkError::StreamClosed)?; + } + ConnectionClosed { peer_id, .. } => { + let swarm = self.swarm.behaviour_mut(); + swarm.connected_peers.remove(&peer_id); + // FIXME remove stale address, not *all* addresses + swarm.kadem.remove_peer(&peer_id); + + send_to_ui + .send_async(NetworkEvent::UpdateConnectedPeers( + swarm.connected_peers.clone(), + )) + .await + .map_err(|_e| NetworkError::StreamClosed)?; + send_to_ui + .send_async(NetworkEvent::UpdateKnownPeers(swarm.known_peers.clone())) + .await + .map_err(|_e| NetworkError::StreamClosed)?; + } + Dialing(_) + | NewListenAddr { .. } + | ExpiredListenAddr { .. } + | ListenerClosed { .. } + | IncomingConnection { .. } + | IncomingConnectionError { .. } + | OutgoingConnectionError { .. } + | BannedPeer { .. } + | ListenerError { .. } => {} + Behaviour(b) => { + // forward messages directly to UI + send_to_ui + .send_async(b) + .await + .map_err(|_e| NetworkError::StreamClosed)?; + } + } + Ok(()) + } + + /// Spawn a task to listen for requests on the returned channel + /// as well as any events produced by libp2p + /// `mut_mut` is disabled b/c must consume `self` + #[allow(clippy::panic)] + #[instrument(skip(self))] + pub async fn spawn_listeners( + mut self, + ) -> Result<(Sender, Receiver), NetworkError> { + let (s_input, s_output) = unbounded::(); + let (r_input, r_output) = unbounded::(); + + spawn( + async move { + loop { + select! { + _ = sleep(Duration::from_secs(30)).fuse() => { + self.handle_peer_discovery(); + }, + _ = sleep(Duration::from_secs(1)).fuse() => { + self.handle_num_connections(); + } + event = self.swarm.next() => { + if let Some(event) = event { + info!("peerid {:?}\t\thandling event {:?}", self.peer_id, event); + self.handle_swarm_events(event, &r_input).await?; + } + }, + msg = s_output.recv_async() => { + let shutdown = self.handle_client_requests(msg).await?; + if shutdown { + break + } + } + } + } + Ok::<(), NetworkError>(()) + } + .instrument(info_span!("Libp2p NetworkBehaviour Handler")), + ); + Ok((s_input, r_output)) + } +} + +/// wrapper type for errors generated by the `Network` +#[derive(Debug, Snafu)] +pub enum NetworkError { + /// Error during dialing or listening + Transport { + /// The underlying source of the error + source: TransportError, + }, + /// Error establishing backend connection + TransportLaunch { + /// The underlying source of the error + source: std::io::Error, + }, + /// Error building the gossipsub configuration + #[snafu(display("Error building the gossipsub configuration: {message}"))] + GossipsubConfig { + /// The underlying source of the error + message: String, + }, + /// Error building the gossipsub instance + #[snafu(display("Error building the gossipsub implementation {message}"))] + GossipsubBuild { + /// The underlying source of the error + message: String, + }, + /// Error if one of the channels to or from the swarm is closed + /// FIXME ideally include more information + /// run into lifetime errors when making NetworkError generic over + /// the type of message. + StreamClosed, + /// Error publishing a gossipsub message + PublishError { + /// The underlying source of the error + source: PublishError, + }, + /// Error when there are no known peers to bootstrap off + NoKnownPeers, +} diff --git a/libp2p-networking/src/network_node_handle.rs b/libp2p-networking/src/network_node_handle.rs new file mode 100644 index 0000000000..149cc382ca --- /dev/null +++ b/libp2p-networking/src/network_node_handle.rs @@ -0,0 +1,257 @@ +use async_std::{ + sync::Mutex, + task::{sleep, spawn}, +}; + +use crate::network_node::{ + gen_multiaddr, ClientRequest, ConnectionData, NetworkError, NetworkEvent, NetworkNode, + NetworkNodeType, +}; +use flume::{Receiver, RecvError, SendError, Sender}; +use futures::{select, Future, FutureExt}; +use libp2p::{Multiaddr, PeerId}; +use rand::{seq::IteratorRandom, thread_rng}; +use snafu::{ResultExt, Snafu}; +use std::{ + fmt::Debug, + sync::{Arc, Once}, + time::Duration, +}; +use tracing::{info, info_span, instrument, warn, Instrument}; + +static INIT: Once = Once::new(); + +/// A handle containing: +/// - A reference to the state +/// - Controls for the swarm +#[derive(Debug)] +pub struct NetworkNodeHandle { + /// the state of the replica + pub state: Arc>, + /// send an action to the networkbehaviour + pub send_network: Sender, + /// receive an action from the networkbehaviour + pub recv_network: Receiver, + /// kill the event handler for events from the swarm + pub kill_switch: Sender<()>, + /// receiving end of `kill_switch` + pub recv_kill: Receiver<()>, + /// the local address we're listening on + pub listen_addr: Multiaddr, + /// the peer id of the networkbehaviour + pub peer_id: PeerId, + /// the connection metadata associated with the networkbehaviour + pub connection_state: Arc>, +} + +impl NetworkNodeHandle { + /// constructs a new node listening on `known_addr` + #[instrument] + pub async fn new( + known_addr: Option, + node_type: NetworkNodeType, + ) -> Result { + //`randomly assigned port + let listen_addr = gen_multiaddr(0); + let mut network = NetworkNode::new(node_type).await.context(NetworkSnafu)?; + let peer_id = network.peer_id; + let listen_addr = network + .start(listen_addr, known_addr) + .await + .context(NetworkSnafu)?; + let (send_chan, recv_chan) = network.spawn_listeners().await.context(NetworkSnafu)?; + let (kill_switch, recv_kill) = flume::bounded(1); + + send_chan + .send_async(ClientRequest::Subscribe("global".to_string())) + .await + .context(SendSnafu)?; + + Ok(NetworkNodeHandle { + state: Arc::new(Mutex::new(S::default())), + send_network: send_chan, + recv_network: recv_chan, + kill_switch, + recv_kill, + listen_addr, + peer_id, + connection_state: Arc::default(), + }) + } + + /// Cleanly shuts down a swarm node + /// This is done by sending a message to + /// the swarm event handler to stop handling events + /// and a message to the swarm itself to spin down + #[instrument] + pub async fn kill(&self) -> Result<(), NetworkError> { + self.send_network + .send_async(ClientRequest::Shutdown) + .await + .map_err(|_e| NetworkError::StreamClosed)?; + self.kill_switch + .send_async(()) + .await + .map_err(|_e| NetworkError::StreamClosed)?; + Ok(()) + } + + /// spins up `num_of_nodes` nodes and connects them to each other + #[instrument] + pub async fn spin_up_swarms(num_of_nodes: usize) -> Result>, HandlerError> { + // FIXME change API to accomodate multiple bootstrap nodes + let bootstrap: NetworkNodeHandle = + NetworkNodeHandle::new(None, NetworkNodeType::Bootstrap).await?; + let bootstrap_addr = bootstrap.listen_addr.clone(); + info!( + "boostrap node {} on addr {}", + bootstrap.peer_id, bootstrap_addr + ); + // give a split second to initialize + // TODO the proper way to do this is to make it event driven. Once it bootstraps *successfully* + // THEN add next peer + sleep(Duration::from_secs(1)).await; + let mut handles = Vec::new(); + for _ in 0..(num_of_nodes - 1) { + handles.push(Arc::new( + NetworkNodeHandle::new(Some(bootstrap_addr.clone()), NetworkNodeType::Regular) + .await?, + )); + sleep(Duration::from_secs(1)).await; + } + Ok(handles) + } +} + +/// General function to spin up testing infra +/// perform tests by calling `run_test` +/// then cleans up tests +/// # Panics +/// Panics if unable to: +/// - Initialize logging +/// - Initialize network nodes +/// - Kill network nodes +/// - a test assertion fails +pub async fn test_bed( + run_test: F, + client_handler: G, + num_nodes: usize, +) where + FutF: Future, + FutG: Future> + 'static + Send + Sync, + F: FnOnce(Vec>>) -> FutF, + G: Fn(NetworkEvent, Arc>) -> FutG + 'static + Send + Sync, +{ + // only call once otherwise panics + // + INIT.call_once(|| { + color_eyre::install().unwrap(); + crate::tracing_setup::setup_tracing(); + }); + + // NOTE we want this to panic if we can't spin up the swarms. + // that amounts to a failed test. + let handles: Vec>> = + NetworkNodeHandle::spin_up_swarms(num_nodes).await.unwrap(); + for handle in &handles { + spawn_handler(handle.clone(), client_handler.clone()).await; + } + print_connections(&handles).await; + + run_test(handles.clone()).await; + + // cleanup + for handle in handles { + handle.kill().await.unwrap(); + } +} + +/// Glue function that listens for events from the Swarm corresponding to `handle` +/// and calls `event_handler` when an event is observed. +/// The idea is that this function can be used independent of the actual behaviour +/// we want +#[allow(clippy::panic)] +#[instrument(skip(event_handler))] +pub async fn spawn_handler( + handle: Arc>, + event_handler: impl (Fn(NetworkEvent, Arc>) -> Fut) + + std::marker::Sync + + std::marker::Send + + 'static, +) where + Fut: + Future> + std::marker::Send + 'static + std::marker::Sync, +{ + let recv_kill = handle.recv_kill.clone(); + let recv_event = handle.recv_network.clone(); + spawn( + async move { + loop { + select!( + _ = recv_kill.recv_async().fuse() => { + break; + }, + event = recv_event.recv_async().fuse() => { + event_handler(event.context(RecvSnafu)?, handle.clone()).await?; + }, + ); + } + Ok::<(), HandlerError>(()) + } + .instrument(info_span!("Libp2p Counter Handler")), + ); +} + +/// given a slice of handles assumed to be larger than 0 +/// chooses one +/// # Panics +/// panics if handles is of length 0 +pub fn get_random_handle(handles: &[Arc>]) -> Arc> { + handles.iter().choose(&mut thread_rng()).unwrap().clone() +} + +/// print the connections for each handle in `handles` +/// useful for debugging +async fn print_connections(handles: &[Arc>]) { + warn!("PRINTING CONNECTION STATES"); + for (i, handle) in handles.iter().enumerate() { + warn!( + "peer {}, connected to {:?}", + i, + handle.connection_state.lock().await.connected_peers + ); + warn!( + "peer {}, knowns about {:?}", + i, + handle.connection_state.lock().await.known_peers + ); + } +} + +/// error wrapper type for interacting with swarm handle +#[derive(Debug, Snafu)] +#[snafu(visibility(pub))] +pub enum HandlerError { + /// error generating network + NetworkError { + /// source of error + source: NetworkError, + }, + /// failure to serialize a message + SerializationError { + /// source of error + source: Box, + }, + /// failure to deserialize a message + DeserializationError {}, + /// error sending request to network + SendError { + /// source of error + source: SendError, + }, + /// error receiving message from network + RecvError { + /// source of error + source: RecvError, + }, +} diff --git a/libp2p-networking/src/node_handle.rs b/libp2p-networking/src/node_handle.rs new file mode 100644 index 0000000000..e69de29bb2 diff --git a/libp2p-networking/src/ui.rs b/libp2p-networking/src/ui.rs index 41316a0d52..64fc9926fb 100644 --- a/libp2p-networking/src/ui.rs +++ b/libp2p-networking/src/ui.rs @@ -1,7 +1,7 @@ #![allow(missing_docs)] use async_std::task::{sleep, spawn}; -use crate::NetworkEvent; +use crate::network_node::NetworkEvent; use bincode::Options; use color_eyre::{ eyre::{Result, WrapErr}, @@ -27,7 +27,7 @@ use tui::{ Frame, Terminal, }; -use crate::{message::Message, ClientRequest}; +use crate::{message::Message, network_node::ClientRequest}; #[derive(Debug, Copy, Clone)] pub enum InputMode { diff --git a/libp2p-networking/tests/common.rs b/libp2p-networking/tests/common.rs new file mode 100644 index 0000000000..8b13789179 --- /dev/null +++ b/libp2p-networking/tests/common.rs @@ -0,0 +1 @@ + diff --git a/libp2p-networking/tests/counter.rs b/libp2p-networking/tests/counter.rs index 7253e67202..593250f34a 100644 --- a/libp2p-networking/tests/counter.rs +++ b/libp2p-networking/tests/counter.rs @@ -1,30 +1,27 @@ use std::{sync::Arc, time::Duration}; -use async_std::{ - sync::Mutex, - task::{sleep, spawn}, -}; +use async_std::task::sleep; use bincode::Options; -use flume::{Receiver, RecvError, SendError, Sender}; -use futures::{select, Future, FutureExt}; -use libp2p::{gossipsub::Topic, Multiaddr, PeerId}; + +use libp2p::gossipsub::Topic; use networking_demo::{ - gen_multiaddr, ClientRequest, ConnectionData, NetworkError, NetworkEvent, NetworkNode, - NetworkNodeType, + network_node::{ClientRequest, NetworkEvent}, + network_node_handle::{ + get_random_handle, test_bed, HandlerError, NetworkNodeHandle, SendSnafu, SerializationSnafu, + }, }; use rand::{seq::IteratorRandom, thread_rng}; use std::fmt::Debug; use serde::{Deserialize, Serialize}; -use snafu::{ResultExt, Snafu}; -use std::sync::Once; -use tracing::{error, info, info_span, instrument, warn, Instrument}; +use snafu::ResultExt; + +use tracing::{error, instrument, warn}; pub type Counter = u8; -const TOTAL_NUM_PEERS: usize = 20; -static INIT: Once = Once::new(); +const TOTAL_NUM_PEERS: usize = 20; /// Message types. We can either /// - increment the Counter @@ -43,150 +40,13 @@ pub enum CounterMessage { #[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, Default)] pub struct CounterState(Counter); -/// A handle containing: -/// - A reference to the state -/// - Controls for the swarm -/// -#[derive(Debug)] -pub struct SwarmHandle { - /// the state. TODO make this generic - state: Arc>, - /// send an action to the networkbehaviour - send_chan: Sender, - /// receive an action from the networkbehaviour - recv_chan: Receiver, - /// kill the event handler for events from the swarm - kill_switch: Sender<()>, - /// receiving end of `kill_switch` - recv_kill: Receiver<()>, - /// the local address we're listening on - listen_addr: Multiaddr, - /// the peer id of the networkbehaviour - peer_id: PeerId, - /// the connection metadata associated with the networkbehaviour - connection_state: Arc>, -} - -impl SwarmHandle { - /// constructs a new node listening on `known_addr` - #[instrument] - pub async fn new( - known_addr: Option, - node_type: NetworkNodeType, - ) -> Result { - //`randomly assigned port - let listen_addr = gen_multiaddr(0); - let mut network = NetworkNode::new(node_type).await.context(NetworkSnafu)?; - let peer_id = network.peer_id; - let listen_addr = network - .start(listen_addr, known_addr) - .await - .context(NetworkSnafu)?; - let (send_chan, recv_chan) = network.spawn_listeners().await.context(NetworkSnafu)?; - let (kill_switch, recv_kill) = flume::bounded(1); - - send_chan - .send_async(ClientRequest::Subscribe("global".to_string())) - .await - .context(SendSnafu)?; - - Ok(SwarmHandle { - state: Arc::new(Mutex::new(S::default())), - send_chan, - recv_chan, - kill_switch, - recv_kill, - listen_addr, - peer_id, - connection_state: Default::default(), - }) - } - - /// Cleanly shuts down a swarm node - /// This is done by sending a message to - /// the swarm event handler to stop handling events - /// and a message to the swarm itself to spin down - #[instrument] - pub async fn kill(&self) -> Result<(), NetworkError> { - self.send_chan - .send_async(ClientRequest::Shutdown) - .await - .map_err(|_e| NetworkError::StreamClosed)?; - self.kill_switch - .send_async(()) - .await - .map_err(|_e| NetworkError::StreamClosed)?; - Ok(()) - } - - /// spins up `num_of_nodes` nodes and connects them to each other - #[instrument] - pub async fn spin_up_swarms(num_of_nodes: usize) -> Result>, HandlerError> { - // FIXME change API to accomodate multiple bootstrap nodes - let bootstrap: SwarmHandle = SwarmHandle::new(None, NetworkNodeType::Bootstrap).await?; - let bootstrap_addr = bootstrap.listen_addr.clone(); - info!( - "boostrap node {} on addr {}", - bootstrap.peer_id, bootstrap_addr - ); - // give a split second to initialize - // TODO the proper way to do this is to make it event driven. Once it bootstraps *successfully* - // THEN add next peer - sleep(Duration::from_secs(1)).await; - let mut handles = Vec::new(); - for _ in 0..(num_of_nodes - 1) { - handles.push(Arc::new( - SwarmHandle::new(Some(bootstrap_addr.clone()), NetworkNodeType::Regular).await?, - )); - sleep(Duration::from_secs(1)).await; - } - Ok(handles) - } -} - -/// general function to spin up testing infra -/// perform tests by calling `run_test` -/// then cleans up tests -pub async fn test_bed( - run_test: F, - client_handler: G, -) where - FutF: Future, - FutG: Future> + 'static + Send + Sync, - F: FnOnce(Vec>>) -> FutF, - G: Fn(NetworkEvent, Arc>) -> FutG + 'static + Send + Sync, -{ - // only call once otherwise panics - // - INIT.call_once(|| { - color_eyre::install().unwrap(); - networking_demo::tracing_setup::setup_tracing(); - }); - - // NOTE we want this to panic if we can't spin up the swarms. - // that amounts to a failed test. - let handles: Vec>> = - SwarmHandle::spin_up_swarms(TOTAL_NUM_PEERS).await.unwrap(); - for handle in handles.iter() { - spawn_handler(handle.clone(), client_handler.clone()).await; - } - print_connections(&handles).await; - - run_test(handles.clone()).await; - - // cleanup - for handle in handles.into_iter() { - handle.kill().await.unwrap(); - } -} - /// event handler for events from the swarm /// - updates state based on events received /// - replies to direct messages #[instrument] -pub async fn handle_counter_event( +pub async fn counter_handle_network_event( event: NetworkEvent, - handle: Arc>, + handle: Arc>, ) -> Result<(), HandlerError> { use CounterMessage::*; #[allow(clippy::enum_glob_use)] @@ -199,7 +59,6 @@ pub async fn handle_counter_event( MyCounterIs(c) | CounterMessage::IncrementCounter { to: c, .. } => { *handle.state.lock().await = c; } - // NOTE doesn't make sense at the request level AskForCounter => {} } } @@ -212,19 +71,15 @@ pub async fn handle_counter_event( } AskForCounter => { let response = MyCounterIs(handle.state.lock().await.clone()); - // FIXME error handling let serialized_response = bincode_options .serialize(&response) .context(SerializationSnafu)?; - // FIXME error handling handle - .send_chan + .send_network .send_async(ClientRequest::DirectResponse(chan, serialized_response)) .await .context(SendSnafu)? } - // NOTE doesn't make sense as request type - // TODO maybe should check this at the type level MyCounterIs(_) => {} } } @@ -239,54 +94,11 @@ pub async fn handle_counter_event( Ok(()) } -/// Glue function that listens for events from the Swarm corresponding to `handle` -/// and calls `event_handler` when an event is observed. -/// The idea is that this function can be used independent of the actual behaviour -/// we want -#[instrument(skip(event_handler))] -pub async fn spawn_handler( - handle: Arc>, - event_handler: impl (Fn(NetworkEvent, Arc>) -> Fut) - + std::marker::Sync - + std::marker::Send - + 'static, -) where - Fut: - Future> + std::marker::Send + 'static + std::marker::Sync, -{ - let recv_kill = handle.recv_kill.clone(); - let recv_event = handle.recv_chan.clone(); - spawn( - async move { - loop { - select!( - _ = recv_kill.recv_async().fuse() => { - break; - }, - event = recv_event.recv_async().fuse() => { - event_handler(event.context(RecvSnafu)?, handle.clone()).await?; - }, - ); - } - Ok::<(), HandlerError>(()) - } - .instrument(info_span!("Libp2p Counter Handler")), - ); -} - -/// given a slice of handles assumed to be larger than 0 -/// chooses one -/// # Panics -/// panics if handles is of length 0 -pub fn get_random_handle(handles: &[Arc>]) -> Arc> { - handles.iter().choose(&mut thread_rng()).unwrap().clone() -} - /// check that we can direct message to increment counter #[async_std::test] #[instrument] async fn test_request_response() { - async fn run_request_response(handles: Vec>>) { + async fn run_request_response(handles: Vec>>) { let send_handle = get_random_handle(handles.as_slice()); let recv_handle = get_random_handle(handles.as_slice()); @@ -300,7 +112,7 @@ async fn test_request_response() { }) .unwrap(); let msg = ClientRequest::DirectRequest(recv_handle.peer_id, msg_inner); - send_handle.send_chan.send_async(msg).await.unwrap(); + send_handle.send_network.send_async(msg).await.unwrap(); // block to let the direction message // TODO make this event driven @@ -319,14 +131,19 @@ async fn test_request_response() { } } - test_bed(run_request_response, handle_counter_event).await + test_bed( + run_request_response, + counter_handle_network_event, + TOTAL_NUM_PEERS, + ) + .await } /// check that we can broadcast a message out and get counter increments #[async_std::test] #[instrument] async fn test_gossip() { - async fn run_gossip(handles: Vec>>) { + async fn run_gossip(handles: Vec>>) { let msg_handle = handles.iter().choose(&mut thread_rng()).unwrap(); *msg_handle.state.lock().await = CounterState(5); let bincode_options = bincode::DefaultOptions::new().with_limit(16_384); @@ -338,7 +155,7 @@ async fn test_gossip() { .unwrap(); let (send, recv) = flume::bounded(1); let msg = ClientRequest::GossipMsg(Topic::new("global"), msg_inner, send); - msg_handle.send_chan.send_async(msg).await.unwrap(); + msg_handle.send_network.send_async(msg).await.unwrap(); recv.recv_async().await.unwrap().unwrap(); // block to let the gossipping happen @@ -359,32 +176,5 @@ async fn test_gossip() { } } - test_bed(run_gossip, handle_counter_event).await; -} - -/// print the connections for each handle in `handles` -/// useful for debugging -async fn print_connections(handles: &[Arc>]) { - warn!("PRINTING CONNECTION STATES"); - for (i, handle) in handles.iter().enumerate() { - warn!( - "peer {}, connected to {:?}", - i, - handle.connection_state.lock().await.connected_peers - ); - warn!( - "peer {}, knowns about {:?}", - i, - handle.connection_state.lock().await.known_peers - ); - } -} - -#[derive(Debug, Snafu)] -pub enum HandlerError { - NetworkError { source: NetworkError }, - SerializationError { source: Box }, - DeserializationError {}, - SendError { source: SendError }, - RecvError { source: RecvError }, + test_bed(run_gossip, counter_handle_network_event, TOTAL_NUM_PEERS).await; } From 3239e18e989d20112b7296a893e1a825a7fd1aec Mon Sep 17 00:00:00 2001 From: Justin Restivo Date: Wed, 2 Feb 2022 12:03:47 -0500 Subject: [PATCH 055/107] feat: spin_up_swarm event driven --- libp2p-networking/src/network_node.rs | 68 ++++++++++++-------- libp2p-networking/src/network_node_handle.rs | 37 +++++++---- libp2p-networking/src/node_handle.rs | 0 libp2p-networking/src/ui.rs | 2 +- libp2p-networking/tests/counter.rs | 11 ++-- 5 files changed, 73 insertions(+), 45 deletions(-) delete mode 100644 libp2p-networking/src/node_handle.rs diff --git a/libp2p-networking/src/network_node.rs b/libp2p-networking/src/network_node.rs index 27c7ab8afd..16d9e4ec0d 100644 --- a/libp2p-networking/src/network_node.rs +++ b/libp2p-networking/src/network_node.rs @@ -66,7 +66,7 @@ pub struct NetworkDef { pub request_response: RequestResponse, /// if the node has been bootstrapped into the kademlia network #[behaviour(ignore)] - pub bootstrap: bool, + pub bootstrap_in_progress: bool, // TODO separate out into ConnectionData struct /// set of connected peers #[behaviour(ignore)] @@ -86,7 +86,7 @@ pub struct NetworkDef { impl Debug for NetworkDef { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { f.debug_struct("NetworkDef") - .field("bootstrap", &self.bootstrap) + .field("bootstrap", &self.bootstrap_in_progress) .field("connected_peers", &self.connected_peers) .field("connecting_peers", &self.connecting_peers) .field("known_peers", &self.known_peers) @@ -101,7 +101,7 @@ pub struct ConnectionData { pub connected_peers: HashSet, /// set of peers that were at one point connected pub connecting_peers: HashSet, - /// set of events to send to UI + /// set of events to send to client pub known_peers: HashSet, } @@ -112,8 +112,8 @@ impl NetworkDef { _: &mut impl PollParameters, ) -> Poll::ProtocolsHandler>> { - // push events that must be relayed back to UI onto queue - // to be consumed by UI event handler + // push events that must be relayed back to client onto queue + // to be consumed by client event handler if !self.client_event_queue.is_empty() { return Poll::Ready(NetworkBehaviourAction::GenerateEvent( self.client_event_queue.remove(0), @@ -145,13 +145,14 @@ impl NetworkBehaviourEventProcess for NetworkDef { QueryResult::Bootstrap(r) => { match r { Ok(_bootstrap) => { + // we're bootstrapped // don't bootstrap again - self.bootstrap = false; + self.bootstrap_in_progress = false; } Err(_) => { // try again - self.bootstrap = true; + self.bootstrap_in_progress = true; } } } @@ -167,14 +168,18 @@ impl NetworkBehaviourEventProcess for NetworkDef { } KademliaEvent::RoutingUpdated { peer, - is_new_peer: _is_new_peer, - addresses: _addresses, + is_new_peer, + addresses, .. } => { self.known_peers.insert(peer); self.client_event_queue .push(NetworkEvent::UpdateKnownPeers(self.known_peers.clone())); - } + // TODO maybe this helps? + // if !is_new_peer && addresses.len() >= 2 { + // self.client_event_queue.push(NetworkEvent::SuccessfulBootstrap(peer)) + // } + }, _ => {} } } @@ -286,6 +291,8 @@ pub enum ClientRequest { /// to relay to the client #[derive(Debug)] pub enum NetworkEvent { + /// successfully bootstrapped the node + SuccessfulBootstrap(PeerId), /// connected to a new peer UpdateConnectedPeers(HashSet), /// discovered a new peer @@ -353,10 +360,15 @@ impl NetworkNode { ) -> Result { self.swarm.listen_on(listen_addr).context(TransportSnafu)?; let addr = loop { - match self.swarm.next().await { - Some(SwarmEvent::NewListenAddr { address, .. }) => break address, - _ => continue, - }; + if let Some(SwarmEvent::NewListenAddr { address, .. }) = self.swarm.next().await { + break address; + // let new_addr = address.to_string(); + // let mut tmp = String::new(); + // tmp.push_str("/ip4/192.168.1.96/tcp/"); + // tmp.push_str(&new_addr[new_addr.len()-5..new_addr.len()]); + // // new_addr[ + // break tmp.parse().unwrap(); + } }; info!("peerid {:?} listen addr: {:?}", self.peer_id, addr); if let Some(known_peer) = known_peer { @@ -451,7 +463,7 @@ impl NetworkNode { connecting_peers: HashSet::new(), known_peers: HashSet::new(), client_event_queue: Vec::new(), - bootstrap: false, + bootstrap_in_progress: false, }; Swarm::new(transport, network, peer_id) @@ -460,8 +472,8 @@ impl NetworkNode { Ok(Self { identity, peer_id, - max_num_peers: 600, - min_num_peers: 50, + max_num_peers: 15, + min_num_peers: 10, swarm, node_type, }) @@ -471,7 +483,7 @@ impl NetworkNode { /// looks up a random peer #[instrument(skip(self))] fn handle_peer_discovery(&mut self) { - if !self.swarm.behaviour().bootstrap { + if !self.swarm.behaviour().bootstrap_in_progress { let random_peer = PeerId::random(); self.swarm .behaviour_mut() @@ -487,7 +499,7 @@ impl NetworkNode { let swarm = self.swarm.behaviour(); // if we're bootstrapped, do nothing // otherwise periodically get more peers if needed - if !swarm.bootstrap { + if !swarm.bootstrap_in_progress { if swarm.connecting_peers.len() + swarm.connected_peers.len() <= self.min_num_peers { // Calcuate the currently connected peers let used_peers = swarm @@ -640,7 +652,7 @@ impl NetworkNode { ProtocolsHandlerUpgrErr, >, >, - send_to_ui: &Sender, + send_to_client: &Sender, ) -> Result<(), NetworkError> { // Make the match cleaner #[allow(clippy::enum_glob_use)] @@ -671,14 +683,14 @@ impl NetworkNode { self.swarm.behaviour_mut().connected_peers.insert(peer_id); self.swarm.behaviour_mut().connecting_peers.remove(&peer_id); // now we have at least one peer so we can bootstrap - if !self.swarm.behaviour().bootstrap { + if !self.swarm.behaviour().bootstrap_in_progress { self.swarm .behaviour_mut() .kadem .bootstrap() .map_err(|_e| NetworkError::NoKnownPeers)?; } - send_to_ui + send_to_client .send_async(NetworkEvent::UpdateConnectedPeers( self.swarm.behaviour_mut().connected_peers.clone(), )) @@ -691,13 +703,13 @@ impl NetworkNode { // FIXME remove stale address, not *all* addresses swarm.kadem.remove_peer(&peer_id); - send_to_ui + send_to_client .send_async(NetworkEvent::UpdateConnectedPeers( swarm.connected_peers.clone(), )) .await .map_err(|_e| NetworkError::StreamClosed)?; - send_to_ui + send_to_client .send_async(NetworkEvent::UpdateKnownPeers(swarm.known_peers.clone())) .await .map_err(|_e| NetworkError::StreamClosed)?; @@ -712,8 +724,8 @@ impl NetworkNode { | BannedPeer { .. } | ListenerError { .. } => {} Behaviour(b) => { - // forward messages directly to UI - send_to_ui + // forward messages directly to Client + send_to_client .send_async(b) .await .map_err(|_e| NetworkError::StreamClosed)?; @@ -724,7 +736,6 @@ impl NetworkNode { /// Spawn a task to listen for requests on the returned channel /// as well as any events produced by libp2p - /// `mut_mut` is disabled b/c must consume `self` #[allow(clippy::panic)] #[instrument(skip(self))] pub async fn spawn_listeners( @@ -736,8 +747,9 @@ impl NetworkNode { spawn( async move { loop { + // TODO variable on futures times select! { - _ = sleep(Duration::from_secs(30)).fuse() => { + _ = sleep(Duration::from_secs(1)).fuse() => { self.handle_peer_discovery(); }, _ = sleep(Duration::from_secs(1)).fuse() => { diff --git a/libp2p-networking/src/network_node_handle.rs b/libp2p-networking/src/network_node_handle.rs index 149cc382ca..dfae498eed 100644 --- a/libp2p-networking/src/network_node_handle.rs +++ b/libp2p-networking/src/network_node_handle.rs @@ -8,7 +8,7 @@ use crate::network_node::{ NetworkNodeType, }; use flume::{Receiver, RecvError, SendError, Sender}; -use futures::{select, Future, FutureExt}; +use futures::{select, Future, FutureExt, future::join}; use libp2p::{Multiaddr, PeerId}; use rand::{seq::IteratorRandom, thread_rng}; use snafu::{ResultExt, Snafu}; @@ -99,6 +99,7 @@ impl NetworkNodeHandle { /// spins up `num_of_nodes` nodes and connects them to each other #[instrument] pub async fn spin_up_swarms(num_of_nodes: usize) -> Result>, HandlerError> { + use NetworkEvent::*; // FIXME change API to accomodate multiple bootstrap nodes let bootstrap: NetworkNodeHandle = NetworkNodeHandle::new(None, NetworkNodeType::Bootstrap).await?; @@ -107,18 +108,32 @@ impl NetworkNodeHandle { "boostrap node {} on addr {}", bootstrap.peer_id, bootstrap_addr ); - // give a split second to initialize - // TODO the proper way to do this is to make it event driven. Once it bootstraps *successfully* - // THEN add next peer - sleep(Duration::from_secs(1)).await; let mut handles = Vec::new(); - for _ in 0..(num_of_nodes - 1) { - handles.push(Arc::new( - NetworkNodeHandle::new(Some(bootstrap_addr.clone()), NetworkNodeType::Regular) - .await?, - )); - sleep(Duration::from_secs(1)).await; + println!("bootstrap addr is: {:?}", bootstrap_addr); + + async fn wait_to_connect(num_of_nodes: usize, chan: Receiver, node_idx: usize){ + 'a: loop { + if let NetworkEvent::UpdateConnectedPeers(pids) = chan.recv_async().await.context(RecvSnafu).unwrap(){ + if pids.len() >= 15 { + println!("node {} done", node_idx); + break 'a; + } + else { + println!("node {} connected to {:?} nodes", node_idx, pids.len()); + } + } + } + } + + + let mut connecting_futs = vec![wait_to_connect(num_of_nodes, bootstrap.recv_network.clone(), 0)]; + for i in 0..(num_of_nodes - 1) { + let node = Arc::new(NetworkNodeHandle::new(Some(bootstrap_addr.clone()), NetworkNodeType::Regular).await?); + connecting_futs.push(wait_to_connect(num_of_nodes, node.recv_network.clone(), i+1)); + + handles.push(node); } + futures::future::join_all(connecting_futs.into_iter()).await; Ok(handles) } } diff --git a/libp2p-networking/src/node_handle.rs b/libp2p-networking/src/node_handle.rs deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/libp2p-networking/src/ui.rs b/libp2p-networking/src/ui.rs index 64fc9926fb..fa55e27a39 100644 --- a/libp2p-networking/src/ui.rs +++ b/libp2p-networking/src/ui.rs @@ -119,7 +119,7 @@ pub async fn run_app(terminal: &mut Terminal, mut app: TableApp) UpdateKnownPeers(peer_set) => { *app.known_peer_list.lock() = peer_set.clone(); } - DirectResponse(_) => { /* NOTE unimplemented in this example */ } + DirectResponse(_) | SuccessfulBootstrap(_) => { /* NOTE unimplemented in this example */ } } } }, diff --git a/libp2p-networking/tests/counter.rs b/libp2p-networking/tests/counter.rs index 593250f34a..5e1e216158 100644 --- a/libp2p-networking/tests/counter.rs +++ b/libp2p-networking/tests/counter.rs @@ -62,7 +62,7 @@ pub async fn counter_handle_network_event( AskForCounter => {} } } - } + }, DirectRequest(m, chan) => { if let Ok(msg) = bincode_options.deserialize::(&m) { match msg { @@ -83,13 +83,14 @@ pub async fn counter_handle_network_event( MyCounterIs(_) => {} } } - } + }, UpdateConnectedPeers(p) => { handle.connection_state.lock().await.connected_peers = p; - } + }, UpdateKnownPeers(p) => { handle.connection_state.lock().await.known_peers = p; - } + }, + SuccessfulBootstrap(_) => {} }; Ok(()) } @@ -162,7 +163,7 @@ async fn test_gossip() { // TODO make this event driven // e.g. everyone receives the gossipmsg event // or timeout - sleep(Duration::from_millis(10)).await; + sleep(Duration::from_secs(10)).await; let mut failing_idxs = Vec::new(); for (i, handle) in handles.iter().enumerate() { From 7ef28353827a56b2e147b3f60145c8e74a4c1231 Mon Sep 17 00:00:00 2001 From: Justin Restivo Date: Wed, 2 Feb 2022 13:17:50 -0500 Subject: [PATCH 056/107] feat: Event driven gossip test --- libp2p-networking/Cargo.lock | 18 ++++++ libp2p-networking/Cargo.toml | 2 +- libp2p-networking/flake.nix | 2 + libp2p-networking/src/network_node.rs | 18 +----- libp2p-networking/src/network_node_handle.rs | 61 ++++++++++++-------- libp2p-networking/src/ui.rs | 2 +- libp2p-networking/tests/counter.rs | 33 +++++++---- 7 files changed, 86 insertions(+), 50 deletions(-) diff --git a/libp2p-networking/Cargo.lock b/libp2p-networking/Cargo.lock index e8a92e533b..3ce9082e04 100644 --- a/libp2p-networking/Cargo.lock +++ b/libp2p-networking/Cargo.lock @@ -199,6 +199,23 @@ dependencies = [ "event-listener", ] +[[package]] +name = "async-process" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "83137067e3a2a6a06d67168e49e68a0957d215410473a740cea95a2425c0b7c6" +dependencies = [ + "async-io", + "blocking", + "cfg-if", + "event-listener", + "futures-lite", + "libc", + "once_cell", + "signal-hook", + "winapi", +] + [[package]] name = "async-std" version = "1.10.0" @@ -210,6 +227,7 @@ dependencies = [ "async-global-executor", "async-io", "async-lock", + "async-process", "crossbeam-utils", "futures-channel", "futures-core", diff --git a/libp2p-networking/Cargo.toml b/libp2p-networking/Cargo.toml index e535c3d75b..9b98694eb4 100644 --- a/libp2p-networking/Cargo.toml +++ b/libp2p-networking/Cargo.toml @@ -6,7 +6,7 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -async-std = { version = "1.10.0", features = ["attributes"] } +async-std = { version = "1.10.0", features = ["attributes", "unstable"] } bincode = "1.3.3" blake3 = "1.3.0" color-eyre = "0.6.0" diff --git a/libp2p-networking/flake.nix b/libp2p-networking/flake.nix index 2d78051efb..e39d6ff871 100644 --- a/libp2p-networking/flake.nix +++ b/libp2p-networking/flake.nix @@ -68,6 +68,7 @@ }; }; + shellHook = '''' + (pkgs.lib.optionals pkgs.stdenv.isDarwin '' ulimit -n 10240 ''); in { packages.${crateName} = project.rootCrate.build; @@ -78,6 +79,7 @@ defaultPackage = self.packages.${system}.${crateName}; devShell = pkgs.mkShell { + inherit shellHook; inputsFrom = builtins.attrValues self.packages.${system}; buildInputs = with pkgs; [ cargo-audit nixpkgs-fmt git-chglog fenix.packages.${system}.rust-analyzer fenixPackage protobuf] diff --git a/libp2p-networking/src/network_node.rs b/libp2p-networking/src/network_node.rs index 16d9e4ec0d..ae269e5647 100644 --- a/libp2p-networking/src/network_node.rs +++ b/libp2p-networking/src/network_node.rs @@ -145,7 +145,6 @@ impl NetworkBehaviourEventProcess for NetworkDef { QueryResult::Bootstrap(r) => { match r { Ok(_bootstrap) => { - // we're bootstrapped // don't bootstrap again self.bootstrap_in_progress = false; @@ -166,20 +165,11 @@ impl NetworkBehaviourEventProcess for NetworkDef { _ => {} } } - KademliaEvent::RoutingUpdated { - peer, - is_new_peer, - addresses, - .. - } => { + KademliaEvent::RoutingUpdated { peer, .. } => { self.known_peers.insert(peer); self.client_event_queue .push(NetworkEvent::UpdateKnownPeers(self.known_peers.clone())); - // TODO maybe this helps? - // if !is_new_peer && addresses.len() >= 2 { - // self.client_event_queue.push(NetworkEvent::SuccessfulBootstrap(peer)) - // } - }, + } _ => {} } } @@ -291,8 +281,6 @@ pub enum ClientRequest { /// to relay to the client #[derive(Debug)] pub enum NetworkEvent { - /// successfully bootstrapped the node - SuccessfulBootstrap(PeerId), /// connected to a new peer UpdateConnectedPeers(HashSet), /// discovered a new peer @@ -368,7 +356,7 @@ impl NetworkNode { // tmp.push_str(&new_addr[new_addr.len()-5..new_addr.len()]); // // new_addr[ // break tmp.parse().unwrap(); - } + } }; info!("peerid {:?} listen addr: {:?}", self.peer_id, addr); if let Some(known_peer) = known_peer { diff --git a/libp2p-networking/src/network_node_handle.rs b/libp2p-networking/src/network_node_handle.rs index dfae498eed..daf40dab9a 100644 --- a/libp2p-networking/src/network_node_handle.rs +++ b/libp2p-networking/src/network_node_handle.rs @@ -1,6 +1,6 @@ use async_std::{ - sync::Mutex, - task::{sleep, spawn}, + sync::{Condvar, Mutex}, + task::spawn, }; use crate::network_node::{ @@ -8,14 +8,13 @@ use crate::network_node::{ NetworkNodeType, }; use flume::{Receiver, RecvError, SendError, Sender}; -use futures::{select, Future, FutureExt, future::join}; +use futures::{select, Future, FutureExt}; use libp2p::{Multiaddr, PeerId}; use rand::{seq::IteratorRandom, thread_rng}; use snafu::{ResultExt, Snafu}; use std::{ fmt::Debug, sync::{Arc, Once}, - time::Duration, }; use tracing::{info, info_span, instrument, warn, Instrument}; @@ -26,6 +25,8 @@ static INIT: Once = Once::new(); /// - Controls for the swarm #[derive(Debug)] pub struct NetworkNodeHandle { + /// notifies that a state change has occurred + pub state_changed: Condvar, /// the state of the replica pub state: Arc>, /// send an action to the networkbehaviour @@ -68,6 +69,7 @@ impl NetworkNodeHandle { .context(SendSnafu)?; Ok(NetworkNodeHandle { + state_changed: Condvar::new(), state: Arc::new(Mutex::new(S::default())), send_network: send_chan, recv_network: recv_chan, @@ -99,7 +101,24 @@ impl NetworkNodeHandle { /// spins up `num_of_nodes` nodes and connects them to each other #[instrument] pub async fn spin_up_swarms(num_of_nodes: usize) -> Result>, HandlerError> { - use NetworkEvent::*; + async fn wait_to_connect( + _num_of_nodes: usize, + chan: Receiver, + node_idx: usize, + ) { + loop { + if let NetworkEvent::UpdateConnectedPeers(pids) = + chan.recv_async().await.context(RecvSnafu).unwrap() + { + // FIXME don't hardcode this + if pids.len() >= 15 { + println!("node {} done", node_idx); + break; + } + } + } + } + // FIXME change API to accomodate multiple bootstrap nodes let bootstrap: NetworkNodeHandle = NetworkNodeHandle::new(None, NetworkNodeType::Bootstrap).await?; @@ -111,25 +130,21 @@ impl NetworkNodeHandle { let mut handles = Vec::new(); println!("bootstrap addr is: {:?}", bootstrap_addr); - async fn wait_to_connect(num_of_nodes: usize, chan: Receiver, node_idx: usize){ - 'a: loop { - if let NetworkEvent::UpdateConnectedPeers(pids) = chan.recv_async().await.context(RecvSnafu).unwrap(){ - if pids.len() >= 15 { - println!("node {} done", node_idx); - break 'a; - } - else { - println!("node {} connected to {:?} nodes", node_idx, pids.len()); - } - } - } - } - - - let mut connecting_futs = vec![wait_to_connect(num_of_nodes, bootstrap.recv_network.clone(), 0)]; + let mut connecting_futs = vec![wait_to_connect( + num_of_nodes, + bootstrap.recv_network.clone(), + 0, + )]; for i in 0..(num_of_nodes - 1) { - let node = Arc::new(NetworkNodeHandle::new(Some(bootstrap_addr.clone()), NetworkNodeType::Regular).await?); - connecting_futs.push(wait_to_connect(num_of_nodes, node.recv_network.clone(), i+1)); + let node = Arc::new( + NetworkNodeHandle::new(Some(bootstrap_addr.clone()), NetworkNodeType::Regular) + .await?, + ); + connecting_futs.push(wait_to_connect( + num_of_nodes, + node.recv_network.clone(), + i + 1, + )); handles.push(node); } diff --git a/libp2p-networking/src/ui.rs b/libp2p-networking/src/ui.rs index fa55e27a39..64fc9926fb 100644 --- a/libp2p-networking/src/ui.rs +++ b/libp2p-networking/src/ui.rs @@ -119,7 +119,7 @@ pub async fn run_app(terminal: &mut Terminal, mut app: TableApp) UpdateKnownPeers(peer_set) => { *app.known_peer_list.lock() = peer_set.clone(); } - DirectResponse(_) | SuccessfulBootstrap(_) => { /* NOTE unimplemented in this example */ } + DirectResponse(_) => { /* NOTE unimplemented in this example */ } } } }, diff --git a/libp2p-networking/tests/counter.rs b/libp2p-networking/tests/counter.rs index 5e1e216158..1f8d9052fc 100644 --- a/libp2p-networking/tests/counter.rs +++ b/libp2p-networking/tests/counter.rs @@ -57,17 +57,22 @@ pub async fn counter_handle_network_event( if let Ok(msg) = bincode_options.deserialize::(&m) { match msg { MyCounterIs(c) | CounterMessage::IncrementCounter { to: c, .. } => { + println!("recv-ed"); *handle.state.lock().await = c; + handle.state_changed.notify_all(); } AskForCounter => {} } } - }, + } DirectRequest(m, chan) => { if let Ok(msg) = bincode_options.deserialize::(&m) { match msg { IncrementCounter { to, .. } => { + // TODO move the state changes out into a function call that triggers the + // condvar *handle.state.lock().await = to; + handle.state_changed.notify_all(); } AskForCounter => { let response = MyCounterIs(handle.state.lock().await.clone()); @@ -83,14 +88,13 @@ pub async fn counter_handle_network_event( MyCounterIs(_) => {} } } - }, + } UpdateConnectedPeers(p) => { handle.connection_state.lock().await.connected_peers = p; - }, + } UpdateKnownPeers(p) => { handle.connection_state.lock().await.known_peers = p; - }, - SuccessfulBootstrap(_) => {} + } }; Ok(()) } @@ -156,14 +160,23 @@ async fn test_gossip() { .unwrap(); let (send, recv) = flume::bounded(1); let msg = ClientRequest::GossipMsg(Topic::new("global"), msg_inner, send); + + let mut futs = Vec::new(); + println!("starting the wait!"); + // FIXME create method out of this + for (_i, a_handle) in handles.iter().enumerate() { + let a_fut = a_handle + .state_changed + .wait_until(a_handle.state.lock().await, |state| { + *state == CounterState(5) + }); + futs.push(a_fut); + } + msg_handle.send_network.send_async(msg).await.unwrap(); recv.recv_async().await.unwrap().unwrap(); - // block to let the gossipping happen - // TODO make this event driven - // e.g. everyone receives the gossipmsg event - // or timeout - sleep(Duration::from_secs(10)).await; + futures::future::join_all(futs).await; let mut failing_idxs = Vec::new(); for (i, handle) in handles.iter().enumerate() { From fa132a2a23172948162012c6f71b8bdc9e8d2f07 Mon Sep 17 00:00:00 2001 From: Justin Restivo Date: Wed, 2 Feb 2022 15:40:03 -0500 Subject: [PATCH 057/107] feat: Event driven requestresponse --- libp2p-networking/src/network_node_handle.rs | 4 +-- libp2p-networking/tests/counter.rs | 26 +++++++++----------- 2 files changed, 14 insertions(+), 16 deletions(-) diff --git a/libp2p-networking/src/network_node_handle.rs b/libp2p-networking/src/network_node_handle.rs index daf40dab9a..0b2ae2b254 100644 --- a/libp2p-networking/src/network_node_handle.rs +++ b/libp2p-networking/src/network_node_handle.rs @@ -102,7 +102,7 @@ impl NetworkNodeHandle { #[instrument] pub async fn spin_up_swarms(num_of_nodes: usize) -> Result>, HandlerError> { async fn wait_to_connect( - _num_of_nodes: usize, + num_of_nodes: usize, chan: Receiver, node_idx: usize, ) { @@ -111,7 +111,7 @@ impl NetworkNodeHandle { chan.recv_async().await.context(RecvSnafu).unwrap() { // FIXME don't hardcode this - if pids.len() >= 15 { + if pids.len() >= 3 * num_of_nodes / 4 { println!("node {} done", node_idx); break; } diff --git a/libp2p-networking/tests/counter.rs b/libp2p-networking/tests/counter.rs index 1f8d9052fc..75d90ca699 100644 --- a/libp2p-networking/tests/counter.rs +++ b/libp2p-networking/tests/counter.rs @@ -1,6 +1,5 @@ -use std::{sync::Arc, time::Duration}; +use std::sync::Arc; -use async_std::task::sleep; use bincode::Options; use libp2p::gossipsub::Topic; @@ -116,14 +115,17 @@ async fn test_request_response() { to: CounterState(5), }) .unwrap(); + let msg = ClientRequest::DirectRequest(recv_handle.peer_id, msg_inner); + + let recv_fut = recv_handle + .state_changed + .wait_until(recv_handle.state.lock().await, |state| { + *state == CounterState(5) + }); send_handle.send_network.send_async(msg).await.unwrap(); - // block to let the direction message - // TODO make this event driven - // e.g. everyone receives the gossipmsg event - // or timeout - sleep(Duration::from_secs(1)).await; + recv_fut.await; for handle in handles.iter() { let expected_state = @@ -162,14 +164,10 @@ async fn test_gossip() { let msg = ClientRequest::GossipMsg(Topic::new("global"), msg_inner, send); let mut futs = Vec::new(); - println!("starting the wait!"); - // FIXME create method out of this - for (_i, a_handle) in handles.iter().enumerate() { - let a_fut = a_handle + for handle in &handles { + let a_fut = handle .state_changed - .wait_until(a_handle.state.lock().await, |state| { - *state == CounterState(5) - }); + .wait_until(handle.state.lock().await, |state| *state == CounterState(5)); futs.push(a_fut); } From 5c2a9bd3b9eb255abf4f430eecbabedfde071be8 Mon Sep 17 00:00:00 2001 From: Justin Restivo Date: Wed, 2 Feb 2022 15:50:21 -0500 Subject: [PATCH 058/107] refactor: tests/common.rs file + cleanup --- libp2p-networking/src/network_node_handle.rs | 109 +++++-------------- libp2p-networking/tests/common.rs | 1 - libp2p-networking/tests/common/mod.rs | 70 ++++++++++++ libp2p-networking/tests/counter.rs | 4 +- 4 files changed, 99 insertions(+), 85 deletions(-) delete mode 100644 libp2p-networking/tests/common.rs create mode 100644 libp2p-networking/tests/common/mod.rs diff --git a/libp2p-networking/src/network_node_handle.rs b/libp2p-networking/src/network_node_handle.rs index 0b2ae2b254..41852ef704 100644 --- a/libp2p-networking/src/network_node_handle.rs +++ b/libp2p-networking/src/network_node_handle.rs @@ -14,11 +14,10 @@ use rand::{seq::IteratorRandom, thread_rng}; use snafu::{ResultExt, Snafu}; use std::{ fmt::Debug, - sync::{Arc, Once}, + sync::{Arc}, }; -use tracing::{info, info_span, instrument, warn, Instrument}; +use tracing::{info, info_span, instrument, Instrument}; -static INIT: Once = Once::new(); /// A handle containing: /// - A reference to the state @@ -98,27 +97,10 @@ impl NetworkNodeHandle { Ok(()) } - /// spins up `num_of_nodes` nodes and connects them to each other + /// Spins up `num_of_nodes` nodes, connects them to each other + /// and waits for connections to propagate to all nodes. #[instrument] pub async fn spin_up_swarms(num_of_nodes: usize) -> Result>, HandlerError> { - async fn wait_to_connect( - num_of_nodes: usize, - chan: Receiver, - node_idx: usize, - ) { - loop { - if let NetworkEvent::UpdateConnectedPeers(pids) = - chan.recv_async().await.context(RecvSnafu).unwrap() - { - // FIXME don't hardcode this - if pids.len() >= 3 * num_of_nodes / 4 { - println!("node {} done", node_idx); - break; - } - } - } - } - // FIXME change API to accomodate multiple bootstrap nodes let bootstrap: NetworkNodeHandle = NetworkNodeHandle::new(None, NetworkNodeType::Bootstrap).await?; @@ -130,7 +112,7 @@ impl NetworkNodeHandle { let mut handles = Vec::new(); println!("bootstrap addr is: {:?}", bootstrap_addr); - let mut connecting_futs = vec![wait_to_connect( + let mut connecting_futs = vec![Self::wait_to_connect( num_of_nodes, bootstrap.recv_network.clone(), 0, @@ -140,7 +122,7 @@ impl NetworkNodeHandle { NetworkNodeHandle::new(Some(bootstrap_addr.clone()), NetworkNodeType::Regular) .await?, ); - connecting_futs.push(wait_to_connect( + connecting_futs.push(Self::wait_to_connect( num_of_nodes, node.recv_network.clone(), i + 1, @@ -151,50 +133,29 @@ impl NetworkNodeHandle { futures::future::join_all(connecting_futs.into_iter()).await; Ok(handles) } -} - -/// General function to spin up testing infra -/// perform tests by calling `run_test` -/// then cleans up tests -/// # Panics -/// Panics if unable to: -/// - Initialize logging -/// - Initialize network nodes -/// - Kill network nodes -/// - a test assertion fails -pub async fn test_bed( - run_test: F, - client_handler: G, - num_nodes: usize, -) where - FutF: Future, - FutG: Future> + 'static + Send + Sync, - F: FnOnce(Vec>>) -> FutF, - G: Fn(NetworkEvent, Arc>) -> FutG + 'static + Send + Sync, -{ - // only call once otherwise panics - // - INIT.call_once(|| { - color_eyre::install().unwrap(); - crate::tracing_setup::setup_tracing(); - }); - // NOTE we want this to panic if we can't spin up the swarms. - // that amounts to a failed test. - let handles: Vec>> = - NetworkNodeHandle::spin_up_swarms(num_nodes).await.unwrap(); - for handle in &handles { - spawn_handler(handle.clone(), client_handler.clone()).await; + /// Wait for a node to connect to other nodes + #[instrument] + async fn wait_to_connect( + num_of_nodes: usize, + chan: Receiver, + node_idx: usize, + ) -> Result<(), HandlerError> { + loop { + if let NetworkEvent::UpdateConnectedPeers(pids) = + chan.recv_async().await.context(RecvSnafu)? + { + // TODO when replaced with config, this should be > min num nodes in config + if pids.len() >= 3 * num_of_nodes / 4 { + info!("node {} done", node_idx); + break Ok(()); + } + } + } } - print_connections(&handles).await; +} - run_test(handles.clone()).await; - // cleanup - for handle in handles { - handle.kill().await.unwrap(); - } -} /// Glue function that listens for events from the Swarm corresponding to `handle` /// and calls `event_handler` when an event is observed. @@ -232,7 +193,7 @@ pub async fn spawn_handler( ); } -/// given a slice of handles assumed to be larger than 0 +/// Given a slice of handles assumed to be larger than 0, /// chooses one /// # Panics /// panics if handles is of length 0 @@ -240,24 +201,6 @@ pub fn get_random_handle(handles: &[Arc>]) -> Arc(handles: &[Arc>]) { - warn!("PRINTING CONNECTION STATES"); - for (i, handle) in handles.iter().enumerate() { - warn!( - "peer {}, connected to {:?}", - i, - handle.connection_state.lock().await.connected_peers - ); - warn!( - "peer {}, knowns about {:?}", - i, - handle.connection_state.lock().await.known_peers - ); - } -} - /// error wrapper type for interacting with swarm handle #[derive(Debug, Snafu)] #[snafu(visibility(pub))] diff --git a/libp2p-networking/tests/common.rs b/libp2p-networking/tests/common.rs deleted file mode 100644 index 8b13789179..0000000000 --- a/libp2p-networking/tests/common.rs +++ /dev/null @@ -1 +0,0 @@ - diff --git a/libp2p-networking/tests/common/mod.rs b/libp2p-networking/tests/common/mod.rs new file mode 100644 index 0000000000..198deaa5be --- /dev/null +++ b/libp2p-networking/tests/common/mod.rs @@ -0,0 +1,70 @@ +use std::sync::{Arc, Once}; + +use futures::Future; +use networking_demo::{network_node::NetworkEvent, network_node_handle::{NetworkNodeHandle, HandlerError, spawn_handler}, tracing_setup}; +use tracing::warn; +use std::fmt::Debug; + + +static INIT: Once = Once::new(); + +/// General function to spin up testing infra +/// perform tests by calling `run_test` +/// then cleans up tests +/// # Panics +/// Panics if unable to: +/// - Initialize logging +/// - Initialize network nodes +/// - Kill network nodes +/// - A test assertion fails +pub async fn test_bed( + run_test: F, + client_handler: G, + num_nodes: usize, +) where + FutF: Future, + FutG: Future> + 'static + Send + Sync, + F: FnOnce(Vec>>) -> FutF, + G: Fn(NetworkEvent, Arc>) -> FutG + 'static + Send + Sync, +{ + // only call once otherwise panics + // + INIT.call_once(|| { + color_eyre::install().unwrap(); + tracing_setup::setup_tracing(); + }); + + // NOTE we want this to panic if we can't spin up the swarms. + // that amounts to a failed test. + let handles: Vec>> = + NetworkNodeHandle::spin_up_swarms(num_nodes).await.unwrap(); + for handle in &handles { + spawn_handler(handle.clone(), client_handler.clone()).await; + } + print_connections(&handles).await; + + run_test(handles.clone()).await; + + // cleanup + for handle in handles { + handle.kill().await.unwrap(); + } +} + +/// print the connections for each handle in `handles` +/// useful for debugging +async fn print_connections(handles: &[Arc>]) { + warn!("PRINTING CONNECTION STATES"); + for (i, handle) in handles.iter().enumerate() { + warn!( + "peer {}, connected to {:?}", + i, + handle.connection_state.lock().await.connected_peers + ); + warn!( + "peer {}, knowns about {:?}", + i, + handle.connection_state.lock().await.known_peers + ); + } +} diff --git a/libp2p-networking/tests/counter.rs b/libp2p-networking/tests/counter.rs index 75d90ca699..e617138165 100644 --- a/libp2p-networking/tests/counter.rs +++ b/libp2p-networking/tests/counter.rs @@ -1,4 +1,6 @@ use std::sync::Arc; +mod common; +use common::test_bed; use bincode::Options; @@ -6,7 +8,7 @@ use libp2p::gossipsub::Topic; use networking_demo::{ network_node::{ClientRequest, NetworkEvent}, network_node_handle::{ - get_random_handle, test_bed, HandlerError, NetworkNodeHandle, SendSnafu, SerializationSnafu, + get_random_handle, HandlerError, NetworkNodeHandle, SendSnafu, SerializationSnafu, }, }; use rand::{seq::IteratorRandom, thread_rng}; From 61ffcf7537e64b7dbdb22f31a8c34fcda2680d80 Mon Sep 17 00:00:00 2001 From: Justin Restivo Date: Wed, 2 Feb 2022 16:05:54 -0500 Subject: [PATCH 059/107] feat: Add timeout to tests --- libp2p-networking/src/network_node_handle.rs | 8 +------- libp2p-networking/tests/common/mod.rs | 9 ++++++--- libp2p-networking/tests/counter.rs | 11 ++++++++--- 3 files changed, 15 insertions(+), 13 deletions(-) diff --git a/libp2p-networking/src/network_node_handle.rs b/libp2p-networking/src/network_node_handle.rs index 41852ef704..ce9a278169 100644 --- a/libp2p-networking/src/network_node_handle.rs +++ b/libp2p-networking/src/network_node_handle.rs @@ -12,13 +12,9 @@ use futures::{select, Future, FutureExt}; use libp2p::{Multiaddr, PeerId}; use rand::{seq::IteratorRandom, thread_rng}; use snafu::{ResultExt, Snafu}; -use std::{ - fmt::Debug, - sync::{Arc}, -}; +use std::{fmt::Debug, sync::Arc}; use tracing::{info, info_span, instrument, Instrument}; - /// A handle containing: /// - A reference to the state /// - Controls for the swarm @@ -155,8 +151,6 @@ impl NetworkNodeHandle { } } - - /// Glue function that listens for events from the Swarm corresponding to `handle` /// and calls `event_handler` when an event is observed. /// The idea is that this function can be used independent of the actual behaviour diff --git a/libp2p-networking/tests/common/mod.rs b/libp2p-networking/tests/common/mod.rs index 198deaa5be..f7afec7bf3 100644 --- a/libp2p-networking/tests/common/mod.rs +++ b/libp2p-networking/tests/common/mod.rs @@ -1,10 +1,13 @@ use std::sync::{Arc, Once}; use futures::Future; -use networking_demo::{network_node::NetworkEvent, network_node_handle::{NetworkNodeHandle, HandlerError, spawn_handler}, tracing_setup}; -use tracing::warn; +use networking_demo::{ + network_node::NetworkEvent, + network_node_handle::{spawn_handler, HandlerError, NetworkNodeHandle}, + tracing_setup, +}; use std::fmt::Debug; - +use tracing::warn; static INIT: Once = Once::new(); diff --git a/libp2p-networking/tests/counter.rs b/libp2p-networking/tests/counter.rs index e617138165..ff2384ca65 100644 --- a/libp2p-networking/tests/counter.rs +++ b/libp2p-networking/tests/counter.rs @@ -1,9 +1,11 @@ -use std::sync::Arc; +use std::{sync::Arc, time::Duration}; mod common; +use async_std::{future::timeout}; use common::test_bed; use bincode::Options; + use libp2p::gossipsub::Topic; use networking_demo::{ network_node::{ClientRequest, NetworkEvent}, @@ -23,6 +25,7 @@ use tracing::{error, instrument, warn}; pub type Counter = u8; const TOTAL_NUM_PEERS: usize = 20; +const TIMEOUT: Duration = Duration::from_secs(30); /// Message types. We can either /// - increment the Counter @@ -127,7 +130,7 @@ async fn test_request_response() { }); send_handle.send_network.send_async(msg).await.unwrap(); - recv_fut.await; + timeout(TIMEOUT, recv_fut).await.unwrap(); for handle in handles.iter() { let expected_state = @@ -176,7 +179,9 @@ async fn test_gossip() { msg_handle.send_network.send_async(msg).await.unwrap(); recv.recv_async().await.unwrap().unwrap(); - futures::future::join_all(futs).await; + timeout(TIMEOUT, futures::future::join_all(futs)) + .await + .unwrap(); let mut failing_idxs = Vec::new(); for (i, handle) in handles.iter().enumerate() { From 5aee8337cf9cb2953b7ed371e7b6195eb04b8294 Mon Sep 17 00:00:00 2001 From: Justin Restivo Date: Wed, 2 Feb 2022 16:14:47 -0500 Subject: [PATCH 060/107] feat: Timeout for replica spin-up --- libp2p-networking/src/network_node_handle.rs | 20 +++++++++++++++++--- libp2p-networking/tests/common/mod.rs | 10 ++++++++-- libp2p-networking/tests/counter.rs | 12 +++++++++--- 3 files changed, 34 insertions(+), 8 deletions(-) diff --git a/libp2p-networking/src/network_node_handle.rs b/libp2p-networking/src/network_node_handle.rs index ce9a278169..90f987d28f 100644 --- a/libp2p-networking/src/network_node_handle.rs +++ b/libp2p-networking/src/network_node_handle.rs @@ -1,4 +1,5 @@ use async_std::{ + future::{timeout, TimeoutError}, sync::{Condvar, Mutex}, task::spawn, }; @@ -12,7 +13,7 @@ use futures::{select, Future, FutureExt}; use libp2p::{Multiaddr, PeerId}; use rand::{seq::IteratorRandom, thread_rng}; use snafu::{ResultExt, Snafu}; -use std::{fmt::Debug, sync::Arc}; +use std::{fmt::Debug, sync::Arc, time::Duration}; use tracing::{info, info_span, instrument, Instrument}; /// A handle containing: @@ -96,7 +97,10 @@ impl NetworkNodeHandle { /// Spins up `num_of_nodes` nodes, connects them to each other /// and waits for connections to propagate to all nodes. #[instrument] - pub async fn spin_up_swarms(num_of_nodes: usize) -> Result>, HandlerError> { + pub async fn spin_up_swarms( + num_of_nodes: usize, + timeout_len: Duration, + ) -> Result>, HandlerError> { // FIXME change API to accomodate multiple bootstrap nodes let bootstrap: NetworkNodeHandle = NetworkNodeHandle::new(None, NetworkNodeType::Bootstrap).await?; @@ -126,7 +130,12 @@ impl NetworkNodeHandle { handles.push(node); } - futures::future::join_all(connecting_futs.into_iter()).await; + timeout( + timeout_len, + futures::future::join_all(connecting_futs.into_iter()), + ) + .await + .context(TimeoutSnafu)?; Ok(handles) } @@ -221,4 +230,9 @@ pub enum HandlerError { /// source of error source: RecvError, }, + /// Timeout spinning up handle + TimeoutError { + /// source of error + source: TimeoutError, + }, } diff --git a/libp2p-networking/tests/common/mod.rs b/libp2p-networking/tests/common/mod.rs index f7afec7bf3..48bb83560a 100644 --- a/libp2p-networking/tests/common/mod.rs +++ b/libp2p-networking/tests/common/mod.rs @@ -1,4 +1,7 @@ -use std::sync::{Arc, Once}; +use std::{ + sync::{Arc, Once}, + time::Duration, +}; use futures::Future; use networking_demo::{ @@ -24,6 +27,7 @@ pub async fn test_bed, FutG: Future> + 'static + Send + Sync, @@ -40,7 +44,9 @@ pub async fn test_bed>> = - NetworkNodeHandle::spin_up_swarms(num_nodes).await.unwrap(); + NetworkNodeHandle::spin_up_swarms(num_nodes, timeout) + .await + .unwrap(); for handle in &handles { spawn_handler(handle.clone(), client_handler.clone()).await; } diff --git a/libp2p-networking/tests/counter.rs b/libp2p-networking/tests/counter.rs index ff2384ca65..9f890b4fec 100644 --- a/libp2p-networking/tests/counter.rs +++ b/libp2p-networking/tests/counter.rs @@ -1,11 +1,10 @@ use std::{sync::Arc, time::Duration}; mod common; -use async_std::{future::timeout}; +use async_std::future::timeout; use common::test_bed; use bincode::Options; - use libp2p::gossipsub::Topic; use networking_demo::{ network_node::{ClientRequest, NetworkEvent}, @@ -147,6 +146,7 @@ async fn test_request_response() { run_request_response, counter_handle_network_event, TOTAL_NUM_PEERS, + TIMEOUT, ) .await } @@ -195,5 +195,11 @@ async fn test_gossip() { } } - test_bed(run_gossip, counter_handle_network_event, TOTAL_NUM_PEERS).await; + test_bed( + run_gossip, + counter_handle_network_event, + TOTAL_NUM_PEERS, + TIMEOUT, + ) + .await; } From 2c19a3fef22a968c0c4c11c969ebc893b5e16ad9 Mon Sep 17 00:00:00 2001 From: Justin Restivo Date: Thu, 3 Feb 2022 09:38:06 -0500 Subject: [PATCH 061/107] feat: Separate out connection parameters to node config + builder --- libp2p-networking/Cargo.lock | 81 +++++++++++++++++++- libp2p-networking/Cargo.toml | 1 + libp2p-networking/examples/clichat.rs | 10 ++- libp2p-networking/src/network_node.rs | 59 ++++++++------ libp2p-networking/src/network_node_handle.rs | 25 ++++-- 5 files changed, 140 insertions(+), 36 deletions(-) diff --git a/libp2p-networking/Cargo.lock b/libp2p-networking/Cargo.lock index 3ce9082e04..1e24707b22 100644 --- a/libp2p-networking/Cargo.lock +++ b/libp2p-networking/Cargo.lock @@ -518,7 +518,7 @@ dependencies = [ "ansi_term", "atty", "bitflags", - "strsim", + "strsim 0.8.0", "textwrap", "unicode-width", "vec_map", @@ -713,12 +713,78 @@ dependencies = [ "zeroize", ] +[[package]] +name = "darling" +version = "0.12.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f2c43f534ea4b0b049015d00269734195e6d3f0f6635cb692251aca6f9f8b3c" +dependencies = [ + "darling_core", + "darling_macro", +] + +[[package]] +name = "darling_core" +version = "0.12.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e91455b86830a1c21799d94524df0845183fa55bafd9aa137b01c7d1065fa36" +dependencies = [ + "fnv", + "ident_case", + "proc-macro2", + "quote", + "strsim 0.10.0", + "syn", +] + +[[package]] +name = "darling_macro" +version = "0.12.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29b5acf0dea37a7f66f7b25d2c5e93fd46f8f6968b1a5d7a3e02e97768afc95a" +dependencies = [ + "darling_core", + "quote", + "syn", +] + [[package]] name = "data-encoding" version = "2.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3ee2393c4a91429dffb4bedf19f4d6abf27d8a732c8ce4980305d782e5426d57" +[[package]] +name = "derive_builder" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d13202debe11181040ae9063d739fa32cfcaaebe2275fe387703460ae2365b30" +dependencies = [ + "derive_builder_macro", +] + +[[package]] +name = "derive_builder_core" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "66e616858f6187ed828df7c64a6d71720d83767a7f19740b2d1b6fe6327b36e5" +dependencies = [ + "darling", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "derive_builder_macro" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "58a94ace95092c5acb1e97a7e846b310cfbd499652f72297da7493f618a98d73" +dependencies = [ + "derive_builder_core", + "syn", +] + [[package]] name = "digest" version = "0.9.0" @@ -1138,6 +1204,12 @@ version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "acd94fdbe1d4ff688b67b04eee2e17bd50995534a61539e45adfefb45e5e5503" +[[package]] +name = "ident_case" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" + [[package]] name = "idna" version = "0.2.3" @@ -2014,6 +2086,7 @@ dependencies = [ "blake3", "color-eyre", "crossterm 0.22.1", + "derive_builder", "flume", "futures", "libp2p", @@ -2875,6 +2948,12 @@ version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" +[[package]] +name = "strsim" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" + [[package]] name = "structopt" version = "0.3.25" diff --git a/libp2p-networking/Cargo.toml b/libp2p-networking/Cargo.toml index 9b98694eb4..7f9ecd65fe 100644 --- a/libp2p-networking/Cargo.toml +++ b/libp2p-networking/Cargo.toml @@ -24,3 +24,4 @@ tracing-subscriber = { version = "0.3.5", features = ["env-filter", "json"] } tui = { version = "0.16.0", features = ["crossterm"], default-features = false } rand = "0.8.4" async-trait = "0.1.52" +derive_builder = "0.10.2" diff --git a/libp2p-networking/examples/clichat.rs b/libp2p-networking/examples/clichat.rs index 339ad242ea..1e9993f0e6 100644 --- a/libp2p-networking/examples/clichat.rs +++ b/libp2p-networking/examples/clichat.rs @@ -17,7 +17,9 @@ use parking_lot::Mutex; use tracing::instrument; use tui::{backend::CrosstermBackend, Terminal}; -use networking_demo::network_node::{gen_multiaddr, ClientRequest, NetworkNode, NetworkNodeType}; +use networking_demo::network_node::{ + gen_multiaddr, ClientRequest, NetworkNode, NetworkNodeConfigBuilder, +}; /// command line arguments #[derive(StructOpt)] @@ -37,7 +39,11 @@ async fn main() -> Result<()> { color_eyre::install()?; networking_demo::tracing_setup::setup_tracing(); // -- Spin up the network connection - let mut networking: NetworkNode = NetworkNode::new(NetworkNodeType::Regular) + let networking_config = NetworkNodeConfigBuilder::default() + .min_num_peers(10usize) + .max_num_peers(15usize) + .build()?; + let mut networking: NetworkNode = NetworkNode::new(networking_config) .await .context("Failed to launch network")?; let port = CliOpt::from_args().port.unwrap_or(0u16); diff --git a/libp2p-networking/src/network_node.rs b/libp2p-networking/src/network_node.rs index ae269e5647..feb8736659 100644 --- a/libp2p-networking/src/network_node.rs +++ b/libp2p-networking/src/network_node.rs @@ -228,6 +228,12 @@ pub enum NetworkNodeType { Regular, } +impl Default for NetworkNodeType { + fn default() -> Self { + Self::Bootstrap + } +} + // FIXME split this out into network config + swarm /// Network definition @@ -238,22 +244,31 @@ pub struct NetworkNode { pub peer_id: PeerId, /// the swarm of networkbehaviours pub swarm: Swarm, - /// maximum number of connections to maintain + /// the configuration parameters of the netework + pub config: NetworkNodeConfig, +} + +/// describe the configuration of the network +#[derive(Debug, Clone, Copy, Default, derive_builder::Builder)] +pub struct NetworkNodeConfig { + /// max number of connections a node may have before it begins + /// to disconnect. Only applies if `node_type` is `Regular` pub max_num_peers: usize, - /// minimum numer of connections to maintain + /// Min number of connections a node may have before it begins + /// to connect to more. Only applies if `node_type` is `Regular` pub min_num_peers: usize, - /// the type of node the network is + /// The type of node: + /// Either bootstrap (greedily connect to all peers) + /// or regular (respect `min_num_peers`/`max num peers`) pub node_type: NetworkNodeType, } impl Debug for NetworkNode { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { f.debug_struct("Network") - .field("peer_id", &self.peer_id) - .field("swarm", self.swarm.behaviour()) - .field("max_num_peers", &self.max_num_peers) - .field("min_num_peers", &self.min_num_peers) - .field("node_type", &self.node_type) + .field("Peer id", &self.peer_id) + .field("Wwarm", self.swarm.behaviour()) + .field("Network Config", &self.config) .finish() } } @@ -299,7 +314,7 @@ pub fn gen_multiaddr(port: u16) -> Multiaddr { build_multiaddr!(Ip4([0, 0, 0, 0]), Tcp(port)) } -/// generate authenticated transport, copied from `development_transport` +/// Generate authenticated transport, copied from `development_transport` /// for definition of XX /// # Errors /// could not sign the noise key with `identity` @@ -350,12 +365,6 @@ impl NetworkNode { let addr = loop { if let Some(SwarmEvent::NewListenAddr { address, .. }) = self.swarm.next().await { break address; - // let new_addr = address.to_string(); - // let mut tmp = String::new(); - // tmp.push_str("/ip4/192.168.1.96/tcp/"); - // tmp.push_str(&new_addr[new_addr.len()-5..new_addr.len()]); - // // new_addr[ - // break tmp.parse().unwrap(); } }; info!("peerid {:?} listen addr: {:?}", self.peer_id, addr); @@ -383,7 +392,7 @@ impl NetworkNode { /// * Generates a connection to the "broadcast" topic /// * Creates a swarm to manage peers and events #[instrument] - pub async fn new(node_type: NetworkNodeType) -> Result { + pub async fn new(config: NetworkNodeConfig) -> Result { // Generate a random PeerId let identity = Keypair::generate_ed25519(); let peer_id = PeerId::from(identity.public()); @@ -460,10 +469,8 @@ impl NetworkNode { Ok(Self { identity, peer_id, - max_num_peers: 15, - min_num_peers: 10, swarm, - node_type, + config, }) } @@ -488,7 +495,9 @@ impl NetworkNode { // if we're bootstrapped, do nothing // otherwise periodically get more peers if needed if !swarm.bootstrap_in_progress { - if swarm.connecting_peers.len() + swarm.connected_peers.len() <= self.min_num_peers { + if swarm.connecting_peers.len() + swarm.connected_peers.len() + <= self.config.min_num_peers + { // Calcuate the currently connected peers let used_peers = swarm .connecting_peers @@ -500,7 +509,7 @@ impl NetworkNode { let potential_peers: HashSet = swarm.known_peers.difference(&used_peers).copied().collect(); // Number of peers we want to try connecting to - let num_to_connect = self.min_num_peers + 1 + let num_to_connect = self.config.min_num_peers + 1 - (swarm.connected_peers.len() + swarm.connecting_peers.len()); // Random(?) subset of the availible peers to try connecting to let chosen_peers = potential_peers @@ -520,14 +529,14 @@ impl NetworkNode { } } // NOTE only prune node connections if we aren't a bootstrap node - else if swarm.connected_peers.len() > self.max_num_peers - && self.node_type == NetworkNodeType::Regular + else if swarm.connected_peers.len() > self.config.max_num_peers + && self.config.node_type == NetworkNodeType::Regular { // If we are connected to too many peers, try disconnecting from // a random (?) subset let peers_to_rm = swarm.connected_peers.iter().copied().choose_multiple( &mut thread_rng(), - swarm.connected_peers.len() - self.max_num_peers, + swarm.connected_peers.len() - self.config.max_num_peers, ); for a_peer in peers_to_rm { // FIXME the error is () ? @@ -537,7 +546,7 @@ impl NetworkNode { } } - /// event handler for UI. + /// event handler for client events /// currectly supported actions include /// - shutting down the swarm /// - gossipping a message to known peers on the `global` topic diff --git a/libp2p-networking/src/network_node_handle.rs b/libp2p-networking/src/network_node_handle.rs index 90f987d28f..70cdc2a92e 100644 --- a/libp2p-networking/src/network_node_handle.rs +++ b/libp2p-networking/src/network_node_handle.rs @@ -6,7 +6,7 @@ use async_std::{ use crate::network_node::{ gen_multiaddr, ClientRequest, ConnectionData, NetworkError, NetworkEvent, NetworkNode, - NetworkNodeType, + NetworkNodeConfig, NetworkNodeConfigBuilder, NetworkNodeConfigBuilderError, NetworkNodeType, }; use flume::{Receiver, RecvError, SendError, Sender}; use futures::{select, Future, FutureExt}; @@ -46,11 +46,11 @@ impl NetworkNodeHandle { #[instrument] pub async fn new( known_addr: Option, - node_type: NetworkNodeType, + config: NetworkNodeConfig, ) -> Result { //`randomly assigned port let listen_addr = gen_multiaddr(0); - let mut network = NetworkNode::new(node_type).await.context(NetworkSnafu)?; + let mut network = NetworkNode::new(config).await.context(NetworkSnafu)?; let peer_id = network.peer_id; let listen_addr = network .start(listen_addr, known_addr) @@ -103,7 +103,7 @@ impl NetworkNodeHandle { ) -> Result>, HandlerError> { // FIXME change API to accomodate multiple bootstrap nodes let bootstrap: NetworkNodeHandle = - NetworkNodeHandle::new(None, NetworkNodeType::Bootstrap).await?; + NetworkNodeHandle::new(None, NetworkNodeConfig::default()).await?; let bootstrap_addr = bootstrap.listen_addr.clone(); info!( "boostrap node {} on addr {}", @@ -117,11 +117,15 @@ impl NetworkNodeHandle { bootstrap.recv_network.clone(), 0, )]; + let regular_node = NetworkNodeConfigBuilder::default() + .node_type(NetworkNodeType::Regular) + .min_num_peers(10usize) + .max_num_peers(15usize) + .build() + .context(NodeConfigSnafu)?; for i in 0..(num_of_nodes - 1) { - let node = Arc::new( - NetworkNodeHandle::new(Some(bootstrap_addr.clone()), NetworkNodeType::Regular) - .await?, - ); + let node = + Arc::new(NetworkNodeHandle::new(Some(bootstrap_addr.clone()), regular_node).await?); connecting_futs.push(Self::wait_to_connect( num_of_nodes, node.recv_network.clone(), @@ -235,4 +239,9 @@ pub enum HandlerError { /// source of error source: TimeoutError, }, + /// Error building Node config + NodeConfigError { + /// source of error + source: NetworkNodeConfigBuilderError, + }, } From 1163aeaa259dd58e4dca0b0163955437d19bc8fe Mon Sep 17 00:00:00 2001 From: Justin Restivo Date: Fri, 4 Feb 2022 10:12:09 -0500 Subject: [PATCH 062/107] feat: add more tests --- libp2p-networking/src/network_node_handle.rs | 21 +- libp2p-networking/tests/common/mod.rs | 4 +- libp2p-networking/tests/counter.rs | 289 +++++++++++++------ 3 files changed, 220 insertions(+), 94 deletions(-) diff --git a/libp2p-networking/src/network_node_handle.rs b/libp2p-networking/src/network_node_handle.rs index 70cdc2a92e..9a2882d51c 100644 --- a/libp2p-networking/src/network_node_handle.rs +++ b/libp2p-networking/src/network_node_handle.rs @@ -47,7 +47,7 @@ impl NetworkNodeHandle { pub async fn new( known_addr: Option, config: NetworkNodeConfig, - ) -> Result { + ) -> Result { //`randomly assigned port let listen_addr = gen_multiaddr(0); let mut network = NetworkNode::new(config).await.context(NetworkSnafu)?; @@ -100,7 +100,7 @@ impl NetworkNodeHandle { pub async fn spin_up_swarms( num_of_nodes: usize, timeout_len: Duration, - ) -> Result>, HandlerError> { + ) -> Result>, NetworkNodeHandleError> { // FIXME change API to accomodate multiple bootstrap nodes let bootstrap: NetworkNodeHandle = NetworkNodeHandle::new(None, NetworkNodeConfig::default()).await?; @@ -110,7 +110,7 @@ impl NetworkNodeHandle { bootstrap.peer_id, bootstrap_addr ); let mut handles = Vec::new(); - println!("bootstrap addr is: {:?}", bootstrap_addr); + info!("bootstrap addr is: {:?}", bootstrap_addr); let mut connecting_futs = vec![Self::wait_to_connect( num_of_nodes, @@ -149,14 +149,14 @@ impl NetworkNodeHandle { num_of_nodes: usize, chan: Receiver, node_idx: usize, - ) -> Result<(), HandlerError> { + ) -> Result<(), NetworkNodeHandleError> { loop { if let NetworkEvent::UpdateConnectedPeers(pids) = chan.recv_async().await.context(RecvSnafu)? { // TODO when replaced with config, this should be > min num nodes in config if pids.len() >= 3 * num_of_nodes / 4 { - info!("node {} done", node_idx); + println!("node {} connected!", node_idx); break Ok(()); } } @@ -177,8 +177,10 @@ pub async fn spawn_handler( + std::marker::Send + 'static, ) where - Fut: - Future> + std::marker::Send + 'static + std::marker::Sync, + Fut: Future> + + std::marker::Send + + 'static + + std::marker::Sync, { let recv_kill = handle.recv_kill.clone(); let recv_event = handle.recv_network.clone(); @@ -194,7 +196,7 @@ pub async fn spawn_handler( }, ); } - Ok::<(), HandlerError>(()) + Ok::<(), NetworkNodeHandleError>(()) } .instrument(info_span!("Libp2p Counter Handler")), ); @@ -211,7 +213,7 @@ pub fn get_random_handle(handles: &[Arc>]) -> Arc, - FutG: Future> + 'static + Send + Sync, + FutG: Future> + 'static + Send + Sync, F: FnOnce(Vec>>) -> FutF, G: Fn(NetworkEvent, Arc>) -> FutG + 'static + Send + Sync, { diff --git a/libp2p-networking/tests/counter.rs b/libp2p-networking/tests/counter.rs index 9f890b4fec..f9afef0b95 100644 --- a/libp2p-networking/tests/counter.rs +++ b/libp2p-networking/tests/counter.rs @@ -5,23 +5,23 @@ use common::test_bed; use bincode::Options; +use futures::future::join_all; use libp2p::gossipsub::Topic; use networking_demo::{ network_node::{ClientRequest, NetworkEvent}, network_node_handle::{ - get_random_handle, HandlerError, NetworkNodeHandle, SendSnafu, SerializationSnafu, + get_random_handle, NetworkNodeHandle, NetworkNodeHandleError, SendSnafu, SerializationSnafu, }, }; -use rand::{seq::IteratorRandom, thread_rng}; use std::fmt::Debug; use serde::{Deserialize, Serialize}; use snafu::ResultExt; -use tracing::{error, instrument, warn}; +use tracing::{error, info, instrument, warn}; -pub type Counter = u8; +pub type CounterState = u32; const TOTAL_NUM_PEERS: usize = 20; const TIMEOUT: Duration = Duration::from_secs(30); @@ -40,9 +40,6 @@ pub enum CounterMessage { MyCounterIs(CounterState), } -#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, Default)] -pub struct CounterState(Counter); - /// event handler for events from the swarm /// - updates state based on events received /// - replies to direct messages @@ -50,7 +47,7 @@ pub struct CounterState(Counter); pub async fn counter_handle_network_event( event: NetworkEvent, handle: Arc>, -) -> Result<(), HandlerError> { +) -> Result<(), NetworkNodeHandleError> { use CounterMessage::*; #[allow(clippy::enum_glob_use)] use NetworkEvent::*; @@ -59,11 +56,16 @@ pub async fn counter_handle_network_event( GossipMsg(m) | DirectResponse(m) => { if let Ok(msg) = bincode_options.deserialize::(&m) { match msg { - MyCounterIs(c) | CounterMessage::IncrementCounter { to: c, .. } => { - println!("recv-ed"); + MyCounterIs(c) => { *handle.state.lock().await = c; handle.state_changed.notify_all(); } + IncrementCounter { from, to, .. } => { + if *handle.state.lock().await == from { + *handle.state.lock().await = to; + handle.state_changed.notify_all(); + } + } AskForCounter => {} } } @@ -71,14 +73,14 @@ pub async fn counter_handle_network_event( DirectRequest(m, chan) => { if let Ok(msg) = bincode_options.deserialize::(&m) { match msg { - IncrementCounter { to, .. } => { - // TODO move the state changes out into a function call that triggers the - // condvar - *handle.state.lock().await = to; - handle.state_changed.notify_all(); + IncrementCounter { from, to, .. } => { + if *handle.state.lock().await == from { + *handle.state.lock().await = to; + handle.state_changed.notify_all(); + } } AskForCounter => { - let response = MyCounterIs(handle.state.lock().await.clone()); + let response = MyCounterIs(*handle.state.lock().await); let serialized_response = bincode_options .serialize(&response) .context(SerializationSnafu)?; @@ -102,48 +104,138 @@ pub async fn counter_handle_network_event( Ok(()) } -/// check that we can direct message to increment counter -#[async_std::test] -#[instrument] -async fn test_request_response() { - async fn run_request_response(handles: Vec>>) { - let send_handle = get_random_handle(handles.as_slice()); - let recv_handle = get_random_handle(handles.as_slice()); +/// `requester_handle` asks for `requestee_handle`'s state, +/// and then `requester_handle` updates its state to equal `requestee_handle`. +async fn run_request_response_increment( + requester_handle: Arc>, + requestee_handle: Arc>, +) { + let bincode_options = bincode::DefaultOptions::new().with_limit(16_384); + let msg_inner = bincode_options + .serialize(&CounterMessage::AskForCounter) + .unwrap(); + + let msg = ClientRequest::DirectRequest(requestee_handle.peer_id, msg_inner); + + let new_state = *requestee_handle.state.lock().await; + + // set up state change listener + let recv_fut = requester_handle + .state_changed + .wait_until(requester_handle.state.lock().await, |state| { + *state == new_state + }); + + requester_handle.send_network.send_async(msg).await.unwrap(); + + timeout(TIMEOUT, recv_fut).await.unwrap(); + + assert_eq!( + *requester_handle.state.lock().await, + *requestee_handle.state.lock().await + ); +} + +/// broadcasts `msg` from a randomly chosen handle +/// then asserts that all nodes match `new_state` +async fn run_gossip_round( + handles: &[Arc>], + msg_inner: Vec, + new_state: CounterState, +) { + let msg_handle = get_random_handle(handles); + *msg_handle.state.lock().await = new_state; + let (send, recv) = flume::bounded(1); + let msg = ClientRequest::GossipMsg(Topic::new("global"), msg_inner, send); + + let mut futs = Vec::new(); + for handle in handles { + let a_fut = handle + .state_changed + .wait_until(handle.state.lock().await, |state| *state == new_state); + futs.push(a_fut); + } + + msg_handle.send_network.send_async(msg).await.unwrap(); + recv.recv_async().await.unwrap().unwrap(); - *send_handle.state.lock().await = CounterState(5); + timeout(TIMEOUT, futures::future::join_all(futs)) + .await + .unwrap(); - let bincode_options = bincode::DefaultOptions::new().with_limit(16_384); + let mut failing_idxs = Vec::new(); + for (i, handle) in handles.iter().enumerate() { + if *handle.state.lock().await != new_state { + failing_idxs.push(i); + } + } + if !failing_idxs.is_empty() { + error!(?failing_idxs, "failing idxs!!"); + panic!("some nodes did not receive the message {:?}", failing_idxs); + } +} + +/// runs `num_rounds` of message broadcast, incrementing the state of all nodes each broadcast +async fn run_gossip_rounds( + handles: &[Arc>], + num_rounds: usize, + starting_state: CounterState, +) { + let mut old_state = starting_state; + let bincode_options = bincode::DefaultOptions::new().with_limit(16_384); + for i in 0..num_rounds { + info!("running gossip round {}", i); + let new_state = old_state + 1; let msg_inner = bincode_options .serialize(&CounterMessage::IncrementCounter { - from: CounterState(0), - to: CounterState(5), + from: old_state, + to: new_state, }) .unwrap(); + run_gossip_round(handles, msg_inner, new_state).await; + old_state = new_state; + } +} - let msg = ClientRequest::DirectRequest(recv_handle.peer_id, msg_inner); - - let recv_fut = recv_handle - .state_changed - .wait_until(recv_handle.state.lock().await, |state| { - *state == CounterState(5) - }); - send_handle.send_network.send_async(msg).await.unwrap(); - - timeout(TIMEOUT, recv_fut).await.unwrap(); - - for handle in handles.iter() { - let expected_state = - if handle.peer_id == send_handle.peer_id || handle.peer_id == recv_handle.peer_id { - CounterState(5) - } else { - CounterState::default() - }; - assert_eq!(*handle.state.lock().await, expected_state); +/// chooses a random handle from `handles` +/// increments its state by 1, +/// then has all other peers request its state +/// and update their state to the recv'ed state +async fn run_request_response_increment_all(handles: &[Arc>]) { + let requestee_handle = get_random_handle(handles); + *requestee_handle.state.lock().await += 1; + info!( + "running request_response increment to {}", + requestee_handle.state.lock().await + ); + let mut futs = Vec::new(); + for h in handles { + // skip `requestee_handle` + if h.peer_id != requestee_handle.peer_id { + let requester_handle = h.clone(); + futs.push(run_request_response_increment( + requester_handle, + requestee_handle.clone(), + )); } } + join_all(futs).await; +} +/// simple case of direct message +#[async_std::test] +#[instrument] +async fn test_request_response_one_round() { + pub async fn run_request_response_one_round( + handles: Vec>>, + ) { + run_request_response_increment_all(&handles).await; + for h in handles.into_iter() { + assert_eq!(*h.state.lock().await, 1); + } + } test_bed( - run_request_response, + run_request_response_one_round, counter_handle_network_event, TOTAL_NUM_PEERS, TIMEOUT, @@ -151,52 +243,83 @@ async fn test_request_response() { .await } -/// check that we can broadcast a message out and get counter increments +/// stress test of direct messsage #[async_std::test] #[instrument] -async fn test_gossip() { - async fn run_gossip(handles: Vec>>) { - let msg_handle = handles.iter().choose(&mut thread_rng()).unwrap(); - *msg_handle.state.lock().await = CounterState(5); - let bincode_options = bincode::DefaultOptions::new().with_limit(16_384); - let msg_inner = bincode_options - .serialize(&CounterMessage::IncrementCounter { - from: CounterState(0), - to: CounterState(5), - }) - .unwrap(); - let (send, recv) = flume::bounded(1); - let msg = ClientRequest::GossipMsg(Topic::new("global"), msg_inner, send); - - let mut futs = Vec::new(); - for handle in &handles { - let a_fut = handle - .state_changed - .wait_until(handle.state.lock().await, |state| *state == CounterState(5)); - futs.push(a_fut); +async fn test_request_response_many_rounds() { + pub async fn run_request_response_many_rounds( + handles: Vec>>, + ) { + let num_rounds = 4092; + for i in 0..num_rounds { + run_request_response_increment_all(&handles).await; + println!("finished {}", i); } + for h in handles.into_iter() { + assert_eq!(*h.state.lock().await, num_rounds); + } + } + test_bed( + run_request_response_many_rounds, + counter_handle_network_event, + TOTAL_NUM_PEERS, + TIMEOUT, + ) + .await +} - msg_handle.send_network.send_async(msg).await.unwrap(); - recv.recv_async().await.unwrap().unwrap(); - - timeout(TIMEOUT, futures::future::join_all(futs)) - .await - .unwrap(); - - let mut failing_idxs = Vec::new(); - for (i, handle) in handles.iter().enumerate() { - if *handle.state.lock().await != CounterState(5) { - failing_idxs.push(i); +/// stress test of broadcast + direct message +#[async_std::test] +#[instrument] +async fn test_intersperse_many_rounds() { + pub async fn run_intersperse_many_rounds(handles: Vec>>) { + let num_rounds = 4092; + for i in 0..num_rounds { + if i % 2 == 0 { + run_request_response_increment_all(&handles).await; + } else { + run_gossip_rounds(&handles, 1, i).await } + println!("finished {}", i); } - if !failing_idxs.is_empty() { - error!(?failing_idxs, "failing idxs!!"); - panic!("some nodes did not receive the message {:?}", failing_idxs); + for h in handles.into_iter() { + assert_eq!(*h.state.lock().await, num_rounds); } } + test_bed( + run_intersperse_many_rounds, + counter_handle_network_event, + TOTAL_NUM_PEERS, + TIMEOUT, + ) + .await +} + +/// stress teset that we can broadcast a message out and get counter increments +#[async_std::test] +#[instrument] +async fn test_gossip_many_rounds() { + pub async fn run_gossip_many_rounds(handles: Vec>>) { + run_gossip_rounds(&handles, 4092, 0).await + } + test_bed( + run_gossip_many_rounds, + counter_handle_network_event, + TOTAL_NUM_PEERS, + TIMEOUT, + ) + .await; +} +/// simple case of broadcast message +#[async_std::test] +#[instrument] +async fn test_gossip_one_round() { + pub async fn run_gossip_one_round(handles: Vec>>) { + run_gossip_rounds(&handles, 1, 0).await + } test_bed( - run_gossip, + run_gossip_one_round, counter_handle_network_event, TOTAL_NUM_PEERS, TIMEOUT, From 23312381ddaa7715cbb44a20db0ca712eadd7bce Mon Sep 17 00:00:00 2001 From: Justin Restivo Date: Fri, 4 Feb 2022 11:47:34 -0500 Subject: [PATCH 063/107] feat: enable additional connections --- libp2p-networking/flake.nix | 2 +- libp2p-networking/src/network_node.rs | 17 +++++++++++++---- libp2p-networking/src/network_node_handle.rs | 12 ++++++------ libp2p-networking/tests/counter.rs | 15 +++++++++------ 4 files changed, 29 insertions(+), 17 deletions(-) diff --git a/libp2p-networking/flake.nix b/libp2p-networking/flake.nix index e39d6ff871..99d658e739 100644 --- a/libp2p-networking/flake.nix +++ b/libp2p-networking/flake.nix @@ -68,7 +68,7 @@ }; }; - shellHook = '''' + (pkgs.lib.optionals pkgs.stdenv.isDarwin '' ulimit -n 10240 ''); + shellHook = '''' + (pkgs.lib.optionals pkgs.stdenv.isDarwin '' ulimit -n 9999999999''); in { packages.${crateName} = project.rootCrate.build; diff --git a/libp2p-networking/src/network_node.rs b/libp2p-networking/src/network_node.rs index feb8736659..1f77495cae 100644 --- a/libp2p-networking/src/network_node.rs +++ b/libp2p-networking/src/network_node.rs @@ -81,6 +81,9 @@ pub struct NetworkDef { /// set of events to send to UI #[behaviour(ignore)] pub client_event_queue: Vec, + /// whether or not to prune nodes + #[behaviour(ignore)] + pub pruning_enabled: bool, } impl Debug for NetworkDef { @@ -267,7 +270,7 @@ impl Debug for NetworkNode { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { f.debug_struct("Network") .field("Peer id", &self.peer_id) - .field("Wwarm", self.swarm.behaviour()) + .field("Swarm", self.swarm.behaviour()) .field("Network Config", &self.config) .finish() } @@ -290,6 +293,8 @@ pub enum ClientRequest { DirectRequest(PeerId, Vec), /// direct reply to a message DirectResponse(ResponseChannel, Vec), + /// disable or enable pruning of connections + Pruning(bool), } /// events generated by the swarm that we wish @@ -451,6 +456,8 @@ impl NetworkNode { RequestResponseConfig::default(), ); + let pruning_enabled = config.node_type == NetworkNodeType::Regular; + let network = NetworkDef { gossipsub, kadem, @@ -461,6 +468,7 @@ impl NetworkNode { known_peers: HashSet::new(), client_event_queue: Vec::new(), bootstrap_in_progress: false, + pruning_enabled }; Swarm::new(transport, network, peer_id) @@ -528,9 +536,7 @@ impl NetworkNode { }; } } - // NOTE only prune node connections if we aren't a bootstrap node - else if swarm.connected_peers.len() > self.config.max_num_peers - && self.config.node_type == NetworkNodeType::Regular + else if (swarm.pruning_enabled || self.config.node_type == NetworkNodeType::Bootstrap) && swarm.connected_peers.len() > self.config.max_num_peers { // If we are connected to too many peers, try disconnecting from // a random (?) subset @@ -628,6 +634,9 @@ impl NetworkNode { error!("Error replying to direct message. {:?}", e); } } + Pruning(is_enabled) => { + self.swarm.behaviour_mut().pruning_enabled = is_enabled; + } } } Err(e) => { diff --git a/libp2p-networking/src/network_node_handle.rs b/libp2p-networking/src/network_node_handle.rs index 9a2882d51c..36909c0a1b 100644 --- a/libp2p-networking/src/network_node_handle.rs +++ b/libp2p-networking/src/network_node_handle.rs @@ -9,7 +9,7 @@ use crate::network_node::{ NetworkNodeConfig, NetworkNodeConfigBuilder, NetworkNodeConfigBuilderError, NetworkNodeType, }; use flume::{Receiver, RecvError, SendError, Sender}; -use futures::{select, Future, FutureExt}; +use futures::{select, Future, FutureExt, future::join_all}; use libp2p::{Multiaddr, PeerId}; use rand::{seq::IteratorRandom, thread_rng}; use snafu::{ResultExt, Snafu}; @@ -110,7 +110,6 @@ impl NetworkNodeHandle { bootstrap.peer_id, bootstrap_addr ); let mut handles = Vec::new(); - info!("bootstrap addr is: {:?}", bootstrap_addr); let mut connecting_futs = vec![Self::wait_to_connect( num_of_nodes, @@ -136,10 +135,11 @@ impl NetworkNodeHandle { } timeout( timeout_len, - futures::future::join_all(connecting_futs.into_iter()), + join_all(connecting_futs.into_iter()), ) .await .context(TimeoutSnafu)?; + println!("Connected!"); Ok(handles) } @@ -156,7 +156,7 @@ impl NetworkNodeHandle { { // TODO when replaced with config, this should be > min num nodes in config if pids.len() >= 3 * num_of_nodes / 4 { - println!("node {} connected!", node_idx); + // println!("node {} connected!", node_idx); break Ok(()); } } @@ -166,8 +166,8 @@ impl NetworkNodeHandle { /// Glue function that listens for events from the Swarm corresponding to `handle` /// and calls `event_handler` when an event is observed. -/// The idea is that this function can be used independent of the actual behaviour -/// we want +/// The idea is that this function can be used independent of the actual state +/// we use #[allow(clippy::panic)] #[instrument(skip(event_handler))] pub async fn spawn_handler( diff --git a/libp2p-networking/tests/counter.rs b/libp2p-networking/tests/counter.rs index f9afef0b95..4769971c81 100644 --- a/libp2p-networking/tests/counter.rs +++ b/libp2p-networking/tests/counter.rs @@ -129,6 +129,7 @@ async fn run_request_response_increment( requester_handle.send_network.send_async(msg).await.unwrap(); timeout(TIMEOUT, recv_fut).await.unwrap(); + // println!("done request_response increment for {}", requester_handle.peer_id); assert_eq!( *requester_handle.state.lock().await, @@ -204,10 +205,11 @@ async fn run_gossip_rounds( async fn run_request_response_increment_all(handles: &[Arc>]) { let requestee_handle = get_random_handle(handles); *requestee_handle.state.lock().await += 1; - info!( - "running request_response increment to {}", - requestee_handle.state.lock().await - ); + requestee_handle.send_network.send_async(ClientRequest::Pruning(false)).await.unwrap(); + // println!( + // "running request_response increment to {}", + // requestee_handle.state.lock().await + // ); let mut futs = Vec::new(); for h in handles { // skip `requestee_handle` @@ -220,6 +222,7 @@ async fn run_request_response_increment_all(handles: &[Arc Date: Fri, 4 Feb 2022 12:31:58 -0500 Subject: [PATCH 064/107] feat: multiple bootstrap nodes --- libp2p-networking/examples/clichat.rs | 3 +- libp2p-networking/src/network_node.rs | 11 +++--- libp2p-networking/src/network_node_handle.rs | 37 ++++++++++---------- libp2p-networking/tests/common/mod.rs | 3 +- libp2p-networking/tests/counter.rs | 10 ++++-- 5 files changed, 36 insertions(+), 28 deletions(-) diff --git a/libp2p-networking/examples/clichat.rs b/libp2p-networking/examples/clichat.rs index 1e9993f0e6..25507dfa21 100644 --- a/libp2p-networking/examples/clichat.rs +++ b/libp2p-networking/examples/clichat.rs @@ -48,8 +48,9 @@ async fn main() -> Result<()> { .context("Failed to launch network")?; let port = CliOpt::from_args().port.unwrap_or(0u16); let known_peer = CliOpt::from_args().first_dial; + let peer_list = if let Some(p) = known_peer { vec![p] } else { Vec::new() }; let listen_addr = gen_multiaddr(port); - networking.start(listen_addr, known_peer).await?; + networking.start(listen_addr, peer_list.as_slice()).await?; let (send_chan, recv_chan) = networking.spawn_listeners().await?; // -- Spin up the UI diff --git a/libp2p-networking/src/network_node.rs b/libp2p-networking/src/network_node.rs index 1f77495cae..1ad33ff32d 100644 --- a/libp2p-networking/src/network_node.rs +++ b/libp2p-networking/src/network_node.rs @@ -364,7 +364,7 @@ impl NetworkNode { pub async fn start( &mut self, listen_addr: Multiaddr, - known_peer: Option, + known_peers: &[Multiaddr], ) -> Result { self.swarm.listen_on(listen_addr).context(TransportSnafu)?; let addr = loop { @@ -373,15 +373,14 @@ impl NetworkNode { } }; info!("peerid {:?} listen addr: {:?}", self.peer_id, addr); - if let Some(known_peer) = known_peer { - let dialing = known_peer.clone(); - match self.swarm.dial(known_peer) { + for known_peer in known_peers { + match self.swarm.dial(known_peer.clone()) { Ok(_) => { - warn!("peerid {:?} dialed {:?}", self.peer_id, dialing); + warn!("peerid {:?} dialed {:?}", self.peer_id, known_peer); } Err(e) => error!( "peerid {:?} dialed {:?} and failed with error: {:?}", - self.peer_id, dialing, e + self.peer_id, known_peer, e ), }; } diff --git a/libp2p-networking/src/network_node_handle.rs b/libp2p-networking/src/network_node_handle.rs index 36909c0a1b..d0e3d385c7 100644 --- a/libp2p-networking/src/network_node_handle.rs +++ b/libp2p-networking/src/network_node_handle.rs @@ -45,7 +45,7 @@ impl NetworkNodeHandle { /// constructs a new node listening on `known_addr` #[instrument] pub async fn new( - known_addr: Option, + known_addrs: &[Multiaddr], config: NetworkNodeConfig, ) -> Result { //`randomly assigned port @@ -53,7 +53,7 @@ impl NetworkNodeHandle { let mut network = NetworkNode::new(config).await.context(NetworkSnafu)?; let peer_id = network.peer_id; let listen_addr = network - .start(listen_addr, known_addr) + .start(listen_addr, known_addrs) .await .context(NetworkSnafu)?; let (send_chan, recv_chan) = network.spawn_listeners().await.context(NetworkSnafu)?; @@ -100,39 +100,40 @@ impl NetworkNodeHandle { pub async fn spin_up_swarms( num_of_nodes: usize, timeout_len: Duration, + num_bootstrap: usize ) -> Result>, NetworkNodeHandleError> { // FIXME change API to accomodate multiple bootstrap nodes - let bootstrap: NetworkNodeHandle = - NetworkNodeHandle::new(None, NetworkNodeConfig::default()).await?; - let bootstrap_addr = bootstrap.listen_addr.clone(); - info!( - "boostrap node {} on addr {}", - bootstrap.peer_id, bootstrap_addr - ); let mut handles = Vec::new(); + let mut bootstrap_addrs = Vec::::new(); + let mut connecting_futs = Vec::new(); - let mut connecting_futs = vec![Self::wait_to_connect( - num_of_nodes, - bootstrap.recv_network.clone(), - 0, - )]; - let regular_node = NetworkNodeConfigBuilder::default() + for i in 0..num_bootstrap { + let node = Arc::new(NetworkNodeHandle::new(&[], NetworkNodeConfig::default()).await?); + let addr = node.listen_addr.clone(); + connecting_futs.push(Self::wait_to_connect(num_of_nodes, node.recv_network.clone(), i)); + handles.push(node); + bootstrap_addrs.push(addr); + } + + let regular_node_config = NetworkNodeConfigBuilder::default() .node_type(NetworkNodeType::Regular) .min_num_peers(10usize) .max_num_peers(15usize) .build() .context(NodeConfigSnafu)?; - for i in 0..(num_of_nodes - 1) { + + for j in 0..(num_of_nodes - num_bootstrap) { let node = - Arc::new(NetworkNodeHandle::new(Some(bootstrap_addr.clone()), regular_node).await?); + Arc::new(NetworkNodeHandle::new(&bootstrap_addrs, regular_node_config).await?); connecting_futs.push(Self::wait_to_connect( num_of_nodes, node.recv_network.clone(), - i + 1, + num_bootstrap + j, )); handles.push(node); } + timeout( timeout_len, join_all(connecting_futs.into_iter()), diff --git a/libp2p-networking/tests/common/mod.rs b/libp2p-networking/tests/common/mod.rs index 772fbf10ba..49f5d9e3f2 100644 --- a/libp2p-networking/tests/common/mod.rs +++ b/libp2p-networking/tests/common/mod.rs @@ -27,6 +27,7 @@ pub async fn test_bed, @@ -44,7 +45,7 @@ pub async fn test_bed>> = - NetworkNodeHandle::spin_up_swarms(num_nodes, timeout) + NetworkNodeHandle::spin_up_swarms(num_nodes, timeout, num_of_bootstrap) .await .unwrap(); for handle in &handles { diff --git a/libp2p-networking/tests/counter.rs b/libp2p-networking/tests/counter.rs index 4769971c81..fcfb7f7305 100644 --- a/libp2p-networking/tests/counter.rs +++ b/libp2p-networking/tests/counter.rs @@ -10,7 +10,7 @@ use libp2p::gossipsub::Topic; use networking_demo::{ network_node::{ClientRequest, NetworkEvent}, network_node_handle::{ - get_random_handle, NetworkNodeHandle, NetworkNodeHandleError, SendSnafu, SerializationSnafu, + get_random_handle, NetworkNodeHandle, NetworkNodeHandleError, SendSnafu, SerializationSnafu, TimeoutSnafu, }, }; use std::fmt::Debug; @@ -24,6 +24,7 @@ use tracing::{error, info, instrument, warn}; pub type CounterState = u32; const TOTAL_NUM_PEERS: usize = 20; +const NUM_OF_BOOTSTRAP: usize = 5; const TIMEOUT: Duration = Duration::from_secs(30); /// Message types. We can either @@ -128,7 +129,7 @@ async fn run_request_response_increment( requester_handle.send_network.send_async(msg).await.unwrap(); - timeout(TIMEOUT, recv_fut).await.unwrap(); + timeout(TIMEOUT, recv_fut).await.context(TimeoutSnafu).unwrap(); // println!("done request_response increment for {}", requester_handle.peer_id); assert_eq!( @@ -241,6 +242,7 @@ async fn test_request_response_one_round() { run_request_response_one_round, counter_handle_network_event, TOTAL_NUM_PEERS, + NUM_OF_BOOTSTRAP, TIMEOUT, ) .await @@ -266,6 +268,7 @@ async fn test_request_response_many_rounds() { run_request_response_many_rounds, counter_handle_network_event, TOTAL_NUM_PEERS, + NUM_OF_BOOTSTRAP, TIMEOUT, ) .await @@ -293,6 +296,7 @@ async fn test_intersperse_many_rounds() { run_intersperse_many_rounds, counter_handle_network_event, TOTAL_NUM_PEERS, + NUM_OF_BOOTSTRAP, TIMEOUT, ) .await @@ -309,6 +313,7 @@ async fn test_gossip_many_rounds() { run_gossip_many_rounds, counter_handle_network_event, TOTAL_NUM_PEERS, + NUM_OF_BOOTSTRAP, TIMEOUT, ) .await; @@ -325,6 +330,7 @@ async fn test_gossip_one_round() { run_gossip_one_round, counter_handle_network_event, TOTAL_NUM_PEERS, + NUM_OF_BOOTSTRAP, TIMEOUT, ) .await; From 8d394b816ba616d52b6d7700a03add108af9b57a Mon Sep 17 00:00:00 2001 From: Justin Restivo Date: Fri, 4 Feb 2022 14:20:57 -0500 Subject: [PATCH 065/107] feat: make bootstrap nodes aware of each other --- libp2p-networking/src/network_node_handle.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/libp2p-networking/src/network_node_handle.rs b/libp2p-networking/src/network_node_handle.rs index d0e3d385c7..0a251fca89 100644 --- a/libp2p-networking/src/network_node_handle.rs +++ b/libp2p-networking/src/network_node_handle.rs @@ -102,13 +102,12 @@ impl NetworkNodeHandle { timeout_len: Duration, num_bootstrap: usize ) -> Result>, NetworkNodeHandleError> { - // FIXME change API to accomodate multiple bootstrap nodes let mut handles = Vec::new(); let mut bootstrap_addrs = Vec::::new(); let mut connecting_futs = Vec::new(); for i in 0..num_bootstrap { - let node = Arc::new(NetworkNodeHandle::new(&[], NetworkNodeConfig::default()).await?); + let node = Arc::new(NetworkNodeHandle::new(&bootstrap_addrs, NetworkNodeConfig::default()).await?); let addr = node.listen_addr.clone(); connecting_futs.push(Self::wait_to_connect(num_of_nodes, node.recv_network.clone(), i)); handles.push(node); From 4d7363819fc75b7090e0c849fac452c880ce6366 Mon Sep 17 00:00:00 2001 From: Justin Restivo Date: Mon, 7 Feb 2022 09:57:44 -0500 Subject: [PATCH 066/107] feat: ping behaviour + connection state check --- libp2p-networking/src/network_node.rs | 79 +++++++++++++++----- libp2p-networking/src/network_node_handle.rs | 37 ++++++--- libp2p-networking/tests/common/mod.rs | 19 +++++ libp2p-networking/tests/counter.rs | 6 +- 4 files changed, 108 insertions(+), 33 deletions(-) diff --git a/libp2p-networking/src/network_node.rs b/libp2p-networking/src/network_node.rs index 1ad33ff32d..1ac5a51f60 100644 --- a/libp2p-networking/src/network_node.rs +++ b/libp2p-networking/src/network_node.rs @@ -1,5 +1,6 @@ use crate::direct_message::{DirectMessageCodec, DirectMessageRequest, DirectMessageResponse}; use async_std::task::{sleep, spawn}; +use libp2p::ping::{Ping, PingEvent, PingConfig, Failure}; use rand::{seq::IteratorRandom, thread_rng}; use std::fmt::Debug; use std::{ @@ -84,6 +85,8 @@ pub struct NetworkDef { /// whether or not to prune nodes #[behaviour(ignore)] pub pruning_enabled: bool, + /// ping event. Keep the connection alive! + pub ping: Ping, } impl Debug for NetworkDef { @@ -127,6 +130,12 @@ impl NetworkDef { } } +impl NetworkBehaviourEventProcess for NetworkDef { + fn inject_event(&mut self, event: PingEvent) { + info!(?event, "ping event recv-ed"); + } +} + impl NetworkBehaviourEventProcess for NetworkDef { fn inject_event(&mut self, event: GossipsubEvent) { info!(?event, "gossipsub msg recv-ed"); @@ -168,7 +177,14 @@ impl NetworkBehaviourEventProcess for NetworkDef { _ => {} } } - KademliaEvent::RoutingUpdated { peer, .. } => { + KademliaEvent::RoutingUpdated { peer, addresses, .. } => { + for address in addresses.iter() { + self.request_response.add_address(&peer, address.clone()); + } + // TODO try add_address to request_response. It looks like stale addresses are + // happening... + // NOTE the other reason this is failing might be because the requester is + // terminating requests self.known_peers.insert(peer); self.client_event_queue .push(NetworkEvent::UpdateKnownPeers(self.known_peers.clone())); @@ -183,6 +199,7 @@ impl NetworkBehaviourEventProcess for NetworkDef { if let IdentifyEvent::Received { peer_id, info, .. } = event { for addr in info.listen_addrs { self.kadem.add_address(&peer_id, addr.clone()); + self.request_response.add_address(&peer_id, addr.clone()); } self.known_peers.insert(peer_id); self.client_event_queue @@ -348,7 +365,8 @@ pub async fn gen_transport( // muxxing streams // useful because only one connection opened // https://docs.libp2p.io/concepts/stream-multiplexing/ - .multiplex(upgrade::SelectUpgrade::new( + .multiplex( + upgrade::SelectUpgrade::new( yamux::YamuxConfig::default(), mplex::MplexConfig::default(), )) @@ -364,7 +382,7 @@ impl NetworkNode { pub async fn start( &mut self, listen_addr: Multiaddr, - known_peers: &[Multiaddr], + known_peers: &[(PeerId, Multiaddr)], ) -> Result { self.swarm.listen_on(listen_addr).context(TransportSnafu)?; let addr = loop { @@ -373,16 +391,24 @@ impl NetworkNode { } }; info!("peerid {:?} listen addr: {:?}", self.peer_id, addr); - for known_peer in known_peers { - match self.swarm.dial(known_peer.clone()) { - Ok(_) => { - warn!("peerid {:?} dialed {:?}", self.peer_id, known_peer); - } - Err(e) => error!( - "peerid {:?} dialed {:?} and failed with error: {:?}", - self.peer_id, known_peer, e - ), - }; + for (peer_id, addr) in known_peers { + self.swarm + .behaviour_mut() + .kadem + .add_address(&peer_id, addr.clone()); + self.swarm + .behaviour_mut() + .request_response + .add_address(&peer_id, addr.clone()); + // match self.swarm.dial(addr.clone()) { + // Ok(_) => { + // warn!("peerid {:?} dialed {:?}", self.peer_id, peer_id); + // } + // Err(e) => error!( + // "peerid {:?} dialed {:?} and failed with error: {:?}", + // self.peer_id, peer_id, e + // ), + // }; } Ok(addr) } @@ -455,6 +481,10 @@ impl NetworkNode { RequestResponseConfig::default(), ); + let ping_config = PingConfig::new().with_keep_alive(true); + + let ping = Ping::new(ping_config); + let pruning_enabled = config.node_type == NetworkNodeType::Regular; let network = NetworkDef { @@ -462,6 +492,7 @@ impl NetworkNode { kadem, identify, request_response, + ping, connected_peers: HashSet::new(), connecting_peers: HashSet::new(), known_peers: HashSet::new(), @@ -539,8 +570,7 @@ impl NetworkNode { { // If we are connected to too many peers, try disconnecting from // a random (?) subset - let peers_to_rm = swarm.connected_peers.iter().copied().choose_multiple( - &mut thread_rng(), + let peers_to_rm = swarm.connected_peers.iter().copied().choose_multiple( &mut thread_rng(), swarm.connected_peers.len() - self.config.max_num_peers, ); for a_peer in peers_to_rm { @@ -652,10 +682,11 @@ impl NetworkNode { &mut self, event: SwarmEvent< NetworkEvent, - EitherError< - EitherError, Error>, + EitherError, Error>, ProtocolsHandlerUpgrErr, >, + Failure>, >, send_to_client: &Sender, ) -> Result<(), NetworkError> { @@ -663,7 +694,7 @@ impl NetworkNode { #[allow(clippy::enum_glob_use)] use SwarmEvent::*; - info!("libp2p event {:?}", event); + warn!("libp2p event {:?}", event); match event { ConnectionEstablished { peer_id, endpoint, .. @@ -673,6 +704,10 @@ impl NetworkNode { self.swarm .behaviour_mut() .kadem + .add_address(&peer_id, address.clone()); + self.swarm + .behaviour_mut() + .request_response .add_address(&peer_id, address); } ConnectedPoint::Listener { @@ -682,6 +717,10 @@ impl NetworkNode { self.swarm .behaviour_mut() .kadem + .add_address(&peer_id, send_back_addr.clone()); + self.swarm + .behaviour_mut() + .request_response .add_address(&peer_id, send_back_addr); } } @@ -702,11 +741,13 @@ impl NetworkNode { .await .map_err(|_e| NetworkError::StreamClosed)?; } - ConnectionClosed { peer_id, .. } => { + ConnectionClosed { peer_id, endpoint, .. } => { let swarm = self.swarm.behaviour_mut(); swarm.connected_peers.remove(&peer_id); // FIXME remove stale address, not *all* addresses swarm.kadem.remove_peer(&peer_id); + // swarm.kadem.remove_address(); + // swarm.request_response.remove_address(peer, address) send_to_client .send_async(NetworkEvent::UpdateConnectedPeers( diff --git a/libp2p-networking/src/network_node_handle.rs b/libp2p-networking/src/network_node_handle.rs index 0a251fca89..cc139d3931 100644 --- a/libp2p-networking/src/network_node_handle.rs +++ b/libp2p-networking/src/network_node_handle.rs @@ -45,7 +45,7 @@ impl NetworkNodeHandle { /// constructs a new node listening on `known_addr` #[instrument] pub async fn new( - known_addrs: &[Multiaddr], + known_addrs: &[(PeerId, Multiaddr)], config: NetworkNodeConfig, ) -> Result { //`randomly assigned port @@ -103,15 +103,15 @@ impl NetworkNodeHandle { num_bootstrap: usize ) -> Result>, NetworkNodeHandleError> { let mut handles = Vec::new(); - let mut bootstrap_addrs = Vec::::new(); + let mut bootstrap_addrs = Vec::<(PeerId, Multiaddr)>::new(); let mut connecting_futs = Vec::new(); for i in 0..num_bootstrap { let node = Arc::new(NetworkNodeHandle::new(&bootstrap_addrs, NetworkNodeConfig::default()).await?); let addr = node.listen_addr.clone(); - connecting_futs.push(Self::wait_to_connect(num_of_nodes, node.recv_network.clone(), i)); + bootstrap_addrs.push((node.peer_id, addr)); + connecting_futs.push(Self::wait_to_connect(node.clone(), num_of_nodes, node.recv_network.clone(), i)); handles.push(node); - bootstrap_addrs.push(addr); } let regular_node_config = NetworkNodeConfigBuilder::default() @@ -125,6 +125,7 @@ impl NetworkNodeHandle { let node = Arc::new(NetworkNodeHandle::new(&bootstrap_addrs, regular_node_config).await?); connecting_futs.push(Self::wait_to_connect( + node.clone(), num_of_nodes, node.recv_network.clone(), num_bootstrap + j, @@ -146,21 +147,33 @@ impl NetworkNodeHandle { /// Wait for a node to connect to other nodes #[instrument] async fn wait_to_connect( + node: Arc>, num_of_nodes: usize, chan: Receiver, node_idx: usize, ) -> Result<(), NetworkNodeHandleError> { - loop { - if let NetworkEvent::UpdateConnectedPeers(pids) = - chan.recv_async().await.context(RecvSnafu)? - { - // TODO when replaced with config, this should be > min num nodes in config - if pids.len() >= 3 * num_of_nodes / 4 { - // println!("node {} connected!", node_idx); - break Ok(()); + let mut connected_ok = false; + let mut known_ok = false; + while !(known_ok && connected_ok) { + match chan.recv_async().await.context(RecvSnafu)? { + NetworkEvent::UpdateConnectedPeers(pids) => + { + node.connection_state.lock().await.connected_peers = pids.clone(); + // TODO when replaced with config, this should be > min num nodes in config + if pids.len() >= 3 * num_of_nodes / 4 { + connected_ok = true; + } } + NetworkEvent::UpdateKnownPeers(pids) => { + node.connection_state.lock().await.known_peers = pids.clone(); + if pids.len() >= 3 * num_of_nodes / 4 { + known_ok = true; + } + } + _ => {} } } + Ok(()) } } diff --git a/libp2p-networking/tests/common/mod.rs b/libp2p-networking/tests/common/mod.rs index 49f5d9e3f2..b54cf7a6eb 100644 --- a/libp2p-networking/tests/common/mod.rs +++ b/libp2p-networking/tests/common/mod.rs @@ -48,6 +48,7 @@ pub async fn test_bed(handles: &[Arc>]) { ); } } + +pub async fn check_connection_state(handles: &[Arc>]){ + let mut err_msg = "".to_string(); + for (i, handle) in handles.iter().enumerate(){ + let state = handle.connection_state.lock().await.clone(); + // TODO these should depend on config + if state.known_peers.len() < handles.len() / 3 { + err_msg.push_str(&format!("\nhad {} known peers for {}-th handle", state.known_peers.len(), i)); + } + if state.connected_peers.len() < 10 { + err_msg.push_str(&format!("\nhad {} connected peers for {}-th handle", state.connected_peers.len(), i)); + } + } + if err_msg.len() != 0 { + panic!("{}", err_msg); + } + +} diff --git a/libp2p-networking/tests/counter.rs b/libp2p-networking/tests/counter.rs index fcfb7f7305..373572808e 100644 --- a/libp2p-networking/tests/counter.rs +++ b/libp2p-networking/tests/counter.rs @@ -1,7 +1,7 @@ use std::{sync::Arc, time::Duration}; mod common; use async_std::future::timeout; -use common::test_bed; +use common::{test_bed, check_connection_state}; use bincode::Options; @@ -204,6 +204,7 @@ async fn run_gossip_rounds( /// then has all other peers request its state /// and update their state to the recv'ed state async fn run_request_response_increment_all(handles: &[Arc>]) { + check_connection_state(handles).await; let requestee_handle = get_random_handle(handles); *requestee_handle.state.lock().await += 1; requestee_handle.send_network.send_async(ClientRequest::Pruning(false)).await.unwrap(); @@ -223,7 +224,8 @@ async fn run_request_response_increment_all(handles: &[Arc Date: Mon, 7 Feb 2022 11:52:39 -0500 Subject: [PATCH 067/107] feat: split out network node connection from init --- libp2p-networking/examples/clichat.rs | 22 ++++-- libp2p-networking/src/network_node.rs | 77 ++++++++++++-------- libp2p-networking/src/network_node_handle.rs | 54 ++++++++------ libp2p-networking/tests/common/mod.rs | 19 +++-- libp2p-networking/tests/counter.rs | 24 ++++-- 5 files changed, 126 insertions(+), 70 deletions(-) diff --git a/libp2p-networking/examples/clichat.rs b/libp2p-networking/examples/clichat.rs index 25507dfa21..740f36a7a4 100644 --- a/libp2p-networking/examples/clichat.rs +++ b/libp2p-networking/examples/clichat.rs @@ -1,4 +1,4 @@ -use libp2p::Multiaddr; +use libp2p::{Multiaddr, PeerId}; use networking_demo::message::Message; use networking_demo::ui::{run_app, TableApp}; @@ -29,7 +29,10 @@ struct CliOpt { port: Option, #[structopt()] - first_dial: Option, + first_dial_peer_id: Option, + + #[structopt()] + first_dial_addr: Option, } #[async_std::main] @@ -47,10 +50,19 @@ async fn main() -> Result<()> { .await .context("Failed to launch network")?; let port = CliOpt::from_args().port.unwrap_or(0u16); - let known_peer = CliOpt::from_args().first_dial; - let peer_list = if let Some(p) = known_peer { vec![p] } else { Vec::new() }; + let known_peer = CliOpt::from_args().first_dial_addr; + let peer_list = if let Some(p) = known_peer { + if let Some(pid) = CliOpt::from_args().first_dial_peer_id { + vec![(pid, p)] + } else { + Vec::new() + } + } else { + Vec::new() + }; let listen_addr = gen_multiaddr(port); - networking.start(listen_addr, peer_list.as_slice()).await?; + networking.start_listen(listen_addr).await?; + networking.add_known_peers(peer_list.as_slice()).await; let (send_chan, recv_chan) = networking.spawn_listeners().await?; // -- Spin up the UI diff --git a/libp2p-networking/src/network_node.rs b/libp2p-networking/src/network_node.rs index 1ac5a51f60..09425a8ed1 100644 --- a/libp2p-networking/src/network_node.rs +++ b/libp2p-networking/src/network_node.rs @@ -1,6 +1,6 @@ use crate::direct_message::{DirectMessageCodec, DirectMessageRequest, DirectMessageResponse}; use async_std::task::{sleep, spawn}; -use libp2p::ping::{Ping, PingEvent, PingConfig, Failure}; +use libp2p::ping::{Failure, Ping, PingConfig, PingEvent}; use rand::{seq::IteratorRandom, thread_rng}; use std::fmt::Debug; use std::{ @@ -177,7 +177,9 @@ impl NetworkBehaviourEventProcess for NetworkDef { _ => {} } } - KademliaEvent::RoutingUpdated { peer, addresses, .. } => { + KademliaEvent::RoutingUpdated { + peer, addresses, .. + } => { for address in addresses.iter() { self.request_response.add_address(&peer, address.clone()); } @@ -312,6 +314,8 @@ pub enum ClientRequest { DirectResponse(ResponseChannel, Vec), /// disable or enable pruning of connections Pruning(bool), + /// add vec of known peers + AddKnownPeers(Vec<(PeerId, Multiaddr)>), } /// events generated by the swarm that we wish @@ -365,8 +369,7 @@ pub async fn gen_transport( // muxxing streams // useful because only one connection opened // https://docs.libp2p.io/concepts/stream-multiplexing/ - .multiplex( - upgrade::SelectUpgrade::new( + .multiplex(upgrade::SelectUpgrade::new( yamux::YamuxConfig::default(), mplex::MplexConfig::default(), )) @@ -379,10 +382,9 @@ impl NetworkNode { /// and optionally dials into peer `known_peer` /// returns the address the swarm is listening upon #[instrument(skip(self))] - pub async fn start( + pub async fn start_listen( &mut self, listen_addr: Multiaddr, - known_peers: &[(PeerId, Multiaddr)], ) -> Result { self.swarm.listen_on(listen_addr).context(TransportSnafu)?; let addr = loop { @@ -390,27 +392,32 @@ impl NetworkNode { break address; } }; - info!("peerid {:?} listen addr: {:?}", self.peer_id, addr); + info!("peerid {:?} started on addr: {:?}", self.peer_id, addr); + Ok(addr) + } + + /// initialize the DHT with known peers + // add the peers to kademlia and then + // the `spawn_listeners` function + // will start connecting to peers + #[instrument(skip(self))] + pub async fn add_known_peers(&mut self, known_peers: &[(PeerId, Multiaddr)]) { for (peer_id, addr) in known_peers { self.swarm .behaviour_mut() .kadem - .add_address(&peer_id, addr.clone()); + .add_address(peer_id, addr.clone()); self.swarm .behaviour_mut() .request_response - .add_address(&peer_id, addr.clone()); - // match self.swarm.dial(addr.clone()) { - // Ok(_) => { - // warn!("peerid {:?} dialed {:?}", self.peer_id, peer_id); - // } - // Err(e) => error!( - // "peerid {:?} dialed {:?} and failed with error: {:?}", - // self.peer_id, peer_id, e - // ), - // }; + .add_address(peer_id, addr.clone()); + self.swarm.behaviour_mut().known_peers.insert(*peer_id); } - Ok(addr) + let new_peers = self.swarm.behaviour().known_peers.clone(); + self.swarm + .behaviour_mut() + .client_event_queue + .push(NetworkEvent::UpdateKnownPeers(new_peers)); } /// Creates a new `Network` with the given settings. @@ -498,7 +505,7 @@ impl NetworkNode { known_peers: HashSet::new(), client_event_queue: Vec::new(), bootstrap_in_progress: false, - pruning_enabled + pruning_enabled, }; Swarm::new(transport, network, peer_id) @@ -565,12 +572,13 @@ impl NetworkNode { } }; } - } - else if (swarm.pruning_enabled || self.config.node_type == NetworkNodeType::Bootstrap) && swarm.connected_peers.len() > self.config.max_num_peers + } else if (swarm.pruning_enabled || self.config.node_type == NetworkNodeType::Bootstrap) + && swarm.connected_peers.len() > self.config.max_num_peers { // If we are connected to too many peers, try disconnecting from // a random (?) subset - let peers_to_rm = swarm.connected_peers.iter().copied().choose_multiple( &mut thread_rng(), + let peers_to_rm = swarm.connected_peers.iter().copied().choose_multiple( + &mut thread_rng(), swarm.connected_peers.len() - self.config.max_num_peers, ); for a_peer in peers_to_rm { @@ -666,6 +674,9 @@ impl NetworkNode { Pruning(is_enabled) => { self.swarm.behaviour_mut().pruning_enabled = is_enabled; } + AddKnownPeers(peers) => { + self.add_known_peers(&peers).await; + } } } Err(e) => { @@ -682,11 +693,13 @@ impl NetworkNode { &mut self, event: SwarmEvent< NetworkEvent, - EitherError, Error>, - ProtocolsHandlerUpgrErr, + EitherError< + EitherError< + EitherError, Error>, + ProtocolsHandlerUpgrErr, + >, + Failure, >, - Failure>, >, send_to_client: &Sender, ) -> Result<(), NetworkError> { @@ -741,7 +754,11 @@ impl NetworkNode { .await .map_err(|_e| NetworkError::StreamClosed)?; } - ConnectionClosed { peer_id, endpoint, .. } => { + ConnectionClosed { + peer_id, + endpoint: _, + .. + } => { let swarm = self.swarm.behaviour_mut(); swarm.connected_peers.remove(&peer_id); // FIXME remove stale address, not *all* addresses @@ -755,10 +772,6 @@ impl NetworkNode { )) .await .map_err(|_e| NetworkError::StreamClosed)?; - send_to_client - .send_async(NetworkEvent::UpdateKnownPeers(swarm.known_peers.clone())) - .await - .map_err(|_e| NetworkError::StreamClosed)?; } Dialing(_) | NewListenAddr { .. } diff --git a/libp2p-networking/src/network_node_handle.rs b/libp2p-networking/src/network_node_handle.rs index cc139d3931..b7392fb2a2 100644 --- a/libp2p-networking/src/network_node_handle.rs +++ b/libp2p-networking/src/network_node_handle.rs @@ -9,12 +9,12 @@ use crate::network_node::{ NetworkNodeConfig, NetworkNodeConfigBuilder, NetworkNodeConfigBuilderError, NetworkNodeType, }; use flume::{Receiver, RecvError, SendError, Sender}; -use futures::{select, Future, FutureExt, future::join_all}; +use futures::{future::join_all, select, Future, FutureExt}; use libp2p::{Multiaddr, PeerId}; use rand::{seq::IteratorRandom, thread_rng}; use snafu::{ResultExt, Snafu}; use std::{fmt::Debug, sync::Arc, time::Duration}; -use tracing::{info, info_span, instrument, Instrument}; +use tracing::{info_span, instrument, Instrument}; /// A handle containing: /// - A reference to the state @@ -44,16 +44,14 @@ pub struct NetworkNodeHandle { impl NetworkNodeHandle { /// constructs a new node listening on `known_addr` #[instrument] - pub async fn new( - known_addrs: &[(PeerId, Multiaddr)], - config: NetworkNodeConfig, - ) -> Result { + pub async fn new(config: NetworkNodeConfig) -> Result { //`randomly assigned port let listen_addr = gen_multiaddr(0); let mut network = NetworkNode::new(config).await.context(NetworkSnafu)?; let peer_id = network.peer_id; + // TODO separate this into a separate function so you can make everyone know about everyone let listen_addr = network - .start(listen_addr, known_addrs) + .start_listen(listen_addr) .await .context(NetworkSnafu)?; let (send_chan, recv_chan) = network.spawn_listeners().await.context(NetworkSnafu)?; @@ -100,17 +98,23 @@ impl NetworkNodeHandle { pub async fn spin_up_swarms( num_of_nodes: usize, timeout_len: Duration, - num_bootstrap: usize + num_bootstrap: usize, ) -> Result>, NetworkNodeHandleError> { let mut handles = Vec::new(); let mut bootstrap_addrs = Vec::<(PeerId, Multiaddr)>::new(); + let mut regular_addrs = Vec::<(PeerId, Multiaddr)>::new(); let mut connecting_futs = Vec::new(); for i in 0..num_bootstrap { - let node = Arc::new(NetworkNodeHandle::new(&bootstrap_addrs, NetworkNodeConfig::default()).await?); - let addr = node.listen_addr.clone(); + let node = Arc::new(NetworkNodeHandle::new(NetworkNodeConfig::default()).await?); + let addr = node.listen_addr.clone(); bootstrap_addrs.push((node.peer_id, addr)); - connecting_futs.push(Self::wait_to_connect(node.clone(), num_of_nodes, node.recv_network.clone(), i)); + connecting_futs.push(Self::wait_to_connect( + node.clone(), + num_of_nodes, + node.recv_network.clone(), + i, + )); handles.push(node); } @@ -122,8 +126,9 @@ impl NetworkNodeHandle { .context(NodeConfigSnafu)?; for j in 0..(num_of_nodes - num_bootstrap) { - let node = - Arc::new(NetworkNodeHandle::new(&bootstrap_addrs, regular_node_config).await?); + let node = Arc::new(NetworkNodeHandle::new(regular_node_config).await?); + let addr = node.listen_addr.clone(); + bootstrap_addrs.push((node.peer_id, addr)); connecting_futs.push(Self::wait_to_connect( node.clone(), num_of_nodes, @@ -134,12 +139,20 @@ impl NetworkNodeHandle { handles.push(node); } - timeout( - timeout_len, - join_all(connecting_futs.into_iter()), - ) - .await - .context(TimeoutSnafu)?; + let mut all_addrs = bootstrap_addrs; + all_addrs.append(&mut regular_addrs); + + for handle in &handles { + handle + .send_network + .send_async(ClientRequest::AddKnownPeers(all_addrs.clone())) + .await + .context(SendSnafu)?; + } + + timeout(timeout_len, join_all(connecting_futs.into_iter())) + .await + .context(TimeoutSnafu)?; println!("Connected!"); Ok(handles) } @@ -156,8 +169,7 @@ impl NetworkNodeHandle { let mut known_ok = false; while !(known_ok && connected_ok) { match chan.recv_async().await.context(RecvSnafu)? { - NetworkEvent::UpdateConnectedPeers(pids) => - { + NetworkEvent::UpdateConnectedPeers(pids) => { node.connection_state.lock().await.connected_peers = pids.clone(); // TODO when replaced with config, this should be > min num nodes in config if pids.len() >= 3 * num_of_nodes / 4 { diff --git a/libp2p-networking/tests/common/mod.rs b/libp2p-networking/tests/common/mod.rs index b54cf7a6eb..dcc10c7f4d 100644 --- a/libp2p-networking/tests/common/mod.rs +++ b/libp2p-networking/tests/common/mod.rs @@ -80,20 +80,27 @@ async fn print_connections(handles: &[Arc>]) { } } -pub async fn check_connection_state(handles: &[Arc>]){ +pub async fn check_connection_state(handles: &[Arc>]) { let mut err_msg = "".to_string(); - for (i, handle) in handles.iter().enumerate(){ + for (i, handle) in handles.iter().enumerate() { let state = handle.connection_state.lock().await.clone(); // TODO these should depend on config if state.known_peers.len() < handles.len() / 3 { - err_msg.push_str(&format!("\nhad {} known peers for {}-th handle", state.known_peers.len(), i)); + err_msg.push_str(&format!( + "\nhad {} known peers for {}-th handle", + state.known_peers.len(), + i + )); } if state.connected_peers.len() < 10 { - err_msg.push_str(&format!("\nhad {} connected peers for {}-th handle", state.connected_peers.len(), i)); + err_msg.push_str(&format!( + "\nhad {} connected peers for {}-th handle", + state.connected_peers.len(), + i + )); } } - if err_msg.len() != 0 { + if !err_msg.is_empty() { panic!("{}", err_msg); } - } diff --git a/libp2p-networking/tests/counter.rs b/libp2p-networking/tests/counter.rs index 373572808e..69bad3a643 100644 --- a/libp2p-networking/tests/counter.rs +++ b/libp2p-networking/tests/counter.rs @@ -1,7 +1,7 @@ use std::{sync::Arc, time::Duration}; mod common; use async_std::future::timeout; -use common::{test_bed, check_connection_state}; +use common::{check_connection_state, test_bed}; use bincode::Options; @@ -10,7 +10,8 @@ use libp2p::gossipsub::Topic; use networking_demo::{ network_node::{ClientRequest, NetworkEvent}, network_node_handle::{ - get_random_handle, NetworkNodeHandle, NetworkNodeHandleError, SendSnafu, SerializationSnafu, TimeoutSnafu, + get_random_handle, NetworkNodeHandle, NetworkNodeHandleError, SendSnafu, + SerializationSnafu, TimeoutSnafu, }, }; use std::fmt::Debug; @@ -129,7 +130,10 @@ async fn run_request_response_increment( requester_handle.send_network.send_async(msg).await.unwrap(); - timeout(TIMEOUT, recv_fut).await.context(TimeoutSnafu).unwrap(); + timeout(TIMEOUT, recv_fut) + .await + .context(TimeoutSnafu) + .unwrap(); // println!("done request_response increment for {}", requester_handle.peer_id); assert_eq!( @@ -207,7 +211,11 @@ async fn run_request_response_increment_all(handles: &[Arc>>, ) { let num_rounds = 4092; - for i in 0..num_rounds { + for _i in 0..num_rounds { run_request_response_increment_all(&handles).await; // println!("finished {}", i); } From 0c371ace8e16541cdea929d6448842eb4922aab2 Mon Sep 17 00:00:00 2001 From: Justin Restivo Date: Mon, 7 Feb 2022 13:50:04 -0500 Subject: [PATCH 068/107] feat: separate pruning from establishing requests --- libp2p-networking/src/network_node.rs | 40 ++++++++++++++++----------- libp2p-networking/tests/common/mod.rs | 2 +- libp2p-networking/tests/counter.rs | 4 +-- 3 files changed, 27 insertions(+), 19 deletions(-) diff --git a/libp2p-networking/src/network_node.rs b/libp2p-networking/src/network_node.rs index 09425a8ed1..c4643cb3fb 100644 --- a/libp2p-networking/src/network_node.rs +++ b/libp2p-networking/src/network_node.rs @@ -397,9 +397,9 @@ impl NetworkNode { } /// initialize the DHT with known peers - // add the peers to kademlia and then - // the `spawn_listeners` function - // will start connecting to peers + /// add the peers to kademlia and then + /// the `spawn_listeners` function + /// will start connecting to peers #[instrument(skip(self))] pub async fn add_known_peers(&mut self, known_peers: &[(PeerId, Multiaddr)]) { for (peer_id, addr) in known_peers { @@ -572,23 +572,28 @@ impl NetworkNode { } }; } - } else if (swarm.pruning_enabled || self.config.node_type == NetworkNodeType::Bootstrap) - && swarm.connected_peers.len() > self.config.max_num_peers - { - // If we are connected to too many peers, try disconnecting from - // a random (?) subset - let peers_to_rm = swarm.connected_peers.iter().copied().choose_multiple( - &mut thread_rng(), - swarm.connected_peers.len() - self.config.max_num_peers, - ); - for a_peer in peers_to_rm { - // FIXME the error is () ? - let _ = self.swarm.disconnect_peer_id(a_peer); - } } } } + #[instrument(skip(self))] + fn prune_num_connections(&mut self) { + // let swarm = self.swarm.behaviour_mut(); + // // If we are connected to too many peers, try disconnecting from + // // a random (?) subset + // if !swarm.bootstrap_in_progress && swarm.pruning_enabled && self.config.node_type != NetworkNodeType::Bootstrap && swarm.connected_peers.len() > self.config.max_num_peers { + // let peers_to_rm = swarm.connected_peers.iter().copied().choose( + // &mut thread_rng(), + // ); + // for a_peer in peers_to_rm { + // // FIXME the error is () ? + // let _ = self.swarm.disconnect_peer_id(a_peer); + // } + // + // } + } + + /// event handler for client events /// currectly supported actions include /// - shutting down the swarm @@ -814,6 +819,9 @@ impl NetworkNode { _ = sleep(Duration::from_secs(1)).fuse() => { self.handle_num_connections(); } + _ = sleep(Duration::from_secs(5)).fuse() => { + self.prune_num_connections(); + } event = self.swarm.next() => { if let Some(event) = event { info!("peerid {:?}\t\thandling event {:?}", self.peer_id, event); diff --git a/libp2p-networking/tests/common/mod.rs b/libp2p-networking/tests/common/mod.rs index dcc10c7f4d..7f6ea2f4c8 100644 --- a/libp2p-networking/tests/common/mod.rs +++ b/libp2p-networking/tests/common/mod.rs @@ -92,7 +92,7 @@ pub async fn check_connection_state(handles: &[Arc>]) { i )); } - if state.connected_peers.len() < 10 { + if state.connected_peers.len() < handles.len() / 3 { err_msg.push_str(&format!( "\nhad {} connected peers for {}-th handle", state.connected_peers.len(), diff --git a/libp2p-networking/tests/counter.rs b/libp2p-networking/tests/counter.rs index 69bad3a643..8e999c9721 100644 --- a/libp2p-networking/tests/counter.rs +++ b/libp2p-networking/tests/counter.rs @@ -24,8 +24,8 @@ use tracing::{error, info, instrument, warn}; pub type CounterState = u32; -const TOTAL_NUM_PEERS: usize = 20; -const NUM_OF_BOOTSTRAP: usize = 5; +const TOTAL_NUM_PEERS: usize = 5; +const NUM_OF_BOOTSTRAP: usize = 1; const TIMEOUT: Duration = Duration::from_secs(30); /// Message types. We can either From e1f25ed7ebacc1916976e4b9151ce58d6a965f7c Mon Sep 17 00:00:00 2001 From: Justin Restivo Date: Mon, 7 Feb 2022 18:48:00 -0500 Subject: [PATCH 069/107] chore: version bump --- libp2p-networking/Cargo.lock | 608 +++++++++++++++++++------- libp2p-networking/Cargo.toml | 20 +- libp2p-networking/flake.nix | 2 +- libp2p-networking/src/network_node.rs | 2 +- 4 files changed, 458 insertions(+), 174 deletions(-) diff --git a/libp2p-networking/Cargo.lock b/libp2p-networking/Cargo.lock index 1e24707b22..6e8ff9fc7d 100644 --- a/libp2p-networking/Cargo.lock +++ b/libp2p-networking/Cargo.lock @@ -376,9 +376,9 @@ dependencies = [ [[package]] name = "blake3" -version = "1.3.0" +version = "1.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "882e99e4a0cb2ae6cb6e442102e8e6b7131718d94110e64c3e6a34ea9b106f37" +checksum = "a08e53fc5a564bb15bfe6fae56bd71522205f1f91893f9c0116edad6496c183f" dependencies = [ "arrayref", "arrayvec 0.7.2", @@ -566,6 +566,22 @@ version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "245097e9a4535ee1e3e3931fcfcd55a796a44c643e8596ff6566d68f09b87bbc" +[[package]] +name = "core-foundation" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "194a7a9e6de53fa55116934067c844d9d749312f75c6f6d0980e8c252f8c2146" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "core-foundation-sys" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5827cebf4670468b8772dd191856768aedcb1b0278a04f989f7766351917b9dc" + [[package]] name = "cpufeatures" version = "0.2.1" @@ -596,15 +612,15 @@ dependencies = [ [[package]] name = "crossterm" -version = "0.20.0" +version = "0.22.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0ebde6a9dd5e331cd6c6f48253254d117642c31653baa475e394657c59c1f7d" +checksum = "c85525306c4291d1b73ce93c8acf9c339f9b213aef6c1d85c3830cbf1c16325c" dependencies = [ "bitflags", - "crossterm_winapi 0.8.0", + "crossterm_winapi", "libc", "mio", - "parking_lot", + "parking_lot 0.11.2", "signal-hook", "signal-hook-mio", "winapi", @@ -612,30 +628,21 @@ dependencies = [ [[package]] name = "crossterm" -version = "0.22.1" +version = "0.23.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c85525306c4291d1b73ce93c8acf9c339f9b213aef6c1d85c3830cbf1c16325c" +checksum = "77b75a27dc8d220f1f8521ea69cd55a34d720a200ebb3a624d9aa19193d3b432" dependencies = [ "bitflags", - "crossterm_winapi 0.9.0", + "crossterm_winapi", "futures-core", "libc", "mio", - "parking_lot", + "parking_lot 0.12.0", "signal-hook", "signal-hook-mio", "winapi", ] -[[package]] -name = "crossterm_winapi" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a6966607622438301997d3dac0d2f6e9a90c68bb6bc1785ea98456ab93c0507" -dependencies = [ - "winapi", -] - [[package]] name = "crossterm_winapi" version = "0.9.0" @@ -824,9 +831,9 @@ checksum = "fea41bba32d969b513997752735605054bc0dfa92b4c56bf1189f2e174be7a10" [[package]] name = "dtoa" -version = "0.4.8" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56899898ce76aaf4a0f24d914c97ea6ed976d42fec6ad33fcbb0a1103e07b2b0" +checksum = "5caaa75cbd2b960ff1e5392d2cfb1f44717fffe12fc1f32b7b5d1267f99732a6" [[package]] name = "ed25519" @@ -847,7 +854,7 @@ dependencies = [ "ed25519", "rand 0.7.3", "serde", - "sha2", + "sha2 0.9.9", "zeroize", ] @@ -944,9 +951,9 @@ dependencies = [ [[package]] name = "futures" -version = "0.3.19" +version = "0.3.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28560757fe2bb34e79f907794bb6b22ae8b0e5c669b638a1132f2592b19035b4" +checksum = "f73fe65f54d1e12b726f517d3e2135ca3125a437b6d998caf1962961f7172d9e" dependencies = [ "futures-channel", "futures-core", @@ -959,9 +966,9 @@ dependencies = [ [[package]] name = "futures-channel" -version = "0.3.19" +version = "0.3.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba3dda0b6588335f360afc675d0564c17a77a2bda81ca178a4b6081bd86c7f0b" +checksum = "c3083ce4b914124575708913bca19bfe887522d6e2e6d0952943f5eac4a74010" dependencies = [ "futures-core", "futures-sink", @@ -969,15 +976,15 @@ dependencies = [ [[package]] name = "futures-core" -version = "0.3.19" +version = "0.3.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0c8ff0461b82559810cdccfde3215c3f373807f5e5232b71479bff7bb2583d7" +checksum = "0c09fd04b7e4073ac7156a9539b57a484a8ea920f79c7c675d05d289ab6110d3" [[package]] name = "futures-executor" -version = "0.3.19" +version = "0.3.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "29d6d2ff5bb10fb95c85b8ce46538a2e5f5e7fdc755623a7d4529ab8a4ed9d2a" +checksum = "9420b90cfa29e327d0429f19be13e7ddb68fa1cccb09d65e5706b8c7a749b8a6" dependencies = [ "futures-core", "futures-task", @@ -987,9 +994,9 @@ dependencies = [ [[package]] name = "futures-io" -version = "0.3.19" +version = "0.3.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1f9d34af5a1aac6fb380f735fe510746c38067c5bf16c7fd250280503c971b2" +checksum = "fc4045962a5a5e935ee2fdedaa4e08284547402885ab326734432bed5d12966b" [[package]] name = "futures-lite" @@ -1008,9 +1015,9 @@ dependencies = [ [[package]] name = "futures-macro" -version = "0.3.19" +version = "0.3.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6dbd947adfffb0efc70599b3ddcf7b5597bb5fa9e245eb99f62b3a5f7bb8bd3c" +checksum = "33c1e13800337f4d4d7a316bf45a567dbcb6ffe087f16424852d97e97a91f512" dependencies = [ "proc-macro2", "quote", @@ -1030,15 +1037,15 @@ dependencies = [ [[package]] name = "futures-sink" -version = "0.3.19" +version = "0.3.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3055baccb68d74ff6480350f8d6eb8fcfa3aa11bdc1a1ae3afdd0514617d508" +checksum = "21163e139fa306126e6eedaf49ecdb4588f939600f0b1e770f4205ee4b7fa868" [[package]] name = "futures-task" -version = "0.3.19" +version = "0.3.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ee7c6485c30167ce4dfb83ac568a849fe53274c831081476ee13e0dce1aad72" +checksum = "57c66a976bf5909d801bbef33416c41372779507e7a6b3a5e25e4749c58f776a" [[package]] name = "futures-timer" @@ -1048,9 +1055,9 @@ checksum = "e64b03909df88034c26dc1547e8970b91f98bdb65165d6a4e9110d94263dbb2c" [[package]] name = "futures-util" -version = "0.3.19" +version = "0.3.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9b5cf40b47a271f77a8b1bec03ca09044d99d2372c0de244e66430761127164" +checksum = "d8b7abd5d659d9b90c8cba917f6ec750a74e2dc23902ef9cd4cc8c8b22e6036a" dependencies = [ "futures-channel", "futures-core", @@ -1223,39 +1230,30 @@ dependencies = [ [[package]] name = "if-addrs" -version = "0.6.7" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2273e421f7c4f0fc99e1934fe4776f59d8df2972f4199d703fc0da9f2a9f73de" +checksum = "cbc0fa01ffc752e9dbc72818cdb072cd028b86be5e09dd04c5a643704fe101a9" dependencies = [ - "if-addrs-sys", "libc", "winapi", ] -[[package]] -name = "if-addrs-sys" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "de74b9dd780476e837e5eb5ab7c88b49ed304126e412030a0adba99c8efe79ea" -dependencies = [ - "cc", - "libc", -] - [[package]] name = "if-watch" -version = "0.2.2" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae8ab7f67bad3240049cb24fb9cb0b4c2c6af4c245840917fbbdededeee91179" +checksum = "ae8f4a3c3d4c89351ca83e120c1c00b27df945d38e05695668c9d4b4f7bc52f3" dependencies = [ "async-io", + "core-foundation", + "fnv", "futures", - "futures-lite", "if-addrs", "ipnet", - "libc", "log", - "winapi", + "rtnetlink", + "system-configuration", + "windows", ] [[package]] @@ -1310,12 +1308,6 @@ dependencies = [ "either", ] -[[package]] -name = "itoa" -version = "0.4.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b71991ff56294aa922b450139ee08b3bfc70982c6b2c7562771375cf73542dd4" - [[package]] name = "itoa" version = "1.0.1" @@ -1360,9 +1352,9 @@ checksum = "1b03d17f364a3a042d5e5d46b053bbbf82c92c9430c592dd4c064dc6ee997125" [[package]] name = "libp2p" -version = "0.41.1" +version = "0.42.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2ec5b70fc23ed1b1b1169ce0d1116260a343f67cf7088b498b8d99255cd68c32" +checksum = "0f592f1b06f12a5686a5de7be9f289a161c96d5f89f12b04b7d14cf3d61d7381" dependencies = [ "atomic", "bytes", @@ -1371,6 +1363,7 @@ dependencies = [ "getrandom 0.2.3", "instant", "lazy_static", + "libp2p-autonat", "libp2p-core", "libp2p-deflate", "libp2p-dns", @@ -1396,17 +1389,36 @@ dependencies = [ "libp2p-websocket", "libp2p-yamux", "multiaddr", - "parking_lot", + "parking_lot 0.11.2", "pin-project 1.0.10", "rand 0.7.3", "smallvec", ] +[[package]] +name = "libp2p-autonat" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c0e6bbc00385edde71430e7d261d13edebcf0e52aecac8f0081a299f960c545" +dependencies = [ + "async-trait", + "futures", + "futures-timer", + "instant", + "libp2p-core", + "libp2p-request-response", + "libp2p-swarm", + "log", + "prost", + "prost-build", + "rand 0.8.4", +] + [[package]] name = "libp2p-core" -version = "0.30.0" +version = "0.31.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bef22d9bba1e8bcb7ec300073e6802943fe8abb8190431842262b5f1c30abba1" +checksum = "77c4178afd65bf7c56744b4e0a6cfa6e9b694fe666efba596e03a46f79454d8d" dependencies = [ "asn1_der", "bs58", @@ -1415,20 +1427,21 @@ dependencies = [ "fnv", "futures", "futures-timer", + "instant", "lazy_static", "libsecp256k1", "log", "multiaddr", "multihash", "multistream-select", - "parking_lot", + "parking_lot 0.11.2", "pin-project 1.0.10", "prost", "prost-build", "rand 0.8.4", "ring", "rw-stream-sink", - "sha2", + "sha2 0.10.1", "smallvec", "thiserror", "unsigned-varint", @@ -1438,9 +1451,9 @@ dependencies = [ [[package]] name = "libp2p-deflate" -version = "0.30.0" +version = "0.31.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "51a800adb195f33de63f4b17b63fe64cfc23bf2c6a0d3d0d5321328664e65197" +checksum = "9d56c68b9c5d435bbd8cdd20101348194b18d1e6ff29ece7a223734aa7eb695c" dependencies = [ "flate2", "futures", @@ -1449,9 +1462,9 @@ dependencies = [ [[package]] name = "libp2p-dns" -version = "0.30.0" +version = "0.31.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb8f89d15cb6e3c5bc22afff7513b11bab7856f2872d3cfba86f7f63a06bc498" +checksum = "39d4a2e7efe62c738833b6be6c0f158cf7ffccba462320f4b3bebe43e1050e7b" dependencies = [ "async-std-resolver", "futures", @@ -1463,9 +1476,9 @@ dependencies = [ [[package]] name = "libp2p-floodsub" -version = "0.32.0" +version = "0.33.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "709047c957360e8f2b3f7e987c0e272038e3003e0cdaf08b42668132ff910161" +checksum = "604b6ad64c07a49a9e5e78d4f25c9ad28a17d5fefb1384d7ea35b3201e4aeed3" dependencies = [ "cuckoofilter", "fnv", @@ -1481,9 +1494,9 @@ dependencies = [ [[package]] name = "libp2p-gossipsub" -version = "0.34.0" +version = "0.35.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "98942284cc1a91f24527a8b1e5bc06f7dd22fc6cee5be3d9bf5785bf902eb934" +checksum = "385ae5f44e84f51e17014c9f1d98464121d3b1b182c167a0b4482d6250c61926" dependencies = [ "asynchronous-codec", "base64", @@ -1503,16 +1516,16 @@ dependencies = [ "prost-build", "rand 0.7.3", "regex", - "sha2", + "sha2 0.10.1", "smallvec", "unsigned-varint", ] [[package]] name = "libp2p-identify" -version = "0.32.1" +version = "0.33.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32329181638a103321c05ef697f406abbccc695780b7c7d3dc34206758e9eb09" +checksum = "ae5d84b4e57cb66abb9dd28ea36f69620816e004a7479c0ad76f45002820f99b" dependencies = [ "futures", "futures-timer", @@ -1527,9 +1540,9 @@ dependencies = [ [[package]] name = "libp2p-kad" -version = "0.33.0" +version = "0.34.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fe4538a739911c178ec96398caa7d9eb3dc540f07613c819b38722a697eaccc" +checksum = "0eeaa28a4c7a8c574874e090c2a731ecc7b81595911fee425b552c799a20abbb" dependencies = [ "arrayvec 0.5.2", "asynchronous-codec", @@ -1545,8 +1558,9 @@ dependencies = [ "prost", "prost-build", "rand 0.7.3", - "sha2", + "sha2 0.10.1", "smallvec", + "thiserror", "uint", "unsigned-varint", "void", @@ -1554,9 +1568,9 @@ dependencies = [ [[package]] name = "libp2p-mdns" -version = "0.33.0" +version = "0.34.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13ea6cb29b2be3317a483f5687cdf4ea387e87331731e53c8a2c9feae7c97cac" +checksum = "1d5904049ad1fee7f2c2c792be892f3dde8ff5c21213d55702a35e777311326f" dependencies = [ "async-io", "data-encoding", @@ -1575,24 +1589,25 @@ dependencies = [ [[package]] name = "libp2p-metrics" -version = "0.2.0" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d59f3be49edeecff13ef0d0dc28295ba4a33910611715f04236325d08e4119e0" +checksum = "0791098ddec13b0c2f9ed37a29175f7c712ce8804ebaba7cbd8bddbc83120190" dependencies = [ "libp2p-core", "libp2p-gossipsub", "libp2p-identify", "libp2p-kad", "libp2p-ping", + "libp2p-relay", "libp2p-swarm", "open-metrics-client", ] [[package]] name = "libp2p-mplex" -version = "0.30.0" +version = "0.31.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f2cd64ef597f40e14bfce0497f50ecb63dd6d201c61796daeb4227078834fbf" +checksum = "49d470ee73a74340e429fa278469ed274a648738e3fb8de2e8d113482441732f" dependencies = [ "asynchronous-codec", "bytes", @@ -1600,7 +1615,7 @@ dependencies = [ "libp2p-core", "log", "nohash-hasher", - "parking_lot", + "parking_lot 0.11.2", "rand 0.7.3", "smallvec", "unsigned-varint", @@ -1608,9 +1623,9 @@ dependencies = [ [[package]] name = "libp2p-noise" -version = "0.33.0" +version = "0.34.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8772c7a99088221bb7ca9c5c0574bf55046a7ab4c319f3619b275f28c8fb87a" +checksum = "3676dc2df10a7f4f6a80fbeaf2ce4168a0ca6567273e3105b21fa4c877be9017" dependencies = [ "bytes", "curve25519-dalek", @@ -1621,7 +1636,7 @@ dependencies = [ "prost", "prost-build", "rand 0.8.4", - "sha2", + "sha2 0.10.1", "snow", "static_assertions", "x25519-dalek", @@ -1630,9 +1645,9 @@ dependencies = [ [[package]] name = "libp2p-ping" -version = "0.32.0" +version = "0.33.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d210cc0774142575a6a95f2c3590f9009cb838652cd295110a12a5d032ac07e0" +checksum = "d384b30135f122a59bf0d186647ad307da0878a9563232cb382d9dbded6a393e" dependencies = [ "futures", "futures-timer", @@ -1646,9 +1661,9 @@ dependencies = [ [[package]] name = "libp2p-plaintext" -version = "0.30.0" +version = "0.31.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5fba1a6ff33e4a274c89a3b1d78b9f34f32af13265cc5c46c16938262d4e945a" +checksum = "83203abb14ae77de42c49be8dbed7ea8dfb83e76773226aa664a96e6c5e18c5d" dependencies = [ "asynchronous-codec", "bytes", @@ -1677,12 +1692,13 @@ dependencies = [ [[package]] name = "libp2p-relay" -version = "0.5.0" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "352001594ebc7538538c5439e6bf8348995ebf28b1b042d8193532e90bc77aee" +checksum = "adb41d0408839f0975af3e5820bdc3ceea308a7282785d7ca77d28ea33dbb62a" dependencies = [ "asynchronous-codec", "bytes", + "either", "futures", "futures-timer", "instant", @@ -1692,17 +1708,19 @@ dependencies = [ "pin-project 1.0.10", "prost", "prost-build", - "rand 0.7.3", + "rand 0.8.4", "smallvec", + "static_assertions", + "thiserror", "unsigned-varint", "void", ] [[package]] name = "libp2p-rendezvous" -version = "0.2.0" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "921bc44c31225d42ac282e0e5a2f5311e4c50906a9e02d861fe8107a9396be49" +checksum = "ec166a822f4167929c8e1673c05106f7c86a42b8e9e917b569e1d86f06b9d8b5" dependencies = [ "asynchronous-codec", "bimap", @@ -1715,7 +1733,7 @@ dependencies = [ "prost", "prost-build", "rand 0.8.4", - "sha2", + "sha2 0.10.1", "thiserror", "unsigned-varint", "void", @@ -1723,9 +1741,9 @@ dependencies = [ [[package]] name = "libp2p-request-response" -version = "0.14.1" +version = "0.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ddfda221e6fea477db4fbe6f566cfd3e0850abb97d6249b8fcb731cb94cc946b" +checksum = "36194499f5b03d66d56badbed430d93bf1bfd9cec80311e03280de130fbe3d5e" dependencies = [ "async-trait", "bytes", @@ -1734,7 +1752,6 @@ dependencies = [ "libp2p-core", "libp2p-swarm", "log", - "lru", "rand 0.7.3", "smallvec", "unsigned-varint", @@ -1742,9 +1759,9 @@ dependencies = [ [[package]] name = "libp2p-swarm" -version = "0.32.0" +version = "0.33.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb84d40627cd109bbbf43da9269d4ef75903f42356c88d98b2b55c47c430c792" +checksum = "db8ae0811c7a05b6edc6684eb5cc69b055cbb715ad780e6b97872d90308503c1" dependencies = [ "either", "futures", @@ -1759,9 +1776,9 @@ dependencies = [ [[package]] name = "libp2p-swarm-derive" -version = "0.26.0" +version = "0.26.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7dd93a7dad9b61c39797572e4fb4fdba8415d6348b4e745b3d4cb008f84331ab" +checksum = "33b4d0acd47739fe0b570728d8d11bbb535050d84c0cf05d6477a4891fceae10" dependencies = [ "quote", "syn", @@ -1769,9 +1786,9 @@ dependencies = [ [[package]] name = "libp2p-tcp" -version = "0.30.0" +version = "0.31.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7399c5b6361ef525d41c11fcf51635724f832baf5819b30d3d873eabb4fbae4b" +checksum = "52042e8796c5b58d0415bceb1bcb1bcca28b222339978e52b1a0305800bb5199" dependencies = [ "async-io", "futures", @@ -1786,9 +1803,9 @@ dependencies = [ [[package]] name = "libp2p-uds" -version = "0.30.0" +version = "0.31.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8b7563e46218165dfd60f64b96f7ce84590d75f53ecbdc74a7dd01450dc5973" +checksum = "098f90cb3a0273a830d2595ca7f4de6ca848530ee42324f5c660e2b8955211df" dependencies = [ "async-std", "futures", @@ -1798,9 +1815,9 @@ dependencies = [ [[package]] name = "libp2p-wasm-ext" -version = "0.30.0" +version = "0.31.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1008a302b73c5020251f9708c653f5ed08368e530e247cc9cd2f109ff30042cf" +checksum = "be0e8a3817fc156752f6695e57630a9bceb6ae92e9b9f0a161552702fd76ad45" dependencies = [ "futures", "js-sys", @@ -1812,9 +1829,9 @@ dependencies = [ [[package]] name = "libp2p-websocket" -version = "0.32.0" +version = "0.33.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa92005fbd67695715c821e1acfe4d7be9fd2d88738574e93d645c49ec2831c8" +checksum = "83d788da0ab952632d6ead2486baf38a98db92907d4bc5d0f324af0d0fab803d" dependencies = [ "either", "futures", @@ -1830,13 +1847,13 @@ dependencies = [ [[package]] name = "libp2p-yamux" -version = "0.34.0" +version = "0.35.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e7362abb8867d7187e7e93df17f460d554c997fc5c8ac57dc1259057f6889af" +checksum = "053d13ce0670d29f9c5a974cf371e6cc4d2d864da1c72bf6870ac5d5e45e2036" dependencies = [ "futures", "libp2p-core", - "parking_lot", + "parking_lot 0.11.2", "thiserror", "yamux", ] @@ -1856,7 +1873,7 @@ dependencies = [ "libsecp256k1-gen-genmult", "rand 0.8.4", "serde", - "sha2", + "sha2 0.9.9", "typenum", ] @@ -1908,9 +1925,9 @@ checksum = "7fb9b38af92608140b86b693604b9ffcc5824240a484d1ecd4795bacb2fe88f3" [[package]] name = "lock_api" -version = "0.4.5" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "712a4d093c9976e24e7dbca41db895dabcbac38eb5f4045393d17a95bdfb1109" +checksum = "88943dd7ef4a2e5a4bfa2753aaab3013e34ce2533d1996fb18ef591e315e2b3b" dependencies = [ "scopeguard", ] @@ -1970,6 +1987,15 @@ version = "2.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "308cc39be01b73d0d18f82a0e7b2a3df85245f84af96fdddc5d202d27e47b86a" +[[package]] +name = "memoffset" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5aa361d4faea93603064a027415f07bd8e1d5c88c9fbf68bf56a285428fd79ce" +dependencies = [ + "autocfg", +] + [[package]] name = "miniz_oxide" version = "0.4.4" @@ -2029,7 +2055,7 @@ dependencies = [ "digest 0.9.0", "generic-array", "multihash-derive", - "sha2", + "sha2 0.9.9", "unsigned-varint", ] @@ -2055,9 +2081,9 @@ checksum = "e5ce46fe64a9d73be07dcbe690a38ce1b293be448fd8ce1e6c1b8062c9f72c6a" [[package]] name = "multistream-select" -version = "0.10.4" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56a336acba8bc87c8876f6425407dbbe6c417bf478b22015f8fb0994ef3bc0ab" +checksum = "363a84be6453a70e63513660f4894ef815daf88e3356bffcda9ca27d810ce83b" dependencies = [ "bytes", "futures", @@ -2076,6 +2102,71 @@ dependencies = [ "getrandom 0.2.3", ] +[[package]] +name = "netlink-packet-core" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8349128e95f5dabcb8a18587ad06b3ca7993e90c0c360b4a2abac0313ebce727" +dependencies = [ + "anyhow", + "byteorder", + "libc", + "netlink-packet-utils", +] + +[[package]] +name = "netlink-packet-route" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9fb5d54077de7c0904111e1d19b661b8cfccbc23d9ce5b6dbcc7362721e6e552" +dependencies = [ + "anyhow", + "bitflags", + "byteorder", + "libc", + "netlink-packet-core", + "netlink-packet-utils", +] + +[[package]] +name = "netlink-packet-utils" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0a008a56eceb0cab06739c7f37f15bda27f1147a14d0e7136e8c913b94f1441d" +dependencies = [ + "anyhow", + "byteorder", + "paste", + "thiserror", +] + +[[package]] +name = "netlink-proto" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "073885f70c1d54fdc6148075e8e38a5e8a28179f59de5bd0fc6277cae4fec95a" +dependencies = [ + "bytes", + "futures", + "log", + "netlink-packet-core", + "netlink-sys", + "tokio", +] + +[[package]] +name = "netlink-sys" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed51a4602bb956eefef0ebc15f478bf9732fa3cc706e0a37112e654f41c5b92c" +dependencies = [ + "async-io", + "bytes", + "futures", + "libc", + "log", +] + [[package]] name = "networking-demo" version = "0.0.0" @@ -2085,12 +2176,12 @@ dependencies = [ "bincode", "blake3", "color-eyre", - "crossterm 0.22.1", + "crossterm 0.23.0", "derive_builder", "flume", "futures", "libp2p", - "parking_lot", + "parking_lot 0.12.0", "rand 0.8.4", "serde", "snafu", @@ -2101,6 +2192,19 @@ dependencies = [ "tui", ] +[[package]] +name = "nix" +version = "0.22.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e4916f159ed8e5de0082076562152a76b7a1f64a01fd9d1e0fea002c37624faf" +dependencies = [ + "bitflags", + "cc", + "cfg-if", + "libc", + "memoffset", +] + [[package]] name = "nohash-hasher" version = "0.2.0" @@ -2149,12 +2253,12 @@ checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" [[package]] name = "open-metrics-client" -version = "0.12.0" +version = "0.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7337d80c23c2d8b1349563981bc4fb531220733743ba8115454a67b181173f0d" +checksum = "f85842b073145726190373213c63f852020fb884c841a3a1f390637267a2fb8c" dependencies = [ "dtoa", - "itoa 0.4.8", + "itoa", "open-metrics-client-derive-text-encode", "owning_ref", ] @@ -2205,7 +2309,17 @@ checksum = "7d17b78036a60663b797adeaee46f5c9dfebb86948d1255007a1d6be0271ff99" dependencies = [ "instant", "lock_api", - "parking_lot_core", + "parking_lot_core 0.8.5", +] + +[[package]] +name = "parking_lot" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87f5ec2493a61ac0506c0f4199f99070cbe83857b0337006a30f3e6719b8ef58" +dependencies = [ + "lock_api", + "parking_lot_core 0.9.1", ] [[package]] @@ -2222,6 +2336,25 @@ dependencies = [ "winapi", ] +[[package]] +name = "parking_lot_core" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "28141e0cc4143da2443301914478dc976a61ffdb3f043058310c70df2fed8954" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall", + "smallvec", + "windows-sys", +] + +[[package]] +name = "paste" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0744126afe1a6dd7f394cb50a716dbe086cb06e255e53d8d0185d82828358fb5" + [[package]] name = "percent-encoding" version = "2.1.0" @@ -2625,6 +2758,21 @@ dependencies = [ "winapi", ] +[[package]] +name = "rtnetlink" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa584f57f271d3fbd9f59503b090a0410a531c8cc272143669bf136c62ef409d" +dependencies = [ + "async-global-executor", + "futures", + "log", + "netlink-packet-route", + "netlink-proto", + "nix", + "thiserror", +] + [[package]] name = "rustc-demangle" version = "0.1.21" @@ -2714,18 +2862,18 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.133" +version = "1.0.136" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97565067517b60e2d1ea8b268e59ce036de907ac523ad83a0475da04e818989a" +checksum = "ce31e24b01e1e524df96f1c2fdd054405f8d7376249a5110886fb4b658484789" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.133" +version = "1.0.136" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed201699328568d8d08208fdd080e3ff594e6c422e438b6705905da01005d537" +checksum = "08597e7152fcd306f41838ed3e37be9eaeed2b61c42e2117266a554fab4662f9" dependencies = [ "proc-macro2", "quote", @@ -2738,7 +2886,7 @@ version = "1.0.74" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ee2bb9cd061c5865d345bb02ca49fcef1391741b672b54a0bf7b679badec3142" dependencies = [ - "itoa 1.0.1", + "itoa", "ryu", "serde", ] @@ -2769,6 +2917,17 @@ dependencies = [ "opaque-debug", ] +[[package]] +name = "sha2" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "99c3bd8169c58782adad9290a9af5939994036b76187f7b4f0e6de91dbbfc0ec" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest 0.10.1", +] + [[package]] name = "sha3" version = "0.9.1" @@ -2873,7 +3032,7 @@ dependencies = [ "rand_core 0.6.3", "ring", "rustc_version", - "sha2", + "sha2 0.9.9", "subtle", "x25519-dalek", ] @@ -2956,9 +3115,9 @@ checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" [[package]] name = "structopt" -version = "0.3.25" +version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "40b9788f4202aa75c240ecc9c15c65185e6a39ccdeb0fd5d008b98825464c87c" +checksum = "0c6b5c64445ba8094a6ab0c3cd2ad323e07171012d9c98b0b15651daf1787a10" dependencies = [ "clap", "lazy_static", @@ -3007,6 +3166,27 @@ dependencies = [ "unicode-xid", ] +[[package]] +name = "system-configuration" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d75182f12f490e953596550b65ee31bda7c8e043d9386174b353bda50838c3fd" +dependencies = [ + "bitflags", + "core-foundation", + "system-configuration-sys", +] + +[[package]] +name = "system-configuration-sys" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a75fb188eb626b924683e3b95e3a48e63551fcfb51949de2f06a9d91dbee93c9" +dependencies = [ + "core-foundation-sys", + "libc", +] + [[package]] name = "tempfile" version = "3.3.0" @@ -3052,9 +3232,9 @@ dependencies = [ [[package]] name = "thread_local" -version = "1.1.3" +version = "1.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8018d24e04c95ac8790716a5987d0fec4f8b27249ffa0f7d33f1369bdfb88cbd" +checksum = "5516c27b78311c50bf42c071425c560ac799b11c30b31f87e3081965fe5e0180" dependencies = [ "once_cell", ] @@ -3074,6 +3254,17 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c" +[[package]] +name = "tokio" +version = "1.16.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c27a64b625de6d309e8c57716ba93021dccf1b3b5c97edd6d3dd2d2135afc0a" +dependencies = [ + "bytes", + "memchr", + "pin-project-lite 0.2.8", +] + [[package]] name = "toml" version = "0.5.8" @@ -3085,9 +3276,9 @@ dependencies = [ [[package]] name = "tracing" -version = "0.1.29" +version = "0.1.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "375a639232caf30edfc78e8d89b2d4c375515393e7af7e16f01cd96917fb2105" +checksum = "2d8d93354fe2a8e50d5953f5ae2e47a3fc2ef03292e7ea46e3cc38f549525fb9" dependencies = [ "cfg-if", "pin-project-lite 0.2.8", @@ -3097,9 +3288,9 @@ dependencies = [ [[package]] name = "tracing-attributes" -version = "0.1.18" +version = "0.1.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4f480b8f81512e825f337ad51e94c1eb5d3bbdf2b363dcd01e2b19a9ffe3f8e" +checksum = "8276d9a4a3a558d7b7ad5303ad50b53d58264641b82914b7ada36bd762e7a716" dependencies = [ "proc-macro2", "quote", @@ -3108,11 +3299,12 @@ dependencies = [ [[package]] name = "tracing-core" -version = "0.1.21" +version = "0.1.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f4ed65637b8390770814083d20756f87bfa2c21bf2f110babdc5438351746e4" +checksum = "03cfcb51380632a72d3111cb8d3447a8d908e577d31beeac006f836383d29a23" dependencies = [ "lazy_static", + "valuable", ] [[package]] @@ -3138,9 +3330,9 @@ dependencies = [ [[package]] name = "tracing-serde" -version = "0.1.2" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb65ea441fbb84f9f6748fd496cf7f63ec9af5bca94dd86456978d055e8eb28b" +checksum = "bc6b213177105856957181934e4920de57730fc69bf42c37ee5bb664d406d9e1" dependencies = [ "serde", "tracing-core", @@ -3148,9 +3340,9 @@ dependencies = [ [[package]] name = "tracing-subscriber" -version = "0.3.5" +version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d81bfa81424cc98cb034b837c985b7a290f592e5b4322f353f94a0ab0f9f594" +checksum = "74786ce43333fcf51efe947aed9718fbe46d5c7328ec3f1029e818083966d9aa" dependencies = [ "ansi_term", "lazy_static", @@ -3203,7 +3395,7 @@ dependencies = [ "lazy_static", "log", "lru-cache", - "parking_lot", + "parking_lot 0.11.2", "resolv-conf", "smallvec", "thiserror", @@ -3212,13 +3404,13 @@ dependencies = [ [[package]] name = "tui" -version = "0.16.0" +version = "0.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39c8ce4e27049eed97cfa363a5048b09d995e209994634a0efc26a14ab6c0c23" +checksum = "23ed0a32c88b039b73f1b6c5acbd0554bfa5b6be94467375fd947c4de3a02271" dependencies = [ "bitflags", "cassowary", - "crossterm 0.20.0", + "crossterm 0.22.1", "unicode-segmentation", "unicode-width", ] @@ -3320,6 +3512,12 @@ dependencies = [ "percent-encoding", ] +[[package]] +name = "valuable" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d" + [[package]] name = "value-bag" version = "1.0.0-alpha.8" @@ -3515,6 +3713,92 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" +[[package]] +name = "windows" +version = "0.29.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aac7fef12f4b59cd0a29339406cc9203ab44e440ddff6b3f5a41455349fa9cf3" +dependencies = [ + "windows_aarch64_msvc 0.29.0", + "windows_i686_gnu 0.29.0", + "windows_i686_msvc 0.29.0", + "windows_x86_64_gnu 0.29.0", + "windows_x86_64_msvc 0.29.0", +] + +[[package]] +name = "windows-sys" +version = "0.32.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3df6e476185f92a12c072be4a189a0210dcdcf512a1891d6dff9edb874deadc6" +dependencies = [ + "windows_aarch64_msvc 0.32.0", + "windows_i686_gnu 0.32.0", + "windows_i686_msvc 0.32.0", + "windows_x86_64_gnu 0.32.0", + "windows_x86_64_msvc 0.32.0", +] + +[[package]] +name = "windows_aarch64_msvc" +version = "0.29.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3d027175d00b01e0cbeb97d6ab6ebe03b12330a35786cbaca5252b1c4bf5d9b" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.32.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8e92753b1c443191654ec532f14c199742964a061be25d77d7a96f09db20bf5" + +[[package]] +name = "windows_i686_gnu" +version = "0.29.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8793f59f7b8e8b01eda1a652b2697d87b93097198ae85f823b969ca5b89bba58" + +[[package]] +name = "windows_i686_gnu" +version = "0.32.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a711c68811799e017b6038e0922cb27a5e2f43a2ddb609fe0b6f3eeda9de615" + +[[package]] +name = "windows_i686_msvc" +version = "0.29.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8602f6c418b67024be2996c512f5f995de3ba417f4c75af68401ab8756796ae4" + +[[package]] +name = "windows_i686_msvc" +version = "0.32.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "146c11bb1a02615db74680b32a68e2d61f553cc24c4eb5b4ca10311740e44172" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.29.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3d615f419543e0bd7d2b3323af0d86ff19cbc4f816e6453f36a2c2ce889c354" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.32.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c912b12f7454c6620635bbff3450962753834be2a594819bd5e945af18ec64bc" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.29.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "11d95421d9ed3672c280884da53201a5c46b7b2765ca6faf34b0d71cf34a3561" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.32.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "504a2476202769977a040c6364301a3f65d0cc9e3fb08600b2bda150a0488316" + [[package]] name = "winreg" version = "0.6.2" @@ -3537,14 +3821,14 @@ dependencies = [ [[package]] name = "yamux" -version = "0.9.0" +version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7d9028f208dd5e63c614be69f115c1b53cacc1111437d4c765185856666c107" +checksum = "29d4c1dd079043fe673e79fe3c3a260ae2d2fb413f1062cae9e062748df0df03" dependencies = [ "futures", "log", "nohash-hasher", - "parking_lot", + "parking_lot 0.11.2", "rand 0.8.4", "static_assertions", ] diff --git a/libp2p-networking/Cargo.toml b/libp2p-networking/Cargo.toml index 7f9ecd65fe..8ba6dffff0 100644 --- a/libp2p-networking/Cargo.toml +++ b/libp2p-networking/Cargo.toml @@ -8,20 +8,20 @@ edition = "2021" [dependencies] async-std = { version = "1.10.0", features = ["attributes", "unstable"] } bincode = "1.3.3" -blake3 = "1.3.0" +blake3 = "1.3.1" color-eyre = "0.6.0" -crossterm = { version = "0.22.1", features = ["event-stream"] } +crossterm = { version = "0.23.0", features = ["event-stream"] } flume = "0.10.10" -futures = "0.3.19" -libp2p = "0.41.1" -parking_lot = "0.11.2" -serde = { version = "1.0.133", features = ["derive"] } +futures = "0.3.21" +libp2p = "0.42.2" +parking_lot = "0.12.0" +serde = { version = "1.0.136", features = ["derive"] } snafu = "0.7.0" -structopt = "0.3.25" -tracing = "0.1.29" +structopt = "0.3.26" +tracing = "0.1.30" tracing-error = "0.2.0" -tracing-subscriber = { version = "0.3.5", features = ["env-filter", "json"] } -tui = { version = "0.16.0", features = ["crossterm"], default-features = false } +tracing-subscriber = { version = "0.3.8", features = ["env-filter", "json"] } +tui = { version = "0.17.0", features = ["crossterm"], default-features = false } rand = "0.8.4" async-trait = "0.1.52" derive_builder = "0.10.2" diff --git a/libp2p-networking/flake.nix b/libp2p-networking/flake.nix index 99d658e739..5760a54e54 100644 --- a/libp2p-networking/flake.nix +++ b/libp2p-networking/flake.nix @@ -83,7 +83,7 @@ inputsFrom = builtins.attrValues self.packages.${system}; buildInputs = with pkgs; [ cargo-audit nixpkgs-fmt git-chglog fenix.packages.${system}.rust-analyzer fenixPackage protobuf] - ++ lib.optionals stdenv.isDarwin [ darwin.apple_sdk.frameworks.Security ]; + ++ lib.optionals stdenv.isDarwin [ darwin.apple_sdk.frameworks.Security pkgs.libiconv darwin.apple_sdk.frameworks.SystemConfiguration ]; }; }); } diff --git a/libp2p-networking/src/network_node.rs b/libp2p-networking/src/network_node.rs index c4643cb3fb..f07dd071ed 100644 --- a/libp2p-networking/src/network_node.rs +++ b/libp2p-networking/src/network_node.rs @@ -718,7 +718,7 @@ impl NetworkNode { peer_id, endpoint, .. } => { match endpoint { - ConnectedPoint::Dialer { address } => { + ConnectedPoint::Dialer { address, .. } => { self.swarm .behaviour_mut() .kadem From 48265c67a723ff24512d01b2e676b941ecb21880 Mon Sep 17 00:00:00 2001 From: Ancients Date: Thu, 10 Feb 2022 10:44:57 -0700 Subject: [PATCH 070/107] Enable CI --- .../.github/actions-rs/grcov.yml | 4 ++ libp2p-networking/.github/dependabot.yml | 11 ++++ libp2p-networking/.github/workflows/build.yml | 53 +++++++++++++++++++ .../.github/workflows/coverage.yml | 52 ++++++++++++++++++ 4 files changed, 120 insertions(+) create mode 100644 libp2p-networking/.github/actions-rs/grcov.yml create mode 100644 libp2p-networking/.github/dependabot.yml create mode 100644 libp2p-networking/.github/workflows/build.yml create mode 100644 libp2p-networking/.github/workflows/coverage.yml diff --git a/libp2p-networking/.github/actions-rs/grcov.yml b/libp2p-networking/.github/actions-rs/grcov.yml new file mode 100644 index 0000000000..d64c9c316f --- /dev/null +++ b/libp2p-networking/.github/actions-rs/grcov.yml @@ -0,0 +1,4 @@ +output-type: lcov +ignore: + - "/*" + - "../*" \ No newline at end of file diff --git a/libp2p-networking/.github/dependabot.yml b/libp2p-networking/.github/dependabot.yml new file mode 100644 index 0000000000..d69e05329a --- /dev/null +++ b/libp2p-networking/.github/dependabot.yml @@ -0,0 +1,11 @@ +version: 2 +updates: + - package-ecosystem: "github-actions" + directory: "/" + schedule: + interval: "daily" + + - package-ecosystem: "cargo" + directory: "/" + schedule: + interval: "daily" diff --git a/libp2p-networking/.github/workflows/build.yml b/libp2p-networking/.github/workflows/build.yml new file mode 100644 index 0000000000..29e335db5a --- /dev/null +++ b/libp2p-networking/.github/workflows/build.yml @@ -0,0 +1,53 @@ +name: Build + +on: + push: + branches: + - main + pull_request: + branches: + - main + schedule: + - cron: '0 0 * * 1' + workflow_dispatch: + +jobs: + build: + runs-on: ubuntu-latest + steps: + - name: Cancel Outdated Builds + uses: styfle/cancel-workflow-action@0.9.1 + with: + all_but_latest: true + access_token: ${{ github.token }} + + - name: Checkout Repository + uses: actions/checkout@v2 + + - name: Install stable toolchain + uses: actions-rs/toolchain@v1 + with: + profile: default + toolchain: stable + override: true + default: true + components: rustfmt, clippy + + - name: Enable Rust Caching + uses: Swatinem/rust-cache@v1 + + - name: Clippy + uses: actions-rs/clippy-check@v1 + with: + token: ${{ github.token }} + + - name: Audit + uses: actions-rs/audit-check@v1 + with: + token: ${{ github.token }} + + - name: Cargo Build + run: cargo build + + - name: Cargo Test + run: cargo test --verbose -- -Zunstable-options --report-time diff --git a/libp2p-networking/.github/workflows/coverage.yml b/libp2p-networking/.github/workflows/coverage.yml new file mode 100644 index 0000000000..fd86ec48f7 --- /dev/null +++ b/libp2p-networking/.github/workflows/coverage.yml @@ -0,0 +1,52 @@ +name: Code Coverage + +on: + push: + branches: + - main + pull_request: + branches: + - main + schedule: + - cron: '0 0 * * 1' + workflow_dispatch: + +jobs: + code-coverage: + runs-on: ubuntu-latest + steps: + - name: Checkout Repository + uses: actions/checkout@v2 + + - name: Install Rust Nightly Toolchain + uses: actions-rs/toolchain@v1 + with: + toolchain: nightly + override: true + + - name: Run Cargo Test With Coverage Options + uses: actions-rs/cargo@v1 + with: + command: test + args: --all-features --no-fail-fast + env: + CARGO_INCREMENTAL: '0' + RUSTFLAGS: '-Zprofile -Ccodegen-units=1 -Cinline-threshold=0 -Clink-dead-code -Coverflow-checks=off -Cpanic=abort -Zpanic_abort_tests' + RUSTDOCFLAGS: '-Zprofile -Ccodegen-units=1 -Cinline-threshold=0 -Clink-dead-code -Coverflow-checks=off -Cpanic=abort -Zpanic_abort_tests' + + - name: Install grcov + run: | + wget -O grcov.tar.gz https://github.com/mozilla/grcov/releases/download/v0.8.2/grcov-linux-x86_64.tar.bz2 + tar -xvf grcov.tar.gz + sudo mv -v grcov /home/runner/.cargo/bin/ + rm -rv grcov.tar.gz + + - name: Run Coverage Tool (grcov) + uses: actions-rs/grcov@v0.1 + id: coverage + + - name: Coveralls upload + uses: coverallsapp/github-action@master + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + path-to-lcov: ${{ steps.coverage.outputs.report }} From e1295bf2daa5f61191efcedc5c7b09ea56c9d3df Mon Sep 17 00:00:00 2001 From: Justin Restivo Date: Fri, 11 Feb 2022 13:24:20 -0500 Subject: [PATCH 071/107] fix: change message sending s.t. tests pass --- libp2p-networking/examples/counter.rs | 4 - libp2p-networking/flake.lock | 12 +- libp2p-networking/flake.nix | 2 +- libp2p-networking/src/direct_message.rs | 2 +- libp2p-networking/src/network_node.rs | 278 ++++++++++--------- libp2p-networking/src/network_node_handle.rs | 104 +------ libp2p-networking/src/ui.rs | 8 +- libp2p-networking/tests/common/mod.rs | 175 +++++++++++- libp2p-networking/tests/counter.rs | 136 +++++---- 9 files changed, 419 insertions(+), 302 deletions(-) delete mode 100644 libp2p-networking/examples/counter.rs diff --git a/libp2p-networking/examples/counter.rs b/libp2p-networking/examples/counter.rs deleted file mode 100644 index 4804093a64..0000000000 --- a/libp2p-networking/examples/counter.rs +++ /dev/null @@ -1,4 +0,0 @@ -#[async_std::main] -async fn main() { - todo!() -} diff --git a/libp2p-networking/flake.lock b/libp2p-networking/flake.lock index 40258af6db..dab1992d01 100644 --- a/libp2p-networking/flake.lock +++ b/libp2p-networking/flake.lock @@ -25,11 +25,11 @@ "rust-analyzer-src": "rust-analyzer-src" }, "locked": { - "lastModified": 1643610217, - "narHash": "sha256-3cFZt9Eyz70s1CNYO3wJeUDgLUC9tC4s5hNpLtX3FQY=", + "lastModified": 1644301403, + "narHash": "sha256-taOPTgB1EFlj7oyG40mplff45QYMJeQ0/Pm4lLuBZ+A=", "owner": "nix-community", "repo": "fenix", - "rev": "bd91b6fddf7fdf90ad9924339fcb40f008f57447", + "rev": "035306bc8de70b8ed7d79f1fd15d3e2b32ef1dde", "type": "github" }, "original": { @@ -82,11 +82,11 @@ "rust-analyzer-src": { "flake": false, "locked": { - "lastModified": 1643580505, - "narHash": "sha256-6+d/x7ZIyvkPLdn7ziXuPyKfxt/7z5PCWs7B960DFqk=", + "lastModified": 1644220273, + "narHash": "sha256-6zg648bgcZkcEeLjTXo+ESCR8DVgF9V4Hw7zjiv8OBY=", "owner": "rust-analyzer", "repo": "rust-analyzer", - "rev": "fd3942eb620e37a4e4bfdd587d8a2893ccf6fea0", + "rev": "9b1978a3ed405c2a5ec34703914ec1878b599e14", "type": "github" }, "original": { diff --git a/libp2p-networking/flake.nix b/libp2p-networking/flake.nix index 5760a54e54..9bd69fe666 100644 --- a/libp2p-networking/flake.nix +++ b/libp2p-networking/flake.nix @@ -80,7 +80,7 @@ devShell = pkgs.mkShell { inherit shellHook; - inputsFrom = builtins.attrValues self.packages.${system}; + # inputsFrom = builtins.attrValues self.packages.${system}; buildInputs = with pkgs; [ cargo-audit nixpkgs-fmt git-chglog fenix.packages.${system}.rust-analyzer fenixPackage protobuf] ++ lib.optionals stdenv.isDarwin [ darwin.apple_sdk.frameworks.Security pkgs.libiconv darwin.apple_sdk.frameworks.SystemConfiguration ]; diff --git a/libp2p-networking/src/direct_message.rs b/libp2p-networking/src/direct_message.rs index 85f896e5df..398fe6cca4 100644 --- a/libp2p-networking/src/direct_message.rs +++ b/libp2p-networking/src/direct_message.rs @@ -29,7 +29,7 @@ impl ProtocolName for DirectMessageProtocol { } } -const MAX_MSG_SIZE: usize = 1_000_000; +const MAX_MSG_SIZE: usize = 500; #[async_trait] impl RequestResponseCodec for DirectMessageCodec { diff --git a/libp2p-networking/src/network_node.rs b/libp2p-networking/src/network_node.rs index f07dd071ed..d29e785b1f 100644 --- a/libp2p-networking/src/network_node.rs +++ b/libp2p-networking/src/network_node.rs @@ -1,7 +1,8 @@ use crate::direct_message::{DirectMessageCodec, DirectMessageRequest, DirectMessageResponse}; use async_std::task::{sleep, spawn}; -use libp2p::ping::{Failure, Ping, PingConfig, PingEvent}; +use libp2p::request_response::RequestId; use rand::{seq::IteratorRandom, thread_rng}; +use std::collections::HashMap; use std::fmt::Debug; use std::{ collections::HashSet, @@ -58,41 +59,49 @@ pub struct NetworkDef { /// NOTE gossipsub works ONLY for sharing messsages right now /// in the future it may be able to do peer discovery and routing /// <`https://github.com/libp2p/rust-libp2p/issues/2398> - pub gossipsub: Gossipsub, + gossipsub: Gossipsub, + /// purpose: peer routing - pub kadem: Kademlia, + kadem: Kademlia, + /// purpose: peer discovery - pub identify: Identify, + identify: Identify, + /// purpose: directly messaging peer - pub request_response: RequestResponse, + request_response: RequestResponse, + /// if the node has been bootstrapped into the kademlia network #[behaviour(ignore)] - pub bootstrap_in_progress: bool, + bootstrap_state: BootstrapState, // TODO separate out into ConnectionData struct /// set of connected peers #[behaviour(ignore)] - pub connected_peers: HashSet, + connected_peers: HashSet, // TODO replace this with a set of queryids /// set of currently connecting peers #[behaviour(ignore)] - pub connecting_peers: HashSet, + connecting_peers: HashSet, /// set of peers that were at one point connected #[behaviour(ignore)] - pub known_peers: HashSet, + known_peers: HashSet, /// set of events to send to UI #[behaviour(ignore)] - pub client_event_queue: Vec, + client_event_queue: Vec, /// whether or not to prune nodes #[behaviour(ignore)] - pub pruning_enabled: bool, - /// ping event. Keep the connection alive! - pub ping: Ping, + pruning_enabled: bool, + /// track in progress request-response + #[behaviour(ignore)] + in_progress_rr: HashMap, PeerId)>, + /// track gossip messages that failed to send and we should send later on + #[behaviour(ignore)] + in_progress_gossip: Vec<(Topic, Vec)>, } impl Debug for NetworkDef { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { f.debug_struct("NetworkDef") - .field("bootstrap", &self.bootstrap_in_progress) + .field("bootstrap", &self.bootstrap_state) .field("connected_peers", &self.connected_peers) .field("connecting_peers", &self.connecting_peers) .field("known_peers", &self.known_peers) @@ -100,6 +109,13 @@ impl Debug for NetworkDef { } } +#[derive(Copy, Clone, Debug, PartialEq, Eq)] +enum BootstrapState { + NotStarted, + Started, + Finished, +} + /// metadata about connections #[derive(Default, Debug, Clone)] pub struct ConnectionData { @@ -118,6 +134,17 @@ impl NetworkDef { _: &mut impl PollParameters, ) -> Poll::ProtocolsHandler>> { + // TODO this should be separated out into a separate event + let mut num_sent = 0; + for (topic, contents) in self.in_progress_gossip.as_slice() { + let res = self.gossipsub.publish(topic.clone(), contents.clone()); + if res.is_err() { + break; + } + num_sent += 1; + } + self.in_progress_gossip = self.in_progress_gossip[num_sent..].into(); + // push events that must be relayed back to client onto queue // to be consumed by client event handler if !self.client_event_queue.is_empty() { @@ -130,15 +157,8 @@ impl NetworkDef { } } -impl NetworkBehaviourEventProcess for NetworkDef { - fn inject_event(&mut self, event: PingEvent) { - info!(?event, "ping event recv-ed"); - } -} - impl NetworkBehaviourEventProcess for NetworkDef { fn inject_event(&mut self, event: GossipsubEvent) { - info!(?event, "gossipsub msg recv-ed"); if let GossipsubEvent::Message { message, .. } = event { self.client_event_queue .push(NetworkEvent::GossipMsg(message.data)); @@ -148,22 +168,20 @@ impl NetworkBehaviourEventProcess for NetworkDef { impl NetworkBehaviourEventProcess for NetworkDef { fn inject_event(&mut self, event: KademliaEvent) { - info!(?event, "kadem msg recv-ed"); + info!(?event, "kadem event"); match event { KademliaEvent::OutboundQueryCompleted { result, .. } => { match result { - // FIXME rebootstrap or fail in the failed - // bootstrap case QueryResult::Bootstrap(r) => { match r { Ok(_bootstrap) => { // we're bootstrapped // don't bootstrap again - self.bootstrap_in_progress = false; + self.bootstrap_state = BootstrapState::Started; } Err(_) => { - // try again - self.bootstrap_in_progress = true; + // bootstrap failed. try again + self.bootstrap_state = BootstrapState::NotStarted; } } } @@ -177,16 +195,7 @@ impl NetworkBehaviourEventProcess for NetworkDef { _ => {} } } - KademliaEvent::RoutingUpdated { - peer, addresses, .. - } => { - for address in addresses.iter() { - self.request_response.add_address(&peer, address.clone()); - } - // TODO try add_address to request_response. It looks like stale addresses are - // happening... - // NOTE the other reason this is failing might be because the requester is - // terminating requests + KademliaEvent::RoutingUpdated { peer, .. } => { self.known_peers.insert(peer); self.client_event_queue .push(NetworkEvent::UpdateKnownPeers(self.known_peers.clone())); @@ -201,7 +210,6 @@ impl NetworkBehaviourEventProcess for NetworkDef { if let IdentifyEvent::Received { peer_id, info, .. } = event { for addr in info.listen_addrs { self.kadem.add_address(&peer_id, addr.clone()); - self.request_response.add_address(&peer_id, addr.clone()); } self.known_peers.insert(peer_id); self.client_event_queue @@ -217,8 +225,22 @@ impl NetworkBehaviourEventProcess, ) { - if let RequestResponseEvent::Message { message, .. } = event { - match message { + match event { + RequestResponseEvent::InboundFailure { + peer, request_id, .. + } + | RequestResponseEvent::OutboundFailure { + peer, request_id, .. + } => { + if let Some((request, _)) = self.in_progress_rr.get(&request_id).cloned() { + let new_request = self + .request_response + .send_request(&peer, DirectMessageRequest(request.clone())); + self.in_progress_rr.remove(&request_id); + self.in_progress_rr.insert(new_request, (request, peer)); + } + } + RequestResponseEvent::Message { message, .. } => match message { RequestResponseMessage::Request { request: DirectMessageRequest(msg), channel, @@ -228,12 +250,16 @@ impl NetworkBehaviourEventProcess { + self.in_progress_rr.remove(&request_id); self.client_event_queue .push(NetworkEvent::DirectResponse(msg)); } + }, + e @ RequestResponseEvent::ResponseSent { .. } => { + info!(?e, " sending response"); } } } @@ -256,8 +282,6 @@ impl Default for NetworkNodeType { } } -// FIXME split this out into network config + swarm - /// Network definition pub struct NetworkNode { /// pub/private key from with peer_id is derived @@ -301,7 +325,7 @@ pub enum ClientRequest { /// kill the swarm Shutdown, /// broadcast a serialized message - GossipMsg(Topic, Vec, Sender>), + GossipMsg(Topic, Vec), /// send the peer id GetId(Sender), /// subscribe to a topic @@ -403,14 +427,13 @@ impl NetworkNode { #[instrument(skip(self))] pub async fn add_known_peers(&mut self, known_peers: &[(PeerId, Multiaddr)]) { for (peer_id, addr) in known_peers { - self.swarm - .behaviour_mut() - .kadem - .add_address(peer_id, addr.clone()); - self.swarm - .behaviour_mut() - .request_response - .add_address(peer_id, addr.clone()); + if *peer_id != self.peer_id { + // FIXME why can't I pattern match this? + self.swarm + .behaviour_mut() + .kadem + .add_address(peer_id, addr.clone()); + } self.swarm.behaviour_mut().known_peers.insert(*peer_id); } let new_peers = self.swarm.behaviour().known_peers.clone(); @@ -488,10 +511,6 @@ impl NetworkNode { RequestResponseConfig::default(), ); - let ping_config = PingConfig::new().with_keep_alive(true); - - let ping = Ping::new(ping_config); - let pruning_enabled = config.node_type == NetworkNodeType::Regular; let network = NetworkDef { @@ -499,13 +518,14 @@ impl NetworkNode { kadem, identify, request_response, - ping, connected_peers: HashSet::new(), connecting_peers: HashSet::new(), known_peers: HashSet::new(), client_event_queue: Vec::new(), - bootstrap_in_progress: false, + bootstrap_state: BootstrapState::NotStarted, pruning_enabled, + in_progress_rr: HashMap::new(), + in_progress_gossip: Vec::new(), }; Swarm::new(transport, network, peer_id) @@ -523,7 +543,7 @@ impl NetworkNode { /// looks up a random peer #[instrument(skip(self))] fn handle_peer_discovery(&mut self) { - if !self.swarm.behaviour().bootstrap_in_progress { + if self.swarm.behaviour().bootstrap_state == BootstrapState::Finished { let random_peer = PeerId::random(); self.swarm .behaviour_mut() @@ -536,35 +556,34 @@ impl NetworkNode { /// the swarm #[instrument(skip(self))] fn handle_num_connections(&mut self) { - let swarm = self.swarm.behaviour(); - // if we're bootstrapped, do nothing + let swarm = self.swarm.behaviour_mut(); + // otherwise periodically get more peers if needed - if !swarm.bootstrap_in_progress { - if swarm.connecting_peers.len() + swarm.connected_peers.len() - <= self.config.min_num_peers - { - // Calcuate the currently connected peers - let used_peers = swarm - .connecting_peers - .union(&swarm.connected_peers) - .copied() - .collect(); - // Calcuate the list of "new" peers, once not currently used for - // a connection - let potential_peers: HashSet = - swarm.known_peers.difference(&used_peers).copied().collect(); - // Number of peers we want to try connecting to - let num_to_connect = self.config.min_num_peers + 1 - - (swarm.connected_peers.len() + swarm.connecting_peers.len()); - // Random(?) subset of the availible peers to try connecting to - let chosen_peers = potential_peers - .iter() - .copied() - .choose_multiple(&mut thread_rng(), num_to_connect); - // Try dialing each random (?) peer - for a_peer in chosen_peers { + if swarm.connecting_peers.len() + swarm.connected_peers.len() <= self.config.min_num_peers { + // Calcuate the currently connected peers + let used_peers = swarm + .connecting_peers + .union(&swarm.connected_peers) + .copied() + .collect(); + // Calcuate the list of "new" peers, once not currently used for + // a connection + let potential_peers: HashSet = + swarm.known_peers.difference(&used_peers).copied().collect(); + // Number of peers we want to try connecting to + let num_to_connect = self.config.min_num_peers + 1 + - (swarm.connected_peers.len() + swarm.connecting_peers.len()); + // Random(?) subset of the availible peers to try connecting to + let chosen_peers = potential_peers + .iter() + .copied() + .choose_multiple(&mut thread_rng(), num_to_connect); + // Try dialing each random peer + for a_peer in chosen_peers { + if a_peer != self.peer_id { match self.swarm.dial(a_peer) { Ok(_) => { + info!("Peer {:?} dial {:?} working!", self.peer_id, a_peer); self.swarm.behaviour_mut().connecting_peers.insert(a_peer); } Err(e) => { @@ -578,22 +597,32 @@ impl NetworkNode { #[instrument(skip(self))] fn prune_num_connections(&mut self) { - // let swarm = self.swarm.behaviour_mut(); - // // If we are connected to too many peers, try disconnecting from - // // a random (?) subset - // if !swarm.bootstrap_in_progress && swarm.pruning_enabled && self.config.node_type != NetworkNodeType::Bootstrap && swarm.connected_peers.len() > self.config.max_num_peers { - // let peers_to_rm = swarm.connected_peers.iter().copied().choose( - // &mut thread_rng(), - // ); - // for a_peer in peers_to_rm { - // // FIXME the error is () ? - // let _ = self.swarm.disconnect_peer_id(a_peer); - // } - // - // } + let swarm = self.swarm.behaviour_mut(); + // If we are connected to too many peers, try disconnecting from + // a random (?) subset + if swarm.bootstrap_state == BootstrapState::Finished + && swarm.pruning_enabled + && self.config.node_type != NetworkNodeType::Bootstrap + && swarm.connected_peers.len() > self.config.max_num_peers + { + let peers_to_rm = swarm.connected_peers.iter().copied().choose_multiple( + &mut thread_rng(), + swarm.connected_peers.len() - self.config.max_num_peers, + ); + let safe_peers = swarm + .in_progress_rr + .iter() + .map(|(_, (_, pid))| pid) + .copied() + .collect::>(); + for a_peer in peers_to_rm { + if !safe_peers.contains(&a_peer) { + let _ = self.swarm.disconnect_peer_id(a_peer); + } + } + } } - /// event handler for client events /// currectly supported actions include /// - shutting down the swarm @@ -616,20 +645,20 @@ impl NetworkNode { warn!("Libp2p listener shutting down"); return Ok(true); } - ClientRequest::GossipMsg(topic, contents, chan) => { + ClientRequest::GossipMsg(topic, contents) => { + // TODO might be better just to push this into the queue and not try to + // send here let res = self .swarm .behaviour_mut() .gossipsub - .publish(topic, contents.clone()) - .map(|_| ()) - .context(PublishSnafu); - info!("publishing reuslt! {:?}", res); - - // send result back to ui to confirm this isn't a duplicate message - chan.send_async(res) - .await - .map_err(|_e| NetworkError::StreamClosed)?; + .publish(topic.clone(), contents.clone()); + if res.is_err() { + self.swarm + .behaviour_mut() + .in_progress_gossip + .push((topic, contents)); + } } GetId(reply_chan) => { // FIXME proper error handling @@ -661,10 +690,15 @@ impl NetworkNode { } } DirectRequest(pid, msg) => { - self.swarm + let request_id = self + .swarm .behaviour_mut() .request_response - .send_request(&pid, DirectMessageRequest(msg)); + .send_request(&pid, DirectMessageRequest(msg.clone())); + self.swarm + .behaviour_mut() + .in_progress_rr + .insert(request_id, (msg, pid)); } DirectResponse(chan, msg) => { let res = self @@ -699,11 +733,8 @@ impl NetworkNode { event: SwarmEvent< NetworkEvent, EitherError< - EitherError< - EitherError, Error>, - ProtocolsHandlerUpgrErr, - >, - Failure, + EitherError, Error>, + ProtocolsHandlerUpgrErr, >, >, send_to_client: &Sender, @@ -711,8 +742,8 @@ impl NetworkNode { // Make the match cleaner #[allow(clippy::enum_glob_use)] use SwarmEvent::*; + warn!("event observed {:?}", event); - warn!("libp2p event {:?}", event); match event { ConnectionEstablished { peer_id, endpoint, .. @@ -722,10 +753,6 @@ impl NetworkNode { self.swarm .behaviour_mut() .kadem - .add_address(&peer_id, address.clone()); - self.swarm - .behaviour_mut() - .request_response .add_address(&peer_id, address); } ConnectedPoint::Listener { @@ -735,17 +762,13 @@ impl NetworkNode { self.swarm .behaviour_mut() .kadem - .add_address(&peer_id, send_back_addr.clone()); - self.swarm - .behaviour_mut() - .request_response .add_address(&peer_id, send_back_addr); } } self.swarm.behaviour_mut().connected_peers.insert(peer_id); self.swarm.behaviour_mut().connecting_peers.remove(&peer_id); // now we have at least one peer so we can bootstrap - if !self.swarm.behaviour().bootstrap_in_progress { + if self.swarm.behaviour_mut().bootstrap_state == BootstrapState::NotStarted { self.swarm .behaviour_mut() .kadem @@ -764,6 +787,7 @@ impl NetworkNode { endpoint: _, .. } => { + warn!("connection closed btwn {:?}, {:?}", self.peer_id, peer_id); let swarm = self.swarm.behaviour_mut(); swarm.connected_peers.remove(&peer_id); // FIXME remove stale address, not *all* addresses @@ -816,7 +840,7 @@ impl NetworkNode { _ = sleep(Duration::from_secs(1)).fuse() => { self.handle_peer_discovery(); }, - _ = sleep(Duration::from_secs(1)).fuse() => { + _ = sleep(Duration::from_millis(25)).fuse() => { self.handle_num_connections(); } _ = sleep(Duration::from_secs(5)).fuse() => { diff --git a/libp2p-networking/src/network_node_handle.rs b/libp2p-networking/src/network_node_handle.rs index b7392fb2a2..9bb63dcbcb 100644 --- a/libp2p-networking/src/network_node_handle.rs +++ b/libp2p-networking/src/network_node_handle.rs @@ -1,19 +1,18 @@ use async_std::{ - future::{timeout, TimeoutError}, sync::{Condvar, Mutex}, task::spawn, }; use crate::network_node::{ gen_multiaddr, ClientRequest, ConnectionData, NetworkError, NetworkEvent, NetworkNode, - NetworkNodeConfig, NetworkNodeConfigBuilder, NetworkNodeConfigBuilderError, NetworkNodeType, + NetworkNodeConfig, NetworkNodeConfigBuilderError, }; use flume::{Receiver, RecvError, SendError, Sender}; -use futures::{future::join_all, select, Future, FutureExt}; +use futures::{select, Future, FutureExt}; use libp2p::{Multiaddr, PeerId}; use rand::{seq::IteratorRandom, thread_rng}; use snafu::{ResultExt, Snafu}; -use std::{fmt::Debug, sync::Arc, time::Duration}; +use std::{fmt::Debug, sync::Arc}; use tracing::{info_span, instrument, Instrument}; /// A handle containing: @@ -21,6 +20,8 @@ use tracing::{info_span, instrument, Instrument}; /// - Controls for the swarm #[derive(Debug)] pub struct NetworkNodeHandle { + /// network configuration + pub network_config: NetworkNodeConfig, /// notifies that a state change has occurred pub state_changed: Condvar, /// the state of the replica @@ -39,12 +40,14 @@ pub struct NetworkNodeHandle { pub peer_id: PeerId, /// the connection metadata associated with the networkbehaviour pub connection_state: Arc>, + /// human readable id + pub id: usize, } impl NetworkNodeHandle { /// constructs a new node listening on `known_addr` #[instrument] - pub async fn new(config: NetworkNodeConfig) -> Result { + pub async fn new(config: NetworkNodeConfig, id: usize) -> Result { //`randomly assigned port let listen_addr = gen_multiaddr(0); let mut network = NetworkNode::new(config).await.context(NetworkSnafu)?; @@ -57,12 +60,8 @@ impl NetworkNodeHandle { let (send_chan, recv_chan) = network.spawn_listeners().await.context(NetworkSnafu)?; let (kill_switch, recv_kill) = flume::bounded(1); - send_chan - .send_async(ClientRequest::Subscribe("global".to_string())) - .await - .context(SendSnafu)?; - Ok(NetworkNodeHandle { + network_config: config, state_changed: Condvar::new(), state: Arc::new(Mutex::new(S::default())), send_network: send_chan, @@ -72,6 +71,7 @@ impl NetworkNodeHandle { listen_addr, peer_id, connection_state: Arc::default(), + id, }) } @@ -92,76 +92,11 @@ impl NetworkNodeHandle { Ok(()) } - /// Spins up `num_of_nodes` nodes, connects them to each other - /// and waits for connections to propagate to all nodes. - #[instrument] - pub async fn spin_up_swarms( - num_of_nodes: usize, - timeout_len: Duration, - num_bootstrap: usize, - ) -> Result>, NetworkNodeHandleError> { - let mut handles = Vec::new(); - let mut bootstrap_addrs = Vec::<(PeerId, Multiaddr)>::new(); - let mut regular_addrs = Vec::<(PeerId, Multiaddr)>::new(); - let mut connecting_futs = Vec::new(); - - for i in 0..num_bootstrap { - let node = Arc::new(NetworkNodeHandle::new(NetworkNodeConfig::default()).await?); - let addr = node.listen_addr.clone(); - bootstrap_addrs.push((node.peer_id, addr)); - connecting_futs.push(Self::wait_to_connect( - node.clone(), - num_of_nodes, - node.recv_network.clone(), - i, - )); - handles.push(node); - } - - let regular_node_config = NetworkNodeConfigBuilder::default() - .node_type(NetworkNodeType::Regular) - .min_num_peers(10usize) - .max_num_peers(15usize) - .build() - .context(NodeConfigSnafu)?; - - for j in 0..(num_of_nodes - num_bootstrap) { - let node = Arc::new(NetworkNodeHandle::new(regular_node_config).await?); - let addr = node.listen_addr.clone(); - bootstrap_addrs.push((node.peer_id, addr)); - connecting_futs.push(Self::wait_to_connect( - node.clone(), - num_of_nodes, - node.recv_network.clone(), - num_bootstrap + j, - )); - - handles.push(node); - } - - let mut all_addrs = bootstrap_addrs; - all_addrs.append(&mut regular_addrs); - - for handle in &handles { - handle - .send_network - .send_async(ClientRequest::AddKnownPeers(all_addrs.clone())) - .await - .context(SendSnafu)?; - } - - timeout(timeout_len, join_all(connecting_futs.into_iter())) - .await - .context(TimeoutSnafu)?; - println!("Connected!"); - Ok(handles) - } - /// Wait for a node to connect to other nodes #[instrument] - async fn wait_to_connect( + pub async fn wait_to_connect( node: Arc>, - num_of_nodes: usize, + num_peers: usize, chan: Receiver, node_idx: usize, ) -> Result<(), NetworkNodeHandleError> { @@ -171,16 +106,11 @@ impl NetworkNodeHandle { match chan.recv_async().await.context(RecvSnafu)? { NetworkEvent::UpdateConnectedPeers(pids) => { node.connection_state.lock().await.connected_peers = pids.clone(); - // TODO when replaced with config, this should be > min num nodes in config - if pids.len() >= 3 * num_of_nodes / 4 { - connected_ok = true; - } + connected_ok = pids.len() >= num_peers; } NetworkEvent::UpdateKnownPeers(pids) => { node.connection_state.lock().await.known_peers = pids.clone(); - if pids.len() >= 3 * num_of_nodes / 4 { - known_ok = true; - } + known_ok = pids.len() >= num_peers; } _ => {} } @@ -261,12 +191,6 @@ pub enum NetworkNodeHandleError { /// source of error source: RecvError, }, - /// Timeout spinning up handle - #[snafu(display("Failed to spin up nodes. Hit timeout instead. {source:?}"))] - TimeoutError { - /// source of error - source: TimeoutError, - }, /// Error building Node config NodeConfigError { /// source of error diff --git a/libp2p-networking/src/ui.rs b/libp2p-networking/src/ui.rs index 64fc9926fb..a684b096af 100644 --- a/libp2p-networking/src/ui.rs +++ b/libp2p-networking/src/ui.rs @@ -170,7 +170,6 @@ pub async fn run_app(terminal: &mut Terminal, mut app: TableApp) } // broadcast message to the swarm with the global topic KeyCode::Enter => { - let mb_handle = app.message_buffer.clone(); let send_swarm = app.send_swarm.clone(); // we don't want this to block the event loop spawn(async move { @@ -181,14 +180,9 @@ pub async fn run_app(terminal: &mut Terminal, mut app: TableApp) content: app.input, sender: r.recv_async().await?.to_string(), }; - let (s, r) = flume::bounded(1); let bincode_options = bincode::DefaultOptions::new().with_limit(16_384); let s_msg = bincode_options.serialize(&msg)?; - send_swarm.send_async(ClientRequest::GossipMsg(Topic::new(msg.topic.clone()), s_msg, s)).await?; - // if it's a duplicate message (error case), fail silently and do nothing - if r.recv_async().await?.is_ok() { - mb_handle.lock().push_back(msg); - } + send_swarm.send_async(ClientRequest::GossipMsg(Topic::new(msg.topic.clone()), s_msg)).await?; Result::<(), Report>::Ok(()) }.instrument(info_span!("Broadcast Handler"))); app.input = String::new(); diff --git a/libp2p-networking/tests/common/mod.rs b/libp2p-networking/tests/common/mod.rs index 7f6ea2f4c8..d09f9ffe96 100644 --- a/libp2p-networking/tests/common/mod.rs +++ b/libp2p-networking/tests/common/mod.rs @@ -1,16 +1,24 @@ use std::{ + collections::HashMap, sync::{Arc, Once}, time::Duration, }; -use futures::Future; +use async_std::future::timeout; +use futures::{future::join_all, Future}; +use libp2p::{Multiaddr, PeerId}; use networking_demo::{ - network_node::NetworkEvent, - network_node_handle::{spawn_handler, NetworkNodeHandle, NetworkNodeHandleError}, + network_node::{ + ClientRequest, NetworkEvent, NetworkNodeConfig, NetworkNodeConfigBuilder, NetworkNodeType, + }, + network_node_handle::{ + spawn_handler, NetworkNodeHandle, NetworkNodeHandleError, NodeConfigSnafu, SendSnafu, + }, tracing_setup, }; +use snafu::{ResultExt, Snafu}; use std::fmt::Debug; -use tracing::warn; +use tracing::{instrument, warn}; static INIT: Once = Once::new(); @@ -45,7 +53,7 @@ pub async fn test_bed>> = - NetworkNodeHandle::spin_up_swarms(num_nodes, timeout, num_of_bootstrap) + spin_up_swarms(num_nodes, timeout, num_of_bootstrap) .await .unwrap(); print_connections(&handles).await; @@ -62,20 +70,43 @@ pub async fn test_bed(handles: &[Arc>]) -> HashMap { + let mut r_val = HashMap::new(); + for handle in handles { + r_val.insert(handle.peer_id, handle.id); + } + r_val +} + /// print the connections for each handle in `handles` /// useful for debugging -async fn print_connections(handles: &[Arc>]) { +pub async fn print_connections(handles: &[Arc>]) { + let m = gen_peerid_map(handles); warn!("PRINTING CONNECTION STATES"); - for (i, handle) in handles.iter().enumerate() { + for handle in handles.iter() { warn!( "peer {}, connected to {:?}", - i, - handle.connection_state.lock().await.connected_peers + handle.id, + handle + .connection_state + .lock() + .await + .connected_peers + .iter() + .map(|pid| m.get(pid).unwrap()) + .collect::>() ); warn!( "peer {}, knowns about {:?}", - i, - handle.connection_state.lock().await.known_peers + handle.id, + handle + .connection_state + .lock() + .await + .known_peers + .iter() + .map(|pid| m.get(pid).unwrap()) + .collect::>() ); } } @@ -84,15 +115,16 @@ pub async fn check_connection_state(handles: &[Arc>]) { let mut err_msg = "".to_string(); for (i, handle) in handles.iter().enumerate() { let state = handle.connection_state.lock().await.clone(); - // TODO these should depend on config - if state.known_peers.len() < handles.len() / 3 { + if state.known_peers.len() < handle.network_config.min_num_peers + && handle.network_config.node_type != NetworkNodeType::Bootstrap + { err_msg.push_str(&format!( "\nhad {} known peers for {}-th handle", state.known_peers.len(), i )); } - if state.connected_peers.len() < handles.len() / 3 { + if state.connected_peers.len() < handle.network_config.min_num_peers { err_msg.push_str(&format!( "\nhad {} connected peers for {}-th handle", state.connected_peers.len(), @@ -104,3 +136,118 @@ pub async fn check_connection_state(handles: &[Arc>]) { panic!("{}", err_msg); } } + +/// Spins up `num_of_nodes` nodes, connects them to each other +/// and waits for connections to propagate to all nodes. +#[instrument] +pub async fn spin_up_swarms( + num_of_nodes: usize, + timeout_len: Duration, + num_bootstrap: usize, +) -> Result>>, TestError> { + let mut handles = Vec::new(); + let mut bootstrap_addrs = Vec::<(PeerId, Multiaddr)>::new(); + let mut connecting_futs = Vec::new(); + let min_num_peers = 5; + let max_num_peers = 10; + + for i in 0..num_bootstrap { + let node = Arc::new( + NetworkNodeHandle::new(NetworkNodeConfig::default(), i) + .await + .context(HandleSnafu)?, + ); + let addr = node.listen_addr.clone(); + bootstrap_addrs.push((node.peer_id, addr)); + connecting_futs.push(timeout( + timeout_len, + NetworkNodeHandle::wait_to_connect( + node.clone(), + min_num_peers, + node.recv_network.clone(), + i, + ), + )); + handles.push(node); + } + + let regular_node_config = NetworkNodeConfigBuilder::default() + .node_type(NetworkNodeType::Regular) + .min_num_peers(min_num_peers) + .max_num_peers(max_num_peers) + .build() + .context(NodeConfigSnafu) + .context(HandleSnafu)?; + + for j in 0..(num_of_nodes - num_bootstrap) { + let node = Arc::new( + NetworkNodeHandle::new(regular_node_config, j + num_bootstrap) + .await + .context(HandleSnafu)?, + ); + let addr = node.listen_addr.clone(); + bootstrap_addrs.push((node.peer_id, addr)); + connecting_futs.push(timeout( + timeout_len, + NetworkNodeHandle::wait_to_connect( + node.clone(), + min_num_peers, + node.recv_network.clone(), + num_bootstrap + j, + ), + )); + + handles.push(node); + } + + for handle in &handles { + handle + .send_network + .send_async(ClientRequest::AddKnownPeers(bootstrap_addrs.clone())) + .await + .context(SendSnafu) + .context(HandleSnafu)?; + } + + let res = join_all(connecting_futs.into_iter()).await; + let mut failing_nodes = Vec::new(); + for (idx, a_node) in res.iter().enumerate() { + match a_node { + Ok(Err(_)) | Err(_) => failing_nodes.push(idx), + Ok(Ok(_)) => (), + } + } + if !failing_nodes.is_empty() { + return Err(TestError::SpinupTimeout { failing_nodes }); + } + + for handle in &handles { + handle + .send_network + .send_async(ClientRequest::Subscribe("global".to_string())) + .await + .context(SendSnafu) + .context(HandleSnafu)?; + } + + Ok(handles) +} + +#[derive(Debug, Snafu)] +#[snafu(visibility(pub))] +pub enum TestError { + #[snafu(display( + "Timeout while running direct message round. Timed out when {requester} dmed {requestee}" + ))] + DirectTimeout { requester: usize, requestee: usize }, + #[snafu(display("Timeout while running gossip round. Timed out on {failing:?}."))] + GossipTimeout { failing: Vec }, + #[snafu(display( + "Inconsistent state while running test. Expected {expected:?}, got {actual:?} on node {id}" + ))] + State { id: usize, expected: S, actual: S }, + #[snafu(display("Handler error while running test. {source:?}"))] + Handle { source: NetworkNodeHandleError }, + #[snafu(display("Failed to spin up nodes. Hit timeout instead. {failing_nodes:?}"))] + SpinupTimeout { failing_nodes: Vec }, +} diff --git a/libp2p-networking/tests/counter.rs b/libp2p-networking/tests/counter.rs index 8e999c9721..bd4e3fd95c 100644 --- a/libp2p-networking/tests/counter.rs +++ b/libp2p-networking/tests/counter.rs @@ -1,7 +1,7 @@ use std::{sync::Arc, time::Duration}; mod common; use async_std::future::timeout; -use common::{check_connection_state, test_bed}; +use common::{check_connection_state, test_bed, HandleSnafu, TestError}; use bincode::Options; @@ -10,8 +10,7 @@ use libp2p::gossipsub::Topic; use networking_demo::{ network_node::{ClientRequest, NetworkEvent}, network_node_handle::{ - get_random_handle, NetworkNodeHandle, NetworkNodeHandleError, SendSnafu, - SerializationSnafu, TimeoutSnafu, + get_random_handle, NetworkNodeHandle, NetworkNodeHandleError, SendSnafu, SerializationSnafu, }, }; use std::fmt::Debug; @@ -20,13 +19,16 @@ use serde::{Deserialize, Serialize}; use snafu::ResultExt; -use tracing::{error, info, instrument, warn}; +use tracing::{info, instrument, warn}; + +use crate::common::print_connections; pub type CounterState = u32; -const TOTAL_NUM_PEERS: usize = 5; -const NUM_OF_BOOTSTRAP: usize = 1; -const TIMEOUT: Duration = Duration::from_secs(30); +const TOTAL_NUM_PEERS: usize = 30; +const NUM_OF_BOOTSTRAP: usize = 5; +const TIMEOUT: Duration = Duration::from_secs(20); +const NUM_ROUNDS: usize = 100; /// Message types. We can either /// - increment the Counter @@ -111,7 +113,7 @@ pub async fn counter_handle_network_event( async fn run_request_response_increment( requester_handle: Arc>, requestee_handle: Arc>, -) { +) -> Result<(), TestError> { let bincode_options = bincode::DefaultOptions::new().with_limit(16_384); let msg_inner = bincode_options .serialize(&CounterMessage::AskForCounter) @@ -122,24 +124,39 @@ async fn run_request_response_increment( let new_state = *requestee_handle.state.lock().await; // set up state change listener - let recv_fut = requester_handle - .state_changed - .wait_until(requester_handle.state.lock().await, |state| { - *state == new_state - }); - - requester_handle.send_network.send_async(msg).await.unwrap(); + let recv_fut = requester_handle.state_changed.wait_timeout_until( + requester_handle.state.lock().await, + TIMEOUT, + |state| *state == new_state, + ); - timeout(TIMEOUT, recv_fut) + requester_handle + .send_network + .send_async(msg) .await - .context(TimeoutSnafu) - .unwrap(); - // println!("done request_response increment for {}", requester_handle.peer_id); + .context(SendSnafu) + .context(HandleSnafu)?; - assert_eq!( - *requester_handle.state.lock().await, - *requestee_handle.state.lock().await - ); + let (_, res) = recv_fut.await; + + if res.timed_out() { + Err(TestError::DirectTimeout { + requester: requester_handle.id, + requestee: requestee_handle.id, + }) + } else { + let s1 = *requester_handle.state.lock().await; + // sanity check + if s1 != new_state { + Err(TestError::State { + id: requester_handle.id, + expected: new_state, + actual: s1, + }) + } else { + Ok(()) + } + } } /// broadcasts `msg` from a randomly chosen handle @@ -148,11 +165,9 @@ async fn run_gossip_round( handles: &[Arc>], msg_inner: Vec, new_state: CounterState, -) { +) -> Result<(), TestError> { let msg_handle = get_random_handle(handles); *msg_handle.state.lock().await = new_state; - let (send, recv) = flume::bounded(1); - let msg = ClientRequest::GossipMsg(Topic::new("global"), msg_inner, send); let mut futs = Vec::new(); for handle in handles { @@ -162,23 +177,31 @@ async fn run_gossip_round( futs.push(a_fut); } - msg_handle.send_network.send_async(msg).await.unwrap(); - recv.recv_async().await.unwrap().unwrap(); - - timeout(TIMEOUT, futures::future::join_all(futs)) + let msg = ClientRequest::GossipMsg(Topic::new("global"), msg_inner.clone()); + msg_handle + .send_network + .send_async(msg) .await - .unwrap(); + .context(SendSnafu) + .context(HandleSnafu)?; - let mut failing_idxs = Vec::new(); - for (i, handle) in handles.iter().enumerate() { - if *handle.state.lock().await != new_state { - failing_idxs.push(i); + if timeout(TIMEOUT, futures::future::join_all(futs)) + .await + .is_err() + { + let mut failing = Vec::new(); + for handle in handles.iter() { + let handle_state = *handle.state.lock().await; + if handle_state != new_state { + failing.push(handle.id); + } + } + if !failing.is_empty() { + print_connections(handles).await; + return Err(TestError::GossipTimeout { failing }); } } - if !failing_idxs.is_empty() { - error!(?failing_idxs, "failing idxs!!"); - panic!("some nodes did not receive the message {:?}", failing_idxs); - } + Ok(()) } /// runs `num_rounds` of message broadcast, incrementing the state of all nodes each broadcast @@ -198,7 +221,9 @@ async fn run_gossip_rounds( to: new_state, }) .unwrap(); - run_gossip_round(handles, msg_inner, new_state).await; + run_gossip_round(handles, msg_inner, new_state) + .await + .unwrap(); old_state = new_state; } } @@ -216,12 +241,8 @@ async fn run_request_response_increment_all(handles: &[Arc>() + ); + } + } + check_connection_state(handles).await; requestee_handle .send_network - .send_async(ClientRequest::Pruning(false)) + .send_async(ClientRequest::Pruning(true)) .await .unwrap(); } @@ -272,7 +306,6 @@ async fn test_request_response_many_rounds() { let num_rounds = 4092; for _i in 0..num_rounds { run_request_response_increment_all(&handles).await; - // println!("finished {}", i); } for h in handles.into_iter() { assert_eq!(*h.state.lock().await, num_rounds); @@ -293,8 +326,7 @@ async fn test_request_response_many_rounds() { #[instrument] async fn test_intersperse_many_rounds() { pub async fn run_intersperse_many_rounds(handles: Vec>>) { - let num_rounds = 4092; - for i in 0..num_rounds { + for i in 0..NUM_ROUNDS as u32 { if i % 2 == 0 { run_request_response_increment_all(&handles).await; } else { @@ -303,7 +335,7 @@ async fn test_intersperse_many_rounds() { // println!("finished {}", i); } for h in handles.into_iter() { - assert_eq!(*h.state.lock().await, num_rounds); + assert_eq!(*h.state.lock().await, NUM_ROUNDS as u32); } } test_bed( @@ -321,7 +353,7 @@ async fn test_intersperse_many_rounds() { #[instrument] async fn test_gossip_many_rounds() { pub async fn run_gossip_many_rounds(handles: Vec>>) { - run_gossip_rounds(&handles, 4092, 0).await + run_gossip_rounds(&handles, NUM_ROUNDS, 0).await } test_bed( run_gossip_many_rounds, From b1b5a4de6ca5d24d846fa1e8ec418c25712c5402 Mon Sep 17 00:00:00 2001 From: Justin Restivo Date: Fri, 11 Feb 2022 13:40:38 -0500 Subject: [PATCH 072/107] fix: longer timeout --- libp2p-networking/tests/counter.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libp2p-networking/tests/counter.rs b/libp2p-networking/tests/counter.rs index bd4e3fd95c..47f6b1a0f6 100644 --- a/libp2p-networking/tests/counter.rs +++ b/libp2p-networking/tests/counter.rs @@ -27,7 +27,7 @@ pub type CounterState = u32; const TOTAL_NUM_PEERS: usize = 30; const NUM_OF_BOOTSTRAP: usize = 5; -const TIMEOUT: Duration = Duration::from_secs(20); +const TIMEOUT: Duration = Duration::from_secs(200); const NUM_ROUNDS: usize = 100; /// Message types. We can either From 941c392c8c68b81de79d3b80c3f8349b034b2dd6 Mon Sep 17 00:00:00 2001 From: Justin Restivo Date: Fri, 11 Feb 2022 15:33:21 -0500 Subject: [PATCH 073/107] fix: try release profile --- libp2p-networking/.github/workflows/build.yml | 4 ++-- libp2p-networking/.github/workflows/coverage.yml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/libp2p-networking/.github/workflows/build.yml b/libp2p-networking/.github/workflows/build.yml index 29e335db5a..b746331338 100644 --- a/libp2p-networking/.github/workflows/build.yml +++ b/libp2p-networking/.github/workflows/build.yml @@ -47,7 +47,7 @@ jobs: token: ${{ github.token }} - name: Cargo Build - run: cargo build + run: cargo build --release - name: Cargo Test - run: cargo test --verbose -- -Zunstable-options --report-time + run: cargo test --verbose --release -- -Zunstable-options --report-time diff --git a/libp2p-networking/.github/workflows/coverage.yml b/libp2p-networking/.github/workflows/coverage.yml index fd86ec48f7..3931f57c8a 100644 --- a/libp2p-networking/.github/workflows/coverage.yml +++ b/libp2p-networking/.github/workflows/coverage.yml @@ -28,7 +28,7 @@ jobs: uses: actions-rs/cargo@v1 with: command: test - args: --all-features --no-fail-fast + args: --all-features --no-fail-fast --release env: CARGO_INCREMENTAL: '0' RUSTFLAGS: '-Zprofile -Ccodegen-units=1 -Cinline-threshold=0 -Clink-dead-code -Coverflow-checks=off -Cpanic=abort -Zpanic_abort_tests' From 091c7fb50d67fd33928b00fa23a7ed1e9cf7e97c Mon Sep 17 00:00:00 2001 From: Justin Restivo Date: Mon, 14 Feb 2022 10:18:06 -0500 Subject: [PATCH 074/107] feat: flamegraph, gossipsub handler, lessened params --- libp2p-networking/flake.nix | 26 +++++++++++++++++++++-- libp2p-networking/flamegraph.sh | 1 + libp2p-networking/src/network_node.rs | 30 +++++++++++++++++---------- libp2p-networking/tests/counter.rs | 4 ++-- 4 files changed, 46 insertions(+), 15 deletions(-) create mode 100755 libp2p-networking/flamegraph.sh diff --git a/libp2p-networking/flake.nix b/libp2p-networking/flake.nix index 9bd69fe666..a0df169460 100644 --- a/libp2p-networking/flake.nix +++ b/libp2p-networking/flake.nix @@ -68,7 +68,28 @@ }; }; - shellHook = '''' + (pkgs.lib.optionals pkgs.stdenv.isDarwin '' ulimit -n 9999999999''); + recent_flamegraph = pkgs.cargo-flamegraph.overrideAttrs (oldAttrs: rec { + src = pkgs.fetchFromGitHub { + owner = "flamegraph-rs"; + repo = "flamegraph"; + rev = "a9837efd8744dac853acbe3d476924083f26743d"; + sha256 = "sha256-Fek2AJ8mYYf92NBT0pmVBqK1BXmr6GdEqt2Rp8To8tI="; + }; + version = "master"; + cargoDeps = oldAttrs.cargoDeps.overrideAttrs (pkgs.lib.const { + name = "${oldAttrs.pname}-vendor.tar.gz"; + inherit src; + outputHash = "sha256-i9/Fe+JaCcdHw2CR0n4hULokDN2RvDAzgXNG2zAUFDg="; + }); + }); + + shellHook = + # '' + # export ASYNC_STD_THREAD_COUNT=1 + # '' + + (pkgs.lib.optionals pkgs.stdenv.isDarwin '' + ulimit -n 9999999999 + ''); in { packages.${crateName} = project.rootCrate.build; @@ -83,7 +104,8 @@ # inputsFrom = builtins.attrValues self.packages.${system}; buildInputs = with pkgs; [ cargo-audit nixpkgs-fmt git-chglog fenix.packages.${system}.rust-analyzer fenixPackage protobuf] - ++ lib.optionals stdenv.isDarwin [ darwin.apple_sdk.frameworks.Security pkgs.libiconv darwin.apple_sdk.frameworks.SystemConfiguration ]; + ++ lib.optionals stdenv.isDarwin [ darwin.apple_sdk.frameworks.Security pkgs.libiconv darwin.apple_sdk.frameworks.SystemConfiguration recent_flamegraph fd ]; }; + }); } diff --git a/libp2p-networking/flamegraph.sh b/libp2p-networking/flamegraph.sh new file mode 100755 index 0000000000..190d0d4940 --- /dev/null +++ b/libp2p-networking/flamegraph.sh @@ -0,0 +1 @@ +sudo nix develop -c flamegraph -- $(fd -I "counter*" -t x | rg debug) test_request_response_one_round diff --git a/libp2p-networking/src/network_node.rs b/libp2p-networking/src/network_node.rs index d29e785b1f..2a36b73ad2 100644 --- a/libp2p-networking/src/network_node.rs +++ b/libp2p-networking/src/network_node.rs @@ -134,17 +134,6 @@ impl NetworkDef { _: &mut impl PollParameters, ) -> Poll::ProtocolsHandler>> { - // TODO this should be separated out into a separate event - let mut num_sent = 0; - for (topic, contents) in self.in_progress_gossip.as_slice() { - let res = self.gossipsub.publish(topic.clone(), contents.clone()); - if res.is_err() { - break; - } - num_sent += 1; - } - self.in_progress_gossip = self.in_progress_gossip[num_sent..].into(); - // push events that must be relayed back to client onto queue // to be consumed by client event handler if !self.client_event_queue.is_empty() { @@ -822,6 +811,22 @@ impl NetworkNode { Ok(()) } + /// periodically resend gossip messages if they have failed + #[allow(clippy::panic)] + #[instrument(skip(self))] + pub fn handle_sending(&mut self) { + let swarm = self.swarm.behaviour_mut(); + let mut num_sent = 0; + for (topic, contents) in swarm.in_progress_gossip.as_slice() { + let res = swarm.gossipsub.publish(topic.clone(), contents.clone()); + if res.is_err() { + break; + } + num_sent += 1; + } + swarm.in_progress_gossip = swarm.in_progress_gossip[num_sent..].into(); + } + /// Spawn a task to listen for requests on the returned channel /// as well as any events produced by libp2p #[allow(clippy::panic)] @@ -837,6 +842,9 @@ impl NetworkNode { loop { // TODO variable on futures times select! { + _ = sleep(Duration::from_secs(1)).fuse() => { + self.handle_sending(); + }, _ = sleep(Duration::from_secs(1)).fuse() => { self.handle_peer_discovery(); }, diff --git a/libp2p-networking/tests/counter.rs b/libp2p-networking/tests/counter.rs index 47f6b1a0f6..ffa0ed65fc 100644 --- a/libp2p-networking/tests/counter.rs +++ b/libp2p-networking/tests/counter.rs @@ -25,8 +25,8 @@ use crate::common::print_connections; pub type CounterState = u32; -const TOTAL_NUM_PEERS: usize = 30; -const NUM_OF_BOOTSTRAP: usize = 5; +const TOTAL_NUM_PEERS: usize = 5; +const NUM_OF_BOOTSTRAP: usize = 1; const TIMEOUT: Duration = Duration::from_secs(200); const NUM_ROUNDS: usize = 100; From e1669dff94df0ebaa9bb7a252fb10dc4bf403e04 Mon Sep 17 00:00:00 2001 From: Justin Restivo Date: Mon, 14 Feb 2022 10:27:41 -0500 Subject: [PATCH 075/107] fix: undo release flag --- libp2p-networking/.github/workflows/coverage.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libp2p-networking/.github/workflows/coverage.yml b/libp2p-networking/.github/workflows/coverage.yml index 3931f57c8a..fd86ec48f7 100644 --- a/libp2p-networking/.github/workflows/coverage.yml +++ b/libp2p-networking/.github/workflows/coverage.yml @@ -28,7 +28,7 @@ jobs: uses: actions-rs/cargo@v1 with: command: test - args: --all-features --no-fail-fast --release + args: --all-features --no-fail-fast env: CARGO_INCREMENTAL: '0' RUSTFLAGS: '-Zprofile -Ccodegen-units=1 -Cinline-threshold=0 -Clink-dead-code -Coverflow-checks=off -Cpanic=abort -Zpanic_abort_tests' From 91e7d414a6ab10c85f19a13dcbf10941965e4988 Mon Sep 17 00:00:00 2001 From: Justin Restivo Date: Mon, 14 Feb 2022 10:44:56 -0500 Subject: [PATCH 076/107] fix: single thread the tests --- libp2p-networking/.github/workflows/build.yml | 2 +- libp2p-networking/.github/workflows/coverage.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/libp2p-networking/.github/workflows/build.yml b/libp2p-networking/.github/workflows/build.yml index b746331338..a8fd368845 100644 --- a/libp2p-networking/.github/workflows/build.yml +++ b/libp2p-networking/.github/workflows/build.yml @@ -50,4 +50,4 @@ jobs: run: cargo build --release - name: Cargo Test - run: cargo test --verbose --release -- -Zunstable-options --report-time + run: cargo test --verbose -- -Zunstable-options --report-time --test-threads=1 diff --git a/libp2p-networking/.github/workflows/coverage.yml b/libp2p-networking/.github/workflows/coverage.yml index fd86ec48f7..9ff8322bec 100644 --- a/libp2p-networking/.github/workflows/coverage.yml +++ b/libp2p-networking/.github/workflows/coverage.yml @@ -28,7 +28,7 @@ jobs: uses: actions-rs/cargo@v1 with: command: test - args: --all-features --no-fail-fast + args: --all-features --no-fail-fast -- --test-threads=1 env: CARGO_INCREMENTAL: '0' RUSTFLAGS: '-Zprofile -Ccodegen-units=1 -Cinline-threshold=0 -Clink-dead-code -Coverflow-checks=off -Cpanic=abort -Zpanic_abort_tests' From cd8aea5deab3eeefe2214176b02c665d88fad605 Mon Sep 17 00:00:00 2001 From: Justin Restivo Date: Mon, 14 Feb 2022 12:14:41 -0500 Subject: [PATCH 077/107] fix: fix tests --- libp2p-networking/flake.nix | 60 ++++++++++++++++++++------- libp2p-networking/src/network_node.rs | 2 +- libp2p-networking/tests/common/mod.rs | 4 +- libp2p-networking/tests/counter.rs | 6 +-- 4 files changed, 50 insertions(+), 22 deletions(-) diff --git a/libp2p-networking/flake.nix b/libp2p-networking/flake.nix index a0df169460..48648eebc6 100644 --- a/libp2p-networking/flake.nix +++ b/libp2p-networking/flake.nix @@ -21,13 +21,16 @@ outputs = { self, nixpkgs, flake-compat, utils, crate2nix, fenix }: utils.lib.eachDefaultSystem (system: let - fenixPackage = fenix.packages.${system}.stable.withComponents [ "cargo" "clippy" "rust-src" "rustc" "rustfmt" ]; + fenixStable = fenix.packages.${system}.stable.withComponents [ "cargo" "clippy" "rust-src" "rustc" "rustfmt" ]; + fenixNightly = fenix.packages.${system}.latest.withComponents [ "cargo" "clippy" "rust-src" "rustc" "rustfmt" ]; rustOverlay = final: prev: { - inherit fenixPackage; - rustc = fenixPackage; - cargo = fenixPackage; - rust-src = fenixPackage; + rustcNightly = fenixNightly; + cargoNightly = fenixNightly; + rust-srcNightly = fenixNightly; + rustc = fenixStable; + cargo = fenixStable; + rust-src = fenixStable; }; pkgs = import nixpkgs { @@ -82,14 +85,33 @@ outputHash = "sha256-i9/Fe+JaCcdHw2CR0n4hULokDN2RvDAzgXNG2zAUFDg="; }); }); + # https://github.com/NixOS/nixpkgs/issues/149209 + grcov = pkgs.rustPlatform.buildRustPackage rec { + pname = "grcov"; + version = "v0.8.7"; + + doCheck = false; + + src = pkgs.fetchFromGitHub { + owner = "mozilla"; + repo = pname; + rev = version; + sha256 = "sha256-4McF9tLIjDCftyGI29pm/LnTUBVWG+pY5z+mGFKySQM="; + }; + + cargoSha256 = "sha256-CdsTAMiEK8udRoD9PQSC0jQbPkdynFL0Tdw5aAZUmsM="; + + meta = with pkgs.lib; { + description = "grcov collects and aggregates code coverage information for multiple source files."; + homepage = "https://github.com/mozilla/grcov"; + license = licenses.mpl20; + }; + }; + + buildDeps = with pkgs; [ + cargo-audit nixpkgs-fmt git-chglog protobuf + ] ++ lib.optionals stdenv.isDarwin [ darwin.apple_sdk.frameworks.Security pkgs.libiconv darwin.apple_sdk.frameworks.SystemConfiguration]; - shellHook = - # '' - # export ASYNC_STD_THREAD_COUNT=1 - # '' + - (pkgs.lib.optionals pkgs.stdenv.isDarwin '' - ulimit -n 9999999999 - ''); in { packages.${crateName} = project.rootCrate.build; @@ -100,11 +122,17 @@ defaultPackage = self.packages.${system}.${crateName}; devShell = pkgs.mkShell { - inherit shellHook; - # inputsFrom = builtins.attrValues self.packages.${system}; buildInputs = - with pkgs; [ cargo-audit nixpkgs-fmt git-chglog fenix.packages.${system}.rust-analyzer fenixPackage protobuf] - ++ lib.optionals stdenv.isDarwin [ darwin.apple_sdk.frameworks.Security pkgs.libiconv darwin.apple_sdk.frameworks.SystemConfiguration recent_flamegraph fd ]; + with pkgs; [ fenix.packages.${system}.rust-analyzer fenixStable ] ++ buildDeps; + }; + + devShells.perfShell = pkgs.mkShell { + buildInputs = with pkgs; [ grcov recent_flamegraph fd fenixNightly fenix.packages.${system}.rust-analyzer ] ++ buildDeps; + shellHook = '' + export RUSTFLAGS='-Zprofile -Ccodegen-units=1 -Cinline-threshold=0 -Clink-dead-code -Coverflow-checks=off -Cpanic=abort -Zpanic_abort_tests' + export RUSTDOCFLAGS='-Zprofile -Ccodegen-units=1 -Cinline-threshold=0 -Clink-dead-code -Coverflow-checks=off -Cpanic=abort -Zpanic_abort_tests' + export CARGO_INCREMENTAL=0 + ''; }; }); diff --git a/libp2p-networking/src/network_node.rs b/libp2p-networking/src/network_node.rs index 2a36b73ad2..68ea3899ae 100644 --- a/libp2p-networking/src/network_node.rs +++ b/libp2p-networking/src/network_node.rs @@ -842,7 +842,7 @@ impl NetworkNode { loop { // TODO variable on futures times select! { - _ = sleep(Duration::from_secs(1)).fuse() => { + _ = sleep(Duration::from_millis(25)).fuse() => { self.handle_sending(); }, _ = sleep(Duration::from_secs(1)).fuse() => { diff --git a/libp2p-networking/tests/common/mod.rs b/libp2p-networking/tests/common/mod.rs index d09f9ffe96..3fc3c86141 100644 --- a/libp2p-networking/tests/common/mod.rs +++ b/libp2p-networking/tests/common/mod.rs @@ -148,8 +148,8 @@ pub async fn spin_up_swarms( let mut handles = Vec::new(); let mut bootstrap_addrs = Vec::<(PeerId, Multiaddr)>::new(); let mut connecting_futs = Vec::new(); - let min_num_peers = 5; - let max_num_peers = 10; + let min_num_peers = num_of_nodes / 4; + let max_num_peers = num_of_nodes / 2; for i in 0..num_bootstrap { let node = Arc::new( diff --git a/libp2p-networking/tests/counter.rs b/libp2p-networking/tests/counter.rs index ffa0ed65fc..0a74a8b78b 100644 --- a/libp2p-networking/tests/counter.rs +++ b/libp2p-networking/tests/counter.rs @@ -25,9 +25,9 @@ use crate::common::print_connections; pub type CounterState = u32; -const TOTAL_NUM_PEERS: usize = 5; -const NUM_OF_BOOTSTRAP: usize = 1; -const TIMEOUT: Duration = Duration::from_secs(200); +const TOTAL_NUM_PEERS: usize = 10; +const NUM_OF_BOOTSTRAP: usize = 3; +const TIMEOUT: Duration = Duration::from_secs(60); const NUM_ROUNDS: usize = 100; /// Message types. We can either From 7ec47c7efd2c1d8ed416edeadfe5ab38029a9a0c Mon Sep 17 00:00:00 2001 From: Justin Restivo Date: Mon, 14 Feb 2022 12:59:24 -0500 Subject: [PATCH 078/107] fix: ignore target directory for code coverage --- libp2p-networking/.github/actions-rs/grcov.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libp2p-networking/.github/actions-rs/grcov.yml b/libp2p-networking/.github/actions-rs/grcov.yml index d64c9c316f..63487effb7 100644 --- a/libp2p-networking/.github/actions-rs/grcov.yml +++ b/libp2p-networking/.github/actions-rs/grcov.yml @@ -1,4 +1,5 @@ output-type: lcov ignore: - "/*" - - "../*" \ No newline at end of file + - "../*" + - "target/*" \ No newline at end of file From 0bd7ada23d0e0cba800886d429ac274ff8fb3f2f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 15 Feb 2022 04:32:04 +0000 Subject: [PATCH 079/107] chore(deps): bump flume from 0.10.10 to 0.10.11 Bumps [flume](https://github.com/zesterer/flume) from 0.10.10 to 0.10.11. - [Release notes](https://github.com/zesterer/flume/releases) - [Changelog](https://github.com/zesterer/flume/blob/master/CHANGELOG.md) - [Commits](https://github.com/zesterer/flume/commits) --- updated-dependencies: - dependency-name: flume dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- libp2p-networking/Cargo.lock | 4 ++-- libp2p-networking/Cargo.toml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/libp2p-networking/Cargo.lock b/libp2p-networking/Cargo.lock index 6e8ff9fc7d..62c1bd5608 100644 --- a/libp2p-networking/Cargo.lock +++ b/libp2p-networking/Cargo.lock @@ -922,9 +922,9 @@ dependencies = [ [[package]] name = "flume" -version = "0.10.10" +version = "0.10.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d04dafd11240188e146b6f6476a898004cace3be31d4ec5e08e216bf4947ac0" +checksum = "0b279436a715a9de95dcd26b151db590a71961cc06e54918b24fe0dd5b7d3fc4" dependencies = [ "futures-core", "futures-sink", diff --git a/libp2p-networking/Cargo.toml b/libp2p-networking/Cargo.toml index 8ba6dffff0..125dd10531 100644 --- a/libp2p-networking/Cargo.toml +++ b/libp2p-networking/Cargo.toml @@ -11,7 +11,7 @@ bincode = "1.3.3" blake3 = "1.3.1" color-eyre = "0.6.0" crossterm = { version = "0.23.0", features = ["event-stream"] } -flume = "0.10.10" +flume = "0.10.11" futures = "0.3.21" libp2p = "0.42.2" parking_lot = "0.12.0" From 9c1972310a0bdb6246285466429688a98905116b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 15 Feb 2022 04:32:12 +0000 Subject: [PATCH 080/107] chore(deps): bump rand from 0.8.4 to 0.8.5 Bumps [rand](https://github.com/rust-random/rand) from 0.8.4 to 0.8.5. - [Release notes](https://github.com/rust-random/rand/releases) - [Changelog](https://github.com/rust-random/rand/blob/master/CHANGELOG.md) - [Commits](https://github.com/rust-random/rand/compare/0.8.4...0.8.5) --- updated-dependencies: - dependency-name: rand dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- libp2p-networking/Cargo.lock | 40 ++++++++++++++---------------------- libp2p-networking/Cargo.toml | 2 +- 2 files changed, 16 insertions(+), 26 deletions(-) diff --git a/libp2p-networking/Cargo.lock b/libp2p-networking/Cargo.lock index 6e8ff9fc7d..952e4b2169 100644 --- a/libp2p-networking/Cargo.lock +++ b/libp2p-networking/Cargo.lock @@ -1411,7 +1411,7 @@ dependencies = [ "log", "prost", "prost-build", - "rand 0.8.4", + "rand 0.8.5", ] [[package]] @@ -1438,7 +1438,7 @@ dependencies = [ "pin-project 1.0.10", "prost", "prost-build", - "rand 0.8.4", + "rand 0.8.5", "ring", "rw-stream-sink", "sha2 0.10.1", @@ -1581,7 +1581,7 @@ dependencies = [ "libp2p-core", "libp2p-swarm", "log", - "rand 0.8.4", + "rand 0.8.5", "smallvec", "socket2 0.4.2", "void", @@ -1635,7 +1635,7 @@ dependencies = [ "log", "prost", "prost-build", - "rand 0.8.4", + "rand 0.8.5", "sha2 0.10.1", "snow", "static_assertions", @@ -1708,7 +1708,7 @@ dependencies = [ "pin-project 1.0.10", "prost", "prost-build", - "rand 0.8.4", + "rand 0.8.5", "smallvec", "static_assertions", "thiserror", @@ -1732,7 +1732,7 @@ dependencies = [ "log", "prost", "prost-build", - "rand 0.8.4", + "rand 0.8.5", "sha2 0.10.1", "thiserror", "unsigned-varint", @@ -1871,7 +1871,7 @@ dependencies = [ "libsecp256k1-core", "libsecp256k1-gen-ecmult", "libsecp256k1-gen-genmult", - "rand 0.8.4", + "rand 0.8.5", "serde", "sha2 0.9.9", "typenum", @@ -2182,7 +2182,7 @@ dependencies = [ "futures", "libp2p", "parking_lot 0.12.0", - "rand 0.8.4", + "rand 0.8.5", "serde", "snafu", "structopt", @@ -2618,19 +2618,18 @@ dependencies = [ "libc", "rand_chacha 0.2.2", "rand_core 0.5.1", - "rand_hc 0.2.0", + "rand_hc", ] [[package]] name = "rand" -version = "0.8.4" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e7573632e6454cf6b99d7aac4ccca54be06da05aca2ef7423d22d27d4d4bcd8" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" dependencies = [ "libc", "rand_chacha 0.3.1", "rand_core 0.6.3", - "rand_hc 0.3.1", ] [[package]] @@ -2680,15 +2679,6 @@ dependencies = [ "rand_core 0.5.1", ] -[[package]] -name = "rand_hc" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d51e9f596de227fda2ea6c84607f5558e196eeaf43c986b724ba4fb8fdf497e7" -dependencies = [ - "rand_core 0.6.3", -] - [[package]] name = "redox_syscall" version = "0.2.10" @@ -3028,7 +3018,7 @@ dependencies = [ "aes-gcm", "blake2", "chacha20poly1305", - "rand 0.8.4", + "rand 0.8.5", "rand_core 0.6.3", "ring", "rustc_version", @@ -3070,7 +3060,7 @@ dependencies = [ "futures", "httparse", "log", - "rand 0.8.4", + "rand 0.8.5", "sha-1", ] @@ -3376,7 +3366,7 @@ dependencies = [ "ipnet", "lazy_static", "log", - "rand 0.8.4", + "rand 0.8.5", "smallvec", "thiserror", "tinyvec", @@ -3829,7 +3819,7 @@ dependencies = [ "log", "nohash-hasher", "parking_lot 0.11.2", - "rand 0.8.4", + "rand 0.8.5", "static_assertions", ] diff --git a/libp2p-networking/Cargo.toml b/libp2p-networking/Cargo.toml index 8ba6dffff0..204b03d387 100644 --- a/libp2p-networking/Cargo.toml +++ b/libp2p-networking/Cargo.toml @@ -22,6 +22,6 @@ tracing = "0.1.30" tracing-error = "0.2.0" tracing-subscriber = { version = "0.3.8", features = ["env-filter", "json"] } tui = { version = "0.17.0", features = ["crossterm"], default-features = false } -rand = "0.8.4" +rand = "0.8.5" async-trait = "0.1.52" derive_builder = "0.10.2" From dd0a32760c73bc30f63db26be977d432c56b40f7 Mon Sep 17 00:00:00 2001 From: Justin Restivo Date: Wed, 16 Feb 2022 16:44:56 -0500 Subject: [PATCH 081/107] feat: stub out multi network examples --- libp2p-networking/Cargo.lock | 8 + libp2p-networking/Cargo.toml | 2 +- libp2p-networking/examples/clichat.rs | 11 +- libp2p-networking/examples/common/mod.rs | 286 ++++++++++++++++++ .../examples/counter_bootstrap.rs | 20 ++ .../examples/counter_controller.rs | 16 + libp2p-networking/examples/counter_regular.rs | 20 ++ libp2p-networking/grcov.sh | 8 + libp2p-networking/repl.nix | 8 + libp2p-networking/src/network_node.rs | 102 +++++-- libp2p-networking/src/network_node_handle.rs | 59 +++- libp2p-networking/src/ui.rs | 2 +- libp2p-networking/tests/common/mod.rs | 8 +- libp2p-networking/tests/counter.rs | 9 +- 14 files changed, 516 insertions(+), 43 deletions(-) create mode 100644 libp2p-networking/examples/common/mod.rs create mode 100644 libp2p-networking/examples/counter_bootstrap.rs create mode 100644 libp2p-networking/examples/counter_controller.rs create mode 100644 libp2p-networking/examples/counter_regular.rs create mode 100644 libp2p-networking/grcov.sh create mode 100644 libp2p-networking/repl.nix diff --git a/libp2p-networking/Cargo.lock b/libp2p-networking/Cargo.lock index 6e8ff9fc7d..c30ba8d3e4 100644 --- a/libp2p-networking/Cargo.lock +++ b/libp2p-networking/Cargo.lock @@ -450,6 +450,9 @@ name = "bytes" version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c4872d67bab6358e59559027aa3b9157c53d9358c51423c17554809a8858e0f8" +dependencies = [ + "serde", +] [[package]] name = "cache-padded" @@ -1077,6 +1080,7 @@ version = "0.14.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fd48d33ec7f05fbfa152300fdad764757cbded343c1aa1cff2fbaf4134851803" dependencies = [ + "serde", "typenum", "version_check", ] @@ -1441,6 +1445,7 @@ dependencies = [ "rand 0.8.4", "ring", "rw-stream-sink", + "serde", "sha2 0.10.1", "smallvec", "thiserror", @@ -1516,6 +1521,7 @@ dependencies = [ "prost-build", "rand 0.7.3", "regex", + "serde", "sha2 0.10.1", "smallvec", "unsigned-varint", @@ -1558,6 +1564,7 @@ dependencies = [ "prost", "prost-build", "rand 0.7.3", + "serde", "sha2 0.10.1", "smallvec", "thiserror", @@ -2055,6 +2062,7 @@ dependencies = [ "digest 0.9.0", "generic-array", "multihash-derive", + "serde", "sha2 0.9.9", "unsigned-varint", ] diff --git a/libp2p-networking/Cargo.toml b/libp2p-networking/Cargo.toml index 8ba6dffff0..aabf777eb2 100644 --- a/libp2p-networking/Cargo.toml +++ b/libp2p-networking/Cargo.toml @@ -13,7 +13,7 @@ color-eyre = "0.6.0" crossterm = { version = "0.23.0", features = ["event-stream"] } flume = "0.10.10" futures = "0.3.21" -libp2p = "0.42.2" +libp2p = { version = "0.42.2", features = ["serde"] } parking_lot = "0.12.0" serde = { version = "1.0.136", features = ["derive"] } snafu = "0.7.0" diff --git a/libp2p-networking/examples/clichat.rs b/libp2p-networking/examples/clichat.rs index 740f36a7a4..6afa0a5ed6 100644 --- a/libp2p-networking/examples/clichat.rs +++ b/libp2p-networking/examples/clichat.rs @@ -1,4 +1,4 @@ -use libp2p::{Multiaddr, PeerId}; +use libp2p::Multiaddr; use networking_demo::message::Message; use networking_demo::ui::{run_app, TableApp}; @@ -28,9 +28,6 @@ struct CliOpt { #[structopt(long = "port", short = "p")] port: Option, - #[structopt()] - first_dial_peer_id: Option, - #[structopt()] first_dial_addr: Option, } @@ -52,11 +49,7 @@ async fn main() -> Result<()> { let port = CliOpt::from_args().port.unwrap_or(0u16); let known_peer = CliOpt::from_args().first_dial_addr; let peer_list = if let Some(p) = known_peer { - if let Some(pid) = CliOpt::from_args().first_dial_peer_id { - vec![(pid, p)] - } else { - Vec::new() - } + vec![(None, p)] } else { Vec::new() }; diff --git a/libp2p-networking/examples/common/mod.rs b/libp2p-networking/examples/common/mod.rs new file mode 100644 index 0000000000..728f2bb080 --- /dev/null +++ b/libp2p-networking/examples/common/mod.rs @@ -0,0 +1,286 @@ +use std::{ + collections::HashMap, + sync::{Arc, Once}, + time::Duration, +}; + +use bincode::Options; +use libp2p::{ + build_multiaddr, gossipsub::Topic, request_response::ResponseChannel, Multiaddr, PeerId, +}; +use networking_demo::{ + direct_message::DirectMessageResponse, + network_node::{ClientRequest, NetworkEvent, NetworkNodeConfigBuilder, NetworkNodeType}, + network_node_handle::{ + spawn_handler, spin_up_swarm, NetworkNodeHandle, NetworkNodeHandleError, NetworkSnafu, + NodeConfigSnafu, SendSnafu, SerializationSnafu, + }, + tracing_setup, +}; +use serde::{Deserialize, Serialize}; +use snafu::ResultExt; +use std::fmt::Debug; +use structopt::StructOpt; +use tracing::instrument; + +pub type CounterState = u32; +pub type ControllerState = HashMap; + +/// Normal message types. We can either +/// - increment the Counter +/// - request a counter value +/// - reply with a counter value +#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq)] +pub enum CounterRequest { + IncrementCounter { + from: CounterState, + to: CounterState, + }, + AskForCounter, + MyCounterIs(CounterState), + Kill, + Recvd, +} + +/// overall message +#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq)] +pub enum Message { + /// message to send from a peer to a peer + NormalMessage(CounterRequest), + /// message a conductor sent to a node + /// that the node must send to other node(s) + ConductorMessage(CounterRequest, ConductorMessageMethod), +} + +#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq)] +pub enum ConductorMessageMethod { + Broadcast, + DirectMessage(PeerId), +} + +pub async fn handle_normal_msg( + handle: Arc>, + msg: CounterRequest, + chan: Option>, +) -> Result<(), NetworkNodeHandleError> { + match msg { + // direct message only + CounterRequest::MyCounterIs(c) => { + *handle.state.lock().await = c; + } + // gossip message only + CounterRequest::IncrementCounter { from, to, .. } => { + if *handle.state.lock().await == from { + *handle.state.lock().await = to; + } + } + // only as a response + CounterRequest::AskForCounter => { + if let Some(chan) = chan { + let response = CounterRequest::MyCounterIs(*handle.state.lock().await); + let bincode_options = bincode::DefaultOptions::new().with_limit(16_384); + let serialized_response = bincode_options + .serialize(&response) + .context(SerializationSnafu)?; + handle + .send_network + .send_async(ClientRequest::DirectResponse(chan, serialized_response)) + .await + .context(SendSnafu)? + } + } + CounterRequest::Kill => { + handle.kill().await.context(NetworkSnafu)?; + } + CounterRequest::Recvd => {} + } + Ok(()) +} + +/// event handler for events from the swarm +/// - updates state based on events received +/// - replies to direct messages +#[instrument] +pub async fn regular_handle_network_event( + event: NetworkEvent, + handle: Arc>, +) -> Result<(), NetworkNodeHandleError> { + #[allow(clippy::enum_glob_use)] + use NetworkEvent::*; + let bincode_options = bincode::DefaultOptions::new().with_limit(16_384); + match event { + GossipMsg(m) | DirectResponse(m, _) => { + if let Ok(msg) = bincode_options.deserialize::(&m) { + match msg { + Message::NormalMessage(msg) => { + handle_normal_msg(handle.clone(), msg, None).await?; + } + Message::ConductorMessage(..) => { + // do nothing. We only expect to be reached out to by the conductor via + // direct message + } + } + } + } + DirectRequest(msg, chan) => { + if let Ok(msg) = bincode_options.deserialize::(&msg) { + match msg { + Message::NormalMessage(msg) => { + handle_normal_msg(handle.clone(), msg, Some(chan)).await?; + } + Message::ConductorMessage(msg, method) => { + let serialized_msg = bincode_options + .serialize(&Message::NormalMessage(msg)) + .context(SerializationSnafu)?; + match method { + ConductorMessageMethod::Broadcast => { + handle + .send_network + .send_async(ClientRequest::GossipMsg( + Topic::new("global"), + serialized_msg, + )) + .await + .context(SendSnafu)?; + } + ConductorMessageMethod::DirectMessage(pid) => { + handle + .send_network + .send_async(ClientRequest::DirectRequest(pid, serialized_msg)) + .await + .context(SendSnafu)?; + let response = bincode_options + .serialize(&Message::NormalMessage(CounterRequest::Recvd)) + .context(SerializationSnafu)?; + handle + .send_network + .send_async(ClientRequest::DirectResponse(chan, response)) + .await + .context(SendSnafu)?; + } + } + } + } + } + } + UpdateConnectedPeers(p) => { + handle.connection_state.lock().await.connected_peers = p; + } + UpdateKnownPeers(p) => { + handle.connection_state.lock().await.known_peers = p; + } + } + Ok(()) +} + +#[derive(StructOpt)] +pub struct CliOpt { + /// Path to the node configuration file + #[structopt(long = "index", short = "i")] + pub idx: Option, +} + +const NUM_NODES: usize = 2; +const PORT_NO: u16 = 1234; +const KNOWN_MULTIADDRS: [([u8; 4], u16); NUM_NODES] = [([0, 0, 0, 0], 1234), ([0, 0, 0, 0], 2345)]; +const TIMEOUT: Duration = Duration::from_secs(1000); +static INIT: Once = Once::new(); + +pub async fn start_main_regular( + idx: usize, + node_type: NetworkNodeType, +) -> Result<(), NetworkNodeHandleError> { + INIT.call_once(|| { + color_eyre::install().unwrap(); + tracing_setup::setup_tracing(); + }); + let mut multiaddrs = Vec::<(Option, Multiaddr)>::new(); + for (ip, port) in KNOWN_MULTIADDRS { + multiaddrs.push((None, build_multiaddr!(Ip4(ip), Tcp(port)))); + } + let config = NetworkNodeConfigBuilder::default() + .port(PORT_NO) + .min_num_peers(KNOWN_MULTIADDRS.len() / 4) + .max_num_peers(KNOWN_MULTIADDRS.len() / 2) + .node_type(node_type) + .build() + .context(NodeConfigSnafu)?; + let handle = spin_up_swarm::(TIMEOUT, multiaddrs, config, idx).await?; + + spawn_handler(handle, regular_handle_network_event).await; + + Ok(()) +} + +pub async fn start_main_controller(idx: usize) -> Result<(), NetworkNodeHandleError> { + INIT.call_once(|| { + color_eyre::install().unwrap(); + tracing_setup::setup_tracing(); + }); + let mut multiaddrs = Vec::<(Option, Multiaddr)>::new(); + for (ip, port) in KNOWN_MULTIADDRS { + multiaddrs.push((None, build_multiaddr!(Ip4(ip), Tcp(port)))); + } + let config = NetworkNodeConfigBuilder::default() + .port(PORT_NO) + .min_num_peers(KNOWN_MULTIADDRS.len() / 4) + .max_num_peers(KNOWN_MULTIADDRS.len() / 2) + .node_type(NetworkNodeType::Controller) + .build() + .context(NodeConfigSnafu)?; + let handle = spin_up_swarm::(TIMEOUT, multiaddrs, config, idx).await?; + + spawn_handler(handle, controller_handle_network_event).await; + + // FIXME + // we need two primitives here: + // - tell a node to tell all other nodes to increment state + // - tell a node to broadcast increment state + // then we need to update the state everywhere + + Ok(()) +} + +#[instrument] +pub async fn controller_handle_network_event( + event: NetworkEvent, + handle: Arc>, +) -> Result<(), NetworkNodeHandleError> { + #[allow(clippy::enum_glob_use)] + use NetworkEvent::*; + let bincode_options = bincode::DefaultOptions::new().with_limit(16_384); + match event { + GossipMsg(..) | DirectRequest(..) => { + // this node isn't going to participate. + // it's only purpose is to recv state + } + DirectResponse(m, peer_id) => { + if let Ok(msg) = bincode_options.deserialize::(&m) { + match msg { + Message::NormalMessage(msg) => match msg { + CounterRequest::MyCounterIs(state) => { + let old_state = (*handle.state.lock().await) + .insert(peer_id, state) + .unwrap_or(0); + handle.state_changed.notify_all(); + debug_assert!(old_state < state); + } + _ => {} + }, + Message::ConductorMessage(..) => { + /* This should also never happen ... */ + unreachable!() + } + } + } + } + // we care about these for the sake of maintaining conenctions, but not much else + UpdateConnectedPeers(p) => { + handle.connection_state.lock().await.connected_peers = p; + } + UpdateKnownPeers(p) => { + handle.connection_state.lock().await.known_peers = p; + } + } + Ok(()) +} diff --git a/libp2p-networking/examples/counter_bootstrap.rs b/libp2p-networking/examples/counter_bootstrap.rs new file mode 100644 index 0000000000..d83c70de3b --- /dev/null +++ b/libp2p-networking/examples/counter_bootstrap.rs @@ -0,0 +1,20 @@ +use structopt::StructOpt; + +use color_eyre::eyre::Result; + +use tracing::instrument; + +use networking_demo::network_node::NetworkNodeType; + +mod common; + +#[async_std::main] +#[instrument] +async fn main() -> Result<()> { + common::start_main_regular( + common::CliOpt::from_args().idx.unwrap(), + NetworkNodeType::Regular, + ) + .await?; + Ok(()) +} diff --git a/libp2p-networking/examples/counter_controller.rs b/libp2p-networking/examples/counter_controller.rs new file mode 100644 index 0000000000..ec70697584 --- /dev/null +++ b/libp2p-networking/examples/counter_controller.rs @@ -0,0 +1,16 @@ +use common::{start_main_controller, CliOpt}; + +use structopt::StructOpt; + +use color_eyre::eyre::Result; + +use tracing::instrument; + +mod common; + +#[async_std::main] +#[instrument] +async fn main() -> Result<()> { + start_main_controller(CliOpt::from_args().idx.unwrap()).await?; + Ok(()) +} diff --git a/libp2p-networking/examples/counter_regular.rs b/libp2p-networking/examples/counter_regular.rs new file mode 100644 index 0000000000..d83c70de3b --- /dev/null +++ b/libp2p-networking/examples/counter_regular.rs @@ -0,0 +1,20 @@ +use structopt::StructOpt; + +use color_eyre::eyre::Result; + +use tracing::instrument; + +use networking_demo::network_node::NetworkNodeType; + +mod common; + +#[async_std::main] +#[instrument] +async fn main() -> Result<()> { + common::start_main_regular( + common::CliOpt::from_args().idx.unwrap(), + NetworkNodeType::Regular, + ) + .await?; + Ok(()) +} diff --git a/libp2p-networking/grcov.sh b/libp2p-networking/grcov.sh new file mode 100644 index 0000000000..43fd2b7eea --- /dev/null +++ b/libp2p-networking/grcov.sh @@ -0,0 +1,8 @@ +#!/usr/bin/env bash +rm -rf target/ +export CARGO_INCREMENTAL=0 +export RUSTFLAGS="-Zprofile -Ccodegen-units=1 -Copt-level=0 -Clink-dead-code -Coverflow-checks=off -Zpanic_abort_tests -Cpanic=abort" +export RUSTDOCFLAGS="-Cpanic=abort" +cargo build +cargo test +grcov . -s . --binary-path ./target/debug/ -t html --branch --ignore-not-existing -o ./target/debug/coverage/ diff --git a/libp2p-networking/repl.nix b/libp2p-networking/repl.nix new file mode 100644 index 0000000000..a8028d7d3e --- /dev/null +++ b/libp2p-networking/repl.nix @@ -0,0 +1,8 @@ +let + flake = builtins.getFlake (toString ./.); +in + { + inherit flake; + self = flake.inputs.self; + pkgs = flake.inputs.nixpkgs.legacyPackages; + } diff --git a/libp2p-networking/src/network_node.rs b/libp2p-networking/src/network_node.rs index 68ea3899ae..786dd6d7e2 100644 --- a/libp2p-networking/src/network_node.rs +++ b/libp2p-networking/src/network_node.rs @@ -1,6 +1,7 @@ use crate::direct_message::{DirectMessageCodec, DirectMessageRequest, DirectMessageResponse}; use async_std::task::{sleep, spawn}; use libp2p::request_response::RequestId; +use libp2p::swarm::DialError; use rand::{seq::IteratorRandom, thread_rng}; use std::collections::HashMap; use std::fmt::Debug; @@ -96,6 +97,9 @@ pub struct NetworkDef { /// track gossip messages that failed to send and we should send later on #[behaviour(ignore)] in_progress_gossip: Vec<(Topic, Vec)>, + // track unknown addrs + #[behaviour(ignore)] + unknown_addrs: HashSet, } impl Debug for NetworkDef { @@ -242,9 +246,12 @@ impl NetworkBehaviourEventProcess { - self.in_progress_rr.remove(&request_id); - self.client_event_queue - .push(NetworkEvent::DirectResponse(msg)); + if let Some((_, peer_id)) = self.in_progress_rr.remove(&request_id) { + self.client_event_queue + .push(NetworkEvent::DirectResponse(msg, peer_id)); + } else { + error!("recv-ed a direct response, but is no longer tracking message!"); + } } }, e @ RequestResponseEvent::ResponseSent { .. } => { @@ -263,6 +270,8 @@ pub enum NetworkNodeType { /// regular node has a limit to the /// number of connections to accept Regular, + /// controller node is never pruned + Controller, } impl Default for NetworkNodeType { @@ -296,6 +305,8 @@ pub struct NetworkNodeConfig { /// Either bootstrap (greedily connect to all peers) /// or regular (respect `min_num_peers`/`max num peers`) pub node_type: NetworkNodeType, + /// The port to bind to + pub port: u16, } impl Debug for NetworkNode { @@ -327,8 +338,8 @@ pub enum ClientRequest { DirectResponse(ResponseChannel, Vec), /// disable or enable pruning of connections Pruning(bool), - /// add vec of known peers - AddKnownPeers(Vec<(PeerId, Multiaddr)>), + /// add vec of known peers or addresses + AddKnownPeers(Vec<(Option, Multiaddr)>), } /// events generated by the swarm that we wish @@ -344,7 +355,7 @@ pub enum NetworkEvent { /// recv-ed a direct message from a node DirectRequest(Vec, ResponseChannel), /// recv-ed a direct response from a node - DirectResponse(Vec), + DirectResponse(Vec, PeerId), } /// bind all interfaces on port `port` @@ -414,16 +425,28 @@ impl NetworkNode { /// the `spawn_listeners` function /// will start connecting to peers #[instrument(skip(self))] - pub async fn add_known_peers(&mut self, known_peers: &[(PeerId, Multiaddr)]) { + pub async fn add_known_peers(&mut self, known_peers: &[(Option, Multiaddr)]) { for (peer_id, addr) in known_peers { - if *peer_id != self.peer_id { - // FIXME why can't I pattern match this? - self.swarm - .behaviour_mut() - .kadem - .add_address(peer_id, addr.clone()); + match peer_id { + Some(peer_id) => { + // if we know the peerid, add address. + // if we don't know the peerid, dial to find out what the peerid is + if *peer_id != self.peer_id { + // FIXME why can't I pattern match this? + self.swarm + .behaviour_mut() + .kadem + .add_address(peer_id, addr.clone()); + } + self.swarm.behaviour_mut().known_peers.insert(*peer_id); + } + None => { + self.swarm + .behaviour_mut() + .unknown_addrs + .insert(addr.clone()); + } } - self.swarm.behaviour_mut().known_peers.insert(*peer_id); } let new_peers = self.swarm.behaviour().known_peers.clone(); self.swarm @@ -515,6 +538,7 @@ impl NetworkNode { pruning_enabled, in_progress_rr: HashMap::new(), in_progress_gossip: Vec::new(), + unknown_addrs: HashSet::new(), }; Swarm::new(transport, network, peer_id) @@ -568,12 +592,12 @@ impl NetworkNode { .copied() .choose_multiple(&mut thread_rng(), num_to_connect); // Try dialing each random peer - for a_peer in chosen_peers { - if a_peer != self.peer_id { - match self.swarm.dial(a_peer) { + for a_peer in &chosen_peers.clone() { + if *a_peer != self.peer_id { + match self.swarm.dial(*a_peer) { Ok(_) => { info!("Peer {:?} dial {:?} working!", self.peer_id, a_peer); - self.swarm.behaviour_mut().connecting_peers.insert(a_peer); + self.swarm.behaviour_mut().connecting_peers.insert(*a_peer); } Err(e) => { info!("Peer {:?} dial {:?} failed: {:?}", self.peer_id, a_peer, e); @@ -581,8 +605,34 @@ impl NetworkNode { }; } } + + // if we don't know any peers, start dialing random peers if we have any. + if chosen_peers.is_empty() { + let chosen_addrs = self + .swarm + .behaviour_mut() + .unknown_addrs + .iter() + .cloned() + .choose_multiple(&mut thread_rng(), num_to_connect); + for a_addr in chosen_addrs { + match self.swarm.dial(a_addr.clone()) { + Ok(_) => { + info!("Peer {:?} dial {:?} working!", self.peer_id, a_addr); + } + Err(e) => { + info!("Peer {:?} dial {:?} failed: {:?}", self.peer_id, a_addr, e); + } + } + } + } } } + // + // /// directly dial a peer + // pub async fn dial_peer(&mut self, addr: Multiaddr) -> Result<(), NetworkError> { + // self.swarm.dial(addr).context(DialSnafu) + // } #[instrument(skip(self))] fn prune_num_connections(&mut self) { @@ -634,7 +684,7 @@ impl NetworkNode { warn!("Libp2p listener shutting down"); return Ok(true); } - ClientRequest::GossipMsg(topic, contents) => { + GossipMsg(topic, contents) => { // TODO might be better just to push this into the queue and not try to // send here let res = self @@ -742,7 +792,8 @@ impl NetworkNode { self.swarm .behaviour_mut() .kadem - .add_address(&peer_id, address); + .add_address(&peer_id, address.clone()); + self.swarm.behaviour_mut().unknown_addrs.remove(&address); } ConnectedPoint::Listener { local_addr: _, @@ -751,7 +802,11 @@ impl NetworkNode { self.swarm .behaviour_mut() .kadem - .add_address(&peer_id, send_back_addr); + .add_address(&peer_id, send_back_addr.clone()); + self.swarm + .behaviour_mut() + .unknown_addrs + .remove(&send_back_addr); } } self.swarm.behaviour_mut().connected_peers.insert(peer_id); @@ -879,6 +934,11 @@ impl NetworkNode { /// wrapper type for errors generated by the `Network` #[derive(Debug, Snafu)] pub enum NetworkError { + /// Error initiating dial of peer + DialError { + /// The underlying source of the error + source: DialError, + }, /// Error during dialing or listening Transport { /// The underlying source of the error diff --git a/libp2p-networking/src/network_node_handle.rs b/libp2p-networking/src/network_node_handle.rs index 9bb63dcbcb..edc3d6d118 100644 --- a/libp2p-networking/src/network_node_handle.rs +++ b/libp2p-networking/src/network_node_handle.rs @@ -1,4 +1,5 @@ use async_std::{ + future::{timeout, TimeoutError}, sync::{Condvar, Mutex}, task::spawn, }; @@ -12,7 +13,7 @@ use futures::{select, Future, FutureExt}; use libp2p::{Multiaddr, PeerId}; use rand::{seq::IteratorRandom, thread_rng}; use snafu::{ResultExt, Snafu}; -use std::{fmt::Debug, sync::Arc}; +use std::{fmt::Debug, sync::Arc, time::Duration}; use tracing::{info_span, instrument, Instrument}; /// A handle containing: @@ -98,7 +99,7 @@ impl NetworkNodeHandle { node: Arc>, num_peers: usize, chan: Receiver, - node_idx: usize, + _node_idx: usize, ) -> Result<(), NetworkNodeHandleError> { let mut connected_ok = false; let mut known_ok = false; @@ -157,6 +158,43 @@ pub async fn spawn_handler( ); } +/// a single node, connects them to each other +/// and waits for connections to propagate to all nodes. +#[instrument] +pub async fn spin_up_swarm( + timeout_len: Duration, + known_nodes: Vec<(Option, Multiaddr)>, + config: NetworkNodeConfig, + idx: usize, +) -> Result>, NetworkNodeHandleError> { + let handle = Arc::new(NetworkNodeHandle::new(config, idx).await?); + + handle + .send_network + .send_async(ClientRequest::AddKnownPeers(known_nodes)) + .await + .context(SendSnafu)?; + + let _result = timeout( + timeout_len, + NetworkNodeHandle::wait_to_connect( + handle.clone(), + config.max_num_peers, + handle.recv_network.clone(), + idx, + ), + ) + .await + .context(TimeoutSnafu)??; + handle + .send_network + .send_async(ClientRequest::Subscribe("global".to_string())) + .await + .context(SendSnafu)?; + + Ok(handle) +} + /// Given a slice of handles assumed to be larger than 0, /// chooses one /// # Panics @@ -165,28 +203,28 @@ pub fn get_random_handle(handles: &[Arc>]) -> Arc, }, - /// failure to deserialize a message + /// Failure to deserialize a message DeserializationError {}, - /// error sending request to network + /// Error sending request to network SendError { /// source of error source: SendError, }, - /// error receiving message from network + /// Error receiving message from network RecvError { /// source of error source: RecvError, @@ -196,4 +234,9 @@ pub enum NetworkNodeHandleError { /// source of error source: NetworkNodeConfigBuilderError, }, + /// Error waiting for connections + TimeoutError { + /// source of error + source: TimeoutError, + }, } diff --git a/libp2p-networking/src/ui.rs b/libp2p-networking/src/ui.rs index a684b096af..04c7b105bd 100644 --- a/libp2p-networking/src/ui.rs +++ b/libp2p-networking/src/ui.rs @@ -119,7 +119,7 @@ pub async fn run_app(terminal: &mut Terminal, mut app: TableApp) UpdateKnownPeers(peer_set) => { *app.known_peer_list.lock() = peer_set.clone(); } - DirectResponse(_) => { /* NOTE unimplemented in this example */ } + DirectResponse(..) => { /* NOTE unimplemented in this example */ } } } }, diff --git a/libp2p-networking/tests/common/mod.rs b/libp2p-networking/tests/common/mod.rs index 3fc3c86141..308fae186d 100644 --- a/libp2p-networking/tests/common/mod.rs +++ b/libp2p-networking/tests/common/mod.rs @@ -172,6 +172,7 @@ pub async fn spin_up_swarms( } let regular_node_config = NetworkNodeConfigBuilder::default() + .port(0) .node_type(NetworkNodeType::Regular) .min_num_peers(min_num_peers) .max_num_peers(max_num_peers) @@ -203,7 +204,12 @@ pub async fn spin_up_swarms( for handle in &handles { handle .send_network - .send_async(ClientRequest::AddKnownPeers(bootstrap_addrs.clone())) + .send_async(ClientRequest::AddKnownPeers( + bootstrap_addrs + .iter() + .map(|(a, b)| (Some(a.clone()), b.clone())) + .collect::>(), + )) .await .context(SendSnafu) .context(HandleSnafu)?; diff --git a/libp2p-networking/tests/counter.rs b/libp2p-networking/tests/counter.rs index 0a74a8b78b..76ef842941 100644 --- a/libp2p-networking/tests/counter.rs +++ b/libp2p-networking/tests/counter.rs @@ -52,24 +52,27 @@ pub async fn counter_handle_network_event( event: NetworkEvent, handle: Arc>, ) -> Result<(), NetworkNodeHandleError> { - use CounterMessage::*; #[allow(clippy::enum_glob_use)] + use CounterMessage::*; use NetworkEvent::*; let bincode_options = bincode::DefaultOptions::new().with_limit(16_384); match event { - GossipMsg(m) | DirectResponse(m) => { + GossipMsg(m) | DirectResponse(m, _) => { if let Ok(msg) = bincode_options.deserialize::(&m) { match msg { + // direct message only MyCounterIs(c) => { *handle.state.lock().await = c; handle.state_changed.notify_all(); } + // gossip message only IncrementCounter { from, to, .. } => { if *handle.state.lock().await == from { *handle.state.lock().await = to; handle.state_changed.notify_all(); } } + // only as a response AskForCounter => {} } } @@ -77,12 +80,14 @@ pub async fn counter_handle_network_event( DirectRequest(m, chan) => { if let Ok(msg) = bincode_options.deserialize::(&m) { match msg { + // direct message request IncrementCounter { from, to, .. } => { if *handle.state.lock().await == from { *handle.state.lock().await = to; handle.state_changed.notify_all(); } } + // direct message response AskForCounter => { let response = MyCounterIs(*handle.state.lock().await); let serialized_response = bincode_options From 5a8337a164848097bfe2425308598e453a0fc1cf Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 18 Feb 2022 04:38:49 +0000 Subject: [PATCH 082/107] chore(deps): bump tracing-subscriber from 0.3.8 to 0.3.9 Bumps [tracing-subscriber](https://github.com/tokio-rs/tracing) from 0.3.8 to 0.3.9. - [Release notes](https://github.com/tokio-rs/tracing/releases) - [Commits](https://github.com/tokio-rs/tracing/compare/tracing-subscriber-0.3.8...tracing-subscriber-0.3.9) --- updated-dependencies: - dependency-name: tracing-subscriber dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- libp2p-networking/Cargo.lock | 4 ++-- libp2p-networking/Cargo.toml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/libp2p-networking/Cargo.lock b/libp2p-networking/Cargo.lock index 5284caf7c0..ffbb98bf69 100644 --- a/libp2p-networking/Cargo.lock +++ b/libp2p-networking/Cargo.lock @@ -3330,9 +3330,9 @@ dependencies = [ [[package]] name = "tracing-subscriber" -version = "0.3.8" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74786ce43333fcf51efe947aed9718fbe46d5c7328ec3f1029e818083966d9aa" +checksum = "9e0ab7bdc962035a87fba73f3acca9b8a8d0034c2e6f60b84aeaaddddc155dce" dependencies = [ "ansi_term", "lazy_static", diff --git a/libp2p-networking/Cargo.toml b/libp2p-networking/Cargo.toml index 7245532f08..60d4c34697 100644 --- a/libp2p-networking/Cargo.toml +++ b/libp2p-networking/Cargo.toml @@ -20,7 +20,7 @@ snafu = "0.7.0" structopt = "0.3.26" tracing = "0.1.30" tracing-error = "0.2.0" -tracing-subscriber = { version = "0.3.8", features = ["env-filter", "json"] } +tracing-subscriber = { version = "0.3.9", features = ["env-filter", "json"] } tui = { version = "0.17.0", features = ["crossterm"], default-features = false } rand = "0.8.5" async-trait = "0.1.52" From e74f4df78c274e309fe0df076eebf791363bfe3b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 18 Feb 2022 04:38:56 +0000 Subject: [PATCH 083/107] chore(deps): bump tracing from 0.1.30 to 0.1.31 Bumps [tracing](https://github.com/tokio-rs/tracing) from 0.1.30 to 0.1.31. - [Release notes](https://github.com/tokio-rs/tracing/releases) - [Commits](https://github.com/tokio-rs/tracing/compare/tracing-0.1.30...tracing-0.1.31) --- updated-dependencies: - dependency-name: tracing dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- libp2p-networking/Cargo.lock | 4 ++-- libp2p-networking/Cargo.toml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/libp2p-networking/Cargo.lock b/libp2p-networking/Cargo.lock index 5284caf7c0..4782219e33 100644 --- a/libp2p-networking/Cargo.lock +++ b/libp2p-networking/Cargo.lock @@ -3266,9 +3266,9 @@ dependencies = [ [[package]] name = "tracing" -version = "0.1.30" +version = "0.1.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d8d93354fe2a8e50d5953f5ae2e47a3fc2ef03292e7ea46e3cc38f549525fb9" +checksum = "f6c650a8ef0cd2dd93736f033d21cbd1224c5a967aa0c258d00fcf7dafef9b9f" dependencies = [ "cfg-if", "pin-project-lite 0.2.8", diff --git a/libp2p-networking/Cargo.toml b/libp2p-networking/Cargo.toml index 7245532f08..ceb0c37d6d 100644 --- a/libp2p-networking/Cargo.toml +++ b/libp2p-networking/Cargo.toml @@ -18,7 +18,7 @@ parking_lot = "0.12.0" serde = { version = "1.0.136", features = ["derive"] } snafu = "0.7.0" structopt = "0.3.26" -tracing = "0.1.30" +tracing = "0.1.31" tracing-error = "0.2.0" tracing-subscriber = { version = "0.3.8", features = ["env-filter", "json"] } tui = { version = "0.17.0", features = ["crossterm"], default-features = false } From 14fdf90fff8e1e943673a66d5500a020f76026eb Mon Sep 17 00:00:00 2001 From: Justin Restivo Date: Fri, 18 Feb 2022 09:19:00 -0500 Subject: [PATCH 084/107] feat: parsing config file --- libp2p-networking/Cargo.lock | 5 +- libp2p-networking/Cargo.toml | 1 + libp2p-networking/examples/common/mod.rs | 209 ++++++++++++------ .../examples/counter_bootstrap.rs | 20 -- .../examples/counter_controller.rs | 16 -- libp2p-networking/examples/counter_regular.rs | 20 -- libp2p-networking/examples/identities.rs | 43 ++++ libp2p-networking/identity_mapping.json | 52 +++++ libp2p-networking/src/lib.rs | 3 + libp2p-networking/src/network_node.rs | 49 +++- libp2p-networking/src/network_node_handle.rs | 10 +- libp2p-networking/src/parse_config.rs | 58 +++++ libp2p-networking/tests/common/mod.rs | 3 +- 13 files changed, 352 insertions(+), 137 deletions(-) delete mode 100644 libp2p-networking/examples/counter_bootstrap.rs delete mode 100644 libp2p-networking/examples/counter_controller.rs delete mode 100644 libp2p-networking/examples/counter_regular.rs create mode 100644 libp2p-networking/examples/identities.rs create mode 100644 libp2p-networking/identity_mapping.json create mode 100644 libp2p-networking/src/parse_config.rs diff --git a/libp2p-networking/Cargo.lock b/libp2p-networking/Cargo.lock index c30ba8d3e4..a64c006c81 100644 --- a/libp2p-networking/Cargo.lock +++ b/libp2p-networking/Cargo.lock @@ -2192,6 +2192,7 @@ dependencies = [ "parking_lot 0.12.0", "rand 0.8.4", "serde", + "serde_json", "snafu", "structopt", "tracing", @@ -2890,9 +2891,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.74" +version = "1.0.79" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee2bb9cd061c5865d345bb02ca49fcef1391741b672b54a0bf7b679badec3142" +checksum = "8e8d9fa5c3b304765ce1fd9c4c8a3de2c8db365a5b91be52f186efc675681d95" dependencies = [ "itoa", "ryu", diff --git a/libp2p-networking/Cargo.toml b/libp2p-networking/Cargo.toml index aabf777eb2..68f3647437 100644 --- a/libp2p-networking/Cargo.toml +++ b/libp2p-networking/Cargo.toml @@ -16,6 +16,7 @@ futures = "0.3.21" libp2p = { version = "0.42.2", features = ["serde"] } parking_lot = "0.12.0" serde = { version = "1.0.136", features = ["derive"] } +serde_json = "1.0.79" snafu = "0.7.0" structopt = "0.3.26" tracing = "0.1.30" diff --git a/libp2p-networking/examples/common/mod.rs b/libp2p-networking/examples/common/mod.rs index 728f2bb080..ad8ef4c181 100644 --- a/libp2p-networking/examples/common/mod.rs +++ b/libp2p-networking/examples/common/mod.rs @@ -1,30 +1,38 @@ +use networking_demo::parse_config::NodeDescription; use std::{ collections::HashMap, sync::{Arc, Once}, time::Duration, }; -use bincode::Options; -use libp2p::{ - build_multiaddr, gossipsub::Topic, request_response::ResponseChannel, Multiaddr, PeerId, -}; +use async_std::fs::File; +use futures::AsyncReadExt; +use libp2p::{gossipsub::Topic, request_response::ResponseChannel, PeerId}; use networking_demo::{ direct_message::DirectMessageResponse, - network_node::{ClientRequest, NetworkEvent, NetworkNodeConfigBuilder, NetworkNodeType}, + network_node::{ + deserialize_msg, serialize_msg, ClientRequest, NetworkEvent, NetworkNodeConfigBuilder, + NetworkNodeType, + }, network_node_handle::{ spawn_handler, spin_up_swarm, NetworkNodeHandle, NetworkNodeHandleError, NetworkSnafu, NodeConfigSnafu, SendSnafu, SerializationSnafu, }, tracing_setup, }; +use rand::{seq::IteratorRandom, thread_rng}; use serde::{Deserialize, Serialize}; use snafu::ResultExt; use std::fmt::Debug; use structopt::StructOpt; use tracing::instrument; +const TIMEOUT: Duration = Duration::from_secs(1000); +static INIT: Once = Once::new(); +const PORT_NO: u16 = 1234; + pub type CounterState = u32; -pub type ControllerState = HashMap; +pub type ConductorState = HashMap; /// Normal message types. We can either /// - increment the Counter @@ -78,10 +86,7 @@ pub async fn handle_normal_msg( CounterRequest::AskForCounter => { if let Some(chan) = chan { let response = CounterRequest::MyCounterIs(*handle.state.lock().await); - let bincode_options = bincode::DefaultOptions::new().with_limit(16_384); - let serialized_response = bincode_options - .serialize(&response) - .context(SerializationSnafu)?; + let serialized_response = serialize_msg(&response).context(SerializationSnafu)?; handle .send_network .send_async(ClientRequest::DirectResponse(chan, serialized_response)) @@ -107,10 +112,9 @@ pub async fn regular_handle_network_event( ) -> Result<(), NetworkNodeHandleError> { #[allow(clippy::enum_glob_use)] use NetworkEvent::*; - let bincode_options = bincode::DefaultOptions::new().with_limit(16_384); match event { GossipMsg(m) | DirectResponse(m, _) => { - if let Ok(msg) = bincode_options.deserialize::(&m) { + if let Ok(msg) = deserialize_msg::(&m) { match msg { Message::NormalMessage(msg) => { handle_normal_msg(handle.clone(), msg, None).await?; @@ -123,14 +127,13 @@ pub async fn regular_handle_network_event( } } DirectRequest(msg, chan) => { - if let Ok(msg) = bincode_options.deserialize::(&msg) { + if let Ok(msg) = deserialize_msg::(&msg) { match msg { Message::NormalMessage(msg) => { handle_normal_msg(handle.clone(), msg, Some(chan)).await?; } Message::ConductorMessage(msg, method) => { - let serialized_msg = bincode_options - .serialize(&Message::NormalMessage(msg)) + let serialized_msg = serialize_msg(&Message::NormalMessage(msg)) .context(SerializationSnafu)?; match method { ConductorMessageMethod::Broadcast => { @@ -149,9 +152,9 @@ pub async fn regular_handle_network_event( .send_async(ClientRequest::DirectRequest(pid, serialized_msg)) .await .context(SendSnafu)?; - let response = bincode_options - .serialize(&Message::NormalMessage(CounterRequest::Recvd)) - .context(SerializationSnafu)?; + let response = + serialize_msg(&Message::NormalMessage(CounterRequest::Recvd)) + .context(SerializationSnafu)?; handle .send_network .send_async(ClientRequest::DirectResponse(chan, response)) @@ -180,82 +183,152 @@ pub struct CliOpt { pub idx: Option, } -const NUM_NODES: usize = 2; -const PORT_NO: u16 = 1234; -const KNOWN_MULTIADDRS: [([u8; 4], u16); NUM_NODES] = [([0, 0, 0, 0], 1234), ([0, 0, 0, 0], 2345)]; -const TIMEOUT: Duration = Duration::from_secs(1000); -static INIT: Once = Once::new(); +pub async fn parse_config() -> Vec { + let mut f = File::open(&"./identity_mapping.json").await.unwrap(); + let mut s = String::new(); + f.read_to_string(&mut s).await.unwrap(); + let res: Vec = serde_json::from_str(&s).unwrap(); + res +} -pub async fn start_main_regular( - idx: usize, - node_type: NetworkNodeType, -) -> Result<(), NetworkNodeHandleError> { +pub async fn start_main(idx: usize) -> Result<(), NetworkNodeHandleError> { INIT.call_once(|| { color_eyre::install().unwrap(); tracing_setup::setup_tracing(); }); - let mut multiaddrs = Vec::<(Option, Multiaddr)>::new(); - for (ip, port) in KNOWN_MULTIADDRS { - multiaddrs.push((None, build_multiaddr!(Ip4(ip), Tcp(port)))); - } - let config = NetworkNodeConfigBuilder::default() - .port(PORT_NO) - .min_num_peers(KNOWN_MULTIADDRS.len() / 4) - .max_num_peers(KNOWN_MULTIADDRS.len() / 2) - .node_type(node_type) - .build() - .context(NodeConfigSnafu)?; - let handle = spin_up_swarm::(TIMEOUT, multiaddrs, config, idx).await?; + let swarm_config = parse_config().await; + + let node_description = &swarm_config[idx]; + + match node_description.node_type { + NetworkNodeType::Conductor => { + let config = NetworkNodeConfigBuilder::default() + .port(PORT_NO) + .min_num_peers(swarm_config.len() - 1) + .max_num_peers(swarm_config.len() - 1) + .node_type(NetworkNodeType::Conductor) + .identity(Some(swarm_config[idx].identity.clone())) + .build() + .context(NodeConfigSnafu)?; + let handle = spin_up_swarm::( + TIMEOUT, + swarm_config + .iter() + .map(|c| (Some(c.identity.public().to_peer_id()), c.multiaddr.clone())) + .collect::>(), + config, + idx, + ) + .await?; + spawn_handler(handle.clone(), conductor_handle_network_event).await; + let mut state = handle.state.lock().await; + for (i, connection) in swarm_config.iter().enumerate() { + if i != idx { + state.insert(connection.identity.public().to_peer_id(), 0); + } + } + drop(state); + + // FIXME we are in desperate need of a error type like TestError + conductor_broadcast(TIMEOUT, 0, handle).await.unwrap(); - spawn_handler(handle, regular_handle_network_event).await; + // FIXME we need to fix clippy warnings + + // FIXME we need to fix the serialization to do error handling properly + + // FIXME we need to convince the inner networking implementation to ignore the conductor nodes + + // FIXME + // we need one other primitive here: + // - tell a node to tell all other nodes to increment state with direct message + + // FIXME we have a bunch of nodes all on the same port. Don't use global variable for + // this. + } + _ => { + let known_peers = swarm_config + .iter() + .filter_map(|x| { + // TODO this is gross. Make this a data structure + if x.node_type == NetworkNodeType::Bootstrap { + Some((Some(x.identity.public().to_peer_id()), x.multiaddr.clone())) + } else { + None + } + }) + .collect::>(); + let config = NetworkNodeConfigBuilder::default() + .port(PORT_NO) + .min_num_peers(swarm_config.len() / 4) + .max_num_peers(swarm_config.len() / 2) + .node_type(node_description.node_type) + .build() + .context(NodeConfigSnafu)?; + let handle = spin_up_swarm::(TIMEOUT, known_peers, config, idx).await?; + spawn_handler(handle, regular_handle_network_event).await; + } + } Ok(()) } -pub async fn start_main_controller(idx: usize) -> Result<(), NetworkNodeHandleError> { - INIT.call_once(|| { - color_eyre::install().unwrap(); - tracing_setup::setup_tracing(); - }); - let mut multiaddrs = Vec::<(Option, Multiaddr)>::new(); - for (ip, port) in KNOWN_MULTIADDRS { - multiaddrs.push((None, build_multiaddr!(Ip4(ip), Tcp(port)))); - } - let config = NetworkNodeConfigBuilder::default() - .port(PORT_NO) - .min_num_peers(KNOWN_MULTIADDRS.len() / 4) - .max_num_peers(KNOWN_MULTIADDRS.len() / 2) - .node_type(NetworkNodeType::Controller) - .build() - .context(NodeConfigSnafu)?; - let handle = spin_up_swarm::(TIMEOUT, multiaddrs, config, idx).await?; +pub async fn conductor_broadcast( + timeout: Duration, + state: CounterState, + handle: Arc>, +) -> Result<(), NetworkNodeHandleError> { + // start listener future with timeout + // + let new_state = state + 1; + // + let mut known_peers = handle.connection_state.lock().await.known_peers.clone(); + known_peers.remove(&handle.peer_id); - spawn_handler(handle, controller_handle_network_event).await; + // FIXME wrapper error + let chosen_peer = known_peers.iter().choose(&mut thread_rng()).unwrap(); - // FIXME - // we need two primitives here: - // - tell a node to tell all other nodes to increment state - // - tell a node to broadcast increment state - // then we need to update the state everywhere + // increment the state + let request = CounterRequest::IncrementCounter { + from: state, + to: new_state, + }; + // broadcast message + let msg = Message::ConductorMessage(request, ConductorMessageMethod::Broadcast); + let serialized_msg = serialize_msg(&msg).context(SerializationSnafu)?; + handle + .send_network + .send_async(ClientRequest::DirectRequest(*chosen_peer, serialized_msg)) + .await + .context(SendSnafu)?; - Ok(()) + let (_, res) = handle + .state_changed + .wait_timeout_until(handle.state.lock().await, timeout, |state| { + state.iter().all(|(_, &s)| s == new_state) + }) + .await; + + if res.timed_out() { + panic!("timeout!"); + } else { + Ok(()) + } } #[instrument] -pub async fn controller_handle_network_event( +pub async fn conductor_handle_network_event( event: NetworkEvent, - handle: Arc>, + handle: Arc>, ) -> Result<(), NetworkNodeHandleError> { #[allow(clippy::enum_glob_use)] use NetworkEvent::*; - let bincode_options = bincode::DefaultOptions::new().with_limit(16_384); match event { GossipMsg(..) | DirectRequest(..) => { // this node isn't going to participate. // it's only purpose is to recv state } DirectResponse(m, peer_id) => { - if let Ok(msg) = bincode_options.deserialize::(&m) { + if let Ok(msg) = deserialize_msg::(&m) { match msg { Message::NormalMessage(msg) => match msg { CounterRequest::MyCounterIs(state) => { diff --git a/libp2p-networking/examples/counter_bootstrap.rs b/libp2p-networking/examples/counter_bootstrap.rs deleted file mode 100644 index d83c70de3b..0000000000 --- a/libp2p-networking/examples/counter_bootstrap.rs +++ /dev/null @@ -1,20 +0,0 @@ -use structopt::StructOpt; - -use color_eyre::eyre::Result; - -use tracing::instrument; - -use networking_demo::network_node::NetworkNodeType; - -mod common; - -#[async_std::main] -#[instrument] -async fn main() -> Result<()> { - common::start_main_regular( - common::CliOpt::from_args().idx.unwrap(), - NetworkNodeType::Regular, - ) - .await?; - Ok(()) -} diff --git a/libp2p-networking/examples/counter_controller.rs b/libp2p-networking/examples/counter_controller.rs deleted file mode 100644 index ec70697584..0000000000 --- a/libp2p-networking/examples/counter_controller.rs +++ /dev/null @@ -1,16 +0,0 @@ -use common::{start_main_controller, CliOpt}; - -use structopt::StructOpt; - -use color_eyre::eyre::Result; - -use tracing::instrument; - -mod common; - -#[async_std::main] -#[instrument] -async fn main() -> Result<()> { - start_main_controller(CliOpt::from_args().idx.unwrap()).await?; - Ok(()) -} diff --git a/libp2p-networking/examples/counter_regular.rs b/libp2p-networking/examples/counter_regular.rs deleted file mode 100644 index d83c70de3b..0000000000 --- a/libp2p-networking/examples/counter_regular.rs +++ /dev/null @@ -1,20 +0,0 @@ -use structopt::StructOpt; - -use color_eyre::eyre::Result; - -use tracing::instrument; - -use networking_demo::network_node::NetworkNodeType; - -mod common; - -#[async_std::main] -#[instrument] -async fn main() -> Result<()> { - common::start_main_regular( - common::CliOpt::from_args().idx.unwrap(), - NetworkNodeType::Regular, - ) - .await?; - Ok(()) -} diff --git a/libp2p-networking/examples/identities.rs b/libp2p-networking/examples/identities.rs new file mode 100644 index 0000000000..a91d0f947e --- /dev/null +++ b/libp2p-networking/examples/identities.rs @@ -0,0 +1,43 @@ +use async_std::fs::File; +use futures::AsyncReadExt; +use libp2p::{identity::Keypair, Multiaddr, PeerId}; +use networking_demo::parse_config::NodeDescription; +use tracing::instrument; + +#[async_std::main] +#[instrument] +async fn main() { + parse_ids().await; +} + +pub async fn parse_ids() { + let mut f = File::open(&"./identity_mapping.json").await.unwrap(); + let mut s = String::new(); + f.read_to_string(&mut s).await.unwrap(); + println!("s{}", s); + let foo: Vec = serde_json::from_str(&s).unwrap(); + println!( + "{:?}", + foo.iter() + .map(|id| id.identity.public().to_peer_id()) + .collect::>() + ); + println!( + "{:?}", + foo.iter() + .map(|id| id.multiaddr.clone()) + .collect::>() + ); + println!( + "{:?}", + foo.iter().map(|id| id.node_type).collect::>() + ); +} + +pub async fn gen_ids() { + for _i in 0..10 { + let identity = Keypair::generate_ed25519(); + let pbuf_encoding = identity.to_protobuf_encoding().unwrap(); + println!("{:?}", pbuf_encoding); + } +} diff --git a/libp2p-networking/identity_mapping.json b/libp2p-networking/identity_mapping.json new file mode 100644 index 0000000000..44f504b747 --- /dev/null +++ b/libp2p-networking/identity_mapping.json @@ -0,0 +1,52 @@ +[ + { + "identity": [8, 1, 18, 64, 192, 235, 232, 64, 137, 178, 181, 217, 34, 70, 59, 32, 35, 193, 254, 194, 148, 154, 101, 168, 113, 144, 23, 125, 60, 34, 176, 91, 190, 213, 214, 30, 46, 217, 99, 68, 172, 148, 59, 128, 61, 36, 129, 138, 22, 163, 255, 13, 239, 88, 131, 43, 18, 75, 129, 165, 88, 80, 226, 94, 40, 154, 61, 137], + "multiaddr": "/ip4/0.0.0.0/tcp/9000", + "node_type" : "Conductor" + }, + { + "identity": [8, 1, 18, 64, 84, 243, 22, 74, 173, 227, 68, 200, 15, 52, 197, 125, 17, 133, 238, 75, 164, 25, 113, 80, 102, 119, 109, 8, 13, 224, 63, 159, 101, 252, 25, 187, 32, 130, 182, 245, 37, 72, 204, 137, 39, 142, 16, 188, 170, 252, 104, 187, 91, 65, 179, 149, 102, 199, 5, 180, 176, 0, 241, 36, 57, 179, 118, 83], + "multiaddr": "/ip4/0.0.0.0/tcp/9001", + "node_type" : "Bootstrap" + }, + { + "identity": [8, 1, 18, 64, 223, 223, 83, 162, 199, 9, 104, 81, 205, 65, 103, 28, 91, 139, 83, 227, 119, 73, 39, 238, 143, 77, 250, 48, 145, 63, 49, 12, 36, 51, 111, 214, 251, 44, 78, 17, 232, 147, 120, 38, 118, 7, 41, 49, 162, 6, 91, 175, 41, 194, 12, 22, 22, 16, 37, 154, 226, 22, 16, 63, 250, 224, 109, 94], + "multiaddr": "/ip4/0.0.0.0/tcp/9002", + "node_type" : "Bootstrap" + }, + { + "identity": [8, 1, 18, 64, 150, 246, 56, 246, 0, 14, 60, 3, 218, 212, 188, 101, 137, 53, 110, 27, 20, 78, 42, 56, 138, 236, 25, 234, 210, 49, 193, 59, 129, 88, 35, 116, 198, 241, 73, 94, 121, 68, 104, 141, 201, 147, 77, 73, 19, 238, 233, 250, 3, 2, 67, 41, 226, 213, 114, 25, 160, 219, 110, 220, 0, 201, 143, 135], + "multiaddr": "/ip4/0.0.0.0/tcp/9003", + "node_type" : "Bootstrap" + }, + { + "identity": [8, 1, 18, 64, 100, 10, 197, 152, 82, 11, 222, 15, 24, 98, 180, 217, 61, 229, 22, 61, 19, 49, 54, 111, 244, 72, 37, 173, 151, 90, 239, 237, 252, 211, 121, 194, 103, 175, 21, 66, 141, 44, 232, 124, 95, 119, 92, 17, 100, 186, 148, 79, 34, 43, 192, 152, 42, 146, 86, 30, 149, 21, 228, 239, 175, 80, 37, 67], + "multiaddr": "/ip4/0.0.0.0/tcp/9004", + "node_type" : "Bootstrap" + }, + { + "identity": [8, 1, 18, 64, 16, 139, 41, 132, 111, 212, 212, 226, 78, 60, 128, 56, 128, 14, 130, 14, 228, 129, 161, 75, 146, 243, 237, 33, 137, 46, 153, 19, 54, 209, 239, 175, 78, 158, 34, 234, 160, 223, 213, 128, 231, 42, 146, 82, 102, 200, 241, 207, 160, 39, 203, 150, 164, 83, 146, 15, 60, 47, 209, 252, 69, 251, 156, 76], + "multiaddr": "/ip4/0.0.0.0/tcp/9005", + "node_type" : "Bootstrap" + }, + { + "identity": [8, 1, 18, 64, 76, 128, 131, 213, 120, 233, 47, 246, 52, 38, 32, 124, 245, 47, 23, 153, 230, 48, 252, 45, 81, 131, 48, 116, 174, 247, 66, 183, 33, 197, 157, 33, 156, 238, 255, 149, 52, 101, 244, 16, 130, 57, 32, 108, 109, 207, 144, 166, 189, 22, 54, 154, 123, 63, 248, 73, 78, 7, 132, 194, 60, 27, 88, 144], + "multiaddr": "/ip4/0.0.0.0/tcp/9006", + "node_type" : "Bootstrap" + }, + { + "identity": [8, 1, 18, 64, 121, 46, 38, 145, 240, 254, 58, 199, 114, 74, 146, 139, 40, 90, 193, 25, 46, 33, 182, 240, 112, 79, 166, 213, 171, 165, 190, 184, 64, 218, 79, 228, 3, 93, 175, 227, 235, 122, 112, 178, 23, 190, 75, 165, 101, 186, 147, 81, 245, 171, 93, 51, 168, 72, 138, 119, 140, 230, 185, 113, 117, 83, 242, 193], + "multiaddr": "/ip4/0.0.0.0/tcp/9007", + "node_type" : "Bootstrap" + }, + { + "identity": [8, 1, 18, 64, 239, 43, 82, 141, 181, 76, 6, 33, 73, 117, 136, 67, 36, 124, 195, 117, 29, 121, 219, 25, 163, 129, 88, 66, 160, 223, 7, 123, 88, 148, 142, 43, 241, 33, 102, 146, 41, 115, 192, 162, 5, 254, 69, 117, 132, 117, 178, 182, 125, 58, 236, 216, 112, 174, 190, 109, 207, 174, 186, 158, 121, 199, 85, 4], + "multiaddr": "/ip4/0.0.0.0/tcp/9008", + "node_type" : "Bootstrap" + }, + { + "identity": [8, 1, 18, 64, 95, 254, 251, 139, 84, 56, 196, 196, 153, 215, 65, 201, 205, 118, 17, 233, 192, 217, 140, 253, 76, 64, 220, 104, 150, 194, 191, 91, 101, 38, 48, 228, 42, 51, 105, 152, 200, 84, 78, 49, 159, 91, 231, 95, 225, 231, 105, 54, 151, 205, 116, 73, 26, 233, 13, 233, 189, 155, 193, 168, 199, 231, 108, 173], + "multiaddr": "/ip4/0.0.0.0/tcp/9009", + "node_type" : "Bootstrap" + } +] diff --git a/libp2p-networking/src/lib.rs b/libp2p-networking/src/lib.rs index 28e0ffcc71..71054cd6f1 100644 --- a/libp2p-networking/src/lib.rs +++ b/libp2p-networking/src/lib.rs @@ -31,3 +31,6 @@ pub mod network_node; /// handle for network behaviour pub mod network_node_handle; + +/// used for parsing config file +pub mod parse_config; diff --git a/libp2p-networking/src/network_node.rs b/libp2p-networking/src/network_node.rs index 786dd6d7e2..a535e06f6a 100644 --- a/libp2p-networking/src/network_node.rs +++ b/libp2p-networking/src/network_node.rs @@ -1,8 +1,10 @@ use crate::direct_message::{DirectMessageCodec, DirectMessageRequest, DirectMessageResponse}; use async_std::task::{sleep, spawn}; +use bincode::Options; use libp2p::request_response::RequestId; use libp2p::swarm::DialError; use rand::{seq::IteratorRandom, thread_rng}; +use serde::{Deserialize, Serialize}; use std::collections::HashMap; use std::fmt::Debug; use std::{ @@ -263,15 +265,33 @@ impl NetworkBehaviourEventProcess(msg: &T) -> Result, Box> { + let bincode_options = bincode::DefaultOptions::new().with_limit(16_384); + bincode_options.serialize(&msg) +} + +/// deserialize an arbitrary message +/// # Errors +/// when unable to deserialize a message +pub fn deserialize_msg<'a, T: Deserialize<'a>>( + msg: &'a [u8], +) -> Result> { + let bincode_options = bincode::DefaultOptions::new().with_limit(16_384); + bincode_options.deserialize(msg) } impl Default for NetworkNodeType { @@ -293,7 +313,7 @@ pub struct NetworkNode { } /// describe the configuration of the network -#[derive(Debug, Clone, Copy, Default, derive_builder::Builder)] +#[derive(Clone, Default, derive_builder::Builder)] pub struct NetworkNodeConfig { /// max number of connections a node may have before it begins /// to disconnect. Only applies if `node_type` is `Regular` @@ -307,6 +327,19 @@ pub struct NetworkNodeConfig { pub node_type: NetworkNodeType, /// The port to bind to pub port: u16, + /// optional identity + pub identity: Option, +} + +impl Debug for NetworkNodeConfig { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.debug_struct("NetworkNodeConfig") + .field("max num peers", &self.max_num_peers) + .field("min num peers", &self.min_num_peers) + .field("node type", &self.node_type) + .field("port", &self.port) + .finish() + } } impl Debug for NetworkNode { @@ -466,7 +499,11 @@ impl NetworkNode { #[instrument] pub async fn new(config: NetworkNodeConfig) -> Result { // Generate a random PeerId - let identity = Keypair::generate_ed25519(); + let identity = if let Some(ref kp) = config.identity { + kp.clone() + } else { + Keypair::generate_ed25519() + }; let peer_id = PeerId::from(identity.public()); debug!(?peer_id); let transport: Boxed<(PeerId, StreamMuxerBox)> = gen_transport(identity.clone()).await?; @@ -592,7 +629,7 @@ impl NetworkNode { .copied() .choose_multiple(&mut thread_rng(), num_to_connect); // Try dialing each random peer - for a_peer in &chosen_peers.clone() { + for a_peer in &chosen_peers { if *a_peer != self.peer_id { match self.swarm.dial(*a_peer) { Ok(_) => { diff --git a/libp2p-networking/src/network_node_handle.rs b/libp2p-networking/src/network_node_handle.rs index edc3d6d118..d104a5e691 100644 --- a/libp2p-networking/src/network_node_handle.rs +++ b/libp2p-networking/src/network_node_handle.rs @@ -51,7 +51,9 @@ impl NetworkNodeHandle { pub async fn new(config: NetworkNodeConfig, id: usize) -> Result { //`randomly assigned port let listen_addr = gen_multiaddr(0); - let mut network = NetworkNode::new(config).await.context(NetworkSnafu)?; + let mut network = NetworkNode::new(config.clone()) + .await + .context(NetworkSnafu)?; let peer_id = network.peer_id; // TODO separate this into a separate function so you can make everyone know about everyone let listen_addr = network @@ -99,7 +101,7 @@ impl NetworkNodeHandle { node: Arc>, num_peers: usize, chan: Receiver, - _node_idx: usize, + node_idx: usize, ) -> Result<(), NetworkNodeHandleError> { let mut connected_ok = false; let mut known_ok = false; @@ -167,7 +169,7 @@ pub async fn spin_up_swarm( config: NetworkNodeConfig, idx: usize, ) -> Result>, NetworkNodeHandleError> { - let handle = Arc::new(NetworkNodeHandle::new(config, idx).await?); + let handle = Arc::new(NetworkNodeHandle::new(config.clone(), idx).await?); handle .send_network @@ -175,7 +177,7 @@ pub async fn spin_up_swarm( .await .context(SendSnafu)?; - let _result = timeout( + timeout( timeout_len, NetworkNodeHandle::wait_to_connect( handle.clone(), diff --git a/libp2p-networking/src/parse_config.rs b/libp2p-networking/src/parse_config.rs new file mode 100644 index 0000000000..68a853a474 --- /dev/null +++ b/libp2p-networking/src/parse_config.rs @@ -0,0 +1,58 @@ +use crate::network_node::NetworkNodeType; +use libp2p::{identity::Keypair, Multiaddr}; +use serde::{de::Visitor, ser::Error, Deserialize, Deserializer, Serialize, Serializer}; +use std::fmt; + +/// starting network topology +#[derive(Serialize, Deserialize, Clone)] +pub struct NodeDescription { + /// keypair for a node + #[serde(deserialize_with = "deserialize_keypair")] + #[serde(serialize_with = "serialize_keypair")] + pub identity: Keypair, + /// multiaddr the thing is running on + pub multiaddr: Multiaddr, + /// the type of node + pub node_type: NetworkNodeType, +} + +/// deserialize a keypair +/// # Errors +/// todo... +pub fn deserialize_keypair<'de, D>(deserializer: D) -> Result +where + D: Deserializer<'de>, +{ + deserializer.deserialize_seq(KeypairVisitor) +} +struct KeypairVisitor; + +impl<'de> Visitor<'de> for KeypairVisitor { + type Value = Keypair; + + fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { + formatter.write_str("a keypair deserialized in protobuf format") + } + + fn visit_seq(self, mut seq: A) -> Result + where + A: serde::de::SeqAccess<'de>, + { + let mut parsed: Vec = Vec::new(); + while let Ok(Some(a)) = seq.next_element() { + parsed.push(a); + } + // FIXME figure out how to use the error type + Ok(Keypair::from_protobuf_encoding(&parsed).unwrap()) + } +} + +/// serialize a keypair +fn serialize_keypair(x: &Keypair, s: S) -> Result +where + S: Serializer, +{ + let bytes = Keypair::to_protobuf_encoding(x) + .map_err(|_e| S::Error::custom("failed to encode keypair"))?; + s.serialize_bytes(&bytes) +} diff --git a/libp2p-networking/tests/common/mod.rs b/libp2p-networking/tests/common/mod.rs index 308fae186d..a72e5a2580 100644 --- a/libp2p-networking/tests/common/mod.rs +++ b/libp2p-networking/tests/common/mod.rs @@ -182,7 +182,8 @@ pub async fn spin_up_swarms( for j in 0..(num_of_nodes - num_bootstrap) { let node = Arc::new( - NetworkNodeHandle::new(regular_node_config, j + num_bootstrap) + // FIXME this should really be a reference + NetworkNodeHandle::new(regular_node_config.clone(), j + num_bootstrap) .await .context(HandleSnafu)?, ); From 49de6d306407c684aedbc4c42754323e4e277f69 Mon Sep 17 00:00:00 2001 From: Justin Restivo Date: Fri, 18 Feb 2022 14:05:18 -0500 Subject: [PATCH 085/107] feat: working broadcast multi-machine test --- libp2p-networking/examples/common/mod.rs | 127 +++++++++++++++---- libp2p-networking/examples/counter.rs | 15 +++ libp2p-networking/examples/identities.rs | 20 +-- libp2p-networking/flake.nix | 2 + libp2p-networking/identity_mapping.json | 49 ++----- libp2p-networking/src/network_node.rs | 76 ++++++----- libp2p-networking/src/network_node_handle.rs | 16 ++- libp2p-networking/src/parse_config.rs | 4 +- libp2p-networking/src/ui.rs | 2 +- libp2p-networking/tests/common/mod.rs | 18 ++- libp2p-networking/tests/counter.rs | 2 +- 11 files changed, 215 insertions(+), 116 deletions(-) create mode 100644 libp2p-networking/examples/counter.rs diff --git a/libp2p-networking/examples/common/mod.rs b/libp2p-networking/examples/common/mod.rs index ad8ef4c181..d5c8d4ea0e 100644 --- a/libp2p-networking/examples/common/mod.rs +++ b/libp2p-networking/examples/common/mod.rs @@ -1,11 +1,14 @@ use networking_demo::parse_config::NodeDescription; use std::{ - collections::HashMap, + collections::{HashMap, HashSet}, sync::{Arc, Once}, time::Duration, }; -use async_std::fs::File; +use async_std::{ + fs::File, + task::{sleep, spawn}, +}; use futures::AsyncReadExt; use libp2p::{gossipsub::Topic, request_response::ResponseChannel, PeerId}; use networking_demo::{ @@ -29,7 +32,6 @@ use tracing::instrument; const TIMEOUT: Duration = Duration::from_secs(1000); static INIT: Once = Once::new(); -const PORT_NO: u16 = 1234; pub type CounterState = u32; pub type ConductorState = HashMap; @@ -95,6 +97,7 @@ pub async fn handle_normal_msg( } } CounterRequest::Kill => { + println!("killing!"); handle.kill().await.context(NetworkSnafu)?; } CounterRequest::Recvd => {} @@ -117,6 +120,7 @@ pub async fn regular_handle_network_event( if let Ok(msg) = deserialize_msg::(&m) { match msg { Message::NormalMessage(msg) => { + println!("recv-ed gossip message"); handle_normal_msg(handle.clone(), msg, None).await?; } Message::ConductorMessage(..) => { @@ -126,13 +130,15 @@ pub async fn regular_handle_network_event( } } } - DirectRequest(msg, chan) => { + DirectRequest(msg, _peer_id, chan) => { if let Ok(msg) = deserialize_msg::(&msg) { match msg { Message::NormalMessage(msg) => { + println!("recv-ed normal direct message"); handle_normal_msg(handle.clone(), msg, Some(chan)).await?; } Message::ConductorMessage(msg, method) => { + println!("recv-ed conductor message!"); let serialized_msg = serialize_msg(&Message::NormalMessage(msg)) .context(SerializationSnafu)?; match method { @@ -198,16 +204,28 @@ pub async fn start_main(idx: usize) -> Result<(), NetworkNodeHandleError> { }); let swarm_config = parse_config().await; + let ignored_peers = swarm_config + .iter() + .filter_map(|n| { + if n.node_type == NetworkNodeType::Conductor { + Some(n.identity.public().to_peer_id()) + } else { + None + } + }) + .collect::>(); + let node_description = &swarm_config[idx]; match node_description.node_type { NetworkNodeType::Conductor => { let config = NetworkNodeConfigBuilder::default() - .port(PORT_NO) + .bound_addr(Some(swarm_config[idx].bound_addr.clone())) .min_num_peers(swarm_config.len() - 1) .max_num_peers(swarm_config.len() - 1) .node_type(NetworkNodeType::Conductor) .identity(Some(swarm_config[idx].identity.clone())) + .ignored_peers(ignored_peers) .build() .context(NodeConfigSnafu)?; let handle = spin_up_swarm::( @@ -221,6 +239,8 @@ pub async fn start_main(idx: usize) -> Result<(), NetworkNodeHandleError> { ) .await?; spawn_handler(handle.clone(), conductor_handle_network_event).await; + + // initialize the state of each node let mut state = handle.state.lock().await; for (i, connection) in swarm_config.iter().enumerate() { if i != idx { @@ -229,8 +249,34 @@ pub async fn start_main(idx: usize) -> Result<(), NetworkNodeHandleError> { } drop(state); + // do 10 rounds of broadcasting // FIXME we are in desperate need of a error type like TestError - conductor_broadcast(TIMEOUT, 0, handle).await.unwrap(); + for i in 0..10 { + conductor_broadcast(TIMEOUT, i, handle.clone()) + .await + .unwrap(); + } + + let kill_msg = Message::NormalMessage(CounterRequest::Kill); + let serialized_kill_msg = serialize_msg(&kill_msg).unwrap(); + for peer_id in &handle.connection_state.lock().await.connected_peers { + handle + .send_network + .send_async(ClientRequest::DirectRequest( + *peer_id, + serialized_kill_msg.clone(), + )) + .await + .context(SendSnafu) + .unwrap(); + } + while !handle + .connection_state + .lock() + .await + .connected_peers + .is_empty() + {} // FIXME we need to fix clippy warnings @@ -241,31 +287,53 @@ pub async fn start_main(idx: usize) -> Result<(), NetworkNodeHandleError> { // FIXME // we need one other primitive here: // - tell a node to tell all other nodes to increment state with direct message - - // FIXME we have a bunch of nodes all on the same port. Don't use global variable for - // this. } - _ => { + NetworkNodeType::Bootstrap | NetworkNodeType::Regular => { let known_peers = swarm_config .iter() .filter_map(|x| { // TODO this is gross. Make this a data structure if x.node_type == NetworkNodeType::Bootstrap { - Some((Some(x.identity.public().to_peer_id()), x.multiaddr.clone())) + Some((Some(x.identity.public().to_peer_id()), x.bound_addr.clone())) } else { None } }) .collect::>(); let config = NetworkNodeConfigBuilder::default() - .port(PORT_NO) + .bound_addr(Some(swarm_config[idx].multiaddr.clone())) + .identity(Some(swarm_config[idx].identity.clone())) + .ignored_peers(ignored_peers) .min_num_peers(swarm_config.len() / 4) .max_num_peers(swarm_config.len() / 2) .node_type(node_description.node_type) .build() .context(NodeConfigSnafu)?; let handle = spin_up_swarm::(TIMEOUT, known_peers, config, idx).await?; - spawn_handler(handle, regular_handle_network_event).await; + let handle_dup = handle.clone(); + // periodically broadcast state back to conductor node + spawn(async move { + let conductor_id = swarm_config + .iter() + .find(|c| c.node_type == NetworkNodeType::Conductor) + .unwrap() + .identity + .public() + .to_peer_id(); + while !*handle_dup.killed.lock().await { + sleep(Duration::from_secs(1)).await; + let counter = *handle_dup.state.lock().await; + let msg = Message::NormalMessage(CounterRequest::MyCounterIs(counter)); + let serialized_msg = serialize_msg(&msg).unwrap(); + handle_dup + .send_network + .send_async(ClientRequest::DirectRequest(conductor_id, serialized_msg)) + .await + .unwrap(); + } + }); + spawn_handler(handle.clone(), regular_handle_network_event).await; + while !*handle.killed.lock().await {} } } @@ -286,14 +354,16 @@ pub async fn conductor_broadcast( // FIXME wrapper error let chosen_peer = known_peers.iter().choose(&mut thread_rng()).unwrap(); + println!("chosen peer is {:?}", chosen_peer); // increment the state let request = CounterRequest::IncrementCounter { from: state, to: new_state, }; + println!("broadcasting message!"); // broadcast message - let msg = Message::ConductorMessage(request, ConductorMessageMethod::Broadcast); + let msg = Message::ConductorMessage(request.clone(), ConductorMessageMethod::Broadcast); let serialized_msg = serialize_msg(&msg).context(SerializationSnafu)?; handle .send_network @@ -301,6 +371,17 @@ pub async fn conductor_broadcast( .await .context(SendSnafu)?; + let msg_direct = Message::NormalMessage(request); + let serialized_msg_direct = serialize_msg(&msg_direct).context(SerializationSnafu)?; + handle + .send_network + .send_async(ClientRequest::DirectRequest( + *chosen_peer, + serialized_msg_direct, + )) + .await + .context(SendSnafu)?; + let (_, res) = handle .state_changed .wait_timeout_until(handle.state.lock().await, timeout, |state| { @@ -323,23 +404,22 @@ pub async fn conductor_handle_network_event( #[allow(clippy::enum_glob_use)] use NetworkEvent::*; match event { - GossipMsg(..) | DirectRequest(..) => { - // this node isn't going to participate. + GossipMsg(..) => { + // this node isn't going to participate in gossip/dms to update state // it's only purpose is to recv state } - DirectResponse(m, peer_id) => { + DirectRequest(m, peer_id, _chan) => { if let Ok(msg) = deserialize_msg::(&m) { match msg { - Message::NormalMessage(msg) => match msg { - CounterRequest::MyCounterIs(state) => { - let old_state = (*handle.state.lock().await) + Message::NormalMessage(msg) => { + if let CounterRequest::MyCounterIs(state) = msg { + let _old_state = (*handle.state.lock().await) .insert(peer_id, state) .unwrap_or(0); + println!("new state: {:?}", *handle.state.lock().await); handle.state_changed.notify_all(); - debug_assert!(old_state < state); } - _ => {} - }, + } Message::ConductorMessage(..) => { /* This should also never happen ... */ unreachable!() @@ -347,6 +427,7 @@ pub async fn conductor_handle_network_event( } } } + DirectResponse(_m, _peer_id) => { /* nothing to do here */ } // we care about these for the sake of maintaining conenctions, but not much else UpdateConnectedPeers(p) => { handle.connection_state.lock().await.connected_peers = p; diff --git a/libp2p-networking/examples/counter.rs b/libp2p-networking/examples/counter.rs new file mode 100644 index 0000000000..a3da08948a --- /dev/null +++ b/libp2p-networking/examples/counter.rs @@ -0,0 +1,15 @@ +use structopt::StructOpt; + +use color_eyre::eyre::Result; + +use tracing::instrument; + +mod common; + +#[async_std::main] +#[instrument] +async fn main() -> Result<()> { + println!("hello world we are starting"); + common::start_main(common::CliOpt::from_args().idx.unwrap()).await?; + Ok(()) +} diff --git a/libp2p-networking/examples/identities.rs b/libp2p-networking/examples/identities.rs index a91d0f947e..d68ef1bbb2 100644 --- a/libp2p-networking/examples/identities.rs +++ b/libp2p-networking/examples/identities.rs @@ -1,6 +1,6 @@ use async_std::fs::File; use futures::AsyncReadExt; -use libp2p::{identity::Keypair, Multiaddr, PeerId}; +use libp2p::identity::Keypair; use networking_demo::parse_config::NodeDescription; use tracing::instrument; @@ -15,23 +15,7 @@ pub async fn parse_ids() { let mut s = String::new(); f.read_to_string(&mut s).await.unwrap(); println!("s{}", s); - let foo: Vec = serde_json::from_str(&s).unwrap(); - println!( - "{:?}", - foo.iter() - .map(|id| id.identity.public().to_peer_id()) - .collect::>() - ); - println!( - "{:?}", - foo.iter() - .map(|id| id.multiaddr.clone()) - .collect::>() - ); - println!( - "{:?}", - foo.iter().map(|id| id.node_type).collect::>() - ); + let _: Vec = serde_json::from_str(&s).unwrap(); } pub async fn gen_ids() { diff --git a/libp2p-networking/flake.nix b/libp2p-networking/flake.nix index 48648eebc6..90fdd7f891 100644 --- a/libp2p-networking/flake.nix +++ b/libp2p-networking/flake.nix @@ -122,6 +122,7 @@ defaultPackage = self.packages.${system}.${crateName}; devShell = pkgs.mkShell { + shellHook = "ulimit -n 1024"; buildInputs = with pkgs; [ fenix.packages.${system}.rust-analyzer fenixStable ] ++ buildDeps; }; @@ -129,6 +130,7 @@ devShells.perfShell = pkgs.mkShell { buildInputs = with pkgs; [ grcov recent_flamegraph fd fenixNightly fenix.packages.${system}.rust-analyzer ] ++ buildDeps; shellHook = '' + ulimit -n 1024 export RUSTFLAGS='-Zprofile -Ccodegen-units=1 -Cinline-threshold=0 -Clink-dead-code -Coverflow-checks=off -Cpanic=abort -Zpanic_abort_tests' export RUSTDOCFLAGS='-Zprofile -Ccodegen-units=1 -Cinline-threshold=0 -Clink-dead-code -Coverflow-checks=off -Cpanic=abort -Zpanic_abort_tests' export CARGO_INCREMENTAL=0 diff --git a/libp2p-networking/identity_mapping.json b/libp2p-networking/identity_mapping.json index 44f504b747..47a1ed9b91 100644 --- a/libp2p-networking/identity_mapping.json +++ b/libp2p-networking/identity_mapping.json @@ -1,52 +1,25 @@ [ { "identity": [8, 1, 18, 64, 192, 235, 232, 64, 137, 178, 181, 217, 34, 70, 59, 32, 35, 193, 254, 194, 148, 154, 101, 168, 113, 144, 23, 125, 60, 34, 176, 91, 190, 213, 214, 30, 46, 217, 99, 68, 172, 148, 59, 128, 61, 36, 129, 138, 22, 163, 255, 13, 239, 88, 131, 43, 18, 75, 129, 165, 88, 80, 226, 94, 40, 154, 61, 137], - "multiaddr": "/ip4/0.0.0.0/tcp/9000", + "multiaddr": "/ip4/127.0.0.1/tcp/9000", + "bound_addr": "/ip4/127.0.0.1/tcp/9000", "node_type" : "Conductor" }, { "identity": [8, 1, 18, 64, 84, 243, 22, 74, 173, 227, 68, 200, 15, 52, 197, 125, 17, 133, 238, 75, 164, 25, 113, 80, 102, 119, 109, 8, 13, 224, 63, 159, 101, 252, 25, 187, 32, 130, 182, 245, 37, 72, 204, 137, 39, 142, 16, 188, 170, 252, 104, 187, 91, 65, 179, 149, 102, 199, 5, 180, 176, 0, 241, 36, 57, 179, 118, 83], - "multiaddr": "/ip4/0.0.0.0/tcp/9001", + "multiaddr": "/ip4/127.0.0.1/tcp/9001", + "bound_addr": "/ip4/127.0.0.1/tcp/9001", "node_type" : "Bootstrap" }, { "identity": [8, 1, 18, 64, 223, 223, 83, 162, 199, 9, 104, 81, 205, 65, 103, 28, 91, 139, 83, 227, 119, 73, 39, 238, 143, 77, 250, 48, 145, 63, 49, 12, 36, 51, 111, 214, 251, 44, 78, 17, 232, 147, 120, 38, 118, 7, 41, 49, 162, 6, 91, 175, 41, 194, 12, 22, 22, 16, 37, 154, 226, 22, 16, 63, 250, 224, 109, 94], - "multiaddr": "/ip4/0.0.0.0/tcp/9002", - "node_type" : "Bootstrap" + "multiaddr": "/ip4/127.0.0.1/tcp/9002", + "bound_addr": "/ip4/127.0.0.1/tcp/9002", + "node_type" : "Regular" }, { "identity": [8, 1, 18, 64, 150, 246, 56, 246, 0, 14, 60, 3, 218, 212, 188, 101, 137, 53, 110, 27, 20, 78, 42, 56, 138, 236, 25, 234, 210, 49, 193, 59, 129, 88, 35, 116, 198, 241, 73, 94, 121, 68, 104, 141, 201, 147, 77, 73, 19, 238, 233, 250, 3, 2, 67, 41, 226, 213, 114, 25, 160, 219, 110, 220, 0, 201, 143, 135], - "multiaddr": "/ip4/0.0.0.0/tcp/9003", - "node_type" : "Bootstrap" - }, - { - "identity": [8, 1, 18, 64, 100, 10, 197, 152, 82, 11, 222, 15, 24, 98, 180, 217, 61, 229, 22, 61, 19, 49, 54, 111, 244, 72, 37, 173, 151, 90, 239, 237, 252, 211, 121, 194, 103, 175, 21, 66, 141, 44, 232, 124, 95, 119, 92, 17, 100, 186, 148, 79, 34, 43, 192, 152, 42, 146, 86, 30, 149, 21, 228, 239, 175, 80, 37, 67], - "multiaddr": "/ip4/0.0.0.0/tcp/9004", - "node_type" : "Bootstrap" - }, - { - "identity": [8, 1, 18, 64, 16, 139, 41, 132, 111, 212, 212, 226, 78, 60, 128, 56, 128, 14, 130, 14, 228, 129, 161, 75, 146, 243, 237, 33, 137, 46, 153, 19, 54, 209, 239, 175, 78, 158, 34, 234, 160, 223, 213, 128, 231, 42, 146, 82, 102, 200, 241, 207, 160, 39, 203, 150, 164, 83, 146, 15, 60, 47, 209, 252, 69, 251, 156, 76], - "multiaddr": "/ip4/0.0.0.0/tcp/9005", - "node_type" : "Bootstrap" - }, - { - "identity": [8, 1, 18, 64, 76, 128, 131, 213, 120, 233, 47, 246, 52, 38, 32, 124, 245, 47, 23, 153, 230, 48, 252, 45, 81, 131, 48, 116, 174, 247, 66, 183, 33, 197, 157, 33, 156, 238, 255, 149, 52, 101, 244, 16, 130, 57, 32, 108, 109, 207, 144, 166, 189, 22, 54, 154, 123, 63, 248, 73, 78, 7, 132, 194, 60, 27, 88, 144], - "multiaddr": "/ip4/0.0.0.0/tcp/9006", - "node_type" : "Bootstrap" - }, - { - "identity": [8, 1, 18, 64, 121, 46, 38, 145, 240, 254, 58, 199, 114, 74, 146, 139, 40, 90, 193, 25, 46, 33, 182, 240, 112, 79, 166, 213, 171, 165, 190, 184, 64, 218, 79, 228, 3, 93, 175, 227, 235, 122, 112, 178, 23, 190, 75, 165, 101, 186, 147, 81, 245, 171, 93, 51, 168, 72, 138, 119, 140, 230, 185, 113, 117, 83, 242, 193], - "multiaddr": "/ip4/0.0.0.0/tcp/9007", - "node_type" : "Bootstrap" - }, - { - "identity": [8, 1, 18, 64, 239, 43, 82, 141, 181, 76, 6, 33, 73, 117, 136, 67, 36, 124, 195, 117, 29, 121, 219, 25, 163, 129, 88, 66, 160, 223, 7, 123, 88, 148, 142, 43, 241, 33, 102, 146, 41, 115, 192, 162, 5, 254, 69, 117, 132, 117, 178, 182, 125, 58, 236, 216, 112, 174, 190, 109, 207, 174, 186, 158, 121, 199, 85, 4], - "multiaddr": "/ip4/0.0.0.0/tcp/9008", - "node_type" : "Bootstrap" - }, - { - "identity": [8, 1, 18, 64, 95, 254, 251, 139, 84, 56, 196, 196, 153, 215, 65, 201, 205, 118, 17, 233, 192, 217, 140, 253, 76, 64, 220, 104, 150, 194, 191, 91, 101, 38, 48, 228, 42, 51, 105, 152, 200, 84, 78, 49, 159, 91, 231, 95, 225, 231, 105, 54, 151, 205, 116, 73, 26, 233, 13, 233, 189, 155, 193, 168, 199, 231, 108, 173], - "multiaddr": "/ip4/0.0.0.0/tcp/9009", - "node_type" : "Bootstrap" - } -] + "multiaddr": "/ip4/127.0.0.1/tcp/9003", + "bound_addr": "/ip4/127.0.0.1/tcp/9003", + "node_type" : "Regular" + }] diff --git a/libp2p-networking/src/network_node.rs b/libp2p-networking/src/network_node.rs index a535e06f6a..9c68bfff18 100644 --- a/libp2p-networking/src/network_node.rs +++ b/libp2p-networking/src/network_node.rs @@ -102,15 +102,23 @@ pub struct NetworkDef { // track unknown addrs #[behaviour(ignore)] unknown_addrs: HashSet, + /// peers we ignore (mainly here for conductor usecase) + #[behaviour(ignore)] + ignored_peers: HashSet, } impl Debug for NetworkDef { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { f.debug_struct("NetworkDef") - .field("bootstrap", &self.bootstrap_state) + .field("bootstrap state", &self.bootstrap_state) .field("connected_peers", &self.connected_peers) .field("connecting_peers", &self.connecting_peers) .field("known_peers", &self.known_peers) + .field("ignored_peers", &self.ignored_peers) + .field("unknown addrs", &self.unknown_addrs) + .field("in progress rr", &self.in_progress_rr) + .field("in progress gossip", &self.in_progress_gossip) + .field("pruning enabled", &self.pruning_enabled) .finish() } } @@ -235,14 +243,16 @@ impl NetworkBehaviourEventProcess match message { + RequestResponseEvent::Message { message, peer, .. } => match message { RequestResponseMessage::Request { request: DirectMessageRequest(msg), channel, .. } => { + // receiver, not initiator. + // don't track. If we are disconnected, sender will reinitiate self.client_event_queue - .push(NetworkEvent::DirectRequest(msg, channel)); + .push(NetworkEvent::DirectRequest(msg, peer, channel)); } RequestResponseMessage::Response { request_id, @@ -325,10 +335,12 @@ pub struct NetworkNodeConfig { /// Either bootstrap (greedily connect to all peers) /// or regular (respect `min_num_peers`/`max num peers`) pub node_type: NetworkNodeType, - /// The port to bind to - pub port: u16, /// optional identity pub identity: Option, + /// nodes to ignore + pub ignored_peers: HashSet, + /// address to bind to + pub bound_addr: Option, } impl Debug for NetworkNodeConfig { @@ -337,7 +349,7 @@ impl Debug for NetworkNodeConfig { .field("max num peers", &self.max_num_peers) .field("min num peers", &self.min_num_peers) .field("node type", &self.node_type) - .field("port", &self.port) + .field("bound_addr", &self.bound_addr) .finish() } } @@ -365,9 +377,9 @@ pub enum ClientRequest { Subscribe(String), /// unsubscribe from a topic Unsubscribe(String), - /// direct message a serialized message + /// client request to send a direct message a serialized message DirectRequest(PeerId, Vec), - /// direct reply to a message + /// client request to send a direct reply to a message DirectResponse(ResponseChannel, Vec), /// disable or enable pruning of connections Pruning(bool), @@ -386,8 +398,8 @@ pub enum NetworkEvent { /// recv-ed a broadcast GossipMsg(Vec), /// recv-ed a direct message from a node - DirectRequest(Vec, ResponseChannel), - /// recv-ed a direct response from a node + DirectRequest(Vec, PeerId, ResponseChannel), + /// recv-ed a direct response from a node (that hopefully was initiated by this node) DirectResponse(Vec, PeerId), } @@ -518,8 +530,6 @@ impl NetworkNode { }; // Create a custom gossipsub // TODO: Extract these defaults into some sort of config - // Use a jank match because Gossipsubconfigbuilder::build returns a non-static str for - // some god forsaken reason let gossipsub_config = GossipsubConfigBuilder::default() .heartbeat_interval(Duration::from_secs(1)) // Force all messages to have valid signatures @@ -548,7 +558,6 @@ impl NetworkNode { )); // - Build DHT needed for peer discovery - // TODO check into the MemoryStore defaults let mut kconfig = KademliaConfig::default(); kconfig.set_caching(kad::KademliaCaching::Disabled); let kadem = Kademlia::with_config(peer_id, MemoryStore::new(peer_id), kconfig); @@ -576,6 +585,8 @@ impl NetworkNode { in_progress_rr: HashMap::new(), in_progress_gossip: Vec::new(), unknown_addrs: HashSet::new(), + // currently only functionality is to "not prune" these nodes + ignored_peers: config.ignored_peers.clone(), }; Swarm::new(transport, network, peer_id) @@ -624,20 +635,23 @@ impl NetworkNode { let num_to_connect = self.config.min_num_peers + 1 - (swarm.connected_peers.len() + swarm.connecting_peers.len()); // Random(?) subset of the availible peers to try connecting to - let chosen_peers = potential_peers + let mut chosen_peers = potential_peers .iter() .copied() - .choose_multiple(&mut thread_rng(), num_to_connect); + .choose_multiple(&mut thread_rng(), num_to_connect) + .into_iter() + .collect::>(); + chosen_peers.remove(&self.peer_id); // Try dialing each random peer for a_peer in &chosen_peers { if *a_peer != self.peer_id { match self.swarm.dial(*a_peer) { Ok(_) => { - info!("Peer {:?} dial {:?} working!", self.peer_id, a_peer); + println!("Peer {:?} dial {:?} working!", self.peer_id, a_peer); self.swarm.behaviour_mut().connecting_peers.insert(*a_peer); } Err(e) => { - info!("Peer {:?} dial {:?} failed: {:?}", self.peer_id, a_peer, e); + println!("Peer {:?} dial {:?} failed: {:?}", self.peer_id, a_peer, e); } }; } @@ -665,32 +679,30 @@ impl NetworkNode { } } } - // - // /// directly dial a peer - // pub async fn dial_peer(&mut self, addr: Multiaddr) -> Result<(), NetworkError> { - // self.swarm.dial(addr).context(DialSnafu) - // } #[instrument(skip(self))] fn prune_num_connections(&mut self) { let swarm = self.swarm.behaviour_mut(); // If we are connected to too many peers, try disconnecting from - // a random (?) subset + // a random subset. Bootstrap nodes accept all connections and + // attempt to connect to all if swarm.bootstrap_state == BootstrapState::Finished && swarm.pruning_enabled - && self.config.node_type != NetworkNodeType::Bootstrap + && self.config.node_type == NetworkNodeType::Regular && swarm.connected_peers.len() > self.config.max_num_peers { let peers_to_rm = swarm.connected_peers.iter().copied().choose_multiple( &mut thread_rng(), swarm.connected_peers.len() - self.config.max_num_peers, ); - let safe_peers = swarm + let rr_peers = swarm .in_progress_rr .iter() .map(|(_, (_, pid))| pid) .copied() .collect::>(); + let ignored_peers = self.swarm.behaviour_mut().ignored_peers.clone(); + let safe_peers = rr_peers.union(&ignored_peers).collect::>(); for a_peer in peers_to_rm { if !safe_peers.contains(&a_peer) { let _ = self.swarm.disconnect_peer_id(a_peer); @@ -868,11 +880,11 @@ impl NetworkNode { endpoint: _, .. } => { - warn!("connection closed btwn {:?}, {:?}", self.peer_id, peer_id); + println!("connection closed btwn {:?}, {:?}", self.peer_id, peer_id); let swarm = self.swarm.behaviour_mut(); swarm.connected_peers.remove(&peer_id); // FIXME remove stale address, not *all* addresses - swarm.kadem.remove_peer(&peer_id); + // swarm.kadem.remove_peer(&peer_id); // swarm.kadem.remove_address(); // swarm.request_response.remove_address(peer, address) @@ -888,9 +900,8 @@ impl NetworkNode { | ExpiredListenAddr { .. } | ListenerClosed { .. } | IncomingConnection { .. } - | IncomingConnectionError { .. } - | OutgoingConnectionError { .. } | BannedPeer { .. } + | IncomingConnectionError { .. } | ListenerError { .. } => {} Behaviour(b) => { // forward messages directly to Client @@ -899,6 +910,13 @@ impl NetworkNode { .await .map_err(|_e| NetworkError::StreamClosed)?; } + OutgoingConnectionError { peer_id, error } => { + println!("connecting error {:?}", error); + if let Some(peer_id) = peer_id { + self.swarm.behaviour_mut().connected_peers.remove(&peer_id); + self.swarm.behaviour_mut().connecting_peers.remove(&peer_id); + } + } } Ok(()) } diff --git a/libp2p-networking/src/network_node_handle.rs b/libp2p-networking/src/network_node_handle.rs index d104a5e691..6ff3562676 100644 --- a/libp2p-networking/src/network_node_handle.rs +++ b/libp2p-networking/src/network_node_handle.rs @@ -31,6 +31,8 @@ pub struct NetworkNodeHandle { pub send_network: Sender, /// receive an action from the networkbehaviour pub recv_network: Receiver, + /// whether or not the handle has been killed + pub killed: Arc>, /// kill the event handler for events from the swarm pub kill_switch: Sender<()>, /// receiving end of `kill_switch` @@ -50,7 +52,10 @@ impl NetworkNodeHandle { #[instrument] pub async fn new(config: NetworkNodeConfig, id: usize) -> Result { //`randomly assigned port - let listen_addr = gen_multiaddr(0); + let listen_addr = config + .bound_addr + .clone() + .unwrap_or_else(|| gen_multiaddr(0)); let mut network = NetworkNode::new(config.clone()) .await .context(NetworkSnafu)?; @@ -69,6 +74,7 @@ impl NetworkNodeHandle { state: Arc::new(Mutex::new(S::default())), send_network: send_chan, recv_network: recv_chan, + killed: Arc::new(Mutex::new(false)), kill_switch, recv_kill, listen_addr, @@ -103,11 +109,17 @@ impl NetworkNodeHandle { chan: Receiver, node_idx: usize, ) -> Result<(), NetworkNodeHandleError> { + println!("waiting to connect!"); let mut connected_ok = false; let mut known_ok = false; while !(known_ok && connected_ok) { match chan.recv_async().await.context(RecvSnafu)? { NetworkEvent::UpdateConnectedPeers(pids) => { + println!( + "updating connected peers to: {}, waiting on {}", + pids.len(), + num_peers + ); node.connection_state.lock().await.connected_peers = pids.clone(); connected_ok = pids.len() >= num_peers; } @@ -147,6 +159,7 @@ pub async fn spawn_handler( loop { select!( _ = recv_kill.recv_async().fuse() => { + *handle.killed.lock().await = true; break; }, event = recv_event.recv_async().fuse() => { @@ -171,6 +184,7 @@ pub async fn spin_up_swarm( ) -> Result>, NetworkNodeHandleError> { let handle = Arc::new(NetworkNodeHandle::new(config.clone(), idx).await?); + println!("known_nodes{:?}", known_nodes); handle .send_network .send_async(ClientRequest::AddKnownPeers(known_nodes)) diff --git a/libp2p-networking/src/parse_config.rs b/libp2p-networking/src/parse_config.rs index 68a853a474..daba2583a1 100644 --- a/libp2p-networking/src/parse_config.rs +++ b/libp2p-networking/src/parse_config.rs @@ -10,8 +10,10 @@ pub struct NodeDescription { #[serde(deserialize_with = "deserialize_keypair")] #[serde(serialize_with = "serialize_keypair")] pub identity: Keypair, - /// multiaddr the thing is running on + /// external multiaddr the node is running on pub multiaddr: Multiaddr, + /// internal address to bind to + pub bound_addr: Multiaddr, /// the type of node pub node_type: NetworkNodeType, } diff --git a/libp2p-networking/src/ui.rs b/libp2p-networking/src/ui.rs index 04c7b105bd..9997a79218 100644 --- a/libp2p-networking/src/ui.rs +++ b/libp2p-networking/src/ui.rs @@ -108,7 +108,7 @@ pub async fn run_app(terminal: &mut Terminal, mut app: TableApp) swarm_msg = app.recv_swarm.recv_async() => { if let Ok(res) = swarm_msg { match res { - DirectRequest(m, _) | GossipMsg(m) => { + DirectRequest(m, _, _) | GossipMsg(m) => { let bincode_options = bincode::DefaultOptions::new().with_limit(16_384); let msg : Message = bincode_options.deserialize(&m)?; app.message_buffer.lock().push_back(msg); diff --git a/libp2p-networking/tests/common/mod.rs b/libp2p-networking/tests/common/mod.rs index a72e5a2580..5775ea107c 100644 --- a/libp2p-networking/tests/common/mod.rs +++ b/libp2p-networking/tests/common/mod.rs @@ -1,5 +1,5 @@ use std::{ - collections::HashMap, + collections::{HashMap, HashSet}, sync::{Arc, Once}, time::Duration, }; @@ -18,7 +18,7 @@ use networking_demo::{ }; use snafu::{ResultExt, Snafu}; use std::fmt::Debug; -use tracing::{instrument, warn}; +use tracing::{error, instrument, warn}; static INIT: Once = Once::new(); @@ -172,7 +172,9 @@ pub async fn spin_up_swarms( } let regular_node_config = NetworkNodeConfigBuilder::default() - .port(0) + .identity(None) + .ignored_peers(HashSet::new()) + .bound_addr(None) .node_type(NetworkNodeType::Regular) .min_num_peers(min_num_peers) .max_num_peers(max_num_peers) @@ -202,13 +204,21 @@ pub async fn spin_up_swarms( handles.push(node); } + error!( + "known nodes: {:?}", + bootstrap_addrs + .iter() + .map(|(a, b)| (Some(*a), b.clone())) + .collect::>() + ); + for handle in &handles { handle .send_network .send_async(ClientRequest::AddKnownPeers( bootstrap_addrs .iter() - .map(|(a, b)| (Some(a.clone()), b.clone())) + .map(|(a, b)| (Some(*a), b.clone())) .collect::>(), )) .await diff --git a/libp2p-networking/tests/counter.rs b/libp2p-networking/tests/counter.rs index 76ef842941..fd27ba7037 100644 --- a/libp2p-networking/tests/counter.rs +++ b/libp2p-networking/tests/counter.rs @@ -77,7 +77,7 @@ pub async fn counter_handle_network_event( } } } - DirectRequest(m, chan) => { + DirectRequest(m, _, chan) => { if let Ok(msg) = bincode_options.deserialize::(&m) { match msg { // direct message request From b0b09884b0c9c62f4603011696d9aa686d36e4f6 Mon Sep 17 00:00:00 2001 From: Justin Restivo Date: Mon, 21 Feb 2022 09:02:53 -0500 Subject: [PATCH 086/107] feat: add counter example error type --- libp2p-networking/examples/common/mod.rs | 61 ++++++++++++++++-------- 1 file changed, 41 insertions(+), 20 deletions(-) diff --git a/libp2p-networking/examples/common/mod.rs b/libp2p-networking/examples/common/mod.rs index d5c8d4ea0e..6bb86d2aef 100644 --- a/libp2p-networking/examples/common/mod.rs +++ b/libp2p-networking/examples/common/mod.rs @@ -25,7 +25,7 @@ use networking_demo::{ }; use rand::{seq::IteratorRandom, thread_rng}; use serde::{Deserialize, Serialize}; -use snafu::ResultExt; +use snafu::{ResultExt, Snafu}; use std::fmt::Debug; use structopt::StructOpt; use tracing::instrument; @@ -189,20 +189,20 @@ pub struct CliOpt { pub idx: Option, } -pub async fn parse_config() -> Vec { - let mut f = File::open(&"./identity_mapping.json").await.unwrap(); +pub async fn parse_config() -> Result, CounterError> { + let mut f = File::open(&"./identity_mapping.json").await.context(FileReadSnafu)?; let mut s = String::new(); - f.read_to_string(&mut s).await.unwrap(); - let res: Vec = serde_json::from_str(&s).unwrap(); - res + f.read_to_string(&mut s).await.context(FileReadSnafu)?; + serde_json::from_str(&s).context(JsonParseSnafu) } -pub async fn start_main(idx: usize) -> Result<(), NetworkNodeHandleError> { +pub async fn start_main(idx: usize) -> Result<(), CounterError> { + // FIXME can we pass in a function that returns an error type INIT.call_once(|| { color_eyre::install().unwrap(); tracing_setup::setup_tracing(); }); - let swarm_config = parse_config().await; + let swarm_config = parse_config().await?; let ignored_peers = swarm_config .iter() @@ -227,7 +227,8 @@ pub async fn start_main(idx: usize) -> Result<(), NetworkNodeHandleError> { .identity(Some(swarm_config[idx].identity.clone())) .ignored_peers(ignored_peers) .build() - .context(NodeConfigSnafu)?; + .context(NodeConfigSnafu) + .context(HandleSnafu)?; let handle = spin_up_swarm::( TIMEOUT, swarm_config @@ -237,7 +238,8 @@ pub async fn start_main(idx: usize) -> Result<(), NetworkNodeHandleError> { config, idx, ) - .await?; + .await + .context(HandleSnafu)?; spawn_handler(handle.clone(), conductor_handle_network_event).await; // initialize the state of each node @@ -249,16 +251,16 @@ pub async fn start_main(idx: usize) -> Result<(), NetworkNodeHandleError> { } drop(state); - // do 10 rounds of broadcasting - // FIXME we are in desperate need of a error type like TestError for i in 0..10 { conductor_broadcast(TIMEOUT, i, handle.clone()) .await - .unwrap(); + .context(HandleSnafu)? } let kill_msg = Message::NormalMessage(CounterRequest::Kill); - let serialized_kill_msg = serialize_msg(&kill_msg).unwrap(); + let serialized_kill_msg = serialize_msg(&kill_msg) + .context(SerializationSnafu) + .context(HandleSnafu)?; for peer_id in &handle.connection_state.lock().await.connected_peers { handle .send_network @@ -268,7 +270,7 @@ pub async fn start_main(idx: usize) -> Result<(), NetworkNodeHandleError> { )) .await .context(SendSnafu) - .unwrap(); + .context(HandleSnafu)? } while !handle .connection_state @@ -308,11 +310,15 @@ pub async fn start_main(idx: usize) -> Result<(), NetworkNodeHandleError> { .max_num_peers(swarm_config.len() / 2) .node_type(node_description.node_type) .build() - .context(NodeConfigSnafu)?; - let handle = spin_up_swarm::(TIMEOUT, known_peers, config, idx).await?; + .context(NodeConfigSnafu) + .context(HandleSnafu)?; + let handle = spin_up_swarm::(TIMEOUT, known_peers, config, idx) + .await + .context(HandleSnafu)?; let handle_dup = handle.clone(); // periodically broadcast state back to conductor node spawn(async move { + // FIXME map option to error let conductor_id = swarm_config .iter() .find(|c| c.node_type == NetworkNodeType::Conductor) @@ -324,13 +330,13 @@ pub async fn start_main(idx: usize) -> Result<(), NetworkNodeHandleError> { sleep(Duration::from_secs(1)).await; let counter = *handle_dup.state.lock().await; let msg = Message::NormalMessage(CounterRequest::MyCounterIs(counter)); - let serialized_msg = serialize_msg(&msg).unwrap(); + let serialized_msg = serialize_msg(&msg).context(SerializationSnafu).context(HandleSnafu)?; handle_dup .send_network .send_async(ClientRequest::DirectRequest(conductor_id, serialized_msg)) - .await - .unwrap(); + .await.context(SendSnafu).context(HandleSnafu)?; } + Ok::<(), CounterError>(()) }); spawn_handler(handle.clone(), regular_handle_network_event).await; while !*handle.killed.lock().await {} @@ -438,3 +444,18 @@ pub async fn conductor_handle_network_event( } Ok(()) } + +#[derive(Debug, Snafu)] +#[snafu(visibility(pub))] +pub enum CounterError { + Handle { + source: NetworkNodeHandleError, + }, + FileRead { + source: std::io::Error, + }, + JsonParse { + source: serde_json::Error, + }, + MissingBootstrap +} From 1248ccfcdae271d64d86f17384af2fc407d3ac60 Mon Sep 17 00:00:00 2001 From: Justin Restivo Date: Mon, 21 Feb 2022 09:01:35 -0500 Subject: [PATCH 087/107] fix: error handling in json keypair deserialization --- libp2p-networking/examples/common/mod.rs | 26 ++++++++++++------------ libp2p-networking/src/parse_config.rs | 12 ++++++++--- libp2p-networking/tests/counter.rs | 20 ++++++++---------- 3 files changed, 31 insertions(+), 27 deletions(-) diff --git a/libp2p-networking/examples/common/mod.rs b/libp2p-networking/examples/common/mod.rs index 6bb86d2aef..ebc8ed00c2 100644 --- a/libp2p-networking/examples/common/mod.rs +++ b/libp2p-networking/examples/common/mod.rs @@ -190,7 +190,9 @@ pub struct CliOpt { } pub async fn parse_config() -> Result, CounterError> { - let mut f = File::open(&"./identity_mapping.json").await.context(FileReadSnafu)?; + let mut f = File::open(&"./identity_mapping.json") + .await + .context(FileReadSnafu)?; let mut s = String::new(); f.read_to_string(&mut s).await.context(FileReadSnafu)?; serde_json::from_str(&s).context(JsonParseSnafu) @@ -330,11 +332,15 @@ pub async fn start_main(idx: usize) -> Result<(), CounterError> { sleep(Duration::from_secs(1)).await; let counter = *handle_dup.state.lock().await; let msg = Message::NormalMessage(CounterRequest::MyCounterIs(counter)); - let serialized_msg = serialize_msg(&msg).context(SerializationSnafu).context(HandleSnafu)?; + let serialized_msg = serialize_msg(&msg) + .context(SerializationSnafu) + .context(HandleSnafu)?; handle_dup .send_network .send_async(ClientRequest::DirectRequest(conductor_id, serialized_msg)) - .await.context(SendSnafu).context(HandleSnafu)?; + .await + .context(SendSnafu) + .context(HandleSnafu)?; } Ok::<(), CounterError>(()) }); @@ -448,14 +454,8 @@ pub async fn conductor_handle_network_event( #[derive(Debug, Snafu)] #[snafu(visibility(pub))] pub enum CounterError { - Handle { - source: NetworkNodeHandleError, - }, - FileRead { - source: std::io::Error, - }, - JsonParse { - source: serde_json::Error, - }, - MissingBootstrap + Handle { source: NetworkNodeHandleError }, + FileRead { source: std::io::Error }, + JsonParse { source: serde_json::Error }, + MissingBootstrap, } diff --git a/libp2p-networking/src/parse_config.rs b/libp2p-networking/src/parse_config.rs index daba2583a1..805d210322 100644 --- a/libp2p-networking/src/parse_config.rs +++ b/libp2p-networking/src/parse_config.rs @@ -1,6 +1,10 @@ use crate::network_node::NetworkNodeType; use libp2p::{identity::Keypair, Multiaddr}; -use serde::{de::Visitor, ser::Error, Deserialize, Deserializer, Serialize, Serializer}; +use serde::{ + de::{Unexpected, Visitor}, + ser::Error, + Deserialize, Deserializer, Serialize, Serializer, +}; use std::fmt; /// starting network topology @@ -44,8 +48,10 @@ impl<'de> Visitor<'de> for KeypairVisitor { while let Ok(Some(a)) = seq.next_element() { parsed.push(a); } - // FIXME figure out how to use the error type - Ok(Keypair::from_protobuf_encoding(&parsed).unwrap()) + // we couldn't deserialize the keypair, so the value + // is unexpected + Keypair::from_protobuf_encoding(&parsed) + .map_err(|_e| serde::de::Error::invalid_value(Unexpected::Seq, &self)) } } diff --git a/libp2p-networking/tests/counter.rs b/libp2p-networking/tests/counter.rs index fd27ba7037..461bf7e0e8 100644 --- a/libp2p-networking/tests/counter.rs +++ b/libp2p-networking/tests/counter.rs @@ -258,17 +258,15 @@ async fn run_request_response_increment_all(handles: &[Arc>() - ); - } + if results.iter().find(|x| x.is_err()).is_some() { + print_connections(handles).await; + panic!( + "{:?}", + results + .into_iter() + .filter(|r| r.is_err()) + .collect::>() + ); } check_connection_state(handles).await; From be08b60874e99f63bdf6b659d9c46aca3d54f1ae Mon Sep 17 00:00:00 2001 From: Justin Restivo Date: Mon, 21 Feb 2022 09:01:56 -0500 Subject: [PATCH 088/107] feat: working direct message test --- libp2p-networking/examples/common/mod.rs | 120 +++++++++++++++++++---- libp2p-networking/examples/counter.rs | 2 + 2 files changed, 101 insertions(+), 21 deletions(-) diff --git a/libp2p-networking/examples/common/mod.rs b/libp2p-networking/examples/common/mod.rs index ebc8ed00c2..8e8ea94cad 100644 --- a/libp2p-networking/examples/common/mod.rs +++ b/libp2p-networking/examples/common/mod.rs @@ -87,8 +87,10 @@ pub async fn handle_normal_msg( // only as a response CounterRequest::AskForCounter => { if let Some(chan) = chan { - let response = CounterRequest::MyCounterIs(*handle.state.lock().await); + let response = + Message::NormalMessage(CounterRequest::MyCounterIs(*handle.state.lock().await)); let serialized_response = serialize_msg(&response).context(SerializationSnafu)?; + println!("sending back reponse: {:?})", response); handle .send_network .send_async(ClientRequest::DirectResponse(chan, serialized_response)) @@ -120,7 +122,6 @@ pub async fn regular_handle_network_event( if let Ok(msg) = deserialize_msg::(&m) { match msg { Message::NormalMessage(msg) => { - println!("recv-ed gossip message"); handle_normal_msg(handle.clone(), msg, None).await?; } Message::ConductorMessage(..) => { @@ -134,7 +135,7 @@ pub async fn regular_handle_network_event( if let Ok(msg) = deserialize_msg::(&msg) { match msg { Message::NormalMessage(msg) => { - println!("recv-ed normal direct message"); + println!("recv-ed normal direct message {:?}", msg); handle_normal_msg(handle.clone(), msg, Some(chan)).await?; } Message::ConductorMessage(msg, method) => { @@ -253,12 +254,18 @@ pub async fn start_main(idx: usize) -> Result<(), CounterError> { } drop(state); - for i in 0..10 { + for i in 0..5 { conductor_broadcast(TIMEOUT, i, handle.clone()) .await .context(HandleSnafu)? } + for j in 5..10 { + conductor_direct_message(TIMEOUT, j, handle.clone()) + .await + .context(HandleSnafu)? + } + let kill_msg = Message::NormalMessage(CounterRequest::Kill); let serialized_kill_msg = serialize_msg(&kill_msg) .context(SerializationSnafu) @@ -282,12 +289,6 @@ pub async fn start_main(idx: usize) -> Result<(), CounterError> { .is_empty() {} - // FIXME we need to fix clippy warnings - - // FIXME we need to fix the serialization to do error handling properly - - // FIXME we need to convince the inner networking implementation to ignore the conductor nodes - // FIXME // we need one other primitive here: // - tell a node to tell all other nodes to increment state with direct message @@ -352,15 +353,91 @@ pub async fn start_main(idx: usize) -> Result<(), CounterError> { Ok(()) } +pub async fn conductor_direct_message( + timeout: Duration, + state: CounterState, + handle: Arc>, +) -> Result<(), NetworkNodeHandleError> { + // new state + let new_state = state + 1; + + // pick a peer to do the be the recipient of the direct messages + let mut known_peers = handle.connection_state.lock().await.known_peers.clone(); + known_peers.remove(&handle.peer_id); + + // FIXME wrapper error + let chosen_peer = known_peers.iter().choose(&mut thread_rng()).unwrap(); + println!("chosen peer is {:?}", chosen_peer); + + // step 1: increment counter on the chosen node + + // set up listener before any state has the chance to change + let res_fut = + handle + .state_changed + .wait_timeout_until(handle.state.lock().await, timeout, |state| { + *state.get(chosen_peer).unwrap() == new_state + }); + + // dispatch message + let msg = Message::NormalMessage(CounterRequest::IncrementCounter { + from: state, + to: new_state, + }); + let serialized_msg = serialize_msg(&msg).context(SerializationSnafu)?; + handle + .send_network + .send_async(ClientRequest::DirectRequest(*chosen_peer, serialized_msg)) + .await + .context(SendSnafu)?; + + if res_fut.await.1.timed_out() { + panic!("timeout!"); + } + + println!("step 1 is complete!"); + + // step 2: iterate through remaining nodes, message them "request state from chosen node" + + // set up listener first + let res_fut = + handle + .state_changed + .wait_timeout_until(handle.state.lock().await, timeout, |state| { + state.iter().all(|(_, &s)| s == new_state) + }); + + // send out the requests to ask the chosen peer for its state (and replace ours) + + let mut remaining_nodes = known_peers.clone(); + remaining_nodes.remove(&chosen_peer); + + for peer in &remaining_nodes { + let msg = Message::ConductorMessage( + CounterRequest::AskForCounter, + ConductorMessageMethod::DirectMessage(*chosen_peer), + ); + let serialized_msg = serialize_msg(&msg).context(SerializationSnafu)?; + handle + .send_network + .send_async(ClientRequest::DirectRequest(*peer, serialized_msg)) + .await + .context(SendSnafu)?; + } + + if res_fut.await.1.timed_out() { + panic!("timeout!"); + } else { + Ok(()) + } +} + pub async fn conductor_broadcast( timeout: Duration, state: CounterState, handle: Arc>, ) -> Result<(), NetworkNodeHandleError> { - // start listener future with timeout - // let new_state = state + 1; - // let mut known_peers = handle.connection_state.lock().await.known_peers.clone(); known_peers.remove(&handle.peer_id); @@ -383,6 +460,14 @@ pub async fn conductor_broadcast( .await .context(SendSnafu)?; + // set up listener before any state has the chance to change + let res_fut = + handle + .state_changed + .wait_timeout_until(handle.state.lock().await, timeout, |state| { + state.iter().all(|(_, &s)| s == new_state) + }); + let msg_direct = Message::NormalMessage(request); let serialized_msg_direct = serialize_msg(&msg_direct).context(SerializationSnafu)?; handle @@ -394,14 +479,7 @@ pub async fn conductor_broadcast( .await .context(SendSnafu)?; - let (_, res) = handle - .state_changed - .wait_timeout_until(handle.state.lock().await, timeout, |state| { - state.iter().all(|(_, &s)| s == new_state) - }) - .await; - - if res.timed_out() { + if res_fut.await.1.timed_out() { panic!("timeout!"); } else { Ok(()) diff --git a/libp2p-networking/examples/counter.rs b/libp2p-networking/examples/counter.rs index a3da08948a..9f8e7c6a2b 100644 --- a/libp2p-networking/examples/counter.rs +++ b/libp2p-networking/examples/counter.rs @@ -11,5 +11,7 @@ mod common; async fn main() -> Result<()> { println!("hello world we are starting"); common::start_main(common::CliOpt::from_args().idx.unwrap()).await?; + + // optional UI perhaps? for monitoring purposes Ok(()) } From aa1015fd46b76eb5b0aaa28a7bfc4cb49c7ba489 Mon Sep 17 00:00:00 2001 From: Justin Restivo Date: Tue, 22 Feb 2022 08:56:53 -0500 Subject: [PATCH 089/107] fix: bind to bound_addr on regular/bootstrap nodes --- libp2p-networking/examples/common/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libp2p-networking/examples/common/mod.rs b/libp2p-networking/examples/common/mod.rs index 8e8ea94cad..4767cd4310 100644 --- a/libp2p-networking/examples/common/mod.rs +++ b/libp2p-networking/examples/common/mod.rs @@ -306,7 +306,7 @@ pub async fn start_main(idx: usize) -> Result<(), CounterError> { }) .collect::>(); let config = NetworkNodeConfigBuilder::default() - .bound_addr(Some(swarm_config[idx].multiaddr.clone())) + .bound_addr(Some(swarm_config[idx].bound_addr.clone())) .identity(Some(swarm_config[idx].identity.clone())) .ignored_peers(ignored_peers) .min_num_peers(swarm_config.len() / 4) From 942a556d5a8f8672c8520a55e47194147f380030 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 23 Feb 2022 04:34:21 +0000 Subject: [PATCH 090/107] chore(deps): bump libp2p from 0.42.2 to 0.43.0 Bumps [libp2p](https://github.com/libp2p/rust-libp2p) from 0.42.2 to 0.43.0. - [Release notes](https://github.com/libp2p/rust-libp2p/releases) - [Changelog](https://github.com/libp2p/rust-libp2p/blob/master/CHANGELOG.md) - [Commits](https://github.com/libp2p/rust-libp2p/compare/v0.42.2...v0.43.0) --- updated-dependencies: - dependency-name: libp2p dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- libp2p-networking/Cargo.lock | 307 +++++++++++++++++++---------------- libp2p-networking/Cargo.toml | 2 +- 2 files changed, 164 insertions(+), 145 deletions(-) diff --git a/libp2p-networking/Cargo.lock b/libp2p-networking/Cargo.lock index 2035cbfaf5..054323c3f5 100644 --- a/libp2p-networking/Cargo.lock +++ b/libp2p-networking/Cargo.lock @@ -365,13 +365,11 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "blake2" -version = "0.9.2" +version = "0.10.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a4e37d16930f5459780f5621038b6382b9bb37c19016f39fb6b5808d831f174" +checksum = "b9cf849ee05b2ee5fba5e36f97ff8ec2533916700fc0758d40d92136a42f3388" dependencies = [ - "crypto-mac", - "digest 0.9.0", - "opaque-debug", + "digest 0.10.3", ] [[package]] @@ -385,7 +383,7 @@ dependencies = [ "cc", "cfg-if", "constant_time_eq", - "digest 0.10.1", + "digest 0.10.3", ] [[package]] @@ -480,9 +478,9 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "chacha20" -version = "0.7.3" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f08493fa7707effc63254c66c6ea908675912493cd67952eda23c09fae2610b1" +checksum = "01b72a433d0cf2aef113ba70f62634c56fddb0f244e6377185c56a7cadbd8f91" dependencies = [ "cfg-if", "cipher", @@ -492,9 +490,9 @@ dependencies = [ [[package]] name = "chacha20poly1305" -version = "0.8.2" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6547abe025f4027edacd9edaa357aded014eecec42a5070d9b885c3c334aba2" +checksum = "3b84ed6d1d5f7aa9bdde921a5090e0ca4d934d250ea3b402a5fab3a994e28a2a" dependencies = [ "aead", "chacha20", @@ -585,6 +583,15 @@ version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5827cebf4670468b8772dd191856768aedcb1b0278a04f989f7766351917b9dc" +[[package]] +name = "core2" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b49ba7ef1ad6107f8824dbe97de947cbaac53c44e7f9756a1fba0d37c1eec505" +dependencies = [ + "memchr", +] + [[package]] name = "cpufeatures" version = "0.2.1" @@ -663,11 +670,12 @@ checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" [[package]] name = "crypto-common" -version = "0.1.1" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "683d6b536309245c849479fba3da410962a43ed8e51c26b729208ec0ac2798d0" +checksum = "57952ca27b5e3606ff4dd79b0020231aaf9d6aa76dc05fd30137538c50bd3ce8" dependencies = [ "generic-array", + "typenum", ] [[package]] @@ -723,6 +731,19 @@ dependencies = [ "zeroize", ] +[[package]] +name = "curve25519-dalek" +version = "4.0.0-pre.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "12dc3116fe595d7847c701796ac1b189bd86b81f4f593c6f775f9d80fb2e29f4" +dependencies = [ + "byteorder", + "digest 0.10.3", + "rand_core 0.6.3", + "subtle", + "zeroize", +] + [[package]] name = "darling" version = "0.12.4" @@ -806,13 +827,12 @@ dependencies = [ [[package]] name = "digest" -version = "0.10.1" +version = "0.10.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b697d66081d42af4fba142d56918a3cb21dc8eb63372c6b85d14f44fb9c5979b" +checksum = "f2fb860ca6fafa5552fb6d0e816a69c8e49f0908bf524e30a90d97c85892d506" dependencies = [ "block-buffer 0.10.0", "crypto-common", - "generic-array", "subtle", ] @@ -853,7 +873,7 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c762bae6dcaf24c4c84667b8579785430908723d5c889f469d76a41d59cc7a9d" dependencies = [ - "curve25519-dalek", + "curve25519-dalek 3.2.0", "ed25519", "rand 0.7.3", "serde", @@ -1080,7 +1100,6 @@ version = "0.14.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fd48d33ec7f05fbfa152300fdad764757cbded343c1aa1cff2fbaf4134851803" dependencies = [ - "serde", "typenum", "version_check", ] @@ -1356,9 +1375,9 @@ checksum = "1b03d17f364a3a042d5e5d46b053bbbf82c92c9430c592dd4c064dc6ee997125" [[package]] name = "libp2p" -version = "0.42.2" +version = "0.43.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f592f1b06f12a5686a5de7be9f289a161c96d5f89f12b04b7d14cf3d61d7381" +checksum = "4e8570e25fa03d4385405dbeaf540ba00e3ee50942f03d84e1a8928a029f35f9" dependencies = [ "atomic", "bytes", @@ -1393,7 +1412,7 @@ dependencies = [ "libp2p-websocket", "libp2p-yamux", "multiaddr", - "parking_lot 0.11.2", + "parking_lot 0.12.0", "pin-project 1.0.10", "rand 0.7.3", "smallvec", @@ -1401,9 +1420,9 @@ dependencies = [ [[package]] name = "libp2p-autonat" -version = "0.1.0" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c0e6bbc00385edde71430e7d261d13edebcf0e52aecac8f0081a299f960c545" +checksum = "cd6314084638e09e4162a5c6d0c1ba859f5d5f8a045ca015f7c95325e4b7c230" dependencies = [ "async-trait", "futures", @@ -1420,9 +1439,9 @@ dependencies = [ [[package]] name = "libp2p-core" -version = "0.31.1" +version = "0.32.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77c4178afd65bf7c56744b4e0a6cfa6e9b694fe666efba596e03a46f79454d8d" +checksum = "9164ec41455856e8187addc870bb4fe1ea2ee28e1a9244831d449a2429b32c1a" dependencies = [ "asn1_der", "bs58", @@ -1438,7 +1457,7 @@ dependencies = [ "multiaddr", "multihash", "multistream-select", - "parking_lot 0.11.2", + "parking_lot 0.12.0", "pin-project 1.0.10", "prost", "prost-build", @@ -1456,9 +1475,9 @@ dependencies = [ [[package]] name = "libp2p-deflate" -version = "0.31.0" +version = "0.32.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d56c68b9c5d435bbd8cdd20101348194b18d1e6ff29ece7a223734aa7eb695c" +checksum = "6b1d37f042f748e224f04785d0e987ae09a2aa518d6401d82d412dad83e360ed" dependencies = [ "flate2", "futures", @@ -1467,9 +1486,9 @@ dependencies = [ [[package]] name = "libp2p-dns" -version = "0.31.0" +version = "0.32.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39d4a2e7efe62c738833b6be6c0f158cf7ffccba462320f4b3bebe43e1050e7b" +checksum = "7838647d33978b77f943687412f4a39e74234c8342cbfdad14282b465b272cb4" dependencies = [ "async-std-resolver", "futures", @@ -1481,9 +1500,9 @@ dependencies = [ [[package]] name = "libp2p-floodsub" -version = "0.33.0" +version = "0.34.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "604b6ad64c07a49a9e5e78d4f25c9ad28a17d5fefb1384d7ea35b3201e4aeed3" +checksum = "df0b7d6c3fa2ead77a5bbeff580bd7507efcc9d7fa9d0caf873795b097d385c0" dependencies = [ "cuckoofilter", "fnv", @@ -1499,9 +1518,9 @@ dependencies = [ [[package]] name = "libp2p-gossipsub" -version = "0.35.0" +version = "0.36.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "385ae5f44e84f51e17014c9f1d98464121d3b1b182c167a0b4482d6250c61926" +checksum = "6f62943fba0b0dae02b87868620c52a581c54ec9fb04b5e195cf20313fc510c3" dependencies = [ "asynchronous-codec", "base64", @@ -1509,14 +1528,12 @@ dependencies = [ "bytes", "fnv", "futures", - "futures-timer", "hex_fmt", "instant", "libp2p-core", "libp2p-swarm", "log", - "open-metrics-client", - "pin-project 1.0.10", + "prometheus-client", "prost", "prost-build", "rand 0.7.3", @@ -1525,13 +1542,14 @@ dependencies = [ "sha2 0.10.1", "smallvec", "unsigned-varint", + "wasm-timer", ] [[package]] name = "libp2p-identify" -version = "0.33.0" +version = "0.34.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae5d84b4e57cb66abb9dd28ea36f69620816e004a7479c0ad76f45002820f99b" +checksum = "1f219b4d4660fe3a04bf5fe6b5970902b7c1918e25b2536be8c70efc480f88f8" dependencies = [ "futures", "futures-timer", @@ -1546,9 +1564,9 @@ dependencies = [ [[package]] name = "libp2p-kad" -version = "0.34.0" +version = "0.35.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0eeaa28a4c7a8c574874e090c2a731ecc7b81595911fee425b552c799a20abbb" +checksum = "aead5ee2322a7b825c7633065370909c8383046f955cda5b56797e6904db7a72" dependencies = [ "arrayvec 0.5.2", "asynchronous-codec", @@ -1575,9 +1593,9 @@ dependencies = [ [[package]] name = "libp2p-mdns" -version = "0.34.0" +version = "0.35.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d5904049ad1fee7f2c2c792be892f3dde8ff5c21213d55702a35e777311326f" +checksum = "54d1914576978e5f3b15ac99e2cda9b56471ce64f1cfc7c2b09ac0cee147175e" dependencies = [ "async-io", "data-encoding", @@ -1596,9 +1614,9 @@ dependencies = [ [[package]] name = "libp2p-metrics" -version = "0.3.0" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0791098ddec13b0c2f9ed37a29175f7c712ce8804ebaba7cbd8bddbc83120190" +checksum = "d29e4e5e4c5aa567fe1ee3133afe088dc2d2fd104e20c5c2c5c2649f75129677" dependencies = [ "libp2p-core", "libp2p-gossipsub", @@ -1607,14 +1625,14 @@ dependencies = [ "libp2p-ping", "libp2p-relay", "libp2p-swarm", - "open-metrics-client", + "prometheus-client", ] [[package]] name = "libp2p-mplex" -version = "0.31.0" +version = "0.32.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49d470ee73a74340e429fa278469ed274a648738e3fb8de2e8d113482441732f" +checksum = "442eb0c9fff0bf22a34f015724b4143ce01877e079ed0963c722d94c07c72160" dependencies = [ "asynchronous-codec", "bytes", @@ -1622,7 +1640,7 @@ dependencies = [ "libp2p-core", "log", "nohash-hasher", - "parking_lot 0.11.2", + "parking_lot 0.12.0", "rand 0.7.3", "smallvec", "unsigned-varint", @@ -1630,12 +1648,12 @@ dependencies = [ [[package]] name = "libp2p-noise" -version = "0.34.0" +version = "0.35.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3676dc2df10a7f4f6a80fbeaf2ce4168a0ca6567273e3105b21fa4c877be9017" +checksum = "9dd7e0c94051cda67123be68cf6b65211ba3dde7277be9068412de3e7ffd63ef" dependencies = [ "bytes", - "curve25519-dalek", + "curve25519-dalek 3.2.0", "futures", "lazy_static", "libp2p-core", @@ -1652,9 +1670,9 @@ dependencies = [ [[package]] name = "libp2p-ping" -version = "0.33.0" +version = "0.34.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d384b30135f122a59bf0d186647ad307da0878a9563232cb382d9dbded6a393e" +checksum = "9ab44a12d372d6abdd326c468c1d5b002be06fbd923c5a799d6a9d3b36646ca3" dependencies = [ "futures", "futures-timer", @@ -1668,9 +1686,9 @@ dependencies = [ [[package]] name = "libp2p-plaintext" -version = "0.31.0" +version = "0.32.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "83203abb14ae77de42c49be8dbed7ea8dfb83e76773226aa664a96e6c5e18c5d" +checksum = "962c0fb0e7212fb96a69b87f2d09bcefd317935239bdc79cda900e7a8897a3fe" dependencies = [ "asynchronous-codec", "bytes", @@ -1699,9 +1717,9 @@ dependencies = [ [[package]] name = "libp2p-relay" -version = "0.6.1" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "adb41d0408839f0975af3e5820bdc3ceea308a7282785d7ca77d28ea33dbb62a" +checksum = "517be90a2ce60b6c3bdfe88f34cc789c61dafe6f694a7b45e644af7353880fa3" dependencies = [ "asynchronous-codec", "bytes", @@ -1725,9 +1743,9 @@ dependencies = [ [[package]] name = "libp2p-rendezvous" -version = "0.3.0" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec166a822f4167929c8e1673c05106f7c86a42b8e9e917b569e1d86f06b9d8b5" +checksum = "597e4a022dd2e168ce1218faf6b3aead5c427fb828eb4f982cef7c40d4b7f49e" dependencies = [ "asynchronous-codec", "bimap", @@ -1748,9 +1766,9 @@ dependencies = [ [[package]] name = "libp2p-request-response" -version = "0.15.0" +version = "0.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "36194499f5b03d66d56badbed430d93bf1bfd9cec80311e03280de130fbe3d5e" +checksum = "12388a73626d1727524069cce0bb05a9c428581de435278a070c55ae27cc7e73" dependencies = [ "async-trait", "bytes", @@ -1766,26 +1784,29 @@ dependencies = [ [[package]] name = "libp2p-swarm" -version = "0.33.0" +version = "0.34.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db8ae0811c7a05b6edc6684eb5cc69b055cbb715ad780e6b97872d90308503c1" +checksum = "53ab2d4eb8ef2966b10fdf859245cdd231026df76d3c6ed2cf9e418a8f688ec9" dependencies = [ "either", + "fnv", "futures", "futures-timer", "instant", "libp2p-core", "log", + "pin-project 1.0.10", "rand 0.7.3", "smallvec", + "thiserror", "void", ] [[package]] name = "libp2p-swarm-derive" -version = "0.26.1" +version = "0.27.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33b4d0acd47739fe0b570728d8d11bbb535050d84c0cf05d6477a4891fceae10" +checksum = "4b8153a6472e84ec888ef2bf21deafe8d4214e811f0f162abbf07156c27f8fa8" dependencies = [ "quote", "syn", @@ -1793,9 +1814,9 @@ dependencies = [ [[package]] name = "libp2p-tcp" -version = "0.31.1" +version = "0.32.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "52042e8796c5b58d0415bceb1bcb1bcca28b222339978e52b1a0305800bb5199" +checksum = "193447aa729c85aac2376828df76d171c1a589c9e6b58fcc7f9d9a020734122c" dependencies = [ "async-io", "futures", @@ -1810,9 +1831,9 @@ dependencies = [ [[package]] name = "libp2p-uds" -version = "0.31.0" +version = "0.32.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "098f90cb3a0273a830d2595ca7f4de6ca848530ee42324f5c660e2b8955211df" +checksum = "24bdab114f7f2701757d6541266e1131b429bbae382008f207f2114ee4222dcb" dependencies = [ "async-std", "futures", @@ -1822,9 +1843,9 @@ dependencies = [ [[package]] name = "libp2p-wasm-ext" -version = "0.31.0" +version = "0.32.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be0e8a3817fc156752f6695e57630a9bceb6ae92e9b9f0a161552702fd76ad45" +checksum = "4f6ea0f84a967ef59a16083f222c18115ae2e91db69809dce275df62e101b279" dependencies = [ "futures", "js-sys", @@ -1836,9 +1857,9 @@ dependencies = [ [[package]] name = "libp2p-websocket" -version = "0.33.0" +version = "0.34.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "83d788da0ab952632d6ead2486baf38a98db92907d4bc5d0f324af0d0fab803d" +checksum = "c932834c3754501c368d1bf3d0fb458487a642b90fc25df082a3a2f3d3b32e37" dependencies = [ "either", "futures", @@ -1854,13 +1875,13 @@ dependencies = [ [[package]] name = "libp2p-yamux" -version = "0.35.0" +version = "0.36.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "053d13ce0670d29f9c5a974cf371e6cc4d2d864da1c72bf6870ac5d5e45e2036" +checksum = "be902ebd89193cd020e89e89107726a38cfc0d16d18f613f4a37d046e92c7517" dependencies = [ "futures", "libp2p-core", - "parking_lot 0.11.2", + "parking_lot 0.12.0", "thiserror", "yamux", ] @@ -2037,9 +2058,9 @@ dependencies = [ [[package]] name = "multiaddr" -version = "0.13.0" +version = "0.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48ee4ea82141951ac6379f964f71b20876d43712bea8faf6dd1a375e08a46499" +checksum = "3c580bfdd8803cce319b047d239559a22f809094aaea4ac13902a1fdcfcd4261" dependencies = [ "arrayref", "bs58", @@ -2055,23 +2076,24 @@ dependencies = [ [[package]] name = "multihash" -version = "0.14.0" +version = "0.16.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "752a61cd890ff691b4411423d23816d5866dd5621e4d1c5687a53b94b5a979d8" +checksum = "7392bffd88bc0c4f8297e36a777ab9f80b7127409c4a1acb8fee99c9f27addcd" dependencies = [ - "digest 0.9.0", - "generic-array", + "core2", + "digest 0.10.3", "multihash-derive", "serde", - "sha2 0.9.9", + "serde-big-array", + "sha2 0.10.1", "unsigned-varint", ] [[package]] name = "multihash-derive" -version = "0.7.2" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "424f6e86263cd5294cbd7f1e95746b95aca0e0d66bff31e5a40d6baa87b4aa99" +checksum = "fc076939022111618a5026d3be019fd8b366e76314538ff9a1b59ffbcbf98bcd" dependencies = [ "proc-macro-crate", "proc-macro-error", @@ -2260,29 +2282,6 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" -[[package]] -name = "open-metrics-client" -version = "0.14.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f85842b073145726190373213c63f852020fb884c841a3a1f390637267a2fb8c" -dependencies = [ - "dtoa", - "itoa", - "open-metrics-client-derive-text-encode", - "owning_ref", -] - -[[package]] -name = "open-metrics-client-derive-text-encode" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a15c83b586f00268c619c1cb3340ec1a6f59dd9ba1d9833a273a68e6d5cd8ffc" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - [[package]] name = "owning_ref" version = "0.4.1" @@ -2370,15 +2369,6 @@ version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e" -[[package]] -name = "pest" -version = "2.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "10f4872ae94d7b90ae48754df22fd42ad52ce740b8f370b03da4835417403e53" -dependencies = [ - "ucd-trie", -] - [[package]] name = "petgraph" version = "0.6.0" @@ -2538,6 +2528,29 @@ dependencies = [ "unicode-xid", ] +[[package]] +name = "prometheus-client" +version = "0.15.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c9a896938cc6018c64f279888b8c7559d3725210d5db9a3a1ee6bc7188d51d34" +dependencies = [ + "dtoa", + "itoa", + "owning_ref", + "prometheus-client-derive-text-encode", +] + +[[package]] +name = "prometheus-client-derive-text-encode" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8e12d01b9d66ad9eb4529c57666b6263fc1993cb30261d83ead658fdd932652" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "prost" version = "0.9.0" @@ -2780,9 +2793,9 @@ checksum = "7ef03e0a2b150c7a90d01faf6254c9c48a41e95fb2a8c2ac1c6f0d2b9aefc342" [[package]] name = "rustc_version" -version = "0.3.3" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0dfe2087c51c460008730de8b57e6a320782fbfb312e1f4d520e6c6fae155ee" +checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" dependencies = [ "semver", ] @@ -2843,28 +2856,26 @@ dependencies = [ [[package]] name = "semver" -version = "0.11.0" +version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f301af10236f6df4160f7c3f04eec6dbc70ace82d23326abad5edee88801c6b6" -dependencies = [ - "semver-parser", -] +checksum = "a4a3381e03edd24287172047536f20cabde766e2cd3e65e6b00fb3af51c4f38d" [[package]] -name = "semver-parser" -version = "0.10.2" +name = "serde" +version = "1.0.136" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00b0bef5b7f9e0df16536d3961cfb6e84331c065b4066afb39768d0e319411f7" +checksum = "ce31e24b01e1e524df96f1c2fdd054405f8d7376249a5110886fb4b658484789" dependencies = [ - "pest", + "serde_derive", ] [[package]] -name = "serde" -version = "1.0.136" +name = "serde-big-array" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce31e24b01e1e524df96f1c2fdd054405f8d7376249a5110886fb4b658484789" +checksum = "18b20e7752957bbe9661cff4e0bb04d183d0948cdab2ea58cdb9df36a61dfe62" dependencies = [ + "serde", "serde_derive", ] @@ -2924,7 +2935,7 @@ checksum = "99c3bd8169c58782adad9290a9af5939994036b76187f7b4f0e6de91dbbfc0ec" dependencies = [ "cfg-if", "cpufeatures", - "digest 0.10.1", + "digest 0.10.3", ] [[package]] @@ -3020,20 +3031,19 @@ dependencies = [ [[package]] name = "snow" -version = "0.8.0" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6142f7c25e94f6fd25a32c3348ec230df9109b463f59c8c7acc4bd34936babb7" +checksum = "774d05a3edae07ce6d68ea6984f3c05e9bba8927e3dd591e3b479e5b03213d0d" dependencies = [ "aes-gcm", "blake2", "chacha20poly1305", - "rand 0.8.5", + "curve25519-dalek 4.0.0-pre.2", "rand_core 0.6.3", "ring", "rustc_version", - "sha2 0.9.9", + "sha2 0.10.1", "subtle", - "x25519-dalek", ] [[package]] @@ -3420,12 +3430,6 @@ version = "1.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dcf81ac59edc17cc8697ff311e8f5ef2d99fcbd9817b34cec66f90b6c3dfd987" -[[package]] -name = "ucd-trie" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56dee185309b50d1f11bfedef0fe6d036842e3fb77413abef29f8f8d1c5d4c1c" - [[package]] name = "uint" version = "0.9.1" @@ -3635,6 +3639,21 @@ version = "0.2.78" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0237232789cf037d5480773fe568aac745bfe2afbc11a863e97901780a6b47cc" +[[package]] +name = "wasm-timer" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be0ecb0db480561e9a7642b5d3e4187c128914e58aa84330b9493e3eb68c5e7f" +dependencies = [ + "futures", + "js-sys", + "parking_lot 0.11.2", + "pin-utils", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", +] + [[package]] name = "web-sys" version = "0.3.55" @@ -3813,7 +3832,7 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2392b6b94a576b4e2bf3c5b2757d63f10ada8020a2e4d08ac849ebcf6ea8e077" dependencies = [ - "curve25519-dalek", + "curve25519-dalek 3.2.0", "rand_core 0.5.1", "zeroize", ] diff --git a/libp2p-networking/Cargo.toml b/libp2p-networking/Cargo.toml index 96ff57e0bc..17ea2bb4b3 100644 --- a/libp2p-networking/Cargo.toml +++ b/libp2p-networking/Cargo.toml @@ -13,7 +13,7 @@ color-eyre = "0.6.0" crossterm = { version = "0.23.0", features = ["event-stream"] } flume = "0.10.11" futures = "0.3.21" -libp2p = { version = "0.42.2", features = ["serde"] } +libp2p = { version = "0.43.0", features = ["serde"] } parking_lot = "0.12.0" serde = { version = "1.0.136", features = ["derive"] } serde_json = "1.0.79" From e7b7c478221c19a33f0a5e0f5414c4736b4f2808 Mon Sep 17 00:00:00 2001 From: Justin Restivo Date: Wed, 23 Feb 2022 08:23:29 -0500 Subject: [PATCH 091/107] chore: ProtocolsHandler -> ConnectionHandler --- libp2p-networking/src/network_node.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/libp2p-networking/src/network_node.rs b/libp2p-networking/src/network_node.rs index 9c68bfff18..0d42006ebb 100644 --- a/libp2p-networking/src/network_node.rs +++ b/libp2p-networking/src/network_node.rs @@ -2,7 +2,7 @@ use crate::direct_message::{DirectMessageCodec, DirectMessageRequest, DirectMess use async_std::task::{sleep, spawn}; use bincode::Options; use libp2p::request_response::RequestId; -use libp2p::swarm::DialError; +use libp2p::swarm::{ConnectionHandlerUpgrErr, DialError}; use rand::{seq::IteratorRandom, thread_rng}; use serde::{Deserialize, Serialize}; use std::collections::HashMap; @@ -41,7 +41,7 @@ use libp2p::{ }, swarm::{ NetworkBehaviour, NetworkBehaviourAction, NetworkBehaviourEventProcess, PollParameters, - ProtocolsHandlerUpgrErr, SwarmEvent, + SwarmEvent, }, tcp, websocket, yamux, Multiaddr, NetworkBehaviour, PeerId, Swarm, Transport, TransportError, }; @@ -146,7 +146,7 @@ impl NetworkDef { &mut self, _cx: &mut Context<'_>, _: &mut impl PollParameters, - ) -> Poll::ProtocolsHandler>> + ) -> Poll::ConnectionHandler>> { // push events that must be relayed back to client onto queue // to be consumed by client event handler @@ -822,7 +822,7 @@ impl NetworkNode { NetworkEvent, EitherError< EitherError, Error>, - ProtocolsHandlerUpgrErr, + ConnectionHandlerUpgrErr, >, >, send_to_client: &Sender, From c41574acc4f1f11df0ef18ec108d8e72968c51b6 Mon Sep 17 00:00:00 2001 From: Justin Restivo Date: Wed, 23 Feb 2022 08:52:28 -0500 Subject: [PATCH 092/107] fix: less verbose tests --- libp2p-networking/src/network_node.rs | 8 ++++---- libp2p-networking/src/network_node_handle.rs | 8 ++++---- libp2p-networking/tests/counter.rs | 2 -- 3 files changed, 8 insertions(+), 10 deletions(-) diff --git a/libp2p-networking/src/network_node.rs b/libp2p-networking/src/network_node.rs index 0d42006ebb..9a8a32a043 100644 --- a/libp2p-networking/src/network_node.rs +++ b/libp2p-networking/src/network_node.rs @@ -647,11 +647,11 @@ impl NetworkNode { if *a_peer != self.peer_id { match self.swarm.dial(*a_peer) { Ok(_) => { - println!("Peer {:?} dial {:?} working!", self.peer_id, a_peer); + info!("Peer {:?} dial {:?} working!", self.peer_id, a_peer); self.swarm.behaviour_mut().connecting_peers.insert(*a_peer); } Err(e) => { - println!("Peer {:?} dial {:?} failed: {:?}", self.peer_id, a_peer, e); + warn!("Peer {:?} dial {:?} failed: {:?}", self.peer_id, a_peer, e); } }; } @@ -880,7 +880,7 @@ impl NetworkNode { endpoint: _, .. } => { - println!("connection closed btwn {:?}, {:?}", self.peer_id, peer_id); + info!("connection closed btwn {:?}, {:?}", self.peer_id, peer_id); let swarm = self.swarm.behaviour_mut(); swarm.connected_peers.remove(&peer_id); // FIXME remove stale address, not *all* addresses @@ -911,7 +911,7 @@ impl NetworkNode { .map_err(|_e| NetworkError::StreamClosed)?; } OutgoingConnectionError { peer_id, error } => { - println!("connecting error {:?}", error); + error!("connecting error {:?}", error); if let Some(peer_id) = peer_id { self.swarm.behaviour_mut().connected_peers.remove(&peer_id); self.swarm.behaviour_mut().connecting_peers.remove(&peer_id); diff --git a/libp2p-networking/src/network_node_handle.rs b/libp2p-networking/src/network_node_handle.rs index 6ff3562676..2ced8301e5 100644 --- a/libp2p-networking/src/network_node_handle.rs +++ b/libp2p-networking/src/network_node_handle.rs @@ -14,7 +14,7 @@ use libp2p::{Multiaddr, PeerId}; use rand::{seq::IteratorRandom, thread_rng}; use snafu::{ResultExt, Snafu}; use std::{fmt::Debug, sync::Arc, time::Duration}; -use tracing::{info_span, instrument, Instrument}; +use tracing::{info, info_span, instrument, Instrument}; /// A handle containing: /// - A reference to the state @@ -109,13 +109,13 @@ impl NetworkNodeHandle { chan: Receiver, node_idx: usize, ) -> Result<(), NetworkNodeHandleError> { - println!("waiting to connect!"); + info!("waiting to connect!"); let mut connected_ok = false; let mut known_ok = false; while !(known_ok && connected_ok) { match chan.recv_async().await.context(RecvSnafu)? { NetworkEvent::UpdateConnectedPeers(pids) => { - println!( + info!( "updating connected peers to: {}, waiting on {}", pids.len(), num_peers @@ -184,7 +184,7 @@ pub async fn spin_up_swarm( ) -> Result>, NetworkNodeHandleError> { let handle = Arc::new(NetworkNodeHandle::new(config.clone(), idx).await?); - println!("known_nodes{:?}", known_nodes); + info!("known_nodes{:?}", known_nodes); handle .send_network .send_async(ClientRequest::AddKnownPeers(known_nodes)) diff --git a/libp2p-networking/tests/counter.rs b/libp2p-networking/tests/counter.rs index 461bf7e0e8..eff618f604 100644 --- a/libp2p-networking/tests/counter.rs +++ b/libp2p-networking/tests/counter.rs @@ -238,7 +238,6 @@ async fn run_gossip_rounds( /// then has all other peers request its state /// and update their state to the recv'ed state async fn run_request_response_increment_all(handles: &[Arc>]) { - check_connection_state(handles).await; let requestee_handle = get_random_handle(handles); *requestee_handle.state.lock().await += 1; requestee_handle @@ -269,7 +268,6 @@ async fn run_request_response_increment_all(handles: &[Arc Date: Wed, 23 Feb 2022 10:51:23 -0500 Subject: [PATCH 093/107] fix: increase timeout, decrease node count --- libp2p-networking/tests/counter.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libp2p-networking/tests/counter.rs b/libp2p-networking/tests/counter.rs index eff618f604..0942c9e77b 100644 --- a/libp2p-networking/tests/counter.rs +++ b/libp2p-networking/tests/counter.rs @@ -25,9 +25,9 @@ use crate::common::print_connections; pub type CounterState = u32; -const TOTAL_NUM_PEERS: usize = 10; +const TOTAL_NUM_PEERS: usize = 9; const NUM_OF_BOOTSTRAP: usize = 3; -const TIMEOUT: Duration = Duration::from_secs(60); +const TIMEOUT: Duration = Duration::from_secs(120); const NUM_ROUNDS: usize = 100; /// Message types. We can either From 3870016b36cbbd2de9152290cae39ee75ff39a8e Mon Sep 17 00:00:00 2001 From: Justin Restivo Date: Wed, 23 Feb 2022 12:02:56 -0500 Subject: [PATCH 094/107] feat: stress and coverage tests --- libp2p-networking/.github/workflows/build.yml | 2 +- .../.github/workflows/coverage.yml | 2 +- libp2p-networking/tests/common/mod.rs | 4 +- libp2p-networking/tests/counter.rs | 253 ++++++++++++------ 4 files changed, 173 insertions(+), 88 deletions(-) diff --git a/libp2p-networking/.github/workflows/build.yml b/libp2p-networking/.github/workflows/build.yml index a8fd368845..e5ae668eb8 100644 --- a/libp2p-networking/.github/workflows/build.yml +++ b/libp2p-networking/.github/workflows/build.yml @@ -50,4 +50,4 @@ jobs: run: cargo build --release - name: Cargo Test - run: cargo test --verbose -- -Zunstable-options --report-time --test-threads=1 + run: cargo test --verbose --release test_stress -- -Zunstable-options --report-time --test-threads=1 diff --git a/libp2p-networking/.github/workflows/coverage.yml b/libp2p-networking/.github/workflows/coverage.yml index 9ff8322bec..b182e128c6 100644 --- a/libp2p-networking/.github/workflows/coverage.yml +++ b/libp2p-networking/.github/workflows/coverage.yml @@ -28,7 +28,7 @@ jobs: uses: actions-rs/cargo@v1 with: command: test - args: --all-features --no-fail-fast -- --test-threads=1 + args: --all-features --no-fail-fast test_coverage -- --test-threads=1 env: CARGO_INCREMENTAL: '0' RUSTFLAGS: '-Zprofile -Ccodegen-units=1 -Cinline-threshold=0 -Clink-dead-code -Coverflow-checks=off -Cpanic=abort -Zpanic_abort_tests' diff --git a/libp2p-networking/tests/common/mod.rs b/libp2p-networking/tests/common/mod.rs index 5775ea107c..ba49addd0b 100644 --- a/libp2p-networking/tests/common/mod.rs +++ b/libp2p-networking/tests/common/mod.rs @@ -40,7 +40,7 @@ pub async fn test_bed, FutG: Future> + 'static + Send + Sync, - F: FnOnce(Vec>>) -> FutF, + F: FnOnce(Vec>>, Duration) -> FutF, G: Fn(NetworkEvent, Arc>) -> FutG + 'static + Send + Sync, { // only call once otherwise panics @@ -62,7 +62,7 @@ pub async fn test_bed>, requestee_handle: Arc>, + timeout: Duration ) -> Result<(), TestError> { let bincode_options = bincode::DefaultOptions::new().with_limit(16_384); let msg_inner = bincode_options @@ -131,7 +137,7 @@ async fn run_request_response_increment( // set up state change listener let recv_fut = requester_handle.state_changed.wait_timeout_until( requester_handle.state.lock().await, - TIMEOUT, + timeout, |state| *state == new_state, ); @@ -170,6 +176,7 @@ async fn run_gossip_round( handles: &[Arc>], msg_inner: Vec, new_state: CounterState, + timeout_duration: Duration ) -> Result<(), TestError> { let msg_handle = get_random_handle(handles); *msg_handle.state.lock().await = new_state; @@ -190,7 +197,7 @@ async fn run_gossip_round( .context(SendSnafu) .context(HandleSnafu)?; - if timeout(TIMEOUT, futures::future::join_all(futs)) + if timeout(timeout_duration, futures::future::join_all(futs)) .await .is_err() { @@ -209,12 +216,57 @@ async fn run_gossip_round( Ok(()) } +async fn run_intersperse_many_rounds(handles: Vec>>, timeout: Duration) { + for i in 0..NUM_ROUNDS as u32 { + if i % 2 == 0 { + run_request_response_increment_all(&handles, timeout).await; + } else { + run_gossip_rounds(&handles, 1, i, timeout).await + } + // println!("finished {}", i); + } + for h in handles.into_iter() { + assert_eq!(*h.state.lock().await, NUM_ROUNDS as u32); + } +} + +async fn run_request_response_many_rounds( + handles: Vec>>, + timeout: Duration + ) { + for _i in 0..NUM_ROUNDS { + run_request_response_increment_all(&handles, timeout).await; + } + for h in handles.into_iter() { + assert_eq!(*h.state.lock().await, NUM_ROUNDS as u32); + } +} + +pub async fn run_request_response_one_round( + handles: Vec>>, + timeout: Duration + ) { + run_request_response_increment_all(&handles, timeout).await; + for h in handles.into_iter() { + assert_eq!(*h.state.lock().await, 1); + } +} + +pub async fn run_gossip_many_rounds(handles: Vec>>, timeout: Duration) { + run_gossip_rounds(&handles, NUM_ROUNDS, 0, timeout).await +} + +async fn run_gossip_one_round(handles: Vec>>, timeout: Duration) { + run_gossip_rounds(&handles, 1, 0, timeout).await +} + /// runs `num_rounds` of message broadcast, incrementing the state of all nodes each broadcast async fn run_gossip_rounds( handles: &[Arc>], num_rounds: usize, starting_state: CounterState, -) { + timeout: Duration + ) { let mut old_state = starting_state; let bincode_options = bincode::DefaultOptions::new().with_limit(16_384); for i in 0..num_rounds { @@ -225,8 +277,8 @@ async fn run_gossip_rounds( from: old_state, to: new_state, }) - .unwrap(); - run_gossip_round(handles, msg_inner, new_state) + .unwrap(); + run_gossip_round(handles, msg_inner, new_state, timeout) .await .unwrap(); old_state = new_state; @@ -237,7 +289,7 @@ async fn run_gossip_rounds( /// increments its state by 1, /// then has all other peers request its state /// and update their state to the recv'ed state -async fn run_request_response_increment_all(handles: &[Arc>]) { +async fn run_request_response_increment_all(handles: &[Arc>], timeout: Duration) { let requestee_handle = get_random_handle(handles); *requestee_handle.state.lock().await += 1; requestee_handle @@ -251,9 +303,10 @@ async fn run_request_response_increment_all(handles: &[Arc>() - ); + .into_iter() + .filter(|r| r.is_err()) + .collect::>() + ); } requestee_handle @@ -278,107 +331,139 @@ async fn run_request_response_increment_all(handles: &[Arc>>, - ) { - run_request_response_increment_all(&handles).await; - for h in handles.into_iter() { - assert_eq!(*h.state.lock().await, 1); - } - } +async fn test_coverage_request_response_one_round() { test_bed( run_request_response_one_round, counter_handle_network_event, - TOTAL_NUM_PEERS, - NUM_OF_BOOTSTRAP, - TIMEOUT, - ) - .await + TOTAL_NUM_PEERS_COVERAGE, + NUM_OF_BOOTSTRAP_COVERAGE, + TIMEOUT_COVERAGE, + ) + .await } /// stress test of direct messsage #[async_std::test] #[instrument] -async fn test_request_response_many_rounds() { - pub async fn run_request_response_many_rounds( - handles: Vec>>, - ) { - let num_rounds = 4092; - for _i in 0..num_rounds { - run_request_response_increment_all(&handles).await; - } - for h in handles.into_iter() { - assert_eq!(*h.state.lock().await, num_rounds); - } - } +async fn test_coverage_request_response_many_rounds() { test_bed( run_request_response_many_rounds, counter_handle_network_event, - TOTAL_NUM_PEERS, - NUM_OF_BOOTSTRAP, - TIMEOUT, - ) - .await + TOTAL_NUM_PEERS_COVERAGE, + NUM_OF_BOOTSTRAP_COVERAGE, + TIMEOUT_COVERAGE, + ) + .await } /// stress test of broadcast + direct message #[async_std::test] #[instrument] -async fn test_intersperse_many_rounds() { - pub async fn run_intersperse_many_rounds(handles: Vec>>) { - for i in 0..NUM_ROUNDS as u32 { - if i % 2 == 0 { - run_request_response_increment_all(&handles).await; - } else { - run_gossip_rounds(&handles, 1, i).await - } - // println!("finished {}", i); - } - for h in handles.into_iter() { - assert_eq!(*h.state.lock().await, NUM_ROUNDS as u32); - } - } +async fn test_coverage_intersperse_many_rounds() { test_bed( run_intersperse_many_rounds, counter_handle_network_event, - TOTAL_NUM_PEERS, - NUM_OF_BOOTSTRAP, - TIMEOUT, - ) - .await + TOTAL_NUM_PEERS_COVERAGE, + NUM_OF_BOOTSTRAP_COVERAGE, + TIMEOUT_COVERAGE, + ) + .await } /// stress teset that we can broadcast a message out and get counter increments #[async_std::test] #[instrument] -async fn test_gossip_many_rounds() { - pub async fn run_gossip_many_rounds(handles: Vec>>) { - run_gossip_rounds(&handles, NUM_ROUNDS, 0).await - } +async fn test_coverage_gossip_many_rounds() { test_bed( run_gossip_many_rounds, counter_handle_network_event, - TOTAL_NUM_PEERS, - NUM_OF_BOOTSTRAP, - TIMEOUT, - ) - .await; + TOTAL_NUM_PEERS_COVERAGE, + NUM_OF_BOOTSTRAP_COVERAGE, + TIMEOUT_COVERAGE, + ) + .await; } /// simple case of broadcast message #[async_std::test] #[instrument] -async fn test_gossip_one_round() { - pub async fn run_gossip_one_round(handles: Vec>>) { - run_gossip_rounds(&handles, 1, 0).await - } +async fn test_coverage_gossip_one_round() { + test_bed( + run_gossip_one_round, + counter_handle_network_event, + TOTAL_NUM_PEERS_COVERAGE, + NUM_OF_BOOTSTRAP_COVERAGE, + TIMEOUT_COVERAGE, + ) + .await; +} + +/// simple case of direct message +#[async_std::test] +#[instrument] +async fn test_stress_request_response_one_round() { + test_bed( + run_request_response_one_round, + counter_handle_network_event, + TOTAL_NUM_PEERS_STRESS, + NUM_OF_BOOTSTRAP_STRESS, + TIMEOUT_STRESS, + ) + .await +} + +/// stress test of direct messsage +#[async_std::test] +#[instrument] +async fn test_stress_request_response_many_rounds() { + test_bed( + run_request_response_many_rounds, + counter_handle_network_event, + TOTAL_NUM_PEERS_STRESS, + NUM_OF_BOOTSTRAP_STRESS, + TIMEOUT_STRESS, + ) + .await +} + +/// stress test of broadcast + direct message +#[async_std::test] +#[instrument] +async fn test_stress_intersperse_many_rounds() { + test_bed( + run_intersperse_many_rounds, + counter_handle_network_event, + TOTAL_NUM_PEERS_STRESS, + NUM_OF_BOOTSTRAP_STRESS, + TIMEOUT_STRESS, + ) + .await +} + +/// stress teset that we can broadcast a message out and get counter increments +#[async_std::test] +#[instrument] +async fn test_stress_gossip_many_rounds() { + test_bed( + run_gossip_many_rounds, + counter_handle_network_event, + TOTAL_NUM_PEERS_STRESS, + NUM_OF_BOOTSTRAP_STRESS, + TIMEOUT_STRESS, + ) + .await; +} + +/// simple case of broadcast message +#[async_std::test] +#[instrument] +async fn test_stress_gossip_one_round() { test_bed( run_gossip_one_round, counter_handle_network_event, - TOTAL_NUM_PEERS, - NUM_OF_BOOTSTRAP, - TIMEOUT, - ) - .await; + TOTAL_NUM_PEERS_STRESS, + NUM_OF_BOOTSTRAP_STRESS, + TIMEOUT_STRESS, + ) + .await; } From 4157ea8a42b6bd5fce0723c924e5b38858997dd6 Mon Sep 17 00:00:00 2001 From: Justin Restivo Date: Thu, 24 Feb 2022 10:09:53 -0500 Subject: [PATCH 095/107] feat: file and ip arguments --- libp2p-networking/examples/common/mod.rs | 27 ++++++++++++++---------- libp2p-networking/examples/counter.rs | 6 ++++-- 2 files changed, 20 insertions(+), 13 deletions(-) diff --git a/libp2p-networking/examples/common/mod.rs b/libp2p-networking/examples/common/mod.rs index 4767cd4310..d5c4aa693d 100644 --- a/libp2p-networking/examples/common/mod.rs +++ b/libp2p-networking/examples/common/mod.rs @@ -186,12 +186,14 @@ pub async fn regular_handle_network_event( #[derive(StructOpt)] pub struct CliOpt { /// Path to the node configuration file - #[structopt(long = "index", short = "i")] - pub idx: Option, + #[structopt(long = "ip_addr", short = "ip")] + pub ip: Option, + #[structopt(long = "toplogy_path", short = "path")] + pub path: Option, } -pub async fn parse_config() -> Result, CounterError> { - let mut f = File::open(&"./identity_mapping.json") +pub async fn parse_config(path: Option) -> Result, CounterError> { + let mut f = File::open(&path.unwrap_or_else(|| "./identity_mapping.json".to_string())) .await .context(FileReadSnafu)?; let mut s = String::new(); @@ -199,13 +201,13 @@ pub async fn parse_config() -> Result, CounterError> { serde_json::from_str(&s).context(JsonParseSnafu) } -pub async fn start_main(idx: usize) -> Result<(), CounterError> { +pub async fn start_main(ip_addr: String, path: Option) -> Result<(), CounterError> { // FIXME can we pass in a function that returns an error type INIT.call_once(|| { color_eyre::install().unwrap(); tracing_setup::setup_tracing(); }); - let swarm_config = parse_config().await?; + let swarm_config = parse_config(path).await?; let ignored_peers = swarm_config .iter() @@ -218,16 +220,19 @@ pub async fn start_main(idx: usize) -> Result<(), CounterError> { }) .collect::>(); - let node_description = &swarm_config[idx]; + let (idx, node_description) = swarm_config.iter().enumerate().find(|(_, node)| { + node.multiaddr.clone().to_string().contains(&ip_addr) + }).unwrap(); + println!("found entry!: {idx}"); match node_description.node_type { NetworkNodeType::Conductor => { let config = NetworkNodeConfigBuilder::default() - .bound_addr(Some(swarm_config[idx].bound_addr.clone())) + .bound_addr(Some(node_description.bound_addr.clone())) .min_num_peers(swarm_config.len() - 1) .max_num_peers(swarm_config.len() - 1) .node_type(NetworkNodeType::Conductor) - .identity(Some(swarm_config[idx].identity.clone())) + .identity(Some(node_description.identity.clone())) .ignored_peers(ignored_peers) .build() .context(NodeConfigSnafu) @@ -306,8 +311,8 @@ pub async fn start_main(idx: usize) -> Result<(), CounterError> { }) .collect::>(); let config = NetworkNodeConfigBuilder::default() - .bound_addr(Some(swarm_config[idx].bound_addr.clone())) - .identity(Some(swarm_config[idx].identity.clone())) + .bound_addr(Some(node_description.bound_addr.clone())) + .identity(Some(node_description.identity.clone())) .ignored_peers(ignored_peers) .min_num_peers(swarm_config.len() / 4) .max_num_peers(swarm_config.len() / 2) diff --git a/libp2p-networking/examples/counter.rs b/libp2p-networking/examples/counter.rs index 9f8e7c6a2b..f32b948cae 100644 --- a/libp2p-networking/examples/counter.rs +++ b/libp2p-networking/examples/counter.rs @@ -6,11 +6,13 @@ use tracing::instrument; mod common; +use common::{start_main, CliOpt}; + #[async_std::main] #[instrument] async fn main() -> Result<()> { - println!("hello world we are starting"); - common::start_main(common::CliOpt::from_args().idx.unwrap()).await?; + let args = CliOpt::from_args(); + start_main(args.ip.unwrap(), args.path).await?; // optional UI perhaps? for monitoring purposes Ok(()) From 84c943fec3a96962ad4f35805fcf622ec52d506e Mon Sep 17 00:00:00 2001 From: Justin Restivo Date: Fri, 25 Feb 2022 10:15:22 -0500 Subject: [PATCH 096/107] feat: build musl --- libp2p-networking/flake.nix | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/libp2p-networking/flake.nix b/libp2p-networking/flake.nix index 90fdd7f891..782431cc8b 100644 --- a/libp2p-networking/flake.nix +++ b/libp2p-networking/flake.nix @@ -21,7 +21,7 @@ outputs = { self, nixpkgs, flake-compat, utils, crate2nix, fenix }: utils.lib.eachDefaultSystem (system: let - fenixStable = fenix.packages.${system}.stable.withComponents [ "cargo" "clippy" "rust-src" "rustc" "rustfmt" ]; + fenixStable = with fenix.packages.${system}; combine [ (stable.withComponents [ "cargo" "clippy" "rustc" "rustfmt" ]) targets.x86_64-unknown-linux-musl.stable.rust-std]; fenixNightly = fenix.packages.${system}.latest.withComponents [ "cargo" "clippy" "rust-src" "rustc" "rustfmt" ]; rustOverlay = final: prev: { @@ -122,7 +122,10 @@ defaultPackage = self.packages.${system}.${crateName}; devShell = pkgs.mkShell { - shellHook = "ulimit -n 1024"; + shellHook = '' + ulimit -n 1024 + export RUSTFLAGS='-C target-feature=+crt-static' + ''; buildInputs = with pkgs; [ fenix.packages.${system}.rust-analyzer fenixStable ] ++ buildDeps; }; From 9b1547d8705126808c11d0e67e1c56a199031220 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 28 Feb 2022 04:47:16 +0000 Subject: [PATCH 097/107] chore(deps): bump color-eyre from 0.6.0 to 0.6.1 Bumps [color-eyre](https://github.com/yaahc/color-eyre) from 0.6.0 to 0.6.1. - [Release notes](https://github.com/yaahc/color-eyre/releases) - [Changelog](https://github.com/yaahc/color-eyre/blob/master/CHANGELOG.md) - [Commits](https://github.com/yaahc/color-eyre/compare/v0.6.0...v0.6.1) --- updated-dependencies: - dependency-name: color-eyre dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- libp2p-networking/Cargo.lock | 4 ++-- libp2p-networking/Cargo.toml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/libp2p-networking/Cargo.lock b/libp2p-networking/Cargo.lock index 054323c3f5..523b2e2ef8 100644 --- a/libp2p-networking/Cargo.lock +++ b/libp2p-networking/Cargo.lock @@ -527,9 +527,9 @@ dependencies = [ [[package]] name = "color-eyre" -version = "0.6.0" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d6ec7641ff3474b7593009c809db602c414cd97c7d47a78ed004162b74ff96c" +checksum = "8ebf286c900a6d5867aeff75cfee3192857bb7f24b547d4f0df2ed6baa812c90" dependencies = [ "backtrace", "color-spantrace", diff --git a/libp2p-networking/Cargo.toml b/libp2p-networking/Cargo.toml index 17ea2bb4b3..c511df5e8d 100644 --- a/libp2p-networking/Cargo.toml +++ b/libp2p-networking/Cargo.toml @@ -9,7 +9,7 @@ edition = "2021" async-std = { version = "1.10.0", features = ["attributes", "unstable"] } bincode = "1.3.3" blake3 = "1.3.1" -color-eyre = "0.6.0" +color-eyre = "0.6.1" crossterm = { version = "0.23.0", features = ["event-stream"] } flume = "0.10.11" futures = "0.3.21" From cd240ff6f0b4e4495dab0d9e3b73f530cd108933 Mon Sep 17 00:00:00 2001 From: Justin Restivo Date: Mon, 28 Feb 2022 09:53:53 -0500 Subject: [PATCH 098/107] docs: update readme --- libp2p-networking/README | 44 +++++++++++++++++++++++++++------------- 1 file changed, 30 insertions(+), 14 deletions(-) diff --git a/libp2p-networking/README b/libp2p-networking/README index ce968fc9bb..154288da21 100644 --- a/libp2p-networking/README +++ b/libp2p-networking/README @@ -10,18 +10,18 @@ To get very verbose logging: RUST_LOG_OUTPUT=OUTFILE RUST_LOG="trace" cargo run --release ``` -The idea here is to spin up several such nodes. Something akin to (in separate terminals) +The idea here is to spin up several nodes in a p2p network. These nodes can share messages with each other. ``` -nix develop -c "RUST_LOG_OUTPUT=OUTFILE_0 RUST_LOG=error cargo run --release -- -p 1111" -nix develop -c "RUST_LOG_OUTPUT=OUTFILE_0 RUST_LOG=error cargo run --release -- /ip4/127.0.0.1/tcp/1111 -p 2222" -nix develop -c "RUST_LOG_OUTPUT=OUTFILE_0 RUST_LOG=error cargo run --release -- /ip4/127.0.0.1/tcp/2222 -p 3333" -nix develop -c "RUST_LOG_OUTPUT=OUTFILE_0 RUST_LOG=error cargo run --release -- /ip4/127.0.0.1/tcp/3333 -p 4444" -nix develop -c "RUST_LOG_OUTPUT=OUTFILE_0 RUST_LOG=error cargo run --release -- /ip4/127.0.0.1/tcp/4444 -p 5555" -nix develop -c "RUST_LOG_OUTPUT=OUTFILE_0 RUST_LOG=error cargo run --release -- /ip4/127.0.0.1/tcp/5555 -p 6666" -nix develop -c "RUST_LOG_OUTPUT=OUTFILE_0 RUST_LOG=error cargo run --release -- /ip4/127.0.0.1/tcp/6666 -p 7777" -nix develop -c "RUST_LOG_OUTPUT=OUTFILE_0 RUST_LOG=error cargo run --release -- /ip4/127.0.0.1/tcp/7777 -p 8888" -nix develop -c "RUST_LOG_OUTPUT=OUTFILE_0 RUST_LOG=error cargo run --release -- /ip4/127.0.0.1/tcp/8888 -p 9999" +nix develop -c "RUST_LOG_OUTPUT=OUTFILE_0 RUST_LOG=error cargo run --release --example clichat -- -p 1111" +nix develop -c "RUST_LOG_OUTPUT=OUTFILE_0 RUST_LOG=error cargo run --release --example -- /ip4/127.0.0.1/tcp/1111 -p 2222" +nix develop -c "RUST_LOG_OUTPUT=OUTFILE_0 RUST_LOG=error cargo run --release --example -- /ip4/127.0.0.1/tcp/2222 -p 3333" +nix develop -c "RUST_LOG_OUTPUT=OUTFILE_0 RUST_LOG=error cargo run --release --example -- /ip4/127.0.0.1/tcp/3333 -p 4444" +nix develop -c "RUST_LOG_OUTPUT=OUTFILE_0 RUST_LOG=error cargo run --release --example -- /ip4/127.0.0.1/tcp/4444 -p 5555" +nix develop -c "RUST_LOG_OUTPUT=OUTFILE_0 RUST_LOG=error cargo run --release --example -- /ip4/127.0.0.1/tcp/5555 -p 6666" +nix develop -c "RUST_LOG_OUTPUT=OUTFILE_0 RUST_LOG=error cargo run --release --example -- /ip4/127.0.0.1/tcp/6666 -p 7777" +nix develop -c "RUST_LOG_OUTPUT=OUTFILE_0 RUST_LOG=error cargo run --release --example -- /ip4/127.0.0.1/tcp/7777 -p 8888" +nix develop -c "RUST_LOG_OUTPUT=OUTFILE_0 RUST_LOG=error cargo run --release --example -- /ip4/127.0.0.1/tcp/8888 -p 9999" ``` At this point the idea is that each node will continue to attempt to connect to nodes @@ -31,14 +31,30 @@ Use `Tab` to switch between messages and prompt. Press `Enter` to broadcast a me Press `Right Arrow` to direct-send a message to a randomly selected peer. Press `q` to quit the program from the messages view. -## Counter Tests +## Counter Single Machine Tests -`cargo test --release` +Each node has its own counter. The idea behind these tests is to support "broadcast" messages and "direct" messages to increment each nodes counter. -spawns off two tests. One that uses gossipsub to broadcast a counter increment, and another that increments a counter directly. +`cargo test --release stress` -This often times fails on MacOS due to "too many open files." The fix here is: +spawns off five integration tests. + +- Two that uses gossipsub to broadcast a counter increment from one node to all other nodes +- Two where one node increments its counter, then direct messages all nodes to increment their counters +- One that intersperses both broadcast and increments. + +This often times fails on MacOS due to ["too many open files."](https://github.com/EspressoSystems/phaselock-networking-demo/issues/18) The fix here is: ```bash ulimit -n 10240 ``` + +## Counter Multi-machine tests + +In these tests, there are three types of nodes. `Regular` nodes that limit the number of incoming connections, `Bootstrap` nodes that allow all connections, and `Conductor` nodes that all nodes (bootstrap and regular) connect to and periodically ping with their state. This "conductor" node instructs nodes in the swarm to increment their state either via broadcast or direct messages in the same fashion as the single machine tests. + +In the direct message case, the conductor will increment the state of a randomly chosen node, `i`. Then the conductor will direct message all other nodes to request node `i`'s counter and increment their counter to the value in `i`'s node. In the broadcast case, the conductor will increment the state of a randomly chose node, `i`, and tell `i` to broadcast this incremented state. + +In both cases, the test terminates as successful when the conductor receives the incremented state from all other nodes. Then, the conductor sends a special "kill" message to all known nodes and waits for them to disconnect. + +Metadata about the toplogy is currently read from an `identity_mapping.json` file that manually labels the type of node (bootstrap, regular, conductor). The conductor uses this to figure out information about all nodes in the network. The regular nodes use this to learn about their ip address and the addresses necessary to bootstrap onto the network. The boostrap nodes only use this to learn about their ip addresses. From f3cb55ece8b48b1bd8e281d46b87e7a376d70c72 Mon Sep 17 00:00:00 2001 From: Victor Koenders Date: Tue, 1 Mar 2022 11:38:52 +0100 Subject: [PATCH 099/107] Marked several NetworkNodeConfig fields optional for the builder --- libp2p-networking/.gitignore | 1 + libp2p-networking/README | 16 ++++++++-------- libp2p-networking/src/network_node.rs | 4 ++++ 3 files changed, 13 insertions(+), 8 deletions(-) diff --git a/libp2p-networking/.gitignore b/libp2p-networking/.gitignore index d787b7061e..b31bea143c 100644 --- a/libp2p-networking/.gitignore +++ b/libp2p-networking/.gitignore @@ -1,2 +1,3 @@ /target /result +/outfile_0 diff --git a/libp2p-networking/README b/libp2p-networking/README index 154288da21..f127b4639f 100644 --- a/libp2p-networking/README +++ b/libp2p-networking/README @@ -14,14 +14,14 @@ The idea here is to spin up several nodes in a p2p network. These nodes can shar ``` nix develop -c "RUST_LOG_OUTPUT=OUTFILE_0 RUST_LOG=error cargo run --release --example clichat -- -p 1111" -nix develop -c "RUST_LOG_OUTPUT=OUTFILE_0 RUST_LOG=error cargo run --release --example -- /ip4/127.0.0.1/tcp/1111 -p 2222" -nix develop -c "RUST_LOG_OUTPUT=OUTFILE_0 RUST_LOG=error cargo run --release --example -- /ip4/127.0.0.1/tcp/2222 -p 3333" -nix develop -c "RUST_LOG_OUTPUT=OUTFILE_0 RUST_LOG=error cargo run --release --example -- /ip4/127.0.0.1/tcp/3333 -p 4444" -nix develop -c "RUST_LOG_OUTPUT=OUTFILE_0 RUST_LOG=error cargo run --release --example -- /ip4/127.0.0.1/tcp/4444 -p 5555" -nix develop -c "RUST_LOG_OUTPUT=OUTFILE_0 RUST_LOG=error cargo run --release --example -- /ip4/127.0.0.1/tcp/5555 -p 6666" -nix develop -c "RUST_LOG_OUTPUT=OUTFILE_0 RUST_LOG=error cargo run --release --example -- /ip4/127.0.0.1/tcp/6666 -p 7777" -nix develop -c "RUST_LOG_OUTPUT=OUTFILE_0 RUST_LOG=error cargo run --release --example -- /ip4/127.0.0.1/tcp/7777 -p 8888" -nix develop -c "RUST_LOG_OUTPUT=OUTFILE_0 RUST_LOG=error cargo run --release --example -- /ip4/127.0.0.1/tcp/8888 -p 9999" +nix develop -c "RUST_LOG_OUTPUT=OUTFILE_0 RUST_LOG=error cargo run --release --example clichat -- /ip4/127.0.0.1/tcp/1111 -p 2222" +nix develop -c "RUST_LOG_OUTPUT=OUTFILE_0 RUST_LOG=error cargo run --release --example clichat -- /ip4/127.0.0.1/tcp/2222 -p 3333" +nix develop -c "RUST_LOG_OUTPUT=OUTFILE_0 RUST_LOG=error cargo run --release --example clichat -- /ip4/127.0.0.1/tcp/3333 -p 4444" +nix develop -c "RUST_LOG_OUTPUT=OUTFILE_0 RUST_LOG=error cargo run --release --example clichat -- /ip4/127.0.0.1/tcp/4444 -p 5555" +nix develop -c "RUST_LOG_OUTPUT=OUTFILE_0 RUST_LOG=error cargo run --release --example clichat -- /ip4/127.0.0.1/tcp/5555 -p 6666" +nix develop -c "RUST_LOG_OUTPUT=OUTFILE_0 RUST_LOG=error cargo run --release --example clichat -- /ip4/127.0.0.1/tcp/6666 -p 7777" +nix develop -c "RUST_LOG_OUTPUT=OUTFILE_0 RUST_LOG=error cargo run --release --example clichat -- /ip4/127.0.0.1/tcp/7777 -p 8888" +nix develop -c "RUST_LOG_OUTPUT=OUTFILE_0 RUST_LOG=error cargo run --release --example clichat -- /ip4/127.0.0.1/tcp/8888 -p 9999" ``` At this point the idea is that each node will continue to attempt to connect to nodes diff --git a/libp2p-networking/src/network_node.rs b/libp2p-networking/src/network_node.rs index 9a8a32a043..c46d846f88 100644 --- a/libp2p-networking/src/network_node.rs +++ b/libp2p-networking/src/network_node.rs @@ -334,12 +334,16 @@ pub struct NetworkNodeConfig { /// The type of node: /// Either bootstrap (greedily connect to all peers) /// or regular (respect `min_num_peers`/`max num peers`) + #[builder(default)] pub node_type: NetworkNodeType, /// optional identity + #[builder(setter(into, strip_option), default)] pub identity: Option, /// nodes to ignore + #[builder(default)] pub ignored_peers: HashSet, /// address to bind to + #[builder(setter(into, strip_option), default)] pub bound_addr: Option, } From 04aeea1469d49956d36a08fb3100605d3005de95 Mon Sep 17 00:00:00 2001 From: Victor Koenders Date: Tue, 1 Mar 2022 11:51:31 +0100 Subject: [PATCH 100/107] Fixed some issues in other tests because of the changed NetworkNodeConfigBuilder --- libp2p-networking/examples/common/mod.rs | 16 ++-- libp2p-networking/tests/common/mod.rs | 3 - libp2p-networking/tests/counter.rs | 94 +++++++++++++----------- 3 files changed, 62 insertions(+), 51 deletions(-) diff --git a/libp2p-networking/examples/common/mod.rs b/libp2p-networking/examples/common/mod.rs index d5c4aa693d..eb1b6ba338 100644 --- a/libp2p-networking/examples/common/mod.rs +++ b/libp2p-networking/examples/common/mod.rs @@ -220,19 +220,21 @@ pub async fn start_main(ip_addr: String, path: Option) -> Result<(), Cou }) .collect::>(); - let (idx, node_description) = swarm_config.iter().enumerate().find(|(_, node)| { - node.multiaddr.clone().to_string().contains(&ip_addr) - }).unwrap(); + let (idx, node_description) = swarm_config + .iter() + .enumerate() + .find(|(_, node)| node.multiaddr.clone().to_string().contains(&ip_addr)) + .unwrap(); println!("found entry!: {idx}"); match node_description.node_type { NetworkNodeType::Conductor => { let config = NetworkNodeConfigBuilder::default() - .bound_addr(Some(node_description.bound_addr.clone())) + .bound_addr(node_description.bound_addr.clone()) .min_num_peers(swarm_config.len() - 1) .max_num_peers(swarm_config.len() - 1) .node_type(NetworkNodeType::Conductor) - .identity(Some(node_description.identity.clone())) + .identity(node_description.identity.clone()) .ignored_peers(ignored_peers) .build() .context(NodeConfigSnafu) @@ -311,8 +313,8 @@ pub async fn start_main(ip_addr: String, path: Option) -> Result<(), Cou }) .collect::>(); let config = NetworkNodeConfigBuilder::default() - .bound_addr(Some(node_description.bound_addr.clone())) - .identity(Some(node_description.identity.clone())) + .bound_addr(node_description.bound_addr.clone()) + .identity(node_description.identity.clone()) .ignored_peers(ignored_peers) .min_num_peers(swarm_config.len() / 4) .max_num_peers(swarm_config.len() / 2) diff --git a/libp2p-networking/tests/common/mod.rs b/libp2p-networking/tests/common/mod.rs index ba49addd0b..1c92aa2ffc 100644 --- a/libp2p-networking/tests/common/mod.rs +++ b/libp2p-networking/tests/common/mod.rs @@ -172,9 +172,6 @@ pub async fn spin_up_swarms( } let regular_node_config = NetworkNodeConfigBuilder::default() - .identity(None) - .ignored_peers(HashSet::new()) - .bound_addr(None) .node_type(NetworkNodeType::Regular) .min_num_peers(min_num_peers) .max_num_peers(max_num_peers) diff --git a/libp2p-networking/tests/counter.rs b/libp2p-networking/tests/counter.rs index 4f3af4c51c..71d318cb97 100644 --- a/libp2p-networking/tests/counter.rs +++ b/libp2p-networking/tests/counter.rs @@ -123,7 +123,7 @@ pub async fn counter_handle_network_event( async fn run_request_response_increment( requester_handle: Arc>, requestee_handle: Arc>, - timeout: Duration + timeout: Duration, ) -> Result<(), TestError> { let bincode_options = bincode::DefaultOptions::new().with_limit(16_384); let msg_inner = bincode_options @@ -176,7 +176,7 @@ async fn run_gossip_round( handles: &[Arc>], msg_inner: Vec, new_state: CounterState, - timeout_duration: Duration + timeout_duration: Duration, ) -> Result<(), TestError> { let msg_handle = get_random_handle(handles); *msg_handle.state.lock().await = new_state; @@ -216,7 +216,10 @@ async fn run_gossip_round( Ok(()) } -async fn run_intersperse_many_rounds(handles: Vec>>, timeout: Duration) { +async fn run_intersperse_many_rounds( + handles: Vec>>, + timeout: Duration, +) { for i in 0..NUM_ROUNDS as u32 { if i % 2 == 0 { run_request_response_increment_all(&handles, timeout).await; @@ -232,8 +235,8 @@ async fn run_intersperse_many_rounds(handles: Vec>>, - timeout: Duration - ) { + timeout: Duration, +) { for _i in 0..NUM_ROUNDS { run_request_response_increment_all(&handles, timeout).await; } @@ -244,19 +247,25 @@ async fn run_request_response_many_rounds( pub async fn run_request_response_one_round( handles: Vec>>, - timeout: Duration - ) { + timeout: Duration, +) { run_request_response_increment_all(&handles, timeout).await; for h in handles.into_iter() { assert_eq!(*h.state.lock().await, 1); } } -pub async fn run_gossip_many_rounds(handles: Vec>>, timeout: Duration) { +pub async fn run_gossip_many_rounds( + handles: Vec>>, + timeout: Duration, +) { run_gossip_rounds(&handles, NUM_ROUNDS, 0, timeout).await } -async fn run_gossip_one_round(handles: Vec>>, timeout: Duration) { +async fn run_gossip_one_round( + handles: Vec>>, + timeout: Duration, +) { run_gossip_rounds(&handles, 1, 0, timeout).await } @@ -265,8 +274,8 @@ async fn run_gossip_rounds( handles: &[Arc>], num_rounds: usize, starting_state: CounterState, - timeout: Duration - ) { + timeout: Duration, +) { let mut old_state = starting_state; let bincode_options = bincode::DefaultOptions::new().with_limit(16_384); for i in 0..num_rounds { @@ -277,7 +286,7 @@ async fn run_gossip_rounds( from: old_state, to: new_state, }) - .unwrap(); + .unwrap(); run_gossip_round(handles, msg_inner, new_state, timeout) .await .unwrap(); @@ -289,7 +298,10 @@ async fn run_gossip_rounds( /// increments its state by 1, /// then has all other peers request its state /// and update their state to the recv'ed state -async fn run_request_response_increment_all(handles: &[Arc>], timeout: Duration) { +async fn run_request_response_increment_all( + handles: &[Arc>], + timeout: Duration, +) { let requestee_handle = get_random_handle(handles); *requestee_handle.state.lock().await += 1; requestee_handle @@ -303,10 +315,10 @@ async fn run_request_response_increment_all(handles: &[Arc>() - ); + .into_iter() + .filter(|r| r.is_err()) + .collect::>() + ); } requestee_handle @@ -338,8 +350,8 @@ async fn test_coverage_request_response_one_round() { TOTAL_NUM_PEERS_COVERAGE, NUM_OF_BOOTSTRAP_COVERAGE, TIMEOUT_COVERAGE, - ) - .await + ) + .await } /// stress test of direct messsage @@ -352,8 +364,8 @@ async fn test_coverage_request_response_many_rounds() { TOTAL_NUM_PEERS_COVERAGE, NUM_OF_BOOTSTRAP_COVERAGE, TIMEOUT_COVERAGE, - ) - .await + ) + .await } /// stress test of broadcast + direct message @@ -366,8 +378,8 @@ async fn test_coverage_intersperse_many_rounds() { TOTAL_NUM_PEERS_COVERAGE, NUM_OF_BOOTSTRAP_COVERAGE, TIMEOUT_COVERAGE, - ) - .await + ) + .await } /// stress teset that we can broadcast a message out and get counter increments @@ -380,8 +392,8 @@ async fn test_coverage_gossip_many_rounds() { TOTAL_NUM_PEERS_COVERAGE, NUM_OF_BOOTSTRAP_COVERAGE, TIMEOUT_COVERAGE, - ) - .await; + ) + .await; } /// simple case of broadcast message @@ -394,8 +406,8 @@ async fn test_coverage_gossip_one_round() { TOTAL_NUM_PEERS_COVERAGE, NUM_OF_BOOTSTRAP_COVERAGE, TIMEOUT_COVERAGE, - ) - .await; + ) + .await; } /// simple case of direct message @@ -408,8 +420,8 @@ async fn test_stress_request_response_one_round() { TOTAL_NUM_PEERS_STRESS, NUM_OF_BOOTSTRAP_STRESS, TIMEOUT_STRESS, - ) - .await + ) + .await } /// stress test of direct messsage @@ -422,8 +434,8 @@ async fn test_stress_request_response_many_rounds() { TOTAL_NUM_PEERS_STRESS, NUM_OF_BOOTSTRAP_STRESS, TIMEOUT_STRESS, - ) - .await + ) + .await } /// stress test of broadcast + direct message @@ -436,8 +448,8 @@ async fn test_stress_intersperse_many_rounds() { TOTAL_NUM_PEERS_STRESS, NUM_OF_BOOTSTRAP_STRESS, TIMEOUT_STRESS, - ) - .await + ) + .await } /// stress teset that we can broadcast a message out and get counter increments @@ -450,8 +462,8 @@ async fn test_stress_gossip_many_rounds() { TOTAL_NUM_PEERS_STRESS, NUM_OF_BOOTSTRAP_STRESS, TIMEOUT_STRESS, - ) - .await; + ) + .await; } /// simple case of broadcast message @@ -464,6 +476,6 @@ async fn test_stress_gossip_one_round() { TOTAL_NUM_PEERS_STRESS, NUM_OF_BOOTSTRAP_STRESS, TIMEOUT_STRESS, - ) - .await; + ) + .await; } From 67abcd3b59b3fd60c5dd8e40f816901bebc7aecf Mon Sep 17 00:00:00 2001 From: Victor Koenders Date: Tue, 1 Mar 2022 12:06:57 +0100 Subject: [PATCH 101/107] Made flake.nix set CARGO_BUILD_TARGET to musl --- libp2p-networking/flake.nix | 1 + 1 file changed, 1 insertion(+) diff --git a/libp2p-networking/flake.nix b/libp2p-networking/flake.nix index 782431cc8b..c69a8c434e 100644 --- a/libp2p-networking/flake.nix +++ b/libp2p-networking/flake.nix @@ -125,6 +125,7 @@ shellHook = '' ulimit -n 1024 export RUSTFLAGS='-C target-feature=+crt-static' + export CARGO_BUILD_TARGET='x86_64-unknown-linux-musl' ''; buildInputs = with pkgs; [ fenix.packages.${system}.rust-analyzer fenixStable ] ++ buildDeps; From a7a4e106f9b8d651ee7599d9b3f431612ffd40b7 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 2 Mar 2022 04:44:36 +0000 Subject: [PATCH 102/107] chore(deps): bump actions/checkout from 2 to 3 Bumps [actions/checkout](https://github.com/actions/checkout) from 2 to 3. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/v2...v3) --- updated-dependencies: - dependency-name: actions/checkout dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- libp2p-networking/.github/workflows/build.yml | 2 +- libp2p-networking/.github/workflows/coverage.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/libp2p-networking/.github/workflows/build.yml b/libp2p-networking/.github/workflows/build.yml index e5ae668eb8..8b8c2be799 100644 --- a/libp2p-networking/.github/workflows/build.yml +++ b/libp2p-networking/.github/workflows/build.yml @@ -22,7 +22,7 @@ jobs: access_token: ${{ github.token }} - name: Checkout Repository - uses: actions/checkout@v2 + uses: actions/checkout@v3 - name: Install stable toolchain uses: actions-rs/toolchain@v1 diff --git a/libp2p-networking/.github/workflows/coverage.yml b/libp2p-networking/.github/workflows/coverage.yml index b182e128c6..71b2d478bd 100644 --- a/libp2p-networking/.github/workflows/coverage.yml +++ b/libp2p-networking/.github/workflows/coverage.yml @@ -16,7 +16,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout Repository - uses: actions/checkout@v2 + uses: actions/checkout@v3 - name: Install Rust Nightly Toolchain uses: actions-rs/toolchain@v1 From a56ce5a946e623200bbbd5a4e53da8b98bb7882b Mon Sep 17 00:00:00 2001 From: Victor Koenders Date: Thu, 3 Mar 2022 10:00:26 +0100 Subject: [PATCH 103/107] Made the tests more stable on my machine --- libp2p-networking/src/tracing_setup.rs | 1 + libp2p-networking/test.sh | 3 +++ libp2p-networking/tests/common/mod.rs | 4 ++-- 3 files changed, 6 insertions(+), 2 deletions(-) create mode 100755 libp2p-networking/test.sh diff --git a/libp2p-networking/src/tracing_setup.rs b/libp2p-networking/src/tracing_setup.rs index ced710372e..9b58a0fd8e 100644 --- a/libp2p-networking/src/tracing_setup.rs +++ b/libp2p-networking/src/tracing_setup.rs @@ -53,6 +53,7 @@ fn internal_setup_tracing(writer: BoxMakeWriter) { let internal_event_filter = parse_span_events(); let fmt_env = var("RUST_LOG_FORMAT").map(|x| x.to_lowercase()); match fmt_env.as_deref().map(|x| x.trim()) { + Ok("none") => {} Ok("full") => { let fmt_layer = fmt::Layer::default() .with_span_events(internal_event_filter) diff --git a/libp2p-networking/test.sh b/libp2p-networking/test.sh new file mode 100755 index 0000000000..93b5dd736d --- /dev/null +++ b/libp2p-networking/test.sh @@ -0,0 +1,3 @@ +#!/usr/bin/env bash +set -ex +RUST_LOG_FORMAT=none cargo test --release -- --test-threads=2 diff --git a/libp2p-networking/tests/common/mod.rs b/libp2p-networking/tests/common/mod.rs index 1c92aa2ffc..c5a446bada 100644 --- a/libp2p-networking/tests/common/mod.rs +++ b/libp2p-networking/tests/common/mod.rs @@ -18,7 +18,7 @@ use networking_demo::{ }; use snafu::{ResultExt, Snafu}; use std::fmt::Debug; -use tracing::{error, instrument, warn}; +use tracing::{info, instrument, warn}; static INIT: Once = Once::new(); @@ -201,7 +201,7 @@ pub async fn spin_up_swarms( handles.push(node); } - error!( + info!( "known nodes: {:?}", bootstrap_addrs .iter() From 09fe625f659d122ada374a5c1ccb6651b472a88c Mon Sep 17 00:00:00 2001 From: Trangar Date: Fri, 4 Mar 2022 15:22:26 +0100 Subject: [PATCH 104/107] Web UI (#46) * Proof of concept for the web UI * Moved the state that is being send to the webui into its own module. Switched from using `Condvar` to `Sender`/`Receiver` * Changes in node handle now properly notify the webui * Almost forgot to remove the temporary default feature * Added chrono and time CVE to the ignored audit list * Fixed some warnings when not using the webui feature --- libp2p-networking/.cargo/audit.toml | 5 + libp2p-networking/Cargo.lock | 938 +++++++++++++++---- libp2p-networking/Cargo.toml | 8 + libp2p-networking/examples/common/mod.rs | 88 +- libp2p-networking/examples/common/web.rs | 143 +++ libp2p-networking/examples/counter.rs | 17 +- libp2p-networking/src/network_node_handle.rs | 34 +- libp2p-networking/tests/counter.rs | 6 + libp2p-networking/web/index.html | 105 +++ 9 files changed, 1143 insertions(+), 201 deletions(-) create mode 100644 libp2p-networking/.cargo/audit.toml create mode 100644 libp2p-networking/examples/common/web.rs create mode 100644 libp2p-networking/web/index.html diff --git a/libp2p-networking/.cargo/audit.toml b/libp2p-networking/.cargo/audit.toml new file mode 100644 index 0000000000..8e436737d9 --- /dev/null +++ b/libp2p-networking/.cargo/audit.toml @@ -0,0 +1,5 @@ +[advisories] +ignore = [ + "RUSTSEC-2020-0159", # https://github.com/chronotope/chrono/issues/499 + "RUSTSEC-2020-0071" # time, dependent on chrono +] diff --git a/libp2p-networking/Cargo.lock b/libp2p-networking/Cargo.lock index 523b2e2ef8..0cc0273367 100644 --- a/libp2p-networking/Cargo.lock +++ b/libp2p-networking/Cargo.lock @@ -17,6 +17,15 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" +[[package]] +name = "aead" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7fc95d1bdb8e6666b2b217308eeeb09f2d6728d104be3e31916cc74d15420331" +dependencies = [ + "generic-array", +] + [[package]] name = "aead" version = "0.4.3" @@ -26,39 +35,84 @@ dependencies = [ "generic-array", ] +[[package]] +name = "aes" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "884391ef1066acaa41e766ba8f596341b96e93ce34f9a43e7d24bf0a0eaf0561" +dependencies = [ + "aes-soft", + "aesni", + "cipher 0.2.5", +] + [[package]] name = "aes" version = "0.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9e8b47f52ea9bae42228d07ec09eb676433d7c4ed1ebdf0f1d1c29ed446f1ab8" dependencies = [ - "cfg-if", - "cipher", + "cfg-if 1.0.0", + "cipher 0.3.0", "cpufeatures", "opaque-debug", ] +[[package]] +name = "aes-gcm" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5278b5fabbb9bd46e24aa69b2fdea62c99088e0a950a9be40e3e0101298f88da" +dependencies = [ + "aead 0.3.2", + "aes 0.6.0", + "cipher 0.2.5", + "ctr 0.6.0", + "ghash 0.3.1", + "subtle", +] + [[package]] name = "aes-gcm" version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "df5f85a83a7d8b0442b6aa7b504b8212c1733da07b98aae43d4bc21b2cb3cdf6" dependencies = [ - "aead", - "aes", - "cipher", - "ctr", - "ghash", + "aead 0.4.3", + "aes 0.7.5", + "cipher 0.3.0", + "ctr 0.8.0", + "ghash 0.4.4", "subtle", ] +[[package]] +name = "aes-soft" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be14c7498ea50828a38d0e24a765ed2effe92a705885b57d029cd67d45744072" +dependencies = [ + "cipher 0.2.5", + "opaque-debug", +] + +[[package]] +name = "aesni" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea2e11f5e94c2f7d386164cc2aa1f97823fed6f259e486940a71c174dd01b0ce" +dependencies = [ + "cipher 0.2.5", + "opaque-debug", +] + [[package]] name = "ahash" version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fcb51a0695d8f838b1ee009b3fbf66bda078cd64590202a864a8f3e8c4315c47" dependencies = [ - "getrandom 0.2.3", + "getrandom 0.2.5", "once_cell", "version_check", ] @@ -83,9 +137,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.52" +version = "1.0.55" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "84450d0b4a8bd1ba4144ce8ce718fbc5d071358b1e5384bace6536b3d1f2d5b3" +checksum = "159bb86af3a200e19a068f4224eae4c8bb2d0fa054c7e5d1cacd5cef95e684cd" [[package]] name = "arrayref" @@ -132,6 +186,16 @@ dependencies = [ "futures-core", ] +[[package]] +name = "async-dup" +version = "1.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7427a12b8dc09291528cfb1da2447059adb4a257388c2acd6497a79d55cf6f7c" +dependencies = [ + "futures-io", + "simple-mutex", +] + [[package]] name = "async-executor" version = "1.4.1" @@ -148,9 +212,9 @@ dependencies = [ [[package]] name = "async-global-executor" -version = "2.0.2" +version = "2.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9586ec52317f36de58453159d48351bc244bc24ced3effc1fce22f3d48664af6" +checksum = "c026b7e44f1316b567ee750fea85103f87fcb80792b860e979f221259796ca0a" dependencies = [ "async-channel", "async-executor", @@ -162,6 +226,22 @@ dependencies = [ "once_cell", ] +[[package]] +name = "async-h1" +version = "2.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8101020758a4fc3a7c326cb42aa99e9fa77cbfb76987c128ad956406fe1f70a7" +dependencies = [ + "async-channel", + "async-dup", + "async-std", + "futures-core", + "http-types", + "httparse", + "log", + "pin-project 1.0.10", +] + [[package]] name = "async-io" version = "1.6.0" @@ -176,16 +256,16 @@ dependencies = [ "parking", "polling", "slab", - "socket2 0.4.2", + "socket2 0.4.4", "waker-fn", "winapi", ] [[package]] name = "async-lock" -version = "2.4.0" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6a8ea61bf9947a1007c5cada31e647dbc77b103c679858150003ba697ea798b" +checksum = "e97a171d191782fba31bb902b14ad94e24a68145032b7eedf871ab0bc0d077b6" dependencies = [ "event-listener", ] @@ -207,7 +287,7 @@ checksum = "83137067e3a2a6a06d67168e49e68a0957d215410473a740cea95a2425c0b7c6" dependencies = [ "async-io", "blocking", - "cfg-if", + "cfg-if 1.0.0", "event-listener", "futures-lite", "libc", @@ -216,6 +296,41 @@ dependencies = [ "winapi", ] +[[package]] +name = "async-session" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "345022a2eed092cd105cc1b26fd61c341e100bd5fcbbd792df4baf31c2cc631f" +dependencies = [ + "anyhow", + "async-std", + "async-trait", + "base64 0.12.3", + "bincode", + "blake3 0.3.8", + "chrono", + "hmac 0.8.1", + "kv-log-macro", + "rand 0.7.3", + "serde", + "serde_json", + "sha2 0.9.9", +] + +[[package]] +name = "async-sse" +version = "4.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53bba003996b8fd22245cd0c59b869ba764188ed435392cf2796d03b805ade10" +dependencies = [ + "async-channel", + "async-std", + "http-types", + "log", + "memchr", + "pin-project-lite 0.1.12", +] + [[package]] name = "async-std" version = "1.10.0" @@ -247,9 +362,9 @@ dependencies = [ [[package]] name = "async-std-resolver" -version = "0.20.3" +version = "0.20.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed4e2c3da14d8ad45acb1e3191db7a918e9505b6f155b218e70a7c9a1a48c638" +checksum = "dbf3e776afdf3a2477ef4854b85ba0dff3bd85792f685fb3c68948b4d304e4f0" dependencies = [ "async-std", "async-trait", @@ -261,9 +376,9 @@ dependencies = [ [[package]] name = "async-task" -version = "4.0.3" +version = "4.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e91831deabf0d6d7ec49552e489aed63b7456a7a3c46cff62adad428110b0af0" +checksum = "677d306121baf53310a3fd342d88dc0824f6bbeace68347593658525565abee8" [[package]] name = "async-trait" @@ -317,25 +432,37 @@ dependencies = [ [[package]] name = "autocfg" -version = "1.0.1" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a" +checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" [[package]] name = "backtrace" -version = "0.3.63" +version = "0.3.64" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "321629d8ba6513061f26707241fa9bc89524ff1cd7a915a97ef0c62c666ce1b6" +checksum = "5e121dee8023ce33ab248d9ce1493df03c3b38a659b240096fcbd7048ff9c31f" dependencies = [ "addr2line", "cc", - "cfg-if", + "cfg-if 1.0.0", "libc", "miniz_oxide", "object", "rustc-demangle", ] +[[package]] +name = "base-x" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4521f3e3d031370679b3b140beb36dfe4801b09ac77e30c61941f97df3ef28b" + +[[package]] +name = "base64" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3441f0f7b02788e948e47f457ca01f1d7e6d92c693bc132c22b087d3141c03ff" + [[package]] name = "base64" version = "0.13.0" @@ -344,9 +471,9 @@ checksum = "904dfeac50f3cdaba28fc6f57fdcddb75f49ed61346676a78c4ffe55877802fd" [[package]] name = "bimap" -version = "0.6.1" +version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50ae17cabbc8a38a1e3e4c1a6a664e9a09672dc14d0896fa8d865d3a5a446b07" +checksum = "bc0455254eb5c6964c4545d8bac815e1a1be4f3afe0ae695ea539c12d728d44b" [[package]] name = "bincode" @@ -372,6 +499,21 @@ dependencies = [ "digest 0.10.3", ] +[[package]] +name = "blake3" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b64485778c4f16a6a5a9d335e80d449ac6c70cdd6a06d2af18a6f6f775a125b3" +dependencies = [ + "arrayref", + "arrayvec 0.5.2", + "cc", + "cfg-if 0.1.10", + "constant_time_eq", + "crypto-mac 0.8.0", + "digest 0.9.0", +] + [[package]] name = "blake3" version = "1.3.1" @@ -381,7 +523,7 @@ dependencies = [ "arrayref", "arrayvec 0.7.2", "cc", - "cfg-if", + "cfg-if 1.0.0", "constant_time_eq", "digest 0.10.3", ] @@ -398,9 +540,9 @@ dependencies = [ [[package]] name = "block-buffer" -version = "0.10.0" +version = "0.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1d36a02058e76b040de25a4464ba1c80935655595b661505c8b39b664828b95" +checksum = "0bf7fe51849ea569fd452f37822f606a5cabb684dc918707a0193fd4664ff324" dependencies = [ "generic-array", ] @@ -466,9 +608,15 @@ checksum = "df8670b8c7b9dae1793364eafadf7239c40d669904660c5960d74cfd80b46a53" [[package]] name = "cc" -version = "1.0.72" +version = "1.0.73" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2fff2a6927b3bb87f9595d67196a70493f627687a71d87a0d692242c33f58c11" + +[[package]] +name = "cfg-if" +version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22a9137b95ea06864e018375b72adfb7db6e6f68cfc8df5a04d00288050485ee" +checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" [[package]] name = "cfg-if" @@ -482,8 +630,8 @@ version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "01b72a433d0cf2aef113ba70f62634c56fddb0f244e6377185c56a7cadbd8f91" dependencies = [ - "cfg-if", - "cipher", + "cfg-if 1.0.0", + "cipher 0.3.0", "cpufeatures", "zeroize", ] @@ -494,13 +642,36 @@ version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3b84ed6d1d5f7aa9bdde921a5090e0ca4d934d250ea3b402a5fab3a994e28a2a" dependencies = [ - "aead", + "aead 0.4.3", "chacha20", - "cipher", + "cipher 0.3.0", "poly1305", "zeroize", ] +[[package]] +name = "chrono" +version = "0.4.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "670ad68c9088c2a963aaa298cb369688cf3f9465ce5e2d4ca10e6e0098a1ce73" +dependencies = [ + "libc", + "num-integer", + "num-traits", + "serde", + "time 0.1.43", + "winapi", +] + +[[package]] +name = "cipher" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "12f8e7987cbd042a63249497f41aed09f8e65add917ea6566effbc56578d6801" +dependencies = [ + "generic-array", +] + [[package]] name = "cipher" version = "0.3.0" @@ -561,12 +732,35 @@ dependencies = [ "cache-padded", ] +[[package]] +name = "const_fn" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fbdcdcb6d86f71c5e97409ad45898af11cbc995b4ee8112d59095a28d376c935" + [[package]] name = "constant_time_eq" version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "245097e9a4535ee1e3e3931fcfcd55a796a44c643e8596ff6566d68f09b87bbc" +[[package]] +name = "cookie" +version = "0.14.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "03a5d7b21829bc7b4bf4754a978a241ae54ea55a40f92bb20216e54096f4b951" +dependencies = [ + "aes-gcm 0.8.0", + "base64 0.13.0", + "hkdf", + "hmac 0.10.1", + "percent-encoding", + "rand 0.8.5", + "sha2 0.9.9", + "time 0.2.27", + "version_check", +] + [[package]] name = "core-foundation" version = "0.9.3" @@ -601,22 +795,28 @@ dependencies = [ "libc", ] +[[package]] +name = "cpuid-bool" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dcb25d077389e53838a8158c8e99174c5a9d902dee4904320db714f3c653ffba" + [[package]] name = "crc32fast" -version = "1.3.0" +version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "738c290dfaea84fc1ca15ad9c168d083b05a714e1efddd8edaab678dc28d2836" +checksum = "b540bd8bc810d3885c6ea91e2018302f68baba2129ab3e88f32389ee9370880d" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", ] [[package]] name = "crossbeam-utils" -version = "0.8.6" +version = "0.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cfcae03edb34f947e64acdb1c33ec169824e20657e9ecb61cef6c8c74dcb8120" +checksum = "b5e5bed1f1c269533fa816a0a5492b3545209a205ca1a54842be180eb63a16a6" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", "lazy_static", ] @@ -688,6 +888,16 @@ dependencies = [ "subtle", ] +[[package]] +name = "crypto-mac" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bff07008ec701e8028e2ceb8f83f0e4274ee62bd2dbdc4fefff2e9a91824081a" +dependencies = [ + "generic-array", + "subtle", +] + [[package]] name = "ctor" version = "0.1.21" @@ -698,13 +908,22 @@ dependencies = [ "syn", ] +[[package]] +name = "ctr" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fb4a30d54f7443bf3d6191dcd486aca19e67cb3c49fa7a06a319966346707e7f" +dependencies = [ + "cipher 0.2.5", +] + [[package]] name = "ctr" version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "049bb91fb4aaf0e3c7efa6cd5ef877dbbbd15b39dad06d9948de4ec8a75761ea" dependencies = [ - "cipher", + "cipher 0.3.0", ] [[package]] @@ -720,9 +939,9 @@ dependencies = [ [[package]] name = "curve25519-dalek" -version = "3.2.0" +version = "3.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b9fdf9972b2bd6af2d913799d9ebc165ea4d2e65878e329d9c6b372c4491b61" +checksum = "90f9d052967f590a76e62eb387bd0bbb1b000182c3cefe5364db6b7211651bc0" dependencies = [ "byteorder", "digest 0.9.0", @@ -779,6 +998,16 @@ dependencies = [ "syn", ] +[[package]] +name = "dashmap" +version = "4.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e77a43b28d0668df09411cb0bc9a8c2adc40f9a048afe863e05fd43251e8e39c" +dependencies = [ + "cfg-if 1.0.0", + "num_cpus", +] + [[package]] name = "data-encoding" version = "2.3.2" @@ -831,11 +1060,17 @@ version = "0.10.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f2fb860ca6fafa5552fb6d0e816a69c8e49f0908bf524e30a90d97c85892d506" dependencies = [ - "block-buffer 0.10.0", + "block-buffer 0.10.2", "crypto-common", "subtle", ] +[[package]] +name = "discard" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "212d0f5754cb6769937f4501cc0e67f4f4483c8d2c3e1e922ee9edbe4ab4c7c0" + [[package]] name = "dns-parser" version = "0.8.0" @@ -860,9 +1095,9 @@ checksum = "5caaa75cbd2b960ff1e5392d2cfb1f44717fffe12fc1f32b7b5d1267f99732a6" [[package]] name = "ed25519" -version = "1.3.0" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74e1069e39f1454367eb2de793ed062fac4c35c2934b76a81d90dd9abcd28816" +checksum = "eed12bbf7b5312f8da1c2722bc06d8c6b12c2d86a7fb35a194c7f3e6fc2bbe39" dependencies = [ "signature", ] @@ -873,7 +1108,7 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c762bae6dcaf24c4c84667b8579785430908723d5c889f469d76a41d59cc7a9d" dependencies = [ - "curve25519-dalek 3.2.0", + "curve25519-dalek 3.2.1", "ed25519", "rand 0.7.3", "serde", @@ -889,11 +1124,11 @@ checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457" [[package]] name = "enum-as-inner" -version = "0.3.3" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c5f0096a91d210159eceb2ff5e1c4da18388a170e1e3ce948aac9c8fdbbf595" +checksum = "570d109b813e904becc80d8d5da38376818a143348413f7149f1340fe04754d4" dependencies = [ - "heck", + "heck 0.4.0", "proc-macro2", "quote", "syn", @@ -901,15 +1136,15 @@ dependencies = [ [[package]] name = "event-listener" -version = "2.5.1" +version = "2.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7531096570974c3a9dcf9e4b8e1cede1ec26cf5046219fb3b9d897503b9be59" +checksum = "77f3309417938f28bf8228fcff79a4a37103981e3e186d2ccd19c74b38f4eb71" [[package]] name = "eyre" -version = "0.6.5" +version = "0.6.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "221239d1d5ea86bf5d6f91c9d6bc3646ffe471b08ff9b0f91c44f115ac969d2b" +checksum = "9289ed2c0440a6536e65119725cf91fc2c6b5e513bfd2e36e1134d7cca6ca12f" dependencies = [ "indenter", "once_cell", @@ -917,13 +1152,29 @@ dependencies = [ [[package]] name = "fastrand" -version = "1.6.0" +version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "779d043b6a0b90cc4c0ed7ee380a6504394cee7efd7db050e3774eee387324b2" +checksum = "c3fcf0cee53519c866c09b5de1f6c56ff9d647101f81c1964fa632e148896cdf" dependencies = [ "instant", ] +[[package]] +name = "femme" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2af1a24f391a5a94d756db5092c6576aad494b88a71a5a36b20c67b63e0df034" +dependencies = [ + "cfg-if 0.1.10", + "js-sys", + "log", + "serde", + "serde_derive", + "serde_json", + "wasm-bindgen", + "web-sys", +] + [[package]] name = "fixedbitset" version = "0.4.1" @@ -936,7 +1187,7 @@ version = "1.0.22" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e6988e897c1c9c485f43b47a529cef42fde0547f9d8d41a7062518f1d8fc53f" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", "crc32fast", "libc", "libz-sys", @@ -1110,24 +1361,34 @@ version = "0.1.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8fc3cb4d91f53b50155bdcfd23f6a4c39ae1969c2ae85982b135750cccaf5fce" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", "libc", "wasi 0.9.0+wasi-snapshot-preview1", ] [[package]] name = "getrandom" -version = "0.2.3" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fcd999463524c52659517fe2cea98493cfe485d10565e7b0fb07dbba7ad2753" +checksum = "d39cd93900197114fa1fcb7ae84ca742095eed9442088988ae74fa744e930e77" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", "js-sys", "libc", "wasi 0.10.2+wasi-snapshot-preview1", "wasm-bindgen", ] +[[package]] +name = "ghash" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97304e4cd182c3846f7575ced3890c53012ce534ad9114046b0a9e00bb30a375" +dependencies = [ + "opaque-debug", + "polyval 0.4.5", +] + [[package]] name = "ghash" version = "0.4.4" @@ -1135,7 +1396,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1583cc1656d7839fd3732b80cf4f38850336cdb9b8ded1cd399ca62958de3c99" dependencies = [ "opaque-debug", - "polyval", + "polyval 0.5.3", ] [[package]] @@ -1146,15 +1407,14 @@ checksum = "78cc372d058dcf6d5ecd98510e7fbc9e5aec4d21de70f65fea8fecebcd881bd4" [[package]] name = "gloo-timers" -version = "0.2.2" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f16c88aa13d2656ef20d1c042086b8767bbe2bdb62526894275a1b062161b2e" +checksum = "4d12a7f4e95cfe710f1d624fb1210b7d961a5fb05c4fd942f4feab06e61f590e" dependencies = [ "futures-channel", "futures-core", "js-sys", "wasm-bindgen", - "web-sys", ] [[package]] @@ -1175,6 +1435,12 @@ dependencies = [ "unicode-segmentation", ] +[[package]] +name = "heck" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2540771e65fc8cb83cd6e8a237f70c319bd5c29f78ed1084ba5d50eeac86f7f9" + [[package]] name = "hermit-abi" version = "0.1.19" @@ -1196,13 +1462,33 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b07f60793ff0a4d9cef0f18e63b5357e06209987153a64648c972c1e5aff336f" +[[package]] +name = "hkdf" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51ab2f639c231793c5f6114bdb9bbe50a7dbbfcd7c7c6bd8475dec2d991e964f" +dependencies = [ + "digest 0.9.0", + "hmac 0.10.1", +] + [[package]] name = "hmac" version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "126888268dcc288495a26bf004b38c5fdbb31682f992c84ceb046a1f0fe38840" dependencies = [ - "crypto-mac", + "crypto-mac 0.8.0", + "digest 0.9.0", +] + +[[package]] +name = "hmac" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1441c6b1e930e2817404b5046f1f989899143a12bf92de603b69f4e0aee1e15" +dependencies = [ + "crypto-mac 0.10.1", "digest 0.9.0", ] @@ -1214,7 +1500,7 @@ checksum = "17ea0a1394df5b6574da6e0c1ade9e78868c9fb0a4e5ef4428e32da4676b85b1" dependencies = [ "digest 0.9.0", "generic-array", - "hmac", + "hmac 0.8.1", ] [[package]] @@ -1228,11 +1514,46 @@ dependencies = [ "winapi", ] +[[package]] +name = "http-client" +version = "6.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea880b03c18a7e981d7fb3608b8904a98425d53c440758fcebf7d934aa56547c" +dependencies = [ + "async-trait", + "cfg-if 1.0.0", + "dashmap", + "http-types", + "log", +] + +[[package]] +name = "http-types" +version = "2.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e9b187a72d63adbfba487f48095306ac823049cb504ee195541e91c7775f5ad" +dependencies = [ + "anyhow", + "async-channel", + "async-std", + "base64 0.13.0", + "cookie", + "futures-lite", + "infer", + "pin-project-lite 0.2.8", + "rand 0.7.3", + "serde", + "serde_json", + "serde_qs", + "serde_urlencoded", + "url", +] + [[package]] name = "httparse" -version = "1.5.1" +version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "acd94fdbe1d4ff688b67b04eee2e17bd50995534a61539e45adfefb45e5e5503" +checksum = "9100414882e15fb7feccb4897e5f0ff0ff1ca7d1a86a23208ada4d7a18e6c6c4" [[package]] name = "ident_case" @@ -1295,13 +1616,19 @@ dependencies = [ "hashbrown", ] +[[package]] +name = "infer" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "64e9829a50b42bb782c1df523f78d332fe371b10c661e78b7a3c34b0198e9fac" + [[package]] name = "instant" version = "0.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", ] [[package]] @@ -1339,9 +1666,9 @@ checksum = "1aab8fc367588b89dcee83ab0fd66b72b50b72fa1904d7095045ace2b0c81c35" [[package]] name = "js-sys" -version = "0.3.55" +version = "0.3.56" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7cc9ffccd38c451a86bf13657df244e9c3f37493cce8e5e21e940963777acc84" +checksum = "a38fc24e30fd564ce974c02bf1d337caddff65be6cc4735a1f7eab22a7440f04" dependencies = [ "wasm-bindgen", ] @@ -1369,9 +1696,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "libc" -version = "0.2.112" +version = "0.2.119" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b03d17f364a3a042d5e5d46b053bbbf82c92c9430c592dd4c064dc6ee997125" +checksum = "1bf2e165bb3457c8e098ea76f3e3bc9db55f87aa90d52d0e6be741470916aaa4" [[package]] name = "libp2p" @@ -1383,7 +1710,7 @@ dependencies = [ "bytes", "futures", "futures-timer", - "getrandom 0.2.3", + "getrandom 0.2.5", "instant", "lazy_static", "libp2p-autonat", @@ -1465,7 +1792,7 @@ dependencies = [ "ring", "rw-stream-sink", "serde", - "sha2 0.10.1", + "sha2 0.10.2", "smallvec", "thiserror", "unsigned-varint", @@ -1523,7 +1850,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6f62943fba0b0dae02b87868620c52a581c54ec9fb04b5e195cf20313fc510c3" dependencies = [ "asynchronous-codec", - "base64", + "base64 0.13.0", "byteorder", "bytes", "fnv", @@ -1539,7 +1866,7 @@ dependencies = [ "rand 0.7.3", "regex", "serde", - "sha2 0.10.1", + "sha2 0.10.2", "smallvec", "unsigned-varint", "wasm-timer", @@ -1583,7 +1910,7 @@ dependencies = [ "prost-build", "rand 0.7.3", "serde", - "sha2 0.10.1", + "sha2 0.10.2", "smallvec", "thiserror", "uint", @@ -1608,7 +1935,7 @@ dependencies = [ "log", "rand 0.8.5", "smallvec", - "socket2 0.4.2", + "socket2 0.4.4", "void", ] @@ -1653,7 +1980,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9dd7e0c94051cda67123be68cf6b65211ba3dde7277be9068412de3e7ffd63ef" dependencies = [ "bytes", - "curve25519-dalek 3.2.0", + "curve25519-dalek 3.2.1", "futures", "lazy_static", "libp2p-core", @@ -1661,7 +1988,7 @@ dependencies = [ "prost", "prost-build", "rand 0.8.5", - "sha2 0.10.1", + "sha2 0.10.2", "snow", "static_assertions", "x25519-dalek", @@ -1758,7 +2085,7 @@ dependencies = [ "prost", "prost-build", "rand 0.8.5", - "sha2 0.10.1", + "sha2 0.10.2", "thiserror", "unsigned-varint", "void", @@ -1826,7 +2153,7 @@ dependencies = [ "libc", "libp2p-core", "log", - "socket2 0.4.2", + "socket2 0.4.4", ] [[package]] @@ -1893,7 +2220,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b0452aac8bab02242429380e9b2f94ea20cea2b37e2c1777a1358799bbe97f37" dependencies = [ "arrayref", - "base64", + "base64 0.13.0", "digest 0.9.0", "hmac-drbg", "libsecp256k1-core", @@ -1966,15 +2293,15 @@ version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "51b9bbe6c47d51fc3e1a9b945965946b4c44142ab8792c50835a980d362c2710" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", "value-bag", ] [[package]] name = "lru" -version = "0.7.2" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "274353858935c992b13c0ca408752e2121da852d07dec7ce5f108c77dfa14d1f" +checksum = "fcb87f3080f6d1d69e8c564c0fcfde1d7aa8cc451ce40cae89479111f03bc0eb" dependencies = [ "hashbrown", ] @@ -2085,7 +2412,7 @@ dependencies = [ "multihash-derive", "serde", "serde-big-array", - "sha2 0.10.1", + "sha2 0.10.2", "unsigned-varint", ] @@ -2129,14 +2456,14 @@ version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "729eb334247daa1803e0a094d0a5c55711b85571179f5ec6e53eccfdf7008958" dependencies = [ - "getrandom 0.2.3", + "getrandom 0.2.5", ] [[package]] name = "netlink-packet-core" -version = "0.4.1" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8349128e95f5dabcb8a18587ad06b3ca7993e90c0c360b4a2abac0313ebce727" +checksum = "345b8ab5bd4e71a2986663e88c56856699d060e78e152e6e9d7966fcd5491297" dependencies = [ "anyhow", "byteorder", @@ -2146,9 +2473,9 @@ dependencies = [ [[package]] name = "netlink-packet-route" -version = "0.10.0" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fb5d54077de7c0904111e1d19b661b8cfccbc23d9ce5b6dbcc7362721e6e552" +checksum = "733ea73609acfd7fa7ddadfb7bf709b0471668c456ad9513685af543a06342b2" dependencies = [ "anyhow", "bitflags", @@ -2160,9 +2487,9 @@ dependencies = [ [[package]] name = "netlink-packet-utils" -version = "0.5.0" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a008a56eceb0cab06739c7f37f15bda27f1147a14d0e7136e8c913b94f1441d" +checksum = "25af9cf0dc55498b7bd94a1508af7a78706aa0ab715a73c5169273e03c84845e" dependencies = [ "anyhow", "byteorder", @@ -2172,9 +2499,9 @@ dependencies = [ [[package]] name = "netlink-proto" -version = "0.9.1" +version = "0.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "073885f70c1d54fdc6148075e8e38a5e8a28179f59de5bd0fc6277cae4fec95a" +checksum = "ef8785b8141e8432aa45fceb922a7e876d7da3fad37fa7e7ec702ace3aa0826b" dependencies = [ "bytes", "futures", @@ -2186,9 +2513,9 @@ dependencies = [ [[package]] name = "netlink-sys" -version = "0.8.1" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed51a4602bb956eefef0ebc15f478bf9732fa3cc706e0a37112e654f41c5b92c" +checksum = "3e4c9f9547a08241bee7b6558b9b98e1f290d187de8b7cfca2bbb4937bcaa8f8" dependencies = [ "async-io", "bytes", @@ -2204,7 +2531,7 @@ dependencies = [ "async-std", "async-trait", "bincode", - "blake3", + "blake3 1.3.1", "color-eyre", "crossterm 0.23.0", "derive_builder", @@ -2217,6 +2544,7 @@ dependencies = [ "serde_json", "snafu", "structopt", + "tide", "tracing", "tracing-error", "tracing-subscriber", @@ -2231,7 +2559,7 @@ checksum = "e4916f159ed8e5de0082076562152a76b7a1f64a01fd9d1e0fea002c37624faf" dependencies = [ "bitflags", "cc", - "cfg-if", + "cfg-if 1.0.0", "libc", "memoffset", ] @@ -2244,13 +2572,32 @@ checksum = "2bf50223579dc7cdcfb3bfcacf7069ff68243f8c363f62ffa99cf000a6b9c451" [[package]] name = "ntapi" -version = "0.3.6" +version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f6bb902e437b6d86e03cce10a7e2af662292c5dfef23b65899ea3ac9354ad44" +checksum = "c28774a7fd2fbb4f0babd8237ce554b73af68021b5f695a3cebd6c59bac0980f" dependencies = [ "winapi", ] +[[package]] +name = "num-integer" +version = "0.1.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2cc698a63b549a70bc047073d2949cce27cd1c7b0a4a862d08a8031bc2801db" +dependencies = [ + "autocfg", + "num-traits", +] + +[[package]] +name = "num-traits" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a64b1ec5cda2586e284722486d802acf1f7dbdc623e2bfc57e65ca1cd099290" +dependencies = [ + "autocfg", +] + [[package]] name = "num_cpus" version = "1.13.1" @@ -2272,9 +2619,9 @@ dependencies = [ [[package]] name = "once_cell" -version = "1.9.0" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da32515d9f6e6e489d7bc9d84c71b060db7247dc035bbe44eac88cf87486d8d5" +checksum = "87f3e037eac156d1775da914196f0f37741a274155e34a0b7e427c35d2a2ecb9" [[package]] name = "opaque-debug" @@ -2336,7 +2683,7 @@ version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d76e8e1493bcac0d2766c42737f34458f1c8c50c0d23bcb24ea953affb273216" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", "instant", "libc", "redox_syscall", @@ -2350,7 +2697,7 @@ version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "28141e0cc4143da2443301914478dc976a61ffdb3f043058310c70df2fed8954" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", "libc", "redox_syscall", "smallvec", @@ -2449,7 +2796,7 @@ version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "685404d509889fade3e86fe3a5803bca2ec09b0c0778d5ada6ec8bf7a8de5259" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", "libc", "log", "wepoll-ffi", @@ -2467,13 +2814,24 @@ dependencies = [ "universal-hash", ] +[[package]] +name = "polyval" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eebcc4aa140b9abd2bc40d9c3f7ccec842679cd79045ac3a7ac698c1a064b7cd" +dependencies = [ + "cpuid-bool", + "opaque-debug", + "universal-hash", +] + [[package]] name = "polyval" version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8419d2b623c7c0896ff2d5d96e2cb4ede590fed28fcc34934f4c33c036e620a1" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", "cpufeatures", "opaque-debug", "universal-hash", @@ -2487,9 +2845,9 @@ checksum = "eb9f9e6e233e5c4a35559a617bf40a4ec447db2e84c20b55a6f83167b7e57872" [[package]] name = "proc-macro-crate" -version = "1.1.0" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ebace6889caf889b4d3f76becee12e90353f2b8c7d875534a71e5742f8f6f83" +checksum = "e17d47ce914bf4de440332250b0edd23ce48c005f59fab39d3335866b114f11a" dependencies = [ "thiserror", "toml", @@ -2519,6 +2877,12 @@ dependencies = [ "version_check", ] +[[package]] +name = "proc-macro-hack" +version = "0.5.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dbf0c48bc1d91375ae5c3cd81e3722dff1abcf81a30960240640d223f59fe0e5" + [[package]] name = "proc-macro2" version = "1.0.36" @@ -2568,7 +2932,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "62941722fb675d463659e49c4f3fe1fe792ff24fe5bbaa9c08cd3b98a1c354f5" dependencies = [ "bytes", - "heck", + "heck 0.3.3", "itertools", "lazy_static", "log", @@ -2623,9 +2987,9 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.14" +version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "47aa80447ce4daf1717500037052af176af5d38cc3e571d9ec1c7353fc10c87d" +checksum = "864d3e96a899863136fc6e99f3d7cae289dafe43bf2c5ac19b70df7210c0a145" dependencies = [ "proc-macro2", ] @@ -2689,7 +3053,7 @@ version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d34f1408f55294453790c48b2f1ebbb1c5b4b7563eb1f418bcfcfdbb06ebb4e7" dependencies = [ - "getrandom 0.2.3", + "getrandom 0.2.5", ] [[package]] @@ -2703,9 +3067,9 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.2.10" +version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8383f39639269cde97d255a32bdb68c047337295414940c68bdd30c2e13203ff" +checksum = "8380fe0152551244f0747b1bf41737e0f8a74f97a14ccefd1148187271634f3c" dependencies = [ "bitflags", ] @@ -2770,11 +3134,17 @@ dependencies = [ "winapi", ] +[[package]] +name = "route-recognizer" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56770675ebc04927ded3e60633437841581c285dc6236109ea25fbf3beb7b59e" + [[package]] name = "rtnetlink" -version = "0.9.0" +version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa584f57f271d3fbd9f59503b090a0410a531c8cc272143669bf136c62ef409d" +checksum = "6f54290e54521dac3de4149d83ddf9f62a359b3cc93bcb494a794a41e6f4744b" dependencies = [ "async-global-executor", "futures", @@ -2791,20 +3161,29 @@ version = "0.1.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7ef03e0a2b150c7a90d01faf6254c9c48a41e95fb2a8c2ac1c6f0d2b9aefc342" +[[package]] +name = "rustc_version" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" +dependencies = [ + "semver 0.9.0", +] + [[package]] name = "rustc_version" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" dependencies = [ - "semver", + "semver 1.0.6", ] [[package]] name = "rustls" -version = "0.20.2" +version = "0.20.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d37e5e2290f3e040b594b1a9e04377c2c671f1a1cfd9bfdef82106ac1c113f84" +checksum = "4fbfeb8d0ddb84706bc597a5574ab8912817c52a397f819e5b614e2265206921" dependencies = [ "log", "ring", @@ -2835,7 +3214,7 @@ version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0c0fbb5f676da676c260ba276a8f43a8dc67cf02d1438423aeb1c677a7212686" dependencies = [ - "cipher", + "cipher 0.3.0", ] [[package]] @@ -2854,12 +3233,27 @@ dependencies = [ "untrusted", ] +[[package]] +name = "semver" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" +dependencies = [ + "semver-parser", +] + [[package]] name = "semver" version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a4a3381e03edd24287172047536f20cabde766e2cd3e65e6b00fb3af51c4f38d" +[[package]] +name = "semver-parser" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" + [[package]] name = "serde" version = "1.0.136" @@ -2901,6 +3295,29 @@ dependencies = [ "serde", ] +[[package]] +name = "serde_qs" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7715380eec75f029a4ef7de39a9200e0a63823176b759d055b613f5a87df6a6" +dependencies = [ + "percent-encoding", + "serde", + "thiserror", +] + +[[package]] +name = "serde_urlencoded" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" +dependencies = [ + "form_urlencoded", + "itoa", + "ryu", + "serde", +] + [[package]] name = "sha-1" version = "0.9.8" @@ -2908,12 +3325,27 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "99cd6713db3cf16b6c84e06321e049a9b9f699826e16096d23bbcc44d15d51a6" dependencies = [ "block-buffer 0.9.0", - "cfg-if", + "cfg-if 1.0.0", "cpufeatures", "digest 0.9.0", "opaque-debug", ] +[[package]] +name = "sha1" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1da05c97445caa12d05e848c4a4fcbbea29e748ac28f7e80e9b010392063770" +dependencies = [ + "sha1_smol", +] + +[[package]] +name = "sha1_smol" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae1a47186c03a32177042e55dbc5fd5aee900b8e0069a8d70fba96a9375cd012" + [[package]] name = "sha2" version = "0.9.9" @@ -2921,7 +3353,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4d58a1e1bf39749807d89cf2d98ac2dfa0ff1cb3faa38fbb64dd88ac8013d800" dependencies = [ "block-buffer 0.9.0", - "cfg-if", + "cfg-if 1.0.0", "cpufeatures", "digest 0.9.0", "opaque-debug", @@ -2929,11 +3361,11 @@ dependencies = [ [[package]] name = "sha2" -version = "0.10.1" +version = "0.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "99c3bd8169c58782adad9290a9af5939994036b76187f7b4f0e6de91dbbfc0ec" +checksum = "55deaec60f81eefe3cce0dc50bda92d6d8e88f2a27df7c5033b42afeb1ed2676" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", "cpufeatures", "digest 0.10.3", ] @@ -2995,6 +3427,15 @@ version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f054c6c1a6e95179d6f23ed974060dcefb2d9388bb7256900badad682c499de4" +[[package]] +name = "simple-mutex" +version = "1.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38aabbeafa6f6dead8cebf246fe9fae1f9215c8d29b3a69f93bd62a9e4a3dcd6" +dependencies = [ + "event-listener", +] + [[package]] name = "slab" version = "0.4.5" @@ -3003,9 +3444,9 @@ checksum = "9def91fd1e018fe007022791f865d0ccc9b3a0d5001e01aabb8b40e46000afb5" [[package]] name = "smallvec" -version = "1.7.0" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ecab6c735a6bb4139c0caafd0cc3635748bbb3acf4550e8138122099251f309" +checksum = "f2dd574626839106c320a323308629dcb1acfc96e32a8cba364ddc61ac23ee83" [[package]] name = "snafu" @@ -3023,7 +3464,7 @@ version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7a7fe9b0669ef117c5cabc5549638528f36771f058ff977d7689deb517833a75" dependencies = [ - "heck", + "heck 0.3.3", "proc-macro2", "quote", "syn", @@ -3035,14 +3476,14 @@ version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "774d05a3edae07ce6d68ea6984f3c05e9bba8927e3dd591e3b479e5b03213d0d" dependencies = [ - "aes-gcm", + "aes-gcm 0.9.4", "blake2", "chacha20poly1305", "curve25519-dalek 4.0.0-pre.2", "rand_core 0.6.3", "ring", - "rustc_version", - "sha2 0.10.1", + "rustc_version 0.4.0", + "sha2 0.10.2", "subtle", ] @@ -3052,16 +3493,16 @@ version = "0.3.19" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "122e570113d28d773067fab24266b66753f6ea915758651696b6e35e49f88d6e" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", "libc", "winapi", ] [[package]] name = "socket2" -version = "0.4.2" +version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5dc90fe6c7be1a323296982db1836d1ea9e47b6839496dde9a541bc496df3516" +checksum = "66d72b759436ae32898a2af0a14218dbf55efde3feeb170eb623637db85ee1e0" dependencies = [ "libc", "winapi", @@ -3073,7 +3514,7 @@ version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "41d1c5305e39e09653383c2c7244f2f78b3bcae37cf50c64cb4789c9f5096ec2" dependencies = [ - "base64", + "base64 0.13.0", "bytes", "flate2", "futures", @@ -3104,12 +3545,70 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" +[[package]] +name = "standback" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e113fb6f3de07a243d434a56ec6f186dfd51cb08448239fe7bcae73f87ff28ff" +dependencies = [ + "version_check", +] + [[package]] name = "static_assertions" version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" +[[package]] +name = "stdweb" +version = "0.4.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d022496b16281348b52d0e30ae99e01a73d737b2f45d38fed4edf79f9325a1d5" +dependencies = [ + "discard", + "rustc_version 0.2.3", + "stdweb-derive", + "stdweb-internal-macros", + "stdweb-internal-runtime", + "wasm-bindgen", +] + +[[package]] +name = "stdweb-derive" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c87a60a40fccc84bef0652345bbbbbe20a605bf5d0ce81719fc476f5c03b50ef" +dependencies = [ + "proc-macro2", + "quote", + "serde", + "serde_derive", + "syn", +] + +[[package]] +name = "stdweb-internal-macros" +version = "0.2.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "58fa5ff6ad0d98d1ffa8cb115892b6e69d67799f6763e162a1c9db421dc22e11" +dependencies = [ + "base-x", + "proc-macro2", + "quote", + "serde", + "serde_derive", + "serde_json", + "sha1", + "syn", +] + +[[package]] +name = "stdweb-internal-runtime" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "213701ba3370744dcd1a12960caa4843b3d68b4d1c0a5d575e0d65b2ee9d16c0" + [[package]] name = "strsim" version = "0.8.0" @@ -3139,7 +3638,7 @@ version = "0.4.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dcb5ae327f9cc13b68763b5749770cb9e048a99bd9dfdfa58d0cf05d5f64afe0" dependencies = [ - "heck", + "heck 0.3.3", "proc-macro-error", "proc-macro2", "quote", @@ -3152,11 +3651,17 @@ version = "2.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6bdef32e8150c2a081110b42772ffe7d7c9032b606bc226c8260fd97e0976601" +[[package]] +name = "sval" +version = "1.0.0-alpha.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "45f6ee7c7b87caf59549e9fe45d6a69c75c8019e79e212a835c5da0e92f0ba08" + [[package]] name = "syn" -version = "1.0.85" +version = "1.0.86" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a684ac3dcd8913827e18cd09a68384ee66c1de24157e3c556c9ab16d85695fb7" +checksum = "8a65b3f4ffa0092e9887669db0eae07941f023991ab58ea44da8fe8e2d511c6b" dependencies = [ "proc-macro2", "quote", @@ -3202,7 +3707,7 @@ version = "3.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5cdb1ef4eaeeaddc8fbd371e5017057064af0911902ef36b39801f67cc6d79e4" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", "fastrand", "libc", "redox_syscall", @@ -3248,6 +3753,77 @@ dependencies = [ "once_cell", ] +[[package]] +name = "tide" +version = "0.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c459573f0dd2cc734b539047f57489ea875af8ee950860ded20cf93a79a1dee0" +dependencies = [ + "async-h1", + "async-session", + "async-sse", + "async-std", + "async-trait", + "femme", + "futures-util", + "http-client", + "http-types", + "kv-log-macro", + "log", + "pin-project-lite 0.2.8", + "route-recognizer", + "serde", + "serde_json", +] + +[[package]] +name = "time" +version = "0.1.43" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca8a50ef2360fbd1eeb0ecd46795a87a19024eb4b53c5dc916ca1fd95fe62438" +dependencies = [ + "libc", + "winapi", +] + +[[package]] +name = "time" +version = "0.2.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4752a97f8eebd6854ff91f1c1824cd6160626ac4bd44287f7f4ea2035a02a242" +dependencies = [ + "const_fn", + "libc", + "standback", + "stdweb", + "time-macros", + "version_check", + "winapi", +] + +[[package]] +name = "time-macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "957e9c6e26f12cb6d0dd7fc776bb67a706312e7299aed74c8dd5b17ebb27e2f1" +dependencies = [ + "proc-macro-hack", + "time-macros-impl", +] + +[[package]] +name = "time-macros-impl" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd3c141a1b43194f3f56a1411225df8646c55781d5f26db825b3d98507eb482f" +dependencies = [ + "proc-macro-hack", + "proc-macro2", + "quote", + "standback", + "syn", +] + [[package]] name = "tinyvec" version = "1.5.1" @@ -3265,9 +3841,9 @@ checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c" [[package]] name = "tokio" -version = "1.16.1" +version = "1.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c27a64b625de6d309e8c57716ba93021dccf1b3b5c97edd6d3dd2d2135afc0a" +checksum = "2af73ac49756f3f7c01172e34a23e5d0216f6c32333757c2c61feb2bbff5a5ee" dependencies = [ "bytes", "memchr", @@ -3289,7 +3865,7 @@ version = "0.1.31" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f6c650a8ef0cd2dd93736f033d21cbd1224c5a967aa0c258d00fcf7dafef9b9f" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", "pin-project-lite 0.2.8", "tracing-attributes", "tracing-core", @@ -3370,12 +3946,12 @@ dependencies = [ [[package]] name = "trust-dns-proto" -version = "0.20.3" +version = "0.20.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad0d7f5db438199a6e2609debe3f69f808d074e0a2888ee0bccb45fe234d03f4" +checksum = "ca94d4e9feb6a181c690c4040d7a24ef34018d8313ac5044a61d21222ae24e31" dependencies = [ "async-trait", - "cfg-if", + "cfg-if 1.0.0", "data-encoding", "enum-as-inner", "futures-channel", @@ -3394,11 +3970,11 @@ dependencies = [ [[package]] name = "trust-dns-resolver" -version = "0.20.3" +version = "0.20.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6ad17b608a64bd0735e67bde16b0636f8aa8591f831a25d18443ed00a699770" +checksum = "ecae383baad9995efaa34ce8e57d12c3f305e545887472a492b838f4b5cfb77a" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", "futures-util", "ipconfig", "lazy_static", @@ -3432,9 +4008,9 @@ checksum = "dcf81ac59edc17cc8697ff311e8f5ef2d99fcbd9817b34cec66f90b6c3dfd987" [[package]] name = "uint" -version = "0.9.1" +version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6470ab50f482bde894a037a57064480a246dbfdd5960bd65a44824693f08da5f" +checksum = "12f03af7ccf01dd611cc450a0d10dbc9b745770d096473e2faf0ca6e2d66d1e0" dependencies = [ "byteorder", "crunchy", @@ -3459,9 +4035,9 @@ dependencies = [ [[package]] name = "unicode-segmentation" -version = "1.8.0" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8895849a949e7845e06bd6dc1aa51731a103c42707010a5b591c0038fb73385b" +checksum = "7e8820f5d777f6224dc4be3632222971ac30164d4a258d595640799554ebfd99" [[package]] name = "unicode-width" @@ -3513,6 +4089,7 @@ dependencies = [ "idna", "matches", "percent-encoding", + "serde", ] [[package]] @@ -3528,6 +4105,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "79923f7731dc61ebfba3633098bf3ac533bbd35ccd8c57e7088d9a5eebe0263f" dependencies = [ "ctor", + "sval", "version_check", ] @@ -3575,19 +4153,21 @@ checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6" [[package]] name = "wasm-bindgen" -version = "0.2.78" +version = "0.2.79" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "632f73e236b219150ea279196e54e610f5dbafa5d61786303d4da54f84e47fce" +checksum = "25f1af7423d8588a3d840681122e72e6a24ddbcb3f0ec385cac0d12d24256c06" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", + "serde", + "serde_json", "wasm-bindgen-macro", ] [[package]] name = "wasm-bindgen-backend" -version = "0.2.78" +version = "0.2.79" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a317bf8f9fba2476b4b2c85ef4c4af8ff39c3c7f0cdfeed4f82c34a880aa837b" +checksum = "8b21c0df030f5a177f3cba22e9bc4322695ec43e7257d865302900290bcdedca" dependencies = [ "bumpalo", "lazy_static", @@ -3600,11 +4180,11 @@ dependencies = [ [[package]] name = "wasm-bindgen-futures" -version = "0.4.28" +version = "0.4.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e8d7523cb1f2a4c96c1317ca690031b714a51cc14e05f712446691f413f5d39" +checksum = "2eb6ec270a31b1d3c7e266b999739109abce8b6c87e4b31fcfcd788b65267395" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", "js-sys", "wasm-bindgen", "web-sys", @@ -3612,9 +4192,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.78" +version = "0.2.79" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d56146e7c495528bf6587663bea13a8eb588d39b36b679d83972e1a2dbbdacf9" +checksum = "2f4203d69e40a52ee523b2529a773d5ffc1dc0071801c87b3d270b471b80ed01" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -3622,9 +4202,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.78" +version = "0.2.79" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7803e0eea25835f8abdc585cd3021b3deb11543c6fe226dcd30b228857c5c5ab" +checksum = "bfa8a30d46208db204854cadbb5d4baf5fcf8071ba5bf48190c3e59937962ebc" dependencies = [ "proc-macro2", "quote", @@ -3635,9 +4215,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-shared" -version = "0.2.78" +version = "0.2.79" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0237232789cf037d5480773fe568aac745bfe2afbc11a863e97901780a6b47cc" +checksum = "3d958d035c4438e28c70e4321a2911302f10135ce78a9c7834c0cab4123d06a2" [[package]] name = "wasm-timer" @@ -3656,9 +4236,9 @@ dependencies = [ [[package]] name = "web-sys" -version = "0.3.55" +version = "0.3.56" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38eb105f1c59d9eaa6b5cdc92b859d85b926e82cb2e0945cd0c9259faa6fe9fb" +checksum = "c060b319f29dd25724f09a2ba1418f142f539b2be99fbf4d2d5a8f7330afb8eb" dependencies = [ "js-sys", "wasm-bindgen", @@ -3694,9 +4274,9 @@ dependencies = [ [[package]] name = "which" -version = "4.2.2" +version = "4.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea187a8ef279bc014ec368c27a920da2024d2a711109bfbe3440585d5cf27ad9" +checksum = "2a5a7e487e921cf220206864a94a89b6c6905bfc19f1057fa26a4cb360e5c1d2" dependencies = [ "either", "lazy_static", @@ -3832,7 +4412,7 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2392b6b94a576b4e2bf3c5b2757d63f10ada8020a2e4d08ac849ebcf6ea8e077" dependencies = [ - "curve25519-dalek 3.2.0", + "curve25519-dalek 3.2.1", "rand_core 0.5.1", "zeroize", ] @@ -3862,9 +4442,9 @@ dependencies = [ [[package]] name = "zeroize_derive" -version = "1.2.2" +version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "65f1a51723ec88c66d5d1fe80c841f17f63587d6691901d66be9bec6c3b51f73" +checksum = "3f8f187641dad4f680d25c4bfc4225b418165984179f26ca76ec4fb6441d3a17" dependencies = [ "proc-macro2", "quote", diff --git a/libp2p-networking/Cargo.toml b/libp2p-networking/Cargo.toml index c511df5e8d..693f9d632f 100644 --- a/libp2p-networking/Cargo.toml +++ b/libp2p-networking/Cargo.toml @@ -26,3 +26,11 @@ tui = { version = "0.17.0", features = ["crossterm"], default-features = false } rand = "0.8.5" async-trait = "0.1.52" derive_builder = "0.10.2" + +# Feature dependencies + +## webui +tide = { version = "0.16", optional = true } + +[features] +webui = ["tide"] diff --git a/libp2p-networking/examples/common/mod.rs b/libp2p-networking/examples/common/mod.rs index eb1b6ba338..5db18a6953 100644 --- a/libp2p-networking/examples/common/mod.rs +++ b/libp2p-networking/examples/common/mod.rs @@ -1,9 +1,5 @@ -use networking_demo::parse_config::NodeDescription; -use std::{ - collections::{HashMap, HashSet}, - sync::{Arc, Once}, - time::Duration, -}; +#[cfg(feature = "webui")] +pub mod web; use async_std::{ fs::File, @@ -11,6 +7,7 @@ use async_std::{ }; use futures::AsyncReadExt; use libp2p::{gossipsub::Topic, request_response::ResponseChannel, PeerId}; +use networking_demo::parse_config::NodeDescription; use networking_demo::{ direct_message::DirectMessageResponse, network_node::{ @@ -27,15 +24,44 @@ use rand::{seq::IteratorRandom, thread_rng}; use serde::{Deserialize, Serialize}; use snafu::{ResultExt, Snafu}; use std::fmt::Debug; +use std::{ + collections::{HashMap, HashSet}, + sync::{Arc, Once}, + time::Duration, +}; use structopt::StructOpt; use tracing::instrument; +#[cfg(feature = "webui")] +use std::net::SocketAddr; + const TIMEOUT: Duration = Duration::from_secs(1000); static INIT: Once = Once::new(); pub type CounterState = u32; pub type ConductorState = HashMap; +#[cfg(feature = "webui")] +impl web::WebInfo for ConductorState { + type Serialized = serde_json::Value; + + fn get_serializable(&self) -> Self::Serialized { + let mut map = serde_json::map::Map::new(); + for (peer, state) in self.iter() { + map.insert(peer.to_base58(), (*state).into()); + } + serde_json::Value::Object(map) + } +} + +#[cfg(feature = "webui")] +impl web::WebInfo for CounterState { + type Serialized = u32; + fn get_serializable(&self) -> Self::Serialized { + *self + } +} + /// Normal message types. We can either /// - increment the Counter /// - request a counter value @@ -77,11 +103,13 @@ pub async fn handle_normal_msg( // direct message only CounterRequest::MyCounterIs(c) => { *handle.state.lock().await = c; + handle.notify_webui().await; } // gossip message only CounterRequest::IncrementCounter { from, to, .. } => { if *handle.state.lock().await == from { *handle.state.lock().await = to; + handle.notify_webui().await; } } // only as a response @@ -175,9 +203,11 @@ pub async fn regular_handle_network_event( } UpdateConnectedPeers(p) => { handle.connection_state.lock().await.connected_peers = p; + handle.notify_webui().await; } UpdateKnownPeers(p) => { handle.connection_state.lock().await.known_peers = p; + handle.notify_webui().await; } } Ok(()) @@ -185,11 +215,17 @@ pub async fn regular_handle_network_event( #[derive(StructOpt)] pub struct CliOpt { - /// Path to the node configuration file + /// Which node to start. Will strong compare with the `multiaddr` value #[structopt(long = "ip_addr", short = "ip")] pub ip: Option, + /// Path to the node configuration file. Defaults to `./identity_mapping.json` #[structopt(long = "toplogy_path", short = "path")] pub path: Option, + + #[cfg(feature = "webui")] + /// If this value is set, a webserver will be spawned on this address with debug info + #[structopt(long = "webui")] + pub webui: Option, } pub async fn parse_config(path: Option) -> Result, CounterError> { @@ -201,7 +237,11 @@ pub async fn parse_config(path: Option) -> Result, serde_json::from_str(&s).context(JsonParseSnafu) } -pub async fn start_main(ip_addr: String, path: Option) -> Result<(), CounterError> { +pub async fn start_main( + ip_addr: String, + path: Option, + #[cfg(feature = "webui")] webui_addr: Option, +) -> Result<(), CounterError> { // FIXME can we pass in a function that returns an error type INIT.call_once(|| { color_eyre::install().unwrap(); @@ -239,7 +279,17 @@ pub async fn start_main(ip_addr: String, path: Option) -> Result<(), Cou .build() .context(NodeConfigSnafu) .context(HandleSnafu)?; - let handle = spin_up_swarm::( + let handle = Arc::new( + NetworkNodeHandle::::new(config.clone(), idx) + .await + .context(HandleSnafu)?, + ); + #[cfg(feature = "webui")] + if let Some(addr) = webui_addr { + web::spawn_server(Arc::clone(&handle), addr); + } + + spin_up_swarm( TIMEOUT, swarm_config .iter() @@ -247,9 +297,11 @@ pub async fn start_main(ip_addr: String, path: Option) -> Result<(), Cou .collect::>(), config, idx, + &handle, ) .await .context(HandleSnafu)?; + spawn_handler(handle.clone(), conductor_handle_network_event).await; // initialize the state of each node @@ -260,6 +312,7 @@ pub async fn start_main(ip_addr: String, path: Option) -> Result<(), Cou } } drop(state); + handle.notify_webui().await; for i in 0..5 { conductor_broadcast(TIMEOUT, i, handle.clone()) @@ -322,7 +375,17 @@ pub async fn start_main(ip_addr: String, path: Option) -> Result<(), Cou .build() .context(NodeConfigSnafu) .context(HandleSnafu)?; - let handle = spin_up_swarm::(TIMEOUT, known_peers, config, idx) + let handle = Arc::new( + NetworkNodeHandle::::new(config.clone(), idx) + .await + .context(HandleSnafu)?, + ); + #[cfg(feature = "webui")] + if let Some(addr) = webui_addr { + web::spawn_server(Arc::clone(&handle), addr); + } + + spin_up_swarm(TIMEOUT, known_peers, config, idx, &handle) .await .context(HandleSnafu)?; let handle_dup = handle.clone(); @@ -417,7 +480,7 @@ pub async fn conductor_direct_message( // send out the requests to ask the chosen peer for its state (and replace ours) let mut remaining_nodes = known_peers.clone(); - remaining_nodes.remove(&chosen_peer); + remaining_nodes.remove(chosen_peer); for peer in &remaining_nodes { let msg = Message::ConductorMessage( @@ -515,6 +578,7 @@ pub async fn conductor_handle_network_event( .unwrap_or(0); println!("new state: {:?}", *handle.state.lock().await); handle.state_changed.notify_all(); + handle.notify_webui().await; } } Message::ConductorMessage(..) => { @@ -528,9 +592,11 @@ pub async fn conductor_handle_network_event( // we care about these for the sake of maintaining conenctions, but not much else UpdateConnectedPeers(p) => { handle.connection_state.lock().await.connected_peers = p; + handle.notify_webui().await; } UpdateKnownPeers(p) => { handle.connection_state.lock().await.known_peers = p; + handle.notify_webui().await; } } Ok(()) diff --git a/libp2p-networking/examples/common/web.rs b/libp2p-networking/examples/common/web.rs new file mode 100644 index 0000000000..dfcbd097c0 --- /dev/null +++ b/libp2p-networking/examples/common/web.rs @@ -0,0 +1,143 @@ +use flume::bounded; +use networking_demo::network_node_handle::NetworkNodeHandle; +use std::{net::SocketAddr, sync::Arc}; +use tracing::{debug, error, info}; + +/// Spawn a web server on the given `addr`. +/// This web server will host the static HTML page `/web/index.html` and expose a `sse` endpoint. +/// This `sse` endpoint will send status updates to the connected clients whenever `NetworkNodeHandle::state_changed` triggers. +/// +/// # Links +/// - SSE on wikipedia: +/// - SEE in `tide`: +pub fn spawn_server(state: Arc>, addr: SocketAddr) +where + S: WebInfo + Send + 'static, +{ + let mut tide = tide::with_state(state); + // Unwrap this in the calling thread so that if it fails we fail completely + // instead of not knowing why the web UI does not work + tide.at("/") + .serve_file("web/index.html") + .expect("Could not register web/index.html"); + tide.at("/sse").get(tide::sse::endpoint( + |req: tide::Request>>, sender| async move { + let peer_addr = req.peer_addr(); + debug!(?peer_addr, "Web client connected, sending initial state"); + + let state = Arc::clone(req.state()); + network_state::State::new(&state) + .await + .send(&sender) + .await?; + + // Register a `Sender<()>` with the `NetworkNodeHandle` so we get notified when it changes + let receiver = { + let (sender, receiver) = bounded(100); + let mut lock = state.webui_listeners.lock().await; + lock.push(sender); + receiver + }; + + while let Ok(()) = receiver.recv_async().await { + // TODO: I think this will not work as this `.lock` will conflict with the other lock, but we'll see + if let Err(e) = network_state::State::new(&state).await.send(&sender).await { + debug!(?peer_addr, ?e, "Could not send to client, aborting"); + break; + } + } + Ok(()) + }, + )); + async_std::task::spawn(async move { + info!(?addr, "Web UI listening on"); + if let Err(e) = tide.listen(addr).await { + error!(?e, "Web UI crashed, this is a bug"); + } + }); +} + +mod network_state { + use std::collections::HashSet; + + use libp2p::PeerId; + use networking_demo::{ + network_node::{ConnectionData, NetworkNodeConfig}, + network_node_handle::NetworkNodeHandle, + }; + + #[derive(serde::Serialize)] + pub struct State { + pub network_config: NetworkConfig, + pub state: S, + pub connection_state: ConnectionState, + } + + #[derive(serde::Serialize)] + pub struct NetworkConfig { + pub max_num_peers: usize, + pub min_num_peers: usize, + pub node_type: String, + pub identity: Option, + pub ignored_peers: Vec, + } + + #[derive(serde::Serialize)] + pub struct ConnectionState { + pub connected_peers: Vec, + pub connecting_peers: Vec, + pub known_peers: Vec, + } + + impl State { + pub async fn new(handle: &NetworkNodeHandle) -> Self + where + W: super::WebInfo + Send + 'static, + { + Self { + network_config: NetworkConfig::new(&handle.network_config), + state: handle.state.lock().await.get_serializable(), + connection_state: ConnectionState::new(&*handle.connection_state.lock().await), + } + } + pub async fn send(self, sender: &tide::sse::Sender) -> std::io::Result<()> { + let str = serde_json::to_string(&self).unwrap(); // serializing JSON should never fail + sender.send("node_state", &str, None).await + } + } + impl NetworkConfig { + fn new(c: &NetworkNodeConfig) -> Self { + Self { + max_num_peers: c.max_num_peers, + min_num_peers: c.min_num_peers, + node_type: format!("{:?}", c.node_type), + identity: c + .identity + .as_ref() + .map(|i| i.public().to_peer_id().to_string()), + ignored_peers: c.ignored_peers.iter().map(|p| p.to_string()).collect(), + } + } + } + impl ConnectionState { + fn new(lock: &ConnectionData) -> ConnectionState { + fn map(set: &HashSet) -> Vec { + set.iter().map(|p| p.to_string()).collect() + } + Self { + connected_peers: map(&lock.connected_peers), + connecting_peers: map(&lock.connecting_peers), + known_peers: map(&lock.known_peers), + } + } + } +} + +/// Trait to unify the info that can be send to the web interface. +/// +/// This has to be implemented for all `S` in `NetworkNodeHandle`, e.g. `CounterState`, `ConductorState`, etc. +pub trait WebInfo: Sync + Send { + type Serialized: serde::Serialize + Send; + + fn get_serializable(&self) -> Self::Serialized; +} diff --git a/libp2p-networking/examples/counter.rs b/libp2p-networking/examples/counter.rs index f32b948cae..4ae9456f81 100644 --- a/libp2p-networking/examples/counter.rs +++ b/libp2p-networking/examples/counter.rs @@ -1,18 +1,21 @@ -use structopt::StructOpt; - use color_eyre::eyre::Result; - +use common::{start_main, CliOpt}; +use structopt::StructOpt; use tracing::instrument; -mod common; - -use common::{start_main, CliOpt}; +pub mod common; #[async_std::main] #[instrument] async fn main() -> Result<()> { let args = CliOpt::from_args(); - start_main(args.ip.unwrap(), args.path).await?; + start_main( + args.ip.unwrap(), + args.path, + #[cfg(feature = "webui")] + args.webui, + ) + .await?; // optional UI perhaps? for monitoring purposes Ok(()) diff --git a/libp2p-networking/src/network_node_handle.rs b/libp2p-networking/src/network_node_handle.rs index 2ced8301e5..f13f36b67b 100644 --- a/libp2p-networking/src/network_node_handle.rs +++ b/libp2p-networking/src/network_node_handle.rs @@ -45,6 +45,12 @@ pub struct NetworkNodeHandle { pub connection_state: Arc>, /// human readable id pub id: usize, + + /// A list of webui listeners that are listening for changes on this node + // TODO: Replace the following fields with `SubscribableMutex` (see https://github.com/EspressoSystems/phaselock/pull/33) + // - `state: Arc>` + // - `connection_state: Arc>` + pub webui_listeners: Arc>>>, } impl NetworkNodeHandle { @@ -81,6 +87,7 @@ impl NetworkNodeHandle { peer_id, connection_state: Arc::default(), id, + webui_listeners: Arc::default(), }) } @@ -122,16 +129,36 @@ impl NetworkNodeHandle { ); node.connection_state.lock().await.connected_peers = pids.clone(); connected_ok = pids.len() >= num_peers; + node.notify_webui().await; } NetworkEvent::UpdateKnownPeers(pids) => { node.connection_state.lock().await.known_peers = pids.clone(); known_ok = pids.len() >= num_peers; + node.notify_webui().await; } _ => {} } } Ok(()) } + + /// Notify the webui that either the `state` or `connection_state` has changed. + /// + /// If the webui is not started, this will do nothing. + pub async fn notify_webui(&self) { + let mut lock = self.webui_listeners.lock().await; + // Keep a list of indexes that are unable to send the update + let mut indexes_to_remove = Vec::new(); + for (idx, sender) in lock.iter().enumerate() { + if sender.send_async(()).await.is_err() { + indexes_to_remove.push(idx); + } + } + // Make sure to remove the indexes in reverse other, else removing an index will invalidate the following indexes. + for idx in indexes_to_remove.into_iter().rev() { + lock.remove(idx); + } + } } /// Glue function that listens for events from the Swarm corresponding to `handle` @@ -181,9 +208,8 @@ pub async fn spin_up_swarm( known_nodes: Vec<(Option, Multiaddr)>, config: NetworkNodeConfig, idx: usize, -) -> Result>, NetworkNodeHandleError> { - let handle = Arc::new(NetworkNodeHandle::new(config.clone(), idx).await?); - + handle: &Arc>, +) -> Result<(), NetworkNodeHandleError> { info!("known_nodes{:?}", known_nodes); handle .send_network @@ -208,7 +234,7 @@ pub async fn spin_up_swarm( .await .context(SendSnafu)?; - Ok(handle) + Ok(()) } /// Given a slice of handles assumed to be larger than 0, diff --git a/libp2p-networking/tests/counter.rs b/libp2p-networking/tests/counter.rs index 71d318cb97..b146bf444e 100644 --- a/libp2p-networking/tests/counter.rs +++ b/libp2p-networking/tests/counter.rs @@ -69,12 +69,14 @@ pub async fn counter_handle_network_event( MyCounterIs(c) => { *handle.state.lock().await = c; handle.state_changed.notify_all(); + handle.notify_webui().await; } // gossip message only IncrementCounter { from, to, .. } => { if *handle.state.lock().await == from { *handle.state.lock().await = to; handle.state_changed.notify_all(); + handle.notify_webui().await; } } // only as a response @@ -90,6 +92,7 @@ pub async fn counter_handle_network_event( if *handle.state.lock().await == from { *handle.state.lock().await = to; handle.state_changed.notify_all(); + handle.notify_webui().await; } } // direct message response @@ -110,9 +113,11 @@ pub async fn counter_handle_network_event( } UpdateConnectedPeers(p) => { handle.connection_state.lock().await.connected_peers = p; + handle.notify_webui().await; } UpdateKnownPeers(p) => { handle.connection_state.lock().await.known_peers = p; + handle.notify_webui().await; } }; Ok(()) @@ -180,6 +185,7 @@ async fn run_gossip_round( ) -> Result<(), TestError> { let msg_handle = get_random_handle(handles); *msg_handle.state.lock().await = new_state; + msg_handle.notify_webui().await; let mut futs = Vec::new(); for handle in handles { diff --git a/libp2p-networking/web/index.html b/libp2p-networking/web/index.html new file mode 100644 index 0000000000..89e03713e2 --- /dev/null +++ b/libp2p-networking/web/index.html @@ -0,0 +1,105 @@ + + + + Phaselock web UI + + + +
+
+
+ min/max peers: /
+
+
+
+ Connected +
    +
    +
    + Connecting +
      +
      +
      + Known +
        +
        +
        +
        +
        +
        +
        + + + + \ No newline at end of file From 447229cf27445b6cbc499d52ce89234ab09538a2 Mon Sep 17 00:00:00 2001 From: Nathan McCarty Date: Fri, 4 Mar 2022 10:05:42 -0500 Subject: [PATCH 105/107] Add networking code to workspace --- Cargo.lock | 3469 +++++++++++++++++++++++--- Cargo.toml | 3 +- libp2p-networking/Cargo.lock | 4453 ---------------------------------- 3 files changed, 3113 insertions(+), 4812 deletions(-) delete mode 100644 libp2p-networking/Cargo.lock diff --git a/Cargo.lock b/Cargo.lock index 8fbf7b1911..552840681b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -17,6 +17,115 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" +[[package]] +name = "aead" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7fc95d1bdb8e6666b2b217308eeeb09f2d6728d104be3e31916cc74d15420331" +dependencies = [ + "generic-array", +] + +[[package]] +name = "aead" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b613b8e1e3cf911a086f53f03bf286f52fd7a7258e4fa606f0ef220d39d8877" +dependencies = [ + "generic-array", +] + +[[package]] +name = "aes" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "884391ef1066acaa41e766ba8f596341b96e93ce34f9a43e7d24bf0a0eaf0561" +dependencies = [ + "aes-soft", + "aesni", + "cipher 0.2.5", +] + +[[package]] +name = "aes" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e8b47f52ea9bae42228d07ec09eb676433d7c4ed1ebdf0f1d1c29ed446f1ab8" +dependencies = [ + "cfg-if 1.0.0", + "cipher 0.3.0", + "cpufeatures", + "opaque-debug", +] + +[[package]] +name = "aes-gcm" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5278b5fabbb9bd46e24aa69b2fdea62c99088e0a950a9be40e3e0101298f88da" +dependencies = [ + "aead 0.3.2", + "aes 0.6.0", + "cipher 0.2.5", + "ctr 0.6.0", + "ghash 0.3.1", + "subtle", +] + +[[package]] +name = "aes-gcm" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df5f85a83a7d8b0442b6aa7b504b8212c1733da07b98aae43d4bc21b2cb3cdf6" +dependencies = [ + "aead 0.4.3", + "aes 0.7.5", + "cipher 0.3.0", + "ctr 0.8.0", + "ghash 0.4.4", + "subtle", +] + +[[package]] +name = "aes-soft" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be14c7498ea50828a38d0e24a765ed2effe92a705885b57d029cd67d45744072" +dependencies = [ + "cipher 0.2.5", + "opaque-debug", +] + +[[package]] +name = "aesni" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea2e11f5e94c2f7d386164cc2aa1f97823fed6f259e486940a71c174dd01b0ce" +dependencies = [ + "cipher 0.2.5", + "opaque-debug", +] + +[[package]] +name = "ahash" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fcb51a0695d8f838b1ee009b3fbf66bda078cd64590202a864a8f3e8c4315c47" +dependencies = [ + "getrandom 0.2.5", + "once_cell", + "version_check", +] + +[[package]] +name = "aho-corasick" +version = "0.7.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e37cfd5e7657ada45f742d6e99ca5788580b5c529dc78faf11ece6dc702656f" +dependencies = [ + "memchr", +] + [[package]] name = "ansi_term" version = "0.12.1" @@ -26,6 +135,12 @@ dependencies = [ "winapi", ] +[[package]] +name = "anyhow" +version = "1.0.55" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "159bb86af3a200e19a068f4224eae4c8bb2d0fa054c7e5d1cacd5cef95e684cd" + [[package]] name = "ark-bls12-381" version = "0.3.0" @@ -77,7 +192,7 @@ dependencies = [ "num-bigint 0.4.3", "num-traits", "paste", - "rustc_version", + "rustc_version 0.3.3", "zeroize", ] @@ -129,12 +244,24 @@ version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a4c527152e37cf757a3f78aae5a06fbeefdb07ccc535c980a3208ee3060dd544" +[[package]] +name = "arrayvec" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23b62fc65de8e4e7f52534fb52b0f3ed04746ae267519eef2a83941e8085068b" + [[package]] name = "arrayvec" version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8da52d66c7071e2e3fa2a1e5c6d088fec47b593032b254f5e980de8ea54454d6" +[[package]] +name = "asn1_der" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e22d1f4b888c298a027c99dc9048015fac177587de20fc30232a057dfbe24a21" + [[package]] name = "async-attributes" version = "1.1.2" @@ -156,6 +283,16 @@ dependencies = [ "futures-core", ] +[[package]] +name = "async-dup" +version = "1.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7427a12b8dc09291528cfb1da2447059adb4a257388c2acd6497a79d55cf6f7c" +dependencies = [ + "futures-io", + "simple-mutex", +] + [[package]] name = "async-executor" version = "1.4.1" @@ -172,9 +309,9 @@ dependencies = [ [[package]] name = "async-global-executor" -version = "2.0.2" +version = "2.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9586ec52317f36de58453159d48351bc244bc24ced3effc1fce22f3d48664af6" +checksum = "c026b7e44f1316b567ee750fea85103f87fcb80792b860e979f221259796ca0a" dependencies = [ "async-channel", "async-executor", @@ -186,6 +323,22 @@ dependencies = [ "once_cell", ] +[[package]] +name = "async-h1" +version = "2.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8101020758a4fc3a7c326cb42aa99e9fa77cbfb76987c128ad956406fe1f70a7" +dependencies = [ + "async-channel", + "async-dup", + "async-std", + "futures-core", + "http-types", + "httparse", + "log", + "pin-project 1.0.10", +] + [[package]] name = "async-io" version = "1.6.0" @@ -200,7 +353,7 @@ dependencies = [ "parking", "polling", "slab", - "socket2", + "socket2 0.4.4", "waker-fn", "winapi", ] @@ -231,7 +384,7 @@ checksum = "83137067e3a2a6a06d67168e49e68a0957d215410473a740cea95a2425c0b7c6" dependencies = [ "async-io", "blocking", - "cfg-if", + "cfg-if 1.0.0", "event-listener", "futures-lite", "libc", @@ -240,6 +393,41 @@ dependencies = [ "winapi", ] +[[package]] +name = "async-session" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "345022a2eed092cd105cc1b26fd61c341e100bd5fcbbd792df4baf31c2cc631f" +dependencies = [ + "anyhow", + "async-std", + "async-trait", + "base64 0.12.3", + "bincode", + "blake3 0.3.8", + "chrono", + "hmac 0.8.1", + "kv-log-macro", + "rand 0.7.3", + "serde", + "serde_json", + "sha2 0.9.9", +] + +[[package]] +name = "async-sse" +version = "4.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53bba003996b8fd22245cd0c59b869ba764188ed435392cf2796d03b805ade10" +dependencies = [ + "async-channel", + "async-std", + "http-types", + "log", + "memchr", + "pin-project-lite 0.1.12", +] + [[package]] name = "async-std" version = "1.10.0" @@ -263,18 +451,43 @@ dependencies = [ "memchr", "num_cpus", "once_cell", - "pin-project-lite", + "pin-project-lite 0.2.8", "pin-utils", "slab", "wasm-bindgen-futures", ] +[[package]] +name = "async-std-resolver" +version = "0.20.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dbf3e776afdf3a2477ef4854b85ba0dff3bd85792f685fb3c68948b4d304e4f0" +dependencies = [ + "async-std", + "async-trait", + "futures-io", + "futures-util", + "pin-utils", + "trust-dns-resolver", +] + [[package]] name = "async-task" version = "4.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "677d306121baf53310a3fd342d88dc0824f6bbeace68347593658525565abee8" +[[package]] +name = "async-trait" +version = "0.1.52" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "061a7acccaa286c011ddc30970520b98fa40e00c9d644633fb26b5fc63a265e3" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "async-tungstenite" version = "0.16.1" @@ -285,10 +498,32 @@ dependencies = [ "futures-io", "futures-util", "log", - "pin-project-lite", + "pin-project-lite 0.2.8", "tungstenite", ] +[[package]] +name = "asynchronous-codec" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0de5164e5edbf51c45fb8c2d9664ae1c095cce1b265ecf7569093c0d66ef690" +dependencies = [ + "bytes", + "futures-sink", + "futures-util", + "memchr", + "pin-project-lite 0.2.8", +] + +[[package]] +name = "atomic" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b88d82667eca772c4aa12f0f1348b3ae643424c8876448f3f7bd5787032e234c" +dependencies = [ + "autocfg", +] + [[package]] name = "atomic-waker" version = "1.0.0" @@ -320,19 +555,37 @@ checksum = "5e121dee8023ce33ab248d9ce1493df03c3b38a659b240096fcbd7048ff9c31f" dependencies = [ "addr2line", "cc", - "cfg-if", + "cfg-if 1.0.0", "libc", "miniz_oxide", "object", "rustc-demangle", ] +[[package]] +name = "base-x" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4521f3e3d031370679b3b140beb36dfe4801b09ac77e30c61941f97df3ef28b" + +[[package]] +name = "base64" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3441f0f7b02788e948e47f457ca01f1d7e6d92c693bc132c22b087d3141c03ff" + [[package]] name = "base64" version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "904dfeac50f3cdaba28fc6f57fdcddb75f49ed61346676a78c4ffe55877802fd" +[[package]] +name = "bimap" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc0455254eb5c6964c4545d8bac815e1a1be4f3afe0ae695ea539c12d728d44b" + [[package]] name = "bincode" version = "1.3.3" @@ -363,6 +616,30 @@ version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" +[[package]] +name = "blake2" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9cf849ee05b2ee5fba5e36f97ff8ec2533916700fc0758d40d92136a42f3388" +dependencies = [ + "digest 0.10.3", +] + +[[package]] +name = "blake3" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b64485778c4f16a6a5a9d335e80d449ac6c70cdd6a06d2af18a6f6f775a125b3" +dependencies = [ + "arrayref", + "arrayvec 0.5.2", + "cc", + "cfg-if 0.1.10", + "constant_time_eq", + "crypto-mac 0.8.0", + "digest 0.9.0", +] + [[package]] name = "blake3" version = "1.3.1" @@ -370,9 +647,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a08e53fc5a564bb15bfe6fae56bd71522205f1f91893f9c0116edad6496c183f" dependencies = [ "arrayref", - "arrayvec", + "arrayvec 0.7.2", "cc", - "cfg-if", + "cfg-if 1.0.0", "constant_time_eq", "digest 0.10.3", ] @@ -383,6 +660,7 @@ version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4152116fd6e9dadb291ae18fc1ec3575ed6d84c29642d97890f4b4a3417297e4" dependencies = [ + "block-padding", "generic-array", ] @@ -395,6 +673,12 @@ dependencies = [ "generic-array", ] +[[package]] +name = "block-padding" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d696c370c750c948ada61c69a0ee2cbbb9c50b1019ddb86d9317157a99c2cae" + [[package]] name = "blocking" version = "1.1.0" @@ -409,6 +693,12 @@ dependencies = [ "once_cell", ] +[[package]] +name = "bs58" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "771fe0050b883fcc3ea2359b1a96bcfbc090b7116eae7c3c512c7a083fdf23d3" + [[package]] name = "bumpalo" version = "3.9.1" @@ -426,6 +716,9 @@ name = "bytes" version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c4872d67bab6358e59559027aa3b9157c53d9358c51423c17554809a8858e0f8" +dependencies = [ + "serde", +] [[package]] name = "cache-padded" @@ -433,12 +726,24 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c1db59621ec70f09c5e9b597b220c7a2b43611f4710dc03ceb8748637775692c" +[[package]] +name = "cassowary" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df8670b8c7b9dae1793364eafadf7239c40d669904660c5960d74cfd80b46a53" + [[package]] name = "cc" version = "1.0.73" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2fff2a6927b3bb87f9595d67196a70493f627687a71d87a0d692242c33f58c11" +[[package]] +name = "cfg-if" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" + [[package]] name = "cfg-if" version = "1.0.0" @@ -446,540 +751,2049 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] -name = "clap" -version = "2.34.0" +name = "chacha20" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a0610544180c38b88101fecf2dd634b174a62eef6946f84dfc6a7127512b381c" +checksum = "01b72a433d0cf2aef113ba70f62634c56fddb0f244e6377185c56a7cadbd8f91" dependencies = [ - "ansi_term", - "atty", - "bitflags", - "strsim", - "textwrap", - "unicode-width", - "vec_map", + "cfg-if 1.0.0", + "cipher 0.3.0", + "cpufeatures", + "zeroize", ] [[package]] -name = "concurrent-queue" -version = "1.2.2" +name = "chacha20poly1305" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30ed07550be01594c6026cff2a1d7fe9c8f683caa798e12b68694ac9e88286a3" +checksum = "3b84ed6d1d5f7aa9bdde921a5090e0ca4d934d250ea3b402a5fab3a994e28a2a" dependencies = [ - "cache-padded", + "aead 0.4.3", + "chacha20", + "cipher 0.3.0", + "poly1305", + "zeroize", ] [[package]] -name = "constant_time_eq" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "245097e9a4535ee1e3e3931fcfcd55a796a44c643e8596ff6566d68f09b87bbc" - -[[package]] -name = "cpufeatures" -version = "0.2.1" +name = "chrono" +version = "0.4.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95059428f66df56b63431fdb4e1947ed2190586af5c5a8a8b71122bdf5a7f469" +checksum = "670ad68c9088c2a963aaa298cb369688cf3f9465ce5e2d4ca10e6e0098a1ce73" dependencies = [ "libc", + "num-integer", + "num-traits", + "serde", + "time 0.1.43", + "winapi", ] [[package]] -name = "crossbeam-utils" -version = "0.8.7" +name = "cipher" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5e5bed1f1c269533fa816a0a5492b3545209a205ca1a54842be180eb63a16a6" +checksum = "12f8e7987cbd042a63249497f41aed09f8e65add917ea6566effbc56578d6801" dependencies = [ - "cfg-if", - "lazy_static", + "generic-array", ] [[package]] -name = "crunchy" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" - -[[package]] -name = "crypto-common" -version = "0.1.3" +name = "cipher" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57952ca27b5e3606ff4dd79b0020231aaf9d6aa76dc05fd30137538c50bd3ce8" +checksum = "7ee52072ec15386f770805afd189a01c8841be8696bed250fa2f13c4c0d6dfb7" dependencies = [ "generic-array", - "typenum", ] [[package]] -name = "ctor" -version = "0.1.21" +name = "clap" +version = "2.34.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ccc0a48a9b826acdf4028595adc9db92caea352f7af011a3034acd172a52a0aa" +checksum = "a0610544180c38b88101fecf2dd634b174a62eef6946f84dfc6a7127512b381c" dependencies = [ - "quote", - "syn", -] - -[[package]] -name = "dashmap" -version = "5.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0834a35a3fce649144119e18da2a4d8ed12ef3862f47183fd46f625d072d96c" -dependencies = [ - "cfg-if", - "num_cpus", - "parking_lot", + "ansi_term", + "atty", + "bitflags", + "strsim 0.8.0", + "textwrap", + "unicode-width", + "vec_map", ] [[package]] -name = "derivative" -version = "2.2.0" +name = "color-eyre" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fcc3dd5e9e9c0b295d6e1e4d811fb6f157d5ffd784b8d202fc62eac8035a770b" +checksum = "8ebf286c900a6d5867aeff75cfee3192857bb7f24b547d4f0df2ed6baa812c90" dependencies = [ - "proc-macro2", - "quote", - "syn", + "backtrace", + "color-spantrace", + "eyre", + "indenter", + "once_cell", + "owo-colors", + "tracing-error", ] [[package]] -name = "digest" -version = "0.9.0" +name = "color-spantrace" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066" +checksum = "1ba75b3d9449ecdccb27ecbc479fdc0b87fa2dd43d2f8298f9bf0e59aacc8dce" dependencies = [ - "generic-array", + "once_cell", + "owo-colors", + "tracing-core", + "tracing-error", ] [[package]] -name = "digest" -version = "0.10.3" +name = "concurrent-queue" +version = "1.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2fb860ca6fafa5552fb6d0e816a69c8e49f0908bf524e30a90d97c85892d506" +checksum = "30ed07550be01594c6026cff2a1d7fe9c8f683caa798e12b68694ac9e88286a3" dependencies = [ - "block-buffer 0.10.2", - "crypto-common", - "subtle", + "cache-padded", ] [[package]] -name = "doc-comment" -version = "0.3.3" +name = "const_fn" +version = "0.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fea41bba32d969b513997752735605054bc0dfa92b4c56bf1189f2e174be7a10" +checksum = "fbdcdcb6d86f71c5e97409ad45898af11cbc995b4ee8112d59095a28d376c935" [[package]] -name = "event-listener" -version = "2.5.2" +name = "constant_time_eq" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77f3309417938f28bf8228fcff79a4a37103981e3e186d2ccd19c74b38f4eb71" +checksum = "245097e9a4535ee1e3e3931fcfcd55a796a44c643e8596ff6566d68f09b87bbc" [[package]] -name = "failure" -version = "0.1.8" +name = "cookie" +version = "0.14.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d32e9bd16cc02eae7db7ef620b392808b89f6a5e16bb3497d159c6b92a0f4f86" +checksum = "03a5d7b21829bc7b4bf4754a978a241ae54ea55a40f92bb20216e54096f4b951" dependencies = [ - "backtrace", - "failure_derive", + "aes-gcm 0.8.0", + "base64 0.13.0", + "hkdf", + "hmac 0.10.1", + "percent-encoding", + "rand 0.8.5", + "sha2 0.9.9", + "time 0.2.27", + "version_check", ] [[package]] -name = "failure_derive" -version = "0.1.8" +name = "core-foundation" +version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa4da3c766cd7a0db8242e326e9e4e081edd567072893ed320008189715366a4" +checksum = "194a7a9e6de53fa55116934067c844d9d749312f75c6f6d0980e8c252f8c2146" dependencies = [ - "proc-macro2", - "quote", - "syn", - "synstructure", + "core-foundation-sys", + "libc", ] [[package]] -name = "fastrand" -version = "1.7.0" +name = "core-foundation-sys" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3fcf0cee53519c866c09b5de1f6c56ff9d647101f81c1964fa632e148896cdf" -dependencies = [ - "instant", -] +checksum = "5827cebf4670468b8772dd191856768aedcb1b0278a04f989f7766351917b9dc" [[package]] -name = "ff" -version = "0.6.0" +name = "core2" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4b967a3ee6ae993f0094174257d404a5818f58be79d67a1aea1ec8996d28906" +checksum = "b49ba7ef1ad6107f8824dbe97de947cbaac53c44e7f9756a1fba0d37c1eec505" dependencies = [ - "byteorder", - "ff_derive", - "rand_core 0.5.1", + "memchr", ] [[package]] -name = "ff_derive" -version = "0.6.0" +name = "cpufeatures" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3776aaf60a45037a9c3cabdd8542b38693acaa3e241ff957181b72579d29feb" +checksum = "95059428f66df56b63431fdb4e1947ed2190586af5c5a8a8b71122bdf5a7f469" dependencies = [ - "num-bigint 0.2.6", - "num-integer", - "num-traits", - "proc-macro2", - "quote", - "syn", + "libc", ] [[package]] -name = "flume" -version = "0.10.11" +name = "cpuid-bool" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b279436a715a9de95dcd26b151db590a71961cc06e54918b24fe0dd5b7d3fc4" +checksum = "dcb25d077389e53838a8158c8e99174c5a9d902dee4904320db714f3c653ffba" + +[[package]] +name = "crc32fast" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b540bd8bc810d3885c6ea91e2018302f68baba2129ab3e88f32389ee9370880d" dependencies = [ - "futures-core", - "futures-sink", - "nanorand", - "pin-project", - "spin", + "cfg-if 1.0.0", ] [[package]] -name = "fnv" -version = "1.0.7" +name = "crossbeam-utils" +version = "0.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" +checksum = "b5e5bed1f1c269533fa816a0a5492b3545209a205ca1a54842be180eb63a16a6" +dependencies = [ + "cfg-if 1.0.0", + "lazy_static", +] [[package]] -name = "form_urlencoded" -version = "1.0.1" +name = "crossterm" +version = "0.22.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5fc25a87fa4fd2094bffb06925852034d90a17f0d1e05197d4956d3555752191" +checksum = "c85525306c4291d1b73ce93c8acf9c339f9b213aef6c1d85c3830cbf1c16325c" dependencies = [ - "matches", - "percent-encoding", + "bitflags", + "crossterm_winapi", + "libc", + "mio", + "parking_lot 0.11.2", + "signal-hook", + "signal-hook-mio", + "winapi", ] [[package]] -name = "futures" -version = "0.3.21" +name = "crossterm" +version = "0.23.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f73fe65f54d1e12b726f517d3e2135ca3125a437b6d998caf1962961f7172d9e" +checksum = "77b75a27dc8d220f1f8521ea69cd55a34d720a200ebb3a624d9aa19193d3b432" dependencies = [ - "futures-channel", + "bitflags", + "crossterm_winapi", "futures-core", - "futures-executor", - "futures-io", - "futures-sink", - "futures-task", - "futures-util", + "libc", + "mio", + "parking_lot 0.12.0", + "signal-hook", + "signal-hook-mio", + "winapi", ] [[package]] -name = "futures-channel" -version = "0.3.21" +name = "crossterm_winapi" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3083ce4b914124575708913bca19bfe887522d6e2e6d0952943f5eac4a74010" +checksum = "2ae1b35a484aa10e07fe0638d02301c5ad24de82d310ccbd2f3693da5f09bf1c" dependencies = [ - "futures-core", - "futures-sink", + "winapi", ] [[package]] -name = "futures-core" -version = "0.3.21" +name = "crunchy" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c09fd04b7e4073ac7156a9539b57a484a8ea920f79c7c675d05d289ab6110d3" +checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" [[package]] -name = "futures-executor" -version = "0.3.21" +name = "crypto-common" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9420b90cfa29e327d0429f19be13e7ddb68fa1cccb09d65e5706b8c7a749b8a6" +checksum = "57952ca27b5e3606ff4dd79b0020231aaf9d6aa76dc05fd30137538c50bd3ce8" dependencies = [ - "futures-core", - "futures-task", - "futures-util", + "generic-array", + "typenum", ] [[package]] -name = "futures-io" -version = "0.3.21" +name = "crypto-mac" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc4045962a5a5e935ee2fdedaa4e08284547402885ab326734432bed5d12966b" +checksum = "b584a330336237c1eecd3e94266efb216c56ed91225d634cb2991c5f3fd1aeab" +dependencies = [ + "generic-array", + "subtle", +] [[package]] -name = "futures-lite" -version = "1.12.0" +name = "crypto-mac" +version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7694489acd39452c77daa48516b894c153f192c3578d5a839b62c58099fcbf48" +checksum = "bff07008ec701e8028e2ceb8f83f0e4274ee62bd2dbdc4fefff2e9a91824081a" dependencies = [ - "fastrand", - "futures-core", - "futures-io", - "memchr", - "parking", - "pin-project-lite", - "waker-fn", + "generic-array", + "subtle", ] [[package]] -name = "futures-macro" -version = "0.3.21" +name = "ctor" +version = "0.1.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33c1e13800337f4d4d7a316bf45a567dbcb6ffe087f16424852d97e97a91f512" +checksum = "ccc0a48a9b826acdf4028595adc9db92caea352f7af011a3034acd172a52a0aa" dependencies = [ - "proc-macro2", "quote", "syn", ] [[package]] -name = "futures-sink" -version = "0.3.21" +name = "ctr" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21163e139fa306126e6eedaf49ecdb4588f939600f0b1e770f4205ee4b7fa868" +checksum = "fb4a30d54f7443bf3d6191dcd486aca19e67cb3c49fa7a06a319966346707e7f" +dependencies = [ + "cipher 0.2.5", +] [[package]] -name = "futures-task" -version = "0.3.21" +name = "ctr" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57c66a976bf5909d801bbef33416c41372779507e7a6b3a5e25e4749c58f776a" +checksum = "049bb91fb4aaf0e3c7efa6cd5ef877dbbbd15b39dad06d9948de4ec8a75761ea" +dependencies = [ + "cipher 0.3.0", +] [[package]] -name = "futures-util" -version = "0.3.21" +name = "cuckoofilter" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8b7abd5d659d9b90c8cba917f6ec750a74e2dc23902ef9cd4cc8c8b22e6036a" +checksum = "b810a8449931679f64cd7eef1bbd0fa315801b6d5d9cdc1ace2804d6529eee18" dependencies = [ - "futures-channel", - "futures-core", - "futures-io", - "futures-macro", - "futures-sink", - "futures-task", - "memchr", - "pin-project-lite", - "pin-utils", - "slab", + "byteorder", + "fnv", + "rand 0.7.3", ] [[package]] -name = "generic-array" -version = "0.14.5" +name = "curve25519-dalek" +version = "3.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd48d33ec7f05fbfa152300fdad764757cbded343c1aa1cff2fbaf4134851803" +checksum = "90f9d052967f590a76e62eb387bd0bbb1b000182c3cefe5364db6b7211651bc0" dependencies = [ - "typenum", - "version_check", + "byteorder", + "digest 0.9.0", + "rand_core 0.5.1", + "subtle", + "zeroize", ] [[package]] -name = "getrandom" -version = "0.1.16" +name = "curve25519-dalek" +version = "4.0.0-pre.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8fc3cb4d91f53b50155bdcfd23f6a4c39ae1969c2ae85982b135750cccaf5fce" +checksum = "12dc3116fe595d7847c701796ac1b189bd86b81f4f593c6f775f9d80fb2e29f4" dependencies = [ - "cfg-if", - "libc", - "wasi 0.9.0+wasi-snapshot-preview1", + "byteorder", + "digest 0.10.3", + "rand_core 0.6.3", + "subtle", + "zeroize", ] [[package]] -name = "getrandom" -version = "0.2.4" +name = "darling" +version = "0.12.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "418d37c8b1d42553c93648be529cb70f920d3baf8ef469b74b9638df426e0b4c" +checksum = "5f2c43f534ea4b0b049015d00269734195e6d3f0f6635cb692251aca6f9f8b3c" dependencies = [ - "cfg-if", - "js-sys", - "libc", - "wasi 0.10.2+wasi-snapshot-preview1", - "wasm-bindgen", + "darling_core", + "darling_macro", ] [[package]] -name = "gimli" -version = "0.26.1" +name = "darling_core" +version = "0.12.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78cc372d058dcf6d5ecd98510e7fbc9e5aec4d21de70f65fea8fecebcd881bd4" +checksum = "8e91455b86830a1c21799d94524df0845183fa55bafd9aa137b01c7d1065fa36" +dependencies = [ + "fnv", + "ident_case", + "proc-macro2", + "quote", + "strsim 0.10.0", + "syn", +] [[package]] -name = "gloo-timers" -version = "0.2.3" +name = "darling_macro" +version = "0.12.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d12a7f4e95cfe710f1d624fb1210b7d961a5fb05c4fd942f4feab06e61f590e" +checksum = "29b5acf0dea37a7f66f7b25d2c5e93fd46f8f6968b1a5d7a3e02e97768afc95a" dependencies = [ - "futures-channel", - "futures-core", - "js-sys", - "wasm-bindgen", + "darling_core", + "quote", + "syn", ] [[package]] -name = "group" -version = "0.6.0" +name = "dashmap" +version = "4.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e77a43b28d0668df09411cb0bc9a8c2adc40f9a048afe863e05fd43251e8e39c" +dependencies = [ + "cfg-if 1.0.0", + "num_cpus", +] + +[[package]] +name = "dashmap" +version = "5.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0834a35a3fce649144119e18da2a4d8ed12ef3862f47183fd46f625d072d96c" +dependencies = [ + "cfg-if 1.0.0", + "num_cpus", + "parking_lot 0.12.0", +] + +[[package]] +name = "data-encoding" +version = "2.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ee2393c4a91429dffb4bedf19f4d6abf27d8a732c8ce4980305d782e5426d57" + +[[package]] +name = "derivative" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fcc3dd5e9e9c0b295d6e1e4d811fb6f157d5ffd784b8d202fc62eac8035a770b" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "derive_builder" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d13202debe11181040ae9063d739fa32cfcaaebe2275fe387703460ae2365b30" +dependencies = [ + "derive_builder_macro", +] + +[[package]] +name = "derive_builder_core" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "66e616858f6187ed828df7c64a6d71720d83767a7f19740b2d1b6fe6327b36e5" +dependencies = [ + "darling", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "derive_builder_macro" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "58a94ace95092c5acb1e97a7e846b310cfbd499652f72297da7493f618a98d73" +dependencies = [ + "derive_builder_core", + "syn", +] + +[[package]] +name = "digest" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066" +dependencies = [ + "generic-array", +] + +[[package]] +name = "digest" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2fb860ca6fafa5552fb6d0e816a69c8e49f0908bf524e30a90d97c85892d506" +dependencies = [ + "block-buffer 0.10.2", + "crypto-common", + "subtle", +] + +[[package]] +name = "discard" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "212d0f5754cb6769937f4501cc0e67f4f4483c8d2c3e1e922ee9edbe4ab4c7c0" + +[[package]] +name = "dns-parser" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4d33be9473d06f75f58220f71f7a9317aca647dc061dbd3c361b0bef505fbea" +dependencies = [ + "byteorder", + "quick-error 1.2.3", +] + +[[package]] +name = "doc-comment" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fea41bba32d969b513997752735605054bc0dfa92b4c56bf1189f2e174be7a10" + +[[package]] +name = "dtoa" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5caaa75cbd2b960ff1e5392d2cfb1f44717fffe12fc1f32b7b5d1267f99732a6" + +[[package]] +name = "ed25519" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eed12bbf7b5312f8da1c2722bc06d8c6b12c2d86a7fb35a194c7f3e6fc2bbe39" +dependencies = [ + "signature", +] + +[[package]] +name = "ed25519-dalek" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c762bae6dcaf24c4c84667b8579785430908723d5c889f469d76a41d59cc7a9d" +dependencies = [ + "curve25519-dalek 3.2.1", + "ed25519", + "rand 0.7.3", + "serde", + "sha2 0.9.9", + "zeroize", +] + +[[package]] +name = "either" +version = "1.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457" + +[[package]] +name = "enum-as-inner" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "570d109b813e904becc80d8d5da38376818a143348413f7149f1340fe04754d4" +dependencies = [ + "heck 0.4.0", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "event-listener" +version = "2.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77f3309417938f28bf8228fcff79a4a37103981e3e186d2ccd19c74b38f4eb71" + +[[package]] +name = "eyre" +version = "0.6.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9289ed2c0440a6536e65119725cf91fc2c6b5e513bfd2e36e1134d7cca6ca12f" +dependencies = [ + "indenter", + "once_cell", +] + +[[package]] +name = "failure" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d32e9bd16cc02eae7db7ef620b392808b89f6a5e16bb3497d159c6b92a0f4f86" +dependencies = [ + "backtrace", + "failure_derive", +] + +[[package]] +name = "failure_derive" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa4da3c766cd7a0db8242e326e9e4e081edd567072893ed320008189715366a4" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "synstructure", +] + +[[package]] +name = "fastrand" +version = "1.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3fcf0cee53519c866c09b5de1f6c56ff9d647101f81c1964fa632e148896cdf" +dependencies = [ + "instant", +] + +[[package]] +name = "femme" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2af1a24f391a5a94d756db5092c6576aad494b88a71a5a36b20c67b63e0df034" +dependencies = [ + "cfg-if 0.1.10", + "js-sys", + "log", + "serde", + "serde_derive", + "serde_json", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "ff" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4b967a3ee6ae993f0094174257d404a5818f58be79d67a1aea1ec8996d28906" +dependencies = [ + "byteorder", + "ff_derive", + "rand_core 0.5.1", +] + +[[package]] +name = "ff_derive" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a3776aaf60a45037a9c3cabdd8542b38693acaa3e241ff957181b72579d29feb" +dependencies = [ + "num-bigint 0.2.6", + "num-integer", + "num-traits", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "fixedbitset" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "279fb028e20b3c4c320317955b77c5e0c9701f05a1d309905d6fc702cdc5053e" + +[[package]] +name = "flate2" +version = "1.0.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e6988e897c1c9c485f43b47a529cef42fde0547f9d8d41a7062518f1d8fc53f" +dependencies = [ + "cfg-if 1.0.0", + "crc32fast", + "libc", + "libz-sys", + "miniz_oxide", +] + +[[package]] +name = "flume" +version = "0.10.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b279436a715a9de95dcd26b151db590a71961cc06e54918b24fe0dd5b7d3fc4" +dependencies = [ + "futures-core", + "futures-sink", + "nanorand", + "pin-project 1.0.10", + "spin 0.9.2", +] + +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + +[[package]] +name = "form_urlencoded" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5fc25a87fa4fd2094bffb06925852034d90a17f0d1e05197d4956d3555752191" +dependencies = [ + "matches", + "percent-encoding", +] + +[[package]] +name = "futures" +version = "0.3.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f73fe65f54d1e12b726f517d3e2135ca3125a437b6d998caf1962961f7172d9e" +dependencies = [ + "futures-channel", + "futures-core", + "futures-executor", + "futures-io", + "futures-sink", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-channel" +version = "0.3.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3083ce4b914124575708913bca19bfe887522d6e2e6d0952943f5eac4a74010" +dependencies = [ + "futures-core", + "futures-sink", +] + +[[package]] +name = "futures-core" +version = "0.3.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c09fd04b7e4073ac7156a9539b57a484a8ea920f79c7c675d05d289ab6110d3" + +[[package]] +name = "futures-executor" +version = "0.3.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9420b90cfa29e327d0429f19be13e7ddb68fa1cccb09d65e5706b8c7a749b8a6" +dependencies = [ + "futures-core", + "futures-task", + "futures-util", + "num_cpus", +] + +[[package]] +name = "futures-io" +version = "0.3.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc4045962a5a5e935ee2fdedaa4e08284547402885ab326734432bed5d12966b" + +[[package]] +name = "futures-lite" +version = "1.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7694489acd39452c77daa48516b894c153f192c3578d5a839b62c58099fcbf48" +dependencies = [ + "fastrand", + "futures-core", + "futures-io", + "memchr", + "parking", + "pin-project-lite 0.2.8", + "waker-fn", +] + +[[package]] +name = "futures-macro" +version = "0.3.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33c1e13800337f4d4d7a316bf45a567dbcb6ffe087f16424852d97e97a91f512" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "futures-rustls" +version = "0.22.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d383f0425d991a05e564c2f3ec150bd6dde863179c131dd60d8aa73a05434461" +dependencies = [ + "futures-io", + "rustls", + "webpki", +] + +[[package]] +name = "futures-sink" +version = "0.3.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "21163e139fa306126e6eedaf49ecdb4588f939600f0b1e770f4205ee4b7fa868" + +[[package]] +name = "futures-task" +version = "0.3.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57c66a976bf5909d801bbef33416c41372779507e7a6b3a5e25e4749c58f776a" + +[[package]] +name = "futures-timer" +version = "3.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e64b03909df88034c26dc1547e8970b91f98bdb65165d6a4e9110d94263dbb2c" + +[[package]] +name = "futures-util" +version = "0.3.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8b7abd5d659d9b90c8cba917f6ec750a74e2dc23902ef9cd4cc8c8b22e6036a" +dependencies = [ + "futures-channel", + "futures-core", + "futures-io", + "futures-macro", + "futures-sink", + "futures-task", + "memchr", + "pin-project-lite 0.2.8", + "pin-utils", + "slab", +] + +[[package]] +name = "generic-array" +version = "0.14.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd48d33ec7f05fbfa152300fdad764757cbded343c1aa1cff2fbaf4134851803" +dependencies = [ + "typenum", + "version_check", +] + +[[package]] +name = "getrandom" +version = "0.1.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8fc3cb4d91f53b50155bdcfd23f6a4c39ae1969c2ae85982b135750cccaf5fce" +dependencies = [ + "cfg-if 1.0.0", + "libc", + "wasi 0.9.0+wasi-snapshot-preview1", +] + +[[package]] +name = "getrandom" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d39cd93900197114fa1fcb7ae84ca742095eed9442088988ae74fa744e930e77" +dependencies = [ + "cfg-if 1.0.0", + "js-sys", + "libc", + "wasi 0.10.2+wasi-snapshot-preview1", + "wasm-bindgen", +] + +[[package]] +name = "ghash" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97304e4cd182c3846f7575ced3890c53012ce534ad9114046b0a9e00bb30a375" +dependencies = [ + "opaque-debug", + "polyval 0.4.5", +] + +[[package]] +name = "ghash" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1583cc1656d7839fd3732b80cf4f38850336cdb9b8ded1cd399ca62958de3c99" +dependencies = [ + "opaque-debug", + "polyval 0.5.3", +] + +[[package]] +name = "gimli" +version = "0.26.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78cc372d058dcf6d5ecd98510e7fbc9e5aec4d21de70f65fea8fecebcd881bd4" + +[[package]] +name = "gloo-timers" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4d12a7f4e95cfe710f1d624fb1210b7d961a5fb05c4fd942f4feab06e61f590e" +dependencies = [ + "futures-channel", + "futures-core", + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "group" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f15be54742789e36f03307c8fdf0621201e1345e94f1387282024178b5e9ec8c" +dependencies = [ + "ff", + "rand 0.7.3", + "rand_xorshift 0.2.0", +] + +[[package]] +name = "hashbrown" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e" +dependencies = [ + "ahash", +] + +[[package]] +name = "heck" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d621efb26863f0e9924c6ac577e8275e5e6b77455db64ffa6c65c904e9e132c" +dependencies = [ + "unicode-segmentation", +] + +[[package]] +name = "heck" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2540771e65fc8cb83cd6e8a237f70c319bd5c29f78ed1084ba5d50eeac86f7f9" + +[[package]] +name = "hermit-abi" +version = "0.1.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" +dependencies = [ + "libc", +] + +[[package]] +name = "hex" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" + +[[package]] +name = "hex_fmt" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b07f60793ff0a4d9cef0f18e63b5357e06209987153a64648c972c1e5aff336f" + +[[package]] +name = "hkdf" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51ab2f639c231793c5f6114bdb9bbe50a7dbbfcd7c7c6bd8475dec2d991e964f" +dependencies = [ + "digest 0.9.0", + "hmac 0.10.1", +] + +[[package]] +name = "hmac" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "126888268dcc288495a26bf004b38c5fdbb31682f992c84ceb046a1f0fe38840" +dependencies = [ + "crypto-mac 0.8.0", + "digest 0.9.0", +] + +[[package]] +name = "hmac" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1441c6b1e930e2817404b5046f1f989899143a12bf92de603b69f4e0aee1e15" +dependencies = [ + "crypto-mac 0.10.1", + "digest 0.9.0", +] + +[[package]] +name = "hmac-drbg" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "17ea0a1394df5b6574da6e0c1ade9e78868c9fb0a4e5ef4428e32da4676b85b1" +dependencies = [ + "digest 0.9.0", + "generic-array", + "hmac 0.8.1", +] + +[[package]] +name = "hostname" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c731c3e10504cc8ed35cfe2f1db4c9274c3d35fa486e3b31df46f068ef3e867" +dependencies = [ + "libc", + "match_cfg", + "winapi", +] + +[[package]] +name = "http" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "31f4c6746584866f0feabcc69893c5b51beef3831656a968ed7ae254cdc4fd03" +dependencies = [ + "bytes", + "fnv", + "itoa", +] + +[[package]] +name = "http-client" +version = "6.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea880b03c18a7e981d7fb3608b8904a98425d53c440758fcebf7d934aa56547c" +dependencies = [ + "async-trait", + "cfg-if 1.0.0", + "dashmap 4.0.2", + "http-types", + "log", +] + +[[package]] +name = "http-types" +version = "2.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e9b187a72d63adbfba487f48095306ac823049cb504ee195541e91c7775f5ad" +dependencies = [ + "anyhow", + "async-channel", + "async-std", + "base64 0.13.0", + "cookie", + "futures-lite", + "infer", + "pin-project-lite 0.2.8", + "rand 0.7.3", + "serde", + "serde_json", + "serde_qs", + "serde_urlencoded", + "url", +] + +[[package]] +name = "httparse" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9100414882e15fb7feccb4897e5f0ff0ff1ca7d1a86a23208ada4d7a18e6c6c4" + +[[package]] +name = "ident_case" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" + +[[package]] +name = "idna" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "418a0a6fab821475f634efe3ccc45c013f742efe03d853e8d3355d5cb850ecf8" +dependencies = [ + "matches", + "unicode-bidi", + "unicode-normalization", +] + +[[package]] +name = "if-addrs" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cbc0fa01ffc752e9dbc72818cdb072cd028b86be5e09dd04c5a643704fe101a9" +dependencies = [ + "libc", + "winapi", +] + +[[package]] +name = "if-watch" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae8f4a3c3d4c89351ca83e120c1c00b27df945d38e05695668c9d4b4f7bc52f3" +dependencies = [ + "async-io", + "core-foundation", + "fnv", + "futures", + "if-addrs", + "ipnet", + "log", + "rtnetlink", + "system-configuration", + "windows", +] + +[[package]] +name = "indenter" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce23b50ad8242c51a442f3ff322d56b02f08852c77e4c0b4d3fd684abc89c683" + +[[package]] +name = "indexmap" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282a6247722caba404c065016bbfa522806e51714c34f5dfc3e4a3a46fcb4223" +dependencies = [ + "autocfg", + "hashbrown", +] + +[[package]] +name = "infer" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "64e9829a50b42bb782c1df523f78d332fe371b10c661e78b7a3c34b0198e9fac" + +[[package]] +name = "instant" +version = "0.1.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" +dependencies = [ + "cfg-if 1.0.0", +] + +[[package]] +name = "ipconfig" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f7e2f18aece9709094573a9f24f483c4f65caa4298e2f7ae1b71cc65d853fad7" +dependencies = [ + "socket2 0.3.19", + "widestring", + "winapi", + "winreg", +] + +[[package]] +name = "ipnet" +version = "2.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68f2d64f2edebec4ce84ad108148e67e1064789bee435edc5b60ad398714a3a9" + +[[package]] +name = "itertools" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a9a9d19fa1e79b6215ff29b9d6880b706147f16e9b1dbb1e4e5947b5b02bc5e3" +dependencies = [ + "either", +] + +[[package]] +name = "itoa" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1aab8fc367588b89dcee83ab0fd66b72b50b72fa1904d7095045ace2b0c81c35" + +[[package]] +name = "js-sys" +version = "0.3.56" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a38fc24e30fd564ce974c02bf1d337caddff65be6cc4735a1f7eab22a7440f04" +dependencies = [ + "wasm-bindgen", +] + +[[package]] +name = "keccak" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67c21572b4949434e4fc1e1978b99c5f77064153c59d998bf13ecd96fb5ecba7" + +[[package]] +name = "kv-log-macro" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0de8b303297635ad57c9f5059fd9cee7a47f8e8daa09df0fcd07dd39fb22977f" +dependencies = [ + "log", +] + +[[package]] +name = "lazy_static" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" + +[[package]] +name = "libc" +version = "0.2.119" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bf2e165bb3457c8e098ea76f3e3bc9db55f87aa90d52d0e6be741470916aaa4" + +[[package]] +name = "libp2p" +version = "0.43.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e8570e25fa03d4385405dbeaf540ba00e3ee50942f03d84e1a8928a029f35f9" +dependencies = [ + "atomic", + "bytes", + "futures", + "futures-timer", + "getrandom 0.2.5", + "instant", + "lazy_static", + "libp2p-autonat", + "libp2p-core", + "libp2p-deflate", + "libp2p-dns", + "libp2p-floodsub", + "libp2p-gossipsub", + "libp2p-identify", + "libp2p-kad", + "libp2p-mdns", + "libp2p-metrics", + "libp2p-mplex", + "libp2p-noise", + "libp2p-ping", + "libp2p-plaintext", + "libp2p-pnet", + "libp2p-relay", + "libp2p-rendezvous", + "libp2p-request-response", + "libp2p-swarm", + "libp2p-swarm-derive", + "libp2p-tcp", + "libp2p-uds", + "libp2p-wasm-ext", + "libp2p-websocket", + "libp2p-yamux", + "multiaddr", + "parking_lot 0.12.0", + "pin-project 1.0.10", + "rand 0.7.3", + "smallvec", +] + +[[package]] +name = "libp2p-autonat" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd6314084638e09e4162a5c6d0c1ba859f5d5f8a045ca015f7c95325e4b7c230" +dependencies = [ + "async-trait", + "futures", + "futures-timer", + "instant", + "libp2p-core", + "libp2p-request-response", + "libp2p-swarm", + "log", + "prost", + "prost-build", + "rand 0.8.5", +] + +[[package]] +name = "libp2p-core" +version = "0.32.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9164ec41455856e8187addc870bb4fe1ea2ee28e1a9244831d449a2429b32c1a" +dependencies = [ + "asn1_der", + "bs58", + "ed25519-dalek", + "either", + "fnv", + "futures", + "futures-timer", + "instant", + "lazy_static", + "libsecp256k1", + "log", + "multiaddr", + "multihash", + "multistream-select", + "parking_lot 0.12.0", + "pin-project 1.0.10", + "prost", + "prost-build", + "rand 0.8.5", + "ring", + "rw-stream-sink", + "serde", + "sha2 0.10.2", + "smallvec", + "thiserror", + "unsigned-varint", + "void", + "zeroize", +] + +[[package]] +name = "libp2p-deflate" +version = "0.32.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6b1d37f042f748e224f04785d0e987ae09a2aa518d6401d82d412dad83e360ed" +dependencies = [ + "flate2", + "futures", + "libp2p-core", +] + +[[package]] +name = "libp2p-dns" +version = "0.32.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7838647d33978b77f943687412f4a39e74234c8342cbfdad14282b465b272cb4" +dependencies = [ + "async-std-resolver", + "futures", + "libp2p-core", + "log", + "smallvec", + "trust-dns-resolver", +] + +[[package]] +name = "libp2p-floodsub" +version = "0.34.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df0b7d6c3fa2ead77a5bbeff580bd7507efcc9d7fa9d0caf873795b097d385c0" +dependencies = [ + "cuckoofilter", + "fnv", + "futures", + "libp2p-core", + "libp2p-swarm", + "log", + "prost", + "prost-build", + "rand 0.7.3", + "smallvec", +] + +[[package]] +name = "libp2p-gossipsub" +version = "0.36.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f62943fba0b0dae02b87868620c52a581c54ec9fb04b5e195cf20313fc510c3" +dependencies = [ + "asynchronous-codec", + "base64 0.13.0", + "byteorder", + "bytes", + "fnv", + "futures", + "hex_fmt", + "instant", + "libp2p-core", + "libp2p-swarm", + "log", + "prometheus-client", + "prost", + "prost-build", + "rand 0.7.3", + "regex", + "serde", + "sha2 0.10.2", + "smallvec", + "unsigned-varint", + "wasm-timer", +] + +[[package]] +name = "libp2p-identify" +version = "0.34.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f219b4d4660fe3a04bf5fe6b5970902b7c1918e25b2536be8c70efc480f88f8" +dependencies = [ + "futures", + "futures-timer", + "libp2p-core", + "libp2p-swarm", + "log", + "lru", + "prost", + "prost-build", + "smallvec", +] + +[[package]] +name = "libp2p-kad" +version = "0.35.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aead5ee2322a7b825c7633065370909c8383046f955cda5b56797e6904db7a72" +dependencies = [ + "arrayvec 0.5.2", + "asynchronous-codec", + "bytes", + "either", + "fnv", + "futures", + "futures-timer", + "instant", + "libp2p-core", + "libp2p-swarm", + "log", + "prost", + "prost-build", + "rand 0.7.3", + "serde", + "sha2 0.10.2", + "smallvec", + "thiserror", + "uint", + "unsigned-varint", + "void", +] + +[[package]] +name = "libp2p-mdns" +version = "0.35.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "54d1914576978e5f3b15ac99e2cda9b56471ce64f1cfc7c2b09ac0cee147175e" +dependencies = [ + "async-io", + "data-encoding", + "dns-parser", + "futures", + "if-watch", + "lazy_static", + "libp2p-core", + "libp2p-swarm", + "log", + "rand 0.8.5", + "smallvec", + "socket2 0.4.4", + "void", +] + +[[package]] +name = "libp2p-metrics" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d29e4e5e4c5aa567fe1ee3133afe088dc2d2fd104e20c5c2c5c2649f75129677" +dependencies = [ + "libp2p-core", + "libp2p-gossipsub", + "libp2p-identify", + "libp2p-kad", + "libp2p-ping", + "libp2p-relay", + "libp2p-swarm", + "prometheus-client", +] + +[[package]] +name = "libp2p-mplex" +version = "0.32.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "442eb0c9fff0bf22a34f015724b4143ce01877e079ed0963c722d94c07c72160" +dependencies = [ + "asynchronous-codec", + "bytes", + "futures", + "libp2p-core", + "log", + "nohash-hasher", + "parking_lot 0.12.0", + "rand 0.7.3", + "smallvec", + "unsigned-varint", +] + +[[package]] +name = "libp2p-noise" +version = "0.35.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9dd7e0c94051cda67123be68cf6b65211ba3dde7277be9068412de3e7ffd63ef" +dependencies = [ + "bytes", + "curve25519-dalek 3.2.1", + "futures", + "lazy_static", + "libp2p-core", + "log", + "prost", + "prost-build", + "rand 0.8.5", + "sha2 0.10.2", + "snow", + "static_assertions", + "x25519-dalek", + "zeroize", +] + +[[package]] +name = "libp2p-ping" +version = "0.34.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ab44a12d372d6abdd326c468c1d5b002be06fbd923c5a799d6a9d3b36646ca3" +dependencies = [ + "futures", + "futures-timer", + "instant", + "libp2p-core", + "libp2p-swarm", + "log", + "rand 0.7.3", + "void", +] + +[[package]] +name = "libp2p-plaintext" +version = "0.32.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "962c0fb0e7212fb96a69b87f2d09bcefd317935239bdc79cda900e7a8897a3fe" +dependencies = [ + "asynchronous-codec", + "bytes", + "futures", + "libp2p-core", + "log", + "prost", + "prost-build", + "unsigned-varint", + "void", +] + +[[package]] +name = "libp2p-pnet" +version = "0.22.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f15be54742789e36f03307c8fdf0621201e1345e94f1387282024178b5e9ec8c" +checksum = "0f1a458bbda880107b5b36fcb9b5a1ef0c329685da0e203ed692a8ebe64cc92c" dependencies = [ - "ff", + "futures", + "log", + "pin-project 1.0.10", "rand 0.7.3", - "rand_xorshift 0.2.0", + "salsa20", + "sha3", ] [[package]] -name = "heck" -version = "0.3.3" +name = "libp2p-relay" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d621efb26863f0e9924c6ac577e8275e5e6b77455db64ffa6c65c904e9e132c" +checksum = "517be90a2ce60b6c3bdfe88f34cc789c61dafe6f694a7b45e644af7353880fa3" dependencies = [ - "unicode-segmentation", + "asynchronous-codec", + "bytes", + "either", + "futures", + "futures-timer", + "instant", + "libp2p-core", + "libp2p-swarm", + "log", + "pin-project 1.0.10", + "prost", + "prost-build", + "rand 0.8.5", + "smallvec", + "static_assertions", + "thiserror", + "unsigned-varint", + "void", ] [[package]] -name = "hermit-abi" -version = "0.1.19" +name = "libp2p-rendezvous" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" +checksum = "597e4a022dd2e168ce1218faf6b3aead5c427fb828eb4f982cef7c40d4b7f49e" +dependencies = [ + "asynchronous-codec", + "bimap", + "futures", + "futures-timer", + "instant", + "libp2p-core", + "libp2p-swarm", + "log", + "prost", + "prost-build", + "rand 0.8.5", + "sha2 0.10.2", + "thiserror", + "unsigned-varint", + "void", +] + +[[package]] +name = "libp2p-request-response" +version = "0.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "12388a73626d1727524069cce0bb05a9c428581de435278a070c55ae27cc7e73" +dependencies = [ + "async-trait", + "bytes", + "futures", + "instant", + "libp2p-core", + "libp2p-swarm", + "log", + "rand 0.7.3", + "smallvec", + "unsigned-varint", +] + +[[package]] +name = "libp2p-swarm" +version = "0.34.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53ab2d4eb8ef2966b10fdf859245cdd231026df76d3c6ed2cf9e418a8f688ec9" +dependencies = [ + "either", + "fnv", + "futures", + "futures-timer", + "instant", + "libp2p-core", + "log", + "pin-project 1.0.10", + "rand 0.7.3", + "smallvec", + "thiserror", + "void", +] + +[[package]] +name = "libp2p-swarm-derive" +version = "0.27.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4b8153a6472e84ec888ef2bf21deafe8d4214e811f0f162abbf07156c27f8fa8" +dependencies = [ + "quote", + "syn", +] + +[[package]] +name = "libp2p-tcp" +version = "0.32.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "193447aa729c85aac2376828df76d171c1a589c9e6b58fcc7f9d9a020734122c" dependencies = [ + "async-io", + "futures", + "futures-timer", + "if-watch", + "ipnet", "libc", + "libp2p-core", + "log", + "socket2 0.4.4", ] [[package]] -name = "hex_fmt" +name = "libp2p-uds" +version = "0.32.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24bdab114f7f2701757d6541266e1131b429bbae382008f207f2114ee4222dcb" +dependencies = [ + "async-std", + "futures", + "libp2p-core", + "log", +] + +[[package]] +name = "libp2p-wasm-ext" +version = "0.32.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4f6ea0f84a967ef59a16083f222c18115ae2e91db69809dce275df62e101b279" +dependencies = [ + "futures", + "js-sys", + "libp2p-core", + "parity-send-wrapper", + "wasm-bindgen", + "wasm-bindgen-futures", +] + +[[package]] +name = "libp2p-websocket" +version = "0.34.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c932834c3754501c368d1bf3d0fb458487a642b90fc25df082a3a2f3d3b32e37" +dependencies = [ + "either", + "futures", + "futures-rustls", + "libp2p-core", + "log", + "quicksink", + "rw-stream-sink", + "soketto", + "url", + "webpki-roots", +] + +[[package]] +name = "libp2p-yamux" +version = "0.36.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be902ebd89193cd020e89e89107726a38cfc0d16d18f613f4a37d046e92c7517" +dependencies = [ + "futures", + "libp2p-core", + "parking_lot 0.12.0", + "thiserror", + "yamux", +] + +[[package]] +name = "libsecp256k1" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0452aac8bab02242429380e9b2f94ea20cea2b37e2c1777a1358799bbe97f37" +dependencies = [ + "arrayref", + "base64 0.13.0", + "digest 0.9.0", + "hmac-drbg", + "libsecp256k1-core", + "libsecp256k1-gen-ecmult", + "libsecp256k1-gen-genmult", + "rand 0.8.5", + "serde", + "sha2 0.9.9", + "typenum", +] + +[[package]] +name = "libsecp256k1-core" version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b07f60793ff0a4d9cef0f18e63b5357e06209987153a64648c972c1e5aff336f" +checksum = "5be9b9bb642d8522a44d533eab56c16c738301965504753b03ad1de3425d5451" +dependencies = [ + "crunchy", + "digest 0.9.0", + "subtle", +] [[package]] -name = "http" -version = "0.2.6" +name = "libsecp256k1-gen-ecmult" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "31f4c6746584866f0feabcc69893c5b51beef3831656a968ed7ae254cdc4fd03" +checksum = "3038c808c55c87e8a172643a7d87187fc6c4174468159cb3090659d55bcb4809" dependencies = [ - "bytes", - "fnv", - "itoa", + "libsecp256k1-core", ] [[package]] -name = "httparse" -version = "1.6.0" +name = "libsecp256k1-gen-genmult" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9100414882e15fb7feccb4897e5f0ff0ff1ca7d1a86a23208ada4d7a18e6c6c4" +checksum = "3db8d6ba2cec9eacc40e6e8ccc98931840301f1006e95647ceb2dd5c3aa06f7c" +dependencies = [ + "libsecp256k1-core", +] [[package]] -name = "idna" -version = "0.2.3" +name = "libz-sys" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "418a0a6fab821475f634efe3ccc45c013f742efe03d853e8d3355d5cb850ecf8" +checksum = "de5435b8549c16d423ed0c03dbaafe57cf6c3344744f1242520d59c9d8ecec66" dependencies = [ - "matches", - "unicode-bidi", - "unicode-normalization", + "cc", + "pkg-config", + "vcpkg", ] [[package]] -name = "instant" -version = "0.1.12" +name = "linked-hash-map" +version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" +checksum = "7fb9b38af92608140b86b693604b9ffcc5824240a484d1ecd4795bacb2fe88f3" + +[[package]] +name = "lock_api" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88943dd7ef4a2e5a4bfa2753aaab3013e34ce2533d1996fb18ef591e315e2b3b" +dependencies = [ + "scopeguard", +] + +[[package]] +name = "log" +version = "0.4.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51b9bbe6c47d51fc3e1a9b945965946b4c44142ab8792c50835a980d362c2710" +dependencies = [ + "cfg-if 1.0.0", + "value-bag", +] + +[[package]] +name = "lru" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fcb87f3080f6d1d69e8c564c0fcfde1d7aa8cc451ce40cae89479111f03bc0eb" +dependencies = [ + "hashbrown", +] + +[[package]] +name = "lru-cache" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "31e24f1ad8321ca0e8a1e0ac13f23cb668e6f5466c2c57319f6a5cf1cc8e3b1c" +dependencies = [ + "linked-hash-map", +] + +[[package]] +name = "match_cfg" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ffbee8634e0d45d258acb448e7eaab3fce7a0a467395d4d9f228e3c1f01fb2e4" + +[[package]] +name = "matchers" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8263075bb86c5a1b1427b5ae862e8889656f126e9f77c484496e8b47cf5c5558" +dependencies = [ + "regex-automata", +] + +[[package]] +name = "matches" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a3e378b66a060d48947b590737b30a1be76706c8dd7b8ba0f2fe3989c68a853f" + +[[package]] +name = "memchr" +version = "2.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "308cc39be01b73d0d18f82a0e7b2a3df85245f84af96fdddc5d202d27e47b86a" + +[[package]] +name = "memoffset" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5aa361d4faea93603064a027415f07bd8e1d5c88c9fbf68bf56a285428fd79ce" +dependencies = [ + "autocfg", +] + +[[package]] +name = "miniz_oxide" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a92518e98c078586bc6c934028adcca4c92a53d6a958196de835170a01d84e4b" +dependencies = [ + "adler", + "autocfg", +] + +[[package]] +name = "mio" +version = "0.7.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8067b404fe97c70829f082dec8bcf4f71225d7eaea1d8645349cb76fa06205cc" +dependencies = [ + "libc", + "log", + "miow", + "ntapi", + "winapi", +] + +[[package]] +name = "miow" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9f1c5b025cda876f66ef43a113f91ebc9f4ccef34843000e0adf6ebbab84e21" +dependencies = [ + "winapi", +] + +[[package]] +name = "multiaddr" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c580bfdd8803cce319b047d239559a22f809094aaea4ac13902a1fdcfcd4261" +dependencies = [ + "arrayref", + "bs58", + "byteorder", + "data-encoding", + "multihash", + "percent-encoding", + "serde", + "static_assertions", + "unsigned-varint", + "url", +] + +[[package]] +name = "multihash" +version = "0.16.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7392bffd88bc0c4f8297e36a777ab9f80b7127409c4a1acb8fee99c9f27addcd" +dependencies = [ + "core2", + "digest 0.10.3", + "multihash-derive", + "serde", + "serde-big-array", + "sha2 0.10.2", + "unsigned-varint", +] + +[[package]] +name = "multihash-derive" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc076939022111618a5026d3be019fd8b366e76314538ff9a1b59ffbcbf98bcd" dependencies = [ - "cfg-if", + "proc-macro-crate", + "proc-macro-error", + "proc-macro2", + "quote", + "syn", + "synstructure", ] [[package]] -name = "itoa" -version = "1.0.1" +name = "multimap" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1aab8fc367588b89dcee83ab0fd66b72b50b72fa1904d7095045ace2b0c81c35" +checksum = "e5ce46fe64a9d73be07dcbe690a38ce1b293be448fd8ce1e6c1b8062c9f72c6a" [[package]] -name = "js-sys" -version = "0.3.56" +name = "multistream-select" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a38fc24e30fd564ce974c02bf1d337caddff65be6cc4735a1f7eab22a7440f04" +checksum = "363a84be6453a70e63513660f4894ef815daf88e3356bffcda9ca27d810ce83b" dependencies = [ - "wasm-bindgen", + "bytes", + "futures", + "log", + "pin-project 1.0.10", + "smallvec", + "unsigned-varint", ] [[package]] -name = "kv-log-macro" -version = "1.0.7" +name = "nanorand" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0de8b303297635ad57c9f5059fd9cee7a47f8e8daa09df0fcd07dd39fb22977f" +checksum = "729eb334247daa1803e0a094d0a5c55711b85571179f5ec6e53eccfdf7008958" dependencies = [ - "log", + "getrandom 0.2.5", ] [[package]] -name = "lazy_static" -version = "1.4.0" +name = "netlink-packet-core" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" +checksum = "345b8ab5bd4e71a2986663e88c56856699d060e78e152e6e9d7966fcd5491297" +dependencies = [ + "anyhow", + "byteorder", + "libc", + "netlink-packet-utils", +] [[package]] -name = "libc" -version = "0.2.119" +name = "netlink-packet-route" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1bf2e165bb3457c8e098ea76f3e3bc9db55f87aa90d52d0e6be741470916aaa4" +checksum = "733ea73609acfd7fa7ddadfb7bf709b0471668c456ad9513685af543a06342b2" +dependencies = [ + "anyhow", + "bitflags", + "byteorder", + "libc", + "netlink-packet-core", + "netlink-packet-utils", +] [[package]] -name = "lock_api" -version = "0.4.6" +name = "netlink-packet-utils" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88943dd7ef4a2e5a4bfa2753aaab3013e34ce2533d1996fb18ef591e315e2b3b" +checksum = "25af9cf0dc55498b7bd94a1508af7a78706aa0ab715a73c5169273e03c84845e" dependencies = [ - "scopeguard", + "anyhow", + "byteorder", + "paste", + "thiserror", ] [[package]] -name = "log" -version = "0.4.14" +name = "netlink-proto" +version = "0.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "51b9bbe6c47d51fc3e1a9b945965946b4c44142ab8792c50835a980d362c2710" +checksum = "ef8785b8141e8432aa45fceb922a7e876d7da3fad37fa7e7ec702ace3aa0826b" dependencies = [ - "cfg-if", - "value-bag", + "bytes", + "futures", + "log", + "netlink-packet-core", + "netlink-sys", + "tokio", ] [[package]] -name = "matchers" -version = "0.1.0" +name = "netlink-sys" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8263075bb86c5a1b1427b5ae862e8889656f126e9f77c484496e8b47cf5c5558" +checksum = "3e4c9f9547a08241bee7b6558b9b98e1f290d187de8b7cfca2bbb4937bcaa8f8" dependencies = [ - "regex-automata", + "async-io", + "bytes", + "futures", + "libc", + "log", ] [[package]] -name = "matches" -version = "0.1.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3e378b66a060d48947b590737b30a1be76706c8dd7b8ba0f2fe3989c68a853f" +name = "networking-demo" +version = "0.0.0" +dependencies = [ + "async-std", + "async-trait", + "bincode", + "blake3 1.3.1", + "color-eyre", + "crossterm 0.23.0", + "derive_builder", + "flume", + "futures", + "libp2p", + "parking_lot 0.12.0", + "rand 0.8.5", + "serde", + "serde_json", + "snafu", + "structopt", + "tide", + "tracing", + "tracing-error", + "tracing-subscriber", + "tui", +] [[package]] -name = "memchr" -version = "2.4.1" +name = "nix" +version = "0.22.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "308cc39be01b73d0d18f82a0e7b2a3df85245f84af96fdddc5d202d27e47b86a" +checksum = "e4916f159ed8e5de0082076562152a76b7a1f64a01fd9d1e0fea002c37624faf" +dependencies = [ + "bitflags", + "cc", + "cfg-if 1.0.0", + "libc", + "memoffset", +] [[package]] -name = "miniz_oxide" -version = "0.4.4" +name = "nohash-hasher" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a92518e98c078586bc6c934028adcca4c92a53d6a958196de835170a01d84e4b" -dependencies = [ - "adler", - "autocfg", -] +checksum = "2bf50223579dc7cdcfb3bfcacf7069ff68243f8c363f62ffa99cf000a6b9c451" [[package]] -name = "nanorand" -version = "0.6.1" +name = "ntapi" +version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "729eb334247daa1803e0a094d0a5c55711b85571179f5ec6e53eccfdf7008958" +checksum = "c28774a7fd2fbb4f0babd8237ce554b73af68021b5f695a3cebd6c59bac0980f" dependencies = [ - "getrandom 0.2.4", + "winapi", ] [[package]] @@ -1044,9 +2858,9 @@ dependencies = [ [[package]] name = "once_cell" -version = "1.9.0" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da32515d9f6e6e489d7bc9d84c71b060db7247dc035bbe44eac88cf87486d8d5" +checksum = "87f3e037eac156d1775da914196f0f37741a274155e34a0b7e427c35d2a2ecb9" [[package]] name = "opaque-debug" @@ -1054,6 +2868,21 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" +[[package]] +name = "owning_ref" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ff55baddef9e4ad00f88b6c743a2a8062d4c6ade126c2a528644b8e444d52ce" +dependencies = [ + "stable_deref_trait", +] + +[[package]] +name = "owo-colors" +version = "3.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "20448fd678ec04e6ea15bbe0476874af65e98a01515d667aa49f1434dc44ebf4" + [[package]] name = "pairing" version = "0.16.0" @@ -1066,12 +2895,29 @@ dependencies = [ "rand_core 0.5.1", ] +[[package]] +name = "parity-send-wrapper" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa9777aa91b8ad9dd5aaa04a9b6bcb02c7f1deb952fca5a66034d5e63afc5c6f" + [[package]] name = "parking" version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "427c3892f9e783d91cc128285287e70a59e206ca452770ece88a76f7a3eddd72" +[[package]] +name = "parking_lot" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d17b78036a60663b797adeaee46f5c9dfebb86948d1255007a1d6be0271ff99" +dependencies = [ + "instant", + "lock_api", + "parking_lot_core 0.8.5", +] + [[package]] name = "parking_lot" version = "0.12.0" @@ -1079,7 +2925,21 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "87f5ec2493a61ac0506c0f4199f99070cbe83857b0337006a30f3e6719b8ef58" dependencies = [ "lock_api", - "parking_lot_core", + "parking_lot_core 0.9.1", +] + +[[package]] +name = "parking_lot_core" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d76e8e1493bcac0d2766c42737f34458f1c8c50c0d23bcb24ea953affb273216" +dependencies = [ + "cfg-if 1.0.0", + "instant", + "libc", + "redox_syscall", + "smallvec", + "winapi", ] [[package]] @@ -1088,7 +2948,7 @@ version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "28141e0cc4143da2443301914478dc976a61ffdb3f043058310c70df2fed8954" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", "libc", "redox_syscall", "smallvec", @@ -1116,6 +2976,16 @@ dependencies = [ "ucd-trie", ] +[[package]] +name = "petgraph" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a13a2fa9d0b63e5f22328828741e523766fff0ee9e779316902290dff3f824f" +dependencies = [ + "fixedbitset", + "indexmap", +] + [[package]] name = "phaselock" version = "0.0.6" @@ -1125,9 +2995,9 @@ dependencies = [ "async-std", "async-tungstenite", "bincode", - "blake3", + "blake3 1.3.1", "byteorder", - "dashmap", + "dashmap 5.1.0", "flume", "futures", "hex_fmt", @@ -1156,7 +3026,7 @@ dependencies = [ "async-std", "async-tungstenite", "bincode", - "blake3", + "blake3 1.3.1", "futures", "hex_fmt", "rand 0.7.3", @@ -1167,13 +3037,33 @@ dependencies = [ "threshold_crypto", ] +[[package]] +name = "pin-project" +version = "0.4.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9615c18d31137579e9ff063499264ddc1278e7b1982757ebc111028c4d1dc909" +dependencies = [ + "pin-project-internal 0.4.29", +] + [[package]] name = "pin-project" version = "1.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "58ad3879ad3baf4e44784bc6a718a8698867bb991f8ce24d1bcbe2cfb4c3a75e" dependencies = [ - "pin-project-internal", + "pin-project-internal 1.0.10", +] + +[[package]] +name = "pin-project-internal" +version = "0.4.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "044964427019eed9d49d9d5bbce6047ef18f37100ea400912a9fa4a3523ab12a" +dependencies = [ + "proc-macro2", + "quote", + "syn", ] [[package]] @@ -1187,6 +3077,12 @@ dependencies = [ "syn", ] +[[package]] +name = "pin-project-lite" +version = "0.1.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "257b64915a082f7811703966789728173279bdebb956b143dbcd23f6f970a777" + [[package]] name = "pin-project-lite" version = "0.2.8" @@ -1199,25 +3095,75 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" +[[package]] +name = "pkg-config" +version = "0.3.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "58893f751c9b0412871a09abd62ecd2a00298c6c83befa223ef98c52aef40cbe" + [[package]] name = "polling" version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "685404d509889fade3e86fe3a5803bca2ec09b0c0778d5ada6ec8bf7a8de5259" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", "libc", "log", "wepoll-ffi", "winapi", ] +[[package]] +name = "poly1305" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "048aeb476be11a4b6ca432ca569e375810de9294ae78f4774e78ea98a9246ede" +dependencies = [ + "cpufeatures", + "opaque-debug", + "universal-hash", +] + +[[package]] +name = "polyval" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eebcc4aa140b9abd2bc40d9c3f7ccec842679cd79045ac3a7ac698c1a064b7cd" +dependencies = [ + "cpuid-bool", + "opaque-debug", + "universal-hash", +] + +[[package]] +name = "polyval" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8419d2b623c7c0896ff2d5d96e2cb4ede590fed28fcc34934f4c33c036e620a1" +dependencies = [ + "cfg-if 1.0.0", + "cpufeatures", + "opaque-debug", + "universal-hash", +] + [[package]] name = "ppv-lite86" version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "eb9f9e6e233e5c4a35559a617bf40a4ec447db2e84c20b55a6f83167b7e57872" +[[package]] +name = "proc-macro-crate" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e17d47ce914bf4de440332250b0edd23ce48c005f59fab39d3335866b114f11a" +dependencies = [ + "thiserror", + "toml", +] + [[package]] name = "proc-macro-error" version = "1.0.4" @@ -1242,6 +3188,12 @@ dependencies = [ "version_check", ] +[[package]] +name = "proc-macro-hack" +version = "0.5.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dbf0c48bc1d91375ae5c3cd81e3722dff1abcf81a30960240640d223f59fe0e5" + [[package]] name = "proc-macro2" version = "1.0.36" @@ -1251,6 +3203,29 @@ dependencies = [ "unicode-xid", ] +[[package]] +name = "prometheus-client" +version = "0.15.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c9a896938cc6018c64f279888b8c7559d3725210d5db9a3a1ee6bc7188d51d34" +dependencies = [ + "dtoa", + "itoa", + "owning_ref", + "prometheus-client-derive-text-encode", +] + +[[package]] +name = "prometheus-client-derive-text-encode" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8e12d01b9d66ad9eb4529c57666b6263fc1993cb30261d83ead658fdd932652" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "proptest" version = "1.0.0" @@ -1271,6 +3246,59 @@ dependencies = [ "tempfile", ] +[[package]] +name = "prost" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "444879275cb4fd84958b1a1d5420d15e6fcf7c235fe47f053c9c2a80aceb6001" +dependencies = [ + "bytes", + "prost-derive", +] + +[[package]] +name = "prost-build" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62941722fb675d463659e49c4f3fe1fe792ff24fe5bbaa9c08cd3b98a1c354f5" +dependencies = [ + "bytes", + "heck 0.3.3", + "itertools", + "lazy_static", + "log", + "multimap", + "petgraph", + "prost", + "prost-types", + "regex", + "tempfile", + "which", +] + +[[package]] +name = "prost-derive" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f9cc1a3263e07e0bf68e96268f37665207b49560d98739662cdfaae215c720fe" +dependencies = [ + "anyhow", + "itertools", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "prost-types" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "534b7a0e836e3c482d2693070f982e39e7611da9695d4d1f5a4b186b51faef0a" +dependencies = [ + "bytes", + "prost", +] + [[package]] name = "quick-error" version = "1.2.3" @@ -1283,6 +3311,17 @@ version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a993555f31e5a609f617c12db6250dedcac1b0a85076912c436e6fc9b2c8e6a3" +[[package]] +name = "quicksink" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77de3c815e5a160b1539c6592796801df2043ae35e123b46d73380cfa57af858" +dependencies = [ + "futures-core", + "futures-sink", + "pin-project-lite 0.1.12", +] + [[package]] name = "quote" version = "1.0.15" @@ -1351,7 +3390,7 @@ version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d34f1408f55294453790c48b2f1ebbb1c5b4b7563eb1f418bcfcfdbb06ebb4e7" dependencies = [ - "getrandom 0.2.4", + "getrandom 0.2.5", ] [[package]] @@ -1392,9 +3431,9 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.2.10" +version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8383f39639269cde97d255a32bdb68c047337295414940c68bdd30c2e13203ff" +checksum = "8380fe0152551244f0747b1bf41737e0f8a74f97a14ccefd1148187271634f3c" dependencies = [ "bitflags", ] @@ -1405,6 +3444,8 @@ version = "1.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d07a8629359eb56f1e2fb1652bb04212c072a87ba68546a04065d525673ac461" dependencies = [ + "aho-corasick", + "memchr", "regex-syntax", ] @@ -1432,19 +3473,95 @@ dependencies = [ "winapi", ] +[[package]] +name = "resolv-conf" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52e44394d2086d010551b14b53b1f24e31647570cd1deb0379e2c21b329aba00" +dependencies = [ + "hostname", + "quick-error 1.2.3", +] + +[[package]] +name = "ring" +version = "0.16.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3053cf52e236a3ed746dfc745aa9cacf1b791d846bdaf412f60a8d7d6e17c8fc" +dependencies = [ + "cc", + "libc", + "once_cell", + "spin 0.5.2", + "untrusted", + "web-sys", + "winapi", +] + +[[package]] +name = "route-recognizer" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56770675ebc04927ded3e60633437841581c285dc6236109ea25fbf3beb7b59e" + +[[package]] +name = "rtnetlink" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f54290e54521dac3de4149d83ddf9f62a359b3cc93bcb494a794a41e6f4744b" +dependencies = [ + "async-global-executor", + "futures", + "log", + "netlink-packet-route", + "netlink-proto", + "nix", + "thiserror", +] + [[package]] name = "rustc-demangle" version = "0.1.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7ef03e0a2b150c7a90d01faf6254c9c48a41e95fb2a8c2ac1c6f0d2b9aefc342" +[[package]] +name = "rustc_version" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" +dependencies = [ + "semver 0.9.0", +] + [[package]] name = "rustc_version" version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f0dfe2087c51c460008730de8b57e6a320782fbfb312e1f4d520e6c6fae155ee" dependencies = [ - "semver", + "semver 0.11.0", +] + +[[package]] +name = "rustc_version" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" +dependencies = [ + "semver 1.0.6", +] + +[[package]] +name = "rustls" +version = "0.20.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fbfeb8d0ddb84706bc597a5574ab8912817c52a397f819e5b614e2265206921" +dependencies = [ + "log", + "ring", + "sct", + "webpki", ] [[package]] @@ -1459,27 +3576,78 @@ dependencies = [ "wait-timeout", ] +[[package]] +name = "rw-stream-sink" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4da5fcb054c46f5a5dff833b129285a93d3f0179531735e6c866e8cc307d2020" +dependencies = [ + "futures", + "pin-project 0.4.29", + "static_assertions", +] + [[package]] name = "ryu" version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "73b4b750c782965c211b42f022f59af1fbceabdd026623714f104152f1ec149f" +[[package]] +name = "salsa20" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c0fbb5f676da676c260ba276a8f43a8dc67cf02d1438423aeb1c677a7212686" +dependencies = [ + "cipher 0.3.0", +] + [[package]] name = "scopeguard" version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" +[[package]] +name = "sct" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d53dcdb7c9f8158937a7981b48accfd39a43af418591a5d008c7b22b5e1b7ca4" +dependencies = [ + "ring", + "untrusted", +] + +[[package]] +name = "semver" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" +dependencies = [ + "semver-parser 0.7.0", +] + [[package]] name = "semver" version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f301af10236f6df4160f7c3f04eec6dbc70ace82d23326abad5edee88801c6b6" dependencies = [ - "semver-parser", + "semver-parser 0.10.2", ] +[[package]] +name = "semver" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4a3381e03edd24287172047536f20cabde766e2cd3e65e6b00fb3af51c4f38d" + +[[package]] +name = "semver-parser" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" + [[package]] name = "semver-parser" version = "0.10.2" @@ -1498,6 +3666,16 @@ dependencies = [ "serde_derive", ] +[[package]] +name = "serde-big-array" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "18b20e7752957bbe9661cff4e0bb04d183d0948cdab2ea58cdb9df36a61dfe62" +dependencies = [ + "serde", + "serde_derive", +] + [[package]] name = "serde_bytes" version = "0.11.5" @@ -1529,6 +3707,29 @@ dependencies = [ "serde", ] +[[package]] +name = "serde_qs" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7715380eec75f029a4ef7de39a9200e0a63823176b759d055b613f5a87df6a6" +dependencies = [ + "percent-encoding", + "serde", + "thiserror", +] + +[[package]] +name = "serde_urlencoded" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" +dependencies = [ + "form_urlencoded", + "itoa", + "ryu", + "serde", +] + [[package]] name = "sha-1" version = "0.9.8" @@ -1536,9 +3737,60 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "99cd6713db3cf16b6c84e06321e049a9b9f699826e16096d23bbcc44d15d51a6" dependencies = [ "block-buffer 0.9.0", - "cfg-if", + "cfg-if 1.0.0", + "cpufeatures", + "digest 0.9.0", + "opaque-debug", +] + +[[package]] +name = "sha1" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1da05c97445caa12d05e848c4a4fcbbea29e748ac28f7e80e9b010392063770" +dependencies = [ + "sha1_smol", +] + +[[package]] +name = "sha1_smol" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae1a47186c03a32177042e55dbc5fd5aee900b8e0069a8d70fba96a9375cd012" + +[[package]] +name = "sha2" +version = "0.9.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4d58a1e1bf39749807d89cf2d98ac2dfa0ff1cb3faa38fbb64dd88ac8013d800" +dependencies = [ + "block-buffer 0.9.0", + "cfg-if 1.0.0", + "cpufeatures", + "digest 0.9.0", + "opaque-debug", +] + +[[package]] +name = "sha2" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55deaec60f81eefe3cce0dc50bda92d6d8e88f2a27df7c5033b42afeb1ed2676" +dependencies = [ + "cfg-if 1.0.0", "cpufeatures", + "digest 0.10.3", +] + +[[package]] +name = "sha3" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f81199417d4e5de3f04b1e871023acea7389672c4135918f05aa9cbf2f2fa809" +dependencies = [ + "block-buffer 0.9.0", "digest 0.9.0", + "keccak", "opaque-debug", ] @@ -1561,6 +3813,17 @@ dependencies = [ "signal-hook-registry", ] +[[package]] +name = "signal-hook-mio" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29fd5867f1c4f2c5be079aee7a2adf1152ebb04a4bc4d341f504b7dece607ed4" +dependencies = [ + "libc", + "mio", + "signal-hook", +] + [[package]] name = "signal-hook-registry" version = "1.4.0" @@ -1570,6 +3833,21 @@ dependencies = [ "libc", ] +[[package]] +name = "signature" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f054c6c1a6e95179d6f23ed974060dcefb2d9388bb7256900badad682c499de4" + +[[package]] +name = "simple-mutex" +version = "1.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38aabbeafa6f6dead8cebf246fe9fae1f9215c8d29b3a69f93bd62a9e4a3dcd6" +dependencies = [ + "event-listener", +] + [[package]] name = "slab" version = "0.4.5" @@ -1577,52 +3855,172 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9def91fd1e018fe007022791f865d0ccc9b3a0d5001e01aabb8b40e46000afb5" [[package]] -name = "smallvec" -version = "1.8.0" +name = "smallvec" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2dd574626839106c320a323308629dcb1acfc96e32a8cba364ddc61ac23ee83" + +[[package]] +name = "snafu" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2eba135d2c579aa65364522eb78590cdf703176ef71ad4c32b00f58f7afb2df5" +dependencies = [ + "backtrace", + "doc-comment", + "snafu-derive", +] + +[[package]] +name = "snafu-derive" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a7fe9b0669ef117c5cabc5549638528f36771f058ff977d7689deb517833a75" +dependencies = [ + "heck 0.3.3", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "snow" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "774d05a3edae07ce6d68ea6984f3c05e9bba8927e3dd591e3b479e5b03213d0d" +dependencies = [ + "aes-gcm 0.9.4", + "blake2", + "chacha20poly1305", + "curve25519-dalek 4.0.0-pre.2", + "rand_core 0.6.3", + "ring", + "rustc_version 0.4.0", + "sha2 0.10.2", + "subtle", +] + +[[package]] +name = "socket2" +version = "0.3.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "122e570113d28d773067fab24266b66753f6ea915758651696b6e35e49f88d6e" +dependencies = [ + "cfg-if 1.0.0", + "libc", + "winapi", +] + +[[package]] +name = "socket2" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "66d72b759436ae32898a2af0a14218dbf55efde3feeb170eb623637db85ee1e0" +dependencies = [ + "libc", + "winapi", +] + +[[package]] +name = "soketto" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41d1c5305e39e09653383c2c7244f2f78b3bcae37cf50c64cb4789c9f5096ec2" +dependencies = [ + "base64 0.13.0", + "bytes", + "flate2", + "futures", + "httparse", + "log", + "rand 0.8.5", + "sha-1", +] + +[[package]] +name = "spin" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" + +[[package]] +name = "spin" +version = "0.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "511254be0c5bcf062b019a6c89c01a664aa359ded62f78aa72c6fc137c0590e5" +dependencies = [ + "lock_api", +] + +[[package]] +name = "stable_deref_trait" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" + +[[package]] +name = "standback" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e113fb6f3de07a243d434a56ec6f186dfd51cb08448239fe7bcae73f87ff28ff" +dependencies = [ + "version_check", +] + +[[package]] +name = "static_assertions" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2dd574626839106c320a323308629dcb1acfc96e32a8cba364ddc61ac23ee83" +checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" [[package]] -name = "snafu" -version = "0.7.0" +name = "stdweb" +version = "0.4.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2eba135d2c579aa65364522eb78590cdf703176ef71ad4c32b00f58f7afb2df5" +checksum = "d022496b16281348b52d0e30ae99e01a73d737b2f45d38fed4edf79f9325a1d5" dependencies = [ - "backtrace", - "doc-comment", - "snafu-derive", + "discard", + "rustc_version 0.2.3", + "stdweb-derive", + "stdweb-internal-macros", + "stdweb-internal-runtime", + "wasm-bindgen", ] [[package]] -name = "snafu-derive" -version = "0.7.0" +name = "stdweb-derive" +version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a7fe9b0669ef117c5cabc5549638528f36771f058ff977d7689deb517833a75" +checksum = "c87a60a40fccc84bef0652345bbbbbe20a605bf5d0ce81719fc476f5c03b50ef" dependencies = [ - "heck", "proc-macro2", "quote", + "serde", + "serde_derive", "syn", ] [[package]] -name = "socket2" -version = "0.4.4" +name = "stdweb-internal-macros" +version = "0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "66d72b759436ae32898a2af0a14218dbf55efde3feeb170eb623637db85ee1e0" +checksum = "58fa5ff6ad0d98d1ffa8cb115892b6e69d67799f6763e162a1c9db421dc22e11" dependencies = [ - "libc", - "winapi", + "base-x", + "proc-macro2", + "quote", + "serde", + "serde_derive", + "serde_json", + "sha1", + "syn", ] [[package]] -name = "spin" -version = "0.9.2" +name = "stdweb-internal-runtime" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "511254be0c5bcf062b019a6c89c01a664aa359ded62f78aa72c6fc137c0590e5" -dependencies = [ - "lock_api", -] +checksum = "213701ba3370744dcd1a12960caa4843b3d68b4d1c0a5d575e0d65b2ee9d16c0" [[package]] name = "strsim" @@ -1630,6 +4028,12 @@ version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" +[[package]] +name = "strsim" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" + [[package]] name = "structopt" version = "0.3.26" @@ -1647,7 +4051,7 @@ version = "0.4.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dcb5ae327f9cc13b68763b5749770cb9e048a99bd9dfdfa58d0cf05d5f64afe0" dependencies = [ - "heck", + "heck 0.3.3", "proc-macro-error", "proc-macro2", "quote", @@ -1660,6 +4064,12 @@ version = "2.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6bdef32e8150c2a081110b42772ffe7d7c9032b606bc226c8260fd97e0976601" +[[package]] +name = "sval" +version = "1.0.0-alpha.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "45f6ee7c7b87caf59549e9fe45d6a69c75c8019e79e212a835c5da0e92f0ba08" + [[package]] name = "syn" version = "1.0.86" @@ -1683,13 +4093,34 @@ dependencies = [ "unicode-xid", ] +[[package]] +name = "system-configuration" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d75182f12f490e953596550b65ee31bda7c8e043d9386174b353bda50838c3fd" +dependencies = [ + "bitflags", + "core-foundation", + "system-configuration-sys", +] + +[[package]] +name = "system-configuration-sys" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a75fb188eb626b924683e3b95e3a48e63551fcfb51949de2f06a9d91dbee93c9" +dependencies = [ + "core-foundation-sys", + "libc", +] + [[package]] name = "tempfile" version = "3.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5cdb1ef4eaeeaddc8fbd371e5017057064af0911902ef36b39801f67cc6d79e4" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", "fastrand", "libc", "redox_syscall", @@ -1755,6 +4186,77 @@ dependencies = [ "zeroize", ] +[[package]] +name = "tide" +version = "0.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c459573f0dd2cc734b539047f57489ea875af8ee950860ded20cf93a79a1dee0" +dependencies = [ + "async-h1", + "async-session", + "async-sse", + "async-std", + "async-trait", + "femme", + "futures-util", + "http-client", + "http-types", + "kv-log-macro", + "log", + "pin-project-lite 0.2.8", + "route-recognizer", + "serde", + "serde_json", +] + +[[package]] +name = "time" +version = "0.1.43" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca8a50ef2360fbd1eeb0ecd46795a87a19024eb4b53c5dc916ca1fd95fe62438" +dependencies = [ + "libc", + "winapi", +] + +[[package]] +name = "time" +version = "0.2.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4752a97f8eebd6854ff91f1c1824cd6160626ac4bd44287f7f4ea2035a02a242" +dependencies = [ + "const_fn", + "libc", + "standback", + "stdweb", + "time-macros", + "version_check", + "winapi", +] + +[[package]] +name = "time-macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "957e9c6e26f12cb6d0dd7fc776bb67a706312e7299aed74c8dd5b17ebb27e2f1" +dependencies = [ + "proc-macro-hack", + "time-macros-impl", +] + +[[package]] +name = "time-macros-impl" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd3c141a1b43194f3f56a1411225df8646c55781d5f26db825b3d98507eb482f" +dependencies = [ + "proc-macro-hack", + "proc-macro2", + "quote", + "standback", + "syn", +] + [[package]] name = "tiny-keccak" version = "2.0.2" @@ -1779,6 +4281,17 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c" +[[package]] +name = "tokio" +version = "1.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2af73ac49756f3f7c01172e34a23e5d0216f6c32333757c2c61feb2bbff5a5ee" +dependencies = [ + "bytes", + "memchr", + "pin-project-lite 0.2.8", +] + [[package]] name = "toml" version = "0.5.8" @@ -1794,8 +4307,8 @@ version = "0.1.31" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f6c650a8ef0cd2dd93736f033d21cbd1224c5a967aa0c258d00fcf7dafef9b9f" dependencies = [ - "cfg-if", - "pin-project-lite", + "cfg-if 1.0.0", + "pin-project-lite 0.2.8", "tracing-attributes", "tracing-core", ] @@ -1837,7 +4350,7 @@ version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "97d095ae15e245a057c8e8451bab9b3ee1e1f68e9ba2b4fbc18d0ac5237835f2" dependencies = [ - "pin-project", + "pin-project 1.0.10", "tracing", ] @@ -1892,13 +4405,69 @@ dependencies = [ "tracing", ] +[[package]] +name = "trust-dns-proto" +version = "0.20.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca94d4e9feb6a181c690c4040d7a24ef34018d8313ac5044a61d21222ae24e31" +dependencies = [ + "async-trait", + "cfg-if 1.0.0", + "data-encoding", + "enum-as-inner", + "futures-channel", + "futures-io", + "futures-util", + "idna", + "ipnet", + "lazy_static", + "log", + "rand 0.8.5", + "smallvec", + "thiserror", + "tinyvec", + "url", +] + +[[package]] +name = "trust-dns-resolver" +version = "0.20.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ecae383baad9995efaa34ce8e57d12c3f305e545887472a492b838f4b5cfb77a" +dependencies = [ + "cfg-if 1.0.0", + "futures-util", + "ipconfig", + "lazy_static", + "log", + "lru-cache", + "parking_lot 0.11.2", + "resolv-conf", + "smallvec", + "thiserror", + "trust-dns-proto", +] + +[[package]] +name = "tui" +version = "0.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23ed0a32c88b039b73f1b6c5acbd0554bfa5b6be94467375fd947c4de3a02271" +dependencies = [ + "bitflags", + "cassowary", + "crossterm 0.22.1", + "unicode-segmentation", + "unicode-width", +] + [[package]] name = "tungstenite" version = "0.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6ad3713a14ae247f22a728a0456a545df14acf3867f905adff84be99e23b3ad1" dependencies = [ - "base64", + "base64 0.13.0", "byteorder", "bytes", "http", @@ -1923,6 +4492,18 @@ version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "56dee185309b50d1f11bfedef0fe6d036842e3fb77413abef29f8f8d1c5d4c1c" +[[package]] +name = "uint" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "12f03af7ccf01dd611cc450a0d10dbc9b745770d096473e2faf0ca6e2d66d1e0" +dependencies = [ + "byteorder", + "crunchy", + "hex", + "static_assertions", +] + [[package]] name = "unicode-bidi" version = "0.3.7" @@ -1956,6 +4537,34 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3" +[[package]] +name = "universal-hash" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f214e8f697e925001e66ec2c6e37a4ef93f0f78c2eed7814394e10c62025b05" +dependencies = [ + "generic-array", + "subtle", +] + +[[package]] +name = "unsigned-varint" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d86a8dc7f45e4c1b0d30e43038c38f274e77af056aa5f74b93c2cf9eb3c1c836" +dependencies = [ + "asynchronous-codec", + "bytes", + "futures-io", + "futures-util", +] + +[[package]] +name = "untrusted" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a" + [[package]] name = "url" version = "2.2.2" @@ -1966,6 +4575,7 @@ dependencies = [ "idna", "matches", "percent-encoding", + "serde", ] [[package]] @@ -1987,9 +4597,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "79923f7731dc61ebfba3633098bf3ac533bbd35ccd8c57e7088d9a5eebe0263f" dependencies = [ "ctor", + "sval", "version_check", ] +[[package]] +name = "vcpkg" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" + [[package]] name = "vec_map" version = "0.8.2" @@ -2002,6 +4619,12 @@ version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" +[[package]] +name = "void" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" + [[package]] name = "wait-timeout" version = "0.2.0" @@ -2035,7 +4658,9 @@ version = "0.2.79" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "25f1af7423d8588a3d840681122e72e6a24ddbcb3f0ec385cac0d12d24256c06" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", + "serde", + "serde_json", "wasm-bindgen-macro", ] @@ -2060,7 +4685,7 @@ version = "0.4.29" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2eb6ec270a31b1d3c7e266b999739109abce8b6c87e4b31fcfcd788b65267395" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", "js-sys", "wasm-bindgen", "web-sys", @@ -2095,6 +4720,21 @@ version = "0.2.79" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3d958d035c4438e28c70e4321a2911302f10135ce78a9c7834c0cab4123d06a2" +[[package]] +name = "wasm-timer" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be0ecb0db480561e9a7642b5d3e4187c128914e58aa84330b9493e3eb68c5e7f" +dependencies = [ + "futures", + "js-sys", + "parking_lot 0.11.2", + "pin-utils", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", +] + [[package]] name = "web-sys" version = "0.3.56" @@ -2105,6 +4745,25 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "webpki" +version = "0.22.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f095d78192e208183081cc07bc5515ef55216397af48b873e5edcd72637fa1bd" +dependencies = [ + "ring", + "untrusted", +] + +[[package]] +name = "webpki-roots" +version = "0.22.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "552ceb903e957524388c4d3475725ff2c8b7960922063af6ce53c9a43da07449" +dependencies = [ + "webpki", +] + [[package]] name = "wepoll-ffi" version = "0.1.2" @@ -2114,6 +4773,23 @@ dependencies = [ "cc", ] +[[package]] +name = "which" +version = "4.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a5a7e487e921cf220206864a94a89b6c6905bfc19f1057fa26a4cb360e5c1d2" +dependencies = [ + "either", + "lazy_static", + "libc", +] + +[[package]] +name = "widestring" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c168940144dd21fd8046987c16a46a33d5fc84eec29ef9dcddc2ac9e31526b7c" + [[package]] name = "winapi" version = "0.3.9" @@ -2136,54 +4812,131 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" +[[package]] +name = "windows" +version = "0.29.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aac7fef12f4b59cd0a29339406cc9203ab44e440ddff6b3f5a41455349fa9cf3" +dependencies = [ + "windows_aarch64_msvc 0.29.0", + "windows_i686_gnu 0.29.0", + "windows_i686_msvc 0.29.0", + "windows_x86_64_gnu 0.29.0", + "windows_x86_64_msvc 0.29.0", +] + [[package]] name = "windows-sys" version = "0.32.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3df6e476185f92a12c072be4a189a0210dcdcf512a1891d6dff9edb874deadc6" dependencies = [ - "windows_aarch64_msvc", - "windows_i686_gnu", - "windows_i686_msvc", - "windows_x86_64_gnu", - "windows_x86_64_msvc", + "windows_aarch64_msvc 0.32.0", + "windows_i686_gnu 0.32.0", + "windows_i686_msvc 0.32.0", + "windows_x86_64_gnu 0.32.0", + "windows_x86_64_msvc 0.32.0", ] +[[package]] +name = "windows_aarch64_msvc" +version = "0.29.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3d027175d00b01e0cbeb97d6ab6ebe03b12330a35786cbaca5252b1c4bf5d9b" + [[package]] name = "windows_aarch64_msvc" version = "0.32.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d8e92753b1c443191654ec532f14c199742964a061be25d77d7a96f09db20bf5" +[[package]] +name = "windows_i686_gnu" +version = "0.29.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8793f59f7b8e8b01eda1a652b2697d87b93097198ae85f823b969ca5b89bba58" + [[package]] name = "windows_i686_gnu" version = "0.32.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6a711c68811799e017b6038e0922cb27a5e2f43a2ddb609fe0b6f3eeda9de615" +[[package]] +name = "windows_i686_msvc" +version = "0.29.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8602f6c418b67024be2996c512f5f995de3ba417f4c75af68401ab8756796ae4" + [[package]] name = "windows_i686_msvc" version = "0.32.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "146c11bb1a02615db74680b32a68e2d61f553cc24c4eb5b4ca10311740e44172" +[[package]] +name = "windows_x86_64_gnu" +version = "0.29.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3d615f419543e0bd7d2b3323af0d86ff19cbc4f816e6453f36a2c2ce889c354" + [[package]] name = "windows_x86_64_gnu" version = "0.32.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c912b12f7454c6620635bbff3450962753834be2a594819bd5e945af18ec64bc" +[[package]] +name = "windows_x86_64_msvc" +version = "0.29.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "11d95421d9ed3672c280884da53201a5c46b7b2765ca6faf34b0d71cf34a3561" + [[package]] name = "windows_x86_64_msvc" version = "0.32.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "504a2476202769977a040c6364301a3f65d0cc9e3fb08600b2bda150a0488316" +[[package]] +name = "winreg" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2986deb581c4fe11b621998a5e53361efe6b48a151178d0cd9eeffa4dc6acc9" +dependencies = [ + "winapi", +] + +[[package]] +name = "x25519-dalek" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2392b6b94a576b4e2bf3c5b2757d63f10ada8020a2e4d08ac849ebcf6ea8e077" +dependencies = [ + "curve25519-dalek 3.2.1", + "rand_core 0.5.1", + "zeroize", +] + +[[package]] +name = "yamux" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29d4c1dd079043fe673e79fe3c3a260ae2d2fb413f1062cae9e062748df0df03" +dependencies = [ + "futures", + "log", + "nohash-hasher", + "parking_lot 0.11.2", + "rand 0.8.5", + "static_assertions", +] + [[package]] name = "zeroize" -version = "1.5.2" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c88870063c39ee00ec285a2f8d6a966e5b6fb2becc4e8dac77ed0d370ed6006" +checksum = "4756f7db3f7b5574938c3eb1c117038b8e07f95ee6718c0efad4ac21508f1efd" dependencies = [ "zeroize_derive", ] diff --git a/Cargo.toml b/Cargo.toml index e729aca54e..28da6cc65f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -78,5 +78,6 @@ lto = "thin" [workspace] members = [ - "phaselock-types" + "phaselock-types", + "libp2p-networking" ] diff --git a/libp2p-networking/Cargo.lock b/libp2p-networking/Cargo.lock deleted file mode 100644 index 0cc0273367..0000000000 --- a/libp2p-networking/Cargo.lock +++ /dev/null @@ -1,4453 +0,0 @@ -# This file is automatically @generated by Cargo. -# It is not intended for manual editing. -version = 3 - -[[package]] -name = "addr2line" -version = "0.17.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9ecd88a8c8378ca913a680cd98f0f13ac67383d35993f86c90a70e3f137816b" -dependencies = [ - "gimli", -] - -[[package]] -name = "adler" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" - -[[package]] -name = "aead" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fc95d1bdb8e6666b2b217308eeeb09f2d6728d104be3e31916cc74d15420331" -dependencies = [ - "generic-array", -] - -[[package]] -name = "aead" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b613b8e1e3cf911a086f53f03bf286f52fd7a7258e4fa606f0ef220d39d8877" -dependencies = [ - "generic-array", -] - -[[package]] -name = "aes" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "884391ef1066acaa41e766ba8f596341b96e93ce34f9a43e7d24bf0a0eaf0561" -dependencies = [ - "aes-soft", - "aesni", - "cipher 0.2.5", -] - -[[package]] -name = "aes" -version = "0.7.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e8b47f52ea9bae42228d07ec09eb676433d7c4ed1ebdf0f1d1c29ed446f1ab8" -dependencies = [ - "cfg-if 1.0.0", - "cipher 0.3.0", - "cpufeatures", - "opaque-debug", -] - -[[package]] -name = "aes-gcm" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5278b5fabbb9bd46e24aa69b2fdea62c99088e0a950a9be40e3e0101298f88da" -dependencies = [ - "aead 0.3.2", - "aes 0.6.0", - "cipher 0.2.5", - "ctr 0.6.0", - "ghash 0.3.1", - "subtle", -] - -[[package]] -name = "aes-gcm" -version = "0.9.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df5f85a83a7d8b0442b6aa7b504b8212c1733da07b98aae43d4bc21b2cb3cdf6" -dependencies = [ - "aead 0.4.3", - "aes 0.7.5", - "cipher 0.3.0", - "ctr 0.8.0", - "ghash 0.4.4", - "subtle", -] - -[[package]] -name = "aes-soft" -version = "0.6.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be14c7498ea50828a38d0e24a765ed2effe92a705885b57d029cd67d45744072" -dependencies = [ - "cipher 0.2.5", - "opaque-debug", -] - -[[package]] -name = "aesni" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea2e11f5e94c2f7d386164cc2aa1f97823fed6f259e486940a71c174dd01b0ce" -dependencies = [ - "cipher 0.2.5", - "opaque-debug", -] - -[[package]] -name = "ahash" -version = "0.7.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fcb51a0695d8f838b1ee009b3fbf66bda078cd64590202a864a8f3e8c4315c47" -dependencies = [ - "getrandom 0.2.5", - "once_cell", - "version_check", -] - -[[package]] -name = "aho-corasick" -version = "0.7.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e37cfd5e7657ada45f742d6e99ca5788580b5c529dc78faf11ece6dc702656f" -dependencies = [ - "memchr", -] - -[[package]] -name = "ansi_term" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d52a9bb7ec0cf484c551830a7ce27bd20d67eac647e1befb56b0be4ee39a55d2" -dependencies = [ - "winapi", -] - -[[package]] -name = "anyhow" -version = "1.0.55" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "159bb86af3a200e19a068f4224eae4c8bb2d0fa054c7e5d1cacd5cef95e684cd" - -[[package]] -name = "arrayref" -version = "0.3.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4c527152e37cf757a3f78aae5a06fbeefdb07ccc535c980a3208ee3060dd544" - -[[package]] -name = "arrayvec" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23b62fc65de8e4e7f52534fb52b0f3ed04746ae267519eef2a83941e8085068b" - -[[package]] -name = "arrayvec" -version = "0.7.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8da52d66c7071e2e3fa2a1e5c6d088fec47b593032b254f5e980de8ea54454d6" - -[[package]] -name = "asn1_der" -version = "0.7.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e22d1f4b888c298a027c99dc9048015fac177587de20fc30232a057dfbe24a21" - -[[package]] -name = "async-attributes" -version = "1.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3203e79f4dd9bdda415ed03cf14dae5a2bf775c683a00f94e9cd1faf0f596e5" -dependencies = [ - "quote", - "syn", -] - -[[package]] -name = "async-channel" -version = "1.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2114d64672151c0c5eaa5e131ec84a74f06e1e559830dabba01ca30605d66319" -dependencies = [ - "concurrent-queue", - "event-listener", - "futures-core", -] - -[[package]] -name = "async-dup" -version = "1.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7427a12b8dc09291528cfb1da2447059adb4a257388c2acd6497a79d55cf6f7c" -dependencies = [ - "futures-io", - "simple-mutex", -] - -[[package]] -name = "async-executor" -version = "1.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "871f9bb5e0a22eeb7e8cf16641feb87c9dc67032ccf8ff49e772eb9941d3a965" -dependencies = [ - "async-task", - "concurrent-queue", - "fastrand", - "futures-lite", - "once_cell", - "slab", -] - -[[package]] -name = "async-global-executor" -version = "2.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c026b7e44f1316b567ee750fea85103f87fcb80792b860e979f221259796ca0a" -dependencies = [ - "async-channel", - "async-executor", - "async-io", - "async-mutex", - "blocking", - "futures-lite", - "num_cpus", - "once_cell", -] - -[[package]] -name = "async-h1" -version = "2.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8101020758a4fc3a7c326cb42aa99e9fa77cbfb76987c128ad956406fe1f70a7" -dependencies = [ - "async-channel", - "async-dup", - "async-std", - "futures-core", - "http-types", - "httparse", - "log", - "pin-project 1.0.10", -] - -[[package]] -name = "async-io" -version = "1.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a811e6a479f2439f0c04038796b5cfb3d2ad56c230e0f2d3f7b04d68cfee607b" -dependencies = [ - "concurrent-queue", - "futures-lite", - "libc", - "log", - "once_cell", - "parking", - "polling", - "slab", - "socket2 0.4.4", - "waker-fn", - "winapi", -] - -[[package]] -name = "async-lock" -version = "2.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e97a171d191782fba31bb902b14ad94e24a68145032b7eedf871ab0bc0d077b6" -dependencies = [ - "event-listener", -] - -[[package]] -name = "async-mutex" -version = "1.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "479db852db25d9dbf6204e6cb6253698f175c15726470f78af0d918e99d6156e" -dependencies = [ - "event-listener", -] - -[[package]] -name = "async-process" -version = "1.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "83137067e3a2a6a06d67168e49e68a0957d215410473a740cea95a2425c0b7c6" -dependencies = [ - "async-io", - "blocking", - "cfg-if 1.0.0", - "event-listener", - "futures-lite", - "libc", - "once_cell", - "signal-hook", - "winapi", -] - -[[package]] -name = "async-session" -version = "2.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "345022a2eed092cd105cc1b26fd61c341e100bd5fcbbd792df4baf31c2cc631f" -dependencies = [ - "anyhow", - "async-std", - "async-trait", - "base64 0.12.3", - "bincode", - "blake3 0.3.8", - "chrono", - "hmac 0.8.1", - "kv-log-macro", - "rand 0.7.3", - "serde", - "serde_json", - "sha2 0.9.9", -] - -[[package]] -name = "async-sse" -version = "4.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53bba003996b8fd22245cd0c59b869ba764188ed435392cf2796d03b805ade10" -dependencies = [ - "async-channel", - "async-std", - "http-types", - "log", - "memchr", - "pin-project-lite 0.1.12", -] - -[[package]] -name = "async-std" -version = "1.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8056f1455169ab86dd47b47391e4ab0cbd25410a70e9fe675544f49bafaf952" -dependencies = [ - "async-attributes", - "async-channel", - "async-global-executor", - "async-io", - "async-lock", - "async-process", - "crossbeam-utils", - "futures-channel", - "futures-core", - "futures-io", - "futures-lite", - "gloo-timers", - "kv-log-macro", - "log", - "memchr", - "num_cpus", - "once_cell", - "pin-project-lite 0.2.8", - "pin-utils", - "slab", - "wasm-bindgen-futures", -] - -[[package]] -name = "async-std-resolver" -version = "0.20.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dbf3e776afdf3a2477ef4854b85ba0dff3bd85792f685fb3c68948b4d304e4f0" -dependencies = [ - "async-std", - "async-trait", - "futures-io", - "futures-util", - "pin-utils", - "trust-dns-resolver", -] - -[[package]] -name = "async-task" -version = "4.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "677d306121baf53310a3fd342d88dc0824f6bbeace68347593658525565abee8" - -[[package]] -name = "async-trait" -version = "0.1.52" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "061a7acccaa286c011ddc30970520b98fa40e00c9d644633fb26b5fc63a265e3" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "asynchronous-codec" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0de5164e5edbf51c45fb8c2d9664ae1c095cce1b265ecf7569093c0d66ef690" -dependencies = [ - "bytes", - "futures-sink", - "futures-util", - "memchr", - "pin-project-lite 0.2.8", -] - -[[package]] -name = "atomic" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b88d82667eca772c4aa12f0f1348b3ae643424c8876448f3f7bd5787032e234c" -dependencies = [ - "autocfg", -] - -[[package]] -name = "atomic-waker" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "065374052e7df7ee4047b1160cca5e1467a12351a40b3da123c870ba0b8eda2a" - -[[package]] -name = "atty" -version = "0.2.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" -dependencies = [ - "hermit-abi", - "libc", - "winapi", -] - -[[package]] -name = "autocfg" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" - -[[package]] -name = "backtrace" -version = "0.3.64" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e121dee8023ce33ab248d9ce1493df03c3b38a659b240096fcbd7048ff9c31f" -dependencies = [ - "addr2line", - "cc", - "cfg-if 1.0.0", - "libc", - "miniz_oxide", - "object", - "rustc-demangle", -] - -[[package]] -name = "base-x" -version = "0.2.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4521f3e3d031370679b3b140beb36dfe4801b09ac77e30c61941f97df3ef28b" - -[[package]] -name = "base64" -version = "0.12.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3441f0f7b02788e948e47f457ca01f1d7e6d92c693bc132c22b087d3141c03ff" - -[[package]] -name = "base64" -version = "0.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "904dfeac50f3cdaba28fc6f57fdcddb75f49ed61346676a78c4ffe55877802fd" - -[[package]] -name = "bimap" -version = "0.6.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc0455254eb5c6964c4545d8bac815e1a1be4f3afe0ae695ea539c12d728d44b" - -[[package]] -name = "bincode" -version = "1.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1f45e9417d87227c7a56d22e471c6206462cba514c7590c09aff4cf6d1ddcad" -dependencies = [ - "serde", -] - -[[package]] -name = "bitflags" -version = "1.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" - -[[package]] -name = "blake2" -version = "0.10.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9cf849ee05b2ee5fba5e36f97ff8ec2533916700fc0758d40d92136a42f3388" -dependencies = [ - "digest 0.10.3", -] - -[[package]] -name = "blake3" -version = "0.3.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b64485778c4f16a6a5a9d335e80d449ac6c70cdd6a06d2af18a6f6f775a125b3" -dependencies = [ - "arrayref", - "arrayvec 0.5.2", - "cc", - "cfg-if 0.1.10", - "constant_time_eq", - "crypto-mac 0.8.0", - "digest 0.9.0", -] - -[[package]] -name = "blake3" -version = "1.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a08e53fc5a564bb15bfe6fae56bd71522205f1f91893f9c0116edad6496c183f" -dependencies = [ - "arrayref", - "arrayvec 0.7.2", - "cc", - "cfg-if 1.0.0", - "constant_time_eq", - "digest 0.10.3", -] - -[[package]] -name = "block-buffer" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4152116fd6e9dadb291ae18fc1ec3575ed6d84c29642d97890f4b4a3417297e4" -dependencies = [ - "block-padding", - "generic-array", -] - -[[package]] -name = "block-buffer" -version = "0.10.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0bf7fe51849ea569fd452f37822f606a5cabb684dc918707a0193fd4664ff324" -dependencies = [ - "generic-array", -] - -[[package]] -name = "block-padding" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d696c370c750c948ada61c69a0ee2cbbb9c50b1019ddb86d9317157a99c2cae" - -[[package]] -name = "blocking" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "046e47d4b2d391b1f6f8b407b1deb8dee56c1852ccd868becf2710f601b5f427" -dependencies = [ - "async-channel", - "async-task", - "atomic-waker", - "fastrand", - "futures-lite", - "once_cell", -] - -[[package]] -name = "bs58" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "771fe0050b883fcc3ea2359b1a96bcfbc090b7116eae7c3c512c7a083fdf23d3" - -[[package]] -name = "bumpalo" -version = "3.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4a45a46ab1f2412e53d3a0ade76ffad2025804294569aae387231a0cd6e0899" - -[[package]] -name = "byteorder" -version = "1.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" - -[[package]] -name = "bytes" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4872d67bab6358e59559027aa3b9157c53d9358c51423c17554809a8858e0f8" -dependencies = [ - "serde", -] - -[[package]] -name = "cache-padded" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1db59621ec70f09c5e9b597b220c7a2b43611f4710dc03ceb8748637775692c" - -[[package]] -name = "cassowary" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df8670b8c7b9dae1793364eafadf7239c40d669904660c5960d74cfd80b46a53" - -[[package]] -name = "cc" -version = "1.0.73" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2fff2a6927b3bb87f9595d67196a70493f627687a71d87a0d692242c33f58c11" - -[[package]] -name = "cfg-if" -version = "0.1.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" - -[[package]] -name = "cfg-if" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" - -[[package]] -name = "chacha20" -version = "0.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "01b72a433d0cf2aef113ba70f62634c56fddb0f244e6377185c56a7cadbd8f91" -dependencies = [ - "cfg-if 1.0.0", - "cipher 0.3.0", - "cpufeatures", - "zeroize", -] - -[[package]] -name = "chacha20poly1305" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b84ed6d1d5f7aa9bdde921a5090e0ca4d934d250ea3b402a5fab3a994e28a2a" -dependencies = [ - "aead 0.4.3", - "chacha20", - "cipher 0.3.0", - "poly1305", - "zeroize", -] - -[[package]] -name = "chrono" -version = "0.4.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "670ad68c9088c2a963aaa298cb369688cf3f9465ce5e2d4ca10e6e0098a1ce73" -dependencies = [ - "libc", - "num-integer", - "num-traits", - "serde", - "time 0.1.43", - "winapi", -] - -[[package]] -name = "cipher" -version = "0.2.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "12f8e7987cbd042a63249497f41aed09f8e65add917ea6566effbc56578d6801" -dependencies = [ - "generic-array", -] - -[[package]] -name = "cipher" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ee52072ec15386f770805afd189a01c8841be8696bed250fa2f13c4c0d6dfb7" -dependencies = [ - "generic-array", -] - -[[package]] -name = "clap" -version = "2.34.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a0610544180c38b88101fecf2dd634b174a62eef6946f84dfc6a7127512b381c" -dependencies = [ - "ansi_term", - "atty", - "bitflags", - "strsim 0.8.0", - "textwrap", - "unicode-width", - "vec_map", -] - -[[package]] -name = "color-eyre" -version = "0.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ebf286c900a6d5867aeff75cfee3192857bb7f24b547d4f0df2ed6baa812c90" -dependencies = [ - "backtrace", - "color-spantrace", - "eyre", - "indenter", - "once_cell", - "owo-colors", - "tracing-error", -] - -[[package]] -name = "color-spantrace" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ba75b3d9449ecdccb27ecbc479fdc0b87fa2dd43d2f8298f9bf0e59aacc8dce" -dependencies = [ - "once_cell", - "owo-colors", - "tracing-core", - "tracing-error", -] - -[[package]] -name = "concurrent-queue" -version = "1.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30ed07550be01594c6026cff2a1d7fe9c8f683caa798e12b68694ac9e88286a3" -dependencies = [ - "cache-padded", -] - -[[package]] -name = "const_fn" -version = "0.4.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fbdcdcb6d86f71c5e97409ad45898af11cbc995b4ee8112d59095a28d376c935" - -[[package]] -name = "constant_time_eq" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "245097e9a4535ee1e3e3931fcfcd55a796a44c643e8596ff6566d68f09b87bbc" - -[[package]] -name = "cookie" -version = "0.14.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03a5d7b21829bc7b4bf4754a978a241ae54ea55a40f92bb20216e54096f4b951" -dependencies = [ - "aes-gcm 0.8.0", - "base64 0.13.0", - "hkdf", - "hmac 0.10.1", - "percent-encoding", - "rand 0.8.5", - "sha2 0.9.9", - "time 0.2.27", - "version_check", -] - -[[package]] -name = "core-foundation" -version = "0.9.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "194a7a9e6de53fa55116934067c844d9d749312f75c6f6d0980e8c252f8c2146" -dependencies = [ - "core-foundation-sys", - "libc", -] - -[[package]] -name = "core-foundation-sys" -version = "0.8.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5827cebf4670468b8772dd191856768aedcb1b0278a04f989f7766351917b9dc" - -[[package]] -name = "core2" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b49ba7ef1ad6107f8824dbe97de947cbaac53c44e7f9756a1fba0d37c1eec505" -dependencies = [ - "memchr", -] - -[[package]] -name = "cpufeatures" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95059428f66df56b63431fdb4e1947ed2190586af5c5a8a8b71122bdf5a7f469" -dependencies = [ - "libc", -] - -[[package]] -name = "cpuid-bool" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dcb25d077389e53838a8158c8e99174c5a9d902dee4904320db714f3c653ffba" - -[[package]] -name = "crc32fast" -version = "1.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b540bd8bc810d3885c6ea91e2018302f68baba2129ab3e88f32389ee9370880d" -dependencies = [ - "cfg-if 1.0.0", -] - -[[package]] -name = "crossbeam-utils" -version = "0.8.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5e5bed1f1c269533fa816a0a5492b3545209a205ca1a54842be180eb63a16a6" -dependencies = [ - "cfg-if 1.0.0", - "lazy_static", -] - -[[package]] -name = "crossterm" -version = "0.22.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c85525306c4291d1b73ce93c8acf9c339f9b213aef6c1d85c3830cbf1c16325c" -dependencies = [ - "bitflags", - "crossterm_winapi", - "libc", - "mio", - "parking_lot 0.11.2", - "signal-hook", - "signal-hook-mio", - "winapi", -] - -[[package]] -name = "crossterm" -version = "0.23.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77b75a27dc8d220f1f8521ea69cd55a34d720a200ebb3a624d9aa19193d3b432" -dependencies = [ - "bitflags", - "crossterm_winapi", - "futures-core", - "libc", - "mio", - "parking_lot 0.12.0", - "signal-hook", - "signal-hook-mio", - "winapi", -] - -[[package]] -name = "crossterm_winapi" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2ae1b35a484aa10e07fe0638d02301c5ad24de82d310ccbd2f3693da5f09bf1c" -dependencies = [ - "winapi", -] - -[[package]] -name = "crunchy" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" - -[[package]] -name = "crypto-common" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57952ca27b5e3606ff4dd79b0020231aaf9d6aa76dc05fd30137538c50bd3ce8" -dependencies = [ - "generic-array", - "typenum", -] - -[[package]] -name = "crypto-mac" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b584a330336237c1eecd3e94266efb216c56ed91225d634cb2991c5f3fd1aeab" -dependencies = [ - "generic-array", - "subtle", -] - -[[package]] -name = "crypto-mac" -version = "0.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bff07008ec701e8028e2ceb8f83f0e4274ee62bd2dbdc4fefff2e9a91824081a" -dependencies = [ - "generic-array", - "subtle", -] - -[[package]] -name = "ctor" -version = "0.1.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ccc0a48a9b826acdf4028595adc9db92caea352f7af011a3034acd172a52a0aa" -dependencies = [ - "quote", - "syn", -] - -[[package]] -name = "ctr" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb4a30d54f7443bf3d6191dcd486aca19e67cb3c49fa7a06a319966346707e7f" -dependencies = [ - "cipher 0.2.5", -] - -[[package]] -name = "ctr" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "049bb91fb4aaf0e3c7efa6cd5ef877dbbbd15b39dad06d9948de4ec8a75761ea" -dependencies = [ - "cipher 0.3.0", -] - -[[package]] -name = "cuckoofilter" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b810a8449931679f64cd7eef1bbd0fa315801b6d5d9cdc1ace2804d6529eee18" -dependencies = [ - "byteorder", - "fnv", - "rand 0.7.3", -] - -[[package]] -name = "curve25519-dalek" -version = "3.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90f9d052967f590a76e62eb387bd0bbb1b000182c3cefe5364db6b7211651bc0" -dependencies = [ - "byteorder", - "digest 0.9.0", - "rand_core 0.5.1", - "subtle", - "zeroize", -] - -[[package]] -name = "curve25519-dalek" -version = "4.0.0-pre.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "12dc3116fe595d7847c701796ac1b189bd86b81f4f593c6f775f9d80fb2e29f4" -dependencies = [ - "byteorder", - "digest 0.10.3", - "rand_core 0.6.3", - "subtle", - "zeroize", -] - -[[package]] -name = "darling" -version = "0.12.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f2c43f534ea4b0b049015d00269734195e6d3f0f6635cb692251aca6f9f8b3c" -dependencies = [ - "darling_core", - "darling_macro", -] - -[[package]] -name = "darling_core" -version = "0.12.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e91455b86830a1c21799d94524df0845183fa55bafd9aa137b01c7d1065fa36" -dependencies = [ - "fnv", - "ident_case", - "proc-macro2", - "quote", - "strsim 0.10.0", - "syn", -] - -[[package]] -name = "darling_macro" -version = "0.12.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "29b5acf0dea37a7f66f7b25d2c5e93fd46f8f6968b1a5d7a3e02e97768afc95a" -dependencies = [ - "darling_core", - "quote", - "syn", -] - -[[package]] -name = "dashmap" -version = "4.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e77a43b28d0668df09411cb0bc9a8c2adc40f9a048afe863e05fd43251e8e39c" -dependencies = [ - "cfg-if 1.0.0", - "num_cpus", -] - -[[package]] -name = "data-encoding" -version = "2.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ee2393c4a91429dffb4bedf19f4d6abf27d8a732c8ce4980305d782e5426d57" - -[[package]] -name = "derive_builder" -version = "0.10.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d13202debe11181040ae9063d739fa32cfcaaebe2275fe387703460ae2365b30" -dependencies = [ - "derive_builder_macro", -] - -[[package]] -name = "derive_builder_core" -version = "0.10.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "66e616858f6187ed828df7c64a6d71720d83767a7f19740b2d1b6fe6327b36e5" -dependencies = [ - "darling", - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "derive_builder_macro" -version = "0.10.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "58a94ace95092c5acb1e97a7e846b310cfbd499652f72297da7493f618a98d73" -dependencies = [ - "derive_builder_core", - "syn", -] - -[[package]] -name = "digest" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066" -dependencies = [ - "generic-array", -] - -[[package]] -name = "digest" -version = "0.10.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2fb860ca6fafa5552fb6d0e816a69c8e49f0908bf524e30a90d97c85892d506" -dependencies = [ - "block-buffer 0.10.2", - "crypto-common", - "subtle", -] - -[[package]] -name = "discard" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "212d0f5754cb6769937f4501cc0e67f4f4483c8d2c3e1e922ee9edbe4ab4c7c0" - -[[package]] -name = "dns-parser" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4d33be9473d06f75f58220f71f7a9317aca647dc061dbd3c361b0bef505fbea" -dependencies = [ - "byteorder", - "quick-error", -] - -[[package]] -name = "doc-comment" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fea41bba32d969b513997752735605054bc0dfa92b4c56bf1189f2e174be7a10" - -[[package]] -name = "dtoa" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5caaa75cbd2b960ff1e5392d2cfb1f44717fffe12fc1f32b7b5d1267f99732a6" - -[[package]] -name = "ed25519" -version = "1.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eed12bbf7b5312f8da1c2722bc06d8c6b12c2d86a7fb35a194c7f3e6fc2bbe39" -dependencies = [ - "signature", -] - -[[package]] -name = "ed25519-dalek" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c762bae6dcaf24c4c84667b8579785430908723d5c889f469d76a41d59cc7a9d" -dependencies = [ - "curve25519-dalek 3.2.1", - "ed25519", - "rand 0.7.3", - "serde", - "sha2 0.9.9", - "zeroize", -] - -[[package]] -name = "either" -version = "1.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457" - -[[package]] -name = "enum-as-inner" -version = "0.3.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "570d109b813e904becc80d8d5da38376818a143348413f7149f1340fe04754d4" -dependencies = [ - "heck 0.4.0", - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "event-listener" -version = "2.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77f3309417938f28bf8228fcff79a4a37103981e3e186d2ccd19c74b38f4eb71" - -[[package]] -name = "eyre" -version = "0.6.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9289ed2c0440a6536e65119725cf91fc2c6b5e513bfd2e36e1134d7cca6ca12f" -dependencies = [ - "indenter", - "once_cell", -] - -[[package]] -name = "fastrand" -version = "1.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3fcf0cee53519c866c09b5de1f6c56ff9d647101f81c1964fa632e148896cdf" -dependencies = [ - "instant", -] - -[[package]] -name = "femme" -version = "2.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2af1a24f391a5a94d756db5092c6576aad494b88a71a5a36b20c67b63e0df034" -dependencies = [ - "cfg-if 0.1.10", - "js-sys", - "log", - "serde", - "serde_derive", - "serde_json", - "wasm-bindgen", - "web-sys", -] - -[[package]] -name = "fixedbitset" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "279fb028e20b3c4c320317955b77c5e0c9701f05a1d309905d6fc702cdc5053e" - -[[package]] -name = "flate2" -version = "1.0.22" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e6988e897c1c9c485f43b47a529cef42fde0547f9d8d41a7062518f1d8fc53f" -dependencies = [ - "cfg-if 1.0.0", - "crc32fast", - "libc", - "libz-sys", - "miniz_oxide", -] - -[[package]] -name = "flume" -version = "0.10.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b279436a715a9de95dcd26b151db590a71961cc06e54918b24fe0dd5b7d3fc4" -dependencies = [ - "futures-core", - "futures-sink", - "nanorand", - "pin-project 1.0.10", - "spin 0.9.2", -] - -[[package]] -name = "fnv" -version = "1.0.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" - -[[package]] -name = "form_urlencoded" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5fc25a87fa4fd2094bffb06925852034d90a17f0d1e05197d4956d3555752191" -dependencies = [ - "matches", - "percent-encoding", -] - -[[package]] -name = "futures" -version = "0.3.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f73fe65f54d1e12b726f517d3e2135ca3125a437b6d998caf1962961f7172d9e" -dependencies = [ - "futures-channel", - "futures-core", - "futures-executor", - "futures-io", - "futures-sink", - "futures-task", - "futures-util", -] - -[[package]] -name = "futures-channel" -version = "0.3.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3083ce4b914124575708913bca19bfe887522d6e2e6d0952943f5eac4a74010" -dependencies = [ - "futures-core", - "futures-sink", -] - -[[package]] -name = "futures-core" -version = "0.3.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c09fd04b7e4073ac7156a9539b57a484a8ea920f79c7c675d05d289ab6110d3" - -[[package]] -name = "futures-executor" -version = "0.3.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9420b90cfa29e327d0429f19be13e7ddb68fa1cccb09d65e5706b8c7a749b8a6" -dependencies = [ - "futures-core", - "futures-task", - "futures-util", - "num_cpus", -] - -[[package]] -name = "futures-io" -version = "0.3.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc4045962a5a5e935ee2fdedaa4e08284547402885ab326734432bed5d12966b" - -[[package]] -name = "futures-lite" -version = "1.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7694489acd39452c77daa48516b894c153f192c3578d5a839b62c58099fcbf48" -dependencies = [ - "fastrand", - "futures-core", - "futures-io", - "memchr", - "parking", - "pin-project-lite 0.2.8", - "waker-fn", -] - -[[package]] -name = "futures-macro" -version = "0.3.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33c1e13800337f4d4d7a316bf45a567dbcb6ffe087f16424852d97e97a91f512" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "futures-rustls" -version = "0.22.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d383f0425d991a05e564c2f3ec150bd6dde863179c131dd60d8aa73a05434461" -dependencies = [ - "futures-io", - "rustls", - "webpki", -] - -[[package]] -name = "futures-sink" -version = "0.3.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21163e139fa306126e6eedaf49ecdb4588f939600f0b1e770f4205ee4b7fa868" - -[[package]] -name = "futures-task" -version = "0.3.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57c66a976bf5909d801bbef33416c41372779507e7a6b3a5e25e4749c58f776a" - -[[package]] -name = "futures-timer" -version = "3.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e64b03909df88034c26dc1547e8970b91f98bdb65165d6a4e9110d94263dbb2c" - -[[package]] -name = "futures-util" -version = "0.3.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8b7abd5d659d9b90c8cba917f6ec750a74e2dc23902ef9cd4cc8c8b22e6036a" -dependencies = [ - "futures-channel", - "futures-core", - "futures-io", - "futures-macro", - "futures-sink", - "futures-task", - "memchr", - "pin-project-lite 0.2.8", - "pin-utils", - "slab", -] - -[[package]] -name = "generic-array" -version = "0.14.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd48d33ec7f05fbfa152300fdad764757cbded343c1aa1cff2fbaf4134851803" -dependencies = [ - "typenum", - "version_check", -] - -[[package]] -name = "getrandom" -version = "0.1.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8fc3cb4d91f53b50155bdcfd23f6a4c39ae1969c2ae85982b135750cccaf5fce" -dependencies = [ - "cfg-if 1.0.0", - "libc", - "wasi 0.9.0+wasi-snapshot-preview1", -] - -[[package]] -name = "getrandom" -version = "0.2.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d39cd93900197114fa1fcb7ae84ca742095eed9442088988ae74fa744e930e77" -dependencies = [ - "cfg-if 1.0.0", - "js-sys", - "libc", - "wasi 0.10.2+wasi-snapshot-preview1", - "wasm-bindgen", -] - -[[package]] -name = "ghash" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97304e4cd182c3846f7575ced3890c53012ce534ad9114046b0a9e00bb30a375" -dependencies = [ - "opaque-debug", - "polyval 0.4.5", -] - -[[package]] -name = "ghash" -version = "0.4.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1583cc1656d7839fd3732b80cf4f38850336cdb9b8ded1cd399ca62958de3c99" -dependencies = [ - "opaque-debug", - "polyval 0.5.3", -] - -[[package]] -name = "gimli" -version = "0.26.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78cc372d058dcf6d5ecd98510e7fbc9e5aec4d21de70f65fea8fecebcd881bd4" - -[[package]] -name = "gloo-timers" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d12a7f4e95cfe710f1d624fb1210b7d961a5fb05c4fd942f4feab06e61f590e" -dependencies = [ - "futures-channel", - "futures-core", - "js-sys", - "wasm-bindgen", -] - -[[package]] -name = "hashbrown" -version = "0.11.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e" -dependencies = [ - "ahash", -] - -[[package]] -name = "heck" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d621efb26863f0e9924c6ac577e8275e5e6b77455db64ffa6c65c904e9e132c" -dependencies = [ - "unicode-segmentation", -] - -[[package]] -name = "heck" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2540771e65fc8cb83cd6e8a237f70c319bd5c29f78ed1084ba5d50eeac86f7f9" - -[[package]] -name = "hermit-abi" -version = "0.1.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" -dependencies = [ - "libc", -] - -[[package]] -name = "hex" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" - -[[package]] -name = "hex_fmt" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b07f60793ff0a4d9cef0f18e63b5357e06209987153a64648c972c1e5aff336f" - -[[package]] -name = "hkdf" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "51ab2f639c231793c5f6114bdb9bbe50a7dbbfcd7c7c6bd8475dec2d991e964f" -dependencies = [ - "digest 0.9.0", - "hmac 0.10.1", -] - -[[package]] -name = "hmac" -version = "0.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "126888268dcc288495a26bf004b38c5fdbb31682f992c84ceb046a1f0fe38840" -dependencies = [ - "crypto-mac 0.8.0", - "digest 0.9.0", -] - -[[package]] -name = "hmac" -version = "0.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1441c6b1e930e2817404b5046f1f989899143a12bf92de603b69f4e0aee1e15" -dependencies = [ - "crypto-mac 0.10.1", - "digest 0.9.0", -] - -[[package]] -name = "hmac-drbg" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17ea0a1394df5b6574da6e0c1ade9e78868c9fb0a4e5ef4428e32da4676b85b1" -dependencies = [ - "digest 0.9.0", - "generic-array", - "hmac 0.8.1", -] - -[[package]] -name = "hostname" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c731c3e10504cc8ed35cfe2f1db4c9274c3d35fa486e3b31df46f068ef3e867" -dependencies = [ - "libc", - "match_cfg", - "winapi", -] - -[[package]] -name = "http-client" -version = "6.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea880b03c18a7e981d7fb3608b8904a98425d53c440758fcebf7d934aa56547c" -dependencies = [ - "async-trait", - "cfg-if 1.0.0", - "dashmap", - "http-types", - "log", -] - -[[package]] -name = "http-types" -version = "2.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e9b187a72d63adbfba487f48095306ac823049cb504ee195541e91c7775f5ad" -dependencies = [ - "anyhow", - "async-channel", - "async-std", - "base64 0.13.0", - "cookie", - "futures-lite", - "infer", - "pin-project-lite 0.2.8", - "rand 0.7.3", - "serde", - "serde_json", - "serde_qs", - "serde_urlencoded", - "url", -] - -[[package]] -name = "httparse" -version = "1.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9100414882e15fb7feccb4897e5f0ff0ff1ca7d1a86a23208ada4d7a18e6c6c4" - -[[package]] -name = "ident_case" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" - -[[package]] -name = "idna" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "418a0a6fab821475f634efe3ccc45c013f742efe03d853e8d3355d5cb850ecf8" -dependencies = [ - "matches", - "unicode-bidi", - "unicode-normalization", -] - -[[package]] -name = "if-addrs" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cbc0fa01ffc752e9dbc72818cdb072cd028b86be5e09dd04c5a643704fe101a9" -dependencies = [ - "libc", - "winapi", -] - -[[package]] -name = "if-watch" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae8f4a3c3d4c89351ca83e120c1c00b27df945d38e05695668c9d4b4f7bc52f3" -dependencies = [ - "async-io", - "core-foundation", - "fnv", - "futures", - "if-addrs", - "ipnet", - "log", - "rtnetlink", - "system-configuration", - "windows", -] - -[[package]] -name = "indenter" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce23b50ad8242c51a442f3ff322d56b02f08852c77e4c0b4d3fd684abc89c683" - -[[package]] -name = "indexmap" -version = "1.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "282a6247722caba404c065016bbfa522806e51714c34f5dfc3e4a3a46fcb4223" -dependencies = [ - "autocfg", - "hashbrown", -] - -[[package]] -name = "infer" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64e9829a50b42bb782c1df523f78d332fe371b10c661e78b7a3c34b0198e9fac" - -[[package]] -name = "instant" -version = "0.1.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" -dependencies = [ - "cfg-if 1.0.0", -] - -[[package]] -name = "ipconfig" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7e2f18aece9709094573a9f24f483c4f65caa4298e2f7ae1b71cc65d853fad7" -dependencies = [ - "socket2 0.3.19", - "widestring", - "winapi", - "winreg", -] - -[[package]] -name = "ipnet" -version = "2.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68f2d64f2edebec4ce84ad108148e67e1064789bee435edc5b60ad398714a3a9" - -[[package]] -name = "itertools" -version = "0.10.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9a9d19fa1e79b6215ff29b9d6880b706147f16e9b1dbb1e4e5947b5b02bc5e3" -dependencies = [ - "either", -] - -[[package]] -name = "itoa" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1aab8fc367588b89dcee83ab0fd66b72b50b72fa1904d7095045ace2b0c81c35" - -[[package]] -name = "js-sys" -version = "0.3.56" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a38fc24e30fd564ce974c02bf1d337caddff65be6cc4735a1f7eab22a7440f04" -dependencies = [ - "wasm-bindgen", -] - -[[package]] -name = "keccak" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67c21572b4949434e4fc1e1978b99c5f77064153c59d998bf13ecd96fb5ecba7" - -[[package]] -name = "kv-log-macro" -version = "1.0.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0de8b303297635ad57c9f5059fd9cee7a47f8e8daa09df0fcd07dd39fb22977f" -dependencies = [ - "log", -] - -[[package]] -name = "lazy_static" -version = "1.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" - -[[package]] -name = "libc" -version = "0.2.119" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1bf2e165bb3457c8e098ea76f3e3bc9db55f87aa90d52d0e6be741470916aaa4" - -[[package]] -name = "libp2p" -version = "0.43.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e8570e25fa03d4385405dbeaf540ba00e3ee50942f03d84e1a8928a029f35f9" -dependencies = [ - "atomic", - "bytes", - "futures", - "futures-timer", - "getrandom 0.2.5", - "instant", - "lazy_static", - "libp2p-autonat", - "libp2p-core", - "libp2p-deflate", - "libp2p-dns", - "libp2p-floodsub", - "libp2p-gossipsub", - "libp2p-identify", - "libp2p-kad", - "libp2p-mdns", - "libp2p-metrics", - "libp2p-mplex", - "libp2p-noise", - "libp2p-ping", - "libp2p-plaintext", - "libp2p-pnet", - "libp2p-relay", - "libp2p-rendezvous", - "libp2p-request-response", - "libp2p-swarm", - "libp2p-swarm-derive", - "libp2p-tcp", - "libp2p-uds", - "libp2p-wasm-ext", - "libp2p-websocket", - "libp2p-yamux", - "multiaddr", - "parking_lot 0.12.0", - "pin-project 1.0.10", - "rand 0.7.3", - "smallvec", -] - -[[package]] -name = "libp2p-autonat" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd6314084638e09e4162a5c6d0c1ba859f5d5f8a045ca015f7c95325e4b7c230" -dependencies = [ - "async-trait", - "futures", - "futures-timer", - "instant", - "libp2p-core", - "libp2p-request-response", - "libp2p-swarm", - "log", - "prost", - "prost-build", - "rand 0.8.5", -] - -[[package]] -name = "libp2p-core" -version = "0.32.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9164ec41455856e8187addc870bb4fe1ea2ee28e1a9244831d449a2429b32c1a" -dependencies = [ - "asn1_der", - "bs58", - "ed25519-dalek", - "either", - "fnv", - "futures", - "futures-timer", - "instant", - "lazy_static", - "libsecp256k1", - "log", - "multiaddr", - "multihash", - "multistream-select", - "parking_lot 0.12.0", - "pin-project 1.0.10", - "prost", - "prost-build", - "rand 0.8.5", - "ring", - "rw-stream-sink", - "serde", - "sha2 0.10.2", - "smallvec", - "thiserror", - "unsigned-varint", - "void", - "zeroize", -] - -[[package]] -name = "libp2p-deflate" -version = "0.32.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b1d37f042f748e224f04785d0e987ae09a2aa518d6401d82d412dad83e360ed" -dependencies = [ - "flate2", - "futures", - "libp2p-core", -] - -[[package]] -name = "libp2p-dns" -version = "0.32.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7838647d33978b77f943687412f4a39e74234c8342cbfdad14282b465b272cb4" -dependencies = [ - "async-std-resolver", - "futures", - "libp2p-core", - "log", - "smallvec", - "trust-dns-resolver", -] - -[[package]] -name = "libp2p-floodsub" -version = "0.34.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df0b7d6c3fa2ead77a5bbeff580bd7507efcc9d7fa9d0caf873795b097d385c0" -dependencies = [ - "cuckoofilter", - "fnv", - "futures", - "libp2p-core", - "libp2p-swarm", - "log", - "prost", - "prost-build", - "rand 0.7.3", - "smallvec", -] - -[[package]] -name = "libp2p-gossipsub" -version = "0.36.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f62943fba0b0dae02b87868620c52a581c54ec9fb04b5e195cf20313fc510c3" -dependencies = [ - "asynchronous-codec", - "base64 0.13.0", - "byteorder", - "bytes", - "fnv", - "futures", - "hex_fmt", - "instant", - "libp2p-core", - "libp2p-swarm", - "log", - "prometheus-client", - "prost", - "prost-build", - "rand 0.7.3", - "regex", - "serde", - "sha2 0.10.2", - "smallvec", - "unsigned-varint", - "wasm-timer", -] - -[[package]] -name = "libp2p-identify" -version = "0.34.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f219b4d4660fe3a04bf5fe6b5970902b7c1918e25b2536be8c70efc480f88f8" -dependencies = [ - "futures", - "futures-timer", - "libp2p-core", - "libp2p-swarm", - "log", - "lru", - "prost", - "prost-build", - "smallvec", -] - -[[package]] -name = "libp2p-kad" -version = "0.35.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aead5ee2322a7b825c7633065370909c8383046f955cda5b56797e6904db7a72" -dependencies = [ - "arrayvec 0.5.2", - "asynchronous-codec", - "bytes", - "either", - "fnv", - "futures", - "futures-timer", - "instant", - "libp2p-core", - "libp2p-swarm", - "log", - "prost", - "prost-build", - "rand 0.7.3", - "serde", - "sha2 0.10.2", - "smallvec", - "thiserror", - "uint", - "unsigned-varint", - "void", -] - -[[package]] -name = "libp2p-mdns" -version = "0.35.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "54d1914576978e5f3b15ac99e2cda9b56471ce64f1cfc7c2b09ac0cee147175e" -dependencies = [ - "async-io", - "data-encoding", - "dns-parser", - "futures", - "if-watch", - "lazy_static", - "libp2p-core", - "libp2p-swarm", - "log", - "rand 0.8.5", - "smallvec", - "socket2 0.4.4", - "void", -] - -[[package]] -name = "libp2p-metrics" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d29e4e5e4c5aa567fe1ee3133afe088dc2d2fd104e20c5c2c5c2649f75129677" -dependencies = [ - "libp2p-core", - "libp2p-gossipsub", - "libp2p-identify", - "libp2p-kad", - "libp2p-ping", - "libp2p-relay", - "libp2p-swarm", - "prometheus-client", -] - -[[package]] -name = "libp2p-mplex" -version = "0.32.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "442eb0c9fff0bf22a34f015724b4143ce01877e079ed0963c722d94c07c72160" -dependencies = [ - "asynchronous-codec", - "bytes", - "futures", - "libp2p-core", - "log", - "nohash-hasher", - "parking_lot 0.12.0", - "rand 0.7.3", - "smallvec", - "unsigned-varint", -] - -[[package]] -name = "libp2p-noise" -version = "0.35.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9dd7e0c94051cda67123be68cf6b65211ba3dde7277be9068412de3e7ffd63ef" -dependencies = [ - "bytes", - "curve25519-dalek 3.2.1", - "futures", - "lazy_static", - "libp2p-core", - "log", - "prost", - "prost-build", - "rand 0.8.5", - "sha2 0.10.2", - "snow", - "static_assertions", - "x25519-dalek", - "zeroize", -] - -[[package]] -name = "libp2p-ping" -version = "0.34.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ab44a12d372d6abdd326c468c1d5b002be06fbd923c5a799d6a9d3b36646ca3" -dependencies = [ - "futures", - "futures-timer", - "instant", - "libp2p-core", - "libp2p-swarm", - "log", - "rand 0.7.3", - "void", -] - -[[package]] -name = "libp2p-plaintext" -version = "0.32.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "962c0fb0e7212fb96a69b87f2d09bcefd317935239bdc79cda900e7a8897a3fe" -dependencies = [ - "asynchronous-codec", - "bytes", - "futures", - "libp2p-core", - "log", - "prost", - "prost-build", - "unsigned-varint", - "void", -] - -[[package]] -name = "libp2p-pnet" -version = "0.22.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f1a458bbda880107b5b36fcb9b5a1ef0c329685da0e203ed692a8ebe64cc92c" -dependencies = [ - "futures", - "log", - "pin-project 1.0.10", - "rand 0.7.3", - "salsa20", - "sha3", -] - -[[package]] -name = "libp2p-relay" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "517be90a2ce60b6c3bdfe88f34cc789c61dafe6f694a7b45e644af7353880fa3" -dependencies = [ - "asynchronous-codec", - "bytes", - "either", - "futures", - "futures-timer", - "instant", - "libp2p-core", - "libp2p-swarm", - "log", - "pin-project 1.0.10", - "prost", - "prost-build", - "rand 0.8.5", - "smallvec", - "static_assertions", - "thiserror", - "unsigned-varint", - "void", -] - -[[package]] -name = "libp2p-rendezvous" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "597e4a022dd2e168ce1218faf6b3aead5c427fb828eb4f982cef7c40d4b7f49e" -dependencies = [ - "asynchronous-codec", - "bimap", - "futures", - "futures-timer", - "instant", - "libp2p-core", - "libp2p-swarm", - "log", - "prost", - "prost-build", - "rand 0.8.5", - "sha2 0.10.2", - "thiserror", - "unsigned-varint", - "void", -] - -[[package]] -name = "libp2p-request-response" -version = "0.16.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "12388a73626d1727524069cce0bb05a9c428581de435278a070c55ae27cc7e73" -dependencies = [ - "async-trait", - "bytes", - "futures", - "instant", - "libp2p-core", - "libp2p-swarm", - "log", - "rand 0.7.3", - "smallvec", - "unsigned-varint", -] - -[[package]] -name = "libp2p-swarm" -version = "0.34.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53ab2d4eb8ef2966b10fdf859245cdd231026df76d3c6ed2cf9e418a8f688ec9" -dependencies = [ - "either", - "fnv", - "futures", - "futures-timer", - "instant", - "libp2p-core", - "log", - "pin-project 1.0.10", - "rand 0.7.3", - "smallvec", - "thiserror", - "void", -] - -[[package]] -name = "libp2p-swarm-derive" -version = "0.27.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b8153a6472e84ec888ef2bf21deafe8d4214e811f0f162abbf07156c27f8fa8" -dependencies = [ - "quote", - "syn", -] - -[[package]] -name = "libp2p-tcp" -version = "0.32.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "193447aa729c85aac2376828df76d171c1a589c9e6b58fcc7f9d9a020734122c" -dependencies = [ - "async-io", - "futures", - "futures-timer", - "if-watch", - "ipnet", - "libc", - "libp2p-core", - "log", - "socket2 0.4.4", -] - -[[package]] -name = "libp2p-uds" -version = "0.32.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24bdab114f7f2701757d6541266e1131b429bbae382008f207f2114ee4222dcb" -dependencies = [ - "async-std", - "futures", - "libp2p-core", - "log", -] - -[[package]] -name = "libp2p-wasm-ext" -version = "0.32.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f6ea0f84a967ef59a16083f222c18115ae2e91db69809dce275df62e101b279" -dependencies = [ - "futures", - "js-sys", - "libp2p-core", - "parity-send-wrapper", - "wasm-bindgen", - "wasm-bindgen-futures", -] - -[[package]] -name = "libp2p-websocket" -version = "0.34.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c932834c3754501c368d1bf3d0fb458487a642b90fc25df082a3a2f3d3b32e37" -dependencies = [ - "either", - "futures", - "futures-rustls", - "libp2p-core", - "log", - "quicksink", - "rw-stream-sink", - "soketto", - "url", - "webpki-roots", -] - -[[package]] -name = "libp2p-yamux" -version = "0.36.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be902ebd89193cd020e89e89107726a38cfc0d16d18f613f4a37d046e92c7517" -dependencies = [ - "futures", - "libp2p-core", - "parking_lot 0.12.0", - "thiserror", - "yamux", -] - -[[package]] -name = "libsecp256k1" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0452aac8bab02242429380e9b2f94ea20cea2b37e2c1777a1358799bbe97f37" -dependencies = [ - "arrayref", - "base64 0.13.0", - "digest 0.9.0", - "hmac-drbg", - "libsecp256k1-core", - "libsecp256k1-gen-ecmult", - "libsecp256k1-gen-genmult", - "rand 0.8.5", - "serde", - "sha2 0.9.9", - "typenum", -] - -[[package]] -name = "libsecp256k1-core" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5be9b9bb642d8522a44d533eab56c16c738301965504753b03ad1de3425d5451" -dependencies = [ - "crunchy", - "digest 0.9.0", - "subtle", -] - -[[package]] -name = "libsecp256k1-gen-ecmult" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3038c808c55c87e8a172643a7d87187fc6c4174468159cb3090659d55bcb4809" -dependencies = [ - "libsecp256k1-core", -] - -[[package]] -name = "libsecp256k1-gen-genmult" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3db8d6ba2cec9eacc40e6e8ccc98931840301f1006e95647ceb2dd5c3aa06f7c" -dependencies = [ - "libsecp256k1-core", -] - -[[package]] -name = "libz-sys" -version = "1.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "de5435b8549c16d423ed0c03dbaafe57cf6c3344744f1242520d59c9d8ecec66" -dependencies = [ - "cc", - "pkg-config", - "vcpkg", -] - -[[package]] -name = "linked-hash-map" -version = "0.5.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fb9b38af92608140b86b693604b9ffcc5824240a484d1ecd4795bacb2fe88f3" - -[[package]] -name = "lock_api" -version = "0.4.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88943dd7ef4a2e5a4bfa2753aaab3013e34ce2533d1996fb18ef591e315e2b3b" -dependencies = [ - "scopeguard", -] - -[[package]] -name = "log" -version = "0.4.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "51b9bbe6c47d51fc3e1a9b945965946b4c44142ab8792c50835a980d362c2710" -dependencies = [ - "cfg-if 1.0.0", - "value-bag", -] - -[[package]] -name = "lru" -version = "0.7.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fcb87f3080f6d1d69e8c564c0fcfde1d7aa8cc451ce40cae89479111f03bc0eb" -dependencies = [ - "hashbrown", -] - -[[package]] -name = "lru-cache" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "31e24f1ad8321ca0e8a1e0ac13f23cb668e6f5466c2c57319f6a5cf1cc8e3b1c" -dependencies = [ - "linked-hash-map", -] - -[[package]] -name = "match_cfg" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ffbee8634e0d45d258acb448e7eaab3fce7a0a467395d4d9f228e3c1f01fb2e4" - -[[package]] -name = "matchers" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8263075bb86c5a1b1427b5ae862e8889656f126e9f77c484496e8b47cf5c5558" -dependencies = [ - "regex-automata", -] - -[[package]] -name = "matches" -version = "0.1.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3e378b66a060d48947b590737b30a1be76706c8dd7b8ba0f2fe3989c68a853f" - -[[package]] -name = "memchr" -version = "2.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "308cc39be01b73d0d18f82a0e7b2a3df85245f84af96fdddc5d202d27e47b86a" - -[[package]] -name = "memoffset" -version = "0.6.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5aa361d4faea93603064a027415f07bd8e1d5c88c9fbf68bf56a285428fd79ce" -dependencies = [ - "autocfg", -] - -[[package]] -name = "miniz_oxide" -version = "0.4.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a92518e98c078586bc6c934028adcca4c92a53d6a958196de835170a01d84e4b" -dependencies = [ - "adler", - "autocfg", -] - -[[package]] -name = "mio" -version = "0.7.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8067b404fe97c70829f082dec8bcf4f71225d7eaea1d8645349cb76fa06205cc" -dependencies = [ - "libc", - "log", - "miow", - "ntapi", - "winapi", -] - -[[package]] -name = "miow" -version = "0.3.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9f1c5b025cda876f66ef43a113f91ebc9f4ccef34843000e0adf6ebbab84e21" -dependencies = [ - "winapi", -] - -[[package]] -name = "multiaddr" -version = "0.14.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c580bfdd8803cce319b047d239559a22f809094aaea4ac13902a1fdcfcd4261" -dependencies = [ - "arrayref", - "bs58", - "byteorder", - "data-encoding", - "multihash", - "percent-encoding", - "serde", - "static_assertions", - "unsigned-varint", - "url", -] - -[[package]] -name = "multihash" -version = "0.16.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7392bffd88bc0c4f8297e36a777ab9f80b7127409c4a1acb8fee99c9f27addcd" -dependencies = [ - "core2", - "digest 0.10.3", - "multihash-derive", - "serde", - "serde-big-array", - "sha2 0.10.2", - "unsigned-varint", -] - -[[package]] -name = "multihash-derive" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc076939022111618a5026d3be019fd8b366e76314538ff9a1b59ffbcbf98bcd" -dependencies = [ - "proc-macro-crate", - "proc-macro-error", - "proc-macro2", - "quote", - "syn", - "synstructure", -] - -[[package]] -name = "multimap" -version = "0.8.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5ce46fe64a9d73be07dcbe690a38ce1b293be448fd8ce1e6c1b8062c9f72c6a" - -[[package]] -name = "multistream-select" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "363a84be6453a70e63513660f4894ef815daf88e3356bffcda9ca27d810ce83b" -dependencies = [ - "bytes", - "futures", - "log", - "pin-project 1.0.10", - "smallvec", - "unsigned-varint", -] - -[[package]] -name = "nanorand" -version = "0.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "729eb334247daa1803e0a094d0a5c55711b85571179f5ec6e53eccfdf7008958" -dependencies = [ - "getrandom 0.2.5", -] - -[[package]] -name = "netlink-packet-core" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "345b8ab5bd4e71a2986663e88c56856699d060e78e152e6e9d7966fcd5491297" -dependencies = [ - "anyhow", - "byteorder", - "libc", - "netlink-packet-utils", -] - -[[package]] -name = "netlink-packet-route" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "733ea73609acfd7fa7ddadfb7bf709b0471668c456ad9513685af543a06342b2" -dependencies = [ - "anyhow", - "bitflags", - "byteorder", - "libc", - "netlink-packet-core", - "netlink-packet-utils", -] - -[[package]] -name = "netlink-packet-utils" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25af9cf0dc55498b7bd94a1508af7a78706aa0ab715a73c5169273e03c84845e" -dependencies = [ - "anyhow", - "byteorder", - "paste", - "thiserror", -] - -[[package]] -name = "netlink-proto" -version = "0.9.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef8785b8141e8432aa45fceb922a7e876d7da3fad37fa7e7ec702ace3aa0826b" -dependencies = [ - "bytes", - "futures", - "log", - "netlink-packet-core", - "netlink-sys", - "tokio", -] - -[[package]] -name = "netlink-sys" -version = "0.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e4c9f9547a08241bee7b6558b9b98e1f290d187de8b7cfca2bbb4937bcaa8f8" -dependencies = [ - "async-io", - "bytes", - "futures", - "libc", - "log", -] - -[[package]] -name = "networking-demo" -version = "0.0.0" -dependencies = [ - "async-std", - "async-trait", - "bincode", - "blake3 1.3.1", - "color-eyre", - "crossterm 0.23.0", - "derive_builder", - "flume", - "futures", - "libp2p", - "parking_lot 0.12.0", - "rand 0.8.5", - "serde", - "serde_json", - "snafu", - "structopt", - "tide", - "tracing", - "tracing-error", - "tracing-subscriber", - "tui", -] - -[[package]] -name = "nix" -version = "0.22.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e4916f159ed8e5de0082076562152a76b7a1f64a01fd9d1e0fea002c37624faf" -dependencies = [ - "bitflags", - "cc", - "cfg-if 1.0.0", - "libc", - "memoffset", -] - -[[package]] -name = "nohash-hasher" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2bf50223579dc7cdcfb3bfcacf7069ff68243f8c363f62ffa99cf000a6b9c451" - -[[package]] -name = "ntapi" -version = "0.3.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c28774a7fd2fbb4f0babd8237ce554b73af68021b5f695a3cebd6c59bac0980f" -dependencies = [ - "winapi", -] - -[[package]] -name = "num-integer" -version = "0.1.44" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2cc698a63b549a70bc047073d2949cce27cd1c7b0a4a862d08a8031bc2801db" -dependencies = [ - "autocfg", - "num-traits", -] - -[[package]] -name = "num-traits" -version = "0.2.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a64b1ec5cda2586e284722486d802acf1f7dbdc623e2bfc57e65ca1cd099290" -dependencies = [ - "autocfg", -] - -[[package]] -name = "num_cpus" -version = "1.13.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19e64526ebdee182341572e50e9ad03965aa510cd94427a4549448f285e957a1" -dependencies = [ - "hermit-abi", - "libc", -] - -[[package]] -name = "object" -version = "0.27.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67ac1d3f9a1d3616fd9a60c8d74296f22406a238b6a72f5cc1e6f314df4ffbf9" -dependencies = [ - "memchr", -] - -[[package]] -name = "once_cell" -version = "1.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87f3e037eac156d1775da914196f0f37741a274155e34a0b7e427c35d2a2ecb9" - -[[package]] -name = "opaque-debug" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" - -[[package]] -name = "owning_ref" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ff55baddef9e4ad00f88b6c743a2a8062d4c6ade126c2a528644b8e444d52ce" -dependencies = [ - "stable_deref_trait", -] - -[[package]] -name = "owo-colors" -version = "3.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "20448fd678ec04e6ea15bbe0476874af65e98a01515d667aa49f1434dc44ebf4" - -[[package]] -name = "parity-send-wrapper" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa9777aa91b8ad9dd5aaa04a9b6bcb02c7f1deb952fca5a66034d5e63afc5c6f" - -[[package]] -name = "parking" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "427c3892f9e783d91cc128285287e70a59e206ca452770ece88a76f7a3eddd72" - -[[package]] -name = "parking_lot" -version = "0.11.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d17b78036a60663b797adeaee46f5c9dfebb86948d1255007a1d6be0271ff99" -dependencies = [ - "instant", - "lock_api", - "parking_lot_core 0.8.5", -] - -[[package]] -name = "parking_lot" -version = "0.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87f5ec2493a61ac0506c0f4199f99070cbe83857b0337006a30f3e6719b8ef58" -dependencies = [ - "lock_api", - "parking_lot_core 0.9.1", -] - -[[package]] -name = "parking_lot_core" -version = "0.8.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d76e8e1493bcac0d2766c42737f34458f1c8c50c0d23bcb24ea953affb273216" -dependencies = [ - "cfg-if 1.0.0", - "instant", - "libc", - "redox_syscall", - "smallvec", - "winapi", -] - -[[package]] -name = "parking_lot_core" -version = "0.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28141e0cc4143da2443301914478dc976a61ffdb3f043058310c70df2fed8954" -dependencies = [ - "cfg-if 1.0.0", - "libc", - "redox_syscall", - "smallvec", - "windows-sys", -] - -[[package]] -name = "paste" -version = "1.0.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0744126afe1a6dd7f394cb50a716dbe086cb06e255e53d8d0185d82828358fb5" - -[[package]] -name = "percent-encoding" -version = "2.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e" - -[[package]] -name = "petgraph" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a13a2fa9d0b63e5f22328828741e523766fff0ee9e779316902290dff3f824f" -dependencies = [ - "fixedbitset", - "indexmap", -] - -[[package]] -name = "pin-project" -version = "0.4.29" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9615c18d31137579e9ff063499264ddc1278e7b1982757ebc111028c4d1dc909" -dependencies = [ - "pin-project-internal 0.4.29", -] - -[[package]] -name = "pin-project" -version = "1.0.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "58ad3879ad3baf4e44784bc6a718a8698867bb991f8ce24d1bcbe2cfb4c3a75e" -dependencies = [ - "pin-project-internal 1.0.10", -] - -[[package]] -name = "pin-project-internal" -version = "0.4.29" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "044964427019eed9d49d9d5bbce6047ef18f37100ea400912a9fa4a3523ab12a" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "pin-project-internal" -version = "1.0.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "744b6f092ba29c3650faf274db506afd39944f48420f6c86b17cfe0ee1cb36bb" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "pin-project-lite" -version = "0.1.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "257b64915a082f7811703966789728173279bdebb956b143dbcd23f6f970a777" - -[[package]] -name = "pin-project-lite" -version = "0.2.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e280fbe77cc62c91527259e9442153f4688736748d24660126286329742b4c6c" - -[[package]] -name = "pin-utils" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" - -[[package]] -name = "pkg-config" -version = "0.3.24" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "58893f751c9b0412871a09abd62ecd2a00298c6c83befa223ef98c52aef40cbe" - -[[package]] -name = "polling" -version = "2.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "685404d509889fade3e86fe3a5803bca2ec09b0c0778d5ada6ec8bf7a8de5259" -dependencies = [ - "cfg-if 1.0.0", - "libc", - "log", - "wepoll-ffi", - "winapi", -] - -[[package]] -name = "poly1305" -version = "0.7.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "048aeb476be11a4b6ca432ca569e375810de9294ae78f4774e78ea98a9246ede" -dependencies = [ - "cpufeatures", - "opaque-debug", - "universal-hash", -] - -[[package]] -name = "polyval" -version = "0.4.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eebcc4aa140b9abd2bc40d9c3f7ccec842679cd79045ac3a7ac698c1a064b7cd" -dependencies = [ - "cpuid-bool", - "opaque-debug", - "universal-hash", -] - -[[package]] -name = "polyval" -version = "0.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8419d2b623c7c0896ff2d5d96e2cb4ede590fed28fcc34934f4c33c036e620a1" -dependencies = [ - "cfg-if 1.0.0", - "cpufeatures", - "opaque-debug", - "universal-hash", -] - -[[package]] -name = "ppv-lite86" -version = "0.2.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb9f9e6e233e5c4a35559a617bf40a4ec447db2e84c20b55a6f83167b7e57872" - -[[package]] -name = "proc-macro-crate" -version = "1.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e17d47ce914bf4de440332250b0edd23ce48c005f59fab39d3335866b114f11a" -dependencies = [ - "thiserror", - "toml", -] - -[[package]] -name = "proc-macro-error" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" -dependencies = [ - "proc-macro-error-attr", - "proc-macro2", - "quote", - "syn", - "version_check", -] - -[[package]] -name = "proc-macro-error-attr" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" -dependencies = [ - "proc-macro2", - "quote", - "version_check", -] - -[[package]] -name = "proc-macro-hack" -version = "0.5.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dbf0c48bc1d91375ae5c3cd81e3722dff1abcf81a30960240640d223f59fe0e5" - -[[package]] -name = "proc-macro2" -version = "1.0.36" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7342d5883fbccae1cc37a2353b09c87c9b0f3afd73f5fb9bba687a1f733b029" -dependencies = [ - "unicode-xid", -] - -[[package]] -name = "prometheus-client" -version = "0.15.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c9a896938cc6018c64f279888b8c7559d3725210d5db9a3a1ee6bc7188d51d34" -dependencies = [ - "dtoa", - "itoa", - "owning_ref", - "prometheus-client-derive-text-encode", -] - -[[package]] -name = "prometheus-client-derive-text-encode" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8e12d01b9d66ad9eb4529c57666b6263fc1993cb30261d83ead658fdd932652" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "prost" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "444879275cb4fd84958b1a1d5420d15e6fcf7c235fe47f053c9c2a80aceb6001" -dependencies = [ - "bytes", - "prost-derive", -] - -[[package]] -name = "prost-build" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62941722fb675d463659e49c4f3fe1fe792ff24fe5bbaa9c08cd3b98a1c354f5" -dependencies = [ - "bytes", - "heck 0.3.3", - "itertools", - "lazy_static", - "log", - "multimap", - "petgraph", - "prost", - "prost-types", - "regex", - "tempfile", - "which", -] - -[[package]] -name = "prost-derive" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9cc1a3263e07e0bf68e96268f37665207b49560d98739662cdfaae215c720fe" -dependencies = [ - "anyhow", - "itertools", - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "prost-types" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "534b7a0e836e3c482d2693070f982e39e7611da9695d4d1f5a4b186b51faef0a" -dependencies = [ - "bytes", - "prost", -] - -[[package]] -name = "quick-error" -version = "1.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0" - -[[package]] -name = "quicksink" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77de3c815e5a160b1539c6592796801df2043ae35e123b46d73380cfa57af858" -dependencies = [ - "futures-core", - "futures-sink", - "pin-project-lite 0.1.12", -] - -[[package]] -name = "quote" -version = "1.0.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "864d3e96a899863136fc6e99f3d7cae289dafe43bf2c5ac19b70df7210c0a145" -dependencies = [ - "proc-macro2", -] - -[[package]] -name = "rand" -version = "0.7.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03" -dependencies = [ - "getrandom 0.1.16", - "libc", - "rand_chacha 0.2.2", - "rand_core 0.5.1", - "rand_hc", -] - -[[package]] -name = "rand" -version = "0.8.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" -dependencies = [ - "libc", - "rand_chacha 0.3.1", - "rand_core 0.6.3", -] - -[[package]] -name = "rand_chacha" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4c8ed856279c9737206bf725bf36935d8666ead7aa69b52be55af369d193402" -dependencies = [ - "ppv-lite86", - "rand_core 0.5.1", -] - -[[package]] -name = "rand_chacha" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" -dependencies = [ - "ppv-lite86", - "rand_core 0.6.3", -] - -[[package]] -name = "rand_core" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19" -dependencies = [ - "getrandom 0.1.16", -] - -[[package]] -name = "rand_core" -version = "0.6.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d34f1408f55294453790c48b2f1ebbb1c5b4b7563eb1f418bcfcfdbb06ebb4e7" -dependencies = [ - "getrandom 0.2.5", -] - -[[package]] -name = "rand_hc" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c" -dependencies = [ - "rand_core 0.5.1", -] - -[[package]] -name = "redox_syscall" -version = "0.2.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8380fe0152551244f0747b1bf41737e0f8a74f97a14ccefd1148187271634f3c" -dependencies = [ - "bitflags", -] - -[[package]] -name = "regex" -version = "1.5.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d07a8629359eb56f1e2fb1652bb04212c072a87ba68546a04065d525673ac461" -dependencies = [ - "aho-corasick", - "memchr", - "regex-syntax", -] - -[[package]] -name = "regex-automata" -version = "0.1.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132" -dependencies = [ - "regex-syntax", -] - -[[package]] -name = "regex-syntax" -version = "0.6.25" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f497285884f3fcff424ffc933e56d7cbca511def0c9831a7f9b5f6153e3cc89b" - -[[package]] -name = "remove_dir_all" -version = "0.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3acd125665422973a33ac9d3dd2df85edad0f4ae9b00dafb1a05e43a9f5ef8e7" -dependencies = [ - "winapi", -] - -[[package]] -name = "resolv-conf" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "52e44394d2086d010551b14b53b1f24e31647570cd1deb0379e2c21b329aba00" -dependencies = [ - "hostname", - "quick-error", -] - -[[package]] -name = "ring" -version = "0.16.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3053cf52e236a3ed746dfc745aa9cacf1b791d846bdaf412f60a8d7d6e17c8fc" -dependencies = [ - "cc", - "libc", - "once_cell", - "spin 0.5.2", - "untrusted", - "web-sys", - "winapi", -] - -[[package]] -name = "route-recognizer" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56770675ebc04927ded3e60633437841581c285dc6236109ea25fbf3beb7b59e" - -[[package]] -name = "rtnetlink" -version = "0.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f54290e54521dac3de4149d83ddf9f62a359b3cc93bcb494a794a41e6f4744b" -dependencies = [ - "async-global-executor", - "futures", - "log", - "netlink-packet-route", - "netlink-proto", - "nix", - "thiserror", -] - -[[package]] -name = "rustc-demangle" -version = "0.1.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ef03e0a2b150c7a90d01faf6254c9c48a41e95fb2a8c2ac1c6f0d2b9aefc342" - -[[package]] -name = "rustc_version" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" -dependencies = [ - "semver 0.9.0", -] - -[[package]] -name = "rustc_version" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" -dependencies = [ - "semver 1.0.6", -] - -[[package]] -name = "rustls" -version = "0.20.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fbfeb8d0ddb84706bc597a5574ab8912817c52a397f819e5b614e2265206921" -dependencies = [ - "log", - "ring", - "sct", - "webpki", -] - -[[package]] -name = "rw-stream-sink" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4da5fcb054c46f5a5dff833b129285a93d3f0179531735e6c866e8cc307d2020" -dependencies = [ - "futures", - "pin-project 0.4.29", - "static_assertions", -] - -[[package]] -name = "ryu" -version = "1.0.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73b4b750c782965c211b42f022f59af1fbceabdd026623714f104152f1ec149f" - -[[package]] -name = "salsa20" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c0fbb5f676da676c260ba276a8f43a8dc67cf02d1438423aeb1c677a7212686" -dependencies = [ - "cipher 0.3.0", -] - -[[package]] -name = "scopeguard" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" - -[[package]] -name = "sct" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d53dcdb7c9f8158937a7981b48accfd39a43af418591a5d008c7b22b5e1b7ca4" -dependencies = [ - "ring", - "untrusted", -] - -[[package]] -name = "semver" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" -dependencies = [ - "semver-parser", -] - -[[package]] -name = "semver" -version = "1.0.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4a3381e03edd24287172047536f20cabde766e2cd3e65e6b00fb3af51c4f38d" - -[[package]] -name = "semver-parser" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" - -[[package]] -name = "serde" -version = "1.0.136" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce31e24b01e1e524df96f1c2fdd054405f8d7376249a5110886fb4b658484789" -dependencies = [ - "serde_derive", -] - -[[package]] -name = "serde-big-array" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "18b20e7752957bbe9661cff4e0bb04d183d0948cdab2ea58cdb9df36a61dfe62" -dependencies = [ - "serde", - "serde_derive", -] - -[[package]] -name = "serde_derive" -version = "1.0.136" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08597e7152fcd306f41838ed3e37be9eaeed2b61c42e2117266a554fab4662f9" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "serde_json" -version = "1.0.79" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e8d9fa5c3b304765ce1fd9c4c8a3de2c8db365a5b91be52f186efc675681d95" -dependencies = [ - "itoa", - "ryu", - "serde", -] - -[[package]] -name = "serde_qs" -version = "0.8.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7715380eec75f029a4ef7de39a9200e0a63823176b759d055b613f5a87df6a6" -dependencies = [ - "percent-encoding", - "serde", - "thiserror", -] - -[[package]] -name = "serde_urlencoded" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" -dependencies = [ - "form_urlencoded", - "itoa", - "ryu", - "serde", -] - -[[package]] -name = "sha-1" -version = "0.9.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "99cd6713db3cf16b6c84e06321e049a9b9f699826e16096d23bbcc44d15d51a6" -dependencies = [ - "block-buffer 0.9.0", - "cfg-if 1.0.0", - "cpufeatures", - "digest 0.9.0", - "opaque-debug", -] - -[[package]] -name = "sha1" -version = "0.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1da05c97445caa12d05e848c4a4fcbbea29e748ac28f7e80e9b010392063770" -dependencies = [ - "sha1_smol", -] - -[[package]] -name = "sha1_smol" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae1a47186c03a32177042e55dbc5fd5aee900b8e0069a8d70fba96a9375cd012" - -[[package]] -name = "sha2" -version = "0.9.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d58a1e1bf39749807d89cf2d98ac2dfa0ff1cb3faa38fbb64dd88ac8013d800" -dependencies = [ - "block-buffer 0.9.0", - "cfg-if 1.0.0", - "cpufeatures", - "digest 0.9.0", - "opaque-debug", -] - -[[package]] -name = "sha2" -version = "0.10.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "55deaec60f81eefe3cce0dc50bda92d6d8e88f2a27df7c5033b42afeb1ed2676" -dependencies = [ - "cfg-if 1.0.0", - "cpufeatures", - "digest 0.10.3", -] - -[[package]] -name = "sha3" -version = "0.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f81199417d4e5de3f04b1e871023acea7389672c4135918f05aa9cbf2f2fa809" -dependencies = [ - "block-buffer 0.9.0", - "digest 0.9.0", - "keccak", - "opaque-debug", -] - -[[package]] -name = "sharded-slab" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "900fba806f70c630b0a382d0d825e17a0f19fcd059a2ade1ff237bcddf446b31" -dependencies = [ - "lazy_static", -] - -[[package]] -name = "signal-hook" -version = "0.3.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "647c97df271007dcea485bb74ffdb57f2e683f1306c854f468a0c244badabf2d" -dependencies = [ - "libc", - "signal-hook-registry", -] - -[[package]] -name = "signal-hook-mio" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "29fd5867f1c4f2c5be079aee7a2adf1152ebb04a4bc4d341f504b7dece607ed4" -dependencies = [ - "libc", - "mio", - "signal-hook", -] - -[[package]] -name = "signal-hook-registry" -version = "1.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e51e73328dc4ac0c7ccbda3a494dfa03df1de2f46018127f60c693f2648455b0" -dependencies = [ - "libc", -] - -[[package]] -name = "signature" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f054c6c1a6e95179d6f23ed974060dcefb2d9388bb7256900badad682c499de4" - -[[package]] -name = "simple-mutex" -version = "1.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38aabbeafa6f6dead8cebf246fe9fae1f9215c8d29b3a69f93bd62a9e4a3dcd6" -dependencies = [ - "event-listener", -] - -[[package]] -name = "slab" -version = "0.4.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9def91fd1e018fe007022791f865d0ccc9b3a0d5001e01aabb8b40e46000afb5" - -[[package]] -name = "smallvec" -version = "1.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2dd574626839106c320a323308629dcb1acfc96e32a8cba364ddc61ac23ee83" - -[[package]] -name = "snafu" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2eba135d2c579aa65364522eb78590cdf703176ef71ad4c32b00f58f7afb2df5" -dependencies = [ - "doc-comment", - "snafu-derive", -] - -[[package]] -name = "snafu-derive" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a7fe9b0669ef117c5cabc5549638528f36771f058ff977d7689deb517833a75" -dependencies = [ - "heck 0.3.3", - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "snow" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "774d05a3edae07ce6d68ea6984f3c05e9bba8927e3dd591e3b479e5b03213d0d" -dependencies = [ - "aes-gcm 0.9.4", - "blake2", - "chacha20poly1305", - "curve25519-dalek 4.0.0-pre.2", - "rand_core 0.6.3", - "ring", - "rustc_version 0.4.0", - "sha2 0.10.2", - "subtle", -] - -[[package]] -name = "socket2" -version = "0.3.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "122e570113d28d773067fab24266b66753f6ea915758651696b6e35e49f88d6e" -dependencies = [ - "cfg-if 1.0.0", - "libc", - "winapi", -] - -[[package]] -name = "socket2" -version = "0.4.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "66d72b759436ae32898a2af0a14218dbf55efde3feeb170eb623637db85ee1e0" -dependencies = [ - "libc", - "winapi", -] - -[[package]] -name = "soketto" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41d1c5305e39e09653383c2c7244f2f78b3bcae37cf50c64cb4789c9f5096ec2" -dependencies = [ - "base64 0.13.0", - "bytes", - "flate2", - "futures", - "httparse", - "log", - "rand 0.8.5", - "sha-1", -] - -[[package]] -name = "spin" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" - -[[package]] -name = "spin" -version = "0.9.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "511254be0c5bcf062b019a6c89c01a664aa359ded62f78aa72c6fc137c0590e5" -dependencies = [ - "lock_api", -] - -[[package]] -name = "stable_deref_trait" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" - -[[package]] -name = "standback" -version = "0.2.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e113fb6f3de07a243d434a56ec6f186dfd51cb08448239fe7bcae73f87ff28ff" -dependencies = [ - "version_check", -] - -[[package]] -name = "static_assertions" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" - -[[package]] -name = "stdweb" -version = "0.4.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d022496b16281348b52d0e30ae99e01a73d737b2f45d38fed4edf79f9325a1d5" -dependencies = [ - "discard", - "rustc_version 0.2.3", - "stdweb-derive", - "stdweb-internal-macros", - "stdweb-internal-runtime", - "wasm-bindgen", -] - -[[package]] -name = "stdweb-derive" -version = "0.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c87a60a40fccc84bef0652345bbbbbe20a605bf5d0ce81719fc476f5c03b50ef" -dependencies = [ - "proc-macro2", - "quote", - "serde", - "serde_derive", - "syn", -] - -[[package]] -name = "stdweb-internal-macros" -version = "0.2.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "58fa5ff6ad0d98d1ffa8cb115892b6e69d67799f6763e162a1c9db421dc22e11" -dependencies = [ - "base-x", - "proc-macro2", - "quote", - "serde", - "serde_derive", - "serde_json", - "sha1", - "syn", -] - -[[package]] -name = "stdweb-internal-runtime" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "213701ba3370744dcd1a12960caa4843b3d68b4d1c0a5d575e0d65b2ee9d16c0" - -[[package]] -name = "strsim" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" - -[[package]] -name = "strsim" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" - -[[package]] -name = "structopt" -version = "0.3.26" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c6b5c64445ba8094a6ab0c3cd2ad323e07171012d9c98b0b15651daf1787a10" -dependencies = [ - "clap", - "lazy_static", - "structopt-derive", -] - -[[package]] -name = "structopt-derive" -version = "0.4.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dcb5ae327f9cc13b68763b5749770cb9e048a99bd9dfdfa58d0cf05d5f64afe0" -dependencies = [ - "heck 0.3.3", - "proc-macro-error", - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "subtle" -version = "2.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6bdef32e8150c2a081110b42772ffe7d7c9032b606bc226c8260fd97e0976601" - -[[package]] -name = "sval" -version = "1.0.0-alpha.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "45f6ee7c7b87caf59549e9fe45d6a69c75c8019e79e212a835c5da0e92f0ba08" - -[[package]] -name = "syn" -version = "1.0.86" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a65b3f4ffa0092e9887669db0eae07941f023991ab58ea44da8fe8e2d511c6b" -dependencies = [ - "proc-macro2", - "quote", - "unicode-xid", -] - -[[package]] -name = "synstructure" -version = "0.12.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f36bdaa60a83aca3921b5259d5400cbf5e90fc51931376a9bd4a0eb79aa7210f" -dependencies = [ - "proc-macro2", - "quote", - "syn", - "unicode-xid", -] - -[[package]] -name = "system-configuration" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d75182f12f490e953596550b65ee31bda7c8e043d9386174b353bda50838c3fd" -dependencies = [ - "bitflags", - "core-foundation", - "system-configuration-sys", -] - -[[package]] -name = "system-configuration-sys" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a75fb188eb626b924683e3b95e3a48e63551fcfb51949de2f06a9d91dbee93c9" -dependencies = [ - "core-foundation-sys", - "libc", -] - -[[package]] -name = "tempfile" -version = "3.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5cdb1ef4eaeeaddc8fbd371e5017057064af0911902ef36b39801f67cc6d79e4" -dependencies = [ - "cfg-if 1.0.0", - "fastrand", - "libc", - "redox_syscall", - "remove_dir_all", - "winapi", -] - -[[package]] -name = "textwrap" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060" -dependencies = [ - "unicode-width", -] - -[[package]] -name = "thiserror" -version = "1.0.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "854babe52e4df1653706b98fcfc05843010039b406875930a70e4d9644e5c417" -dependencies = [ - "thiserror-impl", -] - -[[package]] -name = "thiserror-impl" -version = "1.0.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa32fd3f627f367fe16f893e2597ae3c05020f8bba2666a4e6ea73d377e5714b" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "thread_local" -version = "1.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5516c27b78311c50bf42c071425c560ac799b11c30b31f87e3081965fe5e0180" -dependencies = [ - "once_cell", -] - -[[package]] -name = "tide" -version = "0.16.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c459573f0dd2cc734b539047f57489ea875af8ee950860ded20cf93a79a1dee0" -dependencies = [ - "async-h1", - "async-session", - "async-sse", - "async-std", - "async-trait", - "femme", - "futures-util", - "http-client", - "http-types", - "kv-log-macro", - "log", - "pin-project-lite 0.2.8", - "route-recognizer", - "serde", - "serde_json", -] - -[[package]] -name = "time" -version = "0.1.43" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca8a50ef2360fbd1eeb0ecd46795a87a19024eb4b53c5dc916ca1fd95fe62438" -dependencies = [ - "libc", - "winapi", -] - -[[package]] -name = "time" -version = "0.2.27" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4752a97f8eebd6854ff91f1c1824cd6160626ac4bd44287f7f4ea2035a02a242" -dependencies = [ - "const_fn", - "libc", - "standback", - "stdweb", - "time-macros", - "version_check", - "winapi", -] - -[[package]] -name = "time-macros" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "957e9c6e26f12cb6d0dd7fc776bb67a706312e7299aed74c8dd5b17ebb27e2f1" -dependencies = [ - "proc-macro-hack", - "time-macros-impl", -] - -[[package]] -name = "time-macros-impl" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd3c141a1b43194f3f56a1411225df8646c55781d5f26db825b3d98507eb482f" -dependencies = [ - "proc-macro-hack", - "proc-macro2", - "quote", - "standback", - "syn", -] - -[[package]] -name = "tinyvec" -version = "1.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c1c1d5a42b6245520c249549ec267180beaffcc0615401ac8e31853d4b6d8d2" -dependencies = [ - "tinyvec_macros", -] - -[[package]] -name = "tinyvec_macros" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c" - -[[package]] -name = "tokio" -version = "1.17.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2af73ac49756f3f7c01172e34a23e5d0216f6c32333757c2c61feb2bbff5a5ee" -dependencies = [ - "bytes", - "memchr", - "pin-project-lite 0.2.8", -] - -[[package]] -name = "toml" -version = "0.5.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a31142970826733df8241ef35dc040ef98c679ab14d7c3e54d827099b3acecaa" -dependencies = [ - "serde", -] - -[[package]] -name = "tracing" -version = "0.1.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6c650a8ef0cd2dd93736f033d21cbd1224c5a967aa0c258d00fcf7dafef9b9f" -dependencies = [ - "cfg-if 1.0.0", - "pin-project-lite 0.2.8", - "tracing-attributes", - "tracing-core", -] - -[[package]] -name = "tracing-attributes" -version = "0.1.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8276d9a4a3a558d7b7ad5303ad50b53d58264641b82914b7ada36bd762e7a716" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "tracing-core" -version = "0.1.22" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03cfcb51380632a72d3111cb8d3447a8d908e577d31beeac006f836383d29a23" -dependencies = [ - "lazy_static", - "valuable", -] - -[[package]] -name = "tracing-error" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d686ec1c0f384b1277f097b2f279a2ecc11afe8c133c1aabf036a27cb4cd206e" -dependencies = [ - "tracing", - "tracing-subscriber", -] - -[[package]] -name = "tracing-log" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a6923477a48e41c1951f1999ef8bb5a3023eb723ceadafe78ffb65dc366761e3" -dependencies = [ - "lazy_static", - "log", - "tracing-core", -] - -[[package]] -name = "tracing-serde" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc6b213177105856957181934e4920de57730fc69bf42c37ee5bb664d406d9e1" -dependencies = [ - "serde", - "tracing-core", -] - -[[package]] -name = "tracing-subscriber" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e0ab7bdc962035a87fba73f3acca9b8a8d0034c2e6f60b84aeaaddddc155dce" -dependencies = [ - "ansi_term", - "lazy_static", - "matchers", - "regex", - "serde", - "serde_json", - "sharded-slab", - "smallvec", - "thread_local", - "tracing", - "tracing-core", - "tracing-log", - "tracing-serde", -] - -[[package]] -name = "trust-dns-proto" -version = "0.20.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca94d4e9feb6a181c690c4040d7a24ef34018d8313ac5044a61d21222ae24e31" -dependencies = [ - "async-trait", - "cfg-if 1.0.0", - "data-encoding", - "enum-as-inner", - "futures-channel", - "futures-io", - "futures-util", - "idna", - "ipnet", - "lazy_static", - "log", - "rand 0.8.5", - "smallvec", - "thiserror", - "tinyvec", - "url", -] - -[[package]] -name = "trust-dns-resolver" -version = "0.20.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ecae383baad9995efaa34ce8e57d12c3f305e545887472a492b838f4b5cfb77a" -dependencies = [ - "cfg-if 1.0.0", - "futures-util", - "ipconfig", - "lazy_static", - "log", - "lru-cache", - "parking_lot 0.11.2", - "resolv-conf", - "smallvec", - "thiserror", - "trust-dns-proto", -] - -[[package]] -name = "tui" -version = "0.17.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23ed0a32c88b039b73f1b6c5acbd0554bfa5b6be94467375fd947c4de3a02271" -dependencies = [ - "bitflags", - "cassowary", - "crossterm 0.22.1", - "unicode-segmentation", - "unicode-width", -] - -[[package]] -name = "typenum" -version = "1.15.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dcf81ac59edc17cc8697ff311e8f5ef2d99fcbd9817b34cec66f90b6c3dfd987" - -[[package]] -name = "uint" -version = "0.9.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "12f03af7ccf01dd611cc450a0d10dbc9b745770d096473e2faf0ca6e2d66d1e0" -dependencies = [ - "byteorder", - "crunchy", - "hex", - "static_assertions", -] - -[[package]] -name = "unicode-bidi" -version = "0.3.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a01404663e3db436ed2746d9fefef640d868edae3cceb81c3b8d5732fda678f" - -[[package]] -name = "unicode-normalization" -version = "0.1.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d54590932941a9e9266f0832deed84ebe1bf2e4c9e4a3554d393d18f5e854bf9" -dependencies = [ - "tinyvec", -] - -[[package]] -name = "unicode-segmentation" -version = "1.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e8820f5d777f6224dc4be3632222971ac30164d4a258d595640799554ebfd99" - -[[package]] -name = "unicode-width" -version = "0.1.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ed742d4ea2bd1176e236172c8429aaf54486e7ac098db29ffe6529e0ce50973" - -[[package]] -name = "unicode-xid" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3" - -[[package]] -name = "universal-hash" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f214e8f697e925001e66ec2c6e37a4ef93f0f78c2eed7814394e10c62025b05" -dependencies = [ - "generic-array", - "subtle", -] - -[[package]] -name = "unsigned-varint" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d86a8dc7f45e4c1b0d30e43038c38f274e77af056aa5f74b93c2cf9eb3c1c836" -dependencies = [ - "asynchronous-codec", - "bytes", - "futures-io", - "futures-util", -] - -[[package]] -name = "untrusted" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a" - -[[package]] -name = "url" -version = "2.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a507c383b2d33b5fc35d1861e77e6b383d158b2da5e14fe51b83dfedf6fd578c" -dependencies = [ - "form_urlencoded", - "idna", - "matches", - "percent-encoding", - "serde", -] - -[[package]] -name = "valuable" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d" - -[[package]] -name = "value-bag" -version = "1.0.0-alpha.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "79923f7731dc61ebfba3633098bf3ac533bbd35ccd8c57e7088d9a5eebe0263f" -dependencies = [ - "ctor", - "sval", - "version_check", -] - -[[package]] -name = "vcpkg" -version = "0.2.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" - -[[package]] -name = "vec_map" -version = "0.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191" - -[[package]] -name = "version_check" -version = "0.9.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" - -[[package]] -name = "void" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" - -[[package]] -name = "waker-fn" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d5b2c62b4012a3e1eca5a7e077d13b3bf498c4073e33ccd58626607748ceeca" - -[[package]] -name = "wasi" -version = "0.9.0+wasi-snapshot-preview1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519" - -[[package]] -name = "wasi" -version = "0.10.2+wasi-snapshot-preview1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6" - -[[package]] -name = "wasm-bindgen" -version = "0.2.79" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25f1af7423d8588a3d840681122e72e6a24ddbcb3f0ec385cac0d12d24256c06" -dependencies = [ - "cfg-if 1.0.0", - "serde", - "serde_json", - "wasm-bindgen-macro", -] - -[[package]] -name = "wasm-bindgen-backend" -version = "0.2.79" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b21c0df030f5a177f3cba22e9bc4322695ec43e7257d865302900290bcdedca" -dependencies = [ - "bumpalo", - "lazy_static", - "log", - "proc-macro2", - "quote", - "syn", - "wasm-bindgen-shared", -] - -[[package]] -name = "wasm-bindgen-futures" -version = "0.4.29" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2eb6ec270a31b1d3c7e266b999739109abce8b6c87e4b31fcfcd788b65267395" -dependencies = [ - "cfg-if 1.0.0", - "js-sys", - "wasm-bindgen", - "web-sys", -] - -[[package]] -name = "wasm-bindgen-macro" -version = "0.2.79" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f4203d69e40a52ee523b2529a773d5ffc1dc0071801c87b3d270b471b80ed01" -dependencies = [ - "quote", - "wasm-bindgen-macro-support", -] - -[[package]] -name = "wasm-bindgen-macro-support" -version = "0.2.79" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfa8a30d46208db204854cadbb5d4baf5fcf8071ba5bf48190c3e59937962ebc" -dependencies = [ - "proc-macro2", - "quote", - "syn", - "wasm-bindgen-backend", - "wasm-bindgen-shared", -] - -[[package]] -name = "wasm-bindgen-shared" -version = "0.2.79" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d958d035c4438e28c70e4321a2911302f10135ce78a9c7834c0cab4123d06a2" - -[[package]] -name = "wasm-timer" -version = "0.2.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be0ecb0db480561e9a7642b5d3e4187c128914e58aa84330b9493e3eb68c5e7f" -dependencies = [ - "futures", - "js-sys", - "parking_lot 0.11.2", - "pin-utils", - "wasm-bindgen", - "wasm-bindgen-futures", - "web-sys", -] - -[[package]] -name = "web-sys" -version = "0.3.56" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c060b319f29dd25724f09a2ba1418f142f539b2be99fbf4d2d5a8f7330afb8eb" -dependencies = [ - "js-sys", - "wasm-bindgen", -] - -[[package]] -name = "webpki" -version = "0.22.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f095d78192e208183081cc07bc5515ef55216397af48b873e5edcd72637fa1bd" -dependencies = [ - "ring", - "untrusted", -] - -[[package]] -name = "webpki-roots" -version = "0.22.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "552ceb903e957524388c4d3475725ff2c8b7960922063af6ce53c9a43da07449" -dependencies = [ - "webpki", -] - -[[package]] -name = "wepoll-ffi" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d743fdedc5c64377b5fc2bc036b01c7fd642205a0d96356034ae3404d49eb7fb" -dependencies = [ - "cc", -] - -[[package]] -name = "which" -version = "4.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a5a7e487e921cf220206864a94a89b6c6905bfc19f1057fa26a4cb360e5c1d2" -dependencies = [ - "either", - "lazy_static", - "libc", -] - -[[package]] -name = "widestring" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c168940144dd21fd8046987c16a46a33d5fc84eec29ef9dcddc2ac9e31526b7c" - -[[package]] -name = "winapi" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" -dependencies = [ - "winapi-i686-pc-windows-gnu", - "winapi-x86_64-pc-windows-gnu", -] - -[[package]] -name = "winapi-i686-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" - -[[package]] -name = "winapi-x86_64-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" - -[[package]] -name = "windows" -version = "0.29.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aac7fef12f4b59cd0a29339406cc9203ab44e440ddff6b3f5a41455349fa9cf3" -dependencies = [ - "windows_aarch64_msvc 0.29.0", - "windows_i686_gnu 0.29.0", - "windows_i686_msvc 0.29.0", - "windows_x86_64_gnu 0.29.0", - "windows_x86_64_msvc 0.29.0", -] - -[[package]] -name = "windows-sys" -version = "0.32.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3df6e476185f92a12c072be4a189a0210dcdcf512a1891d6dff9edb874deadc6" -dependencies = [ - "windows_aarch64_msvc 0.32.0", - "windows_i686_gnu 0.32.0", - "windows_i686_msvc 0.32.0", - "windows_x86_64_gnu 0.32.0", - "windows_x86_64_msvc 0.32.0", -] - -[[package]] -name = "windows_aarch64_msvc" -version = "0.29.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3d027175d00b01e0cbeb97d6ab6ebe03b12330a35786cbaca5252b1c4bf5d9b" - -[[package]] -name = "windows_aarch64_msvc" -version = "0.32.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8e92753b1c443191654ec532f14c199742964a061be25d77d7a96f09db20bf5" - -[[package]] -name = "windows_i686_gnu" -version = "0.29.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8793f59f7b8e8b01eda1a652b2697d87b93097198ae85f823b969ca5b89bba58" - -[[package]] -name = "windows_i686_gnu" -version = "0.32.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a711c68811799e017b6038e0922cb27a5e2f43a2ddb609fe0b6f3eeda9de615" - -[[package]] -name = "windows_i686_msvc" -version = "0.29.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8602f6c418b67024be2996c512f5f995de3ba417f4c75af68401ab8756796ae4" - -[[package]] -name = "windows_i686_msvc" -version = "0.32.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "146c11bb1a02615db74680b32a68e2d61f553cc24c4eb5b4ca10311740e44172" - -[[package]] -name = "windows_x86_64_gnu" -version = "0.29.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3d615f419543e0bd7d2b3323af0d86ff19cbc4f816e6453f36a2c2ce889c354" - -[[package]] -name = "windows_x86_64_gnu" -version = "0.32.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c912b12f7454c6620635bbff3450962753834be2a594819bd5e945af18ec64bc" - -[[package]] -name = "windows_x86_64_msvc" -version = "0.29.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11d95421d9ed3672c280884da53201a5c46b7b2765ca6faf34b0d71cf34a3561" - -[[package]] -name = "windows_x86_64_msvc" -version = "0.32.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "504a2476202769977a040c6364301a3f65d0cc9e3fb08600b2bda150a0488316" - -[[package]] -name = "winreg" -version = "0.6.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2986deb581c4fe11b621998a5e53361efe6b48a151178d0cd9eeffa4dc6acc9" -dependencies = [ - "winapi", -] - -[[package]] -name = "x25519-dalek" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2392b6b94a576b4e2bf3c5b2757d63f10ada8020a2e4d08ac849ebcf6ea8e077" -dependencies = [ - "curve25519-dalek 3.2.1", - "rand_core 0.5.1", - "zeroize", -] - -[[package]] -name = "yamux" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "29d4c1dd079043fe673e79fe3c3a260ae2d2fb413f1062cae9e062748df0df03" -dependencies = [ - "futures", - "log", - "nohash-hasher", - "parking_lot 0.11.2", - "rand 0.8.5", - "static_assertions", -] - -[[package]] -name = "zeroize" -version = "1.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4756f7db3f7b5574938c3eb1c117038b8e07f95ee6718c0efad4ac21508f1efd" -dependencies = [ - "zeroize_derive", -] - -[[package]] -name = "zeroize_derive" -version = "1.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f8f187641dad4f680d25c4bfc4225b418165984179f26ca76ec4fb6441d3a17" -dependencies = [ - "proc-macro2", - "quote", - "syn", - "synstructure", -] From b4e40ded93d9dbad26991385e69a85993a82798e Mon Sep 17 00:00:00 2001 From: Victor Koenders Date: Mon, 7 Mar 2022 17:15:13 +0100 Subject: [PATCH 106/107] Merged libp2p-networking and phaselock's .github folder --- .../.github => .github}/actions-rs/grcov.yml | 0 .github/dependabot.yml | 7 ++++++- .../workflows/build_libp2p_networking.yml | 2 +- .../workflows/coverage_libp2p_networking.yml | 2 +- libp2p-networking/.github/dependabot.yml | 11 ----------- 5 files changed, 8 insertions(+), 14 deletions(-) rename {libp2p-networking/.github => .github}/actions-rs/grcov.yml (100%) rename libp2p-networking/.github/workflows/build.yml => .github/workflows/build_libp2p_networking.yml (97%) rename libp2p-networking/.github/workflows/coverage.yml => .github/workflows/coverage_libp2p_networking.yml (97%) delete mode 100644 libp2p-networking/.github/dependabot.yml diff --git a/libp2p-networking/.github/actions-rs/grcov.yml b/.github/actions-rs/grcov.yml similarity index 100% rename from libp2p-networking/.github/actions-rs/grcov.yml rename to .github/actions-rs/grcov.yml diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 9f0a052da1..0218212ac4 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -8,4 +8,9 @@ updates: - package-ecosystem: "cargo" directory: "/" schedule: - interval: "daily" \ No newline at end of file + interval: "daily" + + - package-ecosystem: "cargo" + directory: "/libp2p-networking" + schedule: + interval: "daily" diff --git a/libp2p-networking/.github/workflows/build.yml b/.github/workflows/build_libp2p_networking.yml similarity index 97% rename from libp2p-networking/.github/workflows/build.yml rename to .github/workflows/build_libp2p_networking.yml index 8b8c2be799..9ce38f35d1 100644 --- a/libp2p-networking/.github/workflows/build.yml +++ b/.github/workflows/build_libp2p_networking.yml @@ -1,4 +1,4 @@ -name: Build +name: Build (libp2p-networking) on: push: diff --git a/libp2p-networking/.github/workflows/coverage.yml b/.github/workflows/coverage_libp2p_networking.yml similarity index 97% rename from libp2p-networking/.github/workflows/coverage.yml rename to .github/workflows/coverage_libp2p_networking.yml index 71b2d478bd..20ecd6fbb3 100644 --- a/libp2p-networking/.github/workflows/coverage.yml +++ b/.github/workflows/coverage_libp2p_networking.yml @@ -1,4 +1,4 @@ -name: Code Coverage +name: Code Coverage (libp2p-newtorking) on: push: diff --git a/libp2p-networking/.github/dependabot.yml b/libp2p-networking/.github/dependabot.yml deleted file mode 100644 index d69e05329a..0000000000 --- a/libp2p-networking/.github/dependabot.yml +++ /dev/null @@ -1,11 +0,0 @@ -version: 2 -updates: - - package-ecosystem: "github-actions" - directory: "/" - schedule: - interval: "daily" - - - package-ecosystem: "cargo" - directory: "/" - schedule: - interval: "daily" From 16438e4c5ac387cec8f21d299cb31d5754eabf84 Mon Sep 17 00:00:00 2001 From: Victor Koenders Date: Mon, 7 Mar 2022 17:30:42 +0100 Subject: [PATCH 107/107] Fixed links in libp2p_networking CI --- .github/workflows/build_libp2p_networking.yml | 14 +++++---- .../workflows/coverage_libp2p_networking.yml | 29 ++++++++++--------- 2 files changed, 23 insertions(+), 20 deletions(-) diff --git a/.github/workflows/build_libp2p_networking.yml b/.github/workflows/build_libp2p_networking.yml index 9ce38f35d1..d942c2b64c 100644 --- a/.github/workflows/build_libp2p_networking.yml +++ b/.github/workflows/build_libp2p_networking.yml @@ -40,14 +40,16 @@ jobs: uses: actions-rs/clippy-check@v1 with: token: ${{ github.token }} + args: --manifest-path libp2p-networking/Cargo.toml - - name: Audit - uses: actions-rs/audit-check@v1 - with: - token: ${{ github.token }} + # Does not work with a nested dir + # - name: Audit + # uses: actions-rs/audit-check@v1 + # with: + # token: ${{ github.token }} - name: Cargo Build - run: cargo build --release + run: cargo build --release --manifest-path libp2p-networking/Cargo.toml - name: Cargo Test - run: cargo test --verbose --release test_stress -- -Zunstable-options --report-time --test-threads=1 + run: cargo test --verbose --release test_stress --manifest-path libp2p-networking/Cargo.toml -- -Zunstable-options --report-time --test-threads=1 diff --git a/.github/workflows/coverage_libp2p_networking.yml b/.github/workflows/coverage_libp2p_networking.yml index 20ecd6fbb3..77b7874389 100644 --- a/.github/workflows/coverage_libp2p_networking.yml +++ b/.github/workflows/coverage_libp2p_networking.yml @@ -34,19 +34,20 @@ jobs: RUSTFLAGS: '-Zprofile -Ccodegen-units=1 -Cinline-threshold=0 -Clink-dead-code -Coverflow-checks=off -Cpanic=abort -Zpanic_abort_tests' RUSTDOCFLAGS: '-Zprofile -Ccodegen-units=1 -Cinline-threshold=0 -Clink-dead-code -Coverflow-checks=off -Cpanic=abort -Zpanic_abort_tests' - - name: Install grcov - run: | - wget -O grcov.tar.gz https://github.com/mozilla/grcov/releases/download/v0.8.2/grcov-linux-x86_64.tar.bz2 - tar -xvf grcov.tar.gz - sudo mv -v grcov /home/runner/.cargo/bin/ - rm -rv grcov.tar.gz + # TODO: Seems like we can't override the path where grcov runs, so we're currently code coveraging the main repo + # - name: Install grcov + # run: | + # wget -O grcov.tar.gz https://github.com/mozilla/grcov/releases/download/v0.8.2/grcov-linux-x86_64.tar.bz2 + # tar -xvf grcov.tar.gz + # sudo mv -v grcov /home/runner/.cargo/bin/ + # rm -rv grcov.tar.gz - - name: Run Coverage Tool (grcov) - uses: actions-rs/grcov@v0.1 - id: coverage + # - name: Run Coverage Tool (grcov) + # uses: actions-rs/grcov@v0.1 + # id: coverage - - name: Coveralls upload - uses: coverallsapp/github-action@master - with: - github-token: ${{ secrets.GITHUB_TOKEN }} - path-to-lcov: ${{ steps.coverage.outputs.report }} + # - name: Coveralls upload + # uses: coverallsapp/github-action@master + # with: + # github-token: ${{ secrets.GITHUB_TOKEN }} + # path-to-lcov: ${{ steps.coverage.outputs.report }}