diff --git a/.dockerignore b/.dockerignore index 2922af64..6adc2cd0 100644 --- a/.dockerignore +++ b/.dockerignore @@ -1,13 +1,8 @@ -target -.github -.vscode -.githooks -**/Dockerfile -docker-compose* -LICENSE -**/tests -.env.example -remappings.txt -**/*.ptau -nightfall_bindings/build.rs +# Ignore everything under bin +configuration/bin/* +# But allow the keys directory itself +!configuration/bin/keys/ + +# And allow its contents +!configuration/bin/keys/** \ No newline at end of file diff --git a/.github/workflows/on-pull-request.yml b/.github/workflows/on-pull-request.yml index 5bdf5f82..c1584cb3 100644 --- a/.github/workflows/on-pull-request.yml +++ b/.github/workflows/on-pull-request.yml @@ -92,7 +92,7 @@ jobs: chmod 444 ptau-cache/ppot_26.ptau # Make it read-only echo "Cached ppot_26.ptau created" fi - ln -sf /home/testrunner/ptau-cache/ppot_26.ptau /home/testrunner/actions-runner/_work/nightfall_4_PV/nightfall_4_PV/configuration/bin/ppot_26.ptau + ln -sf /home/testrunner/ptau-cache/ppot_26.ptau /home/testrunner/actions-runner/_work/nightfall_4_PV/nightfall_4_PV/configuration/bin/trusted_setup/ppot_26.ptau - name: link bn254 setup cache shell: bash run: | @@ -101,7 +101,7 @@ jobs: VERSION_SUFFIX="${NF4_SRS_VERSION:-v1}" CACHE_DIR="/home/testrunner/srs-cache" CACHE_FILE="$CACHE_DIR/bn254_setup_26.${VERSION_SUFFIX}.cache" - TARGET_DIR="$GITHUB_WORKSPACE/configuration/bin" + TARGET_DIR="$GITHUB_WORKSPACE/configuration/bin/trusted_setup" TARGET="$TARGET_DIR/bn254_setup_26.cache" mkdir -p "$CACHE_DIR" "$TARGET_DIR" # Prevent two concurrent workflows from trampling the cache @@ -146,7 +146,7 @@ jobs: shell: bash run: | set -euo pipefail - BIN_DIR="$GITHUB_WORKSPACE/configuration/bin" + BIN_DIR="$GITHUB_WORKSPACE/configuration/bin/trusted_setup" mkdir -p "$BIN_DIR" hydrate() { local f="$1" diff --git a/Cargo.lock b/Cargo.lock index 427ad10b..9c07a7e7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -54,7 +54,7 @@ version = "0.7.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "891477e0c6a8957309ee5c45a6368af3ae14bb510732d2684ffa19af310920f9" dependencies = [ - "getrandom 0.2.16", + "getrandom 0.2.17", "once_cell", "version_check", ] @@ -89,9 +89,9 @@ checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923" [[package]] name = "alloy" -version = "1.1.2" +version = "1.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e15860af634cad451f598712c24ca7fd9b45d84fff68ab8d4967567fa996c64" +checksum = "4973038846323e4e69a433916522195dce2947770076c03078fc21c80ea0f1c4" dependencies = [ "alloy-consensus", "alloy-contract", @@ -116,9 +116,9 @@ dependencies = [ [[package]] name = "alloy-chains" -version = "0.2.20" +version = "0.2.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4bc32535569185cbcb6ad5fa64d989a47bccb9a08e27284b1f2a3ccf16e6d010" +checksum = "90f374d3c6d729268bbe2d0e0ff992bb97898b2df756691a62ee1d5f0506bc39" dependencies = [ "alloy-primitives", "num_enum", @@ -127,9 +127,9 @@ dependencies = [ [[package]] name = "alloy-consensus" -version = "1.1.2" +version = "1.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b6440213a22df93a87ed512d2f668e7dc1d62a05642d107f82d61edc9e12370" +checksum = "b0c0dc44157867da82c469c13186015b86abef209bf0e41625e4b68bac61d728" dependencies = [ "alloy-eips", "alloy-primitives", @@ -140,7 +140,7 @@ dependencies = [ "auto_impl", "borsh", "c-kzg", - "derive_more 2.0.1", + "derive_more 2.1.1", "either", "k256 0.13.4", "once_cell", @@ -149,14 +149,14 @@ dependencies = [ "serde", "serde_json", "serde_with 3.16.1", - "thiserror 2.0.17", + "thiserror 2.0.18", ] [[package]] name = "alloy-consensus-any" -version = "1.1.2" +version = "1.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "15d0bea09287942405c4f9d2a4f22d1e07611c2dbd9d5bf94b75366340f9e6e0" +checksum = "ba4cdb42df3871cd6b346d6a938ec2ba69a9a0f49d1f82714bc5c48349268434" dependencies = [ "alloy-consensus", "alloy-eips", @@ -168,9 +168,9 @@ dependencies = [ [[package]] name = "alloy-contract" -version = "1.1.2" +version = "1.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d69af404f1d00ddb42f2419788fa87746a4cd13bab271916d7726fda6c792d94" +checksum = "ca63b7125a981415898ffe2a2a696c83696c9c6bdb1671c8a912946bbd8e49e7" dependencies = [ "alloy-consensus", "alloy-dyn-abi", @@ -186,14 +186,14 @@ dependencies = [ "futures", "futures-util", "serde_json", - "thiserror 2.0.17", + "thiserror 2.0.18", ] [[package]] name = "alloy-core" -version = "1.4.1" +version = "1.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ca96214615ec8cf3fa2a54b32f486eb49100ca7fe7eb0b8c1137cd316e7250a" +checksum = "23e8604b0c092fabc80d075ede181c9b9e596249c70b99253082d7e689836529" dependencies = [ "alloy-dyn-abi", "alloy-json-abi", @@ -204,9 +204,9 @@ dependencies = [ [[package]] name = "alloy-dyn-abi" -version = "1.4.1" +version = "1.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fdff496dd4e98a81f4861e66f7eaf5f2488971848bb42d9c892f871730245c8" +checksum = "cc2db5c583aaef0255aa63a4fe827f826090142528bba48d1bf4119b62780cad" dependencies = [ "alloy-json-abi", "alloy-primitives", @@ -228,7 +228,7 @@ dependencies = [ "alloy-rlp", "crc", "serde", - "thiserror 2.0.17", + "thiserror 2.0.18", ] [[package]] @@ -254,37 +254,50 @@ dependencies = [ "borsh", "k256 0.13.4", "serde", - "thiserror 2.0.17", + "thiserror 2.0.18", +] + +[[package]] +name = "alloy-eip7928" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3231de68d5d6e75332b7489cfcc7f4dfabeba94d990a10e4b923af0e6623540" +dependencies = [ + "alloy-primitives", + "alloy-rlp", + "borsh", + "serde", ] [[package]] name = "alloy-eips" -version = "1.1.2" +version = "1.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4bd2c7ae05abcab4483ce821f12f285e01c0b33804e6883dd9ca1569a87ee2be" +checksum = "b9f7ef09f21bd1e9cb8a686f168cb4a206646804567f0889eadb8dcc4c9288c8" dependencies = [ "alloy-eip2124", "alloy-eip2930", "alloy-eip7702", + "alloy-eip7928", "alloy-primitives", "alloy-rlp", "alloy-serde", "auto_impl", "borsh", "c-kzg", - "derive_more 2.0.1", + "derive_more 2.1.1", "either", "serde", "serde_with 3.16.1", "sha2 0.10.9", - "thiserror 2.0.17", + "thiserror 2.0.18", ] [[package]] name = "alloy-genesis" -version = "1.1.2" +version = "1.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc47eaae86488b07ea8e20236184944072a78784a1f4993f8ec17b3aa5d08c21" +checksum = "7c9cf3b99f46615fbf7dc1add0c96553abb7bf88fc9ec70dfbe7ad0b47ba7fe8" dependencies = [ "alloy-eips", "alloy-primitives", @@ -310,9 +323,9 @@ dependencies = [ [[package]] name = "alloy-json-abi" -version = "1.4.1" +version = "1.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5513d5e6bd1cba6bdcf5373470f559f320c05c8c59493b6e98912fbe6733943f" +checksum = "e9dbe713da0c737d9e5e387b0ba790eb98b14dd207fe53eef50e19a5a8ec3dac" dependencies = [ "alloy-primitives", "alloy-sol-type-parser", @@ -322,24 +335,24 @@ dependencies = [ [[package]] name = "alloy-json-rpc" -version = "1.1.2" +version = "1.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "003f46c54f22854a32b9cc7972660a476968008ad505427eabab49225309ec40" +checksum = "ff42cd777eea61f370c0b10f2648a1c81e0b783066cd7269228aa993afd487f7" dependencies = [ "alloy-primitives", "alloy-sol-types", "http 1.4.0", "serde", "serde_json", - "thiserror 2.0.17", + "thiserror 2.0.18", "tracing", ] [[package]] name = "alloy-network" -version = "1.1.2" +version = "1.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f4029954d9406a40979f3a3b46950928a0fdcfe3ea8a9b0c17490d57e8aa0e3" +checksum = "8cbca04f9b410fdc51aaaf88433cbac761213905a65fe832058bcf6690585762" dependencies = [ "alloy-consensus", "alloy-consensus-any", @@ -354,18 +367,18 @@ dependencies = [ "alloy-sol-types", "async-trait", "auto_impl", - "derive_more 2.0.1", + "derive_more 2.1.1", "futures-utils-wasm", "serde", "serde_json", - "thiserror 2.0.17", + "thiserror 2.0.18", ] [[package]] name = "alloy-network-primitives" -version = "1.1.2" +version = "1.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7805124ad69e57bbae7731c9c344571700b2a18d351bda9e0eba521c991d1bcb" +checksum = "42d6d15e069a8b11f56bef2eccbad2a873c6dd4d4c81d04dda29710f5ea52f04" dependencies = [ "alloy-consensus", "alloy-eips", @@ -376,9 +389,9 @@ dependencies = [ [[package]] name = "alloy-node-bindings" -version = "1.1.2" +version = "1.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b03d35475a02d2a8b76209cb4a1336cb7d85331d10a0f6ec329ee42151695c19" +checksum = "091dc8117d84de3a9ac7ec97f2c4d83987e24d485b478d26aa1ec455d7d52f7d" dependencies = [ "alloy-genesis", "alloy-hardforks", @@ -387,46 +400,47 @@ dependencies = [ "alloy-signer", "alloy-signer-local", "k256 0.13.4", + "libc", "rand 0.8.5", "serde_json", "tempfile", - "thiserror 2.0.17", + "thiserror 2.0.18", "tracing", "url", ] [[package]] name = "alloy-primitives" -version = "1.4.1" +version = "1.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "355bf68a433e0fd7f7d33d5a9fc2583fde70bf5c530f63b80845f8da5505cf28" +checksum = "de3b431b4e72cd8bd0ec7a50b4be18e73dab74de0dba180eef171055e5d5926e" dependencies = [ "alloy-rlp", "bytes", "cfg-if", "const-hex", - "derive_more 2.0.1", + "derive_more 2.1.1", "foldhash 0.2.0", "hashbrown 0.16.1", - "indexmap 2.12.1", + "indexmap 2.13.0", "itoa", "k256 0.13.4", "keccak-asm", "paste", "proptest", "rand 0.9.2", + "rapidhash", "ruint", "rustc-hash", "serde", "sha3", - "tiny-keccak", ] [[package]] name = "alloy-provider" -version = "1.1.2" +version = "1.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d369e12c92870d069e0c9dc5350377067af8a056e29e3badf8446099d7e00889" +checksum = "d181c8cc7cf4805d7e589bf4074d56d55064fa1a979f005a45a62b047616d870" dependencies = [ "alloy-chains", "alloy-consensus", @@ -458,10 +472,10 @@ dependencies = [ "lru", "parking_lot 0.12.5", "pin-project", - "reqwest 0.12.24", + "reqwest 0.12.28", "serde", "serde_json", - "thiserror 2.0.17", + "thiserror 2.0.18", "tokio", "tracing", "url", @@ -470,9 +484,9 @@ dependencies = [ [[package]] name = "alloy-pubsub" -version = "1.1.2" +version = "1.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f77d20cdbb68a614c7a86b3ffef607b37d087bb47a03c58f4c3f8f99bc3ace3b" +checksum = "e8bd82953194dec221aa4cbbbb0b1e2df46066fe9d0333ac25b43a311e122d13" dependencies = [ "alloy-json-rpc", "alloy-primitives", @@ -492,9 +506,9 @@ dependencies = [ [[package]] name = "alloy-rlp" -version = "0.3.12" +version = "0.3.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f70d83b765fdc080dbcd4f4db70d8d23fe4761f2f02ebfa9146b833900634b4" +checksum = "e93e50f64a77ad9c5470bf2ad0ca02f228da70c792a8f06634801e202579f35e" dependencies = [ "alloy-rlp-derive", "arrayvec", @@ -503,20 +517,20 @@ dependencies = [ [[package]] name = "alloy-rlp-derive" -version = "0.3.12" +version = "0.3.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64b728d511962dda67c1bc7ea7c03736ec275ed2cf4c35d9585298ac9ccf3b73" +checksum = "ce8849c74c9ca0f5a03da1c865e3eb6f768df816e67dd3721a398a8a7e398011" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.117", ] [[package]] name = "alloy-rpc-client" -version = "1.1.2" +version = "1.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "31c89883fe6b7381744cbe80fef638ac488ead4f1956a4278956a1362c71cd2e" +checksum = "f2792758a93ae32a32e9047c843d536e1448044f78422d71bf7d7c05149e103f" dependencies = [ "alloy-json-rpc", "alloy-primitives", @@ -527,7 +541,7 @@ dependencies = [ "alloy-transport-ws", "futures", "pin-project", - "reqwest 0.12.24", + "reqwest 0.12.28", "serde", "serde_json", "tokio", @@ -540,9 +554,9 @@ dependencies = [ [[package]] name = "alloy-rpc-types" -version = "1.1.2" +version = "1.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64e279e6d40ee40fe8f76753b678d8d5d260cb276dc6c8a8026099b16d2b43f4" +checksum = "7bdcbf9dfd5eea8bfeb078b1d906da8cd3a39c4d4dbe7a628025648e323611f6" dependencies = [ "alloy-primitives", "alloy-rpc-types-anvil", @@ -557,9 +571,9 @@ dependencies = [ [[package]] name = "alloy-rpc-types-anvil" -version = "1.1.2" +version = "1.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e176c26fdd87893b6afeb5d92099d8f7e7a1fe11d6f4fe0883d6e33ac5f31ba" +checksum = "e0a3100b76987c1b1dc81f3abe592b7edc29e92b1242067a69d65e0030b35cf9" dependencies = [ "alloy-primitives", "alloy-rpc-types-eth", @@ -569,9 +583,9 @@ dependencies = [ [[package]] name = "alloy-rpc-types-any" -version = "1.1.2" +version = "1.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b43c1622aac2508d528743fd4cfdac1dea92d5a8fa894038488ff7edd0af0b32" +checksum = "dd720b63f82b457610f2eaaf1f32edf44efffe03ae25d537632e7d23e7929e1a" dependencies = [ "alloy-consensus-any", "alloy-rpc-types-eth", @@ -580,28 +594,28 @@ dependencies = [ [[package]] name = "alloy-rpc-types-debug" -version = "1.1.2" +version = "1.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b2ca3a434a6d49910a7e8e51797eb25db42ef8a5578c52d877fcb26d0afe7bc" +checksum = "e1b21e1ad18ff1b31ff1030e046462ab8168cf8894e6778cd805c8bdfe2bd649" dependencies = [ "alloy-primitives", - "derive_more 2.0.1", + "derive_more 2.1.1", "serde", "serde_with 3.16.1", ] [[package]] name = "alloy-rpc-types-engine" -version = "1.1.2" +version = "1.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9c4c53a8b0905d931e7921774a1830609713bd3e8222347963172b03a3ecc68" +checksum = "e4ac61f03f1edabccde1c687b5b25fff28f183afee64eaa2e767def3929e4457" dependencies = [ "alloy-consensus", "alloy-eips", "alloy-primitives", "alloy-rlp", "alloy-serde", - "derive_more 2.0.1", + "derive_more 2.1.1", "rand 0.8.5", "serde", "strum 0.27.2", @@ -609,9 +623,9 @@ dependencies = [ [[package]] name = "alloy-rpc-types-eth" -version = "1.1.2" +version = "1.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed5fafb741c19b3cca4cdd04fa215c89413491f9695a3e928dee2ae5657f607e" +checksum = "9b2dc411f13092f237d2bf6918caf80977fc2f51485f9b90cb2a2f956912c8c9" dependencies = [ "alloy-consensus", "alloy-consensus-any", @@ -625,28 +639,28 @@ dependencies = [ "serde", "serde_json", "serde_with 3.16.1", - "thiserror 2.0.17", + "thiserror 2.0.18", ] [[package]] name = "alloy-rpc-types-trace" -version = "1.1.2" +version = "1.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c55324323aa634b01bdecb2d47462a8dce05f5505b14a6e5db361eef16eda476" +checksum = "1ad79f1e27e161943b5a4f99fe5534ef0849876214be411e0032c12f38e94daa" dependencies = [ "alloy-primitives", "alloy-rpc-types-eth", "alloy-serde", "serde", "serde_json", - "thiserror 2.0.17", + "thiserror 2.0.18", ] [[package]] name = "alloy-rpc-types-txpool" -version = "1.1.2" +version = "1.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96b1aa28effb6854be356ce92ed64cea3b323acd04c3f8bfb5126e2839698043" +checksum = "d459f902a2313737bc66d18ed094c25d2aeb268b74d98c26bbbda2aa44182ab0" dependencies = [ "alloy-primitives", "alloy-rpc-types-eth", @@ -656,9 +670,9 @@ dependencies = [ [[package]] name = "alloy-serde" -version = "1.1.2" +version = "1.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a6f180c399ca7c1e2fe17ea58343910cad0090878a696ff5a50241aee12fc529" +checksum = "e2ce1e0dbf7720eee747700e300c99aac01b1a95bb93f493a01e78ee28bb1a37" dependencies = [ "alloy-primitives", "serde", @@ -667,9 +681,9 @@ dependencies = [ [[package]] name = "alloy-signer" -version = "1.1.2" +version = "1.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ecc39ad2c0a3d2da8891f4081565780703a593f090f768f884049aa3aa929cbc" +checksum = "2425c6f314522c78e8198979c8cbf6769362be4da381d4152ea8eefce383535d" dependencies = [ "alloy-primitives", "async-trait", @@ -677,14 +691,14 @@ dependencies = [ "either", "elliptic-curve 0.13.8", "k256 0.13.4", - "thiserror 2.0.17", + "thiserror 2.0.18", ] [[package]] name = "alloy-signer-local" -version = "1.1.2" +version = "1.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "930e17cb1e46446a193a593a3bfff8d0ecee4e510b802575ebe300ae2e43ef75" +checksum = "c3ecb71ee53d8d9c3fa7bac17542c8116ebc7a9726c91b1bf333ec3d04f5a789" dependencies = [ "alloy-consensus", "alloy-network", @@ -693,47 +707,47 @@ dependencies = [ "async-trait", "k256 0.13.4", "rand 0.8.5", - "thiserror 2.0.17", + "thiserror 2.0.18", ] [[package]] name = "alloy-sol-macro" -version = "1.4.1" +version = "1.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3ce480400051b5217f19d6e9a82d9010cdde20f1ae9c00d53591e4a1afbb312" +checksum = "ab81bab693da9bb79f7a95b64b394718259fdd7e41dceeced4cad57cb71c4f6a" dependencies = [ "alloy-sol-macro-expander", "alloy-sol-macro-input", "proc-macro-error2", "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.117", ] [[package]] name = "alloy-sol-macro-expander" -version = "1.4.1" +version = "1.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d792e205ed3b72f795a8044c52877d2e6b6e9b1d13f431478121d8d4eaa9028" +checksum = "489f1620bb7e2483fb5819ed01ab6edc1d2f93939dce35a5695085a1afd1d699" dependencies = [ "alloy-json-abi", "alloy-sol-macro-input", "const-hex", "heck 0.5.0", - "indexmap 2.12.1", + "indexmap 2.13.0", "proc-macro-error2", "proc-macro2", "quote", - "syn 2.0.111", + "sha3", + "syn 2.0.117", "syn-solidity", - "tiny-keccak", ] [[package]] name = "alloy-sol-macro-input" -version = "1.4.1" +version = "1.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0bd1247a8f90b465ef3f1207627547ec16940c35597875cdc09c49d58b19693c" +checksum = "56cef806ad22d4392c5fc83cf8f2089f988eb99c7067b4e0c6f1971fc1cca318" dependencies = [ "alloy-json-abi", "const-hex", @@ -743,15 +757,15 @@ dependencies = [ "proc-macro2", "quote", "serde_json", - "syn 2.0.111", + "syn 2.0.117", "syn-solidity", ] [[package]] name = "alloy-sol-type-parser" -version = "1.4.1" +version = "1.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "954d1b2533b9b2c7959652df3076954ecb1122a28cc740aa84e7b0a49f6ac0a9" +checksum = "a6df77fea9d6a2a75c0ef8d2acbdfd92286cc599983d3175ccdc170d3433d249" dependencies = [ "serde", "winnow 0.7.14", @@ -759,9 +773,9 @@ dependencies = [ [[package]] name = "alloy-sol-types" -version = "1.4.1" +version = "1.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70319350969a3af119da6fb3e9bddb1bce66c9ea933600cb297c8b1850ad2a3c" +checksum = "64612d29379782a5dde6f4b6570d9c756d734d760c0c94c254d361e678a6591f" dependencies = [ "alloy-json-abi", "alloy-primitives", @@ -771,20 +785,20 @@ dependencies = [ [[package]] name = "alloy-transport" -version = "1.1.2" +version = "1.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cae82426d98f8bc18f53c5223862907cac30ab8fc5e4cd2bb50808e6d3ab43d8" +checksum = "fa186e560d523d196580c48bf00f1bf62e63041f28ecf276acc22f8b27bb9f53" dependencies = [ "alloy-json-rpc", "auto_impl", "base64 0.22.1", - "derive_more 2.0.1", + "derive_more 2.1.1", "futures", "futures-utils-wasm", "parking_lot 0.12.5", "serde", "serde_json", - "thiserror 2.0.17", + "thiserror 2.0.18", "tokio", "tower", "tracing", @@ -794,13 +808,14 @@ dependencies = [ [[package]] name = "alloy-transport-http" -version = "1.1.2" +version = "1.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90aa6825760905898c106aba9c804b131816a15041523e80b6d4fe7af6380ada" +checksum = "aa501ad58dd20acddbfebc65b52e60f05ebf97c52fa40d1b35e91f5e2da0ad0e" dependencies = [ "alloy-json-rpc", "alloy-transport", - "reqwest 0.12.24", + "itertools 0.14.0", + "reqwest 0.12.28", "serde_json", "tower", "tracing", @@ -809,9 +824,9 @@ dependencies = [ [[package]] name = "alloy-transport-ipc" -version = "1.1.2" +version = "1.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ace83a4a6bb896e5894c3479042e6ba78aa5271dde599aa8c36a021d49cc8cc" +checksum = "c2ef85688e5ac2da72afc804e0a1f153a1f309f05a864b1998bbbed7804dbaab" dependencies = [ "alloy-json-rpc", "alloy-pubsub", @@ -829,15 +844,14 @@ dependencies = [ [[package]] name = "alloy-transport-ws" -version = "1.1.2" +version = "1.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86c9ab4c199e3a8f3520b60ba81aa67bb21fed9ed0d8304e0569094d0758a56f" +checksum = "b9f00445db69d63298e2b00a0ea1d859f00e6424a3144ffc5eba9c31da995e16" dependencies = [ "alloy-pubsub", "alloy-transport", "futures", "http 1.4.0", - "rustls 0.23.35", "serde_json", "tokio", "tokio-tungstenite 0.26.2", @@ -847,30 +861,31 @@ dependencies = [ [[package]] name = "alloy-trie" -version = "0.9.1" +version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3412d52bb97c6c6cc27ccc28d4e6e8cf605469101193b50b0bd5813b1f990b5" +checksum = "4d7fd448ab0a017de542de1dcca7a58e7019fe0e7a34ed3f9543ebddf6aceffa" dependencies = [ "alloy-primitives", "alloy-rlp", "arrayvec", - "derive_more 2.0.1", + "derive_more 2.1.1", "nybbles", "serde", "smallvec", + "thiserror 2.0.18", "tracing", ] [[package]] name = "alloy-tx-macros" -version = "1.1.2" +version = "1.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae109e33814b49fc0a62f2528993aa8a2dd346c26959b151f05441dc0b9da292" +checksum = "6fa0c53e8c1e1ef4d01066b01c737fb62fc9397ab52c6e7bb5669f97d281b9bc" dependencies = [ "darling 0.21.3", "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.117", ] [[package]] @@ -890,9 +905,9 @@ checksum = "4b46cbb362ab8752921c97e041f5e366ee6297bd428a31275b9fcf1e380f7299" [[package]] name = "anyhow" -version = "1.0.100" +version = "1.0.102" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a23eb6b1614318a8071c9b2521f36b424b2c83db5eb3a0fead4a6c0809af6e61" +checksum = "7f202df86484c868dbad7eaa557ef785d5c66295e41b460ef922eca0723b842c" [[package]] name = "arithmetic" @@ -1125,7 +1140,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "62945a2f7e6de02a31fe400aa489f0e0f5b2502e69f95f853adb82a96c7a6b60" dependencies = [ "quote", - "syn 2.0.111", + "syn 2.0.117", ] [[package]] @@ -1163,7 +1178,7 @@ dependencies = [ "num-traits", "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.117", ] [[package]] @@ -1332,7 +1347,7 @@ checksum = "965c2d33e53cb6b267e148a4cb0760bc01f4904c1cd4bb4002a085bb016d1490" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.117", "synstructure", ] @@ -1344,7 +1359,7 @@ checksum = "7b18050c2cd6fe86c3a76584ef5e0baf286d038cda203eb6223df2cc413565f7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.117", ] [[package]] @@ -1390,9 +1405,9 @@ dependencies = [ [[package]] name = "async-lock" -version = "3.4.1" +version = "3.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5fd03604047cee9b6ce9de9f70c6cd540a0520c813cbd49bae61f33ab80ed1dc" +checksum = "290f7f2596bd5b78a9fec8088ccd89180d7f9f55b94b0576823bbbdc72ee8311" dependencies = [ "event-listener 5.4.1", "event-listener-strategy", @@ -1454,7 +1469,7 @@ checksum = "c7c24de15d275a1ecfd47a380fb4d5ec9bfe0933f309ed5e705b775596a3574d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.117", ] [[package]] @@ -1471,7 +1486,7 @@ checksum = "9035ad2d096bed7955a320ee7e2230574d28fd3c3a0f186cbea1ff3c7eed5dbb" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.117", ] [[package]] @@ -1519,7 +1534,7 @@ checksum = "ffdcb70bdbc4d478427380519163274ac86e52916e10f0a8889adf0f96d3fee7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.117", ] [[package]] @@ -1539,20 +1554,20 @@ dependencies = [ "bytes", "dyn-clone", "futures", - "getrandom 0.2.16", + "getrandom 0.2.17", "http-types", "once_cell", "paste", "pin-project", "rand 0.8.5", - "reqwest 0.12.24", + "reqwest 0.12.28", "rustc_version 0.4.1", "serde", "serde_json", "time", "tracing", "url", - "uuid 1.18.1", + "uuid 1.21.0", ] [[package]] @@ -1573,7 +1588,7 @@ dependencies = [ "tracing", "tz-rs", "url", - "uuid 1.18.1", + "uuid 1.21.0", ] [[package]] @@ -1637,9 +1652,9 @@ checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" [[package]] name = "base64ct" -version = "1.8.0" +version = "1.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "55248b47b0caf0546f7988906588779981c43bb1bc9d0c44087278f80cdb44ba" +checksum = "2af50177e190e07a26ab74f8b1efbfe2ef87da2116221318cb1c2e82baf7de06" [[package]] name = "bech32" @@ -1712,15 +1727,15 @@ checksum = "5e764a1d40d510daf35e07be9eb06e75770908c27d411ee6c92109c9840eaaf7" [[package]] name = "bitcoin-io" -version = "0.1.3" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b47c4ab7a93edb0c7198c5535ed9b52b63095f4e9b45279c6736cec4b856baf" +checksum = "2dee39a0ee5b4095224a0cfc6bf4cc1baf0f9624b96b367e53b66d974e51d953" [[package]] name = "bitcoin_hashes" -version = "0.14.0" +version = "0.14.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb18c03d0db0247e147a21a6faafd5a7eb851c743db062de72018b6b7e8e4d16" +checksum = "26ec84b80c482df901772e931a9a681e26a1b9ee2302edeff23cb30328745c8b" dependencies = [ "bitcoin-io", "hex-conservative", @@ -1734,9 +1749,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.10.0" +version = "2.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "812e12b5285cc515a9c72a5c1d3b6d46a19dac5acfef5265968c166106e31dd3" +checksum = "843867be96c8daad0d758b57df9392b6d8d271134fce549de6ce169ff98a92af" [[package]] name = "bitvec" @@ -1824,7 +1839,7 @@ dependencies = [ "hyperlocal", "log", "pin-project-lite", - "rustls 0.23.35", + "rustls 0.23.36", "rustls-native-certs", "rustls-pemfile 2.2.0", "rustls-pki-types", @@ -1833,7 +1848,7 @@ dependencies = [ "serde_json", "serde_repr", "serde_urlencoded", - "thiserror 2.0.17", + "thiserror 2.0.18", "tokio", "tokio-util", "tower-service", @@ -1872,7 +1887,7 @@ dependencies = [ "proc-macro-crate", "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.117", ] [[package]] @@ -1903,10 +1918,10 @@ dependencies = [ "ahash 0.8.12", "base64 0.22.1", "bitvec", - "getrandom 0.2.16", + "getrandom 0.2.17", "getrandom 0.3.4", "hex", - "indexmap 2.12.1", + "indexmap 2.13.0", "js-sys", "once_cell", "rand 0.9.2", @@ -1914,14 +1929,14 @@ dependencies = [ "serde_bytes", "serde_json", "time", - "uuid 1.18.1", + "uuid 1.21.0", ] [[package]] name = "bumpalo" -version = "3.19.0" +version = "3.20.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46c5e41b57b8bba42a04676d81cb89e9ee8e859a1a66f80a5a72e1cb76b34d43" +checksum = "5d20789868f4b01b2f2caec9f5c4e0213b41e3e5702a50157d699ae31ced2fcb" [[package]] name = "byte-slice-cast" @@ -1931,9 +1946,9 @@ checksum = "7575182f7272186991736b70173b0ea045398f984bf5ebbb3804736ce1330c9d" [[package]] name = "bytemuck" -version = "1.24.0" +version = "1.25.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fbdf580320f38b612e485521afda1ee26d10cc9884efaaa750d383e13e3c5f4" +checksum = "c8efb64bd706a16a1bdde310ae86b351e4d21550d98d056f22f8a7f7a2183fec" [[package]] name = "byteorder" @@ -1943,9 +1958,9 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "bytes" -version = "1.11.0" +version = "1.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b35204fbdc0b3f4446b89fc1ac2cf84a8a68971995d0bf2e925ec7cd960f9cb3" +checksum = "1e748733b7cbc798e1434b6ac524f0c1ff2ab456fe201501e6497c8417a4fc33" dependencies = [ "serde", ] @@ -1987,9 +2002,9 @@ dependencies = [ [[package]] name = "camino" -version = "1.2.1" +version = "1.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "276a59bf2b2c967788139340c9f0c5b12d7fd6630315c15c217e559de85d2609" +checksum = "e629a66d692cb9ff1a1c664e41771b3dcaf961985a9774c0eb0bd1b51cf60a48" dependencies = [ "serde_core", ] @@ -2025,9 +2040,9 @@ checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5" [[package]] name = "cc" -version = "1.2.48" +version = "1.2.56" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c481bdbf0ed3b892f6f806287d72acd515b352a4ec27a208489b8c1bc839633a" +checksum = "aebf35691d1bfb0ac386a69bac2fde4dd276fb618cf8bf4f5318fe285e821bb2" dependencies = [ "find-msvc-tools", "jobserver", @@ -2073,9 +2088,9 @@ dependencies = [ [[package]] name = "chrono" -version = "0.4.42" +version = "0.4.43" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "145052bdd345b87320e369255277e3fb5152762ad123a901ef5c262dd38fe8d2" +checksum = "fac4744fb15ae8337dc853fee7fb3f4e48c0fbaa23d0afe49c447b4fab126118" dependencies = [ "iana-time-zone", "js-sys", @@ -2240,7 +2255,7 @@ dependencies = [ "reqwest 0.11.27", "serde", "serde_json", - "serial_test 3.2.0", + "serial_test 3.4.0", "tokio", "toml 0.7.8", "url", @@ -2301,7 +2316,7 @@ version = "0.1.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f9d839f2a20b0aee515dc581a6172f2321f96cab76c1a38a4c584a194955390e" dependencies = [ - "getrandom 0.2.16", + "getrandom 0.2.17", "once_cell", "tiny-keccak", ] @@ -2338,6 +2353,15 @@ version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "245097e9a4535ee1e3e3931fcfcd55a796a44c643e8596ff6566d68f09b87bbc" +[[package]] +name = "convert_case" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "633458d4ef8c78b72454de2d54fd6ab2e60f9e02be22f3c6104cdc8a4e0fceb9" +dependencies = [ + "unicode-segmentation", +] + [[package]] name = "core-foundation" version = "0.9.4" @@ -2552,7 +2576,7 @@ source = "git+https://github.com/RustCrypto/nacl-compat.git?rev=0720179#0720179f dependencies = [ "blake2", "curve25519-dalek", - "getrandom 0.2.16", + "getrandom 0.2.17", "rand_core 0.6.4", "serdect", ] @@ -2589,7 +2613,7 @@ checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.117", ] [[package]] @@ -2623,7 +2647,7 @@ dependencies = [ "proc-macro2", "quote", "strsim", - "syn 2.0.111", + "syn 2.0.117", ] [[package]] @@ -2638,7 +2662,7 @@ dependencies = [ "quote", "serde", "strsim", - "syn 2.0.111", + "syn 2.0.117", ] [[package]] @@ -2649,7 +2673,7 @@ checksum = "fc34b93ccb385b40dc71c6fceac4b2ad23662c7eeb248cf10d529b7e055b6ead" dependencies = [ "darling_core 0.20.11", "quote", - "syn 2.0.111", + "syn 2.0.117", ] [[package]] @@ -2660,7 +2684,7 @@ checksum = "d38308df82d1080de0afee5d069fa14b0326a88c14f15c5ccda35b4a6c414c81" dependencies = [ "darling_core 0.21.3", "quote", - "syn 2.0.111", + "syn 2.0.117", ] [[package]] @@ -2692,9 +2716,9 @@ dependencies = [ [[package]] name = "data-encoding" -version = "2.9.0" +version = "2.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a2330da5de22e8a3cb63252ce2abb30116bf5265e89c0e01bc17015ce30a476" +checksum = "d7a1e2f27636f116493b8b860f5546edb47c8d8f8ea73e1d2a20be88e28d1fea" [[package]] name = "der" @@ -2731,9 +2755,9 @@ dependencies = [ [[package]] name = "deranged" -version = "0.5.5" +version = "0.5.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ececcb659e7ba858fb4f10388c250a7252eb0a27373f1a72b8748afdd248e587" +checksum = "7cd812cc2bc1d69d4764bd80df88b4317eaef9e773c75226407d9bc0876b211c" dependencies = [ "powerfmt", "serde_core", @@ -2758,7 +2782,7 @@ checksum = "d65d7ce8132b7c0e54497a4d9a55a1c2a0912a0d786cf894472ba818fba45762" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.117", ] [[package]] @@ -2769,7 +2793,7 @@ checksum = "ef941ded77d15ca19b40374869ac6000af1c9f2a4c0f3d4c70926287e6364a8f" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.117", ] [[package]] @@ -2783,11 +2807,11 @@ dependencies = [ [[package]] name = "derive_more" -version = "2.0.1" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "093242cf7570c207c83073cf82f79706fe7b8317e98620a47d5be7c3d8497678" +checksum = "d751e9e49156b02b44f9c1815bcb94b984cdcc4396ecc32521c739452808b134" dependencies = [ - "derive_more-impl 2.0.1", + "derive_more-impl 2.1.1", ] [[package]] @@ -2798,18 +2822,20 @@ checksum = "cb7330aeadfbe296029522e6c40f315320aba36fc43a5b3632f3795348f3bd22" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.117", ] [[package]] name = "derive_more-impl" -version = "2.0.1" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bda628edc44c4bb645fbe0f758797143e4e07926f7ebf4e9bdfbd3d2ce621df3" +checksum = "799a97264921d8623a957f6c3b9011f3b5492f557bbb7a5a19b7fa6d06ba8dcb" dependencies = [ + "convert_case", "proc-macro2", "quote", - "syn 2.0.111", + "rustc_version 0.4.1", + "syn 2.0.117", "unicode-xid", ] @@ -2884,7 +2910,7 @@ checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.117", ] [[package]] @@ -2976,7 +3002,7 @@ dependencies = [ "enum-ordinalize", "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.117", ] [[package]] @@ -3029,9 +3055,9 @@ dependencies = [ [[package]] name = "ena" -version = "0.14.3" +version = "0.14.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d248bdd43ce613d87415282f69b9bb99d947d290b10962dd6c56233312c2ad5" +checksum = "eabffdaee24bd1bf95c5ef7cec31260444317e72ea56c4c91750e8b7ee58d5f1" dependencies = [ "log", ] @@ -3078,7 +3104,7 @@ dependencies = [ "heck 0.5.0", "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.117", ] [[package]] @@ -3098,7 +3124,7 @@ checksum = "8ca9601fb2d62598ee17836250842873a413586e5d7ed88b356e38ddbb0ec631" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.117", ] [[package]] @@ -3252,7 +3278,7 @@ dependencies = [ "regex", "serde", "serde_json", - "syn 2.0.111", + "syn 2.0.117", "toml 0.8.23", "walkdir", ] @@ -3270,7 +3296,7 @@ dependencies = [ "proc-macro2", "quote", "serde_json", - "syn 2.0.111", + "syn 2.0.117", ] [[package]] @@ -3296,7 +3322,7 @@ dependencies = [ "serde", "serde_json", "strum 0.26.3", - "syn 2.0.111", + "syn 2.0.117", "tempfile", "thiserror 1.0.69", "tiny-keccak", @@ -3560,21 +3586,20 @@ dependencies = [ [[package]] name = "filetime" -version = "0.2.26" +version = "0.2.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc0505cd1b6fa6580283f6bdf70a73fcf4aba1184038c90902b92b3dd0df63ed" +checksum = "f98844151eee8917efc50bd9e8318cb963ae8b297431495d3f758616ea5c57db" dependencies = [ "cfg-if", "libc", "libredox", - "windows-sys 0.60.2", ] [[package]] name = "find-msvc-tools" -version = "0.1.5" +version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a3076410a55c90011c298b04d0cfa770b00fa04e1e3c97d3f6c9de105a03844" +checksum = "5baebc0774151f905a1a2cc41989300b1e6fbb29aff0ceffa1064fdd3088d582" [[package]] name = "fixed-hash" @@ -3596,9 +3621,9 @@ checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80" [[package]] name = "flate2" -version = "1.1.5" +version = "1.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfe33edd8e85a12a67454e37f8c75e730830d83e313556ab9ebf9ee7fbeb3bfb" +checksum = "843fba2746e448b37e26a819579957415c8cef339bf08564fe8b7ddbd959573c" dependencies = [ "crc32fast", "miniz_oxide", @@ -3670,9 +3695,9 @@ checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c" [[package]] name = "futures" -version = "0.3.31" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "65bc07b1a8bc7c85c5f2e110c476c7389b4554ba72af57d8445ea63a576b0876" +checksum = "8b147ee9d1f6d097cef9ce628cd2ee62288d963e16fb287bd9286455b241382d" dependencies = [ "futures-channel", "futures-core", @@ -3685,9 +3710,9 @@ dependencies = [ [[package]] name = "futures-channel" -version = "0.3.31" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2dff15bf788c671c1934e366d07e30c1814a8ef514e1af724a602e8a2fbe1b10" +checksum = "07bbe89c50d7a535e539b8c17bc0b49bdb77747034daa8087407d655f3f7cc1d" dependencies = [ "futures-core", "futures-sink", @@ -3695,15 +3720,15 @@ dependencies = [ [[package]] name = "futures-core" -version = "0.3.31" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e" +checksum = "7e3450815272ef58cec6d564423f6e755e25379b217b0bc688e295ba24df6b1d" [[package]] name = "futures-executor" -version = "0.3.31" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e28d1d997f585e54aebc3f97d39e72338912123a67330d723fdbb564d646c9f" +checksum = "baf29c38818342a3b26b5b923639e7b1f4a61fc5e76102d4b1981c6dc7a7579d" dependencies = [ "futures-core", "futures-task", @@ -3712,9 +3737,9 @@ dependencies = [ [[package]] name = "futures-io" -version = "0.3.31" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6" +checksum = "cecba35d7ad927e23624b22ad55235f2239cfa44fd10428eecbeba6d6a717718" [[package]] name = "futures-lite" @@ -3756,26 +3781,26 @@ dependencies = [ [[package]] name = "futures-macro" -version = "0.3.31" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" +checksum = "e835b70203e41293343137df5c0664546da5745f82ec9b84d40be8336958447b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.117", ] [[package]] name = "futures-sink" -version = "0.3.31" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e575fab7d1e0dcb8d0c7bcf9a63ee213816ab51902e6d244a95819acacf1d4f7" +checksum = "c39754e157331b013978ec91992bde1ac089843443c49cbc7f46150b0fad0893" [[package]] name = "futures-task" -version = "0.3.31" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988" +checksum = "037711b3d59c33004d3856fbdc83b99d4ff37a24768fa1be9ce3538a1cde4393" [[package]] name = "futures-timer" @@ -3789,9 +3814,9 @@ dependencies = [ [[package]] name = "futures-util" -version = "0.3.31" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81" +checksum = "389ca41296e6190b48053de0321d02a77f32f8a5d2461dd38762c0593805c6d6" dependencies = [ "futures-channel", "futures-core", @@ -3801,7 +3826,6 @@ dependencies = [ "futures-task", "memchr", "pin-project-lite", - "pin-utils", "slab", ] @@ -3853,9 +3877,9 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.16" +version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "335ff9f135e4384c8150d6f27c6daed433577f86b4750418338c01a1a2528592" +checksum = "ff2abc00be7fca6ebc474524697ae276ad847ad0a6b3faa4bcb027e9a4614ad0" dependencies = [ "cfg-if", "js-sys", @@ -3878,6 +3902,19 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "getrandom" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "139ef39800118c7683f2fd3c98c1b23c09ae076556b435f8e9064ae108aaeeec" +dependencies = [ + "cfg-if", + "libc", + "r-efi", + "wasip2", + "wasip3", +] + [[package]] name = "gimli" version = "0.32.3" @@ -3936,7 +3973,7 @@ dependencies = [ "futures-sink", "futures-util", "http 0.2.12", - "indexmap 2.12.1", + "indexmap 2.13.0", "slab", "tokio", "tokio-util", @@ -3945,9 +3982,9 @@ dependencies = [ [[package]] name = "h2" -version = "0.4.12" +version = "0.4.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3c0b69cfcb4e1b9f1bf2f53f95f766e4661169728ec61cd3fe5a0166f2d1386" +checksum = "2f44da3a8150a6703ed5d34e164b875fd14c2cdab9af1252a9a1020bde2bdc54" dependencies = [ "atomic-waker", "bytes", @@ -3955,7 +3992,7 @@ dependencies = [ "futures-core", "futures-sink", "http 1.4.0", - "indexmap 2.12.1", + "indexmap 2.13.0", "slab", "tokio", "tokio-util", @@ -4003,8 +4040,6 @@ version = "0.15.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1" dependencies = [ - "allocator-api2", - "equivalent", "foldhash 0.1.5", ] @@ -4014,6 +4049,8 @@ version = "0.16.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "841d1cc9bed7f9236f321df977030373f4a4163ae1a7dbfe1a51a2c1a51d9100" dependencies = [ + "allocator-api2", + "equivalent", "foldhash 0.2.0", "serde", "serde_core", @@ -4118,7 +4155,7 @@ dependencies = [ "once_cell", "rand 0.9.2", "ring 0.17.14", - "thiserror 2.0.17", + "thiserror 2.0.18", "tinyvec", "tokio", "tracing", @@ -4141,7 +4178,7 @@ dependencies = [ "rand 0.9.2", "resolv-conf", "smallvec", - "thiserror 2.0.17", + "thiserror 2.0.18", "tokio", "tracing", ] @@ -4291,7 +4328,7 @@ dependencies = [ "bytes", "futures-channel", "futures-core", - "h2 0.4.12", + "h2 0.4.13", "http 1.4.0", "http-body 1.0.1", "httparse", @@ -4342,12 +4379,12 @@ dependencies = [ "http 1.4.0", "hyper 1.8.1", "hyper-util", - "rustls 0.23.35", + "rustls 0.23.36", "rustls-pki-types", "tokio", "tokio-rustls 0.26.4", "tower-service", - "webpki-roots 1.0.4", + "webpki-roots 1.0.6", ] [[package]] @@ -4381,14 +4418,13 @@ dependencies = [ [[package]] name = "hyper-util" -version = "0.1.18" +version = "0.1.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "52e9a2a24dc5c6821e71a7030e1e14b7b632acac55c40e9d2e082c621261bb56" +checksum = "96547c2556ec9d12fb1578c4eaf448b04993e7fb79cbaad930a656880a6bdfa0" dependencies = [ "base64 0.22.1", "bytes", "futures-channel", - "futures-core", "futures-util", "http 1.4.0", "http-body 1.0.1", @@ -4397,8 +4433,8 @@ dependencies = [ "libc", "percent-encoding", "pin-project-lite", - "socket2 0.6.1", - "system-configuration 0.6.1", + "socket2 0.6.2", + "system-configuration 0.7.0", "tokio", "tower-service", "tracing", @@ -4440,9 +4476,9 @@ dependencies = [ [[package]] name = "iana-time-zone" -version = "0.1.64" +version = "0.1.65" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33e57f83510bb73707521ebaffa789ec8caf86f9657cad665b092b581d40e9fb" +checksum = "e31bc9ad994ba00e440a8aa5c9ef0ec67d5cb5e5cb0cc7f8b744a35b389cc470" dependencies = [ "android_system_properties", "core-foundation-sys", @@ -4510,9 +4546,9 @@ checksum = "7aedcccd01fc5fe81e6b489c15b247b8b0690feb23304303a9e560f37efc560a" [[package]] name = "icu_properties" -version = "2.1.1" +version = "2.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e93fcd3157766c0c8da2f8cff6ce651a31f0810eaa1c51ec363ef790bbb5fb99" +checksum = "020bfc02fe870ec3a66d93e677ccca0562506e5872c650f893269e08615d74ec" dependencies = [ "icu_collections", "icu_locale_core", @@ -4524,9 +4560,9 @@ dependencies = [ [[package]] name = "icu_properties_data" -version = "2.1.1" +version = "2.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02845b3647bb045f1100ecd6480ff52f34c35f82d9880e029d329c21d1054899" +checksum = "616c294cf8d725c6afcd8f55abc17c56464ef6211f9ed59cccffe534129c77af" [[package]] name = "icu_provider" @@ -4543,6 +4579,12 @@ dependencies = [ "zerovec", ] +[[package]] +name = "id-arena" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d3067d79b975e8844ca9eb072e16b31c3c1c36928edf9c6789548c524d0d954" + [[package]] name = "ident_case" version = "1.0.1" @@ -4605,7 +4647,7 @@ checksum = "a0eb5a3343abf848c0984fe4604b2b105da9539376e24fc0a3b0007411ae4fd9" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.117", ] [[package]] @@ -4627,9 +4669,9 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.12.1" +version = "2.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ad4bb2b565bca0645f4d68c5c9af97fba094e9791da685bf83cb5f3ce74acf2" +checksum = "7714e70437a7dc3ac8eb7e6f8df75fd8eb422675fc7678aff7364301092b1017" dependencies = [ "equivalent", "hashbrown 0.16.1", @@ -4664,7 +4706,7 @@ version = "0.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0fddf93031af70e75410a2511ec04d49e758ed2f26dad3404a934e0fb45cc12a" dependencies = [ - "bitflags 2.10.0", + "bitflags 2.11.0", "crossterm", "dyn-clone", "fuzzy-matcher", @@ -4686,9 +4728,9 @@ dependencies = [ [[package]] name = "interprocess" -version = "2.2.3" +version = "2.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d941b405bd2322993887859a8ee6ac9134945a24ec5ec763a8a962fc64dfec2d" +checksum = "53bf2b0e0785c5394a7392f66d7c4fb9c653633c29b27a932280da3cb344c66a" dependencies = [ "doctest-file", "futures-core", @@ -4719,9 +4761,9 @@ checksum = "469fb0b9cefa57e3ef31275ee7cacb78f2fdca44e4765491884a2b119d4eb130" [[package]] name = "iri-string" -version = "0.7.9" +version = "0.7.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f867b9d1d896b67beb18518eda36fdb77a32ea590de864f1325b294a6d14397" +checksum = "c91338f0783edbd6195decb37bae672fd3b165faffb89bf7b9e6942f8b1a731a" dependencies = [ "memchr", "serde", @@ -4776,14 +4818,14 @@ dependencies = [ [[package]] name = "itoa" -version = "1.0.15" +version = "1.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" +checksum = "92ecc6618181def0457392ccd0ee51198e065e016d1d527a7ac1b6dc7c1f09d2" [[package]] name = "jf-plonk" version = "0.4.0-pre.0" -source = "git+https://git@github.com/EYBlockchain/nightfish_CE.git#68e2843592ef9713f1f386fbebc6906791a22495" +source = "git+https://git@github.com/EYBlockchain/nightfish_CE.git#8df6bdbaffbc9716b704a20fb615dc243a7e024c" dependencies = [ "ark-bn254", "ark-crypto-primitives", @@ -4822,7 +4864,7 @@ dependencies = [ [[package]] name = "jf-primitives" version = "0.4.0-pre.0" -source = "git+https://git@github.com/EYBlockchain/nightfish_CE.git#68e2843592ef9713f1f386fbebc6906791a22495" +source = "git+https://git@github.com/EYBlockchain/nightfish_CE.git#8df6bdbaffbc9716b704a20fb615dc243a7e024c" dependencies = [ "anyhow", "arithmetic", @@ -4875,7 +4917,7 @@ dependencies = [ [[package]] name = "jf-relation" version = "0.4.0-pre.0" -source = "git+https://git@github.com/EYBlockchain/nightfish_CE.git#68e2843592ef9713f1f386fbebc6906791a22495" +source = "git+https://git@github.com/EYBlockchain/nightfish_CE.git#8df6bdbaffbc9716b704a20fb615dc243a7e024c" dependencies = [ "ark-bls12-377", "ark-bls12-381", @@ -4907,7 +4949,7 @@ dependencies = [ [[package]] name = "jf-utils" version = "0.4.0-pre.0" -source = "git+https://git@github.com/EYBlockchain/nightfish_CE.git#68e2843592ef9713f1f386fbebc6906791a22495" +source = "git+https://git@github.com/EYBlockchain/nightfish_CE.git#8df6bdbaffbc9716b704a20fb615dc243a7e024c" dependencies = [ "ark-ec", "ark-ff 0.4.2", @@ -4932,9 +4974,9 @@ dependencies = [ [[package]] name = "js-sys" -version = "0.3.83" +version = "0.3.88" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "464a3709c7f55f1f721e5389aa6ea4e3bc6aba669353300af094b29ffbdde1d8" +checksum = "c7e709f3e3d22866f9c25b3aff01af289b18422cc8b4262fb19103ee80fe513d" dependencies = [ "once_cell", "wasm-bindgen", @@ -4995,18 +5037,18 @@ dependencies = [ [[package]] name = "keccak" -version = "0.1.5" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ecc2af9a1119c51f12a14607e783cb977bde58bc069ff0c3da1095e635d70654" +checksum = "cb26cec98cce3a3d96cbb7bced3c4b16e3d13f27ec56dbd62cbc8f39cfb9d653" dependencies = [ "cpufeatures", ] [[package]] name = "keccak-asm" -version = "0.1.4" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "505d1856a39b200489082f90d897c3f07c455563880bc5952e38eabf731c83b6" +checksum = "b646a74e746cd25045aa0fd42f4f7f78aa6d119380182c7e63a5593c4ab8df6f" dependencies = [ "digest 0.10.7", "sha3-asm", @@ -5048,6 +5090,12 @@ version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" +[[package]] +name = "leb128fmt" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09edd9e8b54e49e587e4f6295a7d29c3ea94d469cb40ab8ca70b288248a81db2" + [[package]] name = "lib" version = "0.1.0" @@ -5105,25 +5153,25 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.177" +version = "0.2.182" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2874a2af47a2325c2001a6e6fad9b16a53b802102b528163885171cf92b15976" +checksum = "6800badb6cb2082ffd7b6a67e6125bb39f18782f793520caee8cb8846be06112" [[package]] name = "libm" -version = "0.2.15" +version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9fbbcab51052fe104eb5e5d351cf728d30a5be1fe14d9be8a3b097481fb97de" +checksum = "b6d2cec3eae94f9f509c767b45932f1ada8350c4bdb85af2fcab4a3c14807981" [[package]] name = "libredox" -version = "0.1.10" +version = "0.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "416f7e718bdb06000964960ffa43b4335ad4012ae8b99060261aa4a8088d5ccb" +checksum = "3d0b95e02c851351f877147b7deea7b1afb1df71b63aa5f8270716e0c5720616" dependencies = [ - "bitflags 2.10.0", + "bitflags 2.11.0", "libc", - "redox_syscall 0.5.18", + "redox_syscall 0.7.1", ] [[package]] @@ -5155,9 +5203,9 @@ dependencies = [ [[package]] name = "log" -version = "0.4.28" +version = "0.4.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34080505efa8e45a4b816c349525ebe327ceaa8559756f0356cba97ef3bf7432" +checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897" [[package]] name = "log-panics" @@ -5170,11 +5218,11 @@ dependencies = [ [[package]] name = "lru" -version = "0.13.0" +version = "0.16.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "227748d55f2f0ab4735d87fd623798cb6b664512fe979705f829c9f81c934465" +checksum = "a1dc47f592c06f33f8e3aea9591776ec7c9f9e4124778ff8a3c3b87159f7e593" dependencies = [ - "hashbrown 0.15.5", + "hashbrown 0.16.1", ] [[package]] @@ -5191,7 +5239,7 @@ checksum = "1b27834086c65ec3f9387b096d66e99f221cf081c2b738042aa252bcd41204e3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.117", ] [[package]] @@ -5203,7 +5251,7 @@ dependencies = [ "macro_magic_core", "macro_magic_macros", "quote", - "syn 2.0.111", + "syn 2.0.117", ] [[package]] @@ -5217,7 +5265,7 @@ dependencies = [ "macro_magic_core_macros", "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.117", ] [[package]] @@ -5228,7 +5276,7 @@ checksum = "b02abfe41815b5bd98dbd4260173db2c116dda171dc0fe7838cb206333b83308" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.117", ] [[package]] @@ -5239,7 +5287,7 @@ checksum = "73ea28ee64b88876bf45277ed9a5817c1817df061a74f2b988971a12570e5869" dependencies = [ "macro_magic_core", "quote", - "syn 2.0.111", + "syn 2.0.117", ] [[package]] @@ -5254,15 +5302,15 @@ dependencies = [ [[package]] name = "memchr" -version = "2.7.6" +version = "2.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f52b00d39961fc5b2736ea853c9cc86238e165017a493d1d5c8eac6bdc4cc273" +checksum = "f8ca58f447f06ed17d5fc4043ce1b10dd205e060fb3ce5b979b8ed8e59ff3f79" [[package]] name = "memmap2" -version = "0.9.9" +version = "0.9.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "744133e4a0e0a658e1374cf3bf8e415c4052a15a111acd372764c55b4177d490" +checksum = "714098028fe011992e1c3962653c96b2d578c4b4bce9036e15ff220319b1e0e3" dependencies = [ "libc", ] @@ -5325,9 +5373,9 @@ dependencies = [ [[package]] name = "mio" -version = "1.1.0" +version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "69d83b0086dc8ecf3ce9ae2874b2d1290252e2a30720bea58a5c6639b0092873" +checksum = "a69bcab0ad47271a0234d9422b131806bf3968021e5dc9328caf2d4cd58557fc" dependencies = [ "libc", "wasi 0.11.1+wasi-snapshot-preview1", @@ -5336,9 +5384,9 @@ dependencies = [ [[package]] name = "moka" -version = "0.12.11" +version = "0.12.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8261cd88c312e0004c1d51baad2980c66528dfdb2bee62003e643a4d8f86b077" +checksum = "b4ac832c50ced444ef6be0767a008b02c106a909ba79d1d830501e94b96f6b7e" dependencies = [ "crossbeam-channel", "crossbeam-epoch", @@ -5346,10 +5394,9 @@ dependencies = [ "equivalent", "parking_lot 0.12.5", "portable-atomic", - "rustc_version 0.4.1", "smallvec", "tagptr", - "uuid 1.18.1", + "uuid 1.21.0", ] [[package]] @@ -5372,15 +5419,15 @@ checksum = "224484c5d09285a7b8cb0a0c117e847ebd14cb6e4470ecf68cdb89c503b0edb9" [[package]] name = "mongodb" -version = "3.4.1" +version = "3.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "12f5c20217413bed97c613714e6d6dfe39ef59dd79a68999f1043b0566192975" +checksum = "803dd859e8afa084c255a8effd8000ff86f7c8076a50cd6d8c99e8f3496f75c2" dependencies = [ "base64 0.22.1", - "bitflags 2.10.0", + "bitflags 2.11.0", "bson", "derive-where", - "derive_more 2.0.1", + "derive_more 2.1.1", "futures-core", "futures-io", "futures-util", @@ -5396,36 +5443,36 @@ dependencies = [ "percent-encoding", "rand 0.9.2", "rustc_version_runtime", - "rustls 0.23.35", + "rustls 0.23.36", "rustversion", "serde", "serde_bytes", "serde_with 3.16.1", "sha1", "sha2 0.10.9", - "socket2 0.6.1", + "socket2 0.6.2", "stringprep", "strsim", "take_mut", - "thiserror 2.0.17", + "thiserror 2.0.18", "tokio", "tokio-rustls 0.26.4", "tokio-util", "typed-builder", - "uuid 1.18.1", - "webpki-roots 1.0.4", + "uuid 1.21.0", + "webpki-roots 1.0.6", ] [[package]] name = "mongodb-internal-macros" -version = "3.4.1" +version = "3.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "20033442aa13664e70bc9f8be1bacabebf6a31b6d4bb5608ceb99c4ec96e9951" +checksum = "a973ef3dd3dbc6f6e65bbdecfd9ec5e781b9e7493b0f369a7c62e35d8e5ae2c8" dependencies = [ "macro_magic", "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.117", ] [[package]] @@ -5448,9 +5495,9 @@ dependencies = [ [[package]] name = "native-tls" -version = "0.2.14" +version = "0.2.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87de3442987e9dbec73158d5c715e7ad9072fda936bb03d19d7fa10e00520f0e" +checksum = "465500e14ea162429d264d44189adc38b199b62b1c21eea9f69e4b73cb03bbf2" dependencies = [ "libc", "log", @@ -5458,7 +5505,7 @@ dependencies = [ "openssl-probe", "openssl-sys", "schannel", - "security-framework 2.11.1", + "security-framework", "security-framework-sys", "tempfile", ] @@ -5481,7 +5528,7 @@ dependencies = [ [[package]] name = "nf-curves" version = "0.4.0-pre.0" -source = "git+https://git@github.com/EYBlockchain/nightfish_CE.git#68e2843592ef9713f1f386fbebc6906791a22495" +source = "git+https://git@github.com/EYBlockchain/nightfish_CE.git#8df6bdbaffbc9716b704a20fb615dc243a7e024c" dependencies = [ "ark-bn254", "ark-ec", @@ -5564,7 +5611,7 @@ dependencies = [ "tracing", "uint", "url", - "uuid 1.18.1", + "uuid 1.21.0", "warp", ] @@ -5668,7 +5715,7 @@ dependencies = [ "nightfall_bindings", "nightfall_client", "nightfall_test", - "reqwest 0.12.24", + "reqwest 0.12.28", "tokio", ] @@ -5704,16 +5751,16 @@ dependencies = [ "nightfall_client", "nightfall_proposer", "num-bigint", - "reqwest 0.12.24", + "reqwest 0.12.28", "serde", "serde_json", - "serial_test 3.2.0", + "serial_test 3.4.0", "sha2 0.10.9", "tokio", "toml 0.8.23", "tracing", "url", - "uuid 1.18.1", + "uuid 1.21.0", "warp", ] @@ -5762,9 +5809,9 @@ dependencies = [ [[package]] name = "num-conv" -version = "0.1.0" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" +checksum = "cf97ec579c3c42f953ef76dbf8d55ac91fb219dde70e49aa4a6b7d74e9919050" [[package]] name = "num-integer" @@ -5836,7 +5883,7 @@ dependencies = [ "proc-macro-crate", "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.117", ] [[package]] @@ -5850,9 +5897,9 @@ dependencies = [ [[package]] name = "nybbles" -version = "0.4.6" +version = "0.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c4b5ecbd0beec843101bffe848217f770e8b8da81d8355b7d6e226f2199b3dc" +checksum = "0d49ff0c0d00d4a502b39df9af3a525e1efeb14b9dabb5bb83335284c1309210" dependencies = [ "alloy-rlp", "cfg-if", @@ -5870,7 +5917,7 @@ checksum = "c38841cdd844847e3e7c8d29cef9dcfed8877f8f56f9071f77843ecf3baf937f" dependencies = [ "base64 0.13.1", "chrono", - "getrandom 0.2.16", + "getrandom 0.2.17", "http 0.2.12", "rand 0.8.5", "serde", @@ -5952,7 +5999,7 @@ version = "0.10.75" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "08838db121398ad17ab8531ce9de97b244589089e290a384c900cb9ff7434328" dependencies = [ - "bitflags 2.10.0", + "bitflags 2.11.0", "cfg-if", "foreign-types", "libc", @@ -5969,14 +6016,14 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.117", ] [[package]] name = "openssl-probe" -version = "0.1.6" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d05e27ee213611ffe7d6348b942e8f942b37114c00cc03cec254295a4a17852e" +checksum = "7c87def4c32ab89d880effc9e097653c8da5d6ef28e6b539d313baaacfbafcbe" [[package]] name = "openssl-sys" @@ -6037,7 +6084,7 @@ dependencies = [ "proc-macro-crate", "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.117", ] [[package]] @@ -6116,7 +6163,7 @@ dependencies = [ "regex", "regex-syntax", "structmeta", - "syn 2.0.111", + "syn 2.0.117", ] [[package]] @@ -6190,7 +6237,7 @@ dependencies = [ "proc-macro2", "proc-macro2-diagnostics", "quote", - "syn 2.0.111", + "syn 2.0.117", ] [[package]] @@ -6210,9 +6257,9 @@ checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220" [[package]] name = "pest" -version = "2.8.4" +version = "2.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cbcfd20a6d4eeba40179f05735784ad32bdaef05ce8e8af05f180d45bb3e7e22" +checksum = "e0848c601009d37dfa3430c4666e147e49cdcf1b92ecd3e63657d8a5f19da662" dependencies = [ "memchr", "ucd-trie", @@ -6220,9 +6267,9 @@ dependencies = [ [[package]] name = "pest_derive" -version = "2.8.4" +version = "2.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "51f72981ade67b1ca6adc26ec221be9f463f2b5839c7508998daa17c23d94d7f" +checksum = "11f486f1ea21e6c10ed15d5a7c77165d0ee443402f0780849d1768e7d9d6fe77" dependencies = [ "pest", "pest_generator", @@ -6230,22 +6277,22 @@ dependencies = [ [[package]] name = "pest_generator" -version = "2.8.4" +version = "2.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dee9efd8cdb50d719a80088b76f81aec7c41ed6d522ee750178f83883d271625" +checksum = "8040c4647b13b210a963c1ed407c1ff4fdfa01c31d6d2a098218702e6664f94f" dependencies = [ "pest", "pest_meta", "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.117", ] [[package]] name = "pest_meta" -version = "2.8.4" +version = "2.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf1d70880e76bdc13ba52eafa6239ce793d85c8e43896507e43dd8984ff05b82" +checksum = "89815c69d36021a140146f26659a81d6c2afa33d216d736dd4be5381a7362220" dependencies = [ "pest", "sha2 0.10.9", @@ -6258,7 +6305,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b4c5cc86750666a3ed20bdaf5ca2a0344f9c67674cae0515bec2da16fbaa47db" dependencies = [ "fixedbitset", - "indexmap 2.12.1", + "indexmap 2.13.0", ] [[package]] @@ -6301,7 +6348,7 @@ dependencies = [ "phf_shared", "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.117", ] [[package]] @@ -6330,7 +6377,7 @@ checksum = "6e918e4ff8c4549eb882f14b3a4bc8c8bc93de829416eacf579f1207a8fbf861" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.117", ] [[package]] @@ -6427,9 +6474,9 @@ dependencies = [ [[package]] name = "portable-atomic" -version = "1.11.1" +version = "1.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f84267b20a16ea918e43c6a88433c2d54fa145c92a811b5b047ccbe153674483" +checksum = "c33a9471896f1c69cecef8d20cbe2f7accd12527ce60845ff44c153bb2a21b49" [[package]] name = "potential_utf" @@ -6468,7 +6515,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "479ca8adacdd7ce8f1fb39ce9ecccbfe93a3f1344b3d0d97f20bc0196208f62b" dependencies = [ "proc-macro2", - "syn 2.0.111", + "syn 2.0.117", ] [[package]] @@ -6491,7 +6538,7 @@ version = "3.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "219cb19e96be00ab2e37d6e299658a0cfa83e52429179969b0f0121b4ac46983" dependencies = [ - "toml_edit 0.23.7", + "toml_edit 0.23.10+spec-1.0.0", ] [[package]] @@ -6513,14 +6560,14 @@ dependencies = [ "proc-macro-error-attr2", "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.117", ] [[package]] name = "proc-macro2" -version = "1.0.103" +version = "1.0.106" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ee95bc4ef87b8d5ba32e8b7714ccc834865276eab0aed5c9958d00ec45f49e8" +checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934" dependencies = [ "unicode-ident", ] @@ -6533,20 +6580,20 @@ checksum = "af066a9c399a26e020ada66a034357a868728e72cd426f3adcd35f80d88d88c8" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.117", "version_check", "yansi 1.0.1", ] [[package]] name = "proptest" -version = "1.9.0" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bee689443a2bd0a16ab0348b52ee43e3b2d1b1f931c8aa5c9f8de4c86fbe8c40" +checksum = "37566cb3fdacef14c0737f9546df7cfeadbfbc9fef10991038bf5015d0c80532" dependencies = [ "bit-set 0.8.0", "bit-vec 0.8.0", - "bitflags 2.10.0", + "bitflags 2.11.0", "num-traits", "rand 0.9.2", "rand_chacha 0.9.0", @@ -6575,9 +6622,9 @@ dependencies = [ "quinn-proto", "quinn-udp", "rustc-hash", - "rustls 0.23.35", - "socket2 0.6.1", - "thiserror 2.0.17", + "rustls 0.23.36", + "socket2 0.6.2", + "thiserror 2.0.18", "tokio", "tracing", "web-time", @@ -6595,10 +6642,10 @@ dependencies = [ "rand 0.9.2", "ring 0.17.14", "rustc-hash", - "rustls 0.23.35", + "rustls 0.23.36", "rustls-pki-types", "slab", - "thiserror 2.0.17", + "thiserror 2.0.18", "tinyvec", "tracing", "web-time", @@ -6613,16 +6660,16 @@ dependencies = [ "cfg_aliases", "libc", "once_cell", - "socket2 0.6.1", + "socket2 0.6.2", "tracing", "windows-sys 0.60.2", ] [[package]] name = "quote" -version = "1.0.42" +version = "1.0.44" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a338cc41d27e6cc6dce6cefc13a0729dfbb81c262b1f519331575dd80ef3067f" +checksum = "21b2ebcf727b7760c461f091f9f0f539b77b8e87f2fd88131e7f1b433b3cece4" dependencies = [ "proc-macro2", ] @@ -6684,7 +6731,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6db2770f06117d490610c7488547d543617b21bfa07796d7a12f6f1bd53850d1" dependencies = [ "rand_chacha 0.9.0", - "rand_core 0.9.3", + "rand_core 0.9.5", "serde", ] @@ -6715,7 +6762,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb" dependencies = [ "ppv-lite86", - "rand_core 0.9.3", + "rand_core 0.9.5", ] [[package]] @@ -6748,14 +6795,14 @@ version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" dependencies = [ - "getrandom 0.2.16", + "getrandom 0.2.17", ] [[package]] name = "rand_core" -version = "0.9.3" +version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "99d9a13982dcf210057a8a78572b2217b667c3beacbf3a0d8b454f6f82837d38" +checksum = "76afc826de14238e6e8c374ddcc1fa19e374fd8dd986b0d2af0d02377261d83c" dependencies = [ "getrandom 0.3.4", "serde", @@ -6776,7 +6823,16 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "513962919efc330f829edb2535844d1b912b0fbe2ca165d613e4e8788bb05a5a" dependencies = [ - "rand_core 0.9.3", + "rand_core 0.9.5", +] + +[[package]] +name = "rapidhash" +version = "4.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5e48930979c155e2f33aa36ab3119b5ee81332beb6482199a8ecd6029b80b59" +dependencies = [ + "rustversion", ] [[package]] @@ -6838,7 +6894,16 @@ version = "0.5.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ed2bf2547551a7053d6fdfafda3f938979645c44812fbfcda098faae3f1a362d" dependencies = [ - "bitflags 2.10.0", + "bitflags 2.11.0", +] + +[[package]] +name = "redox_syscall" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "35985aa610addc02e24fc232012c86fd11f14111180f902b67e2d5331f8ebf2b" +dependencies = [ + "bitflags 2.11.0", ] [[package]] @@ -6847,7 +6912,7 @@ version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ba009ff324d1fc1b900bd1fdb31564febe58a8ccc8a6fdbb93b543d33b13ca43" dependencies = [ - "getrandom 0.2.16", + "getrandom 0.2.17", "libredox", "thiserror 1.0.69", ] @@ -6869,14 +6934,14 @@ checksum = "b7186006dcb21920990093f30e3dea63b7d6e977bf1256be20c3563a5db070da" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.117", ] [[package]] name = "regex" -version = "1.12.2" +version = "1.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "843bc0191f75f3e22651ae5f1e72939ab2f72a4bc30fa80a066bd66edefc24d4" +checksum = "e10754a14b9137dd7b1e3e5b0493cc9171fdd105e0ab477f51b72e7f3ac0e276" dependencies = [ "aho-corasick", "memchr", @@ -6886,9 +6951,9 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.4.13" +version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5276caf25ac86c8d810222b3dbb938e512c55c6831a10f3e6ed1c93b84041f1c" +checksum = "6e1dd4122fc1595e8162618945476892eefca7b88c52820e74af6262213cae8f" dependencies = [ "aho-corasick", "memchr", @@ -6897,9 +6962,9 @@ dependencies = [ [[package]] name = "regex-syntax" -version = "0.8.8" +version = "0.8.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a2d987857b319362043e95f5353c0535c1f58eec5336fdfcf626430af7def58" +checksum = "a96887878f22d7bad8a3b6dc5b7440e0ada9a245242924394987b21cf2210a4c" [[package]] name = "reqwest" @@ -6949,16 +7014,16 @@ dependencies = [ [[package]] name = "reqwest" -version = "0.12.24" +version = "0.12.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d0946410b9f7b082a427e4ef5c8ff541a88b357bc6c637c40db3a68ac70a36f" +checksum = "eddd3ca559203180a307f12d114c268abf583f59b03cb906fd0b3ff8646c1147" dependencies = [ "base64 0.22.1", "bytes", "encoding_rs", "futures-core", "futures-util", - "h2 0.4.12", + "h2 0.4.13", "http 1.4.0", "http-body 1.0.1", "http-body-util", @@ -6974,7 +7039,7 @@ dependencies = [ "percent-encoding", "pin-project-lite", "quinn", - "rustls 0.23.35", + "rustls 0.23.36", "rustls-pki-types", "serde", "serde_json", @@ -6992,7 +7057,7 @@ dependencies = [ "wasm-bindgen-futures", "wasm-streams", "web-sys", - "webpki-roots 1.0.4", + "webpki-roots 1.0.6", ] [[package]] @@ -7045,7 +7110,7 @@ checksum = "a4689e6c2294d81e88dc6261c768b63bc4fcdb852be6d1352498b114f61383b7" dependencies = [ "cc", "cfg-if", - "getrandom 0.2.16", + "getrandom 0.2.17", "libc", "untrusted 0.9.0", "windows-sys 0.52.0", @@ -7095,9 +7160,9 @@ dependencies = [ [[package]] name = "ruint" -version = "1.17.0" +version = "1.17.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a68df0380e5c9d20ce49534f292a36a7514ae21350726efe1865bdb1fa91d278" +checksum = "c141e807189ad38a07276942c6623032d3753c8859c146104ac2e4d68865945a" dependencies = [ "alloy-rlp", "ark-ff 0.3.0", @@ -7139,9 +7204,9 @@ dependencies = [ [[package]] name = "rustc-demangle" -version = "0.1.26" +version = "0.1.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56f7d92ca342cea22a06f2121d944b4fd82af56988c270852495420f961d4ace" +checksum = "b50b8869d9fc858ce7266cce0194bd74df58b9d0e3f6df3a9fc8eb470d95c09d" [[package]] name = "rustc-hash" @@ -7194,11 +7259,11 @@ dependencies = [ [[package]] name = "rustix" -version = "1.1.2" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd15f8a2c5551a84d56efdc1cd049089e409ac19a3072d5037a17fd70719ff3e" +checksum = "146c9e247ccc180c1f61615433868c99f3de3ae256a30a43b49f67c2d9171f34" dependencies = [ - "bitflags 2.10.0", + "bitflags 2.11.0", "errno", "libc", "linux-raw-sys", @@ -7219,29 +7284,29 @@ dependencies = [ [[package]] name = "rustls" -version = "0.23.35" +version = "0.23.36" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "533f54bc6a7d4f647e46ad909549eda97bf5afc1585190ef692b4286b198bd8f" +checksum = "c665f33d38cea657d9614f766881e4d510e0eda4239891eea56b4cadcf01801b" dependencies = [ "log", "once_cell", "ring 0.17.14", "rustls-pki-types", - "rustls-webpki 0.103.8", + "rustls-webpki 0.103.9", "subtle", "zeroize", ] [[package]] name = "rustls-native-certs" -version = "0.8.2" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9980d917ebb0c0536119ba501e90834767bffc3d60641457fd84a1f3fd337923" +checksum = "612460d5f7bea540c490b2b6395d8e34a953e52b491accd6c86c8164c5932a63" dependencies = [ "openssl-probe", "rustls-pki-types", "schannel", - "security-framework 3.5.1", + "security-framework", ] [[package]] @@ -7264,9 +7329,9 @@ dependencies = [ [[package]] name = "rustls-pki-types" -version = "1.13.1" +version = "1.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "708c0f9d5f54ba0272468c1d306a52c495b31fa155e91bc25371e6df7996908c" +checksum = "be040f8b0a225e40375822a563fa9524378b9d63112f53e19ffff34df5d33fdd" dependencies = [ "web-time", "zeroize", @@ -7284,9 +7349,9 @@ dependencies = [ [[package]] name = "rustls-webpki" -version = "0.103.8" +version = "0.103.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2ffdfa2f5286e2247234e03f680868ac2815974dc39e00ea15adc445d0aafe52" +checksum = "d7df23109aa6c1567d1c575b9952556388da57401e4ace1d15f79eedad0d8f53" dependencies = [ "ring 0.17.14", "rustls-pki-types", @@ -7313,9 +7378,9 @@ dependencies = [ [[package]] name = "ryu" -version = "1.0.20" +version = "1.0.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f" +checksum = "9774ba4a74de5f7b1c1451ed6cd5285a32eddb5cccb8cc655a4e50009e06477f" [[package]] name = "salsa20" @@ -7356,7 +7421,7 @@ dependencies = [ "proc-macro-crate", "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.117", ] [[package]] @@ -7391,9 +7456,9 @@ dependencies = [ [[package]] name = "schemars" -version = "1.1.0" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9558e172d4e8533736ba97870c4b2cd63f84b382a3d6eb063da41b91cce17289" +checksum = "a2b42f36aa1cd011945615b92222f6bf73c599a102a300334cd7f8dbeec726cc" dependencies = [ "dyn-clone", "ref-cast", @@ -7492,24 +7557,11 @@ dependencies = [ [[package]] name = "security-framework" -version = "2.11.1" +version = "3.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02" +checksum = "b7f4bc775c73d9a02cde8bf7b2ec4c9d12743edf609006c7facc23998404cd1d" dependencies = [ - "bitflags 2.10.0", - "core-foundation 0.9.4", - "core-foundation-sys", - "libc", - "security-framework-sys", -] - -[[package]] -name = "security-framework" -version = "3.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3297343eaf830f66ede390ea39da1d462b6b0c1b000f420d0a83f898bbbe6ef" -dependencies = [ - "bitflags 2.10.0", + "bitflags 2.11.0", "core-foundation 0.10.1", "core-foundation-sys", "libc", @@ -7518,9 +7570,9 @@ dependencies = [ [[package]] name = "security-framework-sys" -version = "2.15.0" +version = "2.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc1f0cbffaac4852523ce30d8bd3c5cdc873501d96ff467ca09b6767bb8cd5c0" +checksum = "6ce2691df843ecc5d231c0b14ece2acc3efb62c0a398c7e1d875f3983ce020e3" dependencies = [ "core-foundation-sys", "libc", @@ -7603,21 +7655,21 @@ checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.117", ] [[package]] name = "serde_json" -version = "1.0.145" +version = "1.0.149" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "402a6f66d8c709116cf22f558eab210f5a50187f702eb4d7e5ef38d9a7f1c79c" +checksum = "83fc039473c5595ace860d8c4fafa220ff474b3fc6bfdb4293327f1a37e94d86" dependencies = [ - "indexmap 2.12.1", + "indexmap 2.13.0", "itoa", "memchr", - "ryu", "serde", "serde_core", + "zmij", ] [[package]] @@ -7650,7 +7702,7 @@ checksum = "175ee3e80ae9982737ca543e96133087cbd9a485eecc3bc4de9c1a37b47ea59c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.117", ] [[package]] @@ -7700,9 +7752,9 @@ dependencies = [ "chrono", "hex", "indexmap 1.9.3", - "indexmap 2.12.1", + "indexmap 2.13.0", "schemars 0.9.0", - "schemars 1.1.0", + "schemars 1.2.1", "serde_core", "serde_json", "serde_with_macros 3.16.1", @@ -7718,7 +7770,7 @@ dependencies = [ "darling 0.20.11", "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.117", ] [[package]] @@ -7730,7 +7782,7 @@ dependencies = [ "darling 0.21.3", "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.117", ] [[package]] @@ -7756,16 +7808,17 @@ dependencies = [ [[package]] name = "serial_test" -version = "3.2.0" +version = "3.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b258109f244e1d6891bf1053a55d63a5cd4f8f4c30cf9a1280989f80e7a1fa9" +checksum = "911bd979bf1070a3f3aa7b691a3b3e9968f339ceeec89e08c280a8a22207a32f" dependencies = [ - "futures", + "futures-executor", + "futures-util", "log", "once_cell", "parking_lot 0.12.5", "scc", - "serial_test_derive 3.2.0", + "serial_test_derive 3.4.0", ] [[package]] @@ -7781,13 +7834,13 @@ dependencies = [ [[package]] name = "serial_test_derive" -version = "3.2.0" +version = "3.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d69265a08751de7844521fd15003ae0a888e035773ba05695c5c759a6f89eef" +checksum = "0a7d91949b85b0d2fb687445e448b40d322b6b3e4af6b44a29b21d9a5f33e6d9" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.117", ] [[package]] @@ -7837,9 +7890,9 @@ dependencies = [ [[package]] name = "sha3-asm" -version = "0.1.4" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c28efc5e327c837aa837c59eae585fc250715ef939ac32881bcc11677cd02d46" +checksum = "b31139435f327c93c6038ed350ae4588e2c70a13d50599509fee6349967ba35a" dependencies = [ "cc", "cfg-if", @@ -7874,10 +7927,11 @@ dependencies = [ [[package]] name = "signal-hook-registry" -version = "1.4.7" +version = "1.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7664a098b8e616bdfcc2dc0e9ac44eb231eedf41db4e9fe95d8d32ec728dedad" +checksum = "c4db69cba1110affc0e9f7bcd48bbf87b3f4fc7c61fc9155afd4c469eb3d6c1b" dependencies = [ + "errno", "libc", ] @@ -7903,33 +7957,33 @@ dependencies = [ [[package]] name = "simd-adler32" -version = "0.3.7" +version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d66dc143e6b11c1eddc06d5c423cfc97062865baf299914ab64caa38182078fe" +checksum = "e320a6c5ad31d271ad523dcf3ad13e2767ad8b1cb8f047f75a8aeaf8da139da2" [[package]] name = "simple_asn1" -version = "0.6.3" +version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "297f631f50729c8c99b84667867963997ec0b50f32b2a7dbcab828ef0541e8bb" +checksum = "0d585997b0ac10be3c5ee635f1bab02d512760d14b7c468801ac8a01d9ae5f1d" dependencies = [ "num-bigint", "num-traits", - "thiserror 2.0.17", + "thiserror 2.0.18", "time", ] [[package]] name = "siphasher" -version = "1.0.1" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56199f7ddabf13fe5074ce809e7d3f42b42ae711800501b5b16ea82ad029c39d" +checksum = "b2aa850e253778c88a04c3d7323b043aeda9d3e30d5971937c1855769763678e" [[package]] name = "slab" -version = "0.4.11" +version = "0.4.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a2ae44ef20feb57a68b23d846850f861394c2e02dc425a50098ae8c90267589" +checksum = "0c790de23124f9ab44544d7ac05d60440adc586479ce501c1d6d7da3cd8c9cf5" [[package]] name = "smallvec" @@ -7975,9 +8029,9 @@ dependencies = [ [[package]] name = "socket2" -version = "0.6.1" +version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17129e116933cf371d018bb80ae557e889637989d8638274fb25622827b03881" +checksum = "86f4aa3ad99f2088c990dfa82d367e19cb29268ed67c574d10d0a4bfe71f07e0" dependencies = [ "libc", "windows-sys 0.60.2", @@ -8069,7 +8123,7 @@ dependencies = [ "proc-macro2", "quote", "structmeta-derive", - "syn 2.0.111", + "syn 2.0.117", ] [[package]] @@ -8080,7 +8134,7 @@ checksum = "152a0b65a590ff6c3da95cabe2353ee04e6167c896b28e3b14478c2636c922fc" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.117", ] [[package]] @@ -8111,7 +8165,7 @@ dependencies = [ "proc-macro2", "quote", "rustversion", - "syn 2.0.111", + "syn 2.0.117", ] [[package]] @@ -8123,7 +8177,7 @@ dependencies = [ "heck 0.5.0", "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.117", ] [[package]] @@ -8186,9 +8240,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.111" +version = "2.0.117" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "390cc9a294ab71bdb1aa2e99d13be9c753cd2d7bd6560c77118597410c4d2e87" +checksum = "e665b8803e7b1d2a727f4023456bbbbe74da67099c585258af0ad9c5013b9b99" dependencies = [ "proc-macro2", "quote", @@ -8197,14 +8251,14 @@ dependencies = [ [[package]] name = "syn-solidity" -version = "1.4.1" +version = "1.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff790eb176cc81bb8936aed0f7b9f14fc4670069a2d371b3e3b0ecce908b2cb3" +checksum = "53f425ae0b12e2f5ae65542e00898d500d4d318b4baf09f40fd0d410454e9947" dependencies = [ "paste", "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.117", ] [[package]] @@ -8230,7 +8284,7 @@ checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.117", ] [[package]] @@ -8246,11 +8300,11 @@ dependencies = [ [[package]] name = "system-configuration" -version = "0.6.1" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c879d448e9d986b661742763247d3693ed13609438cf3d006f51f5368a5ba6b" +checksum = "a13f3d0daba03132c0aa9767f98351b3488edc2c100cda2d2ec2b04f3d8d3c8b" dependencies = [ - "bitflags 2.10.0", + "bitflags 2.11.0", "core-foundation 0.9.4", "system-configuration-sys 0.6.0", ] @@ -8321,12 +8375,12 @@ checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" [[package]] name = "tempfile" -version = "3.23.0" +version = "3.25.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d31c77bdf42a745371d260a26ca7163f1e0924b64afa0b688e61b5a9fa02f16" +checksum = "0136791f7c95b1f6dd99f9cc786b91bb81c3800b639b3478e561ddb7be95e5f1" dependencies = [ "fastrand 2.3.0", - "getrandom 0.3.4", + "getrandom 0.4.1", "once_cell", "rustix", "windows-sys 0.61.2", @@ -8373,7 +8427,7 @@ dependencies = [ "serde", "serde_json", "serde_with 3.16.1", - "thiserror 2.0.17", + "thiserror 2.0.18", "tokio", "tokio-stream", "tokio-tar", @@ -8398,11 +8452,11 @@ dependencies = [ [[package]] name = "thiserror" -version = "2.0.17" +version = "2.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f63587ca0f12b72a0600bcba1d40081f830876000bb46dd2337a3051618f4fc8" +checksum = "4288b5bcbc7920c07a1149a35cf9590a2aa808e0bc1eafaade0b80947865fbc4" dependencies = [ - "thiserror-impl 2.0.17", + "thiserror-impl 2.0.18", ] [[package]] @@ -8413,18 +8467,18 @@ checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.117", ] [[package]] name = "thiserror-impl" -version = "2.0.17" +version = "2.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ff15c8ecd7de3849db632e14d18d2571fa09dfc5ed93479bc4485c7a517c913" +checksum = "ebc4ee7f67670e9b64d05fa4253e753e016c6c95ff35b89b7941d6b856dec1d5" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.117", ] [[package]] @@ -8447,9 +8501,9 @@ dependencies = [ [[package]] name = "time" -version = "0.3.44" +version = "0.3.47" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91e7d9e3bb61134e77bde20dd4825b97c010155709965fedf0f49bb138e52a9d" +checksum = "743bd48c283afc0388f9b8827b976905fb217ad9e647fae3a379a9283c4def2c" dependencies = [ "deranged", "itoa", @@ -8458,22 +8512,22 @@ dependencies = [ "num-conv", "num_threads", "powerfmt", - "serde", + "serde_core", "time-core", "time-macros", ] [[package]] name = "time-core" -version = "0.1.6" +version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "40868e7c1d2f0b8d73e4a8c7f0ff63af4f6d19be117e90bd73eb1d62cf831c6b" +checksum = "7694e1cfe791f8d31026952abf09c69ca6f6fa4e1a1229e18988f06a04a12dca" [[package]] name = "time-macros" -version = "0.2.24" +version = "0.2.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30cfb0125f12d9c277f35663a0a33f8c30190f4e4574868a330595412d34ebf3" +checksum = "2e70e4c5a0e0a8a4823ad65dfe1a6930e4f4d756dcd9dd7939022b5e8c501215" dependencies = [ "num-conv", "time-core", @@ -8525,17 +8579,17 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.48.0" +version = "1.49.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff360e02eab121e0bc37a2d3b4d4dc622e6eda3a8e5253d5435ecf5bd4c68408" +checksum = "72a2903cd7736441aac9df9d7688bd0ce48edccaadf181c3b90be801e81d3d86" dependencies = [ "bytes", "libc", - "mio 1.1.0", + "mio 1.1.1", "parking_lot 0.12.5", "pin-project-lite", "signal-hook-registry", - "socket2 0.6.1", + "socket2 0.6.2", "tokio-macros", "windows-sys 0.61.2", ] @@ -8548,7 +8602,7 @@ checksum = "af407857209536a95c8e56f8231ef2c2e2aff839b22e07a1ffcbc617e9db9fa5" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.117", ] [[package]] @@ -8577,15 +8631,15 @@ version = "0.26.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1729aa945f29d91ba541258c8df89027d5792d85a8841fb65e8bf0f4ede4ef61" dependencies = [ - "rustls 0.23.35", + "rustls 0.23.36", "tokio", ] [[package]] name = "tokio-stream" -version = "0.1.17" +version = "0.1.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eca58d7bba4a75707817a2c44174253f9236b2d5fbd055602e9d5c07c139a047" +checksum = "32da49809aab5c3bc678af03902d4ccddea2a87d028d86392a4b1560c6906c70" dependencies = [ "futures-core", "pin-project-lite", @@ -8628,7 +8682,7 @@ checksum = "7a9daff607c6d2bf6c16fd681ccb7eecc83e4e2cdc1ca067ffaadfca5de7f084" dependencies = [ "futures-util", "log", - "rustls 0.23.35", + "rustls 0.23.36", "rustls-pki-types", "tokio", "tokio-rustls 0.26.4", @@ -8638,9 +8692,9 @@ dependencies = [ [[package]] name = "tokio-util" -version = "0.7.17" +version = "0.7.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2efa149fe76073d6e8fd97ef4f4eca7b67f599660115591483572e406e165594" +checksum = "9ae9cec805b01e8fc3fd2fe289f89149a9b66dd16786abd8b19cfa7b48cb0098" dependencies = [ "bytes", "futures-core", @@ -8694,9 +8748,9 @@ dependencies = [ [[package]] name = "toml_datetime" -version = "0.7.3" +version = "0.7.5+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2cdb639ebbc97961c51720f858597f7f24c4fc295327923af55b74c3c724533" +checksum = "92e1cfed4a3038bc5a127e35a2d360f145e1f4b971b551a2ba5fd7aedf7e1347" dependencies = [ "serde_core", ] @@ -8707,7 +8761,7 @@ version = "0.19.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1b5bb770da30e5cbfde35a2d7b9b8a2c4b8ef89548a7a6aeab5c9a576e3e7421" dependencies = [ - "indexmap 2.12.1", + "indexmap 2.13.0", "serde", "serde_spanned", "toml_datetime 0.6.11", @@ -8720,7 +8774,7 @@ version = "0.22.27" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "41fe8c660ae4257887cf66394862d21dbca4a6ddd26f04a3560410406a2f819a" dependencies = [ - "indexmap 2.12.1", + "indexmap 2.13.0", "serde", "serde_spanned", "toml_datetime 0.6.11", @@ -8730,21 +8784,21 @@ dependencies = [ [[package]] name = "toml_edit" -version = "0.23.7" +version = "0.23.10+spec-1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6485ef6d0d9b5d0ec17244ff7eb05310113c3f316f2d14200d4de56b3cb98f8d" +checksum = "84c8b9f757e028cee9fa244aea147aab2a9ec09d5325a9b01e0a49730c2b5269" dependencies = [ - "indexmap 2.12.1", - "toml_datetime 0.7.3", + "indexmap 2.13.0", + "toml_datetime 0.7.5+spec-1.1.0", "toml_parser", "winnow 0.7.14", ] [[package]] name = "toml_parser" -version = "1.0.4" +version = "1.0.9+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0cbe268d35bdb4bb5a56a2de88d0ad0eb70af5384a99d648cd4b3d04039800e" +checksum = "702d4415e08923e7e1ef96cd5727c0dfed80b4d2fa25db9647fe5eb6f7c5a4c4" dependencies = [ "winnow 0.7.14", ] @@ -8757,9 +8811,9 @@ checksum = "5d99f8c9a7727884afe522e9bd5edbfc91a3312b36a77b5fb8926e4c31a41801" [[package]] name = "tower" -version = "0.5.2" +version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d039ad9159c98b70ecfd540b2573b97f7f52c3e8d9f8ad57a24b916a536975f9" +checksum = "ebe5ef63511595f1344e2d5cfa636d973292adc0eec1f0ad45fae9f0851ab1d4" dependencies = [ "futures-core", "futures-util", @@ -8772,11 +8826,11 @@ dependencies = [ [[package]] name = "tower-http" -version = "0.6.7" +version = "0.6.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9cf146f99d442e8e68e585f5d798ccd3cad9a7835b917e09728880a862706456" +checksum = "d4e6559d53cc268e5031cd8429d05415bc4cb4aefc4aa5d6cc35fbf5b924a1f8" dependencies = [ - "bitflags 2.10.0", + "bitflags 2.11.0", "bytes", "futures-util", "http 1.4.0", @@ -8802,9 +8856,9 @@ checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3" [[package]] name = "tracing" -version = "0.1.43" +version = "0.1.44" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d15d90a0b5c19378952d479dc858407149d7bb45a14de0142f6c534b16fc647" +checksum = "63e71662fa4b2a2c3a26f570f037eb95bb1f85397f3cd8076caed2f026a6d100" dependencies = [ "log", "pin-project-lite", @@ -8820,14 +8874,14 @@ checksum = "7490cfa5ec963746568740651ac6781f701c9c5ea257c58e057f3ba8cf69e8da" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.117", ] [[package]] name = "tracing-core" -version = "0.1.35" +version = "0.1.36" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a04e24fab5c89c6a36eb8558c9656f30d81de51dfa4d3b45f26b21d61fa0a6c" +checksum = "db97caf9d906fbde555dd62fa95ddba9eecfd14cb388e4f491a66d74cd5fb79a" dependencies = [ "once_cell", ] @@ -8891,10 +8945,10 @@ dependencies = [ "httparse", "log", "rand 0.9.2", - "rustls 0.23.35", + "rustls 0.23.36", "rustls-pki-types", "sha1", - "thiserror 2.0.17", + "thiserror 2.0.18", "utf-8", ] @@ -8915,7 +8969,7 @@ checksum = "0e48cea23f68d1f78eb7bc092881b6bb88d3d6b5b7e6234f6f9c911da1ffb221" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.117", ] [[package]] @@ -8968,9 +9022,9 @@ dependencies = [ [[package]] name = "unicase" -version = "2.8.1" +version = "2.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75b844d17643ee918803943289730bec8aac480150456169e647ed0b576ba539" +checksum = "dbc4bc3a9f746d862c45cb89d705aa10f187bb96c76001afab07a0d35ce60142" [[package]] name = "unicode-bidi" @@ -8980,9 +9034,9 @@ checksum = "5c1cb5db39152898a79168971543b1cb5020dff7fe43c8dc468b0885f5e29df5" [[package]] name = "unicode-ident" -version = "1.0.22" +version = "1.0.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9312f7c4f6ff9069b165498234ce8be658059c6728633667c526e27dc2cf1df5" +checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75" [[package]] name = "unicode-normalization" @@ -9047,14 +9101,15 @@ checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" [[package]] name = "url" -version = "2.5.7" +version = "2.5.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08bc136a29a3d1758e07a9cca267be308aeebf5cfd5a10f3f67ab2097683ef5b" +checksum = "ff67a8a4397373c3ef660812acab3268222035010ab8680ec4215f38ba3d0eed" dependencies = [ "form_urlencoded", "idna", "percent-encoding", "serde", + "serde_derive", ] [[package]] @@ -9083,19 +9138,19 @@ version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bc5cf98d8186244414c848017f0e2676b3fcb46807f6668a97dfe67359a3c4b7" dependencies = [ - "getrandom 0.2.16", + "getrandom 0.2.17", "serde", ] [[package]] name = "uuid" -version = "1.18.1" +version = "1.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f87b8aa10b915a06587d0dec516c282ff295b475d94abf425d62b57710070a2" +checksum = "b672338555252d43fd2240c714dc444b8c6fb0a5c5335e65a07bba7742735ddb" dependencies = [ - "getrandom 0.3.4", + "getrandom 0.4.1", "js-sys", - "serde", + "serde_core", "wasm-bindgen", ] @@ -9194,18 +9249,27 @@ checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" [[package]] name = "wasip2" -version = "1.0.1+wasi-0.2.4" +version = "1.0.2+wasi-0.2.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9517f9239f02c069db75e65f174b3da828fe5f5b945c4dd26bd25d89c03ebcf5" +dependencies = [ + "wit-bindgen", +] + +[[package]] +name = "wasip3" +version = "0.4.0+wasi-0.3.0-rc-2026-01-06" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0562428422c63773dad2c345a1882263bbf4d65cf3f42e90921f787ef5ad58e7" +checksum = "5428f8bf88ea5ddc08faddef2ac4a67e390b88186c703ce6dbd955e1c145aca5" dependencies = [ "wit-bindgen", ] [[package]] name = "wasm-bindgen" -version = "0.2.106" +version = "0.2.111" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d759f433fa64a2d763d1340820e46e111a7a5ab75f993d1852d70b03dbb80fd" +checksum = "ec1adf1535672f5b7824f817792b1afd731d7e843d2d04ec8f27e8cb51edd8ac" dependencies = [ "cfg-if", "once_cell", @@ -9218,11 +9282,12 @@ dependencies = [ [[package]] name = "wasm-bindgen-futures" -version = "0.4.56" +version = "0.4.61" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "836d9622d604feee9e5de25ac10e3ea5f2d65b41eac0d9ce72eb5deae707ce7c" +checksum = "fe88540d1c934c4ec8e6db0afa536876c5441289d7f9f9123d4f065ac1250a6b" dependencies = [ "cfg-if", + "futures-util", "js-sys", "once_cell", "wasm-bindgen", @@ -9231,9 +9296,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.106" +version = "0.2.111" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48cb0d2638f8baedbc542ed444afc0644a29166f1595371af4fecf8ce1e7eeb3" +checksum = "19e638317c08b21663aed4d2b9a2091450548954695ff4efa75bff5fa546b3b1" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -9241,26 +9306,48 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.106" +version = "0.2.111" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cefb59d5cd5f92d9dcf80e4683949f15ca4b511f4ac0a6e14d4e1ac60c6ecd40" +checksum = "2c64760850114d03d5f65457e96fc988f11f01d38fbaa51b254e4ab5809102af" dependencies = [ "bumpalo", "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.117", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.106" +version = "0.2.111" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cbc538057e648b67f72a982e708d485b2efa771e1ac05fec311f9f63e5800db4" +checksum = "60eecd4fe26177cfa3339eb00b4a36445889ba3ad37080c2429879718e20ca41" dependencies = [ "unicode-ident", ] +[[package]] +name = "wasm-encoder" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "990065f2fe63003fe337b932cfb5e3b80e0b4d0f5ff650e6985b1048f62c8319" +dependencies = [ + "leb128fmt", + "wasmparser", +] + +[[package]] +name = "wasm-metadata" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb0e353e6a2fbdc176932bbaab493762eb1255a7900fe0fea1a2f96c296cc909" +dependencies = [ + "anyhow", + "indexmap 2.13.0", + "wasm-encoder", + "wasmparser", +] + [[package]] name = "wasm-streams" version = "0.4.2" @@ -9274,6 +9361,18 @@ dependencies = [ "web-sys", ] +[[package]] +name = "wasmparser" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "47b807c72e1bac69382b3a6fb3dbe8ea4c0ed87ff5629b8685ae6b9a611028fe" +dependencies = [ + "bitflags 2.11.0", + "hashbrown 0.15.5", + "indexmap 2.13.0", + "semver 1.0.27", +] + [[package]] name = "wasmtimer" version = "0.4.3" @@ -9290,9 +9389,9 @@ dependencies = [ [[package]] name = "web-sys" -version = "0.3.83" +version = "0.3.88" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b32828d774c412041098d182a8b38b16ea816958e07cf40eec2bc080ae137ac" +checksum = "9d6bb20ed2d9572df8584f6dc81d68a41a625cadc6f15999d649a70ce7e3597a" dependencies = [ "js-sys", "wasm-bindgen", @@ -9320,14 +9419,14 @@ version = "0.26.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "521bc38abb08001b01866da9f51eb7c5d647a19260e00054a8c7fd5f9e57f7a9" dependencies = [ - "webpki-roots 1.0.4", + "webpki-roots 1.0.6", ] [[package]] name = "webpki-roots" -version = "1.0.4" +version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2878ef029c47c6e8cf779119f20fcf52bde7ad42a731b2a304bc221df17571e" +checksum = "22cfaf3c063993ff62e73cb4311efde4db1efb31ab78a3e5c457939ad5cc0bed" dependencies = [ "rustls-pki-types", ] @@ -9390,7 +9489,7 @@ checksum = "053e2e040ab57b9dc951b72c264860db7eb3b0200ba345b4e4c3b14f67855ddf" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.117", ] [[package]] @@ -9401,7 +9500,7 @@ checksum = "3f316c4a2570ba26bbec722032c4099d8c8bc095efccdc15688708623367e358" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.117", ] [[package]] @@ -9700,9 +9799,91 @@ dependencies = [ [[package]] name = "wit-bindgen" -version = "0.46.0" +version = "0.51.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d7249219f66ced02969388cf2bb044a09756a083d0fab1e566056b04d9fbcaa5" +dependencies = [ + "wit-bindgen-rust-macro", +] + +[[package]] +name = "wit-bindgen-core" +version = "0.51.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea61de684c3ea68cb082b7a88508a8b27fcc8b797d738bfc99a82facf1d752dc" +dependencies = [ + "anyhow", + "heck 0.5.0", + "wit-parser", +] + +[[package]] +name = "wit-bindgen-rust" +version = "0.51.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b7c566e0f4b284dd6561c786d9cb0142da491f46a9fbed79ea69cdad5db17f21" +dependencies = [ + "anyhow", + "heck 0.5.0", + "indexmap 2.13.0", + "prettyplease", + "syn 2.0.117", + "wasm-metadata", + "wit-bindgen-core", + "wit-component", +] + +[[package]] +name = "wit-bindgen-rust-macro" +version = "0.51.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c0f9bfd77e6a48eccf51359e3ae77140a7f50b1e2ebfe62422d8afdaffab17a" +dependencies = [ + "anyhow", + "prettyplease", + "proc-macro2", + "quote", + "syn 2.0.117", + "wit-bindgen-core", + "wit-bindgen-rust", +] + +[[package]] +name = "wit-component" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d66ea20e9553b30172b5e831994e35fbde2d165325bec84fc43dbf6f4eb9cb2" +dependencies = [ + "anyhow", + "bitflags 2.11.0", + "indexmap 2.13.0", + "log", + "serde", + "serde_derive", + "serde_json", + "wasm-encoder", + "wasm-metadata", + "wasmparser", + "wit-parser", +] + +[[package]] +name = "wit-parser" +version = "0.244.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f17a85883d4e6d00e8a97c586de764dabcc06133f7f1d55dce5cdc070ad7fe59" +checksum = "ecc8ac4bc1dc3381b7f59c34f00b67e18f910c2c0f50015669dde7def656a736" +dependencies = [ + "anyhow", + "id-arena", + "indexmap 2.13.0", + "log", + "semver 1.0.27", + "serde", + "serde_derive", + "serde_json", + "unicode-xid", + "wasmparser", +] [[package]] name = "writeable" @@ -9723,7 +9904,7 @@ dependencies = [ "pharos", "rustc_version 0.4.1", "send_wrapper 0.6.0", - "thiserror 2.0.17", + "thiserror 2.0.18", "wasm-bindgen", "wasm-bindgen-futures", "web-sys", @@ -9805,28 +9986,28 @@ checksum = "b659052874eb698efe5b9e8cf382204678a0086ebf46982b79d6ca3182927e5d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.117", "synstructure", ] [[package]] name = "zerocopy" -version = "0.8.30" +version = "0.8.39" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ea879c944afe8a2b25fef16bb4ba234f47c694565e97383b36f3a878219065c" +checksum = "db6d35d663eadb6c932438e763b262fe1a70987f9ae936e60158176d710cae4a" dependencies = [ "zerocopy-derive", ] [[package]] name = "zerocopy-derive" -version = "0.8.30" +version = "0.8.39" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf955aa904d6040f70dc8e9384444cb1030aed272ba3cb09bbc4ab9e7c1f34f5" +checksum = "4122cd3169e94605190e77839c9a40d40ed048d305bfdc146e7df40ab0f3e517" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.117", ] [[package]] @@ -9846,7 +10027,7 @@ checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.117", "synstructure", ] @@ -9861,13 +10042,13 @@ dependencies = [ [[package]] name = "zeroize_derive" -version = "1.4.2" +version = "1.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" +checksum = "85a5b4158499876c763cb03bc4e49185d3cccbabb15b33c627f7884f43db852e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.117", ] [[package]] @@ -9900,7 +10081,7 @@ checksum = "eadce39539ca5cb3985590102671f2567e659fca9666581ad3411d59207951f3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.117", ] [[package]] @@ -9923,6 +10104,12 @@ dependencies = [ "zstd", ] +[[package]] +name = "zmij" +version = "1.0.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8848ee67ecc8aedbaf3e4122217aff892639231befc6a1b58d29fff4c2cabaa" + [[package]] name = "zstd" version = "0.11.2+zstd.1.5.2" diff --git a/blockchain_assets/contracts/RoundRobin.sol b/blockchain_assets/contracts/RoundRobin.sol index eec61bd8..71accbed 100644 --- a/blockchain_assets/contracts/RoundRobin.sol +++ b/blockchain_assets/contracts/RoundRobin.sol @@ -71,8 +71,8 @@ contract RoundRobin is ProposerManager, Certified, UUPSUpgradeable { __Certified_init(msg.sender, x509_address, sanctionsListAddress); require(cooling_blocks > 0, "Cooling blocks must be > 0"); - require(stake >= exit_penalty, "Stake < exit penalty"); - require(lazy_penalty > exit_penalty, "LazyPenalty <= exit penalty"); + require(stake >= lazy_penalty, "Stake should be more than exit penalty"); + require(lazy_penalty > exit_penalty, "LazyPenalty should be more than exit penalty"); require(grace_blocks > 0 && grace_blocks < rotation_blocks, "Grace blocks must be > 0 and less than rotation blocks"); STAKE = stake; @@ -157,7 +157,7 @@ contract RoundRobin is ProposerManager, Certified, UUPSUpgradeable { lazy_penalize_proposer(current.addr); } // Define the minimum eligibility floor - uint256 eligibilityFloor = EXIT_PENALTY + LAZY_PENALTY; + uint256 eligibilityFloor = LAZY_PENALTY; // Iterate through the proposer list to find an eligible proposer address nextProposer = current.next_addr; diff --git a/configuration/Dockerfile b/configuration/Dockerfile index b6081c61..b7c78c6c 100644 --- a/configuration/Dockerfile +++ b/configuration/Dockerfile @@ -10,11 +10,12 @@ RUN rm /etc/nginx/conf.d/default.conf # Create config directory RUN mkdir -p /var/www/html/configuration/toml + # Copy our nginx config COPY ./configuration/nginx.conf /etc/nginx/conf.d/default.conf # Copy static files (if any go into /var/www/html/bin) -COPY ./configuration/bin/* /var/www/html/ +COPY ./configuration/bin/keys/* /var/www/html/ RUN chown -R nginx:nginx /var/www/html \ && chmod -R 755 /var/www/html diff --git a/configuration/src/addresses.rs b/configuration/src/addresses.rs index 4574149d..5461e64f 100644 --- a/configuration/src/addresses.rs +++ b/configuration/src/addresses.rs @@ -85,7 +85,7 @@ fn deny_if_dns_private(host: &str) -> Result<(), AddressesError> { /// Validates configuration URLs with security enforcement. /// Production: HTTPS. Debug: HTTP allowed for localhost/test containers. -fn validate_config_url(raw: &str) -> Result { +pub fn validate_config_url(raw: &str) -> Result { let url = Url::parse(raw).map_err(|_| AddressesError::Toml(format!("Invalid URL: {raw}")))?; let host = url @@ -137,7 +137,8 @@ fn validate_config_url(raw: &str) -> Result { } // Scheme enforcement: HTTPS only in production - if url.scheme() != "https" && !is_development { + let is_production = matches!(run_mode.as_str(), "production"); + if url.scheme() != "https" && is_production { let scheme = url.scheme(); warn!("HTTP not allowed in production, use HTTPS"); return Err(AddressesError::Toml(format!( @@ -170,8 +171,7 @@ pub fn get_addresses() -> &'static Addresses { } } let base = validate_config_url(&settings.configuration_url).expect("Invalid or untrusted configuration URL"); - let url = base.join("addresses").expect("Could not parse addresses server endpoint"); - // Retry logic: wait for deployer to finish and save addresses + let url = base.join("configuration/toml/addresses.toml").expect("Could not parse addresses server endpoint"); // Retry logic: wait for deployer to finish and save addresses let max_attempts = 32; let mut wait_time = 2; @@ -471,7 +471,7 @@ impl Addresses { #[cfg(unix)] { use std::os::unix::fs::PermissionsExt; - let perms = std::fs::Permissions::from_mode(0o600); + let perms = std::fs::Permissions::from_mode(0o644); std::fs::set_permissions(&path, perms).map_err(|e| { AddressesError::Toml(format!("Could not set permissions: {e}")) })?; diff --git a/configuration/src/settings.rs b/configuration/src/settings.rs index e6733385..68aac15d 100644 --- a/configuration/src/settings.rs +++ b/configuration/src/settings.rs @@ -112,6 +112,10 @@ fn default_max_key_download_bytes() -> u64 { 30 * 1024 * 1024 * 1024 // 30 gb } +fn default_rpc_rate_limit() -> u32 { + 0 // 0 = unlimited +} + #[derive(Debug, Deserialize, Serialize, Default)] #[allow(unused)] pub struct Settings { @@ -139,6 +143,14 @@ pub struct Settings { /// If not set, default value of 30 GB is used #[serde(default = "default_max_key_download_bytes")] pub max_key_download_bytes: u64, + /// Optional log chunk size for RPC queries + /// If not set, defaults based on chain ID are used + #[serde(default)] + pub log_chunk_size: Option, + /// Optional max RPC calls per second (0 = unlimited) + /// Useful for staying within provider rate limits (e.g., Alchemy free tier: 8 calls/sec) + #[serde(default = "default_rpc_rate_limit")] + pub rpc_rate_limit: u32, } impl Settings { diff --git a/doc/Setup Testnet Guide.md b/doc/Setup Testnet Guide.md new file mode 100644 index 00000000..8ae56fc1 --- /dev/null +++ b/doc/Setup Testnet Guide.md @@ -0,0 +1,541 @@ +# Setup Testnet Guide + +## Overview + +Setting up Nightfall_4 on a host chain (testnet) involves deploying smart contracts, generating zero-knowledge proving keys, configuring network metadata, and starting the required services. + +At a high level, the process consists of: + +1. Running the **deployment service** to deploy contracts and generate proving keys. +2. Running the **configuration service** to host contract addresses, contract hashes, and keys. +3. Starting the **designated proposer** to assemble and submit L2 blocks. +4. Starting the **client service** to submit transactions. +5. Optionally registering and rotating additional proposers. + +During deployment, a **designated proposer** is registered by deployer for liveness. This proposer is responsible for assembling L2 blocks and proposing them to the host chain. Additional proposers can later be registered and rotated into the active role when it's ready to rotate proposer (difference between the L1 block number when last proposer is working and the current L1 block number should be more than `proposer_rotation_blocks` defined in `nightfall.toml`). + +------ +****** +______ + +## Step 1: Start the deployer + +> ⚠️ **Important** +> +> The host chain RPC endpoint **must support WebSocket connections** (`ws://` or `wss://`). +> Nightfall subscribes to blockchain events, so an `http://` / `https://` endpoint will **not** work. + +### Step 1.1: Setup the Configuration file + +```bash +git clone https://github.com/EYBlockchain/nightfall_4_CE.git +cd nightfall_4_CE +git checkout -b host-chain/deployer +``` + +#### Step 1.1.1: Chang `nightfall.toml` +Add a stanza to the `nightfall.toml` file for your host chain configuration, if it doesn't already exist. Use the [development] section as a reference, and rename it to your host chain name (e.g. [host-chain]). + +Host-chain dependent items: + +- `[host-chain]-genesis_block`: If you are deploying contracts for the first time, set this to roughly the current Layer 1 block number on the host chain. This speeds up syncing because Nightfall will not scan for events before this block. + +- `[host-chain]-ethereum_client_url`: The host chain RPC URL. Must be WebSocket (`ws://` / `wss://`). + +- `[host-chain]-configuration_url`: URL where the configuration service is exposed. If you change the port (default `8080`), update it here and expose the same port in `docker-compose.yml`. Deployer will host metadat like prving keys, contract addressess and contract hashes on `[host-chain]-configuration_url::8080`, so that client and proposer can download when they need. + +- `[host-chain.network]-chain_id`: Chain ID of the host chain. Deployment logs are written under a folder named after this chain ID. + +- `[host-chain.owners]`: Contract owners. These are required for upgrades. + +- `[host-chain.nightfall_deployer]`: `default_proposer_address` and `default_proposer_url` bootstrap L2 block proposing. +When running the default proposer node, you must expose port `3001` on the host. +Set `default_proposer_url` to something like `http://:3001`. +Other values such as `proposer_stake` and `proposer_ding` are liveness parameters. Note that `proposer_stake` must be greater than `proposer_exit_penalty`. +If you need to modify these after deployment, you must upgrade the RoundRobin contract. +See `doc/Upgradable Contracts Guide.md`. + +- `[host-chain.contracts]-deploy_contracts`: If true, the deployer will deploy new contracts. +If false, it will generate/setup keys but will not deploy contracts before exiting. +It can be convenient to override this via an environment variable to avoid rebuilding containers. + +- `[host-chain.contracts.contract_addresses]`: If contracts are already deployed, place their addresses here so Nightfall can locate them reliably. +Otherwise, Nightfall will attempt to read the latest deployment log file, which is less reliable. +If you want to avoid that behavior, leave these values as empty strings. +These values are ignored if `deploy_contracts=true`. + +- `[host-chain.certificates]`: Root CA information for X.509 certificates. +If you are using the testing certificate setup, you can copy the values from [development.certificates]. + +#### Step 1.1.2: Update `docker-compose.yml` +In `docker-compose.yml`, locate the `indie-deployer` service and update the run mode: + +Set: + +`NF4_RUN_MODE=${NF4_RUN_MODE:host-chain}` + +Go to `Configuration`, uncomment +```bash +restart: unless-stopped + ports: + - "8080:80" +``` + +### Step 1.2: Create `local.env` + +Create a file named `local.env` in the repo root with the following content. +Replace placeholders (`0x...`) where required. + +The deployer will use the account corresponding to DEPLOYER_SIGNING_KEY to deploy contracts on the host chain. + +```bash +DEPLOYER_SIGNING_KEY="0x......." +``` +where `DEPLOYER_SIGNING_KEY` is private key of deployer's L1 address on host chain. +Make sure the deployer account has at least 0.1 ETH: +``` + +export NF4_ETHEREUM_CLIENT_URL="your-rpc-url" +cast balance 0x-L1_Add --rpc-url "$NF4_ETHEREUM_CLIENT_URL" + +``` +Replace `your-rpc-url` with host chain RPC URL, replace `0x-L1_Add` with your L1 address on your host chain. +### Step 1.3: Disable X509 certifiate check if needed +If you don't need clients/proposers to submit X509 certificate, you can disable X509 by changing `x509Contract.enableAllowlisting(true);` to `x509Contract.enableAllowlisting(false);` in `blockchain_assets/script/deployer.s.sol`. + +### Step 1.4: Deploying contracts + +You usually only need to deploy once. If contracts are changed due to governance, you should upgrade related contracts following `doc/Upgradable Contracts Guide.md` for decentralisation. +> ⚠️ **Resource requirement:** +> +> Key generation is heavy. A large server is recommended (e.g., 144 cores / 750GB RAM). + +--- + +#### Step 1.4.1: Build Contracts +```bash +forge clean && forge build +``` +--- + +#### Step 1.4.2: Generate proving keys + +This will download a large file and generate multiple keys: +```bash +NF4_MOCK_PROVER=false cargo run --release --bin key_generation +``` +You should see: + +- `Generating keys for REAL rollup prover` when it begins + +- `Generating keys for rollup prover finished` when complete + +Key generation can take ~1.5 hours the first time, it's because we need to download a huge file and run trusted setup. Subsequent runs are faster (~20 minutes) because `ppot_26.ptau` and `bn254_setup_26.cache` are reused if they are not broken. Only need to change keys when circuits are changed. + +Keys and intermediate files are stored under configuration/bin/, for example for `block_size == 64`, we have the following keys: +```bash +base_bn254_pk: 1.9G +base_grumpkin_pk: 61M +decider_pk: 30G +decider_vk: 1.3K +deposit_proving_key: 233M +merge_bn254_pk_0: 929M +merge_grumpkin_pk_0: 121M +merge_grumpkin_pk_1: 121M +proving_key: 30M +ppot_26.ptau: 73G +bn254_setup_26.cache: 2.1G +``` +We have extra keys for `block_size == 256`. Therefore, if proposer node decides to use a different block size, it will need to generate keys itself. + + +--- + +#### Step 1.4.3: Start deployer service + +```bash +docker compose --profile indie-deployer build +docker compose --profile indie-deployer --env-file local.env up +``` +This deploys all Nightfall contracts. + +- Contract addresses that proposers/clients need to directly interact with are written to: `configuration/toml/addresses.toml` + +- Contract hashes of the aformentioned contracts are written to: `configuration/toml/contract_hashes.toml` + +- Deployment logs are saved under: `blockchain_assets/logs` + + +`nf4_indie_deployer exited with code 0` indicates a successful outcome. + +> ⚠️ **Troubleshooting:** +> +> If you see the following error: +> ` +ERROR panic: 'main' panicked at 'Could not create blockchain client connection: +ProviderError("URL error: URL scheme not supported")': /app/lib/src/lib.rs:63 +` +it usually means the RPC endpoint is invalid or uses an unsupported scheme. Try to use a different RPC URL. + +### Step 1.5: Run the configuration service + +The configuration service hosts: + +- deployed contract addresses, + +- deployed contract hashes (for on-chain verification), + +- generated proving keys. + +Build and Run the Configuration service following the next steps: + +```bash +docker compose --profile configuration build +docker compose --profile configuration --env-file local.env up -d +docker compose --profile configuration --env-file local.env logs -f +``` + +To verify if this step finishes successfully, you can check if configuration url (`[host-chain]-configuration_url`) hosts keys, contract addresses and contract hashes correctly: +1. Open another terminal in a new folder to get keys: +```bash +mkdir configuration/bin/keys +curl -v [host-chain]-configuration_url:8080/ -o configuration/bin/keys/ +``` +where you need to it for following keys `base_bn254_pk`, `base_grumpkin_pk`, `decider_pk`, `deposit_proving_key`, `merge_bn254_pk_0`, `merge_grumpkin_pk_0`, `merge_grumpkin_pk_1`, and `proving_key`. use `ls -lh`to check the key size, it should match the size mentioned before. + +2. `curl [host-chain]-configuration_url/configuration/toml/addresses.toml` to get addresses for `nightfall`, `round_robin`, `x509` and `verifier`. + +3. `curl [host-chain]-configuration_url/configuration/toml/contract_hashes.toml` to get contract hashes for `nightfall_hash`, `round_robin_hash`, `x509_hash`. + + +------ +****** +______ + +## Step 2: Start the disignated proposer +As mentioned before, disignated proposer is for liveness, but this doesn't mean that Nightfall has centralisation problem for proposer. You can safely skip this step, and run Step 4 to start a proposer node, and rotate proposer to its turn when it's time to rotate proposer. +> ⚠️ **Resource requirement:** +> +> Proving a L2 block with full privacy is heavy. A large server is recommended (e.g., 144 cores / 750GB RAM). + +The difference between running a designated propser and a new proposer is that designated propser node doesnt need to call the registration api as deployer has registered this proposer during deployment. + +### Step 2.1: Get the source + +```bash +git clone https://github.com/EYBlockchain/nightfall_4_CE.git +cd nightfall_4_CE +git checkout -b host-chain/proposer +forge clean && forge build +``` +--- + +### Step 2.2: Stop & clean previous Docker state +```bash +docker compose --profile indie-proposer down -v +# DANGER: removes images, containers, networks, and volumes +docker system prune -a --volumes +``` +--- + +### Step 2.3: Generate/download proving keys +There are two ways to form the keys needed to proving a L2 block, proposer can generate itself or download from the configuration url + +1. Method 1: generate keys +```bash +NF4_MOCK_PROVER=false cargo run --release --bin key_generation +``` +2. Method 2: get the keys using the configuartion url in the root of `nightfall_4_CE` folder, +```bash +mkdir configuration/bin/keys +curl -v [host-chain]-configuration_url:8080/ -o configuration/bin/keys/` +``` +Replace `` with: `base_bn254_pk`, `base_grumpkin_pk`, `decider_pk`, `deposit_proving_key`, `merge_bn254_pk_0`, `merge_grumpkin_pk_0`, `merge_grumpkin_pk_1`, `proving_key`. You can verify the key size as mentioned before. + +Note that when the deployer starts the deployment with `block_size == 64` or `block_size == 256`, it will generate the aforementioned keys, but proposer can decide to increase the `block_size` to `256`, in this case, proposer need to run key generation itself and change `block_size = 64` to `block_size = 256` in `[host-chain.nightfall_proposer]` of `nightfall.toml`. Only 64 and 256 are surpported. + +--- +### Step 2.4: Create `local.env` + +Create a file named `local.env` in the repo root with the following content. Replace placeholders (`0x....`) with your values where indicated. + +```bash +PROPOSER_SIGNING_KEY="0x......." +``` + +where `PROPOSER_SIGNING_KEY` is your private key for L1 address on host chain. +--- + +### Step 2.5: Change `nightfall.toml` and `docker-compose.yml` +1. Copy the values added in Step 1.1.1 for `nightfall.toml`. +2. Change `docker-compose.yml`: +Go to `indie-proposer-environment`, change `- NF4_RUN_MODE=${NF4_RUN_MODE:-host-chain}` +Go to `volumes:`, uncomment `mongodb_proposer_data:` +--- + +### Step 2.6: Build and run the Nightfall indie proposer node + +From the repo root: + +```bash +forge clean && forge build + +docker compose --profile indie-proposer build + +docker compose --profile indie-proposer --env-file local.env up -d + +docker compose --profile indie-proposer --env-file local.env logs -f +``` + +If you enable x509 during the deployement, proposer needs to call X509 validation api: + +*** + +POST /v1/certification + +```sh +curl -i -X POST 'http://localhost:3001/v1/certification' \ + -H 'Content-Type: multipart/form-data' \ + -F 'certificate=@blockchain_assets/test_contracts/X509/_certificates/user/user-1.der;type=application/pkix-cert' \ + -F 'certificate_private_key=@blockchain_assets/test_contracts/X509/_certificates/user/user-1.priv_key;type=application/octet-stream' +``` + +Now the proposer is started, it will start to assemble a block when block assembly is triggered. It's fine if you see logs like `nightfall_proposer::driven::block_assembler] Not enough transactions to assemble a block yet.` It means proposer is still waiting. + +When there is a deposit transaction, you will see `Received DepositEscrowed event`, and it will save this tx into its mempool. + +When there is a transfer or withdraw transaction, you will see `Client Transaction is valid, storing in database` if the proof submitted by client is valid. + +When proposer is making a block, you will see `This block has x deposit(s), y transfer(s), and z withdrawal(s)`. + +When proposer is proving a block, you will see `Computing block`, it will take 20 mins depending on your proposer's computing ability. When it's finished you will see `Block computation took xx`, `Proposing x pending blocks` and `Added block to queue (1 pending)`. + +When proposer successfully sent the block to L1, you will see `The L2 block was sent to L1`, you can verify this by checking the L1 exploer of nightfall contract address. + + +Proposer can twist block making parameters by changing `block_assembly_max_wait_secs` `block_assembly_target_fill_ratio`, `block_assembly_initial_interval_secs`, `max_event_listener_attempts`, `block_size` in [host-chain.nightfall_proposer] nightfall.toml. + +------ +****** +______ + + +## Step 3: Start the client node + +As a client, you can do deposit, transfer, withdraw in Nightfall. To be able to deposit some tokens into Nightfall, you should have tokens in an ERC20|721|1155|3525 contract that you can access. + +### Step 3.1: Create `local.env` +```bash +git clone https://github.com/EYBlockchain/nightfall_4_CE.git +cd nightfall_4_CE +git checkout -b host-chain/client +``` + +Create a file named `local.env` in the repo root with the following content. Replace placeholders (`0x....`) with your values where indicated. + +```bash +CLIENT_SIGNING_KEY="0x......." +CLIENT_ADDRESS="0x......." +``` +`CLIENT_SIGNING_KEY` is your L1 address's private key on host chain. +`CLIENT_ADDRESS` is your L1 address on host chain. +--- +### Step 3.2: Deploy ERC contracts +You can deploy your own ERC-20/721/1155/3525 contracts using the following script: `blockchain_assets/script/mock_deployment.s.sol` + +If you want to do mock ERC deployments, you can do: +1. Run `curl [host-chain]-configuration_url:8080/configuration/toml/addresses.toml` to get Nightfall contract address +2. Add `NIGHTFALL_ADDRESS`, `NF4_SIGNING_KEY` and `CLIENT2_ADDRESS` in your `local.env`, where Nightfall contract address is `local.env-NIGHTFALL_ADDRESS` and your host chain L1 private key is `NF4_SIGNING_KEY`. `CLIENT2_ADDRESS` can be a dummy value or the same value as `CLIENT_ADDRESS`, this is just for testing. +3. `forge clean && forge build` +4. `export $(grep -v '^#' local.env | xargs)` +5. `forge script blockchain_assets/script/mock_deployment.s.sol:MockDeployer --rpc-url XXXXXXXXXhost-chain-rpc-urlXXXXXXXXX --broadcast --legacy --slow` +Change `XXXXXXXXXhost-chain-rpc-urlXXXXXXXXX` to the host chain RPC URL. +After this step, you will get the mocked ERC address of `ERC20Mock`, `ERC721Mock`, `ERC1155Mock`, and `ERC3525Mock`. You should store these addresses locally, which will be used later when you are using client APIs. +--- + +### Step 3.3: Get the proving key from configuration server +Client node needs to prove its transfers and withdraws using the `proving_key` from configuration url: +```bash +mkdir configuration/bin/keys +curl -v [host-chain]-configuration_url:8080/keys/proving_key -o configuration/bin/keys/proving_key` +``` + +You can verify that there is `configuration/bin/keys/proving_key` with size 30M. +--- + +### Step 3.4: Stop & clean previous Docker state + +```bash +docker compose --profile indie-client down +# DANGER: removes images, containers, networks, and volumes +docker system prune -a --volumes +``` + + + + +--- +### Step 3.5: Change `nightfall.toml` and `docker-compose.yml` +1. Copy the values added in Step 1.1.1 for `nightfall.toml`. +2. Change `docker-compose.yml`: +Go to `indie-client-environment`, change `- NF4_RUN_MODE=${NF4_RUN_MODE:-host-chain}` and `- NF4_NIGHTFALL_PROPOSER__URL= ${NF4_NIGHTFALL_PROPOSER__URL:-server-ip:3001}` +Go to `volumes:`, uncomment `mongodb_client_data:` +Go to `db_client`, uncomment `volumes: - mongodb_client_data:/data/db` + +### Step 3.6: Build and run the Nightfall client + +From the repo root: + +```bash +forge clean && forge build +docker compose --profile indie-client build + +docker compose --profile indie-client --env-file local.env up +``` +### Step 3.7: Call Client APIs +When you see `nightfall_client::drivers::blockchain::nightfall_event_listener Subscribed to events`, you can then interact with Nightfall using the client APIs: https://github.com/EYBlockchain/nightfall_4_CE/blob/master/doc/nf_4.md#client-apis. /v1/certification should be called first if X509 is enabled during deployment. + +POST /v1/certification + +```sh +curl -i -X POST 'http://localhost:3000/v1/certification' \ + -H 'Content-Type: multipart/form-data' \ + -F 'certificate=@blockchain_assets/test_contracts/X509/_certificates/user/user-3.der;type=application/pkix-cert' \ + -F 'certificate_private_key=@blockchain_assets/test_contracts/X509/_certificates/user/user-3.priv_key;type=application/octet-stream' +``` + +------ +****** +______ + +## Step 4: Start the proposer node + +### Step 4.1: Get the source + +```bash +git clone https://github.com/EYBlockchain/nightfall_4_CE.git +cd nightfall_4_CE +git checkout -b host-chain/proposer +forge clean && forge build +``` +--- + +### Step 4.2: Stop & clean previous Docker state +```bash +docker compose --profile indie-proposer down -v +# DANGER: removes images, containers, networks, and volumes +docker system prune -a --volumes +``` +--- + +### Step 4.3: Generate/download proving keys +There are two ways to form the keys needed to proving a L2 block, proposer can generate itself or download from the configuration url + +1. Method 1: generate keys +```bash +NF4_MOCK_PROVER=false cargo run --release --bin key_generation +``` +2. Method 2: get the keys using the configuartion url in the root of `nightfall_4_CE` folder, +```bash +mkdir configuration/bin/keys +curl -v [host-chain]-configuration_url:8080/ -o configuration/bin/keys/` +``` +Replace `` with: `base_bn254_pk`, `base_grumpkin_pk`, `decider_pk`, `deposit_proving_key`, `merge_bn254_pk_0`, `merge_grumpkin_pk_0`, `merge_grumpkin_pk_1`, `proving_key`. You can verify the key size as mentioned before. + +Note that when the deployer starts the deployment with `block_size == 64` or `block_size == 256`, it will generate the aforementioned keys, but proposer can decide to increase the `block_size` to `256`, in this case, proposer need to run key generation itself and change `block_size = 64` to `block_size = 256` in `[host-chain.nightfall_proposer]` of `nightfall.toml`. Only 64 and 256 are surpported. + +--- +### Step 4.4: Create `local.env` + +Create a file named `local.env` in the repo root with the following content. Replace placeholders (`0x....`) with your values where indicated. + +```bash +PROPOSER_SIGNING_KEY="0x......." +``` + +where `PROPOSER_SIGNING_KEY` is your private key for L1 address on host chain. +--- + +### Step 4.5: Change `nightfall.toml` and `docker-compose.yml` +1. Copy the values added in Step 1.1.1 for `nightfall.toml`. +2. Change `docker-compose.yml`: +Go to `indie-proposer-environment`, change `- NF4_RUN_MODE=${NF4_RUN_MODE:-host-chain}` +Go to `volumes:`, uncomment `mongodb_proposer_data:` +--- + + +### Step 4.6: Register as a Proposer + +Now since you started as a proposer, you need to register as a proposer with the url `http://:3001` using the following api + +POST /v1/register + +```sh +curl -i --request POST 'http://localhost:3000/v1/register' \ + --json '{ "url": "http://:3001" }' +``` +### Step 4.7: Rotate Proposer +If you want create blocks as a proposer, you can call rotate proposer api + +GET v1/rotate + +```sh +curl -i 'http://localhost:3001/v1/rotate' +``` + +Returns: on success `200 OK` if the active `proposer` was rotated, `423 LOCKED` if proposer rotation was not allowed by the smart contract. +This endpoint will rotate the proposers if the current `proposer` has been active for more than the number of Layer 1 blocks that a `proposer` is allowed to propose for (ROTATION_BlOCKS) (currently set as 4 blocks). This value is set in the construction of RoundRobin.sol. + +### Step 4.7: Build and run the Nightfall indie proposer node + +From the repo root: + +```bash +forge clean && forge build + +docker compose --profile indie-proposer build + +docker compose --profile indie-proposer --env-file local.env up -d + +docker compose --profile indie-proposer --env-file local.env logs -f +``` + +If you enable x509 during the deployement, proposer needs to call X509 validation api: + +*** + +POST /v1/certification + +```sh +curl -i -X POST 'http://localhost:3001/v1/certification' \ + -H 'Content-Type: multipart/form-data' \ + -F 'certificate=@blockchain_assets/test_contracts/X509/_certificates/user/user-1.der;type=application/pkix-cert' \ + -F 'certificate_private_key=@blockchain_assets/test_contracts/X509/_certificates/user/user-1.priv_key;type=application/octet-stream' +``` + +Now the proposer is started, it will start to assemble a block when block assembly is triggered. It's fine if you see logs like `nightfall_proposer::driven::block_assembler] Not enough transactions to assemble a block yet.` It means proposer is still waiting. + +When there is a deposit transaction, you will see `Received DepositEscrowed event`, and it will save this tx into its mempool. + +When there is a transfer or withdraw transaction, you will see `Client Transaction is valid, storing in database` if the proof submitted by client is valid. + +When proposer is making a block, you will see `This block has x deposit(s), y transfer(s), and z withdrawal(s)`. + +When proposer is proving a block, you will see `Computing block`, it will take 20 mins depending on your proposer's computing ability. When it's finished you will see `Block computation took xx`, `Proposing x pending blocks` and `Added block to queue (1 pending)`. + +When proposer successfully sent the block to L1, you will see `The L2 block was sent to L1`, you can verify this by checking the L1 exploer of nightfall contract address. + + +Proposer can twist block making parameters by changing `block_assembly_max_wait_secs` `block_assembly_target_fill_ratio`, `block_assembly_initial_interval_secs`, `max_event_listener_attempts`, `block_size` in [host-chain.nightfall_proposer] nightfall.toml. + +------ +****** +______ +## Troubleshooting +```sh +[ ERROR alloy_transport_ws::native] +WS connection error +WebSocket protocol error: Connection reset without closing handshake +``` +This error is related to a temporary host chain RPC WebSocket connection issue. +Nightfall automatically handles recovery by restarting the affected service and re-establishing the connection. No user action is required. \ No newline at end of file diff --git a/doc/nf_4.md b/doc/nf_4.md index 073a97ce..077876a6 100644 --- a/doc/nf_4.md +++ b/doc/nf_4.md @@ -471,10 +471,10 @@ curl -i \ -H 'Content-Type: application/json' \ -X POST 'http://localhost:3000/v1/deposit' \ --data-raw '{ - "ercAddress": "0x5FbDB2315678afecb367f032d93F642f64180aa3", + "ercAddress": "0x6d30362C7e36404646b403876bAAEc3Cb5d689ca", "tokenId": "0x00", "tokenType": "0", - "value": "0x04", + "value": "0x01", "fee": "0x02", "deposit_fee": "0x05" }' @@ -818,8 +818,9 @@ This endpoint will rotate the proposers if the current `proposer` has been activ POST /v1/register ```sh -curl -i --request POST 'http://localhost:3000/v1/register' \ - --json '{ "http://example.com" }' +curl -i -X POST http://localhost:3001/v1/register \ + -H "Content-Type: application/json" \ + -d '"http://example.com"' ``` Returns: on success `200 OK` diff --git a/docker-compose.yml b/docker-compose.yml index 5ea6b09a..ea2969fc 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -75,13 +75,13 @@ services: condition: service_healthy tty: true # required for logs to print in colour environment: - - NF4_RUN_MODE=${NF4_RUN_MODE:-base_sepolia} + - NF4_RUN_MODE=${NF4_RUN_MODE:-sepolia} - RUST_BACKTRACE=${RUST_BACKTRACE:-0} - NF4_SIGNING_KEY=${CLIENT_SIGNING_KEY} - NF4_NIGHTFALL_CLIENT__DB_URL=mongodb://nf4_db_client:27017 - NF4_ETHEREUM_CLIENT_URL - NF4_MOCK_PROVER=${NF4_MOCK_PROVER:-false} - - NF4_NIGHTFALL_PROPOSER__URL=${NF4_NIGHTFALL_PROPOSER__URL:-localhost:3001} + - NF4_NIGHTFALL_PROPOSER__URL=${NF4_NIGHTFALL_PROPOSER__URL:-http://35.225.105.10:3001} client2: container_name: nf4_client2 @@ -208,7 +208,7 @@ services: stdin_open: true # keep stdin open, so we can print things in docker compose up tty: true # required for logs to print in colour environment: - - NF4_RUN_MODE=${NF4_RUN_MODE:-base_sepolia} + - NF4_RUN_MODE=${NF4_RUN_MODE:-sepolia} - RUST_BACKTRACE=${RUST_BACKTRACE:-0} - NF4_SIGNING_KEY=${PROPOSER_SIGNING_KEY} - NF4_MOCK_PROVER=${NF4_MOCK_PROVER:-false} @@ -282,8 +282,8 @@ services: - "27017:27017" networks: - nightfall_network - # volumes: - # - mongodb_client_data:/data/db + volumes: + - mongodb_client_data:/data/db environment: - NF4_RUN_MODE=${NF4_RUN_MODE:-development} @@ -418,10 +418,18 @@ services: volumes: - ./blockchain_assets/test_contracts:/test_contracts - ./blockchain_assets/logs:/app/blockchain_assets/logs # to be able to see deployed contract addresses locally + - type: volume + source: key_data + target: /app/configuration/bin/keys + read_only: false + - type: volume + source: toml_data + target: /app/configuration/toml + read_only: false stdin_open: true # keep stdin open, so we can print things in docker compose up tty: true # required for logs to print in colour environment: - - NF4_RUN_MODE=${NF4_RUN_MODE:-base_sepolia} + - NF4_RUN_MODE=${NF4_RUN_MODE:-sepolia} - NF4_CONTRACTS__DEPLOY_CONTRACTS=${NF4_CONTRACTS__DEPLOY_CONTRACTS:-true} - RUST_BACKTRACE=${RUST_BACKTRACE:-0} - NF4_SIGNING_KEY=${DEPLOYER_SIGNING_KEY} @@ -440,15 +448,19 @@ services: build: dockerfile: configuration/Dockerfile context: . - # restart: unless-stopped - # ports: - # - "8080:80" replace with a port that is exposed for configuration service if required + restart: unless-stopped + ports: + - "8080:80" # replace with a port that is exposed for configuration service if required platform: linux/amd64 # Required for building on M1 Macs volumes: - - type: bind - source: ./configuration/toml + - type: volume + source: toml_data target: /var/www/html/configuration/toml - read_only: false + read_only: true + - type: volume + source: key_data + target: /var/www/html/configuration/bin/keys + read_only: true networks: - nightfall_network stdin_open: true # keep stdin open, so we can print things in docker compose up @@ -562,10 +574,13 @@ services: condition: service_healthy volumes: - # mongodb_client_data: + mongodb_client_data: # mongodb_client2_data: - # mongodb_proposer_data: + mongodb_proposer_data: address_data: + key_data: + toml_data: + networks: nightfall_network: diff --git a/lib/src/circuit_key_generation.rs b/lib/src/circuit_key_generation.rs index c41a1e95..d7e46992 100644 --- a/lib/src/circuit_key_generation.rs +++ b/lib/src/circuit_key_generation.rs @@ -42,10 +42,12 @@ pub fn universal_setup_for_production( .as_path() .join("configuration"); // Download perpetual powers of Tau file if not cached locally, then extract a KZG structured reference string from cached setup if it exists, otherwise create it - let ptau_file = path.join(format!("bin/ppot_{max_kzg_degree}.ptau")); + let ptau_file = path.join(format!("bin/trusted_setup/ppot_{max_kzg_degree}.ptau")); UnivariateKzgPCS::download_ptau_file_if_needed(max_kzg_degree, &ptau_file) .expect("Failed to download ptau file"); - let cache_file = path.join(format!("bin/bn254_setup_{max_kzg_degree}.cache")); + let cache_file = path.join(format!( + "bin/trusted_setup/bn254_setup_{max_kzg_degree}.cache" + )); UnivariateKzgPCS::universal_setup_bn254_cached(&ptau_file, 1 << max_kzg_degree, &cache_file) } diff --git a/lib/src/error.rs b/lib/src/error.rs index 57e57321..3f9fb8c6 100644 --- a/lib/src/error.rs +++ b/lib/src/error.rs @@ -248,6 +248,7 @@ pub enum NightfallContractError { TransactionNotFound(alloy::primitives::TxHash), AbiDecodeError(String), DecodedCallError(String), + X509Error(String), } impl Display for NightfallContractError { @@ -265,6 +266,7 @@ impl Display for NightfallContractError { write!(f, "Did not receive a transaction receipt") } NightfallContractError::EscrowError(s) => write!(f, "Escrow Funds Error: {s}"), + NightfallContractError::X509Error(s) => write!(f, "X509 certificate Error: {s}"), NightfallContractError::ContractVerificationError(s) => { write!(f, "Contract Verification Error: {s}") } diff --git a/lib/src/lib.rs b/lib/src/lib.rs index 8598cfde..579cb18c 100644 --- a/lib/src/lib.rs +++ b/lib/src/lib.rs @@ -11,6 +11,7 @@ pub mod error; pub mod health_check; pub mod hex_conversion; pub mod keys; +pub mod log_fetcher; pub mod merkle_trees; pub mod models; pub mod nf_client_proof; diff --git a/lib/src/log_fetcher.rs b/lib/src/log_fetcher.rs new file mode 100644 index 00000000..7fd782a4 --- /dev/null +++ b/lib/src/log_fetcher.rs @@ -0,0 +1,331 @@ +//! Paginated log fetching utilities for robust multi-chain event retrieval. +//! +//! This module provides utilities to fetch blockchain logs with automatic pagination +//! to handle RPC provider block range limits gracefully. + +use alloy::providers::Provider; +use alloy::rpc::types::{Filter, Log}; +use configuration::settings::get_settings; +use log::{debug, info, warn}; +use std::error::Error; +use std::fmt; + +/// Error type for log fetching operations. +#[derive(Debug)] +pub enum LogFetchError { + /// RPC provider returned an error + ProviderError(String), + /// Block range exceeds provider limits even after reduction + BlockRangeTooLarge, + /// Query returned too many results + TooManyResults, +} + +impl fmt::Display for LogFetchError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + LogFetchError::ProviderError(msg) => write!(f, "Provider error: {msg}"), + LogFetchError::BlockRangeTooLarge => { + write!(f, "Block range exceeds provider limits") + } + LogFetchError::TooManyResults => { + write!(f, "Query returned too many results") + } + } + } +} + +impl Error for LogFetchError {} + +/// Returns the optimal chunk size for log queries based on the current chain configuration. +/// +/// The chunk size is determined in the following order: +/// 1. Explicit `log_chunk_size` from config (if set) +/// 2. Known defaults for common chain IDs +/// 3. A safe fallback of 5,000 blocks +/// +/// # Examples +/// +/// ```ignore +/// let chunk_size = get_log_chunk_size(); +/// // For Anvil (chain_id 31337): returns u64::MAX (unlimited) +/// // For Base Sepolia (chain_id 84532): returns 10,000 +/// // For Ethereum mainnet (chain_id 1): returns 5,000 +/// ``` +pub fn get_log_chunk_size() -> u64 { + let settings = get_settings(); + + // 1. Try config-specified chunk size first + if let Some(chunk) = settings.log_chunk_size { + log::info!( + "Using configured log_chunk_size: {chunk} (chain_id: {})", + settings.network.chain_id + ); + return chunk; + } + + // 2. Fall back to known defaults by chain ID + let chunk_size = match settings.network.chain_id { + // Local development - no limits + 31337 => u64::MAX, + + // Ethereum mainnet & testnets + 1 | 5 | 11155111 => 5_000, + + // Polygon, Mumbai, Amoy + 137 | 80001 | 80002 => 3_000, + + // BSC & BSC Testnet + 56 | 97 => 5_000, + + // Arbitrum One & Sepolia + 42161 | 421614 => 10_000, + + // Optimism & Sepolia + 10 | 11155420 => 10_000, + + // Base & Base Sepolia + 8453 | 84532 => 10_000, + + // Avalanche C-Chain & Fuji + 43114 | 43113 => 100_000, + + // Gnosis & Cronos + 100 | 25 => 10_000, + + // Plume mainnet + 98866 => 100, + + // Plume testnet + 98867 => 1_000, + + // Safe default for unknown chains + _ => 5_000, + }; + + if chunk_size == u64::MAX { + debug!( + "Using chain-id default log_chunk_size: unlimited (chain_id: {})", + settings.network.chain_id + ); + } else { + debug!( + "Using chain-id default log_chunk_size: {} (chain_id: {})", + chunk_size, settings.network.chain_id + ); + } + chunk_size +} + +/// Returns the genesis block number from configuration. +/// +/// This should be used instead of hardcoding `0` for event queries. +#[inline] +pub fn get_genesis_block() -> u64 { + get_settings().genesis_block as u64 +} + +/// Returns the max RPC calls per second (0 = unlimited). +#[inline] +pub fn get_rpc_rate_limit() -> u32 { + get_settings().rpc_rate_limit +} + +/// Fetches logs with automatic pagination for large block ranges. +/// +/// This function handles RPC provider block range limits by splitting large queries +/// into smaller chunks. It uses adaptive retry with reduced chunk sizes when +/// encountering "block range too large" or "too many results" errors. +/// +/// # Arguments +/// +/// * `provider` - The blockchain provider to query +/// * `base_filter` - Base filter with address and event signatures (block range will be overwritten) +/// * `from_block` - Starting block number (inclusive) +/// * `to_block` - Ending block number (inclusive) +/// +/// # Returns +/// +/// A vector of all logs matching the filter across the specified block range. +pub async fn get_logs_paginated( + provider: &P, + base_filter: Filter, + from_block: u64, + to_block: u64, +) -> Result, LogFetchError> { + // Short-circuit if range is empty or invalid + if from_block > to_block { + return Ok(Vec::new()); + } + + let initial_chunk_size = get_log_chunk_size(); + + // If chunk size is unlimited (local dev), try single query first + if initial_chunk_size == u64::MAX { + debug!( + "Chunk size is unlimited - fetching all logs in single query (blocks {from_block} to {to_block})" + ); + let filter = base_filter + .clone() + .from_block(from_block) + .to_block(to_block); + + return provider + .get_logs(&filter) + .await + .map_err(|e| LogFetchError::ProviderError(e.to_string())); + } + + let total_blocks = to_block.saturating_sub(from_block) + 1; + let estimated_chunks_initial = total_blocks.div_ceil(initial_chunk_size); + log::info!( + "Fetching logs: blocks {from_block} to {to_block} ({total_blocks} blocks, chunk_size: {initial_chunk_size}, ~{estimated_chunks_initial} chunks)" + ); + + let mut all_logs = Vec::new(); + let mut current_from = from_block; + let mut chunk_size = initial_chunk_size; + let min_chunk_size = 1u64; + let mut chunk_count = 0u64; + let mut rate_limit_retries = 0u32; + let max_rate_limit_retries = 5; + + // Rate limiting: calculate delay between calls if rate limit is set + let rpc_rate_limit = get_rpc_rate_limit(); + let delay_between_calls = if rpc_rate_limit > 0 { + Some(std::time::Duration::from_secs_f64( + 1.0 / rpc_rate_limit as f64, + )) + } else { + None + }; + + if let Some(delay) = delay_between_calls { + log::info!( + "RPC rate limit: {rpc_rate_limit} calls/sec (delay: {}ms per call)", + delay.as_millis() + ); + } + + let mut last_call_time = std::time::Instant::now(); + + while current_from <= to_block { + chunk_count += 1; + let current_to = current_from.saturating_add(chunk_size - 1).min(to_block); + + let remaining_blocks = to_block.saturating_sub(current_from) + 1; + let estimated_remaining_chunks = remaining_blocks.div_ceil(chunk_size); + let estimated_total_chunks = chunk_count.saturating_sub(1) + estimated_remaining_chunks; + + let filter = base_filter + .clone() + .from_block(current_from) + .to_block(current_to); + + // Log progress every chunk to track progress + info!( + "[Chunk {chunk_count}/~{estimated_total_chunks}] Fetching logs: blocks {current_from} to {current_to} (chunk_size: {chunk_size})" + ); + + // Rate limiting: wait if needed before making the RPC call + if let Some(delay) = delay_between_calls { + let elapsed = last_call_time.elapsed(); + if elapsed < delay { + tokio::time::sleep(delay - elapsed).await; + } + } + + match provider.get_logs(&filter).await { + Ok(logs) => { + let logs_in_chunk = logs.len(); + let total_so_far = all_logs.len() + logs_in_chunk; + all_logs.extend(logs); + info!("[Chunk {chunk_count}] Retrieved {logs_in_chunk} logs (total so far: {total_so_far})"); + current_from = current_to.saturating_add(1); + last_call_time = std::time::Instant::now(); + } + Err(e) => { + let error_msg = e.to_string().to_lowercase(); + warn!("RPC error (will retry): {error_msg}"); + + if is_rate_limit_error(&error_msg) { + rate_limit_retries += 1; + if rate_limit_retries > max_rate_limit_retries { + warn!( + "Rate limited {rate_limit_retries} times, giving up after {max_rate_limit_retries} retries" + ); + return Err(LogFetchError::ProviderError(e.to_string())); + } + + // Exponential backoff: 2s, 4s, 8s, 16s, 32s + let backoff_secs = 2u64.pow(rate_limit_retries.min(5)); + warn!( + "Rate limited by RPC provider (attempt {rate_limit_retries}/{max_rate_limit_retries}), waiting {backoff_secs}s before retry..." + ); + tokio::time::sleep(std::time::Duration::from_secs(backoff_secs)).await; + // Continue without reducing chunk size - retry same request + } else if is_range_error(&error_msg) || is_result_limit_error(&error_msg) { + // Reduce chunk size by half and retry + let new_chunk_size = chunk_size.saturating_div(2).max(min_chunk_size); + + if new_chunk_size == min_chunk_size && chunk_size == min_chunk_size { + // Already at minimum and still failing - this is an RPC limitation + warn!( + "Chunk size already at minimum {min_chunk_size} and still failing - RPC provider block range limit is too restrictive" + ); + return Err(if is_result_limit_error(&error_msg) { + LogFetchError::TooManyResults + } else { + LogFetchError::BlockRangeTooLarge + }); + } + + warn!( + "Reducing chunk size from {chunk_size} to {new_chunk_size} due to RPC limit" + ); + chunk_size = new_chunk_size; + // Add delay to avoid rate limiting + tokio::time::sleep(std::time::Duration::from_millis(500)).await; + // Don't advance current_from, retry with smaller chunk + } else { + // Unknown error, propagate it + return Err(LogFetchError::ProviderError(e.to_string())); + } + } + } + } + + let total_logs = all_logs.len(); + debug!( + "Pagination complete: {total_logs} total logs fetched across {chunk_count} chunks (initial chunk_size: {initial_chunk_size}, final chunk_size: {chunk_size})" + ); + Ok(all_logs) +} + +/// Checks if an error message indicates a block range limit was exceeded. +fn is_range_error(msg: &str) -> bool { + msg.contains("block range") + || msg.contains("range too large") + || msg.contains("block range limit") + || msg.contains("too wide") + || msg.contains("query timeout") + || msg.contains("10 block range") + || msg.contains("10 block") + || msg.contains("超出") +} + +/// Checks if an error message indicates too many results were returned. +fn is_result_limit_error(msg: &str) -> bool { + msg.contains("10000 results") + || msg.contains("too many") + || msg.contains("response size") + || msg.contains("limit exceeded") +} + +/// Checks if an error message indicates a rate limit (429) +fn is_rate_limit_error(msg: &str) -> bool { + msg.contains("rate limit") + || msg.contains("429") + || msg.contains("too many requests") + || msg.contains("throttl") +} diff --git a/lib/src/plonk_prover/mod.rs b/lib/src/plonk_prover/mod.rs index 5fea6645..5755a847 100644 --- a/lib/src/plonk_prover/mod.rs +++ b/lib/src/plonk_prover/mod.rs @@ -2,9 +2,12 @@ pub mod circuit_builder; pub mod circuits; pub mod plonk_proof; +use crate::rollup_circuit_checks::get_configuration_keys_path; +use crate::utils::load_key_locally; use crate::{rollup_circuit_checks::find_file_with_path, utils::load_key_from_server}; use ark_bn254::Bn254; use ark_serialize::CanonicalDeserialize; +use ark_std::path::PathBuf; use jf_plonk::nightfall::ipa_structs::ProvingKey; use jf_primitives::pcs::prelude::UnivariateKzgPCS; use log::warn; @@ -12,12 +15,28 @@ use std::{ path::Path, sync::{Arc, OnceLock}, }; +use warp::path; /// This function is used to retrieve the client proving key. pub fn get_client_proving_key() -> &'static Arc>> { static PK: OnceLock>>> = OnceLock::new(); PK.get_or_init(|| { // We'll try to load from the configuration server first. + let clienpatht_pk_path = get_configuration_keys_path() + .expect("Configuration keys path not found") + .join("proving_key"); + let source_file = find_file_with_path(&clienpatht_pk_path).expect("Could not find path"); + + if let Some(_key_bytes) = load_key_locally(&source_file) { + let proving_key = + ProvingKey::>::deserialize_compressed_unchecked( + &*std::fs::read(source_file).expect("Could not read proving key"), + ) + .expect("Could not deserialise proving key"); + return Arc::new(proving_key); + } + warn!("Could not load proving_key from local file. Loading from server"); + if let Some(key_bytes) = load_key_from_server("proving_key") { let pk = ProvingKey::>::deserialize_compressed_unchecked( &*key_bytes, @@ -25,14 +44,6 @@ pub fn get_client_proving_key() -> &'static Arc>::deserialize_compressed_unchecked( - &*std::fs::read(source_file).expect("Could not read proving key"), - ) - .expect("Could not deserialise proving key"); - Arc::new(pk) + panic!("Failed to load proving_key from both local and server"); }) } diff --git a/lib/src/rollup_circuit_checks.rs b/lib/src/rollup_circuit_checks.rs index 0c948ba9..5b258a9e 100644 --- a/lib/src/rollup_circuit_checks.rs +++ b/lib/src/rollup_circuit_checks.rs @@ -39,11 +39,25 @@ pub fn get_configuration_path() -> Option { } } +/// Function that starts at the current working directory and returns the path to the configuration/keys folder for all the keys needed for proving. +pub fn get_configuration_keys_path() -> Option { + let mut cwd = env::current_dir().ok()?; + loop { + let file_path = cwd.join("configuration/bin/keys"); + if file_path.is_dir() { + return Some(file_path); + } + + cwd = cwd.parent()?.to_path_buf(); + } +} + /// Function that retrieves the client proving key from a local file. pub fn get_client_proving_key_locally() -> Result>> { - let client_pk_path = Path::new("./configuration/bin/proving_key"); - - let source_file = find_file_with_path(client_pk_path).with_context(|| { + let client_pk_path = get_configuration_keys_path() + .expect("Configuration keys path not found") + .join("proving_key"); + let source_file = find_file_with_path(&client_pk_path).with_context(|| { format!( "Could not find proving key file at path: {}", client_pk_path.display() @@ -63,9 +77,10 @@ pub fn get_client_proving_key_locally() -> Result Result>> { - let deposit_pk_path = Path::new("./configuration/bin/deposit_proving_key"); - - let source_file = find_file_with_path(deposit_pk_path).with_context(|| { + let deposit_pk_path = get_configuration_keys_path() + .expect("Configuration keys path not found") + .join("deposit_proving_key"); + let source_file = find_file_with_path(&deposit_pk_path).with_context(|| { format!( "Could not find deposit proving key file at path: {}", deposit_pk_path.display() @@ -398,8 +413,8 @@ impl RecursiveProver for RollupKeyGenerator { } fn store_base_grumpkin_pk(pk: MLEProvingKey) -> Option<()> { - let config_path = get_configuration_path()?; - let file_path = config_path.join("bin/base_grumpkin_pk"); + let config_path = get_configuration_keys_path()?; + let file_path = config_path.join("base_grumpkin_pk"); let mut buf = Vec::::new(); pk.serialize_compressed(&mut buf).ok()?; @@ -409,8 +424,8 @@ impl RecursiveProver for RollupKeyGenerator { } fn store_base_bn254_pk(pk: ProvingKey) -> Option<()> { - let config_path = get_configuration_path()?; - let file_path = config_path.join("bin/base_bn254_pk"); + let config_path = get_configuration_keys_path()?; + let file_path = config_path.join("base_bn254_pk"); let mut buf = Vec::::new(); pk.serialize_compressed(&mut buf).ok()?; @@ -420,9 +435,9 @@ impl RecursiveProver for RollupKeyGenerator { } fn store_merge_grumpkin_pks(pks: Vec>) -> Option<()> { - let config_path = get_configuration_path()?; + let config_path = get_configuration_keys_path()?; for (i, pk) in pks.into_iter().enumerate() { - let file_path = config_path.join(format!("bin/merge_grumpkin_pk_{i}")); + let file_path = config_path.join(format!("merge_grumpkin_pk_{i}")); let mut buf = Vec::::new(); pk.serialize_compressed(&mut buf).ok()?; @@ -435,9 +450,9 @@ impl RecursiveProver for RollupKeyGenerator { } fn store_merge_bn254_pks(pks: Vec>) -> Option<()> { - let config_path = get_configuration_path()?; + let config_path = get_configuration_keys_path()?; for (i, pk) in pks.into_iter().enumerate() { - let file_path: PathBuf = config_path.join(format!("bin/merge_bn254_pk_{i}")); + let file_path: PathBuf = config_path.join(format!("merge_bn254_pk_{i}")); let mut buf = Vec::::new(); pk.serialize_compressed(&mut buf).ok()?; // serialize the proving key @@ -450,8 +465,8 @@ impl RecursiveProver for RollupKeyGenerator { } fn store_decider_pk(pk: PlonkProvingKey) -> Option<()> { - let config_path = get_configuration_path()?; - let file_path = config_path.join("bin/decider_pk"); + let config_path = get_configuration_keys_path()?; + let file_path = config_path.join("decider_pk"); let mut buf = Vec::::new(); pk.serialize_compressed(&mut buf).ok()?; @@ -461,11 +476,16 @@ impl RecursiveProver for RollupKeyGenerator { } fn store_decider_vk(vk: &PlonkVerifyingKey) { - let path = get_configuration_path().unwrap().join("bin/decider_vk"); - let mut file = File::create(path).unwrap(); + let path = get_configuration_keys_path() + .expect("Failed to get path for configuration keys") + .join("decider_vk"); + let mut file = + File::create(path).expect("Failed to create path configuration/bin/keys/decider_vk"); let mut compressed_bytes = Vec::new(); - vk.serialize_compressed(&mut compressed_bytes).unwrap(); - file.write_all(&compressed_bytes).unwrap(); + vk.serialize_compressed(&mut compressed_bytes) + .expect("Failed to serialize vk"); + file.write_all(&compressed_bytes) + .expect("Failed to write vk into configuration/bin/keys/decider_vk"); } fn generate_vk_check_constraint( diff --git a/lib/src/utils.rs b/lib/src/utils.rs index a7275cec..f01ab251 100644 --- a/lib/src/utils.rs +++ b/lib/src/utils.rs @@ -1,17 +1,18 @@ -use std::{fmt, time::Duration}; - +use crate::error::ConfigError; +use alloy_rlp::BytesMut; +use ark_std::fs; +use ark_std::path::PathBuf; /// A module containing uncategorised functions used by more than one component use configuration::settings::get_settings; use futures::StreamExt; use log::{debug, info, warn}; use serde::ser::StdError; -use tokio::{runtime::Handle, task::block_in_place}; -use tokio_util::bytes::BytesMut; +use std::{fmt, time::Duration}; +use tokio::runtime::Handle; +use tokio::task::block_in_place; use url::Url; use warp::hyper::body::Bytes; -use crate::error::ConfigError; - // log progress every 100 MB during key downloads const DOWNLOAD_PROGRESS_LOG_INTERVAL_BYTES: u64 = 100 * 1024 * 1024; @@ -144,6 +145,23 @@ pub fn load_key_from_server(key_file: &str) -> Option { None } +/// function to load the key locally as a byte array +/// Our logic is that proposer should either generated keys or load from server before up the service. So when it's proving it should read keys locally, this is to ensure using correct keys when proposer decides to increase block size which is different from what deployer has used during its key generation. +pub fn load_key_locally(source_file: &PathBuf) -> Option { + if Handle::try_current().is_err() { + return None; + } + + // Check if file exists + if !source_file.exists() { + return None; + } + + // Read file safely + let data = fs::read(source_file).ok()?; + Some(Bytes::from(data)) +} + /// function to drop a database pub async fn drop_database(db_url: &str, db_name: &str) -> Result<(), mongodb::error::Error> { let client = mongodb::Client::with_uri_str(db_url).await?; diff --git a/lib/src/validate_certificate.rs b/lib/src/validate_certificate.rs index 7ad17033..60079e0c 100644 --- a/lib/src/validate_certificate.rs +++ b/lib/src/validate_certificate.rs @@ -1,11 +1,14 @@ use super::models::CertificateReq; +use crate::error::NightfallContractError; use crate::{ blockchain_client::BlockchainClientConnection, error::CertificateVerificationError, initialisation::get_blockchain_client_connection, models::bad_request, verify_contract::VerifiedContracts, }; use alloy::primitives::{Address, U256}; +use alloy::providers::Provider; use configuration::addresses::get_addresses; +use configuration::settings::get_settings; use futures::stream::TryStreamExt; use log::{debug, error, trace, warn}; use nightfall_bindings::artifacts::X509; @@ -123,6 +126,7 @@ pub async fn handle_certificate_validation( error!("Failed to get chain ID: {e}"); warp::reject::custom(CertificateVerificationError::new("Failed to get chain ID")) })?; + ark_std::println!("way 1 get chain id:{}", chain_id); if let Err(e) = prevalidate_certificate_and_key( &certificate_req.certificate, @@ -176,32 +180,9 @@ pub async fn handle_certificate_validation( } }; - // 4) READ-ONLY validation first (no state change). Treat any error as "not certified". - let is_end_user = true; // end-entity certs coming from clients/proposers - let check_only = true; - - if let Err(err) = validate_certificate( - certificate_req.certificate.clone(), - ethereum_address_signature.clone(), - is_end_user, - check_only, // read-only - 0, - requestor_address, - ) - .await - { - error!("Read-only certificate validation failed: {err}"); - let body = warp::reply::json(&serde_json::json!({ - "status": "ok", - "certified": false - })); - return Ok(warp::reply::with_status(body, StatusCode::ACCEPTED)); - } - - // 5) ENROLL (state-changing): write the binding on-chain and await receipt. - // We want one API that validates AND enrolls, so we do the write: + // 4) ENROLL (state-changing): write the binding on-chain and await receipt. let check_only = false; - + let is_end_user = true; // end-entity certs coming from clients/proposers if let Err(err) = validate_certificate( certificate_req.certificate.clone(), ethereum_address_signature, @@ -217,7 +198,7 @@ pub async fn handle_certificate_validation( warn!("Enroll (write) failed: {err}"); } - // 6) Return POST-STATE truth from chain + // 5) Return POST-STATE truth from chain let is_certified_now = x509_instance .x509Check(requestor_address) .call() @@ -247,7 +228,6 @@ async fn validate_certificate( let read_connection = get_blockchain_client_connection().await.read().await; let provider = read_connection.get_client(); let blockchain_client = provider.root(); - let caller = read_connection.get_address(); let verified = VerifiedContracts::resolve_and_verify_contract(blockchain_client.clone(), get_addresses()) .await @@ -273,17 +253,66 @@ async fn validate_certificate( addr: sender_address, }; - let tx_receipt = x509_instance - .validateCertificate(certificate_args) - .from(caller) - .send() + let signer = get_blockchain_client_connection() + .await + .read() + .await + .get_signer(); + + let nonce = blockchain_client + .get_transaction_count(signer.address()) + .await + .map_err(|e| NightfallContractError::X509Error(format!("Transaction unsuccesful: {e}")))?; + let gas_price = blockchain_client + .get_gas_price() + .await + .map_err(|e| NightfallContractError::X509Error(format!("Transaction unsuccesful: {e}")))?; + let max_fee_per_gas = gas_price * 2; + let max_priority_fee_per_gas = gas_price; + let gas_limit = 16777216u64; + + ark_std::println!("way 2 get chain id:{}", get_settings().network.chain_id); + + let call = x509_instance + .validateCertificate(certificate_args.clone()) + .nonce(nonce) + .gas(gas_limit) + .max_fee_per_gas(max_fee_per_gas) + .max_priority_fee_per_gas(max_priority_fee_per_gas) + .chain_id(get_settings().network.chain_id) // Linea testnet chain ID + .build_raw_transaction((*signer).clone()) .await .map_err(|e| { - warn!("{e}"); - X509ValidationError + NightfallContractError::EscrowError(format!("Transaction unsuccesful: {e}")) })?; - if tx_receipt.get_receipt().await.is_err() { - error!("X509Validation transaction failed"); + + let tx_receipt = blockchain_client + .send_raw_transaction(&call) + .await + .map_err(|e| NightfallContractError::EscrowError(format!("Error getting receipt: {e}")))? + .get_receipt() + .await + .map_err(|e| { + NightfallContractError::EscrowError(format!("Transaction unsuccesful: {e}")) + })?; + ark_std::println!("x509 tx receipt: {:?}", tx_receipt); + + // let tx_receipt = x509_instance + // .validateCertificate(certificate_args.clone()) + // .from(caller) + // .send() + // .await + // .map_err(|e| { + // warn!("{e}"); + // X509ValidationError + // })?; + // if tx_receipt.get_receipt().await.is_err() { + // error!("X509Validation transaction failed"); + // return Err(Box::new(X509ValidationError)); + // } + + if !tx_receipt.status() { + // error!("validateCertificate revert (sim): {e:?}"); return Err(Box::new(X509ValidationError)); } Ok(()) @@ -306,7 +335,7 @@ pub fn sign_ethereum_address( let mut key_material = PrivateKeyMaterial { key: der_private_key.to_vec(), }; - + let private_key = Rsa::private_key_from_der(&key_material.key)?; let pkey = PKey::from_rsa(private_key)?; diff --git a/lib/src/validate_keys.rs b/lib/src/validate_keys.rs index 826b5458..22e27bec 100644 --- a/lib/src/validate_keys.rs +++ b/lib/src/validate_keys.rs @@ -74,8 +74,8 @@ fn default_concurrency() -> usize { /// Specification for each key to be validated struct KeySpec { name: String, // e.g., "decider_pk" - url: String, // e.g., "{configuration_url}/decider_pk" - out_path: PathBuf, // e.g., "configuration/bin/decider_pk" + url: String, // e.g., "{configuration_url}/bin/keys/decider_pk" + out_path: PathBuf, // e.g., "configuration/bin/keys/decider_pk" } #[derive(Debug, Clone, serde::Serialize)] @@ -159,7 +159,7 @@ async fn handle_keys_validation(params: FormParams) -> Result anyhow::Result Result<(), warp::Rejection> { )) })?; - let deposit_pk_path = path.join("bin/deposit_proving_key"); - let pk_path = path.join("bin/proving_key"); + let deposit_pk_path = path.join("bin/keys/deposit_proving_key"); + let pk_path = path.join("bin/keys/proving_key"); let mut deposit_file = File::create(deposit_pk_path.clone()).map_err(|e| { error!("Failed to create deposit proving key file: {e}"); @@ -932,7 +932,7 @@ fn delete_existing_key_files( error!("{error_msg}"); return Err(warp::reject::custom(KeyVerificationError::new(&error_msg))); } - let bin_path = base_path.join("configuration/bin"); + let bin_path = base_path.join("configuration/bin/keys"); if !bin_path.exists() { let error_msg = format!( "Bin directory '{}' does not exist - cannot clean up key files", @@ -954,7 +954,9 @@ fn delete_existing_key_files( })?; } } - let ppot_file_path = base_path.join(format!("configuration/bin/ppot_{MAX_KZG_DEGREE}.ptau")); + let ppot_file_path = base_path.join(format!( + "configuration/bin/trusted_setup/ppot_{MAX_KZG_DEGREE}.ptau" + )); if ppot_file_path.exists() { std::fs::remove_file(ppot_file_path.clone()).map_err(|e| { error!( @@ -979,7 +981,7 @@ mod tests { fn test_delete_existing_key_files() { // Create a temporary directory structure let temp_dir = std::env::temp_dir().join("test_key_deletion"); - std::fs::create_dir_all(temp_dir.join("configuration/bin")) + std::fs::create_dir_all(temp_dir.join("configuration/bin/keys")) .unwrap_or_else(|e| panic!("Failed to create test directory structure: {e:?}")); let merge_counts = merge_counts( @@ -1009,7 +1011,7 @@ mod tests { // Create the static test files for file in &static_test_files { - let file_path = temp_dir.join("configuration/bin").join(file); + let file_path = temp_dir.join("configuration/bin/keys").join(file); std::fs::write(&file_path, b"test_key_data") .unwrap_or_else(|e| panic!("Failed to write test key file '{file}': {e:?}")); assert!(file_path.exists(), "Test file should be created: {file}"); @@ -1018,13 +1020,13 @@ mod tests { // Also create some files that should NOT be deleted (to ensure we're selective) let preserve_files = vec!["other_file.txt", "config.toml"]; for file in &preserve_files { - let file_path = temp_dir.join("configuration/bin").join(file); + let file_path = temp_dir.join("configuration/bin/keys").join(file); std::fs::write(&file_path, b"preserve_me") .unwrap_or_else(|e| panic!("Failed to write preserve file '{file}': {e:?}")); } // Get the KeySpecs - let out_dir = PathBuf::from("configuration").join("bin"); + let out_dir = PathBuf::from("configuration").join("bin/keys"); let specs = build_key_specs("http://example.com/configuration", &out_dir) .unwrap_or_else(|e| panic!("Failed to build key specs: {e:?}")); @@ -1038,7 +1040,7 @@ mod tests { // Verify that all static key files are deleted for file in &static_test_files { - let file_path = temp_dir.join("configuration/bin").join(file); + let file_path = temp_dir.join("configuration/bin/keys").join(file); assert!( !file_path.exists(), "Static key file should be deleted: {file}" @@ -1047,7 +1049,7 @@ mod tests { // Verify that non-key files are preserved for file in &preserve_files { - let file_path = temp_dir.join("configuration/bin").join(file); + let file_path = temp_dir.join("configuration/bin/keys").join(file); assert!( file_path.exists(), "Non-key file should be preserved: {file}", @@ -1061,7 +1063,7 @@ mod tests { #[test] fn test_delete_existing_key_files_nonexistent_directory() { // Get the KeySpecs - let out_dir = PathBuf::from("configuration").join("bin"); + let out_dir = PathBuf::from("configuration").join("bin/keys"); let specs = build_key_specs("http://example.com/configuration", &out_dir) .unwrap_or_else(|e| panic!("Failed to build key specs: {e:?}")); @@ -1080,7 +1082,7 @@ mod tests { #[test] fn test_delete_existing_key_files_missing_bin_directory() { // Get the KeySpecs - let out_dir = PathBuf::from("configuration").join("bin"); + let out_dir = PathBuf::from("configuration").join("bin/keys"); let specs = build_key_specs("http://example.com/configuration", &out_dir) .unwrap_or_else(|e| panic!("Failed to build key specs: {e:?}")); @@ -1104,19 +1106,19 @@ mod tests { #[test] fn test_delete_existing_key_files_partial_files() { // Get the KeySpecs - let out_dir = PathBuf::from("configuration").join("bin"); + let out_dir = PathBuf::from("configuration").join("bin/keys"); let specs = build_key_specs("http://example.com/configuration", &out_dir) .unwrap_or_else(|e| panic!("Failed to build key specs: {e:?}")); // Test with only some files existing let temp_dir = std::env::temp_dir().join("test_partial_key_deletion"); - std::fs::create_dir_all(temp_dir.join("configuration/bin")) + std::fs::create_dir_all(temp_dir.join("configuration/bin/keys")) .unwrap_or_else(|e| panic!("Failed to create test directory: {e:?}")); // Create only some of the expected files let partial_files = vec!["base_grumpkin_pk", "merge_bn254_pk_0"]; for file in &partial_files { - let file_path = temp_dir.join("configuration/bin").join(file); + let file_path = temp_dir.join("configuration/bin/keys").join(file); std::fs::write(&file_path, b"test_key_data") .unwrap_or_else(|e| panic!("Failed to write partial test file '{file}': {e:?}")); } @@ -1131,7 +1133,7 @@ mod tests { // Verify that existing files are deleted for file in &partial_files { - let file_path = temp_dir.join("configuration/bin").join(file); + let file_path = temp_dir.join("configuration/bin/keys").join(file); assert!( !file_path.exists(), "Existing key file should be deleted: {file}" @@ -1180,7 +1182,7 @@ mod tests { #[test] fn test_build_key_specs() { - let out_dir = PathBuf::from("test/bin"); + let out_dir = PathBuf::from("test/bin/keys"); let config_url = "http://example.com"; let specs = build_key_specs(config_url, &out_dir) .unwrap_or_else(|e| panic!("Failed to build key specs: {e:?}")); @@ -1192,7 +1194,7 @@ mod tests { .unwrap_or_else(|| panic!("Should have deposit_proving_key in specs: {specs:?}")); assert_eq!( deposit_proving_key.url, - format!("{config_url}/deposit_proving_key") + format!("{config_url}/bin/keys/deposit_proving_key") ); assert_eq!( deposit_proving_key.out_path, @@ -1202,7 +1204,10 @@ mod tests { .iter() .find(|s| s.name == "proving_key") .unwrap_or_else(|| panic!("Should have proving_key in specs: {specs:?}")); - assert_eq!(proving_key.url, format!("{config_url}/proving_key")); + assert_eq!( + proving_key.url, + format!("{config_url}/bin/keys/proving_key") + ); assert_eq!(proving_key.out_path, out_dir.join("proving_key")); // Should contain base keys with correct URLs and paths @@ -1210,28 +1215,34 @@ mod tests { .iter() .find(|s| s.name == "decider_pk") .unwrap_or_else(|| panic!("Should have decider_pk in specs: {specs:?}")); - assert_eq!(decider_pk.url, format!("{config_url}/decider_pk")); + assert_eq!(decider_pk.url, format!("{config_url}/bin/keys/decider_pk")); assert_eq!(decider_pk.out_path, out_dir.join("decider_pk")); let decider_vk = specs .iter() .find(|s| s.name == "decider_vk") .unwrap_or_else(|| panic!("Should have decider_vk in specs: {specs:?}")); - assert_eq!(decider_vk.url, format!("{config_url}/decider_vk")); + assert_eq!(decider_vk.url, format!("{config_url}/bin/keys/decider_vk")); assert_eq!(decider_vk.out_path, out_dir.join("decider_vk")); let base_bn254 = specs .iter() .find(|s| s.name == "base_bn254_pk") .unwrap_or_else(|| panic!("Should have base_bn254_pk in specs: {specs:?}")); - assert_eq!(base_bn254.url, format!("{config_url}/base_bn254_pk")); + assert_eq!( + base_bn254.url, + format!("{config_url}/bin/keys/base_bn254_pk") + ); assert_eq!(base_bn254.out_path, out_dir.join("base_bn254_pk")); let base_grumpkin = specs .iter() .find(|s| s.name == "base_grumpkin_pk") .unwrap_or_else(|| panic!("Should have base_grumpkin_pk in specs: {specs:?}")); - assert_eq!(base_grumpkin.url, format!("{config_url}/base_grumpkin_pk")); + assert_eq!( + base_grumpkin.url, + format!("{config_url}/bin/keys/base_grumpkin_pk") + ); assert_eq!(base_grumpkin.out_path, out_dir.join("base_grumpkin_pk")); let merge_counts = merge_counts( @@ -1258,7 +1269,7 @@ mod tests { .iter() .find(|s| s.name == name) .unwrap_or_else(|| panic!("Should have {name}")); - assert_eq!(spec.url, format!("{config_url}/{name}")); + assert_eq!(spec.url, format!("{config_url}/bin/keys/{name}")); assert_eq!(spec.out_path, out_dir.join(&name)); } } diff --git a/lib/src/verify_contract.rs b/lib/src/verify_contract.rs index 5d80194c..4a001568 100644 --- a/lib/src/verify_contract.rs +++ b/lib/src/verify_contract.rs @@ -3,7 +3,11 @@ use alloy::{ providers::Provider, }; +use configuration::addresses::validate_config_url; use configuration::addresses::Addresses; +use configuration::addresses::AddressesError; +use configuration::settings::Settings; +use eyre::eyre; use nightfall_bindings::artifacts::{Nightfall, RoundRobin, X509}; use nightfall_bindings::artifacts::{ Nightfall::NightfallInstance, RoundRobin::RoundRobinInstance, X509::X509Instance, @@ -19,17 +23,34 @@ struct ContractHashes { } /// Load deployed contract hashes from file written by deployer -fn load_deployed_hashes() -> eyre::Result<([u8; 32], [u8; 32], [u8; 32])> { +pub async fn load_deployed_hashes() -> eyre::Result<([u8; 32], [u8; 32], [u8; 32])> { let hashes_path = PathBuf::from("/app/configuration/toml/contract_hashes.toml"); - - if !hashes_path.exists() { - eyre::bail!( - "Contract hashes file not found. Deployer must run first to generate {:?}", - hashes_path - ); - } - - let content = std::fs::read_to_string(&hashes_path)?; + let settings = Settings::new().map_err(|_| AddressesError::Settings)?; + let content = if hashes_path.exists() { + std::fs::read_to_string(&hashes_path)? + } else { + // Fallback to remote configuration server + let base = validate_config_url(&settings.configuration_url) + .map_err(|e| eyre!("Invalid or untrusted configuration URL: {}", e))?; + + let url = base + .join("configuration/toml/contract_hashes.toml") + .map_err(|e| eyre!("Could not build contract hashes URL: {}", e))?; + + let response = reqwest::get(url.clone()) + .await + .map_err(|e| eyre!("Failed to fetch contract hashes from {}: {}", url, e))?; + + if !response.status().is_success() { + return Err(eyre!( + "Configuration server returned error {} for {}", + response.status(), + url + )); + } + + response.text().await? + }; let hashes: ContractHashes = toml::from_str(&content)?; let nightfall = hex::decode(&hashes.nightfall_hash) @@ -76,14 +97,14 @@ pub async fn get_proxy_implementation( provider: &P, proxy: Address, ) -> eyre::Result
{ - println!("Fetching implementation address from proxy at {proxy:?}..."); + // println!("Fetching implementation address from proxy at {proxy:?}..."); let slot = B256::from_slice(&EIP1967_IMPLEMENTATION_SLOT_BYTES); let raw: B256 = provider.get_storage_at(proxy, slot.into()).await?.into(); let mut addr = [0u8; 20]; addr.copy_from_slice(&raw[12..]); // last 20 bytes - println!("get the address {:?}...", Address::from(addr)); + // println!("get the address {:?}...", Address::from(addr)); Ok(Address::from(addr)) } @@ -100,12 +121,12 @@ fn strip_metadata_and_hash(bytecode: &[u8]) -> [u8; 32] { { // Strip everything from the metadata marker onwards let stripped = &bytecode[..pos]; - println!( - "Stripped {} bytes of metadata (original: {}, stripped: {})", - bytecode.len() - stripped.len(), - bytecode.len(), - stripped.len() - ); + // println!( + // "Stripped {} bytes of metadata (original: {}, stripped: {})", + // bytecode.len() - stripped.len(), + // bytecode.len(), + // stripped.len() + // ); keccak256(stripped).0 } else { println!("No metadata marker found, using full bytecode"); @@ -118,11 +139,11 @@ pub async fn get_onchain_code_hash( implementation: Address, ) -> eyre::Result<[u8; 32]> { let code = provider.get_code_at(implementation).await?; - println!("On-chain code length: {} bytes", code.0.len()); + // println!("On-chain code length: {} bytes", code.0.len()); // Use the same metadata stripping logic as build-time let hash = strip_metadata_and_hash(&code.0); - println!("On-chain hash (metadata stripped): {hash:?}"); + // println!("On-chain hash (metadata stripped): {hash:?}"); Ok(hash) } @@ -196,7 +217,7 @@ impl VerifiedContracts

{ ); // Load the expected hashes from the file written by deployer - let (nightfall_hash, round_robin_hash, x509_hash) = load_deployed_hashes()?; + let (nightfall_hash, round_robin_hash, x509_hash) = load_deployed_hashes().await?; // Verify each contract's deployed implementation verify_impl_hash(&provider, addresses.nightfall, &nightfall_hash, "Nightfall").await?; diff --git a/nightfall.toml b/nightfall.toml index 0c848794..14b909ca 100644 --- a/nightfall.toml +++ b/nightfall.toml @@ -3,6 +3,142 @@ # Select a configuration by setting the environment variable NF4_RUN_MODE to the desired section name, e.g. NF4_RUN_MODE="production" # +[sepolia] +signing_key = "" +azure_vault_url = "vault url is not set" +azure_key_name = "key name not set" +log_app_only = true +test_x509_certificates = true +mock_prover = false +genesis_block = 10252070 +# RPC rate limit (calls per second). 0 = unlimited. +# For Alchemy free tier: 8 calls/sec for eth_getLogs (500 CU/s / 60 CU per call) +rpc_rate_limit = 8 +ethereum_client_url = "wss://ethereum-sepolia-rpc.publicnode.com" +configuration_url = "http://35.225.105.10:8080" # The name of the proposer config to use can be overridden by env var NF4_PROPOSER_CONFIG + + +[sepolia.network] +chain_id = 11155111 + +[sepolia.nightfall_client] +url = "http://client:3000" +log_level = "info" +wallet_type = "local" +db_url = "mongodb://nf4_db_client:27017" +max_event_listener_attempts = 10 +webhook_url = "http://172.18.0.250:8080/webhook" # The webhook URL for the client to send notifications to the propose +max_queue_size = 1000 + +[sepolia.nightfall_proposer] +url = "http://35.225.105.10:3001" +log_level = "info" +wallet_type = "local" +db_url = "mongodb://nf4_db_proposer:27017" +block_assembly_max_wait_secs = 120 +block_assembly_target_fill_ratio = 0.25 +block_assembly_initial_interval_secs = 15 +max_event_listener_attempts = 10 +block_size = 64 + +[sepolia.verifier] +# VK values that the UUPS provider will initialize with +domain_size = 0x2000000 +num_inputs = 0x1 +# Sigma commitments (G1) +sigma_comms_1 = ["0x224aa1e86aa1f1befc63eb7dca0b5933e01f712d95f3a573d92a66efd4b31f60", "0x25f81419c20cd2459e03611d1a3c9339086697876a38b56351df5cb19a7f11ee"] +sigma_comms_2 = ["0xee3ddea5323d9368ed8ccbf50e47f1307ab2a8df47192678f1a9d6329d38ca7", "0x1a4d3eb6cde54c6c52f103b69e3daa37eb46eca3f2a0960df9ae6f6f2c4da8c9"] +sigma_comms_3 = ["0xed11832565538b32a2be9e70ce9eed6b09fd8dcd82e9af87320d2ab5ea1fe9f", "0x17492bbd308b64f54f6baa250c5b523f6c651f4c22210fecbe9799dcf3088d0f"] +sigma_comms_4 = ["0x12f72ea1e0b638e16534d521629b401b42653a505ce1b65bbf682c86c0e1cf3", "0x1af843eb6d58f88397a60932bf485a0215f59f320bbc53d8b6f2334f4249f0ff"] +sigma_comms_5 = ["0x13842fddc8a50704d9a464ed76b0ad1e2badd8e71a362cea8642bd43f195c9d2", "0x1f7d04850eb0775cdeacc96b4d037e22379a41bbf8ce2eb44025cd3acc8f7b45"] +sigma_comms_6 = ["0xef67b9aed33ca744b467dfe54b10588e85c69dd4e1a0ccc482dac77ca6434f4", "0x135309095418997c1acc374386206df445af8046ec0213f1c36f467629860fac"] +# Selector commitments (G1) +selector_comms_1 = ["0x21cf3183e15d395f472df27276929872fce24077b9c2ef3a2f5edc74d309fa6f", "0x23db370ed5fa8b8c069c4a138ee073ea75bf066c8197093841f337e3b5908d23"] +selector_comms_2 = ["0x21356c841d6d4fa77c776d0592feb7be7a8a5461e64a2f1c0fbf9baa261f28cb", "0x22476ebc7c5f1dbe4ccdac48262e33ee3201e62876b8e0dc6146880a98cd7b19"] +selector_comms_3 = ["0x213a4b0a0e2489ad2f44b7208fb4a72387dd92c68b03cf00fe6b137273fc6bf9", "0x1fbfc0e404f50ddc2f80a8224fa040e6ad87b653bd69692d8da8da69cc66e45e"] +selector_comms_4 = ["0x26500f9857b909578887562a24e5eeb00aa6225c3abc211d6a9948c7ad6d900b", "0x3057a638850f561e457865b2fb18e4883b4137ddaf3866eb14c3f8645244d008"] +selector_comms_5 = ["0x90c2b10408f52a49208558c48f6c9e9f1d9027a6e0714d92cd8edfeedf428b", "0x287202d8457a299381e4ef7fa8870f4187a4a99fe414bda0eb9eb213459b8032"] +selector_comms_6 = ["0x6d4d75f7f9ac52cd3ff6a00dc5432fac71b81c95c10b0b6a0cf6c6ad842f82a", "0x21b1a022d8fa08c5877fc29aae4dd10a0bee624b82ef58d9ca2bd885ecaa773c"] +selector_comms_7 = ["0x14fc4c0d862ac23877c9326b88ab6efbdef47ec62925575f07f83bcf012e2e49", "0x2a3162b250bd3f59ce9c425445447a477ab9017a1a67b056592afdd474d3693f"] +selector_comms_8 = ["0x13e081900816842f9e7b6ec2340c6b434d05d061fc72a7613239ae3674f654ee", "0x2077c4369dbb9ad5e11f8dc5c67cf91d055954043a44ff55c887b7b332e1601a"] +selector_comms_9 = ["0x8f35ec1a09b83fe7a89795eef68a71a73ea69164d17ea74e424c18a27cfd154", "0x2da03fa8184b74751c2cddd462510f77807619b5e0a5cb2269e0c2d34c550042"] +selector_comms_10 = ["0x1c980fee742192d7461f564307a8a0cdd469203d4c239c9daf7734d3e25a57af", "0x2d6c75cfc5991b321572cf1a19e0bbadbcadc790101ba3d45bd7110b8b19bdf4"] +selector_comms_11 = ["0x20e8848cb6a4ce2a70e912a954701aff7cc826fb815cf5aa67dce6cb04289d97", "0x31ada280955d6dd78af6d8d63d6dd4d9397bcc5d8ed4af4beb3c466344c9917"] +selector_comms_12 = ["0x15dcbcddb5b26fb6f446047867f51a44ad686b0f68d4d10e94cad7380dcd07a3", "0x1235790b118ca52b2cab3a983d5c7a1ec67827f6704fb747dfb81cac918c45b4"] +selector_comms_13 = ["0x2ae965fefef7a4b2df802a01cfd6d3a2cef4b4309dcd6716a65c829ec304bf52", "0x281f365e16247924b2bd5d2c6467b31ccc3692693a98cfc67f741c089fc5fb3"] +selector_comms_14 = ["0x2fbe8998140323372ac4b68dc400a176f197b6abfdfac3489e410ea772e0a5fa", "0x5c1c6088a434a9925c9e290bc1fb22f05580a3b28e3fbe5a4cdf1a222525960"] +selector_comms_15 = ["0x2937f3d6c6d90b1641899b0af223b7b4254f79dd37ea9c404a7d2e163b6861b7", "0xcd18a059ce70ff69a92c6f8f3b41e688c685a48d960080a0ff7a08c3b301ceb"] +selector_comms_16 = ["0x23585175e379d41275caee601c012a4ca0183693810bde68d02a85d563a398b3", "0x1a6ea9cb335d3f4bb22fdec28497ba8048bf4d0b73351557b3412ee032cc080c"] +selector_comms_17 = ["0x551412252183d89a4bc0de5fabb821a2ed129c9b49f31d148b5f1150f26e1cf", "0x162f5aa78e941410582b437daa750caf997c0f30b5875a4c0aec153fa691aa16"] +selector_comms_18 = ["0x14fcee171c8bf03b333a70d359b2a668ca28cca1707004d67118e7174a8e0d0d", "0x1719b3e69e1d1d21c0ae93122a1d152fa52cb1e900642f91865219078fedf11b"] +# Scalars +k1 = "0x1" +k2 = "0x2f8dd1f1a7583c42c4e12a44e110404c73ca6c94813f85835da4fb7bb1301d4a" +k3 = "0x1ee678a0470a75a6eaa8fe837060498ba828a3703b311d0f77f010424afeb025" +k4 = "0x2042a587a90c187b0a087c03e29c968b950b1db26d5c82d666905a6895790c0a" +k5 = "0x2e2b91456103698adf57b799969dea1c8f739da5d8d40dd3eb9222db7c81e881" +k6 = "0x1f20f5b0adb417179d42df7ddd4410a330afdb03e5c28949665b55adf7d7922d" +# Commitments (G1) +range_table_comm = ["0x1845622f9012f44d4d9b492a254a360ab98914fda5d90031b0a78009cbae56b8", "0x2da38747c37c85b6815a9ac706a061274eaae8f7cfb4e3c83ad4112ba8dcc18f"] +key_table_comm = ["0x2cd3d4b52c4e81a0230fdc2afb118f488f76df3cbb474e688c21cdee5f1274ff", "0x21889c2f2692386e405ffab0d2241794f4b4431e3265d97f42ee7e77894196db"] +table_dom_sep_comm = ["0x3735500ca623cc3fddb6a85a133599035e252fe10286c214f5ea8d1aff8dd34", "0x1f6fff4e2027f91a1cab2cdf2ba43331f8a2bae93bba9659fbc7a6f25d87740c"] +q_dom_sep_comm = ["0x1926d85f74e52438d6ddb98c5e8c21aebdf9d351b907df73e5c3198708371281", "0x2dfa10125652bdee92111199fcb7a4469cc346e1a2e1c970b266562e07ce377b"] +# Group parameters +size_inv = "0x30644e5aaf0a66b91f8030da595e7d1c6787b9b45fc54c546729acf1ff053609" +group_gen = "0x2a734ebb326341efa19b0361d9130cd47b26b7488dc6d26eeccd4f3eb878331a" +group_gen_inv = "0x27f035bdb21de9525bcd0d50e993ee185f43327bf6a8efc445d2f3cb9550fe47" +# Open key (G1) +open_key_g = ["0x1", "0x2"] +# G2 points +h = ["0x198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c2", "0x1800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed", "0x90689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b", "0x12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa"] +beta_h = ["0x1111", "0x285b1f14edd7e6632340a37dfae9005ff762edcfecfe1c732a7474c0708bef80", "0x219edfceee1723de674f5b2f6fdb69d9e32dd53b15844956a630d3c7cdaa6ed9", "0x2bad9a374aec49d329ec66e8f530f68509313450580c4c17c6db5ddb9bde7fd0"] + +[sepolia.owners] +vk_provider_owner = "0xa0Ee7A142d267C1f36714E4a8F75612F20a79720" # Anvil account (9) +x509_owner = "0xa0Ee7A142d267C1f36714E4a8F75612F20a79720" # Anvil account (9) +verifier_owner = "0xa0Ee7A142d267C1f36714E4a8F75612F20a79720" # Anvil account (9) +round_robin_owner = "0xa0Ee7A142d267C1f36714E4a8F75612F20a79720" # Anvil account (9) +nightfall_owner = "0xa0Ee7A142d267C1f36714E4a8F75612F20a79720" # Anvil account (9) + +[sepolia.nightfall_deployer] +log_level = "info" +default_proposer_address = "0x52A57DD934B864e2f6a4AFE08f94E3068Ff5a420" +default_proposer_url = "http://35.225.105.10:3001" +proposer_stake = 4 +proposer_ding = 3 # how much to fine a proposer for not making a block +proposer_exit_penalty = 2 # how much to fine a proposer for deregister during its turn +proposer_cooling_blocks = 4 # how many blocks before a de-registered proposer can register again +proposer_rotation_blocks = 4 # how many blocks before we rotate proposers +proposer_grace_blocks = 1 # how many blocks of inactivity allowed before anyone can skip the current proposer + +[sepolia.nightfall_test] +log_level = "info" + +[sepolia.contracts] +assets = "./blockchain_assets/artifacts" +deployment_file = "./blockchain_assets/logs/deployer.s.sol" +deploy_contracts = true + +[sepolia.contracts.contract_addresses] # Contract addresses for the development network. These are used if deploy_contracts is false and they are not empty +nightfall = "" +round_robin = "" +x509 = "" +verifier = "" + +[sepolia.certificates] +authority_key_identifier = "0xA469FF28BFAB9C4DB09220B24038D6F18EA57F75" +modulus = "0x009DEA9DCA80BFA87C29232B18D6C0072898922A7E7E224A7FF638F61851B5F36392E7FBFDBFF3A0AE409763E2A04CDD3DC692A6DE447391FFE6722456957DD7F031B8D9A7999579F6F4258490AE6E9D629BC40815F689C58037C03B46502243BFD29B02116454453810D160DE1D8C8DDD624B30A25A011185E60BCA9BF71181DD3256112F1EFDBECF19E77AF9640EDE4DB8FF51855E6B490424FC4F5631DD9551D7CD762420E3AFA0B20E6B403A0CB71FA16861F8C591B2BD7BDD564EC6D5A17A932E310876D1D65AF3F3F213D1C49086F32C7C8A0F53750127DF8709F6035688E02E613F1C57A525A21DD83FA27D0622FC0EFC76ABA114194A7FDA1B0879013D0790F3B8D387ACA238FC37135F9BA6BB0C87A972143568B010B62EE8BA71C78202858170F292596AD95DD4FA2DC8E9ABA359B8F511B5F3894906F3FD0A22CA3DEB2E67B2A97CD2B847AC73BE28F69996A4CF51B6FD87B9F932F6049F886AC5A7725755693842DF00795A9D00C76E2C4446BDDA5E595CBE8CDF51E050632DB110D155343188A57F273B4334E5DA5EC556AD3CADC3327268DC0C528FE41F837A393B5B2F76E476CFA64A2A24BA71F5F7078F5360EBF316D4275AB292B031B9CF8787ACB009D3DC5DCD5038C05E1B2225909E596DFE2E968CFAE077FDFF540E3F78FC464966BB19E280DE34F81079B9DCA111904CDC7C5B6FD5CD44A215B0B5A6A9" +exponent = 65537 +extended_key_usages = [ + "0x06082b0601050507030400000000000000000000000000000000000000000000", + "0x06082b0601050507030800000000000000000000000000000000000000000000", +] +certificate_policies = [ + "0x06032d0607000000000000000000000000000000000000000000000000000000", +] +oid_group = 0 + + [development] signing_key = "Key not set" #key (0) azure_vault_url = "vault url is not set" @@ -205,6 +341,7 @@ extended_key_usages = [ certificate_policies = [ "0x06032d0607000000000000000000000000000000000000000000000000000000", ] +oid_group = 0 [production] # This is the production environment - add an appropriate configuration here, using development as a template diff --git a/nightfall_client/Dockerfile b/nightfall_client/Dockerfile index 55f9338c..21fe020a 100644 --- a/nightfall_client/Dockerfile +++ b/nightfall_client/Dockerfile @@ -4,7 +4,7 @@ FROM rust:1.88.0 AS builder WORKDIR /app RUN mkdir bin COPY --exclude=configuration/bin/* . . -COPY configuration/bin/proving_key configuration/bin/deposit_proving_key configuration/bin/ +COPY configuration/bin/keys/proving_key configuration/bin/keys RUN --mount=type=cache,target=/usr/local/cargo/registry \ --mount=type=cache,target=/app/target \ --mount=type=cache,target=/usr/local/cargo/git \ @@ -27,7 +27,8 @@ RUN chmod 644 /usr/local/share/ca-certificates/* && update-ca-certificates # Copy application binaries and configuration COPY --from=builder /app/bin/client bin/ -COPY configuration/bin/proving_key configuration/bin/deposit_proving_key configuration/bin/ +RUN mkdir -p configuration/bin/keys +COPY configuration/bin/keys/proving_key configuration/bin/keys/ COPY .env *.env nightfall.toml . EXPOSE 3000 diff --git a/nightfall_client/src/driven/contract_functions/nightfall_contract.rs b/nightfall_client/src/driven/contract_functions/nightfall_contract.rs index f3161c86..31d3ad8f 100644 --- a/nightfall_client/src/driven/contract_functions/nightfall_contract.rs +++ b/nightfall_client/src/driven/contract_functions/nightfall_contract.rs @@ -12,6 +12,7 @@ use ark_bn254::Fr as Fr254; use ark_ff::BigInteger256; use ark_std::Zero; use configuration::{addresses::get_addresses, settings::get_settings}; +use lib::log_fetcher::get_genesis_block; use lib::{ blockchain_client::BlockchainClientConnection, contract_conversions::{Addr, FrBn254, Uint256}, @@ -361,9 +362,10 @@ impl NightfallContract for Nightfall::NightfallCalls { })?; let event_sig = B256::from(keccak256("BlockProposed(int256)")); + let genenisus_block = get_genesis_block(); let filter = Filter::new() .address(nightfall_address) - .from_block(0u64) + .from_block(genenisus_block) .to_block(latest_block) .event_signature(event_sig) .topic1(block_topic); diff --git a/nightfall_client/src/drivers/blockchain/nightfall_event_listener.rs b/nightfall_client/src/drivers/blockchain/nightfall_event_listener.rs index 05223bf7..c2130ae4 100644 --- a/nightfall_client/src/drivers/blockchain/nightfall_event_listener.rs +++ b/nightfall_client/src/drivers/blockchain/nightfall_event_listener.rs @@ -16,6 +16,7 @@ use alloy::{ use configuration::addresses::get_addresses; use futures::StreamExt; use futures::{future::BoxFuture, FutureExt}; +use lib::log_fetcher::get_logs_paginated; use lib::{ blockchain_client::BlockchainClientConnection, error::EventHandlerError, @@ -115,10 +116,23 @@ pub async fn listen_for_events( .expect("could not get latest block number"); if latest_block >= start_block as u64 { - let past_events = blockchain_client - .get_logs(&events_filter.clone().to_block(latest_block)) - .await - .expect("could not get past events"); + log::info!("Fetching past events from block {start_block} to {latest_block}"); + let past_events = match get_logs_paginated( + blockchain_client.root(), + events_filter.clone(), + start_block as u64, + latest_block, + ) + .await + { + Ok(events) => events, + Err(e) => { + log::error!("Failed to fetch past events: {e}. Will retry..."); + return Err(EventHandlerError::IOError(format!( + "Failed to fetch past events: {e}" + ))); + } + }; log::info!("Found {} past events to process", past_events.len()); for evt in past_events { let event = match Nightfall::NightfallEvents::decode_log(&evt.inner) { diff --git a/nightfall_deployer/Dockerfile b/nightfall_deployer/Dockerfile index 64364f99..8f03dc47 100644 --- a/nightfall_deployer/Dockerfile +++ b/nightfall_deployer/Dockerfile @@ -10,7 +10,8 @@ WORKDIR /app RUN mkdir -p bin COPY --from=foundry /usr/local/bin/forge ./forge COPY --exclude=configuration/bin/* . . -COPY configuration/bin/*_vk configuration/bin/ +RUN mkdir -p configuration/bin/keys +COPY configuration/bin/keys/ configuration/bin/keys/ ENV PATH=/app:$PATH RUN --mount=type=cache,id=cargo-registry-v4,target=/usr/local/cargo/registry,sharing=locked \ --mount=type=cache,id=cargo-git-v4,target=/usr/local/cargo/git,sharing=locked \ @@ -21,7 +22,6 @@ RUN --mount=type=cache,id=cargo-registry-v4,target=/usr/local/cargo/registry,sha FROM debian:bookworm-slim WORKDIR /app COPY --from=builder /app/bin/deployer bin/ -COPY configuration/bin/*_vk configuration/bin/ COPY --from=builder /app/blockchain_assets blockchain_assets/ COPY .env *.env nightfall.toml foundry.toml ./ diff --git a/nightfall_deployer/bin/key_generation.rs b/nightfall_deployer/bin/key_generation.rs index b6e1f5f8..2f9089c0 100644 --- a/nightfall_deployer/bin/key_generation.rs +++ b/nightfall_deployer/bin/key_generation.rs @@ -17,6 +17,7 @@ use lib::{ plonk_prover::circuits::unified_circuit::unified_circuit_builder, shared_entities::DepositData, }; +use std::fs; use std::fs::File; fn main() { let settings: Settings = settings::Settings::new().unwrap(); @@ -26,6 +27,7 @@ fn main() { println!("Generating keys for REAL rollup prover"); } generate_proving_keys(&settings).unwrap(); + println!("Generating keys for rollup prover finished."); } /// Generates the proving key and writes it to file. @@ -74,15 +76,20 @@ pub fn generate_proving_keys(settings: &Settings) -> Result<(), PlonkError> { true, )?; - let pk_path = path.join("bin/proving_key"); + let pk_path = path.join("bin/keys/proving_key"); + if let Some(parent) = pk_path.parent() { + fs::create_dir_all(parent).map_err(PlonkError::IoError)?; + } let mut file = File::create(pk_path).map_err(PlonkError::IoError)?; let mut compressed_bytes = Vec::new(); pk.serialize_compressed(&mut compressed_bytes)?; file.write_all(&compressed_bytes) .map_err(PlonkError::IoError)?; - let deposit_pk_path = path.join("bin/deposit_proving_key"); - + let deposit_pk_path = path.join("bin/keys/deposit_proving_key"); + if let Some(parent) = deposit_pk_path.parent() { + fs::create_dir_all(parent).map_err(PlonkError::IoError)?; + } let mut file = File::create(deposit_pk_path.clone()).map_err(PlonkError::IoError)?; let mut deposit_compressed_bytes = Vec::new(); deposit_pk.serialize_compressed(&mut deposit_compressed_bytes)?; diff --git a/nightfall_proposer/Dockerfile b/nightfall_proposer/Dockerfile index c032a481..ca49a34a 100644 --- a/nightfall_proposer/Dockerfile +++ b/nightfall_proposer/Dockerfile @@ -23,6 +23,8 @@ RUN chmod 644 /usr/local/share/ca-certificates/* && update-ca-certificates # Copy application binaries and configuration COPY --from=builder /app/bin/proposer bin/ COPY configuration/bin/* configuration/bin/ +RUN mkdir -p configuration/bin/keys +COPY configuration/bin/keys/* configuration/bin/keys COPY .env *.env nightfall.toml . EXPOSE 3000 diff --git a/nightfall_proposer/src/driven/nightfall_client_transaction.rs b/nightfall_proposer/src/driven/nightfall_client_transaction.rs index 16d56ec3..365f8436 100644 --- a/nightfall_proposer/src/driven/nightfall_client_transaction.rs +++ b/nightfall_proposer/src/driven/nightfall_client_transaction.rs @@ -42,6 +42,7 @@ pub enum ClientTransactionError, P: Proof> { DuplicateNullifier, CommitmentRootUnknown, NullifiersAllZero, + WrongProof, } impl, P: Proof> Error for ClientTransactionError {} impl, P: Proof> Display for ClientTransactionError { @@ -69,6 +70,9 @@ impl, P: Proof> Display for ClientTransactionError { ClientTransactionError::NullifiersAllZero => { write!(f, "All nullifiers are zero") } + ClientTransactionError::WrongProof => { + write!(f, "Client transaction zk proof is wrong") + } } } } @@ -88,9 +92,16 @@ where let db = get_db_connection().await; // `db` is now &'static mongodb::Client // `db` is directly usable for all database operations, including writes. let public_inputs = PublicInputs::from(&client_transaction); - if let Err(error) = E::verify(&client_transaction.proof, &public_inputs) { - return Err(ClientTransactionError::ProofDidNotVerify(error)); + match E::verify(&client_transaction.proof, &public_inputs) { + Ok(true) => {} + Ok(false) => { + return Err(ClientTransactionError::WrongProof); + } + Err(error) => { + return Err(ClientTransactionError::ProofDidNotVerify(error)); + } } + // 2) then we should check that the transaction is not already in the database i.e. this isn't a replay let hash = &client_transaction .hash() diff --git a/nightfall_proposer/src/driven/nightfall_contract.rs b/nightfall_proposer/src/driven/nightfall_contract.rs index d2fe0958..82f3d0b0 100644 --- a/nightfall_proposer/src/driven/nightfall_contract.rs +++ b/nightfall_proposer/src/driven/nightfall_contract.rs @@ -70,7 +70,7 @@ impl NightfallContract for Nightfall::NightfallCalls { .await .map_err(|_| NightfallContractError::TransactionError)?; info!( - "Received receipt for submitted block with hash: {}, gas used was: {}", + "The L2 block was sent to L1. Received receipt for submitted block with hash: {}, gas used was: {}", receipt.transaction_hash, receipt.gas_used ); Ok(()) diff --git a/nightfall_proposer/src/driven/rollup_prover.rs b/nightfall_proposer/src/driven/rollup_prover.rs index 25a14cd3..be47ac2f 100644 --- a/nightfall_proposer/src/driven/rollup_prover.rs +++ b/nightfall_proposer/src/driven/rollup_prover.rs @@ -54,12 +54,12 @@ use lib::{ shared_entities::DepositData, utils::load_key_from_server, }; +use lib::{rollup_circuit_checks::get_configuration_keys_path, utils::load_key_locally}; use serde::{Deserialize, Serialize}; use std::{ collections::HashMap, error::Error, fmt::{Display, Formatter, Result as FmtResult}, - io::Read, ops::Deref, path::{Path, PathBuf}, sync::{Arc, OnceLock}, @@ -145,21 +145,26 @@ fn find(path: &Path) -> Option { pub fn get_base_grumpkin_proving_key() -> &'static Arc> { static PK: OnceLock>> = OnceLock::new(); PK.get_or_init(|| { - // We'll try to load from the configuration directory first. + // We'll try to load key locally first, if it fails we will load from server. + let path = get_configuration_keys_path() + .expect("Configuration keys path not found") + .join("base_grumpkin_pk"); + let source_file = find(&path).unwrap(); + if let Some(key_bytes) = load_key_locally(&source_file) { + let base_grumpkin_proving_key = + MLEProvingKey::::deserialize_compressed_unchecked(&*key_bytes) + .expect("Could not deserialise base_grumpkin_proving_key"); + return Arc::new(base_grumpkin_proving_key); + } + warn!("Could not load base_grumpkin_proving_key from local file. Loading from server"); if let Some(key_bytes) = load_key_from_server("base_grumpkin_pk") { - let pk = MLEProvingKey::::deserialize_compressed_unchecked(&*key_bytes) - .expect("Could not deserialise proving key"); - return Arc::new(pk); + let base_grumpkin_proving_key = + MLEProvingKey::::deserialize_compressed_unchecked(&*key_bytes) + .expect("Could not deserialise base_grumpkin_proving_key"); + return Arc::new(base_grumpkin_proving_key); } - // If that fails, we'll try to load from a local file - warn!("Could not load deposit proving key from server. Loading from local file"); - let path = Path::new("./configuration/bin/base_grumpkin_pk"); - let source_file = find(path).unwrap(); - let pk = MLEProvingKey::::deserialize_compressed_unchecked( - &*std::fs::read(source_file).expect("Could not read proving key"), - ) - .expect("Could not deserialise proving key"); - Arc::new(pk) + // 3) If both fail, blow up loudly (this is critical infra) + panic!("Failed to load base_grumpkin_proving_key from both local and server"); }) } @@ -167,43 +172,62 @@ pub fn get_base_grumpkin_proving_key() -> &'static Arc> { pub fn get_base_bn254_proving_key() -> &'static Arc> { static PK: OnceLock>> = OnceLock::new(); PK.get_or_init(|| { + // 1) We'll try to load key locally first, if it fails we will load from server. + let path = get_configuration_keys_path() + .expect("Configuration keys path not found") + .join("base_bn254_pk"); + let source_file = find(&path).unwrap(); + if let Some(key_bytes) = load_key_locally(&source_file) { + let base_bn254_proving_key = + ProvingKey::::deserialize_compressed_unchecked(&*key_bytes) + .expect("Could not deserialise base_bn254_proving_key"); + return Arc::new(base_bn254_proving_key); + } + warn!("Could not load base_bn254_proving_key from local file. Loading from server"); + // 2) Try server if let Some(key_bytes) = load_key_from_server("base_bn254_pk") { - let pk = ProvingKey::::deserialize_compressed_unchecked(&*key_bytes) - .expect("Could not deserialise proving key"); - return Arc::new(pk); + let base_bn254_proving_key = + ProvingKey::::deserialize_compressed_unchecked(&*key_bytes) + .expect("Could not deserialise base_bn254_proving_key"); + return Arc::new(base_bn254_proving_key); } - // If that fails, we'll try to load from a local file - warn!("Could not load deposit proving key from server. Loading from local file"); - let path = Path::new("./configuration/bin/base_bn254_pk"); - let source_file = find(path).unwrap(); - let pk = ProvingKey::::deserialize_compressed_unchecked( - &*std::fs::read(source_file).expect("Could not read proving key"), - ) - .expect("Could not deserialise proving key"); - Arc::new(pk) + // 3) If both fail, blow up loudly (this is critical infra) + panic!("Failed to load base_bn254_proving_key from both local and server"); }) } /// This function is used to retrieve the decider proving key. pub fn get_decider_proving_key() -> &'static Arc> { static PK: OnceLock>> = OnceLock::new(); + PK.get_or_init(|| { - /* Downloading from servers takes too longs, generate it yourself and save it, the read it from local */ - // if let Some(key_bytes) = load_key_from_server("decider_pk") { - // let pk = PlonkProvingKey::::deserialize_compressed_unchecked(&*key_bytes) - // .expect("Could not deserialise proving key"); - // return Arc::new(pk); - // } - let path = Path::new("./configuration/bin/decider_pk"); - let source_file = find(path).unwrap(); - let mut file = std::fs::File::open(source_file).unwrap(); - let file_metadata = file.metadata().unwrap(); - let size = file_metadata.len(); - let mut buf = vec![0u8; size as usize]; - file.read_exact(&mut buf).unwrap(); - let pk = PlonkProvingKey::::deserialize_compressed_unchecked(buf.as_slice()) - .expect("Could not deserialise proving key"); - Arc::new(pk) + let path = get_configuration_keys_path() + .expect("Configuration keys path not found") + .join("decider_pk"); + let source_file = find(&path).expect("Could not locate decider_pk file"); + + // 1) We'll try to load key locally first, if it fails we will load from server. + if let Some(bytes) = load_key_locally(&source_file) { + if let Ok(pk) = + PlonkProvingKey::::deserialize_compressed_unchecked(bytes.as_ref()) + { + return Arc::new(pk); + } else { + warn!("Failed to deserialize local decider_pk, trying server"); + } + } else { + warn!("Could not read local decider_proving_key, trying server"); + } + + // 2) Try server + if let Some(key_bytes) = load_key_from_server("decider_pk") { + let pk = PlonkProvingKey::::deserialize_compressed_unchecked(key_bytes.as_ref()) + .expect("Could not deserialise decider_pk from server"); + return Arc::new(pk); + } + + // 3) If both fail, blow up loudly (this is critical infra) + panic!("Failed to load decider proving key from both local file and server"); }) } @@ -288,9 +312,8 @@ impl RecursiveProver for RollupProver { GRUMPKIN_MERGE_PKS .get_or_init(|| { - let config_path = get_configuration_path() - .expect("Configuration path not found") - .join("bin"); + let config_path = + get_configuration_keys_path().expect("Configuration path not found"); let mut pks = Vec::new(); let mut i = 0; @@ -320,9 +343,8 @@ impl RecursiveProver for RollupProver { BN254_MERGE_PKS .get_or_init(|| { - let config_path = get_configuration_path() - .expect("Configuration path not found") - .join("bin"); + let config_path = + get_configuration_keys_path().expect("Configuration path not found"); let mut pks = Vec::new(); let mut i = 0; @@ -354,7 +376,7 @@ impl RecursiveProver for RollupProver { fn get_decider_vk() -> PlonkVerifyingKey { let path = get_configuration_path() .expect("Configuration path not found") - .join("bin/decider_vk"); + .join("bin/keys/decider_vk"); let source_file = find(&path).unwrap(); PlonkVerifyingKey::::deserialize_compressed_unchecked( &*std::fs::read(source_file).expect("Could not read verifying key"), diff --git a/nightfall_proposer/src/drivers/blockchain/block_assembly.rs b/nightfall_proposer/src/drivers/blockchain/block_assembly.rs index a8cbd731..a1d79e72 100644 --- a/nightfall_proposer/src/drivers/blockchain/block_assembly.rs +++ b/nightfall_proposer/src/drivers/blockchain/block_assembly.rs @@ -5,6 +5,7 @@ use crate::{ services::assemble_block::assemble_block, }; use alloy::primitives::Address; +use alloy::sol_types::SolEvent; use alloy::{ primitives::{TxHash, U64}, providers::{Provider, RootProvider}, @@ -13,6 +14,8 @@ use alloy::{ use ark_serialize::SerializationError; use configuration::{addresses::get_addresses, settings::get_settings}; use jf_plonk::errors::PlonkError; +use lib::log_fetcher::get_genesis_block; +use lib::log_fetcher::get_logs_paginated; use lib::{ blockchain_client::BlockchainClientConnection, error::{ConversionError, EventHandlerError, NightfallContractError}, @@ -27,6 +30,7 @@ use std::{ }; use std::{sync::Arc, time::Duration}; use tokio::sync::Mutex; +use std::sync::atomic::{AtomicBool, Ordering}; #[derive(Debug)] pub enum BlockAssemblyError { @@ -252,86 +256,451 @@ where // Shared queue for blocks waiting for finality confirmation let pending_blocks = Arc::new(Mutex::new(Vec::new())); + // Single-writer flag to prevent concurrent block assembly runs + let is_assembling = Arc::new(AtomicBool::new(false)); + // simple RAII guard to clear the flag on drop + struct AssemblingGuard(Arc); + impl Drop for AssemblingGuard { + fn drop(&mut self) { + self.0.store(false, Ordering::SeqCst); + } + } + + let confirmations_required = U64::from(12); let finality_check_interval = Duration::from_secs(5); debug!("Starting block assembly"); + // println!("Starting block assembly"); + // Finality checker task: + // - scan ProposerRotated logs + // - wait finality for the latest seen rotation tx + // - verify the finalized rotation is canonical (matches current contract state) + // - ONLY THEN drain + propose pending blocks (and only if we're the current proposer) // Spawn the finality checking task - // we should start this if we have at least one pending block let _finality_checker: tokio::task::JoinHandle> = { let pending_blocks = Arc::clone(&pending_blocks); let rr = Arc::clone(&round_robin_instance); + let blockchain_client = blockchain_client.clone(); tokio::spawn(async move { + let mut last_scanned: u64 = get_genesis_block(); + loop { - // Check proposer rotation events - let start_block = match rr.start_l1_block().call().await { - Ok(block) => block, - Err(_) => { - return Err(BlockAssemblyError::FailedToAssembleBlock( - "Failed to get start block for round robin".to_string(), - )); - } + let tick = std::time::Instant::now(); + // println!("FINALITY TICK start {:?}", tick); + + // ark_std::println!("Jiajie: Am in the first loop"); + + // If nothing to propose, don't waste RPC calls + let has_pending = { + let guard = pending_blocks.lock().await; + !guard.is_empty() }; - let mut blocks = pending_blocks.lock().await; - // If start_block is zero, then we assume the contract has just been deployed and rotation has not yet started. - if start_block.is_zero() && !blocks.is_empty() { - info!("Proposing {} pending blocks", blocks.len()); - for block in blocks.drain(..) { - if let Err(e) = N::propose_block(block).await { - error!("Failed to propose block: {e}"); - } + if !has_pending { + tokio::time::sleep(finality_check_interval).await; + // println!( + // "FINALITY TICK end (no pending), elapsed={:?}", + // tick.elapsed() + // ); + continue; + } + + let latest_block = match blockchain_client.root().get_block_number().await { + Ok(n) => n, + Err(e) => { + error!("Finality checker: failed to get latest block number: {e}"); + tokio::time::sleep(finality_check_interval).await; + continue; } + }; + + if latest_block < last_scanned { + // chain reorg / provider weirdness; just clamp + last_scanned = latest_block; } - let round_robin_events = rr + // Small safety overlap to not miss logs at boundary. + // NOTE: do NOT always restart from genesis, keep a cursor. + let from_block = last_scanned.saturating_sub(5); + + let rotation_filter = rr .event_filter::() - .from_block(0u64); - let rotate_proposer_log = match round_robin_events.query().await { - Ok(logs) => logs, - Err(_) => { - return Err(BlockAssemblyError::FailedToAssembleBlock( - "Failed to query round robin rotate proposer events".to_string(), - )); + .from_block(from_block); + + let rotation_logs = match get_logs_paginated( + blockchain_client.root(), + rotation_filter.filter.clone(), + from_block, + latest_block, + ) + .await + { + Ok(events) => events, + Err(e) => { + error!( + "Finality checker: failed to fetch ProposerRotated logs paginated: {e}" + ); + tokio::time::sleep(finality_check_interval).await; + continue; + } + }; + + // Advance cursor only after successful fetch. + last_scanned = latest_block; + + if rotation_logs.is_empty() { + debug!("Finality checker: no ProposerRotated logs in range {from_block}..{latest_block}"); + // println!("Finality checker: no ProposerRotated logs in range {from_block}..{latest_block}"); + tokio::time::sleep(finality_check_interval).await; + // println!("FINALITY TICK end, elapsed={:?}", tick.elapsed()); + continue; + } + + // Decode (best-effort) and keep the last event in this window. + let mut decoded_rotation_events = Vec::new(); + for evt in rotation_logs { + if let Ok(decoded) = RoundRobin::ProposerRotated::decode_log(&evt.inner) { + decoded_rotation_events.push((decoded, evt)); + } + } + + // If decode failed for all, just sleep and retry. + let Some((_decoded, evt)) = decoded_rotation_events.last() else { + warn!("Finality checker: ProposerRotated logs found but none decoded"); + // println!("Finality checker: ProposerRotated logs found but none decoded"); + tokio::time::sleep(finality_check_interval).await; + // println!("FINALITY TICK end, elapsed={:?}", tick.elapsed()); + continue; + }; + + let tx_hash = match evt.transaction_hash { + Some(h) => h, + None => { + error!("Finality checker: rotation event missing transaction_hash"); + tokio::time::sleep(finality_check_interval).await; + // println!("FINALITY TICK end, elapsed={:?}", tick.elapsed()); + continue; } }; + + let evt_block_number = match evt.block_number { + Some(n) => n, + None => { + error!("Finality checker: rotation event missing block_number"); + tokio::time::sleep(finality_check_interval).await; + // println!("FINALITY TICK end, elapsed={:?}", tick.elapsed()); + continue; + } + }; + let client = blockchain_client.root().clone(); - for (_, log_meta) in rotate_proposer_log { - let tx_hash = log_meta.transaction_hash.ok_or_else(|| { - BlockAssemblyError::Other("Transaction hash is None".to_string()) - })?; - match check_l1_finality( - &client, - tx_hash, - confirmations_required, - Some(finality_check_interval), - ) - .await - { - Ok(true) => { - // Process all pending blocks - info!("Rotate Proposer Transaction finalized: {tx_hash:?}"); - info!("Proposing {} pending blocks", blocks.len()); - for block in blocks.drain(..) { - if let Err(e) = N::propose_block(block).await { - error!("Failed to propose block: {e}"); - } + + match check_l1_finality( + &client, + tx_hash, + confirmations_required, + Some(finality_check_interval), + ) + .await + { + Ok(true) => { + info!("ProposerRotated tx finalized: {tx_hash:?} (event block: {evt_block_number})"); + + // Canonicality check #1: start_l1_block must match this rotation event's block. + let onchain_start_block = match rr.start_l1_block().call().await { + Ok(b) => b, + Err(e) => { + error!("Finality checker: failed rr.start_l1_block(): {e}"); + tokio::time::sleep(finality_check_interval).await; + // println!("FINALITY TICK end, elapsed={:?}", tick.elapsed()); + continue; } + }; + + if onchain_start_block != evt_block_number { + debug!( + "Finality checker: start_l1_block mismatch (onchain: {}, event: {}). Skipping propose.", + onchain_start_block, evt_block_number + ); + tokio::time::sleep(finality_check_interval).await; + // println!("FINALITY TICK end, elapsed={:?}", tick.elapsed()); + continue; } - Ok(false) => { - debug!("Transaction not yet finalized"); + + // Canonicality check #2: we only propose if we are the current proposer NOW. + let onchain_current_proposer = match rr + .get_current_proposer_address() + .call() + .await + { + Ok(addr) => addr, + Err(e) => { + error!("Finality checker: failed rr.get_current_proposer_address(): {e}"); + tokio::time::sleep(finality_check_interval).await; + // println!("FINALITY TICK end, elapsed={:?}", tick.elapsed()); + continue; + } + }; + + let our_addr = get_blockchain_client_connection() + .await + .read() + .await + .get_address(); + + if onchain_current_proposer != our_addr { + debug!( + "Finality checker: proposer is {:?}, we are {:?}. Not our turn.", + onchain_current_proposer, our_addr + ); + tokio::time::sleep(finality_check_interval).await; + // println!("FINALITY TICK end, elapsed={:?}", tick.elapsed()); + continue; } - Err(e) => { - error!("Finality check error: {e}"); + + // Drain + propose all pending blocks (no lock held across awaits). + let drained_after_finality: Vec<_> = { + let mut guard = pending_blocks.lock().await; + guard.drain(..).collect() + }; + + if !drained_after_finality.is_empty() { + info!( + "Finality checker: finalized & canonical rotation, proposing {} pending blocks", + drained_after_finality.len() + ); + for block in drained_after_finality { + if let Err(e) = N::propose_block(block).await { + error!("Finality checker: propose_block failed: {e}"); + } + } } } + Ok(false) => { + debug!("Finality checker: rotation tx not yet finalized: {tx_hash:?}"); + } + Err(e) => { + error!("Finality checker: finality check error: {e}"); + } } + tokio::time::sleep(finality_check_interval).await; + // println!("FINALITY TICK end, elapsed={:?}", tick.elapsed()); } }) }; + + // tokio::spawn(async move { + // match finality_checker.await { + // Ok(Ok(())) => { + // error!("Finality checker exited unexpectedly with Ok(())"); + // } + // Ok(Err(e)) => { + // error!("Finality checker exited with error: {e}"); + // } + // Err(e) => { + // error!("Finality checker join/panic/cancel: {e}"); + // } + // } + // }); + + // // 1) Fetch start_block (NEVER return Err from inside the loop for transient failures) + // // Check proposer rotation events + // let start_block = match rr.start_l1_block().call().await { + // Ok(block) => block, + // Err(e) => { + // error!("Finality checker: failed to get start_l1_block(): {e}"); + // tokio::time::sleep(finality_check_interval).await; + // continue; + // } + // }; + // // 2) FIRST-PROPOSER PATH: drain + propose if start_block == genesis and queue non-empty + // // Only lock long enough to read/drain, never across awaits + // let drained: Vec<_> = { + // let mut guard = pending_blocks.lock().await; + // if !guard.is_empty() && start_block == get_genesis_block() { + // guard.drain(..).collect() + // } else { + // Vec::new() + // } + // }; + + // // If we drained blocks, propose them (no lock held here) + // if !drained.is_empty() { + // info!( + // "Finality checker (first proposer): proposing {} pending blocks", + // drained.len() + // ); + // for block in drained { + // if let Err(e) = N::propose_block(block).await { + // error!("Finality check (first proposer): propose_block failed: {e}"); + // } + // } + // } + // // let mut blocks = pending_blocks.lock().await; + // // let genenisus_block = get_genesis_block(); + // // ark_std::println!("pending block size:{}", blocks.len()); + // // // If start_block is genenisus_block, then we assume the contract has just been deployed and rotation has not yet started. + // // if start_block == genenisus_block && !blocks.is_empty() { + // // info!("Proposing {} pending blocks", blocks.len()); + // // for block in blocks.drain(..) { + // // ark_std::println!("+++++++++++++++Jiajie: Calling propose_block on 285"); + // // if let Err(e) = N::propose_block(block).await { + // // error!("Failed to propose block: {e}"); + // // } + // // } + // // } + // // 3) ROTATION PATH: query rotation events (don’t return; log+continue) + // // let genenisus_block = get_genesis_block(); + // let latest_block = match blockchain_client.root().get_block_number().await { + // Ok(n) => n, + // Err(e) => { + // error!("Finality checker: failed to get latest block number: {e}"); + // tokio::time::sleep(finality_check_interval).await; + // continue; + // } + // }; + + // if latest_block < last_scanned { + // // chain reorg / provider weirdness; just clamp + // last_scanned = latest_block; + // } + + // // let from_block = get_genesis_block(); + + // // small safety overlap to not miss logs at boundary + // let from_block = last_scanned.saturating_sub(5); + + // // IMPORTANT: use pagination instead of .query() + // let rotation_filter = rr + // .event_filter::() + // .from_block(from_block); + + // let rotate_proposer_log = match get_logs_paginated( + // blockchain_client.root(), + // rotation_filter.filter.clone(), // underlying Filter + // from_block, + // latest_block, + // ) + // .await + // { + // Ok(events) => events, + // Err(e) => { + // error!( + // "Finality checker: failed to fetch ProposerRotated logs paginated: {e}" + // ); + // tokio::time::sleep(finality_check_interval).await; + // continue; + // } + // }; + // // let round_robin_events = rr + // // .event_filter::() + // // .from_block(genenisus_block); + + // // let rotate_proposer_log = match round_robin_events.query().await { + // // Ok(logs) => logs, + // // Err(e) => { + // // // return Err(BlockAssemblyError::FailedToAssembleBlock( + // // // "Failed to query round robin rotate proposer events".to_string(), + // // // )); + // // error!("Finality checker: failed to query ProposerRotated events: {e}"); + // // tokio::time::sleep(finality_check_interval).await; + // // continue; + // // } + // // }; + + // // advance cursor only after successful fetch + // last_scanned = latest_block; + + // if rotate_proposer_log.is_empty() { + // println!("No proposer rotation events found."); + // } else { + // println!( + // "Found {} proposer rotation event(s).", + // rotate_proposer_log.len() + // ); + + // for event in &rotate_proposer_log { + // println!("Event: {:?}", event); + // } + // } + // let client = blockchain_client.root().clone(); + // let mut decoded_rotation_events = Vec::new(); + + // for evt in rotate_proposer_log { + // if let Ok(decoded) = RoundRobin::ProposerRotated::decode_log(&evt.inner) { + // decoded_rotation_events.push((decoded, evt)); + // } + // } + // if let Some((_decoded, evt)) = decoded_rotation_events.last() { + // let tx_hash = evt.transaction_hash.ok_or_else(|| { + // BlockAssemblyError::Other("Transaction hash is None".to_string()) + // })?; + // match check_l1_finality( + // &client, + // tx_hash, + // confirmations_required, + // Some(finality_check_interval), + // ) + // .await + // { + // Ok(true) => { + // // Process all pending blocks + // info!("Rotate Proposer Transaction finalized: {tx_hash:?}"); + // // drain + propose all pending blocks + // let drained_after_finality: Vec<_> = { + // let mut guard = pending_blocks.lock().await; + // guard.drain(..).collect() + // }; + // if !drained_after_finality.is_empty() { + // info!( + // "Finality checker (after rotation finality): proposing {} pending blocks", + // drained_after_finality.len() + // ); + // for block in drained_after_finality { + // if let Err(e) = N::propose_block(block).await { + // error!("Finality checker: propose_block failed: {e}"); + // } + // } + // } + + // // for block in blocks.drain(..) { + // // ark_std::println!("---------------Jiajie: Calling propose_block on 335"); + // // if let Err(e) = N::propose_block(block).await { + // // error!("Failed to propose block: {e}"); + // // } + // // } + // } + // Ok(false) => { + // debug!("Rotation Transaction not yet finalized"); + // } + // Err(e) => { + // error!("Finality check error: {e}"); + // } + // } + // } + // tokio::time::sleep(finality_check_interval).await; + // println!("FINALITY TICK end, elapsed={:?}", tick.elapsed()); + // } + // }) + // }; + // tokio::spawn(async move { + // match finality_checker.await { + // Ok(Ok(())) => { + // error!("Finality checker exited unexpectedly with Ok(())"); + // } + // Ok(Err(e)) => { + // error!("Finality checker exited with error: {e}"); + // } + // Err(e) => { + // error!("Finality checker join/panic/cancel: {e}"); + // } + // } + // }); // Main block assembly loop loop { + // ark_std::println!("Jiajie: Am in the second loop"); debug!("Checking proposer status..."); // Step 1: Get current proposer address from smart contract let current_proposer = match round_robin_instance @@ -408,6 +777,17 @@ where warn!("We are not synchronised. We won't make blocks until we are"); continue; } + // if another assembly is running, skip this trigger + if is_assembling + .compare_exchange(false, true, Ordering::SeqCst, Ordering::SeqCst) + .is_err() + { + info!("Proposer: My another block assembly is currently running; skipping this trigger"); + continue; + } + // ensure the flag is cleared when we leave this scope (success, error, or panic unwind) + let _assembling_guard = AssemblingGuard(Arc::clone(&is_assembling)); + debug!("Triggered block assembly"); let block_result = assemble_block::().await; let block = match block_result { diff --git a/nightfall_proposer/src/drivers/blockchain/nightfall_event_listener.rs b/nightfall_proposer/src/drivers/blockchain/nightfall_event_listener.rs index f8a7f23f..e86ae4a6 100644 --- a/nightfall_proposer/src/drivers/blockchain/nightfall_event_listener.rs +++ b/nightfall_proposer/src/drivers/blockchain/nightfall_event_listener.rs @@ -15,6 +15,7 @@ use ark_bn254::Fr as Fr254; use configuration::{addresses::get_addresses, settings::get_settings}; use futures::StreamExt; use futures::{future::BoxFuture, FutureExt}; +use lib::log_fetcher::get_logs_paginated; use lib::{ blockchain_client::BlockchainClientConnection, error::EventHandlerError, @@ -126,10 +127,23 @@ where .expect("could not get latest block number"); if latest_block >= start_block as u64 { - let past_events = blockchain_client - .get_logs(&events_filter.clone().to_block(latest_block)) - .await - .expect("could not get past events"); + log::info!("Fetching past events from block {start_block} to {latest_block}"); + let past_events = match get_logs_paginated( + blockchain_client.root(), + events_filter.clone(), + start_block as u64, + latest_block, + ) + .await + { + Ok(events) => events, + Err(e) => { + log::error!("Failed to fetch past events: {e}. Will retry..."); + return Err(EventHandlerError::IOError(format!( + "Failed to fetch past events: {e}" + ))); + } + }; log::info!("Found {} past events to process", past_events.len()); for evt in past_events { let event = match Nightfall::NightfallEvents::decode_log(&evt.inner) { diff --git a/nightfall_proposer/src/drivers/rest/proposers.rs b/nightfall_proposer/src/drivers/rest/proposers.rs index 9e27dac9..5ea2f983 100644 --- a/nightfall_proposer/src/drivers/rest/proposers.rs +++ b/nightfall_proposer/src/drivers/rest/proposers.rs @@ -43,28 +43,74 @@ async fn handle_rotate_proposer() -> Result { } } // rotate the proposer - let tx_call = proposer_manager.rotate_proposer(); - let tx_result = tx_call.send().await; - match tx_result { - Ok(tx) => { - let tx_receipt = tx.get_receipt().await.map_err(|e| { - warn!("Failed to get transaction receipt: {e}"); - ProposerError::ProviderError(e.to_string()) - })?; - if tx_receipt.status() { - info!("Rotated proposer successfully"); - Ok(StatusCode::OK) - } else { - warn!("Failed to rotate proposer"); - Err(warp::reject::custom( - ProposerRejection::FailedToRotateProposer, - )) - } - } - Err(_e) => Err(warp::reject::custom( + let signer = get_blockchain_client_connection() + .await + .read() + .await + .get_signer(); + + let nonce = blockchain_client + .get_transaction_count(signer.address()) + .await + .expect("Failed to generate nonce during proposer rotation"); + let gas_price = blockchain_client + .get_gas_price() + .await + .expect("Failed to generate gas_price during proposer rotation"); + let max_fee_per_gas = gas_price * 2; + let max_priority_fee_per_gas = gas_price; + let gas_limit = 5000000u64; + + let call = proposer_manager + .rotate_proposer() + .nonce(nonce) + .gas(gas_limit) + .max_fee_per_gas(max_fee_per_gas) + .max_priority_fee_per_gas(max_priority_fee_per_gas) + .chain_id(get_settings().network.chain_id) // Linea testnet chain ID + .build_raw_transaction((*signer).clone()) + .await + .expect("Failed to call rotate_proposer"); + + let tx_receipt = blockchain_client + .send_raw_transaction(&call) + .await + .expect("Failed to send rotation proposer transaction") + .get_receipt() + .await + .expect("Failed to get receipt of rotation proposer transaction"); + if tx_receipt.status() { + info!("Rotated proposer successfully"); + Ok(StatusCode::OK) + } else { + warn!("Failed to rotate proposer"); + Err(warp::reject::custom( ProposerRejection::FailedToRotateProposer, - )), + )) } + + // let tx_call = proposer_manager.rotate_proposer(); + // let tx_result = tx_call.send().await; + // match tx_result { + // Ok(tx) => { + // let tx_receipt = tx.get_receipt().await.map_err(|e| { + // warn!("Failed to get transaction receipt: {e}"); + // ProposerError::ProviderError(e.to_string()) + // })?; + // if tx_receipt.status() { + // info!("Rotated proposer successfully"); + // Ok(StatusCode::OK) + // } else { + // warn!("Failed to rotate proposer"); + // Err(warp::reject::custom( + // ProposerRejection::FailedToRotateProposer, + // )) + // } + // } + // Err(_e) => Err(warp::reject::custom( + // ProposerRejection::FailedToRotateProposer, + // )), + // } } // Add a proposer diff --git a/nightfall_proposer/src/lib.rs b/nightfall_proposer/src/lib.rs index ebc9422a..b959ea86 100644 --- a/nightfall_proposer/src/lib.rs +++ b/nightfall_proposer/src/lib.rs @@ -6,6 +6,7 @@ pub mod services; use ark_bn254::{Bn254, Fr as Fr254}; use ark_serialize::CanonicalDeserialize; +use ark_std::path::PathBuf; use jf_plonk::nightfall::ipa_structs::ProvingKey; use jf_primitives::{ pcs::prelude::UnivariateKzgPCS, @@ -16,6 +17,7 @@ use jf_primitives::{ }, }; use lib::{rollup_circuit_checks::find_file_with_path, utils::load_key_from_server}; +use lib::{rollup_circuit_checks::get_configuration_keys_path, utils::load_key_locally}; use log::warn; use std::{ collections::HashMap, @@ -52,6 +54,21 @@ pub fn get_deposit_proving_key() -> &'static Arc>>> = OnceLock::new(); PK.get_or_init(|| { // We'll try to load from the configuration directory first. + let path = get_configuration_keys_path() + .expect("Configuration keys path not found") + .join("deposit_proving_key"); + let source_file = find_file_with_path(&path) + .unwrap_or_else(|| panic!("deposit proving key not found at {:?}", path)); + if let Some(_key_bytes) = load_key_locally(&source_file) { + let deposit_proving_key = + ProvingKey::>::deserialize_compressed_unchecked( + &*std::fs::read(source_file).expect("Could not read deposit_proving_key"), + ) + .expect("Could not deserialise deposit_proving_key"); + return Arc::new(deposit_proving_key); + } + warn!("Could not load deposit_proving_key from local file. Loading from server"); + if let Some(key_bytes) = load_key_from_server("deposit_proving_key") { let pk = ProvingKey::>::deserialize_compressed_unchecked( &*key_bytes, @@ -59,15 +76,7 @@ pub fn get_deposit_proving_key() -> &'static Arc>::deserialize_compressed_unchecked( - &*std::fs::read(source_file).expect("Could not read proving key"), - ) - .expect("Could not deserialise proving key"); - Arc::new(pk) + panic!("Failed to load deposit_proving_key from both local and server"); }) } diff --git a/nightfall_test/src/main.rs b/nightfall_test/src/main.rs index 474ff62c..8ac5fb0e 100644 --- a/nightfall_test/src/main.rs +++ b/nightfall_test/src/main.rs @@ -49,10 +49,10 @@ async fn main() -> Result<(), JoinError> { let result = tasks.join_next().await; // wait for any task to finish match result { - Some(Ok(_)) => { + Some(Ok(_)) => { info!("Nightfall tests completed successfully."); return Ok(()); - }, + } Some(Err(e)) => { error!("Nightfall tests failed with error: {e:?}"); return Err(e); diff --git a/rust-toolchain.toml b/rust-toolchain.toml index 8d94ae3b..bf165c7b 100644 --- a/rust-toolchain.toml +++ b/rust-toolchain.toml @@ -1,2 +1,2 @@ [toolchain] -channel = "1.88.0" \ No newline at end of file +channel = "1.93.0" \ No newline at end of file