diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 719ace2..2a9be86 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -21,6 +21,11 @@ jobs: - name: Cache Rust artifacts uses: Swatinem/rust-cache@v2 + - name: Install Foundry + uses: foundry-rs/foundry-toolchain@v1 + with: + version: v1.4.3 + - name: Check run: cargo check --workspace --all-targets --locked diff --git a/Cargo.lock b/Cargo.lock index c0bddad..abf57a2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -11,11 +11,246 @@ dependencies = [ "memchr", ] +[[package]] +name = "allocator-api2" +version = "0.2.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923" + +[[package]] +name = "alloy" +version = "1.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4973038846323e4e69a433916522195dce2947770076c03078fc21c80ea0f1c4" +dependencies = [ + "alloy-consensus", + "alloy-contract", + "alloy-core", + "alloy-eips", + "alloy-genesis", + "alloy-network", + "alloy-node-bindings", + "alloy-provider", + "alloy-rpc-client", + "alloy-rpc-types", + "alloy-serde", + "alloy-signer", + "alloy-signer-local", + "alloy-transport", + "alloy-transport-http", + "alloy-trie", +] + +[[package]] +name = "alloy-chains" +version = "0.2.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90f374d3c6d729268bbe2d0e0ff992bb97898b2df756691a62ee1d5f0506bc39" +dependencies = [ + "alloy-primitives", + "num_enum", + "strum", +] + +[[package]] +name = "alloy-consensus" +version = "1.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0c0dc44157867da82c469c13186015b86abef209bf0e41625e4b68bac61d728" +dependencies = [ + "alloy-eips", + "alloy-primitives", + "alloy-rlp", + "alloy-serde", + "alloy-trie", + "alloy-tx-macros", + "auto_impl", + "borsh", + "c-kzg", + "derive_more", + "either", + "k256", + "once_cell", + "rand 0.8.5", + "secp256k1", + "serde", + "serde_json", + "serde_with", + "thiserror 2.0.18", +] + +[[package]] +name = "alloy-consensus-any" +version = "1.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba4cdb42df3871cd6b346d6a938ec2ba69a9a0f49d1f82714bc5c48349268434" +dependencies = [ + "alloy-consensus", + "alloy-eips", + "alloy-primitives", + "alloy-rlp", + "alloy-serde", + "serde", +] + +[[package]] +name = "alloy-contract" +version = "1.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca63b7125a981415898ffe2a2a696c83696c9c6bdb1671c8a912946bbd8e49e7" +dependencies = [ + "alloy-consensus", + "alloy-dyn-abi", + "alloy-json-abi", + "alloy-network", + "alloy-network-primitives", + "alloy-primitives", + "alloy-provider", + "alloy-rpc-types-eth", + "alloy-sol-types", + "alloy-transport", + "futures", + "futures-util", + "serde_json", + "thiserror 2.0.18", +] + +[[package]] +name = "alloy-core" +version = "1.5.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23e8604b0c092fabc80d075ede181c9b9e596249c70b99253082d7e689836529" +dependencies = [ + "alloy-dyn-abi", + "alloy-json-abi", + "alloy-primitives", + "alloy-rlp", + "alloy-sol-types", +] + +[[package]] +name = "alloy-dyn-abi" +version = "1.5.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc2db5c583aaef0255aa63a4fe827f826090142528bba48d1bf4119b62780cad" +dependencies = [ + "alloy-json-abi", + "alloy-primitives", + "alloy-sol-type-parser", + "alloy-sol-types", + "itoa", + "serde", + "serde_json", + "winnow", +] + +[[package]] +name = "alloy-eip2124" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "741bdd7499908b3aa0b159bba11e71c8cddd009a2c2eb7a06e825f1ec87900a5" +dependencies = [ + "alloy-primitives", + "alloy-rlp", + "crc", + "serde", + "thiserror 2.0.18", +] + +[[package]] +name = "alloy-eip2930" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9441120fa82df73e8959ae0e4ab8ade03de2aaae61be313fbf5746277847ce25" +dependencies = [ + "alloy-primitives", + "alloy-rlp", + "borsh", + "serde", +] + +[[package]] +name = "alloy-eip7702" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2919c5a56a1007492da313e7a3b6d45ef5edc5d33416fdec63c0d7a2702a0d20" +dependencies = [ + "alloy-primitives", + "alloy-rlp", + "borsh", + "serde", + "thiserror 2.0.18", +] + +[[package]] +name = "alloy-eip7928" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8222b1d88f9a6d03be84b0f5e76bb60cd83991b43ad8ab6477f0e4a7809b98d" +dependencies = [ + "alloy-primitives", + "alloy-rlp", + "borsh", + "serde", +] + +[[package]] +name = "alloy-eips" +version = "1.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9f7ef09f21bd1e9cb8a686f168cb4a206646804567f0889eadb8dcc4c9288c8" +dependencies = [ + "alloy-eip2124", + "alloy-eip2930", + "alloy-eip7702", + "alloy-eip7928", + "alloy-primitives", + "alloy-rlp", + "alloy-serde", + "auto_impl", + "borsh", + "c-kzg", + "derive_more", + "either", + "serde", + "serde_with", + "sha2", + "thiserror 2.0.18", +] + +[[package]] +name = "alloy-genesis" +version = "1.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c9cf3b99f46615fbf7dc1add0c96553abb7bf88fc9ec70dfbe7ad0b47ba7fe8" +dependencies = [ + "alloy-eips", + "alloy-primitives", + "alloy-serde", + "alloy-trie", + "borsh", + "serde", + "serde_with", +] + +[[package]] +name = "alloy-hardforks" +version = "0.2.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3165210652f71dfc094b051602bafd691f506c54050a174b1cba18fb5ef706a3" +dependencies = [ + "alloy-chains", + "alloy-eip2124", + "alloy-primitives", + "auto_impl", + "dyn-clone", +] + [[package]] name = "alloy-json-abi" -version = "1.5.4" +version = "1.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8708475665cc00e081c085886e68eada2f64cfa08fc668213a9231655093d4de" +checksum = "e9dbe713da0c737d9e5e387b0ba790eb98b14dd207fe53eef50e19a5a8ec3dac" dependencies = [ "alloy-primitives", "alloy-sol-type-parser", @@ -23,20 +258,96 @@ dependencies = [ "serde_json", ] +[[package]] +name = "alloy-json-rpc" +version = "1.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff42cd777eea61f370c0b10f2648a1c81e0b783066cd7269228aa993afd487f7" +dependencies = [ + "alloy-primitives", + "alloy-sol-types", + "http", + "serde", + "serde_json", + "thiserror 2.0.18", + "tracing", +] + +[[package]] +name = "alloy-network" +version = "1.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8cbca04f9b410fdc51aaaf88433cbac761213905a65fe832058bcf6690585762" +dependencies = [ + "alloy-consensus", + "alloy-consensus-any", + "alloy-eips", + "alloy-json-rpc", + "alloy-network-primitives", + "alloy-primitives", + "alloy-rpc-types-any", + "alloy-rpc-types-eth", + "alloy-serde", + "alloy-signer", + "alloy-sol-types", + "async-trait", + "auto_impl", + "derive_more", + "futures-utils-wasm", + "serde", + "serde_json", + "thiserror 2.0.18", +] + +[[package]] +name = "alloy-network-primitives" +version = "1.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42d6d15e069a8b11f56bef2eccbad2a873c6dd4d4c81d04dda29710f5ea52f04" +dependencies = [ + "alloy-consensus", + "alloy-eips", + "alloy-primitives", + "alloy-serde", + "serde", +] + +[[package]] +name = "alloy-node-bindings" +version = "1.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "091dc8117d84de3a9ac7ec97f2c4d83987e24d485b478d26aa1ec455d7d52f7d" +dependencies = [ + "alloy-genesis", + "alloy-hardforks", + "alloy-network", + "alloy-primitives", + "alloy-signer", + "alloy-signer-local", + "k256", + "libc", + "rand 0.8.5", + "serde_json", + "tempfile", + "thiserror 2.0.18", + "tracing", + "url", +] + [[package]] name = "alloy-primitives" -version = "1.5.4" +version = "1.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b88cf92ed20685979ed1d8472422f0c6c2d010cec77caf63aaa7669cc1a7bc2" +checksum = "de3b431b4e72cd8bd0ec7a50b4be18e73dab74de0dba180eef171055e5d5926e" dependencies = [ "alloy-rlp", "bytes", "cfg-if", "const-hex", "derive_more", - "foldhash", - "hashbrown", - "indexmap", + "foldhash 0.2.0", + "hashbrown 0.16.1", + "indexmap 2.13.0", "itoa", "k256", "keccak-asm", @@ -50,84 +361,338 @@ dependencies = [ "sha3", ] +[[package]] +name = "alloy-provider" +version = "1.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d181c8cc7cf4805d7e589bf4074d56d55064fa1a979f005a45a62b047616d870" +dependencies = [ + "alloy-chains", + "alloy-consensus", + "alloy-eips", + "alloy-json-rpc", + "alloy-network", + "alloy-network-primitives", + "alloy-node-bindings", + "alloy-primitives", + "alloy-rpc-client", + "alloy-rpc-types-anvil", + "alloy-rpc-types-eth", + "alloy-signer", + "alloy-sol-types", + "alloy-transport", + "alloy-transport-http", + "async-stream", + "async-trait", + "auto_impl", + "dashmap", + "either", + "futures", + "futures-utils-wasm", + "lru", + "parking_lot", + "pin-project", + "reqwest", + "serde", + "serde_json", + "thiserror 2.0.18", + "tokio", + "tracing", + "url", + "wasmtimer", +] + [[package]] name = "alloy-rlp" version = "0.3.13" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e93e50f64a77ad9c5470bf2ad0ca02f228da70c792a8f06634801e202579f35e" dependencies = [ + "alloy-rlp-derive", "arrayvec", "bytes", ] +[[package]] +name = "alloy-rlp-derive" +version = "0.3.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce8849c74c9ca0f5a03da1c865e3eb6f768df816e67dd3721a398a8a7e398011" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "alloy-rpc-client" +version = "1.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2792758a93ae32a32e9047c843d536e1448044f78422d71bf7d7c05149e103f" +dependencies = [ + "alloy-json-rpc", + "alloy-primitives", + "alloy-transport", + "alloy-transport-http", + "futures", + "pin-project", + "reqwest", + "serde", + "serde_json", + "tokio", + "tokio-stream", + "tower", + "tracing", + "url", + "wasmtimer", +] + +[[package]] +name = "alloy-rpc-types" +version = "1.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7bdcbf9dfd5eea8bfeb078b1d906da8cd3a39c4d4dbe7a628025648e323611f6" +dependencies = [ + "alloy-primitives", + "alloy-rpc-types-eth", + "alloy-serde", + "serde", +] + +[[package]] +name = "alloy-rpc-types-anvil" +version = "1.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e0a3100b76987c1b1dc81f3abe592b7edc29e92b1242067a69d65e0030b35cf9" +dependencies = [ + "alloy-primitives", + "alloy-rpc-types-eth", + "alloy-serde", + "serde", +] + +[[package]] +name = "alloy-rpc-types-any" +version = "1.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd720b63f82b457610f2eaaf1f32edf44efffe03ae25d537632e7d23e7929e1a" +dependencies = [ + "alloy-consensus-any", + "alloy-rpc-types-eth", + "alloy-serde", +] + +[[package]] +name = "alloy-rpc-types-eth" +version = "1.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b2dc411f13092f237d2bf6918caf80977fc2f51485f9b90cb2a2f956912c8c9" +dependencies = [ + "alloy-consensus", + "alloy-consensus-any", + "alloy-eips", + "alloy-network-primitives", + "alloy-primitives", + "alloy-rlp", + "alloy-serde", + "alloy-sol-types", + "itertools 0.14.0", + "serde", + "serde_json", + "serde_with", + "thiserror 2.0.18", +] + +[[package]] +name = "alloy-serde" +version = "1.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2ce1e0dbf7720eee747700e300c99aac01b1a95bb93f493a01e78ee28bb1a37" +dependencies = [ + "alloy-primitives", + "serde", + "serde_json", +] + +[[package]] +name = "alloy-signer" +version = "1.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2425c6f314522c78e8198979c8cbf6769362be4da381d4152ea8eefce383535d" +dependencies = [ + "alloy-primitives", + "async-trait", + "auto_impl", + "either", + "elliptic-curve", + "k256", + "thiserror 2.0.18", +] + +[[package]] +name = "alloy-signer-local" +version = "1.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3ecb71ee53d8d9c3fa7bac17542c8116ebc7a9726c91b1bf333ec3d04f5a789" +dependencies = [ + "alloy-consensus", + "alloy-network", + "alloy-primitives", + "alloy-signer", + "async-trait", + "k256", + "rand 0.8.5", + "thiserror 2.0.18", +] + [[package]] name = "alloy-sol-macro" -version = "1.5.4" +version = "1.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f5fa1ca7e617c634d2bd9fa71f9ec8e47c07106e248b9fcbd3eaddc13cabd625" +checksum = "ab81bab693da9bb79f7a95b64b394718259fdd7e41dceeced4cad57cb71c4f6a" dependencies = [ "alloy-sol-macro-expander", "alloy-sol-macro-input", "proc-macro-error2", "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.117", ] [[package]] name = "alloy-sol-macro-expander" -version = "1.5.4" +version = "1.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "27c00c0c3a75150a9dc7c8c679ca21853a137888b4e1c5569f92d7e2b15b5102" +checksum = "489f1620bb7e2483fb5819ed01ab6edc1d2f93939dce35a5695085a1afd1d699" dependencies = [ + "alloy-json-abi", "alloy-sol-macro-input", "const-hex", "heck", - "indexmap", + "indexmap 2.13.0", "proc-macro-error2", "proc-macro2", "quote", "sha3", - "syn 2.0.114", + "syn 2.0.117", "syn-solidity", ] [[package]] name = "alloy-sol-macro-input" -version = "1.5.4" +version = "1.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "297db260eb4d67c105f68d6ba11b8874eec681caec5505eab8fbebee97f790bc" +checksum = "56cef806ad22d4392c5fc83cf8f2089f988eb99c7067b4e0c6f1971fc1cca318" dependencies = [ + "alloy-json-abi", "const-hex", "dunce", "heck", "macro-string", "proc-macro2", "quote", - "syn 2.0.114", + "serde_json", + "syn 2.0.117", "syn-solidity", ] [[package]] -name = "alloy-sol-type-parser" -version = "1.5.4" +name = "alloy-sol-type-parser" +version = "1.5.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a6df77fea9d6a2a75c0ef8d2acbdfd92286cc599983d3175ccdc170d3433d249" +dependencies = [ + "serde", + "winnow", +] + +[[package]] +name = "alloy-sol-types" +version = "1.5.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "64612d29379782a5dde6f4b6570d9c756d734d760c0c94c254d361e678a6591f" +dependencies = [ + "alloy-json-abi", + "alloy-primitives", + "alloy-sol-macro", + "serde", +] + +[[package]] +name = "alloy-transport" +version = "1.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa186e560d523d196580c48bf00f1bf62e63041f28ecf276acc22f8b27bb9f53" +dependencies = [ + "alloy-json-rpc", + "auto_impl", + "base64", + "derive_more", + "futures", + "futures-utils-wasm", + "parking_lot", + "serde", + "serde_json", + "thiserror 2.0.18", + "tokio", + "tower", + "tracing", + "url", + "wasmtimer", +] + +[[package]] +name = "alloy-transport-http" +version = "1.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa501ad58dd20acddbfebc65b52e60f05ebf97c52fa40d1b35e91f5e2da0ad0e" +dependencies = [ + "alloy-json-rpc", + "alloy-transport", + "itertools 0.14.0", + "reqwest", + "serde_json", + "tower", + "tracing", + "url", +] + +[[package]] +name = "alloy-trie" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4d7fd448ab0a017de542de1dcca7a58e7019fe0e7a34ed3f9543ebddf6aceffa" +dependencies = [ + "alloy-primitives", + "alloy-rlp", + "arrayvec", + "derive_more", + "nybbles", + "serde", + "smallvec", + "thiserror 2.0.18", + "tracing", +] + +[[package]] +name = "alloy-tx-macros" +version = "1.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94b91b13181d3bcd23680fd29d7bc861d1f33fbe90fdd0af67162434aeba902d" +checksum = "6fa0c53e8c1e1ef4d01066b01c737fb62fc9397ab52c6e7bb5669f97d281b9bc" dependencies = [ - "serde", - "winnow", + "darling 0.21.3", + "proc-macro2", + "quote", + "syn 2.0.117", ] [[package]] -name = "alloy-sol-types" -version = "1.5.4" +name = "android_system_properties" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc442cc2a75207b708d481314098a0f8b6f7b58e3148dd8d8cc7407b0d6f9385" +checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" dependencies = [ - "alloy-json-abi", - "alloy-primitives", - "alloy-sol-macro", - "serde", + "libc", ] [[package]] @@ -180,6 +745,12 @@ dependencies = [ "windows-sys 0.61.2", ] +[[package]] +name = "anyhow" +version = "1.0.102" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f202df86484c868dbad7eaa557ef785d5c66295e41b460ef922eca0723b842c" + [[package]] name = "app-core" version = "0.1.0" @@ -274,7 +845,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "62945a2f7e6de02a31fe400aa489f0e0f5b2502e69f95f853adb82a96c7a6b60" dependencies = [ "quote", - "syn 2.0.114", + "syn 2.0.117", ] [[package]] @@ -312,7 +883,7 @@ dependencies = [ "num-traits", "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.117", ] [[package]] @@ -383,6 +954,53 @@ name = "arrayvec" version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" +dependencies = [ + "serde", +] + +[[package]] +name = "async-recursion" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b43422f69d8ff38f95f1b2bb76517c91589a924d1559a0e935d7c8ce0274c11" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "async-stream" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b5a71a6f37880a80d1d7f19efd781e4b5de42c88f0722cc13bcb6cc2cfe8476" +dependencies = [ + "async-stream-impl", + "futures-core", + "pin-project-lite", +] + +[[package]] +name = "async-stream-impl" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7c24de15d275a1ecfd47a380fb4d5ec9bfe0933f309ed5e705b775596a3574d" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "async-trait" +version = "0.1.89" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9035ad2d096bed7955a320ee7e2230574d28fd3c3a0f186cbea1ff3c7eed5dbb" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] [[package]] name = "atomic-waker" @@ -398,7 +1016,7 @@ checksum = "ffdcb70bdbc4d478427380519163274ac86e52916e10f0a8889adf0f96d3fee7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.117", ] [[package]] @@ -514,11 +1132,27 @@ version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5e764a1d40d510daf35e07be9eb06e75770908c27d411ee6c92109c9840eaaf7" +[[package]] +name = "bitcoin-io" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2dee39a0ee5b4095224a0cfc6bf4cc1baf0f9624b96b367e53b66d974e51d953" + +[[package]] +name = "bitcoin_hashes" +version = "0.14.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26ec84b80c482df901772e931a9a681e26a1b9ee2302edeff23cb30328745c8b" +dependencies = [ + "bitcoin-io", + "hex-conservative", +] + [[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" @@ -541,11 +1175,46 @@ dependencies = [ "generic-array", ] +[[package]] +name = "blst" +version = "0.3.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dcdb4c7013139a150f9fc55d123186dbfaba0d912817466282c73ac49e71fb45" +dependencies = [ + "cc", + "glob", + "threadpool", + "zeroize", +] + +[[package]] +name = "borsh" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d1da5ab77c1437701eeff7c88d968729e7766172279eab0676857b3d63af7a6f" +dependencies = [ + "borsh-derive", + "cfg_aliases", +] + +[[package]] +name = "borsh-derive" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0686c856aa6aac0c4498f936d7d6a02df690f614c03e4d906d1018062b5c5e2c" +dependencies = [ + "once_cell", + "proc-macro-crate", + "proc-macro2", + "quote", + "syn 2.0.117", +] + [[package]] name = "bumpalo" -version = "3.19.1" +version = "3.20.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5dd9dc738b7a8311c7ade152424974d8115f2cdad61e8dab8dac9f2362298510" +checksum = "5d20789868f4b01b2f2caec9f5c4e0213b41e3e5702a50157d699ae31ced2fcb" [[package]] name = "byte-slice-cast" @@ -568,6 +1237,21 @@ dependencies = [ "serde", ] +[[package]] +name = "c-kzg" +version = "2.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a0f582957c24870b7bfd12bf562c40b4734b533cafbaf8ded31d6d85f462c01" +dependencies = [ + "blst", + "cc", + "glob", + "hex", + "libc", + "once_cell", + "serde", +] + [[package]] name = "canonical-app" version = "0.1.0" @@ -575,11 +1259,21 @@ dependencies = [ "app-core", ] +[[package]] +name = "cartesi-rollups-contracts" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5492d925f2960dff0b1eeca7dae0784a5b9af727e879c0290e7a8213af001941" +dependencies = [ + "alloy", + "serde", +] + [[package]] name = "cc" -version = "1.2.55" +version = "1.2.56" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "47b26a0954ae34af09b50f0de26458fa95369a0d478d8236d3f93082b219bd29" +checksum = "aebf35691d1bfb0ac386a69bac2fde4dd276fb618cf8bf4f5318fe285e821bb2" dependencies = [ "find-msvc-tools", "shlex", @@ -591,6 +1285,24 @@ version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" +[[package]] +name = "cfg_aliases" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" + +[[package]] +name = "chrono" +version = "0.4.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c673075a2e0e5f4a1dde27ce9dee1ea4558c7ffe648f576438a20ca1d2acc4b0" +dependencies = [ + "iana-time-zone", + "num-traits", + "serde", + "windows-link", +] + [[package]] name = "clap" version = "4.5.60" @@ -622,7 +1334,7 @@ dependencies = [ "heck", "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.117", ] [[package]] @@ -639,9 +1351,9 @@ checksum = "b05b61dc5112cbb17e4b6cd61790d9845d13888356391624cbe7e41efeac1e75" [[package]] name = "const-hex" -version = "1.17.0" +version = "1.18.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3bb320cac8a0750d7f25280aa97b09c26edfe161164238ecbbb31092b079e735" +checksum = "531185e432bb31db1ecda541e9e7ab21468d4d844ad7505e0546a49b4945d49b" dependencies = [ "cfg-if", "cpufeatures", @@ -684,6 +1396,12 @@ dependencies = [ "unicode-segmentation", ] +[[package]] +name = "core-foundation-sys" +version = "0.8.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" + [[package]] name = "cpufeatures" version = "0.2.17" @@ -693,6 +1411,27 @@ dependencies = [ "libc", ] +[[package]] +name = "crc" +version = "3.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5eb8a2a1cd12ab0d987a5d5e825195d372001a4094a0376319d5a0ad71c1ba0d" +dependencies = [ + "crc-catalog", +] + +[[package]] +name = "crc-catalog" +version = "2.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19d374276b40fb8bbdee95aef7c7fa6b5316ec764510eb64b8dd0e2ed0d7e7f5" + +[[package]] +name = "crossbeam-utils" +version = "0.8.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" + [[package]] name = "crunchy" version = "0.2.4" @@ -721,14 +1460,39 @@ dependencies = [ "typenum", ] +[[package]] +name = "darling" +version = "0.21.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9cdf337090841a411e2a7f3deb9187445851f91b309c0c0a29e05f74a00a48c0" +dependencies = [ + "darling_core 0.21.3", + "darling_macro 0.21.3", +] + [[package]] name = "darling" version = "0.23.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "25ae13da2f202d56bd7f91c25fba009e7717a1e4a1cc98a76d844b65ae912e9d" dependencies = [ - "darling_core", - "darling_macro", + "darling_core 0.23.0", + "darling_macro 0.23.0", +] + +[[package]] +name = "darling_core" +version = "0.21.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1247195ecd7e3c85f83c8d2a366e4210d588e802133e1e355180a9870b517ea4" +dependencies = [ + "fnv", + "ident_case", + "proc-macro2", + "quote", + "serde", + "strsim", + "syn 2.0.117", ] [[package]] @@ -741,7 +1505,18 @@ dependencies = [ "proc-macro2", "quote", "strsim", - "syn 2.0.114", + "syn 2.0.117", +] + +[[package]] +name = "darling_macro" +version = "0.21.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d38308df82d1080de0afee5d069fa14b0326a88c14f15c5ccda35b4a6c414c81" +dependencies = [ + "darling_core 0.21.3", + "quote", + "syn 2.0.117", ] [[package]] @@ -750,9 +1525,23 @@ version = "0.23.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ac3984ec7bd6cfa798e62b4a642426a5be0e68f9401cfc2a01e3fa9ea2fcdb8d" dependencies = [ - "darling_core", + "darling_core 0.23.0", "quote", - "syn 2.0.114", + "syn 2.0.117", +] + +[[package]] +name = "dashmap" +version = "6.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5041cc499144891f3790297212f32a74fb938e5136a14943f338ef9e0ae276cf" +dependencies = [ + "cfg-if", + "crossbeam-utils", + "hashbrown 0.14.5", + "lock_api", + "once_cell", + "parking_lot_core", ] [[package]] @@ -771,6 +1560,16 @@ dependencies = [ "zeroize", ] +[[package]] +name = "deranged" +version = "0.5.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7cd812cc2bc1d69d4764bd80df88b4317eaef9e773c75226407d9bc0876b211c" +dependencies = [ + "powerfmt", + "serde_core", +] + [[package]] name = "derivative" version = "2.2.0" @@ -801,7 +1600,7 @@ dependencies = [ "proc-macro2", "quote", "rustc_version 0.4.1", - "syn 2.0.114", + "syn 2.0.117", "unicode-xid", ] @@ -826,12 +1625,29 @@ dependencies = [ "subtle", ] +[[package]] +name = "displaydoc" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + [[package]] name = "dunce" version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "92773504d58c093f6de2459af4af33faa518c13451eb8f2b5698ed3d36e7c813" +[[package]] +name = "dyn-clone" +version = "1.0.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d0881ea181b1df73ff77ffaaf9c7544ecc11e82fba9b5f27b262a3c73a332555" + [[package]] name = "ecdsa" version = "0.16.9" @@ -842,6 +1658,7 @@ dependencies = [ "digest 0.10.7", "elliptic-curve", "rfc6979", + "serdect", "signature", "spki", ] @@ -855,7 +1672,7 @@ dependencies = [ "enum-ordinalize", "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.117", ] [[package]] @@ -863,6 +1680,9 @@ name = "either" version = "1.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" +dependencies = [ + "serde", +] [[package]] name = "elliptic-curve" @@ -879,6 +1699,7 @@ dependencies = [ "pkcs8", "rand_core 0.6.4", "sec1", + "serdect", "subtle", "zeroize", ] @@ -900,7 +1721,7 @@ checksum = "8ca9601fb2d62598ee17836250842873a413586e5d7ed88b356e38ddbb0ec631" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.117", ] [[package]] @@ -953,10 +1774,10 @@ version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cd596f91cff004fc8d02be44c21c0f9b93140a04b66027ae052f5f8e05b48eba" dependencies = [ - "darling", + "darling 0.23.0", "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.117", ] [[package]] @@ -1033,6 +1854,12 @@ version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" +[[package]] +name = "foldhash" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2" + [[package]] name = "foldhash" version = "0.2.0" @@ -1054,59 +1881,100 @@ version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c" +[[package]] +name = "futures" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b147ee9d1f6d097cef9ce628cd2ee62288d963e16fb287bd9286455b241382d" +dependencies = [ + "futures-channel", + "futures-core", + "futures-executor", + "futures-io", + "futures-sink", + "futures-task", + "futures-util", +] + [[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", ] [[package]] name = "futures-core" -version = "0.3.31" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7e3450815272ef58cec6d564423f6e755e25379b217b0bc688e295ba24df6b1d" + +[[package]] +name = "futures-executor" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf29c38818342a3b26b5b923639e7b1f4a61fc5e76102d4b1981c6dc7a7579d" +dependencies = [ + "futures-core", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-io" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e" +checksum = "cecba35d7ad927e23624b22ad55235f2239cfa44fd10428eecbeba6d6a717718" [[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.114", + "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-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", + "futures-io", "futures-macro", "futures-sink", "futures-task", + "memchr", "pin-project-lite", - "pin-utils", "slab", ] +[[package]] +name = "futures-utils-wasm" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42012b0f064e01aa58b545fe3727f90f7dd4020f4a3ea735b50344965f5a57e9" + [[package]] name = "generic-array" version = "0.14.9" @@ -1125,8 +1993,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ff2abc00be7fca6ebc474524697ae276ad847ad0a6b3faa4bcb027e9a4614ad0" dependencies = [ "cfg-if", + "js-sys", "libc", "wasi", + "wasm-bindgen", ] [[package]] @@ -1134,22 +2004,64 @@ name = "getrandom" version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "899def5c37c4fd7b2664648c28120ecec138e4d395b459e5ca34f9cce2dd77fd" +dependencies = [ + "cfg-if", + "js-sys", + "libc", + "r-efi 5.3.0", + "wasip2", + "wasm-bindgen", +] + +[[package]] +name = "getrandom" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0de51e6874e94e7bf76d726fc5d13ba782deca734ff60d5bb2fb2607c7406555" dependencies = [ "cfg-if", "libc", - "r-efi", + "r-efi 6.0.0", "wasip2", + "wasip3", ] +[[package]] +name = "glob" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0cc23270f6e1808e30a928bdc84dea0b9b4136a8bc82338574f23baf47bbd280" + [[package]] name = "group" version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f0f9ef7462f7c099f518d754361858f86d8a07af53ba9af0fe635bbccb151a63" dependencies = [ - "ff", - "rand_core 0.6.4", - "subtle", + "ff", + "rand_core 0.6.4", + "subtle", +] + +[[package]] +name = "hashbrown" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" + +[[package]] +name = "hashbrown" +version = "0.14.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" + +[[package]] +name = "hashbrown" +version = "0.15.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1" +dependencies = [ + "foldhash 0.1.5", ] [[package]] @@ -1158,7 +2070,9 @@ version = "0.16.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "841d1cc9bed7f9236f321df977030373f4a4163ae1a7dbfe1a51a2c1a51d9100" dependencies = [ - "foldhash", + "allocator-api2", + "equivalent", + "foldhash 0.2.0", "serde", "serde_core", ] @@ -1169,7 +2083,7 @@ version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ea0b22561a9c04a7cb1a302c013e0259cd3b4bb619f145b32f72b8b4bcbed230" dependencies = [ - "hashbrown", + "hashbrown 0.16.1", ] [[package]] @@ -1178,12 +2092,27 @@ version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" +[[package]] +name = "hermit-abi" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc0fef456e4baa96da950455cd02c081ca953b141298e41db3fc7e36b1da849c" + [[package]] name = "hex" version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" +[[package]] +name = "hex-conservative" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fda06d18ac606267c40c04e41b9947729bf8b9efe74bd4e82b61a5f26a510b9f" +dependencies = [ + "arrayvec", +] + [[package]] name = "hmac" version = "0.12.1" @@ -1257,6 +2186,24 @@ dependencies = [ "pin-utils", "smallvec", "tokio", + "want", +] + +[[package]] +name = "hyper-rustls" +version = "0.27.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3c93eb611681b207e1fe55d5a71ecf91572ec8a6705cdb6857f7d8d5242cf58" +dependencies = [ + "http", + "hyper", + "hyper-util", + "rustls", + "rustls-pki-types", + "tokio", + "tokio-rustls", + "tower-service", + "webpki-roots", ] [[package]] @@ -1265,21 +2212,161 @@ version = "0.1.20" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "96547c2556ec9d12fb1578c4eaf448b04993e7fb79cbaad930a656880a6bdfa0" dependencies = [ + "base64", "bytes", + "futures-channel", + "futures-util", "http", "http-body", "hyper", + "ipnet", + "libc", + "percent-encoding", "pin-project-lite", + "socket2", "tokio", "tower-service", + "tracing", +] + +[[package]] +name = "iana-time-zone" +version = "0.1.65" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e31bc9ad994ba00e440a8aa5c9ef0ec67d5cb5e5cb0cc7f8b744a35b389cc470" +dependencies = [ + "android_system_properties", + "core-foundation-sys", + "iana-time-zone-haiku", + "js-sys", + "log", + "wasm-bindgen", + "windows-core", +] + +[[package]] +name = "iana-time-zone-haiku" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f" +dependencies = [ + "cc", +] + +[[package]] +name = "icu_collections" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c6b649701667bbe825c3b7e6388cb521c23d88644678e83c0c4d0a621a34b43" +dependencies = [ + "displaydoc", + "potential_utf", + "yoke", + "zerofrom", + "zerovec", +] + +[[package]] +name = "icu_locale_core" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "edba7861004dd3714265b4db54a3c390e880ab658fec5f7db895fae2046b5bb6" +dependencies = [ + "displaydoc", + "litemap", + "tinystr", + "writeable", + "zerovec", +] + +[[package]] +name = "icu_normalizer" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f6c8828b67bf8908d82127b2054ea1b4427ff0230ee9141c54251934ab1b599" +dependencies = [ + "icu_collections", + "icu_normalizer_data", + "icu_properties", + "icu_provider", + "smallvec", + "zerovec", +] + +[[package]] +name = "icu_normalizer_data" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7aedcccd01fc5fe81e6b489c15b247b8b0690feb23304303a9e560f37efc560a" + +[[package]] +name = "icu_properties" +version = "2.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "020bfc02fe870ec3a66d93e677ccca0562506e5872c650f893269e08615d74ec" +dependencies = [ + "icu_collections", + "icu_locale_core", + "icu_properties_data", + "icu_provider", + "zerotrie", + "zerovec", +] + +[[package]] +name = "icu_properties_data" +version = "2.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "616c294cf8d725c6afcd8f55abc17c56464ef6211f9ed59cccffe534129c77af" + +[[package]] +name = "icu_provider" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85962cf0ce02e1e0a629cc34e7ca3e373ce20dda4c4d7294bbd0bf1fdb59e614" +dependencies = [ + "displaydoc", + "icu_locale_core", + "writeable", + "yoke", + "zerofrom", + "zerotrie", + "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" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" +[[package]] +name = "idna" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b0875f23caa03898994f6ddc501886a45c7d3d62d04d2d90788d47be1b1e4de" +dependencies = [ + "idna_adapter", + "smallvec", + "utf8_iter", +] + +[[package]] +name = "idna_adapter" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3acae9609540aa318d1bc588455225fb2085b9ed0c4f6bd0d9d5bcd86f1a0344" +dependencies = [ + "icu_normalizer", + "icu_properties", +] + [[package]] name = "impl-codec" version = "0.6.0" @@ -1297,7 +2384,18 @@ checksum = "a0eb5a3343abf848c0984fe4604b2b105da9539376e24fc0a3b0007411ae4fd9" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.117", +] + +[[package]] +name = "indexmap" +version = "1.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" +dependencies = [ + "autocfg", + "hashbrown 0.12.3", + "serde", ] [[package]] @@ -1307,11 +2405,27 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7714e70437a7dc3ac8eb7e6f8df75fd8eb422675fc7678aff7364301092b1017" dependencies = [ "equivalent", - "hashbrown", + "hashbrown 0.16.1", "serde", "serde_core", ] +[[package]] +name = "ipnet" +version = "2.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d98f6fed1fde3f8c21bc40a1abb88dd75e67924f9cffc3ef95607bad8017f8e2" + +[[package]] +name = "iri-string" +version = "0.7.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c91338f0783edbd6195decb37bae672fd3b165faffb89bf7b9e6942f8b1a731a" +dependencies = [ + "memchr", + "serde", +] + [[package]] name = "is_terminal_polyfill" version = "1.70.2" @@ -1353,9 +2467,9 @@ checksum = "92ecc6618181def0457392ccd0ee51198e065e016d1d527a7ac1b6dc7c1f09d2" [[package]] name = "js-sys" -version = "0.3.85" +version = "0.3.91" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c942ebf8e95485ca0d52d97da7c5a2c387d0e7f0ba4c35e93bfcaee045955b3" +checksum = "b49715b7073f385ba4bc528e5747d02e66cb39c6146efb66b781f131f0fb399c" dependencies = [ "once_cell", "wasm-bindgen", @@ -1371,15 +2485,16 @@ dependencies = [ "ecdsa", "elliptic-curve", "once_cell", + "serdect", "sha2", "signature", ] [[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", ] @@ -1400,11 +2515,17 @@ 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 = "libc" -version = "0.2.180" +version = "0.2.182" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bcc35a38544a891a5f7c865aca548a982ccb3b8650a5b06d0fd33a10283c56fc" +checksum = "6800badb6cb2082ffd7b6a67e6125bb39f18782f793520caee8cb8846be06112" [[package]] name = "libm" @@ -1425,9 +2546,24 @@ dependencies = [ [[package]] name = "linux-raw-sys" -version = "0.11.0" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a66949e030da00e8c7d4434b251670a91556f4144941d37452769c25d58a53" + +[[package]] +name = "litemap" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6373607a59f0be73a39b6fe456b8192fcc3585f602af20751600e974dd455e77" + +[[package]] +name = "lock_api" +version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df1d3c3b53da64cf5760482273a98e575c651a67eec7f77df96b5b642de8f039" +checksum = "224399e74b87b5f3557511d98dff8b14089b3dadafcab6bb93eab67d3aace965" +dependencies = [ + "scopeguard", +] [[package]] name = "log" @@ -1435,6 +2571,21 @@ version = "0.4.29" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897" +[[package]] +name = "lru" +version = "0.16.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1dc47f592c06f33f8e3aea9591776ec7c9f9e4124778ff8a3c3b87159f7e593" +dependencies = [ + "hashbrown 0.16.1", +] + +[[package]] +name = "lru-slab" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "112b39cec0b298b6c1999fee3e31427f74f676e4cb9879ed1a121b43661a4154" + [[package]] name = "macro-string" version = "0.1.4" @@ -1443,7 +2594,7 @@ checksum = "1b27834086c65ec3f9387b096d66e99f221cf081c2b738042aa252bcd41204e3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.117", ] [[package]] @@ -1463,9 +2614,9 @@ checksum = "47e1ffaa40ddd1f3ed91f717a33c8c0ee23fff369e3aa8772b9605cc1d22f4c3" [[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 = "mime" @@ -1503,6 +2654,12 @@ dependencies = [ "num-traits", ] +[[package]] +name = "num-conv" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf97ec579c3c42f953ef76dbf8d55ac91fb219dde70e49aa4a6b7d74e9919050" + [[package]] name = "num-integer" version = "0.1.46" @@ -1522,6 +2679,51 @@ dependencies = [ "libm", ] +[[package]] +name = "num_cpus" +version = "1.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91df4bbde75afed763b708b7eee1e8e7651e02d97f6d5dd763e89367e957b23b" +dependencies = [ + "hermit-abi", + "libc", +] + +[[package]] +name = "num_enum" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1207a7e20ad57b847bbddc6776b968420d38292bbfe2089accff5e19e82454c" +dependencies = [ + "num_enum_derive", + "rustversion", +] + +[[package]] +name = "num_enum_derive" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff32365de1b6743cb203b710788263c44a03de03802daf96092f2da4fe6ba4d7" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "nybbles" +version = "0.4.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d49ff0c0d00d4a502b39df9af3a525e1efeb14b9dabb5bb83335284c1309210" +dependencies = [ + "alloy-rlp", + "cfg-if", + "proptest", + "ruint", + "serde", + "smallvec", +] + [[package]] name = "once_cell" version = "1.21.3" @@ -1559,7 +2761,30 @@ dependencies = [ "proc-macro-crate", "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.117", +] + +[[package]] +name = "parking_lot" +version = "0.12.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93857453250e3077bd71ff98b6a65ea6621a19bb0f559a85248955ac12c45a1a" +dependencies = [ + "lock_api", + "parking_lot_core", +] + +[[package]] +name = "parking_lot_core" +version = "0.9.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2621685985a2ebf1c516881c026032ac7deafcda1a2c9b7850dc81e3dfcb64c1" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall", + "smallvec", + "windows-link", ] [[package]] @@ -1584,11 +2809,31 @@ dependencies = [ "ucd-trie", ] +[[package]] +name = "pin-project" +version = "1.1.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1749c7ed4bcaf4c3d0a3efc28538844fb29bcdd7d2b67b2be7e20ba861ff517" +dependencies = [ + "pin-project-internal", +] + +[[package]] +name = "pin-project-internal" +version = "1.1.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9b20ed30f105399776b9c883e68e536ef602a16ae6f596d2c473591d6ad64c6" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + [[package]] name = "pin-project-lite" -version = "0.2.16" +version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b" +checksum = "a89322df9ebe1c1578d689c92318e070967d1042b512afbe49518723f4e6d5cd" [[package]] name = "pin-utils" @@ -1612,6 +2857,21 @@ version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c" +[[package]] +name = "potential_utf" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b73949432f5e2a09657003c25bca5e19a0e9c84f8058ca374f49e0ebe605af77" +dependencies = [ + "zerovec", +] + +[[package]] +name = "powerfmt" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" + [[package]] name = "ppv-lite86" version = "0.2.21" @@ -1621,6 +2881,16 @@ dependencies = [ "zerocopy", ] +[[package]] +name = "prettyplease" +version = "0.2.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "479ca8adacdd7ce8f1fb39ce9ecccbfe93a3f1344b3d0d97f20bc0196208f62b" +dependencies = [ + "proc-macro2", + "syn 2.0.117", +] + [[package]] name = "primitive-types" version = "0.12.2" @@ -1634,9 +2904,9 @@ dependencies = [ [[package]] name = "proc-macro-crate" -version = "3.4.0" +version = "3.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "219cb19e96be00ab2e37d6e299658a0cfa83e52429179969b0f0121b4ac46983" +checksum = "e67ba7e9b2b56446f1d419b1d807906278ffa1a658a8a5d8a39dcb1f5a78614f" dependencies = [ "toml_edit", ] @@ -1660,7 +2930,7 @@ dependencies = [ "proc-macro-error-attr2", "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.117", ] [[package]] @@ -1683,25 +2953,80 @@ dependencies = [ "bitflags", "num-traits", "rand 0.9.2", - "rand_chacha 0.9.0", - "rand_xorshift", - "regex-syntax", - "rusty-fork", - "tempfile", - "unarray", + "rand_chacha 0.9.0", + "rand_xorshift", + "regex-syntax", + "rusty-fork", + "tempfile", + "unarray", +] + +[[package]] +name = "quick-error" +version = "1.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0" + +[[package]] +name = "quinn" +version = "0.11.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9e20a958963c291dc322d98411f541009df2ced7b5a4f2bd52337638cfccf20" +dependencies = [ + "bytes", + "cfg_aliases", + "pin-project-lite", + "quinn-proto", + "quinn-udp", + "rustc-hash", + "rustls", + "socket2", + "thiserror 2.0.18", + "tokio", + "tracing", + "web-time", +] + +[[package]] +name = "quinn-proto" +version = "0.11.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1906b49b0c3bc04b5fe5d86a77925ae6524a19b816ae38ce1e426255f1d8a31" +dependencies = [ + "bytes", + "getrandom 0.3.4", + "lru-slab", + "rand 0.9.2", + "ring", + "rustc-hash", + "rustls", + "rustls-pki-types", + "slab", + "thiserror 2.0.18", + "tinyvec", + "tracing", + "web-time", ] [[package]] -name = "quick-error" -version = "1.2.3" +name = "quinn-udp" +version = "0.5.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0" +checksum = "addec6a0dcad8a8d96a771f815f0eaf55f9d1805756410b39f5fa81332574cbd" +dependencies = [ + "cfg_aliases", + "libc", + "once_cell", + "socket2", + "tracing", + "windows-sys 0.60.2", +] [[package]] name = "quote" -version = "1.0.44" +version = "1.0.45" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21b2ebcf727b7760c461f091f9f0f539b77b8e87f2fd88131e7f1b433b3cece4" +checksum = "41f2619966050689382d2b44f664f4bc593e129785a36d6ee376ddf37259b924" dependencies = [ "proc-macro2", ] @@ -1712,6 +3037,12 @@ version = "5.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" +[[package]] +name = "r-efi" +version = "6.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8dcc9c7d52a811697d2151c701e0d08956f92b0e24136cf4cf27b57a6a0d9bf" + [[package]] name = "radium" version = "0.7.0" @@ -1727,6 +3058,7 @@ dependencies = [ "libc", "rand_chacha 0.3.1", "rand_core 0.6.4", + "serde", ] [[package]] @@ -1790,13 +3122,42 @@ dependencies = [ [[package]] name = "rapidhash" -version = "4.2.1" +version = "4.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d8b5b858a440a0bc02625b62dd95131b9201aa9f69f411195dd4a7cfb1de3d7" +checksum = "b5e48930979c155e2f33aa36ab3119b5ee81332beb6482199a8ecd6029b80b59" dependencies = [ "rustversion", ] +[[package]] +name = "redox_syscall" +version = "0.5.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed2bf2547551a7053d6fdfafda3f938979645c44812fbfcda098faae3f1a362d" +dependencies = [ + "bitflags", +] + +[[package]] +name = "ref-cast" +version = "1.0.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f354300ae66f76f1c85c5f84693f0ce81d747e2c3f21a45fef496d89c960bf7d" +dependencies = [ + "ref-cast-impl", +] + +[[package]] +name = "ref-cast-impl" +version = "1.0.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b7186006dcb21920990093f30e3dea63b7d6e977bf1256be20c3563a5db070da" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + [[package]] name = "regex-automata" version = "0.4.14" @@ -1810,9 +3171,47 @@ dependencies = [ [[package]] name = "regex-syntax" -version = "0.8.9" +version = "0.8.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc897dd8d9e8bd1ed8cdad82b5966c3e0ecae09fb1907d58efaa013543185d0a" + +[[package]] +name = "reqwest" +version = "0.12.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a96887878f22d7bad8a3b6dc5b7440e0ada9a245242924394987b21cf2210a4c" +checksum = "eddd3ca559203180a307f12d114c268abf583f59b03cb906fd0b3ff8646c1147" +dependencies = [ + "base64", + "bytes", + "futures-core", + "http", + "http-body", + "http-body-util", + "hyper", + "hyper-rustls", + "hyper-util", + "js-sys", + "log", + "percent-encoding", + "pin-project-lite", + "quinn", + "rustls", + "rustls-pki-types", + "serde", + "serde_json", + "serde_urlencoded", + "sync_wrapper", + "tokio", + "tokio-rustls", + "tower", + "tower-http", + "tower-service", + "url", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", + "webpki-roots", +] [[package]] name = "rfc6979" @@ -1824,6 +3223,20 @@ dependencies = [ "subtle", ] +[[package]] +name = "ring" +version = "0.17.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4689e6c2294d81e88dc6261c768b63bc4fcdb852be6d1352498b114f61383b7" +dependencies = [ + "cc", + "cfg-if", + "getrandom 0.2.17", + "libc", + "untrusted", + "windows-sys 0.52.0", +] + [[package]] name = "rlp" version = "0.5.2" @@ -1840,7 +3253,7 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a8a1f2315036ef6b1fbacd1972e8ee7688030b0a2121edfc2a6550febd41574d" dependencies = [ - "hashbrown", + "hashbrown 0.16.1", "thiserror 2.0.18", ] @@ -1935,9 +3348,9 @@ dependencies = [ [[package]] name = "rustix" -version = "1.1.3" +version = "1.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "146c9e247ccc180c1f61615433868c99f3de3ae256a30a43b49f67c2d9171f34" +checksum = "b6fe4565b9518b83ef4f91bb47ce29620ca828bd32cb7e408f0062e9930ba190" dependencies = [ "bitflags", "errno", @@ -1946,6 +3359,41 @@ dependencies = [ "windows-sys 0.61.2", ] +[[package]] +name = "rustls" +version = "0.23.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "758025cb5fccfd3bc2fd74708fd4682be41d99e5dff73c377c0646c6012c73a4" +dependencies = [ + "once_cell", + "ring", + "rustls-pki-types", + "rustls-webpki", + "subtle", + "zeroize", +] + +[[package]] +name = "rustls-pki-types" +version = "1.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be040f8b0a225e40375822a563fa9524378b9d63112f53e19ffff34df5d33fdd" +dependencies = [ + "web-time", + "zeroize", +] + +[[package]] +name = "rustls-webpki" +version = "0.103.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d7df23109aa6c1567d1c575b9952556388da57401e4ace1d15f79eedad0d8f53" +dependencies = [ + "ring", + "rustls-pki-types", + "untrusted", +] + [[package]] name = "rustversion" version = "1.0.22" @@ -1966,9 +3414,39 @@ dependencies = [ [[package]] name = "ryu" -version = "1.0.22" +version = "1.0.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9774ba4a74de5f7b1c1451ed6cd5285a32eddb5cccb8cc655a4e50009e06477f" + +[[package]] +name = "schemars" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4cd191f9397d57d581cddd31014772520aa448f65ef991055d7f61582c65165f" +dependencies = [ + "dyn-clone", + "ref-cast", + "serde", + "serde_json", +] + +[[package]] +name = "schemars" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2b42f36aa1cd011945615b92222f6bf73c599a102a300334cd7f8dbeec726cc" +dependencies = [ + "dyn-clone", + "ref-cast", + "serde", + "serde_json", +] + +[[package]] +name = "scopeguard" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a50f4cf475b65d88e057964e0e9bb1f0aa9bbb2036dc65c64596b42932536984" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" [[package]] name = "sec1" @@ -1980,10 +3458,32 @@ dependencies = [ "der", "generic-array", "pkcs8", + "serdect", "subtle", "zeroize", ] +[[package]] +name = "secp256k1" +version = "0.30.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b50c5943d326858130af85e049f2661ba3c78b26589b8ab98e65e80ae44a1252" +dependencies = [ + "bitcoin_hashes", + "rand 0.8.5", + "secp256k1-sys", + "serde", +] + +[[package]] +name = "secp256k1-sys" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d4387882333d3aa8cb20530a17c69a3752e97837832f34f6dccc760e715001d9" +dependencies = [ + "cc", +] + [[package]] name = "semver" version = "0.11.0" @@ -2012,10 +3512,13 @@ dependencies = [ name = "sequencer" version = "0.1.0" dependencies = [ + "alloy", "alloy-primitives", "alloy-sol-types", "app-core", + "async-recursion", "axum", + "cartesi-rollups-contracts", "clap", "ethereum_ssz", "ethereum_ssz_derive", @@ -2035,6 +3538,7 @@ dependencies = [ "tower-http", "tracing", "tracing-subscriber", + "url", ] [[package]] @@ -2087,7 +3591,7 @@ checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.117", ] [[package]] @@ -2126,6 +3630,47 @@ dependencies = [ "serde", ] +[[package]] +name = "serde_with" +version = "3.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "381b283ce7bc6b476d903296fb59d0d36633652b633b27f64db4fb46dcbfc3b9" +dependencies = [ + "base64", + "chrono", + "hex", + "indexmap 1.9.3", + "indexmap 2.13.0", + "schemars 0.9.0", + "schemars 1.2.1", + "serde_core", + "serde_json", + "serde_with_macros", + "time", +] + +[[package]] +name = "serde_with_macros" +version = "3.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a6d4e30573c8cb306ed6ab1dca8423eec9a463ea0e155f45399455e0368b27e0" +dependencies = [ + "darling 0.21.3", + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "serdect" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a84f14a19e9a014bb9f4512488d9829a68e04ecabffb0f9904cd1ace94598177" +dependencies = [ + "base16ct", + "serde", +] + [[package]] name = "sha1" version = "0.10.6" @@ -2185,10 +3730,11 @@ checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" [[package]] name = "signal-hook-registry" -version = "1.4.6" +version = "1.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2a4719bff48cee6b39d12c020eeb490953ad2443b7055bd0b21fca26bd8c28b" +checksum = "c4db69cba1110affc0e9f7bcd48bbf87b3f4fc7c61fc9155afd4c469eb3d6c1b" dependencies = [ + "errno", "libc", ] @@ -2213,6 +3759,9 @@ name = "smallvec" version = "1.15.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" +dependencies = [ + "serde", +] [[package]] name = "socket2" @@ -2246,6 +3795,12 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "stable_deref_trait" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ce2be8dc25455e1f91df71bfa12ad37d7af1092ae736f3a6cd0e37bc7810596" + [[package]] name = "static_assertions" version = "1.1.0" @@ -2258,6 +3813,27 @@ version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" +[[package]] +name = "strum" +version = "0.27.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af23d6f6c1a224baef9d3f61e287d2761385a5b88fdab4eb4c6f11aeb54c4bcf" +dependencies = [ + "strum_macros", +] + +[[package]] +name = "strum_macros" +version = "0.27.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7695ce3845ea4b33927c055a39dc438a45b059f7c1b3d91d38d10355fb8cbca7" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "syn 2.0.117", +] + [[package]] name = "subtle" version = "2.6.1" @@ -2277,9 +3853,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.114" +version = "2.0.117" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d4d107df263a3013ef9b1879b0df87d706ff80f65a86ea879bd9c31f9b307c2a" +checksum = "e665b8803e7b1d2a727f4023456bbbbe74da67099c585258af0ad9c5013b9b99" dependencies = [ "proc-macro2", "quote", @@ -2288,14 +3864,14 @@ dependencies = [ [[package]] name = "syn-solidity" -version = "1.5.4" +version = "1.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2379beea9476b89d0237078be761cf8e012d92d5ae4ae0c9a329f974838870fc" +checksum = "53f425ae0b12e2f5ae65542e00898d500d4d318b4baf09f40fd0d410454e9947" dependencies = [ "paste", "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.117", ] [[package]] @@ -2303,6 +3879,20 @@ name = "sync_wrapper" version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0bf256ce5efdfa370213c1dabab5935a12e49f2c58d15e9eac2870d3b4f27263" +dependencies = [ + "futures-core", +] + +[[package]] +name = "synstructure" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] [[package]] name = "tap" @@ -2312,12 +3902,12 @@ checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" [[package]] name = "tempfile" -version = "3.24.0" +version = "3.26.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "655da9c7eb6305c55742045d5a8d2037996d61d8de95806335c7c86ce0f82e9c" +checksum = "82a72c767771b47409d2345987fda8628641887d5466101319899796367354a0" dependencies = [ "fastrand", - "getrandom 0.3.4", + "getrandom 0.4.2", "once_cell", "rustix", "windows-sys 0.61.2", @@ -2349,7 +3939,7 @@ checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.117", ] [[package]] @@ -2360,7 +3950,7 @@ checksum = "ebc4ee7f67670e9b64d05fa4253e753e016c6c95ff35b89b7941d6b856dec1d5" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.117", ] [[package]] @@ -2372,11 +3962,76 @@ dependencies = [ "cfg-if", ] +[[package]] +name = "threadpool" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d050e60b33d41c19108b32cea32164033a9013fe3b46cbd4457559bfbf77afaa" +dependencies = [ + "num_cpus", +] + +[[package]] +name = "time" +version = "0.3.47" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "743bd48c283afc0388f9b8827b976905fb217ad9e647fae3a379a9283c4def2c" +dependencies = [ + "deranged", + "itoa", + "num-conv", + "powerfmt", + "serde_core", + "time-core", + "time-macros", +] + +[[package]] +name = "time-core" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7694e1cfe791f8d31026952abf09c69ca6f6fa4e1a1229e18988f06a04a12dca" + +[[package]] +name = "time-macros" +version = "0.2.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e70e4c5a0e0a8a4823ad65dfe1a6930e4f4d756dcd9dd7939022b5e8c501215" +dependencies = [ + "num-conv", + "time-core", +] + +[[package]] +name = "tinystr" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42d3e9c45c09de15d06dd8acf5f4e0e399e85927b7f00711024eb7ae10fa4869" +dependencies = [ + "displaydoc", + "zerovec", +] + +[[package]] +name = "tinyvec" +version = "1.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa5fdc3bce6191a1dbc8c02d5c8bffcf557bafa17c124c5264a458f1b0613fa" +dependencies = [ + "tinyvec_macros", +] + +[[package]] +name = "tinyvec_macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" + [[package]] name = "tokio" -version = "1.49.0" +version = "1.50.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72a2903cd7736441aac9df9d7688bd0ce48edccaadf181c3b90be801e81d3d86" +checksum = "27ad5e34374e03cfffefc301becb44e9dc3c17584f414349ebe29ed26661822d" dependencies = [ "bytes", "libc", @@ -2390,13 +4045,35 @@ dependencies = [ [[package]] name = "tokio-macros" -version = "2.6.0" +version = "2.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af407857209536a95c8e56f8231ef2c2e2aff839b22e07a1ffcbc617e9db9fa5" +checksum = "5c55a2eff8b69ce66c84f85e1da1c233edc36ceb85a2058d11b0d6a3c7e7569c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.117", +] + +[[package]] +name = "tokio-rustls" +version = "0.26.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1729aa945f29d91ba541258c8df89027d5792d85a8841fb65e8bf0f4ede4ef61" +dependencies = [ + "rustls", + "tokio", +] + +[[package]] +name = "tokio-stream" +version = "0.1.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32da49809aab5c3bc678af03902d4ccddea2a87d028d86392a4b1560c6906c70" +dependencies = [ + "futures-core", + "pin-project-lite", + "tokio", + "tokio-util", ] [[package]] @@ -2426,20 +4103,20 @@ dependencies = [ [[package]] name = "toml_datetime" -version = "0.7.5+spec-1.1.0" +version = "1.0.0+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92e1cfed4a3038bc5a127e35a2d360f145e1f4b971b551a2ba5fd7aedf7e1347" +checksum = "32c2555c699578a4f59f0cc68e5116c8d7cabbd45e1409b989d4be085b53f13e" dependencies = [ "serde_core", ] [[package]] name = "toml_edit" -version = "0.23.10+spec-1.0.0" +version = "0.25.4+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "84c8b9f757e028cee9fa244aea147aab2a9ec09d5325a9b01e0a49730c2b5269" +checksum = "7193cbd0ce53dc966037f54351dbbcf0d5a642c7f0038c382ef9e677ce8c13f2" dependencies = [ - "indexmap", + "indexmap 2.13.0", "toml_datetime", "toml_parser", "winnow", @@ -2447,9 +4124,9 @@ dependencies = [ [[package]] name = "toml_parser" -version = "1.0.6+spec-1.1.0" +version = "1.0.9+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3198b4b0a8e11f09dd03e133c0280504d0801269e9afa46362ffde1cbeebf44" +checksum = "702d4415e08923e7e1ef96cd5727c0dfed80b4d2fa25db9647fe5eb6f7c5a4c4" dependencies = [ "winnow", ] @@ -2479,9 +4156,12 @@ checksum = "d4e6559d53cc268e5031cd8429d05415bc4cb4aefc4aa5d6cc35fbf5b924a1f8" dependencies = [ "bitflags", "bytes", + "futures-util", "http", "http-body", + "iri-string", "pin-project-lite", + "tower", "tower-layer", "tower-service", "tracing", @@ -2519,7 +4199,7 @@ checksum = "7490cfa5ec963746568740651ac6781f701c9c5ea257c58e057f3ba8cf69e8da" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.117", ] [[package]] @@ -2561,6 +4241,12 @@ dependencies = [ "tracing-log", ] +[[package]] +name = "try-lock" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" + [[package]] name = "tungstenite" version = "0.28.0" @@ -2610,21 +4296,40 @@ checksum = "eaea85b334db583fe3274d12b4cd1880032beab409c0d774be044d4480ab9a94" [[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-segmentation" version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6ccf251212114b54433ec949fd6a7841275f9ada20dddd2f29e9ceea4501493" +checksum = "f6ccf251212114b54433ec949fd6a7841275f9ada20dddd2f29e9ceea4501493" + +[[package]] +name = "unicode-xid" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" + +[[package]] +name = "untrusted" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" [[package]] -name = "unicode-xid" -version = "0.2.6" +name = "url" +version = "2.5.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" +checksum = "ff67a8a4397373c3ef660812acab3268222035010ab8680ec4215f38ba3d0eed" +dependencies = [ + "form_urlencoded", + "idna", + "percent-encoding", + "serde", + "serde_derive", +] [[package]] name = "utf-8" @@ -2632,6 +4337,12 @@ version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9" +[[package]] +name = "utf8_iter" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" + [[package]] name = "utf8parse" version = "0.2.2" @@ -2665,6 +4376,15 @@ dependencies = [ "libc", ] +[[package]] +name = "want" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e" +dependencies = [ + "try-lock", +] + [[package]] name = "wasi" version = "0.11.1+wasi-snapshot-preview1" @@ -2680,11 +4400,20 @@ 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 = "5428f8bf88ea5ddc08faddef2ac4a67e390b88186c703ce6dbd955e1c145aca5" +dependencies = [ + "wit-bindgen", +] + [[package]] name = "wasm-bindgen" -version = "0.2.108" +version = "0.2.114" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64024a30ec1e37399cf85a7ffefebdb72205ca1c972291c51512360d90bd8566" +checksum = "6532f9a5c1ece3798cb1c2cfdba640b9b3ba884f5db45973a6f442510a87d38e" dependencies = [ "cfg-if", "once_cell", @@ -2693,11 +4422,25 @@ dependencies = [ "wasm-bindgen-shared", ] +[[package]] +name = "wasm-bindgen-futures" +version = "0.4.64" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e9c5522b3a28661442748e09d40924dfb9ca614b21c00d3fd135720e48b67db8" +dependencies = [ + "cfg-if", + "futures-util", + "js-sys", + "once_cell", + "wasm-bindgen", + "web-sys", +] + [[package]] name = "wasm-bindgen-macro" -version = "0.2.108" +version = "0.2.114" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "008b239d9c740232e71bd39e8ef6429d27097518b6b30bdf9086833bd5b6d608" +checksum = "18a2d50fcf105fb33bb15f00e7a77b772945a2ee45dcf454961fd843e74c18e6" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -2705,39 +4448,178 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.108" +version = "0.2.114" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5256bae2d58f54820e6490f9839c49780dff84c65aeab9e772f15d5f0e913a55" +checksum = "03ce4caeaac547cdf713d280eda22a730824dd11e6b8c3ca9e42247b25c631e3" dependencies = [ "bumpalo", "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.117", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.108" +version = "0.2.114" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f01b580c9ac74c8d8f0c0e4afb04eeef2acf145458e52c03845ee9cd23e3d12" +checksum = "75a326b8c223ee17883a4251907455a2431acc2791c98c26279376490c378c16" 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 = "wasmparser" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "47b807c72e1bac69382b3a6fb3dbe8ea4c0ed87ff5629b8685ae6b9a611028fe" +dependencies = [ + "bitflags", + "hashbrown 0.15.5", + "indexmap 2.13.0", + "semver 1.0.27", +] + +[[package]] +name = "wasmtimer" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1c598d6b99ea013e35844697fc4670d08339d5cda15588f193c6beedd12f644b" +dependencies = [ + "futures", + "js-sys", + "parking_lot", + "pin-utils", + "slab", + "wasm-bindgen", +] + +[[package]] +name = "web-sys" +version = "0.3.91" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "854ba17bb104abfb26ba36da9729addc7ce7f06f5c0f90f3c391f8461cca21f9" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "web-time" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a6580f308b1fad9207618087a65c04e7a10bc77e02c8e84e9b00dd4b12fa0bb" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "webpki-roots" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22cfaf3c063993ff62e73cb4311efde4db1efb31ab78a3e5c457939ad5cc0bed" +dependencies = [ + "rustls-pki-types", +] + +[[package]] +name = "windows-core" +version = "0.62.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8e83a14d34d0623b51dce9581199302a221863196a1dde71a7663a4c2be9deb" +dependencies = [ + "windows-implement", + "windows-interface", + "windows-link", + "windows-result", + "windows-strings", +] + +[[package]] +name = "windows-implement" +version = "0.60.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "053e2e040ab57b9dc951b72c264860db7eb3b0200ba345b4e4c3b14f67855ddf" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "windows-interface" +version = "0.59.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f316c4a2570ba26bbec722032c4099d8c8bc095efccdc15688708623367e358" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + [[package]] name = "windows-link" version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" +[[package]] +name = "windows-result" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7781fa89eaf60850ac3d2da7af8e5242a5ea78d1a11c49bf2910bb5a73853eb5" +dependencies = [ + "windows-link", +] + +[[package]] +name = "windows-strings" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7837d08f69c77cf6b07689544538e017c1bfcf57e34b4c0ff58e6c2cd3b37091" +dependencies = [ + "windows-link", +] + +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets 0.52.6", +] + [[package]] name = "windows-sys" version = "0.60.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f2f500e4d28234f72040990ec9d39e3a6b950f9f22d3dba18416c35882612bcb" dependencies = [ - "windows-targets", + "windows-targets 0.53.5", ] [[package]] @@ -2749,6 +4631,22 @@ dependencies = [ "windows-link", ] +[[package]] +name = "windows-targets" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" +dependencies = [ + "windows_aarch64_gnullvm 0.52.6", + "windows_aarch64_msvc 0.52.6", + "windows_i686_gnu 0.52.6", + "windows_i686_gnullvm 0.52.6", + "windows_i686_msvc 0.52.6", + "windows_x86_64_gnu 0.52.6", + "windows_x86_64_gnullvm 0.52.6", + "windows_x86_64_msvc 0.52.6", +] + [[package]] name = "windows-targets" version = "0.53.5" @@ -2756,58 +4654,106 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4945f9f551b88e0d65f3db0bc25c33b8acea4d9e41163edf90dcd0b19f9069f3" dependencies = [ "windows-link", - "windows_aarch64_gnullvm", - "windows_aarch64_msvc", - "windows_i686_gnu", - "windows_i686_gnullvm", - "windows_i686_msvc", - "windows_x86_64_gnu", - "windows_x86_64_gnullvm", - "windows_x86_64_msvc", + "windows_aarch64_gnullvm 0.53.1", + "windows_aarch64_msvc 0.53.1", + "windows_i686_gnu 0.53.1", + "windows_i686_gnullvm 0.53.1", + "windows_i686_msvc 0.53.1", + "windows_x86_64_gnu 0.53.1", + "windows_x86_64_gnullvm 0.53.1", + "windows_x86_64_msvc 0.53.1", ] +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" + [[package]] name = "windows_aarch64_gnullvm" version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a9d8416fa8b42f5c947f8482c43e7d89e73a173cead56d044f6a56104a6d1b53" +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" + [[package]] name = "windows_aarch64_msvc" version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b9d782e804c2f632e395708e99a94275910eb9100b2114651e04744e9b125006" +[[package]] +name = "windows_i686_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" + [[package]] name = "windows_i686_gnu" version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "960e6da069d81e09becb0ca57a65220ddff016ff2d6af6a223cf372a506593a3" +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" + [[package]] name = "windows_i686_gnullvm" version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fa7359d10048f68ab8b09fa71c3daccfb0e9b559aed648a8f95469c27057180c" +[[package]] +name = "windows_i686_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" + [[package]] name = "windows_i686_msvc" version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e7ac75179f18232fe9c285163565a57ef8d3c89254a30685b57d83a38d326c2" +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" + [[package]] name = "windows_x86_64_gnu" version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c3842cdd74a865a8066ab39c8a7a473c0778a3f29370b5fd6b4b9aa7df4a499" +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" + [[package]] name = "windows_x86_64_gnullvm" version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0ffa179e2d07eee8ad8f57493436566c7cc30ac536a3379fdf008f47f6bb7ae1" +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" + [[package]] name = "windows_x86_64_msvc" version = "0.53.1" @@ -2828,6 +4774,94 @@ name = "wit-bindgen" 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", + "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", + "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", + "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 = "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" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9edde0db4769d2dc68579893f2306b26c6ecfbe0ef499b013d731b7b9247e0b9" [[package]] name = "wyz" @@ -2838,24 +4872,68 @@ dependencies = [ "tap", ] +[[package]] +name = "yoke" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72d6e5c6afb84d73944e5cedb052c4680d5657337201555f9f2a16b7406d4954" +dependencies = [ + "stable_deref_trait", + "yoke-derive", + "zerofrom", +] + +[[package]] +name = "yoke-derive" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b659052874eb698efe5b9e8cf382204678a0086ebf46982b79d6ca3182927e5d" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", + "synstructure", +] + [[package]] name = "zerocopy" -version = "0.8.38" +version = "0.8.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57cf3aa6855b23711ee9852dfc97dfaa51c45feaba5b645d0c777414d494a961" +checksum = "a789c6e490b576db9f7e6b6d661bcc9799f7c0ac8352f56ea20193b2681532e5" dependencies = [ "zerocopy-derive", ] [[package]] name = "zerocopy-derive" -version = "0.8.38" +version = "0.8.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a616990af1a287837c4fe6596ad77ef57948f787e46ce28e166facc0cc1cb75" +checksum = "f65c489a7071a749c849713807783f70672b28094011623e200cb86dcb835953" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.117", +] + +[[package]] +name = "zerofrom" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50cc42e0333e05660c3587f3bf9d0478688e15d870fab3346451ce7f8c9fbea5" +dependencies = [ + "zerofrom-derive", +] + +[[package]] +name = "zerofrom-derive" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", + "synstructure", ] [[package]] @@ -2875,11 +4953,44 @@ checksum = "85a5b4158499876c763cb03bc4e49185d3cccbabb15b33c627f7884f43db852e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.117", +] + +[[package]] +name = "zerotrie" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a59c17a5562d507e4b54960e8569ebee33bee890c70aa3fe7b97e85a9fd7851" +dependencies = [ + "displaydoc", + "yoke", + "zerofrom", +] + +[[package]] +name = "zerovec" +version = "0.11.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c28719294829477f525be0186d13efa9a3c602f7ec202ca9e353d310fb9a002" +dependencies = [ + "yoke", + "zerofrom", + "zerovec-derive", +] + +[[package]] +name = "zerovec-derive" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eadce39539ca5cb3985590102671f2567e659fca9666581ad3411d59207951f3" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", ] [[package]] name = "zmij" -version = "1.0.19" +version = "1.0.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ff05f8caa9038894637571ae6b9e29466c1f4f829d26c9b28f869a29cbe3445" +checksum = "b8848ee67ecc8aedbaf3e4122217aff892639231befc6a1b58d29fff4c2cabaa" diff --git a/sequencer/Cargo.toml b/sequencer/Cargo.toml index e345f96..1cdc57f 100644 --- a/sequencer/Cargo.toml +++ b/sequencer/Cargo.toml @@ -12,24 +12,29 @@ authors.workspace = true [dependencies] app-core = { path = "../examples/app-core" } sequencer-core = { path = "../sequencer-core" } +alloy = { version = "1.4", default-features = false, features = ["contract", "provider-http", "rpc-types", "eips"] } +alloy-primitives = { version = "1.4.1", features = ["serde", "k256"] } +alloy-sol-types = "1.4.1" +cartesi-rollups-contracts = "2.1.1" +async-recursion = "1.0" axum = { version = "0.8.8", features = ["ws"] } -tokio = { version = "1.35", features = ["macros", "rt-multi-thread", "sync", "time", "net"] } +rusqlite = { version = "0.38.0", features = ["bundled"] } +rusqlite_migration = "2.3.0" serde = { version = "1", features = ["derive"] } serde_json = "1" +ssz = { package = "ethereum_ssz", version = "0.10" } +ssz_derive = { package = "ethereum_ssz_derive", version = "0.10" } +thiserror = "1" +tokio = { version = "1.35", features = ["macros", "rt-multi-thread", "sync", "time", "net"] } +url = "2" tracing = "0.1" tracing-subscriber = { version = "0.3", features = ["env-filter"] } tower-http = { version = "0.6.8", features = ["trace"] } tower = { version = "0.5", features = ["limit", "load-shed", "util"] } -rusqlite = { version = "0.38.0", features = ["bundled"] } -rusqlite_migration = "2.3.0" -alloy-primitives = { version = "1.4.1", features = ["serde", "k256"] } -alloy-sol-types = "1.4.1" -thiserror = "1" -ssz = { package = "ethereum_ssz", version = "0.10" } -ssz_derive = { package = "ethereum_ssz_derive", version = "0.10" } clap = { version = "4", features = ["derive", "env"] } [dev-dependencies] +alloy = { version = "1.4", default-features = false, features = ["contract", "provider-http", "rpc-types", "eips", "node-bindings"] } futures-util = "0.3" tokio-tungstenite = "0.28" k256 = "0.13.4" diff --git a/sequencer/src/inclusion_lane/lane.rs b/sequencer/src/inclusion_lane/lane.rs index 3ecd1fa..f5e1908 100644 --- a/sequencer/src/inclusion_lane/lane.rs +++ b/sequencer/src/inclusion_lane/lane.rs @@ -609,6 +609,7 @@ mod tests { .append_safe_direct_inputs(&[crate::storage::IndexedDirectInput { index: 0, payload: vec![0xaa], + block_number: 0, }]) .expect("append safe direct input"); @@ -637,6 +638,7 @@ mod tests { directs.push(crate::storage::IndexedDirectInput { index, payload: vec![index as u8], + block_number: 0, }); } feeder_storage diff --git a/sequencer/src/input_reader/mod.rs b/sequencer/src/input_reader/mod.rs new file mode 100644 index 0000000..16c289e --- /dev/null +++ b/sequencer/src/input_reader/mod.rs @@ -0,0 +1,9 @@ +// (c) Cartesi and individual authors (see AUTHORS) +// SPDX-License-Identifier: Apache-2.0 (see LICENSE) + +//! Reads safe (direct) inputs from a reference source (e.g. InputBox contract) and appends them +//! to sequencer storage. Minimal design: no epochs or consensus; flat contiguous indices only. + +mod reader; + +pub use reader::{InputReader, InputReaderConfig, InputReaderError, InputReaderStop}; diff --git a/sequencer/src/input_reader/reader.rs b/sequencer/src/input_reader/reader.rs new file mode 100644 index 0000000..a4f7084 --- /dev/null +++ b/sequencer/src/input_reader/reader.rs @@ -0,0 +1,564 @@ +// (c) Cartesi and individual authors (see AUTHORS) +// SPDX-License-Identifier: Apache-2.0 (see LICENSE) + +use std::sync::Arc; +use std::sync::atomic::{AtomicBool, Ordering}; +use std::time::Duration; + +use alloy::contract::Error as ContractError; +use alloy::contract::Event; +use alloy::eips::BlockNumberOrTag::Safe; +use alloy::providers::Provider; +use alloy::rpc::types::Topic; +use alloy::sol_types::SolEvent; +use alloy_primitives::Address; +use async_recursion::async_recursion; +use cartesi_rollups_contracts::input_box::InputBox::InputAdded; +use tokio::runtime::Builder; +use tokio::task::JoinHandle; +use tracing::{info, trace}; + +use crate::storage::{IndexedDirectInput, Storage}; + +#[derive(Debug, Clone)] +pub struct InputReaderConfig { + /// RPC URL for the reference node (e.g. L1 or authority node). + pub rpc_url: String, + /// Contract address that emits InputAdded (e.g. InputBox). + pub input_box_address: Address, + /// Application address to filter inputs (topic1). Only InputAdded events for this app are ingested. + pub app_address_filter: Address, + /// First block to scan (e.g. InputBox deployment block). + pub genesis_block: u64, + /// Poll interval when no new blocks. + pub poll_interval: Duration, + /// RPC error substrings that trigger partition retry for large block ranges. + pub long_block_range_error_codes: Vec, +} + +#[derive(Debug, thiserror::Error)] +pub enum InputReaderError { + #[error("provider/transport: {0}")] + Provider(String), + #[error("storage: {0}")] + Storage(#[from] rusqlite::Error), + #[error("shutdown requested")] + ShutdownRequested, +} + +/// Reads InputAdded events in a block range. Retries with half-range partition on configured RPC errors. +#[async_recursion] +async fn get_input_added_events( + provider: &impl Provider, + topic1: Option<&Topic>, + read_from: &Address, + start_block: u64, + end_block: u64, + long_block_range_error_codes: &[String], +) -> Result, Vec> { + let event = { + let mut e = Event::new_sol(provider, read_from) + .from_block(start_block) + .to_block(end_block) + .event(InputAdded::SIGNATURE); + if let Some(t) = topic1 { + e = e.topic1(t.clone()); + } + e + }; + + match event.query().await { + Ok(logs) => Ok(logs), + Err(e) => { + if should_retry_with_partition(&e, long_block_range_error_codes) { + if start_block >= end_block { + return Err(vec![e]); + } + let middle = start_block + (end_block - start_block) / 2; + + let first = get_input_added_events( + provider, + topic1, + read_from, + start_block, + middle, + long_block_range_error_codes, + ) + .await; + let second = get_input_added_events( + provider, + topic1, + read_from, + middle + 1, + end_block, + long_block_range_error_codes, + ) + .await; + + match (first, second) { + (Ok(mut a), Ok(b)) => { + a.extend(b); + Ok(a) + } + (Err(mut a), Err(b)) => { + a.extend(b); + Err(a) + } + (Err(e), _) | (_, Err(e)) => Err(e), + } + } else { + Err(vec![e]) + } + } + } +} + +fn should_retry_with_partition(err: &ContractError, codes: &[String]) -> bool { + error_message_matches_retry_codes(&format!("{err:?}"), codes) +} + +/// Pure predicate: true if `error_message` contains any of `codes`. Used for partition retry. +/// Exposed for unit tests. +pub(crate) fn error_message_matches_retry_codes(error_message: &str, codes: &[String]) -> bool { + codes.iter().any(|c| error_message.contains(c)) +} + +/// Builds a contiguous batch of `IndexedDirectInput` from payloads and block numbers. +/// Exposed for unit tests. +pub(crate) fn build_indexed_direct_input_batch( + payloads_with_blocks: impl IntoIterator, u64)>, + next_index: u64, +) -> Vec { + payloads_with_blocks + .into_iter() + .enumerate() + .map(|(i, (payload, block_number))| IndexedDirectInput { + index: next_index + i as u64, + payload, + block_number, + }) + .collect() +} + +/// Returns the current chain head using the standard "safe" block tag (alloy `BlockNumberOrTag::Safe`). +async fn latest_safe_block(provider: &impl Provider) -> Result { + let block = provider + .get_block(Safe.into()) + .await + .map_err(|e| InputReaderError::Provider(e.to_string()))? + .ok_or_else(|| InputReaderError::Provider("get_block returned None".to_string()))?; + let number = block.header.number; + Ok(number) +} + +/// Token used by main to request input reader shutdown and then join the worker. +#[derive(Debug, Clone)] +pub struct InputReaderStop { + stop: Arc, +} + +impl InputReaderStop { + pub fn request_shutdown(&self) { + self.stop.store(true, Ordering::Relaxed); + } +} + +pub struct InputReader { + config: InputReaderConfig, + storage: Storage, + stop: Arc, +} + +impl InputReader { + pub fn new(config: InputReaderConfig, storage: Storage) -> Self { + Self { + config, + storage, + stop: Arc::new(AtomicBool::new(false)), + } + } + + pub fn request_shutdown(&self) { + self.stop.store(true, Ordering::Relaxed); + } + + /// Spawn the input reader loop on a blocking task. Returns a join handle and a stop token + /// so main can request shutdown and await the worker (same pattern as inclusion lane). + pub fn spawn(self) -> (JoinHandle>, InputReaderStop) { + let stop = InputReaderStop { + stop: Arc::clone(&self.stop), + }; + let handle = tokio::task::spawn_blocking(move || { + let rt = Builder::new_current_thread() + .enable_all() + .build() + .expect("input reader runtime"); + let mut reader = self; + while !reader.stop.load(Ordering::Relaxed) { + if let Err(e) = rt.block_on(reader.advance_once()) { + match &e { + InputReaderError::ShutdownRequested => break, + _ => { + tracing::warn!(error = %e, "input reader advance failed, will retry"); + } + } + } + std::thread::sleep(reader.config.poll_interval); + } + Ok(()) + }); + (handle, stop) + } + + /// Returns true if shutdown has been requested. For tests. + #[cfg(test)] + pub(crate) fn is_shutdown_requested(&self) -> bool { + self.stop.load(Ordering::Relaxed) + } + + /// Run the input reader loop in the background (spawns then returns; no join handle). + /// Prefer `spawn()` so main can request shutdown and join the worker. + pub fn run_blocking(self) -> Result<(), InputReaderError> { + drop(self.spawn()); + Ok(()) + } + + /// One iteration of the input reader loop. Public for tests. + pub(crate) async fn advance_once(&mut self) -> Result<(), InputReaderError> { + let provider = alloy::providers::ProviderBuilder::new() + .connect(self.config.rpc_url.as_str()) + .await + .map_err(|e| InputReaderError::Provider(e.to_string()))?; + + let current = latest_safe_block(&provider).await?; + let mut prev = self.storage.input_reader_last_processed_block()?; + if prev == 0 && self.config.genesis_block > 0 { + prev = self.config.genesis_block.saturating_sub(1); + } + + if current <= prev { + return Ok(()); + } + + let start_block = prev + 1; + let topic1 = self.config.app_address_filter.into_word().into(); + + let events = get_input_added_events( + &provider, + Some(&topic1), + &self.config.input_box_address, + start_block, + current, + &self.config.long_block_range_error_codes, + ) + .await + .map_err(|errs| { + InputReaderError::Provider(format!( + "get_input_added_events: {}", + errs.into_iter() + .next() + .map(|e| e.to_string()) + .unwrap_or_default() + )) + })?; + + if events.is_empty() { + self.storage + .input_reader_set_last_processed_block(current)?; + return Ok(()); + } + + let next_index = self.storage.safe_input_end_exclusive()?; + let payloads_with_blocks: Vec<(Vec, u64)> = events + .into_iter() + .map(|(ev, log)| { + let block_number = log + .block_number + .and_then(|n| n.try_into().ok()) + .unwrap_or(0u64); + (ev.input.to_vec(), block_number) + }) + .collect(); + let batch = build_indexed_direct_input_batch(payloads_with_blocks, next_index); + + for item in &batch { + trace!( + index = item.index, + block_number = item.block_number, + payload_len = item.payload.len(), + "safe input" + ); + } + info!( + block_range = %format!("{}..={}", start_block, current), + count = batch.len(), + "appending safe inputs" + ); + + self.storage + .append_safe_inputs_and_advance_cursor(&batch, current)?; + + Ok(()) + } +} + +#[cfg(test)] +mod tests { + use super::*; + use alloy::node_bindings::Anvil; + use alloy_primitives::Address; + use std::time::Duration; + use tempfile::NamedTempFile; + + // ----- Unit tests: retry predicate ----------------------------------------- + + #[test] + fn error_message_matches_retry_codes_returns_true_when_message_contains_code() { + assert!(error_message_matches_retry_codes( + "RPC error: block range too large", + &["block range".to_string(), "timeout".to_string()] + )); + assert!(error_message_matches_retry_codes( + "timeout after 30s", + &["timeout".to_string()] + )); + } + + #[test] + fn error_message_matches_retry_codes_returns_false_when_no_match() { + assert!(!error_message_matches_retry_codes( + "connection refused", + &["block range".to_string(), "timeout".to_string()] + )); + assert!(!error_message_matches_retry_codes("ok", &[])); + } + + #[test] + fn error_message_matches_retry_codes_returns_false_when_codes_empty() { + assert!(!error_message_matches_retry_codes( + "any error message", + &[] as &[String] + )); + } + + // ----- Unit tests: batch builder ------------------------------------------- + + #[test] + fn build_indexed_direct_input_batch_empty() { + let batch = build_indexed_direct_input_batch(Vec::<(Vec, u64)>::new(), 0); + assert!(batch.is_empty()); + } + + #[test] + fn build_indexed_direct_input_batch_contiguous_indices_and_block_numbers() { + let payloads = vec![ + (vec![0x01], 100_u64), + (vec![0x02, 0x03], 101), + (vec![], 102), + ]; + let batch = build_indexed_direct_input_batch(payloads, 5); + assert_eq!(batch.len(), 3); + assert_eq!(batch[0].index, 5); + assert_eq!(batch[0].payload, vec![0x01]); + assert_eq!(batch[0].block_number, 100); + assert_eq!(batch[1].index, 6); + assert_eq!(batch[1].payload, vec![0x02, 0x03]); + assert_eq!(batch[1].block_number, 101); + assert_eq!(batch[2].index, 7); + assert!(batch[2].payload.is_empty()); + assert_eq!(batch[2].block_number, 102); + } + + #[test] + fn build_indexed_direct_input_batch_single_item() { + let batch = build_indexed_direct_input_batch(vec![(vec![0xaa, 0xbb], 1_u64)], 0); + assert_eq!(batch.len(), 1); + assert_eq!(batch[0].index, 0); + assert_eq!(batch[0].payload, vec![0xaa, 0xbb]); + assert_eq!(batch[0].block_number, 1); + } + + // ----- Unit tests: InputReader construction and shutdown ------------------- + + #[test] + fn input_reader_new_and_request_shutdown_sets_stop_flag() { + let db_file = NamedTempFile::new().expect("temp file"); + let storage = + crate::storage::Storage::open(db_file.path().to_string_lossy().as_ref(), "NORMAL") + .expect("open storage"); + let config = InputReaderConfig { + rpc_url: "http://127.0.0.1:0".to_string(), + input_box_address: Address::ZERO, + app_address_filter: Address::ZERO, + genesis_block: 0, + poll_interval: Duration::from_secs(1), + long_block_range_error_codes: vec![], + }; + let reader = InputReader::new(config, storage); + assert!(!reader.is_shutdown_requested()); + reader.request_shutdown(); + assert!(reader.is_shutdown_requested()); + } + + /// Spawn reader, request shutdown via stop token, then join. Handle should return Ok(Ok(())). + #[tokio::test] + async fn spawn_then_request_shutdown_joins_with_ok() { + let db_file = NamedTempFile::new().expect("temp file"); + let storage = + crate::storage::Storage::open(db_file.path().to_string_lossy().as_ref(), "NORMAL") + .expect("open storage"); + let config = InputReaderConfig { + rpc_url: "http://127.0.0.1:0".to_string(), + input_box_address: Address::ZERO, + app_address_filter: Address::ZERO, + genesis_block: 0, + poll_interval: Duration::from_millis(20), + long_block_range_error_codes: vec![], + }; + let reader = InputReader::new(config, storage); + let (handle, stop) = reader.spawn(); + stop.request_shutdown(); + let join_result = tokio::time::timeout(Duration::from_secs(2), handle).await; + let join_result = join_result.expect("reader should exit within timeout"); + assert!( + matches!(join_result, Ok(Ok(()))), + "expected Ok(Ok(())), got {:?}", + join_result + ); + } + + /// Spawn reader against Anvil, let one advance complete, then request shutdown and join. + #[tokio::test] + async fn spawn_with_anvil_request_shutdown_then_join_returns_ok() { + let anvil = Anvil::default().block_time(1).spawn(); + let rpc_url = anvil.endpoint_url().to_string(); + let db_file = NamedTempFile::new().expect("temp file"); + let db_path = db_file.path().to_string_lossy(); + let storage = crate::storage::Storage::open(&db_path, "NORMAL").expect("open storage"); + + let config = InputReaderConfig { + rpc_url, + input_box_address: Address::ZERO, + app_address_filter: Address::ZERO, + genesis_block: 0, + poll_interval: Duration::from_millis(50), + long_block_range_error_codes: vec![], + }; + let reader = InputReader::new(config, storage); + let (handle, stop) = reader.spawn(); + + tokio::time::sleep(Duration::from_millis(200)).await; + stop.request_shutdown(); + + let join_result = tokio::time::timeout(Duration::from_secs(3), handle).await; + let join_result = join_result.expect("reader should exit within timeout"); + assert!( + matches!(join_result, Ok(Ok(()))), + "expected Ok(Ok(())), got {:?}", + join_result + ); + } + + // ----- Integration tests (Anvil) ----------------------------------------- + + /// Spawn Anvil, run one advance_once with no InputAdded contract (empty events). + /// Asserts the reader connects, reads safe block, and updates last_processed_block when block > 0. + #[tokio::test] + async fn advance_once_with_anvil_updates_cursor_when_block_available() { + let anvil = Anvil::default().block_time(1).spawn(); + let rpc_url = anvil.endpoint_url().to_string(); + let db_file = NamedTempFile::new().expect("temp file"); + let db_path = db_file.path().to_string_lossy(); + let storage = crate::storage::Storage::open(&db_path, "NORMAL").expect("open storage"); + + let config = InputReaderConfig { + rpc_url: rpc_url.to_string(), + input_box_address: Address::ZERO, + app_address_filter: Address::ZERO, + genesis_block: 0, + poll_interval: Duration::from_secs(1), + long_block_range_error_codes: vec![], + }; + let mut reader = InputReader::new(config, storage); + + reader.advance_once().await.expect("advance_once"); + + let _last = reader + .storage + .input_reader_last_processed_block() + .expect("read cursor"); + assert_eq!( + reader.storage.safe_input_end_exclusive().expect("safe end"), + 0, + "no InputAdded contract so no direct inputs" + ); + } + + /// When genesis_block is set and cursor is 0, effective prev becomes genesis_block - 1, + /// so we never read before genesis_block and never set cursor in [1, genesis_block). + #[tokio::test] + async fn advance_once_with_genesis_block_uses_genesis_as_effective_prev() { + let anvil = Anvil::default().block_time(1).spawn(); + let rpc_url = anvil.endpoint_url().to_string(); + let db_file = NamedTempFile::new().expect("temp file"); + let db_path = db_file.path().to_string_lossy(); + let storage = crate::storage::Storage::open(&db_path, "NORMAL").expect("open storage"); + + let genesis_block = 2u64; + let config = InputReaderConfig { + rpc_url, + input_box_address: Address::ZERO, + app_address_filter: Address::ZERO, + genesis_block, + poll_interval: Duration::from_secs(1), + long_block_range_error_codes: vec![], + }; + let mut reader = InputReader::new(config, storage); + + reader.advance_once().await.expect("advance_once"); + + let cursor = reader + .storage + .input_reader_last_processed_block() + .expect("read cursor"); + assert!( + cursor == 0 || cursor >= genesis_block, + "cursor must be 0 (no advance) or >= genesis_block (never in [1, genesis_block))" + ); + } + + /// When storage cursor is already ahead of chain head, advance_once does nothing + /// and does not overwrite last_processed_block. + #[tokio::test] + async fn advance_once_when_cursor_ahead_of_chain_is_no_op() { + let anvil = Anvil::default().block_time(1).spawn(); + let rpc_url = anvil.endpoint_url().to_string(); + let db_file = NamedTempFile::new().expect("temp file"); + let db_path = db_file.path().to_string_lossy(); + let mut storage = crate::storage::Storage::open(&db_path, "NORMAL").expect("open storage"); + storage + .input_reader_set_last_processed_block(1000) + .expect("set cursor ahead of chain"); + + let config = InputReaderConfig { + rpc_url, + input_box_address: Address::ZERO, + app_address_filter: Address::ZERO, + genesis_block: 0, + poll_interval: Duration::from_secs(1), + long_block_range_error_codes: vec![], + }; + let mut reader = InputReader::new(config, storage); + + reader.advance_once().await.expect("advance_once"); + + assert_eq!( + reader + .storage + .input_reader_last_processed_block() + .expect("read"), + 1000, + "cursor must not be overwritten when chain is behind" + ); + } +} diff --git a/sequencer/src/lib.rs b/sequencer/src/lib.rs index 9d711eb..e0fa2ff 100644 --- a/sequencer/src/lib.rs +++ b/sequencer/src/lib.rs @@ -7,5 +7,6 @@ //! The inclusion lane is the single writer that defines execution order. pub mod api; pub mod inclusion_lane; +pub mod input_reader; pub mod l2_tx_broadcaster; pub mod storage; diff --git a/sequencer/src/main.rs b/sequencer/src/main.rs index fe87046..f9ddf05 100644 --- a/sequencer/src/main.rs +++ b/sequencer/src/main.rs @@ -18,6 +18,7 @@ use sequencer::api::AppState; use sequencer::inclusion_lane::{ InclusionLane, InclusionLaneConfig, InclusionLaneError, InclusionLaneInput, }; +use sequencer::input_reader::{InputReader, InputReaderConfig}; use sequencer::l2_tx_broadcaster::{L2TxBroadcaster, L2TxBroadcasterConfig}; use sequencer::storage; @@ -30,6 +31,7 @@ const DEFAULT_MAX_BATCH_OPEN_DURATION: Duration = Duration::from_secs(2 * 60 * 6 const DEFAULT_MAX_BATCH_USER_OP_BYTES: usize = 1_048_576; // 1 MiB const DEFAULT_INCLUSION_LANE_IDLE_POLL_INTERVAL: Duration = Duration::from_millis(2); const DEFAULT_BROADCASTER_IDLE_POLL_INTERVAL: Duration = Duration::from_millis(20); +const DEFAULT_INPUT_READER_POLL_INTERVAL: Duration = Duration::from_secs(12); const DEFAULT_BROADCASTER_PAGE_SIZE: usize = 256; const DEFAULT_BROADCASTER_SUBSCRIBER_BUFFER_CAPACITY: usize = 32_768; const DEFAULT_WS_MAX_SUBSCRIBERS: usize = 64; @@ -42,6 +44,8 @@ const DEFAULT_DOMAIN_NAME: &str = "CartesiAppSequencer"; const DEFAULT_DOMAIN_VERSION: &str = "1"; const DEFAULT_DOMAIN_CHAIN_ID: u64 = 1; const DEFAULT_DOMAIN_VERIFYING_CONTRACT: &str = "0x0000000000000000000000000000000000000000"; +/// Default RPC URL for the input reader (Anvil's default HTTP endpoint). +const DEFAULT_INPUT_READER_RPC_URL: &str = "http://127.0.0.1:8545"; fn default_overload_max_inflight_submissions(queue_capacity: usize) -> usize { queue_capacity @@ -75,6 +79,14 @@ async fn run(args: RunArgs) -> Result<(), Box> { force_zero_frame_fee_for_now(&mut storage)?; let (tx, rx) = tokio::sync::mpsc::channel::(config.queue_capacity); + let storage_ir = storage::Storage::open(&config.db_path, config.sqlite_synchronous.pragma())?; + let reader = InputReader::new(config.input_reader.clone(), storage_ir); + let (mut reader_handle, reader_stop) = reader.spawn(); + tracing::info!( + "input reader started (reference: {})", + config.input_reader.rpc_url + ); + let inclusion_lane = InclusionLane::new( rx, WalletApp::new(WalletConfig), @@ -120,6 +132,7 @@ async fn run(args: RunArgs) -> Result<(), Box> { server_result = axum::serve(listener, app) => { broadcaster_shutdown.request_shutdown(); inclusion_lane_stop.request_shutdown(); + reader_stop.request_shutdown(); let lane_result = inclusion_lane_handle.await; match lane_result { Ok(InclusionLaneError::ShutdownRequested) => {} @@ -128,10 +141,17 @@ async fn run(args: RunArgs) -> Result<(), Box> { return Err(format!("inclusion lane join error during shutdown: {join_err}").into()) } } + let reader_result = reader_handle.await; + match reader_result { + Ok(Ok(())) => {} + Ok(Err(e)) => return Err(format!("input reader exited during shutdown: {e}").into()), + Err(join_err) => return Err(format!("input reader join error during shutdown: {join_err}").into()), + } server_result?; } lane_result = &mut inclusion_lane_handle => { broadcaster_shutdown.request_shutdown(); + reader_stop.request_shutdown(); match lane_result { Ok(err) => return Err(format!("inclusion lane exited: {err}").into()), Err(join_err) => { @@ -139,6 +159,15 @@ async fn run(args: RunArgs) -> Result<(), Box> { } } } + reader_result = &mut reader_handle => { + broadcaster_shutdown.request_shutdown(); + inclusion_lane_stop.request_shutdown(); + match reader_result { + Ok(Ok(())) => return Err("input reader exited unexpectedly".into()), + Ok(Err(e)) => return Err(format!("input reader exited: {e}").into()), + Err(join_err) => return Err(format!("input reader join error: {join_err}").into()), + } + } } Ok(()) @@ -195,6 +224,8 @@ struct Config { domain_version: String, domain_chain_id: u64, domain_verifying_contract: String, + /// InputReader config (required). Feeds safe inputs from a reference node into storage. + input_reader: InputReaderConfig, } #[derive(Debug, Parser)] @@ -309,6 +340,25 @@ struct RunArgs { domain_chain_id: Option, #[arg(long, env = "SEQ_DOMAIN_VERIFYING_CONTRACT")] domain_verifying_contract: Option, + #[arg( + long, + env = "SEQ_INPUT_READER_RPC_URL", + help = "Ethereum RPC URL for input reader (default: Anvil endpoint)" + )] + input_reader_rpc_url: Option, + #[arg(long, env = "SEQ_INPUT_READER_INPUT_BOX_ADDRESS", required = true)] + input_reader_input_box_address: String, + #[arg(long, env = "SEQ_INPUT_READER_APP_ADDRESS", required = true)] + input_reader_app_address: String, + #[arg(long, env = "SEQ_INPUT_READER_GENESIS_BLOCK")] + input_reader_genesis_block: Option, + #[arg( + long, + env = "SEQ_INPUT_READER_POLL_INTERVAL_MS", + value_name = "DURATION", + value_parser = parse_duration_ms_or_unit + )] + input_reader_poll_interval: Option, } #[derive(Debug, Clone, Copy, Serialize, ValueEnum)] @@ -351,6 +401,7 @@ struct ProfileDefaults { max_batch_user_op_bytes: usize, inclusion_lane_idle_poll_interval: Duration, broadcaster_idle_poll_interval: Duration, + input_reader_poll_interval: Duration, broadcaster_page_size: usize, broadcaster_subscriber_buffer_capacity: usize, ws_max_subscribers: usize, @@ -372,6 +423,7 @@ impl Profile { max_batch_user_op_bytes: DEFAULT_MAX_BATCH_USER_OP_BYTES, inclusion_lane_idle_poll_interval: DEFAULT_INCLUSION_LANE_IDLE_POLL_INTERVAL, broadcaster_idle_poll_interval: DEFAULT_BROADCASTER_IDLE_POLL_INTERVAL, + input_reader_poll_interval: DEFAULT_INPUT_READER_POLL_INTERVAL, broadcaster_page_size: DEFAULT_BROADCASTER_PAGE_SIZE, broadcaster_subscriber_buffer_capacity: DEFAULT_BROADCASTER_SUBSCRIBER_BUFFER_CAPACITY, @@ -390,6 +442,7 @@ impl Profile { max_batch_user_op_bytes: 1_572_864, // 1.5 MiB inclusion_lane_idle_poll_interval: Duration::from_millis(1), broadcaster_idle_poll_interval: Duration::from_millis(5), + input_reader_poll_interval: DEFAULT_INPUT_READER_POLL_INTERVAL, broadcaster_page_size: 1_024, broadcaster_subscriber_buffer_capacity: 131_072, ws_max_subscribers: DEFAULT_WS_MAX_SUBSCRIBERS, @@ -407,6 +460,7 @@ impl Profile { max_batch_user_op_bytes: DEFAULT_MAX_BATCH_USER_OP_BYTES, inclusion_lane_idle_poll_interval: Duration::from_millis(5), broadcaster_idle_poll_interval: Duration::from_millis(25), + input_reader_poll_interval: DEFAULT_INPUT_READER_POLL_INTERVAL, broadcaster_page_size: DEFAULT_BROADCASTER_PAGE_SIZE, broadcaster_subscriber_buffer_capacity: DEFAULT_BROADCASTER_SUBSCRIBER_BUFFER_CAPACITY, @@ -433,8 +487,14 @@ impl Config { profile: args.profile, http_addr: args .http_addr - .unwrap_or_else(|| DEFAULT_HTTP_ADDR.to_string()), - db_path: args.db_path.unwrap_or_else(|| DEFAULT_DB_PATH.to_string()), + .as_deref() + .unwrap_or(DEFAULT_HTTP_ADDR) + .to_string(), + db_path: args + .db_path + .as_deref() + .unwrap_or(DEFAULT_DB_PATH) + .to_string(), queue_capacity, overload_max_inflight_submissions, max_user_ops_per_chunk: args @@ -480,14 +540,25 @@ impl Config { .unwrap_or(defaults.sqlite_synchronous), domain_name: args .domain_name - .unwrap_or_else(|| DEFAULT_DOMAIN_NAME.to_string()), + .as_deref() + .unwrap_or(DEFAULT_DOMAIN_NAME) + .to_string(), domain_version: args .domain_version - .unwrap_or_else(|| DEFAULT_DOMAIN_VERSION.to_string()), + .as_deref() + .unwrap_or(DEFAULT_DOMAIN_VERSION) + .to_string(), domain_chain_id: args.domain_chain_id.unwrap_or(DEFAULT_DOMAIN_CHAIN_ID), domain_verifying_contract: args .domain_verifying_contract - .unwrap_or_else(|| DEFAULT_DOMAIN_VERIFYING_CONTRACT.to_string()), + .as_deref() + .unwrap_or(DEFAULT_DOMAIN_VERIFYING_CONTRACT) + .to_string(), + input_reader: input_reader_config_from_run_args( + &args, + args.input_reader_poll_interval + .unwrap_or(defaults.input_reader_poll_interval), + )?, }; config.validate()?; Ok(config) @@ -530,6 +601,9 @@ impl Config { if self.broadcaster_idle_poll_interval.is_zero() { return Err("broadcaster_idle_poll_interval must be > 0".to_string()); } + if self.input_reader.poll_interval.is_zero() { + return Err("input_reader_poll_interval must be > 0".to_string()); + } if self.broadcaster_page_size == 0 { return Err("broadcaster_page_size must be > 0".to_string()); } @@ -645,16 +719,37 @@ impl From for DurationValue { fn parse_address(value: &str) -> Result { if !value.starts_with("0x") { - return Err("verifying contract must be 0x-prefixed".to_string()); + return Err("address must be 0x-prefixed hex".to_string()); } - let bytes = alloy_primitives::hex::decode(value) - .map_err(|err| format!("invalid verifying contract hex: {err}"))?; + let bytes = + alloy_primitives::hex::decode(value).map_err(|e| format!("invalid address hex: {e}"))?; if bytes.len() != 20 { - return Err("verifying contract must be 20 bytes".to_string()); + return Err("address must be 20 bytes".to_string()); } Ok(Address::from_slice(&bytes)) } +fn input_reader_config_from_run_args( + args: &RunArgs, + poll_interval: Duration, +) -> Result { + let input_box_address = parse_address(&args.input_reader_input_box_address)?; + let app_address_filter = parse_address(&args.input_reader_app_address)?; + let genesis_block = args.input_reader_genesis_block.unwrap_or(0); + Ok(InputReaderConfig { + rpc_url: args + .input_reader_rpc_url + .as_deref() + .unwrap_or(DEFAULT_INPUT_READER_RPC_URL) + .to_string(), + input_box_address, + app_address_filter, + genesis_block, + poll_interval, + long_block_range_error_codes: vec!["rate limit".into(), "too many".into()], + }) +} + fn parse_duration_ms_or_unit(raw: &str) -> Result { let value = raw.trim(); if value.is_empty() { diff --git a/sequencer/src/storage/db.rs b/sequencer/src/storage/db.rs index 5d1b490..4b37305 100644 --- a/sequencer/src/storage/db.rs +++ b/sequencer/src/storage/db.rs @@ -8,11 +8,12 @@ use std::time::{Duration, SystemTime, UNIX_EPOCH}; use super::sql::{ sql_count_user_ops_for_frame, sql_insert_direct_inputs_batch, sql_insert_open_batch, sql_insert_open_frame, sql_insert_sequenced_direct_inputs_for_frame, - sql_insert_user_ops_and_sequenced_batch, sql_select_latest_batch_with_user_op_count, - sql_select_latest_frame_in_batch_for_batch, sql_select_max_direct_input_index, - sql_select_ordered_l2_tx_count, sql_select_ordered_l2_txs_from_offset, - sql_select_ordered_l2_txs_page_from_offset, sql_select_recommended_fee, - sql_select_safe_inputs_range, sql_select_total_drained_direct_inputs, + sql_insert_user_ops_and_sequenced_batch, sql_select_last_processed_block, + sql_select_latest_batch_with_user_op_count, sql_select_latest_frame_in_batch_for_batch, + sql_select_max_direct_input_index, sql_select_ordered_l2_tx_count, + sql_select_ordered_l2_txs_from_offset, sql_select_ordered_l2_txs_page_from_offset, + sql_select_recommended_fee, sql_select_safe_inputs_range, + sql_select_total_drained_direct_inputs, sql_update_last_processed_block, sql_update_recommended_fee, }; use super::{IndexedDirectInput, StorageOpenError, WriteHead}; @@ -86,6 +87,21 @@ impl Storage { Ok(i64_to_u64(value)) } + /// Last block number from which safe (direct) inputs have been read. Used by InputReader to resume chain sync. + pub fn input_reader_last_processed_block(&mut self) -> Result { + let value = sql_select_last_processed_block(&self.conn)?; + Ok(i64_to_u64(value)) + } + + /// Set the last block number processed by the InputReader. Callers must pass a block greater than the current value. + pub fn input_reader_set_last_processed_block(&mut self, block: u64) -> Result<()> { + let changed = sql_update_last_processed_block(&self.conn, u64_to_i64(block))?; + if changed != 1 { + return Err(rusqlite::Error::StatementChangedRows(changed)); + } + Ok(()) + } + pub fn safe_input_end_exclusive(&mut self) -> Result { let value = sql_select_max_direct_input_index(&self.conn)?; Ok(match value { @@ -128,6 +144,7 @@ impl Storage { out.push(IndexedDirectInput { index, payload: row.payload, + block_number: i64_to_u64(row.block_number), }); fetched_count = fetched_count.saturating_add(1); } @@ -165,6 +182,38 @@ impl Storage { Ok(()) } + /// Appends safe direct inputs and advances the input-reader cursor in a single transaction. + /// Use this when persisting inputs from the chain so cursor and inputs stay in sync on failure. + pub fn append_safe_inputs_and_advance_cursor( + &mut self, + inputs: &[IndexedDirectInput], + new_last_processed_block: u64, + ) -> Result<()> { + let tx = self + .conn + .transaction_with_behavior(TransactionBehavior::Immediate)?; + + if !inputs.is_empty() { + let mut next_expected = query_latest_direct_input_index_exclusive(&tx)?; + for input in inputs { + assert_eq!( + input.index, next_expected, + "direct input index must be contiguous from storage head" + ); + next_expected = next_expected.saturating_add(1); + } + sql_insert_direct_inputs_batch(&tx, inputs)?; + } + + let changed = sql_update_last_processed_block(&tx, u64_to_i64(new_last_processed_block))?; + if changed != 1 { + return Err(rusqlite::Error::StatementChangedRows(changed)); + } + + tx.commit()?; + Ok(()) + } + pub fn load_open_state(&mut self) -> Result { let tx = self .conn @@ -525,6 +574,23 @@ mod tests { assert_eq!(head_d.frame_in_batch, 0); } + #[test] + fn input_reader_last_processed_block_defaults_and_advances() { + let db = temp_db("input-reader-state"); + let mut storage = Storage::open(db.path.as_str(), "NORMAL").expect("open storage"); + assert_eq!( + storage.input_reader_last_processed_block().expect("read"), + 0 + ); + storage + .input_reader_set_last_processed_block(100) + .expect("set"); + assert_eq!( + storage.input_reader_last_processed_block().expect("read"), + 100 + ); + } + #[test] fn next_frame_fee_comes_from_recommended_fee_singleton() { let db = temp_db("recommended-fee"); @@ -552,10 +618,12 @@ mod tests { IndexedDirectInput { index: 0, payload: vec![0xaa], + block_number: 0, }, IndexedDirectInput { index: 1, payload: vec![0xbb], + block_number: 0, }, ]; storage @@ -594,10 +662,12 @@ mod tests { IndexedDirectInput { index: 0, payload: vec![0x01], + block_number: 0, }, IndexedDirectInput { index: 1, payload: vec![0x02], + block_number: 0, }, ]; storage @@ -632,10 +702,12 @@ mod tests { IndexedDirectInput { index: 0, payload: vec![0xa0], + block_number: 0, }, IndexedDirectInput { index: 1, payload: vec![0xb1], + block_number: 0, }, ]; storage diff --git a/sequencer/src/storage/migrations/0001_schema.sql b/sequencer/src/storage/migrations/0001_schema.sql index 1a9818f..257c25b 100644 --- a/sequencer/src/storage/migrations/0001_schema.sql +++ b/sequencer/src/storage/migrations/0001_schema.sql @@ -29,7 +29,9 @@ CREATE TABLE IF NOT EXISTS user_ops ( CREATE TABLE IF NOT EXISTS direct_inputs ( direct_input_index INTEGER PRIMARY KEY, - payload BLOB NOT NULL + payload BLOB NOT NULL, + -- Block number of the chain block where this direct input was included (e.g. InputAdded event block). + block_number INTEGER NOT NULL DEFAULT 0 ); CREATE TABLE IF NOT EXISTS sequenced_l2_txs ( @@ -72,9 +74,18 @@ CREATE TABLE IF NOT EXISTS recommended_fees ( fee INTEGER NOT NULL CHECK (fee >= 0) ); +-- Input reader: chain sync cursor (last safe block from which direct inputs have been read). +CREATE TABLE IF NOT EXISTS input_reader_state ( + singleton_id INTEGER PRIMARY KEY CHECK (singleton_id = 0), + last_processed_block INTEGER NOT NULL CHECK (last_processed_block >= 0) +); + INSERT OR IGNORE INTO recommended_fees (singleton_id, fee) VALUES (0, 0); +INSERT OR IGNORE INTO input_reader_state (singleton_id, last_processed_block) +VALUES (0, 0); + INSERT OR IGNORE INTO batches (batch_index, created_at_ms) VALUES (0, 0); diff --git a/sequencer/src/storage/mod.rs b/sequencer/src/storage/mod.rs index 9994c1e..4677da7 100644 --- a/sequencer/src/storage/mod.rs +++ b/sequencer/src/storage/mod.rs @@ -13,6 +13,8 @@ pub use db::Storage; pub struct IndexedDirectInput { pub index: u64, pub payload: Vec, + /// Chain block number where this input was included (e.g. InputAdded event block). + pub block_number: u64, } #[derive(Debug, Error)] diff --git a/sequencer/src/storage/queries/select_safe_inputs_range.sql b/sequencer/src/storage/queries/select_safe_inputs_range.sql index 59afc01..281decd 100644 --- a/sequencer/src/storage/queries/select_safe_inputs_range.sql +++ b/sequencer/src/storage/queries/select_safe_inputs_range.sql @@ -1,4 +1,4 @@ -SELECT direct_input_index, payload +SELECT direct_input_index, payload, block_number FROM direct_inputs WHERE direct_input_index >= ?1 AND direct_input_index < ?2 ORDER BY direct_input_index ASC diff --git a/sequencer/src/storage/sql.rs b/sequencer/src/storage/sql.rs index a9a122f..76ab9ec 100644 --- a/sequencer/src/storage/sql.rs +++ b/sequencer/src/storage/sql.rs @@ -23,13 +23,17 @@ const SQL_SELECT_ORDERED_L2_TX_COUNT: &str = "SELECT COUNT(*) FROM sequenced_l2_ const SQL_SELECT_RECOMMENDED_FEE: &str = "SELECT fee FROM recommended_fees WHERE singleton_id = 0 LIMIT 1"; const SQL_INSERT_DIRECT_INPUT: &str = - "INSERT INTO direct_inputs (direct_input_index, payload) VALUES (?1, ?2)"; + "INSERT INTO direct_inputs (direct_input_index, payload, block_number) VALUES (?1, ?2, ?3)"; const SQL_INSERT_USER_OP: &str = include_str!("queries/insert_user_op.sql"); const SQL_INSERT_SEQUENCED_USER_OP: &str = include_str!("queries/insert_sequenced_user_op.sql"); const SQL_INSERT_SEQUENCED_DIRECT_INPUT: &str = include_str!("queries/insert_sequenced_direct_input.sql"); const SQL_UPDATE_RECOMMENDED_FEE: &str = "UPDATE recommended_fees SET fee = ?1 WHERE singleton_id = 0"; +const SQL_SELECT_LAST_PROCESSED_BLOCK: &str = + "SELECT last_processed_block FROM input_reader_state WHERE singleton_id = 0 LIMIT 1"; +const SQL_UPDATE_LAST_PROCESSED_BLOCK: &str = + "UPDATE input_reader_state SET last_processed_block = ?1 WHERE singleton_id = 0"; #[derive(Debug, Clone)] pub(super) struct OrderedL2TxRow { @@ -44,6 +48,7 @@ pub(super) struct OrderedL2TxRow { pub(super) struct SafeInputRow { pub direct_input_index: i64, pub payload: Vec, + pub block_number: i64, } pub(super) fn sql_select_total_drained_direct_inputs(conn: &Connection) -> Result { @@ -67,6 +72,14 @@ pub(super) fn sql_update_recommended_fee(conn: &Connection, fee: i64) -> Result< conn.execute(SQL_UPDATE_RECOMMENDED_FEE, params![fee]) } +pub(super) fn sql_select_last_processed_block(conn: &Connection) -> Result { + conn.query_row(SQL_SELECT_LAST_PROCESSED_BLOCK, [], |row| row.get(0)) +} + +pub(super) fn sql_update_last_processed_block(conn: &Connection, block: i64) -> Result { + conn.execute(SQL_UPDATE_LAST_PROCESSED_BLOCK, params![block]) +} + pub(super) fn sql_select_safe_inputs_range( conn: &Connection, from_inclusive: i64, @@ -90,7 +103,11 @@ pub(super) fn sql_insert_direct_inputs_batch( let mut stmt = tx.prepare_cached(SQL_INSERT_DIRECT_INPUT)?; for input in direct_inputs { - stmt.execute(params![u64_to_i64(input.index), input.payload.as_slice()])?; + stmt.execute(params![ + u64_to_i64(input.index), + input.payload.as_slice(), + u64_to_i64(input.block_number), + ])?; } Ok(()) } @@ -253,6 +270,7 @@ fn convert_row_to_safe_input_row(row: &Row<'_>) -> Result { Ok(SafeInputRow { direct_input_index: row.get(0)?, payload: row.get(1)?, + block_number: row.get(2)?, }) } @@ -342,10 +360,16 @@ mod tests { None ); - conn.execute(SQL_INSERT_DIRECT_INPUT, params![0_i64, vec![0xaa_u8]]) - .expect("insert direct input 0"); - conn.execute(SQL_INSERT_DIRECT_INPUT, params![1_i64, vec![0xbb_u8]]) - .expect("insert direct input 1"); + conn.execute( + SQL_INSERT_DIRECT_INPUT, + params![0_i64, vec![0xaa_u8], 0_i64], + ) + .expect("insert direct input 0"); + conn.execute( + SQL_INSERT_DIRECT_INPUT, + params![1_i64, vec![0xbb_u8], 0_i64], + ) + .expect("insert direct input 1"); assert_eq!( sql_select_max_direct_input_index(&conn).expect("query max direct input"), Some(1) @@ -375,12 +399,21 @@ mod tests { fn safe_inputs_range_is_half_open_and_ordered() { let conn = setup_conn(); - conn.execute(SQL_INSERT_DIRECT_INPUT, params![0_i64, vec![0xaa_u8]]) - .expect("insert direct input 0"); - conn.execute(SQL_INSERT_DIRECT_INPUT, params![1_i64, vec![0xbb_u8]]) - .expect("insert direct input 1"); - conn.execute(SQL_INSERT_DIRECT_INPUT, params![2_i64, vec![0xcc_u8]]) - .expect("insert direct input 2"); + conn.execute( + SQL_INSERT_DIRECT_INPUT, + params![0_i64, vec![0xaa_u8], 0_i64], + ) + .expect("insert direct input 0"); + conn.execute( + SQL_INSERT_DIRECT_INPUT, + params![1_i64, vec![0xbb_u8], 0_i64], + ) + .expect("insert direct input 1"); + conn.execute( + SQL_INSERT_DIRECT_INPUT, + params![2_i64, vec![0xcc_u8], 0_i64], + ) + .expect("insert direct input 2"); let empty = sql_select_safe_inputs_range(&conn, 1, 1).expect("query empty interval"); assert!(empty.is_empty()); @@ -410,8 +443,11 @@ mod tests { ], ) .expect("insert user op"); - conn.execute(SQL_INSERT_DIRECT_INPUT, params![0_i64, vec![0xaa_u8]]) - .expect("insert direct input"); + conn.execute( + SQL_INSERT_DIRECT_INPUT, + params![0_i64, vec![0xaa_u8], 0_i64], + ) + .expect("insert direct input"); conn.execute(SQL_INSERT_SEQUENCED_USER_OP, params![0_i64, 0_i64, 0_i64]) .expect("insert sequenced user op"); conn.execute( @@ -496,10 +532,12 @@ mod tests { IndexedDirectInput { index: 0, payload: vec![0xaa_u8], + block_number: 0, }, IndexedDirectInput { index: 1, payload: vec![0xbb_u8], + block_number: 0, }, ]; sql_insert_direct_inputs_batch(&tx, direct_inputs.as_slice()) diff --git a/sequencer/tests/e2e_sequencer.rs b/sequencer/tests/e2e_sequencer.rs index 48c37bd..bb5737a 100644 --- a/sequencer/tests/e2e_sequencer.rs +++ b/sequencer/tests/e2e_sequencer.rs @@ -459,6 +459,9 @@ async fn start_api_only_server( async fn shutdown_runtime(mut runtime: FullServerRuntime) { runtime.broadcaster.request_shutdown(); + if let Some(stop) = runtime.lane_stop.take() { + stop.request_shutdown(); + } if let Some(tx) = runtime.shutdown_tx.take() { let _ = tx.send(()); } @@ -468,9 +471,6 @@ async fn shutdown_runtime(mut runtime: FullServerRuntime) { .expect("wait for server task") .expect("join server task"); } - if let Some(stop) = runtime.lane_stop.take() { - stop.request_shutdown(); - } if let Some(task) = runtime.lane_handle.take() { let lane_result = tokio::time::timeout(Duration::from_secs(3), task) .await diff --git a/sequencer/tests/ws_broadcaster.rs b/sequencer/tests/ws_broadcaster.rs index b48167c..e5aca5d 100644 --- a/sequencer/tests/ws_broadcaster.rs +++ b/sequencer/tests/ws_broadcaster.rs @@ -21,8 +21,18 @@ use tokio::sync::{Semaphore, mpsc, oneshot}; use tokio_tungstenite::connect_async; use tokio_tungstenite::tungstenite::Message; -#[tokio::test(flavor = "multi_thread", worker_threads = 2)] -async fn ws_subscribe_streams_ordered_txs_from_offset_zero() { +#[tokio::test(flavor = "multi_thread", worker_threads = 4)] +async fn ws_subscribe_tests_sequential() { + scenario_streams_ordered_txs_from_offset_zero().await; + scenario_resumes_from_given_offset().await; + scenario_receives_live_events_after_subscribing().await; + scenario_fanout_delivers_live_event_to_multiple_subscribers().await; + scenario_replies_with_pong_on_ping().await; + scenario_rejects_when_subscriber_limit_is_reached().await; + scenario_closes_when_catchup_window_exceeds_limit().await; +} + +async fn scenario_streams_ordered_txs_from_offset_zero() { let db = temp_db("ws-subscribe-zero"); seed_ordered_txs(db.path.as_str()); let expected = load_ordered_l2_txs_page(db.path.as_str(), 0, 2); @@ -47,8 +57,7 @@ async fn ws_subscribe_streams_ordered_txs_from_offset_zero() { assert_ws_message_matches_tx(second, &expected[1], 1); } -#[tokio::test(flavor = "multi_thread", worker_threads = 2)] -async fn ws_subscribe_resumes_from_given_offset() { +async fn scenario_resumes_from_given_offset() { let db = temp_db("ws-subscribe-resume"); seed_ordered_txs(db.path.as_str()); let expected = load_ordered_l2_txs_page(db.path.as_str(), 1, 1); @@ -75,8 +84,7 @@ async fn ws_subscribe_resumes_from_given_offset() { assert_ws_message_matches_tx(first, &expected[0], 1); } -#[tokio::test(flavor = "multi_thread", worker_threads = 2)] -async fn ws_subscribe_receives_live_events_after_subscribing() { +async fn scenario_receives_live_events_after_subscribing() { let db = temp_db("ws-subscribe-live"); seed_ordered_txs(db.path.as_str()); let base_offset = ordered_l2_tx_count(db.path.as_str()); @@ -107,8 +115,7 @@ async fn ws_subscribe_receives_live_events_after_subscribing() { assert_ws_message_matches_tx(live, &expected[0], base_offset); } -#[tokio::test(flavor = "multi_thread", worker_threads = 2)] -async fn ws_subscribe_fanout_delivers_live_event_to_multiple_subscribers() { +async fn scenario_fanout_delivers_live_event_to_multiple_subscribers() { let db = temp_db("ws-subscribe-fanout"); seed_ordered_txs(db.path.as_str()); let base_offset = ordered_l2_tx_count(db.path.as_str()); @@ -146,8 +153,7 @@ async fn ws_subscribe_fanout_delivers_live_event_to_multiple_subscribers() { assert_ws_message_matches_tx(event_b, &expected[0], base_offset); } -#[tokio::test(flavor = "multi_thread", worker_threads = 2)] -async fn ws_subscribe_replies_with_pong_on_ping() { +async fn scenario_replies_with_pong_on_ping() { let db = temp_db("ws-subscribe-ping-pong"); seed_ordered_txs(db.path.as_str()); // Use a far-future offset so this test validates ping/pong without @@ -179,8 +185,7 @@ async fn ws_subscribe_replies_with_pong_on_ping() { } } -#[tokio::test(flavor = "multi_thread", worker_threads = 2)] -async fn ws_subscribe_rejects_when_subscriber_limit_is_reached() { +async fn scenario_rejects_when_subscriber_limit_is_reached() { let db = temp_db("ws-subscriber-limit"); seed_ordered_txs(db.path.as_str()); let base_offset = ordered_l2_tx_count(db.path.as_str()); @@ -210,8 +215,7 @@ async fn ws_subscribe_rejects_when_subscriber_limit_is_reached() { shutdown_runtime(runtime).await; } -#[tokio::test(flavor = "multi_thread", worker_threads = 2)] -async fn ws_subscribe_closes_when_catchup_window_exceeds_limit() { +async fn scenario_closes_when_catchup_window_exceeds_limit() { let db = temp_db("ws-catchup-limit"); seed_ordered_txs(db.path.as_str()); @@ -267,6 +271,7 @@ fn seed_ordered_txs(db_path: &str) { .append_safe_direct_inputs(&[IndexedDirectInput { index: 0, payload: vec![0xaa], + block_number: 0, }]) .expect("append direct input"); storage @@ -278,7 +283,11 @@ fn append_drained_direct_input(db_path: &str, index: u64, payload: Vec) { let mut storage = Storage::open(db_path, "NORMAL").expect("open storage"); let mut head = storage.load_open_state().expect("load open state"); storage - .append_safe_direct_inputs(&[IndexedDirectInput { index, payload }]) + .append_safe_direct_inputs(&[IndexedDirectInput { + index, + payload, + block_number: 0, + }]) .expect("append direct input"); storage .close_frame_only(&mut head, index, 1) @@ -387,7 +396,7 @@ async fn recv_tx_message( tokio_tungstenite::MaybeTlsStream, >, ) -> WsTxMessage { - let received = tokio::time::timeout(Duration::from_secs(2), ws.next()) + let received = tokio::time::timeout(Duration::from_secs(5), ws.next()) .await .expect("wait for websocket message") .expect("websocket stream ended") @@ -406,7 +415,7 @@ async fn recv_raw_message( tokio_tungstenite::MaybeTlsStream, >, ) -> Message { - tokio::time::timeout(Duration::from_secs(2), ws.next()) + tokio::time::timeout(Duration::from_secs(5), ws.next()) .await .expect("wait for websocket message") .expect("websocket stream ended")