diff --git a/code/Cargo.lock b/code/Cargo.lock index c82430b71..b6aac50c2 100644 --- a/code/Cargo.lock +++ b/code/Cargo.lock @@ -4,19 +4,13 @@ version = 4 [[package]] name = "addr2line" -version = "0.21.0" +version = "0.24.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb" +checksum = "dfbe277e56a376000877090da837660b4427aad530e3028d44e0bffe4f89a1c1" dependencies = [ "gimli", ] -[[package]] -name = "adler" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" - [[package]] name = "adler2" version = "2.0.0" @@ -70,14 +64,14 @@ dependencies = [ [[package]] name = "ahash" -version = "0.8.11" +version = "0.8.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011" +checksum = "5a15f179cd60c4584b8a8c596927aadc462e27f2ca70c04e0071964a73ba7a75" dependencies = [ "cfg-if", "once_cell", "version_check", - "zerocopy 0.7.35", + "zerocopy", ] [[package]] @@ -157,20 +151,20 @@ dependencies = [ [[package]] name = "anstyle-wincon" -version = "3.0.7" +version = "3.0.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca3534e77181a9cc07539ad51f2141fe32f6c3ffd4df76db8ad92346b003ae4e" +checksum = "6680de5231bd6ee4c6191b8a1325daa282b415391ec9d3a37bd34f2060dc73fa" dependencies = [ "anstyle", - "once_cell", + "once_cell_polyfill", "windows-sys 0.59.0", ] [[package]] name = "anyhow" -version = "1.0.97" +version = "1.0.98" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dcfed56ad506cb2c684a14971b8861fdc3baaaae314b9e5f9bb532cbe3ba7a4f" +checksum = "e16d2d3311acee920a9eb8d33b8cbc1787ce4a264e85f964c2404b969bdcd487" [[package]] name = "arrayref" @@ -231,9 +225,9 @@ dependencies = [ [[package]] name = "async-io" -version = "2.4.0" +version = "2.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43a2b323ccce0a1d90b449fd71f2a06ca7faa7c54c2751f06c9bd851fc061059" +checksum = "1237c0ae75a0f3765f58910ff9cdd0a12eeb39ab2f4c7de23262f337f0aacbb3" dependencies = [ "async-lock", "cfg-if", @@ -242,7 +236,7 @@ dependencies = [ "futures-lite", "parking", "polling", - "rustix 0.38.44", + "rustix", "slab", "tracing", "windows-sys 0.59.0", @@ -374,17 +368,17 @@ dependencies = [ [[package]] name = "backtrace" -version = "0.3.71" +version = "0.3.75" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26b05800d2e817c8b3b4b54abd461726265fa9789ae34330622f2db9ee696f9d" +checksum = "6806a6321ec58106fea15becdad98371e28d92ccbc7c8f1b3b6dd724fe8f1002" dependencies = [ "addr2line", - "cc", "cfg-if", "libc", - "miniz_oxide 0.7.4", + "miniz_oxide", "object", "rustc-demangle", + "windows-targets 0.52.6", ] [[package]] @@ -419,9 +413,9 @@ checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" [[package]] name = "base64ct" -version = "1.7.1" +version = "1.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb97d56060ee67d285efb8001fec9d2a4c710c32efd2e14b5cbb5ba71930fc2d" +checksum = "89e25b6adfb930f02d1981565a6e5d9c547ac15a96606256d3b59040e5cd4ca3" [[package]] name = "bitflags" @@ -431,9 +425,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.9.0" +version = "2.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c8214115b7bf84099f1309324e63141d4c5d7cc26862f97a0a857dbefe165bd" +checksum = "1b8e56985ec62d17e9c1001dc89c88ecd7dc08e47eba5ec7c29c7b5eeecde967" [[package]] name = "blake2" @@ -517,9 +511,9 @@ dependencies = [ [[package]] name = "bytesize" -version = "1.3.2" +version = "1.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d2c12f985c78475a6b8d629afd0c360260ef34cfef52efccdcfd31972f81c2e" +checksum = "2e93abca9e28e0a1b9877922aacb20576e05d4679ffa78c3d6dc22a26a216659" dependencies = [ "serde", ] @@ -572,9 +566,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.2.16" +version = "1.2.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be714c154be609ec7f5dad223a33bf1482fff90472de28f7362806e6d4832b8c" +checksum = "16595d3be041c03b09d08d0858631facccee9221e579704070e6e9e4915d3bc7" dependencies = [ "shlex", ] @@ -617,9 +611,9 @@ dependencies = [ [[package]] name = "chrono" -version = "0.4.40" +version = "0.4.41" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a7964611d71df112cb1730f2ee67324fcf4d0fc6606acbbe9bfe06df124637c" +checksum = "c469d952047f47f91b68d1cba3f10d63c11d73e4636f24f08daf0278abf01c4d" dependencies = [ "android-tzdata", "iana-time-zone", @@ -668,9 +662,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.5.37" +version = "4.5.39" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eccb054f56cbd38340b380d4a8e69ef1f02f1af43db2f0cc817a4774d80ae071" +checksum = "fd60e63e9be68e5fb56422e397cf9baddded06dae1d2e523401542383bc72a9f" dependencies = [ "clap_builder", "clap_derive", @@ -678,9 +672,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.37" +version = "4.5.39" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "efd9466fac8543255d3b1fcad4762c5e116ffe808c8a3043d4263cd4fd4862a2" +checksum = "89cc6392a1f72bbeb820d71f32108f61fdaf18bc526e1d23954168a67759ef51" dependencies = [ "anstream", "anstyle", @@ -708,9 +702,9 @@ checksum = "f46ad14479a25103f283c0f10005961cf086d8dc42205bb44c46ac563475dca6" [[package]] name = "color-eyre" -version = "0.6.3" +version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "55146f5e46f237f7423d74111267d4597b59b0dad0ffaf7303bce9945d843ad5" +checksum = "e6e1761c0e16f8883bbbb8ce5990867f4f06bf11a0253da6495a04ce4b6ef0ec" dependencies = [ "backtrace", "color-spantrace", @@ -723,9 +717,9 @@ dependencies = [ [[package]] name = "color-spantrace" -version = "0.2.1" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd6be1b2a7e382e2b98b43b2adcca6bb0e465af0bdd38123873ae61eb17a72c2" +checksum = "2ddd8d5bfda1e11a501d0a7303f3bfed9aa632ebdb859be40d0fd70478ed70d5" dependencies = [ "once_cell", "owo-colors", @@ -959,9 +953,9 @@ dependencies = [ [[package]] name = "darling" -version = "0.20.10" +version = "0.20.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f63b86c8a8826a49b8c21f08a2d07338eec8d900540f8630dc76284be802989" +checksum = "fc7f46116c46ff9ab3eb1597a45688b6715c6e628b5c133e288e709a29bcb4ee" dependencies = [ "darling_core", "darling_macro", @@ -969,9 +963,9 @@ dependencies = [ [[package]] name = "darling_core" -version = "0.20.10" +version = "0.20.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95133861a8032aaea082871032f5815eb9e98cef03fa916ab4500513994df9e5" +checksum = "0d00b9596d185e565c2207a0b01f8bd1a135483d02d9b7b0a54b11da8d53412e" dependencies = [ "fnv", "ident_case", @@ -983,9 +977,9 @@ dependencies = [ [[package]] name = "darling_macro" -version = "0.20.10" +version = "0.20.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d336a2a514f6ccccaa3e09b02d41d35330c07ddf03a62165fcec10bb561c7806" +checksum = "fc34b93ccb385b40dc71c6fceac4b2ad23662c7eeb248cf10d529b7e055b6ead" dependencies = [ "darling_core", "quote", @@ -1008,15 +1002,15 @@ dependencies = [ [[package]] name = "data-encoding" -version = "2.8.0" +version = "2.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "575f75dfd25738df5b91b8e43e14d44bda14637a58fae779fd2b064f8bf3e010" +checksum = "2a2330da5de22e8a3cb63252ce2abb30116bf5265e89c0e01bc17015ce30a476" [[package]] name = "data-encoding-macro" -version = "0.1.17" +version = "0.1.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f9724adfcf41f45bf652b3995837669d73c4d49a1b5ac1ff82905ac7d9b5558" +checksum = "47ce6c96ea0102f01122a185683611bd5ac8d99e62bc59dd12e6bda344ee673d" dependencies = [ "data-encoding", "data-encoding-macro-internal", @@ -1024,9 +1018,9 @@ dependencies = [ [[package]] name = "data-encoding-macro-internal" -version = "0.1.15" +version = "0.1.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "18e4fdb82bd54a12e42fb58a800dcae6b9e13982238ce2296dc3570b92148e1f" +checksum = "8d162beedaa69905488a8da94f5ac3edb4dd4788b732fadb7bd120b2625c1976" dependencies = [ "data-encoding", "syn", @@ -1034,9 +1028,9 @@ dependencies = [ [[package]] name = "der" -version = "0.7.9" +version = "0.7.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f55bf8e7b65898637379c1b74eb1551107c8294ed26d855ceb9fd1a09cfc9bc0" +checksum = "e7c1832837b905bbfb5101e07cc24c8deddf52f93225eee6ead5f4d63d53ddcb" dependencies = [ "const-oid", "pem-rfc7468", @@ -1059,9 +1053,9 @@ dependencies = [ [[package]] name = "deranged" -version = "0.3.11" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b42b6fa04a440b495c8b04d0e71b707c585f83cb9cb28cf8cd0d976c315e31b4" +checksum = "9c9e6a11ca8224451684bc0d7d5a7adbf8f2fd6887261a1cfc3c0432f9d4068e" dependencies = [ "powerfmt", "serde", @@ -1192,7 +1186,7 @@ dependencies = [ "ed25519", "rand_core 0.6.4", "serde", - "sha2 0.10.8", + "sha2 0.10.9", "subtle", "zeroize", ] @@ -1243,9 +1237,9 @@ checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" [[package]] name = "errno" -version = "0.3.10" +version = "0.3.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33d852cb9b869c2a9b3df2f71a3074817f01e1844f839a144f5fcef059a4eb5d" +checksum = "cea14ef9355e3beab063703aa9dab15afd25f0667c341310c1e5274bb1d0da18" dependencies = [ "libc", "windows-sys 0.59.0", @@ -1264,9 +1258,9 @@ dependencies = [ [[package]] name = "event-listener-strategy" -version = "0.5.3" +version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c3e4e0dd3673c1139bf041f3008816d9cf2946bbfac2945c09e523b8d7b05b2" +checksum = "8be9f3dfaaffdae2972880079a491a1a8bb7cbed0b8dd7a347f668b4150a3b93" dependencies = [ "event-listener", "pin-project-lite", @@ -1312,12 +1306,12 @@ checksum = "1d674e81391d1e1ab681a28d99df07927c6d4aa5b027d7da16ba32d1d21ecd99" [[package]] name = "flate2" -version = "1.1.0" +version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11faaf5a5236997af9848be0bef4db95824b1d534ebc64d0f0c6cf3e67bd38dc" +checksum = "7ced92e76e966ca2fd84c8f7aa01a4aea65b0eb6648d72f7c8f3e2764a67fece" dependencies = [ "crc32fast", - "miniz_oxide 0.8.5", + "miniz_oxide", ] [[package]] @@ -1328,9 +1322,9 @@ checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" [[package]] name = "foldhash" -version = "0.1.4" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a0d2fde1f7b3d48b8395d5f2de76c18a528bd6a9cdde438df747bfcba3e05d6f" +checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2" [[package]] name = "form_urlencoded" @@ -1485,15 +1479,16 @@ checksum = "0b32dfe1fdfc0bbde1f22a5da25355514b5e450c33a6af6770884c8750aedfbc" [[package]] name = "generator" -version = "0.8.4" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc6bd114ceda131d3b1d665eba35788690ad37f5916457286b32ab6fd3c438dd" +checksum = "d18470a76cb7f8ff746cf1f7470914f900252ec36bbc40b569d74b1258446827" dependencies = [ + "cc", "cfg-if", "libc", "log", "rustversion", - "windows 0.58.0", + "windows 0.61.1", ] [[package]] @@ -1509,9 +1504,9 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.15" +version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" +checksum = "335ff9f135e4384c8150d6f27c6daed433577f86b4750418338c01a1a2528592" dependencies = [ "cfg-if", "js-sys", @@ -1522,14 +1517,16 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.3.1" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43a49c392881ce6d5c3b8cb70f98717b7c07aabbdff06687b9030dbfbe2725f8" +checksum = "26145e563e54f2cadc477553f1ec5ee650b00862f0a58bcd12cbdc5f0ea2d2f4" dependencies = [ "cfg-if", + "js-sys", "libc", - "wasi 0.13.3+wasi-0.2.2", - "windows-targets 0.52.6", + "r-efi", + "wasi 0.14.2+wasi-0.2.4", + "wasm-bindgen", ] [[package]] @@ -1544,9 +1541,9 @@ dependencies = [ [[package]] name = "gimli" -version = "0.28.1" +version = "0.31.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" +checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f" [[package]] name = "glob" @@ -1567,9 +1564,9 @@ dependencies = [ [[package]] name = "h2" -version = "0.4.8" +version = "0.4.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5017294ff4bb30944501348f6f8e42e6ad28f42c8bbef7a74029aff064a4e3c2" +checksum = "a9421a676d1b147b16b82c9225157dc629087ef8ec4d5e2960f9437a90dac0a5" dependencies = [ "atomic-waker", "bytes", @@ -1577,7 +1574,7 @@ dependencies = [ "futures-core", "futures-sink", "http 1.3.1", - "indexmap 2.8.0", + "indexmap 2.9.0", "slab", "tokio", "tokio-util", @@ -1586,9 +1583,9 @@ dependencies = [ [[package]] name = "half" -version = "2.4.1" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6dd08c532ae367adf81c312a4580bc67f1d0fe8bc9c460520283f4c0ff277888" +checksum = "459196ed295495a68f7d7fe1d84f6c4b7ff0e21fe3017b2f283c6fac3ad803c9" dependencies = [ "cfg-if", "crunchy", @@ -1611,9 +1608,9 @@ dependencies = [ [[package]] name = "hashbrown" -version = "0.15.2" +version = "0.15.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289" +checksum = "84b26c544d002229e640969970a2e74021aadf6e2f96372b9c58eff97de08eb3" dependencies = [ "allocator-api2", "equivalent", @@ -1643,15 +1640,9 @@ checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" [[package]] name = "hermit-abi" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fbf6a919d6cf397374f7dfeeea91d974c7c0a7221d0d0f4f20d859d329e53fcc" - -[[package]] -name = "hermit-abi" -version = "0.5.0" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fbd780fe5cc30f81464441920d82ac8740e2e46b29a6fad543ddd075229ce37e" +checksum = "f154ce46856750ed433c8649605bf7ed2de3bc35fd9d2a9f30cddd873c80cb08" [[package]] name = "hex" @@ -1685,7 +1676,7 @@ dependencies = [ "idna", "ipnet", "once_cell", - "rand 0.9.0", + "rand 0.9.1", "socket2", "thiserror 2.0.12", "tinyvec", @@ -1707,7 +1698,7 @@ dependencies = [ "moka", "once_cell", "parking_lot", - "rand 0.9.0", + "rand 0.9.1", "resolv-conf", "smallvec", "thiserror 2.0.12", @@ -1733,17 +1724,6 @@ dependencies = [ "digest 0.10.7", ] -[[package]] -name = "hostname" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c731c3e10504cc8ed35cfe2f1db4c9274c3d35fa486e3b31df46f068ef3e867" -dependencies = [ - "libc", - "match_cfg", - "winapi", -] - [[package]] name = "http" version = "0.2.12" @@ -1840,16 +1820,18 @@ dependencies = [ [[package]] name = "hyper-util" -version = "0.1.10" +version = "0.1.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df2dcfbe0677734ab2f3ffa7fa7bfd4706bfdc1ef393f2ee30184aed67e631b4" +checksum = "b1c293b6b3d21eca78250dc7dbebd6b9210ec5530e038cbfe0661b5c47ab06e8" dependencies = [ "bytes", "futures-channel", + "futures-core", "futures-util", "http 1.3.1", "http-body", "hyper", + "libc", "pin-project-lite", "socket2", "tokio", @@ -1859,16 +1841,17 @@ dependencies = [ [[package]] name = "iana-time-zone" -version = "0.1.61" +version = "0.1.63" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "235e081f3925a06703c2d0117ea8b91f042756fd6e7a6e5d901e8ca1a996b220" +checksum = "b0c919e5debc312ad217002b8048a17b7d83f80703865bbfcfebb0458b0b27d8" dependencies = [ "android_system_properties", "core-foundation-sys", "iana-time-zone-haiku", "js-sys", + "log", "wasm-bindgen", - "windows-core 0.52.0", + "windows-core 0.61.2", ] [[package]] @@ -1882,21 +1865,22 @@ dependencies = [ [[package]] name = "icu_collections" -version = "1.5.0" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db2fa452206ebee18c4b5c2274dbf1de17008e874b4dc4f0aea9d01ca79e4526" +checksum = "200072f5d0e3614556f94a9930d5dc3e0662a652823904c3a75dc3b0af7fee47" dependencies = [ "displaydoc", + "potential_utf", "yoke", "zerofrom", "zerovec", ] [[package]] -name = "icu_locid" -version = "1.5.0" +name = "icu_locale_core" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13acbb8371917fc971be86fc8057c41a64b521c184808a698c02acc242dbf637" +checksum = "0cde2700ccaed3872079a65fb1a78f6c0a36c91570f28755dda67bc8f7d9f00a" dependencies = [ "displaydoc", "litemap", @@ -1905,31 +1889,11 @@ dependencies = [ "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" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19ce3e0da2ec68599d193c93d088142efd7f9c5d6fc9b803774855747dc6a84f" +checksum = "436880e8e18df4d7bbc06d58432329d6458cc84531f7ac5f024e93deadb37979" dependencies = [ "displaydoc", "icu_collections", @@ -1937,67 +1901,54 @@ dependencies = [ "icu_properties", "icu_provider", "smallvec", - "utf16_iter", - "utf8_iter", - "write16", "zerovec", ] [[package]] name = "icu_normalizer_data" -version = "1.5.0" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8cafbf7aa791e9b22bec55a167906f9e1215fd475cd22adfcf660e03e989516" +checksum = "00210d6893afc98edb752b664b8890f0ef174c8adbb8d0be9710fa66fbbf72d3" [[package]] name = "icu_properties" -version = "1.5.1" +version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93d6020766cfc6302c15dbbc9c8778c37e62c14427cb7f6e601d849e092aeef5" +checksum = "016c619c1eeb94efb86809b015c58f479963de65bdb6253345c1a1276f22e32b" dependencies = [ "displaydoc", "icu_collections", - "icu_locid_transform", + "icu_locale_core", "icu_properties_data", "icu_provider", - "tinystr", + "potential_utf", + "zerotrie", "zerovec", ] [[package]] name = "icu_properties_data" -version = "1.5.0" +version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67a8effbc3dd3e4ba1afa8ad918d5684b8868b3b26500753effea8d2eed19569" +checksum = "298459143998310acd25ffe6810ed544932242d3f07083eee1084d83a71bd632" [[package]] name = "icu_provider" -version = "1.5.0" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ed421c8a8ef78d3e2dbc98a973be2f3770cb42b606e3ab18d6237c4dfde68d9" +checksum = "03c80da27b5f4187909049ee2d72f276f0d9f99a42c306bd0131ecfe04d8e5af" dependencies = [ "displaydoc", - "icu_locid", - "icu_provider_macros", + "icu_locale_core", "stable_deref_trait", "tinystr", "writeable", "yoke", "zerofrom", + "zerotrie", "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", -] - [[package]] name = "ident_case" version = "1.0.1" @@ -2017,9 +1968,9 @@ dependencies = [ [[package]] name = "idna_adapter" -version = "1.2.0" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "daca1df1c957320b2cf139ac61e7bd64fed304c5040df000a745aa1de3b4ef71" +checksum = "3acae9609540aa318d1bc588455225fb2085b9ed0c4f6bd0d9d5bcd86f1a0344" dependencies = [ "icu_normalizer", "icu_properties", @@ -2098,12 +2049,12 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.8.0" +version = "2.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3954d50fe15b02142bf25d3b8bdadb634ec3948f103d04ffe3031bc8fe9d7058" +checksum = "cea70ddb795996207ad57735b50c5982d8844f38ba9ee5f1aedcfb708a2aa11e" dependencies = [ "equivalent", - "hashbrown 0.15.2", + "hashbrown 0.15.3", "serde", ] @@ -2440,6 +2391,7 @@ dependencies = [ "informalsystems-malachitebft-proto", "informalsystems-malachitebft-signing-ed25519", "informalsystems-malachitebft-starknet-p2p-proto", + "prost", "rand 0.8.5", "serde", "sha3", @@ -2709,7 +2661,7 @@ version = "0.4.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e04d7f318608d35d4b61ddd75cbdaee86b023ebe2bd5a66ee0915f0bf93095a9" dependencies = [ - "hermit-abi 0.5.0", + "hermit-abi 0.5.1", "libc", "windows-sys 0.59.0", ] @@ -2784,7 +2736,7 @@ checksum = "bbc2a4da0d9e52ccfe6306801a112e81a8fc0c76aa3e4449fefeda7fef72bb34" dependencies = [ "lambdaworks-math", "serde", - "sha2 0.10.8", + "sha2 0.10.9", "sha3", ] @@ -2806,9 +2758,9 @@ checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" [[package]] name = "libc" -version = "0.2.171" +version = "0.2.172" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c19937216e9d3aa9956d9bb8dfc0b0c8beb6058fc4f7a4dc4d850edf86a237d6" +checksum = "d750af042f7ef4f724306de029d18836c26c1765a54a6a3f094cbd23a7267ffa" [[package]] name = "libp2p" @@ -2820,7 +2772,7 @@ dependencies = [ "either", "futures", "futures-timer", - "getrandom 0.2.15", + "getrandom 0.2.16", "libp2p-allow-block-list", "libp2p-connection-limits", "libp2p-core", @@ -2924,7 +2876,7 @@ dependencies = [ "fnv", "futures", "futures-timer", - "getrandom 0.2.15", + "getrandom 0.2.16", "hashlink", "hex_fmt", "libp2p-core", @@ -2936,7 +2888,7 @@ dependencies = [ "rand 0.8.5", "regex", "serde", - "sha2 0.10.8", + "sha2 0.10.9", "tracing", "web-time", ] @@ -2977,7 +2929,7 @@ dependencies = [ "rand 0.8.5", "sec1", "serde", - "sha2 0.10.8", + "sha2 0.10.9", "thiserror 2.0.12", "tracing", "zeroize", @@ -3003,7 +2955,7 @@ dependencies = [ "quick-protobuf-codec", "rand 0.8.5", "serde", - "sha2 0.10.8", + "sha2 0.10.9", "smallvec", "thiserror 2.0.12", "tracing", @@ -3242,7 +3194,7 @@ dependencies = [ "thiserror 2.0.12", "tracing", "yamux 0.12.1", - "yamux 0.13.4", + "yamux 0.13.5", ] [[package]] @@ -3251,27 +3203,21 @@ version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d" dependencies = [ - "bitflags 2.9.0", + "bitflags 2.9.1", "libc", ] [[package]] name = "linux-raw-sys" -version = "0.4.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d26c52dbd32dccf2d10cac7725f8eae5296885fb5703b261f7d0a0739ec807ab" - -[[package]] -name = "linux-raw-sys" -version = "0.9.2" +version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6db9c683daf087dc577b7506e9695b3d556a9f3849903fa28186283afd6809e9" +checksum = "cd945864f07fe9f5371a27ad7b52a172b4b499999f1d97574c9fa68373937e12" [[package]] name = "litemap" -version = "0.7.5" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23fb14cb19457329c82206317a5663005a4d404783dc74f4252769b0d5f42856" +checksum = "241eaef5fd12c88705a01fc1066c48c4b36e0dd4377dcdc7ec3942cea7a69956" [[package]] name = "lock_api" @@ -3285,9 +3231,9 @@ dependencies = [ [[package]] name = "log" -version = "0.4.26" +version = "0.4.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30bde2b3dc3671ae49d8e2e9f044c7c005836e7a023ee57cffa25ab82764bb9e" +checksum = "13dc2df351e3202783a1fe0d44375f7295ffb4049267b0f3018346dc122a1d94" [[package]] name = "loom" @@ -3308,9 +3254,15 @@ version = "0.12.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "234cf4f4a04dc1f57e24b96cc0cd600cf2af460d4161ac5ecdd0af8e1f3b2a38" dependencies = [ - "hashbrown 0.15.2", + "hashbrown 0.15.3", ] +[[package]] +name = "lru-slab" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "112b39cec0b298b6c1999fee3e31427f74f676e4cb9879ed1a121b43661a4154" + [[package]] name = "lz4_flex" version = "0.11.3" @@ -3320,12 +3272,6 @@ dependencies = [ "twox-hash", ] -[[package]] -name = "match_cfg" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ffbee8634e0d45d258acb448e7eaab3fce7a0a467395d4d9f228e3c1f01fb2e4" - [[package]] name = "matchers" version = "0.1.0" @@ -3361,31 +3307,22 @@ checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" [[package]] name = "miniz_oxide" -version = "0.7.4" +version = "0.8.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8a240ddb74feaf34a79a7add65a741f3167852fba007066dcac1ca548d89c08" -dependencies = [ - "adler", -] - -[[package]] -name = "miniz_oxide" -version = "0.8.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e3e04debbb59698c15bacbb6d93584a8c0ca9cc3213cb423d31f760d8843ce5" +checksum = "3be647b768db090acb35d5ec5db2b0e1f1de11133ca123b9eacf5137868f892a" dependencies = [ "adler2", ] [[package]] name = "mio" -version = "1.0.3" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2886843bf800fba2e3377cff24abf6379b4c4d5c6681eaf9ea5b0d15090450bd" +checksum = "78bed444cc8a2160f01cbcf811ef18cac863ad68ae8ca62092e8db51d51c761c" dependencies = [ "libc", "wasi 0.11.0+wasi-snapshot-preview1", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -3450,9 +3387,9 @@ dependencies = [ [[package]] name = "multimap" -version = "0.10.0" +version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "defc4c55412d89136f966bbb339008b474350e5e6e78d2714439c386b3137a03" +checksum = "1d87ecb2933e8aeadb3e3a02b828fed80a7528047e68b4f424523a0981a3a084" [[package]] name = "multistream-select" @@ -3549,7 +3486,7 @@ version = "0.29.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "71e2746dc3a24dd78b3cfcb7be93368c6de9963d30f43a6a73998a9cf4b17b46" dependencies = [ - "bitflags 2.9.0", + "bitflags 2.9.1", "cfg-if", "cfg_aliases", "libc", @@ -3637,9 +3574,9 @@ dependencies = [ [[package]] name = "object" -version = "0.32.2" +version = "0.36.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a6a622008b6e321afc04970976f62ee297fdbaa6f95318ca343e3eebb9648441" +checksum = "62948e14d923ea95ea2c7c86c71013138b66525b86bdc08d2dcc262bdb497b87" dependencies = [ "memchr", ] @@ -3655,9 +3592,15 @@ dependencies = [ [[package]] name = "once_cell" -version = "1.21.0" +version = "1.21.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cde51589ab56b20a6f686b2c68f7a0bd6add753d697abf720d63f8db3ab7b1ad" +checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" + +[[package]] +name = "once_cell_polyfill" +version = "1.70.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4895175b425cb1f87721b59f0f286c2092bd4af812243672510e1ac53e2e0ad" [[package]] name = "oorandom" @@ -3685,9 +3628,9 @@ checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" [[package]] name = "owo-colors" -version = "3.5.0" +version = "4.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1b04fb49957986fdce4d6ee7a65027d55d4b6d2265e5848bbb507b58ccfdb6f" +checksum = "26995317201fa17f3656c36716aed4a7c81743a9634ac4c99c0eeda495db0cec" [[package]] name = "p256" @@ -3698,7 +3641,7 @@ dependencies = [ "ecdsa", "elliptic-curve", "primeorder", - "sha2 0.10.8", + "sha2 0.10.9", ] [[package]] @@ -3774,7 +3717,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3672b37090dbd86368a4145bc067582552b29c27377cad4e0a306c97f9bd7772" dependencies = [ "fixedbitset", - "indexmap 2.8.0", + "indexmap 2.9.0", ] [[package]] @@ -3849,15 +3792,15 @@ dependencies = [ [[package]] name = "polling" -version = "3.7.4" +version = "3.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a604568c3202727d1507653cb121dbd627a58684eb09a820fd746bee38b4442f" +checksum = "b53a684391ad002dd6a596ceb6c74fd004fdce75f4be2e3f615068abbea5fd50" dependencies = [ "cfg-if", "concurrent-queue", - "hermit-abi 0.4.0", + "hermit-abi 0.5.1", "pin-project-lite", - "rustix 0.38.44", + "rustix", "tracing", "windows-sys 0.59.0", ] @@ -3891,6 +3834,15 @@ version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "350e9b48cbc6b0e028b0473b114454c6316e57336ee184ceab6e53f72c178b3e" +[[package]] +name = "potential_utf" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5a7c30837279ca13e7c867e9e40053bc68740f988cb07f7ca6df43cc734b585" +dependencies = [ + "zerovec", +] + [[package]] name = "powerfmt" version = "0.2.0" @@ -3903,7 +3855,7 @@ version = "0.2.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9" dependencies = [ - "zerocopy 0.8.23", + "zerocopy", ] [[package]] @@ -3918,9 +3870,9 @@ dependencies = [ [[package]] name = "prettyplease" -version = "0.2.30" +version = "0.2.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1ccf34da56fc294e7d4ccf69a85992b7dfb826b7cf57bac6a70bba3494cc08a" +checksum = "664ec5419c51e34154eec046ebcba56312d5a2fc3b09a06da188e1ad21afadf6" dependencies = [ "proc-macro2", "syn", @@ -3937,9 +3889,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.94" +version = "1.0.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a31971752e70b8b2686d7e46ec17fb38dad4051d94024c88df49b667caea9c84" +checksum = "02b3e5e68a3a1a02aad3ec490a98007cbc13c37cbe84a3cd7b8e406d76e7f778" dependencies = [ "unicode-ident", ] @@ -4019,12 +3971,6 @@ dependencies = [ "prost", ] -[[package]] -name = "quick-error" -version = "1.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0" - [[package]] name = "quick-protobuf" version = "0.8.1" @@ -4049,11 +3995,12 @@ dependencies = [ [[package]] name = "quinn" -version = "0.11.6" +version = "0.11.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62e96808277ec6f97351a2380e6c25114bc9e67037775464979f3037c92d05ef" +checksum = "626214629cda6781b6dc1d316ba307189c85ba657213ce642d9c77670f8202c8" dependencies = [ "bytes", + "cfg_aliases", "futures-io", "pin-project-lite", "quinn-proto", @@ -4064,17 +4011,19 @@ dependencies = [ "thiserror 2.0.12", "tokio", "tracing", + "web-time", ] [[package]] name = "quinn-proto" -version = "0.11.9" +version = "0.11.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2fe5ef3495d7d2e377ff17b1a8ce2ee2ec2a18cde8b6ad6619d65d0701c135d" +checksum = "49df843a9161c85bb8aae55f101bc0bac8bcafd637a620d9122fd7e0b2f7422e" dependencies = [ "bytes", - "getrandom 0.2.15", - "rand 0.8.5", + "getrandom 0.3.3", + "lru-slab", + "rand 0.9.1", "ring", "rustc-hash", "rustls", @@ -4088,9 +4037,9 @@ dependencies = [ [[package]] name = "quinn-udp" -version = "0.5.10" +version = "0.5.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e46f3055866785f6b92bc6164b76be02ca8f2eb4b002c0354b28cf4c119e5944" +checksum = "ee4e529991f949c5e25755532370b8af5d114acae52326361d68d47af64aa842" dependencies = [ "cfg_aliases", "libc", @@ -4109,6 +4058,12 @@ dependencies = [ "proc-macro2", ] +[[package]] +name = "r-efi" +version = "5.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "74765f6d916ee2faa39bc8e68e4f3ed8949b48cccdac59983d287a7cb71ce9c5" + [[package]] name = "ractor" version = "0.14.7" @@ -4138,13 +4093,12 @@ dependencies = [ [[package]] name = "rand" -version = "0.9.0" +version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3779b94aeb87e8bd4e834cee3650289ee9e0d5677f976ecdb6d219e5f4f6cd94" +checksum = "9fbfd9d094a40bf3ae768db9361049ace4c0e04a4fd6b359518bd7b73a73dd97" dependencies = [ "rand_chacha 0.9.0", "rand_core 0.9.3", - "zerocopy 0.8.23", ] [[package]] @@ -4173,7 +4127,7 @@ version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" dependencies = [ - "getrandom 0.2.15", + "getrandom 0.2.16", ] [[package]] @@ -4182,7 +4136,7 @@ version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "99d9a13982dcf210057a8a78572b2217b667c3beacbf3a0d8b454f6f82837d38" dependencies = [ - "getrandom 0.3.1", + "getrandom 0.3.3", ] [[package]] @@ -4220,20 +4174,20 @@ dependencies = [ [[package]] name = "redb" -version = "2.5.0" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34bc6763177194266fc3773e2b2bb3693f7b02fdf461e285aa33202e3164b74e" +checksum = "cef6a6d3a65ea334d6cdfb31fa2525c20184b7aa7bd1ad1e2e37502610d4609f" dependencies = [ "libc", ] [[package]] name = "redox_syscall" -version = "0.5.10" +version = "0.5.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b8c0c260b63a8219631167be35e6a988e9554dbd323f8bd08439c8ed1302bd1" +checksum = "928fca9cf2aa042393a8325b9ead81d2f0df4cb12e1e24cef072922ccd99c5af" dependencies = [ - "bitflags 2.9.0", + "bitflags 2.9.1", ] [[package]] @@ -4242,7 +4196,7 @@ version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ba009ff324d1fc1b900bd1fdb31564febe58a8ccc8a6fdbb93b543d33b13ca43" dependencies = [ - "getrandom 0.2.15", + "getrandom 0.2.16", "libredox", "thiserror 1.0.69", ] @@ -4293,13 +4247,9 @@ checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" [[package]] name = "resolv-conf" -version = "0.7.0" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "52e44394d2086d010551b14b53b1f24e31647570cd1deb0379e2c21b329aba00" -dependencies = [ - "hostname", - "quick-error", -] +checksum = "95325155c684b1c89f7765e30bc1c42e4a6da51ca513615660cb8a62ef9a88e3" [[package]] name = "rfc6979" @@ -4319,7 +4269,7 @@ checksum = "a4689e6c2294d81e88dc6261c768b63bc4fcdb852be6d1352498b114f61383b7" dependencies = [ "cc", "cfg-if", - "getrandom 0.2.15", + "getrandom 0.2.16", "libc", "untrusted", "windows-sys 0.52.0", @@ -4375,51 +4325,39 @@ dependencies = [ [[package]] name = "rustix" -version = "0.38.44" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fdb5bc1ae2baa591800df16c9ca78619bf65c0488b41b96ccec5d11220d8c154" -dependencies = [ - "bitflags 2.9.0", - "errno", - "libc", - "linux-raw-sys 0.4.15", - "windows-sys 0.59.0", -] - -[[package]] -name = "rustix" -version = "1.0.2" +version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7178faa4b75a30e269c71e61c353ce2748cf3d76f0c44c393f4e60abf49b825" +checksum = "c71e83d6afe7ff64890ec6b71d6a69bb8a610ab78ce364b3352876bb4c801266" dependencies = [ - "bitflags 2.9.0", + "bitflags 2.9.1", "errno", "libc", - "linux-raw-sys 0.9.2", + "linux-raw-sys", "windows-sys 0.59.0", ] [[package]] name = "rustls" -version = "0.23.23" +version = "0.23.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "47796c98c480fce5406ef69d1c76378375492c3b0a0de587be0c1d9feb12f395" +checksum = "730944ca083c1c233a75c09f199e973ca499344a2b7ba9e755c457e86fb4a321" dependencies = [ "once_cell", "ring", "rustls-pki-types", - "rustls-webpki 0.102.8", + "rustls-webpki 0.103.3", "subtle", "zeroize", ] [[package]] name = "rustls-pki-types" -version = "1.11.0" +version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "917ce264624a4b4db1c364dcc35bfca9ded014d0a958cd47ad3e960e988ea51c" +checksum = "229a4a4c221013e7e1f1a043678c5cc39fe5171437c88fb47151a21e6f5b5c79" dependencies = [ "web-time", + "zeroize", ] [[package]] @@ -4434,9 +4372,9 @@ dependencies = [ [[package]] name = "rustls-webpki" -version = "0.102.8" +version = "0.103.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64ca1bc8749bd4cf37b5ce386cc146580777b4e8572c7b97baf22c83f444bee9" +checksum = "e4a72fe2bcf7a6ac6fd7d0b9e5cb68aeb7d4c0a0271730218b3e92d43b4eb435" dependencies = [ "ring", "rustls-pki-types", @@ -4445,9 +4383,9 @@ dependencies = [ [[package]] name = "rustversion" -version = "1.0.20" +version = "1.0.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eded382c5f5f786b989652c49544c4877d9f015cc22e145a5ea8ea66c2921cd2" +checksum = "8a0d197bd2c9dc6e53b84da9556a69ba4cdfab8619eb41a8bd1cc2027a0f6b1d" [[package]] name = "rw-stream-sink" @@ -4615,7 +4553,7 @@ dependencies = [ "chrono", "hex", "indexmap 1.9.3", - "indexmap 2.8.0", + "indexmap 2.9.0", "serde", "serde_derive", "serde_json", @@ -4662,9 +4600,9 @@ dependencies = [ [[package]] name = "sha2" -version = "0.10.8" +version = "0.10.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" +checksum = "a7507d819769d01a365ab707794a4084392c824f54a7a6a7862f8c3d0892b283" dependencies = [ "cfg-if", "cpufeatures", @@ -4698,9 +4636,9 @@ checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" [[package]] name = "signal-hook-registry" -version = "1.4.2" +version = "1.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9e9e0b4211b72e7b8b6e85c807d36c212bdb33ea8587f7569562a84df5465b1" +checksum = "9203b8055f63a2a00e2f593bb0510367fe707d7ff1e5c872de2f537b339e5410" dependencies = [ "libc", ] @@ -4715,6 +4653,12 @@ dependencies = [ "rand_core 0.6.4", ] +[[package]] +name = "size-of" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4e36eca171fddeda53901b0a436573b3f2391eaa9189d439b2bd8ea8cebd7e3" + [[package]] name = "slab" version = "0.4.9" @@ -4726,9 +4670,9 @@ dependencies = [ [[package]] name = "smallvec" -version = "1.14.0" +version = "1.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fcf8323ef1faaee30a44a340193b1ac6814fd9b7b4e88e9d4519a3e4abe1cfd" +checksum = "8917285742e9f3e1683f0a9c4e6b57960b7314d0b08d30d1ecd426713ee2eee9" [[package]] name = "snow" @@ -4743,15 +4687,15 @@ dependencies = [ "rand_core 0.6.4", "ring", "rustc_version", - "sha2 0.10.8", + "sha2 0.10.9", "subtle", ] [[package]] name = "socket2" -version = "0.5.8" +version = "0.5.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c970269d99b64e60ec3bd6ad27270092a5394c4e309314b18ae3fe575695fbe8" +checksum = "e22376abed350d73dd1cd119b57ffccad95b4e585a7cda43e286245ce23c0678" dependencies = [ "libc", "windows-sys 0.52.0", @@ -4805,7 +4749,7 @@ dependencies = [ "num-integer", "num-traits", "rfc6979", - "sha2 0.10.8", + "sha2 0.10.9", "starknet-curve", "starknet-types-core", "zeroize", @@ -4822,9 +4766,9 @@ dependencies = [ [[package]] name = "starknet-types-core" -version = "0.1.7" +version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa1b9e01ccb217ab6d475c5cda05dbb22c30029f7bb52b192a010a00d77a3d74" +checksum = "4037bcb26ce7c508448d221e570d075196fd4f6912ae6380981098937af9522a" dependencies = [ "lambdaworks-crypto", "lambdaworks-math", @@ -4832,6 +4776,8 @@ dependencies = [ "num-integer", "num-traits", "serde", + "size-of", + "zeroize", ] [[package]] @@ -4882,9 +4828,9 @@ checksum = "734676eb262c623cec13c3155096e08d1f8f29adce39ba17948b18dad1e54142" [[package]] name = "syn" -version = "2.0.100" +version = "2.0.101" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b09a44accad81e1ba1cd74a32461ba89dee89095ba17b32f5d03683b1b1fc2a0" +checksum = "8ce2b7fc941b3a24138a0a7cf8e858bfc6a992e7978a068a5c760deb0ed43caf" dependencies = [ "proc-macro2", "quote", @@ -4899,9 +4845,9 @@ checksum = "0bf256ce5efdfa370213c1dabab5935a12e49f2c58d15e9eac2870d3b4f27263" [[package]] name = "synstructure" -version = "0.13.1" +version = "0.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8af7666ab7b6390ab78131fb5b0fce11d6b7a6951602017c35fa82800708971" +checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2" dependencies = [ "proc-macro2", "quote", @@ -4928,7 +4874,7 @@ version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3c879d448e9d986b661742763247d3693ed13609438cf3d006f51f5368a5ba6b" dependencies = [ - "bitflags 2.9.0", + "bitflags 2.9.1", "core-foundation", "system-configuration-sys", ] @@ -4951,14 +4897,14 @@ checksum = "7b2093cf4c8eb1e67749a6762251bc9cd836b6fc171623bd0a9d324d37af2417" [[package]] name = "tempfile" -version = "3.19.1" +version = "3.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7437ac7763b9b123ccf33c338a5cc1bac6f69b45a136c19bdd8a65e3916435bf" +checksum = "e8a64e3985349f2441a1a9ef0b853f869006c3855f2cda6862a94d26ebb9d6a1" dependencies = [ "fastrand", - "getrandom 0.3.1", + "getrandom 0.3.3", "once_cell", - "rustix 1.0.2", + "rustix", "windows-sys 0.59.0", ] @@ -5049,9 +4995,9 @@ dependencies = [ [[package]] name = "time" -version = "0.3.39" +version = "0.3.41" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dad298b01a40a23aac4580b67e3dbedb7cc8402f3592d7f49469de2ea4aecdd8" +checksum = "8a7619e19bc266e0f9c5e6686659d394bc57973859340060a69221e57dbc0c40" dependencies = [ "deranged", "itoa", @@ -5064,15 +5010,15 @@ dependencies = [ [[package]] name = "time-core" -version = "0.1.3" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "765c97a5b985b7c11d7bc27fa927dc4fe6af3a6dfb021d28deb60d3bf51e76ef" +checksum = "c9e9a38711f559d9e3ce1cdb06dd7c5b8ea546bc90052da6d06bb76da74bb07c" [[package]] name = "time-macros" -version = "0.2.20" +version = "0.2.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8093bc3e81c3bc5f7879de09619d06c9a5a5e45ca44dfeeb7225bae38005c5c" +checksum = "3526739392ec93fd8b359c8e98514cb3e8e021beb4e5f597b00a0221f8ed8a49" dependencies = [ "num-conv", "time-core", @@ -5080,9 +5026,9 @@ dependencies = [ [[package]] name = "tinystr" -version = "0.7.6" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9117f5d4db391c1cf6927e7bea3db74b9a1c1add8f7eda9ffd5364f40f57b82f" +checksum = "5d4f6d1145dcb577acf783d4e601bc1d76a13337bb54e6233add580b07344c8b" dependencies = [ "displaydoc", "zerovec", @@ -5115,9 +5061,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.45.0" +version = "1.45.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2513ca694ef9ede0fb23fe71a4ee4107cb102b9dc1930f6d0fd77aae068ae165" +checksum = "75ef51a33ef1da925cea3e4eb122833cb377c61439ca401b770f54902b806779" dependencies = [ "backtrace", "bytes", @@ -5145,9 +5091,9 @@ dependencies = [ [[package]] name = "tokio-util" -version = "0.7.13" +version = "0.7.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d7fcaa8d55a2bdd6b83ace262b016eca0d79ee02818c5c1bcdf0305114081078" +checksum = "66a539a9ad6d5d281510d5bd368c973d636c02dbf8a67300bfb6b950696ad7df" dependencies = [ "bytes", "futures-core", @@ -5158,9 +5104,9 @@ dependencies = [ [[package]] name = "toml" -version = "0.8.21" +version = "0.8.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "900f6c86a685850b1bc9f6223b20125115ee3f31e01207d81655bbcc0aea9231" +checksum = "05ae329d1f08c4d17a59bed7ff5b5a769d062e64a62d34a3261b219e62cd5aae" dependencies = [ "serde", "serde_spanned", @@ -5179,11 +5125,11 @@ dependencies = [ [[package]] name = "toml_edit" -version = "0.22.25" +version = "0.22.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "10558ed0bd2a1562e630926a2d1f0b98c827da99fabd3fe20920a59642504485" +checksum = "310068873db2c5b3e7659d2cc35d21855dbafa50d1ce336397c666e3cb08137e" dependencies = [ - "indexmap 2.8.0", + "indexmap 2.9.0", "serde", "serde_spanned", "toml_datetime", @@ -5193,9 +5139,9 @@ dependencies = [ [[package]] name = "toml_write" -version = "0.1.0" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28391a4201ba7eb1984cfeb6862c0b3ea2cfe23332298967c749dddc0d6cd976" +checksum = "bfb942dfe1d8e29a7ee7fcbde5bd2b9a25fb89aa70caea2eba3bee836ff41076" [[package]] name = "tower" @@ -5401,12 +5347,6 @@ dependencies = [ "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" @@ -5421,11 +5361,13 @@ checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" [[package]] name = "uuid" -version = "1.15.1" +version = "1.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0f540e3240398cce6128b64ba83fdbdd86129c16a3aa1a3a252efd66eb3d587" +checksum = "3cf4199d1e5d15ddd86a694e4d0dffa9c323ce759fea589f00fef9d81cc1931d" dependencies = [ - "getrandom 0.3.1", + "getrandom 0.3.3", + "js-sys", + "wasm-bindgen", ] [[package]] @@ -5467,9 +5409,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasi" -version = "0.13.3+wasi-0.2.2" +version = "0.14.2+wasi-0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26816d2e1a4a36a2940b96c5296ce403917633dff8f3440e9b236ed6f6bacad2" +checksum = "9683f9a5a998d873c0d21fcbe3c083009670149a8fab228644b8bd36b2c48cb3" dependencies = [ "wit-bindgen-rt", ] @@ -5560,9 +5502,9 @@ dependencies = [ [[package]] name = "whoami" -version = "1.5.2" +version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "372d5b87f58ec45c384ba03563b03544dc5fadc3983e434b286913f5b4a9bb6d" +checksum = "6994d13118ab492c3c80c1f81928718159254c53c472bf9ce36f8dae4add02a7" dependencies = [ "redox_syscall", "wasite", @@ -5571,9 +5513,9 @@ dependencies = [ [[package]] name = "widestring" -version = "1.1.0" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7219d36b6eac893fa81e84ebe06485e7dcbb616177469b142df14f1f4deb1311" +checksum = "dd7cf3379ca1aac9eea11fba24fd7e315d621f8dfe35c8d7d2be8b793726e07d" [[package]] name = "winapi" @@ -5618,21 +5560,24 @@ dependencies = [ [[package]] name = "windows" -version = "0.58.0" +version = "0.61.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd04d41d93c4992d421894c18c8b43496aa748dd4c081bac0dc93eb0489272b6" +checksum = "c5ee8f3d025738cb02bad7868bbb5f8a6327501e870bf51f1b455b0a2454a419" dependencies = [ - "windows-core 0.58.0", - "windows-targets 0.52.6", + "windows-collections", + "windows-core 0.61.2", + "windows-future", + "windows-link", + "windows-numerics", ] [[package]] -name = "windows-core" -version = "0.52.0" +name = "windows-collections" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" +checksum = "3beeceb5e5cfd9eb1d76b381630e82c4241ccd0d27f1a39ed41b2760b255c5e8" dependencies = [ - "windows-targets 0.52.6", + "windows-core 0.61.2", ] [[package]] @@ -5647,22 +5592,33 @@ dependencies = [ [[package]] name = "windows-core" -version = "0.58.0" +version = "0.61.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ba6d44ec8c2591c134257ce647b7ea6b20335bf6379a27dac5f1641fcf59f99" +checksum = "c0fdd3ddb90610c7638aa2b3a3ab2904fb9e5cdbecc643ddb3647212781c4ae3" dependencies = [ "windows-implement", "windows-interface", - "windows-result 0.2.0", + "windows-link", + "windows-result 0.3.4", "windows-strings", - "windows-targets 0.52.6", +] + +[[package]] +name = "windows-future" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc6a41e98427b19fe4b73c550f060b59fa592d7d686537eebf9385621bfbad8e" +dependencies = [ + "windows-core 0.61.2", + "windows-link", + "windows-threading", ] [[package]] name = "windows-implement" -version = "0.58.0" +version = "0.60.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2bbd5b46c938e506ecbce286b6628a02171d56153ba733b6c741fc627ec9579b" +checksum = "a47fddd13af08290e67f4acabf4b459f647552718f683a7b415d290ac744a836" dependencies = [ "proc-macro2", "quote", @@ -5671,9 +5627,9 @@ dependencies = [ [[package]] name = "windows-interface" -version = "0.58.0" +version = "0.59.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "053c4c462dc91d3b1504c6fe5a726dd15e216ba718e84a0e46a88fbe5ded3515" +checksum = "bd9211b69f8dcdfa817bfd14bf1c97c9188afa36f4750130fcdf3f400eca9fa8" dependencies = [ "proc-macro2", "quote", @@ -5682,9 +5638,19 @@ dependencies = [ [[package]] name = "windows-link" -version = "0.1.0" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6dccfd733ce2b1753b03b6d3c65edf020262ea35e20ccdf3e288043e6dd620e3" +checksum = "76840935b766e1b0a05c0066835fb9ec80071d4c09a16f6bd5f7e655e3c14c38" + +[[package]] +name = "windows-numerics" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9150af68066c4c5c07ddc0ce30421554771e528bde427614c61038bc2c92c2b1" +dependencies = [ + "windows-core 0.61.2", + "windows-link", +] [[package]] name = "windows-result" @@ -5697,21 +5663,20 @@ dependencies = [ [[package]] name = "windows-result" -version = "0.2.0" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d1043d8214f791817bab27572aaa8af63732e11bf84aa21a45a78d6c317ae0e" +checksum = "56f42bd332cc6c8eac5af113fc0c1fd6a8fd2aa08a0119358686e5160d0586c6" dependencies = [ - "windows-targets 0.52.6", + "windows-link", ] [[package]] name = "windows-strings" -version = "0.1.0" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4cd9b125c486025df0eabcb585e62173c6c9eddcec5d117d3b6e8c30e2ee4d10" +checksum = "56e6c93f3a0c3b36176cb1327a4958a0353d5d166c2a35cb268ace15e91d3b57" dependencies = [ - "windows-result 0.2.0", - "windows-targets 0.52.6", + "windows-link", ] [[package]] @@ -5772,6 +5737,15 @@ dependencies = [ "windows_x86_64_msvc 0.52.6", ] +[[package]] +name = "windows-threading" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b66463ad2e0ea3bbf808b7f1d371311c80e115c0b71d60efc142cafbcfb057a6" +dependencies = [ + "windows-link", +] + [[package]] name = "windows_aarch64_gnullvm" version = "0.48.5" @@ -5864,9 +5838,9 @@ checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" [[package]] name = "winnow" -version = "0.7.7" +version = "0.7.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6cb8234a863ea0e8cd7284fcdd4f145233eb00fee02bbdd9861aec44e6477bc5" +checksum = "c06928c8748d81b05c9be96aad92e1b6ff01833332f281e8cfca3be4b35fc9ec" dependencies = [ "memchr", ] @@ -5883,24 +5857,18 @@ dependencies = [ [[package]] name = "wit-bindgen-rt" -version = "0.33.0" +version = "0.39.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3268f3d866458b787f390cf61f4bbb563b922d091359f9608842999eaee3943c" +checksum = "6f42320e61fe2cfd34354ecb597f86f413484a798ba44a8ca1165c58d42da6c1" dependencies = [ - "bitflags 2.9.0", + "bitflags 2.9.1", ] -[[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" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e9df38ee2d2c3c5948ea468a8406ff0db0b29ae1ffde1bcf20ef305bcc95c51" +checksum = "ea2f10b9bb0928dfb1b42b65e1f9e36f7f54dbdf08457afefb38afcdec4fa2bb" [[package]] name = "x25519-dalek" @@ -5933,9 +5901,9 @@ dependencies = [ [[package]] name = "xml-rs" -version = "0.8.25" +version = "0.8.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c5b940ebc25896e71dd073bad2dbaa2abfe97b0a391415e22ad1326d9c54e3c4" +checksum = "a62ce76d9b56901b19a74f19431b0d8b3bc7ca4ad685a746dfd78ca8f4fc6bda" [[package]] name = "xmltree" @@ -5963,16 +5931,16 @@ dependencies = [ [[package]] name = "yamux" -version = "0.13.4" +version = "0.13.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17610762a1207ee816c6fadc29220904753648aba0a9ed61c7b8336e80a559c4" +checksum = "3da1acad1c2dc53f0dde419115a38bd8221d8c3e47ae9aeceaf453266d29307e" dependencies = [ "futures", "log", "nohash-hasher", "parking_lot", "pin-project", - "rand 0.8.5", + "rand 0.9.1", "static_assertions", "web-time", ] @@ -5994,9 +5962,9 @@ dependencies = [ [[package]] name = "yoke" -version = "0.7.5" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "120e6aef9aa629e3d4f52dc8cc43a015c7724194c97dfaf45180d2daf2b77f40" +checksum = "5f41bb01b8226ef4bfd589436a297c53d118f65921786300e427be8d487695cc" dependencies = [ "serde", "stable_deref_trait", @@ -6006,9 +5974,9 @@ dependencies = [ [[package]] name = "yoke-derive" -version = "0.7.5" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2380878cad4ac9aac1e2435f3eb4020e8374b5f13c296cb75b4620ff8e229154" +checksum = "38da3c9736e16c5d3c8c597a9aaa5d1fa565d0532ae05e27c24aa62fb32c0ab6" dependencies = [ "proc-macro2", "quote", @@ -6018,38 +5986,18 @@ dependencies = [ [[package]] name = "zerocopy" -version = "0.7.35" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0" -dependencies = [ - "zerocopy-derive 0.7.35", -] - -[[package]] -name = "zerocopy" -version = "0.8.23" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd97444d05a4328b90e75e503a34bad781f14e28a823ad3557f0750df1ebcbc6" -dependencies = [ - "zerocopy-derive 0.8.23", -] - -[[package]] -name = "zerocopy-derive" -version = "0.7.35" +version = "0.8.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" +checksum = "a1702d9583232ddb9174e01bb7c15a2ab8fb1bc6f227aa1233858c351a3ba0cb" dependencies = [ - "proc-macro2", - "quote", - "syn", + "zerocopy-derive", ] [[package]] name = "zerocopy-derive" -version = "0.8.23" +version = "0.8.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6352c01d0edd5db859a63e2605f4ea3183ddbd15e2c4a9e7d32184df75e4f154" +checksum = "28a6e20d751156648aa063f3800b706ee209a32c0b4d9f24be3d980b01be55ef" dependencies = [ "proc-macro2", "quote", @@ -6097,11 +6045,22 @@ dependencies = [ "syn", ] +[[package]] +name = "zerotrie" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "36f0bbd478583f79edad978b407914f61b2972f5af6fa089686016be8f9af595" +dependencies = [ + "displaydoc", + "yoke", + "zerofrom", +] + [[package]] name = "zerovec" -version = "0.10.4" +version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa2b893d79df23bfb12d5461018d408ea19dfafe76c2c7ef6d4eba614f8ff079" +checksum = "4a05eb080e015ba39cc9e23bbe5e7fb04d5fb040350f99f34e338d5fdd294428" dependencies = [ "yoke", "zerofrom", @@ -6110,9 +6069,9 @@ dependencies = [ [[package]] name = "zerovec-derive" -version = "0.10.3" +version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6eafa6dfb17584ea3e2bd6e76e0cc15ad7af12b09abdd1ca55961bed9b1063c6" +checksum = "5b96237efa0c878c64bd89c436f661be4e46b2f3eff1ebb976f7ef2321d2f58f" dependencies = [ "proc-macro2", "quote", diff --git a/code/crates/app-channel/src/connector.rs b/code/crates/app-channel/src/connector.rs index f95cc83ad..2692fdb35 100644 --- a/code/crates/app-channel/src/connector.rs +++ b/code/crates/app-channel/src/connector.rs @@ -79,6 +79,7 @@ where height, round, proposer, + role, } => { let (reply_value, rx_value) = oneshot::channel(); @@ -87,6 +88,7 @@ where height, round, proposer, + role, reply_value, }) .await?; diff --git a/code/crates/app-channel/src/msgs.rs b/code/crates/app-channel/src/msgs.rs index e7d68b5f0..ed62a7b9c 100644 --- a/code/crates/app-channel/src/msgs.rs +++ b/code/crates/app-channel/src/msgs.rs @@ -2,6 +2,7 @@ use std::time::Duration; use bytes::Bytes; use derive_where::derive_where; +use malachitebft_app::consensus::Role; use malachitebft_app::types::core::ValueOrigin; use tokio::sync::mpsc; use tokio::sync::oneshot; @@ -49,6 +50,8 @@ pub enum AppMsg { round: Round, /// Proposer for that round proposer: Ctx::Address, + /// Role that this node is playing in this round + role: Role, /// Channel for sending back previously received undecided values to consensus reply_value: Reply>>, }, diff --git a/code/crates/app/src/spawn.rs b/code/crates/app/src/spawn.rs index fd2b16c5f..ba9eee28c 100644 --- a/code/crates/app/src/spawn.rs +++ b/code/crates/app/src/spawn.rs @@ -199,8 +199,9 @@ fn make_gossip_config(cfg: &ConsensusConfig) -> NetworkConfig { }, PubSubProtocol::Broadcast => GossipSubConfig::default(), }, + channel_names: malachitebft_network::ChannelNames::default(), rpc_max_size: cfg.p2p.rpc_max_size.as_u64() as usize, pubsub_max_size: cfg.p2p.pubsub_max_size.as_u64() as usize, - enable_sync: true, + enable_sync: cfg.vote_sync.mode.is_request_response(), } } diff --git a/code/crates/core-consensus/src/effect.rs b/code/crates/core-consensus/src/effect.rs index b0c2425c6..79e0bc833 100644 --- a/code/crates/core-consensus/src/effect.rs +++ b/code/crates/core-consensus/src/effect.rs @@ -4,7 +4,7 @@ use malachitebft_core_types::*; use crate::input::RequestId; use crate::types::SignedConsensusMsg; -use crate::{ConsensusMsg, VoteExtensionError, WalEntry}; +use crate::{ConsensusMsg, Role, VoteExtensionError, WalEntry}; /// Provides a way to construct the appropriate [`Resume`] value to /// resume execution after handling an [`Effect`]. @@ -77,7 +77,7 @@ where /// Consensus is starting a new round with the given proposer /// /// Resume with: [`resume::Continue`] - StartRound(Ctx::Height, Round, Ctx::Address, resume::Continue), + StartRound(Ctx::Height, Round, Ctx::Address, Role, resume::Continue), /// Publish a message to peers /// diff --git a/code/crates/core-consensus/src/handle/driver.rs b/code/crates/core-consensus/src/handle/driver.rs index a9a014be8..f2938b75f 100644 --- a/code/crates/core-consensus/src/handle/driver.rs +++ b/code/crates/core-consensus/src/handle/driver.rs @@ -10,6 +10,7 @@ use crate::prelude::*; use crate::types::SignedConsensusMsg; use crate::util::pretty::PrettyVal; use crate::LocallyProposedValue; +use crate::Role; use crate::VoteSyncMode; use super::propose::on_propose; @@ -29,12 +30,23 @@ where #[cfg(feature = "metrics")] metrics.round.set(round.as_i64()); - info!(%height, %round, %proposer, "Starting new round"); + let role = if state.address() == proposer { + Role::Proposer + } else if state.is_validator() { + Role::Validator + } else { + Role::None + }; + + info!(%height, %round, %proposer, ?role, "Starting new round"); + + state.last_signed_prevote = None; + state.last_signed_precommit = None; perform!(co, Effect::CancelAllTimeouts(Default::default())); perform!( co, - Effect::StartRound(*height, *round, proposer.clone(), Default::default()) + Effect::StartRound(*height, *round, proposer.clone(), role, Default::default()) ); } diff --git a/code/crates/core-consensus/src/types.rs b/code/crates/core-consensus/src/types.rs index 56184592f..aa877af54 100644 --- a/code/crates/core-consensus/src/types.rs +++ b/code/crates/core-consensus/src/types.rs @@ -10,6 +10,17 @@ pub use malachitebft_core_types::ValuePayload; pub use malachitebft_peer::PeerId; pub use multiaddr::Multiaddr; +/// The role that the node is playing in the consensus protocol during a round. +#[derive(Copy, Clone, Debug, PartialEq, Eq)] +pub enum Role { + /// The node is the proposer for the current round. + Proposer, + /// The node is a validator for the current round. + Validator, + /// The node is not participating in the consensus protocol for the current round. + None, +} + /// A signed consensus message, ie. a signed vote or a signed proposal. #[derive_where(Clone, Debug, PartialEq, Eq)] pub enum SignedConsensusMsg { diff --git a/code/crates/engine/src/consensus.rs b/code/crates/engine/src/consensus.rs index ab3c2ce33..5f3acb795 100644 --- a/code/crates/engine/src/consensus.rs +++ b/code/crates/engine/src/consensus.rs @@ -947,16 +947,18 @@ where Ok(r.resume_with(())) } - Effect::StartRound(height, round, proposer, r) => { + Effect::StartRound(height, round, proposer, role, r) => { self.wal_flush(state.phase).await?; self.host.cast(HostMsg::StartedRound { height, round, - proposer, + proposer: proposer.clone(), + role, })?; - self.tx_event.send(|| Event::StartedRound(height, round)); + self.tx_event + .send(|| Event::StartedRound(height, round, proposer, role)); Ok(r.resume_with(())) } @@ -1256,7 +1258,8 @@ where skip_all, fields( height = %state.consensus.height(), - round = %state.consensus.round() + round = %state.consensus.round(), + address = %state.consensus.address() ) )] async fn post_start( diff --git a/code/crates/engine/src/host.rs b/code/crates/engine/src/host.rs index 3290aae61..07dc92321 100644 --- a/code/crates/engine/src/host.rs +++ b/code/crates/engine/src/host.rs @@ -4,7 +4,7 @@ use std::time::Duration; use derive_where::derive_where; use ractor::{ActorRef, RpcReplyPort}; -use malachitebft_core_consensus::VoteExtensionError; +use malachitebft_core_consensus::{Role, VoteExtensionError}; use malachitebft_core_types::{CommitCertificate, Context, Round, ValueId, VoteExtensions}; use malachitebft_sync::{PeerId, RawDecidedValue}; @@ -27,6 +27,7 @@ pub enum HostMsg { height: Ctx::Height, round: Round, proposer: Ctx::Address, + role: Role, }, /// Request to build a local value to propose diff --git a/code/crates/engine/src/network.rs b/code/crates/engine/src/network.rs index e8226fc23..1c514114d 100644 --- a/code/crates/engine/src/network.rs +++ b/code/crates/engine/src/network.rs @@ -118,7 +118,7 @@ pub enum State { listen_addrs: Vec, peers: BTreeSet, output_port: OutputPort>, - ctrl_handle: CtrlHandle, + ctrl_handle: Box, recv_task: JoinHandle<()>, inbound_requests: HashMap, }, @@ -204,7 +204,7 @@ where listen_addrs: Vec::new(), peers: BTreeSet::new(), output_port: OutputPort::with_capacity(128), - ctrl_handle, + ctrl_handle: Box::new(ctrl_handle), recv_task, inbound_requests: HashMap::new(), }) @@ -329,6 +329,8 @@ where } Msg::NewEvent(Event::Message(Channel::Consensus, from, data)) => { + tracing::trace!(%from, "Received consensus message: {data:?}"); + let msg = match self.codec.decode(data) { Ok(msg) => msg, Err(e) => { diff --git a/code/crates/engine/src/util/events.rs b/code/crates/engine/src/util/events.rs index 0df9e166a..fa5b43a28 100644 --- a/code/crates/engine/src/util/events.rs +++ b/code/crates/engine/src/util/events.rs @@ -6,7 +6,7 @@ use ractor::ActorProcessingErr; use tokio::sync::broadcast; use malachitebft_core_consensus::{ - LocallyProposedValue, ProposedValue, SignedConsensusMsg, WalEntry, + LocallyProposedValue, ProposedValue, Role, SignedConsensusMsg, WalEntry, }; use malachitebft_core_types::{CommitCertificate, Context, Round, SignedVote, ValueOrigin}; @@ -43,7 +43,7 @@ impl Default for TxEvent { #[derive_where(Clone, Debug)] pub enum Event { StartedHeight(Ctx::Height, bool), - StartedRound(Ctx::Height, Round), + StartedRound(Ctx::Height, Round, Ctx::Address, Role), Published(SignedConsensusMsg), ProposedValue(LocallyProposedValue), ReceivedProposedValue(ProposedValue, ValueOrigin), @@ -63,8 +63,8 @@ impl fmt::Display for Event { Event::StartedHeight(height, restart) => { write!(f, "StartedHeight(height: {height}, restart: {restart})") } - Event::StartedRound(height, round) => { - write!(f, "StartedRound(height: {height}, round: {round})") + Event::StartedRound(height, round, proposer, role) => { + write!(f, "StartedRound(height: {height}, round: {round}, proposer: {proposer}, role: {role:?})") } Event::Published(msg) => write!(f, "Published(msg: {msg:?})"), Event::ProposedValue(value) => write!(f, "ProposedValue(value: {value:?})"), diff --git a/code/crates/engine/src/wal.rs b/code/crates/engine/src/wal.rs index a9a0e9a86..db7b244c9 100644 --- a/code/crates/engine/src/wal.rs +++ b/code/crates/engine/src/wal.rs @@ -84,7 +84,10 @@ where match msg { Msg::StartedHeight(height, reply_to) => { if state.height == height { - debug!(%height, "WAL already at height, ignoring"); + debug!(%height, "WAL already at height, returning empty entries"); + reply_to + .send(Ok(None)) + .map_err(|e| eyre!("Failed to send reply: {e}"))?; return Ok(()); } diff --git a/code/crates/network/src/behaviour.rs b/code/crates/network/src/behaviour.rs index 09de9f27b..6e44b79b8 100644 --- a/code/crates/network/src/behaviour.rs +++ b/code/crates/network/src/behaviour.rs @@ -14,7 +14,7 @@ use malachitebft_discovery as discovery; use malachitebft_metrics::Registry; use malachitebft_sync as sync; -use crate::{Config, GossipSubConfig, PROTOCOL}; +use crate::{Config, GossipSubConfig, PubSubProtocol, PROTOCOL}; #[derive(Debug)] pub enum NetworkEvent { @@ -133,6 +133,7 @@ fn message_id(message: &gossipsub::Message) -> gossipsub::MessageId { fn gossipsub_config(config: GossipSubConfig, max_transmit_size: usize) -> gossipsub::Config { gossipsub::ConfigBuilder::default() + .protocol_id_prefix("/meshsub") .max_transmit_size(max_transmit_size) .opportunistic_graft_ticks(3) .heartbeat_interval(Duration::from_secs(1)) diff --git a/code/crates/network/src/channel.rs b/code/crates/network/src/channel.rs index 97b7f4c30..553029269 100644 --- a/code/crates/network/src/channel.rs +++ b/code/crates/network/src/channel.rs @@ -1,9 +1,28 @@ use core::fmt; +use std::sync::OnceLock; +use futures::channel; use libp2p::gossipsub; use libp2p_broadcast as broadcast; use serde::{Deserialize, Serialize}; +#[derive(Clone, Debug, Copy)] +pub struct ChannelNames { + pub consensus: &'static str, + pub proposal_parts: &'static str, + pub sync: &'static str, +} + +impl Default for ChannelNames { + fn default() -> Self { + Self { + consensus: "consensus_votes", + proposal_parts: "consensus_proposals", + sync: "sync", + } + } +} + #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)] pub enum Channel { Consensus, @@ -20,48 +39,61 @@ impl Channel { &[Channel::Consensus, Channel::ProposalParts] } - pub fn to_gossipsub_topic(self) -> gossipsub::IdentTopic { - gossipsub::IdentTopic::new(self.as_str()) + pub fn to_gossipsub_topic(self, channel_names: ChannelNames) -> gossipsub::Sha256Topic { + // gossipsub::IdentTopic::new(self.as_str()) + gossipsub::Sha256Topic::new(self.as_str(channel_names)) } - pub fn to_broadcast_topic(self) -> broadcast::Topic { - broadcast::Topic::new(self.as_str().as_bytes()) + pub fn to_broadcast_topic(self, channel_names: ChannelNames) -> broadcast::Topic { + broadcast::Topic::new(self.as_str(channel_names).as_bytes()) } - pub fn as_str(&self) -> &'static str { + pub fn as_str(&self, channel_names: ChannelNames) -> &'static str { match self { - Channel::Consensus => "/consensus", - Channel::ProposalParts => "/proposal_parts", - Channel::Sync => "/sync", + Channel::Consensus => channel_names.consensus, + Channel::ProposalParts => channel_names.proposal_parts, + Channel::Sync => channel_names.sync, } } - pub fn has_gossipsub_topic(topic_hash: &gossipsub::TopicHash) -> bool { + pub fn has_gossipsub_topic( + topic_hash: &gossipsub::TopicHash, + channel_names: ChannelNames, + ) -> bool { Self::all() .iter() - .any(|channel| &channel.to_gossipsub_topic().hash() == topic_hash) + .any(|channel| &channel.to_gossipsub_topic(channel_names).hash() == topic_hash) } - pub fn has_broadcast_topic(topic: &broadcast::Topic) -> bool { + pub fn has_broadcast_topic(topic: &broadcast::Topic, channel_names: ChannelNames) -> bool { Self::all() .iter() - .any(|channel| &channel.to_broadcast_topic() == topic) + .any(|channel| &channel.to_broadcast_topic(channel_names) == topic) } - pub fn from_gossipsub_topic_hash(topic: &gossipsub::TopicHash) -> Option { - match topic.as_str() { - "/consensus" => Some(Channel::Consensus), - "/proposal_parts" => Some(Channel::ProposalParts), - "/sync" => Some(Channel::Sync), - _ => None, + pub fn from_gossipsub_topic_hash( + topic: &gossipsub::TopicHash, + channel_names: ChannelNames, + ) -> Option { + if topic == &Self::Consensus.to_gossipsub_topic(channel_names).hash() { + Some(Self::Consensus) + } else if topic == &Self::ProposalParts.to_gossipsub_topic(channel_names).hash() { + Some(Self::ProposalParts) + } else if topic == &Self::Sync.to_gossipsub_topic(channel_names).hash() { + Some(Self::Sync) + } else { + None } } - pub fn from_broadcast_topic(topic: &broadcast::Topic) -> Option { + pub fn from_broadcast_topic( + topic: &broadcast::Topic, + channel_names: ChannelNames, + ) -> Option { match topic.as_ref() { - b"/consensus" => Some(Channel::Consensus), - b"/proposal_parts" => Some(Channel::ProposalParts), - b"/sync" => Some(Channel::Sync), + name if name == channel_names.consensus.as_bytes() => Some(Self::Consensus), + name if name == channel_names.proposal_parts.as_bytes() => Some(Self::ProposalParts), + name if name == channel_names.sync.as_bytes() => Some(Self::Sync), _ => None, } } @@ -69,6 +101,7 @@ impl Channel { impl fmt::Display for Channel { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - self.as_str().fmt(f) + // TODO: how to use the correct channel names? + self.as_str(ChannelNames::default()).fmt(f) } } diff --git a/code/crates/network/src/lib.rs b/code/crates/network/src/lib.rs index 14328af24..3fc60ace9 100644 --- a/code/crates/network/src/lib.rs +++ b/code/crates/network/src/lib.rs @@ -1,3 +1,5 @@ +#![allow(unused_variables, unused_imports)] + use std::collections::HashMap; use std::error::Error; use std::ops::ControlFlow; @@ -28,12 +30,12 @@ pub mod handle; pub mod pubsub; mod channel; -pub use channel::Channel; +pub use channel::{Channel, ChannelNames}; use behaviour::{Behaviour, NetworkEvent}; use handle::Handle; -const PROTOCOL: &str = "/malachitebft-core-consensus/v1beta1"; +const PROTOCOL: &str = "/staknet/identify/0.1.0-rc.0"; // Typo is from the sequencer code const METRICS_PREFIX: &str = "malachitebft_network"; const DISCOVERY_METRICS_PREFIX: &str = "malachitebft_discovery"; @@ -92,6 +94,7 @@ pub struct Config { pub transport: TransportProtocol, pub gossipsub: GossipSubConfig, pub pubsub_protocol: PubSubProtocol, + pub channel_names: ChannelNames, pub rpc_max_size: usize, pub pubsub_max_size: usize, pub enable_sync: bool, @@ -218,7 +221,7 @@ pub async fn spawn( let peer_id = PeerId::from_libp2p(swarm.local_peer_id()); let span = error_span!("network"); - info!(parent: span.clone(), %peer_id, "Starting network service"); + info!(parent: span.clone(), %peer_id, "Starting network"); let task_handle = tokio::task::spawn(run(config, metrics, state, swarm, rx_ctrl, tx_event).instrument(span)); @@ -241,13 +244,23 @@ async fn run( state.discovery.dial_bootstrap_nodes(&swarm); - if let Err(e) = pubsub::subscribe(&mut swarm, config.pubsub_protocol, Channel::consensus()) { + if let Err(e) = pubsub::subscribe( + &mut swarm, + config.pubsub_protocol, + Channel::consensus(), + config.channel_names, + ) { error!("Error subscribing to consensus channels: {e}"); return; }; if config.enable_sync { - if let Err(e) = pubsub::subscribe(&mut swarm, PubSubProtocol::Broadcast, &[Channel::Sync]) { + if let Err(e) = pubsub::subscribe( + &mut swarm, + PubSubProtocol::Broadcast, + &[Channel::Sync], + config.channel_names, + ) { error!("Error subscribing to Sync channel: {e}"); return; }; @@ -300,7 +313,13 @@ async fn handle_ctrl_msg( match msg { CtrlMsg::Publish(channel, data) => { let msg_size = data.len(); - let result = pubsub::publish(swarm, config.pubsub_protocol, channel, data); + let result = pubsub::publish( + swarm, + config.pubsub_protocol, + channel, + config.channel_names, + data, + ); match result { Ok(()) => debug!(%channel, size = %msg_size, "Published message"), @@ -317,7 +336,13 @@ async fn handle_ctrl_msg( } let msg_size = data.len(); - let result = pubsub::publish(swarm, PubSubProtocol::Broadcast, channel, data); + let result = pubsub::publish( + swarm, + PubSubProtocol::Broadcast, + channel, + config.channel_names, + data, + ); match result { Ok(()) => debug!(%channel, size = %msg_size, "Broadcasted message"), @@ -369,7 +394,7 @@ async fn handle_ctrl_msg( async fn handle_swarm_event( event: SwarmEvent, - _config: &Config, + config: &Config, metrics: &Metrics, swarm: &mut swarm::Swarm, state: &mut State, @@ -419,13 +444,20 @@ async fn handle_swarm_event( SwarmEvent::ConnectionClosed { peer_id, connection_id, + endpoint, cause, .. } => { if let Some(cause) = cause { - warn!("Connection closed with {peer_id}, reason: {cause}"); + warn!( + "Connection closed with {peer_id} at {}, reason: {cause}", + endpoint.get_remote_address() + ); } else { - warn!("Connection closed with {peer_id}, reason: unknown"); + warn!( + "Connection closed with {peer_id} at {}, reason: unknown", + endpoint.get_remote_address() + ); } state @@ -497,11 +529,11 @@ async fn handle_swarm_event( } SwarmEvent::Behaviour(NetworkEvent::GossipSub(event)) => { - return handle_gossipsub_event(event, metrics, swarm, state, tx_event).await; + return handle_gossipsub_event(event, config, metrics, swarm, state, tx_event).await; } SwarmEvent::Behaviour(NetworkEvent::Broadcast(event)) => { - return handle_broadcast_event(event, metrics, swarm, state, tx_event).await; + return handle_broadcast_event(event, config, metrics, swarm, state, tx_event).await; } SwarmEvent::Behaviour(NetworkEvent::Sync(event)) => { @@ -522,6 +554,7 @@ async fn handle_swarm_event( async fn handle_gossipsub_event( event: gossipsub::Event, + config: &Config, _metrics: &Metrics, _swarm: &mut swarm::Swarm, _state: &mut State, @@ -529,21 +562,23 @@ async fn handle_gossipsub_event( ) -> ControlFlow<()> { match event { gossipsub::Event::Subscribed { peer_id, topic } => { - if !Channel::has_gossipsub_topic(&topic) { + let Some(channel) = Channel::from_gossipsub_topic_hash(&topic, config.channel_names) + else { trace!("Peer {peer_id} tried to subscribe to unknown topic: {topic}"); return ControlFlow::Continue(()); - } + }; - trace!("Peer {peer_id} subscribed to {topic}"); + trace!("Peer {peer_id} subscribed to {channel}"); } gossipsub::Event::Unsubscribed { peer_id, topic } => { - if !Channel::has_gossipsub_topic(&topic) { + let Some(channel) = Channel::from_gossipsub_topic_hash(&topic, config.channel_names) + else { trace!("Peer {peer_id} tried to unsubscribe from unknown topic: {topic}"); return ControlFlow::Continue(()); - } + }; - trace!("Peer {peer_id} unsubscribed from {topic}"); + trace!("Peer {peer_id} unsubscribed from {channel}"); } gossipsub::Event::Message { @@ -555,7 +590,9 @@ async fn handle_gossipsub_event( return ControlFlow::Continue(()); }; - let Some(channel) = Channel::from_gossipsub_topic_hash(&message.topic) else { + let Some(channel) = + Channel::from_gossipsub_topic_hash(&message.topic, config.channel_names) + else { trace!( "Received message {message_id} from {peer_id} on different channel: {}", message.topic @@ -601,6 +638,7 @@ async fn handle_gossipsub_event( async fn handle_broadcast_event( event: broadcast::Event, + config: &Config, _metrics: &Metrics, _swarm: &mut swarm::Swarm, _state: &mut State, @@ -608,7 +646,7 @@ async fn handle_broadcast_event( ) -> ControlFlow<()> { match event { broadcast::Event::Subscribed(peer_id, topic) => { - if !Channel::has_broadcast_topic(&topic) { + if !Channel::has_broadcast_topic(&topic, config.channel_names) { trace!("Peer {peer_id} tried to subscribe to unknown topic: {topic:?}"); return ControlFlow::Continue(()); } @@ -617,7 +655,7 @@ async fn handle_broadcast_event( } broadcast::Event::Unsubscribed(peer_id, topic) => { - if !Channel::has_broadcast_topic(&topic) { + if !Channel::has_broadcast_topic(&topic, config.channel_names) { trace!("Peer {peer_id} tried to unsubscribe from unknown topic: {topic:?}"); return ControlFlow::Continue(()); } @@ -626,7 +664,7 @@ async fn handle_broadcast_event( } broadcast::Event::Received(peer_id, topic, message) => { - let Some(channel) = Channel::from_broadcast_topic(&topic) else { + let Some(channel) = Channel::from_broadcast_topic(&topic, config.channel_names) else { trace!("Received message from {peer_id} on different channel: {topic:?}"); return ControlFlow::Continue(()); }; diff --git a/code/crates/network/src/pubsub.rs b/code/crates/network/src/pubsub.rs index 9d9e0bcc2..2dc7e623a 100644 --- a/code/crates/network/src/pubsub.rs +++ b/code/crates/network/src/pubsub.rs @@ -1,19 +1,21 @@ use bytes::Bytes; use libp2p::swarm; +use tracing::trace; use crate::behaviour::Behaviour; -use crate::{Channel, PubSubProtocol}; +use crate::{Channel, ChannelNames, PubSubProtocol}; pub fn subscribe( swarm: &mut swarm::Swarm, protocol: PubSubProtocol, channels: &[Channel], + channel_names: ChannelNames, ) -> Result<(), eyre::Report> { match protocol { PubSubProtocol::GossipSub => { if let Some(gossipsub) = swarm.behaviour_mut().gossipsub.as_mut() { for channel in channels { - gossipsub.subscribe(&channel.to_gossipsub_topic())?; + gossipsub.subscribe(&channel.to_gossipsub_topic(channel_names))?; } } else { return Err(eyre::eyre!("GossipSub not enabled")); @@ -22,7 +24,7 @@ pub fn subscribe( PubSubProtocol::Broadcast => { if let Some(broadcast) = swarm.behaviour_mut().broadcast.as_mut() { for channel in channels { - broadcast.subscribe(channel.to_broadcast_topic()); + broadcast.subscribe(channel.to_broadcast_topic(channel_names)); } } else { return Err(eyre::eyre!("Broadcast not enabled")); @@ -37,19 +39,20 @@ pub fn publish( swarm: &mut swarm::Swarm, protocol: PubSubProtocol, channel: Channel, + channel_names: ChannelNames, data: Bytes, ) -> Result<(), eyre::Report> { match protocol { PubSubProtocol::GossipSub => { if let Some(gossipsub) = swarm.behaviour_mut().gossipsub.as_mut() { - gossipsub.publish(channel.to_gossipsub_topic(), data)?; + gossipsub.publish(channel.to_gossipsub_topic(channel_names), data)?; } else { return Err(eyre::eyre!("GossipSub not enabled")); } } PubSubProtocol::Broadcast => { if let Some(broadcast) = swarm.behaviour_mut().broadcast.as_mut() { - broadcast.broadcast(&channel.to_broadcast_topic(), data); + broadcast.broadcast(&channel.to_broadcast_topic(channel_names), data); } else { return Err(eyre::eyre!("Broadcast not enabled")); } diff --git a/code/crates/network/test/src/lib.rs b/code/crates/network/test/src/lib.rs index 404ed9009..a7c2b6927 100644 --- a/code/crates/network/test/src/lib.rs +++ b/code/crates/network/test/src/lib.rs @@ -160,6 +160,7 @@ impl Test { transport: malachitebft_network::TransportProtocol::Quic, gossipsub: malachitebft_network::GossipSubConfig::default(), pubsub_protocol: malachitebft_network::PubSubProtocol::default(), + channel_names: malachitebft_network::ChannelNames::default(), rpc_max_size: 10 * 1024 * 1024, // 10 MiB pubsub_max_size: 4 * 1024 * 1024, // 4 MiB enable_sync: false, diff --git a/code/crates/starknet/host/src/actor.rs b/code/crates/starknet/host/src/actor.rs index 7df2aff6e..c7ab83f33 100644 --- a/code/crates/starknet/host/src/actor.rs +++ b/code/crates/starknet/host/src/actor.rs @@ -10,7 +10,7 @@ use rand::SeedableRng; use tokio::time::Instant; use tracing::{debug, error, info, trace, warn}; -use malachitebft_core_consensus::{PeerId, VoteExtensionError}; +use malachitebft_core_consensus::{PeerId, Role, VoteExtensionError}; use malachitebft_core_types::{CommitCertificate, Round, Validity, ValueId, ValueOrigin}; use malachitebft_engine::consensus::{ConsensusMsg, ConsensusRef}; use malachitebft_engine::host::{LocallyProposedValue, ProposedValue}; @@ -131,7 +131,8 @@ impl Host { height, round, proposer, - } => on_started_round(state, height, round, proposer).await, + role, + } => on_started_round(state, height, round, proposer, role).await, HostMsg::GetHistoryMinHeight { reply_to } => { on_get_history_min_height(state, reply_to).await @@ -215,17 +216,26 @@ async fn on_consensus_ready( state: &mut HostState, consensus: ConsensusRef, ) -> Result<(), ActorProcessingErr> { - let latest_block_height = state.block_store.last_height().await.unwrap_or_default(); - let start_height = latest_block_height.increment(); + if !state.ready { + state.consensus = Some(consensus.clone()); + state.ready = true; + } + + let mut start_height = malachitebft_core_types::Height::INITIAL; + if let Some(latest_block_height) = state.block_store.last_height().await { + start_height = latest_block_height.increment(); + } - state.consensus = Some(consensus.clone()); + state.start_height = start_height; + tokio::time::sleep(Duration::from_millis(200)).await; consensus.cast(ConsensusMsg::StartHeight( start_height, state.host.validator_set.clone(), ))?; + Ok(()) } @@ -259,10 +269,14 @@ async fn on_started_round( height: Height, round: Round, proposer: Address, + role: Role, ) -> Result<(), ActorProcessingErr> { state.height = height; state.round = round; state.proposer = Some(proposer); + state.role = role; + + info!(%height, %round, %proposer, ?role, "Started new round"); // If we have already built or seen one or more values for this height and round, // feed them back to consensus. This may happen when we are restarting after a crash. @@ -457,7 +471,7 @@ async fn on_restream_proposal( PartType::Init => init_part.clone(), PartType::BlockInfo => part, PartType::Transactions => part, - PartType::ProposalCommitment => part, + // PartType::ProposalCommitment => part, PartType::Fin => fin_part.clone(), }; diff --git a/code/crates/starknet/host/src/block_store.rs b/code/crates/starknet/host/src/block_store.rs index 85b066aa6..2820a2b54 100644 --- a/code/crates/starknet/host/src/block_store.rs +++ b/code/crates/starknet/host/src/block_store.rs @@ -52,7 +52,7 @@ pub enum StoreError { Commit(#[from] redb::CommitError), #[error("Transaction error: {0}")] - Transaction(#[from] redb::TransactionError), + Transaction(#[from] Box), #[error("Failed to encode/decode Protobuf: {0}")] Protobuf(#[from] ProtoError), @@ -61,6 +61,12 @@ pub enum StoreError { TaskJoin(#[from] tokio::task::JoinError), } +impl From for StoreError { + fn from(err: redb::TransactionError) -> Self { + Self::Transaction(Box::new(err)) + } +} + const CERTIFICATES_TABLE: redb::TableDefinition> = redb::TableDefinition::new("certificates"); diff --git a/code/crates/starknet/host/src/host.rs b/code/crates/starknet/host/src/host.rs index 9abc437ca..338360fe8 100644 --- a/code/crates/starknet/host/src/host.rs +++ b/code/crates/starknet/host/src/host.rs @@ -1,5 +1,3 @@ -use std::collections::BTreeSet; - use async_trait::async_trait; use tokio::sync::{mpsc, oneshot}; use tokio::time::Instant; @@ -83,7 +81,7 @@ pub trait Host { /// - address - tells the networking layer where to send messages. /// - public_key - used for signature verification and identification. /// - voting_power - used for quorum calculations. - async fn validators(&self, height: Self::Height) -> Option>; + async fn validators(&self, height: Self::Height) -> Option>; /// Sign the given message hash async fn sign(&self, message: Self::MessageHash) -> Self::Signature; diff --git a/code/crates/starknet/host/src/host/proposal.rs b/code/crates/starknet/host/src/host/proposal.rs index 6cf49605b..c4582e7ae 100644 --- a/code/crates/starknet/host/src/host/proposal.rs +++ b/code/crates/starknet/host/src/host/proposal.rs @@ -1,10 +1,11 @@ -#![allow(clippy::too_many_arguments)] -use sha3::Digest; +#![allow(unused_imports, clippy::too_many_arguments)] + use std::sync::Arc; use std::time::SystemTime; use bytesize::ByteSize; use eyre::eyre; +use sha3::Digest; use tokio::sync::{mpsc, oneshot}; use tokio::time::Instant; use tracing::{debug, error, trace}; @@ -15,7 +16,7 @@ use crate::host::starknet::StarknetParams; use crate::mempool::{MempoolMsg, MempoolRef}; use crate::types::*; -const PROTOCOL_VERSION: &str = "0.13.0"; +// const PROTOCOL_VERSION: &str = "0.13.0"; pub async fn build_proposal_task( height: Height, @@ -45,6 +46,7 @@ pub async fn build_proposal_task( } } +#[allow(unused_variables, unused_mut)] async fn run_build_proposal_task( height: Height, round: Round, @@ -87,10 +89,10 @@ async fn run_build_proposal_task( height, builder: proposer, timestamp: now, - l1_gas_price_wei: 0, - l1_data_gas_price_wei: 0, - l2_gas_price_fri: 0, - eth_to_strk_rate: 0, + l1_gas_price_wei: 1, + l1_data_gas_price_wei: 1, + l2_gas_price_fri: 100000, + eth_to_strk_rate: 1, l1_da_mode: L1DataAvailabilityMode::Blob, }); @@ -101,68 +103,68 @@ async fn run_build_proposal_task( let max_block_size = params.max_block_size.as_u64() as usize; let mut hasher = sha3::Keccak256::new(); - 'reap: loop { - let reaped_txes = mempool - .call( - |reply| MempoolMsg::Reap { - height: height.as_u64(), - num_txes: params.txs_per_part, - reply, - }, - Some(build_duration), - ) - .await? - .success_or(eyre!("Failed to reap transactions from the mempool"))?; - - debug!("Reaped {} transactions from the mempool", reaped_txes.len()); - - if reaped_txes.is_empty() { - debug!("No more transactions to reap"); - break 'reap; - } - - let mut txes = Vec::new(); - let mut full_block = false; - - 'txes: for tx in reaped_txes { - if block_size + tx.size_bytes() > max_block_size { - full_block = true; - break 'txes; - } - - block_size += tx.size_bytes(); - block_tx_count += 1; - - txes.push(tx.clone()); - hasher.update(tx.clone().hash().as_bytes()); - } - - let exec_time = params.exec_time_per_tx * txes.len() as u32; - tokio::time::sleep(exec_time).await; - - trace!( - %sequence, - "Created a tx batch with {} tx-es of size {} in {:?}", - txes.len(), - ByteSize::b(block_size as u64), - start.elapsed() - ); - - // Transactions - { - let part = ProposalPart::Transactions(TransactionBatch::new(txes)); - tx_part.send(part).await?; - sequence += 1; - } - - if full_block { - debug!("Max block size reached, stopping tx generation"); - break 'reap; - } else if start.elapsed() >= build_duration { - debug!("Time allowance exceeded, stopping tx generation"); - break 'reap; - } - } + // 'reap: loop { + // let reaped_txes = mempool + // .call( + // |reply| MempoolMsg::Reap { + // height: height.as_u64(), + // num_txes: params.txs_per_part, + // reply, + // }, + // Some(build_duration), + // ) + // .await? + // .success_or(eyre!("Failed to reap transactions from the mempool"))?; + // + // debug!("Reaped {} transactions from the mempool", reaped_txes.len()); + // + // if reaped_txes.is_empty() { + // debug!("No more transactions to reap"); + // break 'reap; + // } + // + // let mut txes = Vec::new(); + // let mut full_block = false; + // + // 'txes: for tx in reaped_txes { + // if block_size + tx.size_bytes() > max_block_size { + // full_block = true; + // break 'txes; + // } + // + // block_size += tx.size_bytes(); + // block_tx_count += 1; + // + // txes.push(tx.clone()); + // hasher.update(tx.clone().hash().as_bytes()); + // } + // + // let exec_time = params.exec_time_per_tx * txes.len() as u32; + // tokio::time::sleep(exec_time).await; + // + // trace!( + // %sequence, + // "Created a tx batch with {} tx-es of size {} in {:?}", + // txes.len(), + // ByteSize::b(block_size as u64), + // start.elapsed() + // ); + // + // // Transactions + // { + // let part = ProposalPart::Transactions(TransactionBatch::new(txes)); + // tx_part.send(part).await?; + // sequence += 1; + // } + // + // if full_block { + // debug!("Max block size reached, stopping tx generation"); + // break 'reap; + // } else if start.elapsed() >= build_duration { + // debug!("Time allowance exceeded, stopping tx generation"); + // break 'reap; + // } + // } if params.stable_block_times { // Sleep for the remaining time, in order to not break tests @@ -172,37 +174,37 @@ async fn run_build_proposal_task( let transaction_commitment = Hash::new(hasher.finalize().into()); - // Proposal Commitment - { - let part = ProposalPart::Commitment(Box::new(ProposalCommitment { - height, - parent_commitment: Hash::new([0; 32]), - builder: proposer, - timestamp: now, - protocol_version: PROTOCOL_VERSION.to_string(), - old_state_root: Hash::new([0; 32]), - state_diff_commitment: Hash::new([0; 32]), - transaction_commitment, - event_commitment: Hash::new([0; 32]), - receipt_commitment: Hash::new([0; 32]), - concatenated_counts: Felt::ONE, - l1_gas_price_fri: 0, - l1_data_gas_price_fri: 0, - l2_gas_price_fri: 0, - l2_gas_used: 0, - l1_da_mode: L1DataAvailabilityMode::Blob, - })); - - tx_part.send(part).await?; - sequence += 1; - } + // // Proposal Commitment + // { + // let part = ProposalPart::Commitment(Box::new(ProposalCommitment { + // height, + // parent_commitment: Hash::new([0; 32]), + // builder: proposer, + // timestamp: now, + // protocol_version: PROTOCOL_VERSION.to_string(), + // old_state_root: Hash::new([0; 32]), + // state_diff_commitment: Hash::new([0; 32]), + // transaction_commitment, + // event_commitment: Hash::new([0; 32]), + // receipt_commitment: Hash::new([0; 32]), + // concatenated_counts: Felt::ONE, + // l1_gas_price_fri: 0, + // l1_data_gas_price_fri: 0, + // l2_gas_price_fri: 0, + // l2_gas_used: 0, + // l1_da_mode: L1DataAvailabilityMode::Blob, + // })); + // + // tx_part.send(part).await?; + // sequence += 1; + // } // Fin { let part = ProposalPart::Fin(ProposalFin { - // TODO: Compute the actual propoosal commitment hash, for now - // we use the transaction commitment - proposal_commitment_hash: transaction_commitment, + // TODO: Compute the actual proposal commitment hash, for now + // we use the empty block hash + proposal_commitment_hash: Hash::new([0; 32]), }); tx_part.send(part).await?; sequence += 1; diff --git a/code/crates/starknet/host/src/host/starknet.rs b/code/crates/starknet/host/src/host/starknet.rs index 95a7ca8ae..32cb0db2f 100644 --- a/code/crates/starknet/host/src/host/starknet.rs +++ b/code/crates/starknet/host/src/host/starknet.rs @@ -1,4 +1,3 @@ -use std::collections::BTreeSet; use std::time::Duration; use async_trait::async_trait; @@ -149,7 +148,7 @@ impl Host for StarknetHost { /// - address - tells the networking layer where to send messages. /// - public_key - used for signature verification and identification. /// - voting_power - used for quorum calculations. - async fn validators(&self, _height: Self::Height) -> Option> { + async fn validators(&self, _height: Self::Height) -> Option> { Some(self.validator_set.validators.iter().cloned().collect()) } diff --git a/code/crates/starknet/host/src/host/state.rs b/code/crates/starknet/host/src/host/state.rs index cf6806917..f3623c758 100644 --- a/code/crates/starknet/host/src/host/state.rs +++ b/code/crates/starknet/host/src/host/state.rs @@ -1,32 +1,73 @@ -use sha3::Digest; +use std::collections::HashSet; use std::path::Path; use std::sync::Arc; use std::time::Duration; +use bytes::{Buf, BufMut}; use rand::RngCore; +use sha3::Digest; use tracing::{debug, error, trace}; +use malachitebft_core_consensus::Role; use malachitebft_core_types::{Round, Validity}; use malachitebft_engine::consensus::ConsensusRef; use malachitebft_engine::host::ProposedValue; use malachitebft_engine::util::streaming::StreamId; -use malachitebft_starknet_p2p_proto as p2p_proto; +// use malachitebft_starknet_p2p_proto as p2p_proto; +use malachitebft_sync::PeerId; use crate::block_store::BlockStore; use crate::host::StarknetHost; use crate::streaming::PartStreamsMap; use crate::types::*; +/// HeightAndRound is a tuple struct used as the StreamId for consensus and context. +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub struct HeightAndRound(pub u64, pub u32); + +impl TryFrom> for HeightAndRound { + type Error = &'static str; + + fn try_from(value: Vec) -> Result { + if value.len() != 12 { + return Err("Invalid length"); + } + let mut bytes = value.as_slice(); + let height = bytes.get_u64(); + let round = bytes.get_u32(); + Ok(HeightAndRound(height, round)) + } +} + +impl From for Vec { + fn from(value: HeightAndRound) -> Vec { + let mut bytes = Vec::with_capacity(12); + bytes.put_u64(value.0); + bytes.put_u32(value.1); + bytes + } +} + +impl std::fmt::Display for HeightAndRound { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "(height: {}, round: {})", self.0, self.1) + } +} + pub struct HostState { pub ctx: MockContext, pub height: Height, pub round: Round, pub proposer: Option
, + pub role: Role, pub host: StarknetHost, pub consensus: Option>, pub block_store: BlockStore, pub part_streams_map: PartStreamsMap, pub nonce: u64, + pub ready: bool, + pub peers: HashSet, + pub start_height: Height, } impl HostState { @@ -44,24 +85,24 @@ impl HostState { height: Height::new(0, 0), round: Round::Nil, proposer: None, + role: Role::None, host, consensus: None, block_store: BlockStore::new(db_path).await.unwrap(), part_streams_map: PartStreamsMap::default(), nonce: rng.next_u64(), + ready: false, + peers: HashSet::new(), + start_height: Height::new(0, 0), } } pub fn stream_id(&mut self) -> StreamId { - let stream_id = p2p_proto::ConsensusStreamId { - height: self.height.as_u64(), - round: self.round.as_u32().expect("round is non-nil"), - nonce: self.nonce, - }; + let stream_id = HeightAndRound(self.height.block_number, self.round.as_u32().unwrap()); self.nonce += 1; - let bytes = prost::Message::encode_to_vec(&stream_id); + let bytes = Vec::::from(stream_id); StreamId::new(bytes.into()) } @@ -91,24 +132,31 @@ impl HostState { .find_map(|part| part.as_block_info()) .expect("BlockInfo part not found"); - let commitment = parts - .iter() - .find_map(|part| part.as_commitment()) - .expect("ProposalCommitment part not found"); + // XXX: Starknet interop + // let commitment = parts + // .iter() + // .find_map(|part| part.as_commitment()) + // .expect("ProposalCommitment part not found"); // Collect all transactions from the transaction parts // We expect that the transaction parts are ordered by sequence number but we don't have a way to check // this here, so we just collect them in the order. - let transactions: Vec = parts - .iter() - .filter_map(|part| part.as_transactions()) - .flat_map(|batch| batch.as_slice().iter().cloned()) - .collect(); + // XXX: Starknet interop + // let transactions: Vec = parts + // .iter() + // .filter_map(|part| part.as_transactions()) + // .flat_map(|batch| batch.as_slice().iter().cloned()) + // .collect(); + + // XXX: Starknet interop // Determine the validity of the proposal - let validity = self - .verify_proposal_validity(fin, commitment, transactions) - .await; + // let validity = self + // .verify_proposal_validity(fin, commitment, transactions) + // .await; + + // XXX: Starknet interop + let validity = Validity::Valid; let valid_round = init.valid_round; if valid_round.is_defined() { @@ -127,6 +175,8 @@ impl HostState { } } + // XXX: Starknet interop + #[allow(dead_code)] async fn verify_proposal_validity( &self, fin: &ProposalFin, @@ -214,10 +264,10 @@ impl HostState { return None; }; - let Some(_proposal_commitment) = parts.iter().find_map(|part| part.as_commitment()) else { - debug!("Proposal part has not been received yet: ProposalCommitment"); - return None; - }; + // let Some(_proposal_commitment) = parts.iter().find_map(|part| part.as_commitment()) else { + // debug!("Proposal part has not been received yet: ProposalCommitment"); + // 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(); diff --git a/code/crates/starknet/host/src/mempool_load.rs b/code/crates/starknet/host/src/mempool_load.rs index d424213f3..520f2e342 100644 --- a/code/crates/starknet/host/src/mempool_load.rs +++ b/code/crates/starknet/host/src/mempool_load.rs @@ -63,7 +63,7 @@ impl MempoolLoad { for _ in 0..count { let mut tx_bytes = vec![0; size.as_u64() as usize]; rng.fill_bytes(&mut tx_bytes); - let tx = Transaction::new(tx_bytes); + let tx = Transaction::dummy(tx_bytes); transactions.push(tx); } transactions diff --git a/code/crates/starknet/host/src/node.rs b/code/crates/starknet/host/src/node.rs index 690480eaf..80e99a9f1 100644 --- a/code/crates/starknet/host/src/node.rs +++ b/code/crates/starknet/host/src/node.rs @@ -34,10 +34,9 @@ pub struct PrivateKeyFile { pub address: Address, } -impl From for PrivateKeyFile { - fn from(private_key: PrivateKey) -> Self { +impl PrivateKeyFile { + pub fn new(address: Address, private_key: PrivateKey) -> Self { let public_key = private_key.public_key(); - let address = Address::from_public_key(public_key); Self { private_key, @@ -120,7 +119,7 @@ impl Node for StarknetNode { } fn get_address(&self, pk: &PublicKey) -> Address { - Address::from_public_key(*pk) + Address::from(pk) } fn get_public_key(&self, pk: &PrivateKey) -> PublicKey { @@ -156,6 +155,7 @@ impl Node for StarknetNode { let _enter = span.enter(); let priv_key_file = self.load_private_key_file()?; + let address = priv_key_file.address; let private_key = self.load_private_key(priv_key_file); let genesis = self.load_genesis()?; let tx_event = TxEvent::new(); @@ -167,6 +167,7 @@ impl Node for StarknetNode { self.home_dir.clone(), genesis.validator_set, private_key, + address, start_height, tx_event.clone(), span.clone(), @@ -197,7 +198,9 @@ impl CanGeneratePrivateKey for StarknetNode { impl CanMakePrivateKeyFile for StarknetNode { fn make_private_key_file(&self, private_key: PrivateKey) -> Self::PrivateKeyFile { - PrivateKeyFile::from(private_key) + let public_key = self.get_public_key(&private_key); + let address = self.get_address(&public_key); + PrivateKeyFile::new(address, private_key) } } @@ -205,7 +208,7 @@ impl CanMakeGenesis for StarknetNode { fn make_genesis(&self, validators: Vec<(PublicKey, VotingPower)>) -> Self::Genesis { let validators = validators .into_iter() - .map(|(pk, vp)| Validator::new(pk, vp)); + .map(|(pk, vp)| Validator::new(self.get_address(&pk), pk, vp)); let validator_set = ValidatorSet::new(validators); @@ -456,13 +459,18 @@ fn test_starknet_node() { use malachitebft_test_cli::*; let priv_keys = new::generate_private_keys(&node, 1, true); - let pub_keys = priv_keys.iter().map(|pk| node.get_public_key(pk)).collect(); + let pub_keys = priv_keys + .iter() + .map(|pk| node.get_public_key(pk)) + .collect::>(); + + let address = node.get_address(&pub_keys[0]); let genesis = new::generate_genesis(&node, pub_keys, true); file::save_priv_validator_key( &node, &node.private_key_file(), - &PrivateKeyFile::from(priv_keys[0].clone()), + &PrivateKeyFile::new(address, priv_keys[0].clone()), ) .unwrap(); diff --git a/code/crates/starknet/host/src/spawn.rs b/code/crates/starknet/host/src/spawn.rs index 760663117..7dfe22904 100644 --- a/code/crates/starknet/host/src/spawn.rs +++ b/code/crates/starknet/host/src/spawn.rs @@ -32,11 +32,13 @@ use crate::mempool_load::{MempoolLoad, MempoolLoadRef, Params}; use crate::types::MockContext; use crate::types::{Address, Height, PrivateKey, ValidatorSet}; +#[allow(clippy::too_many_arguments)] pub async fn spawn_node_actor( cfg: Config, home_dir: PathBuf, initial_validator_set: ValidatorSet, private_key: PrivateKey, + address: Address, start_height: Option, tx_event: TxEvent, span: tracing::Span, @@ -47,7 +49,6 @@ pub async fn spawn_node_actor( let registry = SharedRegistry::global().with_moniker(cfg.moniker.as_str()); let metrics = Metrics::register(®istry); - let address = Address::from_public_key(private_key.public_key()); let signing_provider = Ed25519Provider::new(private_key.clone()); // Spawn mempool and its gossip layer @@ -250,9 +251,10 @@ async fn spawn_network_actor( }, config::PubSubProtocol::Broadcast => gossip::GossipSubConfig::default(), }, + channel_names: malachitebft_network::ChannelNames::default(), rpc_max_size: cfg.consensus.p2p.rpc_max_size.as_u64() as usize, pubsub_max_size: cfg.consensus.p2p.pubsub_max_size.as_u64() as usize, - enable_sync: true, + enable_sync: cfg.value_sync.enabled, }; let keypair = make_keypair(private_key); diff --git a/code/crates/starknet/p2p-proto/proto/p2p/proto/consensus/consensus.proto b/code/crates/starknet/p2p-proto/proto/p2p/proto/consensus/consensus.proto index f8a83a82a..38729e354 100644 --- a/code/crates/starknet/p2p-proto/proto/p2p/proto/consensus/consensus.proto +++ b/code/crates/starknet/p2p-proto/proto/p2p/proto/consensus/consensus.proto @@ -1,12 +1,9 @@ syntax = "proto3"; - import "p2p/proto/common.proto"; import "p2p/proto/transaction.proto"; option go_package = "github.com/starknet-io/starknet-p2pspecs/p2p/proto/consensus/consensus"; -// WIP - will change - // Contains all variants of mempool and an L1Handler variant to cover all transactions that can be // in a new block. message ConsensusTransaction { @@ -29,36 +26,21 @@ message Vote { // We use a type field to distinguish between prevotes and precommits instead of different // messages, to make sure the data, and therefore the signatures, are unambiguous between // Prevote and Precommit. - VoteType vote_type = 1; - uint64 block_number = 3; - uint64 fork_id = 4; - uint32 round = 5; + VoteType vote_type = 2; + uint64 height = 3; + uint32 round = 4; // This is optional since a vote can be NIL. - optional Hash block_hash = 6; - // Identifies the voter. - Address voter = 7; -} - -// Streaming of proposals is done on the "consensus_proposal" topic. -message ConsensusStreamId { - uint64 height = 1; - uint32 round = 2; - uint64 nonce = 3; + optional Hash block_hash = 5; + Address voter = 6; } -// The timestamp of a proposal can impact consensus, specifically the lower bound applied. If nodes -// apply a lower bound validation based on their local time, then we risk a scenario where in round -// `R` proposal P is locked. Then in a later round the timestamp in P has gone stale. Therefore the -// lower bound should be "greater than the previous timestamp". Upper bounds don't suffer from this -// problem. -message ProposalPart { - oneof messages { - ProposalInit init = 1; - ProposalFin fin = 2; - BlockInfo block_info = 3; - TransactionBatch transactions = 4; - ProposalCommitment commitment = 5; +message StreamMessage { + oneof message { + bytes content = 1; + Fin fin = 2; } + bytes stream_id = 3; + uint64 message_id = 4; } message ProposalInit { @@ -68,58 +50,35 @@ message ProposalInit { Address proposer = 4; } -// Identifies the content proposed (and executed). Consensus is reached on the value contained here. -message ProposalFin { - Hash proposal_commitment = 1; +message BlockInfo { + uint64 height = 1; + uint64 timestamp = 2; + Address builder = 3; + L1DataAvailabilityMode l1_da_mode = 4; + Uint128 l2_gas_price_fri = 5; + Uint128 l1_gas_price_wei = 6; + Uint128 l1_data_gas_price_wei = 7; + uint64 eth_to_strk_rate = 8; } message TransactionBatch { repeated ConsensusTransaction transactions = 1; } -// The content and stream_id are generic fields. The user of the stream can choose to pass whatever -// message that they want. The messages are then encoded in bytes. -message StreamMessage { - oneof message { - bytes content = 1; - Fin fin = 2; - } - bytes stream_id = 3; - uint64 message_id = 4; -} - -message ProposalCommitment { - uint64 block_number = 1; - uint64 fork_id = 2; - Hash parent_commitment = 3; - Address builder = 4; - uint64 timestamp = 5; - string protocol_version = 6; // Starknet version - // State root of block `H-K`, where `K` is defined by the protocol's version. - Hash old_state_root = 7; - // The state diff commitment returned by the Starknet Feeder Gateway - Hash state_diff_commitment = 8; - Hash transaction_commitment = 9; - Hash event_commitment = 10; - Hash receipt_commitment = 11; - // TODO: Just put the sizes explicitly? This is relatively free compared actually hashing the - // lists we commit to. If not, should we also pack other fields? - Felt252 concatenated_counts = 12; - Uint128 l1_gas_price_fri = 13; - Uint128 l1_data_gas_price_fri = 14; - Uint128 l2_gas_price_fri = 15; - Uint128 l2_gas_used = 16; - L1DataAvailabilityMode l1_da_mode = 17; +message ProposalFin { + // Identifies a Starknet block based on the content streamed in the proposal. + Hash proposal_commitment = 1; } -message BlockInfo { - uint64 block_number = 1; - uint64 fork_id = 2; - Address builder = 3; - uint64 timestamp = 4; - Uint128 l2_gas_price_fri = 5; - Uint128 l1_gas_price_wei = 6; - Uint128 l1_data_gas_price_wei = 7; - Uint128 eth_to_strk_rate = 8; - L1DataAvailabilityMode l1_da_mode = 9; +// Network format: +// 1. First message is ProposalInit +// 2. Last message is ProposalFin +// 3. In between can be any number of other messages. +message ProposalPart { + oneof message { + ProposalInit init = 1; + ProposalFin fin = 2; + BlockInfo block_info = 3; + TransactionBatch transactions = 4; + } } diff --git a/code/crates/starknet/p2p-proto/proto/p2p/proto/transaction.proto b/code/crates/starknet/p2p-proto/proto/p2p/proto/transaction.proto index 1ef63c730..9dfef0552 100644 --- a/code/crates/starknet/p2p-proto/proto/p2p/proto/transaction.proto +++ b/code/crates/starknet/p2p-proto/proto/p2p/proto/transaction.proto @@ -5,7 +5,8 @@ import "p2p/proto/class.proto"; option go_package = "github.com/starknet-io/starknet-p2pspecs/p2p/proto/transaction"; message ResourceLimits { - Felt252 max_amount = 1; + // TODO(shahak, alonl): figure out if max_amount should be uint64 or Felt252 + uint64 max_amount = 1; Felt252 max_price_per_unit = 2; } diff --git a/code/crates/starknet/p2p-types/Cargo.toml b/code/crates/starknet/p2p-types/Cargo.toml index e87192c7d..b6a3253c9 100644 --- a/code/crates/starknet/p2p-types/Cargo.toml +++ b/code/crates/starknet/p2p-types/Cargo.toml @@ -18,6 +18,7 @@ starknet-crypto.workspace = true bytes.workspace = true rand.workspace = true +prost.workspace = true serde.workspace = true sha3.workspace = true diff --git a/code/crates/starknet/p2p-types/src/address.rs b/code/crates/starknet/p2p-types/src/address.rs index 37cf08beb..7ebaadc13 100644 --- a/code/crates/starknet/p2p-types/src/address.rs +++ b/code/crates/starknet/p2p-types/src/address.rs @@ -1,42 +1,58 @@ use bytes::Bytes; use core::fmt; +use malachitebft_signing_ed25519::PublicKey; use serde::{Deserialize, Serialize}; use malachitebft_proto::{Error as ProtoError, Protobuf}; use malachitebft_starknet_p2p_proto as p2p_proto; -use crate::PublicKey; +use crate::Felt; #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)] #[serde(transparent)] -pub struct Address(PublicKey); +pub struct Address(Felt); impl Address { - #[cfg_attr(coverage_nightly, coverage(off))] - pub fn new(bytes: [u8; 32]) -> Self { - Self::from_public_key(PublicKey::from_bytes(bytes)) + pub fn new(felt: Felt) -> Self { + Self(felt) } +} - #[cfg_attr(coverage_nightly, coverage(off))] - pub fn from_public_key(public_key: PublicKey) -> Self { - Self(public_key) +impl From for Address { + fn from(n: u64) -> Self { + Self(Felt::from(n)) + } +} + +impl From<[u8; 32]> for Address { + fn from(bytes: [u8; 32]) -> Self { + Self(Felt::from_bytes_be(&bytes)) + } +} + +impl From for Address { + fn from(public_key: PublicKey) -> Self { + Self::from(*public_key.as_bytes()) + } +} + +impl From<&PublicKey> for Address { + fn from(public_key: &PublicKey) -> Self { + Self::from(*public_key.as_bytes()) } } impl fmt::Display for Address { #[cfg_attr(coverage_nightly, coverage(off))] fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - for byte in self.0.as_bytes().iter() { - write!(f, "{:02X}", byte)?; - } - Ok(()) + write!(f, "{:#x}", self.0) } } impl fmt::Debug for Address { #[cfg_attr(coverage_nightly, coverage(off))] fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "Address({})", self) + write!(f, "Address({:#x})", self.0) } } @@ -46,21 +62,20 @@ impl Protobuf for Address { type Proto = p2p_proto::Address; fn from_proto(proto: Self::Proto) -> Result { + let mut felt = [0; 32]; if proto.elements.len() != 32 { - return Err(ProtoError::Other(format!( - "Invalid address length: expected 32, got {}", - proto.elements.len() - ))); + return Err(ProtoError::invalid_data::("elements")); } - let mut bytes = [0; 32]; - bytes.copy_from_slice(&proto.elements); - Ok(Address::new(bytes)) + felt.copy_from_slice(&proto.elements); + + let hash = Felt::from_bytes_be(&felt); + Ok(Self(hash)) } fn to_proto(&self) -> Result { Ok(p2p_proto::Address { - elements: Bytes::copy_from_slice(self.0.as_bytes().as_slice()), + elements: Bytes::from(self.0.to_bytes_be().to_vec()), }) } } diff --git a/code/crates/starknet/p2p-types/src/block_info.rs b/code/crates/starknet/p2p-types/src/block_info.rs index ff22adbd3..98d7c71ea 100644 --- a/code/crates/starknet/p2p-types/src/block_info.rs +++ b/code/crates/starknet/p2p-types/src/block_info.rs @@ -12,7 +12,7 @@ pub struct BlockInfo { pub l1_gas_price_wei: u128, pub l1_data_gas_price_wei: u128, pub l2_gas_price_fri: u128, - pub eth_to_strk_rate: u128, + pub eth_to_strk_rate: u64, pub l1_da_mode: L1DataAvailabilityMode, } @@ -21,7 +21,7 @@ impl Protobuf for BlockInfo { fn from_proto(proto: Self::Proto) -> Result { Ok(Self { - height: Height::new(proto.block_number, proto.fork_id), + height: Height::new(proto.height, 0), builder: Address::from_proto( proto .builder @@ -40,24 +40,22 @@ impl Protobuf for BlockInfo { .l2_gas_price_fri .ok_or_else(|| ProtoError::missing_field::("l2_gas_price_fri"))? .into(), - eth_to_strk_rate: proto - .eth_to_strk_rate - .ok_or_else(|| ProtoError::missing_field::("eth_to_strk_rate"))? - .into(), + eth_to_strk_rate: proto.eth_to_strk_rate, l1_da_mode: L1DataAvailabilityMode::from_proto(proto.l1_da_mode)?, }) } fn to_proto(&self) -> Result { Ok(Self::Proto { - block_number: self.height.block_number, - fork_id: self.height.fork_id, + height: self.height.block_number, + // block_number: self.height.block_number, + // fork_id: self.height.fork_id, builder: Some(self.builder.to_proto()?), timestamp: self.timestamp, l2_gas_price_fri: Some(self.l2_gas_price_fri.into()), l1_gas_price_wei: Some(self.l1_gas_price_wei.into()), l1_data_gas_price_wei: Some(self.l1_data_gas_price_wei.into()), - eth_to_strk_rate: Some(self.eth_to_strk_rate.into()), + eth_to_strk_rate: self.eth_to_strk_rate, l1_da_mode: self.l1_da_mode.to_proto()?, }) } diff --git a/code/crates/starknet/p2p-types/src/context.rs b/code/crates/starknet/p2p-types/src/context.rs index ec13f4b8c..40efbc5a2 100644 --- a/code/crates/starknet/p2p-types/src/context.rs +++ b/code/crates/starknet/p2p-types/src/context.rs @@ -42,7 +42,7 @@ impl Context for MockContext { let height = height.as_u64() as usize; let round = round.as_i64() as usize; - (height - 1 + round) % validator_set.count() + (height + round) % validator_set.count() }; validator_set diff --git a/code/crates/starknet/p2p-types/src/height.rs b/code/crates/starknet/p2p-types/src/height.rs index 62b4c8c70..adf1bdcf9 100644 --- a/code/crates/starknet/p2p-types/src/height.rs +++ b/code/crates/starknet/p2p-types/src/height.rs @@ -46,7 +46,7 @@ impl fmt::Display for Height { impl malachitebft_core_types::Height for Height { const ZERO: Self = Self::new(0, 0); - const INITIAL: Self = Self::new(1, 0); + const INITIAL: Self = Self::new(0, 0); fn increment_by(&self, n: u64) -> Self { Self { diff --git a/code/crates/starknet/p2p-types/src/proposal_commitment.rs b/code/crates/starknet/p2p-types/src/proposal_commitment.rs index 1a8107dfe..735c6595e 100644 --- a/code/crates/starknet/p2p-types/src/proposal_commitment.rs +++ b/code/crates/starknet/p2p-types/src/proposal_commitment.rs @@ -1,7 +1,7 @@ use malachitebft_proto::{Error as ProtoError, Protobuf}; use malachitebft_starknet_p2p_proto::{self as p2p_proto}; -use crate::felt::FeltExt; +// use crate::felt::FeltExt; use crate::{Address, Felt, Hash, Height}; #[derive(Clone, Debug, PartialEq, Eq)] @@ -52,89 +52,89 @@ impl Protobuf for L1DataAvailabilityMode { } } -impl Protobuf for ProposalCommitment { - type Proto = p2p_proto::ProposalCommitment; - - fn from_proto(proto: Self::Proto) -> Result { - Ok(Self { - height: Height::new(proto.block_number, proto.fork_id), - parent_commitment: Hash::from_proto( - proto - .parent_commitment - .ok_or_else(|| ProtoError::missing_field::("parent_commitment"))?, - )?, - builder: Address::from_proto( - proto - .builder - .ok_or_else(|| ProtoError::missing_field::("builder"))?, - )?, - timestamp: proto.timestamp, - protocol_version: proto.protocol_version, - old_state_root: Hash::from_proto( - proto - .old_state_root - .ok_or_else(|| ProtoError::missing_field::("old_state_root"))?, - )?, - state_diff_commitment: Hash::from_proto(proto.state_diff_commitment.ok_or_else( - || ProtoError::missing_field::("state_diff_commitment"), - )?)?, - transaction_commitment: Hash::from_proto(proto.transaction_commitment.ok_or_else( - || ProtoError::missing_field::("transaction_commitment"), - )?)?, - event_commitment: Hash::from_proto( - proto - .event_commitment - .ok_or_else(|| ProtoError::missing_field::("event_commitment"))?, - )?, - receipt_commitment: Hash::from_proto( - proto.receipt_commitment.ok_or_else(|| { - ProtoError::missing_field::("receipt_commitment") - })?, - )?, - concatenated_counts: Felt::from_proto( - proto.concatenated_counts.ok_or_else(|| { - ProtoError::missing_field::("concatenated_counts") - })?, - )?, - l1_gas_price_fri: proto - .l1_gas_price_fri - .ok_or_else(|| ProtoError::missing_field::("l1_gas_price_fri"))? - .into(), - l1_data_gas_price_fri: proto - .l1_data_gas_price_fri - .ok_or_else(|| ProtoError::missing_field::("l1_data_gas_price_fri"))? - .into(), - l2_gas_price_fri: proto - .l2_gas_price_fri - .ok_or_else(|| ProtoError::missing_field::("l2_gas_price_fri"))? - .into(), - l2_gas_used: proto - .l2_gas_used - .ok_or_else(|| ProtoError::missing_field::("l2_gas_used"))? - .into(), - l1_da_mode: L1DataAvailabilityMode::from_proto(proto.l1_da_mode)?, - }) - } - - fn to_proto(&self) -> Result { - Ok(Self::Proto { - block_number: self.height.block_number, - fork_id: self.height.fork_id, - parent_commitment: Some(self.parent_commitment.to_proto()?), - builder: Some(self.builder.to_proto()?), - timestamp: self.timestamp, - protocol_version: self.protocol_version.clone(), - old_state_root: Some(self.old_state_root.to_proto()?), - state_diff_commitment: Some(self.state_diff_commitment.to_proto()?), - transaction_commitment: Some(self.transaction_commitment.to_proto()?), - event_commitment: Some(self.event_commitment.to_proto()?), - receipt_commitment: Some(self.receipt_commitment.to_proto()?), - concatenated_counts: Some(self.concatenated_counts.to_proto()?), - l1_gas_price_fri: Some(self.l1_gas_price_fri.into()), - l1_data_gas_price_fri: Some(self.l1_data_gas_price_fri.into()), - l2_gas_price_fri: Some(self.l2_gas_price_fri.into()), - l2_gas_used: Some(self.l2_gas_used.into()), - l1_da_mode: self.l1_da_mode.to_proto()?, - }) - } -} +// impl Protobuf for ProposalCommitment { +// type Proto = p2p_proto::ProposalCommitment; +// +// fn from_proto(proto: Self::Proto) -> Result { +// Ok(Self { +// height: Height::new(proto.block_number, proto.fork_id), +// parent_commitment: Hash::from_proto( +// proto +// .parent_commitment +// .ok_or_else(|| ProtoError::missing_field::("parent_commitment"))?, +// )?, +// builder: Address::from_proto( +// proto +// .builder +// .ok_or_else(|| ProtoError::missing_field::("builder"))?, +// )?, +// timestamp: proto.timestamp, +// protocol_version: proto.protocol_version, +// old_state_root: Hash::from_proto( +// proto +// .old_state_root +// .ok_or_else(|| ProtoError::missing_field::("old_state_root"))?, +// )?, +// state_diff_commitment: Hash::from_proto(proto.state_diff_commitment.ok_or_else( +// || ProtoError::missing_field::("state_diff_commitment"), +// )?)?, +// transaction_commitment: Hash::from_proto(proto.transaction_commitment.ok_or_else( +// || ProtoError::missing_field::("transaction_commitment"), +// )?)?, +// event_commitment: Hash::from_proto( +// proto +// .event_commitment +// .ok_or_else(|| ProtoError::missing_field::("event_commitment"))?, +// )?, +// receipt_commitment: Hash::from_proto( +// proto.receipt_commitment.ok_or_else(|| { +// ProtoError::missing_field::("receipt_commitment") +// })?, +// )?, +// concatenated_counts: Felt::from_proto( +// proto.concatenated_counts.ok_or_else(|| { +// ProtoError::missing_field::("concatenated_counts") +// })?, +// )?, +// l1_gas_price_fri: proto +// .l1_gas_price_fri +// .ok_or_else(|| ProtoError::missing_field::("l1_gas_price_fri"))? +// .into(), +// l1_data_gas_price_fri: proto +// .l1_data_gas_price_fri +// .ok_or_else(|| ProtoError::missing_field::("l1_data_gas_price_fri"))? +// .into(), +// l2_gas_price_fri: proto +// .l2_gas_price_fri +// .ok_or_else(|| ProtoError::missing_field::("l2_gas_price_fri"))? +// .into(), +// l2_gas_used: proto +// .l2_gas_used +// .ok_or_else(|| ProtoError::missing_field::("l2_gas_used"))? +// .into(), +// l1_da_mode: L1DataAvailabilityMode::from_proto(proto.l1_da_mode)?, +// }) +// } +// +// fn to_proto(&self) -> Result { +// Ok(Self::Proto { +// block_number: self.height.block_number, +// fork_id: self.height.fork_id, +// parent_commitment: Some(self.parent_commitment.to_proto()?), +// builder: Some(self.builder.to_proto()?), +// timestamp: self.timestamp, +// protocol_version: self.protocol_version.clone(), +// old_state_root: Some(self.old_state_root.to_proto()?), +// state_diff_commitment: Some(self.state_diff_commitment.to_proto()?), +// transaction_commitment: Some(self.transaction_commitment.to_proto()?), +// event_commitment: Some(self.event_commitment.to_proto()?), +// receipt_commitment: Some(self.receipt_commitment.to_proto()?), +// concatenated_counts: Some(self.concatenated_counts.to_proto()?), +// l1_gas_price_fri: Some(self.l1_gas_price_fri.into()), +// l1_data_gas_price_fri: Some(self.l1_data_gas_price_fri.into()), +// l2_gas_price_fri: Some(self.l2_gas_price_fri.into()), +// l2_gas_used: Some(self.l2_gas_used.into()), +// l1_da_mode: self.l1_da_mode.to_proto()?, +// }) +// } +// } diff --git a/code/crates/starknet/p2p-types/src/proposal_part.rs b/code/crates/starknet/p2p-types/src/proposal_part.rs index be4140e02..8d38b5384 100644 --- a/code/crates/starknet/p2p-types/src/proposal_part.rs +++ b/code/crates/starknet/p2p-types/src/proposal_part.rs @@ -3,7 +3,7 @@ use malachitebft_core_types::Round; use malachitebft_proto as proto; use malachitebft_starknet_p2p_proto::{self as p2p_proto}; -use crate::{Address, BlockInfo, Hash, Height, ProposalCommitment, TransactionBatch}; +use crate::{Address, BlockInfo, Hash, Height, TransactionBatch}; #[derive(Clone, Debug, PartialEq, Eq)] pub struct ProposalInit { @@ -23,7 +23,7 @@ pub enum ProposalPart { Init(ProposalInit), BlockInfo(BlockInfo), Transactions(TransactionBatch), - Commitment(Box), + // Commitment(Box), Fin(ProposalFin), } @@ -32,7 +32,7 @@ pub enum PartType { Init, BlockInfo, Transactions, - ProposalCommitment, + // ProposalCommitment, Fin, } @@ -42,7 +42,7 @@ impl ProposalPart { Self::Init(_) => PartType::Init, Self::BlockInfo(_) => PartType::BlockInfo, Self::Transactions(_) => PartType::Transactions, - Self::Commitment(_) => PartType::ProposalCommitment, + // Self::Commitment(_) => PartType::ProposalCommitment, Self::Fin(_) => PartType::Fin, } } @@ -86,13 +86,13 @@ impl ProposalPart { } } - pub fn as_commitment(&self) -> Option<&ProposalCommitment> { - if let Self::Commitment(v) = self { - Some(v) - } else { - None - } - } + // pub fn as_commitment(&self) -> Option<&ProposalCommitment> { + // if let Self::Commitment(v) = self { + // Some(v) + // } else { + // None + // } + // } pub fn as_fin(&self) -> Option<&ProposalFin> { if let Self::Fin(v) = self { @@ -108,14 +108,14 @@ impl proto::Protobuf for ProposalPart { #[cfg_attr(coverage_nightly, coverage(off))] fn from_proto(proto: Self::Proto) -> Result { - use p2p_proto::proposal_part::Messages; + use p2p_proto::proposal_part::Message; let message = proto - .messages - .ok_or_else(|| proto::Error::missing_field::("messages"))?; + .message + .ok_or_else(|| proto::Error::missing_field::("message"))?; Ok(match message { - Messages::Init(init) => ProposalPart::Init(ProposalInit { + Message::Init(init) => ProposalPart::Init(ProposalInit { height: Height::new(init.height, 0), round: Round::new(init.round), valid_round: init.valid_round.into(), @@ -125,20 +125,19 @@ impl proto::Protobuf for ProposalPart { )?, }), - Messages::BlockInfo(block_info) => { + Message::BlockInfo(block_info) => { ProposalPart::BlockInfo(BlockInfo::from_proto(block_info)?) } - Messages::Transactions(txes) => { + Message::Transactions(txes) => { let transactions = TransactionBatch::from_proto(txes)?; ProposalPart::Transactions(transactions) } - Messages::Commitment(commitment) => { - ProposalPart::Commitment(Box::new(ProposalCommitment::from_proto(commitment)?)) - } - - Messages::Fin(fin) => ProposalPart::Fin(ProposalFin { + // Message::Commitment(commitment) => { + // ProposalPart::Commitment(Box::new(ProposalCommitment::from_proto(commitment)?)) + // } + Message::Fin(fin) => ProposalPart::Fin(ProposalFin { proposal_commitment_hash: Hash::from_proto(fin.proposal_commitment.ok_or_else( || proto::Error::missing_field::("proposal_commitment"), )?)?, @@ -148,18 +147,18 @@ impl proto::Protobuf for ProposalPart { #[cfg_attr(coverage_nightly, coverage(off))] fn to_proto(&self) -> Result { - use p2p_proto::proposal_part::Messages; + use p2p_proto::proposal_part::Message; let message = match self { - ProposalPart::Init(init) => Messages::Init(p2p_proto::ProposalInit { + ProposalPart::Init(init) => Message::Init(p2p_proto::ProposalInit { height: init.height.block_number, round: init.round.as_u32().expect("round should not be nil"), valid_round: init.valid_round.as_u32(), proposer: Some(init.proposer.to_proto()?), }), - ProposalPart::BlockInfo(block_info) => Messages::BlockInfo(block_info.to_proto()?), + ProposalPart::BlockInfo(block_info) => Message::BlockInfo(block_info.to_proto()?), ProposalPart::Transactions(txes) => { - Messages::Transactions(p2p_proto::TransactionBatch { + Message::Transactions(p2p_proto::TransactionBatch { transactions: txes .as_slice() .iter() @@ -167,14 +166,14 @@ impl proto::Protobuf for ProposalPart { .collect::, _>>()?, }) } - ProposalPart::Commitment(commitment) => Messages::Commitment(commitment.to_proto()?), - ProposalPart::Fin(fin) => Messages::Fin(p2p_proto::ProposalFin { + // ProposalPart::Commitment(commitment) => Message::Commitment(commitment.to_proto()?), + ProposalPart::Fin(fin) => Message::Fin(p2p_proto::ProposalFin { proposal_commitment: Some(fin.proposal_commitment_hash.to_proto()?), }), }; Ok(p2p_proto::ProposalPart { - messages: Some(message), + message: Some(message), }) } } diff --git a/code/crates/starknet/p2p-types/src/transaction.rs b/code/crates/starknet/p2p-types/src/transaction.rs index ac4864748..a0e3e24c8 100644 --- a/code/crates/starknet/p2p-types/src/transaction.rs +++ b/code/crates/starknet/p2p-types/src/transaction.rs @@ -1,5 +1,3 @@ -use core::fmt; - use bytes::Bytes; use malachitebft_proto::{self as proto}; use malachitebft_starknet_p2p_proto as p2p_proto; @@ -7,38 +5,31 @@ use malachitebft_starknet_p2p_proto as p2p_proto; use crate::Hash; /// Transaction -#[derive(Clone, PartialEq, Eq, Ord, PartialOrd)] -pub struct Transaction { - data: Bytes, - hash: Hash, -} +#[derive(Clone, Debug, PartialEq)] +pub struct Transaction(Box); impl Transaction { - /// Create a new transaction from bytes - pub fn new(data: impl Into) -> Self { - let data = data.into(); - let hash = Self::compute_hash(&data); - Self { data, hash } - } - - /// Get bytes from a transaction - pub fn to_bytes(&self) -> Bytes { - self.data.clone() + /// Create a new transaction from a protobuf message + pub fn new(tx: p2p_proto::ConsensusTransaction) -> Self { + Self(Box::new(tx)) } - /// Get bytes from a transaction - pub fn as_bytes(&self) -> &[u8] { - self.data.as_ref() + /// Crate a new transaction from a bytes + pub fn dummy(bytes: impl Into) -> Self { + Self::new(p2p_proto::ConsensusTransaction { + txn: Some(p2p_proto::consensus_transaction::Txn::Dummy(bytes.into())), + transaction_hash: None, + }) } - /// Size of this transaction in bytes + /// Compute the size of this transaction in bytes pub fn size_bytes(&self) -> usize { - self.data.len() + prost::Message::encoded_len(&self.0) } - /// Hash of this transaction + /// Compute the hash of this transaction pub fn hash(&self) -> Hash { - self.hash + Self::compute_hash(&prost::Message::encode_to_vec(&self.0)) } /// Compute the hash of a transaction @@ -52,47 +43,20 @@ impl Transaction { } } -impl fmt::Debug for Transaction { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(f, "Transaction({}, {} bytes)", self.hash, self.size_bytes()) - } -} - impl proto::Protobuf for Transaction { type Proto = p2p_proto::ConsensusTransaction; fn from_proto(proto: Self::Proto) -> Result { - use malachitebft_starknet_p2p_proto::consensus_transaction::Txn; - - let txn = proto - .txn - .ok_or_else(|| proto::Error::missing_field::("txn"))?; - - let hash = proto - .transaction_hash - .ok_or_else(|| proto::Error::missing_field::("transaction_hash"))?; - - match txn { - Txn::Dummy(bytes) => Ok(Self { - data: bytes, - hash: Hash::from_proto(hash)?, - }), - _ => Err(proto::Error::invalid_data::( - "unknown transaction type", - )), - } + Ok(Self(Box::new(proto))) } fn to_proto(&self) -> Result { - use malachitebft_starknet_p2p_proto::consensus_transaction::Txn; - - Ok(Self::Proto { - transaction_hash: Some(self.hash.to_proto()?), - txn: Some(Txn::Dummy(self.to_bytes())), - }) + Ok(*self.0.clone()) } } +impl Eq for Transaction {} + /// Transaction batch (used by mempool and proposal part) #[derive(Clone, Debug, Default, PartialEq, Eq)] pub struct TransactionBatch(Vec); diff --git a/code/crates/starknet/p2p-types/src/validator.rs b/code/crates/starknet/p2p-types/src/validator.rs index 0de8d1c7e..83a2e3683 100644 --- a/code/crates/starknet/p2p-types/src/validator.rs +++ b/code/crates/starknet/p2p-types/src/validator.rs @@ -13,9 +13,9 @@ pub struct Validator { impl Validator { #[cfg_attr(coverage_nightly, coverage(off))] - pub fn new(public_key: PublicKey, voting_power: VotingPower) -> Self { + pub fn new(address: Address, public_key: PublicKey, voting_power: VotingPower) -> Self { Self { - address: Address::from_public_key(public_key), + address, public_key, voting_power, } diff --git a/code/crates/starknet/p2p-types/src/validator_set.rs b/code/crates/starknet/p2p-types/src/validator_set.rs index 2640e74fd..90bc886b5 100644 --- a/code/crates/starknet/p2p-types/src/validator_set.rs +++ b/code/crates/starknet/p2p-types/src/validator_set.rs @@ -13,8 +13,7 @@ pub struct ValidatorSet { impl ValidatorSet { pub fn new(validators: impl IntoIterator) -> Self { - let mut validators: Vec<_> = validators.into_iter().collect(); - ValidatorSet::sort_validators(&mut validators); + let validators: Vec<_> = validators.into_iter().collect(); assert!(!validators.is_empty()); @@ -37,20 +36,20 @@ impl ValidatorSet { self.validators.iter().find(|v| &v.public_key == public_key) } - /// In place sort and deduplication of a list of validators - fn sort_validators(vals: &mut Vec) { - // Sort the validators according to the current Tendermint requirements - use core::cmp::Reverse; - - // first by validator power descending, then by address ascending - vals.sort_unstable_by(|v1, v2| { - let a = (Reverse(v1.voting_power), &v1.address); - let b = (Reverse(v2.voting_power), &v2.address); - a.cmp(&b) - }); - - vals.dedup(); - } + // /// In place sort and deduplication of a list of validators + // fn sort_validators(vals: &mut Vec) { + // // Sort the validators according to the current Tendermint requirements + // use core::cmp::Reverse; + // + // // first by validator power descending, then by address ascending + // vals.sort_unstable_by(|v1, v2| { + // let a = (Reverse(v1.voting_power), &v1.address); + // let b = (Reverse(v2.voting_power), &v2.address); + // a.cmp(&b) + // }); + // + // vals.dedup(); + // } pub fn get_keys(&self) -> Vec { self.validators.iter().map(|v| v.public_key).collect() diff --git a/code/crates/starknet/p2p-types/src/vote.rs b/code/crates/starknet/p2p-types/src/vote.rs index e1d54a923..382fc20ef 100644 --- a/code/crates/starknet/p2p-types/src/vote.rs +++ b/code/crates/starknet/p2p-types/src/vote.rs @@ -60,7 +60,8 @@ impl proto::Protobuf for Vote { Ok(Self { vote_type, - height: Height::new(proto.block_number, proto.fork_id), + // height: Height::new(proto.block_number, proto.fork_id), + height: Height::new(proto.height, 0), round: Round::new(proto.round), block_hash: match proto.block_hash { Some(block_hash) => NilOrVal::Val(BlockHash::from_proto(block_hash)?), @@ -78,8 +79,9 @@ impl proto::Protobuf for Vote { fn to_proto(&self) -> Result { Ok(Self::Proto { vote_type: common_to_proto_vote_type(self.vote_type).into(), - block_number: self.height.block_number, - fork_id: self.height.fork_id, + height: self.height.block_number, + // block_number: self.height.block_number, + // fork_id: self.height.fork_id, round: self.round.as_u32().expect("round should not be nil"), block_hash: match &self.block_hash { NilOrVal::Nil => None, diff --git a/code/crates/starknet/test/mbt/src/tests/streaming/utils.rs b/code/crates/starknet/test/mbt/src/tests/streaming/utils.rs index 6f60ac163..4f7880956 100644 --- a/code/crates/starknet/test/mbt/src/tests/streaming/utils.rs +++ b/code/crates/starknet/test/mbt/src/tests/streaming/utils.rs @@ -4,7 +4,7 @@ use crate::streaming::{Buffer, Message}; use malachitebft_core_types::Round; use malachitebft_engine::util::streaming::{Sequence, StreamId}; use malachitebft_engine::util::streaming::{StreamContent, StreamMessage}; -use malachitebft_starknet_host::types::{PrivateKey, TransactionBatch}; +use malachitebft_starknet_host::types::TransactionBatch; use malachitebft_starknet_host::{ streaming::MinHeap, types::{Address, Height, ProposalInit, ProposalPart, Transaction}, @@ -73,14 +73,7 @@ pub fn init_message_to_proposal_init(message: &Option) -> Option ProposalInit { - let bytes: [u8; 32] = [ - 0x08, 0xd7, 0xa2, 0x0f, 0x32, 0x0c, 0x4d, 0x23, 0xd9, 0xad, 0xf3, 0x29, 0xf5, 0x7c, 0x7b, - 0x62, 0x35, 0x9d, 0x97, 0xce, 0x0b, 0xb3, 0xb7, 0x66, 0x19, 0xd8, 0x50, 0x4d, 0x59, 0xa1, - 0x88, 0x4b, - ]; - let private_key = PrivateKey::from(bytes); - - let proposer_addr = Address::new(*private_key.public_key().as_bytes()); + let proposer_addr = Address::from(0x65); let height = Height { block_number: 1, @@ -99,9 +92,9 @@ pub fn generate_dummy_proposal_init() -> ProposalInit { } pub fn generate_dummy_transactions() -> TransactionBatch { - let tx1 = Transaction::new(vec![0x01, 0x02, 0x03]); - let tx2 = Transaction::new(vec![0x04, 0x05, 0x06]); - let tx3 = Transaction::new(vec![0x07, 0x08, 0x09]); + let tx1 = Transaction::dummy(vec![0x01, 0x02, 0x03]); + let tx2 = Transaction::dummy(vec![0x04, 0x05, 0x06]); + let tx3 = Transaction::dummy(vec![0x07, 0x08, 0x09]); TransactionBatch::new(vec![tx1, tx2, tx3]) } diff --git a/code/crates/starknet/test/src/lib.rs b/code/crates/starknet/test/src/lib.rs index 3976cd746..12d0c7f02 100644 --- a/code/crates/starknet/test/src/lib.rs +++ b/code/crates/starknet/test/src/lib.rs @@ -11,7 +11,9 @@ use rand::SeedableRng; use malachitebft_config::mempool_load::UniformLoadConfig; use malachitebft_starknet_host::config::Config; use malachitebft_starknet_host::node::{ConfigSource, Handle, StarknetNode}; -use malachitebft_starknet_host::types::{Height, MockContext, PrivateKey, Validator, ValidatorSet}; +use malachitebft_starknet_host::types::{ + Address, Height, MockContext, PrivateKey, Validator, ValidatorSet, +}; use malachitebft_test_framework::HasTestRunner; use malachitebft_test_framework::{NodeRunner, TestNode}; @@ -49,7 +51,7 @@ pub struct TestRunner { fn temp_dir(id: NodeId) -> PathBuf { TempDir::with_prefix(format!("malachitebft-test-app-{id}-")) .unwrap() - .into_path() + .keep() } #[async_trait] @@ -217,7 +219,8 @@ fn make_validators( for node in nodes { let sk = PrivateKey::generate(&mut rng); - let val = Validator::new(sk.public_key(), node.voting_power); + let address = Address::from(sk.public_key()); + let val = Validator::new(address, sk.public_key(), node.voting_power); private_keys.insert(node.id, sk); diff --git a/code/crates/starknet/test/src/tests/n3f0.rs b/code/crates/starknet/test/src/tests/n3f0.rs index 1d6d75601..faf3b8d9c 100644 --- a/code/crates/starknet/test/src/tests/n3f0.rs +++ b/code/crates/starknet/test/src/tests/n3f0.rs @@ -1,5 +1,7 @@ use std::time::Duration; +use malachitebft_test_framework::TestParams; + use crate::TestBuilder; #[tokio::test] @@ -12,5 +14,10 @@ pub async fn all_correct_nodes() { test.add_node().start().wait_until(HEIGHT).success(); test.add_node().start().wait_until(HEIGHT).success(); - test.build().run(Duration::from_secs(30)).await + test.build() + .run_with_params( + Duration::from_secs(30), // Timeout for the whole test + TestParams::default(), + ) + .await } diff --git a/code/crates/test/app/src/app.rs b/code/crates/test/app/src/app.rs index 026828bc9..62f148911 100644 --- a/code/crates/test/app/src/app.rs +++ b/code/crates/test/app/src/app.rs @@ -56,9 +56,10 @@ pub async fn run( height, round, proposer, + role, reply_value, } => { - info!(%height, %round, %proposer, "Started round"); + info!(%height, %round, %proposer, ?role, "Started round"); // We can use that opportunity to update our internal state state.current_height = height; diff --git a/code/crates/test/app/src/state.rs b/code/crates/test/app/src/state.rs index 0bd2a87a1..4f271e93f 100644 --- a/code/crates/test/app/src/state.rs +++ b/code/crates/test/app/src/state.rs @@ -10,7 +10,7 @@ use rand::{Rng, SeedableRng}; use sha3::Digest; use tracing::{debug, error}; -use malachitebft_app_channel::app::consensus::ProposedValue; +use malachitebft_app_channel::app::consensus::{ProposedValue, Role}; use malachitebft_app_channel::app::streaming::{StreamContent, StreamId, StreamMessage}; use malachitebft_app_channel::app::types::codec::Codec; use malachitebft_app_channel::app::types::core::{CommitCertificate, Round, Validity}; @@ -38,6 +38,7 @@ pub struct State { pub current_height: Height, pub current_round: Round, pub current_proposer: Option
, + pub current_role: Role, pub peers: HashSet, pub store: Store, @@ -67,6 +68,7 @@ impl State { current_height: height, current_round: Round::new(0), current_proposer: None, + current_role: Role::None, streams_map: PartStreamsMap::new(), rng: StdRng::from_entropy(), peers: HashSet::new(), diff --git a/code/crates/test/app/src/store.rs b/code/crates/test/app/src/store.rs index 3ac886391..b2559dd9c 100644 --- a/code/crates/test/app/src/store.rs +++ b/code/crates/test/app/src/store.rs @@ -50,7 +50,7 @@ pub enum StoreError { Commit(#[from] redb::CommitError), #[error("Transaction error: {0}")] - Transaction(#[from] redb::TransactionError), + Transaction(#[from] Box), #[error("Failed to encode/decode Protobuf: {0}")] Protobuf(#[from] ProtoError), @@ -59,6 +59,12 @@ pub enum StoreError { TaskJoin(#[from] tokio::task::JoinError), } +impl From for StoreError { + fn from(err: redb::TransactionError) -> Self { + Self::Transaction(Box::new(err)) + } +} + const CERTIFICATES_TABLE: redb::TableDefinition> = redb::TableDefinition::new("certificates"); diff --git a/code/crates/test/cli/src/cmd/distributed_testnet.rs b/code/crates/test/cli/src/cmd/distributed_testnet.rs index 48ef1e8bb..95c3f933e 100644 --- a/code/crates/test/cli/src/cmd/distributed_testnet.rs +++ b/code/crates/test/cli/src/cmd/distributed_testnet.rs @@ -178,7 +178,7 @@ where &N::make_distributed_config(i, nodes, machines.clone(), bootstrap_set_size, settings), )?; - let priv_validator_key = node.make_private_key_file((*private_key).clone()); + let priv_validator_key = node.make_private_key_file(private_key.clone()); save_priv_validator_key( node, &args.get_priv_validator_key_file_path()?, diff --git a/code/crates/test/cli/src/cmd/testnet.rs b/code/crates/test/cli/src/cmd/testnet.rs index f83a2daea..8f94c9121 100644 --- a/code/crates/test/cli/src/cmd/testnet.rs +++ b/code/crates/test/cli/src/cmd/testnet.rs @@ -179,7 +179,7 @@ where )?; // Save private key - let priv_validator_key = node.make_private_key_file((*private_key).clone()); + let priv_validator_key = node.make_private_key_file(private_key.clone()); save_priv_validator_key( node, &args.get_priv_validator_key_file_path()?, diff --git a/code/crates/test/framework/src/lib.rs b/code/crates/test/framework/src/lib.rs index 8b62bfac5..559cd7d60 100644 --- a/code/crates/test/framework/src/lib.rs +++ b/code/crates/test/framework/src/lib.rs @@ -292,11 +292,11 @@ where return TestResult::Failure(failure); } - let Event::StartedRound(_, round) = event else { + let Event::StartedRound(_, round, _, role) = event else { continue 'inner; }; - info!("Node started round {round}"); + info!(%round, ?role, "Node started round"); if round.as_u32() == Some(target_round) { break 'inner; diff --git a/code/crates/test/mempool/src/behaviour.rs b/code/crates/test/mempool/src/behaviour.rs index 694e26b08..9b9b1126c 100644 --- a/code/crates/test/mempool/src/behaviour.rs +++ b/code/crates/test/mempool/src/behaviour.rs @@ -31,6 +31,7 @@ fn message_id(message: &gossipsub::Message) -> gossipsub::MessageId { fn gossipsub_config() -> gossipsub::Config { gossipsub::ConfigBuilder::default() + .protocol_id_prefix("/meshsub") .max_transmit_size(MAX_TRANSMIT_SIZE) .opportunistic_graft_ticks(3) .heartbeat_interval(Duration::from_secs(1)) diff --git a/code/crates/test/tests/it/main.rs b/code/crates/test/tests/it/main.rs index 7f68d0813..19eebfe58 100644 --- a/code/crates/test/tests/it/main.rs +++ b/code/crates/test/tests/it/main.rs @@ -55,7 +55,7 @@ pub struct TestRunner { fn temp_dir(id: NodeId) -> PathBuf { TempDir::with_prefix(format!("malachitebft-test-app-{id}")) .unwrap() - .into_path() + .keep() } #[derive(Clone)] diff --git a/code/crates/wal/benches/wal.rs b/code/crates/wal/benches/wal.rs index c7a4ce069..28111d092 100644 --- a/code/crates/wal/benches/wal.rs +++ b/code/crates/wal/benches/wal.rs @@ -1,7 +1,8 @@ use std::fs; +use std::hint::black_box; use std::path::PathBuf; -use criterion::{black_box, criterion_group, criterion_main, BenchmarkId, Criterion, Throughput}; +use criterion::{criterion_group, criterion_main, BenchmarkId, Criterion, Throughput}; use tempfile::tempdir; use informalsystems_malachitebft_wal::Log; diff --git a/code/crates/wal/src/file.rs b/code/crates/wal/src/file.rs index bd942e424..04a1e6d90 100644 --- a/code/crates/wal/src/file.rs +++ b/code/crates/wal/src/file.rs @@ -28,10 +28,7 @@ impl Storage for File { .open(&path)?; AdvisoryFileLock::try_lock(&file, FileLockMode::Exclusive).map_err(|e| { - io::Error::new( - io::ErrorKind::Other, - format!("Failed to acquire exclusive advisory lock: {e}"), - ) + io::Error::other(format!("Failed to acquire exclusive advisory lock: {e}")) })?; Ok(file) diff --git a/code/crates/wal/tests/it/crashes.rs b/code/crates/wal/tests/it/crashes.rs index 3eafedae0..810d7cf45 100644 --- a/code/crates/wal/tests/it/crashes.rs +++ b/code/crates/wal/tests/it/crashes.rs @@ -66,10 +66,7 @@ impl Read for FailingFile { impl Write for FailingFile { fn write(&mut self, buf: &[u8]) -> io::Result { if self.bytes_written + buf.len() > self.fail_after { - return Err(io::Error::new( - io::ErrorKind::Other, - "Simulated system failure", - )); + return Err(io::Error::other("Simulated system failure")); } let written = self.inner.write(buf)?; self.bytes_written += written; @@ -204,10 +201,7 @@ impl Storage for FailingSync { fn sync_all(&mut self) -> io::Result<()> { if self.should_fail { - return Err(io::Error::new( - io::ErrorKind::Other, - "Simulated power failure during fsync", - )); + return Err(io::Error::other("Simulated power failure during fsync")); } self.inner.sync_all() diff --git a/code/examples/channel/src/app.rs b/code/examples/channel/src/app.rs index da8e735a6..76b9516d9 100644 --- a/code/examples/channel/src/app.rs +++ b/code/examples/channel/src/app.rs @@ -46,9 +46,10 @@ pub async fn run(state: &mut State, channels: &mut Channels) -> eyr height, round, proposer, + role, reply_value, } => { - info!(%height, %round, %proposer, "Started round"); + info!(%height, %round, %proposer, ?role, "Started round"); reload_log_level(height, round); diff --git a/code/examples/channel/src/state.rs b/code/examples/channel/src/state.rs index 964a2f162..851c8ec4d 100644 --- a/code/examples/channel/src/state.rs +++ b/code/examples/channel/src/state.rs @@ -408,7 +408,7 @@ impl State { /// validators from the genesis validator set. pub fn get_validator_set(&self, height: Height) -> ValidatorSet { let num_validators = self.genesis.validator_set.len(); - let selection_size = (num_validators + 1) / 2; + let selection_size = num_validators.div_ceil(2); if num_validators <= selection_size { return self.genesis.validator_set.clone(); diff --git a/code/examples/channel/src/store.rs b/code/examples/channel/src/store.rs index 663764ff3..f44331e27 100644 --- a/code/examples/channel/src/store.rs +++ b/code/examples/channel/src/store.rs @@ -54,7 +54,7 @@ pub enum StoreError { Commit(#[from] redb::CommitError), #[error("Transaction error: {0}")] - Transaction(#[from] redb::TransactionError), + Transaction(#[from] Box), #[error("Failed to encode/decode Protobuf: {0}")] Protobuf(#[from] ProtoError), @@ -63,6 +63,12 @@ pub enum StoreError { TaskJoin(#[from] tokio::task::JoinError), } +impl From for StoreError { + fn from(err: redb::TransactionError) -> Self { + Self::Transaction(Box::new(err)) + } +} + const CERTIFICATES_TABLE: redb::TableDefinition> = redb::TableDefinition::new("certificates"); diff --git a/code/scripts/spawn.bash b/code/scripts/spawn.bash index d3204d91d..0a992786f 100755 --- a/code/scripts/spawn.bash +++ b/code/scripts/spawn.bash @@ -46,13 +46,13 @@ export MALACHITE__CONSENSUS__TIMEOUT_COMMIT="0s" # Set the timeout step to 2 seconds to trigger the vote sync and polka certificate faster export MALACHITE__CONSENSUS__TIMEOUT_STEP="2s" # Set to request-response to be able to sync polka certificates, "broadcast" does not yet send the certificates -export MALACHITE__CONSENSUS__VOTE_SYNC__MODE="request-response" +export MALACHITE__CONSENSUS__VOTE_SYNC__MODE="rebroadcast" export MALACHITE__MEMPOOL__MAX_TX_COUNT="10000" export MALACHITE__MEMPOOL__GOSSIP_BATCH_SIZE=0 export MALACHITE__TEST__MAX_BLOCK_SIZE="50KiB" # Only use "parts-only" with starknet app for now, but for the channel app use "proposal-and-parts". # "proposal-and-parts" also works for starknet app -export MALACHITE__TEST__VALUE_PAYLOAD="proposal-and-parts" +export MALACHITE__TEST__VALUE_PAYLOAD="parts-only" export MALACHITE__TEST__TX_SIZE="1KiB" export MALACHITE__TEST__TXS_PER_PART=256 export MALACHITE__TEST__TIME_ALLOWANCE_FACTOR=0.3 diff --git a/qa/starknet/.gitignore b/qa/starknet/.gitignore new file mode 100644 index 000000000..21e51b9a5 --- /dev/null +++ b/qa/starknet/.gitignore @@ -0,0 +1,5 @@ +shared/* +!shared/build +shared/build/*/* +!shared/build/*/README.md +!shared/scripts diff --git a/qa/starknet/.python-version b/qa/starknet/.python-version new file mode 100644 index 000000000..24ee5b1be --- /dev/null +++ b/qa/starknet/.python-version @@ -0,0 +1 @@ +3.13 diff --git a/qa/starknet/README.md b/qa/starknet/README.md new file mode 100644 index 000000000..cb72d6d5a --- /dev/null +++ b/qa/starknet/README.md @@ -0,0 +1,92 @@ +# Starknet Interoperability Setup + +This setup generates networks composed of any combination of Malachite and Sequencer nodes. It uses a containerized architecture with configurable latency between nodes. + +## Usage + +1. Install dependencies: + + Run the appropriate script based on your OS from the `setup/` folder. + +>[!NOTE] +> If you encounter an `error: externally-managed-environment` error while running the script, please refer to the last section of this document. + +2. Clone the Starknet sequencer fork: + ```bash + git clone https://github.com/informalsystems/sequencer.git + cd sequencer + git checkout bastien/validators-ids + ``` + +3. Generate a network: + ```bash + python3 generate.py --help + ``` + +4. Apply the latency: + ```bash + ./apply-latency.sh + ``` + +5. Spawn the network: + ```bash + ./manage.sh up + ``` + +>[!NOTE] +> Spawning the network does not mean that the nodes have started yet. It only means that the containers are up and running. The `manage.sh` script outputs the commands to enter the containers if needed. + +6. Build the nodes: + + If it is the first time you are running the nodes, or if you made changes to the code, you need to build the nodes. You can do this by running the following command: + ```bash + ./manage.sh build + ``` + +7. Start the nodes: + ```bash + ./manage.sh start + ``` + The logs are located in the `shared/networks//logs/` folder. + +8. Reset the state: + + You might want to reset the state (db, wal, etc.) of the nodes. You can do this by running the following command: + ```bash + ./manage.sh reset + ``` + +9. Stop the network: + ```bash + ./manage.sh down + ``` + +>[!NOTE] +> The `build`, `start`, and `reset` commands are also available inside each node's container. This can be useful if you want to run a command inside a specific node. Simply enter the container (with the command provided by the `manage.sh` script) and run the command: `build`, `start`, or `reset`. + +## Advanced usage + +You might want to make modifications to the config files of the nodes. You can find them under the `shared/networks///` folder. The config files are mounted in the containers so that you can edit them directly from your host machine. + +>[!WARNING] +> Some Docker engines (e.g., Docker Desktop) sometimes have synchronization issues with mounted volumes, leading to corrupted config files in the containers. If you encounter such issues, stop the network, make your changes to the config files, and start the network again. It will ensure that the changes are applied correctly. + +Moreover, for the latency, you can edit it in detail in the `shared/networks//latencies.csv` file. Then, you can apply it again by running the `./apply-latency.sh ` command. It will update the latency between the nodes without stopping the network. The `latencies.csv` file is a _from/to_ matrix, where the first column is the source node and the first row is the destination node. The values are the latencies in milliseconds. + +If you plan to make more long-term changes to the configuration, feel free to edit the templates under the `templates/` directory. + +## Troubleshooting + +### Error: `error: externally-managed-environment` + +The easiest way to fix this error without using `--break-system-packages` is to create a global virtual environment imitating the system environment. It can be done by running the following setup: + +```bash +# 1. Create a virtual environment +python3 -m venv ~/.venv +# 2. Create aliases to activate/deactivate the virtual environment anywhere +echo "alias py-start='source ~/.venv/bin/activate'" >> ~/.bashrc +echo "alias py-stop='deactivate'" >> ~/.bashrc +``` + +Then, you can activate the virtual environment by running `py-start` and deactivate it by running `py-stop`. You should now be able to install any package without any issues. diff --git a/qa/starknet/apply-latency.sh b/qa/starknet/apply-latency.sh new file mode 100755 index 000000000..2b60bde2c --- /dev/null +++ b/qa/starknet/apply-latency.sh @@ -0,0 +1,29 @@ +#!/bin/bash + +set -e + +print_help() { + echo "Usage: $0 " + echo + echo "Apply TC rules to all containers in the given Docker Compose network." + echo + echo "Arguments:" + echo " network_name Name of the network (e.g., m2-s3)" + exit 1 +} + +if [[ "$1" == "-h" || "$1" == "--help" || -z "$1" ]]; then + print_help +fi + +network_name="$1" +compose_file="shared/networks/${network_name}/docker-compose.yml" + +if [[ ! -f "$compose_file" ]]; then + echo "Error: Compose file not found at $compose_file" + exit 1 +fi + +for container in $(docker compose -f "$compose_file" ps -q); do + docker exec "$container" /shared/scripts/apply-tc-rules.py /shared/networks/$network_name/latencies.csv +done diff --git a/qa/starknet/generate.py b/qa/starknet/generate.py new file mode 100644 index 000000000..df3b2051f --- /dev/null +++ b/qa/starknet/generate.py @@ -0,0 +1,302 @@ +#!/usr/bin/env python3 + +import os +import argparse +import base64 +import json +import csv +import libp2p.peer.id as PeerID +import libp2p.crypto.ed25519 as Ed25519 +from jinja2 import Environment, FileSystemLoader +from eth_hash.auto import keccak +from nacl.signing import SigningKey + +ADDRESS_LENGTH = 31 + + +def generate_key(): + signing_key = SigningKey.generate() + verify_key = signing_key.verify_key + + private_key_bytes = signing_key.encode() + public_key_bytes = verify_key.encode() + private_key_b64 = base64.b64encode(private_key_bytes).decode() + public_key_b64 = base64.b64encode(public_key_bytes).decode() + private_key_hex = "0x" + private_key_bytes.hex() + address = "0x" + keccak(public_key_bytes)[:ADDRESS_LENGTH].hex() + + key_data = { + "private_key": {"type": "tendermint/PrivKeyEd25519", "value": private_key_b64}, + "public_key": {"type": "tendermint/PubKeyEd25519", "value": public_key_b64}, + "address": address, + } + + peer_id = PeerID.ID.from_pubkey( + Ed25519.Ed25519PublicKey.from_bytes(public_key_bytes) + ) + + return key_data, private_key_hex, peer_id + + +def save_malachite_config(dir, rendered_config, genesis, key_data): + os.makedirs(dir, exist_ok=True) + with open(f"{dir}/config.toml", "w") as c: + c.write(rendered_config) + with open(f"{dir}/genesis.json", "w") as g: + g.write(json.dumps(genesis, indent=4)) + with open(f"{dir}/priv_validator_key.json", "w") as p: + p.write(json.dumps(key_data, indent=4)) + + +def save_sequencer_config(dir, rendered_config): + os.makedirs(dir, exist_ok=True) + with open(f"{dir}/config.json", "w") as c: + c.write(json.dumps(rendered_config, indent=4)) + + +def save_cli(dir, cmd, rendered_cli): + os.makedirs(dir, exist_ok=True) + with open(f"{dir}/{cmd}.sh", "w") as c: + c.write(rendered_cli) + os.chmod(f"{dir}/{cmd}.sh", 0o755) + + +def save_bashrc(dir, rendered_bashrc): + os.makedirs(dir, exist_ok=True) + with open(f"{dir}/.bashrc", "w") as c: + c.write(rendered_bashrc) + os.chmod(f"{dir}/.bashrc", 0o755) + + +def main(): + parser = argparse.ArgumentParser() + parser.add_argument("--name", type=str, required=False, help="Name of the network") + parser.add_argument( + "--malachite_path", + type=str, + required=True, + help="Absolute path to malachite repository", + ) + parser.add_argument( + "--sequencer_path", + type=str, + required=True, + help="Absolute path to sequencer repository", + ) + parser.add_argument( + "--malachite_nodes", type=int, required=True, help="Number of malachite nodes" + ) + parser.add_argument( + "--sequencer_nodes", type=int, required=True, help="Number of sequencer nodes" + ) + parser.add_argument( + "--proposal_timeout", + type=int, + required=False, + default=1500, + help="Proposal timeout (in ms)", + ) + parser.add_argument( + "--prevote_timeout", + type=int, + required=False, + default=500, + help="Prevote timeout (in ms)", + ) + parser.add_argument( + "--precommit_timeout", + type=int, + required=False, + default=500, + help="Precommit timeout (in ms)", + ) + parser.add_argument( + "--latency", + type=int, + required=False, + default=0, + help="Latency (in ms) between nodes", + ) + args = parser.parse_args() + + if not args.name: + args.name = f"m{args.malachite_nodes}-s{args.sequencer_nodes}" + + # Create base directory for the network + base_dir = f"./shared/networks/{args.name}" + os.makedirs(base_dir, exist_ok=True) + + env = Environment(loader=FileSystemLoader(".")) + + compose_template = env.get_template("templates/docker-compose.j2") + rendered_compose = compose_template.render( + network_name=args.name, + starknet_interop_path=os.path.dirname(os.path.abspath(__file__)), + malachite_path=args.malachite_path, + sequencer_path=args.sequencer_path, + malachite_count=args.malachite_nodes, + sequencer_count=args.sequencer_nodes, + ) + with open(f"{base_dir}/docker-compose.yml", "w") as f: + f.write(rendered_compose) + + malachite_data = [] + sequencer_data = [] + genesis = {"validator_set": {"validators": []}} + addresses = [] + + # Generate keys and configs for malachite nodes + malachite_config_template = env.get_template("templates/malachite-config.j2") + for i in range(1, args.malachite_nodes + 1): + peers = [] + for j in range(1, args.malachite_nodes + 1): + if j != i: + peers.append(f"malachite-node-{j}") + for k in range(1, args.sequencer_nodes + 1): + peers.append(f"sequencer-node-{k}") + + rendered_config = malachite_config_template.render( + id=i, + persistent_peers=peers, + proposal_timeout=f"{args.proposal_timeout}ms", + prevote_timeout=f"{args.prevote_timeout}ms", + precommit_timeout=f"{args.precommit_timeout}ms", + ) + key_data, _, _ = generate_key() + + malachite_data.append( + { + "rendered_config": rendered_config, + "key_data": key_data, + } + ) + + genesis["validator_set"]["validators"].append( + { + "address": key_data["address"], + "public_key": key_data["public_key"], + "voting_power": 1, + } + ) + + addresses.append(key_data["address"]) + + # Generate keys and config for sequencer nodes + # TODO: for now, there is no config file for sequencer nodes + for i in range(1, args.sequencer_nodes + 1): + key_data, private_key_hex, peer_id = generate_key() + + sequencer_data.append( + { + "key_data": key_data, + "private_key_hex": private_key_hex, + "peer_id": peer_id, + } + ) + + genesis["validator_set"]["validators"].append( + { + "address": key_data["address"], + "public_key": key_data["public_key"], + "voting_power": 1, + } + ) + + addresses.append(key_data["address"]) + + # Save malachite configs + for i, data in enumerate(malachite_data): + save_malachite_config( + f"{base_dir}/malachite-node-{i + 1}/config", + data["rendered_config"], + genesis, + data["key_data"], + ) + + # Save sequencer configs + # TODO: for now, there is no config file for sequencer nodes + + bashrc_template = env.get_template("templates/bashrc.j2") + + # Generate and save malachite cli + malachite_cli_start_template = env.get_template("templates/malachite-cli-start.j2") + malachite_cli_reset_template = env.get_template("templates/malachite-cli-reset.j2") + for i in range(1, args.malachite_nodes + 1): + rendered_cli = malachite_cli_start_template.render(network_name=args.name, id=i) + save_cli(f"{base_dir}/malachite-node-{i}/", "start", rendered_cli) + rendered_cli = malachite_cli_reset_template.render(network_name=args.name, id=i) + save_cli(f"{base_dir}/malachite-node-{i}/", "reset", rendered_cli) + + rendered_bashrc = bashrc_template.render( + network_name=args.name, + node_type="malachite", + node_bin="informalsystems-malachitebft-starknet-app", + id=i, + ) + save_bashrc(f"{base_dir}/malachite-node-{i}/", rendered_bashrc) + + # Generate and save sequencer cli + sequencer_cli_start_template = env.get_template("templates/sequencer-cli-start.j2") + sequencer_cli_reset_template = env.get_template("templates/sequencer-cli-reset.j2") + + if args.proposal_timeout <= 1000: + print( + "Warning: Proposal timeout should be > 1s for the sequencer. Setting it to 1500ms." + ) + args.proposal_timeout = 1500 + + for i in range(1, args.sequencer_nodes + 1): + rendered_cli = sequencer_cli_start_template.render( + network_name=args.name, + id=i, + consensus_secret_key=sequencer_data[i - 1]["private_key_hex"], + validator_id=sequencer_data[i - 1]["key_data"]["address"], + num_validators=args.malachite_nodes + args.sequencer_nodes, + validator_ids=",".join(addresses), + bootstrap_peer=( + f'/dns/sequencer-node-{((i - 2) % args.sequencer_nodes) + 1}/tcp/27000/p2p/{sequencer_data[(i - 2) % args.sequencer_nodes]["peer_id"]}' + if args.sequencer_nodes >= 2 + else None + ), + proposal_timeout=args.proposal_timeout / 1000, + prevote_timeout=args.prevote_timeout / 1000, + precommit_timeout=args.precommit_timeout / 1000, + ) + save_cli(f"{base_dir}/sequencer-node-{i}/", "start", rendered_cli) + rendered_cli = sequencer_cli_reset_template.render(network_name=args.name, id=i) + save_cli(f"{base_dir}/sequencer-node-{i}/", "reset", rendered_cli) + + rendered_bashrc = bashrc_template.render( + network_name=args.name, + node_type="sequencer", + node_bin="starknet_sequencer_node", + id=i, + ) + save_bashrc(f"{base_dir}/sequencer-node-{i}/", rendered_bashrc) + + # Generate and save latency config + data = [ + ["From/To"] + + [f"malachite-node-{i}" for i in range(1, args.malachite_nodes + 1)] + + [f"sequencer-node-{i}" for i in range(1, args.sequencer_nodes + 1)] + ] + for i in range(1, args.malachite_nodes + 1): + row = [f"malachite-node-{i}"] + [args.latency] * ( + args.malachite_nodes + args.sequencer_nodes + ) + data.append(row) + for i in range(1, args.sequencer_nodes + 1): + row = [f"sequencer-node-{i}"] + [args.latency] * ( + args.malachite_nodes + args.sequencer_nodes + ) + data.append(row) + with open(f"{base_dir}/latencies.csv", "w", newline="") as f: + writer = csv.writer(f) + writer.writerows(data) + + # Create logs directory + os.makedirs(f"{base_dir}/logs", exist_ok=True) + + +if __name__ == "__main__": + main() diff --git a/qa/starknet/malachite.Dockerfile b/qa/starknet/malachite.Dockerfile new file mode 100644 index 000000000..7cf3ac7da --- /dev/null +++ b/qa/starknet/malachite.Dockerfile @@ -0,0 +1,7 @@ +FROM rust:1-slim + +RUN apt-get update && apt-get install -y bash bash-completion protobuf-compiler python3 iproute2 make procps librust-tikv-jemalloc-sys-dev && \ + echo 'set editing-mode emacs' >> /etc/inputrc && \ + echo '[[ $PS1 && -f /etc/bash_completion ]] && . /etc/bash_completion' >> /etc/bash.bashrc + +SHELL [ "/bin/bash", "-c" ] diff --git a/qa/starknet/manage.sh b/qa/starknet/manage.sh new file mode 100755 index 000000000..4a2a7ade9 --- /dev/null +++ b/qa/starknet/manage.sh @@ -0,0 +1,82 @@ +#!/bin/bash + +set -e + +print_help() { + echo "Usage: $0 [duration]" + echo + echo "Manage Docker Compose for the given network." + echo + echo "Arguments:" + echo " network_name Name of the network (e.g., m2-s3)" + echo " action up | down | build | start | stop | reset" + echo " duration Number of seconds (required only if action=start)" + exit 1 +} + +if [[ "$1" == "-h" || "$1" == "--help" || -z "$1" || -z "$2" ]]; then + print_help +fi + +network_name="$1" +action="$2" +compose_file="shared/networks/${network_name}/docker-compose.yml" + +if [[ ! -f "$compose_file" ]]; then + echo "Error: Compose file not found at $compose_file" + exit 1 +fi + +case "$action" in + up) + docker compose -f "$compose_file" up -d || exit 1 + for container in $(docker compose -f "$compose_file" ps --format '{{.Name}}'); do + echo "docker exec -it $container /bin/bash" + done + ;; + down) + docker compose -f "$compose_file" down + ;; + build) + containers=( $(docker compose -f "$compose_file" ps --format '{{.Name}}' \ + | grep -E '(malachite-node-1|sequencer-node-1)') ) + for container in "${containers[@]}"; do + docker exec -it "$container" /bin/bash -lic "build" + done + ;; + start) + duration="$3" + if [[ -z "$duration" ]]; then + echo "Error: 'start' requires a duration in seconds" + exit 1 + fi + echo "Starting the nodes..." + containers=( $(docker compose -f "$compose_file" ps --format '{{.Name}}' ) ) + for container in "${containers[@]}"; do + if [[ "$container" =~ malachite-node- ]]; then + docker exec -itd "$container" /bin/bash -lic "sleep 10 && start > /shared/networks/${network_name}/logs/${container}.log 2>&1" + else + docker exec -itd "$container" /bin/bash -lic "start > /shared/networks/${network_name}/logs/${container}.log 2>&1" + fi + done + sleep 10 # The sequencer takes about 5 seconds to start + echo "Running for $duration seconds..." + sleep "$duration" + for container in "${containers[@]}"; do + docker exec -it "$container" /bin/bash -lic "pkill -f shared" + done + ;; + stop) + docker compose -f "$compose_file" stop + ;; + reset) + containers=( $(docker compose -f "$compose_file" ps --format '{{.Name}}' ) ) + for container in "${containers[@]}"; do + docker exec -it "$container" /bin/bash -lic "reset" + done + ;; + *) + echo "Error: Invalid action '$action'. Use 'up', 'down', 'build', or 'start'." + print_help + ;; +esac diff --git a/qa/starknet/pyproject.toml b/qa/starknet/pyproject.toml new file mode 100644 index 000000000..893dcc999 --- /dev/null +++ b/qa/starknet/pyproject.toml @@ -0,0 +1,12 @@ +[project] +name = "starknet" +version = "0.1.0" +description = "Add your description here" +readme = "README.md" +requires-python = ">=3.13" +dependencies = [ + "jinja2", + "eth-hash", + "pynacl", + "libp2p==0.2.4", +] diff --git a/qa/starknet/sequencer b/qa/starknet/sequencer new file mode 120000 index 000000000..21823bff7 --- /dev/null +++ b/qa/starknet/sequencer @@ -0,0 +1 @@ +../../../sequencer \ No newline at end of file diff --git a/qa/starknet/sequencer.Dockerfile b/qa/starknet/sequencer.Dockerfile new file mode 100644 index 000000000..3b39ab774 --- /dev/null +++ b/qa/starknet/sequencer.Dockerfile @@ -0,0 +1,12 @@ +FROM rust:1-slim + +RUN apt-get update && apt-get install -y bash bash-completion python3 iproute2 procps libssl-dev librust-tikv-jemalloc-sys-dev librust-clang-sys-dev pkg-config zstd lld && \ + echo 'set editing-mode emacs' >> /etc/inputrc && \ + echo '[[ $PS1 && -f /etc/bash_completion ]] && . /etc/bash_completion' >> /etc/bash.bashrc + +# COPY scripts/install_build_tools.sh . +# COPY scripts/dependencies.sh . + +# RUN ./install_build_tools.sh + +SHELL [ "/bin/bash", "-c" ] diff --git a/qa/starknet/setup/macos.sh b/qa/starknet/setup/macos.sh new file mode 100755 index 000000000..80d9fcbe0 --- /dev/null +++ b/qa/starknet/setup/macos.sh @@ -0,0 +1,49 @@ +#!/bin/bash + +set -e +trap 'echo "An error occurred. Exiting..."; exit 1;' ERR + +cd "$(dirname "$0")" || exit 1 + +echo "Checking for Homebrew..." +if ! command -v brew &>/dev/null; then + echo "Error: Homebrew is not installed. Please install it from https://brew.sh/ and re-run this script." + exit 1 +fi + +echo "Checking for pip3..." +if ! command -v pip3 &>/dev/null; then + echo "Error: pip3 is not installed. Please install Python 3 and pip3 before continuing." + exit 1 +fi + +echo "Installing Python requirements..." +pip3 install -r requirements.txt + +echo "Checking for GMP..." +if ! brew list gmp &>/dev/null; then + echo "Installing GMP via Homebrew..." + brew install gmp +else + echo "GMP already installed." +fi + +echo "Relinking GMP..." +brew unlink gmp && brew link gmp + +ARCH=$(uname -m) +if [ "$ARCH" = "arm64" ]; then + # Apple Silicon + export CFLAGS="-I/opt/homebrew/include" + export LDFLAGS="-L/opt/homebrew/lib" +else + # Intel + export CFLAGS="-I/usr/local/include" + export LDFLAGS="-L/usr/local/lib" +fi + +echo "Installing libp2p with correct compile flags..." +pip3 install libp2p==0.2.4 + +trap - ERR +echo "Setup complete!" diff --git a/qa/starknet/setup/requirements.txt b/qa/starknet/setup/requirements.txt new file mode 100644 index 000000000..f6fa313f5 --- /dev/null +++ b/qa/starknet/setup/requirements.txt @@ -0,0 +1,4 @@ +jinja2 +eth-hash +pynacl +libp2p diff --git a/qa/starknet/shared/build/README.md b/qa/starknet/shared/build/README.md new file mode 100644 index 000000000..520487388 --- /dev/null +++ b/qa/starknet/shared/build/README.md @@ -0,0 +1,3 @@ +# Build directory + +This directory is mounted in all containers at /shared/build. It is used to persist cargo builds. diff --git a/qa/starknet/shared/build/malachite/README.md b/qa/starknet/shared/build/malachite/README.md new file mode 100644 index 000000000..e5bf933f1 --- /dev/null +++ b/qa/starknet/shared/build/malachite/README.md @@ -0,0 +1 @@ +# Malachite node 1 build diff --git a/qa/starknet/shared/scripts/apply-tc-rules.py b/qa/starknet/shared/scripts/apply-tc-rules.py new file mode 100755 index 000000000..588aca590 --- /dev/null +++ b/qa/starknet/shared/scripts/apply-tc-rules.py @@ -0,0 +1,69 @@ +#!/usr/bin/python3 +import sys +import csv +import subprocess +import os +import socket + + +def read_matrix(csv_file): + with open(csv_file) as f: + reader = csv.reader(f) + header = next(reader)[1:] + matrix = {} + for row in reader: + row_zone = row[0] + matrix[row_zone] = {} + for i, col_zone in enumerate(header): + matrix[row_zone][col_zone] = int(row[i + 1]) + return header, matrix + + +def resolve_ips(hostnames): + return {host: socket.gethostbyname(host) for host in hostnames} + + +def execute_command(cmd): + subprocess.run(cmd, shell=True, check=True) + + +def build_tc_commands(header, matrix, local_dns, ip_map): + commands = [] + commands.append("tc qdisc del dev eth0 root 2> /dev/null || true") + commands.append("tc qdisc add dev eth0 root handle 1: htb default 10") + commands.append("tc class add dev eth0 parent 1: classid 1:1 htb rate 1gbit") + commands.append("tc class add dev eth0 parent 1:1 classid 1:10 htb rate 1gbit") + commands.append("tc qdisc add dev eth0 parent 1:10 handle 10: sfq perturb 10") + + handle = 11 + for zone in header: + if zone == local_dns: + continue + latency = matrix[local_dns][zone] + if latency > 0: + delta = latency // 20 or 1 + commands.append( + f"tc class add dev eth0 parent 1:1 classid 1:{handle} htb rate 1gbit" + ) + commands.append( + f"tc qdisc add dev eth0 parent 1:{handle} handle {handle}: netem delay {latency}ms {delta}ms distribution normal" + ) + commands.append( + f"tc filter add dev eth0 protocol ip parent 1: prio 1 u32 match ip dst {ip_map[zone]}/32 flowid 1:{handle}" + ) + handle += 1 + return commands + + +def main(): + csv_file = sys.argv[1] + local_dns = os.environ["LOCAL_DNS"] + header, matrix = read_matrix(csv_file) + ip_map = resolve_ips(header) + commands = build_tc_commands(header, matrix, local_dns, ip_map) + for cmd in commands: + execute_command(cmd) + + +if __name__ == "__main__": + main() diff --git a/qa/starknet/templates/bashrc.j2 b/qa/starknet/templates/bashrc.j2 new file mode 100644 index 000000000..abe6f7e23 --- /dev/null +++ b/qa/starknet/templates/bashrc.j2 @@ -0,0 +1,7 @@ +# export CARGO_HOME=/shared/build/{{ node_type }} +# export CARGO_TARGET_DIR=/shared/build/{{ node_type }} +export PATH=/usr/local/cargo/bin:$PATH + +alias build="cd {{ node_type }} && cargo build --locked --bin {{ node_bin }}" +alias start="/shared/networks/{{ network_name }}/{{ node_type }}-node-{{ id }}/start.sh" +alias reset="/shared/networks/{{ network_name }}/{{ node_type }}-node-{{ id }}/reset.sh" diff --git a/qa/starknet/templates/docker-compose.j2 b/qa/starknet/templates/docker-compose.j2 new file mode 100644 index 000000000..3f1bcc145 --- /dev/null +++ b/qa/starknet/templates/docker-compose.j2 @@ -0,0 +1,72 @@ +volumes: + + shared: + driver: local + driver_opts: + type: none + device: ../../../shared + o: bind +{% if malachite_count > 0 %} + malachite: + driver: local + driver_opts: + type: none + device: {{ malachite_path }}/code + o: bind{% endif %} +{% if sequencer_count > 0 %} + sequencer: + driver: local + driver_opts: + type: none + device: {{ sequencer_path }} + o: bind{% endif %} + +networks: + test-network: + driver: bridge + +services: +{% for i in range(1, malachite_count+1) %} + malachite-node-{{ i }}: + container_name: {{ network_name }}-malachite-node-{{ i }} + build: + context: {{ malachite_path }} + dockerfile: {{ starknet_interop_path }}/malachite.Dockerfile + environment: + - CARGO_HOME=/shared/build/malachite + - CARGO_TARGET_DIR=/shared/build/malachite + - LOCAL_DNS=malachite-node-{{ i }} + volumes: + - malachite:/malachite + - shared:/shared + - ../../../shared/networks/{{ network_name }}/malachite-node-{{ i }}/.bashrc:/root/.bashrc + networks: + - test-network + cap_add: + - NET_ADMIN + working_dir: / + tty: true + stdin_open: true +{% endfor %} +{% for i in range(1, sequencer_count+1) %} + sequencer-node-{{ i }}: + container_name: {{ network_name }}-sequencer-node-{{ i }} + build: + context: {{ sequencer_path }} + dockerfile: {{ starknet_interop_path }}/sequencer.Dockerfile + environment: + - CARGO_HOME=/shared/build/sequencer + - CARGO_TARGET_DIR=/shared/build/sequencer + - LOCAL_DNS=sequencer-node-{{ i }} + volumes: + - sequencer:/sequencer + - shared:/shared + - ../../../shared/networks/{{ network_name }}/sequencer-node-{{ i }}/.bashrc:/root/.bashrc + networks: + - test-network + cap_add: + - NET_ADMIN + working_dir: / + tty: true + stdin_open: true +{% endfor %} diff --git a/qa/starknet/templates/malachite-cli-reset.j2 b/qa/starknet/templates/malachite-cli-reset.j2 new file mode 100644 index 000000000..a08229cd6 --- /dev/null +++ b/qa/starknet/templates/malachite-cli-reset.j2 @@ -0,0 +1,3 @@ +#!/bin/bash + +rm -rf /shared/networks/{{ network_name }}/malachite-node-{{ id }}/db /shared/networks/{{ network_name }}/malachite-node-{{ id }}/wal diff --git a/qa/starknet/templates/malachite-cli-start.j2 b/qa/starknet/templates/malachite-cli-start.j2 new file mode 100644 index 000000000..cbcfab95b --- /dev/null +++ b/qa/starknet/templates/malachite-cli-start.j2 @@ -0,0 +1,3 @@ +#!/bin/bash + +${CARGO_TARGET_DIR}/debug/informalsystems-malachitebft-starknet-app start --home /shared/networks/{{ network_name }}/malachite-node-{{ id }} diff --git a/qa/starknet/templates/malachite-config.j2 b/qa/starknet/templates/malachite-config.j2 new file mode 100644 index 000000000..f93250993 --- /dev/null +++ b/qa/starknet/templates/malachite-config.j2 @@ -0,0 +1,98 @@ +moniker = "malachite-node-{{ id }}" + +[logging] +log_level = "debug" +log_format = "plaintext" + +[consensus] +value_payload = "parts-only" + +timeout_propose = "{{ proposal_timeout }}" +timeout_propose_delta = "500ms" +timeout_prevote = "{{ prevote_timeout }}" +timeout_prevote_delta = "500ms" +timeout_precommit = "{{ precommit_timeout }}" +timeout_precommit_delta = "500ms" +timeout_commit = "0s" +timeout_step = "300s" + +[consensus.p2p] +listen_addr = "/ip4/0.0.0.0/tcp/27000" +persistent_peers = [{% for peer in persistent_peers %} + "/dns/{{ peer }}/tcp/27000"{% if not loop.last %},{% endif %}{% endfor %} +] +transport = "tcp" +pubsub_max_size = "4.2 MB" +rpc_max_size = "10.5 MB" + +[consensus.p2p.discovery] +enabled = false +bootstrap_protocol = "kademlia" +selector = "random" +num_outbound_peers = 1 +num_inbound_peers = 5 +ephemeral_connection_timeout = "5s" +connect_request_max_retries = 10000 + +[consensus.p2p.protocol] +type = "gossipsub" +mesh_n = 6 +mesh_n_high = 12 +mesh_n_low = 4 +mesh_outbound_min = 2 + +[consensus.vote_sync] +mode = "rebroadcast" + +[mempool] +max_tx_count = 10000 +gossip_batch_size = 0 + +[mempool.load] +load_type = "no_load" + +[mempool.p2p] +listen_addr = "/ip4/127.0.0.1/tcp/28000" +persistent_peers = [] +transport = "tcp" +pubsub_max_size = "4.2 MB" +rpc_max_size = "10.5 MB" + +[mempool.p2p.discovery] +enabled = false +bootstrap_protocol = "full" +selector = "random" +num_outbound_peers = 20 +num_inbound_peers = 20 +ephemeral_connection_timeout = "5s" + +[mempool.p2p.protocol] +type = "gossipsub" +mesh_n = 6 +mesh_n_high = 12 +mesh_n_low = 4 +mesh_outbound_min = 2 + +[value_sync] +enabled = false +status_update_interval = "10s" +request_timeout = "10s" + +[metrics] +enabled = true +listen_addr = "127.0.0.1:29000" + +[runtime] +flavor = "single_threaded" + +[test] +max_block_size = "1048.6 KB" +tx_size = "1.0 KB" +txs_per_part = 256 +time_allowance_factor = 0.5 +exec_time_per_tx = "1ms" +max_retain_blocks = 1000 + +[test.vote_extensions] +enabled = false +size = "0 B" diff --git a/qa/starknet/templates/sequencer-cli-reset.j2 b/qa/starknet/templates/sequencer-cli-reset.j2 new file mode 100644 index 000000000..b30f09f91 --- /dev/null +++ b/qa/starknet/templates/sequencer-cli-reset.j2 @@ -0,0 +1,3 @@ +#!/bin/bash + +rm -rf /shared/networks/{{ network_name }}/sequencer-node-{{ id }}/storage diff --git a/qa/starknet/templates/sequencer-cli-start.j2 b/qa/starknet/templates/sequencer-cli-start.j2 new file mode 100644 index 000000000..9844b83d0 --- /dev/null +++ b/qa/starknet/templates/sequencer-cli-start.j2 @@ -0,0 +1,26 @@ +#!/bin/bash + +RUST_LOG=starknet_consensus=debug,starknet=info,papyrus_network=debug,papyrus=info \ + ${CARGO_TARGET_DIR}/debug/starknet_sequencer_node \ + --chain_id MY_CUSTOM_CHAIN_ID \ + --eth_fee_token_address 0x1001 \ + --strk_fee_token_address 0x1002 \ + --recorder_url http://invalid_address.com \ + --base_layer_config.node_url http://invalid_address.com \ + --batcher_config.storage.db_config.path_prefix /shared/networks/{{ network_name }}/sequencer-node-{{ id }}/storage/batcher_data \ + --class_manager_config.class_storage_config.class_hash_storage_config.path_prefix /shared/networks/{{ network_name }}/sequencer-node-{{ id }}/storage/class_manager_data \ + --state_sync_config.storage_config.db_config.path_prefix /shared/networks/{{ network_name }}/sequencer-node-{{ id }}/storage/sync_data \ + --consensus_manager_config.network_config.tcp_port 27000 \ + --mempool_p2p_config.network_config.tcp_port 11000 \ + --state_sync_config.network_config.tcp_port 12000 \ + --http_server_config.port 13000 \ + --monitoring_endpoint_config.port 14000 \ + --consensus_manager_config.network_config.secret_key {{ consensus_secret_key }} \ + --validator_id {{ validator_id }} \ + --consensus_manager_config.context_config.num_validators {{ num_validators }} \ + --consensus_manager_config.context_config.validator_ids {{ validator_ids }} \ + {% if bootstrap_peers is defined and bootstrap_peers %}{% for peer in bootstrap_peers %}--consensus_manager_config.network_config.bootstrap_peer_multiaddr {{ peer }} \ + {% endfor %}--consensus_manager_config.network_config.bootstrap_peer_multiaddr.#is_none false{% endif %} \ + --consensus_manager_config.consensus_config.timeouts.proposal_timeout {{ proposal_timeout }} \ + --consensus_manager_config.consensus_config.timeouts.prevote_timeout {{ prevote_timeout }} \ + --consensus_manager_config.consensus_config.timeouts.precommit_timeout {{ precommit_timeout }} diff --git a/qa/starknet/uv.lock b/qa/starknet/uv.lock new file mode 100644 index 000000000..a234ff985 --- /dev/null +++ b/qa/starknet/uv.lock @@ -0,0 +1,510 @@ +version = 1 +revision = 2 +requires-python = ">=3.13" + +[[package]] +name = "async-generator" +version = "1.10" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/ce/b6/6fa6b3b598a03cba5e80f829e0dadbb49d7645f523d209b2fb7ea0bbb02a/async_generator-1.10.tar.gz", hash = "sha256:6ebb3d106c12920aaae42ccb6f787ef5eefdcdd166ea3d628fa8476abe712144", size = 29870, upload-time = "2018-08-01T03:36:21.69Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/71/52/39d20e03abd0ac9159c162ec24b93fbcaa111e8400308f2465432495ca2b/async_generator-1.10-py3-none-any.whl", hash = "sha256:01c7bf666359b4967d2cda0000cc2e4af16a0ae098cbffcb8472fb9e8ad6585b", size = 18857, upload-time = "2018-08-01T03:36:20.029Z" }, +] + +[[package]] +name = "attrs" +version = "25.3.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/5a/b0/1367933a8532ee6ff8d63537de4f1177af4bff9f3e829baf7331f595bb24/attrs-25.3.0.tar.gz", hash = "sha256:75d7cefc7fb576747b2c81b4442d4d4a1ce0900973527c011d1030fd3bf4af1b", size = 812032, upload-time = "2025-03-13T11:10:22.779Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/77/06/bb80f5f86020c4551da315d78b3ab75e8228f89f0162f2c3a819e407941a/attrs-25.3.0-py3-none-any.whl", hash = "sha256:427318ce031701fea540783410126f03899a97ffc6f61596ad581ac2e40e3bc3", size = 63815, upload-time = "2025-03-13T11:10:21.14Z" }, +] + +[[package]] +name = "base58" +version = "2.1.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/7f/45/8ae61209bb9015f516102fa559a2914178da1d5868428bd86a1b4421141d/base58-2.1.1.tar.gz", hash = "sha256:c5d0cb3f5b6e81e8e35da5754388ddcc6d0d14b6c6a132cb93d69ed580a7278c", size = 6528, upload-time = "2021-10-30T22:12:17.858Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/4a/45/ec96b29162a402fc4c1c5512d114d7b3787b9d1c2ec241d9568b4816ee23/base58-2.1.1-py3-none-any.whl", hash = "sha256:11a36f4d3ce51dfc1043f3218591ac4eb1ceb172919cebe05b52a5bcc8d245c2", size = 5621, upload-time = "2021-10-30T22:12:16.658Z" }, +] + +[[package]] +name = "cffi" +version = "1.17.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "pycparser" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/fc/97/c783634659c2920c3fc70419e3af40972dbaf758daa229a7d6ea6135c90d/cffi-1.17.1.tar.gz", hash = "sha256:1c39c6016c32bc48dd54561950ebd6836e1670f2ae46128f67cf49e789c52824", size = 516621, upload-time = "2024-09-04T20:45:21.852Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/8d/f8/dd6c246b148639254dad4d6803eb6a54e8c85c6e11ec9df2cffa87571dbe/cffi-1.17.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:f3a2b4222ce6b60e2e8b337bb9596923045681d71e5a082783484d845390938e", size = 182989, upload-time = "2024-09-04T20:44:28.956Z" }, + { url = "https://files.pythonhosted.org/packages/8b/f1/672d303ddf17c24fc83afd712316fda78dc6fce1cd53011b839483e1ecc8/cffi-1.17.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:0984a4925a435b1da406122d4d7968dd861c1385afe3b45ba82b750f229811e2", size = 178802, upload-time = "2024-09-04T20:44:30.289Z" }, + { url = "https://files.pythonhosted.org/packages/0e/2d/eab2e858a91fdff70533cab61dcff4a1f55ec60425832ddfdc9cd36bc8af/cffi-1.17.1-cp313-cp313-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d01b12eeeb4427d3110de311e1774046ad344f5b1a7403101878976ecd7a10f3", size = 454792, upload-time = "2024-09-04T20:44:32.01Z" }, + { url = "https://files.pythonhosted.org/packages/75/b2/fbaec7c4455c604e29388d55599b99ebcc250a60050610fadde58932b7ee/cffi-1.17.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:706510fe141c86a69c8ddc029c7910003a17353970cff3b904ff0686a5927683", size = 478893, upload-time = "2024-09-04T20:44:33.606Z" }, + { url = "https://files.pythonhosted.org/packages/4f/b7/6e4a2162178bf1935c336d4da8a9352cccab4d3a5d7914065490f08c0690/cffi-1.17.1-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:de55b766c7aa2e2a3092c51e0483d700341182f08e67c63630d5b6f200bb28e5", size = 485810, upload-time = "2024-09-04T20:44:35.191Z" }, + { url = "https://files.pythonhosted.org/packages/c7/8a/1d0e4a9c26e54746dc08c2c6c037889124d4f59dffd853a659fa545f1b40/cffi-1.17.1-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c59d6e989d07460165cc5ad3c61f9fd8f1b4796eacbd81cee78957842b834af4", size = 471200, upload-time = "2024-09-04T20:44:36.743Z" }, + { url = "https://files.pythonhosted.org/packages/26/9f/1aab65a6c0db35f43c4d1b4f580e8df53914310afc10ae0397d29d697af4/cffi-1.17.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dd398dbc6773384a17fe0d3e7eeb8d1a21c2200473ee6806bb5e6a8e62bb73dd", size = 479447, upload-time = "2024-09-04T20:44:38.492Z" }, + { url = "https://files.pythonhosted.org/packages/5f/e4/fb8b3dd8dc0e98edf1135ff067ae070bb32ef9d509d6cb0f538cd6f7483f/cffi-1.17.1-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:3edc8d958eb099c634dace3c7e16560ae474aa3803a5df240542b305d14e14ed", size = 484358, upload-time = "2024-09-04T20:44:40.046Z" }, + { url = "https://files.pythonhosted.org/packages/f1/47/d7145bf2dc04684935d57d67dff9d6d795b2ba2796806bb109864be3a151/cffi-1.17.1-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:72e72408cad3d5419375fc87d289076ee319835bdfa2caad331e377589aebba9", size = 488469, upload-time = "2024-09-04T20:44:41.616Z" }, + { url = "https://files.pythonhosted.org/packages/bf/ee/f94057fa6426481d663b88637a9a10e859e492c73d0384514a17d78ee205/cffi-1.17.1-cp313-cp313-win32.whl", hash = "sha256:e03eab0a8677fa80d646b5ddece1cbeaf556c313dcfac435ba11f107ba117b5d", size = 172475, upload-time = "2024-09-04T20:44:43.733Z" }, + { url = "https://files.pythonhosted.org/packages/7c/fc/6a8cb64e5f0324877d503c854da15d76c1e50eb722e320b15345c4d0c6de/cffi-1.17.1-cp313-cp313-win_amd64.whl", hash = "sha256:f6a16c31041f09ead72d69f583767292f750d24913dadacf5756b966aacb3f1a", size = 182009, upload-time = "2024-09-04T20:44:45.309Z" }, +] + +[[package]] +name = "coincurve" +version = "21.0.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/6f/a2/f2a38eb05b747ed3e54e1be33be339d4a14c1f5cc6a6e2b342b5e8160d51/coincurve-21.0.0.tar.gz", hash = "sha256:8b37ce4265a82bebf0e796e21a769e56fdbf8420411ccbe3fafee4ed75b6a6e5", size = 128986, upload-time = "2025-03-08T15:31:24.266Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/b3/40/cce55adaec37a588eb24b67da8eb68926546458e12ed2c4c2a21deb93d4c/coincurve-21.0.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:9df5ceb5de603b9caf270629996710cf5ed1d43346887bc3895a11258644b65b", size = 1391762, upload-time = "2025-03-08T15:30:49.586Z" }, + { url = "https://files.pythonhosted.org/packages/ca/7a/628a30281d246ce98aea56592e0c8e79b03a93ee8b85d688db3388130c2d/coincurve-21.0.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:154467858d23c48f9e5ab380433bc2625027b50617400e2984cc16f5799ab601", size = 1384921, upload-time = "2025-03-08T15:30:51.103Z" }, + { url = "https://files.pythonhosted.org/packages/61/cc/719c5da31e6ba07e438abcf962f7a365eb69a06a0621ca4f2a484f344e09/coincurve-21.0.0-cp313-cp313-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f57f07c44d14d939bed289cdeaba4acb986bba9f729a796b6a341eab1661eedc", size = 1606559, upload-time = "2025-03-08T15:30:53.218Z" }, + { url = "https://files.pythonhosted.org/packages/b2/ee/dd14237013d732e7fc3248c0c33a1d36b88b5378dfa3e624a50a23fb6f19/coincurve-21.0.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3fb03e3a388a93d31ed56a442bdec7983ea404490e21e12af76fb1dbf097082a", size = 1613684, upload-time = "2025-03-08T15:30:55.087Z" }, + { url = "https://files.pythonhosted.org/packages/f0/05/eaa7f36a03376ced1c19e0cb563341cc83fe48f5734b2effe8f16d0ee0ab/coincurve-21.0.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d09ba4fd9d26b00b06645fcd768c5ad44832a1fa847ebe8fb44970d3204c3cb7", size = 1617001, upload-time = "2025-03-08T15:30:57.036Z" }, + { url = "https://files.pythonhosted.org/packages/39/32/fc75f1dd914ac95eb2704425c7ca1a9f509f982e15d05e0ca895b9e6ea9c/coincurve-21.0.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:1a1e7ee73bc1b3bcf14c7b0d1f44e6485785d3b53ef7b16173c36d3cefa57f93", size = 1643924, upload-time = "2025-03-08T15:30:58.737Z" }, + { url = "https://files.pythonhosted.org/packages/1a/4b/8c6e65b5755e26fc02077803879747615c1c327047328d1784bccb4ff4c3/coincurve-21.0.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:ad05952b6edc593a874df61f1bc79db99d716ec48ba4302d699e14a419fe6f51", size = 1619964, upload-time = "2025-03-08T15:31:00.275Z" }, + { url = "https://files.pythonhosted.org/packages/64/bc/d0a743305ff9fa26e72b4c77b534d5958ec8030b3772555a7172a0c134e5/coincurve-21.0.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:4d2bf350ced38b73db9efa1ff8fd16a67a1cb35abb2dda50d89661b531f03fd3", size = 1645526, upload-time = "2025-03-08T15:31:01.952Z" }, + { url = "https://files.pythonhosted.org/packages/9d/44/ab082e2dc8c9a45774f1bb9961f58b43c0882b866f5c469ead932d45a35d/coincurve-21.0.0-cp313-cp313-win_amd64.whl", hash = "sha256:54d9500c56d5499375e579c3917472ffcf804c3584dd79052a79974280985c74", size = 1329285, upload-time = "2025-03-08T15:31:03.591Z" }, + { url = "https://files.pythonhosted.org/packages/f3/94/407f6fc811310f15b1fc7255f436f6a9040854213beeb10093f56b5b7fd3/coincurve-21.0.0-cp313-cp313-win_arm64.whl", hash = "sha256:773917f075ec4b94a7a742637d303a3a082616a115c36568eb6c873a8d950d18", size = 1326027, upload-time = "2025-03-08T15:31:05.318Z" }, +] + +[[package]] +name = "cryptography" +version = "45.0.2" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "cffi", marker = "platform_python_implementation != 'PyPy'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/f6/47/92a8914716f2405f33f1814b97353e3cfa223cd94a77104075d42de3099e/cryptography-45.0.2.tar.gz", hash = "sha256:d784d57b958ffd07e9e226d17272f9af0c41572557604ca7554214def32c26bf", size = 743865, upload-time = "2025-05-18T02:46:34.986Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/3d/2f/46b9e715157643ad16f039ec3c3c47d174da6f825bf5034b1c5f692ab9e2/cryptography-45.0.2-cp311-abi3-macosx_10_9_universal2.whl", hash = "sha256:61a8b1bbddd9332917485b2453d1de49f142e6334ce1d97b7916d5a85d179c84", size = 7043448, upload-time = "2025-05-18T02:45:12.495Z" }, + { url = "https://files.pythonhosted.org/packages/90/52/49e6c86278e1b5ec226e96b62322538ccc466306517bf9aad8854116a088/cryptography-45.0.2-cp311-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4cc31c66411e14dd70e2f384a9204a859dc25b05e1f303df0f5326691061b839", size = 4201098, upload-time = "2025-05-18T02:45:15.178Z" }, + { url = "https://files.pythonhosted.org/packages/7b/3a/201272539ac5b66b4cb1af89021e423fc0bfacb73498950280c51695fb78/cryptography-45.0.2-cp311-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:463096533acd5097f8751115bc600b0b64620c4aafcac10c6d0041e6e68f88fe", size = 4429839, upload-time = "2025-05-18T02:45:17.614Z" }, + { url = "https://files.pythonhosted.org/packages/99/89/fa1a84832b8f8f3917875cb15324bba98def5a70175a889df7d21a45dc75/cryptography-45.0.2-cp311-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:cdafb86eb673c3211accffbffdb3cdffa3aaafacd14819e0898d23696d18e4d3", size = 4205154, upload-time = "2025-05-18T02:45:19.874Z" }, + { url = "https://files.pythonhosted.org/packages/1c/c5/5225d5230d538ab461725711cf5220560a813d1eb68bafcfb00131b8f631/cryptography-45.0.2-cp311-abi3-manylinux_2_28_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:05c2385b1f5c89a17df19900cfb1345115a77168f5ed44bdf6fd3de1ce5cc65b", size = 3897145, upload-time = "2025-05-18T02:45:22.209Z" }, + { url = "https://files.pythonhosted.org/packages/fe/24/f19aae32526cc55ae17d473bc4588b1234af2979483d99cbfc57e55ffea6/cryptography-45.0.2-cp311-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:e9e4bdcd70216b08801e267c0b563316b787f957a46e215249921f99288456f9", size = 4462192, upload-time = "2025-05-18T02:45:24.773Z" }, + { url = "https://files.pythonhosted.org/packages/19/18/4a69ac95b0b3f03355970baa6c3f9502bbfc54e7df81fdb179654a00f48e/cryptography-45.0.2-cp311-abi3-manylinux_2_34_aarch64.whl", hash = "sha256:b2de529027579e43b6dc1f805f467b102fb7d13c1e54c334f1403ee2b37d0059", size = 4208093, upload-time = "2025-05-18T02:45:27.028Z" }, + { url = "https://files.pythonhosted.org/packages/7c/54/2dea55ccc9558b8fa14f67156250b6ee231e31765601524e4757d0b5db6b/cryptography-45.0.2-cp311-abi3-manylinux_2_34_x86_64.whl", hash = "sha256:10d68763892a7b19c22508ab57799c4423c7c8cd61d7eee4c5a6a55a46511949", size = 4461819, upload-time = "2025-05-18T02:45:29.39Z" }, + { url = "https://files.pythonhosted.org/packages/37/f1/1b220fcd5ef4b1f0ff3e59e733b61597505e47f945606cc877adab2c1a17/cryptography-45.0.2-cp311-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:d2a90ce2f0f5b695e4785ac07c19a58244092f3c85d57db6d8eb1a2b26d2aad6", size = 4329202, upload-time = "2025-05-18T02:45:31.925Z" }, + { url = "https://files.pythonhosted.org/packages/6d/e0/51d1dc4f96f819a56db70f0b4039b4185055bbb8616135884c3c3acc4c6d/cryptography-45.0.2-cp311-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:59c0c8f043dd376bbd9d4f636223836aed50431af4c5a467ed9bf61520294627", size = 4570412, upload-time = "2025-05-18T02:45:34.348Z" }, + { url = "https://files.pythonhosted.org/packages/dc/44/88efb40a3600d15277a77cdc69eeeab45a98532078d2a36cffd9325d3b3f/cryptography-45.0.2-cp311-abi3-win32.whl", hash = "sha256:80303ee6a02ef38c4253160446cbeb5c400c07e01d4ddbd4ff722a89b736d95a", size = 2933584, upload-time = "2025-05-18T02:45:36.198Z" }, + { url = "https://files.pythonhosted.org/packages/d9/a1/bc9f82ba08760442cc8346d1b4e7b769b86d197193c45b42b3595d231e84/cryptography-45.0.2-cp311-abi3-win_amd64.whl", hash = "sha256:7429936146063bd1b2cfc54f0e04016b90ee9b1c908a7bed0800049cbace70eb", size = 3408537, upload-time = "2025-05-18T02:45:38.184Z" }, + { url = "https://files.pythonhosted.org/packages/59/bc/1b6acb1dca366f9c0b3880888ecd7fcfb68023930d57df854847c6da1d10/cryptography-45.0.2-cp37-abi3-macosx_10_9_universal2.whl", hash = "sha256:e86c8d54cd19a13e9081898b3c24351683fd39d726ecf8e774aaa9d8d96f5f3a", size = 7025581, upload-time = "2025-05-18T02:45:40.632Z" }, + { url = "https://files.pythonhosted.org/packages/31/a3/a3e4a298d3db4a04085728f5ae6c8cda157e49c5bb784886d463b9fbff70/cryptography-45.0.2-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e328357b6bbf79928363dbf13f4635b7aac0306afb7e5ad24d21d0c5761c3253", size = 4189148, upload-time = "2025-05-18T02:45:42.538Z" }, + { url = "https://files.pythonhosted.org/packages/53/90/100dfadd4663b389cb56972541ec1103490a19ebad0132af284114ba0868/cryptography-45.0.2-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:49af56491473231159c98c2c26f1a8f3799a60e5cf0e872d00745b858ddac9d2", size = 4424113, upload-time = "2025-05-18T02:45:44.316Z" }, + { url = "https://files.pythonhosted.org/packages/0d/40/e2b9177dbed6f3fcbbf1942e1acea2fd15b17007204b79d675540dd053af/cryptography-45.0.2-cp37-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:f169469d04a23282de9d0be349499cb6683b6ff1b68901210faacac9b0c24b7d", size = 4189696, upload-time = "2025-05-18T02:45:46.622Z" }, + { url = "https://files.pythonhosted.org/packages/70/ae/ec29c79f481e1767c2ff916424ba36f3cf7774de93bbd60428a3c52d1357/cryptography-45.0.2-cp37-abi3-manylinux_2_28_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:9cfd1399064b13043082c660ddd97a0358e41c8b0dc7b77c1243e013d305c344", size = 3881498, upload-time = "2025-05-18T02:45:48.884Z" }, + { url = "https://files.pythonhosted.org/packages/5f/4a/72937090e5637a232b2f73801c9361cd08404a2d4e620ca4ec58c7ea4b70/cryptography-45.0.2-cp37-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:18f8084b7ca3ce1b8d38bdfe33c48116edf9a08b4d056ef4a96dceaa36d8d965", size = 4451678, upload-time = "2025-05-18T02:45:50.706Z" }, + { url = "https://files.pythonhosted.org/packages/d3/fa/1377fced81fd67a4a27514248261bb0d45c3c1e02169411fe231583088c8/cryptography-45.0.2-cp37-abi3-manylinux_2_34_aarch64.whl", hash = "sha256:2cb03a944a1a412724d15a7c051d50e63a868031f26b6a312f2016965b661942", size = 4192296, upload-time = "2025-05-18T02:45:52.422Z" }, + { url = "https://files.pythonhosted.org/packages/d1/cf/b6fe837c83a08b9df81e63299d75fc5b3c6d82cf24b3e1e0e331050e9e5c/cryptography-45.0.2-cp37-abi3-manylinux_2_34_x86_64.whl", hash = "sha256:a9727a21957d3327cf6b7eb5ffc9e4b663909a25fea158e3fcbc49d4cdd7881b", size = 4451749, upload-time = "2025-05-18T02:45:55.025Z" }, + { url = "https://files.pythonhosted.org/packages/af/d8/5a655675cc635c7190bfc8cffb84bcdc44fc62ce945ad1d844adaa884252/cryptography-45.0.2-cp37-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:ddb8d01aa900b741d6b7cc585a97aff787175f160ab975e21f880e89d810781a", size = 4317601, upload-time = "2025-05-18T02:45:56.911Z" }, + { url = "https://files.pythonhosted.org/packages/b9/d4/75d2375a20d80aa262a8adee77bf56950e9292929e394b9fae2481803f11/cryptography-45.0.2-cp37-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:c0c000c1a09f069632d8a9eb3b610ac029fcc682f1d69b758e625d6ee713f4ed", size = 4560535, upload-time = "2025-05-18T02:45:59.33Z" }, + { url = "https://files.pythonhosted.org/packages/aa/18/c3a94474987ebcfb88692036b2ec44880d243fefa73794bdcbf748679a6e/cryptography-45.0.2-cp37-abi3-win32.whl", hash = "sha256:08281de408e7eb71ba3cd5098709a356bfdf65eebd7ee7633c3610f0aa80d79b", size = 2922045, upload-time = "2025-05-18T02:46:01.012Z" }, + { url = "https://files.pythonhosted.org/packages/63/63/fb28b30c144182fd44ce93d13ab859791adbf923e43bdfb610024bfecda1/cryptography-45.0.2-cp37-abi3-win_amd64.whl", hash = "sha256:48caa55c528617fa6db1a9c3bf2e37ccb31b73e098ac2b71408d1f2db551dde4", size = 3393321, upload-time = "2025-05-18T02:46:03.441Z" }, +] + +[[package]] +name = "eth-hash" +version = "0.7.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/ee/38/577b7bc9380ef9dff0f1dffefe0c9a1ded2385e7a06c306fd95afb6f9451/eth_hash-0.7.1.tar.gz", hash = "sha256:d2411a403a0b0a62e8247b4117932d900ffb4c8c64b15f92620547ca5ce46be5", size = 12227, upload-time = "2025-01-13T21:29:21.765Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/eb/db/f8775490669d28aca24871c67dd56b3e72105cb3bcae9a4ec65dd70859b3/eth_hash-0.7.1-py3-none-any.whl", hash = "sha256:0fb1add2adf99ef28883fd6228eb447ef519ea72933535ad1a0b28c6f65f868a", size = 8028, upload-time = "2025-01-13T21:29:19.365Z" }, +] + +[[package]] +name = "fastecdsa" +version = "1.7.5" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "six" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/d7/9a/dbc950929ba56731588c68f34e5a7a1f507eb51f2a59d943020ec8ba399a/fastecdsa-1.7.5.tar.gz", hash = "sha256:bd3b7808cc2bea1e8b3c4dd5928ecfc14072403ab2a47580a7a8350800e6fedd", size = 40426, upload-time = "2019-11-05T06:14:45.006Z" } + +[[package]] +name = "idna" +version = "3.10" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/f1/70/7703c29685631f5a7590aa73f1f1d3fa9a380e654b86af429e0934a32f7d/idna-3.10.tar.gz", hash = "sha256:12f65c9b470abda6dc35cf8e63cc574b1c52b11df2c86030af0ac09b01b13ea9", size = 190490, upload-time = "2024-09-15T18:07:39.745Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/76/c6/c88e154df9c4e1a2a66ccf0005a88dfb2650c1dffb6f5ce603dfbd452ce3/idna-3.10-py3-none-any.whl", hash = "sha256:946d195a0d259cbba61165e88e65941f16e9b36ea6ddb97f00452bae8b1287d3", size = 70442, upload-time = "2024-09-15T18:07:37.964Z" }, +] + +[[package]] +name = "importlib-metadata" +version = "8.7.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "zipp" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/76/66/650a33bd90f786193e4de4b3ad86ea60b53c89b669a5c7be931fac31cdb0/importlib_metadata-8.7.0.tar.gz", hash = "sha256:d13b81ad223b890aa16c5471f2ac3056cf76c5f10f82d6f9292f0b415f389000", size = 56641, upload-time = "2025-04-27T15:29:01.736Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/20/b0/36bd937216ec521246249be3bf9855081de4c5e06a0c9b4219dbeda50373/importlib_metadata-8.7.0-py3-none-any.whl", hash = "sha256:e5dd1551894c77868a30651cef00984d50e1002d06942a7101d34870c5f02afd", size = 27656, upload-time = "2025-04-27T15:29:00.214Z" }, +] + +[[package]] +name = "jinja2" +version = "3.1.6" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "markupsafe" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/df/bf/f7da0350254c0ed7c72f3e33cef02e048281fec7ecec5f032d4aac52226b/jinja2-3.1.6.tar.gz", hash = "sha256:0137fb05990d35f1275a587e9aee6d56da821fc83491a0fb838183be43f66d6d", size = 245115, upload-time = "2025-03-05T20:05:02.478Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/62/a1/3d680cbfd5f4b8f15abc1d571870c5fc3e594bb582bc3b64ea099db13e56/jinja2-3.1.6-py3-none-any.whl", hash = "sha256:85ece4451f492d0c13c5dd7c13a64681a86afae63a5f347908daf103ce6d2f67", size = 134899, upload-time = "2025-03-05T20:05:00.369Z" }, +] + +[[package]] +name = "libp2p" +version = "0.2.4" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "base58" }, + { name = "coincurve" }, + { name = "fastecdsa" }, + { name = "lru-dict" }, + { name = "multiaddr" }, + { name = "mypy-protobuf" }, + { name = "noiseprotocol" }, + { name = "protobuf" }, + { name = "pycryptodome" }, + { name = "pymultihash" }, + { name = "pynacl" }, + { name = "rpcudp" }, + { name = "trio" }, + { name = "trio-typing" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/0f/a6/5d856001ee91dda7689d6ac654ae384053662572040fd704c6821940dab3/libp2p-0.2.4.tar.gz", hash = "sha256:33caea78da9908a26c2790b1f81c7b3ff17f00fc75b20a18e8af5f6951ad6b44", size = 195863, upload-time = "2025-03-27T21:54:06.263Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/0d/c2/31711c96549827374fc0b475d77d7303bb129a8c5aff624c41a29e21dd84/libp2p-0.2.4-py3-none-any.whl", hash = "sha256:2f2ae8842dfe25a20c2c66d5493ece9a6fa8fc245d020b9a21e2a17feeacb81b", size = 130236, upload-time = "2025-03-27T21:54:05.097Z" }, +] + +[[package]] +name = "lru-dict" +version = "1.3.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/96/e3/42c87871920602a3c8300915bd0292f76eccc66c38f782397acbf8a62088/lru-dict-1.3.0.tar.gz", hash = "sha256:54fd1966d6bd1fcde781596cb86068214edeebff1db13a2cea11079e3fd07b6b", size = 13123, upload-time = "2023-11-06T01:40:12.951Z" } + +[[package]] +name = "markupsafe" +version = "3.0.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/b2/97/5d42485e71dfc078108a86d6de8fa46db44a1a9295e89c5d6d4a06e23a62/markupsafe-3.0.2.tar.gz", hash = "sha256:ee55d3edf80167e48ea11a923c7386f4669df67d7994554387f84e7d8b0a2bf0", size = 20537, upload-time = "2024-10-18T15:21:54.129Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/83/0e/67eb10a7ecc77a0c2bbe2b0235765b98d164d81600746914bebada795e97/MarkupSafe-3.0.2-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:ba9527cdd4c926ed0760bc301f6728ef34d841f405abf9d4f959c478421e4efd", size = 14274, upload-time = "2024-10-18T15:21:24.577Z" }, + { url = "https://files.pythonhosted.org/packages/2b/6d/9409f3684d3335375d04e5f05744dfe7e9f120062c9857df4ab490a1031a/MarkupSafe-3.0.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:f8b3d067f2e40fe93e1ccdd6b2e1d16c43140e76f02fb1319a05cf2b79d99430", size = 12352, upload-time = "2024-10-18T15:21:25.382Z" }, + { url = "https://files.pythonhosted.org/packages/d2/f5/6eadfcd3885ea85fe2a7c128315cc1bb7241e1987443d78c8fe712d03091/MarkupSafe-3.0.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:569511d3b58c8791ab4c2e1285575265991e6d8f8700c7be0e88f86cb0672094", size = 24122, upload-time = "2024-10-18T15:21:26.199Z" }, + { url = "https://files.pythonhosted.org/packages/0c/91/96cf928db8236f1bfab6ce15ad070dfdd02ed88261c2afafd4b43575e9e9/MarkupSafe-3.0.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:15ab75ef81add55874e7ab7055e9c397312385bd9ced94920f2802310c930396", size = 23085, upload-time = "2024-10-18T15:21:27.029Z" }, + { url = "https://files.pythonhosted.org/packages/c2/cf/c9d56af24d56ea04daae7ac0940232d31d5a8354f2b457c6d856b2057d69/MarkupSafe-3.0.2-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f3818cb119498c0678015754eba762e0d61e5b52d34c8b13d770f0719f7b1d79", size = 22978, upload-time = "2024-10-18T15:21:27.846Z" }, + { url = "https://files.pythonhosted.org/packages/2a/9f/8619835cd6a711d6272d62abb78c033bda638fdc54c4e7f4272cf1c0962b/MarkupSafe-3.0.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:cdb82a876c47801bb54a690c5ae105a46b392ac6099881cdfb9f6e95e4014c6a", size = 24208, upload-time = "2024-10-18T15:21:28.744Z" }, + { url = "https://files.pythonhosted.org/packages/f9/bf/176950a1792b2cd2102b8ffeb5133e1ed984547b75db47c25a67d3359f77/MarkupSafe-3.0.2-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:cabc348d87e913db6ab4aa100f01b08f481097838bdddf7c7a84b7575b7309ca", size = 23357, upload-time = "2024-10-18T15:21:29.545Z" }, + { url = "https://files.pythonhosted.org/packages/ce/4f/9a02c1d335caabe5c4efb90e1b6e8ee944aa245c1aaaab8e8a618987d816/MarkupSafe-3.0.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:444dcda765c8a838eaae23112db52f1efaf750daddb2d9ca300bcae1039adc5c", size = 23344, upload-time = "2024-10-18T15:21:30.366Z" }, + { url = "https://files.pythonhosted.org/packages/ee/55/c271b57db36f748f0e04a759ace9f8f759ccf22b4960c270c78a394f58be/MarkupSafe-3.0.2-cp313-cp313-win32.whl", hash = "sha256:bcf3e58998965654fdaff38e58584d8937aa3096ab5354d493c77d1fdd66d7a1", size = 15101, upload-time = "2024-10-18T15:21:31.207Z" }, + { url = "https://files.pythonhosted.org/packages/29/88/07df22d2dd4df40aba9f3e402e6dc1b8ee86297dddbad4872bd5e7b0094f/MarkupSafe-3.0.2-cp313-cp313-win_amd64.whl", hash = "sha256:e6a2a455bd412959b57a172ce6328d2dd1f01cb2135efda2e4576e8a23fa3b0f", size = 15603, upload-time = "2024-10-18T15:21:32.032Z" }, + { url = "https://files.pythonhosted.org/packages/62/6a/8b89d24db2d32d433dffcd6a8779159da109842434f1dd2f6e71f32f738c/MarkupSafe-3.0.2-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:b5a6b3ada725cea8a5e634536b1b01c30bcdcd7f9c6fff4151548d5bf6b3a36c", size = 14510, upload-time = "2024-10-18T15:21:33.625Z" }, + { url = "https://files.pythonhosted.org/packages/7a/06/a10f955f70a2e5a9bf78d11a161029d278eeacbd35ef806c3fd17b13060d/MarkupSafe-3.0.2-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:a904af0a6162c73e3edcb969eeeb53a63ceeb5d8cf642fade7d39e7963a22ddb", size = 12486, upload-time = "2024-10-18T15:21:34.611Z" }, + { url = "https://files.pythonhosted.org/packages/34/cf/65d4a571869a1a9078198ca28f39fba5fbb910f952f9dbc5220afff9f5e6/MarkupSafe-3.0.2-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4aa4e5faecf353ed117801a068ebab7b7e09ffb6e1d5e412dc852e0da018126c", size = 25480, upload-time = "2024-10-18T15:21:35.398Z" }, + { url = "https://files.pythonhosted.org/packages/0c/e3/90e9651924c430b885468b56b3d597cabf6d72be4b24a0acd1fa0e12af67/MarkupSafe-3.0.2-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c0ef13eaeee5b615fb07c9a7dadb38eac06a0608b41570d8ade51c56539e509d", size = 23914, upload-time = "2024-10-18T15:21:36.231Z" }, + { url = "https://files.pythonhosted.org/packages/66/8c/6c7cf61f95d63bb866db39085150df1f2a5bd3335298f14a66b48e92659c/MarkupSafe-3.0.2-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d16a81a06776313e817c951135cf7340a3e91e8c1ff2fac444cfd75fffa04afe", size = 23796, upload-time = "2024-10-18T15:21:37.073Z" }, + { url = "https://files.pythonhosted.org/packages/bb/35/cbe9238ec3f47ac9a7c8b3df7a808e7cb50fe149dc7039f5f454b3fba218/MarkupSafe-3.0.2-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:6381026f158fdb7c72a168278597a5e3a5222e83ea18f543112b2662a9b699c5", size = 25473, upload-time = "2024-10-18T15:21:37.932Z" }, + { url = "https://files.pythonhosted.org/packages/e6/32/7621a4382488aa283cc05e8984a9c219abad3bca087be9ec77e89939ded9/MarkupSafe-3.0.2-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:3d79d162e7be8f996986c064d1c7c817f6df3a77fe3d6859f6f9e7be4b8c213a", size = 24114, upload-time = "2024-10-18T15:21:39.799Z" }, + { url = "https://files.pythonhosted.org/packages/0d/80/0985960e4b89922cb5a0bac0ed39c5b96cbc1a536a99f30e8c220a996ed9/MarkupSafe-3.0.2-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:131a3c7689c85f5ad20f9f6fb1b866f402c445b220c19fe4308c0b147ccd2ad9", size = 24098, upload-time = "2024-10-18T15:21:40.813Z" }, + { url = "https://files.pythonhosted.org/packages/82/78/fedb03c7d5380df2427038ec8d973587e90561b2d90cd472ce9254cf348b/MarkupSafe-3.0.2-cp313-cp313t-win32.whl", hash = "sha256:ba8062ed2cf21c07a9e295d5b8a2a5ce678b913b45fdf68c32d95d6c1291e0b6", size = 15208, upload-time = "2024-10-18T15:21:41.814Z" }, + { url = "https://files.pythonhosted.org/packages/4f/65/6079a46068dfceaeabb5dcad6d674f5f5c61a6fa5673746f42a9f4c233b3/MarkupSafe-3.0.2-cp313-cp313t-win_amd64.whl", hash = "sha256:e444a31f8db13eb18ada366ab3cf45fd4b31e4db1236a4448f68778c1d1a5a2f", size = 15739, upload-time = "2024-10-18T15:21:42.784Z" }, +] + +[[package]] +name = "multiaddr" +version = "0.0.9" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "base58" }, + { name = "netaddr" }, + { name = "six" }, + { name = "varint" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/12/f4/fa5353022ad8e0fd364bfa8b474f9562c36ce1305fad31fe52b849e30795/multiaddr-0.0.9.tar.gz", hash = "sha256:30b2695189edc3d5b90f1c303abb8f02d963a3a4edf2e7178b975eb417ab0ecf", size = 24726, upload-time = "2019-12-23T07:06:21.146Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/51/59/df732566d951c33f00a4022fc5bf9c5d1661b1c2cdaf56e75a1a5fa8f829/multiaddr-0.0.9-py2.py3-none-any.whl", hash = "sha256:5c0f862cbcf19aada2a899f80ef896ddb2e85614e0c8f04dd287c06c69dac95b", size = 16281, upload-time = "2019-12-23T07:06:18.915Z" }, +] + +[[package]] +name = "mypy-extensions" +version = "1.1.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/a2/6e/371856a3fb9d31ca8dac321cda606860fa4548858c0cc45d9d1d4ca2628b/mypy_extensions-1.1.0.tar.gz", hash = "sha256:52e68efc3284861e772bbcd66823fde5ae21fd2fdb51c62a211403730b916558", size = 6343, upload-time = "2025-04-22T14:54:24.164Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/79/7b/2c79738432f5c924bef5071f933bcc9efd0473bac3b4aa584a6f7c1c8df8/mypy_extensions-1.1.0-py3-none-any.whl", hash = "sha256:1be4cccdb0f2482337c4743e60421de3a356cd97508abadd57d47403e94f5505", size = 4963, upload-time = "2025-04-22T14:54:22.983Z" }, +] + +[[package]] +name = "mypy-protobuf" +version = "3.6.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "protobuf" }, + { name = "types-protobuf" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/4d/6f/282d64d66bf48ce60e38a6560753f784e0f88ab245ac2fb5e93f701a36cd/mypy-protobuf-3.6.0.tar.gz", hash = "sha256:02f242eb3409f66889f2b1a3aa58356ec4d909cdd0f93115622e9e70366eca3c", size = 24445, upload-time = "2024-04-01T20:24:42.837Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e8/73/d6b999782ae22f16971cc05378b3b33f6a89ede3b9619e8366aa23484bca/mypy_protobuf-3.6.0-py3-none-any.whl", hash = "sha256:56176e4d569070e7350ea620262478b49b7efceba4103d468448f1d21492fd6c", size = 16434, upload-time = "2024-04-01T20:24:40.583Z" }, +] + +[[package]] +name = "netaddr" +version = "1.3.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/54/90/188b2a69654f27b221fba92fda7217778208532c962509e959a9cee5229d/netaddr-1.3.0.tar.gz", hash = "sha256:5c3c3d9895b551b763779ba7db7a03487dc1f8e3b385af819af341ae9ef6e48a", size = 2260504, upload-time = "2024-05-28T21:30:37.743Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/12/cc/f4fe2c7ce68b92cbf5b2d379ca366e1edae38cccaad00f69f529b460c3ef/netaddr-1.3.0-py3-none-any.whl", hash = "sha256:c2c6a8ebe5554ce33b7d5b3a306b71bbb373e000bbbf2350dd5213cc56e3dbbe", size = 2262023, upload-time = "2024-05-28T21:30:34.191Z" }, +] + +[[package]] +name = "noiseprotocol" +version = "0.3.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "cryptography" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/76/17/fcf8a90dcf36fe00b475e395f34d92f42c41379c77b25a16066f63002f95/noiseprotocol-0.3.1.tar.gz", hash = "sha256:b092a871b60f6a8f07f17950dc9f7098c8fe7d715b049bd4c24ee3752b90d645", size = 16890, upload-time = "2020-11-25T19:06:48.938Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/9d/e1/76e4694201d67b93a6f1644b2588b4a3d965419fe189416e3496cf415db5/noiseprotocol-0.3.1-py3-none-any.whl", hash = "sha256:2e1a603a38439636cf0ffd8b3e8b12cee27d368a28b41be7dbe568b2abb23111", size = 20546, upload-time = "2020-03-03T18:51:28.095Z" }, +] + +[[package]] +name = "outcome" +version = "1.3.0.post0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "attrs" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/98/df/77698abfac98571e65ffeb0c1fba8ffd692ab8458d617a0eed7d9a8d38f2/outcome-1.3.0.post0.tar.gz", hash = "sha256:9dcf02e65f2971b80047b377468e72a268e15c0af3cf1238e6ff14f7f91143b8", size = 21060, upload-time = "2023-10-26T04:26:04.361Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/55/8b/5ab7257531a5d830fc8000c476e63c935488d74609b50f9384a643ec0a62/outcome-1.3.0.post0-py2.py3-none-any.whl", hash = "sha256:e771c5ce06d1415e356078d3bdd68523f284b4ce5419828922b6871e65eda82b", size = 10692, upload-time = "2023-10-26T04:26:02.532Z" }, +] + +[[package]] +name = "packaging" +version = "25.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/a1/d4/1fc4078c65507b51b96ca8f8c3ba19e6a61c8253c72794544580a7b6c24d/packaging-25.0.tar.gz", hash = "sha256:d443872c98d677bf60f6a1f2f8c1cb748e8fe762d2bf9d3148b5599295b0fc4f", size = 165727, upload-time = "2025-04-19T11:48:59.673Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/20/12/38679034af332785aac8774540895e234f4d07f7545804097de4b666afd8/packaging-25.0-py3-none-any.whl", hash = "sha256:29572ef2b1f17581046b3a2227d5c611fb25ec70ca1ba8554b24b0e69331a484", size = 66469, upload-time = "2025-04-19T11:48:57.875Z" }, +] + +[[package]] +name = "protobuf" +version = "6.31.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/13/48/718c1e104a2e89970a8ff3b06d87e152834b576c570a6908f8c17ba88d65/protobuf-6.31.0.tar.gz", hash = "sha256:314fab1a6a316469dc2dd46f993cbbe95c861ea6807da910becfe7475bc26ffe", size = 441644, upload-time = "2025-05-14T17:58:27.862Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/b6/77/8671682038b08237c927215fa3296bc1c54e4086fe542c87017c1b626663/protobuf-6.31.0-cp310-abi3-win32.whl", hash = "sha256:10bd62802dfa0588649740a59354090eaf54b8322f772fbdcca19bc78d27f0d6", size = 423437, upload-time = "2025-05-14T17:58:16.116Z" }, + { url = "https://files.pythonhosted.org/packages/e4/07/cc9b0cbf7593f6ef8cf87fa9b0e55cd74c5cb526dd89ad84aa7d6547ef8d/protobuf-6.31.0-cp310-abi3-win_amd64.whl", hash = "sha256:3e987c99fd634be8347246a02123250f394ba20573c953de133dc8b2c107dd71", size = 435118, upload-time = "2025-05-14T17:58:18.591Z" }, + { url = "https://files.pythonhosted.org/packages/21/46/33f884aa8bc59114dc97e0d954ca4618c556483670236008c88fbb7e834f/protobuf-6.31.0-cp39-abi3-macosx_10_9_universal2.whl", hash = "sha256:2c812f0f96ceb6b514448cefeb1df54ec06dde456783f5099c0e2f8a0f2caa89", size = 425439, upload-time = "2025-05-14T17:58:19.709Z" }, + { url = "https://files.pythonhosted.org/packages/9b/f2/9a676b50229ce37b12777d7b21de90ae7bc0f9505d07e72e2e8d47b8d165/protobuf-6.31.0-cp39-abi3-manylinux2014_aarch64.whl", hash = "sha256:67ce50195e4e584275623b8e6bc6d3d3dfd93924bf6116b86b3b8975ab9e4571", size = 321950, upload-time = "2025-05-14T17:58:22.04Z" }, + { url = "https://files.pythonhosted.org/packages/a1/a7/243fa2d3c1b7675d54744b32dacf30356f4c27c0d3ad940ca8745a1c6b2c/protobuf-6.31.0-cp39-abi3-manylinux2014_x86_64.whl", hash = "sha256:5353e38844168a327acd2b2aa440044411cd8d1b6774d5701008bd1dba067c79", size = 320904, upload-time = "2025-05-14T17:58:23.438Z" }, + { url = "https://files.pythonhosted.org/packages/ee/01/1ed1d482960a5718fd99c82f6d79120181947cfd4667ec3944d448ed44a3/protobuf-6.31.0-py3-none-any.whl", hash = "sha256:6ac2e82556e822c17a8d23aa1190bbc1d06efb9c261981da95c71c9da09e9e23", size = 168558, upload-time = "2025-05-14T17:58:26.923Z" }, +] + +[[package]] +name = "pycparser" +version = "2.22" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/1d/b2/31537cf4b1ca988837256c910a668b553fceb8f069bedc4b1c826024b52c/pycparser-2.22.tar.gz", hash = "sha256:491c8be9c040f5390f5bf44a5b07752bd07f56edf992381b05c701439eec10f6", size = 172736, upload-time = "2024-03-30T13:22:22.564Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/13/a3/a812df4e2dd5696d1f351d58b8fe16a405b234ad2886a0dab9183fb78109/pycparser-2.22-py3-none-any.whl", hash = "sha256:c3702b6d3dd8c7abc1afa565d7e63d53a1d0bd86cdc24edd75470f4de499cfcc", size = 117552, upload-time = "2024-03-30T13:22:20.476Z" }, +] + +[[package]] +name = "pycryptodome" +version = "3.23.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/8e/a6/8452177684d5e906854776276ddd34eca30d1b1e15aa1ee9cefc289a33f5/pycryptodome-3.23.0.tar.gz", hash = "sha256:447700a657182d60338bab09fdb27518f8856aecd80ae4c6bdddb67ff5da44ef", size = 4921276, upload-time = "2025-05-17T17:21:45.242Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/04/5d/bdb09489b63cd34a976cc9e2a8d938114f7a53a74d3dd4f125ffa49dce82/pycryptodome-3.23.0-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:0011f7f00cdb74879142011f95133274741778abba114ceca229adbf8e62c3e4", size = 2495152, upload-time = "2025-05-17T17:20:20.833Z" }, + { url = "https://files.pythonhosted.org/packages/a7/ce/7840250ed4cc0039c433cd41715536f926d6e86ce84e904068eb3244b6a6/pycryptodome-3.23.0-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:90460fc9e088ce095f9ee8356722d4f10f86e5be06e2354230a9880b9c549aae", size = 1639348, upload-time = "2025-05-17T17:20:23.171Z" }, + { url = "https://files.pythonhosted.org/packages/ee/f0/991da24c55c1f688d6a3b5a11940567353f74590734ee4a64294834ae472/pycryptodome-3.23.0-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4764e64b269fc83b00f682c47443c2e6e85b18273712b98aa43bcb77f8570477", size = 2184033, upload-time = "2025-05-17T17:20:25.424Z" }, + { url = "https://files.pythonhosted.org/packages/54/16/0e11882deddf00f68b68dd4e8e442ddc30641f31afeb2bc25588124ac8de/pycryptodome-3.23.0-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:eb8f24adb74984aa0e5d07a2368ad95276cf38051fe2dc6605cbcf482e04f2a7", size = 2270142, upload-time = "2025-05-17T17:20:27.808Z" }, + { url = "https://files.pythonhosted.org/packages/d5/fc/4347fea23a3f95ffb931f383ff28b3f7b1fe868739182cb76718c0da86a1/pycryptodome-3.23.0-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d97618c9c6684a97ef7637ba43bdf6663a2e2e77efe0f863cce97a76af396446", size = 2309384, upload-time = "2025-05-17T17:20:30.765Z" }, + { url = "https://files.pythonhosted.org/packages/6e/d9/c5261780b69ce66d8cfab25d2797bd6e82ba0241804694cd48be41add5eb/pycryptodome-3.23.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:9a53a4fe5cb075075d515797d6ce2f56772ea7e6a1e5e4b96cf78a14bac3d265", size = 2183237, upload-time = "2025-05-17T17:20:33.736Z" }, + { url = "https://files.pythonhosted.org/packages/5a/6f/3af2ffedd5cfa08c631f89452c6648c4d779e7772dfc388c77c920ca6bbf/pycryptodome-3.23.0-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:763d1d74f56f031788e5d307029caef067febf890cd1f8bf61183ae142f1a77b", size = 2343898, upload-time = "2025-05-17T17:20:36.086Z" }, + { url = "https://files.pythonhosted.org/packages/9a/dc/9060d807039ee5de6e2f260f72f3d70ac213993a804f5e67e0a73a56dd2f/pycryptodome-3.23.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:954af0e2bd7cea83ce72243b14e4fb518b18f0c1649b576d114973e2073b273d", size = 2269197, upload-time = "2025-05-17T17:20:38.414Z" }, + { url = "https://files.pythonhosted.org/packages/f9/34/e6c8ca177cb29dcc4967fef73f5de445912f93bd0343c9c33c8e5bf8cde8/pycryptodome-3.23.0-cp313-cp313t-win32.whl", hash = "sha256:257bb3572c63ad8ba40b89f6fc9d63a2a628e9f9708d31ee26560925ebe0210a", size = 1768600, upload-time = "2025-05-17T17:20:40.688Z" }, + { url = "https://files.pythonhosted.org/packages/e4/1d/89756b8d7ff623ad0160f4539da571d1f594d21ee6d68be130a6eccb39a4/pycryptodome-3.23.0-cp313-cp313t-win_amd64.whl", hash = "sha256:6501790c5b62a29fcb227bd6b62012181d886a767ce9ed03b303d1f22eb5c625", size = 1799740, upload-time = "2025-05-17T17:20:42.413Z" }, + { url = "https://files.pythonhosted.org/packages/5d/61/35a64f0feaea9fd07f0d91209e7be91726eb48c0f1bfc6720647194071e4/pycryptodome-3.23.0-cp313-cp313t-win_arm64.whl", hash = "sha256:9a77627a330ab23ca43b48b130e202582e91cc69619947840ea4d2d1be21eb39", size = 1703685, upload-time = "2025-05-17T17:20:44.388Z" }, + { url = "https://files.pythonhosted.org/packages/db/6c/a1f71542c969912bb0e106f64f60a56cc1f0fabecf9396f45accbe63fa68/pycryptodome-3.23.0-cp37-abi3-macosx_10_9_universal2.whl", hash = "sha256:187058ab80b3281b1de11c2e6842a357a1f71b42cb1e15bce373f3d238135c27", size = 2495627, upload-time = "2025-05-17T17:20:47.139Z" }, + { url = "https://files.pythonhosted.org/packages/6e/4e/a066527e079fc5002390c8acdd3aca431e6ea0a50ffd7201551175b47323/pycryptodome-3.23.0-cp37-abi3-macosx_10_9_x86_64.whl", hash = "sha256:cfb5cd445280c5b0a4e6187a7ce8de5a07b5f3f897f235caa11f1f435f182843", size = 1640362, upload-time = "2025-05-17T17:20:50.392Z" }, + { url = "https://files.pythonhosted.org/packages/50/52/adaf4c8c100a8c49d2bd058e5b551f73dfd8cb89eb4911e25a0c469b6b4e/pycryptodome-3.23.0-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:67bd81fcbe34f43ad9422ee8fd4843c8e7198dd88dd3d40e6de42ee65fbe1490", size = 2182625, upload-time = "2025-05-17T17:20:52.866Z" }, + { url = "https://files.pythonhosted.org/packages/5f/e9/a09476d436d0ff1402ac3867d933c61805ec2326c6ea557aeeac3825604e/pycryptodome-3.23.0-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c8987bd3307a39bc03df5c8e0e3d8be0c4c3518b7f044b0f4c15d1aa78f52575", size = 2268954, upload-time = "2025-05-17T17:20:55.027Z" }, + { url = "https://files.pythonhosted.org/packages/f9/c5/ffe6474e0c551d54cab931918127c46d70cab8f114e0c2b5a3c071c2f484/pycryptodome-3.23.0-cp37-abi3-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:aa0698f65e5b570426fc31b8162ed4603b0c2841cbb9088e2b01641e3065915b", size = 2308534, upload-time = "2025-05-17T17:20:57.279Z" }, + { url = "https://files.pythonhosted.org/packages/18/28/e199677fc15ecf43010f2463fde4c1a53015d1fe95fb03bca2890836603a/pycryptodome-3.23.0-cp37-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:53ecbafc2b55353edcebd64bf5da94a2a2cdf5090a6915bcca6eca6cc452585a", size = 2181853, upload-time = "2025-05-17T17:20:59.322Z" }, + { url = "https://files.pythonhosted.org/packages/ce/ea/4fdb09f2165ce1365c9eaefef36625583371ee514db58dc9b65d3a255c4c/pycryptodome-3.23.0-cp37-abi3-musllinux_1_2_i686.whl", hash = "sha256:156df9667ad9f2ad26255926524e1c136d6664b741547deb0a86a9acf5ea631f", size = 2342465, upload-time = "2025-05-17T17:21:03.83Z" }, + { url = "https://files.pythonhosted.org/packages/22/82/6edc3fc42fe9284aead511394bac167693fb2b0e0395b28b8bedaa07ef04/pycryptodome-3.23.0-cp37-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:dea827b4d55ee390dc89b2afe5927d4308a8b538ae91d9c6f7a5090f397af1aa", size = 2267414, upload-time = "2025-05-17T17:21:06.72Z" }, + { url = "https://files.pythonhosted.org/packages/59/fe/aae679b64363eb78326c7fdc9d06ec3de18bac68be4b612fc1fe8902693c/pycryptodome-3.23.0-cp37-abi3-win32.whl", hash = "sha256:507dbead45474b62b2bbe318eb1c4c8ee641077532067fec9c1aa82c31f84886", size = 1768484, upload-time = "2025-05-17T17:21:08.535Z" }, + { url = "https://files.pythonhosted.org/packages/54/2f/e97a1b8294db0daaa87012c24a7bb714147c7ade7656973fd6c736b484ff/pycryptodome-3.23.0-cp37-abi3-win_amd64.whl", hash = "sha256:c75b52aacc6c0c260f204cbdd834f76edc9fb0d8e0da9fbf8352ef58202564e2", size = 1799636, upload-time = "2025-05-17T17:21:10.393Z" }, + { url = "https://files.pythonhosted.org/packages/18/3d/f9441a0d798bf2b1e645adc3265e55706aead1255ccdad3856dbdcffec14/pycryptodome-3.23.0-cp37-abi3-win_arm64.whl", hash = "sha256:11eeeb6917903876f134b56ba11abe95c0b0fd5e3330def218083c7d98bbcb3c", size = 1703675, upload-time = "2025-05-17T17:21:13.146Z" }, +] + +[[package]] +name = "pymultihash" +version = "0.8.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/32/64/53a5c75b11fa697d74ae5c52b38ee6c98fa3bf3bfd50e064ae11ef1a0db3/pymultihash-0.8.2.tar.gz", hash = "sha256:49c75a1ae9ecc6d22d259064d4597b3685da3f0258f4ded632e03a3a79af215b", size = 17471, upload-time = "2016-06-12T18:06:00.432Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/1e/1c/570697fafd87adcec479b9ad34dc8371a363aa14bd9edaece5f0b8066903/pymultihash-0.8.2-py3-none-any.whl", hash = "sha256:f7fa840b24bd6acbd6b073fcd330f10e15619387297babf1dd13ca4dae6e8209", size = 13505, upload-time = "2016-06-12T18:05:55.562Z" }, +] + +[[package]] +name = "pynacl" +version = "1.5.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "cffi" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/a7/22/27582568be639dfe22ddb3902225f91f2f17ceff88ce80e4db396c8986da/PyNaCl-1.5.0.tar.gz", hash = "sha256:8ac7448f09ab85811607bdd21ec2464495ac8b7c66d146bf545b0f08fb9220ba", size = 3392854, upload-time = "2022-01-07T22:05:41.134Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/ce/75/0b8ede18506041c0bf23ac4d8e2971b4161cd6ce630b177d0a08eb0d8857/PyNaCl-1.5.0-cp36-abi3-macosx_10_10_universal2.whl", hash = "sha256:401002a4aaa07c9414132aaed7f6836ff98f59277a234704ff66878c2ee4a0d1", size = 349920, upload-time = "2022-01-07T22:05:49.156Z" }, + { url = "https://files.pythonhosted.org/packages/59/bb/fddf10acd09637327a97ef89d2a9d621328850a72f1fdc8c08bdf72e385f/PyNaCl-1.5.0-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl", hash = "sha256:52cb72a79269189d4e0dc537556f4740f7f0a9ec41c1322598799b0bdad4ef92", size = 601722, upload-time = "2022-01-07T22:05:50.989Z" }, + { url = "https://files.pythonhosted.org/packages/5d/70/87a065c37cca41a75f2ce113a5a2c2aa7533be648b184ade58971b5f7ccc/PyNaCl-1.5.0-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a36d4a9dda1f19ce6e03c9a784a2921a4b726b02e1c736600ca9c22029474394", size = 680087, upload-time = "2022-01-07T22:05:52.539Z" }, + { url = "https://files.pythonhosted.org/packages/ee/87/f1bb6a595f14a327e8285b9eb54d41fef76c585a0edef0a45f6fc95de125/PyNaCl-1.5.0-cp36-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:0c84947a22519e013607c9be43706dd42513f9e6ae5d39d3613ca1e142fba44d", size = 856678, upload-time = "2022-01-07T22:05:54.251Z" }, + { url = "https://files.pythonhosted.org/packages/66/28/ca86676b69bf9f90e710571b67450508484388bfce09acf8a46f0b8c785f/PyNaCl-1.5.0-cp36-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:06b8f6fa7f5de8d5d2f7573fe8c863c051225a27b61e6860fd047b1775807858", size = 1133660, upload-time = "2022-01-07T22:05:56.056Z" }, + { url = "https://files.pythonhosted.org/packages/3d/85/c262db650e86812585e2bc59e497a8f59948a005325a11bbbc9ecd3fe26b/PyNaCl-1.5.0-cp36-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:a422368fc821589c228f4c49438a368831cb5bbc0eab5ebe1d7fac9dded6567b", size = 663824, upload-time = "2022-01-07T22:05:57.434Z" }, + { url = "https://files.pythonhosted.org/packages/fd/1a/cc308a884bd299b651f1633acb978e8596c71c33ca85e9dc9fa33a5399b9/PyNaCl-1.5.0-cp36-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:61f642bf2378713e2c2e1de73444a3778e5f0a38be6fee0fe532fe30060282ff", size = 1117912, upload-time = "2022-01-07T22:05:58.665Z" }, + { url = "https://files.pythonhosted.org/packages/25/2d/b7df6ddb0c2a33afdb358f8af6ea3b8c4d1196ca45497dd37a56f0c122be/PyNaCl-1.5.0-cp36-abi3-win32.whl", hash = "sha256:e46dae94e34b085175f8abb3b0aaa7da40767865ac82c928eeb9e57e1ea8a543", size = 204624, upload-time = "2022-01-07T22:06:00.085Z" }, + { url = "https://files.pythonhosted.org/packages/5e/22/d3db169895faaf3e2eda892f005f433a62db2decbcfbc2f61e6517adfa87/PyNaCl-1.5.0-cp36-abi3-win_amd64.whl", hash = "sha256:20f42270d27e1b6a29f54032090b972d97f0a1b0948cc52392041ef7831fee93", size = 212141, upload-time = "2022-01-07T22:06:01.861Z" }, +] + +[[package]] +name = "rpcudp" +version = "5.0.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "u-msgpack-python" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/39/5b/99ee4dd6080d857f029ad209860d461305f5fba9fef2316548a1d131e4c2/rpcudp-5.0.1.tar.gz", hash = "sha256:b6793b9b3e84e9c8510fa78e259cc3204c1b03fd2bb4fbf0f457cd391933bb78", size = 8777, upload-time = "2025-03-31T01:01:56.602Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/05/8b/33f35f2a730f848b5e5ac24dcb50c97387b98756e0f199ee8da30ef19fe7/rpcudp-5.0.1-py3-none-any.whl", hash = "sha256:8bf7cf1caed687acbbf2a37b67a92b02d109483a2da28fa13cca93b9ee873b9a", size = 5594, upload-time = "2025-03-31T01:01:55.296Z" }, +] + +[[package]] +name = "six" +version = "1.17.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/94/e7/b2c673351809dca68a0e064b6af791aa332cf192da575fd474ed7d6f16a2/six-1.17.0.tar.gz", hash = "sha256:ff70335d468e7eb6ec65b95b99d3a2836546063f63acc5171de367e834932a81", size = 34031, upload-time = "2024-12-04T17:35:28.174Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/b7/ce/149a00dd41f10bc29e5921b496af8b574d8413afcd5e30dfa0ed46c2cc5e/six-1.17.0-py2.py3-none-any.whl", hash = "sha256:4721f391ed90541fddacab5acf947aa0d3dc7d27b2e1e8eda2be8970586c3274", size = 11050, upload-time = "2024-12-04T17:35:26.475Z" }, +] + +[[package]] +name = "sniffio" +version = "1.3.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/a2/87/a6771e1546d97e7e041b6ae58d80074f81b7d5121207425c964ddf5cfdbd/sniffio-1.3.1.tar.gz", hash = "sha256:f4324edc670a0f49750a81b895f35c3adb843cca46f0530f79fc1babb23789dc", size = 20372, upload-time = "2024-02-25T23:20:04.057Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e9/44/75a9c9421471a6c4805dbf2356f7c181a29c1879239abab1ea2cc8f38b40/sniffio-1.3.1-py3-none-any.whl", hash = "sha256:2f6da418d1f1e0fddd844478f41680e794e6051915791a034ff65e5f100525a2", size = 10235, upload-time = "2024-02-25T23:20:01.196Z" }, +] + +[[package]] +name = "sortedcontainers" +version = "2.4.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/e8/c4/ba2f8066cceb6f23394729afe52f3bf7adec04bf9ed2c820b39e19299111/sortedcontainers-2.4.0.tar.gz", hash = "sha256:25caa5a06cc30b6b83d11423433f65d1f9d76c4c6a0c90e3379eaa43b9bfdb88", size = 30594, upload-time = "2021-05-16T22:03:42.897Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/32/46/9cb0e58b2deb7f82b84065f37f3bffeb12413f947f9388e4cac22c4621ce/sortedcontainers-2.4.0-py2.py3-none-any.whl", hash = "sha256:a163dcaede0f1c021485e957a39245190e74249897e2ae4b2aa38595db237ee0", size = 29575, upload-time = "2021-05-16T22:03:41.177Z" }, +] + +[[package]] +name = "starknet" +version = "0.1.0" +source = { virtual = "." } +dependencies = [ + { name = "eth-hash" }, + { name = "jinja2" }, + { name = "libp2p" }, + { name = "pynacl" }, +] + +[package.metadata] +requires-dist = [ + { name = "eth-hash" }, + { name = "jinja2" }, + { name = "libp2p", specifier = "==0.2.4" }, + { name = "pynacl" }, +] + +[[package]] +name = "trio" +version = "0.30.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "attrs" }, + { name = "cffi", marker = "implementation_name != 'pypy' and os_name == 'nt'" }, + { name = "idna" }, + { name = "outcome" }, + { name = "sniffio" }, + { name = "sortedcontainers" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/01/c1/68d582b4d3a1c1f8118e18042464bb12a7c1b75d64d75111b297687041e3/trio-0.30.0.tar.gz", hash = "sha256:0781c857c0c81f8f51e0089929a26b5bb63d57f927728a5586f7e36171f064df", size = 593776, upload-time = "2025-04-21T00:48:19.507Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/69/8e/3f6dfda475ecd940e786defe6df6c500734e686c9cd0a0f8ef6821e9b2f2/trio-0.30.0-py3-none-any.whl", hash = "sha256:3bf4f06b8decf8d3cf00af85f40a89824669e2d033bb32469d34840edcfc22a5", size = 499194, upload-time = "2025-04-21T00:48:17.167Z" }, +] + +[[package]] +name = "trio-typing" +version = "0.10.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "async-generator" }, + { name = "importlib-metadata" }, + { name = "mypy-extensions" }, + { name = "packaging" }, + { name = "trio" }, + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/b5/74/a87aafa40ec3a37089148b859892cbe2eef08d132c816d58a60459be5337/trio-typing-0.10.0.tar.gz", hash = "sha256:065ee684296d52a8ab0e2374666301aec36ee5747ac0e7a61f230250f8907ac3", size = 38747, upload-time = "2023-12-01T02:54:55.508Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/89/ff/9bd795273eb14fac7f6a59d16cc8c4d0948a619a1193d375437c7f50f3eb/trio_typing-0.10.0-py3-none-any.whl", hash = "sha256:6d0e7ec9d837a2fe03591031a172533fbf4a1a95baf369edebfc51d5a49f0264", size = 42224, upload-time = "2023-12-01T02:54:54.1Z" }, +] + +[[package]] +name = "types-protobuf" +version = "6.30.2.20250516" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/ac/6c/5cf088aaa3927d1cc39910f60f220f5ff573ab1a6485b2836e8b26beb58c/types_protobuf-6.30.2.20250516.tar.gz", hash = "sha256:aecd1881770a9bb225ede66872ef7f0da4505edd0b193108edd9892e48d49a41", size = 62254, upload-time = "2025-05-16T03:06:50.794Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/c0/66/06a9c161f5dd5deb4f5c016ba29106a8f1903eb9a1ba77d407dd6588fecb/types_protobuf-6.30.2.20250516-py3-none-any.whl", hash = "sha256:8c226d05b5e8b2623111765fa32d6e648bbc24832b4c2fddf0fa340ba5d5b722", size = 76480, upload-time = "2025-05-16T03:06:49.444Z" }, +] + +[[package]] +name = "typing-extensions" +version = "4.13.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/f6/37/23083fcd6e35492953e8d2aaaa68b860eb422b34627b13f2ce3eb6106061/typing_extensions-4.13.2.tar.gz", hash = "sha256:e6c81219bd689f51865d9e372991c540bda33a0379d5573cddb9a3a23f7caaef", size = 106967, upload-time = "2025-04-10T14:19:05.416Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/8b/54/b1ae86c0973cc6f0210b53d508ca3641fb6d0c56823f288d108bc7ab3cc8/typing_extensions-4.13.2-py3-none-any.whl", hash = "sha256:a439e7c04b49fec3e5d3e2beaa21755cadbbdc391694e28ccdd36ca4a1408f8c", size = 45806, upload-time = "2025-04-10T14:19:03.967Z" }, +] + +[[package]] +name = "u-msgpack-python" +version = "2.8.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/36/9d/a40411a475e7d4838994b7f6bcc6bfca9acc5b119ce3a7503608c4428b49/u-msgpack-python-2.8.0.tar.gz", hash = "sha256:b801a83d6ed75e6df41e44518b4f2a9c221dc2da4bcd5380e3a0feda520bc61a", size = 18167, upload-time = "2023-05-18T09:28:12.187Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/b1/5e/512aeb40fd819f4660d00f96f5c7371ee36fc8c6b605128c5ee59e0b28c6/u_msgpack_python-2.8.0-py2.py3-none-any.whl", hash = "sha256:1d853d33e78b72c4228a2025b4db28cda81214076e5b0422ed0ae1b1b2bb586a", size = 10590, upload-time = "2023-05-18T09:28:10.323Z" }, +] + +[[package]] +name = "varint" +version = "1.0.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/a8/fe/1ea0ba0896dfa47186692655b86db3214c4b7c9e0e76c7b1dc257d101ab1/varint-1.0.2.tar.gz", hash = "sha256:a6ecc02377ac5ee9d65a6a8ad45c9ff1dac8ccee19400a5950fb51d594214ca5", size = 1886, upload-time = "2016-02-24T20:42:38.5Z" } + +[[package]] +name = "zipp" +version = "3.21.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/3f/50/bad581df71744867e9468ebd0bcd6505de3b275e06f202c2cb016e3ff56f/zipp-3.21.0.tar.gz", hash = "sha256:2c9958f6430a2040341a52eb608ed6dd93ef4392e02ffe219417c1b28b5dd1f4", size = 24545, upload-time = "2024-11-10T15:05:20.202Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/b7/1a/7e4798e9339adc931158c9d69ecc34f5e6791489d469f5e50ec15e35f458/zipp-3.21.0-py3-none-any.whl", hash = "sha256:ac1bbe05fd2991f160ebce24ffbac5f6d11d83dc90891255885223d42b3cd931", size = 9630, upload-time = "2024-11-10T15:05:19.275Z" }, +]