diff --git a/Cargo.lock b/Cargo.lock index 7e7dcfd..d66cde4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1076,12 +1076,6 @@ version = "1.0.94" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c1fd03a028ef38ba2276dce7e33fcd6369c158a1bca17946c4b1b701891c1ff7" -[[package]] -name = "arc-swap" -version = "1.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "69f7f8c3906b62b754cd5326047894316021dcfe5a194c8ea52bdd94934a3457" - [[package]] name = "ark-bls12-377" version = "0.4.0" @@ -1487,29 +1481,14 @@ dependencies = [ "term", ] -[[package]] -name = "asn1-rs" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f6fd5ddaf0351dff5b8da21b2fb4ff8e08ddd02857f0bf69c47639106c0fff0" -dependencies = [ - "asn1-rs-derive 0.4.0", - "asn1-rs-impl 0.1.0", - "displaydoc", - "nom", - "num-traits", - "rusticata-macros", - "thiserror 1.0.69", -] - [[package]] name = "asn1-rs" version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5493c3bedbacf7fd7382c6346bbd66687d12bbaad3a89a2d2c303ee6cf20b048" dependencies = [ - "asn1-rs-derive 0.5.1", - "asn1-rs-impl 0.2.0", + "asn1-rs-derive", + "asn1-rs-impl", "displaydoc", "nom", "num-traits", @@ -1518,18 +1497,6 @@ dependencies = [ "time", ] -[[package]] -name = "asn1-rs-derive" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "726535892e8eae7e70657b4c8ea93d26b8553afb1ce617caee529ef96d7dee6c" -dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", - "synstructure 0.12.6", -] - [[package]] name = "asn1-rs-derive" version = "0.5.1" @@ -1539,18 +1506,7 @@ dependencies = [ "proc-macro2", "quote", "syn 2.0.90", - "synstructure 0.13.1", -] - -[[package]] -name = "asn1-rs-impl" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2777730b2039ac0f95f093556e61b6d26cebed5393ca6f152717777cec3a42ed" -dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", + "synstructure", ] [[package]] @@ -1564,17 +1520,6 @@ dependencies = [ "syn 2.0.90", ] -[[package]] -name = "async-channel" -version = "1.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81953c529336010edd6d8e358f886d9581267795c61b19475b71314bffa46d35" -dependencies = [ - "concurrent-queue", - "event-listener 2.5.3", - "futures-core", -] - [[package]] name = "async-channel" version = "2.3.1" @@ -1587,19 +1532,6 @@ dependencies = [ "pin-project-lite", ] -[[package]] -name = "async-compat" -version = "0.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7bab94bde396a3f7b4962e396fdad640e241ed797d4d8d77fc8c237d14c58fc0" -dependencies = [ - "futures-core", - "futures-io", - "once_cell", - "pin-project-lite", - "tokio", -] - [[package]] name = "async-compression" version = "0.4.18" @@ -1637,21 +1569,6 @@ dependencies = [ "futures-lite", ] -[[package]] -name = "async-global-executor" -version = "2.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05b1b633a2115cd122d73b955eadd9916c18c8f510ec9cd1686404c60ad1c29c" -dependencies = [ - "async-channel 2.3.1", - "async-executor", - "async-io", - "async-lock", - "blocking", - "futures-lite", - "once_cell", -] - [[package]] name = "async-io" version = "2.4.0" @@ -1699,7 +1616,7 @@ version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "63255f1dc2381611000436537bbedfe83183faa303a5a0edaf191edef06526bb" dependencies = [ - "async-channel 2.3.1", + "async-channel", "async-io", "async-lock", "async-signal", @@ -1730,32 +1647,6 @@ dependencies = [ "windows-sys 0.59.0", ] -[[package]] -name = "async-std" -version = "1.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c634475f29802fde2b8f0b505b1bd00dfe4df7d4a000f0b36f7671197d5c3615" -dependencies = [ - "async-channel 1.9.0", - "async-global-executor", - "async-io", - "async-lock", - "crossbeam-utils", - "futures-channel", - "futures-core", - "futures-io", - "futures-lite", - "gloo-timers 0.3.0", - "kv-log-macro", - "log", - "memchr", - "once_cell", - "pin-project-lite", - "pin-utils", - "slab", - "wasm-bindgen-futures", -] - [[package]] name = "async-stream" version = "0.3.6" @@ -1784,19 +1675,6 @@ version = "4.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b75356056920673b02621b35afd0f7dda9306d03c79a30f5c56c44cf256e3de" -[[package]] -name = "async-tls" -version = "0.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2ae3c9eba89d472a0e4fe1dea433df78fbbe63d2b764addaf2ba3a6bde89a5e" -dependencies = [ - "futures-core", - "futures-io", - "rustls 0.21.12", - "rustls-pemfile 1.0.4", - "webpki-roots 0.22.6", -] - [[package]] name = "async-trait" version = "0.1.83" @@ -1808,21 +1686,6 @@ dependencies = [ "syn 2.0.90", ] -[[package]] -name = "async-tungstenite" -version = "0.26.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb786dab48e539c5f17b23bac20d812ac027c01732ed7c7b58850c69a684e46c" -dependencies = [ - "async-std", - "async-tls", - "futures-io", - "futures-util", - "log", - "pin-project-lite", - "tungstenite 0.23.0", -] - [[package]] name = "async_io_stream" version = "0.3.3" @@ -2440,22 +2303,13 @@ dependencies = [ "generic-array", ] -[[package]] -name = "block-padding" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8894febbff9f758034a5b8e12d87918f56dfc64a8e1fe757d65e29041538d93" -dependencies = [ - "generic-array", -] - [[package]] name = "blocking" version = "1.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "703f41c54fc768e63e091340b424302bb1c29ef4aa0c7f10fe849dfb114d29ea" dependencies = [ - "async-channel 2.3.1", + "async-channel", "async-task", "futures-io", "futures-lite", @@ -2651,15 +2505,6 @@ dependencies = [ "thiserror 1.0.69", ] -[[package]] -name = "cbc" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26b52a9543ae338f279b96b0b9fed9c8093744685043739079ce85cd58f289a6" -dependencies = [ - "cipher", -] - [[package]] name = "cbor4ii" version = "0.3.3" @@ -2680,18 +2525,6 @@ dependencies = [ "shlex", ] -[[package]] -name = "ccm" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ae3c82e4355234767756212c570e29833699ab63e6ffd161887314cc5b43847" -dependencies = [ - "aead", - "cipher", - "ctr", - "subtle", -] - [[package]] name = "cesu8" version = "1.1.0" @@ -3060,21 +2893,6 @@ dependencies = [ "serde", ] -[[package]] -name = "crc" -version = "3.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "69e6e4d7b33a94f0991c26729976b10ebde1d34c3ee82408fb536164fa10d636" -dependencies = [ - "crc-catalog", -] - -[[package]] -name = "crc-catalog" -version = "2.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19d374276b40fb8bbdee95aef7c7fa6b5316ec764510eb64b8dd0e2ed0d7e7f5" - [[package]] name = "crc32fast" version = "1.4.2" @@ -3337,26 +3155,13 @@ dependencies = [ "zeroize", ] -[[package]] -name = "der-parser" -version = "8.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dbd676fbbab537128ef0278adb5576cf363cff6aa22a7b24effe97347cfab61e" -dependencies = [ - "asn1-rs 0.5.2", - "displaydoc", - "nom", - "num-traits", - "rusticata-macros", -] - [[package]] name = "der-parser" version = "9.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5cd0a5c643689626bec213c4d8bd4d96acc8ffdb4ad4bb6bc16abf27d5f4b553" dependencies = [ - "asn1-rs 0.6.2", + "asn1-rs", "displaydoc", "nom", "num-bigint", @@ -3920,7 +3725,6 @@ dependencies = [ "ff", "generic-array", "group", - "hkdf", "pem-rfc7468", "pkcs8", "rand_core 0.6.4", @@ -4362,12 +4166,6 @@ dependencies = [ "yansi", ] -[[package]] -name = "event-listener" -version = "2.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0" - [[package]] name = "event-listener" version = "4.0.3" @@ -4740,7 +4538,7 @@ version = "3.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f288b0a4f20f9a56b5d1da57e2227c661b7b16168e2f72365f57b63326e29b24" dependencies = [ - "gloo-timers 0.2.6", + "gloo-timers", "send_wrapper 0.4.0", ] @@ -4949,6 +4747,7 @@ dependencies = [ name = "gadget-crypto" version = "0.1.0" dependencies = [ + "blake3", "gadget-crypto-bls", "gadget-crypto-bn254", "gadget-crypto-core", @@ -4987,6 +4786,7 @@ dependencies = [ "ark-serialize 0.5.0", "gadget-crypto-core", "gadget-std", + "hex", "num-bigint", "num-traits", "serde", @@ -5228,6 +5028,13 @@ dependencies = [ "tracing-subscriber 0.3.19", ] +[[package]] +name = "gadget-metrics" +version = "0.1.0" +dependencies = [ + "gadget-rpc-calls", +] + [[package]] name = "gadget-networking" version = "0.1.0" @@ -5246,7 +5053,6 @@ dependencies = [ "k256", "libp2p", "lru-mem", - "matchbox_socket", "parking_lot", "round-based", "serde", @@ -5262,7 +5068,7 @@ name = "gadget-rpc-calls" version = "0.1.0" dependencies = [ "gadget-logging", - "metrics 0.24.1", + "metrics", ] [[package]] @@ -5484,18 +5290,6 @@ dependencies = [ "wasm-bindgen", ] -[[package]] -name = "gloo-timers" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbb143cf96099802033e0d4f4963b19fd2e0b728bcf076cd9cf7f6634f092994" -dependencies = [ - "futures-channel", - "futures-core", - "js-sys", - "wasm-bindgen", -] - [[package]] name = "gloo-utils" version = "0.2.0" @@ -6308,7 +6102,6 @@ version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a0c10553d664a4d0bcff9f4215d0aac67a639cc68ef660840afe309b807bc9f5" dependencies = [ - "block-padding", "generic-array", ] @@ -6333,26 +6126,6 @@ dependencies = [ "num-traits", ] -[[package]] -name = "interceptor" -version = "0.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4705c00485029e738bea8c9505b5ddb1486a8f3627a953e1e77e6abdf5eef90c" -dependencies = [ - "async-trait", - "bytes", - "log", - "portable-atomic", - "rand", - "rtcp", - "rtp", - "thiserror 1.0.69", - "tokio", - "waitgroup", - "webrtc-srtp", - "webrtc-util", -] - [[package]] name = "interprocess" version = "2.2.2" @@ -6736,15 +6509,6 @@ dependencies = [ "sha3-asm", ] -[[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 = "lalrpop" version = "0.20.2" @@ -7270,7 +7034,7 @@ dependencies = [ "futures-rustls", "libp2p-core", "libp2p-identity", - "rcgen 0.11.3", + "rcgen", "ring 0.17.8", "rustls 0.23.20", "rustls-webpki 0.101.7", @@ -7420,9 +7184,6 @@ name = "log" version = "0.4.22" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" -dependencies = [ - "value-bag", -] [[package]] name = "lru" @@ -7466,49 +7227,6 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ffbee8634e0d45d258acb448e7eaab3fce7a0a467395d4d9f228e3c1f01fb2e4" -[[package]] -name = "matchbox_protocol" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "296e69f2a38468879c63c5cebeeb959e97c2a1cf42d65f5384822435992b51d1" -dependencies = [ - "cfg-if", - "derive_more 0.99.18", - "serde", - "uuid 1.11.0", -] - -[[package]] -name = "matchbox_socket" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96d47ab26c3bf1effd83e01a3f16b09f3cb05356fbb9dc77b7e7fb6950e6c4c7" -dependencies = [ - "async-compat", - "async-trait", - "async-tungstenite", - "bytes", - "cfg-if", - "derive_more 0.99.18", - "futures", - "futures-channel", - "futures-timer", - "futures-util", - "js-sys", - "log", - "matchbox_protocol", - "once_cell", - "serde", - "serde-wasm-bindgen", - "serde_json", - "thiserror 1.0.69", - "wasm-bindgen", - "wasm-bindgen-futures", - "web-sys", - "webrtc", - "ws_stream_wasm", -] - [[package]] name = "matchers" version = "0.0.1" @@ -7597,13 +7315,6 @@ dependencies = [ "zeroize", ] -[[package]] -name = "metrics" -version = "0.1.0" -dependencies = [ - "gadget-rpc-calls", -] - [[package]] name = "metrics" version = "0.24.1" @@ -7993,7 +7704,7 @@ version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a8d8034d9489cdaf79228eb9f6a3b8d7bb32ba00d6645ebd48eef4077ceb5bd9" dependencies = [ - "asn1-rs 0.6.2", + "asn1-rs", ] [[package]] @@ -8095,30 +7806,6 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" -[[package]] -name = "p256" -version = "0.13.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c9863ad85fa8f4460f9c48cb909d38a0d689dba1f6f6988a5e3e0d31071bcd4b" -dependencies = [ - "ecdsa", - "elliptic-curve", - "primeorder", - "sha2 0.10.8", -] - -[[package]] -name = "p384" -version = "0.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70786f51bcc69f6a4c0360e063a4cac5419ef7c5cd5b3c99ad70f3be5ba79209" -dependencies = [ - "ecdsa", - "elliptic-curve", - "primeorder", - "sha2 0.10.8", -] - [[package]] name = "parity-bip39" version = "2.0.1" @@ -8623,15 +8310,6 @@ dependencies = [ "syn 2.0.90", ] -[[package]] -name = "primeorder" -version = "0.13.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "353e1ca18966c16d9deb1c69278edbc5f194139612772bd9537af60ac231e1e6" -dependencies = [ - "elliptic-curve", -] - [[package]] name = "primitive-types" version = "0.12.2" @@ -8968,20 +8646,6 @@ dependencies = [ "yasna", ] -[[package]] -name = "rcgen" -version = "0.13.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "54077e1872c46788540de1ea3d7f4ccb1983d12f9aa909b234468676c1a36779" -dependencies = [ - "pem 3.0.4", - "ring 0.17.8", - "rustls-pki-types", - "time", - "x509-parser", - "yasna", -] - [[package]] name = "reconnecting-jsonrpsee-ws-client" version = "0.4.3" @@ -9291,17 +8955,6 @@ dependencies = [ "tracing", ] -[[package]] -name = "rtcp" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc9f775ff89c5fe7f0cc0abafb7c57688ae25ce688f1a52dd88e277616c76ab2" -dependencies = [ - "bytes", - "thiserror 1.0.69", - "webrtc-util", -] - [[package]] name = "rtnetlink" version = "0.13.1" @@ -9320,20 +8973,6 @@ dependencies = [ "tokio", ] -[[package]] -name = "rtp" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6870f09b5db96f8b9e7290324673259fd15519ebb7d55acf8e7eb044a9ead6af" -dependencies = [ - "bytes", - "portable-atomic", - "rand", - "serde", - "thiserror 1.0.69", - "webrtc-util", -] - [[package]] name = "ruint" version = "1.12.3" @@ -9913,18 +9552,6 @@ dependencies = [ "untrusted 0.9.0", ] -[[package]] -name = "sdp" -version = "0.6.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13254db766b17451aced321e7397ebf0a446ef0c8d2942b6e67a95815421093f" -dependencies = [ - "rand", - "substring", - "thiserror 1.0.69", - "url", -] - [[package]] name = "sec1" version = "0.7.3" @@ -10065,17 +9692,6 @@ dependencies = [ "serde_derive", ] -[[package]] -name = "serde-wasm-bindgen" -version = "0.6.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8302e169f0eddcc139c70f139d19d6467353af16f9fce27e8c30158036a1e16b" -dependencies = [ - "js-sys", - "serde", - "wasm-bindgen", -] - [[package]] name = "serde_bytes" version = "0.11.15" @@ -10345,7 +9961,7 @@ version = "2.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a33bd3e260892199c3ccfc487c88b2da2265080acb316cd920da72fdfd7c599f" dependencies = [ - "async-channel 2.3.1", + "async-channel", "async-executor", "async-fs", "async-io", @@ -10356,15 +9972,6 @@ dependencies = [ "futures-lite", ] -[[package]] -name = "smol_str" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd538fb6910ac1099850255cf94a94df6551fbdd602454387d0adb2d1ca6dead" -dependencies = [ - "serde", -] - [[package]] name = "smoldot" version = "0.16.0" @@ -10426,7 +10033,7 @@ version = "0.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5496f2d116b7019a526b1039ec2247dd172b8670633b1a64a614c9ea12c9d8c7" dependencies = [ - "async-channel 2.3.1", + "async-channel", "async-lock", "base64 0.21.7", "blake2-rfc", @@ -11177,25 +10784,6 @@ dependencies = [ "syn 2.0.90", ] -[[package]] -name = "stun" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28fad383a1cc63ae141e84e48eaef44a1063e9d9e55bcb8f51a99b886486e01b" -dependencies = [ - "base64 0.21.7", - "crc", - "lazy_static", - "md-5", - "rand", - "ring 0.17.8", - "subtle", - "thiserror 1.0.69", - "tokio", - "url", - "webrtc-util", -] - [[package]] name = "substrate-bip39" version = "0.5.0" @@ -11222,15 +10810,6 @@ dependencies = [ "zeroize", ] -[[package]] -name = "substring" -version = "1.4.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42ee6433ecef213b2e72f587ef64a2f5943e7cd16fbd82dbe8bc07486c534c86" -dependencies = [ - "autocfg", -] - [[package]] name = "subtle" version = "2.6.1" @@ -11471,18 +11050,6 @@ dependencies = [ "futures-core", ] -[[package]] -name = "synstructure" -version = "0.12.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f36bdaa60a83aca3921b5259d5400cbf5e90fc51931376a9bd4a0eb79aa7210f" -dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", - "unicode-xid", -] - [[package]] name = "synstructure" version = "0.13.1" @@ -12217,24 +11784,6 @@ dependencies = [ "utf-8", ] -[[package]] -name = "tungstenite" -version = "0.23.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e2e2ce1e47ed2994fd43b04c8f618008d4cabdd5ee34027cf14f9d918edd9c8" -dependencies = [ - "byteorder", - "bytes", - "data-encoding", - "http 1.2.0", - "httparse", - "log", - "rand", - "sha1", - "thiserror 1.0.69", - "utf-8", -] - [[package]] name = "tungstenite" version = "0.24.0" @@ -12255,27 +11804,6 @@ dependencies = [ "utf-8", ] -[[package]] -name = "turn" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b000cebd930420ac1ed842c8128e3b3412512dfd5b82657eab035a3f5126acc" -dependencies = [ - "async-trait", - "base64 0.21.7", - "futures", - "log", - "md-5", - "portable-atomic", - "rand", - "ring 0.17.8", - "stun", - "thiserror 1.0.69", - "tokio", - "tokio-util", - "webrtc-util", -] - [[package]] name = "twox-hash" version = "1.6.3" @@ -12438,7 +11966,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f8c5f0a0af699448548ad1a2fbf920fb4bee257eae39953ba95cb84891a0446a" dependencies = [ "getrandom", - "serde", ] [[package]] @@ -12447,12 +11974,6 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d" -[[package]] -name = "value-bag" -version = "1.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ef4c4aa54d5d05a279399bfa921ec387b7aba77caf7a682ae8d86785b8fdad2" - [[package]] name = "vcpkg" version = "0.2.15" @@ -12533,15 +12054,6 @@ dependencies = [ "libc", ] -[[package]] -name = "waitgroup" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d1f50000a783467e6c0200f9d10642f4bc424e39efc1b770203e88b488f79292" -dependencies = [ - "atomic-waker", -] - [[package]] name = "walkdir" version = "2.5.0" @@ -12863,25 +12375,6 @@ dependencies = [ "wasm-bindgen", ] -[[package]] -name = "webpki" -version = "0.22.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed63aea5ce73d0ff405984102c42de94fc55a6b75765d621c65262469b3c9b53" -dependencies = [ - "ring 0.17.8", - "untrusted 0.9.0", -] - -[[package]] -name = "webpki-roots" -version = "0.22.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6c71e40d7d2c34a5106301fb632274ca37242cd0c9d3e64dbece371a40a2d87" -dependencies = [ - "webpki", -] - [[package]] name = "webpki-roots" version = "0.25.4" @@ -12897,215 +12390,6 @@ dependencies = [ "rustls-pki-types", ] -[[package]] -name = "webrtc" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8b3a840e31c969844714f93b5a87e73ee49f3bc2a4094ab9132c69497eb31db" -dependencies = [ - "arc-swap", - "async-trait", - "bytes", - "cfg-if", - "hex", - "interceptor", - "lazy_static", - "log", - "portable-atomic", - "rand", - "rcgen 0.13.1", - "regex", - "ring 0.17.8", - "rtcp", - "rtp", - "rustls 0.23.20", - "sdp", - "serde", - "serde_json", - "sha2 0.10.8", - "smol_str", - "stun", - "thiserror 1.0.69", - "time", - "tokio", - "turn", - "url", - "waitgroup", - "webrtc-data", - "webrtc-dtls", - "webrtc-ice", - "webrtc-mdns", - "webrtc-media", - "webrtc-sctp", - "webrtc-srtp", - "webrtc-util", -] - -[[package]] -name = "webrtc-data" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8b7c550f8d35867b72d511640adf5159729b9692899826fe00ba7fa74f0bf70" -dependencies = [ - "bytes", - "log", - "portable-atomic", - "thiserror 1.0.69", - "tokio", - "webrtc-sctp", - "webrtc-util", -] - -[[package]] -name = "webrtc-dtls" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86e5eedbb0375aa04da93fc3a189b49ed3ed9ee844b6997d5aade14fc3e2c26e" -dependencies = [ - "aes", - "aes-gcm", - "async-trait", - "bincode", - "byteorder", - "cbc", - "ccm", - "der-parser 8.2.0", - "hkdf", - "hmac 0.12.1", - "log", - "p256", - "p384", - "portable-atomic", - "rand", - "rand_core 0.6.4", - "rcgen 0.13.1", - "ring 0.17.8", - "rustls 0.23.20", - "sec1", - "serde", - "sha1", - "sha2 0.10.8", - "subtle", - "thiserror 1.0.69", - "tokio", - "webrtc-util", - "x25519-dalek", - "x509-parser", -] - -[[package]] -name = "webrtc-ice" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d4f0ca6d4df8d1bdd34eece61b51b62540840b7a000397bcfb53a7bfcf347c8" -dependencies = [ - "arc-swap", - "async-trait", - "crc", - "log", - "portable-atomic", - "rand", - "serde", - "serde_json", - "stun", - "thiserror 1.0.69", - "tokio", - "turn", - "url", - "uuid 1.11.0", - "waitgroup", - "webrtc-mdns", - "webrtc-util", -] - -[[package]] -name = "webrtc-mdns" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0804694f3b2acfdff48f6df217979b13cb0a00377c63b5effd111daaee7e8c4" -dependencies = [ - "log", - "socket2", - "thiserror 1.0.69", - "tokio", - "webrtc-util", -] - -[[package]] -name = "webrtc-media" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1c15b20e98167b22949abc1c20eca7c6d814307d187068fe7a48f0b87a4f6d46" -dependencies = [ - "byteorder", - "bytes", - "rand", - "rtp", - "thiserror 1.0.69", -] - -[[package]] -name = "webrtc-sctp" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d850daa68639b9d7bb16400676e97525d1e52b15b4928240ae2ba0e849817a5" -dependencies = [ - "arc-swap", - "async-trait", - "bytes", - "crc", - "log", - "portable-atomic", - "rand", - "thiserror 1.0.69", - "tokio", - "webrtc-util", -] - -[[package]] -name = "webrtc-srtp" -version = "0.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fbec5da43a62c228d321d93fb12cc9b4d9c03c9b736b0c215be89d8bd0774cfe" -dependencies = [ - "aead", - "aes", - "aes-gcm", - "byteorder", - "bytes", - "ctr", - "hmac 0.12.1", - "log", - "rtcp", - "rtp", - "sha1", - "subtle", - "thiserror 1.0.69", - "tokio", - "webrtc-util", -] - -[[package]] -name = "webrtc-util" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc8d9bc631768958ed97b8d68b5d301e63054ae90b09083d43e2fefb939fd77e" -dependencies = [ - "async-trait", - "bitflags 1.3.2", - "bytes", - "ipnet", - "lazy_static", - "libc", - "log", - "nix", - "portable-atomic", - "rand", - "thiserror 1.0.69", - "tokio", - "winapi", -] - [[package]] name = "widestring" version = "1.1.0" @@ -13546,13 +12830,12 @@ version = "0.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fcbc162f30700d6f3f82a24bf7cc62ffe7caea42c0b2cba8bf7f3ae50cf51f69" dependencies = [ - "asn1-rs 0.6.2", + "asn1-rs", "data-encoding", - "der-parser 9.0.0", + "der-parser", "lazy_static", "nom", "oid-registry", - "ring 0.17.8", "rusticata-macros", "thiserror 1.0.69", "time", @@ -13663,7 +12946,7 @@ dependencies = [ "proc-macro2", "quote", "syn 2.0.90", - "synstructure 0.13.1", + "synstructure", ] [[package]] @@ -13705,7 +12988,7 @@ dependencies = [ "proc-macro2", "quote", "syn 2.0.90", - "synstructure 0.13.1", + "synstructure", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index 6d5856c..dca9063 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -256,7 +256,7 @@ dashmap = { version = "6.1.0", default-features = false } lru-mem = { version = "0.3.0", default-features = false } # Metrics -metrics = { version = "0.24" } +metrics = { version = "0.24.1", default-features = false } metrics-exporter-prometheus = { version = "0.16" } prometheus = { version = "0.13.4", default-features = false } diff --git a/crates/crypto/Cargo.toml b/crates/crypto/Cargo.toml index 170a519..1b70352 100644 --- a/crates/crypto/Cargo.toml +++ b/crates/crypto/Cargo.toml @@ -14,6 +14,7 @@ gadget-crypto-sp-core = { path = "sp-core", optional = true } gadget-crypto-tangle-pair-signer = { workspace = true, optional = true } sha2 = { workspace = true, optional = true } sha3 = { workspace = true, optional = true } +blake3 = { workspace = true, optional = true } thiserror = { workspace = true } [features] @@ -37,4 +38,4 @@ sp-core = ["gadget-crypto-sp-core", "gadget-crypto-core/tangle"] sp-core-bls = ["gadget-crypto-sp-core/bls", "gadget-crypto-core/tangle"] tangle-pair-signer = ["gadget-crypto-tangle-pair-signer"] -hashing = ["sha2", "sha3"] \ No newline at end of file +hashing = ["sha2", "sha3", "blake3"] \ No newline at end of file diff --git a/crates/crypto/bls/src/w3f_bls.rs b/crates/crypto/bls/src/w3f_bls.rs index c376d93..cbe86e7 100644 --- a/crates/crypto/bls/src/w3f_bls.rs +++ b/crates/crypto/bls/src/w3f_bls.rs @@ -36,7 +36,8 @@ macro_rules! impl_w3f_serde { &self, serializer: S, ) -> core::result::Result { - serializer.serialize_bytes(&to_bytes(self.0.clone())) + let bytes = to_bytes(self.0.clone()); + Vec::serialize(&bytes, serializer) } } @@ -45,7 +46,7 @@ macro_rules! impl_w3f_serde { where D: serde::Deserializer<'de>, { - // Deserialize as bytes + // Deserialize as Vec let bytes = >::deserialize(deserializer)?; // Convert bytes back to inner type @@ -137,3 +138,15 @@ macro_rules! define_bls_key { } define_bls_key!(Bls377, Bls381); + +#[cfg(test)] +mod test_bls377 { + use super::bls377::{Secret, W3fBls377, W3fBls377Signature}; + gadget_crypto_core::impl_crypto_tests!(W3fBls377, Secret, W3fBls377Signature); +} + +#[cfg(test)] +mod test_bls381 { + use super::bls381::{Secret, W3fBls381, W3fBls381Signature}; + gadget_crypto_core::impl_crypto_tests!(W3fBls381, Secret, W3fBls381Signature); +} diff --git a/crates/crypto/bn254/Cargo.toml b/crates/crypto/bn254/Cargo.toml index c54ce33..de81d76 100644 --- a/crates/crypto/bn254/Cargo.toml +++ b/crates/crypto/bn254/Cargo.toml @@ -17,6 +17,7 @@ thiserror = { workspace = true } num-bigint = { workspace = true, features = ["serde"] } num-traits = { workspace = true } sha2 = { workspace = true } +hex = { workspace = true, features = ["alloc"] } [features] default = ["std"] diff --git a/crates/crypto/bn254/src/arkworks_bn254.rs b/crates/crypto/bn254/src/arkworks_bn254.rs index e539278..5a3ed4b 100644 --- a/crates/crypto/bn254/src/arkworks_bn254.rs +++ b/crates/crypto/bn254/src/arkworks_bn254.rs @@ -37,7 +37,8 @@ macro_rules! impl_ark_serde { &self, serializer: S, ) -> core::result::Result { - serializer.serialize_bytes(&to_bytes(self.0)) + let bytes = to_bytes(self.0); + Vec::serialize(&bytes, serializer) } } @@ -114,4 +115,8 @@ impl KeyType for ArkBlsBn254 { } } -// Continue with KeyType implementation... +#[cfg(test)] +mod tests { + use super::*; + gadget_crypto_core::impl_crypto_tests!(ArkBlsBn254, ArkBlsBn254Secret, ArkBlsBn254Signature); +} diff --git a/crates/crypto/core/src/lib.rs b/crates/crypto/core/src/lib.rs index 07f65fa..c1c36a8 100644 --- a/crates/crypto/core/src/lib.rs +++ b/crates/crypto/core/src/lib.rs @@ -130,3 +130,94 @@ pub trait KeyType: Sized + 'static { ) -> Result; fn verify(public: &Self::Public, msg: &[u8], signature: &Self::Signature) -> bool; } + +#[macro_export] +macro_rules! impl_crypto_tests { + ($crypto_type:ty, $signing_key:ty, $signature:ty) => { + use $crate::KeyType; + #[test] + fn test_key_generation() { + // Test random key generation + let secret = <$crypto_type>::generate_with_seed(None).unwrap(); + let _public = <$crypto_type>::public_from_secret(&secret); + } + + #[test] + fn test_signing_and_verification() { + let mut secret = <$crypto_type>::generate_with_seed(None).unwrap(); + let public = <$crypto_type>::public_from_secret(&secret); + + // Test normal signing + let message = b"Hello, world!"; + let signature = <$crypto_type>::sign_with_secret(&mut secret, message).unwrap(); + assert!( + <$crypto_type>::verify(&public, message, &signature), + "Signature verification failed" + ); + + // Test pre-hashed signing + let hashed_msg = [42u8; 32]; + let signature = + <$crypto_type>::sign_with_secret_pre_hashed(&mut secret, &hashed_msg).unwrap(); + + // Verify with wrong message should fail + let wrong_message = b"Wrong message"; + assert!( + !<$crypto_type>::verify(&public, wrong_message, &signature), + "Verification should fail with wrong message" + ); + } + + #[test] + fn test_key_serialization() { + let secret = <$crypto_type>::generate_with_seed(None).unwrap(); + let public = <$crypto_type>::public_from_secret(&secret); + + // Test signing key serialization + let serialized = serde_json::to_string(&secret).unwrap(); + let deserialized: $signing_key = serde_json::from_str(&serialized).unwrap(); + assert_eq!( + secret, deserialized, + "SigningKey serialization roundtrip failed" + ); + + // Test verifying key serialization + let serialized = serde_json::to_string(&public).unwrap(); + let deserialized = serde_json::from_str(&serialized).unwrap(); + assert_eq!( + public, deserialized, + "VerifyingKey serialization roundtrip failed" + ); + } + + #[test] + fn test_signature_serialization() { + let mut secret = <$crypto_type>::generate_with_seed(None).unwrap(); + let message = b"Test message"; + let signature = <$crypto_type>::sign_with_secret(&mut secret, message).unwrap(); + + // Test signature serialization + let serialized = serde_json::to_string(&signature).unwrap(); + let deserialized: $signature = serde_json::from_str(&serialized).unwrap(); + assert_eq!( + signature, deserialized, + "Signature serialization roundtrip failed" + ); + } + + #[test] + fn test_key_comparison() { + let secret1 = <$crypto_type>::generate_with_seed(None).unwrap(); + let secret2 = <$crypto_type>::generate_with_seed(None).unwrap(); + let public1 = <$crypto_type>::public_from_secret(&secret1); + let public2 = <$crypto_type>::public_from_secret(&secret2); + + // Test Ord implementation + assert!(public1 != public2, "Different keys should not be equal"); + assert_eq!(public1.cmp(&public1), gadget_std::cmp::Ordering::Equal); + + // Verify consistency between PartialOrd and Ord + assert_eq!(public1.partial_cmp(&public2), Some(public1.cmp(&public2))); + } + }; +} diff --git a/crates/crypto/ed25519/src/zebra_ed25519.rs b/crates/crypto/ed25519/src/zebra_ed25519.rs index a6f2c6b..753f61e 100644 --- a/crates/crypto/ed25519/src/zebra_ed25519.rs +++ b/crates/crypto/ed25519/src/zebra_ed25519.rs @@ -45,8 +45,8 @@ macro_rules! impl_zebra_serde { S: serde::Serializer, { // Get the raw bytes - let bytes = self.0.as_ref(); - serializer.serialize_bytes(bytes) + let bytes = self.0.as_ref().to_vec(); + Vec::serialize(&bytes, serializer) } } @@ -75,7 +75,7 @@ pub struct Ed25519Signature(pub ed25519_zebra::Signature); impl PartialOrd for Ed25519Signature { fn partial_cmp(&self, other: &Self) -> Option { - self.0.to_bytes().partial_cmp(&other.0.to_bytes()) + Some(self.cmp(other)) } } @@ -159,3 +159,9 @@ impl KeyType for Ed25519Zebra { public.0.verify(&signature.0, msg).is_ok() } } + +#[cfg(test)] +mod tests { + use super::*; + gadget_crypto_core::impl_crypto_tests!(Ed25519Zebra, Ed25519SigningKey, Ed25519Signature); +} diff --git a/crates/crypto/k256/Cargo.toml b/crates/crypto/k256/Cargo.toml index abd1506..b9dbfc5 100644 --- a/crates/crypto/k256/Cargo.toml +++ b/crates/crypto/k256/Cargo.toml @@ -6,9 +6,9 @@ edition = "2021" [dependencies] gadget-crypto-core = { workspace = true, features = ["k256"] } gadget-std = { workspace = true } -k256 = { workspace = true, features = ["ecdsa", "alloc"] } +k256 = { workspace = true, features = ["ecdsa", "alloc", "serde", "pem"] } serde = { workspace = true } -serde_json = { workspace = true, features = ["alloc"] } +serde_json = { workspace = true } thiserror = { workspace = true } hex = { workspace = true, features = ["alloc"] } diff --git a/crates/crypto/k256/src/k256_ecdsa.rs b/crates/crypto/k256/src/k256_ecdsa.rs index df5ee97..d7e0ecc 100644 --- a/crates/crypto/k256/src/k256_ecdsa.rs +++ b/crates/crypto/k256/src/k256_ecdsa.rs @@ -1,22 +1,19 @@ +use crate::error::{K256Error, Result}; use gadget_crypto_core::{KeyType, KeyTypeId}; +use gadget_std::string::{String, ToString}; use gadget_std::UniformRand; -use gadget_std::{ - string::{String, ToString}, - vec::Vec, -}; use k256::ecdsa::signature::SignerMut; - -use crate::error::{K256Error, Result}; +use serde::{Deserialize, Serialize}; /// ECDSA key type pub struct K256Ecdsa; -#[derive(Clone, Copy, PartialEq, Eq, Debug)] +#[derive(Clone, Copy, PartialEq, Eq, Debug, Serialize, Deserialize)] pub struct K256VerifyingKey(pub k256::ecdsa::VerifyingKey); impl PartialOrd for K256VerifyingKey { fn partial_cmp(&self, other: &Self) -> Option { - self.0.to_sec1_bytes().partial_cmp(&other.0.to_sec1_bytes()) + Some(self.cmp(other)) } } @@ -26,28 +23,6 @@ impl Ord for K256VerifyingKey { } } -impl serde::Serialize for K256VerifyingKey { - fn serialize(&self, serializer: S) -> core::result::Result - where - S: serde::Serializer, - { - let bytes = self.0.to_sec1_bytes(); - serializer.serialize_bytes(&bytes) - } -} - -impl<'de> serde::Deserialize<'de> for K256VerifyingKey { - fn deserialize(deserializer: D) -> core::result::Result - where - D: serde::Deserializer<'de>, - { - let bytes = >::deserialize(deserializer)?; - let verifying_key = k256::ecdsa::VerifyingKey::from_sec1_bytes(&bytes) - .map_err(|e| serde::de::Error::custom(e.to_string()))?; - Ok(K256VerifyingKey(verifying_key)) - } -} - macro_rules! impl_serde_bytes { ($wrapper:ident, $inner:path) => { #[derive(Clone, PartialEq, Eq, Debug)] @@ -55,7 +30,7 @@ macro_rules! impl_serde_bytes { impl PartialOrd for $wrapper { fn partial_cmp(&self, other: &Self) -> Option { - self.0.to_bytes().partial_cmp(&other.0.to_bytes()) + Some(self.cmp(other)) } } @@ -70,8 +45,8 @@ macro_rules! impl_serde_bytes { where S: serde::Serializer, { - let bytes = self.0.to_bytes(); - serializer.serialize_bytes(&bytes) + let bytes = self.0.to_bytes().to_vec(); + Vec::serialize(&bytes, serializer) } } @@ -93,8 +68,8 @@ impl_serde_bytes!(K256SigningKey, k256::ecdsa::SigningKey); impl_serde_bytes!(K256Signature, k256::ecdsa::Signature); impl KeyType for K256Ecdsa { - type Public = K256VerifyingKey; type Secret = K256SigningKey; + type Public = K256VerifyingKey; type Signature = K256Signature; type Error = K256Error; @@ -124,7 +99,7 @@ impl KeyType for K256Ecdsa { } fn public_from_secret(secret: &Self::Secret) -> Self::Public { - K256VerifyingKey(secret.0.verifying_key().clone()) + K256VerifyingKey(*secret.0.verifying_key()) } fn sign_with_secret(secret: &mut Self::Secret, msg: &[u8]) -> Result { @@ -151,6 +126,18 @@ impl KeyType for K256Ecdsa { impl K256SigningKey { pub fn verifying_key(&self) -> K256VerifyingKey { - K256VerifyingKey(self.0.verifying_key().clone()) + K256VerifyingKey(*self.0.verifying_key()) } + + /// Alias for `verifying_key` for consistency + pub fn public(&self) -> K256VerifyingKey { + self.verifying_key() + } +} + +#[cfg(test)] +mod tests { + use super::*; + // Generate tests for K256 ECDSA + gadget_crypto_core::impl_crypto_tests!(K256Ecdsa, K256SigningKey, K256Signature); } diff --git a/crates/crypto/sp-core/src/sp_core_bls_util.rs b/crates/crypto/sp-core/src/sp_core_bls_util.rs index 417bd89..703ae11 100644 --- a/crates/crypto/sp-core/src/sp_core_bls_util.rs +++ b/crates/crypto/sp-core/src/sp_core_bls_util.rs @@ -12,7 +12,7 @@ use crate::{impl_sp_core_key_type, impl_sp_core_pair_public}; macro_rules! impl_sp_core_bls_signature { ($key_type:ident, $signature:ty) => { paste::paste! { - #[derive(Clone, PartialEq, Eq)] + #[derive(Clone, PartialEq, Eq, serde::Serialize, serde::Deserialize)] pub struct [<$key_type Signature>](pub $signature); impl PartialOrd for [<$key_type Signature>] { @@ -37,27 +37,6 @@ macro_rules! impl_sp_core_bls_signature { write!(f, "{:?}", bytes) } } - - impl serde::Serialize for [<$key_type Signature>] { - fn serialize(&self, serializer: S) -> Result - where - S: serde::Serializer, - { - serializer.serialize_bytes(self.0.as_ref()) - } - } - - impl<'de> serde::Deserialize<'de> for [<$key_type Signature>] { - fn deserialize(deserializer: D) -> Result - where - D: serde::Deserializer<'de>, - { - let bytes = >::deserialize(deserializer)?; - let sig = <$signature>::from_slice(&bytes) - .map_err(|_| serde::de::Error::custom("Invalid signature length"))?; - Ok([<$key_type Signature>](sig)) - } - } } }; } diff --git a/crates/crypto/sp-core/src/sp_core_util.rs b/crates/crypto/sp-core/src/sp_core_util.rs index 0e55bdc..b47bd2c 100644 --- a/crates/crypto/sp-core/src/sp_core_util.rs +++ b/crates/crypto/sp-core/src/sp_core_util.rs @@ -29,7 +29,7 @@ macro_rules! impl_sp_core_pair_public { impl PartialOrd for [<$key_type Pair>] { fn partial_cmp(&self, other: &Self) -> Option { - self.0.to_raw_vec().partial_cmp(&other.0.to_raw_vec()) + Some(self.cmp(other)) } } @@ -51,7 +51,7 @@ macro_rules! impl_sp_core_pair_public { S: serde::Serializer, { let bytes = self.0.to_raw_vec(); - serializer.serialize_bytes(&bytes) + Vec::serialize(&bytes, serializer) } } @@ -62,14 +62,14 @@ macro_rules! impl_sp_core_pair_public { { let bytes = >::deserialize(deserializer)?; let pair = <$pair_type>::from_seed_slice(&bytes) - .map_err(crate::error::SecretStringErrorWrapper) + .map_err($crate::error::SecretStringErrorWrapper) .map_err(|e| serde::de::Error::custom(e.to_string()))?; Ok([<$key_type Pair>](pair)) } } /// Wrapper struct for the cryptographic public key. - #[derive(Clone)] + #[derive(Clone, serde::Serialize, serde::Deserialize)] pub struct [<$key_type Public>](pub <$pair_type as sp_core::Pair>::Public); impl PartialEq for [<$key_type Public>]{ @@ -82,7 +82,7 @@ macro_rules! impl_sp_core_pair_public { impl PartialOrd for [<$key_type Public>]{ fn partial_cmp(&self, other: &Self) -> Option { - self.0.to_raw_vec().partial_cmp(&other.0.to_raw_vec()) + Some(self.cmp(other)) } } @@ -97,28 +97,6 @@ macro_rules! impl_sp_core_pair_public { write!(f, "{:?}", self.0.to_raw_vec()) } } - - impl serde::Serialize for [<$key_type Public>]{ - fn serialize(&self, serializer: S) -> core::result::Result - where - S: serde::Serializer, - { - let bytes = self.0.to_raw_vec(); - serializer.serialize_bytes(&bytes) - } - } - - impl<'de> serde::Deserialize<'de> for [<$key_type Public>]{ - fn deserialize(deserializer: D) -> core::result::Result - where - D: serde::Deserializer<'de>, - { - let bytes = >::deserialize(deserializer)?; - let public = <$pair_type as sp_core::Pair>::Public::from_slice(&bytes) - .map_err(|_| serde::de::Error::custom("Invalid public key length"))?; - Ok([<$key_type Public>](public)) - } - } } }; } @@ -127,12 +105,12 @@ macro_rules! impl_sp_core_pair_public { macro_rules! impl_sp_core_signature { ($key_type:ident, $pair_type:ty) => { paste::paste! { - #[derive(Clone, PartialEq, Eq)] + #[derive(Clone, PartialEq, Eq, serde::Serialize, serde::Deserialize)] pub struct [<$key_type Signature>](pub <$pair_type as sp_core::Pair>::Signature); impl PartialOrd for [<$key_type Signature>] { fn partial_cmp(&self, other: &Self) -> Option { - self.0.0.partial_cmp(&other.0.0) + Some(self.cmp(other)) } } @@ -147,27 +125,6 @@ macro_rules! impl_sp_core_signature { write!(f, "{:?}", self.0.0) } } - - impl serde::Serialize for [<$key_type Signature>] { - fn serialize(&self, serializer: S) -> core::result::Result - where - S: serde::Serializer, - { - serializer.serialize_bytes(self.0.as_ref()) - } - } - - impl<'de> serde::Deserialize<'de> for [<$key_type Signature>] { - fn deserialize(deserializer: D) -> core::result::Result - where - D: serde::Deserializer<'de>, - { - let bytes = >::deserialize(deserializer)?; - let sig = <$pair_type as sp_core::Pair>::Signature::from_slice(&bytes) - .ok_or_else(|| serde::de::Error::custom("Invalid signature length"))?; - Ok([<$key_type Signature>](sig)) - } - } } }; } @@ -183,18 +140,18 @@ macro_rules! impl_sp_core_key_type { type Public = [<$key_type Public>]; type Secret = [<$key_type Pair>]; type Signature = [<$key_type Signature>]; - type Error = crate::error::SpCoreError; + type Error = $crate::error::SpCoreError; fn key_type_id() -> gadget_crypto_core::KeyTypeId { gadget_crypto_core::KeyTypeId::$key_type } - fn generate_with_seed(seed: Option<&[u8]>) -> crate::error::Result { + fn generate_with_seed(seed: Option<&[u8]>) -> $crate::error::Result { match seed { Some(seed) => { let pair = <$pair_type>::from_seed_slice(seed) - .map_err(crate::error::SecretStringErrorWrapper) - .map_err(Into::::into)?; + .map_err($crate::error::SecretStringErrorWrapper) + .map_err(Into::<$crate::error::SpCoreError>::into)?; Ok([<$key_type Pair>](pair)) } None => { @@ -205,17 +162,17 @@ macro_rules! impl_sp_core_key_type { use gadget_std::Rng; let mut seed = Self::get_test_rng().gen::<[u8; 32]>(); <$pair_type>::from_seed_slice(&mut seed) - .map_err(crate::error::SecretStringErrorWrapper) - .map_err(Into::::into)? + .map_err($crate::error::SecretStringErrorWrapper) + .map_err(Into::<$crate::error::SpCoreError>::into)? }; Ok([<$key_type Pair>](pair)) } } } - fn generate_with_string(secret: String) -> crate::error::Result { + fn generate_with_string(secret: String) -> $crate::error::Result { let pair = <$pair_type>::from_string(&secret, None) - .map_err(|_| crate::error::SpCoreError::InvalidSeed("Invalid secret string".to_string()))?; + .map_err(|_| $crate::error::SpCoreError::InvalidSeed("Invalid secret string".to_string()))?; Ok([<$key_type Pair>](pair)) } @@ -226,14 +183,14 @@ macro_rules! impl_sp_core_key_type { fn sign_with_secret( secret: &mut Self::Secret, msg: &[u8], - ) -> crate::error::Result { + ) -> $crate::error::Result { Ok([<$key_type Signature>](secret.0.sign(msg))) } fn sign_with_secret_pre_hashed( secret: &mut Self::Secret, msg: &[u8; 32], - ) -> crate::error::Result { + ) -> $crate::error::Result { Ok([<$key_type Signature>](secret.0.sign(msg))) } @@ -241,6 +198,26 @@ macro_rules! impl_sp_core_key_type { <$pair_type as sp_core::Pair>::verify(&signature.0, msg, &public.0) } } + + impl [<$key_type Pair>] { + pub fn public(&self) -> [<$key_type Public>] { + [<$key_type Public>](self.0.public()) + } + } + + impl gadget_std::ops::Deref for [<$key_type Pair>] { + type Target = $pair_type; + + fn deref(&self) -> &Self::Target { + &self.0 + } + } + + impl gadget_std::ops::DerefMut for [<$key_type Pair>] { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.0 + } + } } }; } @@ -257,3 +234,25 @@ macro_rules! impl_sp_core_crypto { impl_sp_core_crypto!(SpEcdsa, ecdsa); impl_sp_core_crypto!(SpEd25519, ed25519); impl_sp_core_crypto!(SpSr25519, sr25519); + +impl Copy for SpEcdsaPublic {} +impl Copy for SpEd25519Public {} +impl Copy for SpSr25519Public {} + +#[cfg(test)] +mod tests_ecdsa { + use super::*; + gadget_crypto_core::impl_crypto_tests!(SpEcdsa, SpEcdsaPair, SpEcdsaSignature); +} + +#[cfg(test)] +mod tests_ed25519 { + use super::*; + gadget_crypto_core::impl_crypto_tests!(SpEd25519, SpEd25519Pair, SpEd25519Signature); +} + +#[cfg(test)] +mod tests_sr25519 { + use super::*; + gadget_crypto_core::impl_crypto_tests!(SpSr25519, SpSr25519Pair, SpSr25519Signature); +} diff --git a/crates/crypto/sr25519/src/schnorrkel_sr25519.rs b/crates/crypto/sr25519/src/schnorrkel_sr25519.rs index 3c6a41d..ad9fd42 100644 --- a/crates/crypto/sr25519/src/schnorrkel_sr25519.rs +++ b/crates/crypto/sr25519/src/schnorrkel_sr25519.rs @@ -31,7 +31,8 @@ macro_rules! impl_schnorrkel_serde { &self, serializer: S, ) -> core::result::Result { - serializer.serialize_bytes(&self.0.to_bytes()) + let bytes = self.0.to_bytes().into(); + Vec::serialize(&bytes, serializer) } } @@ -53,8 +54,8 @@ impl_schnorrkel_serde!(Secret, schnorrkel::SecretKey); impl_schnorrkel_serde!(SchnorrkelSignature, schnorrkel::Signature); impl KeyType for SchnorrkelSr25519 { - type Public = Public; type Secret = Secret; + type Public = Public; type Signature = SchnorrkelSignature; type Error = Sr25519Error; @@ -113,3 +114,9 @@ impl KeyType for SchnorrkelSr25519 { } } } + +#[cfg(test)] +mod tests { + use super::*; + gadget_crypto_core::impl_crypto_tests!(SchnorrkelSr25519, Secret, SchnorrkelSignature); +} diff --git a/crates/crypto/src/hashing.rs b/crates/crypto/src/hashing.rs index c4902a4..8d6f42c 100644 --- a/crates/crypto/src/hashing.rs +++ b/crates/crypto/src/hashing.rs @@ -24,3 +24,10 @@ pub fn keccak_256(data: &[u8]) -> [u8; 32] { let output = hasher.finalize(); output.into() } + +pub fn blake3_256(data: &[u8]) -> [u8; 32] { + let mut hasher = blake3::Hasher::new(); + hasher.update(data); + let output = hasher.finalize(); + output.into() +} diff --git a/crates/metrics/Cargo.toml b/crates/metrics/Cargo.toml index 3602d37..5d1a121 100644 --- a/crates/metrics/Cargo.toml +++ b/crates/metrics/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "metrics" +name = "gadget-metrics" version = "0.1.0" authors.workspace = true edition.workspace = true diff --git a/crates/networking/Cargo.toml b/crates/networking/Cargo.toml index f6f0ceb..8e16c5c 100644 --- a/crates/networking/Cargo.toml +++ b/crates/networking/Cargo.toml @@ -26,8 +26,7 @@ lru-mem = { workspace = true } serde = { workspace = true } serde_json = { workspace = true, features = ["alloc"] } hex = { workspace = true } -itertools = { workspace = true, features = ["use_alloc"]} -matchbox_socket = { workspace = true } +itertools = { workspace = true, features = ["use_alloc"] } parking_lot = { workspace = true } thiserror = { workspace = true } @@ -76,6 +75,14 @@ std = [ "serde_json/std", "round-based?/std", ] -round-based-compat = [ - "round-based", -] \ No newline at end of file + +round-based-compat = ["round-based"] + +# Only one of these features should be enabled at a time. +# If none are enabled, k256 ECDSA will be used by default. +sp-core-ecdsa = ["gadget-crypto/sp-core"] +sp-core-sr25519 = ["gadget-crypto/sp-core"] +sp-core-ed25519 = ["gadget-crypto/sp-core"] + +[lints] +workspace = true diff --git a/crates/networking/src/gossip.rs b/crates/networking/src/gossip.rs index 88bcbed..1be4fe3 100644 --- a/crates/networking/src/gossip.rs +++ b/crates/networking/src/gossip.rs @@ -4,13 +4,13 @@ clippy::module_name_repetitions, clippy::exhaustive_enums )] + +use crate::key_types::{KeyPair, PublicKey, Signature}; use crate::Error; use async_trait::async_trait; -use gadget_crypto::hashing::keccak_256; -use gadget_crypto::k256_crypto::{K256Signature, K256SigningKey, K256VerifyingKey}; +use gadget_crypto::hashing::blake3_256; use gadget_std::collections::BTreeMap; use gadget_std::string::ToString; -use gadget_std::sync::atomic::AtomicU32; use gadget_std::sync::Arc; use libp2p::gossipsub::IdentTopic; use libp2p::kad::store::MemoryStore; @@ -19,6 +19,7 @@ use libp2p::{ }; use lru_mem::LruCache; use serde::{Deserialize, Serialize}; +use std::sync::atomic::AtomicUsize; use tokio::sync::mpsc::UnboundedSender; use tokio::sync::{Mutex, RwLock}; @@ -41,12 +42,13 @@ pub struct MyBehaviour { pub ping: libp2p::ping::Behaviour, } -pub type InboundMapping = (IdentTopic, UnboundedSender>, Arc); +pub type InboundMapping = (IdentTopic, UnboundedSender>, Arc); pub struct NetworkServiceWithoutSwarm<'a> { pub inbound_mapping: &'a [InboundMapping], - pub ecdsa_peer_id_to_libp2p_id: Arc>>, - pub ecdsa_secret_key: &'a K256SigningKey, + pub public_key_to_libp2p_id: Arc>>, + pub secret_key: &'a KeyPair, + pub connected_peers: Arc, pub span: tracing::Span, pub my_id: PeerId, } @@ -59,8 +61,9 @@ impl<'a> NetworkServiceWithoutSwarm<'a> { NetworkService { swarm, inbound_mapping: self.inbound_mapping, - ecdsa_peer_id_to_libp2p_id: &self.ecdsa_peer_id_to_libp2p_id, - ecdsa_secret_key: self.ecdsa_secret_key, + public_key_to_libp2p_id: &self.public_key_to_libp2p_id, + secret_key: self.secret_key, + connected_peers: self.connected_peers.clone(), span: &self.span, my_id: self.my_id, } @@ -70,8 +73,9 @@ impl<'a> NetworkServiceWithoutSwarm<'a> { pub struct NetworkService<'a> { pub swarm: &'a mut libp2p::Swarm, pub inbound_mapping: &'a [InboundMapping], - pub ecdsa_peer_id_to_libp2p_id: &'a Arc>>, - pub ecdsa_secret_key: &'a K256SigningKey, + pub public_key_to_libp2p_id: &'a Arc>>, + pub connected_peers: Arc, + pub secret_key: &'a KeyPair, pub span: &'a tracing::Span, pub my_id: PeerId, } @@ -260,8 +264,8 @@ pub struct GossipHandle { pub topic: IdentTopic, pub tx_to_outbound: UnboundedSender, pub rx_from_inbound: Arc>>>, - pub connected_peers: Arc, - pub ecdsa_peer_id_to_libp2p_id: Arc>>, + pub connected_peers: Arc, + pub public_key_to_libp2p_id: Arc>>, pub recent_messages: parking_lot::Mutex>, pub my_id: PeerId, } @@ -270,7 +274,7 @@ impl GossipHandle { #[must_use] pub fn connected_peers(&self) -> usize { self.connected_peers - .load(std::sync::atomic::Ordering::Relaxed) as usize + .load(std::sync::atomic::Ordering::Relaxed) } #[must_use] @@ -279,8 +283,8 @@ impl GossipHandle { } /// Returns an ordered vector of public keys of the peers that are connected to the gossipsub topic. - pub async fn peers(&self) -> Vec { - self.ecdsa_peer_id_to_libp2p_id + pub async fn peers(&self) -> Vec { + self.public_key_to_libp2p_id .read() .await .keys() @@ -321,8 +325,8 @@ pub struct GossipMessage { #[derive(Serialize, Deserialize, Debug)] pub enum MyBehaviourRequest { Handshake { - ecdsa_public_key: K256VerifyingKey, - signature: K256Signature, + public_key: PublicKey, + signature: Signature, }, Message { topic: String, @@ -330,39 +334,12 @@ pub enum MyBehaviourRequest { }, } -#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)] -pub struct EcdsaSignatureWrapper(pub [u8; 65]); - -impl serde::Serialize for EcdsaSignatureWrapper { - fn serialize(&self, serializer: S) -> Result - where - S: serde::Serializer, - { - serializer.serialize_bytes(&self.0) - } -} - -impl<'de> serde::Deserialize<'de> for EcdsaSignatureWrapper { - fn deserialize(deserializer: D) -> Result - where - D: serde::Deserializer<'de>, - { - let bytes = >::deserialize(deserializer)?; - if bytes.len() != 65 { - return Err(serde::de::Error::custom("Invalid signature length")); - } - let mut signature = [0u8; 65]; - signature.copy_from_slice(&bytes); - Ok(EcdsaSignatureWrapper(signature)) - } -} - #[non_exhaustive] #[derive(Serialize, Deserialize, Debug)] pub enum MyBehaviourResponse { Handshaked { - ecdsa_public_key: K256VerifyingKey, - ecdsa_signature: K256Signature, + public_key: PublicKey, + signature: Signature, }, MessageHandled, } @@ -385,7 +362,7 @@ impl Network for GossipHandle { drop(lock); match bincode::deserialize::(&message_bytes) { Ok(message) => { - let hash = keccak_256(&message.payload); + let hash = blake3_256(&message_bytes); let mut map = self.recent_messages.lock(); if map .insert(hash, ()) @@ -396,7 +373,7 @@ impl Network for GossipHandle { } } Err(e) => { - gadget_logging::error!("Failed to deserialize message: {e}"); + gadget_logging::error!("Failed to deserialize message (gossip): {e}"); } } } @@ -404,20 +381,19 @@ impl Network for GossipHandle { async fn send_message(&self, message: ProtocolMessage) -> Result<(), Error> { let message_type = if let Some(ParticipantInfo { - ecdsa_public_key: Some(to), + public_key: Some(to), .. }) = message.recipient { - let libp2p_id = self - .ecdsa_peer_id_to_libp2p_id - .read() - .await + let pub_key_to_libp2p_id = self.public_key_to_libp2p_id.read().await; + gadget_logging::trace!("Handshake count: {}", pub_key_to_libp2p_id.len()); + let libp2p_id = pub_key_to_libp2p_id .get(&to) .copied() .ok_or_else(|| { Error::NetworkError(format!( - "No libp2p ID found for ecdsa public key: {:?}. No handshake happened?", - to + "No libp2p ID found for crypto public key: {:?}. No handshake happened? Total handshakes: {}", + to, pub_key_to_libp2p_id.len(), )) })?; @@ -426,7 +402,8 @@ impl Network for GossipHandle { MessageType::Broadcast }; - let raw_payload = serde_json::to_vec(&message).map_err(|e| Error::SerdeJson(e))?; + let raw_payload = + bincode::serialize(&message).map_err(|err| Error::MessagingError(err.to_string()))?; let payload_inner = match message_type { MessageType::Broadcast => GossipOrRequestResponse::Gossip(GossipMessage { topic: self.topic.to_string(), diff --git a/crates/networking/src/handlers/connections.rs b/crates/networking/src/handlers/connections.rs index 07344d4..d80d382 100644 --- a/crates/networking/src/handlers/connections.rs +++ b/crates/networking/src/handlers/connections.rs @@ -1,7 +1,8 @@ #![allow(unused_results, clippy::used_underscore_binding)] use crate::gossip::{MyBehaviourRequest, NetworkService}; -use gadget_crypto::{hashing::keccak_256, k256_crypto::K256Ecdsa, KeyType}; +use crate::key_types::Curve; +use gadget_crypto::{hashing::blake3_256, KeyType}; use itertools::Itertools; use libp2p::PeerId; @@ -10,20 +11,26 @@ impl NetworkService<'_> { pub(crate) async fn handle_connection_established( &mut self, peer_id: PeerId, - num_established: u32, + _num_established: u32, ) { gadget_logging::debug!("Connection established"); - if num_established == 1 { - let my_peer_id = self.swarm.local_peer_id(); + if !self + .public_key_to_libp2p_id + .read() + .await + .iter() + .any(|(_, id)| id == &peer_id) + { + let my_peer_id = *self.swarm.local_peer_id(); let msg = my_peer_id.to_bytes(); - let hash = keccak_256(&msg); - match ::sign_with_secret_pre_hashed( - &mut self.ecdsa_secret_key.clone(), + let hash = blake3_256(&msg); + match ::sign_with_secret_pre_hashed( + &mut self.secret_key.clone(), &hash, ) { Ok(signature) => { let handshake = MyBehaviourRequest::Handshake { - ecdsa_public_key: self.ecdsa_secret_key.verifying_key(), + public_key: self.secret_key.public(), signature, }; self.swarm @@ -34,6 +41,7 @@ impl NetworkService<'_> { .behaviour_mut() .gossipsub .add_explicit_peer(&peer_id); + gadget_logging::info!("Sent handshake from {my_peer_id} to {peer_id}"); } Err(e) => { gadget_logging::error!("Failed to sign handshake: {e}"); @@ -55,6 +63,13 @@ impl NetworkService<'_> { .behaviour_mut() .gossipsub .remove_explicit_peer(&peer_id); + let mut pub_key_to_libp2p_id = self.public_key_to_libp2p_id.write().await; + let len_initial = 0; + pub_key_to_libp2p_id.retain(|_, id| *id != peer_id); + if pub_key_to_libp2p_id.len() == len_initial + 1 { + self.connected_peers + .fetch_sub(1, std::sync::atomic::Ordering::Relaxed); + } } } @@ -96,7 +111,7 @@ impl NetworkService<'_> { error: libp2p::swarm::DialError, ) { if let libp2p::swarm::DialError::Transport(addrs) = error { - let read = self.ecdsa_peer_id_to_libp2p_id.read().await; + let read = self.public_key_to_libp2p_id.read().await; for (addr, err) in addrs { if let Some(peer_id) = get_peer_id_from_multiaddr(&addr) { if !read.values().contains(&peer_id) { diff --git a/crates/networking/src/handlers/gossip.rs b/crates/networking/src/handlers/gossip.rs index 3e63d4e..215effa 100644 --- a/crates/networking/src/handlers/gossip.rs +++ b/crates/networking/src/handlers/gossip.rs @@ -2,16 +2,16 @@ use crate::gossip::{GossipMessage, NetworkService}; use gadget_std::string::ToString; -use gadget_std::sync::atomic::AtomicU32; use gadget_std::sync::Arc; use libp2p::gossipsub::TopicHash; use libp2p::{gossipsub, PeerId}; +use std::sync::atomic::AtomicUsize; impl NetworkService<'_> { #[tracing::instrument(skip(self, event))] pub(crate) async fn handle_gossip(&mut self, event: gossipsub::Event) { use gossipsub::Event::{GossipsubNotSupported, Message, Subscribed, Unsubscribed}; - let with_connected_peers = |topic: &TopicHash, f: fn(&Arc)| { + let with_connected_peers = |topic: &TopicHash, f: fn(&Arc)| { let maybe_mapping = self .inbound_mapping .iter() @@ -34,8 +34,11 @@ impl NetworkService<'_> { .await; } Subscribed { peer_id, topic } => { - let added = with_connected_peers(&topic, |connected_peers| { - connected_peers.fetch_add(1, gadget_std::sync::atomic::Ordering::Relaxed); + let added = with_connected_peers(&topic, |_connected_peers| { + // Code commented out because each peer needs to do a request-response + // direct P2P handshake, which is where the connected_peers counter is + // incremented. Adding here will just add twice, which is undesirable. + // connected_peers.fetch_add(1, gadget_std::sync::atomic::Ordering::Relaxed); }); if added { gadget_logging::trace!("{peer_id} subscribed to {topic}"); @@ -44,8 +47,11 @@ impl NetworkService<'_> { } } Unsubscribed { peer_id, topic } => { - let removed = with_connected_peers(&topic, |connected_peers| { - connected_peers.fetch_sub(1, gadget_std::sync::atomic::Ordering::Relaxed); + let removed = with_connected_peers(&topic, |_connected_peers| { + // Code commented out because each peer needs to do a request-response + // direct P2P handshake, which is where the connected_peers counter is + // decremented. Subbing here will just sub twice, which is undesirable. + // connected_peers.fetch_sub(1, gadget_std::sync::atomic::Ordering::Relaxed); }); if removed { gadget_logging::trace!("{peer_id} unsubscribed from {topic}"); @@ -99,7 +105,7 @@ impl NetworkService<'_> { } } Err(e) => { - gadget_logging::error!("Failed to deserialize message: {e}"); + gadget_logging::error!("Failed to deserialize message (handlers/gossip): {e}"); } } } diff --git a/crates/networking/src/handlers/p2p.rs b/crates/networking/src/handlers/p2p.rs index c7f138f..b612d4e 100644 --- a/crates/networking/src/handlers/p2p.rs +++ b/crates/networking/src/handlers/p2p.rs @@ -1,12 +1,13 @@ #![allow(unused_results)] use crate::gossip::{MyBehaviourRequest, MyBehaviourResponse, NetworkService}; -use gadget_crypto::hashing::keccak_256; -use gadget_crypto::k256_crypto::K256Ecdsa; +use crate::key_types::Curve; +use gadget_crypto::hashing::blake3_256; use gadget_crypto::KeyType; use gadget_std::string::ToString; use libp2p::gossipsub::IdentTopic; use libp2p::{request_response, PeerId}; +use std::sync::atomic::Ordering; impl NetworkService<'_> { #[tracing::instrument(skip(self, event))] @@ -73,42 +74,6 @@ impl NetworkService<'_> { } } - #[tracing::instrument(skip(self, message))] - async fn handle_p2p_response( - &mut self, - peer: PeerId, - request_id: request_response::OutboundRequestId, - message: MyBehaviourResponse, - ) { - use crate::gossip::MyBehaviourResponse::{Handshaked, MessageHandled}; - match message { - Handshaked { - ecdsa_public_key, - ecdsa_signature, - } => { - let msg = peer.to_bytes(); - let hash = keccak_256(&msg); - let valid = - ::verify(&ecdsa_public_key, &hash, &ecdsa_signature); - if !valid { - gadget_logging::warn!("Invalid signature from peer: {peer}"); - // TODO: report this peer. - self.ecdsa_peer_id_to_libp2p_id - .write() - .await - .remove(&ecdsa_public_key); - let _ = self.swarm.disconnect_peer_id(peer); - return; - } - self.ecdsa_peer_id_to_libp2p_id - .write() - .await - .insert(ecdsa_public_key, peer); - } - MessageHandled => {} - } - } - #[tracing::instrument(skip(self, req, channel))] async fn handle_p2p_request( &mut self, @@ -120,36 +85,41 @@ impl NetworkService<'_> { use crate::gossip::MyBehaviourRequest::{Handshake, Message}; let result = match req { Handshake { - ecdsa_public_key, + public_key, signature, } => { gadget_logging::trace!("Received handshake from peer: {peer}"); // Verify the signature let msg = peer.to_bytes(); - let hash = keccak_256(&msg); - let valid = ::verify(&ecdsa_public_key, &hash, &signature); + let hash = blake3_256(&msg); + let valid = ::verify(&public_key, &hash, &signature); if !valid { gadget_logging::warn!("Invalid signature from peer: {peer}"); let _ = self.swarm.disconnect_peer_id(peer); return; } - self.ecdsa_peer_id_to_libp2p_id + if self + .public_key_to_libp2p_id .write() .await - .insert(ecdsa_public_key, peer); + .insert(public_key, peer) + .is_none() + { + let _ = self.connected_peers.fetch_add(1, Ordering::Relaxed); + } // Send response with our public key let my_peer_id = self.swarm.local_peer_id(); let msg = my_peer_id.to_bytes(); - let hash = keccak_256(&msg); - match ::sign_with_secret_pre_hashed( - &mut self.ecdsa_secret_key.clone(), + let hash = blake3_256(&msg); + match ::sign_with_secret_pre_hashed( + &mut self.secret_key.clone(), &hash, ) { Ok(signature) => self.swarm.behaviour_mut().p2p.send_response( channel, MyBehaviourResponse::Handshaked { - ecdsa_public_key: self.ecdsa_secret_key.verifying_key(), - ecdsa_signature: signature, + public_key: self.secret_key.public(), + signature, }, ), Err(e) => { @@ -186,4 +156,45 @@ impl NetworkService<'_> { gadget_logging::error!("Failed to send response for {request_id}"); } } + + #[tracing::instrument(skip(self, message))] + async fn handle_p2p_response( + &mut self, + peer: PeerId, + request_id: request_response::OutboundRequestId, + message: MyBehaviourResponse, + ) { + use crate::gossip::MyBehaviourResponse::{Handshaked, MessageHandled}; + match message { + Handshaked { + public_key, + signature, + } => { + gadget_logging::trace!("Received handshake-ack message from peer: {peer}"); + let msg = peer.to_bytes(); + let hash = blake3_256(&msg); + let valid = ::verify(&public_key, &hash, &signature); + if !valid { + gadget_logging::warn!("Invalid signature from peer: {peer}"); + // TODO: report this peer. + self.public_key_to_libp2p_id + .write() + .await + .remove(&public_key); + let _ = self.swarm.disconnect_peer_id(peer); + return; + } + if self + .public_key_to_libp2p_id + .write() + .await + .insert(public_key, peer) + .is_none() + { + let _ = self.connected_peers.fetch_add(1, Ordering::Relaxed); + } + } + MessageHandled => {} + } + } } diff --git a/crates/networking/src/handlers/ping.rs b/crates/networking/src/handlers/ping.rs index 08375d2..b669bc9 100644 --- a/crates/networking/src/handlers/ping.rs +++ b/crates/networking/src/handlers/ping.rs @@ -3,6 +3,6 @@ use crate::gossip::NetworkService; impl NetworkService<'_> { #[tracing::instrument(skip(self, event))] pub async fn handle_ping_event(&mut self, event: libp2p::ping::Event) { - gadget_logging::trace!("Ping event: {event:?}") + gadget_logging::trace!("Ping event: {event:?}"); } } diff --git a/crates/networking/src/lib.rs b/crates/networking/src/lib.rs index 8a57dff..4b0fa50 100644 --- a/crates/networking/src/lib.rs +++ b/crates/networking/src/lib.rs @@ -7,14 +7,13 @@ pub mod messaging; pub mod networking; #[cfg(feature = "round-based-compat")] pub mod round_based_compat; +#[cfg(feature = "round-based-compat")] +pub use round_based; + pub mod setup; use gadget_std::string::String; -/// Re-exported networking crates -#[cfg(feature = "round-based-compat")] -pub use round_based; - /// Unique identifier for a party pub type UserID = u16; @@ -47,3 +46,64 @@ pub enum Error { #[error("Other error: {0}")] Other(String), } + +pub use key_types::*; + +#[cfg(all( + feature = "sp-core-ecdsa", + not(feature = "sp-core-sr25519"), + not(feature = "sp-core-ed25519") +))] +pub(crate) mod key_types { + pub use gadget_crypto::sp_core_crypto::{ + SpEcdsa as Curve, SpEcdsaPair as KeyPair, SpEcdsaPublic as PublicKey, + SpEcdsaSignature as Signature, + }; +} + +#[cfg(all( + feature = "sp-core-sr25519", + not(feature = "sp-core-ecdsa"), + not(feature = "sp-core-ed25519") +))] +pub(crate) mod key_types { + pub use gadget_crypto::sp_core_crypto::{ + SpSr25519 as Curve, SpSr25519Pair as KeyPair, SpSr25519Public as PublicKey, + SpSr25519Signature as Signature, + }; +} + +#[cfg(all( + feature = "sp-core-ed25519", + not(feature = "sp-core-ecdsa"), + not(feature = "sp-core-sr25519") +))] +pub(crate) mod key_types { + pub use gadget_crypto::sp_core_crypto::{ + SpEd25519 as Curve, SpEd25519Pair as KeyPair, SpEd25519Public as PublicKey, + SpEd25519Signature as Signature, + }; +} + +#[cfg(all( + not(feature = "sp-core-ecdsa"), + not(feature = "sp-core-sr25519"), + not(feature = "sp-core-ed25519") +))] +pub(crate) mod key_types { + // Default to k256 ECDSA implementation + pub use gadget_crypto::k256_crypto::{ + K256Ecdsa as Curve, K256Signature as Signature, K256SigningKey as KeyPair, + K256VerifyingKey as PublicKey, + }; +} + +// Compile-time assertion to ensure only one feature is enabled +#[cfg(any( + all(feature = "sp-core-ecdsa", feature = "sp-core-sr25519"), + all(feature = "sp-core-ecdsa", feature = "sp-core-ed25519"), + all(feature = "sp-core-sr25519", feature = "sp-core-ed25519") +))] +compile_error!( + "Only one of 'sp-core-ecdsa', 'sp-core-sr25519', or 'sp-core-ed25519' features can be enabled at a time" +); diff --git a/crates/networking/src/messaging.rs b/crates/networking/src/messaging.rs index 6cccdf3..0e31e06 100644 --- a/crates/networking/src/messaging.rs +++ b/crates/networking/src/messaging.rs @@ -39,7 +39,7 @@ pub trait MessageMetadata { } #[async_trait] -pub trait MessagingNetwork { +pub trait NetworkMessagingIO { type Message: MessageMetadata + Send + Sync + 'static; async fn next_message(&self) -> Option>; @@ -135,7 +135,7 @@ where M: MessageMetadata + Clone + Send + Sync + Serialize + for<'de> Deserialize<'de> + 'static, B: Backend + Send + Sync + 'static, L: LocalDelivery + Send + Sync + 'static, - N: MessagingNetwork + Send + Sync + 'static, + N: NetworkMessagingIO + Send + Sync + 'static, { backend: Arc, local_delivery: Arc, @@ -149,7 +149,7 @@ where M: MessageMetadata + Clone + Send + Sync + Serialize + for<'de> Deserialize<'de> + 'static, B: Backend + Send + Sync + 'static, L: LocalDelivery + Send + Sync + 'static, - N: MessagingNetwork + Send + Sync + 'static, + N: NetworkMessagingIO + Send + Sync + 'static, { fn clone(&self) -> Self { Self { @@ -167,7 +167,7 @@ where M: MessageMetadata + Clone + Send + Sync + Serialize + for<'de> Deserialize<'de> + 'static, B: Backend + Send + Sync + 'static, L: LocalDelivery + Send + Sync + 'static, - N: MessagingNetwork + Send + Sync + 'static, + N: NetworkMessagingIO + Send + Sync + 'static, { pub fn new(backend: B, local_delivery: L, network: N) -> Self { let this = Self { @@ -251,7 +251,7 @@ where let tracker = self.tracker.read().await; for ((job_id, peer_id), mut messages) in grouped_messages { // Sort messages by MessageId - messages.sort_by_key(|m| m.message_id()); + messages.sort_by_key(MessageMetadata::message_id); // Find the first message we can send based on ACKs if let Some(msg) = messages @@ -277,7 +277,7 @@ where // Sort the pending messages in order by MessageID let pending_messages: Vec = pending_messages .into_iter() - .sorted_by_key(|r| r.message_id()) + .sorted_by_key(MessageMetadata::message_id) .collect(); for message in pending_messages { @@ -286,7 +286,7 @@ where // Create and send ACK if let Err(e) = self .network - .send_message(&self.create_ack_message(&message)) + .send_message(&Self::create_ack_message(&message)) .await { gadget_logging::error!("Failed to send ACK: {e:?}"); @@ -341,6 +341,12 @@ where } } + /// Send a message through the message system + /// + /// # Errors + /// + /// Returns `BackendError::Stopped` if the message system is not running. + /// May also return other `BackendError` variants if the backend storage operation fails. pub async fn send_message(&self, message: M) -> Result<(), BackendError> { if self.is_running.load(std::sync::atomic::Ordering::Relaxed) { self.backend.store_outbound(message).await @@ -349,7 +355,7 @@ where } } - fn create_ack_message(&self, original_message: &M) -> Payload { + fn create_ack_message(original_message: &M) -> Payload { Payload::Ack { job_id: original_message.job_id(), from_id: original_message.source_id(), @@ -368,6 +374,7 @@ type Mailbox = Arc>>; impl InMemoryBackend { + #[must_use] pub fn new() -> Self { Self { outbound: Arc::new(RwLock::new(HashMap::new())), diff --git a/crates/networking/src/networking.rs b/crates/networking/src/networking.rs index cc47ad6..ed9d346 100644 --- a/crates/networking/src/networking.rs +++ b/crates/networking/src/networking.rs @@ -1,10 +1,9 @@ +use crate::key_types::PublicKey; use crate::Error; -use crate::UserID; use async_trait::async_trait; use dashmap::DashMap; use futures::{Stream, StreamExt}; -use gadget_crypto::hashing::keccak_256; -use gadget_crypto::k256_crypto::K256VerifyingKey; +use gadget_crypto::hashing::blake3_256; use gadget_std::boxed::Box; use gadget_std::cmp::Reverse; use gadget_std::collections::{BinaryHeap, HashMap}; @@ -18,6 +17,8 @@ use serde::{Deserialize, Serialize}; use tokio::sync::Mutex; use tracing::trace; +pub type UserID = u16; + #[derive(Debug, Serialize, Deserialize, Clone, Copy, Default)] pub struct IdentifierInfo { pub message_id: u64, @@ -35,16 +36,16 @@ impl Display for IdentifierInfo { #[derive(Debug, Serialize, Deserialize, Clone, Copy)] pub struct ParticipantInfo { pub user_id: u16, - pub ecdsa_public_key: Option, + pub public_key: Option, } impl Display for ParticipantInfo { fn fmt(&self, f: &mut gadget_std::fmt::Formatter<'_>) -> gadget_std::fmt::Result { - let ecdsa_public_key = self - .ecdsa_public_key - .map(|key| format!("ecdsa_public_key: {:?}", key)) + let public_key = self + .public_key + .map(|key| format!("public_key: {:?}", key)) .unwrap_or_default(); - write!(f, "user_id: {}, {}", self.user_id, ecdsa_public_key) + write!(f, "user_id: {}, {}", self.user_id, public_key) } } @@ -77,22 +78,22 @@ pub trait Network: Send + Sync + 'static { from: UserID, to: Option, payload: &Payload, - from_account_id: Option, - to_network_id: Option, + from_account_id: Option, + to_network_id: Option, ) -> ProtocolMessage { let sender_participant_info = ParticipantInfo { user_id: from, - ecdsa_public_key: from_account_id, + public_key: from_account_id, }; let receiver_participant_info = to.map(|to| ParticipantInfo { user_id: to, - ecdsa_public_key: to_network_id, + public_key: to_network_id, }); ProtocolMessage { identifier_info, sender: sender_participant_info, recipient: receiver_participant_info, - payload: serialize(payload).expect("Failed to serialize message"), + payload: bincode::serialize(payload).expect("Failed to serialize message"), } } } @@ -153,7 +154,7 @@ pub struct StreamKey { impl From for StreamKey { fn from(identifier_info: IdentifierInfo) -> Self { let str_repr = identifier_info.to_string(); - let task_hash = keccak_256(str_repr.as_bytes()); + let task_hash = blake3_256(str_repr.as_bytes()); Self { task_hash, round_id: -1, @@ -175,6 +176,18 @@ pub struct MultiplexedSender { } impl MultiplexedSender { + /// Sends a protocol message through the multiplexed channel. + /// + /// # Arguments + /// * `message` - The protocol message to send + /// + /// # Returns + /// * `Ok(())` - If the message was successfully sent + /// * `Err(Error)` - If there was an error sending the message + /// + /// # Errors + /// Returns an error if the receiving end of the channel has been closed, + /// indicating that the network connection is no longer available. pub fn send(&self, message: ProtocolMessage) -> Result<(), Error> { self.inner .send((self.stream_id, message)) @@ -214,12 +227,26 @@ impl Drop for MultiplexedReceiver { // we need to make a key that is unique for each (send->dest) pair and stream. #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)] struct CompoundStreamKey { - stream_id: StreamKey, - send_user_id: UserID, - recv_user_id: Option, + stream_key: StreamKey, + send_user: UserID, + recv_user: Option, } impl NetworkMultiplexer { + /// Creates a new `NetworkMultiplexer` instance. + /// + /// # Arguments + /// * `network` - The underlying network implementation that implements the Network trait + /// + /// # Type Parameters + /// * `N` - The network type that implements the Network trait + /// + /// # Returns + /// * `Self` - A new `NetworkMultiplexer` instance + /// + /// # Panics + /// This function will panic if the internal receiver has already been taken, which should not happen. + #[allow(clippy::too_many_lines)] pub fn new(network: N) -> Self { let (tx_to_networking_layer, mut rx_from_substreams) = tokio::sync::mpsc::unbounded_channel(); @@ -228,7 +255,7 @@ impl NetworkMultiplexer { unclaimed_receiving_streams: Arc::new(DashMap::new()), tx_to_networking_layer: MultiplexedSender { inner: tx_to_networking_layer, - stream_id: Default::default(), + stream_id: StreamKey::default(), }, sequence_numbers: Arc::new(DashMap::new()), }; @@ -244,9 +271,9 @@ impl NetworkMultiplexer { let task1 = async move { while let Some((stream_id, msg)) = rx_from_substreams.recv().await { let compound_key = CompoundStreamKey { - stream_id, - send_user_id: msg.sender.user_id, - recv_user_id: msg.recipient.as_ref().map(|p| p.user_id), + stream_key: stream_id, + send_user: msg.sender.user_id, + recv_user: msg.recipient.as_ref().map(|p| p.user_id), }; let mut seq = sequence_numbers.entry(compound_key).or_insert(0); @@ -276,7 +303,7 @@ impl NetworkMultiplexer { }; if let Err(err) = network_clone.send_message(message).await { - gadget_logging::error!(%err, "Failed to send message to network"); + gadget_logging::error!("Failed to send message to network: {err:?}"); break; } } @@ -286,8 +313,8 @@ impl NetworkMultiplexer { let mut pending_messages: HashMap< CompoundStreamKey, BinaryHeap>, - > = Default::default(); - let mut expected_seqs: HashMap = Default::default(); + > = HashMap::default(); + let mut expected_seqs: HashMap = HashMap::default(); while let Some(mut msg) = network_clone.next_message().await { if let Ok(multiplexed_message) = @@ -295,9 +322,9 @@ impl NetworkMultiplexer { { let stream_id = multiplexed_message.stream_id; let compound_key = CompoundStreamKey { - stream_id, - send_user_id: msg.sender.user_id, - recv_user_id: msg.recipient.as_ref().map(|p| p.user_id), + stream_key: stream_id, + send_user: msg.sender.user_id, + recv_user: msg.recipient.as_ref().map(|p| p.user_id), }; let seq = multiplexed_message.payload.seq; msg.payload = multiplexed_message.payload.payload; @@ -307,12 +334,7 @@ impl NetworkMultiplexer { let expected_seq = expected_seqs.entry(compound_key).or_default(); let send_user = msg.sender.user_id; - let recv_user = msg - .recipient - .as_ref() - .map(|p| p.user_id as i32) - .unwrap_or(-1); - + let recv_user = msg.recipient.as_ref().map_or(-1, |p| i32::from(p.user_id)); let compound_key_hex = hex::encode(bincode::serialize(&compound_key).unwrap()); trace!( @@ -377,16 +399,16 @@ impl NetworkMultiplexer { let _ = unclaimed_streams.insert(stream_id, rx); } } else { - gadget_logging::error!("Failed to deserialize message"); + gadget_logging::error!("Failed to deserialize message (networking)"); } } }; tokio::select! { - _ = task1 => { + () = task1 => { gadget_logging::error!("Task 1 exited"); }, - _ = task2 => { + () = task2 => { gadget_logging::error!("Task 2 exited"); } } @@ -420,6 +442,11 @@ impl NetworkMultiplexer { /// Creates a subnetwork, and also forwards all messages to the given channel. The network cannot be used to /// receive messages since the messages will be forwarded to the provided channel. + /// + /// # Panics + /// + /// This function will panic if the internal receiver has already been taken, which should not happen + /// under normal circumstances. pub fn multiplex_with_forwarding( &self, id: impl Into, @@ -486,6 +513,17 @@ pub struct SubNetwork { } impl SubNetwork { + /// Sends a protocol message through the subnetwork. + /// + /// # Arguments + /// * `message` - The protocol message to send + /// + /// # Returns + /// * `Ok(())` - If the message was successfully sent + /// * `Err(Error)` - If there was an error sending the message + /// + /// # Errors + /// * Returns an error if the underlying network connection is closed or unavailable pub fn send(&self, message: ProtocolMessage) -> Result<(), Error> { self.tx.send(message) } @@ -506,32 +544,26 @@ impl Network for SubNetwork { } } -pub fn deserialize<'a, T>(data: &'a [u8]) -> Result -where - T: Deserialize<'a>, -{ - serde_json::from_slice::(data) -} - -pub fn serialize(object: &impl Serialize) -> Result, serde_json::Error> { - serde_json::to_vec(object) -} - #[cfg(test)] mod tests { use super::*; use crate::gossip::GossipHandle; use futures::{stream, StreamExt}; - use gadget_crypto::{ - hashing::sha2_256, - k256_crypto::{K256Ecdsa, K256SigningKey}, - KeyType, - }; + use gadget_crypto::hashing::blake3_256; + use gadget_crypto::KeyType; + use gadget_logging::setup_log; use gadget_std::collections::BTreeMap; use serde::{Deserialize, Serialize}; const TOPIC: &str = "/gadget/test/1.0.0"; + fn deserialize<'a, T>(data: &'a [u8]) -> Result + where + T: Deserialize<'a>, + { + bincode::deserialize(data).map_err(|err| Error::Other(err.to_string())) + } + #[derive(Debug, Serialize, Deserialize, Clone)] enum Msg { Round1(Round1Msg), @@ -561,58 +593,41 @@ mod tests { } const NODE_COUNT: u16 = 10; - - pub fn setup_log() { - use tracing_subscriber::util::SubscriberInitExt; - let env_filter = tracing_subscriber::EnvFilter::from_default_env() - .add_directive("tokio=off".parse().unwrap()) - .add_directive("hyper=off".parse().unwrap()) - .add_directive("gadget=debug".parse().unwrap()); - - let _ = tracing_subscriber::fmt::SubscriberBuilder::default() - .compact() - .without_time() - .with_span_events(tracing_subscriber::fmt::format::FmtSpan::NONE) - .with_target(false) - .with_env_filter(env_filter) - .with_test_writer() - .finish() - .try_init(); - } - async fn wait_for_nodes_connected(nodes: &[GossipHandle]) { let node_count = nodes.len(); // wait for the nodes to connect to each other - let max_retries = 30 * node_count; + let max_retries = 10 * node_count; let mut retry = 0; loop { gadget_logging::debug!(%node_count, %max_retries, %retry, "Checking if all nodes are connected to each other"); let connected = nodes .iter() - .map(|node| node.connected_peers()) + .map(super::super::gossip::GossipHandle::connected_peers) .collect::>(); let all_connected = connected .iter() .enumerate() .inspect(|(node, peers)| { - gadget_logging::debug!("Node {node} has {peers} connected peers") + gadget_logging::debug!("Node {node} has {peers} connected peers"); }) - .all(|(_, &peers)| peers == node_count - 1); + .all(|(_, &peers)| peers >= node_count - 1); if all_connected { gadget_logging::debug!("All nodes are connected to each other"); return; } tokio::time::sleep(tokio::time::Duration::from_millis(300)).await; retry += 1; - if retry > max_retries { - panic!("Failed to connect all nodes to each other"); - } + assert!( + retry <= max_retries, + "Failed to connect all nodes to each other" + ); } } #[tokio::test(flavor = "multi_thread")] + #[allow(clippy::cast_possible_truncation)] async fn test_p2p() { setup_log(); let nodes = stream::iter(0..NODE_COUNT) @@ -633,11 +648,12 @@ mod tests { .expect("Failed to run protocol"); // Assert that all are okay. assert!( - results.iter().all(|r| r.is_ok()), + results.iter().all(std::result::Result::is_ok), "Some nodes failed to run protocol" ); } + #[allow(clippy::too_many_lines)] async fn run_protocol(node: N, i: u16) -> Result<(), crate::Error> { let task_hash = [0u8; 32]; // Safety note: We should be passed a NetworkMultiplexer, and all uses of the N: Network @@ -820,27 +836,29 @@ mod tests { Ok(()) } - fn node_with_id() -> (crate::gossip::GossipHandle, K256SigningKey) { + fn node_with_id() -> (crate::gossip::GossipHandle, crate::key_types::KeyPair) { let identity = libp2p::identity::Keypair::generate_ed25519(); - let ecdsa_key = K256Ecdsa::generate_with_seed(None).unwrap(); + let crypto_key = crate::key_types::Curve::generate_with_seed(None).unwrap(); let bind_port = 0; let handle = crate::setup::start_p2p_network(crate::setup::NetworkConfig::new_service_network( identity, - ecdsa_key.clone(), - Default::default(), + crypto_key.clone(), + Vec::default(), bind_port, TOPIC, )) .unwrap(); - (handle, ecdsa_key) + (handle, crypto_key) } fn node() -> crate::gossip::GossipHandle { node_with_id().0 } + const MESSAGE_COUNT: u64 = 100; + #[tokio::test(flavor = "multi_thread")] async fn test_stress_test_multiplexer() { setup_log(); @@ -848,33 +866,26 @@ mod tests { let (network0, id0) = node_with_id(); let (network1, id1) = node_with_id(); - let mut networks = vec![network0, network1]; - - wait_for_nodes_connected(&networks).await; + let mut gossip_networks = vec![network0, network1]; - let (network0, network1) = (networks.remove(0), networks.remove(0)); + wait_for_nodes_connected(&gossip_networks).await; + gadget_logging::info!("Gossiping test"); + let (network0, network1) = (gossip_networks.remove(0), gossip_networks.remove(0)); - let public0 = id0.verifying_key(); - let public1 = id1.verifying_key(); + let public0 = id0.public(); + let public1 = id1.public(); let multiplexer0 = NetworkMultiplexer::new(network0); let multiplexer1 = NetworkMultiplexer::new(network1); let stream_key = StreamKey { - task_hash: sha2_256(&[255u8]), + task_hash: blake3_256(&[255u8]), round_id: 100, }; let sub0 = multiplexer0.multiplex(stream_key); let sub1 = multiplexer1.multiplex(stream_key); - const MESSAGE_COUNT: u64 = 100; - - #[derive(Serialize, Deserialize)] - struct StressTestPayload { - value: u64, - } - let handle0 = tokio::spawn(async move { let sub0 = &sub0; @@ -951,81 +962,92 @@ mod tests { } #[tokio::test(flavor = "multi_thread")] + #[allow(clippy::cast_possible_truncation)] async fn test_nested_multiplexer() { setup_log(); gadget_logging::info!("Starting test_nested_multiplexer"); - let network0 = node(); - let network1 = node(); + let (network0, network1) = get_networks().await; - let mut networks = vec![network0, network1]; + nested_multiplex(0, 10, network0, network1).await; + } - wait_for_nodes_connected(&networks).await; + async fn get_networks() -> (GossipHandle, GossipHandle) { + let network0 = node(); + let network1 = node(); - let (network0, network1) = (networks.remove(0), networks.remove(0)); + let mut gossip_networks = vec![network0, network1]; - async fn nested_multiplex( - cur_depth: usize, - max_depth: usize, - network0: N, - network1: N, - ) { - gadget_logging::info!("At nested depth = {cur_depth}/{max_depth}"); + wait_for_nodes_connected(&gossip_networks).await; - if cur_depth == max_depth { - return; - } + (gossip_networks.remove(0), gossip_networks.remove(0)) + } - let multiplexer0 = NetworkMultiplexer::new(network0); - let multiplexer1 = NetworkMultiplexer::new(network1); + async fn nested_multiplex( + cur_depth: usize, + max_depth: usize, + network0: N, + network1: N, + ) { + gadget_logging::info!("At nested depth = {cur_depth}/{max_depth}"); - let stream_key = StreamKey { - task_hash: sha2_256(&[(cur_depth % 255) as u8]), - round_id: 0, - }; + if cur_depth == max_depth { + return; + } - let subnetwork0 = multiplexer0.multiplex(stream_key); - let subnetwork1 = multiplexer1.multiplex(stream_key); + let multiplexer0 = NetworkMultiplexer::new(network0); + let multiplexer1 = NetworkMultiplexer::new(network1); - // Send a message in the subnetwork0 to subnetwork1 and vice versa, assert values of message - let payload = vec![1, 2, 3]; - let msg = GossipHandle::build_protocol_message( - IdentifierInfo::default(), - 0, - Some(1), - &payload, - None, - None, - ); + let stream_key = StreamKey { + #[allow(clippy::cast_possible_truncation)] + task_hash: blake3_256(&[(cur_depth % 255) as u8]), + round_id: 0, + }; - subnetwork0.send(msg.clone()).unwrap(); + let subnetwork0 = multiplexer0.multiplex(stream_key); + let subnetwork1 = multiplexer1.multiplex(stream_key); + + // Send a message in the subnetwork0 to subnetwork1 and vice versa, assert values of message + let payload = vec![1, 2, 3]; + let msg = GossipHandle::build_protocol_message( + IdentifierInfo::default(), + 0, + Some(1), + &payload, + None, + None, + ); - let received_msg = subnetwork1.recv().await.unwrap(); - assert_eq!(received_msg.payload, msg.payload); + subnetwork0.send(msg.clone()).unwrap(); - let msg = GossipHandle::build_protocol_message( - IdentifierInfo::default(), - 1, - Some(0), - &payload, - None, - None, - ); + let received_msg = subnetwork1.recv().await.unwrap(); + assert_eq!(received_msg.payload, msg.payload); - subnetwork1.send(msg.clone()).unwrap(); + let msg = GossipHandle::build_protocol_message( + IdentifierInfo::default(), + 1, + Some(0), + &payload, + None, + None, + ); - let received_msg = subnetwork0.recv().await.unwrap(); - assert_eq!(received_msg.payload, msg.payload); - tracing::info!("Done nested depth = {cur_depth}/{max_depth}"); + subnetwork1.send(msg.clone()).unwrap(); - Box::pin(nested_multiplex( - cur_depth + 1, - max_depth, - subnetwork0, - subnetwork1, - )) - .await - } + let received_msg = subnetwork0.recv().await.unwrap(); + assert_eq!(received_msg.payload, msg.payload); + tracing::info!("Done nested depth = {cur_depth}/{max_depth}"); - nested_multiplex(0, 10, network0, network1).await; + Box::pin(nested_multiplex( + cur_depth + 1, + max_depth, + subnetwork0, + subnetwork1, + )) + .await; } } + +#[derive(Serialize, Deserialize)] +struct StressTestPayload { + value: u64, +} diff --git a/crates/networking/src/round_based_compat.rs b/crates/networking/src/round_based_compat.rs index 93a9740..a49ed3b 100644 --- a/crates/networking/src/round_based_compat.rs +++ b/crates/networking/src/round_based_compat.rs @@ -1,3 +1,4 @@ +use crate::key_types::PublicKey; use crate::networking::{ IdentifierInfo, NetworkMultiplexer, ProtocolMessage, StreamKey, SubNetwork, }; @@ -5,7 +6,6 @@ use core::pin::Pin; use core::sync::atomic::AtomicU64; use core::task::{ready, Context, Poll}; use futures::prelude::*; -use gadget_crypto::k256_crypto::K256VerifyingKey; use gadget_std::collections::{BTreeMap, HashMap, VecDeque}; use gadget_std::string::ToString; use gadget_std::sync::Arc; @@ -25,12 +25,13 @@ where M: Clone + Send + Unpin + 'static, M: serde::Serialize + serde::de::DeserializeOwned, { - /// Create a new NetworkDeliveryWrapper over a network implementation with the given party index. + /// Create a new `NetworkDeliveryWrapper` over a network implementation with the given party index. + #[must_use] pub fn new( mux: Arc, i: PartyIndex, task_hash: [u8; 32], - parties: BTreeMap, + parties: BTreeMap, ) -> Self { let (tx_forward, rx) = tokio::sync::mpsc::unbounded_channel(); // By default, we create 10 substreams for each party. @@ -60,7 +61,7 @@ where } } -/// A NetworkWrapper wraps a network implementation +/// A `NetworkWrapper` wraps a network implementation /// and implements [`Stream`] and [`Sink`] for it. pub struct NetworkWrapper { /// The current party index. @@ -72,9 +73,9 @@ pub struct NetworkWrapper { /// A queue of incoming messages. #[allow(dead_code)] incoming_queue: VecDeque>, - /// Participants in the network with their corresponding ECDSA public keys. - /// Note: This is a BTreeMap to ensure that the participants are sorted by their party index. - participants: BTreeMap, + /// Participants in the network with their corresponding public keys. + /// Note: This is a `BTreeMap` to ensure that the participants are sorted by their party index. + participants: BTreeMap, next_msg_id: Arc, tx_forward: tokio::sync::mpsc::UnboundedSender, rx: tokio::sync::mpsc::UnboundedReceiver, @@ -116,10 +117,10 @@ where let id = res.identifier_info.message_id; - let msg = match bincode::deserialize(&res.payload) { + let msg = match serde_json::from_slice(&res.payload) { Ok(msg) => msg, Err(err) => { - gadget_logging::error!(%err, "Failed to deserialize message"); + gadget_logging::error!(%err, "Failed to deserialize message (round_based_compat)"); return Poll::Ready(Some(Err(crate::Error::Other(err.to_string())))); } }; @@ -177,7 +178,7 @@ where }; let (to, to_network_id) = match out.recipient { MessageDestination::AllParties => (None, None), - MessageDestination::OneParty(p) => (Some(p), this.participants.get(&p).cloned()), + MessageDestination::OneParty(p) => (Some(p), this.participants.get(&p).copied()), }; if matches!(out.recipient, MessageDestination::OneParty(_)) && to_network_id.is_none() { @@ -189,13 +190,13 @@ where identifier_info, sender: ParticipantInfo { user_id: this.me, - ecdsa_public_key: this.participants.get(&this.me).cloned(), + public_key: this.participants.get(&this.me).copied(), }, recipient: to.map(|user_id| ParticipantInfo { user_id, - ecdsa_public_key: to_network_id, + public_key: to_network_id, }), - payload: bincode::serialize(&out.msg).expect("Should be able to serialize message"), + payload: serde_json::to_vec(&out.msg).expect("Should be able to serialize message"), }; match substream.send(protocol_message) { diff --git a/crates/networking/src/setup.rs b/crates/networking/src/setup.rs index a149e6c..1a95e46 100644 --- a/crates/networking/src/setup.rs +++ b/crates/networking/src/setup.rs @@ -1,9 +1,10 @@ #![allow(unused_results, missing_docs)] + use crate::gossip::{ GossipHandle, IntraNodePayload, MyBehaviour, NetworkServiceWithoutSwarm, MAX_MESSAGE_SIZE, }; +use crate::key_types::KeyPair; use futures::StreamExt; -use gadget_crypto::k256_crypto::K256SigningKey; use gadget_std::boxed::Box; use gadget_std::collections::BTreeMap; use gadget_std::error::Error; @@ -11,7 +12,6 @@ use gadget_std::io; use gadget_std::net::IpAddr; use gadget_std::str::FromStr; use gadget_std::string::String; -use gadget_std::sync::atomic::AtomicU32; use gadget_std::sync::Arc; use gadget_std::time::Duration; use gadget_std::vec::Vec; @@ -21,6 +21,7 @@ use libp2p::{ swarm::dial_opts::DialOpts, StreamProtocol, }; use lru_mem::LruCache; +use std::sync::atomic::AtomicUsize; use tokio::select; use tokio::sync::{Mutex, RwLock}; use tokio::task::{spawn, JoinHandle}; @@ -37,7 +38,7 @@ pub const CLIENT_VERSION: &str = "1.0.0"; /// [`NetworkConfig::new_service_network`] ordinarily. pub struct NetworkConfig { pub identity: libp2p::identity::Keypair, - pub ecdsa_secret_key: K256SigningKey, + pub secret_key: KeyPair, pub bootnodes: Vec, pub bind_port: u16, pub topics: Vec, @@ -60,14 +61,14 @@ impl NetworkConfig { #[must_use] pub fn new( identity: libp2p::identity::Keypair, - ecdsa_secret_key: K256SigningKey, + secret_key: KeyPair, bootnodes: Vec, bind_port: u16, topics: Vec, ) -> Self { Self { identity, - ecdsa_secret_key, + secret_key, bootnodes, bind_port, topics, @@ -78,14 +79,14 @@ impl NetworkConfig { /// Each service within a blueprint must have a unique network name. pub fn new_service_network>( identity: libp2p::identity::Keypair, - ecdsa_secret_key: K256SigningKey, + secret_key: KeyPair, bootnodes: Vec, bind_port: u16, service_name: T, ) -> Self { Self::new( identity, - ecdsa_secret_key, + secret_key, bootnodes, bind_port, vec![service_name.into()], @@ -141,7 +142,7 @@ pub fn multiplexed_libp2p_network(config: NetworkConfig) -> NetworkResult { bootnodes, bind_port, topics, - ecdsa_secret_key, + secret_key, } = config; // Ensure all topics are unique @@ -250,23 +251,23 @@ pub fn multiplexed_libp2p_network(config: NetworkConfig) -> NetworkResult { let mut inbound_mapping = Vec::new(); let (tx_to_outbound, mut rx_to_outbound) = tokio::sync::mpsc::unbounded_channel::(); - let ecdsa_peer_id_to_libp2p_id = Arc::new(RwLock::new(BTreeMap::new())); + let public_key_to_libp2p_id = Arc::new(RwLock::new(BTreeMap::new())); let mut handles_ret = BTreeMap::new(); + let connected_peers = Arc::new(AtomicUsize::new(0)); for network in networks { let topic = IdentTopic::new(network.clone()); swarm.behaviour_mut().gossipsub.subscribe(&topic)?; let (inbound_tx, inbound_rx) = tokio::sync::mpsc::unbounded_channel(); - let connected_peers = Arc::new(AtomicU32::new(0)); inbound_mapping.push((topic.clone(), inbound_tx, connected_peers.clone())); handles_ret.insert( network, GossipHandle { - connected_peers, + connected_peers: connected_peers.clone(), topic, tx_to_outbound: tx_to_outbound.clone(), rx_from_inbound: Arc::new(Mutex::new(inbound_rx)), - ecdsa_peer_id_to_libp2p_id: ecdsa_peer_id_to_libp2p_id.clone(), + public_key_to_libp2p_id: public_key_to_libp2p_id.clone(), // Each key is 32 bytes, therefore 512 messages hashes can be stored in the set recent_messages: LruCache::new(16 * 1024).into(), my_id, @@ -301,8 +302,9 @@ pub fn multiplexed_libp2p_network(config: NetworkConfig) -> NetworkResult { let _enter = span.enter(); let service = NetworkServiceWithoutSwarm { inbound_mapping: &inbound_mapping, - ecdsa_peer_id_to_libp2p_id, - ecdsa_secret_key: &ecdsa_secret_key, + connected_peers, + public_key_to_libp2p_id, + secret_key: &secret_key, span: tracing::debug_span!(parent: &span, "network_service"), my_id, };