diff --git a/Cargo.lock b/Cargo.lock index 1eff947..f7d0460 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -194,12 +194,31 @@ version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" +[[package]] +name = "ascii-canvas" +version = "3.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8824ecca2e851cec16968d54a01dd372ef8f95b244fb84b84e70128be347c3c6" +dependencies = [ + "term", +] + [[package]] name = "asn1_der" version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "155a5a185e42c6b77ac7b88a15143d930a9e9727a5b7b77eed417404ab15c247" +[[package]] +name = "assert-json-diff" +version = "2.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "47e4f2b81832e72834d7518d8487a0396a28cc408186a2e8854c0f98011faf12" +dependencies = [ + "serde", + "serde_json", +] + [[package]] name = "assert_cmd" version = "2.0.16" @@ -216,6 +235,221 @@ dependencies = [ "wait-timeout", ] +[[package]] +name = "async-attributes" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a3203e79f4dd9bdda415ed03cf14dae5a2bf775c683a00f94e9cd1faf0f596e5" +dependencies = [ + "quote", + "syn 1.0.109", +] + +[[package]] +name = "async-channel" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81953c529336010edd6d8e358f886d9581267795c61b19475b71314bffa46d35" +dependencies = [ + "concurrent-queue", + "event-listener 2.5.3", + "futures-core", +] + +[[package]] +name = "async-channel" +version = "2.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89b47800b0be77592da0afd425cc03468052844aff33b84e33cc696f64e77b6a" +dependencies = [ + "concurrent-queue", + "event-listener-strategy", + "futures-core", + "pin-project-lite", +] + +[[package]] +name = "async-executor" +version = "1.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d7ebdfa2ebdab6b1760375fa7d6f382b9f486eac35fc994625a00e89280bdbb7" +dependencies = [ + "async-task", + "concurrent-queue", + "fastrand 2.1.0", + "futures-lite 2.3.0", + "slab", +] + +[[package]] +name = "async-global-executor" +version = "2.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05b1b633a2115cd122d73b955eadd9916c18c8f510ec9cd1686404c60ad1c29c" +dependencies = [ + "async-channel 2.3.1", + "async-executor", + "async-io 2.3.4", + "async-lock 3.4.0", + "blocking", + "futures-lite 2.3.0", + "once_cell", +] + +[[package]] +name = "async-io" +version = "1.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fc5b45d93ef0529756f812ca52e44c221b35341892d3dcc34132ac02f3dd2af" +dependencies = [ + "async-lock 2.8.0", + "autocfg", + "cfg-if", + "concurrent-queue", + "futures-lite 1.13.0", + "log", + "parking", + "polling 2.8.0", + "rustix 0.37.27", + "slab", + "socket2 0.4.10", + "waker-fn", +] + +[[package]] +name = "async-io" +version = "2.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "444b0228950ee6501b3568d3c93bf1176a1fdbc3b758dcd9475046d30f4dc7e8" +dependencies = [ + "async-lock 3.4.0", + "cfg-if", + "concurrent-queue", + "futures-io", + "futures-lite 2.3.0", + "parking", + "polling 3.7.3", + "rustix 0.38.34", + "slab", + "tracing", + "windows-sys 0.59.0", +] + +[[package]] +name = "async-lock" +version = "2.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "287272293e9d8c41773cec55e365490fe034813a2f172f502d6ddcf75b2f582b" +dependencies = [ + "event-listener 2.5.3", +] + +[[package]] +name = "async-lock" +version = "3.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff6e472cdea888a4bd64f342f09b3f50e1886d32afe8df3d663c01140b811b18" +dependencies = [ + "event-listener 5.3.1", + "event-listener-strategy", + "pin-project-lite", +] + +[[package]] +name = "async-object-pool" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aeb901c30ebc2fc4ab46395bbfbdba9542c16559d853645d75190c3056caf3bc" +dependencies = [ + "async-std", +] + +[[package]] +name = "async-process" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea6438ba0a08d81529c69b36700fa2f95837bfe3e776ab39cde9c14d9149da88" +dependencies = [ + "async-io 1.13.0", + "async-lock 2.8.0", + "async-signal", + "blocking", + "cfg-if", + "event-listener 3.1.0", + "futures-lite 1.13.0", + "rustix 0.38.34", + "windows-sys 0.48.0", +] + +[[package]] +name = "async-signal" +version = "0.2.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "637e00349800c0bdf8bfc21ebbc0b6524abea702b0da4168ac00d070d0c0b9f3" +dependencies = [ + "async-io 2.3.4", + "async-lock 3.4.0", + "atomic-waker", + "cfg-if", + "futures-core", + "futures-io", + "rustix 0.38.34", + "signal-hook-registry", + "slab", + "windows-sys 0.59.0", +] + +[[package]] +name = "async-std" +version = "1.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62565bb4402e926b29953c785397c6dc0391b7b446e45008b0049eb43cec6f5d" +dependencies = [ + "async-attributes", + "async-channel 1.9.0", + "async-global-executor", + "async-io 1.13.0", + "async-lock 2.8.0", + "async-process", + "crossbeam-utils", + "futures-channel", + "futures-core", + "futures-io", + "futures-lite 1.13.0", + "gloo-timers", + "kv-log-macro", + "log", + "memchr", + "once_cell", + "pin-project-lite", + "pin-utils", + "slab", + "wasm-bindgen-futures", +] + +[[package]] +name = "async-task" +version = "4.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b75356056920673b02621b35afd0f7dda9306d03c79a30f5c56c44cf256e3de" + +[[package]] +name = "async-trait" +version = "0.1.81" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e0c28dcc82d7c8ead5cb13beb15405b57b8546e93215673ff8ca0349a028107" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.75", +] + +[[package]] +name = "atomic-waker" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" + [[package]] name = "autocfg" version = "1.3.0" @@ -267,6 +501,17 @@ version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b" +[[package]] +name = "basic-cookies" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67bd8fd42c16bdb08688243dc5f0cc117a3ca9efeeaba3a345a18a6159ad96f7" +dependencies = [ + "lalrpop", + "lalrpop-util", + "regex", +] + [[package]] name = "bindgen" version = "0.66.1" @@ -290,6 +535,21 @@ dependencies = [ "which", ] +[[package]] +name = "bit-set" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0700ddab506f33b20a03b13996eccd309a48e5ff77d0d95926aa0210fb4e95f1" +dependencies = [ + "bit-vec", +] + +[[package]] +name = "bit-vec" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "349f9b6a179ed607305526ca489b34ad0a41aed5f7980fa90eb03160b69598fb" + [[package]] name = "bitflags" version = "1.3.2" @@ -332,6 +592,19 @@ dependencies = [ "generic-array", ] +[[package]] +name = "blocking" +version = "1.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "703f41c54fc768e63e091340b424302bb1c29ef4aa0c7f10fe849dfb114d29ea" +dependencies = [ + "async-channel 2.3.1", + "async-task", + "futures-io", + "futures-lite 2.3.0", + "piper", +] + [[package]] name = "bls" version = "0.2.0" @@ -574,7 +847,7 @@ name = "compare_fields" version = "0.2.0" source = "git+https://github.com/ChorusOne/lighthouse?rev=1be5253610dc8fee3bf4b7a8dc1d01254bc5b57d#1be5253610dc8fee3bf4b7a8dc1d01254bc5b57d" dependencies = [ - "itertools", + "itertools 0.10.5", ] [[package]] @@ -586,6 +859,15 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "concurrent-queue" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ca0197aee26d1ae37445ee532fefce43251d24cc7c166799f4d46817f1d3973" +dependencies = [ + "crossbeam-utils", +] + [[package]] name = "const-oid" version = "0.9.6" @@ -1031,6 +1313,15 @@ dependencies = [ "zeroize", ] +[[package]] +name = "ena" +version = "0.14.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d248bdd43ce613d87415282f69b9bb99d947d290b10962dd6c56233312c2ad5" +dependencies = [ + "log", +] + [[package]] name = "encoding_rs" version = "0.8.34" @@ -1123,11 +1414,13 @@ dependencies = [ "ethereum_ssz_derive", "getrandom", "hex", + "httpmock", "lazy_static", "log", "predicates", "pretty_assertions", "regex", + "reqwest", "serde", "serde_derive", "serde_json", @@ -1136,6 +1429,7 @@ dependencies = [ "tree_hash", "tree_hash_derive", "types", + "url", "uuid 1.10.0", ] @@ -1304,7 +1598,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7d3627f83d8b87b432a5fad9934b4565260722a141a2c40f371f8080adec9425" dependencies = [ "ethereum-types", - "itertools", + "itertools 0.10.5", "smallvec", ] @@ -1320,6 +1614,44 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "event-listener" +version = "2.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0" + +[[package]] +name = "event-listener" +version = "3.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d93877bcde0eb80ca09131a08d23f0a5c18a620b01db137dba666d18cd9b30c2" +dependencies = [ + "concurrent-queue", + "parking", + "pin-project-lite", +] + +[[package]] +name = "event-listener" +version = "5.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6032be9bd27023a771701cc49f9f053c751055f71efb2e0ae5c15809093675ba" +dependencies = [ + "concurrent-queue", + "parking", + "pin-project-lite", +] + +[[package]] +name = "event-listener-strategy" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0f214dc438f977e6d4e3500aaa277f5ad94ca83fbbd9b1a15713ce2344ccc5a1" +dependencies = [ + "event-listener 5.3.1", + "pin-project-lite", +] + [[package]] name = "fallible-iterator" version = "0.2.0" @@ -1332,6 +1664,15 @@ version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7360491ce676a36bf9bb3c56c1aa791658183a54d2744120f27285738d90465a" +[[package]] +name = "fastrand" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e51093e27b0797c359783294ca4f0a911c270184cb10f85783b118614a1501be" +dependencies = [ + "instant", +] + [[package]] name = "fastrand" version = "2.1.0" @@ -1377,6 +1718,12 @@ dependencies = [ "static_assertions", ] +[[package]] +name = "fixedbitset" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80" + [[package]] name = "flate2" version = "1.0.31" @@ -1481,6 +1828,34 @@ version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a44623e20b9681a318efdd71c299b6b222ed6f231972bfe2f224ebad6311f0c1" +[[package]] +name = "futures-lite" +version = "1.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49a9d51ce47660b1e808d3c990b4709f2f415d928835a17dfd16991515c46bce" +dependencies = [ + "fastrand 1.9.0", + "futures-core", + "futures-io", + "memchr", + "parking", + "pin-project-lite", + "waker-fn", +] + +[[package]] +name = "futures-lite" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52527eb5074e35e9339c6b4e8d12600c7128b68fb25dcb9fa9dec18f7c25f3a5" +dependencies = [ + "fastrand 2.1.0", + "futures-core", + "futures-io", + "parking", + "pin-project-lite", +] + [[package]] name = "futures-macro" version = "0.3.30" @@ -1572,6 +1947,18 @@ version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" +[[package]] +name = "gloo-timers" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b995a66bb87bebce9a0f4a95aed01daca4872c050bfcb21653361c03bc35e5c" +dependencies = [ + "futures-channel", + "futures-core", + "js-sys", + "wasm-bindgen", +] + [[package]] name = "group" version = "0.13.0" @@ -1743,6 +2130,34 @@ version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" +[[package]] +name = "httpmock" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08ec9586ee0910472dec1a1f0f8acf52f0fdde93aea74d70d4a3107b4be0fd5b" +dependencies = [ + "assert-json-diff", + "async-object-pool", + "async-std", + "async-trait", + "base64 0.21.7", + "basic-cookies", + "crossbeam-utils", + "form_urlencoded", + "futures-util", + "hyper", + "lazy_static", + "levenshtein", + "log", + "regex", + "serde", + "serde_json", + "serde_regex", + "similar", + "tokio", + "url", +] + [[package]] name = "humantime" version = "2.1.0" @@ -1913,6 +2328,17 @@ dependencies = [ "bytes", ] +[[package]] +name = "io-lifetimes" +version = "1.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eae7b9aee968036d54dce06cebaefd919e4472e753296daccd6d344e3e2df0c2" +dependencies = [ + "hermit-abi 0.3.9", + "libc", + "windows-sys 0.48.0", +] + [[package]] name = "ipnet" version = "2.9.0" @@ -1945,6 +2371,15 @@ dependencies = [ "either", ] +[[package]] +name = "itertools" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1c173a5686ce8bfa551b3563d0c2170bf24ca44da99c7ca4bfdab5418c3fe57" +dependencies = [ + "either", +] + [[package]] name = "itoa" version = "1.0.11" @@ -1992,6 +2427,15 @@ dependencies = [ "cpufeatures", ] +[[package]] +name = "kv-log-macro" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0de8b303297635ad57c9f5059fd9cee7a47f8e8daa09df0fcd07dd39fb22977f" +dependencies = [ + "log", +] + [[package]] name = "kzg" version = "0.1.0" @@ -2009,6 +2453,37 @@ dependencies = [ "tree_hash", ] +[[package]] +name = "lalrpop" +version = "0.20.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55cb077ad656299f160924eb2912aa147d7339ea7d69e1b5517326fdcec3c1ca" +dependencies = [ + "ascii-canvas", + "bit-set", + "ena", + "itertools 0.11.0", + "lalrpop-util", + "petgraph", + "pico-args", + "regex", + "regex-syntax 0.8.4", + "string_cache", + "term", + "tiny-keccak", + "unicode-xid", + "walkdir", +] + +[[package]] +name = "lalrpop-util" +version = "0.20.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "507460a910eb7b32ee961886ff48539633b788a36b65692b95f225b844c82553" +dependencies = [ + "regex-automata 0.4.7", +] + [[package]] name = "lazy_static" version = "1.5.0" @@ -2024,6 +2499,12 @@ version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" +[[package]] +name = "levenshtein" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db13adb97ab515a3691f56e4dbab09283d0b86cb45abd991d8634a9d6f501760" + [[package]] name = "libc" version = "0.2.158" @@ -2259,6 +2740,12 @@ dependencies = [ "prometheus", ] +[[package]] +name = "linux-raw-sys" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef53942eb7bf7ff43a617b3e2c1c4a5ecf5944a7c1bc12d7ee39bbb15e5c1519" + [[package]] name = "linux-raw-sys" version = "0.4.14" @@ -2280,6 +2767,9 @@ name = "log" version = "0.4.22" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" +dependencies = [ + "value-bag", +] [[package]] name = "logging" @@ -2371,7 +2861,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7c3a991d4536c933306e52f0e8ab303757185ec13a09d1f3e1cbde5a0d8410bf" dependencies = [ "darling", - "itertools", + "itertools 0.10.5", "proc-macro2", "quote", "smallvec", @@ -2487,6 +2977,12 @@ dependencies = [ "tempfile", ] +[[package]] +name = "new_debug_unreachable" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "650eef8c711430f1a879fdd01d4745a7deea475becfb90269c06775983bbf086" + [[package]] name = "nom" version = "7.1.3" @@ -2693,6 +3189,12 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "parking" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb813b8af86854136c6922af0598d719255ecb2179515e6e7730d468f05c9cae" + [[package]] name = "parking_lot" version = "0.11.2" @@ -2791,6 +3293,31 @@ version = "2.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" +[[package]] +name = "petgraph" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4c5cc86750666a3ed20bdaf5ca2a0344f9c67674cae0515bec2da16fbaa47db" +dependencies = [ + "fixedbitset", + "indexmap", +] + +[[package]] +name = "phf_shared" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6796ad771acdc0123d2a88dc428b5e38ef24456743ddb1744ed628f9815c096" +dependencies = [ + "siphasher", +] + +[[package]] +name = "pico-args" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5be167a7af36ee22fe3115051bc51f6e6c7054c9348e28deb4f49bd6f705a315" + [[package]] name = "pin-project" version = "1.1.5" @@ -2823,6 +3350,17 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" +[[package]] +name = "piper" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96c8c490f422ef9a4efd2cb5b42b76c8613d7e7dfc1caf667b8a3350a5acc066" +dependencies = [ + "atomic-waker", + "fastrand 2.1.0", + "futures-io", +] + [[package]] name = "pkcs8" version = "0.10.2" @@ -2839,6 +3377,37 @@ version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d231b230927b5e4ad203db57bbcbee2802f6bce620b1e4a9024a07d94e2907ec" +[[package]] +name = "polling" +version = "2.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4b2d323e8ca7996b3e23126511a523f7e62924d93ecd5ae73b333815b0eb3dce" +dependencies = [ + "autocfg", + "bitflags 1.3.2", + "cfg-if", + "concurrent-queue", + "libc", + "log", + "pin-project-lite", + "windows-sys 0.48.0", +] + +[[package]] +name = "polling" +version = "3.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc2790cd301dec6cd3b7a025e4815cf825724a51c98dccfe6a3e55f05ffb6511" +dependencies = [ + "cfg-if", + "concurrent-queue", + "hermit-abi 0.4.0", + "pin-project-lite", + "rustix 0.38.34", + "tracing", + "windows-sys 0.59.0", +] + [[package]] name = "polyval" version = "0.5.3" @@ -2866,6 +3435,12 @@ dependencies = [ "zerocopy", ] +[[package]] +name = "precomputed-hash" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c" + [[package]] name = "predicates" version = "3.1.2" @@ -3276,6 +3851,20 @@ dependencies = [ "semver", ] +[[package]] +name = "rustix" +version = "0.37.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fea8ca367a3a01fe35e6943c400addf443c0f57670e6ec51196f71a4b8762dd2" +dependencies = [ + "bitflags 1.3.2", + "errno", + "io-lifetimes", + "libc", + "linux-raw-sys 0.3.8", + "windows-sys 0.48.0", +] + [[package]] name = "rustix" version = "0.38.34" @@ -3285,7 +3874,7 @@ dependencies = [ "bitflags 2.6.0", "errno", "libc", - "linux-raw-sys", + "linux-raw-sys 0.4.14", "windows-sys 0.52.0", ] @@ -3356,6 +3945,15 @@ dependencies = [ "cipher 0.3.0", ] +[[package]] +name = "same-file" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" +dependencies = [ + "winapi-util", +] + [[package]] name = "schannel" version = "0.1.23" @@ -3477,6 +4075,16 @@ dependencies = [ "serde", ] +[[package]] +name = "serde_regex" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8136f1a4ea815d7eac4101cfd0b16dc0cb5e1fe1b8609dfd728058656b7badf" +dependencies = [ + "regex", + "serde", +] + [[package]] name = "serde_repr" version = "0.1.19" @@ -3592,6 +4200,18 @@ dependencies = [ "rand_core", ] +[[package]] +name = "similar" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1de1d4f81173b03af4c0cbed3c898f6bff5b870e4a7f5d6f4057d62a7a4b686e" + +[[package]] +name = "siphasher" +version = "0.3.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38b58827f4464d87d377d175e90bf58eb00fd8716ff0a62f80356b5e61555d0d" + [[package]] name = "slab" version = "0.4.9" @@ -3761,7 +4381,7 @@ dependencies = [ "derivative", "ethereum_serde_utils", "ethereum_ssz", - "itertools", + "itertools 0.10.5", "serde", "serde_derive", "smallvec", @@ -3775,6 +4395,19 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" +[[package]] +name = "string_cache" +version = "0.8.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f91138e76242f575eb1d3b38b4f1362f10d3a43f47d182a5b359af488a02293b" +dependencies = [ + "new_debug_unreachable", + "once_cell", + "parking_lot 0.12.3", + "phf_shared", + "precomputed-hash", +] + [[package]] name = "strsim" version = "0.10.0" @@ -3822,7 +4455,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "75b9e5728aa1a87141cefd4e7509903fc01fa0dcb108022b1e841a67c5159fc5" dependencies = [ "darling", - "itertools", + "itertools 0.10.5", "proc-macro2", "quote", "smallvec", @@ -3906,9 +4539,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "04cbcdd0c794ebb0d4cf35e88edd2f7d2c4c3e9a5a6dab322839b321c6a87a64" dependencies = [ "cfg-if", - "fastrand", + "fastrand 2.1.0", "once_cell", - "rustix", + "rustix 0.38.34", "windows-sys 0.59.0", ] @@ -4304,7 +4937,7 @@ dependencies = [ "ethereum_ssz_derive", "hex", "int_to_bytes", - "itertools", + "itertools 0.10.5", "kzg", "lazy_static", "log", @@ -4367,6 +5000,12 @@ dependencies = [ "tinyvec", ] +[[package]] +name = "unicode-xid" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "229730647fbc343e3a80e463c1db7f78f3855d3f3739bee0dda773c9a037c90a" + [[package]] name = "universal-hash" version = "0.4.1" @@ -4449,6 +5088,12 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d" +[[package]] +name = "value-bag" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a84c137d37ab0142f0f2ddfe332651fdbf252e7b7dbb4e67b6c1f1b2e925101" + [[package]] name = "vcpkg" version = "0.2.15" @@ -4476,6 +5121,22 @@ dependencies = [ "libc", ] +[[package]] +name = "waker-fn" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "317211a0dc0ceedd78fb2ca9a44aed3d7b9b26f81870d485c07122b4350673b7" + +[[package]] +name = "walkdir" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b" +dependencies = [ + "same-file", + "winapi-util", +] + [[package]] name = "want" version = "0.3.1" @@ -4596,7 +5257,7 @@ dependencies = [ "either", "home", "once_cell", - "rustix", + "rustix 0.38.34", ] [[package]] @@ -4621,6 +5282,15 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" +[[package]] +name = "winapi-util" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" +dependencies = [ + "windows-sys 0.59.0", +] + [[package]] name = "winapi-x86_64-pc-windows-gnu" version = "0.4.0" diff --git a/Cargo.toml b/Cargo.toml index 962f655..5edce20 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -25,6 +25,8 @@ env_logger = "^0.11" hex = "0.4" lazy_static = "1.5" log = "^0.4" +# eth2_network_config uses native-tls, so do we +reqwest = { version = "0.11", default-features = false, features = ["native-tls"] } getrandom = "0.2" regex = "1.10.6" serde = "1.0.204" @@ -35,6 +37,7 @@ tiny-bip39 = "1.0.0" tree_hash = "0.5.2" tree_hash_derive = "0.5.2" types = { git = "https://github.com/ChorusOne/lighthouse", rev = "1be5253610dc8fee3bf4b7a8dc1d01254bc5b57d"} +url = "2.5" uuid = { version = "1.10", features = ["v4"] } [dev-dependencies] @@ -42,6 +45,7 @@ test-log = "^0.2" pretty_assertions = "^1.4" assert_cmd = "2.0" predicates = "3.0" +httpmock = "0.7" [[test]] name = "e2e-tests" diff --git a/README.md b/README.md index 9ad3b8e..32ed811 100644 --- a/README.md +++ b/README.md @@ -76,7 +76,7 @@ You can use `eth-staking-smith` as follows to convert your address: ### Command to generate SignedBLSToExecutionChange ``` -./target/debug/eth-staking-smith bls-to-execution-change --chain mainnet --mnemonic "entire habit bottom mention spoil clown finger wheat motion fox axis mechanic country make garment bar blind stadium sugar water scissors canyon often ketchup" --validator_start_index 0 --validator_index 100 --withdrawal_credentials "0x0045b91b2f60b88e7392d49ae1364b55e713d06f30e563f9f99e10994b26221d" +./target/debug/eth-staking-smith bls-to-execution-change --chain mainnet --mnemonic "entire habit bottom mention spoil clown finger wheat motion fox axis mechanic country make garment bar blind stadium sugar water scissors canyon often ketchup" --validator_start_index 0 --validator_index 100 --withdrawal_credentials "0x0045b91b2f60b88e7392d49ae1364b55e713d06f30e563f9f99e10994b26221d" \ --execution_address "0x71C7656EC7ab88b098defB751B7401B5f6d8976F" ``` @@ -86,16 +86,13 @@ Note that --validator-index and --validator-start-index are two distinct paramet ### Command to send SignedBLSToExecutionChange request to Beacon node ``` -curl -H "Content-Type: application/json" -d '{ - "message": { - "validator_index": 100, - "from_bls_pubkey": "0x0045b91b2f60b88e7392d49ae1364b55e713d06f30e563f9f99e10994b26221d", - "to_execution_address": "0x71C7656EC7ab88b098defB751B7401B5f6d8976F" - }, - "signature": "0x9220e5badefdfe8abc36cae01af29b981edeb940ff88c438f72c8af876fbd6416138c85f5348c5ace92a081fa15291aa0ffb856141b871dc807f3ec2fe9c8415cac3d76579c61455ab3938bc162e139d060c8aa13fcd670febe46bf0bb579c5a" -}' http://localhost:3500/eth/v1/beacon/pool/bls_to_execution_change +./target/debug/eth-staking-smith bls-to-execution-change --chain mainnet --mnemonic "entire habit bottom mention spoil clown finger wheat motion fox axis mechanic country make garment bar blind stadium sugar water scissors canyon often ketchup" --validator_start_index 0 --validator_index 100 --withdrawal_credentials "0x0045b91b2f60b88e7392d49ae1364b55e713d06f30e563f9f99e10994b26221d" \ +--execution_address "0x71C7656EC7ab88b098defB751B7401B5f6d8976F" \ +--beacon-node-uri http://beacon-node.local:5052 ``` +Notice `--beacon-node-uri` parameter which makes payload to be sent to beacon node + ## Generating pre-signed exit message It is possible to create pre-signed voluntary exit message for every validator that @@ -112,6 +109,16 @@ Use `eth-staking-smith` via command line like: Note that --validator-beacon-index and --validator-seed-index are two distinct parameter, the former being index of validator on Beacon chain, and the latter is the index of validator private key derived from the seed +### Command to send SignedBLSToExecutionChange request to Beacon node + +``` +./target/debug/eth-staking-smith presigned-exit-message --chain mainnet --mnemonic "entire habit bottom mention spoil clown finger wheat motion fox axis mechanic country make garment bar blind stadium sugar water scissors canyon often ketchup" --validator_seed_index 0 --validator_beacon_index 100 --epoch 300000 \ +--beacon-node-uri http://beacon-node.local:5052 +``` + +Notice `--beacon-node-uri` parameter which makes payload to be sent to beacon node + + ## Exporting CLI standard output into common keystores folder format Most validator clients recognize the keystore folder format, diff --git a/src/beacon_node.rs b/src/beacon_node.rs new file mode 100644 index 0000000..fc1020f --- /dev/null +++ b/src/beacon_node.rs @@ -0,0 +1,44 @@ +#[derive(Debug)] +pub enum BeaconNodeError { + InvalidBeaconNodeURI, + ClientConfigurationError, + NodeCommunicationError, + Non200Response, +} + +/// A trait for types that can be sent to beacon node as-is +/// without transformations +pub trait BeaconNodeExportable { + /// Export an entity as JSON + fn export(&self) -> serde_json::Value; + + /// The path at beacon node where to send data + fn beacon_node_path(&self) -> String; + + /// Send the JSON payload to beacon node + fn send_beacon_payload(&self, beacon_node_uri: url::Url) -> Result<(), BeaconNodeError> { + let reqwc = reqwest::blocking::Client::builder() + .build() + .map_err(|_| BeaconNodeError::ClientConfigurationError)?; + let joined_url = beacon_node_uri + .join(&self.beacon_node_path()) + .map_err(|_| BeaconNodeError::InvalidBeaconNodeURI)?; + let resp = reqwc + .post(joined_url) + .header("Content-Type", "application/json") + .body(self.export().to_string()) + .send(); + + match resp { + Ok(response) => { + let code = response.status().as_u16(); + if code != 200 { + Err(BeaconNodeError::Non200Response) + } else { + Ok(()) + } + } + Err(_) => Err(BeaconNodeError::NodeCommunicationError), + } + } +} diff --git a/src/bls_to_execution_change/operator.rs b/src/bls_to_execution_change/operator.rs index b4b49ba..4925ca5 100644 --- a/src/bls_to_execution_change/operator.rs +++ b/src/bls_to_execution_change/operator.rs @@ -5,11 +5,9 @@ use types::{ SignedRoot, }; -use crate::utils::get_withdrawal_credentials; +use crate::{beacon_node::BeaconNodeExportable, utils::get_withdrawal_credentials}; pub(crate) trait SignedBlsToExecutionChangeOperator { - fn export(&self) -> serde_json::Value; - fn validate( self, from_bls_withdrawal_credentials: &str, @@ -19,18 +17,26 @@ pub(crate) trait SignedBlsToExecutionChangeOperator { ); } -impl SignedBlsToExecutionChangeOperator for SignedBlsToExecutionChange { +impl BeaconNodeExportable for SignedBlsToExecutionChange { fn export(&self) -> serde_json::Value { - serde_json::json!({ - "message": { - "validator_index": self.message.validator_index.to_string(), - "from_bls_pubkey": self.message.from_bls_pubkey, - "to_execution_address": format!("0x{}", hex::encode(self.message.to_execution_address)), - }, - "signature": self.signature.to_string() - }) + serde_json::json!([ + { + "message": { + "validator_index": self.message.validator_index.to_string(), + "from_bls_pubkey": self.message.from_bls_pubkey, + "to_execution_address": format!("0x{}", hex::encode(self.message.to_execution_address)), + }, + "signature": self.signature.to_string() + } + ]) + } + + fn beacon_node_path(&self) -> String { + "/eth/v1/beacon/pool/bls_to_execution_changes".to_string() } +} +impl SignedBlsToExecutionChangeOperator for SignedBlsToExecutionChange { fn validate( self, from_bls_withdrawal_credentials: &str, diff --git a/src/cli/bls_to_execution_change.rs b/src/cli/bls_to_execution_change.rs index 54b9d87..70012dc 100644 --- a/src/cli/bls_to_execution_change.rs +++ b/src/cli/bls_to_execution_change.rs @@ -1,6 +1,6 @@ -use crate::bls_to_execution_change; use crate::bls_to_execution_change::operator::SignedBlsToExecutionChangeOperator; use crate::chain_spec::validators_root_and_spec; +use crate::{beacon_node::BeaconNodeExportable, bls_to_execution_change}; use clap::{arg, Parser}; #[derive(Clone, Parser)] @@ -27,12 +27,12 @@ pub struct BlsToExecutionChangeSubcommandOpts { /// and you want to generate for the 2nd validator, /// the validator_start_index would be 1. /// If no index specified, it will be set to 0. - #[arg(long, visible_alias = "validator_start_index")] - pub validator_start_index: u32, + #[arg(long, visible_alias = "validator_seed_index")] + pub validator_seed_index: u32, /// On-chain beacon index of the validator. - #[arg(long, visible_alias = "validator_index")] - pub validator_index: u32, + #[arg(long, visible_alias = "validator_beacon_index")] + pub validator_beacon_index: u32, /// BLS withdrawal credentials you used when depositing the validator. #[arg(long, visible_alias = "bls_withdrawal_credentials")] @@ -51,6 +51,11 @@ pub struct BlsToExecutionChangeSubcommandOpts { /// description #[arg(long, visible_alias = "genesis_validators_root")] pub genesis_validators_root: Option, + + /// Optional beacon node URL. If set, the bls-to-execution-change message + /// will not be printed on stdout, but instead sent to beacon node + #[arg(long, visible_alias = "beacon_node_uri")] + pub beacon_node_uri: Option, } impl BlsToExecutionChangeSubcommandOpts { @@ -83,8 +88,8 @@ impl BlsToExecutionChangeSubcommandOpts { let (bls_to_execution_change, keypair) = bls_to_execution_change::bls_execution_change_from_mnemonic( self.mnemonic.as_bytes(), - self.validator_start_index as u64, - self.validator_index as u64, + self.validator_seed_index as u64, + self.validator_beacon_index as u64, self.execution_address.as_str(), ); @@ -101,10 +106,16 @@ impl BlsToExecutionChangeSubcommandOpts { &genesis_validators_root, ); - let export = signed_bls_to_execution_change.export(); + if self.beacon_node_uri.is_some() { + signed_bls_to_execution_change + .send_beacon_payload(self.beacon_node_uri.clone().unwrap()) + .unwrap_or_else(|e| panic!("Failed sending beacon node payload: {:?}", e)) + } else { + let export = signed_bls_to_execution_change.export(); - let signed_bls_to_execution_change_json = - serde_json::to_string_pretty(&export).expect("could not parse validator export"); - println!("{}", signed_bls_to_execution_change_json); + let signed_bls_to_execution_change_json = + serde_json::to_string_pretty(&export).expect("could not parse validator export"); + println!("{}", signed_bls_to_execution_change_json); + } } } diff --git a/src/cli/presigned_exit_message.rs b/src/cli/presigned_exit_message.rs index 275285c..d27b539 100644 --- a/src/cli/presigned_exit_message.rs +++ b/src/cli/presigned_exit_message.rs @@ -1,5 +1,6 @@ use clap::{arg, Parser}; +use crate::beacon_node::BeaconNodeExportable; use crate::voluntary_exit::operator::SignedVoluntaryExitOperator; use crate::{chain_spec::validators_root_and_spec, voluntary_exit}; @@ -47,6 +48,11 @@ pub struct PresignedExitMessageSubcommandOpts { /// description #[arg(long, visible_alias = "genesis_validators_root")] pub genesis_validators_root: Option, + + /// Optional beacon node URL. If set, the bls-to-execution-change message + /// will not be printed on stdout, but instead sent to beacon node + #[arg(long, visible_alias = "beacon_node_uri")] + pub beacon_node_uri: Option, } impl PresignedExitMessageSubcommandOpts { @@ -91,10 +97,16 @@ impl PresignedExitMessageSubcommandOpts { &spec, &genesis_validators_root, ); - let export = signed_voluntary_exit.export(); - let presigned_exit_message_json = - serde_json::to_string_pretty(&export).expect("could not parse validator export"); - println!("{}", presigned_exit_message_json); + if self.beacon_node_uri.is_some() { + signed_voluntary_exit + .send_beacon_payload(self.beacon_node_uri.clone().unwrap()) + .unwrap_or_else(|e| panic!("Failed sending beacon node payload: {:?}", e)) + } else { + let export = signed_voluntary_exit.export(); + let presigned_exit_message_json = + serde_json::to_string_pretty(&export).expect("could not parse validator export"); + println!("{}", presigned_exit_message_json); + } } } diff --git a/src/lib.rs b/src/lib.rs index 54e0a61..e61b504 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,4 +1,5 @@ #![forbid(unsafe_code)] +pub(crate) mod beacon_node; pub mod bls_to_execution_change; pub mod chain_spec; pub mod cli; diff --git a/src/voluntary_exit/operator.rs b/src/voluntary_exit/operator.rs index 0721159..32362fc 100644 --- a/src/voluntary_exit/operator.rs +++ b/src/voluntary_exit/operator.rs @@ -3,23 +3,31 @@ use types::{ ChainSpec, Domain, ForkName, PublicKey, SignedRoot, SignedVoluntaryExit, VoluntaryExit, }; -pub(crate) trait SignedVoluntaryExitOperator { - fn export(&self) -> serde_json::Value; +use crate::beacon_node::BeaconNodeExportable; +pub(crate) trait SignedVoluntaryExitOperator { fn validate(self, pubkey: &PublicKey, spec: &ChainSpec, genesis_validators_root: &Hash256); } -impl SignedVoluntaryExitOperator for SignedVoluntaryExit { +impl BeaconNodeExportable for SignedVoluntaryExit { fn export(&self) -> serde_json::Value { - serde_json::json!({ - "message": { - "epoch": self.message.epoch.as_u64(), - "validator_index": self.message.validator_index, - }, - "signature": self.signature.to_string() - }) + serde_json::json!([ + { + "message": { + "epoch": self.message.epoch.as_u64(), + "validator_index": self.message.validator_index, + }, + "signature": self.signature.to_string() + } + ]) } + fn beacon_node_path(&self) -> String { + "/eth/v1/beacon/pool/voluntary_exits".to_string() + } +} + +impl SignedVoluntaryExitOperator for SignedVoluntaryExit { fn validate(self, pubkey: &PublicKey, spec: &ChainSpec, genesis_validators_root: &Hash256) { let fork_name = spec.fork_name_at_epoch(self.message.epoch); let fork_version = match fork_name { diff --git a/tests/e2e/bls_to_execution_change.rs b/tests/e2e/bls_to_execution_change.rs index 32f66b2..8f321b3 100644 --- a/tests/e2e/bls_to_execution_change.rs +++ b/tests/e2e/bls_to_execution_change.rs @@ -37,9 +37,9 @@ fn test_bls_to_execution_change() -> Result<(), Box> { cmd.arg("bls-to-execution-change"); cmd.arg("--chain"); cmd.arg(chain); - cmd.arg("--validator_start_index"); + cmd.arg("--validator_seed_index"); cmd.arg(validator_start_index); - cmd.arg("--validator_index"); + cmd.arg("--validator_beacon_index"); cmd.arg(validator_index); cmd.arg("--mnemonic"); cmd.arg(expected_mnemonic); @@ -55,8 +55,10 @@ fn test_bls_to_execution_change() -> Result<(), Box> { let output = &cmd.output()?.stdout; let command_output = std::str::from_utf8(output)?; - let signed_bls_to_execution_change: SignedBlsToExecutionChange = + let signed_bls_to_execution_changes: Vec = serde_json::from_str(command_output)?; + assert_eq!(1, signed_bls_to_execution_changes.len()); + let signed_bls_to_execution_change = signed_bls_to_execution_changes.first().unwrap(); assert_eq!(100, signed_bls_to_execution_change.message.validator_index); assert_eq!( @@ -86,4 +88,57 @@ fn test_bls_to_execution_change() -> Result<(), Box> { Ok(()) } -// negative test inputs +#[test] +fn test_bls_to_execution_change_send_beacon_node() -> Result<(), Box> { + let server = httpmock::MockServer::start(); + + let beacon_node_mock = server.mock(|when, then| { + when.method(httpmock::Method::POST) + .path("/eth/v1/beacon/pool/bls_to_execution_changes") + .json_body(serde_json::json!([ + { + "message": { + "from_bls_pubkey": "0x958823db41e63bdb54b8445e454f24a592a44faef7bf1161c482c254d36cd2ffb027af3cc87817064c6a09f54acec5a0", + "to_execution_address": "0x71C7656EC7ab88b098defB751B7401B5f6d8976F".to_lowercase(), + "validator_index": "100", + }, + "signature": "0xb9e6fcdf66962fbaeec762908e7c986c154ba2274fdfe307603d71c465acda49af98a75aa62743fc59a71e678fccd433164247130c1cede0832a17cc61fc21204ec83c7f8fd76848d6520805939547b4c677fca85f98d1f749c428814fd6a6c5" + } + ])); + then.status(200); + }); + + let chain = "holesky"; + let expected_mnemonic = "ski interest capable knee usual ugly duty exercise tattoo subway delay upper bid forget say"; + let validator_start_index = "0"; + let validator_index = "100"; + let execution_address = "0x71C7656EC7ab88b098defB751B7401B5f6d8976F"; + let bls_withdrawal_credentials = + "0x0045b91b2f60b88e7392d49ae1364b55e713d06f30e563f9f99e10994b26221d"; + // run eth-staking-smith + let mut cmd = Command::cargo_bin("eth-staking-smith")?; + + cmd.arg("bls-to-execution-change"); + cmd.arg("--chain"); + cmd.arg(chain); + cmd.arg("--validator_seed_index"); + cmd.arg(validator_start_index); + cmd.arg("--validator_beacon_index"); + cmd.arg(validator_index); + cmd.arg("--mnemonic"); + cmd.arg(expected_mnemonic); + cmd.arg("--bls_withdrawal_credentials"); + cmd.arg(bls_withdrawal_credentials); + cmd.arg("--execution_address"); + cmd.arg(execution_address); + cmd.arg("--beacon-node-uri"); + cmd.arg(server.base_url()); + + cmd.assert().success(); + + // verify request path and body + + beacon_node_mock.assert(); + + Ok(()) +} diff --git a/tests/e2e/presigned_exit_message.rs b/tests/e2e/presigned_exit_message.rs index d8d1d03..6594ba4 100644 --- a/tests/e2e/presigned_exit_message.rs +++ b/tests/e2e/presigned_exit_message.rs @@ -92,7 +92,9 @@ fn test_presigned_exit_message() -> Result<(), Box> { let output = &cmd.output()?.stdout; let command_output = std::str::from_utf8(output)?; - let signed_voluntary_exit: SignedVoluntaryExit = serde_json::from_str(command_output)?; + let signed_voluntary_exits: Vec = serde_json::from_str(command_output)?; + assert_eq!(1, signed_voluntary_exits.len()); + let signed_voluntary_exit = signed_voluntary_exits.first().unwrap(); assert_eq!( signed_voluntary_exit.signature.to_string(), @@ -101,3 +103,54 @@ fn test_presigned_exit_message() -> Result<(), Box> { Ok(()) } + +#[test] +fn test_presigned_exit_message_send_beacon_node() -> Result<(), Box> { + let chain = "mainnet"; + let expected_mnemonic = "ski interest capable knee usual ugly duty exercise tattoo subway delay upper bid forget say"; + let validator_start_index = "0"; + let validator_index = "100"; + let epoch = "305658"; + + let server = httpmock::MockServer::start(); + + let beacon_node_mock = server.mock(|when, then| { + when.method(httpmock::Method::POST) + .path("/eth/v1/beacon/pool/voluntary_exits") + .json_body(serde_json::json!([ + { + "message": { + "epoch": epoch.parse::().unwrap(), + "validator_index": validator_index.parse::().unwrap(), + }, + "signature": "0xa74f22d26da9934c2a9c783799fb9e7bef49b3d7c3759a0683b52ee5d71516c0ecdbcc47703f11959c5e701a6c47194410bed800217bd4dd0dab1e0587b14551771accd04ff1c78302f9605f44c3894976c5b3537b70cb7ac9dcb5398dc22079" + } + ])); + then.status(200); + }); + + // run eth-staking-smith + let mut cmd = Command::cargo_bin("eth-staking-smith")?; + + cmd.arg("presigned-exit-message"); + cmd.arg("--chain"); + cmd.arg(chain); + cmd.arg("--validator_seed_index"); + cmd.arg(validator_start_index); + cmd.arg("--validator_beacon_index"); + cmd.arg(validator_index); + cmd.arg("--mnemonic"); + cmd.arg(expected_mnemonic); + cmd.arg("--epoch"); + cmd.arg(epoch); + cmd.arg("--beacon-node-uri"); + cmd.arg(server.base_url()); + + cmd.assert().success(); + + // verify request path and body + + beacon_node_mock.assert(); + + Ok(()) +}