diff --git a/code/Cargo.lock b/code/Cargo.lock index 3bdb65886..98bc9e033 100644 --- a/code/Cargo.lock +++ b/code/Cargo.lock @@ -79,9 +79,9 @@ dependencies = [ [[package]] name = "allocator-api2" -version = "0.2.18" +version = "0.2.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c6cb57a04249c6480766f7f7cef5467412af1490f8d1e243141daddada3264f" +checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923" [[package]] name = "android-tzdata" @@ -106,9 +106,9 @@ checksum = "4b46cbb362ab8752921c97e041f5e366ee6297bd428a31275b9fcf1e380f7299" [[package]] name = "anstream" -version = "0.6.15" +version = "0.6.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64e15c1ab1f89faffbf04a634d5e1962e9074f2741eef6d97f3c4e322426d526" +checksum = "8acc5369981196006228e28809f761875c0327210a891e941f4c683b3a99529b" dependencies = [ "anstyle", "anstyle-parse", @@ -121,43 +121,43 @@ dependencies = [ [[package]] name = "anstyle" -version = "1.0.8" +version = "1.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1bec1de6f59aedf83baf9ff929c98f2ad654b97c9510f4e70cf6f661d49fd5b1" +checksum = "55cc3b69f167a1ef2e161439aa98aed94e6028e5f9a59be9a6ffb47aef1651f9" [[package]] name = "anstyle-parse" -version = "0.2.5" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb47de1e80c2b463c735db5b217a0ddc39d612e7ac9e2e96a5aed1f57616c1cb" +checksum = "3b2d16507662817a6a20a9ea92df6652ee4f94f914589377d69f3b21bc5798a9" dependencies = [ "utf8parse", ] [[package]] name = "anstyle-query" -version = "1.1.1" +version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d36fc52c7f6c869915e99412912f22093507da8d9e942ceaf66fe4b7c14422a" +checksum = "79947af37f4177cfead1110013d678905c37501914fba0efea834c3fe9a8d60c" dependencies = [ - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] name = "anstyle-wincon" -version = "3.0.4" +version = "3.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5bf74e1b6e971609db8ca7a9ce79fd5768ab6ae46441c572e46cf596f59e57f8" +checksum = "2109dbce0e72be3ec00bed26e6a7479ca384ad226efdd66db8fa2e3a38c83125" dependencies = [ "anstyle", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] name = "anyhow" -version = "1.0.89" +version = "1.0.94" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86fdf8605db99b54d3cd748a44c6d04df638eb5dafb219b135d0149bd0db01f6" +checksum = "c1fd03a028ef38ba2276dce7e33fcd6369c158a1bca17946c4b1b701891c1ff7" [[package]] name = "arrayref" @@ -183,7 +183,7 @@ dependencies = [ "nom", "num-traits", "rusticata-macros", - "thiserror 1.0.68", + "thiserror 1.0.69", "time", ] @@ -195,7 +195,7 @@ checksum = "965c2d33e53cb6b267e148a4cb0760bc01f4904c1cd4bb4002a085bb016d1490" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.90", "synstructure", ] @@ -207,14 +207,14 @@ checksum = "7b18050c2cd6fe86c3a76584ef5e0baf286d038cda203eb6223df2cc413565f7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.90", ] [[package]] name = "async-io" -version = "2.3.4" +version = "2.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "444b0228950ee6501b3568d3c93bf1176a1fdbc3b758dcd9475046d30f4dc7e8" +checksum = "43a2b323ccce0a1d90b449fd71f2a06ca7faa7c54c2751f06c9bd851fc061059" dependencies = [ "async-lock", "cfg-if", @@ -248,7 +248,7 @@ checksum = "3b43422f69d8ff38f95f1b2bb76517c91589a924d1559a0e935d7c8ce0274c11" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.90", ] [[package]] @@ -259,7 +259,7 @@ checksum = "721cae7de5c34fbb2acd27e21e6d2cf7b886dce0c27388d46c4e6c47ea4318dd" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.90", ] [[package]] @@ -302,10 +302,10 @@ dependencies = [ "axum-core", "bytes", "futures-util", - "http 1.1.0", + "http 1.2.0", "http-body 1.0.1", "http-body-util", - "hyper 1.5.0", + "hyper 1.5.1", "hyper-util", "itoa", "matchit", @@ -318,7 +318,7 @@ dependencies = [ "serde_json", "serde_path_to_error", "serde_urlencoded", - "sync_wrapper 1.0.1", + "sync_wrapper 1.0.2", "tokio", "tower", "tower-layer", @@ -335,13 +335,13 @@ dependencies = [ "async-trait", "bytes", "futures-util", - "http 1.1.0", + "http 1.2.0", "http-body 1.0.1", "http-body-util", "mime", "pin-project-lite", "rustversion", - "sync_wrapper 1.0.1", + "sync_wrapper 1.0.2", "tower-layer", "tower-service", "tracing", @@ -457,7 +457,7 @@ dependencies = [ "ident_case", "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.90", ] [[package]] @@ -547,9 +547,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.1.30" +version = "1.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b16803a61b81d9eabb7eae2588776c4c1e584b738ede45fdbb4c972cec1e9945" +checksum = "f34d93e62b03caf570cccc334cbc6c2fceca82f39211051345108adcba3eebdc" dependencies = [ "shlex", ] @@ -643,9 +643,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.5.21" +version = "4.5.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb3b4b9e5a7c7514dfa52869339ee98b3156b0bfb4e8a77c4ff4babb64b1604f" +checksum = "69371e34337c4c984bbe322360c2547210bf632eb2814bbe78a6e87a2935bd2b" dependencies = [ "clap_builder", "clap_derive", @@ -653,9 +653,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.21" +version = "4.5.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b17a95aa67cc7b5ebd32aa5370189aa0d79069ef1c64ce893bd30fb24bff20ec" +checksum = "6e24c1b4099818523236a8ca881d2b45db98dadfb4625cf6608c12069fcbbde1" dependencies = [ "anstream", "anstyle", @@ -672,14 +672,14 @@ dependencies = [ "heck", "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.90", ] [[package]] name = "clap_lex" -version = "0.7.2" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1462739cb27611015575c0c11df5df7601141071f07518d56fcc1be504cbec97" +checksum = "afb84c814227b90d6895e01398aee0d8033c00e7466aca416fb6a8e0eb19d8a7" [[package]] name = "color-eyre" @@ -710,9 +710,9 @@ dependencies = [ [[package]] name = "colorchoice" -version = "1.0.2" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3fd119d74b830634cea2a0f58bbd0d54540518a14397557951e79340abc28c0" +checksum = "5b63caa9aa9397e2d9480a9b13673856c78d8ac123288526c37d7839f2a86990" [[package]] name = "concurrent-queue" @@ -768,9 +768,9 @@ dependencies = [ [[package]] name = "cpufeatures" -version = "0.2.14" +version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "608697df725056feaccfa42cffdaeeec3fccc4ffc38358ecd19b243e716a78e0" +checksum = "16b80225097f2e5ae4e7179dd2266824648f3e2f49d9134d584b76389d31c4c3" dependencies = [ "libc", ] @@ -916,7 +916,7 @@ checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.90", ] [[package]] @@ -953,7 +953,7 @@ dependencies = [ "proc-macro2", "quote", "strsim", - "syn 2.0.87", + "syn 2.0.90", ] [[package]] @@ -964,7 +964,7 @@ checksum = "d336a2a514f6ccccaa3e09b02d41d35330c07ddf03a62165fcec10bb561c7806" dependencies = [ "darling_core", "quote", - "syn 2.0.87", + "syn 2.0.90", ] [[package]] @@ -1050,7 +1050,7 @@ checksum = "62d671cc41a825ebabc75757b62d3d168c577f9149b2d49ece1dad1f72119d25" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.90", ] [[package]] @@ -1109,7 +1109,7 @@ checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.90", ] [[package]] @@ -1153,7 +1153,7 @@ dependencies = [ "rand_core", "serde", "sha2 0.9.9", - "thiserror 1.0.68", + "thiserror 1.0.69", "zeroize", ] @@ -1207,7 +1207,7 @@ dependencies = [ "heck", "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.90", ] [[package]] @@ -1218,12 +1218,12 @@ checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" [[package]] name = "errno" -version = "0.3.9" +version = "0.3.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "534c5cf6194dfab3db3242765c03bbe257cf92f22b38f6bc0c58d59108a820ba" +checksum = "33d852cb9b869c2a9b3df2f71a3074817f01e1844f839a144f5fcef059a4eb5d" dependencies = [ "libc", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -1239,9 +1239,9 @@ dependencies = [ [[package]] name = "event-listener-strategy" -version = "0.5.2" +version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f214dc438f977e6d4e3500aaa277f5ad94ca83fbbd9b1a15713ce2344ccc5a1" +checksum = "3c3e4e0dd3673c1139bf041f3008816d9cf2946bbfac2945c09e523b8d7b05b2" dependencies = [ "event-listener", "pin-project-lite", @@ -1259,9 +1259,9 @@ dependencies = [ [[package]] name = "fastrand" -version = "2.1.1" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8c02a5121d4ea3eb16a80748c74f5549a5665e4c21333c6098f283870fbdea6" +checksum = "486f806e73c5707928240ddc295403b1b93c96a02038563881c4a2fd84b81ac4" [[package]] name = "ff" @@ -1287,9 +1287,9 @@ checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80" [[package]] name = "flate2" -version = "1.0.34" +version = "1.0.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1b589b4dc103969ad3cf85c950899926ec64300a1a46d76c03a6072957036f0" +checksum = "c936bfdafb507ebbf50b8074c54fa31c5be9a1e7e5f467dd659697041407d07c" dependencies = [ "crc32fast", "miniz_oxide 0.8.0", @@ -1377,9 +1377,9 @@ checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6" [[package]] name = "futures-lite" -version = "2.3.0" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "52527eb5074e35e9339c6b4e8d12600c7128b68fb25dcb9fa9dec18f7c25f3a5" +checksum = "cef40d21ae2c515b51041df9ed313ed21e572df340ea58a922a0aefe7e8891a1" dependencies = [ "futures-core", "pin-project-lite", @@ -1393,7 +1393,7 @@ checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.90", ] [[package]] @@ -1487,8 +1487,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" dependencies = [ "cfg-if", + "js-sys", "libc", "wasi", + "wasm-bindgen", ] [[package]] @@ -1536,7 +1538,7 @@ dependencies = [ "futures-sink", "futures-util", "http 0.2.12", - "indexmap 2.6.0", + "indexmap 2.7.0", "slab", "tokio", "tokio-util", @@ -1567,9 +1569,9 @@ checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" [[package]] name = "hashbrown" -version = "0.15.0" +version = "0.15.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e087f84d4f86bf4b218b927129862374b72199ae7d8657835f1e89000eea4fb" +checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289" dependencies = [ "allocator-api2", "equivalent", @@ -1627,7 +1629,7 @@ dependencies = [ "once_cell", "rand", "socket2", - "thiserror 1.0.68", + "thiserror 1.0.69", "tinyvec", "tokio", "tracing", @@ -1650,7 +1652,7 @@ dependencies = [ "rand", "resolv-conf", "smallvec", - "thiserror 1.0.68", + "thiserror 1.0.69", "tokio", "tracing", ] @@ -1697,9 +1699,9 @@ dependencies = [ [[package]] name = "http" -version = "1.1.0" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21b9ddb458710bc376481b842f5da65cdf31522de232c1ca8146abce2a358258" +checksum = "f16ca2af56261c99fba8bac40a10251ce8188205a4c448fbb745a2e4daa76fea" dependencies = [ "bytes", "fnv", @@ -1724,7 +1726,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184" dependencies = [ "bytes", - "http 1.1.0", + "http 1.2.0", ] [[package]] @@ -1735,7 +1737,7 @@ checksum = "793429d76616a256bcb62c2a2ec2bed781c8307e797e2598c50010f2bee2544f" dependencies = [ "bytes", "futures-util", - "http 1.1.0", + "http 1.2.0", "http-body 1.0.1", "pin-project-lite", ] @@ -1794,14 +1796,14 @@ dependencies = [ [[package]] name = "hyper" -version = "1.5.0" +version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbbff0a806a4728c99295b254c8838933b5b082d75e3cb70c8dab21fdfbcfa9a" +checksum = "97818827ef4f364230e16705d4706e2897df2bb60617d6ca15d598025a3c481f" dependencies = [ "bytes", "futures-channel", "futures-util", - "http 1.1.0", + "http 1.2.0", "http-body 1.0.1", "httparse", "httpdate", @@ -1813,15 +1815,15 @@ dependencies = [ [[package]] name = "hyper-util" -version = "0.1.9" +version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41296eb09f183ac68eec06e03cdbea2e759633d4067b2f6552fc2e009bcad08b" +checksum = "df2dcfbe0677734ab2f3ffa7fa7bfd4706bfdc1ef393f2ee30184aed67e631b4" dependencies = [ "bytes", "futures-util", - "http 1.1.0", + "http 1.2.0", "http-body 1.0.1", - "hyper 1.5.0", + "hyper 1.5.1", "pin-project-lite", "tokio", "tower-service", @@ -1850,6 +1852,124 @@ dependencies = [ "cc", ] +[[package]] +name = "icu_collections" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db2fa452206ebee18c4b5c2274dbf1de17008e874b4dc4f0aea9d01ca79e4526" +dependencies = [ + "displaydoc", + "yoke", + "zerofrom", + "zerovec", +] + +[[package]] +name = "icu_locid" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13acbb8371917fc971be86fc8057c41a64b521c184808a698c02acc242dbf637" +dependencies = [ + "displaydoc", + "litemap", + "tinystr", + "writeable", + "zerovec", +] + +[[package]] +name = "icu_locid_transform" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "01d11ac35de8e40fdeda00d9e1e9d92525f3f9d887cdd7aa81d727596788b54e" +dependencies = [ + "displaydoc", + "icu_locid", + "icu_locid_transform_data", + "icu_provider", + "tinystr", + "zerovec", +] + +[[package]] +name = "icu_locid_transform_data" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fdc8ff3388f852bede6b579ad4e978ab004f139284d7b28715f773507b946f6e" + +[[package]] +name = "icu_normalizer" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19ce3e0da2ec68599d193c93d088142efd7f9c5d6fc9b803774855747dc6a84f" +dependencies = [ + "displaydoc", + "icu_collections", + "icu_normalizer_data", + "icu_properties", + "icu_provider", + "smallvec", + "utf16_iter", + "utf8_iter", + "write16", + "zerovec", +] + +[[package]] +name = "icu_normalizer_data" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8cafbf7aa791e9b22bec55a167906f9e1215fd475cd22adfcf660e03e989516" + +[[package]] +name = "icu_properties" +version = "1.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93d6020766cfc6302c15dbbc9c8778c37e62c14427cb7f6e601d849e092aeef5" +dependencies = [ + "displaydoc", + "icu_collections", + "icu_locid_transform", + "icu_properties_data", + "icu_provider", + "tinystr", + "zerovec", +] + +[[package]] +name = "icu_properties_data" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67a8effbc3dd3e4ba1afa8ad918d5684b8868b3b26500753effea8d2eed19569" + +[[package]] +name = "icu_provider" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ed421c8a8ef78d3e2dbc98a973be2f3770cb42b606e3ab18d6237c4dfde68d9" +dependencies = [ + "displaydoc", + "icu_locid", + "icu_provider_macros", + "stable_deref_trait", + "tinystr", + "writeable", + "yoke", + "zerofrom", + "zerovec", +] + +[[package]] +name = "icu_provider_macros" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ec89e9337638ecdc08744df490b221a7399bf8d164eb52a665454e60e075ad6" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.90", +] + [[package]] name = "ident_case" version = "1.0.1" @@ -1868,12 +1988,23 @@ dependencies = [ [[package]] name = "idna" -version = "0.5.0" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6" +checksum = "686f825264d630750a544639377bae737628043f20d38bbc029e8f29ea968a7e" dependencies = [ - "unicode-bidi", - "unicode-normalization", + "idna_adapter", + "smallvec", + "utf8_iter", +] + +[[package]] +name = "idna_adapter" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "daca1df1c957320b2cf139ac61e7bd64fed304c5040df000a745aa1de3b4ef71" +dependencies = [ + "icu_normalizer", + "icu_properties", ] [[package]] @@ -1888,9 +2019,9 @@ dependencies = [ [[package]] name = "if-watch" -version = "3.2.0" +version = "3.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d6b0422c86d7ce0e97169cc42e04ae643caf278874a7a3c87b8150a220dc7e1e" +checksum = "cdf9d64cfcf380606e64f9a0bcf493616b65331199f984151a6fa11a7b3cde38" dependencies = [ "async-io", "core-foundation", @@ -1899,6 +2030,10 @@ dependencies = [ "if-addrs", "ipnet", "log", + "netlink-packet-core", + "netlink-packet-route", + "netlink-proto", + "netlink-sys", "rtnetlink", "system-configuration", "tokio", @@ -1943,12 +2078,12 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.6.0" +version = "2.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "707907fe3c25f5424cce2cb7e1cbcafee6bdbe735ca90ef77c29e84591e5b9da" +checksum = "62f822373a4fe84d4bb149bf54e584a7f4abec90e072ed49cda0edea5b95471f" dependencies = [ "equivalent", - "hashbrown 0.15.0", + "hashbrown 0.15.2", "serde", ] @@ -2038,16 +2173,17 @@ dependencies = [ [[package]] name = "itoa" -version = "1.0.11" +version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" +checksum = "d75a2a4b1b190afb6f5425f10f6a8f959d2ea0b9c2b1d79553551850539e4674" [[package]] name = "js-sys" -version = "0.3.72" +version = "0.3.74" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a88f1bda2bd75b0452a14784937d796722fdebfe50df998aeb3f0b7603019a9" +checksum = "a865e038f7f6ed956f788f0d7d60c541fff74c7bd74272c5d4cf15c63743e705" dependencies = [ + "once_cell", "wasm-bindgen", ] @@ -2090,9 +2226,9 @@ checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" [[package]] name = "libc" -version = "0.2.164" +version = "0.2.167" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "433bfe06b8c75da9b2e3fbea6e5329ff87748f0b144ef75306e674c3f6f7c13f" +checksum = "09d6582e104315a817dff97f75133544b2e094ee22447d2acf4a74e189ba06fc" [[package]] name = "libp2p" @@ -2126,7 +2262,7 @@ dependencies = [ "multiaddr", "pin-project", "rw-stream-sink", - "thiserror 1.0.68", + "thiserror 1.0.69", ] [[package]] @@ -2175,7 +2311,7 @@ dependencies = [ "rw-stream-sink", "serde", "smallvec", - "thiserror 1.0.68", + "thiserror 1.0.69", "tracing", "unsigned-varint 0.8.0", "void", @@ -2248,7 +2384,7 @@ dependencies = [ "quick-protobuf", "quick-protobuf-codec", "smallvec", - "thiserror 1.0.68", + "thiserror 1.0.69", "tracing", "void", ] @@ -2269,7 +2405,7 @@ dependencies = [ "sec1", "serde", "sha2 0.10.8", - "thiserror 1.0.68", + "thiserror 1.0.69", "tracing", "zeroize", ] @@ -2297,7 +2433,7 @@ dependencies = [ "serde", "sha2 0.10.8", "smallvec", - "thiserror 1.0.68", + "thiserror 1.0.69", "tracing", "uint", "void", @@ -2363,7 +2499,7 @@ dependencies = [ "sha2 0.10.8", "snow", "static_assertions", - "thiserror 1.0.68", + "thiserror 1.0.69", "tracing", "x25519-dalek", "zeroize", @@ -2406,7 +2542,7 @@ dependencies = [ "ring 0.17.8", "rustls", "socket2", - "thiserror 1.0.68", + "thiserror 1.0.69", "tokio", "tracing", ] @@ -2481,7 +2617,7 @@ dependencies = [ "heck", "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.90", ] [[package]] @@ -2515,7 +2651,7 @@ dependencies = [ "ring 0.17.8", "rustls", "rustls-webpki 0.101.7", - "thiserror 1.0.68", + "thiserror 1.0.69", "x509-parser", "yasna", ] @@ -2545,10 +2681,10 @@ dependencies = [ "either", "futures", "libp2p-core", - "thiserror 1.0.68", + "thiserror 1.0.69", "tracing", "yamux 0.12.1", - "yamux 0.13.3", + "yamux 0.13.4", ] [[package]] @@ -2573,6 +2709,12 @@ version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" +[[package]] +name = "litemap" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ee93343901ab17bd981295f2cf0026d4ad018c7c31ba84549a4ddbb47a45104" + [[package]] name = "lock_api" version = "0.4.12" @@ -2595,7 +2737,7 @@ version = "0.12.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "234cf4f4a04dc1f57e24b96cc0cd600cf2af460d4161ac5ecdd0af8e1f3b2a38" dependencies = [ - "hashbrown 0.15.0", + "hashbrown 0.15.2", ] [[package]] @@ -2647,7 +2789,6 @@ version = "0.1.0" dependencies = [ "bytes", "derive-where", - "libp2p-identity", "malachite-actors", "malachite-blocksync", "malachite-codec", @@ -2657,7 +2798,10 @@ dependencies = [ "malachite-gossip-consensus", "malachite-metrics", "malachite-node", + "malachite-peer", + "malachite-test", "ractor", + "rand", "tokio", "tracing", ] @@ -2675,9 +2819,10 @@ dependencies = [ "libp2p", "malachite-common", "malachite-metrics", + "malachite-peer", "rand", "serde", - "thiserror 2.0.3", + "thiserror 2.0.4", "tracing", ] @@ -2697,7 +2842,7 @@ dependencies = [ "malachite-node", "rand", "serde_json", - "thiserror 2.0.3", + "thiserror 2.0.4", "tokio", "toml", "tracing", @@ -2718,7 +2863,7 @@ version = "0.1.0" dependencies = [ "bytes", "derive-where", - "thiserror 2.0.3", + "thiserror 2.0.4", ] [[package]] @@ -2741,13 +2886,13 @@ dependencies = [ "async-recursion", "derive-where", "genawaiter", - "libp2p-identity", "malachite-common", "malachite-driver", "malachite-metrics", + "malachite-peer", "malachite-test", "multiaddr", - "thiserror 2.0.3", + "thiserror 2.0.4", "tracing", ] @@ -2788,7 +2933,7 @@ dependencies = [ "malachite-round", "malachite-test", "malachite-vote", - "thiserror 2.0.3", + "thiserror 2.0.4", ] [[package]] @@ -2815,6 +2960,7 @@ dependencies = [ "malachite-blocksync", "malachite-discovery", "malachite-metrics", + "malachite-peer", "seahash", "serde", "tokio", @@ -2854,13 +3000,24 @@ dependencies = [ "serde", ] +[[package]] +name = "malachite-peer" +version = "0.1.0" +dependencies = [ + "bs58", + "multihash", + "rand", + "serde", + "thiserror 2.0.4", +] + [[package]] name = "malachite-proto" version = "0.1.0" dependencies = [ "prost", "prost-types", - "thiserror 2.0.3", + "thiserror 2.0.4", ] [[package]] @@ -2932,7 +3089,7 @@ dependencies = [ "serde_json", "sha3", "tempfile", - "thiserror 2.0.3", + "thiserror 2.0.4", "tokio", "tracing", ] @@ -2989,7 +3146,11 @@ dependencies = [ "bytes", "ed25519-consensus", "hex", + "malachite-actors", + "malachite-blocksync", + "malachite-codec", "malachite-common", + "malachite-consensus", "malachite-proto", "malachite-signing-ed25519", "prost", @@ -2997,6 +3158,7 @@ dependencies = [ "prost-types", "rand", "serde", + "serde_json", "sha3", "signature", ] @@ -3028,7 +3190,7 @@ dependencies = [ "derive-where", "malachite-common", "malachite-test", - "thiserror 2.0.3", + "thiserror 2.0.4", ] [[package]] @@ -3106,11 +3268,10 @@ dependencies = [ [[package]] name = "mio" -version = "1.0.2" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "80e04d1dcff3aae0704555fe5fee3bcfaf3d1fdf8a7e521d5b9d2b42acb52cec" +checksum = "2886843bf800fba2e3377cff24abf6379b4c4d5c6681eaf9ea5b0d15090450bd" dependencies = [ - "hermit-abi 0.3.9", "libc", "wasi", "windows-sys 0.52.0", @@ -3148,13 +3309,13 @@ dependencies = [ [[package]] name = "multihash" -version = "0.19.1" +version = "0.19.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "076d548d76a0e2a0d4ab471d0b1c36c577786dfc4471242035d97a12a735c492" +checksum = "cc41f430805af9d1cf4adae4ed2149c759b877b01d909a1f40256188d09345d2" dependencies = [ "core2", "serde", - "unsigned-varint 0.7.2", + "unsigned-varint 0.8.0", ] [[package]] @@ -3179,21 +3340,20 @@ dependencies = [ [[package]] name = "netlink-packet-core" -version = "0.4.2" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "345b8ab5bd4e71a2986663e88c56856699d060e78e152e6e9d7966fcd5491297" +checksum = "72724faf704479d67b388da142b186f916188505e7e0b26719019c525882eda4" dependencies = [ "anyhow", "byteorder", - "libc", "netlink-packet-utils", ] [[package]] name = "netlink-packet-route" -version = "0.12.0" +version = "0.17.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9ea4302b9759a7a88242299225ea3688e63c85ea136371bb6cf94fd674efaab" +checksum = "053998cea5a306971f88580d0829e90f270f940befd7cf928da179d4187a5a66" dependencies = [ "anyhow", "bitflags 1.3.2", @@ -3212,21 +3372,21 @@ dependencies = [ "anyhow", "byteorder", "paste", - "thiserror 1.0.68", + "thiserror 1.0.69", ] [[package]] name = "netlink-proto" -version = "0.10.0" +version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "65b4b14489ab424703c092062176d52ba55485a89c076b4f9db05092b7223aa6" +checksum = "86b33524dc0968bfad349684447bfce6db937a9ac3332a1fe60c0c5a5ce63f21" dependencies = [ "bytes", "futures", "log", "netlink-packet-core", "netlink-sys", - "thiserror 1.0.68", + "thiserror 1.0.69", "tokio", ] @@ -3245,9 +3405,9 @@ dependencies = [ [[package]] name = "nix" -version = "0.24.3" +version = "0.26.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa52e972a9a719cecb6864fb88568781eb706bac2cd1d4f04a648542dbf78069" +checksum = "598beaf3cc6fdd9a5dfb1630c2800c7acd31df7aaf0f565796fba2b53ca1af1b" dependencies = [ "bitflags 1.3.2", "cfg-if", @@ -3449,9 +3609,9 @@ checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" [[package]] name = "pathdiff" -version = "0.2.2" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d61c5ce1153ab5b689d0c074c4e7fc613e942dfb7dd9eea5ab202d2ad91fe361" +checksum = "df94ce210e5bc13cb6651479fa48d14f601d9858cfe0467f43ae157023b938d3" [[package]] name = "pem" @@ -3485,34 +3645,34 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b4c5cc86750666a3ed20bdaf5ca2a0344f9c67674cae0515bec2da16fbaa47db" dependencies = [ "fixedbitset", - "indexmap 2.6.0", + "indexmap 2.7.0", ] [[package]] name = "pin-project" -version = "1.1.6" +version = "1.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "baf123a161dde1e524adf36f90bc5d8d3462824a9c43553ad07a8183161189ec" +checksum = "be57f64e946e500c8ee36ef6331845d40a93055567ec57e8fae13efd33759b95" dependencies = [ "pin-project-internal", ] [[package]] name = "pin-project-internal" -version = "1.1.6" +version = "1.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4502d8515ca9f32f1fb543d987f63d95a14934883db45bdb48060b6b69257f8" +checksum = "3c0f5fad0874fc7abcd4d750e76917eaebbecaa2c20bde22e1dbeeba8beb758c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.90", ] [[package]] name = "pin-project-lite" -version = "0.2.14" +version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02" +checksum = "915a1e146535de9163f3987b8944ed8cf49a18bb0056bcebcdcece385cece4ff" [[package]] name = "pin-utils" @@ -3560,9 +3720,9 @@ dependencies = [ [[package]] name = "polling" -version = "3.7.3" +version = "3.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc2790cd301dec6cd3b7a025e4815cf825724a51c98dccfe6a3e55f05ffb6511" +checksum = "a604568c3202727d1507653cb121dbd627a58684eb09a820fd746bee38b4442f" dependencies = [ "cfg-if", "concurrent-queue", @@ -3623,12 +3783,12 @@ dependencies = [ [[package]] name = "prettyplease" -version = "0.2.22" +version = "0.2.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "479cf940fbbb3426c32c5d5176f62ad57549a0bb84773423ba8be9d089f5faba" +checksum = "64d1ec885c64d0457d564db4ec299b2dae3f9c02808b8ad9c3a089c591b18033" dependencies = [ "proc-macro2", - "syn 2.0.87", + "syn 2.0.90", ] [[package]] @@ -3642,9 +3802,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.87" +version = "1.0.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3e4daa0dcf6feba26f985457cdf104d4b4256fc5a09547140f3631bb076b19a" +checksum = "37d3544b3f2748c54e147655edb5025752e2303145b5aefb3c3ea2c78b973bb0" dependencies = [ "unicode-ident", ] @@ -3669,7 +3829,7 @@ checksum = "440f724eba9f6996b75d63681b0a92b06947f1457076d503a4d2e2c8f56442b8" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.90", ] [[package]] @@ -3699,7 +3859,7 @@ dependencies = [ "prost", "prost-types", "regex", - "syn 2.0.87", + "syn 2.0.90", "tempfile", ] @@ -3713,7 +3873,7 @@ dependencies = [ "itertools 0.13.0", "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.90", ] [[package]] @@ -3749,15 +3909,15 @@ dependencies = [ "asynchronous-codec", "bytes", "quick-protobuf", - "thiserror 1.0.68", + "thiserror 1.0.69", "unsigned-varint 0.8.0", ] [[package]] name = "quinn" -version = "0.11.5" +version = "0.11.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c7c5fdde3cdae7203427dc4f0a68fe0ed09833edc525a03456b153b79828684" +checksum = "62e96808277ec6f97351a2380e6c25114bc9e67037775464979f3037c92d05ef" dependencies = [ "bytes", "futures-io", @@ -3767,34 +3927,38 @@ dependencies = [ "rustc-hash", "rustls", "socket2", - "thiserror 1.0.68", + "thiserror 2.0.4", "tokio", "tracing", ] [[package]] name = "quinn-proto" -version = "0.11.8" +version = "0.11.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fadfaed2cd7f389d0161bb73eeb07b7b78f8691047a6f3e73caaeae55310a4a6" +checksum = "a2fe5ef3495d7d2e377ff17b1a8ce2ee2ec2a18cde8b6ad6619d65d0701c135d" dependencies = [ "bytes", + "getrandom", "rand", "ring 0.17.8", "rustc-hash", "rustls", + "rustls-pki-types", "slab", - "thiserror 1.0.68", + "thiserror 2.0.4", "tinyvec", "tracing", + "web-time", ] [[package]] name = "quinn-udp" -version = "0.5.5" +version = "0.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fe68c2e9e1a1234e218683dbdf9f9dfcb094113c5ac2b938dfcb9bab4c4140b" +checksum = "7d5a626c6807713b15cac82a6acaccd6043c9a5408c24baae07611fec3f243da" dependencies = [ + "cfg_aliases", "libc", "once_cell", "socket2", @@ -3915,18 +4079,18 @@ checksum = "ba009ff324d1fc1b900bd1fdb31564febe58a8ccc8a6fdbb93b543d33b13ca43" dependencies = [ "getrandom", "libredox", - "thiserror 1.0.68", + "thiserror 1.0.69", ] [[package]] name = "regex" -version = "1.11.0" +version = "1.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38200e5ee88914975b69f657f0801b6f6dccafd44fd9326302a4aaeecfacb1d8" +checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191" dependencies = [ "aho-corasick", "memchr", - "regex-automata 0.4.8", + "regex-automata 0.4.9", "regex-syntax 0.8.5", ] @@ -3941,9 +4105,9 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.4.8" +version = "0.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "368758f23274712b504848e9d5a6f010445cc8b87a7cdb4d7cbee666c1288da3" +checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908" dependencies = [ "aho-corasick", "memchr", @@ -4014,16 +4178,19 @@ dependencies = [ [[package]] name = "rtnetlink" -version = "0.10.1" +version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "322c53fd76a18698f1c27381d58091de3a043d356aa5bd0d510608b565f469a0" +checksum = "7a552eb82d19f38c3beed3f786bd23aa434ceb9ac43ab44419ca6d67a7e186c0" dependencies = [ "futures", "log", + "netlink-packet-core", "netlink-packet-route", + "netlink-packet-utils", "netlink-proto", - "nix 0.24.3", - "thiserror 1.0.68", + "netlink-sys", + "nix 0.26.4", + "thiserror 1.0.69", "tokio", ] @@ -4035,9 +4202,9 @@ checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" [[package]] name = "rustc-hash" -version = "2.0.0" +version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "583034fd73374156e66797ed8e5b0d5690409c9226b22d87cb7f19821c05d152" +checksum = "c7fb8039b3032c191086b10f11f319a6e99e1e82889c5cc6046f515c9db1d497" [[package]] name = "rustc_version" @@ -4089,6 +4256,9 @@ name = "rustls-pki-types" version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "16f1201b3c9a7ee8039bcadc17b7e605e2945b27eee7631788c1bd2b0643674b" +dependencies = [ + "web-time", +] [[package]] name = "rustls-webpki" @@ -4195,7 +4365,7 @@ checksum = "ad1e866f866923f252f05c889987993144fb74e722403468a4ebd70c3cd756c0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.90", ] [[package]] @@ -4277,7 +4447,7 @@ dependencies = [ "chrono", "hex", "indexmap 1.9.3", - "indexmap 2.6.0", + "indexmap 2.7.0", "serde", "serde_derive", "serde_json", @@ -4294,7 +4464,7 @@ dependencies = [ "darling", "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.90", ] [[package]] @@ -4306,7 +4476,7 @@ dependencies = [ "darling", "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.90", ] [[package]] @@ -4411,9 +4581,9 @@ dependencies = [ [[package]] name = "socket2" -version = "0.5.7" +version = "0.5.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce305eb0b4296696835b71df73eb912e0f1ffd2556a501fcede6e0c50349191c" +checksum = "c970269d99b64e60ec3bd6ad27270092a5394c4e309314b18ae3fe575695fbe8" dependencies = [ "libc", "windows-sys 0.52.0", @@ -4441,6 +4611,12 @@ dependencies = [ "der", ] +[[package]] +name = "stable_deref_trait" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" + [[package]] name = "starknet-core" version = "0.11.1" @@ -4533,7 +4709,7 @@ dependencies = [ "proc-macro2", "quote", "rustversion", - "syn 2.0.87", + "syn 2.0.90", ] [[package]] @@ -4561,9 +4737,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.87" +version = "2.0.90" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25aa4ce346d03a6dcd68dd8b4010bcb74e54e62c90c573f394c46eae99aba32d" +checksum = "919d3b74a5dd0ccd15aeb8f93e7006bd9e14c295087c9896a110f490752bcf31" dependencies = [ "proc-macro2", "quote", @@ -4578,9 +4754,9 @@ checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160" [[package]] name = "sync_wrapper" -version = "1.0.1" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7065abeca94b6a8a577f9bd45aa0867a2238b74e8eb67cf10d492bc39351394" +checksum = "0bf256ce5efdfa370213c1dabab5935a12e49f2c58d15e9eac2870d3b4f27263" [[package]] name = "synstructure" @@ -4590,7 +4766,7 @@ checksum = "c8af7666ab7b6390ab78131fb5b0fce11d6b7a6951602017c35fa82800708971" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.90", ] [[package]] @@ -4609,20 +4785,20 @@ dependencies = [ [[package]] name = "system-configuration" -version = "0.5.1" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba3a3adc5c275d719af8cb4272ea1c4a6d668a777f37e115f6d11ddbc1c8e0e7" +checksum = "3c879d448e9d986b661742763247d3693ed13609438cf3d006f51f5368a5ba6b" dependencies = [ - "bitflags 1.3.2", + "bitflags 2.6.0", "core-foundation", "system-configuration-sys", ] [[package]] name = "system-configuration-sys" -version = "0.5.0" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a75fb188eb626b924683e3b95e3a48e63551fcfb51949de2f06a9d91dbee93c9" +checksum = "8e1d1b10ced5ca923a1fcb8d03e96b8d3268065d724548c0211415ff6ac6bac4" dependencies = [ "core-foundation-sys", "libc", @@ -4643,12 +4819,13 @@ dependencies = [ [[package]] name = "testdir" -version = "0.9.1" +version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee79e927b64d193f5abb60d20a0eb56be0ee5a242fdeb8ce3bf054177006de52" +checksum = "c9ffa013be124f7e8e648876190de818e3a87088ed97ccd414a398b403aec8c8" dependencies = [ "anyhow", "backtrace", + "cargo-platform", "cargo_metadata", "once_cell", "sysinfo", @@ -4657,42 +4834,42 @@ dependencies = [ [[package]] name = "thiserror" -version = "1.0.68" +version = "1.0.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02dd99dc800bbb97186339685293e1cc5d9df1f8fae2d0aecd9ff1c77efea892" +checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" dependencies = [ - "thiserror-impl 1.0.68", + "thiserror-impl 1.0.69", ] [[package]] name = "thiserror" -version = "2.0.3" +version = "2.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c006c85c7651b3cf2ada4584faa36773bd07bac24acfb39f3c431b36d7e667aa" +checksum = "2f49a1853cf82743e3b7950f77e0f4d622ca36cf4317cba00c767838bac8d490" dependencies = [ - "thiserror-impl 2.0.3", + "thiserror-impl 2.0.4", ] [[package]] name = "thiserror-impl" -version = "1.0.68" +version = "1.0.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7c61ec9a6f64d2793d8a45faba21efbe3ced62a886d44c36a009b2b519b4c7e" +checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.90", ] [[package]] name = "thiserror-impl" -version = "2.0.3" +version = "2.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f077553d607adc1caf65430528a576c757a71ed73944b66ebb58ef2bbd243568" +checksum = "8381894bb3efe0c4acac3ded651301ceee58a15d47c2e34885ed1908ad667061" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.90", ] [[package]] @@ -4727,9 +4904,9 @@ dependencies = [ [[package]] name = "time" -version = "0.3.36" +version = "0.3.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5dfd88e563464686c916c7e46e623e520ddc6d79fa6641390f2e3fa86e83e885" +checksum = "35e7868883861bd0e56d9ac6efcaaca0d6d5d82a2a7ec8209ff492c07cf37b21" dependencies = [ "deranged", "itoa", @@ -4748,14 +4925,24 @@ checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3" [[package]] name = "time-macros" -version = "0.2.18" +version = "0.2.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f252a68540fde3a3877aeea552b832b40ab9a69e318efd078774a01ddee1ccf" +checksum = "2834e6017e3e5e4b9834939793b282bc03b37a3336245fa820e35e233e2a85de" dependencies = [ "num-conv", "time-core", ] +[[package]] +name = "tinystr" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9117f5d4db391c1cf6927e7bea3db74b9a1c1add8f7eda9ffd5364f40f57b82f" +dependencies = [ + "displaydoc", + "zerovec", +] + [[package]] name = "tinytemplate" version = "1.2.1" @@ -4783,9 +4970,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.41.1" +version = "1.42.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22cfb5bee7a6a52939ca9224d6ac897bb669134078daa8735560897f69de4d33" +checksum = "5cec9b21b0450273377fc97bd4c33a8acffc8c996c987a7c5b319a0083707551" dependencies = [ "backtrace", "bytes", @@ -4808,14 +4995,14 @@ checksum = "693d596312e88961bc67d7f1f97af8a70227d9f90c31bba5806eec004978d752" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.90", ] [[package]] name = "tokio-util" -version = "0.7.12" +version = "0.7.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61e7c3654c13bcd040d4a03abee2c75b1d14a37b423cf5a813ceae1cc903ec6a" +checksum = "d7fcaa8d55a2bdd6b83ace262b016eca0d79ee02818c5c1bcdf0305114081078" dependencies = [ "bytes", "futures-core", @@ -4851,7 +5038,7 @@ version = "0.22.22" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4ae48d6208a266e853d946088ed816055e556cc6028c5e8e2b84d9fa5dd7c7f5" dependencies = [ - "indexmap 2.6.0", + "indexmap 2.7.0", "serde", "serde_spanned", "toml_datetime", @@ -4905,7 +5092,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3566e8ce28cc0a3fe42519fc80e6b4c943cc4c8cef275620eb8dac2d3d4e06cf" dependencies = [ "crossbeam-channel", - "thiserror 1.0.68", + "thiserror 1.0.69", "time", "tracing-subscriber", ] @@ -4918,7 +5105,7 @@ checksum = "395ae124c09f9e6918a2310af6038fba074bcf474ac352496d5910dd59a2226d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.90", ] [[package]] @@ -4933,9 +5120,9 @@ dependencies = [ [[package]] name = "tracing-error" -version = "0.2.0" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d686ec1c0f384b1277f097b2f279a2ecc11afe8c133c1aabf036a27cb4cd206e" +checksum = "8b1581020d7a273442f5b45074a6a57d5757ad0a47dac0e9f0bd57b81936f3db" dependencies = [ "tracing", "tracing-subscriber", @@ -4954,9 +5141,9 @@ dependencies = [ [[package]] name = "tracing-serde" -version = "0.1.3" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc6b213177105856957181934e4920de57730fc69bf42c37ee5bb664d406d9e1" +checksum = "704b1aeb7be0d0a84fc9828cae51dab5970fee5088f83d1dd7ee6f6246fc6ff1" dependencies = [ "serde", "tracing-core", @@ -4964,9 +5151,9 @@ dependencies = [ [[package]] name = "tracing-subscriber" -version = "0.3.18" +version = "0.3.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad0f048c97dbd9faa9b7df56362b8ebcaa52adb06b498c050d2f4e32f90a7a8b" +checksum = "e8189decb5ac0fa7bc8b96b7cb9b2701d60d48805aca84a238004d665fcc4008" dependencies = [ "matchers", "nu-ansi-term", @@ -5025,9 +5212,9 @@ checksum = "5ab17db44d7388991a428b2ee655ce0c212e862eff1768a455c58f9aad6e7893" [[package]] name = "unicode-ident" -version = "1.0.13" +version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e91b56cd4cadaeb79bbf1a5645f6b4f8dc5bde8834ad5894a8db35fda9efa1fe" +checksum = "adb9e6ca4f869e1180728b7950e35922a7fc6397f7b641499e8f3ef06e50dc83" [[package]] name = "unicode-normalization" @@ -5074,15 +5261,27 @@ checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" [[package]] name = "url" -version = "2.5.2" +version = "2.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22784dbdf76fdde8af1aeda5622b546b422b6fc585325248a2bf9f5e41e94d6c" +checksum = "32f8b686cadd1473f4bd0117a5d28d36b1ade384ea9b5069a1c40aefed7fda60" dependencies = [ "form_urlencoded", - "idna 0.5.0", + "idna 1.0.3", "percent-encoding", ] +[[package]] +name = "utf16_iter" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8232dd3cdaed5356e0f716d285e4b40b932ac434100fe9b7e0e8e935b9e6246" + +[[package]] +name = "utf8_iter" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" + [[package]] name = "utf8parse" version = "0.2.2" @@ -5140,9 +5339,9 @@ checksum = "b8dad83b4f25e74f184f64c43b150b91efe7647395b42289f38e50566d82855b" [[package]] name = "wasm-bindgen" -version = "0.2.95" +version = "0.2.97" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "128d1e363af62632b8eb57219c8fd7877144af57558fb2ef0368d0087bddeb2e" +checksum = "d15e63b4482863c109d70a7b8706c1e364eb6ea449b201a76c5b89cedcec2d5c" dependencies = [ "cfg-if", "once_cell", @@ -5151,24 +5350,24 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.95" +version = "0.2.97" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb6dd4d3ca0ddffd1dd1c9c04f94b868c37ff5fac97c30b97cff2d74fce3a358" +checksum = "8d36ef12e3aaca16ddd3f67922bc63e48e953f126de60bd33ccc0101ef9998cd" dependencies = [ "bumpalo", "log", "once_cell", "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.90", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-macro" -version = "0.2.95" +version = "0.2.97" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e79384be7f8f5a9dd5d7167216f022090cf1f9ec128e6e6a482a2cb5c5422c56" +checksum = "705440e08b42d3e4b36de7d66c944be628d579796b8090bfa3471478a2260051" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -5176,28 +5375,28 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.95" +version = "0.2.97" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26c6ab57572f7a24a4985830b120de1594465e5d500f24afe89e16b4e833ef68" +checksum = "98c9ae5a76e46f4deecd0f0255cc223cfa18dc9b261213b8aa0c7b36f61b3f1d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.90", "wasm-bindgen-backend", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.95" +version = "0.2.97" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "65fc09f10666a9f147042251e0dda9c18f166ff7de300607007e96bdebc1068d" +checksum = "6ee99da9c5ba11bd675621338ef6fa52296b76b83305e9b6e5c77d4c286d6d49" [[package]] name = "web-sys" -version = "0.3.72" +version = "0.3.74" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6488b90108c040df0fe62fa815cbdee25124641df01814dd7282749234c6112" +checksum = "a98bc3c33f0fe7e59ad7cd041b89034fa82a7c2d4365ca538dda6cdaf513863c" dependencies = [ "js-sys", "wasm-bindgen", @@ -5263,28 +5462,38 @@ checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" [[package]] name = "windows" -version = "0.51.1" +version = "0.53.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca229916c5ee38c2f2bc1e9d8f04df975b4bd93f9955dc69fabb5d91270045c9" +checksum = "efc5cf48f83140dcaab716eeaea345f9e93d0018fb81162753a3f76c3397b538" dependencies = [ - "windows-core 0.51.1", - "windows-targets 0.48.5", + "windows-core 0.53.0", + "windows-targets 0.52.6", ] [[package]] name = "windows-core" -version = "0.51.1" +version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1f8cf84f35d2db49a46868f947758c7a1138116f7fac3bc844f43ade1292e64" +checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" dependencies = [ - "windows-targets 0.48.5", + "windows-targets 0.52.6", ] [[package]] name = "windows-core" -version = "0.52.0" +version = "0.53.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" +checksum = "9dcc5b895a6377f1ab9fa55acedab1fd5ac0db66ad1e6c7f47e28a22e446a5dd" +dependencies = [ + "windows-result", + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-result" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e383302e8ec8515204254685643de10811af0ed97ea37210dc26fb0032647f8" dependencies = [ "windows-targets 0.52.6", ] @@ -5456,6 +5665,18 @@ dependencies = [ "windows-sys 0.48.0", ] +[[package]] +name = "write16" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d1890f4022759daae28ed4fe62859b1236caebfc61ede2f63ed4e695f3f6d936" + +[[package]] +name = "writeable" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e9df38ee2d2c3c5948ea468a8406ff0db0b29ae1ffde1bcf20ef305bcc95c51" + [[package]] name = "x25519-dalek" version = "2.0.1" @@ -5481,15 +5702,15 @@ dependencies = [ "nom", "oid-registry", "rusticata-macros", - "thiserror 1.0.68", + "thiserror 1.0.69", "time", ] [[package]] name = "xml-rs" -version = "0.8.22" +version = "0.8.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af4e2e2f7cba5a093896c1e150fbfe177d1883e7448200efb81d40b9d339ef26" +checksum = "ea8b391c9a790b496184c29f7f93b9ed5b16abb306c05415b68bcc16e4d06432" [[package]] name = "xmltree" @@ -5517,9 +5738,9 @@ dependencies = [ [[package]] name = "yamux" -version = "0.13.3" +version = "0.13.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a31b5e376a8b012bee9c423acdbb835fc34d45001cfa3106236a624e4b738028" +checksum = "17610762a1207ee816c6fadc29220904753648aba0a9ed61c7b8336e80a559c4" dependencies = [ "futures", "log", @@ -5546,6 +5767,30 @@ dependencies = [ "time", ] +[[package]] +name = "yoke" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "120e6aef9aa629e3d4f52dc8cc43a015c7724194c97dfaf45180d2daf2b77f40" +dependencies = [ + "serde", + "stable_deref_trait", + "yoke-derive", + "zerofrom", +] + +[[package]] +name = "yoke-derive" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2380878cad4ac9aac1e2435f3eb4020e8374b5f13c296cb75b4620ff8e229154" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.90", + "synstructure", +] + [[package]] name = "zerocopy" version = "0.7.35" @@ -5564,7 +5809,28 @@ checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.90", +] + +[[package]] +name = "zerofrom" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cff3ee08c995dee1859d998dea82f7374f2826091dd9cd47def953cae446cd2e" +dependencies = [ + "zerofrom-derive", +] + +[[package]] +name = "zerofrom-derive" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "595eed982f7d355beb85837f651fa22e90b3c044842dc7f2c2842c086f295808" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.90", + "synstructure", ] [[package]] @@ -5584,5 +5850,27 @@ checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.90", +] + +[[package]] +name = "zerovec" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa2b893d79df23bfb12d5461018d408ea19dfafe76c2c7ef6d4eba614f8ff079" +dependencies = [ + "yoke", + "zerofrom", + "zerovec-derive", +] + +[[package]] +name = "zerovec-derive" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6eafa6dfb17584ea3e2bd6e76e0cc15ad7af12b09abdd1ca55961bed9b1063c6" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.90", ] diff --git a/code/Cargo.toml b/code/Cargo.toml index d6e18818b..c3527d5f4 100644 --- a/code/Cargo.toml +++ b/code/Cargo.toml @@ -16,6 +16,7 @@ members = [ "crates/gossip-mempool", "crates/metrics", "crates/node", + "crates/peer", "crates/proto", "crates/round", "crates/vote", @@ -71,6 +72,7 @@ malachite-gossip-consensus = { version = "0.1.0", path = "crates/gossip-consensu malachite-gossip-mempool = { version = "0.1.0", path = "crates/gossip-mempool" } malachite-metrics = { version = "0.1.0", path = "crates/metrics" } malachite-node = { version = "0.1.0", path = "crates/node" } +malachite-peer = { version = "0.1.0", path = "crates/peer" } malachite-proto = { version = "0.1.0", path = "crates/proto" } malachite-round = { version = "0.1.0", path = "crates/round" } malachite-vote = { version = "0.1.0", path = "crates/vote" } @@ -97,6 +99,7 @@ async-recursion = "1.1" async-trait = "0.1.83" axum = "0.7" base64 = "0.22.0" +bs58 = "0.5.1" bytes = { version = "1", default-features = false } byteorder = "1.5" bytesize = "1.3" @@ -124,6 +127,7 @@ libp2p = { version = "0.54.1", features = ["macros", "identify", "to libp2p-identity = "0.2.10" libp2p-broadcast = { version = "0.1.1", package = "libp2p-scatter" } multiaddr = "0.18.2" +multihash = { version = "0.19.2", default-features = false } nix = { version = "0.29.0", features = ["signal"] } num-bigint = "0.4.4" num-traits = "0.2.17" diff --git a/code/crates/actors/src/block_sync.rs b/code/crates/actors/src/block_sync.rs index f244e2c8b..55137f618 100644 --- a/code/crates/actors/src/block_sync.rs +++ b/code/crates/actors/src/block_sync.rs @@ -6,7 +6,6 @@ use bytes::Bytes; use derive_where::derive_where; use eyre::eyre; use libp2p::request_response::InboundRequestId; -use libp2p::PeerId; use ractor::{Actor, ActorProcessingErr, ActorRef}; use rand::SeedableRng; use tokio::task::JoinHandle; @@ -15,6 +14,7 @@ use tracing::{debug, error, warn}; use malachite_blocksync::{self as blocksync, OutboundRequestId}; use malachite_blocksync::{Request, SyncedBlock}; use malachite_common::{CertificateError, CommitCertificate, Context, Height}; +use malachite_consensus::PeerId; use crate::gossip_consensus::{GossipConsensusMsg, GossipConsensusRef, GossipEvent, Status}; use crate::host::{HostMsg, HostRef}; diff --git a/code/crates/actors/src/consensus.rs b/code/crates/actors/src/consensus.rs index 2084b798f..581049d57 100644 --- a/code/crates/actors/src/consensus.rs +++ b/code/crates/actors/src/consensus.rs @@ -3,7 +3,6 @@ use std::time::Duration; use async_trait::async_trait; use eyre::eyre; -use libp2p::PeerId; use ractor::{Actor, ActorProcessingErr, ActorRef, RpcReplyPort}; use tokio::time::Instant; use tracing::{debug, error, info, warn}; @@ -13,7 +12,7 @@ use malachite_common::{ Context, Round, SignedExtension, Timeout, TimeoutStep, ValidatorSet, ValueOrigin, }; use malachite_config::TimeoutConfig; -use malachite_consensus::{Effect, Resume, SignedConsensusMsg, ValueToPropose}; +use malachite_consensus::{Effect, PeerId, Resume, SignedConsensusMsg, ValueToPropose}; use malachite_metrics::Metrics; use crate::block_sync::BlockSyncRef; @@ -213,6 +212,7 @@ where match msg { Msg::StartHeight(height, validator_set) => { state.phase = Phase::Running; + let result = self .process_input( &myself, @@ -225,12 +225,6 @@ where error!(%height, "Error when starting height: {e}"); } - self.tx_event.send(|| Event::StartedHeight(height)); - - if let Err(e) = self.check_and_replay_wal(&myself, state, height).await { - error!(%height, "Error when checking and replaying WAL: {e}"); - } - // Notify the BlockSync actor that we have started a new height if let Some(block_sync) = &self.block_sync { if let Err(e) = block_sync.cast(BlockSyncMsg::StartedHeight(height)) { @@ -238,6 +232,12 @@ where } } + self.tx_event.send(|| Event::StartedHeight(height)); + + if let Err(e) = self.check_and_replay_wal(&myself, state, height).await { + error!(%height, "Error when checking and replaying WAL: {e}"); + } + Ok(()) } @@ -592,7 +592,7 @@ where |reply| HostMsg::GetValue { height, round, - timeout_duration, + timeout: timeout_duration, address: self.params.address.clone(), reply_to: reply, }, diff --git a/code/crates/actors/src/host.rs b/code/crates/actors/src/host.rs index 427d2a53d..4f78c866f 100644 --- a/code/crates/actors/src/host.rs +++ b/code/crates/actors/src/host.rs @@ -2,11 +2,11 @@ use bytes::Bytes; use std::time::Duration; use derive_where::derive_where; -use libp2p::PeerId; use ractor::{ActorRef, RpcReplyPort}; use malachite_blocksync::SyncedBlock; use malachite_common::{CommitCertificate, Context, Round, SignedExtension, ValueId}; +use malachite_consensus::PeerId; use crate::consensus::ConsensusRef; use crate::util::streaming::StreamMessage; @@ -61,7 +61,7 @@ pub enum HostMsg { GetValue { height: Ctx::Height, round: Round, - timeout_duration: Duration, + timeout: Duration, address: Ctx::Address, reply_to: RpcReplyPort>, }, diff --git a/code/crates/app-channel/Cargo.toml b/code/crates/app-channel/Cargo.toml index 7e620e123..7919d247a 100644 --- a/code/crates/app-channel/Cargo.toml +++ b/code/crates/app-channel/Cargo.toml @@ -10,7 +10,6 @@ rust-version.workspace = true [dependencies] bytes.workspace = true derive-where.workspace = true -libp2p-identity.workspace = true ractor.workspace = true tokio.workspace = true tracing.workspace = true @@ -24,6 +23,11 @@ malachite-consensus.workspace = true malachite-gossip-consensus.workspace = true malachite-metrics.workspace = true malachite-node.workspace = true +malachite-peer.workspace = true [lints] workspace = true + +[dev-dependencies] +malachite-test.workspace = true +rand.workspace = true diff --git a/code/crates/app-channel/src/channel.rs b/code/crates/app-channel/src/channel.rs index 495213213..602e9c6fc 100644 --- a/code/crates/app-channel/src/channel.rs +++ b/code/crates/app-channel/src/channel.rs @@ -2,14 +2,13 @@ use std::time::Duration; use bytes::Bytes; use derive_where::derive_where; -use libp2p_identity::PeerId; use tokio::sync::oneshot; use malachite_actors::host::LocallyProposedValue; use malachite_actors::util::streaming::StreamMessage; use malachite_blocksync::SyncedBlock; use malachite_common::{CommitCertificate, Context, Round, ValueId}; -use malachite_consensus::ProposedValue; +use malachite_consensus::{PeerId, ProposedValue}; /// Messages that will be sent on the channel. #[derive_where(Debug)] diff --git a/code/crates/app-channel/src/connector.rs b/code/crates/app-channel/src/connector.rs index 2b90db40e..bb94d072f 100644 --- a/code/crates/app-channel/src/connector.rs +++ b/code/crates/app-channel/src/connector.rs @@ -77,7 +77,7 @@ where HostMsg::GetValue { height, round, - timeout_duration, + timeout: timeout_duration, address, reply_to, } => { diff --git a/code/crates/app-channel/src/run.rs b/code/crates/app-channel/src/run.rs index 002977a91..ab4b59634 100644 --- a/code/crates/app-channel/src/run.rs +++ b/code/crates/app-channel/src/run.rs @@ -17,14 +17,13 @@ use crate::spawn::{ spawn_wal_actor, }; -// Todo: Remove clippy exception when the function signature is finalized #[allow(clippy::too_many_arguments)] -pub async fn run( +pub async fn run( cfg: NodeConfig, start_height: Option, ctx: Ctx, - node: Node, codec: Codec, + node: Node, keypair: Keypair, // Todo: see note in code address: Ctx::Address, // Todo: remove it when Node was properly implemented initial_validator_set: Ctx::ValidatorSet, diff --git a/code/crates/blocksync/Cargo.toml b/code/crates/blocksync/Cargo.toml index 40536deb7..9489e8c48 100644 --- a/code/crates/blocksync/Cargo.toml +++ b/code/crates/blocksync/Cargo.toml @@ -10,6 +10,7 @@ rust-version.workspace = true [dependencies] malachite-common = { workspace = true } malachite-metrics = { workspace = true } +malachite-peer = { workspace = true } async-trait = { workspace = true } bytes = { workspace = true, features = ["serde"] } diff --git a/code/crates/blocksync/src/state.rs b/code/crates/blocksync/src/state.rs index 7b56826ed..3c7c5c30f 100644 --- a/code/crates/blocksync/src/state.rs +++ b/code/crates/blocksync/src/state.rs @@ -1,9 +1,9 @@ use std::collections::BTreeMap; -use libp2p::PeerId; +use rand::seq::IteratorRandom; use malachite_common::Context; -use rand::seq::IteratorRandom; +use malachite_peer::PeerId; use crate::Status; diff --git a/code/crates/blocksync/src/types.rs b/code/crates/blocksync/src/types.rs index a338dbfdd..f6fd33280 100644 --- a/code/crates/blocksync/src/types.rs +++ b/code/crates/blocksync/src/types.rs @@ -3,10 +3,11 @@ use derive_where::derive_where; use displaydoc::Display; use serde::{Deserialize, Serialize}; -use malachite_common::{CommitCertificate, Context}; +use malachite_common::Context; -pub use libp2p::identity::PeerId; pub use libp2p::request_response::{InboundRequestId, OutboundRequestId}; +pub use malachite_common::CommitCertificate; +pub use malachite_peer::PeerId; pub type ResponseChannel = libp2p::request_response::ResponseChannel; diff --git a/code/crates/consensus/Cargo.toml b/code/crates/consensus/Cargo.toml index 56668358d..62400aed7 100644 --- a/code/crates/consensus/Cargo.toml +++ b/code/crates/consensus/Cargo.toml @@ -15,11 +15,11 @@ debug = ["std", "malachite-driver/debug"] malachite-common.workspace = true malachite-driver.workspace = true malachite-metrics.workspace = true +malachite-peer.workspace = true async-recursion = { workspace = true } genawaiter = { workspace = true } derive-where = { workspace = true } -libp2p-identity = { workspace = true, features = ["peerid"] } multiaddr = { workspace = true } thiserror = { workspace = true } tracing = { workspace = true } diff --git a/code/crates/consensus/src/types.rs b/code/crates/consensus/src/types.rs index 4c8bb0573..d862ba96f 100644 --- a/code/crates/consensus/src/types.rs +++ b/code/crates/consensus/src/types.rs @@ -4,7 +4,7 @@ use malachite_common::{ Context, Proposal, Round, SignedExtension, SignedProposal, SignedVote, Validity, Vote, }; -pub use libp2p_identity::PeerId; +pub use malachite_peer::PeerId; pub use multiaddr::Multiaddr; /// A signed consensus message, ie. a signed vote or a signed proposal. diff --git a/code/crates/gossip-consensus/Cargo.toml b/code/crates/gossip-consensus/Cargo.toml index 0772052cb..69eb254a1 100644 --- a/code/crates/gossip-consensus/Cargo.toml +++ b/code/crates/gossip-consensus/Cargo.toml @@ -13,6 +13,7 @@ workspace = true malachite-metrics = { workspace = true } malachite-blocksync = { workspace = true } malachite-discovery = { workspace = true } +malachite-peer = { workspace = true } bytes = { workspace = true } either = { workspace = true } diff --git a/code/crates/gossip-consensus/src/handle.rs b/code/crates/gossip-consensus/src/handle.rs index 6c2d69594..4b2b50265 100644 --- a/code/crates/gossip-consensus/src/handle.rs +++ b/code/crates/gossip-consensus/src/handle.rs @@ -1,10 +1,11 @@ use bytes::Bytes; use libp2p::request_response::InboundRequestId; -use libp2p::PeerId; -use malachite_blocksync::OutboundRequestId; use tokio::sync::{mpsc, oneshot}; use tokio::task; +use malachite_blocksync::OutboundRequestId; +use malachite_peer::PeerId; + use crate::{Channel, CtrlMsg, Event}; pub struct RecvHandle { diff --git a/code/crates/gossip-consensus/src/lib.rs b/code/crates/gossip-consensus/src/lib.rs index 5e449e619..46ee9d140 100644 --- a/code/crates/gossip-consensus/src/lib.rs +++ b/code/crates/gossip-consensus/src/lib.rs @@ -20,10 +20,12 @@ use malachite_blocksync::{self as blocksync, OutboundRequestId}; use malachite_discovery::{self as discovery, ConnectionData}; use malachite_metrics::SharedRegistry; +pub use malachite_peer::PeerId; + pub use bytes::Bytes; pub use libp2p::gossipsub::MessageId; pub use libp2p::identity::Keypair; -pub use libp2p::{Multiaddr, PeerId}; +pub use libp2p::Multiaddr; pub mod behaviour; pub mod handle; @@ -200,7 +202,7 @@ pub async fn spawn( let state = State::new(discovery); - let peer_id = *swarm.local_peer_id(); + let peer_id = PeerId::from_libp2p(swarm.local_peer_id()); let span = error_span!("gossip.consensus", peer = %peer_id); let task_handle = tokio::task::spawn(run(config, metrics, state, swarm, rx_ctrl, tx_event).instrument(span)); @@ -301,7 +303,7 @@ async fn handle_ctrl_msg( let request_id = swarm .behaviour_mut() .blocksync - .send_request(peer_id, request); + .send_request(peer_id.to_libp2p(), request); if let Err(e) = reply_to.send(request_id) { error!(%peer_id, "Error sending BlockSync request: {e}"); @@ -475,7 +477,10 @@ async fn handle_gossipsub_event( trace!("Peer {peer_id} subscribed to {topic}"); - if let Err(e) = tx_event.send(Event::PeerConnected(peer_id)).await { + if let Err(e) = tx_event + .send(Event::PeerConnected(PeerId::from_libp2p(&peer_id))) + .await + { error!("Error sending peer connected event to handle: {e}"); return ControlFlow::Break(()); } @@ -489,7 +494,10 @@ async fn handle_gossipsub_event( trace!("Peer {peer_id} unsubscribed from {topic}"); - if let Err(e) = tx_event.send(Event::PeerDisconnected(peer_id)).await { + if let Err(e) = tx_event + .send(Event::PeerDisconnected(PeerId::from_libp2p(&peer_id))) + .await + { error!("Error sending peer disconnected event to handle: {e}"); return ControlFlow::Break(()); } @@ -518,7 +526,11 @@ async fn handle_gossipsub_event( message.data.len() ); - let event = Event::Message(channel, peer_id, Bytes::from(message.data)); + let event = Event::Message( + channel, + PeerId::from_libp2p(&peer_id), + Bytes::from(message.data), + ); if let Err(e) = tx_event.send(event).await { error!("Error sending message to handle: {e}"); @@ -549,7 +561,10 @@ async fn handle_broadcast_event( trace!("Peer {peer_id} subscribed to {topic:?}"); - if let Err(e) = tx_event.send(Event::PeerConnected(peer_id)).await { + if let Err(e) = tx_event + .send(Event::PeerConnected(PeerId::from_libp2p(&peer_id))) + .await + { error!("Error sending peer connected event to handle: {e}"); return ControlFlow::Break(()); } @@ -563,7 +578,10 @@ async fn handle_broadcast_event( trace!("Peer {peer_id} unsubscribed from {topic:?}"); - if let Err(e) = tx_event.send(Event::PeerDisconnected(peer_id)).await { + if let Err(e) = tx_event + .send(Event::PeerDisconnected(PeerId::from_libp2p(&peer_id))) + .await + { error!("Error sending peer disconnected event to handle: {e}"); return ControlFlow::Break(()); } @@ -580,7 +598,11 @@ async fn handle_broadcast_event( message.len() ); - let event = Event::Message(channel, peer_id, Bytes::copy_from_slice(message.as_ref())); + let event = Event::Message( + channel, + PeerId::from_libp2p(&peer_id), + Bytes::copy_from_slice(message.as_ref()), + ); if let Err(e) = tx_event.send(event).await { error!("Error sending message to handle: {e}"); @@ -612,7 +634,7 @@ async fn handle_blocksync_event( let _ = tx_event .send(Event::BlockSync(blocksync::RawMessage::Request { request_id, - peer, + peer: PeerId::from_libp2p(&peer), body: request.0, })) .await @@ -628,7 +650,7 @@ async fn handle_blocksync_event( let _ = tx_event .send(Event::BlockSync(blocksync::RawMessage::Response { request_id, - peer, + peer: PeerId::from_libp2p(&peer), body: response.0, })) .await @@ -665,3 +687,18 @@ async fn handle_blocksync_event( } } } + +pub trait PeerIdExt { + fn to_libp2p(&self) -> libp2p::PeerId; + fn from_libp2p(peer_id: &libp2p::PeerId) -> Self; +} + +impl PeerIdExt for PeerId { + fn to_libp2p(&self) -> libp2p::PeerId { + libp2p::PeerId::from_bytes(&self.to_bytes()).expect("valid PeerId") + } + + fn from_libp2p(peer_id: &libp2p::PeerId) -> Self { + Self::from_bytes(&peer_id.to_bytes()).expect("valid PeerId") + } +} diff --git a/code/crates/gossip-consensus/test/src/lib.rs b/code/crates/gossip-consensus/test/src/lib.rs index fd8954176..240c4b356 100644 --- a/code/crates/gossip-consensus/test/src/lib.rs +++ b/code/crates/gossip-consensus/test/src/lib.rs @@ -3,7 +3,7 @@ use std::time::{Duration, SystemTime, UNIX_EPOCH}; use libp2p_identity::{ecdsa, PeerId}; use malachite_config::TransportProtocol; -use malachite_gossip_consensus::{spawn, Config, DiscoveryConfig, Keypair}; +use malachite_gossip_consensus::{spawn, Config, DiscoveryConfig, Keypair, PeerIdExt}; use malachite_metrics::SharedRegistry; use malachite_starknet_host::types::PrivateKey; use rand::{rngs::StdRng, Rng, SeedableRng}; @@ -207,12 +207,12 @@ impl Test { event = handle.recv() => { match event { Some(malachite_gossip_consensus::Event::PeerConnected(peer_id)) => { - if !peers.contains(&peer_id) { - peers.push(peer_id); + if !peers.contains(&peer_id.to_libp2p()) { + peers.push(peer_id.to_libp2p()); } } Some(malachite_gossip_consensus::Event::PeerDisconnected(peer_id)) => { - if let Some(pos) = peers.iter().position(|p| p == &peer_id) { + if let Some(pos) = peers.iter().position(|p| p == &peer_id.to_libp2p()) { peers.remove(pos); } } diff --git a/code/crates/peer/Cargo.toml b/code/crates/peer/Cargo.toml new file mode 100644 index 000000000..8c9dc0615 --- /dev/null +++ b/code/crates/peer/Cargo.toml @@ -0,0 +1,24 @@ +[package] +name = "malachite-peer" +version.workspace = true +edition.workspace = true +repository.workspace = true +license.workspace = true +publish.workspace = true +rust-version.workspace = true + +[features] +rand = ["dep:rand"] +serde = ["dep:serde"] + +[dependencies] +# TODO: Remove `std` once https://github.com/multiformats/rust-multihash/issues/375 is resolved +multihash = { workspace = true, features = ["std", "alloc"] } + +bs58 = { workspace = true } +thiserror = { workspace = true } +rand = { workspace = true, optional = true } +serde = { workspace = true, optional = true } + +[lints] +workspace = true diff --git a/code/crates/peer/src/lib.rs b/code/crates/peer/src/lib.rs new file mode 100644 index 000000000..ad54b2d8d --- /dev/null +++ b/code/crates/peer/src/lib.rs @@ -0,0 +1,221 @@ +// Copyright 2018 Parity Technologies (UK) Ltd. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +// FIXME: Make the crate no_std compatible once https://github.com/multiformats/rust-multihash/issues/375 is resolved + +use std::{fmt, str::FromStr}; + +use thiserror::Error; + +#[cfg(feature = "rand")] +use rand::Rng; + +/// Local type-alias for multihash. +/// +/// Must be big enough to accommodate for `MAX_INLINE_KEY_LENGTH`. +/// 64 satisfies that and can hold 512 bit hashes which is what the ecosystem typically uses. +/// Given that this appears in our type-signature, using a "common" number here makes us more compatible. +type Multihash = multihash::Multihash<64>; + +#[cfg(feature = "serde")] +use serde::{Deserialize, Serialize}; + +/// Public keys with byte-lengths smaller than `MAX_INLINE_KEY_LENGTH` will be +/// automatically used as the peer id using an identity multihash. +const MAX_INLINE_KEY_LENGTH: usize = 42; + +const MULTIHASH_IDENTITY_CODE: u64 = 0; +const MULTIHASH_SHA256_CODE: u64 = 0x12; + +/// Identifier of a peer of the network. +/// +/// The data is a CIDv0 compatible multihash of the protobuf encoded public key of the peer +/// as specified in [specs/peer-ids](https://github.com/libp2p/specs/blob/master/peer-ids/peer-ids.md). +#[derive(Clone, Copy, Eq, Hash, Ord, PartialEq, PartialOrd)] +pub struct PeerId { + multihash: Multihash, +} + +impl fmt::Debug for PeerId { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_tuple("PeerId").field(&self.to_base58()).finish() + } +} + +impl fmt::Display for PeerId { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + self.to_base58().fmt(f) + } +} + +impl PeerId { + /// Parses a `PeerId` from bytes. + pub fn from_bytes(data: &[u8]) -> Result { + PeerId::from_multihash(Multihash::from_bytes(data)?) + .map_err(|mh| ParseError::UnsupportedCode(mh.code())) + } + + /// Tries to turn a `Multihash` into a `PeerId`. + /// + /// If the multihash does not use a valid hashing algorithm for peer IDs, + /// or the hash value does not satisfy the constraints for a hashed + /// peer ID, it is returned as an `Err`. + pub fn from_multihash(multihash: Multihash) -> Result { + match multihash.code() { + MULTIHASH_SHA256_CODE => Ok(PeerId { multihash }), + MULTIHASH_IDENTITY_CODE if multihash.digest().len() <= MAX_INLINE_KEY_LENGTH => { + Ok(PeerId { multihash }) + } + _ => Err(multihash), + } + } + + /// Generates a random peer ID from a cryptographically secure PRNG. + /// + /// This is useful for randomly walking on a DHT, or for testing purposes. + #[cfg(feature = "rand")] + pub fn random() -> PeerId { + let peer_id = rand::thread_rng().gen::<[u8; 32]>(); + PeerId { + multihash: Multihash::wrap(0x0, &peer_id).expect("The digest size is never too large"), + } + } + + /// Returns a raw bytes representation of this `PeerId`. + pub fn to_bytes(self) -> Vec { + self.multihash.to_bytes() + } + + /// Returns a base-58 encoded string of this `PeerId`. + pub fn to_base58(self) -> String { + bs58::encode(self.to_bytes()).into_string() + } +} + +impl TryFrom> for PeerId { + type Error = Vec; + + fn try_from(value: Vec) -> Result { + PeerId::from_bytes(&value).map_err(|_| value) + } +} + +impl TryFrom for PeerId { + type Error = Multihash; + + fn try_from(value: Multihash) -> Result { + PeerId::from_multihash(value) + } +} + +impl AsRef for PeerId { + fn as_ref(&self) -> &Multihash { + &self.multihash + } +} + +impl From for Multihash { + fn from(peer_id: PeerId) -> Self { + peer_id.multihash + } +} + +impl From for Vec { + fn from(peer_id: PeerId) -> Self { + peer_id.to_bytes() + } +} + +#[cfg(feature = "serde")] +impl Serialize for PeerId { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + if serializer.is_human_readable() { + serializer.serialize_str(&self.to_base58()) + } else { + serializer.serialize_bytes(&self.to_bytes()[..]) + } + } +} + +#[cfg(feature = "serde")] +impl<'de> Deserialize<'de> for PeerId { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + use serde::de::*; + + struct PeerIdVisitor; + + impl Visitor<'_> for PeerIdVisitor { + type Value = PeerId; + + fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "valid peer id") + } + + fn visit_bytes(self, v: &[u8]) -> Result + where + E: Error, + { + PeerId::from_bytes(v).map_err(|_| Error::invalid_value(Unexpected::Bytes(v), &self)) + } + + fn visit_str(self, v: &str) -> Result + where + E: Error, + { + PeerId::from_str(v).map_err(|_| Error::invalid_value(Unexpected::Str(v), &self)) + } + } + + if deserializer.is_human_readable() { + deserializer.deserialize_str(PeerIdVisitor) + } else { + deserializer.deserialize_bytes(PeerIdVisitor) + } + } +} + +/// Error when parsing a [`PeerId`] from string or bytes. +#[derive(Debug, Error)] +pub enum ParseError { + #[error("base-58 decode error: {0}")] + B58(#[from] bs58::decode::Error), + #[error("unsupported multihash code '{0}'")] + UnsupportedCode(u64), + #[error("invalid multihash")] + InvalidMultihash(#[from] multihash::Error), +} + +impl FromStr for PeerId { + type Err = ParseError; + + #[inline] + fn from_str(s: &str) -> Result { + let bytes = bs58::decode(s).into_vec()?; + let peer_id = PeerId::from_bytes(&bytes)?; + + Ok(peer_id) + } +} diff --git a/code/crates/starknet/host/src/actor.rs b/code/crates/starknet/host/src/actor.rs index 50bdefd48..e250ede97 100644 --- a/code/crates/starknet/host/src/actor.rs +++ b/code/crates/starknet/host/src/actor.rs @@ -1,279 +1,48 @@ -use std::path::{Path, PathBuf}; -use std::sync::Arc; +use std::path::PathBuf; +use std::time::Duration; +use bytes::Bytes; use eyre::eyre; - use itertools::Itertools; -use ractor::{async_trait, Actor, ActorProcessingErr, SpawnErr}; +use ractor::{async_trait, Actor, ActorProcessingErr, RpcReplyPort, SpawnErr}; use rand::rngs::StdRng; -use rand::{RngCore, SeedableRng}; -use sha3::Digest; +use rand::SeedableRng; use tokio::time::Instant; use tracing::{debug, error, info, trace, warn}; -use malachite_actors::consensus::ConsensusMsg; -use malachite_actors::gossip_consensus::{GossipConsensusMsg, GossipConsensusRef}; +use malachite_actors::consensus::{ConsensusMsg, ConsensusRef}; +use malachite_actors::gossip_consensus::{ + GossipConsensusMsg as GossipMsg, GossipConsensusRef as GossipRef, +}; use malachite_actors::host::{LocallyProposedValue, ProposedValue}; -use malachite_actors::util::streaming::{StreamContent, StreamId, StreamMessage}; +use malachite_actors::util::streaming::{StreamContent, StreamMessage}; use malachite_blocksync::SyncedBlock; -use malachite_common::{Round, SignedExtension, Validity}; +use malachite_common::{CommitCertificate, Round, Validity}; +use malachite_consensus::PeerId; use malachite_metrics::Metrics; -use malachite_starknet_p2p_types::{Block, PartType}; -use crate::block_store::BlockStore; +use crate::host::proposal::compute_proposal_signature; +use crate::host::state::HostState; +use crate::host::{Host as _, StarknetHost}; use crate::mempool::{MempoolMsg, MempoolRef}; -use crate::mock::host::{compute_proposal_hash, compute_proposal_signature, MockHost}; use crate::proto::Protobuf; -use crate::streaming::PartStreamsMap; use crate::types::*; -use crate::Host; -pub struct StarknetHost { +pub struct Host { mempool: MempoolRef, - gossip_consensus: GossipConsensusRef, + gossip: GossipRef, metrics: Metrics, } -pub struct HostState { - height: Height, - round: Round, - proposer: Option
, - host: MockHost, - block_store: BlockStore, - part_streams_map: PartStreamsMap, - next_stream_id: StreamId, -} - -impl HostState { - pub fn new(host: MockHost, db_path: impl AsRef, rng: &mut R) -> Self - where - R: RngCore, - { - Self { - height: Height::new(0, 0), - round: Round::Nil, - proposer: None, - host, - block_store: BlockStore::new(db_path).unwrap(), - part_streams_map: PartStreamsMap::default(), - next_stream_id: rng.next_u64(), - } - } - - pub fn next_stream_id(&mut self) -> StreamId { - let stream_id = self.next_stream_id; - // Wrap around if we get to u64::MAX, which may happen if the initial - // stream id was close to it already. - self.next_stream_id = self.next_stream_id.wrapping_add(1); - stream_id - } - - #[tracing::instrument(skip_all, fields(%height, %round))] - pub async fn build_block_from_parts( - &self, - parts: &[Arc], - height: Height, - round: Round, - ) -> Option<(ProposedValue, Block)> { - let value = self.build_value_from_parts(parts, height, round).await?; - - let txes = parts - .iter() - .filter_map(|part| part.as_transactions()) - .flat_map(|txes| txes.to_vec()) - .collect::>(); - - let block = Block { - height, - transactions: Transactions::new(txes), - block_hash: value.value, - }; - - Some((value, block)) - } - - #[tracing::instrument(skip_all, fields(%height, %round))] - pub async fn build_value_from_parts( - &self, - parts: &[Arc], - height: Height, - round: Round, - ) -> Option> { - let (valid_round, value, validator_address, validity, extension) = self - .build_proposal_content_from_parts(parts, height, round) - .await?; - - Some(ProposedValue { - validator_address, - height, - round, - valid_round, - value, - validity, - extension, - }) - } - - #[allow(clippy::type_complexity)] - #[tracing::instrument(skip_all, fields(%height, %round))] - pub async fn build_proposal_content_from_parts( - &self, - parts: &[Arc], - height: Height, - round: Round, - ) -> Option<( - Round, - BlockHash, - Address, - Validity, - Option>, - )> { - if parts.is_empty() { - return None; - } - - let Some(init) = parts.iter().find_map(|part| part.as_init()) else { - error!("No Init part found in the proposal parts"); - return None; - }; - - let valid_round = init.valid_round; - if valid_round.is_defined() { - debug!("Reassembling a Proposal we might have seen before: {init:?}"); - } - - let Some(fin) = parts.iter().find_map(|part| part.as_fin()) else { - error!("No Fin part found in the proposal parts"); - return None; - }; - - trace!(parts.len = %parts.len(), "Building proposal content from parts"); - - let extension = self.host.generate_vote_extension(height, round); - - let block_hash = { - let mut block_hasher = sha3::Keccak256::new(); - for part in parts { - if part.as_init().is_some() || part.as_fin().is_some() { - // NOTE: We do not hash over Init, so restreaming returns the same hash - // NOTE: We do not hash over Fin, because Fin includes a signature over the block hash - // TODO: we should probably still include height - continue; - } - - block_hasher.update(part.to_sign_bytes()); - } - - BlockHash::new(block_hasher.finalize().into()) - }; - - trace!(%block_hash, "Computed block hash"); - - let proposal_hash = compute_proposal_hash(init, &block_hash); - - let validity = self - .verify_proposal_validity(init, &proposal_hash, &fin.signature) - .await?; - - Some(( - valid_round, - block_hash, - init.proposer.clone(), - validity, - extension, - )) - } - - async fn verify_proposal_validity( - &self, - init: &ProposalInit, - proposal_hash: &Hash, - signature: &Signature, - ) -> Option { - let validators = self.host.validators(init.height).await?; - - let public_key = validators - .iter() - .find(|v| v.address == init.proposer) - .map(|v| v.public_key); - - let Some(public_key) = public_key else { - error!(proposer = %init.proposer, "No validator found for the proposer"); - return None; - }; - - let valid = public_key.verify(&proposal_hash.as_felt(), signature); - Some(Validity::from_bool(valid)) - } - - #[tracing::instrument(skip_all, fields( - part.height = %height, - part.round = %round, - part.message = ?part.part_type(), - ))] - async fn build_value_from_part( - &mut self, - height: Height, - round: Round, - part: ProposalPart, - ) -> Option> { - self.host.part_store.store(height, round, part.clone()); - - if let ProposalPart::Transactions(_txes) = &part { - debug!("Simulating tx execution and proof verification"); - - // Simulate Tx execution and proof verification (assumes success) - // TODO: Add config knob for invalid blocks - let num_txes = part.tx_count() as u32; - let exec_time = self.host.params.exec_time_per_tx * num_txes; - tokio::time::sleep(exec_time).await; - - trace!("Simulation took {exec_time:?} to execute {num_txes} txes"); - } - - let parts = self.host.part_store.all_parts(height, round); - - trace!( - count = self.host.part_store.blocks_count(), - "Blocks for which we have parts" - ); - - // TODO: Do more validations, e.g. there is no higher tx proposal part, - // check that we have received the proof, etc. - let Some(_fin) = parts.iter().find_map(|part| part.as_fin()) else { - debug!("Final proposal part has not been received yet"); - return None; - }; - - let block_size: usize = parts.iter().map(|p| p.size_bytes()).sum(); - let tx_count: usize = parts.iter().map(|p| p.tx_count()).sum(); - - debug!( - tx.count = %tx_count, block.size = %block_size, parts.count = %parts.len(), - "All parts have been received already, building value" - ); - - let result = self.build_value_from_parts(&parts, height, round).await; - - if let Some(ref proposed_value) = result { - self.host - .part_store - .store_value_id(height, round, proposed_value.value); - } - - result - } -} - pub type HostRef = malachite_actors::host::HostRef; pub type HostMsg = malachite_actors::host::HostMsg; -impl StarknetHost { +impl Host { pub async fn spawn( home_dir: PathBuf, - host: MockHost, + host: StarknetHost, mempool: MempoolRef, - gossip_consensus: GossipConsensusRef, + gossip: GossipRef, metrics: Metrics, ) -> Result { let db_dir = home_dir.join("db"); @@ -282,7 +51,7 @@ impl StarknetHost { let (actor_ref, _) = Actor::spawn( None, - Self::new(mempool, gossip_consensus, metrics), + Self::new(mempool, gossip, metrics), HostState::new(host, db_path, &mut StdRng::from_entropy()), ) .await?; @@ -290,46 +59,17 @@ impl StarknetHost { Ok(actor_ref) } - pub fn new( - mempool: MempoolRef, - gossip_consensus: GossipConsensusRef, - metrics: Metrics, - ) -> Self { + pub fn new(mempool: MempoolRef, gossip: GossipRef, metrics: Metrics) -> Self { Self { mempool, - gossip_consensus, + gossip, metrics, } } - - async fn prune_block_store(&self, state: &mut HostState) { - let max_height = state.block_store.last_height().unwrap_or_default(); - let max_retain_blocks = state.host.params.max_retain_blocks as u64; - - // Compute the height to retain blocks higher than - let retain_height = max_height.as_u64().saturating_sub(max_retain_blocks); - if retain_height <= 1 { - // No need to prune anything, since we would retain every blocks - return; - } - - let retain_height = Height::new(retain_height, max_height.fork_id); - match state.block_store.prune(retain_height).await { - Ok(pruned) => { - debug!( - %retain_height, pruned_heights = pruned.iter().join(", "), - "Pruned the block store" - ); - } - Err(e) => { - error!(%e, %retain_height, "Failed to prune the block store"); - } - } - } } #[async_trait] -impl Actor for StarknetHost { +impl Actor for Host { type Arguments = HostState; type State = HostState; type Msg = HostMsg; @@ -348,365 +88,480 @@ impl Actor for StarknetHost { msg: Self::Msg, state: &mut Self::State, ) -> Result<(), ActorProcessingErr> { - match msg { - HostMsg::ConsensusReady(consensus) => { - let latest_block_height = state.block_store.last_height().unwrap_or_default(); - let start_height = latest_block_height.increment(); + if let Err(e) = self.handle_msg(_myself, msg, state).await { + error!(%e, "Failed to handle message"); + } - consensus.cast(ConsensusMsg::StartHeight( - start_height, - state.host.validator_set.clone(), - ))?; + Ok(()) + } +} - Ok(()) - } +impl Host { + async fn handle_msg( + &self, + _myself: HostRef, + msg: HostMsg, + state: &mut HostState, + ) -> Result<(), ActorProcessingErr> { + match msg { + HostMsg::ConsensusReady(consensus) => on_consensus_ready(state, consensus), HostMsg::StartedRound { height, round, proposer, - } => { - state.height = height; - state.round = round; - state.proposer = Some(proposer); - - Ok(()) - } + } => on_started_round(state, height, round, proposer), HostMsg::GetEarliestBlockHeight { reply_to } => { - let earliest_block_height = state.block_store.first_height().unwrap_or_default(); - reply_to.send(earliest_block_height)?; - Ok(()) + on_get_earliest_block_height(state, reply_to) } HostMsg::GetValue { height, round, - timeout_duration, + timeout, address: _, reply_to, + } => on_get_value(state, &self.gossip, height, round, timeout, reply_to).await, + + HostMsg::RestreamValue { + height, + round, + valid_round, + address, + value_id, } => { - // If we have already built a block for this height and round, return it - // This may happen when we are restarting after a crash and replaying the WAL. - if let Some(block) = state.block_store.get_undecided_block(height, round).await? { - info!(%height, %round, hash = %block.block_hash, "Returning previously built block"); + on_restream_value( + state, + &self.gossip, + height, + round, + value_id, + valid_round, + address, + ) + .await + } - let value = LocallyProposedValue::new(height, round, block.block_hash, None); - reply_to.send(value)?; + HostMsg::ReceivedProposalPart { + from, + part, + reply_to, + } => on_received_proposal_part(state, part, from, reply_to).await, - return Ok(()); - } + HostMsg::GetValidatorSet { height, reply_to } => { + on_get_validator_set(state, height, reply_to).await + } - let deadline = Instant::now() + timeout_duration; + HostMsg::Decided { + certificate, + consensus, + } => on_decided(state, &consensus, &self.mempool, certificate, &self.metrics).await, - debug!(%height, %round, "Building new proposal..."); + HostMsg::GetDecidedBlock { height, reply_to } => { + on_get_decided_block(height, state, reply_to).await + } - let (mut rx_part, rx_hash) = - state.host.build_new_proposal(height, round, deadline).await; + HostMsg::ProcessSyncedBlock { + height, + round, + validator_address, + block_bytes, + reply_to, + } => on_process_synced_block(block_bytes, height, round, validator_address, reply_to), + } + } +} - let stream_id = state.next_stream_id(); +fn on_consensus_ready( + state: &mut HostState, + consensus: ConsensusRef, +) -> Result<(), ActorProcessingErr> { + let latest_block_height = state.block_store.last_height().unwrap_or_default(); + let start_height = latest_block_height.increment(); - let mut sequence = 0; + consensus.cast(ConsensusMsg::StartHeight( + start_height, + state.host.validator_set.clone(), + ))?; - while let Some(part) = rx_part.recv().await { - state.host.part_store.store(height, round, part.clone()); + Ok(()) +} - if state.host.params.value_payload.include_parts() { - debug!(%stream_id, %sequence, "Broadcasting proposal part"); +fn on_started_round( + state: &mut HostState, + height: Height, + round: Round, + proposer: Address, +) -> Result<(), ActorProcessingErr> { + state.height = height; + state.round = round; + state.proposer = Some(proposer); - let msg = StreamMessage::new( - stream_id, - sequence, - StreamContent::Data(part.clone()), - ); + Ok(()) +} - self.gossip_consensus - .cast(GossipConsensusMsg::PublishProposalPart(msg))?; - } +fn on_get_earliest_block_height( + state: &mut HostState, + reply_to: RpcReplyPort, +) -> Result<(), ActorProcessingErr> { + let earliest_block_height = state.block_store.first_height().unwrap_or_default(); + reply_to.send(earliest_block_height)?; - sequence += 1; - } + Ok(()) +} - if state.host.params.value_payload.include_parts() { - let msg = StreamMessage::new(stream_id, sequence, StreamContent::Fin(true)); +async fn on_get_validator_set( + state: &mut HostState, + height: Height, + reply_to: RpcReplyPort, +) -> Result<(), ActorProcessingErr> { + let Some(validators) = state.host.validators(height).await else { + return Err(eyre!("No validator set found for the given height {height}").into()); + }; + + reply_to.send(ValidatorSet::new(validators))?; + Ok(()) +} - self.gossip_consensus - .cast(GossipConsensusMsg::PublishProposalPart(msg))?; - } +async fn on_get_value( + state: &mut HostState, + gossip: &GossipRef, + height: Height, + round: Round, + timeout: Duration, + reply_to: RpcReplyPort>, +) -> Result<(), ActorProcessingErr> { + // If we have already built a block for this height and round, return it + // This may happen when we are restarting after a crash and replaying the WAL. + if let Some(block) = state.block_store.get_undecided_block(height, round).await? { + info!(%height, %round, hash = %block.block_hash, "Returning previously built block"); + + let value = LocallyProposedValue::new(height, round, block.block_hash, None); + reply_to.send(value)?; + + return Ok(()); + } - let block_hash = rx_hash.await?; - debug!(%block_hash, "Assembled block"); + let deadline = Instant::now() + timeout; - state - .host - .part_store - .store_value_id(height, round, block_hash); + debug!(%height, %round, "Building new proposal..."); - let parts = state.host.part_store.all_parts(height, round); + let (mut rx_part, rx_hash) = state.host.build_new_proposal(height, round, deadline).await; - let Some((value, block)) = - state.build_block_from_parts(&parts, height, round).await - else { - error!(%height, %round, "Failed to build block from parts"); - return Ok(()); - }; + let stream_id = state.next_stream_id(); - if let Err(e) = state - .block_store - .store_undecided_block(value.height, value.round, block) - .await - { - error!(%e, %height, %round, "Failed to store the proposed block"); - } + let mut sequence = 0; - reply_to.send(LocallyProposedValue::new( - value.height, - value.round, - value.value, - value.extension, - ))?; + while let Some(part) = rx_part.recv().await { + state.host.part_store.store(height, round, part.clone()); - Ok(()) - } + if state.host.params.value_payload.include_parts() { + debug!(%stream_id, %sequence, "Broadcasting proposal part"); - HostMsg::RestreamValue { - height, - round, - valid_round, - address, - value_id, - } => { - debug!(%height, %round, "Restreaming existing proposal..."); + let msg = StreamMessage::new(stream_id, sequence, StreamContent::Data(part.clone())); + gossip.cast(GossipMsg::PublishProposalPart(msg))?; + } - let mut rx_part = state.host.send_known_proposal(value_id).await; + sequence += 1; + } - let stream_id = state.next_stream_id(); + if state.host.params.value_payload.include_parts() { + let msg = StreamMessage::new(stream_id, sequence, StreamContent::Fin(true)); + gossip.cast(GossipMsg::PublishProposalPart(msg))?; + } - let init = ProposalInit { - height, - proposal_round: round, - valid_round, - proposer: address.clone(), - }; + let block_hash = rx_hash.await?; + debug!(%block_hash, "Assembled block"); - let signature = - compute_proposal_signature(&init, &value_id, &state.host.private_key); + state + .host + .part_store + .store_value_id(height, round, block_hash); - let init_part = ProposalPart::Init(init); - let fin_part = ProposalPart::Fin(ProposalFin { signature }); + let parts = state.host.part_store.all_parts(height, round); - debug!(%height, %round, "Created new Init part: {init_part:?}"); + let Some((value, block)) = state.build_block_from_parts(&parts, height, round).await else { + error!(%height, %round, "Failed to build block from parts"); + return Ok(()); + }; - let mut sequence = 0; + if let Err(e) = state + .block_store + .store_undecided_block(value.height, value.round, block) + .await + { + error!(%e, %height, %round, "Failed to store the proposed block"); + } - while let Some(part) = rx_part.recv().await { - let new_part = match part.part_type() { - PartType::Init => init_part.clone(), - PartType::Fin => fin_part.clone(), - PartType::Transactions | PartType::BlockProof => part, - }; + reply_to.send(LocallyProposedValue::new( + value.height, + value.round, + value.value, + value.extension, + ))?; - state.host.part_store.store(height, round, new_part.clone()); + Ok(()) +} - if state.host.params.value_payload.include_parts() { - debug!(%stream_id, %sequence, "Broadcasting proposal part"); +async fn on_restream_value( + state: &mut HostState, + gossip: &GossipRef, + height: Height, + round: Round, + value_id: Hash, + valid_round: Round, + address: Address, +) -> Result<(), ActorProcessingErr> { + debug!(%height, %round, "Restreaming existing proposal..."); - let msg = - StreamMessage::new(stream_id, sequence, StreamContent::Data(new_part)); + let mut rx_part = state.host.send_known_proposal(value_id).await; - self.gossip_consensus - .cast(GossipConsensusMsg::PublishProposalPart(msg))?; + let stream_id = state.next_stream_id(); - sequence += 1; - } - } + let init = ProposalInit { + height, + proposal_round: round, + valid_round, + proposer: address.clone(), + }; - Ok(()) - } + let signature = compute_proposal_signature(&init, &value_id, &state.host.private_key); - HostMsg::ReceivedProposalPart { - from, - part, - reply_to, - } => { - // TODO - use state.host.receive_proposal() and move some of the logic below there - let sequence = part.sequence; - - let Some(parts) = state.part_streams_map.insert(from, part) else { - return Ok(()); - }; - - if parts.height < state.height { - trace!( - height = %state.height, - round = %state.round, - part.height = %parts.height, - part.round = %parts.round, - part.sequence = %sequence, - "Received outdated proposal part, ignoring" - ); - - return Ok(()); - } - - for part in parts.parts { - debug!( - part.sequence = %sequence, - part.height = %parts.height, - part.round = %parts.round, - part.message = ?part.part_type(), - "Processing proposal part" - ); - - if let Some(value) = state - .build_value_from_part(parts.height, parts.round, part) - .await - { - reply_to.send(value)?; - break; - } - } - - Ok(()) - } + let init_part = ProposalPart::Init(init); + let fin_part = ProposalPart::Fin(ProposalFin { signature }); - HostMsg::GetValidatorSet { height, reply_to } => { - if let Some(validators) = state.host.validators(height).await { - reply_to.send(ValidatorSet::new(validators))?; - Ok(()) - } else { - Err(eyre!("No validator set found for the given height {height}").into()) - } - } + debug!(%height, %round, "Created new Init part: {init_part:?}"); - HostMsg::Decided { - certificate, - consensus, - } => { - let (height, round) = (certificate.height, certificate.round); - - let mut all_parts = state.host.part_store.all_parts(height, round); - - let mut all_txes = vec![]; - for part in all_parts.iter_mut() { - if let ProposalPart::Transactions(transactions) = part.as_ref() { - let mut txes = transactions.to_vec(); - all_txes.append(&mut txes); - } - } - - // Build the block from transaction parts and certificate, and store it - if let Err(e) = state - .block_store - .store_decided_block(&certificate, &all_txes) - .await - { - error!(%e, %height, %round, "Failed to store the block"); - } - - // Update metrics - let block_size: usize = all_parts.iter().map(|p| p.size_bytes()).sum(); - let extension_size: usize = certificate - .aggregated_signature - .signatures - .iter() - .map(|c| c.extension.as_ref().map(|e| e.size_bytes()).unwrap_or(0)) - .sum(); - - let block_and_commits_size = block_size + extension_size; - let tx_count: usize = all_parts.iter().map(|p| p.tx_count()).sum(); - - self.metrics.block_tx_count.observe(tx_count as f64); - self.metrics - .block_size_bytes - .observe(block_and_commits_size as f64); - self.metrics.finalized_txes.inc_by(tx_count as u64); - - // Gather hashes of all the tx-es included in the block, - // so that we can notify the mempool to remove them. - let mut tx_hashes = vec![]; - for part in all_parts { - if let ProposalPart::Transactions(txes) = &part.as_ref() { - tx_hashes.extend(txes.as_slice().iter().map(|tx| tx.hash())); - } - } - - // Prune the PartStore of all parts for heights lower than `state.height` - state.host.part_store.prune(state.height); - - // Store the block - self.prune_block_store(state).await; - - // Notify the mempool to remove corresponding txs - self.mempool.cast(MempoolMsg::Update { tx_hashes })?; - - // Notify Starknet Host of the decision - state.host.decision(certificate).await; - - // Start the next height - consensus.cast(ConsensusMsg::StartHeight( - state.height.increment(), - state.host.validator_set.clone(), - ))?; - - Ok(()) - } + let mut sequence = 0; - HostMsg::GetDecidedBlock { height, reply_to } => { - debug!(%height, "Received request for block"); - - match state.block_store.get(height).await { - Ok(None) => { - let min = state.block_store.first_height().unwrap_or_default(); - let max = state.block_store.last_height().unwrap_or_default(); - - warn!(%height, "No block for this height, available blocks: {min}..={max}"); - - reply_to.send(None)?; - } - - Ok(Some(block)) => { - let block = SyncedBlock { - block_bytes: block.block.to_bytes().unwrap(), - certificate: block.certificate, - }; - - debug!(%height, "Found decided block in store"); - reply_to.send(Some(block))?; - } - Err(e) => { - error!(%e, %height, "Failed to get decided block"); - reply_to.send(None)?; - } - } - - Ok(()) - } + while let Some(part) = rx_part.recv().await { + let new_part = match part.part_type() { + PartType::Init => init_part.clone(), + PartType::Fin => fin_part.clone(), + PartType::Transactions | PartType::BlockProof => part, + }; - HostMsg::ProcessSyncedBlock { - height, - round, - validator_address, - block_bytes, - reply_to, - } => { - let maybe_block = Block::from_bytes(block_bytes.as_ref()); - if let Ok(block) = maybe_block { - let proposed_value = ProposedValue { - height, - round, - valid_round: Round::Nil, - validator_address, - value: block.block_hash, - validity: Validity::Valid, - extension: None, - }; - - reply_to.send(proposed_value)?; - } - - Ok(()) - } + state.host.part_store.store(height, round, new_part.clone()); + + if state.host.params.value_payload.include_parts() { + debug!(%stream_id, %sequence, "Broadcasting proposal part"); + + let msg = StreamMessage::new(stream_id, sequence, StreamContent::Data(new_part)); + + gossip.cast(GossipMsg::PublishProposalPart(msg))?; + + sequence += 1; + } + } + + Ok(()) +} + +fn on_process_synced_block( + block_bytes: Bytes, + height: Height, + round: Round, + validator_address: Address, + reply_to: RpcReplyPort>, +) -> Result<(), ActorProcessingErr> { + let maybe_block = Block::from_bytes(block_bytes.as_ref()); + if let Ok(block) = maybe_block { + let proposed_value = ProposedValue { + height, + round, + valid_round: Round::Nil, + validator_address, + value: block.block_hash, + validity: Validity::Valid, + extension: None, + }; + + reply_to.send(proposed_value)?; + } + + Ok(()) +} + +async fn on_get_decided_block( + height: Height, + state: &mut HostState, + reply_to: RpcReplyPort>>, +) -> Result<(), ActorProcessingErr> { + debug!(%height, "Received request for block"); + + match state.block_store.get(height).await { + Ok(None) => { + let min = state.block_store.first_height().unwrap_or_default(); + let max = state.block_store.last_height().unwrap_or_default(); + + warn!(%height, "No block for this height, available blocks: {min}..={max}"); + + reply_to.send(None)?; + } + + Ok(Some(block)) => { + let block = SyncedBlock { + block_bytes: block.block.to_bytes().unwrap(), + certificate: block.certificate, + }; + + debug!(%height, "Found decided block in store"); + reply_to.send(Some(block))?; + } + Err(e) => { + error!(%e, %height, "Failed to get decided block"); + reply_to.send(None)?; + } + } + + Ok(()) +} + +async fn on_received_proposal_part( + state: &mut HostState, + part: StreamMessage, + from: PeerId, + reply_to: RpcReplyPort>, +) -> Result<(), ActorProcessingErr> { + // TODO - use state.host.receive_proposal() and move some of the logic below there + let sequence = part.sequence; + + let Some(parts) = state.part_streams_map.insert(from, part) else { + return Ok(()); + }; + + if parts.height < state.height { + trace!( + height = %state.height, + round = %state.round, + part.height = %parts.height, + part.round = %parts.round, + part.sequence = %sequence, + "Received outdated proposal part, ignoring" + ); + + return Ok(()); + } + + for part in parts.parts { + debug!( + part.sequence = %sequence, + part.height = %parts.height, + part.round = %parts.round, + part.message = ?part.part_type(), + "Processing proposal part" + ); + + if let Some(value) = state + .build_value_from_part(parts.height, parts.round, part) + .await + { + reply_to.send(value)?; + break; + } + } + + Ok(()) +} + +async fn on_decided( + state: &mut HostState, + consensus: &ConsensusRef, + mempool: &MempoolRef, + certificate: CommitCertificate, + metrics: &Metrics, +) -> Result<(), ActorProcessingErr> { + let (height, round) = (certificate.height, certificate.round); + + let mut all_parts = state.host.part_store.all_parts(height, round); + + let mut all_txes = vec![]; + for part in all_parts.iter_mut() { + if let ProposalPart::Transactions(transactions) = part.as_ref() { + let mut txes = transactions.to_vec(); + all_txes.append(&mut txes); + } + } + + // Build the block from transaction parts and certificate, and store it + if let Err(e) = state + .block_store + .store_decided_block(&certificate, &all_txes) + .await + { + error!(%e, %height, %round, "Failed to store the block"); + } + + // Update metrics + let block_size: usize = all_parts.iter().map(|p| p.size_bytes()).sum(); + let extension_size: usize = certificate + .aggregated_signature + .signatures + .iter() + .map(|c| c.extension.as_ref().map(|e| e.size_bytes()).unwrap_or(0)) + .sum(); + + let block_and_commits_size = block_size + extension_size; + let tx_count: usize = all_parts.iter().map(|p| p.tx_count()).sum(); + + metrics.block_tx_count.observe(tx_count as f64); + metrics + .block_size_bytes + .observe(block_and_commits_size as f64); + metrics.finalized_txes.inc_by(tx_count as u64); + + // Gather hashes of all the tx-es included in the block, + // so that we can notify the mempool to remove them. + let mut tx_hashes = vec![]; + for part in all_parts { + if let ProposalPart::Transactions(txes) = &part.as_ref() { + tx_hashes.extend(txes.as_slice().iter().map(|tx| tx.hash())); + } + } + + // Prune the PartStore of all parts for heights lower than `state.height` + state.host.part_store.prune(state.height); + + // Store the block + prune_block_store(state).await; + + // Notify the mempool to remove corresponding txs + mempool.cast(MempoolMsg::Update { tx_hashes })?; + + // Notify Starknet Host of the decision + state.host.decision(certificate).await; + + // Start the next height + consensus.cast(ConsensusMsg::StartHeight( + state.height.increment(), + state.host.validator_set.clone(), + ))?; + + Ok(()) +} + +async fn prune_block_store(state: &mut HostState) { + let max_height = state.block_store.last_height().unwrap_or_default(); + let max_retain_blocks = state.host.params.max_retain_blocks as u64; + + // Compute the height to retain blocks higher than + let retain_height = max_height.as_u64().saturating_sub(max_retain_blocks); + if retain_height <= 1 { + // No need to prune anything, since we would retain every blocks + return; + } + + let retain_height = Height::new(retain_height, max_height.fork_id); + match state.block_store.prune(retain_height).await { + Ok(pruned) => { + debug!( + %retain_height, pruned_heights = pruned.iter().join(", "), + "Pruned the block store" + ); + } + Err(e) => { + error!(%e, %retain_height, "Failed to prune the block store"); } } } diff --git a/code/crates/starknet/host/src/codec.rs b/code/crates/starknet/host/src/codec.rs index 0a5505b4d..a02276dfd 100644 --- a/code/crates/starknet/host/src/codec.rs +++ b/code/crates/starknet/host/src/codec.rs @@ -1,5 +1,4 @@ use bytes::Bytes; -use libp2p_identity::PeerId; use prost::Message; use malachite_actors::util::streaming::{StreamContent, StreamMessage}; @@ -9,7 +8,7 @@ use malachite_common::{ AggregatedSignature, CommitCertificate, CommitSignature, Extension, Round, SignedExtension, SignedProposal, SignedVote, Validity, }; -use malachite_consensus::{ProposedValue, SignedConsensusMsg}; +use malachite_consensus::{PeerId, ProposedValue, SignedConsensusMsg}; use crate::proto::consensus_message::Messages; use crate::proto::{self as proto, Error as ProtoError, Protobuf}; diff --git a/code/crates/starknet/host/src/host.rs b/code/crates/starknet/host/src/host.rs index 6640b2599..c3fcfa9d2 100644 --- a/code/crates/starknet/host/src/host.rs +++ b/code/crates/starknet/host/src/host.rs @@ -8,6 +8,12 @@ use malachite_common::{CommitCertificate, Round}; use crate::types::MockContext; +pub mod proposal; +pub mod starknet; +pub mod state; + +pub use starknet::{StarknetHost, StarknetParams}; + #[async_trait] pub trait Host { type Height; diff --git a/code/crates/starknet/host/src/mock/host/build_proposal.rs b/code/crates/starknet/host/src/host/proposal.rs similarity index 85% rename from code/crates/starknet/host/src/mock/host/build_proposal.rs rename to code/crates/starknet/host/src/host/proposal.rs index 5be3490f7..9a220f1f0 100644 --- a/code/crates/starknet/host/src/mock/host/build_proposal.rs +++ b/code/crates/starknet/host/src/host/proposal.rs @@ -14,8 +14,8 @@ use tracing::{error, trace}; use malachite_common::Round; +use crate::host::starknet::StarknetParams; use crate::mempool::{MempoolMsg, MempoolRef}; -use crate::mock::host::{compute_proposal_signature, MockParams}; use crate::types::*; pub async fn build_proposal_task( @@ -23,7 +23,7 @@ pub async fn build_proposal_task( round: Round, proposer: Address, private_key: PrivateKey, - params: MockParams, + params: StarknetParams, deadline: Instant, mempool: MempoolRef, tx_part: mpsc::Sender, @@ -51,7 +51,7 @@ async fn run_build_proposal_task( round: Round, proposer: Address, private_key: PrivateKey, - params: MockParams, + params: StarknetParams, deadline: Instant, mempool: MempoolRef, tx_part: mpsc::Sender, @@ -212,3 +212,31 @@ async fn run_repropose_task( } Ok(()) } + +pub fn compute_proposal_hash(init: &ProposalInit, block_hash: &BlockHash) -> Hash { + use sha3::Digest; + + let mut hasher = sha3::Keccak256::new(); + + // 1. Block number + hasher.update(init.height.block_number.to_be_bytes()); + // 2. Fork id + hasher.update(init.height.fork_id.to_be_bytes()); + // 3. Proposal round + hasher.update(init.proposal_round.as_i64().to_be_bytes()); + // 4. Valid round + hasher.update(init.valid_round.as_i64().to_be_bytes()); + // 5. Block hash + hasher.update(block_hash.as_bytes()); + + Hash::new(hasher.finalize().into()) +} + +pub fn compute_proposal_signature( + init: &ProposalInit, + block_hash: &BlockHash, + private_key: &PrivateKey, +) -> Signature { + let hash = compute_proposal_hash(init, block_hash); + private_key.sign(&hash.as_felt()) +} diff --git a/code/crates/starknet/host/src/mock/host.rs b/code/crates/starknet/host/src/host/starknet.rs similarity index 86% rename from code/crates/starknet/host/src/mock/host.rs rename to code/crates/starknet/host/src/host/starknet.rs index 7c1d74ee4..9b879a69f 100644 --- a/code/crates/starknet/host/src/mock/host.rs +++ b/code/crates/starknet/host/src/host/starknet.rs @@ -11,16 +11,15 @@ use malachite_common::{CommitCertificate, Extension, Round, SignedExtension, Sig use malachite_config::VoteExtensionsConfig; use malachite_consensus::ValuePayload; +use crate::host::Host; use crate::mempool::MempoolRef; use crate::part_store::PartStore; use crate::types::*; -use crate::Host; -mod build_proposal; -use build_proposal::{build_proposal_task, repropose_task}; +use super::proposal::{build_proposal_task, repropose_task}; #[derive(Copy, Clone, Debug)] -pub struct MockParams { +pub struct StarknetParams { pub max_block_size: ByteSize, pub value_payload: ValuePayload, pub tx_size: ByteSize, @@ -31,8 +30,8 @@ pub struct MockParams { pub vote_extensions: VoteExtensionsConfig, } -pub struct MockHost { - pub params: MockParams, +pub struct StarknetHost { + pub params: StarknetParams, pub mempool: MempoolRef, pub address: Address, pub private_key: PrivateKey, @@ -40,9 +39,9 @@ pub struct MockHost { pub part_store: PartStore, } -impl MockHost { +impl StarknetHost { pub fn new( - params: MockParams, + params: StarknetParams, mempool: MempoolRef, address: Address, private_key: PrivateKey, @@ -85,7 +84,7 @@ impl MockHost { } #[async_trait] -impl Host for MockHost { +impl Host for StarknetHost { type Height = Height; type BlockHash = BlockHash; type MessageHash = MessageHash; @@ -204,31 +203,3 @@ impl Host for MockHost { #[tracing::instrument(skip_all, fields(height = %_certificate.height, block_hash = %_certificate.value_id))] async fn decision(&self, _certificate: CommitCertificate) {} } - -pub fn compute_proposal_hash(init: &ProposalInit, block_hash: &BlockHash) -> Hash { - use sha3::Digest; - - let mut hasher = sha3::Keccak256::new(); - - // 1. Block number - hasher.update(init.height.block_number.to_be_bytes()); - // 2. Fork id - hasher.update(init.height.fork_id.to_be_bytes()); - // 3. Proposal round - hasher.update(init.proposal_round.as_i64().to_be_bytes()); - // 4. Valid round - hasher.update(init.valid_round.as_i64().to_be_bytes()); - // 5. Block hash - hasher.update(block_hash.as_bytes()); - - Hash::new(hasher.finalize().into()) -} - -pub fn compute_proposal_signature( - init: &ProposalInit, - block_hash: &BlockHash, - private_key: &PrivateKey, -) -> Signature { - let hash = compute_proposal_hash(init, block_hash); - private_key.sign(&hash.as_felt()) -} diff --git a/code/crates/starknet/host/src/host/state.rs b/code/crates/starknet/host/src/host/state.rs new file mode 100644 index 000000000..ee621057c --- /dev/null +++ b/code/crates/starknet/host/src/host/state.rs @@ -0,0 +1,247 @@ +use std::path::Path; +use std::sync::Arc; + +use rand::RngCore; +use sha3::Digest; +use tracing::{debug, error, trace}; + +use malachite_actors::host::ProposedValue; +use malachite_actors::util::streaming::StreamId; +use malachite_common::{Round, SignedExtension, Validity}; + +use crate::block_store::BlockStore; +use crate::host::proposal::compute_proposal_hash; +use crate::host::{Host, StarknetHost}; +use crate::streaming::PartStreamsMap; +use crate::types::*; + +pub struct HostState { + pub height: Height, + pub round: Round, + pub proposer: Option
, + pub host: StarknetHost, + pub block_store: BlockStore, + pub part_streams_map: PartStreamsMap, + pub next_stream_id: StreamId, +} + +impl HostState { + pub fn new(host: StarknetHost, db_path: impl AsRef, rng: &mut R) -> Self + where + R: RngCore, + { + Self { + height: Height::new(0, 0), + round: Round::Nil, + proposer: None, + host, + block_store: BlockStore::new(db_path).unwrap(), + part_streams_map: PartStreamsMap::default(), + next_stream_id: rng.next_u64(), + } + } + + pub fn next_stream_id(&mut self) -> StreamId { + let stream_id = self.next_stream_id; + // Wrap around if we get to u64::MAX, which may happen if the initial + // stream id was close to it already. + self.next_stream_id = self.next_stream_id.wrapping_add(1); + stream_id + } + + #[tracing::instrument(skip_all, fields(%height, %round))] + pub async fn build_block_from_parts( + &self, + parts: &[Arc], + height: Height, + round: Round, + ) -> Option<(ProposedValue, Block)> { + let value = self.build_value_from_parts(parts, height, round).await?; + + let txes = parts + .iter() + .filter_map(|part| part.as_transactions()) + .flat_map(|txes| txes.to_vec()) + .collect::>(); + + let block = Block { + height, + transactions: Transactions::new(txes), + block_hash: value.value, + }; + + Some((value, block)) + } + + #[tracing::instrument(skip_all, fields(%height, %round))] + pub async fn build_value_from_parts( + &self, + parts: &[Arc], + height: Height, + round: Round, + ) -> Option> { + let (valid_round, value, validator_address, validity, extension) = self + .build_proposal_content_from_parts(parts, height, round) + .await?; + + Some(ProposedValue { + validator_address, + height, + round, + valid_round, + value, + validity, + extension, + }) + } + + #[allow(clippy::type_complexity)] + #[tracing::instrument(skip_all, fields(%height, %round))] + pub async fn build_proposal_content_from_parts( + &self, + parts: &[Arc], + height: Height, + round: Round, + ) -> Option<( + Round, + BlockHash, + Address, + Validity, + Option>, + )> { + if parts.is_empty() { + return None; + } + + let Some(init) = parts.iter().find_map(|part| part.as_init()) else { + error!("No Init part found in the proposal parts"); + return None; + }; + + let valid_round = init.valid_round; + if valid_round.is_defined() { + debug!("Reassembling a Proposal we might have seen before: {init:?}"); + } + + let Some(fin) = parts.iter().find_map(|part| part.as_fin()) else { + error!("No Fin part found in the proposal parts"); + return None; + }; + + trace!(parts.len = %parts.len(), "Building proposal content from parts"); + + let extension = self.host.generate_vote_extension(height, round); + + let block_hash = { + let mut block_hasher = sha3::Keccak256::new(); + for part in parts { + if part.as_init().is_some() || part.as_fin().is_some() { + // NOTE: We do not hash over Init, so restreaming returns the same hash + // NOTE: We do not hash over Fin, because Fin includes a signature over the block hash + // TODO: we should probably still include height + continue; + } + + block_hasher.update(part.to_sign_bytes()); + } + + BlockHash::new(block_hasher.finalize().into()) + }; + + trace!(%block_hash, "Computed block hash"); + + let proposal_hash = compute_proposal_hash(init, &block_hash); + + let validity = self + .verify_proposal_validity(init, &proposal_hash, &fin.signature) + .await?; + + Some(( + valid_round, + block_hash, + init.proposer.clone(), + validity, + extension, + )) + } + + async fn verify_proposal_validity( + &self, + init: &ProposalInit, + proposal_hash: &Hash, + signature: &Signature, + ) -> Option { + let validators = self.host.validators(init.height).await?; + + let public_key = validators + .iter() + .find(|v| v.address == init.proposer) + .map(|v| v.public_key); + + let Some(public_key) = public_key else { + error!(proposer = %init.proposer, "No validator found for the proposer"); + return None; + }; + + let valid = public_key.verify(&proposal_hash.as_felt(), signature); + Some(Validity::from_bool(valid)) + } + + #[tracing::instrument(skip_all, fields( + part.height = %height, + part.round = %round, + part.message = ?part.part_type(), + ))] + pub async fn build_value_from_part( + &mut self, + height: Height, + round: Round, + part: ProposalPart, + ) -> Option> { + self.host.part_store.store(height, round, part.clone()); + + if let ProposalPart::Transactions(_txes) = &part { + debug!("Simulating tx execution and proof verification"); + + // Simulate Tx execution and proof verification (assumes success) + // TODO: Add config knob for invalid blocks + let num_txes = part.tx_count() as u32; + let exec_time = self.host.params.exec_time_per_tx * num_txes; + tokio::time::sleep(exec_time).await; + + trace!("Simulation took {exec_time:?} to execute {num_txes} txes"); + } + + let parts = self.host.part_store.all_parts(height, round); + + trace!( + count = self.host.part_store.blocks_count(), + "Blocks for which we have parts" + ); + + // TODO: Do more validations, e.g. there is no higher tx proposal part, + // check that we have received the proof, etc. + let Some(_fin) = parts.iter().find_map(|part| part.as_fin()) else { + debug!("Final proposal part has not been received yet"); + return None; + }; + + let block_size: usize = parts.iter().map(|p| p.size_bytes()).sum(); + let tx_count: usize = parts.iter().map(|p| p.tx_count()).sum(); + + debug!( + tx.count = %tx_count, block.size = %block_size, parts.count = %parts.len(), + "All parts have been received already, building value" + ); + + let result = self.build_value_from_parts(&parts, height, round).await; + + if let Some(ref proposed_value) = result { + self.host + .part_store + .store_value_id(height, round, proposed_value.value); + } + + result + } +} diff --git a/code/crates/starknet/host/src/lib.rs b/code/crates/starknet/host/src/lib.rs index 28ca6d439..10db6863b 100644 --- a/code/crates/starknet/host/src/lib.rs +++ b/code/crates/starknet/host/src/lib.rs @@ -2,14 +2,11 @@ #![allow(unexpected_cfgs)] #![cfg_attr(coverage_nightly, feature(coverage_attribute))] -mod host; -pub use host::Host; - pub mod actor; pub mod block_store; pub mod codec; +pub mod host; pub mod mempool; -pub mod mock; pub mod node; pub mod part_store; pub mod spawn; diff --git a/code/crates/starknet/host/src/mock/mod.rs b/code/crates/starknet/host/src/mock/mod.rs deleted file mode 100644 index 5361e40d0..000000000 --- a/code/crates/starknet/host/src/mock/mod.rs +++ /dev/null @@ -1 +0,0 @@ -pub mod host; diff --git a/code/crates/starknet/host/src/spawn.rs b/code/crates/starknet/host/src/spawn.rs index dcb99c02d..23545849d 100644 --- a/code/crates/starknet/host/src/spawn.rs +++ b/code/crates/starknet/host/src/spawn.rs @@ -25,10 +25,10 @@ use malachite_gossip_mempool::Config as GossipMempoolConfig; use malachite_metrics::Metrics; use malachite_metrics::SharedRegistry; -use crate::actor::StarknetHost; +use crate::actor::Host; use crate::codec::ProtobufCodec; +use crate::host::{StarknetHost, StarknetParams}; use crate::mempool::{Mempool, MempoolRef}; -use crate::mock::host::{MockHost, MockParams}; use crate::types::MockContext; use crate::types::{Address, Height, PrivateKey, ValidatorSet}; @@ -294,7 +294,7 @@ async fn spawn_host_actor( malachite_config::ValuePayload::ProposalAndParts => ValuePayload::ProposalAndParts, }; - let mock_params = MockParams { + let mock_params = StarknetParams { value_payload, max_block_size: cfg.consensus.max_block_size, tx_size: cfg.test.tx_size, @@ -305,7 +305,7 @@ async fn spawn_host_actor( vote_extensions: cfg.test.vote_extensions, }; - let mock_host = MockHost::new( + let mock_host = StarknetHost::new( mock_params, mempool.clone(), address.clone(), @@ -313,7 +313,7 @@ async fn spawn_host_actor( initial_validator_set.clone(), ); - StarknetHost::spawn( + Host::spawn( home_dir.to_owned(), mock_host, mempool, diff --git a/code/crates/starknet/host/src/streaming.rs b/code/crates/starknet/host/src/streaming.rs index b5dad7775..21660048c 100644 --- a/code/crates/starknet/host/src/streaming.rs +++ b/code/crates/starknet/host/src/streaming.rs @@ -5,7 +5,7 @@ use derive_where::derive_where; use malachite_actors::util::streaming::{Sequence, StreamId, StreamMessage}; use malachite_common::Round; -use malachite_gossip_mempool::PeerId; +use malachite_consensus::PeerId; use crate::types::{Address, Height, ProposalInit, ProposalPart}; diff --git a/code/crates/starknet/test/tests/wal.rs b/code/crates/starknet/test/tests/wal.rs index 4a3a2b57b..d26af8008 100644 --- a/code/crates/starknet/test/tests/wal.rs +++ b/code/crates/starknet/test/tests/wal.rs @@ -11,7 +11,6 @@ use malachite_starknet_host::types::MockContext; use malachite_starknet_test::{init_logging, HandlerResult, TestBuilder, TestParams}; #[tokio::test] -#[ignore] // Test fails on CI but passes locally async fn proposer_crashes_after_proposing_parts_only() { proposer_crashes_after_proposing(TestParams { value_payload: ValuePayload::PartsOnly, diff --git a/code/crates/test/Cargo.toml b/code/crates/test/Cargo.toml index 78f979fd9..509e07415 100644 --- a/code/crates/test/Cargo.toml +++ b/code/crates/test/Cargo.toml @@ -10,7 +10,11 @@ license.workspace = true rust-version.workspace = true [dependencies] +malachite-actors = { workspace = true } +malachite-blocksync = { workspace = true } +malachite-codec = { workspace = true } malachite-common = { workspace = true } +malachite-consensus = { workspace = true } malachite-proto = { workspace = true } malachite-signing-ed25519 = { workspace = true, features = ["rand", "serde"] } @@ -21,7 +25,8 @@ hex = { workspace = true } prost = { workspace = true } prost-types = { workspace = true } rand = { workspace = true } -serde = { workspace = true, features = ["derive"] } +serde = { workspace = true, features = ["derive", "rc"] } +serde_json = { workspace = true } sha3 = { workspace = true } signature = { workspace = true } diff --git a/code/crates/test/src/codec/mod.rs b/code/crates/test/src/codec/mod.rs new file mode 100644 index 000000000..61fafb4f6 --- /dev/null +++ b/code/crates/test/src/codec/mod.rs @@ -0,0 +1,2 @@ +pub mod testcodec; +pub(crate) mod types; diff --git a/code/crates/test/src/codec/testcodec.rs b/code/crates/test/src/codec/testcodec.rs new file mode 100644 index 000000000..da5b59d8b --- /dev/null +++ b/code/crates/test/src/codec/testcodec.rs @@ -0,0 +1,84 @@ +use bytes::Bytes; +use malachite_codec::Codec; + +use crate::codec::types::{ + RawRequest, RawResponse, RawSignedConsensusMsg, RawStatus, RawStreamMessage, +}; +use crate::{ProposalPart, TestContext}; +use malachite_actors::util::streaming::StreamMessage; +use malachite_blocksync::{Request, Response, Status}; +use malachite_consensus::SignedConsensusMsg; + +pub struct TestCodec; + +impl Codec for TestCodec { + type Error = serde_json::Error; + + fn decode(&self, bytes: Bytes) -> Result { + serde_json::from_slice(&bytes) + } + + fn encode(&self, msg: &ProposalPart) -> Result { + serde_json::to_vec(&msg).map(Bytes::from) + } +} + +impl Codec> for TestCodec { + type Error = serde_json::Error; + + fn decode(&self, bytes: Bytes) -> Result, Self::Error> { + serde_json::from_slice::(&bytes).map(Into::into) + } + + fn encode(&self, msg: &SignedConsensusMsg) -> Result { + serde_json::to_vec(&RawSignedConsensusMsg::from(msg.clone())).map(Bytes::from) + } +} + +impl Codec> for TestCodec { + type Error = serde_json::Error; + + fn decode(&self, bytes: Bytes) -> Result, Self::Error> { + serde_json::from_slice::(&bytes).map(Into::into) + } + + fn encode(&self, msg: &StreamMessage) -> Result { + serde_json::to_vec(&RawStreamMessage::from(msg.clone())).map(Bytes::from) + } +} + +impl Codec> for TestCodec { + type Error = serde_json::Error; + + fn decode(&self, bytes: Bytes) -> Result, Self::Error> { + serde_json::from_slice::(&bytes).map(Into::into) + } + + fn encode(&self, msg: &Status) -> Result { + serde_json::to_vec(&RawStatus::from(msg.clone())).map(Bytes::from) + } +} + +impl Codec> for TestCodec { + type Error = serde_json::Error; + + fn decode(&self, bytes: Bytes) -> Result, Self::Error> { + serde_json::from_slice::(&bytes).map(Into::into) + } + + fn encode(&self, msg: &Request) -> Result { + serde_json::to_vec(&RawRequest::from(msg.clone())).map(Bytes::from) + } +} + +impl Codec> for TestCodec { + type Error = serde_json::Error; + + fn decode(&self, bytes: Bytes) -> Result, Self::Error> { + serde_json::from_slice::(&bytes).map(Into::into) + } + + fn encode(&self, msg: &Response) -> Result { + serde_json::to_vec(&RawResponse::from(msg.clone())).map(Bytes::from) + } +} diff --git a/code/crates/test/src/codec/types.rs b/code/crates/test/src/codec/types.rs new file mode 100644 index 000000000..5c1ec2ba9 --- /dev/null +++ b/code/crates/test/src/codec/types.rs @@ -0,0 +1,255 @@ +use crate::{Address, Height, Proposal, ProposalPart, RoundDef, TestContext, ValueId, Vote}; +use bytes::Bytes; +use ed25519_consensus::Signature; +use malachite_actors::util::streaming::{StreamContent, StreamMessage}; +use malachite_blocksync::{PeerId, Request, Response, Status, SyncedBlock}; +use malachite_common::{ + AggregatedSignature, CommitCertificate, CommitSignature, Extension, Round, SignedExtension, + SignedProposal, SignedVote, +}; +use malachite_consensus::SignedConsensusMsg; +use malachite_proto::Protobuf; +use serde::{Deserialize, Serialize}; + +#[derive(Serialize, Deserialize)] +pub struct RawSignedMessage { + message: Bytes, + signature: Signature, +} + +#[derive(Serialize, Deserialize)] +pub enum RawSignedConsensusMsg { + Vote(RawSignedMessage), + Proposal(RawSignedMessage), +} + +impl From> for RawSignedConsensusMsg { + fn from(value: SignedConsensusMsg) -> Self { + match value { + SignedConsensusMsg::Vote(vote) => Self::Vote(RawSignedMessage { + message: vote.message.to_bytes(), + signature: *vote.signature.inner(), + }), + SignedConsensusMsg::Proposal(proposal) => Self::Proposal(RawSignedMessage { + message: proposal.message.to_bytes(), + signature: *proposal.signature.inner(), + }), + } + } +} + +impl From for SignedConsensusMsg { + fn from(value: RawSignedConsensusMsg) -> Self { + match value { + RawSignedConsensusMsg::Vote(vote) => SignedConsensusMsg::Vote(SignedVote { + message: Vote::from_bytes(&vote.message).unwrap(), + signature: vote.signature.into(), + }), + RawSignedConsensusMsg::Proposal(proposal) => { + SignedConsensusMsg::Proposal(SignedProposal { + message: Proposal::from_bytes(&proposal.message).unwrap(), + signature: proposal.signature.into(), + }) + } + } + } +} + +#[derive(Serialize, Deserialize)] +pub struct RawStreamMessage { + pub stream_id: u64, + pub sequence: u64, + pub content: RawStreamContent, +} + +#[derive(Serialize, Deserialize)] +pub enum RawStreamContent { + Data(ProposalPart), + Fin(bool), +} + +impl From> for RawStreamMessage { + fn from(value: StreamMessage) -> Self { + Self { + stream_id: value.stream_id, + sequence: value.sequence, + content: match value.content { + StreamContent::Data(proposal_part) => RawStreamContent::Data(proposal_part), + StreamContent::Fin(fin) => RawStreamContent::Fin(fin), + }, + } + } +} + +impl From for StreamMessage { + fn from(value: RawStreamMessage) -> Self { + Self { + stream_id: value.stream_id, + sequence: value.sequence, + content: match value.content { + RawStreamContent::Data(proposal_part) => StreamContent::Data(proposal_part), + RawStreamContent::Fin(fin) => StreamContent::Fin(fin), + }, + } + } +} + +#[derive(Serialize, Deserialize)] +pub struct RawStatus { + pub peer_id: Vec, + pub height: Height, + pub earliest_block_height: Height, +} + +impl From> for RawStatus { + fn from(value: Status) -> Self { + Self { + peer_id: value.peer_id.to_bytes(), + height: value.height, + earliest_block_height: value.earliest_block_height, + } + } +} + +impl From for Status { + fn from(value: RawStatus) -> Self { + Self { + peer_id: PeerId::from_bytes(&value.peer_id).unwrap(), + height: value.height, + earliest_block_height: value.earliest_block_height, + } + } +} + +#[derive(Serialize, Deserialize)] +pub struct RawRequest { + pub height: Height, +} + +impl From> for RawRequest { + fn from(value: Request) -> Self { + Self { + height: value.height, + } + } +} + +impl From for Request { + fn from(value: RawRequest) -> Self { + Self { + height: value.height, + } + } +} + +#[derive(Serialize, Deserialize)] +pub struct RawExtension { + pub data: Bytes, +} + +#[derive(Serialize, Deserialize)] +pub struct RawSignedExtension { + pub extension: RawExtension, + pub signature: Signature, +} + +#[derive(Serialize, Deserialize)] +pub struct RawCommitSignature { + pub address: Address, + pub signature: Signature, + pub extension: Option, +} + +#[derive(Serialize, Deserialize)] +pub struct RawAggregatedSignature { + pub signatures: Vec, +} + +#[derive(Serialize, Deserialize)] +pub struct RawCommitCertificate { + pub height: Height, + #[serde(with = "RoundDef")] + pub round: Round, + pub value_id: ValueId, + pub aggregated_signature: RawAggregatedSignature, +} + +#[derive(Serialize, Deserialize)] +pub struct RawSyncedBlock { + pub block_bytes: Bytes, + pub certificate: RawCommitCertificate, +} + +#[derive(Serialize, Deserialize)] +pub struct RawResponse { + pub height: Height, + pub block: Option, +} + +impl From> for RawResponse { + fn from(value: Response) -> Self { + Self { + height: value.height, + block: value.block.map(|block| RawSyncedBlock { + block_bytes: block.block_bytes, + certificate: RawCommitCertificate { + height: block.certificate.height, + round: block.certificate.round, + value_id: block.certificate.value_id, + aggregated_signature: RawAggregatedSignature { + signatures: block + .certificate + .aggregated_signature + .signatures + .iter() + .map(|sig| RawCommitSignature { + address: sig.address, + signature: *sig.signature.inner(), + extension: sig.extension.as_ref().map(|ext| RawSignedExtension { + extension: RawExtension { + data: ext.message.data.clone(), + }, + signature: *ext.signature.inner(), + }), + }) + .collect(), + }, + }, + }), + } + } +} + +impl From for Response { + fn from(value: RawResponse) -> Self { + Self { + height: value.height, + block: value.block.map(|block| SyncedBlock { + block_bytes: block.block_bytes, + certificate: CommitCertificate { + height: block.certificate.height, + round: block.certificate.round, + value_id: block.certificate.value_id, + aggregated_signature: AggregatedSignature { + signatures: block + .certificate + .aggregated_signature + .signatures + .iter() + .map(|sig| CommitSignature { + address: sig.address, + signature: sig.signature.into(), + extension: sig.extension.as_ref().map(|ext| SignedExtension { + message: Extension { + data: ext.extension.data.clone(), + }, + signature: ext.signature.into(), + }), + }) + .collect(), + }, + }, + }), + } + } +} diff --git a/code/crates/test/src/height.rs b/code/crates/test/src/height.rs index 832501dd0..17f0a7759 100644 --- a/code/crates/test/src/height.rs +++ b/code/crates/test/src/height.rs @@ -1,11 +1,11 @@ use core::fmt; - use malachite_proto::{Error as ProtoError, Protobuf}; +use serde::{Deserialize, Serialize}; use crate::proto; /// A blockchain height -#[derive(Copy, Clone, Default, PartialEq, Eq, PartialOrd, Ord, Hash)] +#[derive(Copy, Clone, Default, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)] pub struct Height(u64); impl Height { diff --git a/code/crates/test/src/lib.rs b/code/crates/test/src/lib.rs index e8439a39b..a2a0aa0dd 100644 --- a/code/crates/test/src/lib.rs +++ b/code/crates/test/src/lib.rs @@ -5,6 +5,7 @@ #![cfg_attr(coverage_nightly, feature(coverage_attribute))] mod address; +mod codec; mod context; mod height; mod proposal; @@ -19,6 +20,7 @@ pub mod proto; pub mod utils; pub use crate::address::*; +pub use crate::codec::testcodec::*; pub use crate::context::*; pub use crate::height::*; pub use crate::proposal::*; diff --git a/code/crates/test/src/proposal_part.rs b/code/crates/test/src/proposal_part.rs index 50e138e50..e745e08fb 100644 --- a/code/crates/test/src/proposal_part.rs +++ b/code/crates/test/src/proposal_part.rs @@ -3,10 +3,11 @@ use std::sync::Arc; use bytes::Bytes; use malachite_common::Round; use malachite_proto::{Error as ProtoError, Protobuf}; +use serde::{Deserialize, Serialize}; use crate::{Address, Height, TestContext, Value}; -#[derive(Clone, Debug, PartialEq, Eq)] +#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] pub struct BlockMetadata { proof: Vec, value: Value, @@ -54,7 +55,7 @@ impl Protobuf for BlockMetadata { } } -#[derive(Clone, Debug, PartialEq, Eq)] +#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] pub struct Content { metadata: BlockMetadata, } @@ -87,10 +88,21 @@ impl Protobuf for Content { } } +#[derive(Serialize, Deserialize)] +#[serde(remote = "Round")] +pub enum RoundDef { + /// No round, ie. `-1` + Nil, + + /// Some round `r` where `r >= 0` + Some(u32), +} + /// A part of a value for a height, round. Identified in this scope by the sequence. -#[derive(Clone, Debug, PartialEq, Eq)] +#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] pub struct ProposalPart { pub height: Height, + #[serde(with = "RoundDef")] pub round: Round, pub sequence: u64, pub content: Arc, diff --git a/code/crates/test/src/value.rs b/code/crates/test/src/value.rs index 99644bea7..f05947eb6 100644 --- a/code/crates/test/src/value.rs +++ b/code/crates/test/src/value.rs @@ -1,10 +1,10 @@ use core::fmt; - use malachite_proto::{Error as ProtoError, Protobuf}; +use serde::{Deserialize, Serialize}; use crate::proto; -#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Copy)] +#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Copy, Serialize, Deserialize)] pub struct ValueId(u64); impl ValueId { @@ -58,7 +58,7 @@ impl Protobuf for ValueId { } /// The value to decide on -#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord)] +#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)] pub struct Value(u64); impl Value {