Verify Versioned Hashes During Optimistic Sync (#4832)
* Convert NewPayloadRequest to use Reference * Refactor for Clarity * Verify Versioned Hashes * Added Tests for Version Hash Verification * Added Moar Tests * Fix Problems Caused By Merge * Update to use Alloy Instead of Reth Crates (#14) * Update beacon_node/execution_layer/src/engine_api/new_payload_request.rs Co-authored-by: realbigsean <seananderson33@GMAIL.com> * Faster Versioned Hash Extraction * Update to rust 1.75 & Pin alloy-consensus
This commit is contained in:
parent
1711b80779
commit
a264afd19f
423
Cargo.lock
generated
423
Cargo.lock
generated
@ -179,6 +179,95 @@ version = "0.2.16"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "0942ffc6dcaadf03badf6e6a2d0228460359d5e34b57ccdc720b7382dfbd5ec5"
|
checksum = "0942ffc6dcaadf03badf6e6a2d0228460359d5e34b57ccdc720b7382dfbd5ec5"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "alloy-consensus"
|
||||||
|
version = "0.1.0"
|
||||||
|
source = "git+https://github.com/alloy-rs/alloy.git?rev=974d488bab5e21e9f17452a39a4bfa56677367b2#974d488bab5e21e9f17452a39a4bfa56677367b2"
|
||||||
|
dependencies = [
|
||||||
|
"alloy-eips",
|
||||||
|
"alloy-network",
|
||||||
|
"alloy-primitives",
|
||||||
|
"alloy-rlp",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "alloy-eips"
|
||||||
|
version = "0.1.0"
|
||||||
|
source = "git+https://github.com/alloy-rs/alloy.git?rev=974d488bab5e21e9f17452a39a4bfa56677367b2#974d488bab5e21e9f17452a39a4bfa56677367b2"
|
||||||
|
dependencies = [
|
||||||
|
"alloy-primitives",
|
||||||
|
"alloy-rlp",
|
||||||
|
"serde",
|
||||||
|
"thiserror",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "alloy-json-rpc"
|
||||||
|
version = "0.1.0"
|
||||||
|
source = "git+https://github.com/alloy-rs/alloy.git?rev=974d488bab5e21e9f17452a39a4bfa56677367b2#974d488bab5e21e9f17452a39a4bfa56677367b2"
|
||||||
|
dependencies = [
|
||||||
|
"alloy-primitives",
|
||||||
|
"serde",
|
||||||
|
"serde_json",
|
||||||
|
"thiserror",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "alloy-network"
|
||||||
|
version = "0.1.0"
|
||||||
|
source = "git+https://github.com/alloy-rs/alloy.git?rev=974d488bab5e21e9f17452a39a4bfa56677367b2#974d488bab5e21e9f17452a39a4bfa56677367b2"
|
||||||
|
dependencies = [
|
||||||
|
"alloy-eips",
|
||||||
|
"alloy-json-rpc",
|
||||||
|
"alloy-primitives",
|
||||||
|
"alloy-rlp",
|
||||||
|
"serde",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "alloy-primitives"
|
||||||
|
version = "0.6.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f4b6fb2b432ff223d513db7f908937f63c252bee0af9b82bfd25b0a5dd1eb0d8"
|
||||||
|
dependencies = [
|
||||||
|
"alloy-rlp",
|
||||||
|
"bytes",
|
||||||
|
"cfg-if",
|
||||||
|
"const-hex",
|
||||||
|
"derive_more",
|
||||||
|
"hex-literal",
|
||||||
|
"itoa",
|
||||||
|
"k256 0.13.3",
|
||||||
|
"keccak-asm",
|
||||||
|
"proptest",
|
||||||
|
"rand",
|
||||||
|
"ruint",
|
||||||
|
"serde",
|
||||||
|
"tiny-keccak",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "alloy-rlp"
|
||||||
|
version = "0.3.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8d58d9f5da7b40e9bfff0b7e7816700be4019db97d4b6359fe7f94a9e22e42ac"
|
||||||
|
dependencies = [
|
||||||
|
"alloy-rlp-derive",
|
||||||
|
"arrayvec",
|
||||||
|
"bytes",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "alloy-rlp-derive"
|
||||||
|
version = "0.3.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1a047897373be4bbb0224c1afdabca92648dc57a9c9ef6e7b0be3aff7a859c83"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn 2.0.48",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "amcl"
|
name = "amcl"
|
||||||
version = "0.3.0"
|
version = "0.3.0"
|
||||||
@ -229,6 +318,130 @@ version = "1.6.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "bddcadddf5e9015d310179a59bb28c4d4b9920ad0f11e8e14dbadf654890c9a6"
|
checksum = "bddcadddf5e9015d310179a59bb28c4d4b9920ad0f11e8e14dbadf654890c9a6"
|
||||||
|
|
||||||
|
[[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",
|
||||||
|
"num-bigint",
|
||||||
|
"num-traits",
|
||||||
|
"paste",
|
||||||
|
"rustc_version 0.4.0",
|
||||||
|
"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]]
|
[[package]]
|
||||||
name = "arrayref"
|
name = "arrayref"
|
||||||
version = "0.3.7"
|
version = "0.3.7"
|
||||||
@ -485,7 +698,7 @@ checksum = "b6d7b9decdf35d8908a7e3ef02f64c5e9b1695e230154c0e8de3969142d9b94c"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"futures",
|
"futures",
|
||||||
"pharos",
|
"pharos",
|
||||||
"rustc_version",
|
"rustc_version 0.4.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -838,6 +1051,21 @@ dependencies = [
|
|||||||
"which",
|
"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]]
|
[[package]]
|
||||||
name = "bitflags"
|
name = "bitflags"
|
||||||
version = "1.3.2"
|
version = "1.3.2"
|
||||||
@ -1119,7 +1347,7 @@ checksum = "eee4243f1f26fc7a42710e7439c149e2b10b05472f88090acce52632f231a73a"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"camino",
|
"camino",
|
||||||
"cargo-platform",
|
"cargo-platform",
|
||||||
"semver",
|
"semver 1.0.21",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
"thiserror",
|
"thiserror",
|
||||||
@ -1331,6 +1559,19 @@ dependencies = [
|
|||||||
"crossbeam-utils",
|
"crossbeam-utils",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "const-hex"
|
||||||
|
version = "1.10.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a5104de16b218eddf8e34ffe2f86f74bfa4e61e95a1b89732fccf6325efd0557"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"cpufeatures",
|
||||||
|
"hex",
|
||||||
|
"proptest",
|
||||||
|
"serde",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "const-oid"
|
name = "const-oid"
|
||||||
version = "0.9.6"
|
version = "0.9.6"
|
||||||
@ -1593,7 +1834,7 @@ dependencies = [
|
|||||||
"digest 0.10.7",
|
"digest 0.10.7",
|
||||||
"fiat-crypto",
|
"fiat-crypto",
|
||||||
"platforms 3.3.0",
|
"platforms 3.3.0",
|
||||||
"rustc_version",
|
"rustc_version 0.4.0",
|
||||||
"subtle",
|
"subtle",
|
||||||
"zeroize",
|
"zeroize",
|
||||||
]
|
]
|
||||||
@ -1820,7 +2061,7 @@ dependencies = [
|
|||||||
"convert_case",
|
"convert_case",
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"rustc_version",
|
"rustc_version 0.4.0",
|
||||||
"syn 1.0.109",
|
"syn 1.0.109",
|
||||||
]
|
]
|
||||||
|
|
||||||
@ -2755,6 +2996,8 @@ dependencies = [
|
|||||||
name = "execution_layer"
|
name = "execution_layer"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"alloy-consensus",
|
||||||
|
"alloy-rlp",
|
||||||
"arc-swap",
|
"arc-swap",
|
||||||
"async-trait",
|
"async-trait",
|
||||||
"builder_client",
|
"builder_client",
|
||||||
@ -2848,6 +3091,17 @@ version = "2.0.1"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "25cbce373ec4653f1a01a31e8a5e5ec0c622dc27ff9c4e6606eefef5cbbed4a5"
|
checksum = "25cbce373ec4653f1a01a31e8a5e5ec0c622dc27ff9c4e6606eefef5cbbed4a5"
|
||||||
|
|
||||||
|
[[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]]
|
[[package]]
|
||||||
name = "ff"
|
name = "ff"
|
||||||
version = "0.12.1"
|
version = "0.12.1"
|
||||||
@ -2887,7 +3141,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "38e2275cc4e4fc009b0669731a1e5ab7ebf11f469eaede2bab9309a5b4d6057f"
|
checksum = "38e2275cc4e4fc009b0669731a1e5ab7ebf11f469eaede2bab9309a5b4d6057f"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"memoffset",
|
"memoffset",
|
||||||
"rustc_version",
|
"rustc_version 0.4.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -3454,6 +3708,15 @@ name = "hex"
|
|||||||
version = "0.4.3"
|
version = "0.4.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70"
|
checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70"
|
||||||
|
dependencies = [
|
||||||
|
"serde",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "hex-literal"
|
||||||
|
version = "0.4.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "6fe2267d4ed49bc07b63801559be28c718ea06c4738b7a03c94df7386d2cde46"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "hex_fmt"
|
name = "hex_fmt"
|
||||||
@ -4188,6 +4451,16 @@ dependencies = [
|
|||||||
"cpufeatures",
|
"cpufeatures",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "keccak-asm"
|
||||||
|
version = "0.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "bb8515fff80ed850aea4a1595f2e519c003e2a00a82fe168ebf5269196caf444"
|
||||||
|
dependencies = [
|
||||||
|
"digest 0.10.7",
|
||||||
|
"sha3-asm",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "keccak-hash"
|
name = "keccak-hash"
|
||||||
version = "0.10.0"
|
version = "0.10.0"
|
||||||
@ -5618,6 +5891,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "39e3200413f237f41ab11ad6d161bc7239c84dcb631773ccd7de3dfe4b5c267c"
|
checksum = "39e3200413f237f41ab11ad6d161bc7239c84dcb631773ccd7de3dfe4b5c267c"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"autocfg",
|
"autocfg",
|
||||||
|
"libm",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -5986,6 +6260,17 @@ version = "2.3.1"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e"
|
checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "pest"
|
||||||
|
version = "2.7.7"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "219c0dcc30b6a27553f9cc242972b67f75b60eb0db71f0b5462f38b058c41546"
|
||||||
|
dependencies = [
|
||||||
|
"memchr",
|
||||||
|
"thiserror",
|
||||||
|
"ucd-trie",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pharos"
|
name = "pharos"
|
||||||
version = "0.5.3"
|
version = "0.5.3"
|
||||||
@ -5993,7 +6278,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "e9567389417feee6ce15dd6527a8a1ecac205ef62c2932bcf3d9f6fc5b78b414"
|
checksum = "e9567389417feee6ce15dd6527a8a1ecac205ef62c2932bcf3d9f6fc5b78b414"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"futures",
|
"futures",
|
||||||
"rustc_version",
|
"rustc_version 0.4.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -6373,6 +6658,26 @@ dependencies = [
|
|||||||
"syn 2.0.48",
|
"syn 2.0.48",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "proptest"
|
||||||
|
version = "1.4.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "31b476131c3c86cb68032fdc5cb6d5a1045e3e42d96b69fa599fd77701e1f5bf"
|
||||||
|
dependencies = [
|
||||||
|
"bit-set",
|
||||||
|
"bit-vec",
|
||||||
|
"bitflags 2.4.2",
|
||||||
|
"lazy_static",
|
||||||
|
"num-traits",
|
||||||
|
"rand",
|
||||||
|
"rand_chacha",
|
||||||
|
"rand_xorshift",
|
||||||
|
"regex-syntax 0.8.2",
|
||||||
|
"rusty-fork",
|
||||||
|
"tempfile",
|
||||||
|
"unarray",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "proto_array"
|
name = "proto_array"
|
||||||
version = "0.2.0"
|
version = "0.2.0"
|
||||||
@ -6865,6 +7170,36 @@ dependencies = [
|
|||||||
"tokio",
|
"tokio",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ruint"
|
||||||
|
version = "1.11.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "608a5726529f2f0ef81b8fde9873c4bb829d6b5b5ca6be4d97345ddf0749c825"
|
||||||
|
dependencies = [
|
||||||
|
"alloy-rlp",
|
||||||
|
"ark-ff 0.3.0",
|
||||||
|
"ark-ff 0.4.2",
|
||||||
|
"bytes",
|
||||||
|
"fastrlp",
|
||||||
|
"num-bigint",
|
||||||
|
"num-traits",
|
||||||
|
"parity-scale-codec 3.6.9",
|
||||||
|
"primitive-types 0.12.2",
|
||||||
|
"proptest",
|
||||||
|
"rand",
|
||||||
|
"rlp",
|
||||||
|
"ruint-macro",
|
||||||
|
"serde",
|
||||||
|
"valuable",
|
||||||
|
"zeroize",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ruint-macro"
|
||||||
|
version = "1.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e666a5496a0b2186dbcd0ff6106e29e093c15591bde62c20d3842007c6978a09"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rusqlite"
|
name = "rusqlite"
|
||||||
version = "0.28.0"
|
version = "0.28.0"
|
||||||
@ -6897,13 +7232,22 @@ version = "2.1.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "3e75f6a532d0fd9f7f13144f392b6ad56a32696bfcd9c78f797f16bbb6f072d6"
|
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]]
|
[[package]]
|
||||||
name = "rustc_version"
|
name = "rustc_version"
|
||||||
version = "0.4.0"
|
version = "0.4.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366"
|
checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"semver",
|
"semver 1.0.21",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -6993,6 +7337,18 @@ version = "1.0.14"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "7ffc183a10b4478d04cbbbfc96d0873219d962dd5accaff2ffbd4ceb7df837f4"
|
checksum = "7ffc183a10b4478d04cbbbfc96d0873219d962dd5accaff2ffbd4ceb7df837f4"
|
||||||
|
|
||||||
|
[[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]]
|
[[package]]
|
||||||
name = "rw-stream-sink"
|
name = "rw-stream-sink"
|
||||||
version = "0.4.0"
|
version = "0.4.0"
|
||||||
@ -7159,6 +7515,15 @@ dependencies = [
|
|||||||
"libc",
|
"libc",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "semver"
|
||||||
|
version = "0.11.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f301af10236f6df4160f7c3f04eec6dbc70ace82d23326abad5edee88801c6b6"
|
||||||
|
dependencies = [
|
||||||
|
"semver-parser",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "semver"
|
name = "semver"
|
||||||
version = "1.0.21"
|
version = "1.0.21"
|
||||||
@ -7168,6 +7533,15 @@ dependencies = [
|
|||||||
"serde",
|
"serde",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "semver-parser"
|
||||||
|
version = "0.10.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "00b0bef5b7f9e0df16536d3961cfb6e84331c065b4066afb39768d0e319411f7"
|
||||||
|
dependencies = [
|
||||||
|
"pest",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "send_wrapper"
|
name = "send_wrapper"
|
||||||
version = "0.6.0"
|
version = "0.6.0"
|
||||||
@ -7367,6 +7741,16 @@ dependencies = [
|
|||||||
"keccak",
|
"keccak",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "sha3-asm"
|
||||||
|
version = "0.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "bac61da6b35ad76b195eb4771210f947734321a8d81d7738e1580d953bc7a15e"
|
||||||
|
dependencies = [
|
||||||
|
"cc",
|
||||||
|
"cfg-if",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "sharded-slab"
|
name = "sharded-slab"
|
||||||
version = "0.1.7"
|
version = "0.1.7"
|
||||||
@ -7659,7 +8043,7 @@ dependencies = [
|
|||||||
"curve25519-dalek",
|
"curve25519-dalek",
|
||||||
"rand_core",
|
"rand_core",
|
||||||
"ring 0.17.7",
|
"ring 0.17.7",
|
||||||
"rustc_version",
|
"rustc_version 0.4.0",
|
||||||
"sha2 0.10.8",
|
"sha2 0.10.8",
|
||||||
"subtle",
|
"subtle",
|
||||||
]
|
]
|
||||||
@ -8621,6 +9005,12 @@ dependencies = [
|
|||||||
"tree_hash_derive",
|
"tree_hash_derive",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ucd-trie"
|
||||||
|
version = "0.1.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ed646292ffc8188ef8ea4d1e0e0150fb15a5c2e12ad9b8fc191ae7a8a7f3c4b9"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "uint"
|
name = "uint"
|
||||||
version = "0.9.5"
|
version = "0.9.5"
|
||||||
@ -8634,6 +9024,12 @@ dependencies = [
|
|||||||
"static_assertions",
|
"static_assertions",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "unarray"
|
||||||
|
version = "0.1.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "eaea85b334db583fe3274d12b4cd1880032beab409c0d774be044d4480ab9a94"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "unescape"
|
name = "unescape"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
@ -8911,6 +9307,15 @@ version = "1.0.2"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d"
|
checksum = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "wait-timeout"
|
||||||
|
version = "0.2.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9f200f5b12eb75f8c1ed65abd4b2db8a6e1b138a20de009dacee265a2498f3f6"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "waker-fn"
|
name = "waker-fn"
|
||||||
version = "1.1.1"
|
version = "1.1.1"
|
||||||
@ -9496,7 +9901,7 @@ dependencies = [
|
|||||||
"js-sys",
|
"js-sys",
|
||||||
"log",
|
"log",
|
||||||
"pharos",
|
"pharos",
|
||||||
"rustc_version",
|
"rustc_version 0.4.0",
|
||||||
"send_wrapper",
|
"send_wrapper",
|
||||||
"thiserror",
|
"thiserror",
|
||||||
"wasm-bindgen",
|
"wasm-bindgen",
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
FROM rust:1.73.0-bullseye AS builder
|
FROM rust:1.75.0-bullseye AS builder
|
||||||
RUN apt-get update && apt-get -y upgrade && apt-get install -y cmake libclang-dev
|
RUN apt-get update && apt-get -y upgrade && apt-get install -y cmake libclang-dev
|
||||||
COPY . lighthouse
|
COPY . lighthouse
|
||||||
ARG FEATURES
|
ARG FEATURES
|
||||||
|
@ -81,14 +81,10 @@ impl<T: BeaconChainTypes> PayloadNotifier<T> {
|
|||||||
|
|
||||||
match notify_execution_layer {
|
match notify_execution_layer {
|
||||||
NotifyExecutionLayer::No if chain.config.optimistic_finalized_sync => {
|
NotifyExecutionLayer::No if chain.config.optimistic_finalized_sync => {
|
||||||
// Verify the block hash here in Lighthouse and immediately mark the block as
|
// Create a NewPayloadRequest (no clones required) and check optimistic sync verifications
|
||||||
// optimistically imported. This saves a lot of roundtrips to the EL.
|
let new_payload_request: NewPayloadRequest<T::EthSpec> =
|
||||||
let execution_layer = chain
|
block_message.try_into()?;
|
||||||
.execution_layer
|
if let Err(e) = new_payload_request.perform_optimistic_sync_verifications() {
|
||||||
.as_ref()
|
|
||||||
.ok_or(ExecutionPayloadError::NoExecutionConnection)?;
|
|
||||||
|
|
||||||
if let Err(e) = execution_layer.verify_payload_block_hash(block_message) {
|
|
||||||
warn!(
|
warn!(
|
||||||
chain.log,
|
chain.log,
|
||||||
"Falling back to slow block hash verification";
|
"Falling back to slow block hash verification";
|
||||||
@ -143,11 +139,8 @@ async fn notify_new_payload<'a, T: BeaconChainTypes>(
|
|||||||
.as_ref()
|
.as_ref()
|
||||||
.ok_or(ExecutionPayloadError::NoExecutionConnection)?;
|
.ok_or(ExecutionPayloadError::NoExecutionConnection)?;
|
||||||
|
|
||||||
let new_payload_request: NewPayloadRequest<T::EthSpec> = block.try_into()?;
|
let execution_block_hash = block.execution_payload()?.block_hash();
|
||||||
let execution_block_hash = new_payload_request.block_hash();
|
let new_payload_response = execution_layer.notify_new_payload(block.try_into()?).await;
|
||||||
let new_payload_response = execution_layer
|
|
||||||
.notify_new_payload(new_payload_request)
|
|
||||||
.await;
|
|
||||||
|
|
||||||
match new_payload_response {
|
match new_payload_response {
|
||||||
Ok(status) => match status {
|
Ok(status) => match status {
|
||||||
|
@ -51,3 +51,5 @@ hash-db = "0.15.2"
|
|||||||
pretty_reqwest_error = { workspace = true }
|
pretty_reqwest_error = { workspace = true }
|
||||||
arc-swap = "1.6.0"
|
arc-swap = "1.6.0"
|
||||||
eth2_network_config = { workspace = true }
|
eth2_network_config = { workspace = true }
|
||||||
|
alloy-rlp = "0.3"
|
||||||
|
alloy-consensus = { git = "https://github.com/alloy-rs/alloy.git", rev = "974d488bab5e21e9f17452a39a4bfa56677367b2" }
|
||||||
|
@ -1,25 +1,23 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
json_structures::JsonWithdrawal,
|
json_structures::JsonWithdrawal,
|
||||||
keccak::{keccak256, KeccakHasher},
|
keccak::{keccak256, KeccakHasher},
|
||||||
metrics, Error, ExecutionLayer,
|
|
||||||
};
|
};
|
||||||
use ethers_core::utils::rlp::RlpStream;
|
use ethers_core::utils::rlp::RlpStream;
|
||||||
use keccak_hash::KECCAK_EMPTY_LIST_RLP;
|
use keccak_hash::KECCAK_EMPTY_LIST_RLP;
|
||||||
use triehash::ordered_trie_root;
|
use triehash::ordered_trie_root;
|
||||||
use types::{
|
use types::{
|
||||||
map_execution_block_header_fields_base, Address, BeaconBlockRef, EthSpec, ExecutionBlockHash,
|
map_execution_block_header_fields_base, Address, EthSpec, ExecutionBlockHash,
|
||||||
ExecutionBlockHeader, ExecutionPayloadRef, Hash256, Hash64, Uint256,
|
ExecutionBlockHeader, ExecutionPayloadRef, Hash256, Hash64, Uint256,
|
||||||
};
|
};
|
||||||
|
|
||||||
impl<T: EthSpec> ExecutionLayer<T> {
|
/// Calculate the block hash of an execution block.
|
||||||
/// Calculate the block hash of an execution block.
|
///
|
||||||
///
|
/// Return `(block_hash, transactions_root)`, where `transactions_root` is the root of the RLP
|
||||||
/// Return `(block_hash, transactions_root)`, where `transactions_root` is the root of the RLP
|
/// transactions.
|
||||||
/// transactions.
|
pub fn calculate_execution_block_hash<T: EthSpec>(
|
||||||
pub fn calculate_execution_block_hash(
|
|
||||||
payload: ExecutionPayloadRef<T>,
|
payload: ExecutionPayloadRef<T>,
|
||||||
parent_beacon_block_root: Hash256,
|
parent_beacon_block_root: Option<Hash256>,
|
||||||
) -> (ExecutionBlockHash, Hash256) {
|
) -> (ExecutionBlockHash, Hash256) {
|
||||||
// Calculate the transactions root.
|
// Calculate the transactions root.
|
||||||
// We're currently using a deprecated Parity library for this. We should move to a
|
// We're currently using a deprecated Parity library for this. We should move to a
|
||||||
// better alternative when one appears, possibly following Reth.
|
// better alternative when one appears, possibly following Reth.
|
||||||
@ -30,9 +28,9 @@ impl<T: EthSpec> ExecutionLayer<T> {
|
|||||||
// Calculate withdrawals root (post-Capella).
|
// Calculate withdrawals root (post-Capella).
|
||||||
let rlp_withdrawals_root = if let Ok(withdrawals) = payload.withdrawals() {
|
let rlp_withdrawals_root = if let Ok(withdrawals) = payload.withdrawals() {
|
||||||
Some(ordered_trie_root::<KeccakHasher, _>(
|
Some(ordered_trie_root::<KeccakHasher, _>(
|
||||||
withdrawals.iter().map(|withdrawal| {
|
withdrawals
|
||||||
rlp_encode_withdrawal(&JsonWithdrawal::from(withdrawal.clone()))
|
.iter()
|
||||||
}),
|
.map(|withdrawal| rlp_encode_withdrawal(&JsonWithdrawal::from(withdrawal.clone()))),
|
||||||
))
|
))
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
@ -41,11 +39,6 @@ impl<T: EthSpec> ExecutionLayer<T> {
|
|||||||
let rlp_blob_gas_used = payload.blob_gas_used().ok();
|
let rlp_blob_gas_used = payload.blob_gas_used().ok();
|
||||||
let rlp_excess_blob_gas = payload.excess_blob_gas().ok();
|
let rlp_excess_blob_gas = payload.excess_blob_gas().ok();
|
||||||
|
|
||||||
// Calculate parent beacon block root (post-Deneb).
|
|
||||||
let rlp_parent_beacon_block_root = rlp_excess_blob_gas
|
|
||||||
.as_ref()
|
|
||||||
.map(|_| parent_beacon_block_root);
|
|
||||||
|
|
||||||
// Construct the block header.
|
// Construct the block header.
|
||||||
let exec_block_header = ExecutionBlockHeader::from_payload(
|
let exec_block_header = ExecutionBlockHeader::from_payload(
|
||||||
payload,
|
payload,
|
||||||
@ -54,7 +47,7 @@ impl<T: EthSpec> ExecutionLayer<T> {
|
|||||||
rlp_withdrawals_root,
|
rlp_withdrawals_root,
|
||||||
rlp_blob_gas_used,
|
rlp_blob_gas_used,
|
||||||
rlp_excess_blob_gas,
|
rlp_excess_blob_gas,
|
||||||
rlp_parent_beacon_block_root,
|
parent_beacon_block_root,
|
||||||
);
|
);
|
||||||
|
|
||||||
// Hash the RLP encoding of the block header.
|
// Hash the RLP encoding of the block header.
|
||||||
@ -63,30 +56,6 @@ impl<T: EthSpec> ExecutionLayer<T> {
|
|||||||
ExecutionBlockHash::from_root(keccak256(&rlp_block_header)),
|
ExecutionBlockHash::from_root(keccak256(&rlp_block_header)),
|
||||||
rlp_transactions_root,
|
rlp_transactions_root,
|
||||||
)
|
)
|
||||||
}
|
|
||||||
|
|
||||||
/// Verify `payload.block_hash` locally within Lighthouse.
|
|
||||||
///
|
|
||||||
/// No remote calls to the execution client will be made, so this is quite a cheap check.
|
|
||||||
pub fn verify_payload_block_hash(&self, block: BeaconBlockRef<T>) -> Result<(), Error> {
|
|
||||||
let payload = block.execution_payload()?.execution_payload_ref();
|
|
||||||
let parent_beacon_block_root = block.parent_root();
|
|
||||||
|
|
||||||
let _timer = metrics::start_timer(&metrics::EXECUTION_LAYER_VERIFY_BLOCK_HASH);
|
|
||||||
|
|
||||||
let (header_hash, rlp_transactions_root) =
|
|
||||||
Self::calculate_execution_block_hash(payload, parent_beacon_block_root);
|
|
||||||
|
|
||||||
if header_hash != payload.block_hash() {
|
|
||||||
return Err(Error::BlockHashMismatch {
|
|
||||||
computed: header_hash,
|
|
||||||
payload: payload.block_hash(),
|
|
||||||
transactions_root: rlp_transactions_root,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// RLP encode a withdrawal.
|
/// RLP encode a withdrawal.
|
||||||
|
@ -17,7 +17,6 @@ pub use json_structures::{JsonWithdrawal, TransitionConfigurationV1};
|
|||||||
use pretty_reqwest_error::PrettyReqwestError;
|
use pretty_reqwest_error::PrettyReqwestError;
|
||||||
use reqwest::StatusCode;
|
use reqwest::StatusCode;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use state_processing::per_block_processing::deneb::kzg_commitment_to_versioned_hash;
|
|
||||||
use std::convert::TryFrom;
|
use std::convert::TryFrom;
|
||||||
use strum::IntoStaticStr;
|
use strum::IntoStaticStr;
|
||||||
use superstruct::superstruct;
|
use superstruct::superstruct;
|
||||||
@ -26,14 +25,16 @@ pub use types::{
|
|||||||
ExecutionPayloadRef, FixedVector, ForkName, Hash256, Transactions, Uint256, VariableList,
|
ExecutionPayloadRef, FixedVector, ForkName, Hash256, Transactions, Uint256, VariableList,
|
||||||
Withdrawal, Withdrawals,
|
Withdrawal, Withdrawals,
|
||||||
};
|
};
|
||||||
use types::{
|
use types::{ExecutionPayloadCapella, ExecutionPayloadDeneb, ExecutionPayloadMerge, KzgProofs};
|
||||||
BeaconStateError, ExecutionPayloadCapella, ExecutionPayloadDeneb, ExecutionPayloadMerge,
|
|
||||||
KzgProofs, VersionedHash,
|
|
||||||
};
|
|
||||||
|
|
||||||
pub mod auth;
|
pub mod auth;
|
||||||
pub mod http;
|
pub mod http;
|
||||||
pub mod json_structures;
|
pub mod json_structures;
|
||||||
|
mod new_payload_request;
|
||||||
|
|
||||||
|
pub use new_payload_request::{
|
||||||
|
NewPayloadRequest, NewPayloadRequestCapella, NewPayloadRequestDeneb, NewPayloadRequestMerge,
|
||||||
|
};
|
||||||
|
|
||||||
pub const LATEST_TAG: &str = "latest";
|
pub const LATEST_TAG: &str = "latest";
|
||||||
|
|
||||||
@ -571,110 +572,6 @@ impl<E: EthSpec> ExecutionPayloadBodyV1<E> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[superstruct(
|
|
||||||
variants(Merge, Capella, Deneb),
|
|
||||||
variant_attributes(derive(Clone, Debug, PartialEq),),
|
|
||||||
map_into(ExecutionPayload),
|
|
||||||
map_ref_into(ExecutionPayloadRef),
|
|
||||||
cast_error(
|
|
||||||
ty = "BeaconStateError",
|
|
||||||
expr = "BeaconStateError::IncorrectStateVariant"
|
|
||||||
),
|
|
||||||
partial_getter_error(
|
|
||||||
ty = "BeaconStateError",
|
|
||||||
expr = "BeaconStateError::IncorrectStateVariant"
|
|
||||||
)
|
|
||||||
)]
|
|
||||||
#[derive(Clone, Debug, PartialEq)]
|
|
||||||
pub struct NewPayloadRequest<E: EthSpec> {
|
|
||||||
#[superstruct(only(Merge), partial_getter(rename = "execution_payload_merge"))]
|
|
||||||
pub execution_payload: ExecutionPayloadMerge<E>,
|
|
||||||
#[superstruct(only(Capella), partial_getter(rename = "execution_payload_capella"))]
|
|
||||||
pub execution_payload: ExecutionPayloadCapella<E>,
|
|
||||||
#[superstruct(only(Deneb), partial_getter(rename = "execution_payload_deneb"))]
|
|
||||||
pub execution_payload: ExecutionPayloadDeneb<E>,
|
|
||||||
#[superstruct(only(Deneb))]
|
|
||||||
pub versioned_hashes: Vec<VersionedHash>,
|
|
||||||
#[superstruct(only(Deneb))]
|
|
||||||
pub parent_beacon_block_root: Hash256,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<E: EthSpec> NewPayloadRequest<E> {
|
|
||||||
pub fn parent_hash(&self) -> ExecutionBlockHash {
|
|
||||||
match self {
|
|
||||||
Self::Merge(payload) => payload.execution_payload.parent_hash,
|
|
||||||
Self::Capella(payload) => payload.execution_payload.parent_hash,
|
|
||||||
Self::Deneb(payload) => payload.execution_payload.parent_hash,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn block_hash(&self) -> ExecutionBlockHash {
|
|
||||||
match self {
|
|
||||||
Self::Merge(payload) => payload.execution_payload.block_hash,
|
|
||||||
Self::Capella(payload) => payload.execution_payload.block_hash,
|
|
||||||
Self::Deneb(payload) => payload.execution_payload.block_hash,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn block_number(&self) -> u64 {
|
|
||||||
match self {
|
|
||||||
Self::Merge(payload) => payload.execution_payload.block_number,
|
|
||||||
Self::Capella(payload) => payload.execution_payload.block_number,
|
|
||||||
Self::Deneb(payload) => payload.execution_payload.block_number,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn into_execution_payload(self) -> ExecutionPayload<E> {
|
|
||||||
map_new_payload_request_into_execution_payload!(self, |request, cons| {
|
|
||||||
cons(request.execution_payload)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a, E: EthSpec> TryFrom<BeaconBlockRef<'a, E>> for NewPayloadRequest<E> {
|
|
||||||
type Error = BeaconStateError;
|
|
||||||
|
|
||||||
fn try_from(block: BeaconBlockRef<'a, E>) -> Result<Self, Self::Error> {
|
|
||||||
match block {
|
|
||||||
BeaconBlockRef::Base(_) | BeaconBlockRef::Altair(_) => {
|
|
||||||
Err(Self::Error::IncorrectStateVariant)
|
|
||||||
}
|
|
||||||
BeaconBlockRef::Merge(block_ref) => Ok(Self::Merge(NewPayloadRequestMerge {
|
|
||||||
execution_payload: block_ref.body.execution_payload.execution_payload.clone(),
|
|
||||||
})),
|
|
||||||
BeaconBlockRef::Capella(block_ref) => Ok(Self::Capella(NewPayloadRequestCapella {
|
|
||||||
execution_payload: block_ref.body.execution_payload.execution_payload.clone(),
|
|
||||||
})),
|
|
||||||
BeaconBlockRef::Deneb(block_ref) => Ok(Self::Deneb(NewPayloadRequestDeneb {
|
|
||||||
execution_payload: block_ref.body.execution_payload.execution_payload.clone(),
|
|
||||||
versioned_hashes: block_ref
|
|
||||||
.body
|
|
||||||
.blob_kzg_commitments
|
|
||||||
.iter()
|
|
||||||
.map(kzg_commitment_to_versioned_hash)
|
|
||||||
.collect(),
|
|
||||||
parent_beacon_block_root: block_ref.parent_root,
|
|
||||||
})),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<E: EthSpec> TryFrom<ExecutionPayload<E>> for NewPayloadRequest<E> {
|
|
||||||
type Error = BeaconStateError;
|
|
||||||
|
|
||||||
fn try_from(payload: ExecutionPayload<E>) -> Result<Self, Self::Error> {
|
|
||||||
match payload {
|
|
||||||
ExecutionPayload::Merge(payload) => Ok(Self::Merge(NewPayloadRequestMerge {
|
|
||||||
execution_payload: payload,
|
|
||||||
})),
|
|
||||||
ExecutionPayload::Capella(payload) => Ok(Self::Capella(NewPayloadRequestCapella {
|
|
||||||
execution_payload: payload,
|
|
||||||
})),
|
|
||||||
ExecutionPayload::Deneb(_) => Err(Self::Error::IncorrectStateVariant),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug)]
|
#[derive(Clone, Copy, Debug)]
|
||||||
pub struct EngineCapabilities {
|
pub struct EngineCapabilities {
|
||||||
pub new_payload_v1: bool,
|
pub new_payload_v1: bool,
|
||||||
|
@ -803,10 +803,10 @@ impl HttpJsonRpc {
|
|||||||
|
|
||||||
pub async fn new_payload_v3<T: EthSpec>(
|
pub async fn new_payload_v3<T: EthSpec>(
|
||||||
&self,
|
&self,
|
||||||
new_payload_request_deneb: NewPayloadRequestDeneb<T>,
|
new_payload_request_deneb: NewPayloadRequestDeneb<'_, T>,
|
||||||
) -> Result<PayloadStatusV1, Error> {
|
) -> Result<PayloadStatusV1, Error> {
|
||||||
let params = json!([
|
let params = json!([
|
||||||
JsonExecutionPayload::V3(new_payload_request_deneb.execution_payload.into()),
|
JsonExecutionPayload::V3(new_payload_request_deneb.execution_payload.clone().into()),
|
||||||
new_payload_request_deneb.versioned_hashes,
|
new_payload_request_deneb.versioned_hashes,
|
||||||
new_payload_request_deneb.parent_beacon_block_root,
|
new_payload_request_deneb.parent_beacon_block_root,
|
||||||
]);
|
]);
|
||||||
@ -1079,7 +1079,7 @@ impl HttpJsonRpc {
|
|||||||
// new_payload that the execution engine supports
|
// new_payload that the execution engine supports
|
||||||
pub async fn new_payload<T: EthSpec>(
|
pub async fn new_payload<T: EthSpec>(
|
||||||
&self,
|
&self,
|
||||||
new_payload_request: NewPayloadRequest<T>,
|
new_payload_request: NewPayloadRequest<'_, T>,
|
||||||
) -> Result<PayloadStatusV1, Error> {
|
) -> Result<PayloadStatusV1, Error> {
|
||||||
let engine_capabilities = self.get_engine_capabilities(None).await?;
|
let engine_capabilities = self.get_engine_capabilities(None).await?;
|
||||||
match new_payload_request {
|
match new_payload_request {
|
||||||
|
@ -0,0 +1,332 @@
|
|||||||
|
use crate::{block_hash::calculate_execution_block_hash, metrics, Error};
|
||||||
|
|
||||||
|
use crate::versioned_hashes::verify_versioned_hashes;
|
||||||
|
use state_processing::per_block_processing::deneb::kzg_commitment_to_versioned_hash;
|
||||||
|
use superstruct::superstruct;
|
||||||
|
use types::{
|
||||||
|
BeaconBlockRef, BeaconStateError, EthSpec, ExecutionBlockHash, ExecutionPayload,
|
||||||
|
ExecutionPayloadRef, Hash256, VersionedHash,
|
||||||
|
};
|
||||||
|
use types::{ExecutionPayloadCapella, ExecutionPayloadDeneb, ExecutionPayloadMerge};
|
||||||
|
|
||||||
|
#[superstruct(
|
||||||
|
variants(Merge, Capella, Deneb),
|
||||||
|
variant_attributes(derive(Clone, Debug, PartialEq),),
|
||||||
|
map_into(ExecutionPayload),
|
||||||
|
map_ref_into(ExecutionPayloadRef),
|
||||||
|
cast_error(
|
||||||
|
ty = "BeaconStateError",
|
||||||
|
expr = "BeaconStateError::IncorrectStateVariant"
|
||||||
|
),
|
||||||
|
partial_getter_error(
|
||||||
|
ty = "BeaconStateError",
|
||||||
|
expr = "BeaconStateError::IncorrectStateVariant"
|
||||||
|
)
|
||||||
|
)]
|
||||||
|
#[derive(Clone, Debug, PartialEq)]
|
||||||
|
pub struct NewPayloadRequest<'block, E: EthSpec> {
|
||||||
|
#[superstruct(only(Merge), partial_getter(rename = "execution_payload_merge"))]
|
||||||
|
pub execution_payload: &'block ExecutionPayloadMerge<E>,
|
||||||
|
#[superstruct(only(Capella), partial_getter(rename = "execution_payload_capella"))]
|
||||||
|
pub execution_payload: &'block ExecutionPayloadCapella<E>,
|
||||||
|
#[superstruct(only(Deneb), partial_getter(rename = "execution_payload_deneb"))]
|
||||||
|
pub execution_payload: &'block ExecutionPayloadDeneb<E>,
|
||||||
|
#[superstruct(only(Deneb))]
|
||||||
|
pub versioned_hashes: Vec<VersionedHash>,
|
||||||
|
#[superstruct(only(Deneb))]
|
||||||
|
pub parent_beacon_block_root: Hash256,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'block, E: EthSpec> NewPayloadRequest<'block, E> {
|
||||||
|
pub fn parent_hash(&self) -> ExecutionBlockHash {
|
||||||
|
match self {
|
||||||
|
Self::Merge(payload) => payload.execution_payload.parent_hash,
|
||||||
|
Self::Capella(payload) => payload.execution_payload.parent_hash,
|
||||||
|
Self::Deneb(payload) => payload.execution_payload.parent_hash,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn block_hash(&self) -> ExecutionBlockHash {
|
||||||
|
match self {
|
||||||
|
Self::Merge(payload) => payload.execution_payload.block_hash,
|
||||||
|
Self::Capella(payload) => payload.execution_payload.block_hash,
|
||||||
|
Self::Deneb(payload) => payload.execution_payload.block_hash,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn block_number(&self) -> u64 {
|
||||||
|
match self {
|
||||||
|
Self::Merge(payload) => payload.execution_payload.block_number,
|
||||||
|
Self::Capella(payload) => payload.execution_payload.block_number,
|
||||||
|
Self::Deneb(payload) => payload.execution_payload.block_number,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn execution_payload_ref(&self) -> ExecutionPayloadRef<'block, E> {
|
||||||
|
match self {
|
||||||
|
Self::Merge(request) => ExecutionPayloadRef::Merge(request.execution_payload),
|
||||||
|
Self::Capella(request) => ExecutionPayloadRef::Capella(request.execution_payload),
|
||||||
|
Self::Deneb(request) => ExecutionPayloadRef::Deneb(request.execution_payload),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn into_execution_payload(self) -> ExecutionPayload<E> {
|
||||||
|
match self {
|
||||||
|
Self::Merge(request) => ExecutionPayload::Merge(request.execution_payload.clone()),
|
||||||
|
Self::Capella(request) => ExecutionPayload::Capella(request.execution_payload.clone()),
|
||||||
|
Self::Deneb(request) => ExecutionPayload::Deneb(request.execution_payload.clone()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Performs the required verifications of the payload when the chain is optimistically syncing.
|
||||||
|
///
|
||||||
|
/// ## Specification
|
||||||
|
///
|
||||||
|
/// Performs the verifications in the `verify_and_notify_new_payload` function:
|
||||||
|
///
|
||||||
|
/// https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.2/specs/deneb/beacon-chain.md#modified-verify_and_notify_new_payload
|
||||||
|
pub fn perform_optimistic_sync_verifications(&self) -> Result<(), Error> {
|
||||||
|
self.verfiy_payload_block_hash()?;
|
||||||
|
self.verify_versioned_hashes()?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Verify the block hash is consistent locally within Lighthouse.
|
||||||
|
///
|
||||||
|
/// ## Specification
|
||||||
|
///
|
||||||
|
/// Equivalent to `is_valid_block_hash` in the spec:
|
||||||
|
/// https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.2/specs/deneb/beacon-chain.md#is_valid_block_hash
|
||||||
|
pub fn verfiy_payload_block_hash(&self) -> Result<(), Error> {
|
||||||
|
let payload = self.execution_payload_ref();
|
||||||
|
let parent_beacon_block_root = self.parent_beacon_block_root().ok().cloned();
|
||||||
|
|
||||||
|
let _timer = metrics::start_timer(&metrics::EXECUTION_LAYER_VERIFY_BLOCK_HASH);
|
||||||
|
|
||||||
|
let (header_hash, rlp_transactions_root) =
|
||||||
|
calculate_execution_block_hash(payload, parent_beacon_block_root);
|
||||||
|
|
||||||
|
if header_hash != self.block_hash() {
|
||||||
|
return Err(Error::BlockHashMismatch {
|
||||||
|
computed: header_hash,
|
||||||
|
payload: payload.block_hash(),
|
||||||
|
transactions_root: rlp_transactions_root,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Verify the versioned hashes computed by the blob transactions match the versioned hashes computed from the commitments.
|
||||||
|
///
|
||||||
|
/// ## Specification
|
||||||
|
///
|
||||||
|
/// Equivalent to `is_valid_versioned_hashes` in the spec:
|
||||||
|
/// https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.2/specs/deneb/beacon-chain.md#is_valid_versioned_hashes
|
||||||
|
pub fn verify_versioned_hashes(&self) -> Result<(), Error> {
|
||||||
|
if let Ok(versioned_hashes) = self.versioned_hashes() {
|
||||||
|
verify_versioned_hashes(self.execution_payload_ref(), versioned_hashes)
|
||||||
|
.map_err(Error::VerifyingVersionedHashes)?;
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, E: EthSpec> TryFrom<BeaconBlockRef<'a, E>> for NewPayloadRequest<'a, E> {
|
||||||
|
type Error = BeaconStateError;
|
||||||
|
|
||||||
|
fn try_from(block: BeaconBlockRef<'a, E>) -> Result<Self, Self::Error> {
|
||||||
|
match block {
|
||||||
|
BeaconBlockRef::Base(_) | BeaconBlockRef::Altair(_) => {
|
||||||
|
Err(Self::Error::IncorrectStateVariant)
|
||||||
|
}
|
||||||
|
BeaconBlockRef::Merge(block_ref) => Ok(Self::Merge(NewPayloadRequestMerge {
|
||||||
|
execution_payload: &block_ref.body.execution_payload.execution_payload,
|
||||||
|
})),
|
||||||
|
BeaconBlockRef::Capella(block_ref) => Ok(Self::Capella(NewPayloadRequestCapella {
|
||||||
|
execution_payload: &block_ref.body.execution_payload.execution_payload,
|
||||||
|
})),
|
||||||
|
BeaconBlockRef::Deneb(block_ref) => Ok(Self::Deneb(NewPayloadRequestDeneb {
|
||||||
|
execution_payload: &block_ref.body.execution_payload.execution_payload,
|
||||||
|
versioned_hashes: block_ref
|
||||||
|
.body
|
||||||
|
.blob_kzg_commitments
|
||||||
|
.iter()
|
||||||
|
.map(kzg_commitment_to_versioned_hash)
|
||||||
|
.collect(),
|
||||||
|
parent_beacon_block_root: block_ref.parent_root,
|
||||||
|
})),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, E: EthSpec> TryFrom<ExecutionPayloadRef<'a, E>> for NewPayloadRequest<'a, E> {
|
||||||
|
type Error = BeaconStateError;
|
||||||
|
|
||||||
|
fn try_from(payload: ExecutionPayloadRef<'a, E>) -> Result<Self, Self::Error> {
|
||||||
|
match payload {
|
||||||
|
ExecutionPayloadRef::Merge(payload) => Ok(Self::Merge(NewPayloadRequestMerge {
|
||||||
|
execution_payload: payload,
|
||||||
|
})),
|
||||||
|
ExecutionPayloadRef::Capella(payload) => Ok(Self::Capella(NewPayloadRequestCapella {
|
||||||
|
execution_payload: payload,
|
||||||
|
})),
|
||||||
|
ExecutionPayloadRef::Deneb(_) => Err(Self::Error::IncorrectStateVariant),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod test {
|
||||||
|
use crate::versioned_hashes::Error as VersionedHashError;
|
||||||
|
use crate::{Error, NewPayloadRequest};
|
||||||
|
use state_processing::per_block_processing::deneb::kzg_commitment_to_versioned_hash;
|
||||||
|
use types::{BeaconBlock, ExecPayload, ExecutionBlockHash, Hash256, MainnetEthSpec};
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_optimistic_sync_verifications_valid_block() {
|
||||||
|
let beacon_block = get_valid_beacon_block();
|
||||||
|
let new_payload_request = NewPayloadRequest::try_from(beacon_block.to_ref())
|
||||||
|
.expect("should create new payload request");
|
||||||
|
|
||||||
|
assert!(
|
||||||
|
new_payload_request
|
||||||
|
.perform_optimistic_sync_verifications()
|
||||||
|
.is_ok(),
|
||||||
|
"validations should pass"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_optimistic_sync_verifications_bad_block_hash() {
|
||||||
|
let mut beacon_block = get_valid_beacon_block();
|
||||||
|
let correct_block_hash = beacon_block
|
||||||
|
.body()
|
||||||
|
.execution_payload()
|
||||||
|
.expect("should get payload")
|
||||||
|
.block_hash();
|
||||||
|
let invalid_block_hash = ExecutionBlockHash(Hash256::repeat_byte(0x42));
|
||||||
|
|
||||||
|
// now mutate the block hash
|
||||||
|
beacon_block
|
||||||
|
.body_mut()
|
||||||
|
.execution_payload_deneb_mut()
|
||||||
|
.expect("should get payload")
|
||||||
|
.execution_payload
|
||||||
|
.block_hash = invalid_block_hash;
|
||||||
|
|
||||||
|
let new_payload_request = NewPayloadRequest::try_from(beacon_block.to_ref())
|
||||||
|
.expect("should create new payload request");
|
||||||
|
let verification_result = new_payload_request.perform_optimistic_sync_verifications();
|
||||||
|
println!("verification_result: {:?}", verification_result);
|
||||||
|
let got_expected_result = match verification_result {
|
||||||
|
Err(Error::BlockHashMismatch {
|
||||||
|
computed, payload, ..
|
||||||
|
}) => computed == correct_block_hash && payload == invalid_block_hash,
|
||||||
|
_ => false,
|
||||||
|
};
|
||||||
|
assert!(got_expected_result, "should return expected error");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_optimistic_sync_verifications_bad_versioned_hashes() {
|
||||||
|
let mut beacon_block = get_valid_beacon_block();
|
||||||
|
|
||||||
|
let mut commitments: Vec<_> = beacon_block
|
||||||
|
.body()
|
||||||
|
.blob_kzg_commitments()
|
||||||
|
.expect("should get commitments")
|
||||||
|
.clone()
|
||||||
|
.into();
|
||||||
|
|
||||||
|
let correct_versioned_hash = kzg_commitment_to_versioned_hash(
|
||||||
|
commitments.last().expect("should get last commitment"),
|
||||||
|
);
|
||||||
|
|
||||||
|
// mutate the last commitment
|
||||||
|
commitments
|
||||||
|
.last_mut()
|
||||||
|
.expect("should get last commitment")
|
||||||
|
.0[0] = 0x42;
|
||||||
|
|
||||||
|
// calculate versioned hash from mutated commitment
|
||||||
|
let bad_versioned_hash = kzg_commitment_to_versioned_hash(
|
||||||
|
commitments.last().expect("should get last commitment"),
|
||||||
|
);
|
||||||
|
|
||||||
|
*beacon_block
|
||||||
|
.body_mut()
|
||||||
|
.blob_kzg_commitments_mut()
|
||||||
|
.expect("should get commitments") = commitments.into();
|
||||||
|
|
||||||
|
let new_payload_request = NewPayloadRequest::try_from(beacon_block.to_ref())
|
||||||
|
.expect("should create new payload request");
|
||||||
|
let verification_result = new_payload_request.perform_optimistic_sync_verifications();
|
||||||
|
println!("verification_result: {:?}", verification_result);
|
||||||
|
|
||||||
|
let got_expected_result = match verification_result {
|
||||||
|
Err(Error::VerifyingVersionedHashes(VersionedHashError::VersionHashMismatch {
|
||||||
|
expected,
|
||||||
|
found,
|
||||||
|
})) => expected == bad_versioned_hash && found == correct_versioned_hash,
|
||||||
|
_ => false,
|
||||||
|
};
|
||||||
|
assert!(got_expected_result, "should return expected error");
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_valid_beacon_block() -> BeaconBlock<MainnetEthSpec> {
|
||||||
|
BeaconBlock::Deneb(serde_json::from_str(r#"{
|
||||||
|
"slot": "88160",
|
||||||
|
"proposer_index": "583",
|
||||||
|
"parent_root": "0x60770cd86a497ca3aa2e91f1687aa3ebafac87af52c30a920b5f40bd9e930eb6",
|
||||||
|
"state_root": "0x4a0e0abbcbcf576f2cb7387c4289ab13b8a128e32127642f056143d6164941a6",
|
||||||
|
"body": {
|
||||||
|
"randao_reveal": "0xb5253d5739496abc4f67c7c92e39e46cca452c2fdfc5275e3e0426a012aa62df82f47f7dece348e28db4bb212f0e793d187120bbd47b8031ed79344116eb4128f0ce0b05ba18cd615bb13966c1bd7d89e23cc769c8e4d8e4a63755f623ac3bed",
|
||||||
|
"eth1_data": {
|
||||||
|
"deposit_root": "0xe4785ac914d8673797f886e3151ce2647f81ae070c7ddb6845e65fd1c47d1222",
|
||||||
|
"deposit_count": "1181",
|
||||||
|
"block_hash": "0x010671bdfbfce6b0071984a06a7ded6deef13b4f8fdbae402c606a7a0c8780d1"
|
||||||
|
},
|
||||||
|
"graffiti": "0x6c6f6465737461722f6765746800000000000000000000000000000000000000",
|
||||||
|
"proposer_slashings": [],
|
||||||
|
"attester_slashings": [],
|
||||||
|
"attestations": [],
|
||||||
|
"deposits": [],
|
||||||
|
"voluntary_exits": [],
|
||||||
|
"sync_aggregate": {
|
||||||
|
"sync_committee_bits": "0xfebffffffebfff7fff7f7fffbbefffff6affffffffbfffffefffebfffdbf77fff7fd77ffffefffdff7ffffeffffffe7e5ffffffdefffff7ffbffff7fffffffff",
|
||||||
|
"sync_committee_signature": "0x91939b5baf2a6f52d405b6dd396f5346ec435eca7d25912c91cc6a2f7030d870d68bebe4f2b21872a06929ff4cf3e5e9191053cb43eb24ebe34b9a75fb88a3acd06baf329c87f68bd664b49891260c698d7bca0f5365870b5b2b3a76f582156c"
|
||||||
|
},
|
||||||
|
"execution_payload": {
|
||||||
|
"parent_hash": "0xa6f3ed782a992f79ad38da2af91b3e8923c71b801c50bc9033bb35a2e1da885f",
|
||||||
|
"fee_recipient": "0xf97e180c050e5ab072211ad2c213eb5aee4df134",
|
||||||
|
"state_root": "0x3bfd1a7f309ed35048c349a8daf01815bdc09a6d5df86ea77d1056f248ba2017",
|
||||||
|
"receipts_root": "0xcb5b8ffea57cd0fa87194d49bc8bb7fad08c93c9934b886489503c328d15fd36",
|
||||||
|
"logs_bloom": "0x002000000000000000000000800000000000000000001040000000000000000000000001000000000000000000000000000000000000100000000020000c0800000000000000008000000008000000200000800000000000000000000000000000000000000000008000000000008000000000000000000002000010000000000000000000000000000000000000000000000000000000080000004000000000800000000000000000000100000000000000000000000000000000000800000000000102000000000000000000000000000000080000001000000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||||
|
"prev_randao": "0xb2693020177d99ffbd4c267023be172d759e7306ff51b0e7d677d3148fbd7f1d",
|
||||||
|
"block_number": "74807",
|
||||||
|
"gas_limit": "30000000",
|
||||||
|
"gas_used": "128393",
|
||||||
|
"timestamp": "1697039520",
|
||||||
|
"extra_data": "0xd883010d03846765746888676f312e32312e31856c696e7578",
|
||||||
|
"base_fee_per_gas": "7",
|
||||||
|
"block_hash": "0xc64f3a43c64aeb98518a237f6279fa03095b9f95ca673c860ad7f16fb9340062",
|
||||||
|
"transactions": [
|
||||||
|
"0x02f9017a8501a1f0ff4382317585012a05f2008512a05f2000830249f094c1b0bc605e2c808aa0867bfc98e51a1fe3e9867f80b901040cc7326300000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000036e534e16b8920d000000000000000000000000fb3e9c7cb92443931ee6b5b9728598d4eb9618c1000000000000000000000000fc7360b3b28cf4204268a8354dbec60720d155d2000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000009a054a063f0fe7b9c68de8df91aaa5e96c15ab540000000000000000000000000c8d41b8fcc066cdabaf074d78e5153e8ce018a9c080a07dd9be0d014ffcd5b6883d0917c66b74ba51f0d976c8fc5674af192af6fa9450a02dad2c660974c125f5f22b1e6e8862a292e08cc2b4cafda35af650ee62868a43",
|
||||||
|
"0x03f8db8501a1f0ff430d84773594008504a817c8008252089454e594b6de0aa4b0188cd1549dd7ba715a455d078080c08504a817c800f863a001253ce00f525e3495cffa0b865eadb90a4c5ee812185cc796af74b6ec0a5dd7a0010720372a4d7dcab84413ed0cfc164fb91fb6ef1562ec2f7a82e912a1d9e129a0015a73e97950397896ed2c47dcab7c0360220bcfb413a8f210a7b6e6264e698880a04402cb0f13c17ef41dca106b1e1520c7aadcbe62984d81171e29914f587d67c1a02db62a8edb581917958e4a3884e7eececbaec114c5ee496e238033e896f997ac"
|
||||||
|
],
|
||||||
|
"withdrawals": [],
|
||||||
|
"blob_gas_used": "393216",
|
||||||
|
"excess_blob_gas": "58720256"
|
||||||
|
},
|
||||||
|
"bls_to_execution_changes": [],
|
||||||
|
"blob_kzg_commitments": [
|
||||||
|
"0xa7accb7a25224a8c2e0cee9cd569fc1798665bfbfe780e08945fa9098ec61da4061f5b04e750a88d3340a801850a54fa",
|
||||||
|
"0xac7b47f99836510ae9076dc5f5da1f370679dea1d47073307a14cbb125cdc7822ae619637135777cb40e13d897fd00a7",
|
||||||
|
"0x997794110b9655833a88ad5a4ec40a3dc7964877bfbeb04ca1abe1d51bdc43e20e4c5757028896d298d7da954a6f14a1"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}"#).expect("should decode"))
|
||||||
|
}
|
||||||
|
}
|
@ -61,6 +61,7 @@ mod metrics;
|
|||||||
pub mod payload_cache;
|
pub mod payload_cache;
|
||||||
mod payload_status;
|
mod payload_status;
|
||||||
pub mod test_utils;
|
pub mod test_utils;
|
||||||
|
mod versioned_hashes;
|
||||||
|
|
||||||
/// Indicates the default jwt authenticated execution endpoint.
|
/// Indicates the default jwt authenticated execution endpoint.
|
||||||
pub const DEFAULT_EXECUTION_ENDPOINT: &str = "http://localhost:8551/";
|
pub const DEFAULT_EXECUTION_ENDPOINT: &str = "http://localhost:8551/";
|
||||||
@ -141,6 +142,7 @@ pub enum Error {
|
|||||||
InvalidBlobConversion(String),
|
InvalidBlobConversion(String),
|
||||||
BeaconStateError(BeaconStateError),
|
BeaconStateError(BeaconStateError),
|
||||||
PayloadTypeMismatch,
|
PayloadTypeMismatch,
|
||||||
|
VerifyingVersionedHashes(versioned_hashes::Error),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<BeaconStateError> for Error {
|
impl From<BeaconStateError> for Error {
|
||||||
@ -1321,7 +1323,7 @@ impl<T: EthSpec> ExecutionLayer<T> {
|
|||||||
/// Maps to the `engine_newPayload` JSON-RPC call.
|
/// Maps to the `engine_newPayload` JSON-RPC call.
|
||||||
pub async fn notify_new_payload(
|
pub async fn notify_new_payload(
|
||||||
&self,
|
&self,
|
||||||
new_payload_request: NewPayloadRequest<T>,
|
new_payload_request: NewPayloadRequest<'_, T>,
|
||||||
) -> Result<PayloadStatus, Error> {
|
) -> Result<PayloadStatus, Error> {
|
||||||
let _timer = metrics::start_timer_vec(
|
let _timer = metrics::start_timer_vec(
|
||||||
&metrics::EXECUTION_LAYER_REQUEST_TIMES,
|
&metrics::EXECUTION_LAYER_REQUEST_TIMES,
|
||||||
|
@ -699,7 +699,7 @@ pub fn generate_blobs<E: EthSpec>(
|
|||||||
Ok((bundle, transactions.into()))
|
Ok((bundle, transactions.into()))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn static_valid_tx<T: EthSpec>() -> Result<Transaction<T::MaxBytesPerTransaction>, String> {
|
pub fn static_valid_tx<T: EthSpec>() -> Result<Transaction<T::MaxBytesPerTransaction>, String> {
|
||||||
// This is a real transaction hex encoded, but we don't care about the contents of the transaction.
|
// This is a real transaction hex encoded, but we don't care about the contents of the transaction.
|
||||||
let transaction: EthersTransaction = serde_json::from_str(
|
let transaction: EthersTransaction = serde_json::from_str(
|
||||||
r#"{
|
r#"{
|
||||||
|
@ -244,7 +244,7 @@ impl<T: EthSpec> MockExecutionLayer<T> {
|
|||||||
// TODO: again consider forks
|
// TODO: again consider forks
|
||||||
let status = self
|
let status = self
|
||||||
.el
|
.el
|
||||||
.notify_new_payload(payload.try_into().unwrap())
|
.notify_new_payload(payload.to_ref().try_into().unwrap())
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
assert_eq!(status, PayloadStatus::Valid);
|
assert_eq!(status, PayloadStatus::Valid);
|
||||||
|
@ -25,8 +25,8 @@ use warp::{http::StatusCode, Filter, Rejection};
|
|||||||
|
|
||||||
use crate::EngineCapabilities;
|
use crate::EngineCapabilities;
|
||||||
pub use execution_block_generator::{
|
pub use execution_block_generator::{
|
||||||
generate_blobs, generate_genesis_block, generate_genesis_header, generate_pow_block, Block,
|
generate_blobs, generate_genesis_block, generate_genesis_header, generate_pow_block,
|
||||||
ExecutionBlockGenerator,
|
static_valid_tx, Block, ExecutionBlockGenerator,
|
||||||
};
|
};
|
||||||
pub use hook::Hook;
|
pub use hook::Hook;
|
||||||
pub use mock_builder::{MockBuilder, Operation};
|
pub use mock_builder::{MockBuilder, Operation};
|
||||||
|
135
beacon_node/execution_layer/src/versioned_hashes.rs
Normal file
135
beacon_node/execution_layer/src/versioned_hashes.rs
Normal file
@ -0,0 +1,135 @@
|
|||||||
|
extern crate alloy_consensus;
|
||||||
|
extern crate alloy_rlp;
|
||||||
|
use alloy_consensus::TxEnvelope;
|
||||||
|
use alloy_rlp::Decodable;
|
||||||
|
use types::{EthSpec, ExecutionPayloadRef, Hash256, Unsigned, VersionedHash};
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum Error {
|
||||||
|
DecodingTransaction(String),
|
||||||
|
LengthMismatch { expected: usize, found: usize },
|
||||||
|
VersionHashMismatch { expected: Hash256, found: Hash256 },
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn verify_versioned_hashes<E: EthSpec>(
|
||||||
|
execution_payload: ExecutionPayloadRef<E>,
|
||||||
|
expected_versioned_hashes: &[VersionedHash],
|
||||||
|
) -> Result<(), Error> {
|
||||||
|
let versioned_hashes =
|
||||||
|
extract_versioned_hashes_from_transactions::<E>(execution_payload.transactions())?;
|
||||||
|
if versioned_hashes.len() != expected_versioned_hashes.len() {
|
||||||
|
return Err(Error::LengthMismatch {
|
||||||
|
expected: expected_versioned_hashes.len(),
|
||||||
|
found: versioned_hashes.len(),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
for (found, expected) in versioned_hashes
|
||||||
|
.iter()
|
||||||
|
.zip(expected_versioned_hashes.iter())
|
||||||
|
{
|
||||||
|
if found != expected {
|
||||||
|
return Err(Error::VersionHashMismatch {
|
||||||
|
expected: *expected,
|
||||||
|
found: *found,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn extract_versioned_hashes_from_transactions<E: EthSpec>(
|
||||||
|
transactions: &types::Transactions<E>,
|
||||||
|
) -> Result<Vec<VersionedHash>, Error> {
|
||||||
|
let mut versioned_hashes = Vec::new();
|
||||||
|
|
||||||
|
for tx in transactions {
|
||||||
|
match beacon_tx_to_tx_envelope(tx)? {
|
||||||
|
TxEnvelope::Eip4844(signed_tx_eip4844) => {
|
||||||
|
versioned_hashes.extend(
|
||||||
|
signed_tx_eip4844
|
||||||
|
.tx()
|
||||||
|
.blob_versioned_hashes
|
||||||
|
.iter()
|
||||||
|
.map(|fb| Hash256::from(fb.0)),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
// enumerating all variants explicitly to make pattern irrefutable
|
||||||
|
// in case new types are added in the future which also have blobs
|
||||||
|
TxEnvelope::Legacy(_)
|
||||||
|
| TxEnvelope::TaggedLegacy(_)
|
||||||
|
| TxEnvelope::Eip2930(_)
|
||||||
|
| TxEnvelope::Eip1559(_) => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(versioned_hashes)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn beacon_tx_to_tx_envelope<N: Unsigned>(
|
||||||
|
tx: &types::Transaction<N>,
|
||||||
|
) -> Result<TxEnvelope, Error> {
|
||||||
|
let tx_bytes = Vec::from(tx.clone());
|
||||||
|
TxEnvelope::decode(&mut tx_bytes.as_slice())
|
||||||
|
.map_err(|e| Error::DecodingTransaction(e.to_string()))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod test {
|
||||||
|
use super::*;
|
||||||
|
use crate::test_utils::static_valid_tx;
|
||||||
|
use alloy_consensus::{TxKind, TxLegacy};
|
||||||
|
|
||||||
|
type E = types::MainnetEthSpec;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_decode_static_transaction() {
|
||||||
|
let valid_tx = static_valid_tx::<E>().expect("should give me known valid transaction");
|
||||||
|
let tx_envelope = beacon_tx_to_tx_envelope(&valid_tx).expect("should decode tx");
|
||||||
|
let TxEnvelope::Legacy(signed_tx) = tx_envelope else {
|
||||||
|
panic!("should decode to legacy transaction");
|
||||||
|
};
|
||||||
|
|
||||||
|
assert!(matches!(
|
||||||
|
signed_tx.tx(),
|
||||||
|
TxLegacy {
|
||||||
|
chain_id: Some(0x01),
|
||||||
|
nonce: 0x15,
|
||||||
|
gas_price: 0x4a817c800,
|
||||||
|
to: TxKind::Call(..),
|
||||||
|
..
|
||||||
|
}
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_extract_versioned_hashes() {
|
||||||
|
use serde::Deserialize;
|
||||||
|
|
||||||
|
#[derive(Deserialize)]
|
||||||
|
#[serde(transparent)]
|
||||||
|
struct TestTransactions<E: EthSpec>(
|
||||||
|
#[serde(with = "ssz_types::serde_utils::list_of_hex_var_list")] types::Transactions<E>,
|
||||||
|
);
|
||||||
|
|
||||||
|
let TestTransactions(raw_transactions): TestTransactions<E> = serde_json::from_str(r#"[
|
||||||
|
"0x03f901388501a1f0ff430f843b9aca00843b9aca0082520894e7249813d8ccf6fa95a2203f46a64166073d58878080c002f8c6a0012e98362c814f1724262c0d211a1463418a5f6382a8d457b37a2698afbe7b5ea00100ef985761395dfa8ed5ce91f3f2180b612401909e4cb8f33b90c8a454d9baa0013d45411623b90d90f916e4025ada74b453dd4ca093c017c838367c9de0f801a001753e2af0b1e70e7ef80541355b2a035cc9b2c177418bb2a4402a9b346cf84da0011789b520a8068094a92aa0b04db8d8ef1c6c9818947c5210821732b8744049a0011c4c4f95597305daa5f62bf5f690e37fa11f5de05a95d05cac4e2119e394db80a0ccd86a742af0e042d08cbb35d910ddc24bbc6538f9e53be6620d4b6e1bb77662a01a8bacbc614940ac2f5c23ffc00a122c9f085046883de65c88ab0edb859acb99",
|
||||||
|
"0x02f9017a8501a1f0ff4382363485012a05f2008512a05f2000830249f094c1b0bc605e2c808aa0867bfc98e51a1fe3e9867f80b901040cc7326300000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000009445a285baa43e00000000000000000000000000c500931f24edb821cef6e28f7adb33b38578c82000000000000000000000000fc7360b3b28cf4204268a8354dbec60720d155d2000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000009a054a063f0fe7b9c68de8df91aaa5e96c15ab540000000000000000000000000c8d41b8fcc066cdabaf074d78e5153e8ce018a9c080a008e14475c1173cd9f5740c24c08b793f9e16c36c08fa73769db95050e31e3396a019767dcdda26c4a774ca28c9df15d0c20e43bd07bd33ee0f84d6096cb5a1ebed"
|
||||||
|
]"#).expect("should get raw transactions");
|
||||||
|
let expected_versioned_hashes = vec![
|
||||||
|
"0x012e98362c814f1724262c0d211a1463418a5f6382a8d457b37a2698afbe7b5e",
|
||||||
|
"0x0100ef985761395dfa8ed5ce91f3f2180b612401909e4cb8f33b90c8a454d9ba",
|
||||||
|
"0x013d45411623b90d90f916e4025ada74b453dd4ca093c017c838367c9de0f801",
|
||||||
|
"0x01753e2af0b1e70e7ef80541355b2a035cc9b2c177418bb2a4402a9b346cf84d",
|
||||||
|
"0x011789b520a8068094a92aa0b04db8d8ef1c6c9818947c5210821732b8744049",
|
||||||
|
"0x011c4c4f95597305daa5f62bf5f690e37fa11f5de05a95d05cac4e2119e394db",
|
||||||
|
]
|
||||||
|
.into_iter()
|
||||||
|
.map(|tx| Hash256::from_slice(&hex::decode(&tx[2..]).expect("should decode hex")))
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
|
let versioned_hashes = extract_versioned_hashes_from_transactions::<E>(&raw_transactions)
|
||||||
|
.expect("should get versioned hashes");
|
||||||
|
assert_eq!(versioned_hashes, expected_versioned_hashes);
|
||||||
|
}
|
||||||
|
}
|
@ -1,7 +1,7 @@
|
|||||||
# `lcli` requires the full project to be in scope, so this should be built either:
|
# `lcli` requires the full project to be in scope, so this should be built either:
|
||||||
# - from the `lighthouse` dir with the command: `docker build -f ./lcli/Dockerflie .`
|
# - from the `lighthouse` dir with the command: `docker build -f ./lcli/Dockerflie .`
|
||||||
# - from the current directory with the command: `docker build -f ./Dockerfile ../`
|
# - from the current directory with the command: `docker build -f ./Dockerfile ../`
|
||||||
FROM rust:1.73.0-bullseye AS builder
|
FROM rust:1.75.0-bullseye AS builder
|
||||||
RUN apt-get update && apt-get -y upgrade && apt-get install -y cmake libclang-dev
|
RUN apt-get update && apt-get -y upgrade && apt-get install -y cmake libclang-dev
|
||||||
COPY . lighthouse
|
COPY . lighthouse
|
||||||
ARG FEATURES
|
ARG FEATURES
|
||||||
|
@ -4,7 +4,7 @@ version = "4.6.0"
|
|||||||
authors = ["Sigma Prime <contact@sigmaprime.io>"]
|
authors = ["Sigma Prime <contact@sigmaprime.io>"]
|
||||||
edition = { workspace = true }
|
edition = { workspace = true }
|
||||||
autotests = false
|
autotests = false
|
||||||
rust-version = "1.73.0"
|
rust-version = "1.75.0"
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = ["slasher-lmdb"]
|
default = ["slasher-lmdb"]
|
||||||
|
@ -381,7 +381,7 @@ impl<E: GenericExecutionEngine> TestRig<E> {
|
|||||||
let status = self
|
let status = self
|
||||||
.ee_a
|
.ee_a
|
||||||
.execution_layer
|
.execution_layer
|
||||||
.notify_new_payload(valid_payload.clone().try_into().unwrap())
|
.notify_new_payload(valid_payload.to_ref().try_into().unwrap())
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
assert_eq!(status, PayloadStatus::Valid);
|
assert_eq!(status, PayloadStatus::Valid);
|
||||||
@ -435,7 +435,7 @@ impl<E: GenericExecutionEngine> TestRig<E> {
|
|||||||
let status = self
|
let status = self
|
||||||
.ee_a
|
.ee_a
|
||||||
.execution_layer
|
.execution_layer
|
||||||
.notify_new_payload(invalid_payload.try_into().unwrap())
|
.notify_new_payload(invalid_payload.to_ref().try_into().unwrap())
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
assert!(matches!(
|
assert!(matches!(
|
||||||
@ -507,7 +507,7 @@ impl<E: GenericExecutionEngine> TestRig<E> {
|
|||||||
let status = self
|
let status = self
|
||||||
.ee_a
|
.ee_a
|
||||||
.execution_layer
|
.execution_layer
|
||||||
.notify_new_payload(second_payload.clone().try_into().unwrap())
|
.notify_new_payload(second_payload.to_ref().try_into().unwrap())
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
assert_eq!(status, PayloadStatus::Valid);
|
assert_eq!(status, PayloadStatus::Valid);
|
||||||
@ -559,7 +559,7 @@ impl<E: GenericExecutionEngine> TestRig<E> {
|
|||||||
let status = self
|
let status = self
|
||||||
.ee_b
|
.ee_b
|
||||||
.execution_layer
|
.execution_layer
|
||||||
.notify_new_payload(second_payload.clone().try_into().unwrap())
|
.notify_new_payload(second_payload.to_ref().try_into().unwrap())
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
assert!(matches!(status, PayloadStatus::Syncing));
|
assert!(matches!(status, PayloadStatus::Syncing));
|
||||||
@ -597,7 +597,7 @@ impl<E: GenericExecutionEngine> TestRig<E> {
|
|||||||
let status = self
|
let status = self
|
||||||
.ee_b
|
.ee_b
|
||||||
.execution_layer
|
.execution_layer
|
||||||
.notify_new_payload(valid_payload.clone().try_into().unwrap())
|
.notify_new_payload(valid_payload.to_ref().try_into().unwrap())
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
assert_eq!(status, PayloadStatus::Valid);
|
assert_eq!(status, PayloadStatus::Valid);
|
||||||
@ -611,7 +611,7 @@ impl<E: GenericExecutionEngine> TestRig<E> {
|
|||||||
let status = self
|
let status = self
|
||||||
.ee_b
|
.ee_b
|
||||||
.execution_layer
|
.execution_layer
|
||||||
.notify_new_payload(second_payload.clone().try_into().unwrap())
|
.notify_new_payload(second_payload.to_ref().try_into().unwrap())
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
assert_eq!(status, PayloadStatus::Valid);
|
assert_eq!(status, PayloadStatus::Valid);
|
||||||
|
Loading…
Reference in New Issue
Block a user