mirror of
https://github.com/paradigmxyz/reth.git
synced 2026-04-30 03:01:58 -04:00
Compare commits
21 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f568349be9 | ||
|
|
62abfdaeb5 | ||
|
|
256a9fdb79 | ||
|
|
4d9aff99bf | ||
|
|
28bb2891bb | ||
|
|
1d8f265744 | ||
|
|
c754caf8c7 | ||
|
|
e1b0046329 | ||
|
|
ddfe177578 | ||
|
|
178558c6d7 | ||
|
|
f4d3a9701f | ||
|
|
42e41a9370 | ||
|
|
a66dcce834 | ||
|
|
21d835cf2b | ||
|
|
29438631be | ||
|
|
0eb4e0ce29 | ||
|
|
9147f9aafe | ||
|
|
13b111e058 | ||
|
|
25c247b14c | ||
|
|
72bea44d8c | ||
|
|
63b9d5fe57 |
274
Cargo.lock
generated
274
Cargo.lock
generated
@@ -177,9 +177,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "alloy-dyn-abi"
|
||||
version = "1.4.1"
|
||||
version = "1.5.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3fdff496dd4e98a81f4861e66f7eaf5f2488971848bb42d9c892f871730245c8"
|
||||
checksum = "0d48a9101f4a67c22fae57489f1ddf3057b8ab4a368d8eac3be088b6e9d9c9d9"
|
||||
dependencies = [
|
||||
"alloy-json-abi",
|
||||
"alloy-primitives",
|
||||
@@ -329,9 +329,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "alloy-json-abi"
|
||||
version = "1.5.0"
|
||||
version = "1.5.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6bfca3dbbcb7498f0f60e67aff2ad6aff57032e22eb2fd03189854be11a22c03"
|
||||
checksum = "9914c147bb9b25f440eca68a31dc29f5c22298bfa7754aa802965695384122b0"
|
||||
dependencies = [
|
||||
"alloy-primitives",
|
||||
"alloy-sol-type-parser",
|
||||
@@ -426,9 +426,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "alloy-primitives"
|
||||
version = "1.5.0"
|
||||
version = "1.5.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5c850e6ccbd34b8a463a1e934ffc8fc00e1efc5e5489f2ad82d7797949f3bd4e"
|
||||
checksum = "7db950a29746be9e2f2c6288c8bd7a6202a81f999ce109a2933d2379970ec0fa"
|
||||
dependencies = [
|
||||
"alloy-rlp",
|
||||
"arbitrary",
|
||||
@@ -436,6 +436,7 @@ dependencies = [
|
||||
"cfg-if",
|
||||
"const-hex",
|
||||
"derive_more",
|
||||
"fixed-cache",
|
||||
"foldhash 0.2.0",
|
||||
"getrandom 0.3.4",
|
||||
"hashbrown 0.16.1",
|
||||
@@ -782,9 +783,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "alloy-sol-macro"
|
||||
version = "1.5.0"
|
||||
version = "1.5.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b2218e3aeb3ee665d117fdf188db0d5acfdc3f7b7502c827421cb78f26a2aec0"
|
||||
checksum = "a3b96d5f5890605ba9907ce1e2158e2701587631dc005bfa582cf92dd6f21147"
|
||||
dependencies = [
|
||||
"alloy-sol-macro-expander",
|
||||
"alloy-sol-macro-input",
|
||||
@@ -796,9 +797,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "alloy-sol-macro-expander"
|
||||
version = "1.5.0"
|
||||
version = "1.5.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b231cb8cc48e66dd1c6e11a1402f3ac86c3667cbc13a6969a0ac030ba7bb8c88"
|
||||
checksum = "b8247b7cca5cde556e93f8b3882b01dbd272f527836049083d240c57bf7b4c15"
|
||||
dependencies = [
|
||||
"alloy-sol-macro-input",
|
||||
"const-hex",
|
||||
@@ -814,9 +815,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "alloy-sol-macro-input"
|
||||
version = "1.5.0"
|
||||
version = "1.5.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "49a522d79929c1bf0152b07567a38f7eaed3ab149e53e7528afa78ff11994668"
|
||||
checksum = "3cd54f38512ac7bae10bbc38480eefb1b9b398ca2ce25db9cc0c048c6411c4f1"
|
||||
dependencies = [
|
||||
"const-hex",
|
||||
"dunce",
|
||||
@@ -830,9 +831,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "alloy-sol-type-parser"
|
||||
version = "1.5.0"
|
||||
version = "1.5.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0475c459859c8d9428af6ff3736614655a57efda8cc435a3b8b4796fa5ac1dd0"
|
||||
checksum = "444b09815b44899564566d4d56613d14fa9a274b1043a021f00468568752f449"
|
||||
dependencies = [
|
||||
"serde",
|
||||
"winnow",
|
||||
@@ -840,9 +841,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "alloy-sol-types"
|
||||
version = "1.5.0"
|
||||
version = "1.5.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "35287d9d821d5f26011bcd8d9101340898f761c9933cf50fca689bb7ed62fdeb"
|
||||
checksum = "dc1038284171df8bfd48befc0c7b78f667a7e2be162f45f07bd1c378078ebe58"
|
||||
dependencies = [
|
||||
"alloy-json-abi",
|
||||
"alloy-primitives",
|
||||
@@ -1939,9 +1940,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "bumpalo"
|
||||
version = "3.19.0"
|
||||
version = "3.19.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "46c5e41b57b8bba42a04676d81cb89e9ee8e859a1a66f80a5a72e1cb76b34d43"
|
||||
checksum = "5dd9dc738b7a8311c7ade152424974d8115f2cdad61e8dab8dac9f2362298510"
|
||||
|
||||
[[package]]
|
||||
name = "byte-slice-cast"
|
||||
@@ -2018,9 +2019,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "camino"
|
||||
version = "1.2.1"
|
||||
version = "1.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "276a59bf2b2c967788139340c9f0c5b12d7fd6630315c15c217e559de85d2609"
|
||||
checksum = "e629a66d692cb9ff1a1c664e41771b3dcaf961985a9774c0eb0bd1b51cf60a48"
|
||||
dependencies = [
|
||||
"serde_core",
|
||||
]
|
||||
@@ -2131,7 +2132,7 @@ dependencies = [
|
||||
"num-traits",
|
||||
"serde",
|
||||
"wasm-bindgen",
|
||||
"windows-link 0.2.1",
|
||||
"windows-link",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -3986,6 +3987,15 @@ dependencies = [
|
||||
"windows-sys 0.60.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "fixed-cache"
|
||||
version = "0.1.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ba59b6c98ba422a13f17ee1305c995cb5742bba7997f5b4d9af61b2ff0ffb213"
|
||||
dependencies = [
|
||||
"equivalent",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "fixed-hash"
|
||||
version = "0.8.0"
|
||||
@@ -4229,16 +4239,17 @@ checksum = "42012b0f064e01aa58b545fe3727f90f7dd4020f4a3ea735b50344965f5a57e9"
|
||||
|
||||
[[package]]
|
||||
name = "generator"
|
||||
version = "0.8.7"
|
||||
version = "0.8.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "605183a538e3e2a9c1038635cc5c2d194e2ee8fd0d1b66b8349fad7dbacce5a2"
|
||||
checksum = "52f04ae4152da20c76fe800fa48659201d5cf627c5149ca0b707b69d7eef6cf9"
|
||||
dependencies = [
|
||||
"cc",
|
||||
"cfg-if",
|
||||
"libc",
|
||||
"log",
|
||||
"rustversion",
|
||||
"windows 0.61.3",
|
||||
"windows-link",
|
||||
"windows-result 0.4.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -5017,13 +5028,14 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "insta"
|
||||
version = "1.44.3"
|
||||
version = "1.45.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b5c943d4415edd8153251b6f197de5eb1640e56d84e8d9159bea190421c73698"
|
||||
checksum = "b76866be74d68b1595eb8060cb9191dca9c021db2316558e52ddc5d55d41b66c"
|
||||
dependencies = [
|
||||
"console",
|
||||
"once_cell",
|
||||
"similar",
|
||||
"tempfile",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -5146,9 +5158,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "itoa"
|
||||
version = "1.0.15"
|
||||
version = "1.0.16"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c"
|
||||
checksum = "7ee5b5339afb4c41626dde77b7a611bd4f2c202b897852b4bcf5d03eddc61010"
|
||||
|
||||
[[package]]
|
||||
name = "jni"
|
||||
@@ -5464,7 +5476,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d7c4b02199fee7c5d21a5ae7d8cfa79a6ef5bb2fc834d6e9058e89c825efdc55"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"windows-link 0.2.1",
|
||||
"windows-link",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -5505,13 +5517,13 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "libredox"
|
||||
version = "0.1.10"
|
||||
version = "0.1.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "416f7e718bdb06000964960ffa43b4335ad4012ae8b99060261aa4a8088d5ccb"
|
||||
checksum = "df15f6eac291ed1cf25865b1ee60399f57e7c227e7f51bdbd4c5270396a9ed50"
|
||||
dependencies = [
|
||||
"bitflags 2.10.0",
|
||||
"libc",
|
||||
"redox_syscall",
|
||||
"redox_syscall 0.6.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -6020,9 +6032,9 @@ checksum = "5e0826a989adedc2a244799e823aece04662b66609d96af8dff7ac6df9a8925d"
|
||||
|
||||
[[package]]
|
||||
name = "ntapi"
|
||||
version = "0.4.1"
|
||||
version = "0.4.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e8a3895c6391c39d7fe7ebc444a87eb2991b2a0bc718fdabd071eec617fc68e4"
|
||||
checksum = "c70f219e21142367c70c0b30c6a9e3a14d55b4d12a204d897fbec83a0363f081"
|
||||
dependencies = [
|
||||
"winapi",
|
||||
]
|
||||
@@ -6545,9 +6557,9 @@ checksum = "2621685985a2ebf1c516881c026032ac7deafcda1a2c9b7850dc81e3dfcb64c1"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"libc",
|
||||
"redox_syscall",
|
||||
"redox_syscall 0.5.18",
|
||||
"smallvec",
|
||||
"windows-link 0.2.1",
|
||||
"windows-link",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -6744,9 +6756,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "portable-atomic"
|
||||
version = "1.11.1"
|
||||
version = "1.12.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f84267b20a16ea918e43c6a88433c2d54fa145c92a811b5b047ccbe153674483"
|
||||
checksum = "f59e70c4aef1e55797c2e8fd94a4f2a973fc972cfde0e0b05f683667b0cd39dd"
|
||||
|
||||
[[package]]
|
||||
name = "potential_utf"
|
||||
@@ -6818,7 +6830,7 @@ version = "3.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "219cb19e96be00ab2e37d6e299658a0cfa83e52429179969b0f0121b4ac46983"
|
||||
dependencies = [
|
||||
"toml_edit 0.23.9",
|
||||
"toml_edit 0.23.10+spec-1.0.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -7212,9 +7224,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "rapidhash"
|
||||
version = "4.1.1"
|
||||
version = "4.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d8e65c75143ce5d47c55b510297eeb1182f3c739b6043c537670e9fc18612dae"
|
||||
checksum = "2988730ee014541157f48ce4dcc603940e00915edc3c7f9a8d78092256bb2493"
|
||||
dependencies = [
|
||||
"rand 0.9.2",
|
||||
"rustversion",
|
||||
@@ -7285,6 +7297,15 @@ dependencies = [
|
||||
"bitflags 2.10.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "redox_syscall"
|
||||
version = "0.6.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ec96166dafa0886eb81fe1c0a388bece180fbef2135f97c1e2cf8302e74b43b5"
|
||||
dependencies = [
|
||||
"bitflags 2.10.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "redox_users"
|
||||
version = "0.4.6"
|
||||
@@ -7374,9 +7395,9 @@ checksum = "ba39f3699c378cd8970968dcbff9c43159ea4cfbd88d43c00b22f2ef10a435d2"
|
||||
|
||||
[[package]]
|
||||
name = "reqwest"
|
||||
version = "0.12.25"
|
||||
version = "0.12.26"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b6eff9328d40131d43bd911d42d79eb6a47312002a4daefc9e37f17e74a7701a"
|
||||
checksum = "3b4c14b2d9afca6a60277086b0cc6a6ae0b568f6f7916c943a8cdc79f8be240f"
|
||||
dependencies = [
|
||||
"base64 0.22.1",
|
||||
"bytes",
|
||||
@@ -9613,6 +9634,7 @@ dependencies = [
|
||||
"alloy-consensus",
|
||||
"alloy-genesis",
|
||||
"alloy-network",
|
||||
"alloy-op-hardforks",
|
||||
"alloy-primitives",
|
||||
"alloy-rpc-types-engine",
|
||||
"alloy-rpc-types-eth",
|
||||
@@ -10829,6 +10851,7 @@ dependencies = [
|
||||
"tracing-appender",
|
||||
"tracing-journald",
|
||||
"tracing-logfmt",
|
||||
"tracing-samply",
|
||||
"tracing-subscriber 0.3.22",
|
||||
]
|
||||
|
||||
@@ -11592,9 +11615,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "rustls-pki-types"
|
||||
version = "1.13.1"
|
||||
version = "1.13.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "708c0f9d5f54ba0272468c1d306a52c495b31fa155e91bc25371e6df7996908c"
|
||||
checksum = "21e6f2ab2928ca4291b86736a8bd920a277a399bba1589409d72154ff87c1282"
|
||||
dependencies = [
|
||||
"web-time",
|
||||
"zeroize",
|
||||
@@ -11658,9 +11681,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "ryu"
|
||||
version = "1.0.20"
|
||||
version = "1.0.21"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f"
|
||||
checksum = "62049b2877bf12821e8f9ad256ee38fdc31db7387ec2d3b3f403024de2034aea"
|
||||
|
||||
[[package]]
|
||||
name = "ryu-js"
|
||||
@@ -12358,9 +12381,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "syn-solidity"
|
||||
version = "1.5.0"
|
||||
version = "1.5.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "60ceeb7c95a4536de0c0e1649bd98d1a72a4bb9590b1f3e45a8a0bfdb7c188c0"
|
||||
checksum = "f6b1d2e2059056b66fec4a6bb2b79511d5e8d76196ef49c38996f4b48db7662f"
|
||||
dependencies = [
|
||||
"paste",
|
||||
"proc-macro2",
|
||||
@@ -12818,9 +12841,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "toml_datetime"
|
||||
version = "0.7.3"
|
||||
version = "0.7.5+spec-1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f2cdb639ebbc97961c51720f858597f7f24c4fc295327923af55b74c3c724533"
|
||||
checksum = "92e1cfed4a3038bc5a127e35a2d360f145e1f4b971b551a2ba5fd7aedf7e1347"
|
||||
dependencies = [
|
||||
"serde_core",
|
||||
]
|
||||
@@ -12841,21 +12864,21 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "toml_edit"
|
||||
version = "0.23.9"
|
||||
version = "0.23.10+spec-1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5d7cbc3b4b49633d57a0509303158ca50de80ae32c265093b24c414705807832"
|
||||
checksum = "84c8b9f757e028cee9fa244aea147aab2a9ec09d5325a9b01e0a49730c2b5269"
|
||||
dependencies = [
|
||||
"indexmap 2.12.1",
|
||||
"toml_datetime 0.7.3",
|
||||
"toml_datetime 0.7.5+spec-1.1.0",
|
||||
"toml_parser",
|
||||
"winnow",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "toml_parser"
|
||||
version = "1.0.4"
|
||||
version = "1.0.6+spec-1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c0cbe268d35bdb4bb5a56a2de88d0ad0eb70af5384a99d648cd4b3d04039800e"
|
||||
checksum = "a3198b4b0a8e11f09dd03e133c0280504d0801269e9afa46362ffde1cbeebf44"
|
||||
dependencies = [
|
||||
"winnow",
|
||||
]
|
||||
@@ -12968,9 +12991,9 @@ checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3"
|
||||
|
||||
[[package]]
|
||||
name = "tracing"
|
||||
version = "0.1.43"
|
||||
version = "0.1.44"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2d15d90a0b5c19378952d479dc858407149d7bb45a14de0142f6c534b16fc647"
|
||||
checksum = "63e71662fa4b2a2c3a26f570f037eb95bb1f85397f3cd8076caed2f026a6d100"
|
||||
dependencies = [
|
||||
"log",
|
||||
"pin-project-lite",
|
||||
@@ -13003,9 +13026,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "tracing-core"
|
||||
version = "0.1.35"
|
||||
version = "0.1.36"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7a04e24fab5c89c6a36eb8558c9656f30d81de51dfa4d3b45f26b21d61fa0a6c"
|
||||
checksum = "db97caf9d906fbde555dd62fa95ddba9eecfd14cb388e4f491a66d74cd5fb79a"
|
||||
dependencies = [
|
||||
"once_cell",
|
||||
"valuable",
|
||||
@@ -13074,6 +13097,22 @@ dependencies = [
|
||||
"web-time",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tracing-samply"
|
||||
version = "0.1.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c175f7ecc002b6ef04776a39f440503e4e788790ddbdbfac8259b7a069526334"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"itoa",
|
||||
"libc",
|
||||
"mach2",
|
||||
"memmap2",
|
||||
"smallvec",
|
||||
"tracing-core",
|
||||
"tracing-subscriber 0.3.22",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tracing-serde"
|
||||
version = "0.2.0"
|
||||
@@ -13685,38 +13724,16 @@ dependencies = [
|
||||
"windows-targets 0.52.6",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows"
|
||||
version = "0.61.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9babd3a767a4c1aef6900409f85f5d53ce2544ccdfaa86dad48c91782c6d6893"
|
||||
dependencies = [
|
||||
"windows-collections 0.2.0",
|
||||
"windows-core 0.61.2",
|
||||
"windows-future 0.2.1",
|
||||
"windows-link 0.1.3",
|
||||
"windows-numerics 0.2.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows"
|
||||
version = "0.62.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "527fadee13e0c05939a6a05d5bd6eec6cd2e3dbd648b9f8e447c6518133d8580"
|
||||
dependencies = [
|
||||
"windows-collections 0.3.2",
|
||||
"windows-collections",
|
||||
"windows-core 0.62.2",
|
||||
"windows-future 0.3.2",
|
||||
"windows-numerics 0.3.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-collections"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3beeceb5e5cfd9eb1d76b381630e82c4241ccd0d27f1a39ed41b2760b255c5e8"
|
||||
dependencies = [
|
||||
"windows-core 0.61.2",
|
||||
"windows-future",
|
||||
"windows-numerics",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -13740,19 +13757,6 @@ dependencies = [
|
||||
"windows-targets 0.52.6",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-core"
|
||||
version = "0.61.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c0fdd3ddb90610c7638aa2b3a3ab2904fb9e5cdbecc643ddb3647212781c4ae3"
|
||||
dependencies = [
|
||||
"windows-implement 0.60.2",
|
||||
"windows-interface 0.59.3",
|
||||
"windows-link 0.1.3",
|
||||
"windows-result 0.3.4",
|
||||
"windows-strings 0.4.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-core"
|
||||
version = "0.62.2"
|
||||
@@ -13761,20 +13765,9 @@ checksum = "b8e83a14d34d0623b51dce9581199302a221863196a1dde71a7663a4c2be9deb"
|
||||
dependencies = [
|
||||
"windows-implement 0.60.2",
|
||||
"windows-interface 0.59.3",
|
||||
"windows-link 0.2.1",
|
||||
"windows-link",
|
||||
"windows-result 0.4.1",
|
||||
"windows-strings 0.5.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-future"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fc6a41e98427b19fe4b73c550f060b59fa592d7d686537eebf9385621bfbad8e"
|
||||
dependencies = [
|
||||
"windows-core 0.61.2",
|
||||
"windows-link 0.1.3",
|
||||
"windows-threading 0.1.0",
|
||||
"windows-strings",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -13784,8 +13777,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e1d6f90251fe18a279739e78025bd6ddc52a7e22f921070ccdc67dde84c605cb"
|
||||
dependencies = [
|
||||
"windows-core 0.62.2",
|
||||
"windows-link 0.2.1",
|
||||
"windows-threading 0.2.1",
|
||||
"windows-link",
|
||||
"windows-threading",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -13832,28 +13825,12 @@ dependencies = [
|
||||
"syn 2.0.111",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-link"
|
||||
version = "0.1.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5e6ad25900d524eaabdbbb96d20b4311e1e7ae1699af4fb28c17ae66c80d798a"
|
||||
|
||||
[[package]]
|
||||
name = "windows-link"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5"
|
||||
|
||||
[[package]]
|
||||
name = "windows-numerics"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9150af68066c4c5c07ddc0ce30421554771e528bde427614c61038bc2c92c2b1"
|
||||
dependencies = [
|
||||
"windows-core 0.61.2",
|
||||
"windows-link 0.1.3",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-numerics"
|
||||
version = "0.3.1"
|
||||
@@ -13861,7 +13838,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6e2e40844ac143cdb44aead537bbf727de9b044e107a0f1220392177d15b0f26"
|
||||
dependencies = [
|
||||
"windows-core 0.62.2",
|
||||
"windows-link 0.2.1",
|
||||
"windows-link",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -13873,31 +13850,13 @@ dependencies = [
|
||||
"windows-targets 0.52.6",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-result"
|
||||
version = "0.3.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "56f42bd332cc6c8eac5af113fc0c1fd6a8fd2aa08a0119358686e5160d0586c6"
|
||||
dependencies = [
|
||||
"windows-link 0.1.3",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-result"
|
||||
version = "0.4.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7781fa89eaf60850ac3d2da7af8e5242a5ea78d1a11c49bf2910bb5a73853eb5"
|
||||
dependencies = [
|
||||
"windows-link 0.2.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-strings"
|
||||
version = "0.4.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "56e6c93f3a0c3b36176cb1327a4958a0353d5d166c2a35cb268ace15e91d3b57"
|
||||
dependencies = [
|
||||
"windows-link 0.1.3",
|
||||
"windows-link",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -13906,7 +13865,7 @@ version = "0.5.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7837d08f69c77cf6b07689544538e017c1bfcf57e34b4c0ff58e6c2cd3b37091"
|
||||
dependencies = [
|
||||
"windows-link 0.2.1",
|
||||
"windows-link",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -13960,7 +13919,7 @@ version = "0.61.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc"
|
||||
dependencies = [
|
||||
"windows-link 0.2.1",
|
||||
"windows-link",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -14015,7 +13974,7 @@ version = "0.53.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4945f9f551b88e0d65f3db0bc25c33b8acea4d9e41163edf90dcd0b19f9069f3"
|
||||
dependencies = [
|
||||
"windows-link 0.2.1",
|
||||
"windows-link",
|
||||
"windows_aarch64_gnullvm 0.53.1",
|
||||
"windows_aarch64_msvc 0.53.1",
|
||||
"windows_i686_gnu 0.53.1",
|
||||
@@ -14026,22 +13985,13 @@ dependencies = [
|
||||
"windows_x86_64_msvc 0.53.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-threading"
|
||||
version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b66463ad2e0ea3bbf808b7f1d371311c80e115c0b71d60efc142cafbcfb057a6"
|
||||
dependencies = [
|
||||
"windows-link 0.1.3",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-threading"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3949bd5b99cafdf1c7ca86b43ca564028dfe27d66958f2470940f73d86d75b37"
|
||||
dependencies = [
|
||||
"windows-link 0.2.1",
|
||||
"windows-link",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
||||
@@ -730,6 +730,7 @@ socket2 = { version = "0.5", default-features = false }
|
||||
sysinfo = { version = "0.33", default-features = false }
|
||||
tracing-journald = "0.3"
|
||||
tracing-logfmt = "0.3.3"
|
||||
tracing-samply = "0.1"
|
||||
tracing-subscriber = { version = "0.3", default-features = false }
|
||||
triehash = "0.8"
|
||||
typenum = "1.15.0"
|
||||
|
||||
@@ -329,6 +329,7 @@ pub(crate) async fn run_comparison(args: Args, _ctx: CliContext) -> Result<()> {
|
||||
output_dir.clone(),
|
||||
git_manager.clone(),
|
||||
args.features.clone(),
|
||||
args.profile,
|
||||
)?;
|
||||
// Initialize node manager
|
||||
let mut node_manager = NodeManager::new(&args);
|
||||
|
||||
@@ -14,6 +14,7 @@ pub(crate) struct CompilationManager {
|
||||
output_dir: PathBuf,
|
||||
git_manager: GitManager,
|
||||
features: String,
|
||||
enable_profiling: bool,
|
||||
}
|
||||
|
||||
impl CompilationManager {
|
||||
@@ -23,8 +24,9 @@ impl CompilationManager {
|
||||
output_dir: PathBuf,
|
||||
git_manager: GitManager,
|
||||
features: String,
|
||||
enable_profiling: bool,
|
||||
) -> Result<Self> {
|
||||
Ok(Self { repo_root, output_dir, git_manager, features })
|
||||
Ok(Self { repo_root, output_dir, git_manager, features, enable_profiling })
|
||||
}
|
||||
|
||||
/// Detect if the RPC endpoint is an Optimism chain
|
||||
@@ -100,9 +102,18 @@ impl CompilationManager {
|
||||
let mut cmd = Command::new("cargo");
|
||||
cmd.arg("build").arg("--profile").arg("profiling");
|
||||
|
||||
// Add features
|
||||
cmd.arg("--features").arg(&self.features);
|
||||
info!("Using features: {}", self.features);
|
||||
// Append samply feature when profiling to enable tracing span markers.
|
||||
// NOTE: The `samply` feature must exist in the branch being compiled. If comparing
|
||||
// against an older branch that predates the samply integration, compilation will fail
|
||||
// or markers won't appear. In that case, omit --profile or ensure both branches
|
||||
// include the samply feature support.
|
||||
let features = if self.enable_profiling && !self.features.contains("samply") {
|
||||
format!("{},samply", self.features)
|
||||
} else {
|
||||
self.features.clone()
|
||||
};
|
||||
cmd.arg("--features").arg(&features);
|
||||
info!("Using features: {}", features);
|
||||
|
||||
// Add bin-specific arguments for optimism
|
||||
if is_optimism {
|
||||
|
||||
@@ -87,6 +87,10 @@ otlp = [
|
||||
"reth-ethereum-cli/otlp",
|
||||
"reth-node-core/otlp",
|
||||
]
|
||||
samply = [
|
||||
"reth-ethereum-cli/samply",
|
||||
"reth-node-core/samply",
|
||||
]
|
||||
js-tracer = [
|
||||
"reth-node-builder/js-tracer",
|
||||
"reth-node-ethereum/js-tracer",
|
||||
@@ -103,6 +107,7 @@ asm-keccak = [
|
||||
"reth-node-ethereum/asm-keccak",
|
||||
]
|
||||
keccak-cache-global = [
|
||||
"reth-node-core/keccak-cache-global",
|
||||
"reth-node-ethereum/keccak-cache-global",
|
||||
]
|
||||
jemalloc = [
|
||||
|
||||
@@ -115,6 +115,10 @@ harness = false
|
||||
name = "state_root_task"
|
||||
harness = false
|
||||
|
||||
[[bench]]
|
||||
name = "state_provider_builder"
|
||||
harness = false
|
||||
|
||||
[features]
|
||||
test-utils = [
|
||||
"reth-chain-state/test-utils",
|
||||
|
||||
49
crates/engine/tree/benches/state_provider_builder.rs
Normal file
49
crates/engine/tree/benches/state_provider_builder.rs
Normal file
@@ -0,0 +1,49 @@
|
||||
//! Benchmark for state provider builder reuse.
|
||||
|
||||
#![allow(missing_docs)]
|
||||
|
||||
use alloy_consensus::Header;
|
||||
use alloy_primitives::B256;
|
||||
use criterion::{criterion_group, criterion_main, BenchmarkId, Criterion};
|
||||
use reth_engine_tree::tree::StateProviderBuilder;
|
||||
use reth_ethereum_primitives::EthPrimitives;
|
||||
use reth_provider::{test_utils::MockEthProvider, HeaderProvider};
|
||||
use std::hint::black_box;
|
||||
|
||||
fn build_builder(
|
||||
provider: &MockEthProvider<EthPrimitives>,
|
||||
hash: B256,
|
||||
) -> StateProviderBuilder<EthPrimitives, MockEthProvider<EthPrimitives>> {
|
||||
let header = provider.header(hash).expect("header lookup failed");
|
||||
assert!(header.is_some(), "missing header for hash");
|
||||
StateProviderBuilder::new(provider.clone(), hash, None)
|
||||
}
|
||||
|
||||
fn bench_state_provider_builder(c: &mut Criterion) {
|
||||
let provider = MockEthProvider::<EthPrimitives>::new();
|
||||
let hash = B256::from([0x11u8; 32]);
|
||||
let header = Header { number: 1, ..Header::default() };
|
||||
provider.add_header(hash, header);
|
||||
|
||||
let mut group = c.benchmark_group("state_provider_builder_reuse");
|
||||
|
||||
group.bench_with_input(BenchmarkId::new("single_lookup", 1), &hash, |b, hash| {
|
||||
b.iter(|| {
|
||||
let builder = build_builder(&provider, *hash);
|
||||
black_box(builder);
|
||||
});
|
||||
});
|
||||
|
||||
group.bench_with_input(BenchmarkId::new("double_lookup", 2), &hash, |b, hash| {
|
||||
b.iter(|| {
|
||||
let first = build_builder(&provider, *hash);
|
||||
let second = build_builder(&provider, *hash);
|
||||
black_box((first, second));
|
||||
});
|
||||
});
|
||||
|
||||
group.finish();
|
||||
}
|
||||
|
||||
criterion_group!(benches, bench_state_provider_builder);
|
||||
criterion_main!(benches);
|
||||
@@ -1,5 +1,4 @@
|
||||
use crate::metrics::PersistenceMetrics;
|
||||
use alloy_consensus::BlockHeader;
|
||||
use alloy_eips::BlockNumHash;
|
||||
use reth_chain_state::ExecutedBlock;
|
||||
use reth_errors::ProviderError;
|
||||
@@ -142,27 +141,23 @@ where
|
||||
&self,
|
||||
blocks: Vec<ExecutedBlock<N::Primitives>>,
|
||||
) -> Result<Option<BlockNumHash>, PersistenceError> {
|
||||
let first_block_hash = blocks.first().map(|b| b.recovered_block.num_hash());
|
||||
let last_block_hash = blocks.last().map(|b| b.recovered_block.num_hash());
|
||||
debug!(target: "engine::persistence", first=?first_block_hash, last=?last_block_hash, "Saving range of blocks");
|
||||
let first_block = blocks.first().map(|b| b.recovered_block.num_hash());
|
||||
let last_block = blocks.last().map(|b| b.recovered_block.num_hash());
|
||||
debug!(target: "engine::persistence", first=?first_block, last=?last_block, "Saving range of blocks");
|
||||
|
||||
let start_time = Instant::now();
|
||||
let last_block_hash_num = blocks.last().map(|block| BlockNumHash {
|
||||
hash: block.recovered_block().hash(),
|
||||
number: block.recovered_block().header().number(),
|
||||
});
|
||||
|
||||
if last_block_hash_num.is_some() {
|
||||
if last_block.is_some() {
|
||||
let provider_rw = self.provider.database_provider_rw()?;
|
||||
|
||||
provider_rw.save_blocks(blocks)?;
|
||||
provider_rw.commit()?;
|
||||
}
|
||||
|
||||
debug!(target: "engine::persistence", first=?first_block_hash, last=?last_block_hash, "Saved range of blocks");
|
||||
debug!(target: "engine::persistence", first=?first_block, last=?last_block, "Saved range of blocks");
|
||||
|
||||
self.metrics.save_blocks_duration_seconds.record(start_time.elapsed());
|
||||
Ok(last_block_hash_num)
|
||||
Ok(last_block)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@ use std::collections::{BTreeMap, HashMap, HashSet, VecDeque};
|
||||
/// * [`BlockBuffer::remove_old_blocks`] to remove old blocks that precede the finalized number.
|
||||
///
|
||||
/// Note: Buffer is limited by number of blocks that it can contain and eviction of the block
|
||||
/// is done by last recently used block.
|
||||
/// is done in FIFO order (oldest inserted block is evicted first).
|
||||
#[derive(Debug)]
|
||||
pub struct BlockBuffer<B: Block> {
|
||||
/// All blocks in the buffer stored by their block hash.
|
||||
|
||||
@@ -321,7 +321,7 @@ where
|
||||
BlockReader<Block = N::Block, Header = N::BlockHeader>,
|
||||
C: ConfigureEvm<Primitives = N> + 'static,
|
||||
T: PayloadTypes<BuiltPayload: BuiltPayload<Primitives = N>>,
|
||||
V: EngineValidator<T>,
|
||||
V: EngineValidator<T, N>,
|
||||
{
|
||||
/// Creates a new [`EngineApiTreeHandler`].
|
||||
#[expect(clippy::too_many_arguments)]
|
||||
@@ -931,48 +931,6 @@ where
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Determines if the given block is part of a fork by checking that these
|
||||
/// conditions are true:
|
||||
/// * walking back from the target hash to verify that the target hash is not part of an
|
||||
/// extension of the canonical chain.
|
||||
/// * walking back from the current head to verify that the target hash is not already part of
|
||||
/// the canonical chain.
|
||||
///
|
||||
/// The header is required as an arg, because we might be checking that the header is a fork
|
||||
/// block before it's in the tree state and before it's in the database.
|
||||
fn is_fork(&self, target: BlockWithParent) -> ProviderResult<bool> {
|
||||
let target_hash = target.block.hash;
|
||||
// verify that the given hash is not part of an extension of the canon chain.
|
||||
let canonical_head = self.state.tree_state.canonical_head();
|
||||
let mut current_hash;
|
||||
let mut current_block = target;
|
||||
loop {
|
||||
if current_block.block.hash == canonical_head.hash {
|
||||
return Ok(false)
|
||||
}
|
||||
// We already passed the canonical head
|
||||
if current_block.block.number <= canonical_head.number {
|
||||
break
|
||||
}
|
||||
current_hash = current_block.parent;
|
||||
|
||||
let Some(next_block) = self.sealed_header_by_hash(current_hash)? else { break };
|
||||
current_block = next_block.block_with_parent();
|
||||
}
|
||||
|
||||
// verify that the given hash is not already part of canonical chain stored in memory
|
||||
if self.canonical_in_memory_state.header_by_hash(target_hash).is_some() {
|
||||
return Ok(false)
|
||||
}
|
||||
|
||||
// verify that the given hash is not already part of persisted canonical chain
|
||||
if self.provider.block_number(target_hash)?.is_some() {
|
||||
return Ok(false)
|
||||
}
|
||||
|
||||
Ok(true)
|
||||
}
|
||||
|
||||
/// Invoked when we receive a new forkchoice update message. Calls into the blockchain tree
|
||||
/// to resolve chain forks and ensure that the Execution Layer is working with the latest valid
|
||||
/// chain.
|
||||
@@ -2479,7 +2437,9 @@ where
|
||||
self.insert_block_or_payload(
|
||||
payload.block_with_parent(),
|
||||
payload,
|
||||
|validator, payload, ctx| validator.validate_payload(payload, ctx),
|
||||
|validator, payload, ctx, provider_builder| {
|
||||
validator.validate_payload(payload, ctx, provider_builder)
|
||||
},
|
||||
|this, payload| Ok(this.payload_validator.convert_payload_to_block(payload)?),
|
||||
)
|
||||
}
|
||||
@@ -2491,7 +2451,9 @@ where
|
||||
self.insert_block_or_payload(
|
||||
block.block_with_parent(),
|
||||
block,
|
||||
|validator, block, ctx| validator.validate_block(block, ctx),
|
||||
|validator, block, ctx, provider_builder| {
|
||||
validator.validate_block(block, ctx, provider_builder)
|
||||
},
|
||||
|_, block| Ok(block),
|
||||
)
|
||||
}
|
||||
@@ -2517,7 +2479,12 @@ where
|
||||
&mut self,
|
||||
block_id: BlockWithParent,
|
||||
input: Input,
|
||||
execute: impl FnOnce(&mut V, Input, TreeCtx<'_, N>) -> Result<ExecutedBlock<N>, Err>,
|
||||
execute: impl FnOnce(
|
||||
&mut V,
|
||||
Input,
|
||||
TreeCtx<'_, N>,
|
||||
V::ProviderBuilder,
|
||||
) -> Result<ExecutedBlock<N>, Err>,
|
||||
convert_to_block: impl FnOnce(&mut Self, Input) -> Result<SealedBlock<N::Block>, Err>,
|
||||
) -> Result<InsertPayloadOk, Err>
|
||||
where
|
||||
@@ -2542,7 +2509,7 @@ where
|
||||
};
|
||||
|
||||
// Ensure that the parent state is available.
|
||||
match self.state_provider_builder(block_id.parent) {
|
||||
let provider_builder = match self.payload_validator.provider_builder(block_id.parent, &self.state) {
|
||||
Err(err) => {
|
||||
let block = convert_to_block(self, input)?;
|
||||
return Err(InsertBlockError::new(block, err.into()).into());
|
||||
@@ -2566,23 +2533,20 @@ where
|
||||
missing_ancestor,
|
||||
}))
|
||||
}
|
||||
Ok(Some(_)) => {}
|
||||
}
|
||||
|
||||
// determine whether we are on a fork chain
|
||||
let is_fork = match self.is_fork(block_id) {
|
||||
Err(err) => {
|
||||
let block = convert_to_block(self, input)?;
|
||||
return Err(InsertBlockError::new(block, err.into()).into());
|
||||
}
|
||||
Ok(is_fork) => is_fork,
|
||||
Ok(Some(provider_builder)) => provider_builder,
|
||||
};
|
||||
|
||||
// determine whether we are on a fork chain by comparing the block number with the
|
||||
// canonical head. This is a simple check that is sufficient for the event emission below.
|
||||
// A block is considered a fork if its number is less than or equal to the canonical head,
|
||||
// as this indicates there's already a canonical block at that height.
|
||||
let is_fork = block_id.block.number <= self.state.tree_state.current_canonical_head.number;
|
||||
|
||||
let ctx = TreeCtx::new(&mut self.state, &self.canonical_in_memory_state);
|
||||
|
||||
let start = Instant::now();
|
||||
|
||||
let executed = execute(&mut self.payload_validator, input, ctx)?;
|
||||
let executed = execute(&mut self.payload_validator, input, ctx, provider_builder)?;
|
||||
|
||||
// if the parent is the canonical head, we can insert the block as the pending block
|
||||
if self.state.tree_state.canonical_block_hash() == executed.recovered_block().parent_hash()
|
||||
|
||||
@@ -3,11 +3,7 @@
|
||||
use crate::tree::payload_processor::bal::bal_to_hashed_post_state;
|
||||
use alloy_eip7928::BlockAccessList;
|
||||
use alloy_evm::block::StateChangeSource;
|
||||
use alloy_primitives::{
|
||||
keccak256,
|
||||
map::{B256Set, HashSet},
|
||||
B256,
|
||||
};
|
||||
use alloy_primitives::{keccak256, map::HashSet, B256};
|
||||
use crossbeam_channel::{unbounded, Receiver as CrossbeamReceiver, Sender as CrossbeamSender};
|
||||
use dashmap::DashMap;
|
||||
use derive_more::derive::Deref;
|
||||
@@ -23,7 +19,6 @@ use reth_trie_parallel::{
|
||||
proof::ParallelProof,
|
||||
proof_task::{
|
||||
AccountMultiproofInput, ProofResultContext, ProofResultMessage, ProofWorkerHandle,
|
||||
StorageProofInput,
|
||||
},
|
||||
};
|
||||
use std::{collections::BTreeMap, mem, ops::DerefMut, sync::Arc, time::Instant};
|
||||
@@ -236,74 +231,6 @@ pub(crate) fn evm_state_to_hashed_post_state(update: EvmState) -> HashedPostStat
|
||||
hashed_state
|
||||
}
|
||||
|
||||
/// A pending multiproof task, either [`StorageMultiproofInput`] or [`MultiproofInput`].
|
||||
#[derive(Debug)]
|
||||
enum PendingMultiproofTask {
|
||||
/// A storage multiproof task input.
|
||||
Storage(StorageMultiproofInput),
|
||||
/// A regular multiproof task input.
|
||||
Regular(MultiproofInput),
|
||||
}
|
||||
|
||||
impl PendingMultiproofTask {
|
||||
/// Returns the proof sequence number of the task.
|
||||
const fn proof_sequence_number(&self) -> u64 {
|
||||
match self {
|
||||
Self::Storage(input) => input.proof_sequence_number,
|
||||
Self::Regular(input) => input.proof_sequence_number,
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns whether or not the proof targets are empty.
|
||||
fn proof_targets_is_empty(&self) -> bool {
|
||||
match self {
|
||||
Self::Storage(input) => input.proof_targets.is_empty(),
|
||||
Self::Regular(input) => input.proof_targets.is_empty(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Destroys the input and sends a [`MultiProofMessage::EmptyProof`] message to the sender.
|
||||
fn send_empty_proof(self) {
|
||||
match self {
|
||||
Self::Storage(input) => input.send_empty_proof(),
|
||||
Self::Regular(input) => input.send_empty_proof(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<StorageMultiproofInput> for PendingMultiproofTask {
|
||||
fn from(input: StorageMultiproofInput) -> Self {
|
||||
Self::Storage(input)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<MultiproofInput> for PendingMultiproofTask {
|
||||
fn from(input: MultiproofInput) -> Self {
|
||||
Self::Regular(input)
|
||||
}
|
||||
}
|
||||
|
||||
/// Input parameters for dispatching a dedicated storage multiproof calculation.
|
||||
#[derive(Debug)]
|
||||
struct StorageMultiproofInput {
|
||||
hashed_state_update: HashedPostState,
|
||||
hashed_address: B256,
|
||||
proof_targets: B256Set,
|
||||
proof_sequence_number: u64,
|
||||
state_root_message_sender: CrossbeamSender<MultiProofMessage>,
|
||||
multi_added_removed_keys: Arc<MultiAddedRemovedKeys>,
|
||||
}
|
||||
|
||||
impl StorageMultiproofInput {
|
||||
/// Destroys the input and sends a [`MultiProofMessage::EmptyProof`] message to the sender.
|
||||
fn send_empty_proof(self) {
|
||||
let _ = self.state_root_message_sender.send(MultiProofMessage::EmptyProof {
|
||||
sequence_number: self.proof_sequence_number,
|
||||
state: self.hashed_state_update,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/// Input parameters for dispatching a multiproof calculation.
|
||||
#[derive(Debug)]
|
||||
struct MultiproofInput {
|
||||
@@ -378,91 +305,18 @@ impl MultiproofManager {
|
||||
}
|
||||
|
||||
/// Dispatches a new multiproof calculation to worker pools.
|
||||
fn dispatch(&self, input: PendingMultiproofTask) {
|
||||
fn dispatch(&self, input: MultiproofInput) {
|
||||
// If there are no proof targets, we can just send an empty multiproof back immediately
|
||||
if input.proof_targets_is_empty() {
|
||||
if input.proof_targets.is_empty() {
|
||||
trace!(
|
||||
sequence_number = input.proof_sequence_number(),
|
||||
sequence_number = input.proof_sequence_number,
|
||||
"No proof targets, sending empty multiproof back immediately"
|
||||
);
|
||||
input.send_empty_proof();
|
||||
return;
|
||||
}
|
||||
|
||||
match input {
|
||||
PendingMultiproofTask::Storage(storage_input) => {
|
||||
self.dispatch_storage_proof(storage_input);
|
||||
}
|
||||
PendingMultiproofTask::Regular(multiproof_input) => {
|
||||
self.dispatch_multiproof(multiproof_input);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Dispatches a single storage proof calculation to worker pool.
|
||||
fn dispatch_storage_proof(&self, storage_multiproof_input: StorageMultiproofInput) {
|
||||
let StorageMultiproofInput {
|
||||
hashed_state_update,
|
||||
hashed_address,
|
||||
proof_targets,
|
||||
proof_sequence_number,
|
||||
multi_added_removed_keys,
|
||||
state_root_message_sender: _,
|
||||
} = storage_multiproof_input;
|
||||
|
||||
let storage_targets = proof_targets.len();
|
||||
|
||||
trace!(
|
||||
target: "engine::tree::payload_processor::multiproof",
|
||||
proof_sequence_number,
|
||||
?proof_targets,
|
||||
storage_targets,
|
||||
"Dispatching storage proof to workers"
|
||||
);
|
||||
|
||||
let start = Instant::now();
|
||||
|
||||
// Create prefix set from targets
|
||||
let prefix_set = reth_trie::prefix_set::PrefixSetMut::from(
|
||||
proof_targets.iter().map(reth_trie::Nibbles::unpack),
|
||||
);
|
||||
let prefix_set = prefix_set.freeze();
|
||||
|
||||
// Build computation input (data only)
|
||||
let input = StorageProofInput::new(
|
||||
hashed_address,
|
||||
prefix_set,
|
||||
proof_targets,
|
||||
true, // with_branch_node_masks
|
||||
Some(multi_added_removed_keys),
|
||||
);
|
||||
|
||||
// Dispatch to storage worker
|
||||
if let Err(e) = self.proof_worker_handle.dispatch_storage_proof(
|
||||
input,
|
||||
ProofResultContext::new(
|
||||
self.proof_result_tx.clone(),
|
||||
proof_sequence_number,
|
||||
hashed_state_update,
|
||||
start,
|
||||
),
|
||||
) {
|
||||
error!(target: "engine::tree::payload_processor::multiproof", ?e, "Failed to dispatch storage proof");
|
||||
return;
|
||||
}
|
||||
|
||||
self.metrics
|
||||
.active_storage_workers_histogram
|
||||
.record(self.proof_worker_handle.active_storage_workers() as f64);
|
||||
self.metrics
|
||||
.active_account_workers_histogram
|
||||
.record(self.proof_worker_handle.active_account_workers() as f64);
|
||||
self.metrics
|
||||
.pending_storage_multiproofs_histogram
|
||||
.record(self.proof_worker_handle.pending_storage_tasks() as f64);
|
||||
self.metrics
|
||||
.pending_account_multiproofs_histogram
|
||||
.record(self.proof_worker_handle.pending_account_tasks() as f64);
|
||||
self.dispatch_multiproof(input);
|
||||
}
|
||||
|
||||
/// Signals that a multiproof calculation has finished.
|
||||
@@ -809,17 +663,14 @@ impl MultiProofTask {
|
||||
available_storage_workers,
|
||||
MultiProofTargets::chunks,
|
||||
|proof_targets| {
|
||||
self.multiproof_manager.dispatch(
|
||||
MultiproofInput {
|
||||
source: None,
|
||||
hashed_state_update: Default::default(),
|
||||
proof_targets,
|
||||
proof_sequence_number: self.proof_sequencer.next_sequence(),
|
||||
state_root_message_sender: self.tx.clone(),
|
||||
multi_added_removed_keys: Some(multi_added_removed_keys.clone()),
|
||||
}
|
||||
.into(),
|
||||
);
|
||||
self.multiproof_manager.dispatch(MultiproofInput {
|
||||
source: None,
|
||||
hashed_state_update: Default::default(),
|
||||
proof_targets,
|
||||
proof_sequence_number: self.proof_sequencer.next_sequence(),
|
||||
state_root_message_sender: self.tx.clone(),
|
||||
multi_added_removed_keys: Some(multi_added_removed_keys.clone()),
|
||||
});
|
||||
},
|
||||
);
|
||||
self.metrics.prefetch_proof_chunks_histogram.record(num_chunks as f64);
|
||||
@@ -967,17 +818,14 @@ impl MultiProofTask {
|
||||
);
|
||||
spawned_proof_targets.extend_ref(&proof_targets);
|
||||
|
||||
self.multiproof_manager.dispatch(
|
||||
MultiproofInput {
|
||||
source: Some(source),
|
||||
hashed_state_update,
|
||||
proof_targets,
|
||||
proof_sequence_number: self.proof_sequencer.next_sequence(),
|
||||
state_root_message_sender: self.tx.clone(),
|
||||
multi_added_removed_keys: Some(multi_added_removed_keys.clone()),
|
||||
}
|
||||
.into(),
|
||||
);
|
||||
self.multiproof_manager.dispatch(MultiproofInput {
|
||||
source: Some(source),
|
||||
hashed_state_update,
|
||||
proof_targets,
|
||||
proof_sequence_number: self.proof_sequencer.next_sequence(),
|
||||
state_root_message_sender: self.tx.clone(),
|
||||
multi_added_removed_keys: Some(multi_added_removed_keys.clone()),
|
||||
});
|
||||
},
|
||||
);
|
||||
self.metrics
|
||||
|
||||
@@ -166,8 +166,7 @@ where
|
||||
|
||||
// Update storage slots with new values and calculate storage roots.
|
||||
let span = tracing::Span::current();
|
||||
let (tx, rx) = mpsc::channel();
|
||||
state
|
||||
let results: Vec<_> = state
|
||||
.storages
|
||||
.into_iter()
|
||||
.map(|(address, storage)| (address, storage, trie.take_storage_trie(&address)))
|
||||
@@ -217,13 +216,7 @@ where
|
||||
|
||||
SparseStateTrieResult::Ok((address, storage_trie))
|
||||
})
|
||||
.for_each_init(
|
||||
|| tx.clone(),
|
||||
|tx, result| {
|
||||
let _ = tx.send(result);
|
||||
},
|
||||
);
|
||||
drop(tx);
|
||||
.collect();
|
||||
|
||||
// Defer leaf removals until after updates/additions, so that we don't delete an intermediate
|
||||
// branch node during a removal and then re-add that branch back during a later leaf addition.
|
||||
@@ -235,7 +228,7 @@ where
|
||||
let _enter =
|
||||
tracing::debug_span!(target: "engine::tree::payload_processor::sparse_trie", "account trie")
|
||||
.entered();
|
||||
for result in rx {
|
||||
for result in results {
|
||||
let (address, storage_trie) = result?;
|
||||
trie.insert_storage_trie(address, storage_trie);
|
||||
|
||||
|
||||
@@ -323,6 +323,7 @@ where
|
||||
&mut self,
|
||||
input: BlockOrPayload<T>,
|
||||
mut ctx: TreeCtx<'_, N>,
|
||||
provider_builder: StateProviderBuilder<N, P>,
|
||||
) -> ValidationOutcome<N, InsertPayloadError<N::Block>>
|
||||
where
|
||||
V: PayloadValidator<T, Block = N::Block>,
|
||||
@@ -362,16 +363,6 @@ where
|
||||
trace!(target: "engine::tree::payload_validator", "Fetching block state provider");
|
||||
let _enter =
|
||||
debug_span!(target: "engine::tree::payload_validator", "state provider").entered();
|
||||
let Some(provider_builder) =
|
||||
ensure_ok!(self.state_provider_builder(parent_hash, ctx.state()))
|
||||
else {
|
||||
// this is pre-validated in the tree
|
||||
return Err(InsertBlockError::new(
|
||||
self.convert_to_block(input)?,
|
||||
ProviderError::HeaderNotFound(parent_hash.into()).into(),
|
||||
)
|
||||
.into())
|
||||
};
|
||||
let mut state_provider = ensure_ok!(provider_builder.build());
|
||||
drop(_enter);
|
||||
|
||||
@@ -876,37 +867,6 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
/// Creates a `StateProviderBuilder` for the given parent hash.
|
||||
///
|
||||
/// This method checks if the parent is in the tree state (in-memory) or persisted to disk,
|
||||
/// and creates the appropriate provider builder.
|
||||
fn state_provider_builder(
|
||||
&self,
|
||||
hash: B256,
|
||||
state: &EngineApiTreeState<N>,
|
||||
) -> ProviderResult<Option<StateProviderBuilder<N, P>>> {
|
||||
if let Some((historical, blocks)) = state.tree_state.blocks_by_hash(hash) {
|
||||
debug!(target: "engine::tree::payload_validator", %hash, %historical, "found canonical state for block in memory, creating provider builder");
|
||||
// the block leads back to the canonical chain
|
||||
return Ok(Some(StateProviderBuilder::new(
|
||||
self.provider.clone(),
|
||||
historical,
|
||||
Some(blocks),
|
||||
)))
|
||||
}
|
||||
|
||||
// Check if the block is persisted
|
||||
if let Some(header) = self.provider.header(hash)? {
|
||||
debug!(target: "engine::tree::payload_validator", %hash, number = %header.number(), "found canonical state for block in database, creating provider builder");
|
||||
// For persisted blocks, we create a builder that will fetch state directly from the
|
||||
// database
|
||||
return Ok(Some(StateProviderBuilder::new(self.provider.clone(), hash, None)))
|
||||
}
|
||||
|
||||
debug!(target: "engine::tree::payload_validator", %hash, "no canonical state found for block");
|
||||
Ok(None)
|
||||
}
|
||||
|
||||
/// Determines the state root computation strategy based on configuration.
|
||||
///
|
||||
/// Note: Use state root task only if prefix sets are empty, otherwise proof generation is
|
||||
@@ -1129,6 +1089,19 @@ pub trait EngineValidator<
|
||||
N: NodePrimitives = <<Types as PayloadTypes>::BuiltPayload as BuiltPayload>::Primitives,
|
||||
>: Send + Sync + 'static
|
||||
{
|
||||
/// State provider builder type used by the validator.
|
||||
type ProviderBuilder;
|
||||
|
||||
/// Creates a `StateProviderBuilder` for the given parent hash.
|
||||
///
|
||||
/// This method checks if the parent is in the tree state (in-memory) or persisted to disk,
|
||||
/// and creates the appropriate provider builder.
|
||||
fn provider_builder(
|
||||
&self,
|
||||
hash: B256,
|
||||
state: &EngineApiTreeState<N>,
|
||||
) -> ProviderResult<Option<Self::ProviderBuilder>>;
|
||||
|
||||
/// Validates the payload attributes with respect to the header.
|
||||
///
|
||||
/// By default, this enforces that the payload attributes timestamp is greater than the
|
||||
@@ -1162,6 +1135,7 @@ pub trait EngineValidator<
|
||||
&mut self,
|
||||
payload: Types::ExecutionData,
|
||||
ctx: TreeCtx<'_, N>,
|
||||
provider_builder: Self::ProviderBuilder,
|
||||
) -> ValidationOutcome<N>;
|
||||
|
||||
/// Validates a block downloaded from the network.
|
||||
@@ -1169,6 +1143,7 @@ pub trait EngineValidator<
|
||||
&mut self,
|
||||
block: SealedBlock<N::Block>,
|
||||
ctx: TreeCtx<'_, N>,
|
||||
provider_builder: Self::ProviderBuilder,
|
||||
) -> ValidationOutcome<N>;
|
||||
|
||||
/// Hook called after an executed block is inserted directly into the tree.
|
||||
@@ -1193,6 +1168,35 @@ where
|
||||
Evm: ConfigureEngineEvm<Types::ExecutionData, Primitives = N> + 'static,
|
||||
Types: PayloadTypes<BuiltPayload: BuiltPayload<Primitives = N>>,
|
||||
{
|
||||
type ProviderBuilder = StateProviderBuilder<N, P>;
|
||||
|
||||
fn provider_builder(
|
||||
&self,
|
||||
hash: B256,
|
||||
state: &EngineApiTreeState<N>,
|
||||
) -> ProviderResult<Option<Self::ProviderBuilder>> {
|
||||
if let Some((historical, blocks)) = state.tree_state.blocks_by_hash(hash) {
|
||||
debug!(target: "engine::tree::payload_validator", %hash, %historical, "found canonical state for block in memory, creating provider builder");
|
||||
// the block leads back to the canonical chain
|
||||
return Ok(Some(StateProviderBuilder::new(
|
||||
self.provider.clone(),
|
||||
historical,
|
||||
Some(blocks),
|
||||
)))
|
||||
}
|
||||
|
||||
// Check if the block is persisted
|
||||
if let Some(header) = self.provider.header(hash)? {
|
||||
debug!(target: "engine::tree::payload_validator", %hash, number = %header.number(), "found canonical state for block in database, creating provider builder");
|
||||
// For persisted blocks, we create a builder that will fetch state directly from the
|
||||
// database
|
||||
return Ok(Some(StateProviderBuilder::new(self.provider.clone(), hash, None)))
|
||||
}
|
||||
|
||||
debug!(target: "engine::tree::payload_validator", %hash, "no canonical state found for block");
|
||||
Ok(None)
|
||||
}
|
||||
|
||||
fn validate_payload_attributes_against_header(
|
||||
&self,
|
||||
attr: &Types::PayloadAttributes,
|
||||
@@ -1213,16 +1217,18 @@ where
|
||||
&mut self,
|
||||
payload: Types::ExecutionData,
|
||||
ctx: TreeCtx<'_, N>,
|
||||
provider_builder: Self::ProviderBuilder,
|
||||
) -> ValidationOutcome<N> {
|
||||
self.validate_block_with_state(BlockOrPayload::Payload(payload), ctx)
|
||||
self.validate_block_with_state(BlockOrPayload::Payload(payload), ctx, provider_builder)
|
||||
}
|
||||
|
||||
fn validate_block(
|
||||
&mut self,
|
||||
block: SealedBlock<N::Block>,
|
||||
ctx: TreeCtx<'_, N>,
|
||||
provider_builder: Self::ProviderBuilder,
|
||||
) -> ValidationOutcome<N> {
|
||||
self.validate_block_with_state(BlockOrPayload::Block(block), ctx)
|
||||
self.validate_block_with_state(BlockOrPayload::Block(block), ctx, provider_builder)
|
||||
}
|
||||
|
||||
fn on_inserted_executed_block(&self, block: ExecutedBlock<N>) {
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
use alloy_primitives::Bytes;
|
||||
use dashmap::DashMap;
|
||||
use moka::policy::EvictionPolicy;
|
||||
use reth_evm::precompiles::{DynPrecompile, Precompile, PrecompileInput};
|
||||
use revm::precompile::{PrecompileId, PrecompileOutput, PrecompileResult};
|
||||
use revm_primitives::Address;
|
||||
@@ -49,6 +50,7 @@ where
|
||||
Self(
|
||||
moka::sync::CacheBuilder::new(MAX_CACHE_SIZE as u64)
|
||||
.initial_capacity(MAX_CACHE_SIZE as usize)
|
||||
.eviction_policy(EvictionPolicy::lru())
|
||||
.build_with_hasher(Default::default()),
|
||||
)
|
||||
}
|
||||
|
||||
@@ -428,7 +428,13 @@ impl ValidatorTestHarness {
|
||||
&mut self.harness.tree.state,
|
||||
&self.harness.tree.canonical_in_memory_state,
|
||||
);
|
||||
let result = self.validator.validate_block(block, ctx);
|
||||
let provider_builder = self
|
||||
.harness
|
||||
.tree
|
||||
.state_provider_builder(block.parent_hash())
|
||||
.expect("state provider builder lookup failed")
|
||||
.expect("missing parent state provider builder");
|
||||
let result = self.validator.validate_block(block, ctx, provider_builder);
|
||||
self.metrics.record_validation(result.is_ok());
|
||||
result
|
||||
}
|
||||
|
||||
@@ -38,6 +38,7 @@ tempfile.workspace = true
|
||||
default = []
|
||||
|
||||
otlp = ["reth-tracing/otlp", "reth-node-core/otlp"]
|
||||
samply = ["reth-tracing/samply", "reth-node-core/samply"]
|
||||
|
||||
dev = ["reth-cli-commands/arbitrary"]
|
||||
|
||||
|
||||
@@ -87,9 +87,7 @@ fn verify_receipts<R: Receipt>(
|
||||
logs_bloom,
|
||||
expected_receipts_root,
|
||||
expected_logs_bloom,
|
||||
)?;
|
||||
|
||||
Ok(())
|
||||
)
|
||||
}
|
||||
|
||||
/// Compare the calculated receipts root with the expected receipts root, also compare
|
||||
|
||||
@@ -91,6 +91,7 @@ asm-keccak = [
|
||||
]
|
||||
keccak-cache-global = [
|
||||
"alloy-primitives/keccak-cache-global",
|
||||
"reth-node-core/keccak-cache-global",
|
||||
]
|
||||
js-tracer = [
|
||||
"reth-node-builder/js-tracer",
|
||||
|
||||
@@ -81,6 +81,7 @@ arbitrary = [
|
||||
]
|
||||
keccak-cache-global = [
|
||||
"reth-node-ethereum?/keccak-cache-global",
|
||||
"reth-node-core?/keccak-cache-global",
|
||||
]
|
||||
test-utils = [
|
||||
"reth-chainspec/test-utils",
|
||||
|
||||
@@ -61,8 +61,6 @@ pub use alloy_evm::{
|
||||
*,
|
||||
};
|
||||
|
||||
pub use alloy_evm::block::state_changes as state_change;
|
||||
|
||||
/// A complete configuration of EVM for Reth.
|
||||
///
|
||||
/// This trait encapsulates complete configuration required for transaction execution and block
|
||||
|
||||
@@ -312,7 +312,6 @@ impl ECIES {
|
||||
|
||||
/// Create a new ECIES client with the given static secret key and remote peer ID.
|
||||
pub fn new_client(secret_key: SecretKey, remote_id: PeerId) -> Result<Self, ECIESError> {
|
||||
// TODO(rand): use rng for nonce
|
||||
let mut rng = rng();
|
||||
let nonce = B256::random();
|
||||
let ephemeral_secret_key = SecretKey::new(&mut rng);
|
||||
|
||||
@@ -938,9 +938,13 @@ where
|
||||
///
|
||||
/// A target block hash if the pipeline is inconsistent, otherwise `None`.
|
||||
pub fn check_pipeline_consistency(&self) -> ProviderResult<Option<B256>> {
|
||||
// We skip the era stage if it's not enabled
|
||||
let era_enabled = self.era_import_source().is_some();
|
||||
let mut all_stages =
|
||||
StageId::ALL.into_iter().filter(|id| era_enabled || id != &StageId::Era);
|
||||
|
||||
// Get the expected first stage based on config.
|
||||
let first_stage =
|
||||
if self.era_import_source().is_some() { StageId::Era } else { StageId::Headers };
|
||||
let first_stage = all_stages.next().expect("there must be at least one stage");
|
||||
|
||||
// If no target was provided, check if the stages are congruent - check if the
|
||||
// checkpoint of the last stage matches the checkpoint of the first.
|
||||
@@ -950,20 +954,28 @@ where
|
||||
.unwrap_or_default()
|
||||
.block_number;
|
||||
|
||||
// Skip the first stage as we've already retrieved it and comparing all other checkpoints
|
||||
// against it.
|
||||
for stage_id in StageId::ALL.iter().skip(1) {
|
||||
// Compare all other stages against the first
|
||||
for stage_id in all_stages {
|
||||
let stage_checkpoint = self
|
||||
.blockchain_db()
|
||||
.get_stage_checkpoint(*stage_id)?
|
||||
.get_stage_checkpoint(stage_id)?
|
||||
.unwrap_or_default()
|
||||
.block_number;
|
||||
|
||||
// If the checkpoint of any stage is less than the checkpoint of the first stage,
|
||||
// retrieve and return the block hash of the latest header and use it as the target.
|
||||
debug!(
|
||||
target: "consensus::engine",
|
||||
first_stage_id = %first_stage,
|
||||
first_stage_checkpoint,
|
||||
stage_id = %stage_id,
|
||||
stage_checkpoint = stage_checkpoint,
|
||||
"Checking stage against first stage",
|
||||
);
|
||||
if stage_checkpoint < first_stage_checkpoint {
|
||||
debug!(
|
||||
target: "consensus::engine",
|
||||
first_stage_id = %first_stage,
|
||||
first_stage_checkpoint,
|
||||
inconsistent_stage_id = %stage_id,
|
||||
inconsistent_stage_checkpoint = stage_checkpoint,
|
||||
|
||||
@@ -80,8 +80,9 @@ tokio.workspace = true
|
||||
# Features for vergen to generate correct env vars
|
||||
jemalloc = ["reth-cli-util/jemalloc"]
|
||||
asm-keccak = ["alloy-primitives/asm-keccak"]
|
||||
# Feature to enable opentelemetry export
|
||||
keccak-cache-global = ["alloy-primitives/keccak-cache-global"]
|
||||
otlp = ["reth-tracing/otlp"]
|
||||
samply = ["reth-tracing/samply"]
|
||||
|
||||
min-error-logs = ["tracing/release_max_level_error"]
|
||||
min-warn-logs = ["tracing/release_max_level_warn"]
|
||||
|
||||
@@ -30,6 +30,7 @@ workspace = true
|
||||
default = ["jemalloc", "otlp", "reth-optimism-evm/portable", "js-tracer", "keccak-cache-global", "asm-keccak"]
|
||||
|
||||
otlp = ["reth-optimism-cli/otlp"]
|
||||
samply = ["reth-optimism-cli/samply"]
|
||||
|
||||
js-tracer = [
|
||||
"reth-optimism-node/js-tracer",
|
||||
|
||||
@@ -78,6 +78,7 @@ default = []
|
||||
|
||||
# Opentelemtry feature to activate metrics export
|
||||
otlp = ["reth-tracing/otlp", "reth-node-core/otlp"]
|
||||
samply = ["reth-tracing/samply", "reth-node-core/samply"]
|
||||
|
||||
asm-keccak = [
|
||||
"alloy-primitives/asm-keccak",
|
||||
|
||||
@@ -83,6 +83,7 @@ reth-rpc-eth-types.workspace = true
|
||||
reth-stages-types.workspace = true
|
||||
|
||||
alloy-network.workspace = true
|
||||
alloy-op-hardforks.workspace = true
|
||||
futures.workspace = true
|
||||
op-alloy-network.workspace = true
|
||||
|
||||
@@ -96,6 +97,7 @@ asm-keccak = [
|
||||
]
|
||||
keccak-cache-global = [
|
||||
"alloy-primitives/keccak-cache-global",
|
||||
"reth-node-core/keccak-cache-global",
|
||||
"reth-optimism-node/keccak-cache-global",
|
||||
]
|
||||
js-tracer = [
|
||||
|
||||
@@ -299,23 +299,16 @@ mod test {
|
||||
use super::*;
|
||||
|
||||
use crate::engine;
|
||||
use alloy_op_hardforks::BASE_SEPOLIA_JOVIAN_TIMESTAMP;
|
||||
use alloy_primitives::{b64, Address, B256, B64};
|
||||
use alloy_rpc_types_engine::PayloadAttributes;
|
||||
use reth_chainspec::{ChainSpec, ForkCondition, Hardfork};
|
||||
use reth_chainspec::ChainSpec;
|
||||
use reth_optimism_chainspec::{OpChainSpec, BASE_SEPOLIA};
|
||||
use reth_optimism_forks::OpHardfork;
|
||||
use reth_provider::noop::NoopProvider;
|
||||
use reth_trie_common::KeccakKeyHasher;
|
||||
|
||||
const JOVIAN_TIMESTAMP: u64 = 1744909000;
|
||||
|
||||
fn get_chainspec() -> Arc<OpChainSpec> {
|
||||
let mut base_sepolia_spec = BASE_SEPOLIA.inner.clone();
|
||||
|
||||
// TODO: Remove this once we know the Jovian timestamp
|
||||
base_sepolia_spec
|
||||
.hardforks
|
||||
.insert(OpHardfork::Jovian.boxed(), ForkCondition::Timestamp(JOVIAN_TIMESTAMP));
|
||||
let base_sepolia_spec = BASE_SEPOLIA.inner.clone();
|
||||
|
||||
Arc::new(OpChainSpec {
|
||||
inner: ChainSpec {
|
||||
@@ -427,7 +420,8 @@ mod test {
|
||||
fn test_well_formed_attributes_jovian_valid() {
|
||||
let validator =
|
||||
OpEngineValidator::new::<KeccakKeyHasher>(get_chainspec(), NoopProvider::default());
|
||||
let attributes = get_attributes(Some(b64!("0000000000000000")), Some(1), JOVIAN_TIMESTAMP);
|
||||
let attributes =
|
||||
get_attributes(Some(b64!("0000000000000000")), Some(1), BASE_SEPOLIA_JOVIAN_TIMESTAMP);
|
||||
|
||||
let result = <engine::OpEngineValidator<_, _, _> as EngineApiValidator<
|
||||
OpEngineTypes,
|
||||
@@ -442,7 +436,7 @@ mod test {
|
||||
fn test_malformed_attributes_jovian_with_eip_1559_params_none() {
|
||||
let validator =
|
||||
OpEngineValidator::new::<KeccakKeyHasher>(get_chainspec(), NoopProvider::default());
|
||||
let attributes = get_attributes(None, Some(1), JOVIAN_TIMESTAMP);
|
||||
let attributes = get_attributes(None, Some(1), BASE_SEPOLIA_JOVIAN_TIMESTAMP);
|
||||
|
||||
let result = <engine::OpEngineValidator<_, _, _> as EngineApiValidator<
|
||||
OpEngineTypes,
|
||||
@@ -472,7 +466,8 @@ mod test {
|
||||
fn test_malformed_attributes_post_jovian_with_min_base_fee_none() {
|
||||
let validator =
|
||||
OpEngineValidator::new::<KeccakKeyHasher>(get_chainspec(), NoopProvider::default());
|
||||
let attributes = get_attributes(Some(b64!("0000000000000000")), None, JOVIAN_TIMESTAMP);
|
||||
let attributes =
|
||||
get_attributes(Some(b64!("0000000000000000")), None, BASE_SEPOLIA_JOVIAN_TIMESTAMP);
|
||||
|
||||
let result = <engine::OpEngineValidator<_, _, _> as EngineApiValidator<
|
||||
OpEngineTypes,
|
||||
|
||||
@@ -76,6 +76,7 @@ arbitrary = [
|
||||
]
|
||||
keccak-cache-global = [
|
||||
"reth-optimism-node?/keccak-cache-global",
|
||||
"reth-node-core?/keccak-cache-global",
|
||||
]
|
||||
test-utils = [
|
||||
"reth-chainspec/test-utils",
|
||||
|
||||
@@ -5,7 +5,7 @@ use reth_consensus::ConsensusError;
|
||||
use reth_primitives_traits::{GotExpected, SealedHeader};
|
||||
use reth_provider::{
|
||||
ChainStateBlockReader, DBProvider, HeaderProvider, ProviderError, PruneCheckpointReader,
|
||||
PruneCheckpointWriter, StageCheckpointReader, TrieWriter,
|
||||
PruneCheckpointWriter, StageCheckpointReader, StageCheckpointWriter, TrieWriter,
|
||||
};
|
||||
use reth_prune_types::{
|
||||
PruneCheckpoint, PruneMode, PruneSegment, MERKLE_CHANGESETS_RETENTION_BLOCKS,
|
||||
@@ -300,6 +300,7 @@ where
|
||||
+ DBProvider
|
||||
+ HeaderProvider
|
||||
+ ChainStateBlockReader
|
||||
+ StageCheckpointWriter
|
||||
+ PruneCheckpointReader
|
||||
+ PruneCheckpointWriter,
|
||||
{
|
||||
@@ -404,6 +405,28 @@ where
|
||||
computed_range.start = computed_range.end;
|
||||
}
|
||||
|
||||
// If we've unwound so far that there are no longer enough trie changesets available then
|
||||
// simply clear them and the checkpoints, so that on next pipeline startup they will be
|
||||
// regenerated.
|
||||
debug!(
|
||||
target: "sync::stages::merkle_changesets",
|
||||
?computed_range,
|
||||
retention_blocks=?self.retention_blocks,
|
||||
"Checking if computed range is over retention threshold",
|
||||
);
|
||||
if computed_range.end - computed_range.start < self.retention_blocks {
|
||||
debug!(
|
||||
target: "sync::stages::merkle_changesets",
|
||||
?computed_range,
|
||||
retention_blocks=?self.retention_blocks,
|
||||
"Clearing checkpoints completely",
|
||||
);
|
||||
provider.clear_trie_changesets()?;
|
||||
provider
|
||||
.save_stage_checkpoint(StageId::MerkleChangeSets, StageCheckpoint::default())?;
|
||||
return Ok(UnwindOutput { checkpoint: StageCheckpoint::default() })
|
||||
}
|
||||
|
||||
// `computed_range.end` is exclusive
|
||||
let checkpoint = StageCheckpoint::new(computed_range.end.saturating_sub(1));
|
||||
|
||||
|
||||
@@ -30,7 +30,7 @@ pub trait DbTxUnwindExt: DbTxMut {
|
||||
let mut deleted = 0;
|
||||
|
||||
while let Some(Ok((entry_key, _))) = reverse_walker.next() {
|
||||
if selector(entry_key.clone()) <= key {
|
||||
if selector(entry_key) <= key {
|
||||
break
|
||||
}
|
||||
reverse_walker.delete_current()?;
|
||||
|
||||
119
crates/storage/libmdbx-rs/mdbx-sys/libmdbx/mdbx.c
vendored
119
crates/storage/libmdbx-rs/mdbx-sys/libmdbx/mdbx.c
vendored
@@ -12936,125 +12936,6 @@ int mdbx_txn_renew(MDBX_txn *txn) {
|
||||
return LOG_IFERR(rc);
|
||||
}
|
||||
|
||||
int mdbx_txn_clone(const MDBX_txn *src, MDBX_txn **dest) {
|
||||
if (unlikely(!dest))
|
||||
return LOG_IFERR(MDBX_EINVAL);
|
||||
*dest = nullptr;
|
||||
|
||||
int rc = check_txn(src, MDBX_TXN_BLOCKED);
|
||||
if (unlikely(rc != MDBX_SUCCESS))
|
||||
return LOG_IFERR(rc);
|
||||
|
||||
if (unlikely((src->flags & MDBX_TXN_RDONLY) == 0))
|
||||
return LOG_IFERR(MDBX_EINVAL);
|
||||
|
||||
MDBX_env *const env = src->env;
|
||||
rc = check_env(env, true);
|
||||
if (unlikely(rc != MDBX_SUCCESS))
|
||||
return LOG_IFERR(rc);
|
||||
|
||||
if (unlikely((env->flags & MDBX_NOSTICKYTHREADS) == 0))
|
||||
return LOG_IFERR(MDBX_TXN_OVERLAPPING);
|
||||
|
||||
MDBX_txn *txn = nullptr;
|
||||
const intptr_t bitmap_bytes =
|
||||
#if MDBX_ENABLE_DBI_SPARSE
|
||||
ceil_powerof2(env->max_dbi, CHAR_BIT * sizeof(txn->dbi_sparse[0])) / CHAR_BIT;
|
||||
#else
|
||||
0;
|
||||
#endif /* MDBX_ENABLE_DBI_SPARSE */
|
||||
|
||||
STATIC_ASSERT(sizeof(txn->tw) > sizeof(txn->to));
|
||||
const size_t base = sizeof(MDBX_txn) - sizeof(txn->tw) + sizeof(txn->to);
|
||||
const size_t size = base + (size_t)bitmap_bytes + env->max_dbi * sizeof(txn->dbi_seqs[0]) +
|
||||
env->max_dbi * (sizeof(txn->dbs[0]) + sizeof(txn->cursors[0]) + sizeof(txn->dbi_state[0]));
|
||||
|
||||
txn = osal_malloc(size);
|
||||
if (unlikely(txn == nullptr))
|
||||
return LOG_IFERR(MDBX_ENOMEM);
|
||||
#if MDBX_DEBUG
|
||||
memset(txn, 0xCD, size);
|
||||
VALGRIND_MAKE_MEM_UNDEFINED(txn, size);
|
||||
#endif /* MDBX_DEBUG */
|
||||
MDBX_ANALYSIS_ASSUME(size > base);
|
||||
memset(txn, 0, (MDBX_GOOFY_MSVC_STATIC_ANALYZER && base > size) ? size : base);
|
||||
txn->dbs = ptr_disp(txn, base);
|
||||
txn->cursors = ptr_disp(txn->dbs, env->max_dbi * sizeof(txn->dbs[0]));
|
||||
#if MDBX_DEBUG
|
||||
txn->cursors[FREE_DBI] = nullptr; /* avoid SIGSEGV in an assertion later */
|
||||
#endif
|
||||
txn->dbi_state = ptr_disp(txn, size - env->max_dbi * sizeof(txn->dbi_state[0]));
|
||||
txn->dbi_seqs = ptr_disp(txn->cursors, env->max_dbi * sizeof(txn->cursors[0]));
|
||||
#if MDBX_ENABLE_DBI_SPARSE
|
||||
txn->dbi_sparse = ptr_disp(txn->dbi_state, -bitmap_bytes);
|
||||
#endif /* MDBX_ENABLE_DBI_SPARSE */
|
||||
|
||||
txn->env = env;
|
||||
txn->flags = src->flags & ~txn_state_flags;
|
||||
txn->parent = nullptr;
|
||||
txn->nested = nullptr;
|
||||
|
||||
txn->txnid = src->txnid;
|
||||
txn->front_txnid = src->front_txnid;
|
||||
txn->geo = src->geo;
|
||||
txn->canary = src->canary;
|
||||
txn->owner = (env->flags & MDBX_NOSTICKYTHREADS) ? 0 : osal_thread_self();
|
||||
|
||||
if (unlikely(src->n_dbi > env->max_dbi)) {
|
||||
rc = MDBX_CORRUPTED;
|
||||
goto bailout;
|
||||
}
|
||||
|
||||
txn->n_dbi = src->n_dbi;
|
||||
memset(txn->cursors, 0, env->max_dbi * sizeof(txn->cursors[0]));
|
||||
memset(txn->dbi_state, 0, env->max_dbi * sizeof(txn->dbi_state[0]));
|
||||
memset(txn->dbi_seqs, 0, env->max_dbi * sizeof(txn->dbi_seqs[0]));
|
||||
#if MDBX_ENABLE_DBI_SPARSE
|
||||
if (bitmap_bytes)
|
||||
memset(txn->dbi_sparse, 0, bitmap_bytes);
|
||||
#endif /* MDBX_ENABLE_DBI_SPARSE */
|
||||
|
||||
memcpy(txn->dbs, src->dbs, txn->n_dbi * sizeof(txn->dbs[0]));
|
||||
memcpy(txn->dbi_state, src->dbi_state, txn->n_dbi * sizeof(txn->dbi_state[0]));
|
||||
memcpy(txn->dbi_seqs, src->dbi_seqs, txn->n_dbi * sizeof(txn->dbi_seqs[0]));
|
||||
#if MDBX_ENABLE_DBI_SPARSE
|
||||
if (bitmap_bytes)
|
||||
memcpy(txn->dbi_sparse, src->dbi_sparse, bitmap_bytes);
|
||||
#endif /* MDBX_ENABLE_DBI_SPARSE */
|
||||
|
||||
txn->to.reader = nullptr;
|
||||
if (env->lck_mmap.lck) {
|
||||
bsr_t brs = mvcc_bind_slot(env);
|
||||
if (unlikely(brs.err != MDBX_SUCCESS)) {
|
||||
rc = brs.err;
|
||||
goto bailout;
|
||||
}
|
||||
txn->to.reader = brs.rslot;
|
||||
safe64_reset(&txn->to.reader->txnid, true);
|
||||
if (src->to.reader) {
|
||||
atomic_store32(&txn->to.reader->snapshot_pages_used,
|
||||
atomic_load32(&src->to.reader->snapshot_pages_used, mo_Relaxed), mo_Relaxed);
|
||||
atomic_store64(&txn->to.reader->snapshot_pages_retired,
|
||||
atomic_load64(&src->to.reader->snapshot_pages_retired, mo_Relaxed), mo_Relaxed);
|
||||
} else {
|
||||
atomic_store32(&txn->to.reader->snapshot_pages_used, src->geo.first_unallocated, mo_Relaxed);
|
||||
atomic_store64(&txn->to.reader->snapshot_pages_retired, 0, mo_Relaxed);
|
||||
}
|
||||
safe64_write(&txn->to.reader->txnid, src->txnid);
|
||||
atomic_store32(&env->lck->rdt_refresh_flag, true, mo_AcquireRelease);
|
||||
}
|
||||
|
||||
txn->signature = txn_signature;
|
||||
txn->userctx = nullptr;
|
||||
*dest = txn;
|
||||
DEBUG("clone txn %" PRIaTXN "r %p from %p on env %p", txn->txnid, (void *)txn, (void *)src, (void *)env);
|
||||
return MDBX_SUCCESS;
|
||||
|
||||
bailout:
|
||||
osal_free(txn);
|
||||
return LOG_IFERR(rc);
|
||||
}
|
||||
|
||||
int mdbx_txn_set_userctx(MDBX_txn *txn, void *ctx) {
|
||||
int rc = check_txn(txn, MDBX_TXN_FINISHED);
|
||||
if (unlikely(rc != MDBX_SUCCESS))
|
||||
|
||||
@@ -3882,35 +3882,6 @@ MDBX_NOTHROW_PURE_FUNCTION LIBMDBX_API void *mdbx_env_get_userctx(const MDBX_env
|
||||
LIBMDBX_API int mdbx_txn_begin_ex(MDBX_env *env, MDBX_txn *parent, MDBX_txn_flags_t flags, MDBX_txn **txn,
|
||||
void *context);
|
||||
|
||||
/** \brief Clone a read-only transaction snapshot.
|
||||
* \ingroup c_transactions
|
||||
*
|
||||
* Creates a new read-only transaction that uses the same MVCC snapshot as
|
||||
* the \p src transaction. This allows parallel read operations across threads
|
||||
* without re-opening a read transaction and re-fetching state.
|
||||
*
|
||||
* \note This function requires \ref MDBX_NOSTICKYTHREADS (aka MDBX_NOTLS)
|
||||
* to be enabled for the environment. Otherwise it will return
|
||||
* \ref MDBX_TXN_OVERLAPPING.
|
||||
*
|
||||
* \note The \p src transaction must be an active read-only transaction.
|
||||
*
|
||||
* \note The \p src transaction and the cloned transaction must not be used
|
||||
* concurrently from multiple threads. Each transaction and its cursors must
|
||||
* be confined to a single thread at a time.
|
||||
*
|
||||
* \param [in] src A read-only transaction handle returned by
|
||||
* \ref mdbx_txn_begin_ex() or \ref mdbx_txn_begin().
|
||||
* \param [out] dest Address where the cloned \ref MDBX_txn handle will be
|
||||
* stored. Must not be NULL.
|
||||
*
|
||||
* \returns A non-zero error value on failure and 0 on success.
|
||||
* \retval MDBX_EINVAL Invalid arguments or \p src is not read-only.
|
||||
* \retval MDBX_TXN_OVERLAPPING \ref MDBX_NOSTICKYTHREADS is not enabled.
|
||||
* \retval MDBX_READERS_FULL Reader lock table is full.
|
||||
* \retval MDBX_ENOMEM Out of memory. */
|
||||
LIBMDBX_API int mdbx_txn_clone(const MDBX_txn *src, MDBX_txn **dest);
|
||||
|
||||
/** \brief Create a transaction for use with the environment.
|
||||
* \ingroup c_transactions
|
||||
*
|
||||
|
||||
@@ -483,20 +483,6 @@ impl Transaction<RW> {
|
||||
}
|
||||
|
||||
impl Transaction<RO> {
|
||||
/// Clones this read-only transaction, preserving the same MVCC snapshot.
|
||||
///
|
||||
/// This requires the environment to be opened with `MDBX_NOSTICKYTHREADS` (aka `MDBX_NOTLS`).
|
||||
/// The cloned transaction must not be used concurrently with this transaction from multiple
|
||||
/// threads.
|
||||
pub fn clone_snapshot(&self) -> Result<Self> {
|
||||
let cloned = self.txn_execute(|txn| {
|
||||
let mut cloned: *mut ffi::MDBX_txn = ptr::null_mut();
|
||||
mdbx_result(unsafe { ffi::mdbx_txn_clone(txn, &mut cloned) }).map(|_| cloned)
|
||||
})??;
|
||||
|
||||
Ok(Self::new_from_ptr(self.env().clone(), cloned))
|
||||
}
|
||||
|
||||
/// Closes the database handle.
|
||||
///
|
||||
/// # Safety
|
||||
|
||||
@@ -373,35 +373,3 @@ fn test_stat_dupsort() {
|
||||
assert_eq!(stat.entries(), 8);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_txn_clone_snapshot() {
|
||||
let dir = tempdir().unwrap();
|
||||
let env = Environment::builder().open(dir.path()).unwrap();
|
||||
{
|
||||
let txn = env.begin_rw_txn().unwrap();
|
||||
let db = txn.open_db(None).unwrap();
|
||||
txn.put(db.dbi(), b"k", b"v1", WriteFlags::empty()).unwrap();
|
||||
txn.commit().unwrap();
|
||||
}
|
||||
|
||||
let ro = env.begin_ro_txn().unwrap();
|
||||
let clone = ro.clone_snapshot().unwrap();
|
||||
|
||||
{
|
||||
let txn = env.begin_rw_txn().unwrap();
|
||||
let db = txn.open_db(None).unwrap();
|
||||
txn.put(db.dbi(), b"k", b"v2", WriteFlags::empty()).unwrap();
|
||||
txn.commit().unwrap();
|
||||
}
|
||||
|
||||
let db = ro.open_db(None).unwrap();
|
||||
assert_eq!(ro.get::<[u8; 2]>(db.dbi(), b"k").unwrap(), Some(*b"v1"));
|
||||
|
||||
let db = clone.open_db(None).unwrap();
|
||||
assert_eq!(clone.get::<[u8; 2]>(db.dbi(), b"k").unwrap(), Some(*b"v1"));
|
||||
|
||||
let ro2 = env.begin_ro_txn().unwrap();
|
||||
let db = ro2.open_db(None).unwrap();
|
||||
assert_eq!(ro2.get::<[u8; 2]>(db.dbi(), b"k").unwrap(), Some(*b"v2"));
|
||||
}
|
||||
|
||||
@@ -26,7 +26,9 @@ tracing-logfmt.workspace = true
|
||||
clap = { workspace = true, features = ["derive"] }
|
||||
eyre.workspace = true
|
||||
rolling-file.workspace = true
|
||||
tracing-samply = { workspace = true, optional = true }
|
||||
|
||||
[features]
|
||||
default = ["otlp"]
|
||||
otlp = ["reth-tracing-otlp"]
|
||||
samply = ["tracing-samply"]
|
||||
|
||||
@@ -224,6 +224,12 @@ impl Tracer for RethTracer {
|
||||
None
|
||||
};
|
||||
|
||||
#[cfg(feature = "samply")]
|
||||
layers.add_layer(
|
||||
tracing_samply::SamplyLayer::new()
|
||||
.map_err(|e| eyre::eyre!("Failed to create samply layer: {}", e))?,
|
||||
);
|
||||
|
||||
// The error is returned if the global default subscriber is already set,
|
||||
// so it's safe to ignore it
|
||||
let _ = tracing_subscriber::registry().with(layers.into_inner()).try_init();
|
||||
|
||||
@@ -151,6 +151,9 @@ impl BlobStore for DiskFileBlobStore {
|
||||
}
|
||||
|
||||
fn delete_all(&self, txs: Vec<B256>) -> Result<(), BlobStoreError> {
|
||||
if txs.is_empty() {
|
||||
return Ok(())
|
||||
}
|
||||
let txs = self.inner.retain_existing(txs)?;
|
||||
self.inner.txs_to_delete.write().extend(txs);
|
||||
Ok(())
|
||||
|
||||
@@ -269,17 +269,26 @@ pub async fn maintain_transaction_pool<N, Client, P, St, Tasks>(
|
||||
}
|
||||
}
|
||||
_ = stale_eviction_interval.tick() => {
|
||||
let stale_txs: Vec<_> = pool
|
||||
.queued_transactions()
|
||||
let queued = pool
|
||||
.queued_transactions();
|
||||
let mut stale_blobs = Vec::new();
|
||||
let now = std::time::Instant::now();
|
||||
let stale_txs: Vec<_> = queued
|
||||
.into_iter()
|
||||
.filter(|tx| {
|
||||
// filter stale transactions based on config
|
||||
(tx.origin.is_external() || config.no_local_exemptions) && tx.timestamp.elapsed() > config.max_tx_lifetime
|
||||
(tx.origin.is_external() || config.no_local_exemptions) && now - tx.timestamp > config.max_tx_lifetime
|
||||
})
|
||||
.map(|tx| {
|
||||
if tx.is_eip4844() {
|
||||
stale_blobs.push(*tx.hash());
|
||||
}
|
||||
*tx.hash()
|
||||
})
|
||||
.map(|tx| *tx.hash())
|
||||
.collect();
|
||||
debug!(target: "txpool", count=%stale_txs.len(), "removing stale transactions");
|
||||
pool.remove_transactions(stale_txs);
|
||||
pool.delete_blobs(stale_blobs);
|
||||
}
|
||||
}
|
||||
// handle the result of the account reload
|
||||
|
||||
@@ -276,13 +276,12 @@ where
|
||||
{
|
||||
use rayon::iter::{ParallelBridge, ParallelIterator};
|
||||
|
||||
let (tx, rx) = std::sync::mpsc::channel();
|
||||
let retain_updates = self.retain_updates;
|
||||
|
||||
// Process all storage trie revealings in parallel, having first removed the
|
||||
// `reveal_nodes` tracking and `SparseTrie`s for each account from their HashMaps.
|
||||
// These will be returned after processing.
|
||||
storages
|
||||
let results: Vec<_> = storages
|
||||
.into_iter()
|
||||
.map(|(account, storage_subtree)| {
|
||||
let revealed_nodes = self.storage.take_or_create_revealed_paths(&account);
|
||||
@@ -301,14 +300,12 @@ where
|
||||
|
||||
(account, revealed_nodes, trie, result)
|
||||
})
|
||||
.for_each_init(|| tx.clone(), |tx, result| tx.send(result).unwrap());
|
||||
|
||||
drop(tx);
|
||||
.collect();
|
||||
|
||||
// Return `revealed_nodes` and `SparseTrie` for each account, incrementing metrics and
|
||||
// returning the last error seen if any.
|
||||
let mut any_err = Ok(());
|
||||
for (account, revealed_nodes, trie, result) in rx {
|
||||
for (account, revealed_nodes, trie, result) in results {
|
||||
self.storage.revealed_paths.insert(account, revealed_nodes);
|
||||
self.storage.tries.insert(account, trie);
|
||||
if let Ok(_metric_values) = result {
|
||||
|
||||
@@ -160,15 +160,15 @@ where
|
||||
///
|
||||
/// If `metrics` feature is enabled, it also updates the metrics.
|
||||
fn next_hashed_entry(&mut self) -> Result<Option<(B256, H::Value)>, DatabaseError> {
|
||||
let result = self.hashed_cursor.next();
|
||||
let next = self.hashed_cursor.next()?;
|
||||
|
||||
self.last_next_result = result.clone()?;
|
||||
self.last_next_result = next;
|
||||
|
||||
#[cfg(feature = "metrics")]
|
||||
{
|
||||
self.metrics.inc_leaf_nodes_advanced();
|
||||
}
|
||||
result
|
||||
Ok(next)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -26,7 +26,7 @@ The methods are grouped into namespaces, which are listed below:
|
||||
| [`trace`](/jsonrpc/trace) | The `trace` API provides several methods to inspect the Ethereum state, including Parity-style traces. | No |
|
||||
| [`admin`](/jsonrpc/admin) | The `admin` API allows you to configure your node. | **Yes** |
|
||||
| [`rpc`](/jsonrpc/rpc) | The `rpc` API provides information about the RPC server and its modules. | No |
|
||||
| `reth` | The `reth` API provides reth-specific methods like balance changes and chain notifications. | No |
|
||||
| [`reth`](/jsonrpc/reth) | The `reth` API provides reth-specific methods like balance changes and chain notifications. | No |
|
||||
| `ots` | The `ots` API provides Otterscan-compatible methods for block exploration. | No |
|
||||
| `flashbots` | The `flashbots` API provides block submission validation methods for builders. | No |
|
||||
| `miner` | The `miner` API allows you to configure miner/builder settings like extra data and gas limits. | **Yes** |
|
||||
|
||||
89
docs/vocs/docs/pages/jsonrpc/reth.mdx
Normal file
89
docs/vocs/docs/pages/jsonrpc/reth.mdx
Normal file
@@ -0,0 +1,89 @@
|
||||
---
|
||||
description: Reth-specific API for balance changes and chain notifications.
|
||||
---
|
||||
|
||||
# `reth` Namespace
|
||||
|
||||
The `reth` API provides reth-specific methods that are not part of the standard Ethereum JSON-RPC specification. These methods offer additional functionality for monitoring balance changes and subscribing to chain state notifications.
|
||||
|
||||
## `reth_getBalanceChangesInBlock`
|
||||
|
||||
Returns all ETH balance changes that occurred in a specific block.
|
||||
|
||||
This method is useful for tracking value transfers, mining rewards, and other balance modifications without having to trace every transaction in a block.
|
||||
|
||||
The method accepts a block identifier (number, hash, or tag like `latest`) and returns a map of addresses to their new balances.
|
||||
|
||||
| Client | Method invocation |
|
||||
| ------ | -------------------------------------------------------------- |
|
||||
| RPC | `{"method": "reth_getBalanceChangesInBlock", "params": [block]}` |
|
||||
|
||||
### Example
|
||||
|
||||
```js
|
||||
// > {"jsonrpc":"2.0","id":1,"method":"reth_getBalanceChangesInBlock","params":["latest"]}
|
||||
{"jsonrpc":"2.0","id":1,"result":{"0x95222290dd7278aa3ddd389cc1e1d165cc4bafe5":"0x1bc16d674ec80000","0x388c818ca8b9251b393131c08a736a67ccb19297":"0x0"}}
|
||||
```
|
||||
|
||||
The result is a mapping of addresses to their new balance after the block was executed. Only addresses whose balance changed during block execution are included.
|
||||
|
||||
## `reth_subscribeChainNotifications`, `reth_unsubscribeChainNotifications`
|
||||
|
||||
Subscribe to canonical chain state notifications. This creates a subscription that emits notifications whenever the canonical chain state changes.
|
||||
|
||||
Like other subscription methods, this returns the ID of the subscription, which is then used in all events subsequently.
|
||||
|
||||
To unsubscribe from chain notifications, call `reth_unsubscribeChainNotifications` with the subscription ID.
|
||||
|
||||
| Client | Method invocation |
|
||||
| ------ | -------------------------------------------------------------------------- |
|
||||
| RPC | `{"method": "reth_subscribeChainNotifications", "params": []}` |
|
||||
| RPC | `{"method": "reth_unsubscribeChainNotifications", "params": [subscription_id]}` |
|
||||
|
||||
### Event Types
|
||||
|
||||
The subscription emits events with the following structure:
|
||||
|
||||
```json
|
||||
{
|
||||
"jsonrpc": "2.0",
|
||||
"method": "reth_subscription",
|
||||
"params": {
|
||||
"subscription": "0xcd0c3e8af590364c09d0fa6a1210faf5",
|
||||
"result": {
|
||||
"Commit": { // or "Reorg"
|
||||
"new": {
|
||||
// Chain segment with blocks, receipts, etc.
|
||||
},
|
||||
"old": {
|
||||
// Only present for "Reorg": chain segment that was reverted
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
- **Commit**: New blocks are added to the canonical chain. Contains only `new` with the committed chain segment.
|
||||
- **Reorg**: Chain reorganization occurred. Contains both `old` (reverted blocks) and `new` (replacement blocks).
|
||||
|
||||
This is particularly useful for applications that need to react immediately to chain state changes, such as indexers, monitoring tools, or ExEx (Execution Extensions).
|
||||
|
||||
### Example
|
||||
|
||||
```js
|
||||
// > {"jsonrpc":"2.0","id":1,"method":"reth_subscribeChainNotifications","params":[]}
|
||||
// responds with subscription ID
|
||||
{"jsonrpc":"2.0","id":1,"result":"0xcd0c3e8af590364c09d0fa6a1210faf5"}
|
||||
|
||||
// Example notification when new blocks are committed
|
||||
{"jsonrpc":"2.0","method":"reth_subscription","params":{"subscription":"0xcd0c3e8af590364c09d0fa6a1210faf5","result":{"Commit":{"new":{"blocks":[...],"receipts":[...],"first_block":1000,"last_block":1000}}}}}
|
||||
|
||||
// Unsubscribe
|
||||
// > {"jsonrpc":"2.0","id":2,"method":"reth_unsubscribeChainNotifications","params":["0xcd0c3e8af590364c09d0fa6a1210faf5"]}
|
||||
{"jsonrpc":"2.0","id":2,"result":true}
|
||||
```
|
||||
|
||||
:::note
|
||||
This subscription is only available over WebSocket and IPC transports, as HTTP does not support server-initiated messages.
|
||||
:::
|
||||
@@ -201,13 +201,16 @@ The following tables describe RPC methods available in the full node.
|
||||
| RPC / Segment | Note |
|
||||
| ------------------------------- | ------------------------------ |
|
||||
| `trace_block` | Only for the last 10064 blocks |
|
||||
| `trace_blockOpcodeGas` | Only for the last 10064 blocks |
|
||||
| `trace_call` | Only for the last 10064 blocks |
|
||||
| `trace_callMany` | Only for the last 10064 blocks |
|
||||
| `trace_filter` | Only for the last 10064 blocks |
|
||||
| `trace_get` | Only for the last 10064 blocks |
|
||||
| `trace_rawTransaction` | Only for the last 10064 blocks |
|
||||
| `trace_replayBlockTransactions` | Only for the last 10064 blocks |
|
||||
| `trace_replayTransaction` | Only for the last 10064 blocks |
|
||||
| `trace_transaction` | Only for the last 10064 blocks |
|
||||
| `trace_transactionOpcodeGas` | Only for the last 10064 blocks |
|
||||
|
||||
#### `txpool` namespace
|
||||
|
||||
@@ -301,13 +304,16 @@ The following tables describe the requirements for prune segments, per RPC metho
|
||||
| RPC / Segment | Sender Recovery | Transaction Lookup | Receipts | Account History | Storage History |
|
||||
| ------------------------------- | --------------- | ------------------ | -------- | --------------- | --------------- |
|
||||
| `trace_block` | ✅ | ✅ | ✅ | ❌ | ❌ |
|
||||
| `trace_blockOpcodeGas` | ✅ | ✅ | ✅ | ❌ | ❌ |
|
||||
| `trace_call` | ✅ | ✅ | ✅ | ❌ | ❌ |
|
||||
| `trace_callMany` | ✅ | ✅ | ✅ | ❌ | ❌ |
|
||||
| `trace_filter` | ✅ | ✅ | ✅ | ❌ | ❌ |
|
||||
| `trace_get` | ✅ | ❌ | ✅ | ❌ | ❌ |
|
||||
| `trace_rawTransaction` | ✅ | ✅ | ✅ | ❌ | ❌ |
|
||||
| `trace_replayBlockTransactions` | ✅ | ✅ | ✅ | ❌ | ❌ |
|
||||
| `trace_replayTransaction` | ✅ | ❌ | ✅ | ❌ | ❌ |
|
||||
| `trace_transaction` | ✅ | ❌ | ✅ | ❌ | ❌ |
|
||||
| `trace_transactionOpcodeGas` | ✅ | ❌ | ✅ | ❌ | ❌ |
|
||||
|
||||
#### `txpool` namespace
|
||||
|
||||
|
||||
@@ -441,7 +441,6 @@ pub fn random_contract_account_range<R: Rng>(
|
||||
let mut accounts = Vec::with_capacity(acc_range.end.saturating_sub(acc_range.start) as usize);
|
||||
for _ in acc_range {
|
||||
let (address, eoa_account) = random_eoa_account(rng);
|
||||
// todo: can a non-eoa account have a nonce > 0?
|
||||
let account = Account { bytecode_hash: Some(B256::random()), ..eoa_account };
|
||||
accounts.push((address, account))
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user