diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..10a2f71 --- /dev/null +++ b/.gitignore @@ -0,0 +1,5 @@ +/target +.vscode/ +.DS_Store +node_modules +/*.json diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 0000000..cfc2f21 --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,4507 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "addr2line" +version = "0.24.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dfbe277e56a376000877090da837660b4427aad530e3028d44e0bffe4f89a1c1" +dependencies = [ + "gimli", +] + +[[package]] +name = "adler2" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627" + +[[package]] +name = "aho-corasick" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" +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 = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "239e728d663a3bdababa24dfdc697faec987593161c5ff54d72ee01df6721d59" +dependencies = [ + "alloy-consensus", + "alloy-contract", + "alloy-core", + "alloy-eips", + "alloy-genesis", + "alloy-network", + "alloy-provider", + "alloy-pubsub", + "alloy-rpc-client", + "alloy-rpc-types", + "alloy-serde", + "alloy-signer", + "alloy-signer-local", + "alloy-transport", + "alloy-transport-http", + "alloy-transport-ipc", +] + +[[package]] +name = "alloy-chains" +version = "0.1.66" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8e42c54af787e3521229df1787d7b8300910dc6d9d04d378eb593b26388bd11" +dependencies = [ + "alloy-primitives", + "num_enum", + "strum", +] + +[[package]] +name = "alloy-consensus" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "27d301f5bcfd37e3aac727c360d8b50c33ddff9169ce0370198dedda36a9927d" +dependencies = [ + "alloy-eips", + "alloy-primitives", + "alloy-rlp", + "alloy-serde", + "alloy-trie", + "auto_impl", + "c-kzg", + "derive_more 2.0.1", + "either", + "k256", + "once_cell", + "rand", + "serde", + "serde_with", + "thiserror", +] + +[[package]] +name = "alloy-consensus-any" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f4f97a85a45965e0e4f9f5b94bbafaa3e4ee6868bdbcf2e4a9acb4b358038fe" +dependencies = [ + "alloy-consensus", + "alloy-eips", + "alloy-primitives", + "alloy-rlp", + "alloy-serde", + "serde", +] + +[[package]] +name = "alloy-contract" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f39e8b96c9e25dde7222372332489075f7e750e4fd3e81c11eec0939b78b71b8" +dependencies = [ + "alloy-consensus", + "alloy-dyn-abi", + "alloy-json-abi", + "alloy-network", + "alloy-network-primitives", + "alloy-primitives", + "alloy-provider", + "alloy-pubsub", + "alloy-rpc-types-eth", + "alloy-sol-types", + "alloy-transport", + "futures", + "futures-util", + "thiserror", +] + +[[package]] +name = "alloy-core" +version = "0.8.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca1380cc3c81b83d5234865779494970c83b5893b423c59cdd68c3cd1ed0b671" +dependencies = [ + "alloy-dyn-abi", + "alloy-json-abi", + "alloy-primitives", + "alloy-rlp", + "alloy-sol-types", +] + +[[package]] +name = "alloy-dyn-abi" +version = "0.8.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7078bef2bc353c1d1a97b44981d0186198be320038fbfbb0b37d1dd822a555d3" +dependencies = [ + "alloy-json-abi", + "alloy-primitives", + "alloy-sol-type-parser", + "alloy-sol-types", + "const-hex", + "itoa", + "serde", + "serde_json", + "winnow", +] + +[[package]] +name = "alloy-eip2124" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "675264c957689f0fd75f5993a73123c2cc3b5c235a38f5b9037fe6c826bfb2c0" +dependencies = [ + "alloy-primitives", + "alloy-rlp", + "crc", + "serde", + "thiserror", +] + +[[package]] +name = "alloy-eip2930" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0069cf0642457f87a01a014f6dc29d5d893cd4fd8fddf0c3cdfad1bb3ebafc41" +dependencies = [ + "alloy-primitives", + "alloy-rlp", + "serde", +] + +[[package]] +name = "alloy-eip7702" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b15b13d38b366d01e818fe8e710d4d702ef7499eacd44926a06171dd9585d0c" +dependencies = [ + "alloy-primitives", + "alloy-rlp", + "serde", + "thiserror", +] + +[[package]] +name = "alloy-eips" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "10b11c382ca8075128d1ae6822b60921cf484c911d9a5831797a01218f98125f" +dependencies = [ + "alloy-eip2124", + "alloy-eip2930", + "alloy-eip7702", + "alloy-primitives", + "alloy-rlp", + "alloy-serde", + "auto_impl", + "c-kzg", + "derive_more 2.0.1", + "either", + "serde", + "sha2", +] + +[[package]] +name = "alloy-genesis" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7bd9e75c5dd40319ebbe807ebe9dfb10c24e4a70d9c7d638e62921d8dd093c8b" +dependencies = [ + "alloy-eips", + "alloy-primitives", + "alloy-serde", + "alloy-trie", + "serde", +] + +[[package]] +name = "alloy-json-abi" +version = "0.8.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec80745c33797e8baf547a8cfeb850e60d837fe9b9e67b3f579c1fcd26f527e9" +dependencies = [ + "alloy-primitives", + "alloy-sol-type-parser", + "serde", + "serde_json", +] + +[[package]] +name = "alloy-json-rpc" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbcf26d02a72e23d5bc245425ea403c93ba17d254f20f9c23556a249c6c7e143" +dependencies = [ + "alloy-primitives", + "alloy-sol-types", + "serde", + "serde_json", + "thiserror", + "tracing", +] + +[[package]] +name = "alloy-network" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b44dd4429e190f727358571175ebf323db360a303bf4e1731213f510ced1c2e6" +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 2.0.1", + "futures-utils-wasm", + "serde", + "serde_json", + "thiserror", +] + +[[package]] +name = "alloy-network-primitives" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "86f736e1d1eb1b770dbd32919bdf46d4dcd4617f2eed07947dfb32649962baba" +dependencies = [ + "alloy-consensus", + "alloy-eips", + "alloy-primitives", + "alloy-serde", + "serde", +] + +[[package]] +name = "alloy-primitives" +version = "0.8.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eacedba97e65cdc7ab592f2b22ef5d3ab8d60b2056bc3a6e6363577e8270ec6f" +dependencies = [ + "alloy-rlp", + "bytes", + "cfg-if", + "const-hex", + "derive_more 2.0.1", + "foldhash", + "hashbrown 0.15.2", + "indexmap 2.8.0", + "itoa", + "k256", + "keccak-asm", + "paste", + "proptest", + "rand", + "ruint", + "rustc-hash", + "serde", + "sha3", + "tiny-keccak", +] + +[[package]] +name = "alloy-provider" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a557f9e3ec89437b06db3bfc97d20782b1f7cc55b5b602b6a82bf3f64d7efb0e" +dependencies = [ + "alloy-chains", + "alloy-consensus", + "alloy-eips", + "alloy-json-rpc", + "alloy-network", + "alloy-network-primitives", + "alloy-primitives", + "alloy-pubsub", + "alloy-rpc-client", + "alloy-rpc-types-debug", + "alloy-rpc-types-eth", + "alloy-rpc-types-trace", + "alloy-signer", + "alloy-sol-types", + "alloy-transport", + "alloy-transport-http", + "alloy-transport-ipc", + "async-stream", + "async-trait", + "auto_impl", + "dashmap", + "either", + "futures", + "futures-utils-wasm", + "lru", + "parking_lot", + "pin-project", + "reqwest", + "serde", + "serde_json", + "thiserror", + "tokio", + "tracing", + "url", + "wasmtimer", +] + +[[package]] +name = "alloy-pubsub" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0a261caff6c2ec6fe1d6eb77ba41159024c8387d05e4138804a387d403def55" +dependencies = [ + "alloy-json-rpc", + "alloy-primitives", + "alloy-transport", + "bimap", + "futures", + "parking_lot", + "serde", + "serde_json", + "tokio", + "tokio-stream", + "tower", + "tracing", +] + +[[package]] +name = "alloy-rlp" +version = "0.3.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d6c1d995bff8d011f7cd6c81820d51825e6e06d6db73914c1630ecf544d83d6" +dependencies = [ + "alloy-rlp-derive", + "arrayvec", + "bytes", +] + +[[package]] +name = "alloy-rlp-derive" +version = "0.3.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a40e1ef334153322fd878d07e86af7a529bcb86b2439525920a88eba87bcf943" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.100", +] + +[[package]] +name = "alloy-rpc-client" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cec6dc89c4c3ef166f9fa436d1831f8142c16cf2e637647c936a6aaaabd8d898" +dependencies = [ + "alloy-json-rpc", + "alloy-primitives", + "alloy-pubsub", + "alloy-transport", + "alloy-transport-http", + "alloy-transport-ipc", + "async-stream", + "futures", + "pin-project", + "reqwest", + "serde", + "serde_json", + "tokio", + "tokio-stream", + "tower", + "tracing", + "tracing-futures", + "url", + "wasmtimer", +] + +[[package]] +name = "alloy-rpc-types" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3849f8131a18cc5d7f95f301d68a6af5aa2db28ad8522fb9db1f27b3794e8b68" +dependencies = [ + "alloy-primitives", + "alloy-rpc-types-eth", + "alloy-rpc-types-trace", + "alloy-serde", + "serde", +] + +[[package]] +name = "alloy-rpc-types-any" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ecd6d480e4e6e456f30eeeb3aef1512aaecb68df2a35d1f78865dbc4d20dc0fd" +dependencies = [ + "alloy-consensus-any", + "alloy-rpc-types-eth", + "alloy-serde", +] + +[[package]] +name = "alloy-rpc-types-debug" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "805eb9fa07f92f1225253e842b5454b4b3e258813445c1a1c9d8dd0fd90817c1" +dependencies = [ + "alloy-primitives", + "serde", +] + +[[package]] +name = "alloy-rpc-types-eth" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a8b6d55bdaa0c4a08650d4b32f174494cbade56adf6f2fcfa2a4f3490cb5511" +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", + "thiserror", +] + +[[package]] +name = "alloy-rpc-types-trace" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6019cd6a89230d765a621a7b1bc8af46a6a9cde2d2e540e6f9ce930e0fb7c6db" +dependencies = [ + "alloy-primitives", + "alloy-rpc-types-eth", + "alloy-serde", + "serde", + "serde_json", + "thiserror", +] + +[[package]] +name = "alloy-serde" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1824791912f468a481dedc1db50feef3e85a078f6d743a62db2ee9c2ca674882" +dependencies = [ + "alloy-primitives", + "serde", + "serde_json", +] + +[[package]] +name = "alloy-signer" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d087fe5aea96a93fbe71be8aaed5c57c3caac303c09e674bc5b1647990d648b" +dependencies = [ + "alloy-primitives", + "async-trait", + "auto_impl", + "either", + "elliptic-curve", + "k256", + "thiserror", +] + +[[package]] +name = "alloy-signer-local" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2940353d2425bb75965cd5101075334e6271051e35610f903bf8099a52b0b1a9" +dependencies = [ + "alloy-consensus", + "alloy-network", + "alloy-primitives", + "alloy-signer", + "async-trait", + "k256", + "rand", + "thiserror", +] + +[[package]] +name = "alloy-sol-macro" +version = "0.8.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3637022e781bc73a9e300689cd91105a0e6be00391dd4e2110a71cc7e9f20a94" +dependencies = [ + "alloy-sol-macro-expander", + "alloy-sol-macro-input", + "proc-macro-error2", + "proc-macro2", + "quote", + "syn 2.0.100", +] + +[[package]] +name = "alloy-sol-macro-expander" +version = "0.8.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b9bd22d0bba90e40f40c625c33d39afb7d62b22192476a2ce1dcf8409dce880" +dependencies = [ + "alloy-json-abi", + "alloy-sol-macro-input", + "const-hex", + "heck", + "indexmap 2.8.0", + "proc-macro-error2", + "proc-macro2", + "quote", + "syn 2.0.100", + "syn-solidity", + "tiny-keccak", +] + +[[package]] +name = "alloy-sol-macro-input" +version = "0.8.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05ae4646e8123ec2fd10f9c22e361ffe4365c42811431829c2eabae528546bcc" +dependencies = [ + "alloy-json-abi", + "const-hex", + "dunce", + "heck", + "macro-string", + "proc-macro2", + "quote", + "serde_json", + "syn 2.0.100", + "syn-solidity", +] + +[[package]] +name = "alloy-sol-type-parser" +version = "0.8.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "488a747fdcefeec5c1ed5aa9e08becd775106777fdeae2a35730729fc8a95910" +dependencies = [ + "serde", + "winnow", +] + +[[package]] +name = "alloy-sol-types" +version = "0.8.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "767957235807b021126dca1598ac3ef477007eace07961607dc5f490550909c7" +dependencies = [ + "alloy-json-abi", + "alloy-primitives", + "alloy-sol-macro", + "const-hex", + "serde", +] + +[[package]] +name = "alloy-transport" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6818b4c82a474cc01ac9e88ccfcd9f9b7bc893b2f8aea7e890a28dcd55c0a7aa" +dependencies = [ + "alloy-json-rpc", + "base64", + "derive_more 2.0.1", + "futures", + "futures-utils-wasm", + "parking_lot", + "serde", + "serde_json", + "thiserror", + "tokio", + "tower", + "tracing", + "url", + "wasmtimer", +] + +[[package]] +name = "alloy-transport-http" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4cc3079a33483afa1b1365a3add3ea3e21c75b10f704870198ba7846627d10f2" +dependencies = [ + "alloy-json-rpc", + "alloy-transport", + "reqwest", + "serde_json", + "tower", + "tracing", + "url", +] + +[[package]] +name = "alloy-transport-ipc" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "66c6f8e20aa6b748357bed157c14e561a176d0f6cffed7f99ee37758a7d16202" +dependencies = [ + "alloy-json-rpc", + "alloy-pubsub", + "alloy-transport", + "bytes", + "futures", + "interprocess", + "pin-project", + "serde", + "serde_json", + "tokio", + "tokio-util", + "tracing", +] + +[[package]] +name = "alloy-trie" +version = "0.7.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d95a94854e420f07e962f7807485856cde359ab99ab6413883e15235ad996e8b" +dependencies = [ + "alloy-primitives", + "alloy-rlp", + "arrayvec", + "derive_more 1.0.0", + "nybbles", + "serde", + "smallvec", + "tracing", +] + +[[package]] +name = "android-tzdata" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0" + +[[package]] +name = "android_system_properties" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" +dependencies = [ + "libc", +] + +[[package]] +name = "anstream" +version = "0.6.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8acc5369981196006228e28809f761875c0327210a891e941f4c683b3a99529b" +dependencies = [ + "anstyle", + "anstyle-parse", + "anstyle-query", + "anstyle-wincon", + "colorchoice", + "is_terminal_polyfill", + "utf8parse", +] + +[[package]] +name = "anstyle" +version = "1.0.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55cc3b69f167a1ef2e161439aa98aed94e6028e5f9a59be9a6ffb47aef1651f9" + +[[package]] +name = "anstyle-parse" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b2d16507662817a6a20a9ea92df6652ee4f94f914589377d69f3b21bc5798a9" +dependencies = [ + "utf8parse", +] + +[[package]] +name = "anstyle-query" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "79947af37f4177cfead1110013d678905c37501914fba0efea834c3fe9a8d60c" +dependencies = [ + "windows-sys 0.59.0", +] + +[[package]] +name = "anstyle-wincon" +version = "3.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca3534e77181a9cc07539ad51f2141fe32f6c3ffd4df76db8ad92346b003ae4e" +dependencies = [ + "anstyle", + "once_cell", + "windows-sys 0.59.0", +] + +[[package]] +name = "anyhow" +version = "1.0.97" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dcfed56ad506cb2c684a14971b8861fdc3baaaae314b9e5f9bb532cbe3ba7a4f" + +[[package]] +name = "arbitrary" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dde20b3d026af13f561bdd0f15edf01fc734f0dafcedbaf42bba506a9517f223" +dependencies = [ + "derive_arbitrary", +] + +[[package]] +name = "ark-ff" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6b3235cc41ee7a12aaaf2c575a2ad7b46713a8a50bda2fc3b003a04845c05dd6" +dependencies = [ + "ark-ff-asm 0.3.0", + "ark-ff-macros 0.3.0", + "ark-serialize 0.3.0", + "ark-std 0.3.0", + "derivative", + "num-bigint", + "num-traits", + "paste", + "rustc_version 0.3.3", + "zeroize", +] + +[[package]] +name = "ark-ff" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec847af850f44ad29048935519032c33da8aa03340876d351dfab5660d2966ba" +dependencies = [ + "ark-ff-asm 0.4.2", + "ark-ff-macros 0.4.2", + "ark-serialize 0.4.2", + "ark-std 0.4.0", + "derivative", + "digest 0.10.7", + "itertools 0.10.5", + "num-bigint", + "num-traits", + "paste", + "rustc_version 0.4.1", + "zeroize", +] + +[[package]] +name = "ark-ff-asm" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db02d390bf6643fb404d3d22d31aee1c4bc4459600aef9113833d17e786c6e44" +dependencies = [ + "quote", + "syn 1.0.109", +] + +[[package]] +name = "ark-ff-asm" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ed4aa4fe255d0bc6d79373f7e31d2ea147bcf486cba1be5ba7ea85abdb92348" +dependencies = [ + "quote", + "syn 1.0.109", +] + +[[package]] +name = "ark-ff-macros" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db2fd794a08ccb318058009eefdf15bcaaaaf6f8161eb3345f907222bac38b20" +dependencies = [ + "num-bigint", + "num-traits", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "ark-ff-macros" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7abe79b0e4288889c4574159ab790824d0033b9fdcb2a112a3182fac2e514565" +dependencies = [ + "num-bigint", + "num-traits", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "ark-serialize" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d6c2b318ee6e10f8c2853e73a83adc0ccb88995aa978d8a3408d492ab2ee671" +dependencies = [ + "ark-std 0.3.0", + "digest 0.9.0", +] + +[[package]] +name = "ark-serialize" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "adb7b85a02b83d2f22f89bd5cac66c9c89474240cb6207cb1efc16d098e822a5" +dependencies = [ + "ark-std 0.4.0", + "digest 0.10.7", + "num-bigint", +] + +[[package]] +name = "ark-std" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1df2c09229cbc5a028b1d70e00fdb2acee28b1055dfb5ca73eea49c5a25c4e7c" +dependencies = [ + "num-traits", + "rand", +] + +[[package]] +name = "ark-std" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94893f1e0c6eeab764ade8dc4c0db24caf4fe7cbbaafc0eba0a9030f447b5185" +dependencies = [ + "num-traits", + "rand", +] + +[[package]] +name = "arrayvec" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" +dependencies = [ + "serde", +] + +[[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.100", +] + +[[package]] +name = "async-trait" +version = "0.1.88" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e539d3fca749fcee5236ab05e93a52867dd549cc157c8cb7f99595f3cedffdb5" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.100", +] + +[[package]] +name = "atomic-waker" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" + +[[package]] +name = "auto_impl" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e12882f59de5360c748c4cbf569a042d5fb0eb515f7bea9c1f470b47f6ffbd73" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.100", +] + +[[package]] +name = "autocfg" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" + +[[package]] +name = "backtrace" +version = "0.3.74" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d82cb332cdfaed17ae235a638438ac4d4839913cc2af585c3c6746e8f8bee1a" +dependencies = [ + "addr2line", + "cfg-if", + "libc", + "miniz_oxide", + "object", + "rustc-demangle", + "windows-targets 0.52.6", +] + +[[package]] +name = "base16ct" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c7f02d4ea65f2c1853089ffd8d2787bdbc63de2f0d29dedbcf8ccdfa0ccd4cf" + +[[package]] +name = "base64" +version = "0.22.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" + +[[package]] +name = "base64ct" +version = "1.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89e25b6adfb930f02d1981565a6e5d9c547ac15a96606256d3b59040e5cd4ca3" + +[[package]] +name = "bimap" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "230c5f1ca6a325a32553f8640d31ac9b49f2411e901e427570154868b46da4f7" + +[[package]] +name = "bit-set" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08807e080ed7f9d5433fa9b275196cfc35414f66a0c79d864dc51a0d825231a3" +dependencies = [ + "bit-vec", +] + +[[package]] +name = "bit-vec" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e764a1d40d510daf35e07be9eb06e75770908c27d411ee6c92109c9840eaaf7" + +[[package]] +name = "bitflags" +version = "2.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c8214115b7bf84099f1309324e63141d4c5d7cc26862f97a0a857dbefe165bd" + +[[package]] +name = "bitvec" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bc2832c24239b0141d5674bb9174f9d68a8b5b3f2753311927c172ca46f7e9c" +dependencies = [ + "funty", + "radium", + "tap", + "wyz", +] + +[[package]] +name = "block-buffer" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" +dependencies = [ + "generic-array", +] + +[[package]] +name = "blst" +version = "0.3.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "47c79a94619fade3c0b887670333513a67ac28a6a7e653eb260bf0d4103db38d" +dependencies = [ + "cc", + "glob", + "threadpool", + "zeroize", +] + +[[package]] +name = "bumpalo" +version = "3.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1628fb46dfa0b37568d12e5edd512553eccf6a22a78e8bde00bb4aed84d5bdbf" + +[[package]] +name = "byte-slice-cast" +version = "1.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7575182f7272186991736b70173b0ea045398f984bf5ebbb3804736ce1330c9d" + +[[package]] +name = "byteorder" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" + +[[package]] +name = "bytes" +version = "1.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d71b6127be86fdcfddb610f7182ac57211d4b18a3e9c82eb2d17662f2227ad6a" +dependencies = [ + "serde", +] + +[[package]] +name = "c-kzg" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e7e3c397401eb76228c89561cf22f85f41c95aa799ee9d860de3ea1cbc728fc" +dependencies = [ + "arbitrary", + "blst", + "cc", + "glob", + "hex", + "libc", + "once_cell", + "serde", +] + +[[package]] +name = "cc" +version = "1.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be714c154be609ec7f5dad223a33bf1482fff90472de28f7362806e6d4832b8c" +dependencies = [ + "shlex", +] + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "chrono" +version = "0.4.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a7964611d71df112cb1730f2ee67324fcf4d0fc6606acbbe9bfe06df124637c" +dependencies = [ + "android-tzdata", + "iana-time-zone", + "num-traits", + "serde", + "windows-link", +] + +[[package]] +name = "clap" +version = "4.5.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6088f3ae8c3608d19260cd7445411865a485688711b78b5be70d78cd96136f83" +dependencies = [ + "clap_builder", + "clap_derive", +] + +[[package]] +name = "clap_builder" +version = "4.5.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22a7ef7f676155edfb82daa97f99441f3ebf4a58d5e32f295a56259f1b6facc8" +dependencies = [ + "anstream", + "anstyle", + "clap_lex", + "strsim", +] + +[[package]] +name = "clap_derive" +version = "4.5.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09176aae279615badda0765c0c0b3f6ed53f4709118af73cf4655d85d1530cd7" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "syn 2.0.100", +] + +[[package]] +name = "clap_lex" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f46ad14479a25103f283c0f10005961cf086d8dc42205bb44c46ac563475dca6" + +[[package]] +name = "colorchoice" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b63caa9aa9397e2d9480a9b13673856c78d8ac123288526c37d7839f2a86990" + +[[package]] +name = "const-hex" +version = "1.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4b0485bab839b018a8f1723fc5391819fea5f8f0f32288ef8a735fd096b6160c" +dependencies = [ + "cfg-if", + "cpufeatures", + "hex", + "proptest", + "serde", +] + +[[package]] +name = "const-oid" +version = "0.9.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8" + +[[package]] +name = "const_format" +version = "0.2.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "126f97965c8ad46d6d9163268ff28432e8f6a1196a55578867832e3049df63dd" +dependencies = [ + "const_format_proc_macros", +] + +[[package]] +name = "const_format_proc_macros" +version = "0.2.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d57c2eccfb16dbac1f4e61e206105db5820c9d26c3c472bc17c774259ef7744" +dependencies = [ + "proc-macro2", + "quote", + "unicode-xid", +] + +[[package]] +name = "core-foundation" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[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" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280" +dependencies = [ + "libc", +] + +[[package]] +name = "crc" +version = "3.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69e6e4d7b33a94f0991c26729976b10ebde1d34c3ee82408fb536164fa10d636" +dependencies = [ + "crc-catalog", +] + +[[package]] +name = "crc-catalog" +version = "2.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19d374276b40fb8bbdee95aef7c7fa6b5316ec764510eb64b8dd0e2ed0d7e7f5" + +[[package]] +name = "crossbeam-deque" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9dd111b7b7f7d55b72c0a6ae361660ee5853c9af73f70c3c2ef6858b950e2e51" +dependencies = [ + "crossbeam-epoch", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-epoch" +version = "0.9.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" +dependencies = [ + "crossbeam-utils", +] + +[[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.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43da5946c66ffcc7745f48db692ffbb10a83bfe0afd96235c5c2a4fb23994929" + +[[package]] +name = "crypto-bigint" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0dc92fb57ca44df6db8059111ab3af99a63d5d0f8375d9972e319a379c6bab76" +dependencies = [ + "generic-array", + "rand_core", + "subtle", + "zeroize", +] + +[[package]] +name = "crypto-common" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" +dependencies = [ + "generic-array", + "typenum", +] + +[[package]] +name = "darling" +version = "0.20.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f63b86c8a8826a49b8c21f08a2d07338eec8d900540f8630dc76284be802989" +dependencies = [ + "darling_core", + "darling_macro", +] + +[[package]] +name = "darling_core" +version = "0.20.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95133861a8032aaea082871032f5815eb9e98cef03fa916ab4500513994df9e5" +dependencies = [ + "fnv", + "ident_case", + "proc-macro2", + "quote", + "strsim", + "syn 2.0.100", +] + +[[package]] +name = "darling_macro" +version = "0.20.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d336a2a514f6ccccaa3e09b02d41d35330c07ddf03a62165fcec10bb561c7806" +dependencies = [ + "darling_core", + "quote", + "syn 2.0.100", +] + +[[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]] +name = "der" +version = "0.7.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f55bf8e7b65898637379c1b74eb1551107c8294ed26d855ceb9fd1a09cfc9bc0" +dependencies = [ + "const-oid", + "zeroize", +] + +[[package]] +name = "deranged" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c9e6a11ca8224451684bc0d7d5a7adbf8f2fd6887261a1cfc3c0432f9d4068e" +dependencies = [ + "powerfmt", + "serde", +] + +[[package]] +name = "derivative" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fcc3dd5e9e9c0b295d6e1e4d811fb6f157d5ffd784b8d202fc62eac8035a770b" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "derive_arbitrary" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "30542c1ad912e0e3d22a1935c290e12e8a29d704a420177a31faad4a601a0800" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.100", +] + +[[package]] +name = "derive_more" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a9b99b9cbbe49445b21764dc0625032a89b145a2642e67603e1c936f5458d05" +dependencies = [ + "derive_more-impl 1.0.0", +] + +[[package]] +name = "derive_more" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "093242cf7570c207c83073cf82f79706fe7b8317e98620a47d5be7c3d8497678" +dependencies = [ + "derive_more-impl 2.0.1", +] + +[[package]] +name = "derive_more-impl" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb7330aeadfbe296029522e6c40f315320aba36fc43a5b3632f3795348f3bd22" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.100", +] + +[[package]] +name = "derive_more-impl" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bda628edc44c4bb645fbe0f758797143e4e07926f7ebf4e9bdfbd3d2ce621df3" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.100", + "unicode-xid", +] + +[[package]] +name = "digest" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066" +dependencies = [ + "generic-array", +] + +[[package]] +name = "digest" +version = "0.10.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" +dependencies = [ + "block-buffer", + "const-oid", + "crypto-common", + "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.100", +] + +[[package]] +name = "doctest-file" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aac81fa3e28d21450aa4d2ac065992ba96a1d7303efbce51a95f4fd175b67562" + +[[package]] +name = "dunce" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92773504d58c093f6de2459af4af33faa518c13451eb8f2b5698ed3d36e7c813" + +[[package]] +name = "ecdsa" +version = "0.16.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee27f32b5c5292967d2d4a9d7f1e0b0aed2c15daded5a60300e4abb9d8020bca" +dependencies = [ + "der", + "digest 0.10.7", + "elliptic-curve", + "rfc6979", + "serdect", + "signature", + "spki", +] + +[[package]] +name = "either" +version = "1.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" +dependencies = [ + "serde", +] + +[[package]] +name = "elliptic-curve" +version = "0.13.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5e6043086bf7973472e0c7dff2142ea0b680d30e18d9cc40f267efbf222bd47" +dependencies = [ + "base16ct", + "crypto-bigint", + "digest 0.10.7", + "ff", + "generic-array", + "group", + "pkcs8", + "rand_core", + "sec1", + "serdect", + "subtle", + "zeroize", +] + +[[package]] +name = "encoding_rs" +version = "0.8.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75030f3c4f45dafd7586dd6780965a8c7e8e285a5ecb86713e63a79c5b2766f3" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "env_filter" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "186e05a59d4c50738528153b83b0b0194d3a29507dfec16eccd4b342903397d0" +dependencies = [ + "log", + "regex", +] + +[[package]] +name = "env_logger" +version = "0.11.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3716d7a920fb4fac5d84e9d4bce8ceb321e9414b4409da61b07b75c1e3d0697" +dependencies = [ + "anstream", + "anstyle", + "env_filter", + "jiff", + "log", +] + +[[package]] +name = "equivalent" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" + +[[package]] +name = "errno" +version = "0.3.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33d852cb9b869c2a9b3df2f71a3074817f01e1844f839a144f5fcef059a4eb5d" +dependencies = [ + "libc", + "windows-sys 0.59.0", +] + +[[package]] +name = "fastrand" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" + +[[package]] +name = "fastrlp" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "139834ddba373bbdd213dffe02c8d110508dcf1726c2be27e8d1f7d7e1856418" +dependencies = [ + "arrayvec", + "auto_impl", + "bytes", +] + +[[package]] +name = "fastrlp" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce8dba4714ef14b8274c371879b175aa55b16b30f269663f19d576f380018dc4" +dependencies = [ + "arrayvec", + "auto_impl", + "bytes", +] + +[[package]] +name = "ff" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0b50bfb653653f9ca9095b427bed08ab8d75a137839d9ad64eb11810d5b6393" +dependencies = [ + "rand_core", + "subtle", +] + +[[package]] +name = "fixed-hash" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "835c052cb0c08c1acf6ffd71c022172e18723949c8282f2b9f27efbc51e64534" +dependencies = [ + "byteorder", + "rand", + "rustc-hex", + "static_assertions", +] + +[[package]] +name = "fnv" +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 = "foreign-types" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" +dependencies = [ + "foreign-types-shared", +] + +[[package]] +name = "foreign-types-shared" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" + +[[package]] +name = "form_urlencoded" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456" +dependencies = [ + "percent-encoding", +] + +[[package]] +name = "funty" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c" + +[[package]] +name = "futures" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "65bc07b1a8bc7c85c5f2e110c476c7389b4554ba72af57d8445ea63a576b0876" +dependencies = [ + "futures-channel", + "futures-core", + "futures-executor", + "futures-io", + "futures-sink", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-channel" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2dff15bf788c671c1934e366d07e30c1814a8ef514e1af724a602e8a2fbe1b10" +dependencies = [ + "futures-core", + "futures-sink", +] + +[[package]] +name = "futures-core" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e" + +[[package]] +name = "futures-executor" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e28d1d997f585e54aebc3f97d39e72338912123a67330d723fdbb564d646c9f" +dependencies = [ + "futures-core", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-io" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6" + +[[package]] +name = "futures-macro" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.100", +] + +[[package]] +name = "futures-sink" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e575fab7d1e0dcb8d0c7bcf9a63ee213816ab51902e6d244a95819acacf1d4f7" + +[[package]] +name = "futures-task" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988" + +[[package]] +name = "futures-util" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81" +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.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" +dependencies = [ + "typenum", + "version_check", + "zeroize", +] + +[[package]] +name = "getrandom" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" +dependencies = [ + "cfg-if", + "libc", + "wasi 0.11.0+wasi-snapshot-preview1", +] + +[[package]] +name = "getrandom" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73fea8450eea4bac3940448fb7ae50d91f034f941199fcd9d909a5a07aa455f0" +dependencies = [ + "cfg-if", + "libc", + "r-efi", + "wasi 0.14.2+wasi-0.2.4", +] + +[[package]] +name = "gimli" +version = "0.31.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f" + +[[package]] +name = "glob" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8d1add55171497b4705a648c6b583acafb01d58050a51727785f0b2c8e0a2b2" + +[[package]] +name = "group" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0f9ef7462f7c099f518d754361858f86d8a07af53ba9af0fe635bbccb151a63" +dependencies = [ + "ff", + "rand_core", + "subtle", +] + +[[package]] +name = "h2" +version = "0.4.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5017294ff4bb30944501348f6f8e42e6ad28f42c8bbef7a74029aff064a4e3c2" +dependencies = [ + "atomic-waker", + "bytes", + "fnv", + "futures-core", + "futures-sink", + "http", + "indexmap 2.8.0", + "slab", + "tokio", + "tokio-util", + "tracing", +] + +[[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.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289" +dependencies = [ + "allocator-api2", + "equivalent", + "foldhash", + "serde", +] + +[[package]] +name = "heck" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" + +[[package]] +name = "hermit-abi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" + +[[package]] +name = "hex" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" +dependencies = [ + "serde", +] + +[[package]] +name = "hmac" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" +dependencies = [ + "digest 0.10.7", +] + +[[package]] +name = "http" +version = "1.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4a85d31aea989eead29a3aaf9e1115a180df8282431156e533de47660892565" +dependencies = [ + "bytes", + "fnv", + "itoa", +] + +[[package]] +name = "http-body" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184" +dependencies = [ + "bytes", + "http", +] + +[[package]] +name = "http-body-util" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b021d93e26becf5dc7e1b75b1bed1fd93124b374ceb73f43d4d4eafec896a64a" +dependencies = [ + "bytes", + "futures-core", + "http", + "http-body", + "pin-project-lite", +] + +[[package]] +name = "httparse" +version = "1.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6dbf3de79e51f3d586ab4cb9d5c3e2c14aa28ed23d180cf89b4df0454a69cc87" + +[[package]] +name = "hyper" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc2b571658e38e0c01b1fdca3bbbe93c00d3d71693ff2770043f8c29bc7d6f80" +dependencies = [ + "bytes", + "futures-channel", + "futures-util", + "h2", + "http", + "http-body", + "httparse", + "itoa", + "pin-project-lite", + "smallvec", + "tokio", + "want", +] + +[[package]] +name = "hyper-rustls" +version = "0.27.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d191583f3da1305256f22463b9bb0471acad48a4e534a5218b9963e9c1f59b2" +dependencies = [ + "futures-util", + "http", + "hyper", + "hyper-util", + "rustls", + "rustls-pki-types", + "tokio", + "tokio-rustls", + "tower-service", +] + +[[package]] +name = "hyper-tls" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70206fc6890eaca9fde8a0bf71caa2ddfc9fe045ac9e5c70df101a7dbde866e0" +dependencies = [ + "bytes", + "http-body-util", + "hyper", + "hyper-util", + "native-tls", + "tokio", + "tokio-native-tls", + "tower-service", +] + +[[package]] +name = "hyper-util" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df2dcfbe0677734ab2f3ffa7fa7bfd4706bfdc1ef393f2ee30184aed67e631b4" +dependencies = [ + "bytes", + "futures-channel", + "futures-util", + "http", + "http-body", + "hyper", + "pin-project-lite", + "socket2", + "tokio", + "tower-service", + "tracing", +] + +[[package]] +name = "iana-time-zone" +version = "0.1.61" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "235e081f3925a06703c2d0117ea8b91f042756fd6e7a6e5d901e8ca1a996b220" +dependencies = [ + "android_system_properties", + "core-foundation-sys", + "iana-time-zone-haiku", + "js-sys", + "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 = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db2fa452206ebee18c4b5c2274dbf1de17008e874b4dc4f0aea9d01ca79e4526" +dependencies = [ + "displaydoc", + "yoke", + "zerofrom", + "zerovec", +] + +[[package]] +name = "icu_locid" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13acbb8371917fc971be86fc8057c41a64b521c184808a698c02acc242dbf637" +dependencies = [ + "displaydoc", + "litemap", + "tinystr", + "writeable", + "zerovec", +] + +[[package]] +name = "icu_locid_transform" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "01d11ac35de8e40fdeda00d9e1e9d92525f3f9d887cdd7aa81d727596788b54e" +dependencies = [ + "displaydoc", + "icu_locid", + "icu_locid_transform_data", + "icu_provider", + "tinystr", + "zerovec", +] + +[[package]] +name = "icu_locid_transform_data" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fdc8ff3388f852bede6b579ad4e978ab004f139284d7b28715f773507b946f6e" + +[[package]] +name = "icu_normalizer" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19ce3e0da2ec68599d193c93d088142efd7f9c5d6fc9b803774855747dc6a84f" +dependencies = [ + "displaydoc", + "icu_collections", + "icu_normalizer_data", + "icu_properties", + "icu_provider", + "smallvec", + "utf16_iter", + "utf8_iter", + "write16", + "zerovec", +] + +[[package]] +name = "icu_normalizer_data" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8cafbf7aa791e9b22bec55a167906f9e1215fd475cd22adfcf660e03e989516" + +[[package]] +name = "icu_properties" +version = "1.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93d6020766cfc6302c15dbbc9c8778c37e62c14427cb7f6e601d849e092aeef5" +dependencies = [ + "displaydoc", + "icu_collections", + "icu_locid_transform", + "icu_properties_data", + "icu_provider", + "tinystr", + "zerovec", +] + +[[package]] +name = "icu_properties_data" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67a8effbc3dd3e4ba1afa8ad918d5684b8868b3b26500753effea8d2eed19569" + +[[package]] +name = "icu_provider" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ed421c8a8ef78d3e2dbc98a973be2f3770cb42b606e3ab18d6237c4dfde68d9" +dependencies = [ + "displaydoc", + "icu_locid", + "icu_provider_macros", + "stable_deref_trait", + "tinystr", + "writeable", + "yoke", + "zerofrom", + "zerovec", +] + +[[package]] +name = "icu_provider_macros" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ec89e9337638ecdc08744df490b221a7399bf8d164eb52a665454e60e075ad6" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.100", +] + +[[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.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "686f825264d630750a544639377bae737628043f20d38bbc029e8f29ea968a7e" +dependencies = [ + "idna_adapter", + "smallvec", + "utf8_iter", +] + +[[package]] +name = "idna_adapter" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "daca1df1c957320b2cf139ac61e7bd64fed304c5040df000a745aa1de3b4ef71" +dependencies = [ + "icu_normalizer", + "icu_properties", +] + +[[package]] +name = "impl-codec" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba6a270039626615617f3f36d15fc827041df3b78c439da2cadfa47455a77f2f" +dependencies = [ + "parity-scale-codec", +] + +[[package]] +name = "impl-trait-for-tuples" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a0eb5a3343abf848c0984fe4604b2b105da9539376e24fc0a3b0007411ae4fd9" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.100", +] + +[[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]] +name = "indexmap" +version = "2.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3954d50fe15b02142bf25d3b8bdadb634ec3948f103d04ffe3031bc8fe9d7058" +dependencies = [ + "equivalent", + "hashbrown 0.15.2", + "serde", +] + +[[package]] +name = "interprocess" +version = "2.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d941b405bd2322993887859a8ee6ac9134945a24ec5ec763a8a962fc64dfec2d" +dependencies = [ + "doctest-file", + "futures-core", + "libc", + "recvmsg", + "tokio", + "widestring", + "windows-sys 0.52.0", +] + +[[package]] +name = "ipnet" +version = "2.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "469fb0b9cefa57e3ef31275ee7cacb78f2fdca44e4765491884a2b119d4eb130" + +[[package]] +name = "is_terminal_polyfill" +version = "1.70.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf" + +[[package]] +name = "itertools" +version = "0.10.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473" +dependencies = [ + "either", +] + +[[package]] +name = "itertools" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b192c782037fadd9cfa75548310488aabdbf3d2da73885b31bd0abd03351285" +dependencies = [ + "either", +] + +[[package]] +name = "itoa" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" + +[[package]] +name = "jiff" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d699bc6dfc879fb1bf9bdff0d4c56f0884fc6f0d0eb0fba397a6d00cd9a6b85e" +dependencies = [ + "jiff-static", + "log", + "portable-atomic", + "portable-atomic-util", + "serde", +] + +[[package]] +name = "jiff-static" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d16e75759ee0aa64c57a56acbf43916987b20c77373cb7e808979e02b93c9f9" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.100", +] + +[[package]] +name = "js-sys" +version = "0.3.77" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1cfaf33c695fc6e08064efbc1f72ec937429614f25eef83af942d0e227c3a28f" +dependencies = [ + "once_cell", + "wasm-bindgen", +] + +[[package]] +name = "k256" +version = "0.13.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6e3919bbaa2945715f0bb6d3934a173d1e9a59ac23767fbaaef277265a7411b" +dependencies = [ + "cfg-if", + "ecdsa", + "elliptic-curve", + "once_cell", + "serdect", + "sha2", +] + +[[package]] +name = "keccak" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ecc2af9a1119c51f12a14607e783cb977bde58bc069ff0c3da1095e635d70654" +dependencies = [ + "cpufeatures", +] + +[[package]] +name = "keccak-asm" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "505d1856a39b200489082f90d897c3f07c455563880bc5952e38eabf731c83b6" +dependencies = [ + "digest 0.10.7", + "sha3-asm", +] + +[[package]] +name = "lazy_static" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" + +[[package]] +name = "libc" +version = "0.2.171" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c19937216e9d3aa9956d9bb8dfc0b0c8beb6058fc4f7a4dc4d850edf86a237d6" + +[[package]] +name = "libm" +version = "0.2.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8355be11b20d696c8f18f6cc018c4e372165b1fa8126cef092399c9951984ffa" + +[[package]] +name = "linux-raw-sys" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fe7db12097d22ec582439daf8618b8fdd1a7bef6270e9af3b1ebcd30893cf413" + +[[package]] +name = "litemap" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23fb14cb19457329c82206317a5663005a4d404783dc74f4252769b0d5f42856" + +[[package]] +name = "lock_api" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17" +dependencies = [ + "autocfg", + "scopeguard", +] + +[[package]] +name = "log" +version = "0.4.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "30bde2b3dc3671ae49d8e2e9f044c7c005836e7a023ee57cffa25ab82764bb9e" + +[[package]] +name = "lru" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "227748d55f2f0ab4735d87fd623798cb6b664512fe979705f829c9f81c934465" +dependencies = [ + "hashbrown 0.15.2", +] + +[[package]] +name = "macro-string" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b27834086c65ec3f9387b096d66e99f221cf081c2b738042aa252bcd41204e3" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.100", +] + +[[package]] +name = "memchr" +version = "2.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" + +[[package]] +name = "mime" +version = "0.3.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" + +[[package]] +name = "miniz_oxide" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e3e04debbb59698c15bacbb6d93584a8c0ca9cc3213cb423d31f760d8843ce5" +dependencies = [ + "adler2", +] + +[[package]] +name = "mio" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2886843bf800fba2e3377cff24abf6379b4c4d5c6681eaf9ea5b0d15090450bd" +dependencies = [ + "libc", + "wasi 0.11.0+wasi-snapshot-preview1", + "windows-sys 0.52.0", +] + +[[package]] +name = "native-tls" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87de3442987e9dbec73158d5c715e7ad9072fda936bb03d19d7fa10e00520f0e" +dependencies = [ + "libc", + "log", + "openssl", + "openssl-probe", + "openssl-sys", + "schannel", + "security-framework", + "security-framework-sys", + "tempfile", +] + +[[package]] +name = "num-bigint" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9" +dependencies = [ + "num-integer", + "num-traits", +] + +[[package]] +name = "num-conv" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" + +[[package]] +name = "num-integer" +version = "0.1.46" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" +dependencies = [ + "num-traits", +] + +[[package]] +name = "num-traits" +version = "0.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" +dependencies = [ + "autocfg", + "libm", +] + +[[package]] +name = "num_cpus" +version = "1.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" +dependencies = [ + "hermit-abi", + "libc", +] + +[[package]] +name = "num_enum" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e613fc340b2220f734a8595782c551f1250e969d87d3be1ae0579e8d4065179" +dependencies = [ + "num_enum_derive", +] + +[[package]] +name = "num_enum_derive" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af1844ef2428cc3e1cb900be36181049ef3d3193c63e43026cfe202983b27a56" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.100", +] + +[[package]] +name = "nybbles" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8983bb634df7248924ee0c4c3a749609b5abcb082c28fffe3254b3eb3602b307" +dependencies = [ + "alloy-rlp", + "const-hex", + "proptest", + "serde", + "smallvec", +] + +[[package]] +name = "object" +version = "0.36.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62948e14d923ea95ea2c7c86c71013138b66525b86bdc08d2dcc262bdb497b87" +dependencies = [ + "memchr", +] + +[[package]] +name = "once_cell" +version = "1.21.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d75b0bedcc4fe52caa0e03d9f1151a323e4aa5e2d78ba3580400cd3c9e2bc4bc" + +[[package]] +name = "openssl" +version = "0.10.71" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e14130c6a98cd258fdcb0fb6d744152343ff729cbfcb28c656a9d12b999fbcd" +dependencies = [ + "bitflags", + "cfg-if", + "foreign-types", + "libc", + "once_cell", + "openssl-macros", + "openssl-sys", +] + +[[package]] +name = "openssl-macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.100", +] + +[[package]] +name = "openssl-probe" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d05e27ee213611ffe7d6348b942e8f942b37114c00cc03cec254295a4a17852e" + +[[package]] +name = "openssl-sys" +version = "0.9.106" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8bb61ea9811cc39e3c2069f40b8b8e2e70d8569b361f879786cc7ed48b777cdd" +dependencies = [ + "cc", + "libc", + "pkg-config", + "vcpkg", +] + +[[package]] +name = "parity-scale-codec" +version = "3.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c9fde3d0718baf5bc92f577d652001da0f8d54cd03a7974e118d04fc888dc23d" +dependencies = [ + "arrayvec", + "bitvec", + "byte-slice-cast", + "const_format", + "impl-trait-for-tuples", + "parity-scale-codec-derive", + "rustversion", + "serde", +] + +[[package]] +name = "parity-scale-codec-derive" +version = "3.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "581c837bb6b9541ce7faa9377c20616e4fb7650f6b0f68bc93c827ee504fb7b3" +dependencies = [ + "proc-macro-crate", + "proc-macro2", + "quote", + "syn 2.0.100", +] + +[[package]] +name = "parking_lot" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1bf18183cf54e8d6059647fc3063646a1801cf30896933ec2311622cc4b9a27" +dependencies = [ + "lock_api", + "parking_lot_core", +] + +[[package]] +name = "parking_lot_core" +version = "0.9.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall", + "smallvec", + "windows-targets 0.52.6", +] + +[[package]] +name = "paste" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" + +[[package]] +name = "percent-encoding" +version = "2.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" + +[[package]] +name = "pest" +version = "2.7.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b7cafe60d6cf8e62e1b9b2ea516a089c008945bb5a275416789e7db0bc199dc" +dependencies = [ + "memchr", + "thiserror", + "ucd-trie", +] + +[[package]] +name = "pin-project" +version = "1.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "677f1add503faace112b9f1373e43e9e054bfdd22ff1a63c1bc485eaec6a6a8a" +dependencies = [ + "pin-project-internal", +] + +[[package]] +name = "pin-project-internal" +version = "1.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e918e4ff8c4549eb882f14b3a4bc8c8bc93de829416eacf579f1207a8fbf861" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.100", +] + +[[package]] +name = "pin-project-lite" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b" + +[[package]] +name = "pin-utils" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" + +[[package]] +name = "pkcs8" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f950b2377845cebe5cf8b5165cb3cc1a5e0fa5cfa3e1f7f55707d8fd82e0a7b7" +dependencies = [ + "der", + "spki", +] + +[[package]] +name = "pkg-config" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c" + +[[package]] +name = "portable-atomic" +version = "1.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "350e9b48cbc6b0e028b0473b114454c6316e57336ee184ceab6e53f72c178b3e" + +[[package]] +name = "portable-atomic-util" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8a2f0d8d040d7848a709caf78912debcc3f33ee4b3cac47d73d1e1069e83507" +dependencies = [ + "portable-atomic", +] + +[[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" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9" +dependencies = [ + "zerocopy", +] + +[[package]] +name = "primitive-types" +version = "0.12.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b34d9fd68ae0b74a41b21c03c2f62847aa0ffea044eee893b4c140b37e244e2" +dependencies = [ + "fixed-hash", + "impl-codec", + "uint", +] + +[[package]] +name = "proc-macro-crate" +version = "3.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "edce586971a4dfaa28950c6f18ed55e0406c1ab88bbce2c6f6293a7aaba73d35" +dependencies = [ + "toml_edit", +] + +[[package]] +name = "proc-macro-error-attr2" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96de42df36bb9bba5542fe9f1a054b8cc87e172759a1868aa05c1f3acc89dfc5" +dependencies = [ + "proc-macro2", + "quote", +] + +[[package]] +name = "proc-macro-error2" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "11ec05c52be0a07b08061f7dd003e7d7092e0472bc731b4af7bb1ef876109802" +dependencies = [ + "proc-macro-error-attr2", + "proc-macro2", + "quote", + "syn 2.0.100", +] + +[[package]] +name = "proc-macro2" +version = "1.0.94" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a31971752e70b8b2686d7e46ec17fb38dad4051d94024c88df49b667caea9c84" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "proptest" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "14cae93065090804185d3b75f0bf93b8eeda30c7a9b4a33d3bdb3988d6229e50" +dependencies = [ + "bit-set", + "bit-vec", + "bitflags", + "lazy_static", + "num-traits", + "rand", + "rand_chacha", + "rand_xorshift", + "regex-syntax", + "rusty-fork", + "tempfile", + "unarray", +] + +[[package]] +name = "psm" +version = "0.1.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f58e5423e24c18cc840e1c98370b3993c6649cd1678b4d24318bcf0a083cbe88" +dependencies = [ + "cc", +] + +[[package]] +name = "quick-error" +version = "1.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0" + +[[package]] +name = "quote" +version = "1.0.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "r-efi" +version = "5.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "74765f6d916ee2faa39bc8e68e4f3ed8949b48cccdac59983d287a7cb71ce9c5" + +[[package]] +name = "radium" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09" + +[[package]] +name = "rand" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +dependencies = [ + "libc", + "rand_chacha", + "rand_core", + "serde", +] + +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", + "rand_core", +] + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "getrandom 0.2.15", +] + +[[package]] +name = "rand_xorshift" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d25bf25ec5ae4a3f1b92f929810509a2f53d7dca2f50b794ff57e3face536c8f" +dependencies = [ + "rand_core", +] + +[[package]] +name = "rayon" +version = "1.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b418a60154510ca1a002a752ca9714984e21e4241e804d32555251faf8b78ffa" +dependencies = [ + "either", + "rayon-core", +] + +[[package]] +name = "rayon-core" +version = "1.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1465873a3dfdaa8ae7cb14b4383657caab0b3e8a0aa9ae8e04b044854c8dfce2" +dependencies = [ + "crossbeam-deque", + "crossbeam-utils", +] + +[[package]] +name = "recvmsg" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3edd4d5d42c92f0a659926464d4cce56b562761267ecf0f469d85b7de384175" + +[[package]] +name = "redox_syscall" +version = "0.5.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b8c0c260b63a8219631167be35e6a988e9554dbd323f8bd08439c8ed1302bd1" +dependencies = [ + "bitflags", +] + +[[package]] +name = "regex" +version = "1.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax", +] + +[[package]] +name = "regex-automata" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" + +[[package]] +name = "reqwest" +version = "0.12.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d19c46a6fdd48bc4dab94b6103fccc55d34c67cc0ad04653aad4ea2a07cd7bbb" +dependencies = [ + "base64", + "bytes", + "encoding_rs", + "futures-channel", + "futures-core", + "futures-util", + "h2", + "http", + "http-body", + "http-body-util", + "hyper", + "hyper-rustls", + "hyper-tls", + "hyper-util", + "ipnet", + "js-sys", + "log", + "mime", + "native-tls", + "once_cell", + "percent-encoding", + "pin-project-lite", + "rustls-pemfile", + "serde", + "serde_json", + "serde_urlencoded", + "sync_wrapper", + "system-configuration", + "tokio", + "tokio-native-tls", + "tower", + "tower-service", + "url", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", + "windows-registry", +] + +[[package]] +name = "revive-common" +version = "0.1.0-dev.12" +source = "git+https://github.com/paritytech/revive?rev=497dae2494dabe12d1af32d6d687122903cb2ada#497dae2494dabe12d1af32d6d687122903cb2ada" +dependencies = [ + "anyhow", + "serde", + "serde_json", + "serde_stacker", +] + +[[package]] +name = "revive-dt-compiler" +version = "0.1.0" +dependencies = [ + "anyhow", + "revive-common", + "revive-solc-json-interface", + "semver 1.0.26", + "serde_json", +] + +[[package]] +name = "revive-dt-config" +version = "0.1.0" +dependencies = [ + "alloy", + "clap", + "semver 1.0.26", + "temp-dir", +] + +[[package]] +name = "revive-dt-core" +version = "0.1.0" +dependencies = [ + "alloy", + "anyhow", + "clap", + "env_logger", + "log", + "rayon", + "revive-dt-compiler", + "revive-dt-config", + "revive-dt-format", + "revive-dt-node", + "revive-dt-node-interaction", + "revive-dt-solc-binaries", + "revive-solc-json-interface", + "semver 1.0.26", + "serde", + "serde_json", + "temp-dir", +] + +[[package]] +name = "revive-dt-format" +version = "0.1.0" +dependencies = [ + "alloy", + "anyhow", + "log", + "semver 1.0.26", + "serde", + "serde_json", +] + +[[package]] +name = "revive-dt-node" +version = "0.1.0" +dependencies = [ + "alloy", + "anyhow", + "log", + "revive-dt-config", + "revive-dt-node-interaction", + "serde_json", + "temp-dir", +] + +[[package]] +name = "revive-dt-node-interaction" +version = "0.1.0" +dependencies = [ + "alloy", + "anyhow", + "hex", + "log", + "once_cell", + "serde_json", + "tokio", +] + +[[package]] +name = "revive-dt-solc-binaries" +version = "0.1.0" +dependencies = [ + "anyhow", + "hex", + "log", + "reqwest", + "semver 1.0.26", + "serde", + "sha2", +] + +[[package]] +name = "revive-solc-json-interface" +version = "0.1.0-dev.12" +source = "git+https://github.com/paritytech/revive?rev=497dae2494dabe12d1af32d6d687122903cb2ada#497dae2494dabe12d1af32d6d687122903cb2ada" +dependencies = [ + "anyhow", + "rayon", + "revive-common", + "semver 1.0.26", + "serde", + "serde_json", +] + +[[package]] +name = "rfc6979" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8dd2a808d456c4a54e300a23e9f5a67e122c3024119acbfd73e3bf664491cb2" +dependencies = [ + "hmac", + "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.15", + "libc", + "untrusted", + "windows-sys 0.52.0", +] + +[[package]] +name = "rlp" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb919243f34364b6bd2fc10ef797edbfa75f33c252e7998527479c6d6b47e1ec" +dependencies = [ + "bytes", + "rustc-hex", +] + +[[package]] +name = "ruint" +version = "1.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "825df406ec217a8116bd7b06897c6cc8f65ffefc15d030ae2c9540acc9ed50b6" +dependencies = [ + "alloy-rlp", + "ark-ff 0.3.0", + "ark-ff 0.4.2", + "bytes", + "fastrlp 0.3.1", + "fastrlp 0.4.0", + "num-bigint", + "num-integer", + "num-traits", + "parity-scale-codec", + "primitive-types", + "proptest", + "rand", + "rlp", + "ruint-macro", + "serde", + "valuable", + "zeroize", +] + +[[package]] +name = "ruint-macro" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48fd7bd8a6377e15ad9d42a8ec25371b94ddc67abe7c8b9127bec79bebaaae18" + +[[package]] +name = "rustc-demangle" +version = "0.1.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" + +[[package]] +name = "rustc-hash" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "357703d41365b4b27c590e3ed91eabb1b663f07c4c084095e60cbed4362dff0d" + +[[package]] +name = "rustc-hex" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3e75f6a532d0fd9f7f13144f392b6ad56a32696bfcd9c78f797f16bbb6f072d6" + +[[package]] +name = "rustc_version" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0dfe2087c51c460008730de8b57e6a320782fbfb312e1f4d520e6c6fae155ee" +dependencies = [ + "semver 0.11.0", +] + +[[package]] +name = "rustc_version" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92" +dependencies = [ + "semver 1.0.26", +] + +[[package]] +name = "rustix" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e56a18552996ac8d29ecc3b190b4fdbb2d91ca4ec396de7bbffaf43f3d637e96" +dependencies = [ + "bitflags", + "errno", + "libc", + "linux-raw-sys", + "windows-sys 0.59.0", +] + +[[package]] +name = "rustls" +version = "0.23.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "822ee9188ac4ec04a2f0531e55d035fb2de73f18b41a63c70c2712503b6fb13c" +dependencies = [ + "once_cell", + "rustls-pki-types", + "rustls-webpki", + "subtle", + "zeroize", +] + +[[package]] +name = "rustls-pemfile" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dce314e5fee3f39953d46bb63bb8a46d40c2f8fb7cc5a3b6cab2bde9721d6e50" +dependencies = [ + "rustls-pki-types", +] + +[[package]] +name = "rustls-pki-types" +version = "1.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "917ce264624a4b4db1c364dcc35bfca9ded014d0a958cd47ad3e960e988ea51c" + +[[package]] +name = "rustls-webpki" +version = "0.103.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0aa4eeac2588ffff23e9d7a7e9b3f971c5fb5b7ebc9452745e0c232c64f83b2f" +dependencies = [ + "ring", + "rustls-pki-types", + "untrusted", +] + +[[package]] +name = "rustversion" +version = "1.0.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eded382c5f5f786b989652c49544c4877d9f015cc22e145a5ea8ea66c2921cd2" + +[[package]] +name = "rusty-fork" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb3dcc6e454c328bb824492db107ab7c0ae8fcffe4ad210136ef014458c1bc4f" +dependencies = [ + "fnv", + "quick-error", + "tempfile", + "wait-timeout", +] + +[[package]] +name = "ryu" +version = "1.0.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f" + +[[package]] +name = "schannel" +version = "0.1.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f29ebaa345f945cec9fbbc532eb307f0fdad8161f281b6369539c8d84876b3d" +dependencies = [ + "windows-sys 0.59.0", +] + +[[package]] +name = "scopeguard" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" + +[[package]] +name = "sec1" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3e97a565f76233a6003f9f5c54be1d9c5bdfa3eccfb189469f11ec4901c47dc" +dependencies = [ + "base16ct", + "der", + "generic-array", + "pkcs8", + "serdect", + "subtle", + "zeroize", +] + +[[package]] +name = "security-framework" +version = "2.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02" +dependencies = [ + "bitflags", + "core-foundation", + "core-foundation-sys", + "libc", + "security-framework-sys", +] + +[[package]] +name = "security-framework-sys" +version = "2.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49db231d56a190491cb4aeda9527f1ad45345af50b0851622a7adb8c03b01c32" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "semver" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f301af10236f6df4160f7c3f04eec6dbc70ace82d23326abad5edee88801c6b6" +dependencies = [ + "semver-parser", +] + +[[package]] +name = "semver" +version = "1.0.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56e6fa9c48d24d85fb3de5ad847117517440f6beceb7798af16b4a87d616b8d0" +dependencies = [ + "serde", +] + +[[package]] +name = "semver-parser" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9900206b54a3527fdc7b8a938bffd94a568bac4f4aa8113b209df75a09c0dec2" +dependencies = [ + "pest", +] + +[[package]] +name = "serde" +version = "1.0.219" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f0e2c6ed6606019b4e29e69dbaba95b11854410e5347d525002456dbbb786b6" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.219" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.100", +] + +[[package]] +name = "serde_json" +version = "1.0.140" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "20068b6e96dc6c9bd23e01df8827e6c7e1f2fddd43c21810382803c136b99373" +dependencies = [ + "itoa", + "memchr", + "ryu", + "serde", +] + +[[package]] +name = "serde_stacker" +version = "0.1.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69c8defe6c780725cce4ec6ad3bd91e321baf6fa4e255df1f31e345d507ef01a" +dependencies = [ + "serde", + "stacker", +] + +[[package]] +name = "serde_urlencoded" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" +dependencies = [ + "form_urlencoded", + "itoa", + "ryu", + "serde", +] + +[[package]] +name = "serde_with" +version = "3.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6b6f7f2fcb69f747921f79f3926bd1e203fce4fef62c268dd3abfb6d86029aa" +dependencies = [ + "base64", + "chrono", + "hex", + "indexmap 1.9.3", + "indexmap 2.8.0", + "serde", + "serde_derive", + "serde_json", + "serde_with_macros", + "time", +] + +[[package]] +name = "serde_with_macros" +version = "3.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d00caa5193a3c8362ac2b73be6b9e768aa5a4b2f721d8f4b339600c3cb51f8e" +dependencies = [ + "darling", + "proc-macro2", + "quote", + "syn 2.0.100", +] + +[[package]] +name = "serdect" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a84f14a19e9a014bb9f4512488d9829a68e04ecabffb0f9904cd1ace94598177" +dependencies = [ + "base16ct", + "serde", +] + +[[package]] +name = "sha2" +version = "0.10.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest 0.10.7", +] + +[[package]] +name = "sha3" +version = "0.10.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75872d278a8f37ef87fa0ddbda7802605cb18344497949862c0d4dcb291eba60" +dependencies = [ + "digest 0.10.7", + "keccak", +] + +[[package]] +name = "sha3-asm" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c28efc5e327c837aa837c59eae585fc250715ef939ac32881bcc11677cd02d46" +dependencies = [ + "cc", + "cfg-if", +] + +[[package]] +name = "shlex" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" + +[[package]] +name = "signature" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77549399552de45a898a580c1b41d445bf730df867cc44e6c0233bbc4b8329de" +dependencies = [ + "digest 0.10.7", + "rand_core", +] + +[[package]] +name = "slab" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" +dependencies = [ + "autocfg", +] + +[[package]] +name = "smallvec" +version = "1.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7fcf8323ef1faaee30a44a340193b1ac6814fd9b7b4e88e9d4519a3e4abe1cfd" +dependencies = [ + "serde", +] + +[[package]] +name = "socket2" +version = "0.5.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c970269d99b64e60ec3bd6ad27270092a5394c4e309314b18ae3fe575695fbe8" +dependencies = [ + "libc", + "windows-sys 0.52.0", +] + +[[package]] +name = "spki" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d91ed6c858b01f942cd56b37a94b3e0a1798290327d1236e4d9cf4eaca44d29d" +dependencies = [ + "base64ct", + "der", +] + +[[package]] +name = "stable_deref_trait" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" + +[[package]] +name = "stacker" +version = "0.1.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "601f9201feb9b09c00266478bf459952b9ef9a6b94edb2f21eba14ab681a60a9" +dependencies = [ + "cc", + "cfg-if", + "libc", + "psm", + "windows-sys 0.59.0", +] + +[[package]] +name = "static_assertions" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" + +[[package]] +name = "strsim" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" + +[[package]] +name = "strum" +version = "0.27.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f64def088c51c9510a8579e3c5d67c65349dcf755e5479ad3d010aa6454e2c32" +dependencies = [ + "strum_macros", +] + +[[package]] +name = "strum_macros" +version = "0.27.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c77a8c5abcaf0f9ce05d62342b7d298c346515365c36b673df4ebe3ced01fde8" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "rustversion", + "syn 2.0.100", +] + +[[package]] +name = "subtle" +version = "2.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" + +[[package]] +name = "syn" +version = "1.0.109" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "syn" +version = "2.0.100" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b09a44accad81e1ba1cd74a32461ba89dee89095ba17b32f5d03683b1b1fc2a0" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "syn-solidity" +version = "0.8.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d975606bae72d8aad5b07d9342465e123a2cccf53a5a735aedf81ca92a709ecb" +dependencies = [ + "paste", + "proc-macro2", + "quote", + "syn 2.0.100", +] + +[[package]] +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.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8af7666ab7b6390ab78131fb5b0fce11d6b7a6951602017c35fa82800708971" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.100", +] + +[[package]] +name = "system-configuration" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c879d448e9d986b661742763247d3693ed13609438cf3d006f51f5368a5ba6b" +dependencies = [ + "bitflags", + "core-foundation", + "system-configuration-sys", +] + +[[package]] +name = "system-configuration-sys" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e1d1b10ced5ca923a1fcb8d03e96b8d3268065d724548c0211415ff6ac6bac4" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "tap" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" + +[[package]] +name = "temp-dir" +version = "0.1.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc1ee6eef34f12f765cb94725905c6312b6610ab2b0940889cfe58dae7bc3c72" + +[[package]] +name = "tempfile" +version = "3.19.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7437ac7763b9b123ccf33c338a5cc1bac6f69b45a136c19bdd8a65e3916435bf" +dependencies = [ + "fastrand", + "getrandom 0.3.2", + "once_cell", + "rustix", + "windows-sys 0.59.0", +] + +[[package]] +name = "thiserror" +version = "2.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "567b8a2dae586314f7be2a752ec7474332959c6460e02bde30d702a66d488708" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "2.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f7cf42b4507d8ea322120659672cf1b9dbb93f8f2d4ecfd6e51350ff5b17a1d" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.100", +] + +[[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.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d9c75b47bdff86fa3334a3db91356b8d7d86a9b839dab7d0bdc5c3d3a077618" +dependencies = [ + "deranged", + "itoa", + "num-conv", + "powerfmt", + "serde", + "time-core", + "time-macros", +] + +[[package]] +name = "time-core" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c9e9a38711f559d9e3ce1cdb06dd7c5b8ea546bc90052da6d06bb76da74bb07c" + +[[package]] +name = "time-macros" +version = "0.2.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29aa485584182073ed57fd5004aa09c371f021325014694e432313345865fd04" +dependencies = [ + "num-conv", + "time-core", +] + +[[package]] +name = "tiny-keccak" +version = "2.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c9d3793400a45f954c52e73d068316d76b6f4e36977e3fcebb13a2721e80237" +dependencies = [ + "crunchy", +] + +[[package]] +name = "tinystr" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9117f5d4db391c1cf6927e7bea3db74b9a1c1add8f7eda9ffd5364f40f57b82f" +dependencies = [ + "displaydoc", + "zerovec", +] + +[[package]] +name = "tokio" +version = "1.44.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f382da615b842244d4b8738c82ed1275e6c5dd90c459a30941cd07080b06c91a" +dependencies = [ + "backtrace", + "bytes", + "libc", + "mio", + "pin-project-lite", + "socket2", + "tokio-macros", + "windows-sys 0.52.0", +] + +[[package]] +name = "tokio-macros" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e06d43f1345a3bcd39f6a56dbb7dcab2ba47e68e8ac134855e7e2bdbaf8cab8" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.100", +] + +[[package]] +name = "tokio-native-tls" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbae76ab933c85776efabc971569dd6119c580d8f5d448769dec1764bf796ef2" +dependencies = [ + "native-tls", + "tokio", +] + +[[package]] +name = "tokio-rustls" +version = "0.26.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e727b36a1a0e8b74c376ac2211e40c2c8af09fb4013c60d910495810f008e9b" +dependencies = [ + "rustls", + "tokio", +] + +[[package]] +name = "tokio-stream" +version = "0.1.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eca58d7bba4a75707817a2c44174253f9236b2d5fbd055602e9d5c07c139a047" +dependencies = [ + "futures-core", + "pin-project-lite", + "tokio", + "tokio-util", +] + +[[package]] +name = "tokio-util" +version = "0.7.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6b9590b93e6fcc1739458317cccd391ad3955e2bde8913edf6f95f9e65a8f034" +dependencies = [ + "bytes", + "futures-core", + "futures-sink", + "pin-project-lite", + "tokio", +] + +[[package]] +name = "toml_datetime" +version = "0.6.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0dd7358ecb8fc2f8d014bf86f6f638ce72ba252a2c3a2572f2a795f1d23efb41" + +[[package]] +name = "toml_edit" +version = "0.22.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "17b4795ff5edd201c7cd6dca065ae59972ce77d1b80fa0a84d94950ece7d1474" +dependencies = [ + "indexmap 2.8.0", + "toml_datetime", + "winnow", +] + +[[package]] +name = "tower" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d039ad9159c98b70ecfd540b2573b97f7f52c3e8d9f8ad57a24b916a536975f9" +dependencies = [ + "futures-core", + "futures-util", + "pin-project-lite", + "sync_wrapper", + "tokio", + "tower-layer", + "tower-service", +] + +[[package]] +name = "tower-layer" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "121c2a6cda46980bb0fcd1647ffaf6cd3fc79a013de288782836f6df9c48780e" + +[[package]] +name = "tower-service" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3" + +[[package]] +name = "tracing" +version = "0.1.41" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "784e0ac535deb450455cbfa28a6f0df145ea1bb7ae51b821cf5e7927fdcfbdd0" +dependencies = [ + "pin-project-lite", + "tracing-attributes", + "tracing-core", +] + +[[package]] +name = "tracing-attributes" +version = "0.1.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "395ae124c09f9e6918a2310af6038fba074bcf474ac352496d5910dd59a2226d" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.100", +] + +[[package]] +name = "tracing-core" +version = "0.1.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e672c95779cf947c5311f83787af4fa8fffd12fb27e4993211a84bdfd9610f9c" +dependencies = [ + "once_cell", +] + +[[package]] +name = "tracing-futures" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97d095ae15e245a057c8e8451bab9b3ee1e1f68e9ba2b4fbc18d0ac5237835f2" +dependencies = [ + "futures", + "futures-task", + "pin-project", + "tracing", +] + +[[package]] +name = "try-lock" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" + +[[package]] +name = "typenum" +version = "1.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1dccffe3ce07af9386bfd29e80c0ab1a8205a2fc34e4bcd40364df902cfa8f3f" + +[[package]] +name = "ucd-trie" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2896d95c02a80c6d6a5d6e953d479f5ddf2dfdb6a244441010e373ac0fb88971" + +[[package]] +name = "uint" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76f64bba2c53b04fcab63c01a7d7427eadc821e3bc48c34dc9ba29c501164b52" +dependencies = [ + "byteorder", + "crunchy", + "hex", + "static_assertions", +] + +[[package]] +name = "unarray" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eaea85b334db583fe3274d12b4cd1880032beab409c0d774be044d4480ab9a94" + +[[package]] +name = "unicode-ident" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512" + +[[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 = "url" +version = "2.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32f8b686cadd1473f4bd0117a5d28d36b1ade384ea9b5069a1c40aefed7fda60" +dependencies = [ + "form_urlencoded", + "idna", + "percent-encoding", +] + +[[package]] +name = "utf16_iter" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8232dd3cdaed5356e0f716d285e4b40b932ac434100fe9b7e0e8e935b9e6246" + +[[package]] +name = "utf8_iter" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" + +[[package]] +name = "utf8parse" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" + +[[package]] +name = "valuable" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba73ea9cf16a25df0c8caa16c51acb937d5712a8429db78a3ee29d5dcacd3a65" + +[[package]] +name = "vcpkg" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" + +[[package]] +name = "version_check" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" + +[[package]] +name = "wait-timeout" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09ac3b126d3914f9849036f826e054cbabdc8519970b8998ddaf3b5bd3c65f11" +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.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" + +[[package]] +name = "wasi" +version = "0.14.2+wasi-0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9683f9a5a998d873c0d21fcbe3c083009670149a8fab228644b8bd36b2c48cb3" +dependencies = [ + "wit-bindgen-rt", +] + +[[package]] +name = "wasm-bindgen" +version = "0.2.100" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1edc8929d7499fc4e8f0be2262a241556cfc54a0bea223790e71446f2aab1ef5" +dependencies = [ + "cfg-if", + "once_cell", + "rustversion", + "wasm-bindgen-macro", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.100" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2f0a0651a5c2bc21487bde11ee802ccaf4c51935d0d3d42a6101f98161700bc6" +dependencies = [ + "bumpalo", + "log", + "proc-macro2", + "quote", + "syn 2.0.100", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-futures" +version = "0.4.50" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "555d470ec0bc3bb57890405e5d4322cc9ea83cebb085523ced7be4144dac1e61" +dependencies = [ + "cfg-if", + "js-sys", + "once_cell", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.100" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7fe63fc6d09ed3792bd0897b314f53de8e16568c2b3f7982f468c0bf9bd0b407" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.100" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.100", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.100" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a05d73b933a847d6cccdda8f838a22ff101ad9bf93e33684f39c1f5f0eece3d" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "wasmtimer" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0048ad49a55b9deb3953841fa1fc5858f0efbcb7a18868c899a360269fac1b23" +dependencies = [ + "futures", + "js-sys", + "parking_lot", + "pin-utils", + "slab", + "wasm-bindgen", +] + +[[package]] +name = "web-sys" +version = "0.3.77" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33b6dd2ef9186f1f2072e409e99cd22a975331a6b3591b12c764e0e55c60d5d2" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "widestring" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7219d36b6eac893fa81e84ebe06485e7dcbb616177469b142df14f1f4deb1311" + +[[package]] +name = "windows-core" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" +dependencies = [ + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-link" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76840935b766e1b0a05c0066835fb9ec80071d4c09a16f6bd5f7e655e3c14c38" + +[[package]] +name = "windows-registry" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4286ad90ddb45071efd1a66dfa43eb02dd0dfbae1545ad6cc3c51cf34d7e8ba3" +dependencies = [ + "windows-result", + "windows-strings", + "windows-targets 0.53.0", +] + +[[package]] +name = "windows-result" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c64fd11a4fd95df68efcfee5f44a294fe71b8bc6a91993e2791938abcc712252" +dependencies = [ + "windows-link", +] + +[[package]] +name = "windows-strings" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87fa48cc5d406560701792be122a10132491cff9d0aeb23583cc2dcafc847319" +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.59.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" +dependencies = [ + "windows-targets 0.52.6", +] + +[[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.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1e4c7e8ceaaf9cb7d7507c974735728ab453b67ef8f18febdd7c11fe59dca8b" +dependencies = [ + "windows_aarch64_gnullvm 0.53.0", + "windows_aarch64_msvc 0.53.0", + "windows_i686_gnu 0.53.0", + "windows_i686_gnullvm 0.53.0", + "windows_i686_msvc 0.53.0", + "windows_x86_64_gnu 0.53.0", + "windows_x86_64_gnullvm 0.53.0", + "windows_x86_64_msvc 0.53.0", +] + +[[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.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "86b8d5f90ddd19cb4a147a5fa63ca848db3df085e25fee3cc10b39b6eebae764" + +[[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.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7651a1f62a11b8cbd5e0d42526e55f2c99886c77e007179efff86c2b137e66c" + +[[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.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1dc67659d35f387f5f6c479dc4e28f1d4bb90ddd1a5d3da2e5d97b42d6272c3" + +[[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.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ce6ccbdedbf6d6354471319e781c0dfef054c81fbc7cf83f338a4296c0cae11" + +[[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.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "581fee95406bb13382d2f65cd4a908ca7b1e4c2f1917f143ba16efe98a589b5d" + +[[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.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e55b5ac9ea33f2fc1716d1742db15574fd6fc8dadc51caab1c16a3d3b4190ba" + +[[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.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0a6e035dd0599267ce1ee132e51c27dd29437f63325753051e71dd9e42406c57" + +[[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.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "271414315aff87387382ec3d271b52d7ae78726f5d44ac98b4f4030c91880486" + +[[package]] +name = "winnow" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e97b544156e9bebe1a0ffbc03484fc1ffe3100cbce3ffb17eac35f7cdd7ab36" +dependencies = [ + "memchr", +] + +[[package]] +name = "wit-bindgen-rt" +version = "0.39.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f42320e61fe2cfd34354ecb597f86f413484a798ba44a8ca1165c58d42da6c1" +dependencies = [ + "bitflags", +] + +[[package]] +name = "write16" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d1890f4022759daae28ed4fe62859b1236caebfc61ede2f63ed4e695f3f6d936" + +[[package]] +name = "writeable" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e9df38ee2d2c3c5948ea468a8406ff0db0b29ae1ffde1bcf20ef305bcc95c51" + +[[package]] +name = "wyz" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05f360fc0b24296329c78fda852a1e9ae82de9cf7b27dae4b7f62f118f77b9ed" +dependencies = [ + "tap", +] + +[[package]] +name = "yoke" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "120e6aef9aa629e3d4f52dc8cc43a015c7724194c97dfaf45180d2daf2b77f40" +dependencies = [ + "serde", + "stable_deref_trait", + "yoke-derive", + "zerofrom", +] + +[[package]] +name = "yoke-derive" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2380878cad4ac9aac1e2435f3eb4020e8374b5f13c296cb75b4620ff8e229154" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.100", + "synstructure", +] + +[[package]] +name = "zerocopy" +version = "0.8.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd97444d05a4328b90e75e503a34bad781f14e28a823ad3557f0750df1ebcbc6" +dependencies = [ + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.8.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6352c01d0edd5db859a63e2605f4ea3183ddbd15e2c4a9e7d32184df75e4f154" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.100", +] + +[[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.100", + "synstructure", +] + +[[package]] +name = "zeroize" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde" +dependencies = [ + "zeroize_derive", +] + +[[package]] +name = "zeroize_derive" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.100", +] + +[[package]] +name = "zerovec" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa2b893d79df23bfb12d5461018d408ea19dfafe76c2c7ef6d4eba614f8ff079" +dependencies = [ + "yoke", + "zerofrom", + "zerovec-derive", +] + +[[package]] +name = "zerovec-derive" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6eafa6dfb17584ea3e2bd6e76e0cc15ad7af12b09abdd1ca55961bed9b1063c6" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.100", +] diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..31bfb70 --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,62 @@ +[workspace] +resolver = "2" +members = ["crates/*"] + +[workspace.package] +version = "0.1.0" +authors = [ + "Parity Technologies ", +] +license = "MIT/Apache-2.0" +edition = "2024" +repository = "https://github.com/paritytech/revive-differential-testing.git" +rust-version = "1.85.0" + +[workspace.dependencies] +revive-dt-compiler = { version = "0.1.0", path = "crates/compiler" } +revive-dt-config = { version = "0.1.0", path = "crates/config" } +revive-dt-core = { version = "0.1.0", path = "crates/core" } +revive-dt-format = { version = "0.1.0", path = "crates/format" } +revive-dt-node = { version = "0.1.0", path = "crates/node" } +revive-dt-node-interaction = { version = "0.1.0", path = "crates/node-interaction" } +revive-dt-node-pool = { version = "0.1.0", path = "crates/node-pool" } +revive-dt-solc-binaries = { version = "0.1.0", path = "crates/solc-binaries" } + +anyhow = "1.0" +clap = { version = "4", features = ["derive"] } +env_logger = "0.11.7" +hex = "0.4.3" +reqwest = { version = "0.12.15", features = ["blocking", "json"] } +log = "0.4.26" +once_cell = "1.21" +rayon = { version = "1.10" } +semver = { version = "1.0", features = ["serde"] } +serde = { version = "1.0", default-features = false, features = ["derive"] } +serde_json = { version = "1.0", default-features = false, features = ["arbitrary_precision", "std"] } +sha2 = { version = "0.10.8" } +temp-dir = { version = "0.1.14" } +tokio = { version = "1", default-features = false, features = ["rt-multi-thread"] } + +# revive compiler +revive-solc-json-interface = { git = "https://github.com/paritytech/revive", rev = "497dae2494dabe12d1af32d6d687122903cb2ada" } +revive-common = { git = "https://github.com/paritytech/revive", rev = "497dae2494dabe12d1af32d6d687122903cb2ada" } +revive-differential = { git = "https://github.com/paritytech/revive", rev = "497dae2494dabe12d1af32d6d687122903cb2ada" } + +[workspace.dependencies.alloy] +version = "0.13.0" +default-features = false +features = [ + "json-abi", + "providers", + "provider-ipc", + "provider-debug-api", + "reqwest", + "rpc-types", + "signer-local", + "std", +] + +[profile.bench] +inherits = "release" +lto = true +codegen-units = 1 diff --git a/crates/compiler/Cargo.toml b/crates/compiler/Cargo.toml new file mode 100644 index 0000000..7c5af19 --- /dev/null +++ b/crates/compiler/Cargo.toml @@ -0,0 +1,16 @@ +[package] +name = "revive-dt-compiler" +description = "Library for compiling Solidity contracts to EVM and PVM" +version.workspace = true +authors.workspace = true +license.workspace = true +edition.workspace = true +repository.workspace = true +rust-version.workspace = true + +[dependencies] +anyhow = { workspace = true } +revive-solc-json-interface = { workspace = true } +revive-common = { workspace = true } +semver = { workspace = true } +serde_json = { workspace = true } diff --git a/crates/compiler/src/lib.rs b/crates/compiler/src/lib.rs new file mode 100644 index 0000000..3651eb3 --- /dev/null +++ b/crates/compiler/src/lib.rs @@ -0,0 +1,155 @@ +//! This crate provides compiler helpers for all supported Solidity targets: +//! - Ethereum solc compiler +//! - Polkadot revive resolc compiler +//! - Polkadot revive Wasm compiler + +use std::{ + fs::read_to_string, + hash::Hash, + path::{Path, PathBuf}, +}; + +use revive_common::EVMVersion; +use revive_solc_json_interface::{ + SolcStandardJsonInput, SolcStandardJsonInputLanguage, SolcStandardJsonInputSettings, + SolcStandardJsonInputSettingsOptimizer, SolcStandardJsonInputSettingsSelection, + SolcStandardJsonOutput, +}; +use semver::Version; + +pub mod revive_js; +pub mod revive_resolc; +pub mod solc; + +/// A common interface for all supported Solidity compilers. +pub trait SolidityCompiler { + /// Extra options specific to the compiler. + type Options: Default + PartialEq + Eq + Hash; + + /// The low-level compiler interface. + fn build( + &self, + input: CompilerInput, + ) -> anyhow::Result>; + + fn new(solc_executable: PathBuf) -> Self; +} + +/// The generic compilation input configuration. +#[derive(Debug)] +pub struct CompilerInput { + pub extra_options: T, + pub input: SolcStandardJsonInput, +} + +/// The generic compilation output configuration. +pub struct CompilerOutput { + pub input: CompilerInput, + pub output: SolcStandardJsonOutput, +} + +impl PartialEq for CompilerInput +where + T: PartialEq + Eq + Hash, +{ + fn eq(&self, other: &Self) -> bool { + let self_input = serde_json::to_vec(&self.input).unwrap_or_default(); + let other_input = serde_json::to_vec(&self.input).unwrap_or_default(); + self.extra_options.eq(&other.extra_options) && self_input == other_input + } +} + +impl Eq for CompilerInput where T: PartialEq + Eq + Hash {} + +impl Hash for CompilerInput +where + T: PartialEq + Eq + Hash, +{ + fn hash(&self, state: &mut H) { + self.extra_options.hash(state); + state.write(&serde_json::to_vec(&self.input).unwrap_or_default()); + } +} + +/// A generic builder style interface for configuring all compiler options. +pub struct Compiler { + input: SolcStandardJsonInput, + extra_options: T::Options, + allow_paths: Vec, + base_path: Option, +} + +impl Default for Compiler { + fn default() -> Self { + Self::new() + } +} + +impl Compiler +where + T: SolidityCompiler, +{ + pub fn new() -> Self { + Self { + input: SolcStandardJsonInput { + language: SolcStandardJsonInputLanguage::Solidity, + sources: Default::default(), + settings: SolcStandardJsonInputSettings::new( + None, + Default::default(), + None, + SolcStandardJsonInputSettingsSelection::new_required(), + SolcStandardJsonInputSettingsOptimizer::new( + false, + None, + &Version::new(0, 0, 0), + false, + ), + None, + ), + }, + extra_options: Default::default(), + allow_paths: Default::default(), + base_path: None, + } + } + + pub fn solc_optimizer(mut self, enabled: bool) -> Self { + self.input.settings.optimizer.enabled = enabled; + self + } + + pub fn with_source(mut self, path: &Path) -> anyhow::Result { + self.input + .sources + .insert(path.display().to_string(), read_to_string(path)?.into()); + Ok(self) + } + + pub fn evm_version(mut self, evm_version: EVMVersion) -> Self { + self.input.settings.evm_version = Some(evm_version); + self + } + + pub fn extra_options(mut self, extra_options: T::Options) -> Self { + self.extra_options = extra_options; + self + } + + pub fn allow_path(mut self, path: String) -> Self { + self.allow_paths.push(path); + self + } + + pub fn base_path(mut self, base_path: String) -> Self { + self.base_path = Some(base_path); + self + } + + pub fn try_build(self, solc_path: PathBuf) -> anyhow::Result> { + T::new(solc_path).build(CompilerInput { + extra_options: self.extra_options, + input: self.input, + }) + } +} diff --git a/crates/compiler/src/revive_js.rs b/crates/compiler/src/revive_js.rs new file mode 100644 index 0000000..49c7f6d --- /dev/null +++ b/crates/compiler/src/revive_js.rs @@ -0,0 +1,2 @@ +//! Implements the [crate::SolidityCompiler] trait with revive Wasm for +//! compiling contracts to PVM bytecode (via Wasm). diff --git a/crates/compiler/src/revive_resolc.rs b/crates/compiler/src/revive_resolc.rs new file mode 100644 index 0000000..ff76bc6 --- /dev/null +++ b/crates/compiler/src/revive_resolc.rs @@ -0,0 +1,2 @@ +//! Implements the [crate::SolidityCompiler] trait with resolc for +//! compiling contracts to PVM bytecode. diff --git a/crates/compiler/src/solc.rs b/crates/compiler/src/solc.rs new file mode 100644 index 0000000..aa21d51 --- /dev/null +++ b/crates/compiler/src/solc.rs @@ -0,0 +1,42 @@ +//! Implements the [SolidityCompiler] trait with solc for +//! compiling contracts to EVM bytecode. + +use std::{ + path::PathBuf, + process::{Command, Stdio}, +}; + +use crate::{CompilerInput, CompilerOutput, SolidityCompiler}; + +pub struct Solc { + solc_path: PathBuf, +} + +impl SolidityCompiler for Solc { + type Options = (); + + fn build( + &self, + input: CompilerInput, + ) -> anyhow::Result> { + let mut child = Command::new(&self.solc_path) + .stdin(Stdio::piped()) + .stdout(Stdio::piped()) + .stderr(Stdio::piped()) + .arg("--standard-json") + .spawn()?; + + let stdin = child.stdin.as_mut().expect("should be piped"); + serde_json::to_writer(stdin, &input.input)?; + + let output = child.wait_with_output()?.stdout; + Ok(CompilerOutput { + input, + output: serde_json::from_slice(&output)?, + }) + } + + fn new(solc_path: PathBuf) -> Self { + Self { solc_path } + } +} diff --git a/crates/config/Cargo.toml b/crates/config/Cargo.toml new file mode 100644 index 0000000..5df52e9 --- /dev/null +++ b/crates/config/Cargo.toml @@ -0,0 +1,15 @@ +[package] +name = "revive-dt-config" +description = "global configuration for the revive differential tester" +version.workspace = true +authors.workspace = true +license.workspace = true +edition.workspace = true +repository.workspace = true +rust-version.workspace = true + +[dependencies] +alloy = { workspace = true } +clap = { workspace = true } +semver = { workspace = true } +temp-dir = { workspace = true } diff --git a/crates/config/src/lib.rs b/crates/config/src/lib.rs new file mode 100644 index 0000000..b186416 --- /dev/null +++ b/crates/config/src/lib.rs @@ -0,0 +1,134 @@ +//! The global configuration used accross all revive differential testing crates. + +use std::path::{Path, PathBuf}; + +use alloy::{network::EthereumWallet, signers::local::PrivateKeySigner}; +use clap::{Parser, ValueEnum}; +use semver::Version; +use temp_dir::TempDir; + +#[derive(Debug, Parser, Clone)] +#[command(name = "retester")] +pub struct Arguments { + /// The `solc` version to use if the test didn't specify it explicitly. + #[arg(long = "solc", short, default_value = "0.8.29")] + pub solc: Version, + + /// Use the Wasm compiler versions. + #[arg(long = "wasm")] + pub wasm: bool, + + /// The path to the `resolc` executable to be tested. + /// + /// By default it uses the `resolc` binary found in `$PATH`. + /// + /// If `--wasm` is set, this should point to the resolc Wasm ile. + #[arg(long = "resolc", short, default_value = "resolc")] + pub resolc: PathBuf, + + /// A list of test corpus JSON files to be tested. + #[arg(long = "corpus", short)] + pub corpus: Vec, + + /// A place to store temporary artifacts during test execution. + /// + /// Creates a temporary dir if not specified. + #[arg(long = "workdir", short)] + pub working_directory: Option, + + /// Add a tempdir manually if `working_directory` was not given. + /// + /// We attach it here because [TempDir] prunes itself on drop. + #[clap(skip)] + pub temp_dir: Option<&'static TempDir>, + + /// The path to the `geth` executable. + /// + /// By default it uses `geth` binary found in `$PATH`. + #[arg(short, long = "geth", default_value = "geth")] + pub geth: PathBuf, + + /// The maximum time in milliseconds to wait for geth to start. + #[arg(long = "geth-start-timeout", default_value = "2000")] + pub geth_start_timeout: u64, + + /// The test network chain ID. + #[arg(short, long = "network-id", default_value = "420420420")] + pub network_id: u64, + + /// Configure nodes according to this genesis.json file. + #[arg(long = "genesis", default_value = "genesis.json")] + pub genesis_file: PathBuf, + + /// The signing account private key. + #[arg( + short, + long = "account", + default_value = "0x4f3edf983ac636a65a842ce7c78d9aa706d3b113bce9c46f30d7d21715b23b1d" + )] + pub account: String, + + /// The differential testing leader node implementation. + #[arg(short, long = "leader", default_value = "geth")] + pub leader: TestingPlatform, + + /// The differential testing follower node implementation. + #[arg(short, long = "follower", default_value = "kitchensink")] + pub follower: TestingPlatform, + + /// Only compile against this testing platform (doesn't execute the tests). + #[arg(long = "compile-only")] + pub compile_only: Option, + + /// Determines the amount of tests that are executed in parallel. + #[arg(long = "workers", default_value = "12")] + pub workers: usize, +} + +impl Arguments { + /// Return the configured working directory with the following precedence: + /// 1. `self.working_directory` if it was provided. + /// 2. `self.temp_dir` if it it was provided + /// 3. Panic. + pub fn directory(&self) -> &Path { + if let Some(path) = &self.working_directory { + return path.as_path(); + } + + if let Some(temp_dir) = &self.temp_dir { + return temp_dir.path(); + } + + panic!("should have a workdir configured") + } + + /// Try to parse `self.account` into a [PrivateKeySigner], + /// panicing on error. + pub fn wallet(&self) -> EthereumWallet { + let signer = self + .account + .parse::() + .unwrap_or_else(|error| { + panic!("private key '{}' parsing error: {error}", self.account); + }); + EthereumWallet::new(signer) + } +} + +impl Default for Arguments { + fn default() -> Self { + Arguments::parse_from(["retester"]) + } +} + +/// The Solidity compatible node implementation. +/// +/// This describes the solutions to be tested against on a high level. +#[derive(Clone, Debug, Eq, Hash, PartialEq, ValueEnum)] +#[clap(rename_all = "lower")] +pub enum TestingPlatform { + /// The go-ethereum reference full node EVM implementation. + Geth, + /// The kitchensink runtime provides the PolkaVM (PVM) based node implentation. + Kitchensink, +} diff --git a/crates/core/Cargo.toml b/crates/core/Cargo.toml new file mode 100644 index 0000000..f5785c7 --- /dev/null +++ b/crates/core/Cargo.toml @@ -0,0 +1,33 @@ +[package] +name = "revive-dt-core" +description = "revive differential testing core utility" +version.workspace = true +authors.workspace = true +license.workspace = true +edition.workspace = true +repository.workspace = true +rust-version.workspace = true + +[[bin]] +name = "retester" +path = "src/main.rs" + +[dependencies] +revive-dt-compiler = { workspace = true } +revive-dt-config = { workspace = true } +revive-dt-format = { workspace = true } +revive-dt-node = { workspace = true } +revive-dt-node-interaction = { workspace = true } +revive-dt-solc-binaries = { workspace = true } + +alloy = { workspace = true } +anyhow = { workspace = true } +clap = { workspace = true } +log = { workspace = true } +env_logger = { workspace = true } +rayon = { workspace = true } +revive-solc-json-interface = { workspace = true } +semver = { workspace = true } +serde = { workspace = true, features = [ "derive" ] } +serde_json = { workspace = true } +temp-dir = { workspace = true } diff --git a/crates/core/src/driver/mod.rs b/crates/core/src/driver/mod.rs new file mode 100644 index 0000000..8c8d256 --- /dev/null +++ b/crates/core/src/driver/mod.rs @@ -0,0 +1,122 @@ +//! The test driver handles the compilation and execution of the test cases. + +use alloy::{ + primitives::{Address, map::HashMap}, + rpc::types::trace::geth::GethTrace, +}; +use revive_dt_compiler::{Compiler, CompilerInput, SolidityCompiler}; +use revive_dt_config::Arguments; +use revive_dt_format::{input::Input, metadata::Metadata, mode::SolcMode}; +use revive_dt_node_interaction::EthereumNode; +use revive_dt_solc_binaries::download_solc; +use revive_solc_json_interface::SolcStandardJsonOutput; + +use crate::Platform; + +type Contracts = HashMap< + CompilerInput<<::Compiler as SolidityCompiler>::Options>, + SolcStandardJsonOutput, +>; + +pub struct State<'a, T: Platform> { + config: &'a Arguments, + contracts: Contracts, + deployed_contracts: HashMap, +} + +impl<'a, T> State<'a, T> +where + T: Platform, +{ + pub fn new(config: &'a Arguments) -> Self { + Self { + config, + contracts: Default::default(), + deployed_contracts: Default::default(), + } + } + + pub fn build_contracts(&mut self, mode: &SolcMode, metadata: &Metadata) -> anyhow::Result<()> { + let Some(version) = mode.last_patch_version(&self.config.solc) else { + anyhow::bail!("unsupported solc version: {:?}", mode.solc_version); + }; + + let sources = metadata.contract_sources()?; + let base_path = metadata.directory()?.display().to_string(); + let mut compiler = Compiler::::new().base_path(base_path.clone()); + for (file, _contract) in sources.values() { + log::debug!("contract source {}", file.display()); + compiler = compiler.with_source(file)?; + } + + let solc_path = download_solc(self.config.directory(), version, self.config.wasm)?; + let output = compiler + .solc_optimizer(mode.solc_optimize()) + .try_build(solc_path)?; + + self.contracts.insert(output.input, output.output); + + Ok(()) + } + + pub fn execute_input( + &mut self, + input: &Input, + node: &T::Blockchain, + ) -> anyhow::Result { + let receipt = node.execute_transaction(input.legacy_transaction( + self.config.network_id, + 0, + &self.deployed_contracts, + )?)?; + dbg!(&receipt); + //node.trace_transaction(receipt) + todo!() + } +} + +pub struct Driver<'a, Leader: Platform, Follower: Platform> { + metadata: &'a Metadata, + config: &'a Arguments, + leader_node: &'a Leader::Blockchain, + follower_node: &'a Follower::Blockchain, +} + +impl<'a, L, F> Driver<'a, L, F> +where + L: Platform, + F: Platform, +{ + pub fn new( + metadata: &'a Metadata, + config: &'a Arguments, + leader_node: &'a L::Blockchain, + follower_node: &'a F::Blockchain, + ) -> Driver<'a, L, F> { + Self { + metadata, + config, + leader_node, + follower_node, + } + } + + pub fn execute(&mut self) -> anyhow::Result<()> { + for mode in self.metadata.solc_modes() { + let mut leader_state = State::::new(self.config); + leader_state.build_contracts(&mode, self.metadata)?; + + let mut follower_state = State::::new(self.config); + follower_state.build_contracts(&mode, self.metadata)?; + + for case in &self.metadata.cases { + for input in &case.inputs { + let _ = leader_state.execute_input(input, self.leader_node)?; + let _ = follower_state.execute_input(input, self.follower_node)?; + } + } + } + + Ok(()) + } +} diff --git a/crates/core/src/lib.rs b/crates/core/src/lib.rs new file mode 100644 index 0000000..9ae8f3a --- /dev/null +++ b/crates/core/src/lib.rs @@ -0,0 +1,34 @@ +//! The revive differential testing core library. +//! +//! This crate defines the testing configuration and +//! provides a helper utilty to execute tests. + +use revive_dt_compiler::{SolidityCompiler, solc}; +use revive_dt_node::geth; +use revive_dt_node_interaction::EthereumNode; + +pub mod driver; + +/// One platform can be tested differentially against another. +/// +/// For this we need a blockchain node implementation and a compiler. +pub trait Platform { + type Blockchain: EthereumNode; + type Compiler: SolidityCompiler; +} + +#[derive(Default)] +pub struct Geth; + +impl Platform for Geth { + type Blockchain = geth::Instance; + type Compiler = solc::Solc; +} + +#[derive(Default)] +pub struct Kitchensink; + +impl Platform for Kitchensink { + type Blockchain = geth::Instance; + type Compiler = solc::Solc; +} diff --git a/crates/core/src/main.rs b/crates/core/src/main.rs new file mode 100644 index 0000000..21ab8b0 --- /dev/null +++ b/crates/core/src/main.rs @@ -0,0 +1,121 @@ +use std::{collections::HashMap, sync::LazyLock}; + +use clap::Parser; +use rayon::{ThreadPoolBuilder, prelude::*}; + +use revive_dt_config::*; +use revive_dt_core::{ + Geth, + driver::{Driver, State}, +}; +use revive_dt_format::{corpus::Corpus, metadata::Metadata}; +use revive_dt_node::pool::NodePool; +use temp_dir::TempDir; + +static TEMP_DIR: LazyLock = LazyLock::new(|| TempDir::new().unwrap()); + +fn main() -> anyhow::Result<()> { + let args = init_cli()?; + + let corpora = collect_corpora(&args)?; + + if let Some(platform) = &args.compile_only { + for tests in corpora.values() { + main_compile_only(&args, tests, platform)?; + } + + return Ok(()); + } + + for tests in corpora.values() { + main_execute_differential(&args, tests)?; + } + + Ok(()) +} + +fn init_cli() -> anyhow::Result { + env_logger::init(); + + let mut args = Arguments::parse(); + if args.corpus.is_empty() { + anyhow::bail!("no test corpus specified"); + } + if args.working_directory.is_none() { + args.temp_dir = Some(&TEMP_DIR); + } + + ThreadPoolBuilder::new() + .num_threads(args.workers) + .build_global() + .unwrap(); + + Ok(args) +} + +fn collect_corpora(args: &Arguments) -> anyhow::Result>> { + let mut corpora = HashMap::new(); + + for path in &args.corpus { + let corpus = Corpus::try_from_path(path)?; + log::info!("found corpus: {}", path.display()); + let tests = corpus.enumerate_tests(); + log::info!("corpus '{}' contains {} tests", &corpus.name, tests.len()); + corpora.insert(corpus, tests); + } + + Ok(corpora) +} + +fn main_execute_differential(args: &Arguments, tests: &[Metadata]) -> anyhow::Result<()> { + let leader_nodes = NodePool::new(args)?; + let follower_nodes = NodePool::new(args)?; + + tests.par_iter().for_each(|metadata| { + let mut driver = match (&args.leader, &args.follower) { + (TestingPlatform::Geth, TestingPlatform::Kitchensink) => Driver::::new( + metadata, + args, + leader_nodes.round_robbin(), + follower_nodes.round_robbin(), + ), + _ => unimplemented!(), + }; + + match driver.execute() { + Ok(build) => { + log::info!( + "metadata {} success", + metadata.directory().as_ref().unwrap().display() + ); + build + } + Err(error) => { + log::warn!( + "metadata {} failure: {error:?}", + metadata.file_path.as_ref().unwrap().display() + ); + } + } + }); + + Ok(()) +} + +fn main_compile_only( + config: &Arguments, + tests: &[Metadata], + platform: &TestingPlatform, +) -> anyhow::Result<()> { + tests.par_iter().for_each(|metadata| { + for mode in &metadata.solc_modes() { + let mut state = match platform { + TestingPlatform::Geth => State::::new(config), + _ => todo!(), + }; + let _ = state.build_contracts(mode, metadata); + } + }); + + Ok(()) +} diff --git a/crates/format/Cargo.toml b/crates/format/Cargo.toml new file mode 100644 index 0000000..d8fc345 --- /dev/null +++ b/crates/format/Cargo.toml @@ -0,0 +1,17 @@ +[package] +name = "revive-dt-format" +description = "declarative test definition format" +version.workspace = true +authors.workspace = true +license.workspace = true +edition.workspace = true +repository.workspace = true +rust-version.workspace = true + +[dependencies] +alloy = { workspace = true } +anyhow = { workspace = true } +log = { workspace = true } +semver = { workspace = true } +serde = { workspace = true, features = [ "derive" ] } +serde_json = { workspace = true } diff --git a/crates/format/src/case.rs b/crates/format/src/case.rs new file mode 100644 index 0000000..5516406 --- /dev/null +++ b/crates/format/src/case.rs @@ -0,0 +1,12 @@ +use serde::Deserialize; + +use crate::{input::Input, mode::Mode}; + +#[derive(Debug, Default, Deserialize, Clone, Eq, PartialEq)] +pub struct Case { + pub name: Option, + pub comment: Option, + pub modes: Option>, + pub inputs: Vec, + pub group: Option, +} diff --git a/crates/format/src/corpus.rs b/crates/format/src/corpus.rs new file mode 100644 index 0000000..5f0fe5a --- /dev/null +++ b/crates/format/src/corpus.rs @@ -0,0 +1,67 @@ +use std::{ + fs::File, + path::{Path, PathBuf}, +}; + +use serde::Deserialize; + +use crate::metadata::Metadata; + +#[derive(Clone, Debug, Default, Deserialize, Eq, PartialEq, Hash)] +pub struct Corpus { + pub name: String, + pub path: PathBuf, +} + +impl Corpus { + /// Try to read and parse the corpus definition file at given `path`. + pub fn try_from_path(path: &Path) -> anyhow::Result { + let file = File::open(path)?; + Ok(serde_json::from_reader(file)?) + } + + /// Scan the corpus base directory and return all tests found. + pub fn enumerate_tests(&self) -> Vec { + let mut tests = Vec::new(); + collect_metadata(&self.path, &mut tests); + tests + } +} + +/// Recursively walks `path` and parses any JSON or Solidity file into a test +/// definition [Metadata]. +/// +/// Found tests are inserted into `tests`. +/// +/// `path` is expected to be a directory. +pub fn collect_metadata(path: &Path, tests: &mut Vec) { + let dir_entry = match std::fs::read_dir(path) { + Ok(dir_entry) => dir_entry, + Err(error) => { + log::error!("failed to read dir '{}': {error}", path.display()); + return; + } + }; + + for entry in dir_entry { + let entry = match entry { + Ok(entry) => entry, + Err(error) => { + log::error!("error reading dir entry: {error}"); + continue; + } + }; + + let path = entry.path(); + if path.is_dir() { + collect_metadata(&path, tests); + continue; + } + + if path.is_file() { + if let Some(metadata) = Metadata::try_from_file(&path) { + tests.push(metadata) + } + } + } +} diff --git a/crates/format/src/input.rs b/crates/format/src/input.rs new file mode 100644 index 0000000..0631db8 --- /dev/null +++ b/crates/format/src/input.rs @@ -0,0 +1,132 @@ +use std::collections::HashMap; + +use alloy::{ + json_abi::Function, network::TransactionBuilder, primitives::Address, + rpc::types::TransactionRequest, +}; +use semver::VersionReq; +use serde::{Deserialize, de::Deserializer}; +use serde_json::Value; + +#[derive(Clone, Debug, Default, Deserialize, Eq, PartialEq)] +pub struct Input { + #[serde(default = "default_caller")] + pub caller: Address, + pub comment: Option, + #[serde(default = "default_instance")] + pub instance: String, + #[serde(deserialize_with = "deserialize_method")] + pub method: Method, + pub calldata: Option, + pub expected: Option, + pub value: Option, + pub storage: Option>, +} + +#[derive(Clone, Debug, Deserialize, Eq, PartialEq)] +#[serde(untagged)] +pub enum Expected { + Calldata(Calldata), + Expected(ExpectedOutput), + ExpectedMany(Vec), +} + +#[derive(Clone, Debug, Default, Deserialize, Eq, PartialEq)] +pub struct ExpectedOutput { + compiler_version: Option, + return_data: Option, + events: Option, + exception: Option, +} + +#[derive(Clone, Debug, Deserialize, Eq, PartialEq)] +#[serde(untagged)] +pub enum Calldata { + Single(String), + Compound(Vec), +} + +/// Specify how the contract is called. +#[derive(Debug, Default, Clone, Eq, PartialEq)] +pub enum Method { + /// Initiate a deploy transaction, calling contracts constructor. + /// + /// Indicated by `#deployer`. + Deployer, + /// Does not calculate and insert a function selector. + /// + /// Indicated by `#fallback`. + #[default] + Fallback, + /// Call the public function with this selector. + /// + /// Calculates the selector if neither deployer or fallback matches. + Function([u8; 4]), +} + +fn deserialize_method<'de, D>(deserializer: D) -> Result +where + D: Deserializer<'de>, +{ + Ok(match String::deserialize(deserializer)?.as_str() { + "#deployer" => Method::Deployer, + "#fallback" => Method::Fallback, + signature => { + let signature = if signature.ends_with(')') { + signature.to_string() + } else { + format!("{signature}()") + }; + match Function::parse(&signature) { + Ok(function) => Method::Function(function.selector().0), + Err(error) => { + return Err(serde::de::Error::custom(format!( + "parsing function signature '{signature}' error: {error}" + ))); + } + } + } + }) +} + +impl Input { + fn instance_to_address( + &self, + instance: &str, + deployed_contracts: &HashMap, + ) -> anyhow::Result
{ + deployed_contracts + .get(instance) + .copied() + .ok_or_else(|| anyhow::anyhow!("instance {instance} not deployed")) + } + + /// Parse this input into a legacy transaction. + pub fn legacy_transaction( + &self, + chain_id: u64, + nonce: u64, + deployed_contracts: &HashMap, + ) -> anyhow::Result { + let to = match self.method { + Method::Deployer => Address::ZERO, + _ => self.instance_to_address(&self.instance, deployed_contracts)?, + }; + + Ok(TransactionRequest::default() + .with_from(self.caller) + .with_to(to) + .with_nonce(nonce) + .with_chain_id(chain_id) + .with_gas_price(20_000_000_000) + .with_gas_limit(20_000_000_000)) + } +} + +fn default_instance() -> String { + "Test".to_string() +} + +fn default_caller() -> Address { + "90F8bf6A479f320ead074411a4B0e7944Ea8c9C1".parse().unwrap() +} diff --git a/crates/format/src/lib.rs b/crates/format/src/lib.rs new file mode 100644 index 0000000..21ae375 --- /dev/null +++ b/crates/format/src/lib.rs @@ -0,0 +1,7 @@ +//! The revive differential tests case format. + +pub mod case; +pub mod corpus; +pub mod input; +pub mod metadata; +pub mod mode; diff --git a/crates/format/src/metadata.rs b/crates/format/src/metadata.rs new file mode 100644 index 0000000..6bb7a74 --- /dev/null +++ b/crates/format/src/metadata.rs @@ -0,0 +1,168 @@ +use std::{ + collections::BTreeMap, + fs::{File, read_to_string}, + path::{Path, PathBuf}, +}; + +use serde::Deserialize; + +use crate::{ + case::Case, + mode::{Mode, SolcMode}, +}; + +pub const METADATA_FILE_EXTENSION: &str = "json"; +pub const SOLIDITY_CASE_FILE_EXTENSION: &str = "sol"; +pub const SOLIDITY_CASE_COMMENT_MARKER: &str = "//!"; + +#[derive(Debug, Default, Deserialize, Clone, Eq, PartialEq)] +pub struct Metadata { + pub cases: Vec, + pub contracts: Option>, + pub libraries: Option>>, + pub ignore: Option, + pub modes: Option>, + pub file_path: Option, +} + +impl Metadata { + /// Returns the solc modes of this metadata, inserting a default mode if not present. + pub fn solc_modes(&self) -> Vec { + self.modes + .to_owned() + .unwrap_or_else(|| vec![Mode::Solidity(Default::default())]) + .iter() + .filter_map(|mode| match mode { + Mode::Solidity(solc_mode) => Some(solc_mode), + Mode::Unknown(mode) => { + log::debug!("compiler: ignoring unknown mode '{mode}'"); + None + } + }) + .cloned() + .collect() + } + + /// Returns the base directory of this metadata. + pub fn directory(&self) -> anyhow::Result { + Ok(self + .file_path + .as_ref() + .and_then(|path| path.parent()) + .ok_or_else(|| anyhow::anyhow!("metadata invalid file path: {:?}", self.file_path))? + .to_path_buf()) + } + + /// Extract the contract sources. + /// + /// Returns a mapping of contract IDs to their source path and contract name. + pub fn contract_sources(&self) -> anyhow::Result> { + let directory = self.directory()?; + let mut sources = BTreeMap::new(); + let Some(contracts) = &self.contracts else { + return Ok(sources); + }; + + for (id, contract) in contracts { + // TODO: broken if a colon is in the dir name.. + let mut parts = contract.split(':'); + let (Some(file_name), Some(contract_name)) = (parts.next(), parts.next()) else { + anyhow::bail!("metadata contains invalid contract: {contract}"); + }; + let file = directory.to_path_buf().join(file_name); + if !file.is_file() { + anyhow::bail!("contract {id} is not a file: {}", file.display()); + } + + sources.insert(id.clone(), (file, contract_name.to_string())); + } + + Ok(sources) + } + + /// Try to parse the test metadata struct from the given file at `path`. + /// + /// Returns `None` if `path` didn't contain a test metadata or case definition. + /// + /// # Panics + /// Expects the supplied `path` to be a file. + pub fn try_from_file(path: &Path) -> Option { + assert!(path.is_file(), "not a file: {}", path.display()); + + let Some(file_extension) = path.extension() else { + log::debug!("skipping corpus file: {}", path.display()); + return None; + }; + + if file_extension == METADATA_FILE_EXTENSION { + return Self::try_from_json(path); + } + + if file_extension == SOLIDITY_CASE_FILE_EXTENSION { + return Self::try_from_solidity(path); + } + + log::debug!("ignoring invalid corpus file: {}", path.display()); + None + } + + fn try_from_json(path: &Path) -> Option { + let file = File::open(path) + .inspect_err(|error| { + log::error!( + "opening JSON test metadata file '{}' error: {error}", + path.display() + ); + }) + .ok()?; + + match serde_json::from_reader::<_, Metadata>(file) { + Ok(mut metadata) => { + metadata.file_path = Some(path.to_path_buf()); + Some(metadata) + } + Err(error) => { + log::error!( + "parsing JSON test metadata file '{}' error: {error}", + path.display() + ); + None + } + } + } + + fn try_from_solidity(path: &Path) -> Option { + let buf = read_to_string(path) + .inspect_err(|error| { + log::error!( + "opening JSON test metadata file '{}' error: {error}", + path.display() + ); + }) + .ok()? + .lines() + .filter_map(|line| line.strip_prefix(SOLIDITY_CASE_COMMENT_MARKER)) + .fold(String::new(), |mut buf, string| { + buf.push_str(string); + buf + }); + + if buf.is_empty() { + return None; + } + + match serde_json::from_str::(&buf) { + Ok(mut metadata) => { + metadata.file_path = Some(path.to_path_buf()); + Some(metadata) + } + Err(error) => { + log::error!( + "parsing Solidity test metadata file '{}' error: {error}", + path.display() + ); + None + } + } + } +} diff --git a/crates/format/src/mode.rs b/crates/format/src/mode.rs new file mode 100644 index 0000000..638bf67 --- /dev/null +++ b/crates/format/src/mode.rs @@ -0,0 +1,96 @@ +use semver::Version; +use serde::Deserialize; +use serde::de::Deserializer; + +/// Specifies the compilation mode of the test artifact. +#[derive(Debug, Clone, Eq, PartialEq)] +pub enum Mode { + Solidity(SolcMode), + Unknown(String), +} + +/// Specify Solidity specific compiler options. +#[derive(Debug, Default, Clone, Eq, PartialEq)] +pub struct SolcMode { + pub solc_version: Option, + solc_optimize: Option, + pub llvm_optimizer_settings: Vec, +} + +impl SolcMode { + /// Try to parse a mode string into a solc mode. + /// Returns `None` if the string wasn't a solc YUL mode string. + /// + /// The mode string is expected to start with the `Y` ID (YUL ID), + /// optionally followed by `+` or `-` for the solc optimizer settings. + /// + /// Options can be separated by a whitespace contain the following + /// - A solc `SemVer version requirement` string + /// - One or more `-OX` where X is a supposed to be an LLVM opt mode + pub fn parse_from_mode_string(mode_string: &str) -> Option { + let mut result = Self::default(); + + let mut parts = mode_string.trim().split(" "); + + match parts.next()? { + "Y" => {} + "Y+" => result.solc_optimize = Some(true), + "Y-" => result.solc_optimize = Some(false), + _ => return None, + } + + for part in parts { + if let Ok(solc_version) = semver::VersionReq::parse(part) { + result.solc_version = Some(solc_version); + continue; + } + if let Some(level) = part.strip_prefix("-O") { + result.llvm_optimizer_settings.push(level.to_string()); + continue; + } + panic!("the YUL mode string {mode_string} failed to parse, invalid part: {part}") + } + + Some(result) + } + + /// Returns whether to enable the solc optimizer. + pub fn solc_optimize(&self) -> bool { + self.solc_optimize.unwrap_or(true) + } + + /// Calculate the latest matching solc patch version. Returns: + /// - `latest_supported` if no version request was specified. + /// - A matching version with the same minor version as `latest_supported`, if any. + /// - `None` if no minor version of the `latest_supported` version matches. + pub fn last_patch_version(&self, latest_supported: &Version) -> Option { + let Some(version_req) = self.solc_version.as_ref() else { + return Some(latest_supported.to_owned()); + }; + + // lgtm + for patch in (0..latest_supported.patch + 1).rev() { + let version = Version::new(0, latest_supported.minor, patch); + if version_req.matches(&version) { + return Some(version); + } + } + + None + } +} + +impl<'de> Deserialize<'de> for Mode { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + let mode_string = String::deserialize(deserializer)?; + + if let Some(solc_mode) = SolcMode::parse_from_mode_string(&mode_string) { + return Ok(Self::Solidity(solc_mode)); + } + + Ok(Self::Unknown(mode_string)) + } +} diff --git a/crates/node-interaction/Cargo.toml b/crates/node-interaction/Cargo.toml new file mode 100644 index 0000000..7029edc --- /dev/null +++ b/crates/node-interaction/Cargo.toml @@ -0,0 +1,18 @@ +[package] +name = "revive-dt-node-interaction" +description = "send and trace transactions to nodes" +version.workspace = true +authors.workspace = true +license.workspace = true +edition.workspace = true +repository.workspace = true +rust-version.workspace = true + +[dependencies] +alloy = { workspace = true } +anyhow = { workspace = true } +hex = { workspace = true } +log = { workspace = true } +once_cell = { workspace = true } +serde_json = { workspace = true } +tokio = { workspace = true } diff --git a/crates/node-interaction/src/lib.rs b/crates/node-interaction/src/lib.rs new file mode 100644 index 0000000..bcdf308 --- /dev/null +++ b/crates/node-interaction/src/lib.rs @@ -0,0 +1,21 @@ +//! This crate implements all node interactions. + +use alloy::rpc::types::trace::geth::GethTrace; +use alloy::rpc::types::{TransactionReceipt, TransactionRequest}; +use tokio_runtime::TO_TOKIO; + +mod tokio_runtime; +pub mod trace; +pub mod transaction; + +/// An interface for all interactions with Ethereum compatible nodes. +pub trait EthereumNode { + /// Execute the [TransactionRequest] and return a [TransactionReceipt]. + fn execute_transaction( + &self, + transaction: TransactionRequest, + ) -> anyhow::Result; + + /// Trace the transaction in the [TransactionReceipt] and return a [GethTrace]. + fn trace_transaction(&self, transaction: TransactionReceipt) -> anyhow::Result; +} diff --git a/crates/node-interaction/src/tokio_runtime.rs b/crates/node-interaction/src/tokio_runtime.rs new file mode 100644 index 0000000..d58aa2f --- /dev/null +++ b/crates/node-interaction/src/tokio_runtime.rs @@ -0,0 +1,79 @@ +//! The alloy crate __requires__ a tokio runtime. +//! We contain any async rust right here. + +use once_cell::sync::Lazy; +use std::pin::Pin; +use std::sync::Mutex; +use std::thread; +use tokio::runtime::Runtime; +use tokio::spawn; +use tokio::sync::{mpsc, oneshot}; +use tokio::task::JoinError; + +use crate::trace::Trace; +use crate::transaction::Transaction; + +pub(crate) static TO_TOKIO: Lazy> = + Lazy::new(|| Mutex::new(TokioRuntime::spawn())); + +/// Common interface for executing async node interactions from a non-async context. +#[allow(clippy::type_complexity)] +pub(crate) trait AsyncNodeInteraction: Send + 'static { + type Output: Send; + + //// Returns the task and the output sender. + fn split( + self, + ) -> ( + Pin + Send>>, + oneshot::Sender, + ); +} + +pub(crate) struct TokioRuntime { + pub(crate) transaction_sender: mpsc::Sender, + pub(crate) trace_sender: mpsc::Sender, +} + +impl TokioRuntime { + fn spawn() -> Self { + let rt = Runtime::new().expect("should be able to create the tokio runtime"); + let (transaction_sender, transaction_receiver) = mpsc::channel::(1024); + let (trace_sender, trace_receiver) = mpsc::channel::(1024); + + thread::spawn(move || { + rt.block_on(async move { + let transaction_task = spawn(interaction::(transaction_receiver)); + let trace_task = spawn(interaction::(trace_receiver)); + + if let Err(error) = transaction_task.await { + log::error!("tokio transaction task failed: {error}"); + } + if let Err(error) = trace_task.await { + log::error!("tokio trace transaction task failed: {error}"); + } + }); + }); + + Self { + transaction_sender, + trace_sender, + } + } +} + +async fn interaction(mut receiver: mpsc::Receiver) -> Result<(), JoinError> +where + T: AsyncNodeInteraction, +{ + while let Some(task) = receiver.recv().await { + spawn(async move { + let (task, sender) = task.split(); + sender + .send(task.await) + .unwrap_or_else(|_| panic!("failed to send task output")); + }); + } + + Ok(()) +} diff --git a/crates/node-interaction/src/trace.rs b/crates/node-interaction/src/trace.rs new file mode 100644 index 0000000..9255d00 --- /dev/null +++ b/crates/node-interaction/src/trace.rs @@ -0,0 +1,43 @@ +//! Trace transactions in a sync context. + +use std::pin::Pin; + +use alloy::rpc::types::trace::geth::GethTrace; +use tokio::sync::oneshot; + +use crate::TO_TOKIO; +use crate::tokio_runtime::AsyncNodeInteraction; + +pub type Task = Pin> + Send>>; + +pub(crate) struct Trace { + sender: oneshot::Sender>, + task: Task, +} + +impl AsyncNodeInteraction for Trace { + type Output = anyhow::Result; + + fn split( + self, + ) -> ( + std::pin::Pin + Send>>, + oneshot::Sender, + ) { + (self.task, self.sender) + } +} + +/// Execute some [Task] that return a [GethTrace] result. +pub fn trace_transaction(task: Task) -> anyhow::Result { + let task_sender = TO_TOKIO.lock().unwrap().trace_sender.clone(); + let (sender, receiver) = oneshot::channel(); + + task_sender + .blocking_send(Trace { task, sender }) + .expect("we are not calling this from an async context"); + + receiver + .blocking_recv() + .unwrap_or_else(|error| anyhow::bail!("no trace received: {error}")) +} diff --git a/crates/node-interaction/src/transaction.rs b/crates/node-interaction/src/transaction.rs new file mode 100644 index 0000000..b5af221 --- /dev/null +++ b/crates/node-interaction/src/transaction.rs @@ -0,0 +1,46 @@ +//! Execute transactions in a sync context. + +use std::pin::Pin; + +use alloy::rpc::types::TransactionReceipt; +use tokio::sync::oneshot; + +use crate::TO_TOKIO; +use crate::tokio_runtime::AsyncNodeInteraction; + +pub type Task = Pin> + Send>>; + +pub(crate) struct Transaction { + receipt_sender: oneshot::Sender>, + task: Task, +} + +impl AsyncNodeInteraction for Transaction { + type Output = anyhow::Result; + + fn split( + self, + ) -> ( + Pin + Send>>, + oneshot::Sender, + ) { + (self.task, self.receipt_sender) + } +} + +/// Execute some [Task] that returns a [TransactionReceipt]. +pub fn execute_transaction(task: Task) -> anyhow::Result { + let request_sender = TO_TOKIO.lock().unwrap().transaction_sender.clone(); + let (receipt_sender, receipt_receiver) = oneshot::channel(); + + request_sender + .blocking_send(Transaction { + receipt_sender, + task, + }) + .expect("we are not calling this from an async context"); + + receipt_receiver + .blocking_recv() + .unwrap_or_else(|error| anyhow::bail!("no receipt received: {error}")) +} diff --git a/crates/node/Cargo.toml b/crates/node/Cargo.toml new file mode 100644 index 0000000..6ee9473 --- /dev/null +++ b/crates/node/Cargo.toml @@ -0,0 +1,21 @@ +[package] +name = "revive-dt-node" +description = "abstraction over blockchain nodes" +version.workspace = true +authors.workspace = true +license.workspace = true +edition.workspace = true +repository.workspace = true +rust-version.workspace = true + +[dependencies] +anyhow = { workspace = true } +alloy = { workspace = true } +log = { workspace = true } +serde_json = { workspace = true } + +revive-dt-node-interaction = { workspace = true } +revive-dt-config = { workspace = true } + +[dev-dependencies] +temp-dir = { workspace = true } diff --git a/crates/node/src/geth.rs b/crates/node/src/geth.rs new file mode 100644 index 0000000..e3de017 --- /dev/null +++ b/crates/node/src/geth.rs @@ -0,0 +1,298 @@ +//! The go-ethereum node implementation. + +use std::{ + fs::{File, create_dir_all, remove_dir_all}, + io::{BufRead, BufReader, Read, Write}, + path::PathBuf, + process::{Child, Command, Stdio}, + sync::atomic::{AtomicU32, Ordering}, + thread, + time::{Duration, Instant}, +}; + +use alloy::{ + network::EthereumWallet, + providers::{Provider, ProviderBuilder, ext::DebugApi}, + rpc::types::{ + TransactionReceipt, TransactionRequest, + trace::geth::{DiffMode, GethDebugTracingOptions, PreStateConfig, PreStateFrame}, + }, +}; +use revive_dt_config::Arguments; +use revive_dt_node_interaction::{ + EthereumNode, trace::trace_transaction, transaction::execute_transaction, +}; + +use crate::Node; + +static NODE_COUNT: AtomicU32 = AtomicU32::new(0); + +/// The go-ethereum node instance implementation. +/// +/// Implements helpers to initialize, spawn and wait the node. +/// +/// Assumes dev mode and IPC only (`P2P`, `http`` etc. are kept disabled). +/// +/// Prunes the child process and the base directory on drop. +#[derive(Debug)] +pub struct Instance { + connection_string: String, + base_directory: PathBuf, + data_directory: PathBuf, + geth: PathBuf, + id: u32, + handle: Option, + network_id: u64, + start_timeout: u64, + wallet: EthereumWallet, +} + +impl Instance { + const BASE_DIRECTORY: &str = "geth"; + const DATA_DIRECTORY: &str = "data"; + + const IPC_FILE: &str = "geth.ipc"; + const GENESIS_JSON_FILE: &str = "genesis.json"; + + const READY_MARKER: &str = "IPC endpoint opened"; + const ERROR_MARKER: &str = "Fatal:"; + + /// Create the node directory and call `geth init` to configure the genesis. + fn init(&mut self, genesis: String) -> anyhow::Result<&mut Self> { + create_dir_all(&self.base_directory)?; + + let genesis_path = self.base_directory.join(Self::GENESIS_JSON_FILE); + File::create(&genesis_path)?.write_all(genesis.as_bytes())?; + + let mut child = Command::new(&self.geth) + .arg("init") + .arg("--datadir") + .arg(&self.data_directory) + .arg(genesis_path) + .stderr(Stdio::piped()) + .stdout(Stdio::null()) + .spawn()?; + + let mut stderr = String::new(); + child + .stderr + .take() + .expect("should be piped") + .read_to_string(&mut stderr)?; + + if !child.wait()?.success() { + anyhow::bail!("failed to initialize geth node #{:?}: {stderr}", &self.id); + } + + Ok(self) + } + + /// Spawn the go-ethereum node child process. + /// + /// [Instance::init] must be called priorly. + fn spawn_process(&mut self) -> anyhow::Result<&mut Self> { + self.handle = Command::new(&self.geth) + .arg("--dev") + .arg("--datadir") + .arg(&self.data_directory) + .arg("--ipcpath") + .arg(&self.connection_string) + .arg("--networkid") + .arg(self.network_id.to_string()) + .arg("--nodiscover") + .arg("--maxpeers") + .arg("0") + .stderr(Stdio::piped()) + .stdout(Stdio::null()) + .spawn()? + .into(); + Ok(self) + } + + /// Wait for the g-ethereum node child process getting ready. + /// + /// [Instance::spawn_process] must be called priorly. + fn wait_ready(&mut self) -> anyhow::Result<&mut Self> { + // Thanks clippy but geth is a server; we don't `wait` but eventually kill it. + #[allow(clippy::zombie_processes)] + let mut child = self.handle.take().expect("should be spawned"); + let start_time = Instant::now(); + let maximum_wait_time = Duration::from_millis(self.start_timeout); + let mut stderr = BufReader::new(child.stderr.take().expect("should be piped")).lines(); + let error = loop { + let Some(Ok(line)) = stderr.next() else { + break "child process stderr reading error".to_string(); + }; + if line.contains(Self::ERROR_MARKER) { + break line; + } + if line.contains(Self::READY_MARKER) { + // Keep stderr alive + // https://github.com/alloy-rs/alloy/issues/2091#issuecomment-2676134147 + thread::spawn(move || for _ in stderr.by_ref() {}); + + self.handle = child.into(); + return Ok(self); + } + if Instant::now().duration_since(start_time) > maximum_wait_time { + break "spawn timeout".to_string(); + } + }; + + let _ = child.kill(); + anyhow::bail!("geth node #{} spawn error: {error}", self.id) + } +} + +impl EthereumNode for Instance { + fn execute_transaction( + &self, + transaction: TransactionRequest, + ) -> anyhow::Result { + let connection_string = self.connection_string(); + let wallet = self.wallet.clone(); + + execute_transaction(Box::pin(async move { + Ok(ProviderBuilder::new() + .wallet(wallet) + .connect(&connection_string) + .await? + .send_transaction(transaction) + .await? + .get_receipt() + .await?) + })) + } + + fn trace_transaction( + &self, + transaction: TransactionReceipt, + ) -> anyhow::Result { + let connection_string = self.connection_string(); + let trace_options = GethDebugTracingOptions::prestate_tracer(PreStateConfig { + diff_mode: Some(true), + disable_code: None, + disable_storage: None, + }); + let wallet = self.wallet.clone(); + + trace_transaction(Box::pin(async move { + Ok(ProviderBuilder::new() + .wallet(wallet) + .connect(&connection_string) + .await? + .debug_trace_transaction(transaction.transaction_hash, trace_options) + .await?) + })) + } +} + +impl Node for Instance { + fn new(config: &Arguments) -> Self { + let geth_directory = config.directory().join(Self::BASE_DIRECTORY); + let id = NODE_COUNT.fetch_add(1, Ordering::SeqCst); + let base_directory = geth_directory.join(id.to_string()); + + Self { + connection_string: base_directory.join(Self::IPC_FILE).display().to_string(), + data_directory: base_directory.join(Self::DATA_DIRECTORY), + base_directory, + geth: config.geth.clone(), + id, + handle: None, + network_id: config.network_id, + start_timeout: config.geth_start_timeout, + wallet: config.wallet(), + } + } + + fn connection_string(&self) -> String { + self.connection_string.clone() + } + + fn shutdown(self) -> anyhow::Result<()> { + Ok(()) + } + + fn spawn(&mut self, genesis: String) -> anyhow::Result<()> { + self.init(genesis)?.spawn_process()?.wait_ready()?; + Ok(()) + } + + fn state_diff( + &self, + transaction: alloy::rpc::types::TransactionReceipt, + ) -> anyhow::Result { + match self + .trace_transaction(transaction)? + .try_into_pre_state_frame()? + { + PreStateFrame::Diff(diff) => Ok(diff), + _ => anyhow::bail!("expected a diff mode trace"), + } + } + + fn version(&self) -> anyhow::Result { + let output = Command::new(&self.geth) + .arg("--version") + .stdin(Stdio::null()) + .stdout(Stdio::piped()) + .stderr(Stdio::null()) + .spawn()? + .wait_with_output()? + .stdout; + Ok(String::from_utf8_lossy(&output).into()) + } +} + +impl Drop for Instance { + fn drop(&mut self) { + if let Some(child) = self.handle.as_mut() { + let _ = child.kill(); + } + if self.base_directory.exists() { + let _ = remove_dir_all(&self.base_directory); + } + } +} + +#[cfg(test)] +mod tests { + use revive_dt_config::Arguments; + use temp_dir::TempDir; + + use crate::{GENESIS_JSON, Node}; + + use super::Instance; + + fn test_config() -> (Arguments, TempDir) { + let mut config = Arguments::default(); + let temp_dir = TempDir::new().unwrap(); + config.working_directory = temp_dir.path().to_path_buf().into(); + + (config, temp_dir) + } + + #[test] + fn init_works() { + Instance::new(&test_config().0) + .init(GENESIS_JSON.to_string()) + .unwrap(); + } + + #[test] + fn spawn_works() { + Instance::new(&test_config().0) + .spawn(GENESIS_JSON.to_string()) + .unwrap(); + } + + #[test] + fn version_works() { + let version = Instance::new(&test_config().0).version().unwrap(); + assert!( + version.starts_with("geth version"), + "expected version string, got: '{version}'" + ); + } +} diff --git a/crates/node/src/lib.rs b/crates/node/src/lib.rs new file mode 100644 index 0000000..6a7c704 --- /dev/null +++ b/crates/node/src/lib.rs @@ -0,0 +1,36 @@ +//! This crate implements the testing nodes. + +use alloy::rpc::types::{TransactionReceipt, trace::geth::DiffMode}; +use revive_dt_config::Arguments; +use revive_dt_node_interaction::EthereumNode; + +pub mod geth; +pub mod pool; + +/// The default genesis configuration. +pub const GENESIS_JSON: &str = include_str!("../../../genesis.json"); + +/// An abstract interface for testing nodes. +pub trait Node: EthereumNode { + /// Create a new uninitialized instance. + fn new(config: &Arguments) -> Self; + + /// Spawns a node configured according to the genesis json. + /// + /// Blocking until it's ready to accept transactions. + fn spawn(&mut self, genesis: String) -> anyhow::Result<()>; + + /// Prune the node instance and related data. + /// + /// Blocking until it's completely stopped. + fn shutdown(self) -> anyhow::Result<()>; + + /// Returns the nodes connection string. + fn connection_string(&self) -> String; + + /// Returns the state diff of the transaction hash in the [TransactionReceipt]. + fn state_diff(&self, transaction: TransactionReceipt) -> anyhow::Result; + + /// Returns the node version. + fn version(&self) -> anyhow::Result; +} diff --git a/crates/node/src/pool.rs b/crates/node/src/pool.rs new file mode 100644 index 0000000..864a742 --- /dev/null +++ b/crates/node/src/pool.rs @@ -0,0 +1,68 @@ +//! This crate implements concurrent handling of testing node. + +use std::{ + fs::read_to_string, + sync::atomic::{AtomicUsize, Ordering}, + thread, +}; + +use anyhow::Context; +use revive_dt_config::Arguments; + +use crate::Node; + +/// The node pool starts one or more [Node] which then can be accessed +/// in a round robbin fasion. +pub struct NodePool { + next: AtomicUsize, + nodes: Vec, +} + +impl NodePool +where + T: Node + Send + 'static, +{ + /// Create a new Pool. This will start as many nodes as there are workers in `config`. + pub fn new(config: &Arguments) -> anyhow::Result { + let nodes = config.workers; + let genesis = read_to_string(&config.genesis_file).context(format!( + "can not read genesis file: {}", + config.genesis_file.display() + ))?; + + let mut handles = Vec::with_capacity(nodes); + for _ in 0..nodes { + let config = config.clone(); + let genesis = genesis.clone(); + handles.push(thread::spawn(move || spawn_node::(&config, genesis))); + } + + let mut nodes = Vec::with_capacity(nodes); + for handle in handles { + nodes.push( + handle + .join() + .map_err(|error| anyhow::anyhow!("failed to spawn node: {:?}", error))? + .map_err(|error| anyhow::anyhow!("node failed to spawn: {error}"))?, + ); + } + + Ok(Self { + nodes, + next: Default::default(), + }) + } + + /// Get a handle to the next node. + pub fn round_robbin(&self) -> &T { + let current = self.next.fetch_add(1, Ordering::SeqCst) % self.nodes.len(); + self.nodes.get(current).unwrap() + } +} + +fn spawn_node(args: &Arguments, genesis: String) -> anyhow::Result { + let mut node = T::new(args); + log::info!("starting node: {}", node.connection_string()); + node.spawn(genesis)?; + Ok(node) +} diff --git a/crates/solc-binaries/Cargo.toml b/crates/solc-binaries/Cargo.toml new file mode 100644 index 0000000..e694d3b --- /dev/null +++ b/crates/solc-binaries/Cargo.toml @@ -0,0 +1,18 @@ +[package] +name = "revive-dt-solc-binaries" +dependencies = "Download and cache solc binaries" +version.workspace = true +authors.workspace = true +license.workspace = true +edition.workspace = true +repository.workspace = true +rust-version.workspace = true + +[dependencies] +anyhow = { workspace = true } +hex = { workspace = true } +log = { workspace = true } +reqwest = { workspace = true } +semver = { workspace = true } +serde = { workspace = true } +sha2 = { workspace = true } diff --git a/crates/solc-binaries/src/cache.rs b/crates/solc-binaries/src/cache.rs new file mode 100644 index 0000000..75b83f3 --- /dev/null +++ b/crates/solc-binaries/src/cache.rs @@ -0,0 +1,71 @@ +//! Helper for caching the solc binaries. + +use std::{ + collections::HashSet, + fs::{File, create_dir_all}, + io::{BufWriter, Write}, + os::unix::fs::PermissionsExt, + path::{Path, PathBuf}, + sync::{LazyLock, Mutex}, +}; + +use crate::download::GHDownloader; + +pub const SOLC_CACHE_DIRECTORY: &str = "solc"; +pub(crate) static SOLC_CACHER: LazyLock>> = LazyLock::new(Default::default); + +pub(crate) fn get_or_download( + working_directory: &Path, + downloader: &GHDownloader, +) -> anyhow::Result { + let target_directory = working_directory + .join(SOLC_CACHE_DIRECTORY) + .join(downloader.version.to_string()); + let target_file = target_directory.join(downloader.target); + + let mut cache = SOLC_CACHER.lock().unwrap(); + if cache.contains(&target_file) { + log::debug!("using cached solc: {}", target_file.display()); + return Ok(target_file); + } + + create_dir_all(target_directory)?; + download_to_file(&target_file, downloader)?; + cache.insert(target_file.clone()); + + Ok(target_file) +} + +fn download_to_file(path: &Path, downloader: &GHDownloader) -> anyhow::Result<()> { + log::info!("caching file: {}", path.display()); + + let Ok(file) = File::create_new(path) else { + log::debug!("cache file already exists: {}", path.display()); + return Ok(()); + }; + + #[cfg(unix)] + { + let mut permissions = file.metadata()?.permissions(); + permissions.set_mode(permissions.mode() | 0o111); + file.set_permissions(permissions)?; + } + + let mut file = BufWriter::new(file); + file.write_all(&downloader.download()?)?; + file.flush()?; + drop(file); + + #[cfg(target_os = "macos")] + std::process::Command::new("xattr") + .arg("-d") + .arg("com.apple.quarantine") + .arg(&path) + .stderr(std::process::Stdio::null()) + .stdout(std::process::Stdio::null()) + .stdout(std::process::Stdio::null()) + .spawn()? + .wait()?; + + Ok(()) +} diff --git a/crates/solc-binaries/src/download.rs b/crates/solc-binaries/src/download.rs new file mode 100644 index 0000000..17693f2 --- /dev/null +++ b/crates/solc-binaries/src/download.rs @@ -0,0 +1,146 @@ +//! This module downloads solc binaries. + +use std::{ + collections::HashMap, + sync::{LazyLock, Mutex}, +}; + +use semver::Version; +use sha2::{Digest, Sha256}; + +use crate::list::List; + +pub static LIST_CACHE: LazyLock>> = + LazyLock::new(Default::default); + +impl List { + pub const LINUX_URL: &str = "https://binaries.soliditylang.org/linux-amd64/list.json"; + pub const WINDOWS_URL: &str = "https://binaries.soliditylang.org/windows-amd64/list.json"; + pub const MACOSX_URL: &str = "https://binaries.soliditylang.org/macosx-amd64/list.json"; + pub const WASM_URL: &str = "https://binaries.soliditylang.org/wasm/list.json"; + + /// Try to downloads the list from the given URL. + /// + /// Caches the list retrieved from the `url` into [LIST_CACHE], + /// subsequent calls with the same `url` will return the cached list. + pub fn download(url: &'static str) -> anyhow::Result { + if let Some(list) = LIST_CACHE.lock().unwrap().get(url) { + return Ok(list.clone()); + } + + let body: List = reqwest::blocking::get(url)?.json()?; + + LIST_CACHE.lock().unwrap().insert(url, body.clone()); + + Ok(body) + } +} + +/// Download solc binaries from GitHub releases (IPFS links aren't reliable). +#[derive(Clone, Debug)] +pub struct GHDownloader { + pub version: Version, + pub target: &'static str, + pub list: &'static str, +} + +impl GHDownloader { + pub const BASE_URL: &str = "https://github.com/ethereum/solidity/releases/download"; + + pub const LINUX_NAME: &str = "solc-static-linux"; + pub const MACOSX_NAME: &str = "solc-macos"; + pub const WINDOWS_NAME: &str = "solc-windows.exe"; + pub const WASM_NAME: &str = "soljson.js"; + + fn new(version: Version, target: &'static str, list: &'static str) -> Self { + Self { + version, + target, + list, + } + } + + pub fn linux(version: Version) -> Self { + Self::new(version, Self::LINUX_NAME, List::LINUX_URL) + } + + pub fn macosx(version: Version) -> Self { + Self::new(version, Self::MACOSX_NAME, List::MACOSX_URL) + } + + pub fn windows(version: Version) -> Self { + Self::new(version, Self::WINDOWS_NAME, List::WINDOWS_URL) + } + + pub fn wasm(version: Version) -> Self { + Self::new(version, Self::WASM_NAME, List::WASM_URL) + } + + /// Returns the download link. + pub fn url(&self) -> String { + format!("{}/v{}/{}", Self::BASE_URL, &self.version, &self.target) + } + + /// Download the solc binary. + /// + /// Errors out if the download fails or the digest of the downloaded file + /// mismatches the expected digest from the release [List]. + pub fn download(&self) -> anyhow::Result> { + log::info!("downloading solc: {self:?}"); + let expected_digest = List::download(self.list)? + .builds + .iter() + .find(|build| build.version == self.version) + .ok_or_else(|| anyhow::anyhow!("solc v{} not found builds", self.version)) + .map(|b| b.sha256.strip_prefix("0x").unwrap_or(&b.sha256).to_string())?; + + let file = reqwest::blocking::get(self.url())?.bytes()?.to_vec(); + + if hex::encode(Sha256::digest(&file)) != expected_digest { + anyhow::bail!("sha256 mismatch for solc version {}", self.version); + } + + Ok(file) + } +} + +#[cfg(test)] +mod tests { + use crate::{download::GHDownloader, list::List}; + + #[test] + fn try_get_windows() { + let version = List::download(List::WINDOWS_URL) + .unwrap() + .latest_release + .into(); + GHDownloader::windows(version).download().unwrap(); + } + + #[test] + fn try_get_macosx() { + let version = List::download(List::MACOSX_URL) + .unwrap() + .latest_release + .into(); + GHDownloader::macosx(version).download().unwrap(); + } + + #[test] + fn try_get_linux() { + let version = List::download(List::LINUX_URL) + .unwrap() + .latest_release + .into(); + GHDownloader::linux(version).download().unwrap(); + } + + #[test] + fn try_get_wasm() { + let version = List::download(List::WASM_URL) + .unwrap() + .latest_release + .into(); + GHDownloader::wasm(version).download().unwrap(); + } +} diff --git a/crates/solc-binaries/src/lib.rs b/crates/solc-binaries/src/lib.rs new file mode 100644 index 0000000..aabc86e --- /dev/null +++ b/crates/solc-binaries/src/lib.rs @@ -0,0 +1,39 @@ +//! This crates provides serializable Rust type definitions for the [solc binary lists][0] +//! and download helpers. +//! +//! [0]: https://binaries.soliditylang.org + +use std::path::{Path, PathBuf}; + +use cache::get_or_download; +use download::GHDownloader; +use semver::Version; + +pub mod cache; +pub mod download; +pub mod list; + +/// Downloads the solc binary for Wasm is `wasm` is set, otherwise for +/// the target platform. +/// +/// Subsequent calls for the same version will use a cached artifact +/// and not download it again. +pub fn download_solc( + cache_directory: &Path, + version: Version, + wasm: bool, +) -> anyhow::Result { + let downloader = if wasm { + GHDownloader::wasm(version) + } else if cfg!(target_os = "linux") { + GHDownloader::linux(version) + } else if cfg!(target_os = "macos") { + GHDownloader::macosx(version) + } else if cfg!(target_os = "windows") { + GHDownloader::windows(version) + } else { + unimplemented!() + }; + + get_or_download(cache_directory, &downloader) +} diff --git a/crates/solc-binaries/src/list.rs b/crates/solc-binaries/src/list.rs new file mode 100644 index 0000000..2287158 --- /dev/null +++ b/crates/solc-binaries/src/list.rs @@ -0,0 +1,26 @@ +//! Rust type definitions for the solc binary lists. + +use std::{collections::HashMap, path::PathBuf}; + +use semver::Version; +use serde::Deserialize; + +#[derive(Debug, Deserialize, Clone, Eq, PartialEq)] +pub struct List { + pub builds: Vec, + pub releases: HashMap, + #[serde(rename = "latestRelease")] + pub latest_release: Version, +} + +#[derive(Debug, Deserialize, Clone, Eq, PartialEq)] +pub struct Build { + pub path: PathBuf, + pub version: Version, + pub build: String, + #[serde(rename = "longVersion")] + pub long_version: String, + pub keccak256: String, + pub sha256: String, + pub urls: Vec, +} diff --git a/genesis.json b/genesis.json new file mode 100644 index 0000000..ae85d1f --- /dev/null +++ b/genesis.json @@ -0,0 +1,41 @@ +{ + "config": { + "chainId": 420420420, + "homesteadBlock": 0, + "eip150Block": 0, + "eip155Block": 0, + "eip158Block": 0, + "byzantiumBlock": 0, + "constantinopleBlock": 0, + "petersburgBlock": 0, + "istanbulBlock": 0, + "berlinBlock": 0, + "londonBlock": 0, + "arrowGlacierBlock": 0, + "grayGlacierBlock": 0, + "shanghaiTime": 0, + "cancunTime": 0, + "terminalTotalDifficulty": 0, + "terminalTotalDifficultyPassed": true, + "blobSchedule": { + "cancun": { + "target": 3, + "max": 6, + "baseFeeUpdateFraction": 3338477 + } + } + }, + "coinbase": "0xffffffffffffffffffffffffffffffffffffffff", + "difficulty": "0x00", + "extraData": "", + "gasLimit": "0xffffffff", + "nonce": "0x0000000000000042", + "mixhash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "timestamp": "0x00", + "alloc": { + "90F8bf6A479f320ead074411a4B0e7944Ea8c9C1": { + "balance": "1000000000000000000" + } + } +} \ No newline at end of file