Verify execution block hashes during finalized sync (#3794)
## Issue Addressed Recent discussions with other client devs about optimistic sync have revealed a conceptual issue with the optimisation implemented in #3738. In designing that feature I failed to consider that the execution node checks the `blockHash` of the execution payload before responding with `SYNCING`, and that omitting this check entirely results in a degradation of the full node's validation. A node omitting the `blockHash` checks could be tricked by a supermajority of validators into following an invalid chain, something which is ordinarily impossible. ## Proposed Changes I've added verification of the `payload.block_hash` in Lighthouse. In case of failure we log a warning and fall back to verifying the payload with the execution client. I've used our existing dependency on `ethers_core` for RLP support, and a new dependency on Parity's `triehash` crate for the Merkle patricia trie. Although the `triehash` crate is currently unmaintained it seems like our best option at the moment (it is also used by Reth, and requires vastly less boilerplate than Parity's generic `trie-root` library). Block hash verification is pretty quick, about 500us per block on my machine (mainnet). The optimistic finalized sync feature can be disabled using `--disable-optimistic-finalized-sync` which forces full verification with the EL. ## Additional Info This PR also introduces a new dependency on our [`metastruct`](https://github.com/sigp/metastruct) library, which was perfectly suited to the RLP serialization method. There will likely be changes as `metastruct` grows, but I think this is a good way to start dogfooding it. I took inspiration from some Parity and Reth code while writing this, and have preserved the relevant license headers on the files containing code that was copied and modified.
This commit is contained in:
parent
1d9a2022b4
commit
4bd2b777ec
403
Cargo.lock
generated
403
Cargo.lock
generated
@ -755,7 +755,7 @@ dependencies = [
|
||||
"eth2_hashing",
|
||||
"eth2_serde_utils",
|
||||
"eth2_ssz",
|
||||
"ethereum-types 0.12.1",
|
||||
"ethereum-types 0.14.1",
|
||||
"hex",
|
||||
"milagro_bls",
|
||||
"rand 0.7.3",
|
||||
@ -804,51 +804,6 @@ dependencies = [
|
||||
"types",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "borsh"
|
||||
version = "0.9.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "15bf3650200d8bffa99015595e10f1fbd17de07abbc25bb067da79e769939bfa"
|
||||
dependencies = [
|
||||
"borsh-derive",
|
||||
"hashbrown 0.11.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "borsh-derive"
|
||||
version = "0.9.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6441c552f230375d18e3cc377677914d2ca2b0d36e52129fe15450a2dce46775"
|
||||
dependencies = [
|
||||
"borsh-derive-internal",
|
||||
"borsh-schema-derive-internal",
|
||||
"proc-macro-crate 0.1.5",
|
||||
"proc-macro2",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "borsh-derive-internal"
|
||||
version = "0.9.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5449c28a7b352f2d1e592a8a28bf139bc71afb0764a14f3c02500935d8c44065"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "borsh-schema-derive-internal"
|
||||
version = "0.9.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cdbd5696d8bfa21d53d9fe39a714a18538bad11492a42d066dbbc395fb1951c0"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bs58"
|
||||
version = "0.4.0"
|
||||
@ -900,27 +855,6 @@ version = "1.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c3ac9f8b63eca6fd385229b3675f6cc0dc5c8a5c8a54a59d4f52ffd670d87b0c"
|
||||
|
||||
[[package]]
|
||||
name = "bytecheck"
|
||||
version = "0.6.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d11cac2c12b5adc6570dad2ee1b87eff4955dac476fe12d81e5fdd352e52406f"
|
||||
dependencies = [
|
||||
"bytecheck_derive",
|
||||
"ptr_meta",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bytecheck_derive"
|
||||
version = "0.6.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "13e576ebe98e605500b3c8041bb888e966653577172df6dd97398714eb30b9bf"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "byteorder"
|
||||
version = "1.4.3"
|
||||
@ -965,7 +899,7 @@ dependencies = [
|
||||
"eth2_ssz",
|
||||
"eth2_ssz_derive",
|
||||
"eth2_ssz_types",
|
||||
"ethereum-types 0.12.1",
|
||||
"ethereum-types 0.14.1",
|
||||
"quickcheck",
|
||||
"quickcheck_macros",
|
||||
"smallvec",
|
||||
@ -1102,7 +1036,7 @@ dependencies = [
|
||||
"dirs",
|
||||
"eth2_network_config",
|
||||
"eth2_ssz",
|
||||
"ethereum-types 0.12.1",
|
||||
"ethereum-types 0.14.1",
|
||||
"hex",
|
||||
"serde",
|
||||
"serde_json",
|
||||
@ -1972,7 +1906,7 @@ dependencies = [
|
||||
"derivative",
|
||||
"eth2_ssz",
|
||||
"eth2_ssz_derive",
|
||||
"ethereum-types 0.12.1",
|
||||
"ethereum-types 0.14.1",
|
||||
"execution_layer",
|
||||
"fork_choice",
|
||||
"fs2",
|
||||
@ -2273,7 +2207,7 @@ dependencies = [
|
||||
name = "eth2_serde_utils"
|
||||
version = "0.1.1"
|
||||
dependencies = [
|
||||
"ethereum-types 0.12.1",
|
||||
"ethereum-types 0.14.1",
|
||||
"hex",
|
||||
"serde",
|
||||
"serde_derive",
|
||||
@ -2285,7 +2219,7 @@ name = "eth2_ssz"
|
||||
version = "0.4.1"
|
||||
dependencies = [
|
||||
"eth2_ssz_derive",
|
||||
"ethereum-types 0.12.1",
|
||||
"ethereum-types 0.14.1",
|
||||
"itertools",
|
||||
"smallvec",
|
||||
]
|
||||
@ -2359,11 +2293,11 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "ethabi"
|
||||
version = "17.2.0"
|
||||
version = "18.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e4966fba78396ff92db3b817ee71143eccd98acf0f876b8d600e585a670c5d1b"
|
||||
checksum = "7413c5f74cc903ea37386a8965a936cbeb334bd270862fdece542c1b2dcbc898"
|
||||
dependencies = [
|
||||
"ethereum-types 0.13.1",
|
||||
"ethereum-types 0.14.1",
|
||||
"hex",
|
||||
"once_cell",
|
||||
"regex",
|
||||
@ -2381,22 +2315,24 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bfb684ac8fa8f6c5759f788862bb22ec6fe3cb392f6bfd08e3c64b603661e3f8"
|
||||
dependencies = [
|
||||
"crunchy",
|
||||
"fixed-hash",
|
||||
"fixed-hash 0.7.0",
|
||||
"impl-rlp",
|
||||
"impl-serde",
|
||||
"impl-serde 0.3.2",
|
||||
"tiny-keccak",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ethbloom"
|
||||
version = "0.12.1"
|
||||
version = "0.13.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "11da94e443c60508eb62cf256243a64da87304c2802ac2528847f79d750007ef"
|
||||
checksum = "c22d4b5885b6aa2fe5e8b9329fb8d232bf739e434e6b87347c63bdd00c120f60"
|
||||
dependencies = [
|
||||
"crunchy",
|
||||
"fixed-hash",
|
||||
"fixed-hash 0.8.0",
|
||||
"impl-codec 0.6.0",
|
||||
"impl-rlp",
|
||||
"impl-serde",
|
||||
"impl-serde 0.4.0",
|
||||
"scale-info",
|
||||
"tiny-keccak",
|
||||
]
|
||||
|
||||
@ -2429,46 +2365,47 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "05136f7057fe789f06e6d41d07b34e6f70d8c86e5693b60f97aaa6553553bdaf"
|
||||
dependencies = [
|
||||
"ethbloom 0.11.1",
|
||||
"fixed-hash",
|
||||
"fixed-hash 0.7.0",
|
||||
"impl-rlp",
|
||||
"impl-serde",
|
||||
"impl-serde 0.3.2",
|
||||
"primitive-types 0.10.1",
|
||||
"uint",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ethereum-types"
|
||||
version = "0.13.1"
|
||||
version = "0.14.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b2827b94c556145446fcce834ca86b7abf0c39a805883fe20e72c5bfdb5a0dc6"
|
||||
checksum = "02d215cbf040552efcbe99a38372fe80ab9d00268e20012b79fcd0f073edd8ee"
|
||||
dependencies = [
|
||||
"ethbloom 0.12.1",
|
||||
"fixed-hash",
|
||||
"ethbloom 0.13.0",
|
||||
"fixed-hash 0.8.0",
|
||||
"impl-codec 0.6.0",
|
||||
"impl-rlp",
|
||||
"impl-serde",
|
||||
"primitive-types 0.11.1",
|
||||
"impl-serde 0.4.0",
|
||||
"primitive-types 0.12.1",
|
||||
"scale-info",
|
||||
"uint",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ethers-core"
|
||||
version = "0.17.0"
|
||||
version = "1.0.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0ebdd63c828f58aa067f40f9adcbea5e114fb1f90144b3a1e2858e0c9b1ff4e8"
|
||||
checksum = "ade3e9c97727343984e1ceada4fdab11142d2ee3472d2c67027d56b1251d4f15"
|
||||
dependencies = [
|
||||
"arrayvec",
|
||||
"bytes",
|
||||
"chrono",
|
||||
"elliptic-curve",
|
||||
"ethabi 17.2.0",
|
||||
"fastrlp",
|
||||
"ethabi 18.0.0",
|
||||
"generic-array",
|
||||
"hex",
|
||||
"k256",
|
||||
"open-fastrlp",
|
||||
"rand 0.8.5",
|
||||
"rlp",
|
||||
"rlp-derive",
|
||||
"rust_decimal",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"strum",
|
||||
@ -2479,9 +2416,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "ethers-providers"
|
||||
version = "0.17.0"
|
||||
version = "1.0.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e46482e4d1e79b20c338fd9db9e166184eb387f0a4e7c05c5b5c0aa2e8c8900c"
|
||||
checksum = "a1a9e0597aa6b2fdc810ff58bc95e4eeaa2c219b3e615ed025106ecb027407d8"
|
||||
dependencies = [
|
||||
"async-trait",
|
||||
"auto_impl",
|
||||
@ -2560,8 +2497,11 @@ dependencies = [
|
||||
"exit-future",
|
||||
"fork_choice",
|
||||
"futures",
|
||||
"hash-db",
|
||||
"hash256-std-hasher",
|
||||
"hex",
|
||||
"jsonwebtoken",
|
||||
"keccak-hash",
|
||||
"lazy_static",
|
||||
"lighthouse_metrics",
|
||||
"lru 0.7.8",
|
||||
@ -2583,6 +2523,7 @@ dependencies = [
|
||||
"tokio-stream",
|
||||
"tree_hash",
|
||||
"tree_hash_derive",
|
||||
"triehash",
|
||||
"types",
|
||||
"warp",
|
||||
"zeroize",
|
||||
@ -2618,31 +2559,6 @@ dependencies = [
|
||||
"instant",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "fastrlp"
|
||||
version = "0.1.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "089263294bb1c38ac73649a6ad563dd9a5142c8dc0482be15b8b9acb22a1611e"
|
||||
dependencies = [
|
||||
"arrayvec",
|
||||
"auto_impl",
|
||||
"bytes",
|
||||
"ethereum-types 0.13.1",
|
||||
"fastrlp-derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "fastrlp-derive"
|
||||
version = "0.1.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d6e454d03710df0cd95ce075d7731ce3fa35fb3779c15270cd491bc5f2ef9355"
|
||||
dependencies = [
|
||||
"bytes",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ff"
|
||||
version = "0.12.1"
|
||||
@ -2687,6 +2603,18 @@ dependencies = [
|
||||
name = "fixed-hash"
|
||||
version = "0.7.0"
|
||||
source = "git+https://github.com/paritytech/parity-common?rev=df638ab0885293d21d656dc300d39236b69ce57d#df638ab0885293d21d656dc300d39236b69ce57d"
|
||||
dependencies = [
|
||||
"byteorder",
|
||||
"rand 0.8.5",
|
||||
"rustc-hex",
|
||||
"static_assertions",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "fixed-hash"
|
||||
version = "0.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "835c052cb0c08c1acf6ffd71c022172e18723949c8282f2b9f27efbc51e64534"
|
||||
dependencies = [
|
||||
"arbitrary",
|
||||
"byteorder",
|
||||
@ -3057,6 +2985,21 @@ version = "1.8.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "eabb4a44450da02c90444cf74558da904edde8fb4e9035a9a6a4e15445af0bd7"
|
||||
|
||||
[[package]]
|
||||
name = "hash-db"
|
||||
version = "0.15.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d23bd4e7b5eda0d0f3a307e8b381fdc8ba9000f26fbe912250c0a4cc3956364a"
|
||||
|
||||
[[package]]
|
||||
name = "hash256-std-hasher"
|
||||
version = "0.15.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "92c171d55b98633f4ed3860808f004099b36c1cc29c42cfc53aa8591b21efcf2"
|
||||
dependencies = [
|
||||
"crunchy",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hashbrown"
|
||||
version = "0.11.2"
|
||||
@ -3525,6 +3468,15 @@ dependencies = [
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "impl-serde"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ebc88fc67028ae3db0c853baa36269d398d5f45b6982f95549ff5def78c935cd"
|
||||
dependencies = [
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "impl-trait-for-tuples"
|
||||
version = "0.2.2"
|
||||
@ -3694,6 +3646,16 @@ dependencies = [
|
||||
"cpufeatures",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "keccak-hash"
|
||||
version = "0.10.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4b286e6b663fb926e1eeb68528e69cb70ed46c6d65871a21b2215ae8154c6d3c"
|
||||
dependencies = [
|
||||
"primitive-types 0.12.1",
|
||||
"tiny-keccak",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "lazy_static"
|
||||
version = "1.4.0"
|
||||
@ -4627,13 +4589,36 @@ name = "merkle_proof"
|
||||
version = "0.2.0"
|
||||
dependencies = [
|
||||
"eth2_hashing",
|
||||
"ethereum-types 0.12.1",
|
||||
"ethereum-types 0.14.1",
|
||||
"lazy_static",
|
||||
"quickcheck",
|
||||
"quickcheck_macros",
|
||||
"safe_arith",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "metastruct"
|
||||
version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "734788dec2091fe9afa39530ca2ea7994f4a2c9aff3dbfebb63f2c1945c6f10b"
|
||||
dependencies = [
|
||||
"metastruct_macro",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "metastruct_macro"
|
||||
version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "42ded15e7570c2a507a23e6c3a1c8d74507b779476e43afe93ddfc261d44173d"
|
||||
dependencies = [
|
||||
"darling 0.13.4",
|
||||
"itertools",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"smallvec",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "mev-build-rs"
|
||||
version = "0.2.1"
|
||||
@ -4797,7 +4782,7 @@ version = "0.8.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1d6d4752e6230d8ef7adf7bd5d8c4b1f6561c1014c5ba9a37445ccefe18aa1db"
|
||||
dependencies = [
|
||||
"proc-macro-crate 1.1.3",
|
||||
"proc-macro-crate",
|
||||
"proc-macro-error",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
@ -4952,7 +4937,7 @@ dependencies = [
|
||||
"error-chain",
|
||||
"eth2_ssz",
|
||||
"eth2_ssz_types",
|
||||
"ethereum-types 0.12.1",
|
||||
"ethereum-types 0.14.1",
|
||||
"exit-future",
|
||||
"fnv",
|
||||
"futures",
|
||||
@ -5209,6 +5194,31 @@ version = "0.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5"
|
||||
|
||||
[[package]]
|
||||
name = "open-fastrlp"
|
||||
version = "0.1.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "786393f80485445794f6043fd3138854dd109cc6c4bd1a6383db304c9ce9b9ce"
|
||||
dependencies = [
|
||||
"arrayvec",
|
||||
"auto_impl",
|
||||
"bytes",
|
||||
"ethereum-types 0.14.1",
|
||||
"open-fastrlp-derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "open-fastrlp-derive"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "003b2be5c6c53c1cfeb0a238b8a1c3915cd410feb684457a36c10038f764bb1c"
|
||||
dependencies = [
|
||||
"bytes",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "openssl"
|
||||
version = "0.10.44"
|
||||
@ -5359,7 +5369,7 @@ version = "2.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1557010476e0595c9b568d16dcfb81b93cdeb157612726f5170d31aa707bed27"
|
||||
dependencies = [
|
||||
"proc-macro-crate 1.1.3",
|
||||
"proc-macro-crate",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
@ -5371,7 +5381,7 @@ version = "3.1.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9299338969a3d2f491d65f140b00ddec470858402f888af98e8642fb5e8965cd"
|
||||
dependencies = [
|
||||
"proc-macro-crate 1.1.3",
|
||||
"proc-macro-crate",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
@ -5679,35 +5689,27 @@ version = "0.10.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "05e4722c697a58a99d5d06a08c30821d7c082a4632198de1eaa5a6c22ef42373"
|
||||
dependencies = [
|
||||
"fixed-hash",
|
||||
"fixed-hash 0.7.0",
|
||||
"impl-codec 0.5.1",
|
||||
"impl-rlp",
|
||||
"impl-serde",
|
||||
"impl-serde 0.3.2",
|
||||
"uint",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "primitive-types"
|
||||
version = "0.11.1"
|
||||
version = "0.12.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e28720988bff275df1f51b171e1b2a18c30d194c4d2b61defdacecd625a5d94a"
|
||||
checksum = "9f3486ccba82358b11a77516035647c34ba167dfa53312630de83b12bd4f3d66"
|
||||
dependencies = [
|
||||
"fixed-hash",
|
||||
"fixed-hash 0.8.0",
|
||||
"impl-codec 0.6.0",
|
||||
"impl-rlp",
|
||||
"impl-serde",
|
||||
"impl-serde 0.4.0",
|
||||
"scale-info",
|
||||
"uint",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro-crate"
|
||||
version = "0.1.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1d6ea3c4595b96363c13943497db34af4460fb474a95c43f4446ad341b8c9785"
|
||||
dependencies = [
|
||||
"toml",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro-crate"
|
||||
version = "1.1.3"
|
||||
@ -5913,26 +5915,6 @@ dependencies = [
|
||||
"unescape",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ptr_meta"
|
||||
version = "0.1.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0738ccf7ea06b608c10564b31debd4f5bc5e197fc8bfe088f68ae5ce81e7a4f1"
|
||||
dependencies = [
|
||||
"ptr_meta_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ptr_meta_derive"
|
||||
version = "0.1.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "16b845dbfca988fa33db069c0e230574d15a3088f147a87b64c7589eb662c9ac"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quick-error"
|
||||
version = "1.2.3"
|
||||
@ -6215,15 +6197,6 @@ dependencies = [
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rend"
|
||||
version = "0.3.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "79af64b4b6362ffba04eef3a4e10829718a4896dac19daa741851c86781edf95"
|
||||
dependencies = [
|
||||
"bytecheck",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "reqwest"
|
||||
version = "0.11.13"
|
||||
@ -6303,31 +6276,6 @@ dependencies = [
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rkyv"
|
||||
version = "0.7.39"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cec2b3485b07d96ddfd3134767b8a447b45ea4eb91448d0a35180ec0ffd5ed15"
|
||||
dependencies = [
|
||||
"bytecheck",
|
||||
"hashbrown 0.12.3",
|
||||
"ptr_meta",
|
||||
"rend",
|
||||
"rkyv_derive",
|
||||
"seahash",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rkyv_derive"
|
||||
version = "0.7.39"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6eaedadc88b53e36dd32d940ed21ae4d850d5916f2581526921f553a72ac34c4"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rle-decode-fast"
|
||||
version = "1.0.3"
|
||||
@ -6420,24 +6368,6 @@ dependencies = [
|
||||
"smallvec",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rust_decimal"
|
||||
version = "1.27.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "33c321ee4e17d2b7abe12b5d20c1231db708dd36185c8a21e9de5fed6da4dbe9"
|
||||
dependencies = [
|
||||
"arrayvec",
|
||||
"borsh",
|
||||
"bytecheck",
|
||||
"byteorder",
|
||||
"bytes",
|
||||
"num-traits",
|
||||
"rand 0.8.5",
|
||||
"rkyv",
|
||||
"serde",
|
||||
"serde_json",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustc-demangle"
|
||||
version = "0.1.21"
|
||||
@ -6577,6 +6507,30 @@ dependencies = [
|
||||
"winapi-util",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "scale-info"
|
||||
version = "2.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "001cf62ece89779fd16105b5f515ad0e5cedcd5440d3dd806bb067978e7c3608"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"derive_more",
|
||||
"parity-scale-codec 3.2.1",
|
||||
"scale-info-derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "scale-info-derive"
|
||||
version = "2.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "303959cf613a6f6efd19ed4b4ad5bf79966a13352716299ad532cfb115f4205c"
|
||||
dependencies = [
|
||||
"proc-macro-crate",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "schannel"
|
||||
version = "0.1.20"
|
||||
@ -6658,12 +6612,6 @@ dependencies = [
|
||||
"url",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "seahash"
|
||||
version = "4.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1c107b6f4780854c8b126e228ea8869f4d7b71260f962fefb57b996b8959ba6b"
|
||||
|
||||
[[package]]
|
||||
name = "sec1"
|
||||
version = "0.3.0"
|
||||
@ -7466,7 +7414,7 @@ version = "0.2.0"
|
||||
dependencies = [
|
||||
"criterion",
|
||||
"eth2_hashing",
|
||||
"ethereum-types 0.12.1",
|
||||
"ethereum-types 0.14.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -8087,7 +8035,7 @@ dependencies = [
|
||||
"eth2_hashing",
|
||||
"eth2_ssz",
|
||||
"eth2_ssz_derive",
|
||||
"ethereum-types 0.12.1",
|
||||
"ethereum-types 0.14.1",
|
||||
"rand 0.8.5",
|
||||
"smallvec",
|
||||
"tree_hash_derive",
|
||||
@ -8103,6 +8051,16 @@ dependencies = [
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "triehash"
|
||||
version = "0.8.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a1631b201eb031b563d2e85ca18ec8092508e262a3196ce9bd10a67ec87b9f5c"
|
||||
dependencies = [
|
||||
"hash-db",
|
||||
"rlp",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "trust-dns-proto"
|
||||
version = "0.22.0"
|
||||
@ -8247,7 +8205,7 @@ dependencies = [
|
||||
"eth2_ssz",
|
||||
"eth2_ssz_derive",
|
||||
"eth2_ssz_types",
|
||||
"ethereum-types 0.12.1",
|
||||
"ethereum-types 0.14.1",
|
||||
"hex",
|
||||
"int_to_bytes",
|
||||
"itertools",
|
||||
@ -8255,6 +8213,7 @@ dependencies = [
|
||||
"log",
|
||||
"maplit",
|
||||
"merkle_proof",
|
||||
"metastruct",
|
||||
"parking_lot 0.12.1",
|
||||
"rand 0.8.5",
|
||||
"rand_xorshift",
|
||||
|
@ -65,6 +65,8 @@ pub struct ChainConfig {
|
||||
/// Low values are useful for execution engines which don't improve their payload after the
|
||||
/// first call, and high values are useful for ensuring the EL is given ample notice.
|
||||
pub prepare_payload_lookahead: Duration,
|
||||
/// Use EL-free optimistic sync for the finalized part of the chain.
|
||||
pub optimistic_finalized_sync: bool,
|
||||
}
|
||||
|
||||
impl Default for ChainConfig {
|
||||
@ -89,6 +91,7 @@ impl Default for ChainConfig {
|
||||
count_unrealized_full: CountUnrealizedFull::default(),
|
||||
checkpoint_sync_url_timeout: 60,
|
||||
prepare_payload_lookahead: Duration::from_secs(4),
|
||||
optimistic_finalized_sync: true,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -15,7 +15,7 @@ use crate::{
|
||||
use execution_layer::{BuilderParams, PayloadStatus};
|
||||
use fork_choice::{InvalidationOperation, PayloadVerificationStatus};
|
||||
use proto_array::{Block as ProtoBlock, ExecutionStatus};
|
||||
use slog::debug;
|
||||
use slog::{debug, warn};
|
||||
use slot_clock::SlotClock;
|
||||
use state_processing::per_block_processing::{
|
||||
compute_timestamp_at_slot, is_execution_enabled, is_merge_transition_complete,
|
||||
@ -59,26 +59,46 @@ impl<T: BeaconChainTypes> PayloadNotifier<T> {
|
||||
state: &BeaconState<T::EthSpec>,
|
||||
notify_execution_layer: NotifyExecutionLayer,
|
||||
) -> Result<Self, BlockError<T::EthSpec>> {
|
||||
let payload_verification_status = match notify_execution_layer {
|
||||
NotifyExecutionLayer::No => Some(PayloadVerificationStatus::Optimistic),
|
||||
NotifyExecutionLayer::Yes => {
|
||||
if is_execution_enabled(state, block.message().body()) {
|
||||
// Perform the initial stages of payload verification.
|
||||
//
|
||||
// We will duplicate these checks again during `per_block_processing`, however these checks
|
||||
// are cheap and doing them here ensures we protect the execution engine from junk.
|
||||
partially_verify_execution_payload(
|
||||
state,
|
||||
block.slot(),
|
||||
block.message().execution_payload()?,
|
||||
&chain.spec,
|
||||
)
|
||||
.map_err(BlockError::PerBlockProcessingError)?;
|
||||
None
|
||||
} else {
|
||||
Some(PayloadVerificationStatus::Irrelevant)
|
||||
let payload_verification_status = if is_execution_enabled(state, block.message().body()) {
|
||||
// Perform the initial stages of payload verification.
|
||||
//
|
||||
// We will duplicate these checks again during `per_block_processing`, however these
|
||||
// checks are cheap and doing them here ensures we have verified them before marking
|
||||
// the block as optimistically imported. This is particularly relevant in the case
|
||||
// where we do not send the block to the EL at all.
|
||||
let block_message = block.message();
|
||||
let payload = block_message.execution_payload()?;
|
||||
partially_verify_execution_payload(state, block.slot(), payload, &chain.spec)
|
||||
.map_err(BlockError::PerBlockProcessingError)?;
|
||||
|
||||
match notify_execution_layer {
|
||||
NotifyExecutionLayer::No if chain.config.optimistic_finalized_sync => {
|
||||
// Verify the block hash here in Lighthouse and immediately mark the block as
|
||||
// optimistically imported. This saves a lot of roundtrips to the EL.
|
||||
let execution_layer = chain
|
||||
.execution_layer
|
||||
.as_ref()
|
||||
.ok_or(ExecutionPayloadError::NoExecutionConnection)?;
|
||||
|
||||
if let Err(e) =
|
||||
execution_layer.verify_payload_block_hash(&payload.execution_payload)
|
||||
{
|
||||
warn!(
|
||||
chain.log,
|
||||
"Falling back to slow block hash verification";
|
||||
"block_number" => payload.block_number(),
|
||||
"info" => "you can silence this warning with --disable-optimistic-finalized-sync",
|
||||
"error" => ?e,
|
||||
);
|
||||
None
|
||||
} else {
|
||||
Some(PayloadVerificationStatus::Optimistic)
|
||||
}
|
||||
}
|
||||
_ => None,
|
||||
}
|
||||
} else {
|
||||
Some(PayloadVerificationStatus::Irrelevant)
|
||||
};
|
||||
|
||||
Ok(Self {
|
||||
|
@ -37,7 +37,7 @@ rand = "0.8.5"
|
||||
zeroize = { version = "1.4.2", features = ["zeroize_derive"] }
|
||||
lighthouse_metrics = { path = "../../common/lighthouse_metrics" }
|
||||
lazy_static = "1.4.0"
|
||||
ethers-core = "0.17.0"
|
||||
ethers-core = "1.0.2"
|
||||
builder_client = { path = "../builder_client" }
|
||||
fork_choice = { path = "../../consensus/fork_choice" }
|
||||
mev-build-rs = { git = "https://github.com/ralexstokes/mev-rs", rev = "6c99b0fbdc0427b1625469d2e575303ce08de5b8" }
|
||||
@ -45,3 +45,7 @@ ethereum-consensus = { git = "https://github.com/ralexstokes/ethereum-consensus"
|
||||
ssz-rs = { git = "https://github.com/ralexstokes/ssz-rs", rev = "cb08f1" }
|
||||
tokio-stream = { version = "0.1.9", features = [ "sync" ] }
|
||||
strum = "0.24.0"
|
||||
keccak-hash = "0.10.0"
|
||||
hash256-std-hasher = "0.15.2"
|
||||
triehash = "0.8.4"
|
||||
hash-db = "0.15.2"
|
||||
|
163
beacon_node/execution_layer/src/block_hash.rs
Normal file
163
beacon_node/execution_layer/src/block_hash.rs
Normal file
@ -0,0 +1,163 @@
|
||||
use crate::{
|
||||
keccak::{keccak256, KeccakHasher},
|
||||
metrics, Error, ExecutionLayer,
|
||||
};
|
||||
use ethers_core::utils::rlp::RlpStream;
|
||||
use keccak_hash::KECCAK_EMPTY_LIST_RLP;
|
||||
use triehash::ordered_trie_root;
|
||||
use types::{
|
||||
map_execution_block_header_fields, Address, EthSpec, ExecutionBlockHash, ExecutionBlockHeader,
|
||||
ExecutionPayload, Hash256, Hash64, Uint256,
|
||||
};
|
||||
|
||||
impl<T: EthSpec> ExecutionLayer<T> {
|
||||
/// 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, payload: &ExecutionPayload<T>) -> Result<(), Error> {
|
||||
let _timer = metrics::start_timer(&metrics::EXECUTION_LAYER_VERIFY_BLOCK_HASH);
|
||||
|
||||
// Calculate the transactions root.
|
||||
// We're currently using a deprecated Parity library for this. We should move to a
|
||||
// better alternative when one appears, possibly following Reth.
|
||||
let rlp_transactions_root = ordered_trie_root::<KeccakHasher, _>(
|
||||
payload.transactions.iter().map(|txn_bytes| &**txn_bytes),
|
||||
);
|
||||
|
||||
// Construct the block header.
|
||||
let exec_block_header = ExecutionBlockHeader::from_payload(
|
||||
payload,
|
||||
KECCAK_EMPTY_LIST_RLP.as_fixed_bytes().into(),
|
||||
rlp_transactions_root,
|
||||
);
|
||||
|
||||
// Hash the RLP encoding of the block header.
|
||||
let rlp_block_header = rlp_encode_block_header(&exec_block_header);
|
||||
let header_hash = ExecutionBlockHash::from_root(keccak256(&rlp_block_header));
|
||||
|
||||
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 an execution block header.
|
||||
pub fn rlp_encode_block_header(header: &ExecutionBlockHeader) -> Vec<u8> {
|
||||
let mut rlp_header_stream = RlpStream::new();
|
||||
rlp_header_stream.begin_unbounded_list();
|
||||
map_execution_block_header_fields!(&header, |_, field| {
|
||||
rlp_header_stream.append(field);
|
||||
});
|
||||
rlp_header_stream.finalize_unbounded_list();
|
||||
rlp_header_stream.out().into()
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
use hex::FromHex;
|
||||
use std::str::FromStr;
|
||||
|
||||
fn test_rlp_encoding(
|
||||
header: &ExecutionBlockHeader,
|
||||
expected_rlp: Option<&str>,
|
||||
expected_hash: Hash256,
|
||||
) {
|
||||
let rlp_encoding = rlp_encode_block_header(header);
|
||||
|
||||
if let Some(expected_rlp) = expected_rlp {
|
||||
let computed_rlp = hex::encode(&rlp_encoding);
|
||||
assert_eq!(expected_rlp, computed_rlp);
|
||||
}
|
||||
|
||||
let computed_hash = keccak256(&rlp_encoding);
|
||||
assert_eq!(expected_hash, computed_hash);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_rlp_encode_eip1559_block() {
|
||||
let header = ExecutionBlockHeader {
|
||||
parent_hash: Hash256::from_str("e0a94a7a3c9617401586b1a27025d2d9671332d22d540e0af72b069170380f2a").unwrap(),
|
||||
ommers_hash: Hash256::from_str("1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347").unwrap(),
|
||||
beneficiary: Address::from_str("ba5e000000000000000000000000000000000000").unwrap(),
|
||||
state_root: Hash256::from_str("ec3c94b18b8a1cff7d60f8d258ec723312932928626b4c9355eb4ab3568ec7f7").unwrap(),
|
||||
transactions_root: Hash256::from_str("50f738580ed699f0469702c7ccc63ed2e51bc034be9479b7bff4e68dee84accf").unwrap(),
|
||||
receipts_root: Hash256::from_str("29b0562f7140574dd0d50dee8a271b22e1a0a7b78fca58f7c60370d8317ba2a9").unwrap(),
|
||||
logs_bloom: <[u8; 256]>::from_hex("00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000").unwrap().into(),
|
||||
difficulty: 0x020000.into(),
|
||||
number: 0x01_u64.into(),
|
||||
gas_limit: 0x016345785d8a0000_u64.into(),
|
||||
gas_used: 0x015534_u64.into(),
|
||||
timestamp: 0x079e,
|
||||
extra_data: vec![0x42],
|
||||
mix_hash: Hash256::from_str("0000000000000000000000000000000000000000000000000000000000000000").unwrap(),
|
||||
nonce: Hash64::zero(),
|
||||
base_fee_per_gas: 0x036b_u64.into(),
|
||||
};
|
||||
let expected_rlp = "f90200a0e0a94a7a3c9617401586b1a27025d2d9671332d22d540e0af72b069170380f2aa01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d4934794ba5e000000000000000000000000000000000000a0ec3c94b18b8a1cff7d60f8d258ec723312932928626b4c9355eb4ab3568ec7f7a050f738580ed699f0469702c7ccc63ed2e51bc034be9479b7bff4e68dee84accfa029b0562f7140574dd0d50dee8a271b22e1a0a7b78fca58f7c60370d8317ba2a9b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000830200000188016345785d8a00008301553482079e42a0000000000000000000000000000000000000000000000000000000000000000088000000000000000082036b";
|
||||
let expected_hash =
|
||||
Hash256::from_str("6a251c7c3c5dca7b42407a3752ff48f3bbca1fab7f9868371d9918daf1988d1f")
|
||||
.unwrap();
|
||||
test_rlp_encoding(&header, Some(expected_rlp), expected_hash);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_rlp_encode_merge_block() {
|
||||
let header = ExecutionBlockHeader {
|
||||
parent_hash: Hash256::from_str("927ca537f06c783a3a2635b8805eef1c8c2124f7444ad4a3389898dd832f2dbe").unwrap(),
|
||||
ommers_hash: Hash256::from_str("1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347").unwrap(),
|
||||
beneficiary: Address::from_str("ba5e000000000000000000000000000000000000").unwrap(),
|
||||
state_root: Hash256::from_str("0xe97859b065bd8dbbb4519c7cb935024de2484c2b7f881181b4360492f0b06b82").unwrap(),
|
||||
transactions_root: Hash256::from_str("50f738580ed699f0469702c7ccc63ed2e51bc034be9479b7bff4e68dee84accf").unwrap(),
|
||||
receipts_root: Hash256::from_str("29b0562f7140574dd0d50dee8a271b22e1a0a7b78fca58f7c60370d8317ba2a9").unwrap(),
|
||||
logs_bloom: <[u8; 256]>::from_hex("00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000").unwrap().into(),
|
||||
difficulty: 0x00.into(),
|
||||
number: 0x01_u64.into(),
|
||||
gas_limit: 0x016345785d8a0000_u64.into(),
|
||||
gas_used: 0x015534_u64.into(),
|
||||
timestamp: 0x079e,
|
||||
extra_data: vec![0x42],
|
||||
mix_hash: Hash256::from_str("0000000000000000000000000000000000000000000000000000000000020000").unwrap(),
|
||||
nonce: Hash64::zero(),
|
||||
base_fee_per_gas: 0x036b_u64.into(),
|
||||
};
|
||||
let expected_rlp = "f901fda0927ca537f06c783a3a2635b8805eef1c8c2124f7444ad4a3389898dd832f2dbea01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d4934794ba5e000000000000000000000000000000000000a0e97859b065bd8dbbb4519c7cb935024de2484c2b7f881181b4360492f0b06b82a050f738580ed699f0469702c7ccc63ed2e51bc034be9479b7bff4e68dee84accfa029b0562f7140574dd0d50dee8a271b22e1a0a7b78fca58f7c60370d8317ba2a9b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800188016345785d8a00008301553482079e42a0000000000000000000000000000000000000000000000000000000000002000088000000000000000082036b";
|
||||
let expected_hash =
|
||||
Hash256::from_str("0x5b1f0f2efdaa19e996b4aea59eeb67620259f09732732a339a10dac311333684")
|
||||
.unwrap();
|
||||
test_rlp_encoding(&header, Some(expected_rlp), expected_hash);
|
||||
}
|
||||
|
||||
// Test a real payload from mainnet.
|
||||
#[test]
|
||||
fn test_rlp_encode_block_16182891() {
|
||||
let header = ExecutionBlockHeader {
|
||||
parent_hash: Hash256::from_str("3e9c7b3f403947f110f68c4564a004b73dd8ebf73b143e46cc637926eec01a6d").unwrap(),
|
||||
ommers_hash: Hash256::from_str("1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347").unwrap(),
|
||||
beneficiary: Address::from_str("dafea492d9c6733ae3d56b7ed1adb60692c98bc5").unwrap(),
|
||||
state_root: Hash256::from_str("5a8183d230818a167477420ce3a393ca3ef8706a7d596694ab6059894ed6fda9").unwrap(),
|
||||
transactions_root: Hash256::from_str("0223f0cb35f184d2ac409e89dc0768ad738f777bd1c85d3302ca50f307180c94").unwrap(),
|
||||
receipts_root: Hash256::from_str("371c76821b1cc21232574604eac5349d51647eb530e2a45d4f6fe2c501351aa5").unwrap(),
|
||||
logs_bloom: <[u8; 256]>::from_hex("1a2c559955848d2662a0634cb40c7a6192a1524f11061203689bcbcdec901b054084d4f4d688009d24c10918e0089b48e72fe2d7abafb903889d10c3827c6901096612d259801b1b7ba1663a4201f5f88f416a9997c55bcc2c54785280143b057a008764c606182e324216822a2d5913e797a05c16cc1468d001acf3783b18e00e0203033e43106178db554029e83ca46402dc49d929d7882a04a0e7215041bdabf7430bd10ef4bb658a40f064c63c4816660241c2480862f26742fdf9ca41637731350301c344e439428182a03e384484e6d65d0c8a10117c6739ca201b60974519a1ae6b0c3966c0f650b449d10eae065dab2c83ab4edbab5efdea50bbc801").unwrap().into(),
|
||||
difficulty: 0.into(),
|
||||
number: 16182891.into(),
|
||||
gas_limit: 0x1c9c380.into(),
|
||||
gas_used: 0xe9b752.into(),
|
||||
timestamp: 0x6399bf63,
|
||||
extra_data: hex::decode("496c6c756d696e61746520446d6f63726174697a6520447374726962757465").unwrap(),
|
||||
mix_hash: Hash256::from_str("bf5289894b2ceab3549f92f063febbac896b280ddb18129a57cff13113c11b13").unwrap(),
|
||||
nonce: Hash64::zero(),
|
||||
base_fee_per_gas: 0x34187b238_u64.into(),
|
||||
};
|
||||
let expected_hash =
|
||||
Hash256::from_str("6da69709cd5a34079b6604d29cd78fc01dacd7c6268980057ad92a2bede87351")
|
||||
.unwrap();
|
||||
test_rlp_encoding(&header, None, expected_hash);
|
||||
}
|
||||
}
|
35
beacon_node/execution_layer/src/keccak.rs
Normal file
35
beacon_node/execution_layer/src/keccak.rs
Normal file
@ -0,0 +1,35 @@
|
||||
// Copyright 2017, 2018 Parity Technologies
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
use hash256_std_hasher::Hash256StdHasher;
|
||||
use hash_db::Hasher;
|
||||
use types::Hash256;
|
||||
|
||||
pub fn keccak256(bytes: &[u8]) -> Hash256 {
|
||||
Hash256::from(ethers_core::utils::keccak256(bytes))
|
||||
}
|
||||
|
||||
/// Keccak hasher.
|
||||
#[derive(Default, Debug, Clone, PartialEq)]
|
||||
pub struct KeccakHasher;
|
||||
|
||||
impl Hasher for KeccakHasher {
|
||||
type Out = Hash256;
|
||||
type StdHasher = Hash256StdHasher;
|
||||
|
||||
const LENGTH: usize = 32;
|
||||
|
||||
fn hash(x: &[u8]) -> Self::Out {
|
||||
keccak256(x)
|
||||
}
|
||||
}
|
@ -40,8 +40,10 @@ use types::{
|
||||
ProposerPreparationData, PublicKeyBytes, Signature, SignedBeaconBlock, Slot, Uint256,
|
||||
};
|
||||
|
||||
mod block_hash;
|
||||
mod engine_api;
|
||||
mod engines;
|
||||
mod keccak;
|
||||
mod metrics;
|
||||
pub mod payload_cache;
|
||||
mod payload_status;
|
||||
@ -90,6 +92,11 @@ pub enum Error {
|
||||
ShuttingDown,
|
||||
FeeRecipientUnspecified,
|
||||
MissingLatestValidHash,
|
||||
BlockHashMismatch {
|
||||
computed: ExecutionBlockHash,
|
||||
payload: ExecutionBlockHash,
|
||||
transactions_root: Hash256,
|
||||
},
|
||||
InvalidJWTSecret(String),
|
||||
}
|
||||
|
||||
|
@ -45,6 +45,11 @@ lazy_static::lazy_static! {
|
||||
"execution_layer_get_payload_by_block_hash_time",
|
||||
"Time to reconstruct a payload from the EE using eth_getBlockByHash"
|
||||
);
|
||||
pub static ref EXECUTION_LAYER_VERIFY_BLOCK_HASH: Result<Histogram> = try_create_histogram_with_buckets(
|
||||
"execution_layer_verify_block_hash_time",
|
||||
"Time to verify the execution block hash in Lighthouse, without the EL",
|
||||
Ok(vec![10e-6, 50e-6, 100e-6, 500e-6, 1e-3, 5e-3, 10e-3, 50e-3, 100e-3, 500e-3]),
|
||||
);
|
||||
pub static ref EXECUTION_LAYER_PAYLOAD_STATUS: Result<IntCounterVec> = try_create_int_counter_vec(
|
||||
"execution_layer_payload_status",
|
||||
"Indicates the payload status returned for a particular method",
|
||||
|
@ -44,7 +44,7 @@ strum = "0.24.0"
|
||||
tokio-util = { version = "0.6.3", features = ["time"] }
|
||||
derivative = "2.2.0"
|
||||
delay_map = "0.1.1"
|
||||
ethereum-types = { version = "0.12.1", optional = true }
|
||||
ethereum-types = { version = "0.14.1", optional = true }
|
||||
|
||||
[features]
|
||||
deterministic_long_lived_attnets = [ "ethereum-types" ]
|
||||
|
@ -900,6 +900,13 @@ pub fn cli_app<'a, 'b>() -> App<'a, 'b> {
|
||||
Useful if you intend to run a non-validating beacon node.")
|
||||
.takes_value(false)
|
||||
)
|
||||
.arg(
|
||||
Arg::with_name("disable-optimistic-finalized-sync")
|
||||
.long("disable-optimistic-finalized-sync")
|
||||
.help("Force Lighthouse to verify every execution block hash with the execution \
|
||||
client during finalized sync. By default block hashes will be checked in \
|
||||
Lighthouse and only passed to the EL if initial verification fails.")
|
||||
)
|
||||
.arg(
|
||||
Arg::with_name("light-client-server")
|
||||
.long("light-client-server")
|
||||
|
@ -741,6 +741,10 @@ pub fn get_config<E: EthSpec>(
|
||||
client_config.validator_monitor_auto = true;
|
||||
}
|
||||
|
||||
// Optimistic finalized sync.
|
||||
client_config.chain.optimistic_finalized_sync =
|
||||
!cli_args.is_present("disable-optimistic-finalized-sync");
|
||||
|
||||
Ok(client_config)
|
||||
}
|
||||
|
||||
|
@ -12,7 +12,7 @@ hex = "0.4.2"
|
||||
dirs = "3.0.1"
|
||||
eth2_network_config = { path = "../eth2_network_config" }
|
||||
eth2_ssz = "0.4.1"
|
||||
ethereum-types = "0.12.1"
|
||||
ethereum-types = "0.14.1"
|
||||
serde = "1.0.116"
|
||||
serde_json = "1.0.59"
|
||||
serde_yaml = "0.8.13"
|
||||
|
@ -5,7 +5,7 @@ authors = ["Michael Sproul <michael@sigmaprime.io>"]
|
||||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
ethereum-types = "0.12.1"
|
||||
ethereum-types = "0.14.1"
|
||||
eth2_ssz_types = "0.2.2"
|
||||
eth2_hashing = "0.3.0"
|
||||
eth2_ssz_derive = "0.3.0"
|
||||
|
@ -5,7 +5,7 @@ authors = ["Michael Sproul <michael@sigmaprime.io>"]
|
||||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
ethereum-types = "0.12.1"
|
||||
ethereum-types = "0.14.1"
|
||||
eth2_hashing = "0.3.0"
|
||||
lazy_static = "1.4.0"
|
||||
safe_arith = { path = "../safe_arith" }
|
||||
|
@ -11,4 +11,4 @@ serde = { version = "1.0.116", features = ["derive"] }
|
||||
serde_derive = "1.0.116"
|
||||
serde_json = "1.0.58"
|
||||
hex = "0.4.2"
|
||||
ethereum-types = "0.12.1"
|
||||
ethereum-types = "0.14.1"
|
||||
|
@ -13,7 +13,7 @@ name = "ssz"
|
||||
eth2_ssz_derive = "0.3.0"
|
||||
|
||||
[dependencies]
|
||||
ethereum-types = "0.12.1"
|
||||
ethereum-types = "0.14.1"
|
||||
smallvec = { version = "1.6.1", features = ["const_generics"] }
|
||||
itertools = "0.10.3"
|
||||
|
||||
|
@ -13,7 +13,7 @@ criterion = "0.3.3"
|
||||
|
||||
[dependencies]
|
||||
eth2_hashing = "0.3.0"
|
||||
ethereum-types = "0.12.1"
|
||||
ethereum-types = "0.14.1"
|
||||
|
||||
[features]
|
||||
arbitrary = ["ethereum-types/arbitrary"]
|
||||
|
@ -15,7 +15,7 @@ eth2_ssz = "0.4.1"
|
||||
eth2_ssz_derive = "0.3.0"
|
||||
|
||||
[dependencies]
|
||||
ethereum-types = "0.12.1"
|
||||
ethereum-types = "0.14.1"
|
||||
eth2_hashing = "0.3.0"
|
||||
smallvec = "1.6.1"
|
||||
|
||||
|
@ -14,7 +14,7 @@ bls = { path = "../../crypto/bls" }
|
||||
compare_fields = { path = "../../common/compare_fields" }
|
||||
compare_fields_derive = { path = "../../common/compare_fields_derive" }
|
||||
eth2_interop_keypairs = { path = "../../common/eth2_interop_keypairs" }
|
||||
ethereum-types = "0.12.1"
|
||||
ethereum-types = "0.14.1"
|
||||
eth2_hashing = "0.3.0"
|
||||
hex = "0.4.2"
|
||||
int_to_bytes = { path = "../int_to_bytes" }
|
||||
@ -45,6 +45,7 @@ lazy_static = "1.4.0"
|
||||
parking_lot = "0.12.0"
|
||||
itertools = "0.10.0"
|
||||
superstruct = "0.5.0"
|
||||
metastruct = "0.1.0"
|
||||
serde_json = "1.0.74"
|
||||
smallvec = "1.8.0"
|
||||
serde_with = "1.13.0"
|
||||
|
74
consensus/types/src/execution_block_header.rs
Normal file
74
consensus/types/src/execution_block_header.rs
Normal file
@ -0,0 +1,74 @@
|
||||
// Copyright (c) 2022 Reth Contributors
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
use crate::{Address, EthSpec, ExecutionPayload, Hash256, Hash64, Uint256};
|
||||
use metastruct::metastruct;
|
||||
|
||||
/// Execution block header as used for RLP encoding and Keccak hashing.
|
||||
///
|
||||
/// Credit to Reth for the type definition.
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||
#[metastruct(mappings(map_execution_block_header_fields()))]
|
||||
pub struct ExecutionBlockHeader {
|
||||
pub parent_hash: Hash256,
|
||||
pub ommers_hash: Hash256,
|
||||
pub beneficiary: Address,
|
||||
pub state_root: Hash256,
|
||||
pub transactions_root: Hash256,
|
||||
pub receipts_root: Hash256,
|
||||
pub logs_bloom: Vec<u8>,
|
||||
pub difficulty: Uint256,
|
||||
pub number: Uint256,
|
||||
pub gas_limit: Uint256,
|
||||
pub gas_used: Uint256,
|
||||
pub timestamp: u64,
|
||||
pub extra_data: Vec<u8>,
|
||||
pub mix_hash: Hash256,
|
||||
pub nonce: Hash64,
|
||||
pub base_fee_per_gas: Uint256,
|
||||
}
|
||||
|
||||
impl ExecutionBlockHeader {
|
||||
pub fn from_payload<E: EthSpec>(
|
||||
payload: &ExecutionPayload<E>,
|
||||
rlp_empty_list_root: Hash256,
|
||||
rlp_transactions_root: Hash256,
|
||||
) -> Self {
|
||||
// Most of these field mappings are defined in EIP-3675 except for `mixHash`, which is
|
||||
// defined in EIP-4399.
|
||||
ExecutionBlockHeader {
|
||||
parent_hash: payload.parent_hash.into_root(),
|
||||
ommers_hash: rlp_empty_list_root,
|
||||
beneficiary: payload.fee_recipient,
|
||||
state_root: payload.state_root,
|
||||
transactions_root: rlp_transactions_root,
|
||||
receipts_root: payload.receipts_root,
|
||||
logs_bloom: payload.logs_bloom.clone().into(),
|
||||
difficulty: Uint256::zero(),
|
||||
number: payload.block_number.into(),
|
||||
gas_limit: payload.gas_limit.into(),
|
||||
gas_used: payload.gas_used.into(),
|
||||
timestamp: payload.timestamp,
|
||||
extra_data: payload.extra_data.clone().into(),
|
||||
mix_hash: payload.prev_randao,
|
||||
nonce: Hash64::zero(),
|
||||
base_fee_per_gas: payload.base_fee_per_gas,
|
||||
}
|
||||
}
|
||||
}
|
@ -74,6 +74,7 @@ pub mod voluntary_exit;
|
||||
#[macro_use]
|
||||
pub mod slot_epoch_macros;
|
||||
pub mod config_and_preset;
|
||||
pub mod execution_block_header;
|
||||
pub mod fork_context;
|
||||
pub mod participation_flags;
|
||||
pub mod participation_list;
|
||||
@ -127,6 +128,7 @@ pub use crate::enr_fork_id::EnrForkId;
|
||||
pub use crate::eth1_data::Eth1Data;
|
||||
pub use crate::eth_spec::EthSpecId;
|
||||
pub use crate::execution_block_hash::ExecutionBlockHash;
|
||||
pub use crate::execution_block_header::ExecutionBlockHeader;
|
||||
pub use crate::execution_payload::{ExecutionPayload, Transaction, Transactions};
|
||||
pub use crate::execution_payload_header::ExecutionPayloadHeader;
|
||||
pub use crate::fork::Fork;
|
||||
@ -179,6 +181,7 @@ pub type Hash256 = H256;
|
||||
pub type Uint256 = ethereum_types::U256;
|
||||
pub type Address = H160;
|
||||
pub type ForkVersion = [u8; 4];
|
||||
pub type Hash64 = ethereum_types::H64;
|
||||
|
||||
pub use bls::{
|
||||
AggregatePublicKey, AggregateSignature, Keypair, PublicKey, PublicKeyBytes, SecretKey,
|
||||
|
@ -14,7 +14,7 @@ serde_derive = "1.0.116"
|
||||
eth2_serde_utils = "0.1.1"
|
||||
hex = "0.4.2"
|
||||
eth2_hashing = "0.3.0"
|
||||
ethereum-types = "0.12.1"
|
||||
ethereum-types = "0.14.1"
|
||||
arbitrary = { version = "1.0", features = ["derive"], optional = true }
|
||||
zeroize = { version = "1.4.2", features = ["zeroize_derive"] }
|
||||
blst = { version = "0.3.3", optional = true }
|
||||
|
@ -1697,3 +1697,22 @@ fn gui_flag() {
|
||||
assert!(config.validator_monitor_auto);
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn optimistic_finalized_sync_default() {
|
||||
CommandLineTest::new()
|
||||
.run_with_zero_port()
|
||||
.with_config(|config| {
|
||||
assert!(config.chain.optimistic_finalized_sync);
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn disable_optimistic_finalized_sync() {
|
||||
CommandLineTest::new()
|
||||
.flag("disable-optimistic-finalized-sync", None)
|
||||
.run_with_zero_port()
|
||||
.with_config(|config| {
|
||||
assert!(!config.chain.optimistic_finalized_sync);
|
||||
});
|
||||
}
|
||||
|
@ -15,7 +15,7 @@ bls = { path = "../../crypto/bls", default-features = false }
|
||||
compare_fields = { path = "../../common/compare_fields" }
|
||||
compare_fields_derive = { path = "../../common/compare_fields_derive" }
|
||||
derivative = "2.1.1"
|
||||
ethereum-types = "0.12.1"
|
||||
ethereum-types = "0.14.1"
|
||||
hex = "0.4.2"
|
||||
rayon = "1.4.1"
|
||||
serde = "1.0.116"
|
||||
|
@ -15,8 +15,8 @@ execution_layer = { path = "../../beacon_node/execution_layer" }
|
||||
sensitive_url = { path = "../../common/sensitive_url" }
|
||||
types = { path = "../../consensus/types" }
|
||||
unused_port = { path = "../../common/unused_port" }
|
||||
ethers-core = "0.17.0"
|
||||
ethers-providers = "0.17.0"
|
||||
ethers-core = "1.0.2"
|
||||
ethers-providers = "1.0.2"
|
||||
deposit_contract = { path = "../../common/deposit_contract" }
|
||||
reqwest = { version = "0.11.0", features = ["json"] }
|
||||
hex = "0.4.2"
|
||||
|
Loading…
Reference in New Issue
Block a user